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

Revision 2947, 8.2 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
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,
140                                                                   float farthestVisibleDistance) const
141{
142        float z_near = mNear;
143        float z_far = min(mFar, farthestVisibleDistance);
144
145        float fov = mFovy;
146
147        const float aspectRatio = GetAspect();
148
149        const float h_near = tan(fov * 0.5f) * z_near;
150        const float w_near = h_near * aspectRatio;
151
152        const float h_far = tan(fov * 0.5f) * z_far;
153        const float w_far = h_far * aspectRatio;
154
155        const Vector3 fc = pos + view * z_far;
156       
157        Vector3 t1, t2;
158
159        t1 = h_far * up;
160        t2 = w_far * right;
161
162        ftl = fc + t1 - t2;
163        ftr = fc + t1 + t2;
164        fbl = fc - t1 - t2;
165        fbr = fc - t1 + t2;
166
167        const Vector3 nc = pos + view * z_near;
168       
169        t1 = h_near * up;
170        t2 = w_near * right;
171
172        ntl = nc + t1 - t2;
173        ntr = nc + t1 + t2;
174        nbl = nc - t1 - t2;
175        nbr = nc - t1 + t2;
176}
177
178
179void Camera::ComputePoints(Vector3 &ftl, Vector3 &ftr, Vector3 &fbl, Vector3 &fbr,
180                                                   Vector3 &ntl, Vector3 &ntr, Vector3 &nbl, Vector3 &nbr,
181                                                   float farthestVisibleDistance) const
182{
183        ComputePointsInternal(ftl, ftr, fbl, fbr, ntl, ntr, nbl, nbr,
184                                                  GetDirection(), GetRightVector(), GetUpVector(), GetPosition(),
185                                                  farthestVisibleDistance);
186}
187
188
189void Camera::SetOrtho(bool ortho)
190{
191        mIsOrtho = true;
192}
193
194
195void Camera::Yaw(float angle)
196{
197        mYaw += angle;
198        CalculateFromPitchAndYaw();
199}
200
201
202void Camera::Pitch(float angle)
203{
204        mPitch += angle;
205        CalculateFromPitchAndYaw();
206}
207
208
209void Camera::SetDirection(const Vector3 &dir)
210{
211        Vector3 ndir = -Normalize(dir);
212
213        mPitch = -atan2(ndir.x, ndir.y);
214        mYaw = atan2(ndir.z, sqrt((ndir.x * ndir.x) + (ndir.y * ndir.y)));
215
216        CalculateFromPitchAndYaw();
217}
218
219
220void Camera::CalculateFromPitchAndYaw()
221{
222        mViewOrientation = mBaseOrientation;
223
224        Matrix4x4 roty = RotationYMatrix(mPitch);
225        Matrix4x4 rotx = RotationXMatrix(mYaw);
226
227        mViewOrientation *= roty;
228        mViewOrientation *= rotx;
229}
230
231
232Vector3 Camera::GetDirection() const
233{
234        return -Vector3(mViewOrientation.x[0][2], mViewOrientation.x[1][2], mViewOrientation.x[2][2]);
235}
236
237
238Vector3 Camera::GetUpVector() const
239{
240        return Vector3(mViewOrientation.x[0][1], mViewOrientation.x[1][1], mViewOrientation.x[2][1]);
241}
242
243
244Vector3 Camera::GetRightVector() const
245{
246        return Vector3(mViewOrientation.x[0][0], mViewOrientation.x[1][0], mViewOrientation.x[2][0]);           
247}
248
249
250Vector3 Camera::GetBaseDirection() const
251{
252        return -Vector3(mBaseOrientation.x[0][2], mBaseOrientation.x[1][2], mBaseOrientation.x[2][2]);
253}
254
255
256Vector3 Camera::GetBaseUpVector() const
257{
258        return Vector3(mBaseOrientation.x[0][1], mBaseOrientation.x[1][1], mBaseOrientation.x[2][1]);
259}
260
261
262Vector3 Camera::GetBaseRightVector() const
263{
264        return Vector3(mBaseOrientation.x[0][0], mBaseOrientation.x[1][0], mBaseOrientation.x[2][0]);
265}
266
267
268Frustum::Frustum(const Matrix4x4 &trafo)
269{
270        //////////
271        //-- extract the plane equations
272
273        for (int i = 0; i < 4; ++ i)
274        {
275                mClipPlanes[Frustum::RIGHT_PLANE][i] = trafo.x[i][3] - trafo.x[i][0];
276                mClipPlanes[Frustum::LEFT_PLANE][i] = trafo.x[i][3] + trafo.x[i][0];
277               
278                mClipPlanes[Frustum::BOTTOM_PLANE][i] = trafo.x[i][3] + trafo.x[i][1];
279                mClipPlanes[Frustum::TOP_PLANE][i] = trafo.x[i][3] - trafo.x[i][1];
280
281                mClipPlanes[Frustum::FAR_PLANE][i] = trafo.x[i][3] - trafo.x[i][2];
282                mClipPlanes[Frustum::NEAR_PLANE][i] = trafo.x[i][3] + trafo.x[i][2];
283        }
284}
285
286
287void Frustum::EnclosePolyhedron(const Polyhedron &polyhedron)
288{
289        VertexArray vertices;
290        polyhedron.CollectVertices(vertices);
291
292        for (int i = 0; i < 6; ++ i)
293        {
294                Plane3 &plane = mClipPlanes[i];
295
296                //cout << "p" << i << " " << plane.mD  << endl;
297
298                VertexArray::const_iterator it, it_end = vertices.end();
299
300                float minDist = 1e20;
301
302                for (it = vertices.begin(); it != it_end; ++ it)
303                {
304                        float dist = plane.Distance(*it);
305
306                        if (dist < minDist)
307                        {
308                                cout << "minDist: " << dist << endl;
309                                minDist = dist;
310                        }
311                }
312
313                plane.mD += minDist;
314        }
315}
316
317
318void Frustum::ExtractTransformation(Matrix4x4 &m) const
319{
320        for (int i = 0; i < 4; ++ i)
321        {
322                m.x[i][0] = (mClipPlanes[LEFT_PLANE][i] - mClipPlanes[RIGHT_PLANE][i]) * 0.5f;
323                m.x[i][1] = (mClipPlanes[BOTTOM_PLANE][i] - mClipPlanes[TOP_PLANE][i]) * 0.5f;
324                m.x[i][2] = (mClipPlanes[NEAR_PLANE][i] - mClipPlanes[FAR_PLANE][i]) * 0.5f;
325                m.x[i][3] = (mClipPlanes[LEFT_PLANE][i] + mClipPlanes[RIGHT_PLANE][i]) * 0.5f;
326        }
327}
328
329
330Polyhedron *Camera::ComputeFrustum(float farthestVisibleDistance) const
331{
332        Vector3 ftl, ftr, fbl, fbr;
333        Vector3 ntl, ntr, nbl, nbr;
334
335        VertexArray sides[6];
336
337        ComputePoints(ftl, ftr, fbl, fbr, ntl, ntr, nbl, nbr, farthestVisibleDistance);
338
339        for (int i = 0; i < 6; ++ i)
340                sides[i].resize(4);
341       
342        // left, right
343        sides[0][0] = ftl; sides[0][1] = fbl; sides[0][2] = nbl; sides[0][3] = ntl;
344        sides[1][0] = fbr; sides[1][1] = ftr; sides[1][2] = ntr; sides[1][3] = nbr;
345        // bottom, top
346        sides[2][0] = fbl; sides[2][1] = fbr; sides[2][2] = nbr; sides[2][3] = nbl;
347        sides[3][0] = ftr; sides[3][1] = ftl; sides[3][2] = ntl; sides[3][3] = ntr;
348        // near, far
349        sides[4][0] = ntr; sides[4][1] = ntl; sides[4][2] = nbl; sides[4][3] = nbr;
350        sides[5][0] = ftl; sides[5][1] = ftr; sides[5][2] = fbr; sides[5][3] = fbl;
351
352
353        //////////
354        //-- compute polyhedron
355
356        PolygonContainer polygons;
357
358        for (int i = 0; i < 6; ++ i)
359        {
360                Polygon3 *poly = new Polygon3(sides[i]);
361                polygons.push_back(poly);
362        }
363
364        return new Polyhedron(polygons);
365}
366
367
368}
Note: See TracBrowser for help on using the repository browser.