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

Revision 3063, 9.0 KB checked in by mattausch, 16 years ago (diff)
RevLine 
[2753]1#include "common.h"
2#include "Camera.h"
[2755]3#include "glInterface.h"
[2911]4#include "Polygon3.h"
5#include "Matrix4x4.h"
6#include "Polyhedron.h"
[2753]7
[2776]8namespace CHCDemoEngine
[2753]9{
10
[2796]11using namespace std;
[2753]12
[2932]13// our coordinate system is left-handed
14// we look into positive y and have the positive z axis pointing up
[2928]15static const Vector3 baseDir = -Vector3::UNIT_Y();
[2796]16
[2887]17
[3062]18
19/**********************************************************/
20/*            class Frustum implementation                */
21/**********************************************************/
22
23
24Frustum::Frustum(const Matrix4x4 &trafo)
[2753]25{
[3062]26        //////////
27        //-- extract the plane equations
[2796]28
[3062]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];
[2887]36
[3062]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        }
[2753]40}
41
42
[3062]43void Frustum::EnclosePolyhedron(const Polyhedron &polyhedron)
[2753]44{
[3062]45        VertexArray vertices;
46        polyhedron.CollectVertices(vertices);
[2796]47
[3062]48        for (int i = 0; i < 6; ++ i)
49        {
50                Plane3 &plane = mClipPlanes[i];
[2796]51
[3062]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
[2796]93        mPitch = mYaw = 0;
[2918]94        Precompute(baseDir);
[2887]95
96        CalculateFromPitchAndYaw();
[2753]97}
98
99
[2928]100void Camera::Precompute(const Vector3 &dir)
[2753]101{
[2928]102        Vector3 up = Vector3::UNIT_Z();
[3061]103       
104        mBaseOrientation = LookAt(Vector3::ZERO(), dir, up);
[2796]105        mViewOrientation = mBaseOrientation;
[2753]106}
107
108
109void Camera::SetPosition(const Vector3 &pos)
110{
111        mPosition = pos;
112}
113
114
[2764]115void Camera::SetNear(float nearDist)
116{
117        mNear = nearDist;
[3063]118        UpdateProjectionMatrix();
[2764]119}
120
121
[2806]122void Camera::SetFar(float farDist)
123{
124        mFar = farDist;
[3063]125        UpdateProjectionMatrix();
[2806]126}
127
128
[2986]129void Camera::GetModelViewMatrix(Matrix4x4 &mat) const
[2755]130{
[2893]131        mat = mViewOrientation;
132
[2932]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);
[2755]137}
138
139
[2986]140void Camera::GetViewOrientationMatrix(Matrix4x4 &mat) const
141{
142        mat = mViewOrientation;
143}
144
145
[3061]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{
[3062]159        Matrix4x4 m;
160
161        GetProjectionMatrix(m);
162        glLoadMatrixf((float *)m.x);
[3061]163}
164
165
[2756]166void Camera::SetupCameraView()
167{
[2932]168        Matrix4x4 m;
169        GetModelViewMatrix(m);
[2780]170
[2932]171        glLoadMatrixf((float *)m.x);
[2755]172}
173
[2756]174
[2796]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
[2864]189void Camera::SetDirection(const Vector3 &dir)
[2829]190{
[2927]191        Vector3 ndir = -Normalize(dir);
[2829]192
[2888]193        mPitch = -atan2(ndir.x, ndir.y);
194        mYaw = atan2(ndir.z, sqrt((ndir.x * ndir.x) + (ndir.y * ndir.y)));
[2887]195
[2829]196        CalculateFromPitchAndYaw();
197}
198
199
[2796]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{
[2927]214        return -Vector3(mViewOrientation.x[0][2], mViewOrientation.x[1][2], mViewOrientation.x[2][2]);
[2796]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{
[2911]226        return Vector3(mViewOrientation.x[0][0], mViewOrientation.x[1][0], mViewOrientation.x[2][0]);           
[2796]227}
228
229
[2911]230Vector3 Camera::GetBaseDirection() const
231{
[2927]232        return -Vector3(mBaseOrientation.x[0][2], mBaseOrientation.x[1][2], mBaseOrientation.x[2][2]);
[2796]233}
234
[2911]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
[3062]248void Camera::CalcFrustum(Frustum &frustum)
[2911]249{
[3062]250        // we grab the plane equations of the six clipplanes of the viewfrustum
251        Matrix4x4 matViewing, matProjectionView;
[2911]252
[3062]253        GetModelViewMatrix(matViewing);
254        GetProjectionMatrix(matProjectionView);
[2936]255
[3062]256        matProjectionView = matViewing * matProjectionView;
[2911]257
[3062]258        frustum = Frustum(matProjectionView);
[2911]259
260
[3062]261        ////////////
262        //-- normalize the coefficients
263
[2911]264        for (int i = 0; i < 6; ++ i)
265        {
[3062]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}
[2911]274
275
[3063]276void Camera::GetProjectionMatrix(Matrix4x4 &m)const
277{
278        m = mProjection;
279}
280
281
[3062]282/*********************************************************/
283/*       Class PerspectiveCamera implementation           */
284/*********************************************************/
[2911]285
286
[3062]287PerspectiveCamera::PerspectiveCamera()
288{
289        mFOVy = 60.0f * M_PI / 180.0f;
[3063]290        mAspect = 1.0f;
291
292        UpdateProjectionMatrix();
[2911]293}
294
295
[3062]296PerspectiveCamera::PerspectiveCamera(float aspect, float fieldOfView)
[2911]297{
[3062]298        mFOVy = fieldOfView * M_PI / 180.0f;
299        mAspect = aspect;
[3063]300
301        UpdateProjectionMatrix();
[2911]302}
303
304
[3062]305Polyhedron *PerspectiveCamera::ComputeFrustum(float farthestVisibleDistance) const
[2931]306{
307        Vector3 ftl, ftr, fbl, fbr;
308        Vector3 ntl, ntr, nbl, nbr;
[2911]309
[2931]310        VertexArray sides[6];
311
[2947]312        ComputePoints(ftl, ftr, fbl, fbr, ntl, ntr, nbl, nbr, farthestVisibleDistance);
[2931]313
314        for (int i = 0; i < 6; ++ i)
315                sides[i].resize(4);
316       
317        // left, right
318        sides[0][0] = ftl; sides[0][1] = fbl; sides[0][2] = nbl; sides[0][3] = ntl;
319        sides[1][0] = fbr; sides[1][1] = ftr; sides[1][2] = ntr; sides[1][3] = nbr;
320        // bottom, top
321        sides[2][0] = fbl; sides[2][1] = fbr; sides[2][2] = nbr; sides[2][3] = nbl;
322        sides[3][0] = ftr; sides[3][1] = ftl; sides[3][2] = ntl; sides[3][3] = ntr;
323        // near, far
324        sides[4][0] = ntr; sides[4][1] = ntl; sides[4][2] = nbl; sides[4][3] = nbr;
325        sides[5][0] = ftl; sides[5][1] = ftr; sides[5][2] = fbr; sides[5][3] = fbl;
326
327
328        //////////
329        //-- compute polyhedron
330
331        PolygonContainer polygons;
332
333        for (int i = 0; i < 6; ++ i)
334        {
335                Polygon3 *poly = new Polygon3(sides[i]);
336                polygons.push_back(poly);
337        }
338
339        return new Polyhedron(polygons);
[2911]340}
341
[2931]342
[3062]343void PerspectiveCamera::ComputePointsInternal(Vector3 &ftl, Vector3 &ftr, Vector3 &fbl, Vector3 &fbr,
344                                                                                          Vector3 &ntl, Vector3 &ntr, Vector3 &nbl, Vector3 &nbr,
345                                                                                          const Vector3 &view, const Vector3 &right, const Vector3 &up,
346                                                                                          const Vector3 &pos,
347                                                                                          float farthestVisibleDistance) const
348{
349        const float z_near = mNear;
350        const float z_far = min(mFar, farthestVisibleDistance);
351
352        const float fov = mFOVy;
353
354        const float aspectRatio = GetAspect();
355
356        const float h_near = tan(fov * 0.5f) * z_near;
357        const float w_near = h_near * aspectRatio;
358
359        const float h_far = tan(fov * 0.5f) * z_far;
360        const float w_far = h_far * aspectRatio;
361
362        const Vector3 fc = pos + view * z_far;
363       
364
365        Vector3 t1, t2;
366
367        t1 = h_far * up;
368        t2 = w_far * right;
369
370        ftl = fc + t1 - t2;
371        ftr = fc + t1 + t2;
372        fbl = fc - t1 - t2;
373        fbr = fc - t1 + t2;
374
375        const Vector3 nc = pos + view * z_near;
376       
377        t1 = h_near * up;
378        t2 = w_near * right;
379
380        ntl = nc + t1 - t2;
381        ntr = nc + t1 + t2;
382        nbl = nc - t1 - t2;
383        nbr = nc - t1 + t2;
384}
385
386
387void PerspectiveCamera::ComputePoints(Vector3 &ftl, Vector3 &ftr, Vector3 &fbl, Vector3 &fbr,
388                                                                          Vector3 &ntl, Vector3 &ntr, Vector3 &nbl, Vector3 &nbr,
389                                                                          float farthestVisibleDistance) const
390{
391        ComputePointsInternal(ftl, ftr, fbl, fbr,
392                                  ntl, ntr, nbl, nbr,
393                                                  GetDirection(), GetRightVector(), GetUpVector(),
394                                                  GetPosition(),
395                                                  farthestVisibleDistance);
396}
397
398
[3063]399void PerspectiveCamera::UpdateProjectionMatrix()
[3062]400{
[3063]401        mProjection = GetPerspective(mFOVy, 1.0f / mAspect, mNear, mFar);
[3062]402}
403
404
[2931]405}
Note: See TracBrowser for help on using the repository browser.