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

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