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

Revision 2911, 8.6 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// this is the start vector.
14// warning: our coordinate system has the negative z axis pointing up
15// which is different from the system used in opengl!!
16static Vector3 startVector = Vector3(0, 1, 0);
17
18
19Camera::Camera()
20{
21        mWidth = 100;
22        mHeight = 100;
23        mFovy = 60.0f * M_PI / 180.0f;
24        mIsOrtho = false;
25       
26        SetPosition(Vector3(0, 0, 0));
27
28        mPitch = mYaw = 0;
29        Precompute(startVector);
30
31        CalculateFromPitchAndYaw();
32}
33
34
35Camera::Camera(int width, int height, float fieldOfView)
36{
37        mWidth = width;
38        mHeight = height;
39       
40        mFovy = fieldOfView * M_PI / 180.0f;
41
42        mIsOrtho = false;
43
44        SetPosition(Vector3(0, 0, 0));
45
46        mPitch = mYaw = 0;
47        Precompute(startVector);
48
49        CalculateFromPitchAndYaw();
50}
51
52
53void Camera::Precompute(const Vector3 &direction)
54{
55        Vector3 up = Vector3(0, 0, 1);
56        Vector3 right = Normalize(CrossProd(up, direction));
57        up = Normalize(CrossProd(direction, right));
58
59        mBaseOrientation = Matrix4x4(right, up, direction);
60        mViewOrientation = mBaseOrientation;
61}
62
63
64void Camera::SetPosition(const Vector3 &pos)
65{
66        mPosition = pos;
67}
68
69
70void Camera::SetNear(float nearDist)
71{
72        mNear = nearDist;
73}
74
75
76void Camera::SetFar(float farDist)
77{
78        mFar = farDist;
79}
80
81
82void Camera::GetProjectionMatrix(Matrix4x4 &mat)
83{
84        glGetFloatv(GL_PROJECTION_MATRIX, (float *)mat.x);
85}
86
87
88void Camera::GetModelViewMatrix(Matrix4x4 &mat)
89{
90        mat = mViewOrientation;
91
92        Vector3 pos = mViewOrientation * -mPosition;
93       
94        mat.x[3][0] = pos.x;
95        mat.x[3][1] = pos.y;
96        mat.x[3][2] = pos.z;
97
98        //glGetFloatv(GL_MODELVIEW_MATRIX, (float *)mat.x);
99}
100
101
102void Camera::CalcFrustum(Frustum &frustum)
103{
104        // we grab the plane equations of the six clipplanes of the viewfrustum
105        Matrix4x4 matViewing, matProjectionView;
106
107        GetModelViewMatrix(matViewing);
108        GetProjectionMatrix(matProjectionView);
109
110        matProjectionView = matViewing * matProjectionView;
111
112        frustum = Frustum(matProjectionView);
113
114        ////////////
115        //-- normalize the coefficients
116
117        for (int i = 0; i < 6; ++ i)
118        {
119                // the clipping planes look outward the frustum,
120                // so distances > 0 mean that a point is outside
121                const float invLength = -1.0f / Magnitude(frustum.mClipPlanes[i].mNormal);
122       
123                frustum.mClipPlanes[i].mD *= invLength;
124                frustum.mClipPlanes[i].mNormal *= invLength;
125        }
126}
127
128
129void Camera::SetupCameraView()
130{
131        Matrix4x4 viewOrientation = mViewOrientation;
132
133        Vector3 pos = mViewOrientation * -mPosition;
134
135        viewOrientation.x[3][0] = pos.x;
136        viewOrientation.x[3][1] = pos.y;
137        viewOrientation.x[3][2] = pos.z;
138
139        glLoadMatrixf((float *)viewOrientation.x);
140}
141
142
143void Camera::ComputePointsInternal(Vector3 &ftl, Vector3 &ftr, Vector3 &fbl, Vector3 &fbr,
144                                                                   Vector3 &ntl, Vector3 &ntr, Vector3 &nbl, Vector3 &nbr,
145                                                                   const Vector3 &view, const Vector3 &right, const Vector3 &up,
146                                                                   const Vector3 &pos) const
147{
148        float z_near = mNear;
149        float z_far = mFar;
150
151        float fov = mFovy;
152
153        const float w_near = 2.0f * tan(fov * 0.5f) * z_near;
154        const float h_near = w_near / GetAspect();
155
156        const float w_far = 2.0f * tan(fov * 0.5f) * z_far;
157        const float h_far = w_far / GetAspect();
158
159        const Vector3 fc = pos + view * z_far;
160       
161        Vector3 t1, t2;
162
163        t1 = h_far * 0.5f * up;
164        t2 = w_far * 0.5f * right;
165
166        ftl = fc + t1 - t2;
167        ftr = fc + t1 + t2;
168        fbl = fc - t1 - t2;
169        fbr = fc - t1 + t2;
170
171        const Vector3 nc = pos + view * z_near;
172       
173        t1 = h_near * 0.5f * up;
174        t2 = w_near * 0.5f * right;
175
176        ntl = nc + t1 - t2;
177        ntr = nc + t1 + t2;
178        nbl = nc - t1 - t2;
179        nbr = nc - t1 + t2;
180}
181
182
183void Camera::ComputePoints(Vector3 &ftl, Vector3 &ftr, Vector3 &fbl, Vector3 &fbr,
184                                                   Vector3 &ntl, Vector3 &ntr, Vector3 &nbl, Vector3 &nbr) const
185{
186        ComputePointsInternal(ftl, ftr, fbl, fbr, ntl, ntr, nbl, nbr,
187                                                  GetDirection(), GetRightVector(), GetUpVector(), GetPosition());
188}
189
190
191void Camera::ComputeBasePoints(Vector3 &ftl, Vector3 &ftr, Vector3 &fbl, Vector3 &fbr,
192                                                           Vector3 &ntl, Vector3 &ntr, Vector3 &nbl, Vector3 &nbr) const
193{
194        ComputePointsInternal(ftl, ftr, fbl, fbr, ntl, ntr, nbl, nbr,
195                GetBaseDirection(), GetBaseRightVector(), GetBaseUpVector(), Vector3(0, 0, 0));
196}
197
198
199Polyhedron *Camera::CalcClippedFrustum(const AxisAlignedBox3 &box) const
200{
201        Vector3 ftl, ftr, fbl, fbr;
202        Vector3 ntl, ntr, nbl, nbr;
203
204        VertexArray sides[6];
205
206        ComputeBasePoints(ftl, ftr, fbl, fbr,ntl, ntr, nbl, nbr);
207        //ComputePoints(ftl, ftr, fbl, fbr,ntl, ntr, nbl, nbr);
208
209        for (int i = 0; i < 6; i ++)
210                sides[i].resize(4);
211       
212        // left, right
213        sides[0][0] = ntl; sides[0][1] = ftl; sides[0][2] = fbl; sides[0][3] = nbl;
214        sides[1][0] = ntr; sides[1][1] = ftr; sides[1][2] = fbr; sides[1][3] = nbr;
215        // bottom, top
216        sides[2][0] = ntl; sides[2][1] = ftl; sides[2][2] = ftr; sides[2][3] = ntr;
217        sides[3][0] = nbl; sides[3][1] = fbl; sides[3][2] = fbr; sides[3][3] = nbr;
218        // near, far
219        sides[4][0] = ntl; sides[4][1] = ntr; sides[4][2] = nbr; sides[4][3] = nbl;
220        sides[5][0] = ntl; sides[5][1] = ntr; sides[5][2] = nbr; sides[5][3] = nbl;
221
222
223        //////////
224        //-- compute polyhedron
225
226        PolygonContainer polygons;
227
228        for (int i = 0; i < 6; ++ i)
229        {
230                Polygon3 *poly = new Polygon3(sides[i]);
231                polygons.push_back(poly);
232        }
233
234        Polyhedron *p = new Polyhedron(polygons);
235
236        //Polyhedron *clippedPolyhedron = box.CalcIntersection(po);
237        //DEL_PTR(p);
238
239        //return clippedPolyhedron;
240        return p;
241}
242
243
244void Camera::SetOrtho(bool ortho)
245{
246        mIsOrtho = true;
247}
248
249
250void Camera::Yaw(float angle)
251{
252        mYaw += angle;
253        CalculateFromPitchAndYaw();
254}
255
256
257void Camera::Pitch(float angle)
258{
259        mPitch += angle;
260        CalculateFromPitchAndYaw();
261}
262
263
264void Camera::SetDirection(const Vector3 &dir)
265{
266        Vector3 ndir = -Normalize(dir);
267
268        mPitch = -atan2(ndir.x, ndir.y);
269        mYaw = atan2(ndir.z, sqrt((ndir.x * ndir.x) + (ndir.y * ndir.y)));
270
271        CalculateFromPitchAndYaw();
272}
273
274
275void Camera::CalculateFromPitchAndYaw()
276{
277        mViewOrientation = mBaseOrientation;
278
279        Matrix4x4 roty = RotationYMatrix(mPitch);
280        Matrix4x4 rotx = RotationXMatrix(mYaw);
281
282        mViewOrientation *= roty;
283        mViewOrientation *= rotx;
284}
285
286
287Vector3 Camera::GetDirection() const
288{
289        return -Vector3(mViewOrientation.x[0][2], mViewOrientation.x[1][2], mViewOrientation.x[2][2]);
290}
291
292
293Vector3 Camera::GetUpVector() const
294{
295        return Vector3(mViewOrientation.x[0][1], mViewOrientation.x[1][1], mViewOrientation.x[2][1]);
296}
297
298
299Vector3 Camera::GetRightVector() const
300{
301        return Vector3(mViewOrientation.x[0][0], mViewOrientation.x[1][0], mViewOrientation.x[2][0]);           
302}
303
304
305Vector3 Camera::GetBaseDirection() const
306{
307        return -Vector3(mBaseOrientation.x[0][2], mBaseOrientation.x[1][2], mBaseOrientation.x[2][2]);
308}
309
310
311Vector3 Camera::GetBaseUpVector() const
312{
313        return Vector3(mBaseOrientation.x[0][1], mBaseOrientation.x[1][1], mBaseOrientation.x[2][1]);
314}
315
316
317Vector3 Camera::GetBaseRightVector() const
318{
319        return Vector3(mBaseOrientation.x[0][0], mBaseOrientation.x[1][0], mBaseOrientation.x[2][0]);
320}
321
322
323Frustum::Frustum(const Matrix4x4 &trafo)
324{
325        //////////
326        //-- extract the plane equations
327
328        for (int i = 0; i < 4; ++ i)
329        {
330                mClipPlanes[Frustum::RIGHT_PLANE][i] = trafo.x[i][3] - trafo.x[i][0];
331                mClipPlanes[Frustum::LEFT_PLANE][i] = trafo.x[i][3] + trafo.x[i][0];
332                mClipPlanes[Frustum::BOTTOM_PLANE][i] = trafo.x[i][3] + trafo.x[i][1];
333                mClipPlanes[Frustum::TOP_PLANE][i] = trafo.x[i][3] - trafo.x[i][1];
334                mClipPlanes[Frustum::FAR_PLANE][i] = trafo.x[i][3] - trafo.x[i][2];
335                mClipPlanes[Frustum::NEAR_PLANE][i] = trafo.x[i][3] + trafo.x[i][2];
336        }
337}
338
339
340void Frustum::EnclosePolyhedron(const Polyhedron &polyhedron)
341{
342        VertexArray vertices;
343        polyhedron.CollectVertices(vertices);
344
345        for (int i = 0; i < 6; ++ i)
346        {
347                Plane3 &plane = mClipPlanes[i];
348
349                //cout << "p" << i << " " << plane.mD  << endl;
350
351                VertexArray::const_iterator it, it_end = vertices.end();
352
353                float minDist = 1e20;
354
355                for (it = vertices.begin(); it != it_end; ++ it)
356                {
357                        float dist = plane.Distance(*it);
358
359                        if (dist < minDist)
360                        {
361                                cout << "minDist: " << dist << endl;
362                                minDist = dist;
363                        }
364                }
365
366                plane.mD += minDist;
367        }
368}
369
370
371void Frustum::ExtractTransformation(Matrix4x4 &m) const
372{
373        for (int i = 0; i < 4; ++ i)
374        {
375                m.x[i][0] = (mClipPlanes[LEFT_PLANE][i] - mClipPlanes[RIGHT_PLANE][i]) * 0.5f;
376                m.x[i][1] = (mClipPlanes[BOTTOM_PLANE][i] - mClipPlanes[TOP_PLANE][i]) * 0.5f;
377                m.x[i][2] = (mClipPlanes[NEAR_PLANE][i] - mClipPlanes[FAR_PLANE][i]) * 0.5f;
378                m.x[i][3] = (mClipPlanes[LEFT_PLANE][i] + mClipPlanes[RIGHT_PLANE][i]) * 0.5f;
379        }
380}
381
382
383
384}
385
Note: See TracBrowser for help on using the repository browser.