[2753] | 1 | #include "common.h"
|
---|
| 2 | #include "Camera.h"
|
---|
[2755] | 3 | #include "glInterface.h"
|
---|
[2753] | 4 |
|
---|
| 5 |
|
---|
[2776] | 6 | namespace CHCDemoEngine
|
---|
[2753] | 7 | {
|
---|
| 8 |
|
---|
[2796] | 9 | using namespace std;
|
---|
[2753] | 10 |
|
---|
[2796] | 11 |
|
---|
[2753] | 12 | Camera::Camera()
|
---|
| 13 | {
|
---|
| 14 | mWidth = 100;
|
---|
| 15 | mHeight = 100;
|
---|
[2796] | 16 | mFovy = 60.0f * M_PI / 180.0f;
|
---|
| 17 | mIsOrtho = false;
|
---|
| 18 |
|
---|
| 19 | SetPosition(Vector3(0, 0, 0));
|
---|
| 20 |
|
---|
| 21 | mPitch = mYaw = 0;
|
---|
| 22 | Precompute(Vector3(0, 1, 0));
|
---|
[2753] | 23 | }
|
---|
| 24 |
|
---|
| 25 |
|
---|
| 26 | Camera::Camera(int width, int height, float fieldOfView)
|
---|
| 27 | {
|
---|
| 28 | mWidth = width;
|
---|
| 29 | mHeight = height;
|
---|
| 30 |
|
---|
[2760] | 31 | mFovy = fieldOfView * M_PI / 180.0f;
|
---|
[2796] | 32 |
|
---|
| 33 | mIsOrtho = false;
|
---|
| 34 |
|
---|
| 35 | SetPosition(Vector3(0, 0, 0));
|
---|
| 36 |
|
---|
| 37 | mPitch = mYaw = 0;
|
---|
| 38 | Precompute(Vector3(0, 1, 0));
|
---|
[2753] | 39 | }
|
---|
| 40 |
|
---|
| 41 |
|
---|
[2796] | 42 | void Camera::Precompute(const Vector3 &direction)
|
---|
[2753] | 43 | {
|
---|
[2796] | 44 | Vector3 up = Vector3(0, 0, 1);
|
---|
[2838] | 45 | Vector3 right = Normalize(CrossProd(up, direction));
|
---|
| 46 | up = Normalize(CrossProd(direction, right));
|
---|
[2753] | 47 |
|
---|
[2796] | 48 | mBaseOrientation = Matrix4x4(right, up, direction);
|
---|
| 49 | mViewOrientation = mBaseOrientation;
|
---|
[2753] | 50 | }
|
---|
| 51 |
|
---|
| 52 |
|
---|
[2796] | 53 |
|
---|
[2753] | 54 | void Camera::SetPosition(const Vector3 &pos)
|
---|
| 55 | {
|
---|
| 56 | mPosition = pos;
|
---|
| 57 | }
|
---|
| 58 |
|
---|
| 59 |
|
---|
[2764] | 60 | void Camera::SetNear(float nearDist)
|
---|
| 61 | {
|
---|
| 62 | mNear = nearDist;
|
---|
| 63 | }
|
---|
| 64 |
|
---|
| 65 |
|
---|
[2806] | 66 | void Camera::SetFar(float farDist)
|
---|
| 67 | {
|
---|
| 68 | mFar = farDist;
|
---|
| 69 | }
|
---|
| 70 |
|
---|
| 71 |
|
---|
[2755] | 72 | void Camera::GetProjectionMatrix(Matrix4x4 &mat)
|
---|
| 73 | {
|
---|
| 74 | glGetFloatv(GL_PROJECTION_MATRIX, (float *)mat.x);
|
---|
[2753] | 75 | }
|
---|
| 76 |
|
---|
[2755] | 77 |
|
---|
| 78 | void Camera::GetModelViewMatrix(Matrix4x4 &mat)
|
---|
| 79 | {
|
---|
| 80 | glGetFloatv(GL_MODELVIEW_MATRIX, (float *)mat.x);
|
---|
| 81 | }
|
---|
| 82 |
|
---|
| 83 |
|
---|
| 84 | void Camera::CalcFrustum(Frustum &frustum)
|
---|
| 85 | {
|
---|
| 86 | // we grab the plane equations of the six clipplanes of the viewfrustum
|
---|
| 87 | Matrix4x4 matViewing, matProjectionView;
|
---|
| 88 |
|
---|
| 89 | GetModelViewMatrix(matViewing);
|
---|
| 90 | GetProjectionMatrix(matProjectionView);
|
---|
| 91 |
|
---|
[2762] | 92 | matProjectionView = matViewing * matProjectionView;
|
---|
[2834] | 93 |
|
---|
[2755] | 94 | float planes[6][4];
|
---|
| 95 |
|
---|
[2762] | 96 |
|
---|
[2755] | 97 | //////////
|
---|
| 98 | //-- extract the plane equations
|
---|
| 99 |
|
---|
| 100 | for (int i = 0; i < 4; ++ i)
|
---|
| 101 | {
|
---|
| 102 | planes[0][i] = matProjectionView.x[i][3] - matProjectionView.x[i][0]; // right plane
|
---|
| 103 | planes[1][i] = matProjectionView.x[i][3] + matProjectionView.x[i][0]; // left plane
|
---|
| 104 | planes[2][i] = matProjectionView.x[i][3] + matProjectionView.x[i][1]; // bottom plane
|
---|
| 105 | planes[3][i] = matProjectionView.x[i][3] - matProjectionView.x[i][1]; // top plane
|
---|
| 106 | planes[4][i] = matProjectionView.x[i][3] - matProjectionView.x[i][2]; // far plane
|
---|
| 107 | planes[5][i] = matProjectionView.x[i][3] + matProjectionView.x[i][2]; // near plane
|
---|
| 108 | }
|
---|
| 109 |
|
---|
| 110 |
|
---|
| 111 | ////////////
|
---|
| 112 | //-- normalize the coefficients
|
---|
| 113 |
|
---|
| 114 | for (int i = 0; i < 6; ++ i)
|
---|
| 115 | {
|
---|
| 116 | // the clipping planes look outward the frustum,
|
---|
| 117 | // so distances > 0 mean that a point is outside
|
---|
[2762] | 118 | float fInvLength = -1.0f /
|
---|
| 119 | sqrt(planes[i][0] * planes[i][0] +
|
---|
| 120 | planes[i][1] * planes[i][1] +
|
---|
| 121 | planes[i][2] * planes[i][2]);
|
---|
[2755] | 122 |
|
---|
| 123 | planes[i][0] *= fInvLength;
|
---|
| 124 | planes[i][1] *= fInvLength;
|
---|
| 125 | planes[i][2] *= fInvLength;
|
---|
| 126 | planes[i][3] *= fInvLength;
|
---|
| 127 |
|
---|
[2762] | 128 | frustum.mClipPlanes[i].mNormal = Vector3(planes[i][0], planes[i][1], planes[i][2]);
|
---|
| 129 | frustum.mClipPlanes[i].mD = planes[i][3];
|
---|
[2755] | 130 | }
|
---|
| 131 | }
|
---|
| 132 |
|
---|
| 133 |
|
---|
| 134 | void Camera::Frustum::CalcNPVertexIndices(int *indices)
|
---|
| 135 | {
|
---|
| 136 | for (int i = 0; i < 6; ++ i)
|
---|
| 137 | {
|
---|
| 138 | // n-vertex
|
---|
| 139 | indices[i * 2 + 0] = AxisAlignedBox3::GetIndexNearestVertex(mClipPlanes[i].mNormal);
|
---|
| 140 | // p-vertex
|
---|
| 141 | indices[i * 2 + 1] = AxisAlignedBox3::GetIndexFarthestVertex(mClipPlanes[i].mNormal);
|
---|
| 142 | }
|
---|
| 143 | }
|
---|
| 144 |
|
---|
| 145 |
|
---|
[2756] | 146 | void Camera::SetupCameraView()
|
---|
| 147 | {
|
---|
[2796] | 148 | Matrix4x4 tview = mViewOrientation;
|
---|
[2780] | 149 |
|
---|
[2796] | 150 | Vector3 pos = -mPosition;
|
---|
| 151 | pos = tview * pos;
|
---|
| 152 |
|
---|
| 153 | Matrix4x4 viewOrientation = mViewOrientation;
|
---|
| 154 |
|
---|
| 155 | viewOrientation.x[3][0] = pos.x;
|
---|
| 156 | viewOrientation.x[3][1] = pos.y;
|
---|
| 157 | viewOrientation.x[3][2] = pos.z;
|
---|
| 158 |
|
---|
| 159 | glLoadMatrixf((float *)viewOrientation.x);
|
---|
[2755] | 160 | }
|
---|
| 161 |
|
---|
[2756] | 162 |
|
---|
[2762] | 163 |
|
---|
| 164 | void Camera::ComputePoints(Vector3 &ftl, Vector3 &ftr, Vector3 &fbl, Vector3 &fbr,
|
---|
| 165 | Vector3 &ntl, Vector3 &ntr, Vector3 &nbl, Vector3 &nbr)
|
---|
| 166 | {
|
---|
[2806] | 167 | float z_near = mNear;
|
---|
| 168 | float z_far = mFar;
|
---|
[2762] | 169 |
|
---|
[2833] | 170 | const float w_near = 2.0f * tan(mFovy / 2) * z_near;
|
---|
| 171 | const float h_near = w_near / GetAspect();
|
---|
| 172 | const float w_far = 2.0f * tan(mFovy / 2) * z_far;
|
---|
| 173 | const float h_far = w_far / GetAspect();
|
---|
[2762] | 174 |
|
---|
[2796] | 175 | const Vector3 view = GetDirection();
|
---|
[2762] | 176 | const Vector3 fc = mPosition + view * z_far;
|
---|
| 177 |
|
---|
[2838] | 178 | const Vector3 up = GetUpVector();
|
---|
[2796] | 179 | const Vector3 right = GetRightVector();
|
---|
| 180 |
|
---|
[2762] | 181 | Vector3 t1, t2;
|
---|
| 182 |
|
---|
| 183 | t1 = h_far * 0.5f * up;
|
---|
| 184 | t2 = w_far * 0.5f * right;
|
---|
| 185 |
|
---|
| 186 | ftl = fc + t1 - t2;
|
---|
| 187 | ftr = fc + t1 + t2;
|
---|
| 188 | fbl = fc - t1 - t2;
|
---|
| 189 | fbr = fc - t1 + t2;
|
---|
| 190 |
|
---|
[2796] | 191 | const Vector3 nc = mPosition + view * z_near;
|
---|
[2762] | 192 |
|
---|
| 193 | t1 = h_near * 0.5f * up;
|
---|
| 194 | t2 = w_near * 0.5f * right;
|
---|
| 195 |
|
---|
| 196 | ntl = nc + t1 - t2;
|
---|
| 197 | ntr = nc + t1 + t2;
|
---|
| 198 | nbl = nc - t1 - t2;
|
---|
| 199 | nbr = nc - t1 + t2;
|
---|
[2756] | 200 | }
|
---|
| 201 |
|
---|
[2762] | 202 |
|
---|
[2796] | 203 | void Camera::SetOrtho(bool ortho)
|
---|
| 204 | {
|
---|
| 205 | mIsOrtho = true;
|
---|
[2762] | 206 | }
|
---|
| 207 |
|
---|
[2796] | 208 |
|
---|
| 209 | void Camera::Yaw(float angle)
|
---|
| 210 | {
|
---|
| 211 | mYaw += angle;
|
---|
| 212 | CalculateFromPitchAndYaw();
|
---|
| 213 | }
|
---|
| 214 |
|
---|
| 215 |
|
---|
| 216 | void Camera::Pitch(float angle)
|
---|
| 217 | {
|
---|
| 218 | mPitch += angle;
|
---|
| 219 | CalculateFromPitchAndYaw();
|
---|
| 220 | }
|
---|
| 221 |
|
---|
| 222 |
|
---|
[2864] | 223 | void Camera::SetDirection(const Vector3 &dir)
|
---|
[2829] | 224 | {
|
---|
[2864] | 225 | Normalize(dir);
|
---|
[2829] | 226 |
|
---|
[2864] | 227 | mPitch = atan2(dir.x, dir.z);
|
---|
| 228 | mYaw = atan2(dir.y, sqrt((dir.x * dir.x) + (dir.z * dir.z)));
|
---|
[2829] | 229 |
|
---|
| 230 | CalculateFromPitchAndYaw();
|
---|
| 231 | }
|
---|
| 232 |
|
---|
| 233 |
|
---|
[2796] | 234 | void Camera::CalculateFromPitchAndYaw()
|
---|
| 235 | {
|
---|
| 236 | mViewOrientation = mBaseOrientation;
|
---|
| 237 |
|
---|
| 238 | Matrix4x4 roty = RotationYMatrix(mPitch);
|
---|
| 239 | Matrix4x4 rotx = RotationXMatrix(mYaw);
|
---|
| 240 |
|
---|
| 241 | mViewOrientation *= roty;
|
---|
| 242 | mViewOrientation *= rotx;
|
---|
| 243 | }
|
---|
| 244 |
|
---|
| 245 |
|
---|
| 246 | Vector3 Camera::GetDirection() const
|
---|
| 247 | {
|
---|
| 248 | return -Vector3(mViewOrientation.x[0][2], mViewOrientation.x[1][2], mViewOrientation.x[2][2]);
|
---|
| 249 | }
|
---|
| 250 |
|
---|
| 251 |
|
---|
| 252 | Vector3 Camera::GetUpVector() const
|
---|
| 253 | {
|
---|
| 254 | return Vector3(mViewOrientation.x[0][1], mViewOrientation.x[1][1], mViewOrientation.x[2][1]);
|
---|
| 255 | }
|
---|
| 256 |
|
---|
| 257 |
|
---|
| 258 | Vector3 Camera::GetRightVector() const
|
---|
| 259 | {
|
---|
| 260 | return Vector3(mViewOrientation.x[0][0], mViewOrientation.x[1][0], mViewOrientation.x[2][0]);
|
---|
| 261 |
|
---|
| 262 | }
|
---|
| 263 |
|
---|
| 264 |
|
---|
| 265 | }
|
---|
| 266 |
|
---|