source: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/Camera.cpp @ 3102

Revision 3102, 9.8 KB checked in by mattausch, 16 years ago (diff)

orthocam not working yet

Line 
1#include "common.h"
2#include "Camera.h"
3#include "glInterface.h"
4#include "Polygon3.h"
5#include "Matrix4x4.h"
6#include "Polyhedron.h"
7
8namespace CHCDemoEngine
9{
10
11using namespace std;
12
13// our coordinate system is left-handed
14// we look into positive y and have the positive z axis pointing up
15static const Vector3 baseDir = -Vector3::UNIT_Y();
16
17
18
19/**********************************************************/
20/*            class Frustum implementation                */
21/**********************************************************/
22
23
24Frustum::Frustum(const Matrix4x4 &trafo)
25{
26        //////////
27        //-- extract the plane equations
28
29        for (int i = 0; i < 4; ++ i)
30        {
31                mClipPlanes[Frustum::RIGHT_PLANE][i] = trafo.x[i][3] - trafo.x[i][0];
32                mClipPlanes[Frustum::LEFT_PLANE][i] = trafo.x[i][3] + trafo.x[i][0];
33               
34                mClipPlanes[Frustum::BOTTOM_PLANE][i] = trafo.x[i][3] + trafo.x[i][1];
35                mClipPlanes[Frustum::TOP_PLANE][i] = trafo.x[i][3] - trafo.x[i][1];
36
37                mClipPlanes[Frustum::FAR_PLANE][i] = trafo.x[i][3] - trafo.x[i][2];
38                mClipPlanes[Frustum::NEAR_PLANE][i] = trafo.x[i][3] + trafo.x[i][2];
39        }
40}
41
42
43void Frustum::EnclosePolyhedron(const Polyhedron &polyhedron)
44{
45        VertexArray vertices;
46        polyhedron.CollectVertices(vertices);
47
48        for (int i = 0; i < 6; ++ i)
49        {
50                Plane3 &plane = mClipPlanes[i];
51
52                VertexArray::const_iterator it, it_end = vertices.end();
53                float minDist = 1e20;
54
55                for (it = vertices.begin(); it != it_end; ++ it)
56                {
57                        float dist = plane.Distance(*it);
58
59                        if (dist < minDist)
60                        {
61                                cout << "minDist: " << dist << endl;
62                                minDist = dist;
63                        }
64                }
65
66                plane.mD += minDist;
67        }
68}
69
70
71void Frustum::ExtractTransformation(Matrix4x4 &m) const
72{
73        for (int i = 0; i < 4; ++ i)
74        {
75                m.x[i][0] = (mClipPlanes[LEFT_PLANE][i] - mClipPlanes[RIGHT_PLANE][i]) * 0.5f;
76                m.x[i][1] = (mClipPlanes[BOTTOM_PLANE][i] - mClipPlanes[TOP_PLANE][i]) * 0.5f;
77                m.x[i][2] = (mClipPlanes[NEAR_PLANE][i] - mClipPlanes[FAR_PLANE][i]) * 0.5f;
78                m.x[i][3] = (mClipPlanes[LEFT_PLANE][i] + mClipPlanes[RIGHT_PLANE][i]) * 0.5f;
79        }
80}
81
82
83
84/*********************************************************/
85/*            class Camera implementation                */
86/*********************************************************/
87
88
89Camera::Camera()
90{
91        SetPosition(Vector3(0, 0, 0));
92
93        mPitch = mYaw = 0;
94        Precompute(baseDir);
95
96        CalculateFromPitchAndYaw();
97}
98
99
100void Camera::Precompute(const Vector3 &dir)
101{
102        Vector3 up = Vector3::UNIT_Z();
103       
104        mBaseOrientation = LookAt(Vector3::ZERO(), dir, up);
105        mViewOrientation = mBaseOrientation;
106}
107
108
109void Camera::SetPosition(const Vector3 &pos)
110{
111        mPosition = pos;
112}
113
114
115void Camera::SetNear(float nearDist)
116{
117        mNear = nearDist;
118        UpdateProjectionMatrix();
119}
120
121
122void Camera::SetFar(float farDist)
123{
124        mFar = farDist;
125        UpdateProjectionMatrix();
126}
127
128
129void Camera::GetModelViewMatrix(Matrix4x4 &mat) const
130{
131        mat = mViewOrientation;
132
133        // note: left handed system => we go into positive z
134        mat.x[3][0] = -DotProd(GetRightVector(), mPosition);
135        mat.x[3][1] = -DotProd(GetUpVector(), mPosition);
136        mat.x[3][2] = DotProd(GetDirection(), mPosition);
137}
138
139
140void Camera::GetViewOrientationMatrix(Matrix4x4 &mat) const
141{
142        mat = mViewOrientation;
143}
144
145
146void Camera::SetupViewProjection()
147{
148        glMatrixMode(GL_PROJECTION);
149        SetupProjection();
150
151        glMatrixMode(GL_MODELVIEW);
152        // set up the view matrix
153        SetupCameraView();
154}
155
156
157void Camera::SetupProjection()
158{
159        Matrix4x4 m;
160
161        GetProjectionMatrix(m);
162        glLoadMatrixf((float *)m.x);
163}
164
165
166void Camera::SetupCameraView()
167{
168        Matrix4x4 m;
169        GetModelViewMatrix(m);
170
171        glLoadMatrixf((float *)m.x);
172}
173
174
175void Camera::Yaw(float angle)
176{
177        mYaw += angle;
178        CalculateFromPitchAndYaw();
179}
180
181
182void Camera::Pitch(float angle)
183{
184        mPitch += angle;
185        CalculateFromPitchAndYaw();
186}
187
188
189void Camera::SetDirection(const Vector3 &dir)
190{
191        Vector3 ndir = -Normalize(dir);
192
193        mPitch = -atan2(ndir.x, ndir.y);
194        mYaw = atan2(ndir.z, sqrt((ndir.x * ndir.x) + (ndir.y * ndir.y)));
195
196        CalculateFromPitchAndYaw();
197}
198
199
200void Camera::CalculateFromPitchAndYaw()
201{
202        mViewOrientation = mBaseOrientation;
203
204        Matrix4x4 roty = RotationYMatrix(mPitch);
205        Matrix4x4 rotx = RotationXMatrix(mYaw);
206
207        mViewOrientation *= roty;
208        mViewOrientation *= rotx;
209}
210
211
212Vector3 Camera::GetDirection() const
213{
214        return -Vector3(mViewOrientation.x[0][2], mViewOrientation.x[1][2], mViewOrientation.x[2][2]);
215}
216
217
218Vector3 Camera::GetUpVector() const
219{
220        return Vector3(mViewOrientation.x[0][1], mViewOrientation.x[1][1], mViewOrientation.x[2][1]);
221}
222
223
224Vector3 Camera::GetRightVector() const
225{
226        return Vector3(mViewOrientation.x[0][0], mViewOrientation.x[1][0], mViewOrientation.x[2][0]);           
227}
228
229
230Vector3 Camera::GetBaseDirection() const
231{
232        return -Vector3(mBaseOrientation.x[0][2], mBaseOrientation.x[1][2], mBaseOrientation.x[2][2]);
233}
234
235
236Vector3 Camera::GetBaseUpVector() const
237{
238        return Vector3(mBaseOrientation.x[0][1], mBaseOrientation.x[1][1], mBaseOrientation.x[2][1]);
239}
240
241
242Vector3 Camera::GetBaseRightVector() const
243{
244        return Vector3(mBaseOrientation.x[0][0], mBaseOrientation.x[1][0], mBaseOrientation.x[2][0]);
245}
246
247
248void Camera::CalcFrustum(Frustum &frustum)
249{
250        // we grab the plane equations of the six clipplanes of the viewfrustum
251        Matrix4x4 matViewing, matProjectionView;
252
253        GetModelViewMatrix(matViewing);
254        GetProjectionMatrix(matProjectionView);
255
256        matProjectionView = matViewing * matProjectionView;
257
258        frustum = Frustum(matProjectionView);
259
260
261        ////////////
262        //-- normalize the coefficients
263
264        for (int i = 0; i < 6; ++ i)
265        {
266                // the clipping planes look outward the frustum,
267                // so distances > 0 mean that a point is outside
268                const float invLength = -1.0f / Magnitude(frustum.mClipPlanes[i].mNormal);
269       
270                frustum.mClipPlanes[i].mD *= invLength;
271                frustum.mClipPlanes[i].mNormal *= invLength;
272        }
273}
274
275
276void Camera::GetProjectionMatrix(Matrix4x4 &m)const
277{
278        //glGetFloatv(GL_PROJECTION_MATRIX, (float *)m.x);
279        m = mProjection;
280}
281
282
283
284/*********************************************************/
285/*       Class PerspectiveCamera implementation          */
286/*********************************************************/
287
288
289PerspectiveCamera::PerspectiveCamera()
290{
291        mFOVy = 60.0f * M_PI / 180.0f;
292        mAspect = 1.0f;
293
294        UpdateProjectionMatrix();
295}
296
297
298PerspectiveCamera::PerspectiveCamera(float aspect, float fieldOfView)
299{
300        mFOVy = fieldOfView * M_PI / 180.0f;
301        mAspect = aspect;
302
303        UpdateProjectionMatrix();
304}
305
306
307Polyhedron *PerspectiveCamera::ComputeFrustum(float farthestVisibleDistance) const
308{
309        Vector3 ftl, ftr, fbl, fbr;
310        Vector3 ntl, ntr, nbl, nbr;
311
312        VertexArray sides[6];
313
314        ComputePoints(ftl, ftr, fbl, fbr, ntl, ntr, nbl, nbr, farthestVisibleDistance);
315
316        for (int i = 0; i < 6; ++ i)
317                sides[i].resize(4);
318       
319        // left, right
320        sides[0][0] = ftl; sides[0][1] = fbl; sides[0][2] = nbl; sides[0][3] = ntl;
321        sides[1][0] = fbr; sides[1][1] = ftr; sides[1][2] = ntr; sides[1][3] = nbr;
322        // bottom, top
323        sides[2][0] = fbl; sides[2][1] = fbr; sides[2][2] = nbr; sides[2][3] = nbl;
324        sides[3][0] = ftr; sides[3][1] = ftl; sides[3][2] = ntl; sides[3][3] = ntr;
325        // near, far
326        sides[4][0] = ntr; sides[4][1] = ntl; sides[4][2] = nbl; sides[4][3] = nbr;
327        sides[5][0] = ftl; sides[5][1] = ftr; sides[5][2] = fbr; sides[5][3] = fbl;
328
329
330        //////////
331        //-- compute polyhedron
332
333        PolygonContainer polygons;
334
335        for (int i = 0; i < 6; ++ i)
336        {
337                Polygon3 *poly = new Polygon3(sides[i]);
338                polygons.push_back(poly);
339        }
340
341        return new Polyhedron(polygons);
342}
343
344
345void PerspectiveCamera::ComputePointsInternal(Vector3 &ftl, Vector3 &ftr, Vector3 &fbl, Vector3 &fbr,
346                                                                                          Vector3 &ntl, Vector3 &ntr, Vector3 &nbl, Vector3 &nbr,
347                                                                                          const Vector3 &view, const Vector3 &right, const Vector3 &up,
348                                                                                          const Vector3 &pos,
349                                                                                          float farthestVisibleDistance) const
350{
351        const float z_near = mNear;
352        const float z_far = min(mFar, farthestVisibleDistance);
353
354        const float fov = mFOVy;
355
356        const float aspectRatio = GetAspect();
357
358        const float h_near = tan(fov * 0.5f) * z_near;
359        const float w_near = h_near * aspectRatio;
360
361        const float h_far = tan(fov * 0.5f) * z_far;
362        const float w_far = h_far * aspectRatio;
363
364        const Vector3 fc = pos + view * z_far;
365       
366
367        Vector3 t1, t2;
368
369        t1 = h_far * up;
370        t2 = w_far * right;
371
372        ftl = fc + t1 - t2;
373        ftr = fc + t1 + t2;
374        fbl = fc - t1 - t2;
375        fbr = fc - t1 + t2;
376
377        const Vector3 nc = pos + view * z_near;
378       
379        t1 = h_near * up;
380        t2 = w_near * right;
381
382        ntl = nc + t1 - t2;
383        ntr = nc + t1 + t2;
384        nbl = nc - t1 - t2;
385        nbr = nc - t1 + t2;
386}
387
388
389void PerspectiveCamera::UpdateProjectionMatrix()
390{
391        mProjection = GetPerspective(mFOVy, 1.0f / mAspect, mNear, mFar);
392}
393
394
395
396void PerspectiveCamera::ComputePoints(Vector3 &ftl, Vector3 &ftr, Vector3 &fbl, Vector3 &fbr,
397                                                                          Vector3 &ntl, Vector3 &ntr, Vector3 &nbl, Vector3 &nbr,
398                                                                          float farthestVisibleDistance) const
399{
400        ComputePointsInternal(ftl, ftr, fbl, fbr,
401                                  ntl, ntr, nbl, nbr,
402                                                  GetDirection(), GetRightVector(), GetUpVector(),
403                                                  GetPosition(),
404                                                  farthestVisibleDistance);
405}
406
407
408
409/*********************************************************/
410/*          Class OrthoCamera implementation             */
411/*********************************************************/
412
413
414OrthoCamera::OrthoCamera():
415mLeft(0), mRight(1), mBottom(0), mTop(1)
416{
417        mNear = 0; mFar = 1;
418        UpdateProjectionMatrix();
419}
420
421
422OrthoCamera::OrthoCamera(float l, float r, float b, float t):
423mLeft(l), mRight(r), mBottom(b), mTop(t)
424{
425        mNear = 0; mFar = 1;
426        UpdateProjectionMatrix();
427}
428
429
430OrthoCamera::OrthoCamera(float l, float r, float b, float t, float n, float f):
431mLeft(l), mRight(r), mBottom(b), mTop(t)
432{
433        mNear = n; mFar = f;
434        UpdateProjectionMatrix();
435}
436
437
438void OrthoCamera::UpdateProjectionMatrix()
439{
440        mProjection = GetOrtho(mLeft, mRight, mBottom, mTop, mNear, mFar);
441}
442
443
444}
Note: See TracBrowser for help on using the repository browser.