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

Revision 3063, 9.0 KB checked in by mattausch, 16 years ago (diff)
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        m = mProjection;
279}
280
281
282/*********************************************************/
283/*       Class PerspectiveCamera implementation           */
284/*********************************************************/
285
286
287PerspectiveCamera::PerspectiveCamera()
288{
289        mFOVy = 60.0f * M_PI / 180.0f;
290        mAspect = 1.0f;
291
292        UpdateProjectionMatrix();
293}
294
295
296PerspectiveCamera::PerspectiveCamera(float aspect, float fieldOfView)
297{
298        mFOVy = fieldOfView * M_PI / 180.0f;
299        mAspect = aspect;
300
301        UpdateProjectionMatrix();
302}
303
304
305Polyhedron *PerspectiveCamera::ComputeFrustum(float farthestVisibleDistance) const
306{
307        Vector3 ftl, ftr, fbl, fbr;
308        Vector3 ntl, ntr, nbl, nbr;
309
310        VertexArray sides[6];
311
312        ComputePoints(ftl, ftr, fbl, fbr, ntl, ntr, nbl, nbr, farthestVisibleDistance);
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);
340}
341
342
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
399void PerspectiveCamera::UpdateProjectionMatrix()
400{
401        mProjection = GetPerspective(mFOVy, 1.0f / mAspect, mNear, mFar);
402}
403
404
405}
Note: See TracBrowser for help on using the repository browser.