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

Revision 2944, 8.3 KB checked in by mattausch, 16 years ago (diff)

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