source: branches/VUT/0.2/chcdemo/Geometry.cpp @ 10

Revision 10, 11.6 KB checked in by gametools, 20 years ago (diff)

vienna university of technology first files

Line 
1#include "Geometry.h"
2#include "glInterface.h"
3#include "stdio.h"
4#include "teapot.h"
5#include <math.h>
6
7#define NO_LIST    -1
8#define STRIP_END  -1
9
10int Geometry::num_torus_indices;
11int Geometry::num_torus_vertices;
12int Geometry::num_torus_normals;
13
14const int Geometry::torus_precision = 24;
15const int Geometry::sphere_precision = 24;
16
17float *Geometry::torus_vertices;
18float *Geometry::torus_normals;
19int *Geometry::torus_indices;
20
21// choose size so the glut-rendered sphere is approximately
22// as big as the other objects
23const float Geometry::sphere_radius = 1.0 / 9.0f;
24const float Geometry::torus_inner_radius = 0.05;
25const float Geometry::torus_outer_radius = 0.07;
26
27int Geometry::sDisplayList[NUM_OBJECTS];
28
29bool Geometry::sIsInitialised = Init();
30
31Geometry::Geometry():
32mXRotation(0), mYRotation(0), mZRotation(0), mScale(1.0), mObjectType(TEAPOT)
33{
34        copyVector3Values(mTranslation, 0, 0, 0);
35       
36        SetAmbientColor(0.1745, 0.01175, 0.01175);
37        SetDiffuseColor(0.61424, 0.04136, 0.04136);
38        SetSpecularColor(0.727811, 0.626959, 0.626959);
39       
40        CalcBoundingVolume();
41        CalcTransform();
42        GenerateList();
43}
44
45Geometry::Geometry(Vector3 translation, float xRot, float yRot, float zRot, float scale, int objectType):
46mXRotation(xRot), mYRotation(yRot), mZRotation(zRot), mScale(scale), mObjectType(objectType)
47{
48        copyVector3(mTranslation, translation);
49
50        SetAmbientColor(0.1745, 0.01175, 0.01175);
51        SetDiffuseColor(0.61424, 0.04136, 0.04136);
52        SetSpecularColor(0.727811, 0.626959, 0.626959);
53       
54        CalcBoundingVolume();
55        CalcTransform();
56        GenerateList();
57}
58
59void Geometry::ResetLists()
60{
61        for(int i = 0; i < NUM_OBJECTS; i++)
62        {
63        if(sDisplayList[i] == NO_LIST)
64                        glDeleteLists(sDisplayList[i], 1);
65
66                sDisplayList[i] = NO_LIST;
67        }
68}
69
70void Geometry::CleanUp()
71{
72        ResetLists();
73
74        delete [] torus_vertices;
75        delete [] torus_normals;
76        delete [] torus_indices;
77}
78
79
80bool Geometry::Init()
81{
82        for(int i=0; i < NUM_OBJECTS; i++)
83                sDisplayList[i] = NO_LIST;
84
85        // parameters chosen so torus is approximately as big as teapot
86        CreateTorus(torus_inner_radius, torus_outer_radius, torus_precision);
87
88        return true;
89}
90
91void Geometry::GenerateList()
92{
93        if(sDisplayList[mObjectType] == NO_LIST)
94        {
95                sDisplayList[mObjectType] = glGenLists(1);
96                glNewList(sDisplayList[mObjectType], GL_COMPILE);
97
98                switch(mObjectType)
99                {
100                        case TEAPOT:
101                                RenderTeapot();
102                                break;
103                        case TORUS:
104                                RenderTorus();
105                                break;
106                        case SPHERE:   
107                                RenderSphere();
108                                break;
109                       
110                        default:
111                                break;
112                }
113                glEndList();
114        }
115}
116
117void Geometry::Render()
118{
119        glMaterialfv(GL_FRONT, GL_AMBIENT, mAmbientColor);
120        glMaterialfv(GL_FRONT, GL_DIFFUSE, mDiffuseColor);
121        glMaterialfv(GL_FRONT, GL_SPECULAR, mSpecularColor);
122       
123        glPushMatrix();
124       
125        Transform();
126       
127        glCallList(sDisplayList[mObjectType]);
128
129        glPopMatrix();
130}
131
132
133//! sets rotations around the three axis: executed in the order specified here
134void Geometry::SetRotations(float xRot, float yRot, float zRot)
135{
136        mXRotation = xRot;
137        mYRotation = yRot;
138        mZRotation = zRot;
139
140        CalcBoundingVolume();
141        CalcTransform();
142}
143
144
145void Geometry::SetTranslation(Vector3 translation)
146{
147        copyVector3(mTranslation, translation);
148
149        CalcBoundingVolume();
150        CalcTransform();
151}
152
153
154void Geometry::SetScale(float scale)
155{
156        mScale = scale;
157        CalcTransform();
158
159        CalcBoundingVolume();
160}
161
162
163void Geometry::SetAmbientColor(float ambientR, float ambientG, float ambientB)
164{
165        mAmbientColor[0] = ambientR;
166        mAmbientColor[1] = ambientG;
167        mAmbientColor[2] = ambientB;
168}
169
170
171void Geometry::SetDiffuseColor(float diffuseR, float diffuseG, float diffuseB)
172{
173        mDiffuseColor[0] = diffuseR;
174        mDiffuseColor[1] = diffuseG;
175        mDiffuseColor[2] = diffuseB;
176}
177
178
179void Geometry::SetSpecularColor(float specularR, float specularG, float specularB)
180{
181        mSpecularColor[0] = specularR;
182        mSpecularColor[1] = specularG;
183        mSpecularColor[2] = specularB;
184}
185
186
187float Geometry::GetScale()
188{
189        return mScale;
190}
191
192
193void Geometry::GetTranslation(Vector3 translation)
194{
195        copyVector3(translation, mTranslation);
196}
197
198
199void Geometry::GetRotations(float &xRot, float &yRot, float &zRot)
200{
201        xRot = mXRotation;
202        yRot = mYRotation;
203        zRot = mZRotation;
204}
205
206       
207const AABox &Geometry::GetBoundingVolume()
208{
209        return mBoundingBox;
210}
211
212
213void Geometry::SetLastVisited(int lastVisited)
214{
215        mLastVisited = lastVisited;
216}
217
218
219int Geometry::GetLastVisited()
220{
221        return mLastVisited;
222}
223
224
225void Geometry::SetObjectType(int type)
226{
227        mObjectType = type;
228        GenerateList();
229}
230
231
232void Geometry::RenderTeapot()
233{
234        int i = 0;
235
236        while(i < num_teapot_indices)
237        {
238                glBegin(GL_TRIANGLE_STRIP);
239                        while(teapot_indices[i] != STRIP_END)
240                        {       
241                                int index = teapot_indices[i] * 3;
242                               
243                                glNormal3fv(teapot_normals + index);
244                                glVertex3fv(teapot_vertices + index);
245                               
246                                i++;           
247                        }
248                glEnd();
249               
250                i++; // skip strip end flag
251        }
252}
253
254void Geometry::CalcBoundingVolume()
255{
256    switch(mObjectType)
257        {
258                case TORUS:
259                        CalcBoundingVolume(torus_vertices, num_torus_vertices);
260                        break;
261                case SPHERE:
262                        CalcSphereBoundingVolume();
263                        break;
264                case TEAPOT:
265                        CalcBoundingVolume(teapot_vertices, num_teapot_vertices);
266                        break;
267                default:
268                        break;
269        }
270}
271
272
273void Geometry::CalcBoundingVolume(float *vertices, const int num_vertices)
274{
275        Vector3 *rotatedPoints = new Vector3[num_vertices];
276       
277        for(int i = 0; i < num_vertices; i++)
278        {
279                copyVector3Values(rotatedPoints[i], vertices[i * 3],
280                                                  vertices[i * 3 + 1], vertices[i * 3 + 2]);
281       
282                rotateVectorZ(rotatedPoints[i], mZRotation * PI_180);
283                rotateVectorY(rotatedPoints[i], mYRotation * PI_180);
284                rotateVectorX(rotatedPoints[i], mXRotation * PI_180);
285        }
286
287        calcCubicHull(mBoundingBox.min, mBoundingBox.max, rotatedPoints, num_vertices);
288
289        for(int i=0; i< 3; i++)
290        {
291                mBoundingBox.min[i] *= mScale;
292                mBoundingBox.max[i] *= mScale;
293        }
294
295        addVector3(mBoundingBox.min, mTranslation, mBoundingBox.min);
296    addVector3(mBoundingBox.max, mTranslation, mBoundingBox.max);
297
298        delete [] rotatedPoints;
299}
300
301
302void Geometry::CalcSphereBoundingVolume()
303{
304        float len = mScale * sphere_radius;
305        Vector3 size = {len, len, len};
306                                       
307        diffVector3(mBoundingBox.min, mTranslation, size);
308        addVector3(mBoundingBox.max, mTranslation, size);
309}
310
311
312void Geometry::RenderTorus()
313{
314        glVertexPointer(3, GL_FLOAT, sizeof(float), torus_vertices);
315        glEnableClientState(GL_VERTEX_ARRAY);
316
317        glNormalPointer(GL_FLOAT, sizeof(float), torus_normals);
318        glEnableClientState(GL_NORMAL_ARRAY);
319
320    glDrawElements(GL_TRIANGLES, num_torus_indices, GL_UNSIGNED_INT, torus_indices);
321
322        glDisableClientState(GL_VERTEX_ARRAY);
323        glDisableClientState(GL_NORMAL_ARRAY);
324}
325
326/*
327        creates a torus with specified radii, with number of rings and ring
328        subdivision = precision.
329*/
330void Geometry::CreateTorus(float innerRadius, float outerRadius, int precision)
331{
332        num_torus_vertices = num_torus_normals = (precision + 1) * (precision + 1);
333        num_torus_indices = 2 * precision * precision * 3;
334
335        torus_vertices = new float[num_torus_vertices * 3];
336        torus_normals = new float[num_torus_normals * 3];
337        torus_indices = new int[num_torus_indices];
338
339        for(int i=0; i<precision+1; i++)
340        {
341                int index = i * 3;
342
343                Vector3 currentVertex = {innerRadius, 0.0f, 0.0f};
344                rotateVectorZ(currentVertex, ((float)i * 2.0 * PI) / (float)precision);
345
346                currentVertex[0] += outerRadius;
347               
348                Vector3 sTangent = {0.0f, 0.0f, -1.0f};
349                Vector3 tTangent = {0, -1, 0};
350                rotateVectorZ(tTangent, ((float)i * 2.0 * PI) / (float)precision);
351
352        Vector3 currentNormal;
353
354                cross(currentNormal, tTangent, sTangent);
355
356                torus_normals[index + 0] = currentNormal[0];
357                torus_normals[index + 1] = currentNormal[1];
358                torus_normals[index + 2] = currentNormal[2];
359               
360                torus_vertices[index + 0] = currentVertex[0];
361                torus_vertices[index + 1] = currentVertex[1];
362                torus_vertices[index + 2] = currentVertex[2];
363        }
364
365        for(int i_rng=1; i_rng<precision+1; ++i_rng)
366        {
367                for(int i=0; i<precision+1; ++i)
368                {
369                        int index = 3 * (i_rng * (precision + 1) + i);
370
371                        Vector3 currentVertex = {torus_vertices[i*3], torus_vertices[i*3+1], torus_vertices[i*3+2]};
372                       
373                        rotateVectorY(currentVertex, ((float)i_rng * 2.0 * PI) / (float)precision);
374                                               
375                        Vector3 currentNormal = {torus_normals[i*3], torus_normals[i*3+1], torus_normals[i*3+2]};
376                       
377                        rotateVectorY(currentNormal, ((float)i_rng * 2.0 * PI) / (float)precision);
378
379                        torus_normals[index + 0] = currentNormal[0];
380                        torus_normals[index + 1] = currentNormal[1];
381                        torus_normals[index + 2] = currentNormal[2];
382               
383                        torus_vertices[index + 0] = currentVertex[0];
384                        torus_vertices[index + 1] = currentVertex[1];
385                        torus_vertices[index + 2] = currentVertex[2];
386                }
387        }
388
389        for(i_rng=0; i_rng<precision; ++i_rng)
390        {
391                for(i=0; i<precision; ++i)
392                {
393                        int index = ((i_rng * precision + i) * 2) * 3;
394
395                        torus_indices[index+0] = (i_rng     * (precision+1) + i)*3;
396                        torus_indices[index+1] = ((i_rng+1) * (precision+1) + i)*3;
397                        torus_indices[index+2] = (i_rng     * (precision+1) + i + 1)*3;
398
399                        index = ((i_rng * precision + i) * 2 + 1) * 3;
400
401                        torus_indices[index+0] = (i_rng     * (precision+1) + i + 1)*3;
402                        torus_indices[index+1] = ((i_rng+1) * (precision+1) + i)*3;
403                        torus_indices[index+2] = ((i_rng+1) * (precision+1) + i + 1)*3;
404                }
405        }
406}
407
408/**
409        counts the triangles of the teapot.
410        traverses through all the triangle strips.
411*/
412int Geometry::CountTeapotTriangles()
413{
414        int result = 0;
415        int i=0;
416        // n - 2 triangles are drawn for a strip
417        while(i < num_teapot_indices)
418        {
419                while(teapot_indices[i] != STRIP_END)
420                {       
421                        result ++;;
422                        i++;           
423                }
424                result -= 2;
425                i++; // skip STRIP_END
426        }
427        return result;
428}
429
430/**
431        counts the triangles of the torus
432*/
433int Geometry::CountTorusTriangles()
434{
435        // every 3 indices specify one triangle
436        return num_torus_indices / 3;
437}
438
439/**
440        counts the triangles of the sphere.
441        sphere_precision / 2 + 1 strips with sphere_precision * 2 - 2 triangles each
442*/
443int Geometry::CountSphereTriangles()
444{
445        return sphere_precision * sphere_precision;
446}
447
448
449int Geometry::CountTriangles(int objectType)
450{
451        int result = 0;
452
453        switch(objectType)
454        {
455                case TEAPOT:
456                        result = CountTeapotTriangles();
457                        break;
458                case TORUS:
459                        result = CountTorusTriangles();
460                        break;
461                case SPHERE:   
462                        result = CountSphereTriangles();
463                        break;
464                default:
465                        break;
466        }
467        return result;
468}
469
470
471void Geometry::Transform()
472{
473        glMultMatrixd(mTransform);
474}
475
476void Geometry::CalcTransform()
477{
478        Matrix4x4 scale;
479        Matrix4x4 xrot;
480        Matrix4x4 yrot;
481        Matrix4x4 zrot;
482        Matrix4x4 transl;
483
484        makeScaleMtx(scale, mScale, mScale, mScale);
485        makeTranslationMtx(transl, mTranslation);
486        makeRotationXMtx(xrot, mXRotation * PI_180);
487        makeRotationYMtx(yrot, mYRotation * PI_180);
488        makeRotationZMtx(zrot, mZRotation * PI_180);
489
490        copyMatrix(mTransform, IDENTITY);
491        mult(mTransform, mTransform, transl);
492        mult(mTransform, mTransform, xrot);
493        mult(mTransform, mTransform, yrot);
494        mult(mTransform, mTransform, zrot);
495        mult(mTransform, mTransform, scale);
496}
497
498/**
499   renders a sphere with sphere_precision subdivisions.
500   note: works only for even sphere_precision
501*/
502void Geometry::RenderSphere()
503{
504        Vector3 vertex;
505
506        // this algorithm renders the triangles clockwise
507        glFrontFace(GL_CW);
508
509        for (int j = 0; j < sphere_precision/2; ++j)
510        {
511                double alpha = j * PI * 2.0 / (double)sphere_precision - PI_2;
512                double beta = (j + 1) * PI * 2.0 / (double)sphere_precision - PI_2;
513
514                glBegin(GL_TRIANGLE_STRIP);
515
516                for (int i = 0; i <= sphere_precision; ++i)
517                {
518                        double gamma = i * PI * 2.0 / (double)sphere_precision;
519       
520                        vertex[0] = sphere_radius * cos(beta) * cos(gamma);
521                        vertex[1] = sphere_radius * sin(beta);
522                        vertex[2] = sphere_radius * cos(beta) * sin(gamma);
523
524                        glNormal3dv(vertex);
525                        glVertex3dv(vertex);
526
527                        vertex[0] = sphere_radius * cos(alpha) * cos(gamma);
528                        vertex[1] = sphere_radius * sin(alpha);
529                        vertex[2] = sphere_radius * cos(alpha) * sin(gamma);
530
531                    glNormal3dv(vertex);
532                        glVertex3dv(vertex);
533
534                }
535                glEnd();
536        }
537        glFrontFace(GL_CCW);
538}
Note: See TracBrowser for help on using the repository browser.