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

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