#include "common.h" #include "Camera.h" #include "glInterface.h" namespace CHCDemo { Camera::Camera() { mWidth = 100; mHeight = 100; mFovy = 90.0f * M_PI / 180.0f; } Camera::Camera(int width, int height, float fieldOfView) { mWidth = width; mHeight = height; mFovy = fieldOfView * M_PI / 180.0f; } void Camera::Precompute() { mDirection.Normalize(); Vector3 side = CrossProd(Vector3(0, 1, 0), mDirection); mUp = -Normalize(CrossProd(side, mDirection)); mRight = -Normalize(CrossProd(mDirection, mUp)); float k = tan(mFovy/2); mUp *= k; mRight *= k*mWidth/mHeight; } void Camera::SetPosition(const Vector3 &pos) { mPosition = pos; Precompute(); } void Camera::SetDirection(const Vector3 &dir) { mDirection = dir; Precompute(); } void Camera::LookInBox(const AxisAlignedBox3 &box) { mDirection = Vector3(0, 0, 1); mPosition = box.Center(); mPosition.y += 50; Precompute(); } void Camera::LookAtBox(const AxisAlignedBox3 &box) { mDirection = box.Min() - box.Max(); mPosition = box.Max() - mDirection; Precompute(); } void Camera::GetProjectionMatrix(Matrix4x4 &mat) { glGetFloatv(GL_PROJECTION_MATRIX, (float *)mat.x); } void Camera::GetModelViewMatrix(Matrix4x4 &mat) { glGetFloatv(GL_MODELVIEW_MATRIX, (float *)mat.x); } void Camera::CalcFrustum(Frustum &frustum) { // we grab the plane equations of the six clipplanes of the viewfrustum Matrix4x4 matViewing, matProjectionView; GetModelViewMatrix(matViewing); GetProjectionMatrix(matProjectionView); matProjectionView *= matViewing; float fInvLength; float planes[6][4]; ////////// //-- extract the plane equations for (int i = 0; i < 4; ++ i) { planes[0][i] = matProjectionView.x[i][3] - matProjectionView.x[i][0]; // right plane planes[1][i] = matProjectionView.x[i][3] + matProjectionView.x[i][0]; // left plane planes[2][i] = matProjectionView.x[i][3] + matProjectionView.x[i][1]; // bottom plane planes[3][i] = matProjectionView.x[i][3] - matProjectionView.x[i][1]; // top plane planes[4][i] = matProjectionView.x[i][3] - matProjectionView.x[i][2]; // far plane planes[5][i] = matProjectionView.x[i][3] + matProjectionView.x[i][2]; // near plane } //////////// //-- normalize the coefficients for (int i = 0; i < 6; ++ i) { // the clipping planes look outward the frustum, // so distances > 0 mean that a point is outside fInvLength = -1.0f / sqrt(planes[i][0] * planes[i][0] + planes[i][1] * planes[i][1] + planes[i][2] * planes[i][2]); planes[i][0] *= fInvLength; planes[i][1] *= fInvLength; planes[i][2] *= fInvLength; planes[i][3] *= fInvLength; Vector3 normal(planes[i][0], planes[i][1], planes[i][2]); frustum.mClipPlanes[i] = Plane3(normal, planes[i][3]); } } void Camera::Frustum::CalcNPVertexIndices(int *indices) { for (int i = 0; i < 6; ++ i) { // n-vertex indices[i * 2 + 0] = AxisAlignedBox3::GetIndexNearestVertex(mClipPlanes[i].mNormal); // p-vertex indices[i * 2 + 1] = AxisAlignedBox3::GetIndexFarthestVertex(mClipPlanes[i].mNormal); } } void Camera::SetupCameraView() { glLoadIdentity(); gluLookAt(mPosition.x, mPosition.y, mPosition.z, mPosition.x + mDirection.x, mPosition.y + mDirection.y, mPosition.z + mDirection.z, mUp.x, mUp.y, mUp.z); //std::cout << "dir: " << mDirection << " pos: " << mPosition << " up: " << mUp << std::endl; } }