Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/graphics/importer/vertex_array_model.cc @ 6009

Last change on this file since 6009 was 6009, checked in by bensch, 18 years ago

orxonox/trunk: abstract model implementation in .cc

@patrick: do you aprove?

File size: 30.3 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   ### File Specific:
12   main-programmer: Benjamin Grauer
13   co-programmer: ...
14
15   2005-07-06: (Patrick) added new function buildTriangleList()
16*/
17
18#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_IMPORTER
19
20#include "vertex_list_model.h"
21
22#include "stdlibincl.h"
23#include <stdarg.h>
24
25#include "vector.h"
26
27using namespace std;
28
29/////////////
30/// MODEL ///
31/////////////
32/**
33 *  Creates a 3D-Model.
34
35   assigns it a Name and a Type
36*/
37Model::Model(const char* modelName, MODEL_TYPE type)
38{
39  this->setClassID(CL_MODEL, "Model");
40  PRINTF(4)("new 3D-Model is being created\n");
41  this->setName(modelName);
42  this->type = type;
43
44  this->finalized = false;
45  // setting the start group;
46
47  this->scaleFactor = 1;
48
49  this->vertices = new tArray<GLfloat>();
50  this->vTexture = new tArray<GLfloat>();
51  this->normals = new tArray<GLfloat>();
52
53  if (this->type == MODEL_VERTEX_ARRAY)
54    glEnableClientState(GL_VERTEX_ARRAY | GL_NORMAL_ARRAY | GL_TEXTURE_COORD_ARRAY);
55}
56
57/**
58 *  deletes an Model.
59
60   Looks if any from model allocated space is still in use, and if so deleted it.
61*/
62Model::~Model()
63{
64  PRINTF(4)("Deleting Model ");
65  if (this->getName())
66  {
67    PRINT(4)("%s\n", this->getName());
68  }
69  else
70  {
71    PRINT(4)("\n");
72  }
73  this->cleanup();
74
75  PRINTF(5)("Deleting display Lists.\n");
76  delete this->firstGroup;
77
78  // deleting Arrays (if not allready done by finalize)
79  this->deleteArrays();
80
81  // deleting the MaterialList
82  PRINTF(5)("Deleting Materials.\n");
83
84  //! @todo do we really have to delete this material??
85  list<ModelMaterial*>::iterator modMat;
86  for(modMat = this->materialList.begin(); modMat != this->materialList.end(); modMat++)
87  {
88    if (!(*modMat)->external)
89      delete (*modMat)->material;
90    delete (*modMat);
91  }
92  delete this->pModelInfo;
93}
94
95/**
96 *  Finalizes an Object. This can be done outside of the Class.
97*/
98void Model::finalize()
99{
100  // this creates the display List.
101  this->importToDisplayList();
102  this->buildTriangleList();
103
104  // deletes everything we allocated.
105  //if (this->type == MODEL_DISPLAY_LIST)
106    //this->deleteArrays();
107  //  this->cleanup();
108
109  /* load the ModelInfo */
110  this->pModelInfo = new modelInfo;
111  this->pModelInfo->numVertices = this->vertexCount;
112  this->pModelInfo->pVertices = this->vertices->getArray();
113  this->pModelInfo->numTriangles = this->triangleCount;
114  this->pModelInfo->pTriangles = this->triangles;
115  this->pModelInfo->numNormals = this->normalCount;
116  this->pModelInfo->pNormals = this->normals->getArray();
117  this->pModelInfo->numTexCoor = this->vTexture->getCount();
118  this->pModelInfo->pTexCoor = this->vTexture->getArray();
119
120  this->finalized = true;
121}
122
123/**
124 * rebuild the Model from the Information we got.
125 */
126void Model::rebuild()
127{
128  PRINTF(3)("Rebuilding Model '%s'\n", this->getName());
129  this->finalize();
130
131}
132
133//////////
134// DRAW //
135//////////
136/**
137 *  Draws the Models of all Groups.
138   It does this by just calling the Lists that must have been created earlier.
139*/
140void Model::draw () const
141{
142
143  PRINTF(4)("drawing the 3D-Models\n");
144  ModelGroup* tmpGroup = this->firstGroup;
145  while (tmpGroup != NULL)
146    {
147      PRINTF(5)("Drawing model %s\n", tmpGroup->name);
148      glCallList (tmpGroup->listNumber);
149      tmpGroup = tmpGroup->next;
150    }
151
152
153/*  const GLfloat* pVertices = NULL;
154  const GLfloat* pNorm = NULL;
155
156  glBegin(GL_TRIANGLES);
157  for( int i = 0; i < this->triangleCount; ++i)
158  {
159    //printf("int i = %i\n", i);
160    pNorm = &this->normals->getArray()[this->triangles[i].indexToNormals[0]];
161    pVertices = &this->vertices->getArray()[this->triangles[i].indexToVertices[0]];
162    glNormal3f(pNorm[0], pNorm[1], pNorm[2]);
163    glVertex3f(pVertices[0], pVertices[1], pVertices[2]);
164
165    pNorm = &this->normals->getArray()[this->triangles[i].indexToNormals[1]];
166    pVertices = &this->vertices->getArray()[this->triangles[i].indexToVertices[1]];
167    glNormal3f(pNorm[0], pNorm[1], pNorm[2]);
168    glVertex3f(pVertices[0], pVertices[1], pVertices[2]);
169
170    pNorm = &this->normals->getArray()[this->triangles[i].indexToNormals[2]];
171    pVertices = &this->vertices->getArray()[this->triangles[i].indexToVertices[2]];
172    glNormal3f(pNorm[0], pNorm[1], pNorm[2]);
173    glVertex3f(pVertices[0], pVertices[1], pVertices[2]);
174
175  }
176  glEnd();*/
177}
178
179/**
180 *  Draws the Model number groupNumber
181 * @param groupNumber The number of the group that will be displayed.
182
183   It does this by just calling the List that must have been created earlier.
184*/
185void Model::draw (int groupNumber) const
186{
187  if (groupNumber >= this->groupCount)
188    {
189      PRINTF(2)("You requested model number %i, but this File only contains of %i Models.\n", groupNumber-1, this->groupCount);
190      return;
191    }
192  PRINTF(4)("drawing the requested 3D-Models if found.\n");
193  ModelGroup* tmpGroup = this->firstGroup;
194  int counter = 0;
195  while (tmpGroup != NULL)
196    {
197      if (counter == groupNumber)
198        {
199          PRINTF(4)("Drawing model number %i named %s\n", counter, tmpGroup->name);
200          glCallList (tmpGroup->listNumber);
201          return;
202        }
203      ++counter;
204      tmpGroup = tmpGroup->next;
205    }
206  PRINTF(2)("Model number %i in %s not Found.\n", groupNumber, this->getName());
207  return;
208
209}
210
211/**
212 *  Draws the Model with a specific groupName
213 * @param groupName The name of the group that will be displayed.
214
215   It does this by just calling the List that must have been created earlier.
216*/
217void Model::draw (char* groupName) const
218{
219  PRINTF(4)("drawing the requested 3D-Models if found.\n");
220  ModelGroup* tmpGroup = this->firstGroup;
221  while (tmpGroup != NULL)
222    {
223      if (!strcmp(tmpGroup->name, groupName))
224        {
225          PRINTF(4)("Drawing model %s\n", tmpGroup->name);
226          glCallList (tmpGroup->listNumber);
227          return;
228        }
229      tmpGroup = tmpGroup->next;
230    }
231  PRINTF(2)("Model Named %s in %s not Found.\n", groupName, this->getName());
232  return;
233}
234
235//////////
236// INIT //
237//////////
238/**
239 *  deletes all the arrays
240*/
241bool Model::deleteArrays()
242{
243  if (this->vertices)
244    delete this->vertices;
245  if (this->vTexture)
246    delete this->vTexture;
247  if (this->normals)
248    delete this->normals;
249  if (this->triangles)
250    delete[] this->triangles;
251
252  this->vertices = NULL;
253  this->vTexture = NULL;
254  this->normals = NULL;
255  this->triangles = NULL;
256  this->triangleCount = 0;
257}
258
259/**
260 *  finalizes an Model.
261 * This funcion is needed, to delete all the Lists, and arrays that are no more
262 * needed because they are already imported into openGL.
263 * This will be applied at the end of the importing Process.
264*/
265bool Model::cleanup()
266{
267  PRINTF(4)("cleaning up the 3D-Model to save Memory.\n");
268  this->firstGroup->cleanup();
269  return true;
270}
271
272//////////
273// MESH //
274//////////
275/**
276 * adds a new Material to the Material List
277 * @param material the Material to add
278 * @returns the added material
279 *
280 * this also tells this Model, that all the Materials are handled externally
281 * with this option set the Materials will not be deleted with the Model.
282 */
283Material* Model::addMaterial(Material* material)
284{
285  if (material == NULL)
286    return NULL;
287  ModelMaterial* modMat = new ModelMaterial;
288  modMat->external = true;
289  modMat->material = material;
290  this->materialList.push_back(modMat);
291  return modMat->material;
292}
293
294/**
295 *  adds a new Material to the Material List
296 * @param materialName the name of the Material to add
297 * @returns the added material
298*/
299Material* Model::addMaterial(const char* materialName)
300{
301  ModelMaterial* modMat = new ModelMaterial;
302  modMat->external = false;
303  modMat->material = new Material(materialName);
304
305  // adding material to the List of materials
306  this->materialList.push_back(modMat);
307  return modMat->material;
308}
309
310/**
311 *  finds a Material by its name and returns it
312 * @param materialName the Name of the material to search for.
313 * @returns the Material if found, NULL otherwise
314*/
315Material* Model::findMaterialByName(const char* materialName)
316{
317  list<ModelMaterial*>::iterator modMat;
318  for  (modMat = this->materialList.begin(); modMat != this->materialList.end(); modMat++)
319    if (!strcmp((*modMat)->material->getName(), materialName))
320      return (*modMat)->material;
321  return NULL;
322}
323
324/**
325 *  parses a group String
326 * @param groupString the new Group to create
327
328   This function initializes a new Group.
329   With it you should be able to create Models with more than one SubModel inside
330*/
331bool Model::addGroup(const char* groupString)
332{
333  PRINTF(5)("Read Group: %s.\n", groupString);
334  if (this->groupCount != 0 && this->currentGroup->faceCount > 0)
335    {
336      // finalizeGroup(currentGroup);
337      this->currentGroup = this->currentGroup->next = new ModelGroup;
338    }
339  // setting the group name if not default.
340  if (strcmp(groupString, "default"))
341    {
342      this->currentGroup->name = new char [strlen(groupString)+1];
343      strcpy(this->currentGroup->name, groupString);
344    }
345  ++this->groupCount;
346}
347
348/**
349 *  parses a vertex-String
350 * @param vertexString The String that will be parsed.
351
352   If a vertex line is found this function will inject it into the vertex-Array
353*/
354bool Model::addVertex (const char* vertexString)
355{
356  float subbuffer1;
357  float subbuffer2;
358  float subbuffer3;
359  sscanf (vertexString, "%f %f %f", &subbuffer1, &subbuffer2, &subbuffer3);
360  this->vertices->addEntry(subbuffer1*scaleFactor, subbuffer2*scaleFactor, subbuffer3*scaleFactor);
361  this->vertexCount++;
362  return true;
363}
364
365/**
366 *  parses a vertex-String
367 * @param x the X-coordinate of the Vertex to add.
368 * @param y the Y-coordinate of the Vertex to add.
369 * @param z the Z-coordinate of the Vertex to add.
370
371*/
372bool Model::addVertex(float x, float y, float z)
373{
374  PRINTF(5)("reading in a vertex: %f %f %f\n", x, y, z);
375  this->vertices->addEntry(x*scaleFactor, y*scaleFactor, z*scaleFactor);
376  this->vertexCount++;
377  return true;
378}
379
380/**
381 *  parses a vertexNormal-String
382 * @param normalString The String that will be parsed.
383
384   If a vertexNormal line is found this function will inject it into the vertexNormal-Array
385*/
386bool Model::addVertexNormal (const char* normalString)
387{
388  float subbuffer1;
389  float subbuffer2;
390  float subbuffer3;
391  sscanf (normalString, "%f %f %f", &subbuffer1, &subbuffer2, &subbuffer3);
392  this->normals->addEntry(subbuffer1, subbuffer2, subbuffer3);
393  this->normalCount++;
394  return true;
395}
396
397/**
398 *  adds a VertexNormal.
399 * @param x The x coordinate of the Normal.
400 * @param y The y coordinate of the Normal.
401 * @param z The z coordinate of the Normal.
402
403   If a vertexNormal line is found this function will inject it into the vertexNormal-Array
404*/
405bool Model::addVertexNormal(float x, float y, float z)
406{
407  PRINTF(5)("found vertex-Normal %f, %f, %f\n", x, y, z);
408  this->normals->addEntry(x, y, z);
409  this->normalCount++;
410  return true;
411}
412
413/**
414 *  parses a vertexTextureCoordinate-String
415 * @param vTextureString The String that will be parsed.
416
417   If a vertexTextureCoordinate line is found,
418   this function will inject it into the vertexTexture-Array
419
420   !! WARNING THIS IS DIFFERNT FROM addVervexTexture(float, float); because it changes the second entry to 1-v !!
421*/
422bool Model::addVertexTexture (const char* vTextureString)
423{
424  float subbuffer1;
425  float subbuffer2;
426  sscanf (vTextureString, "%f %f", &subbuffer1, &subbuffer2);
427  this->vTexture->addEntry(subbuffer1);
428  this->vTexture->addEntry(1 - subbuffer2);
429  this->texCoordCount++;
430  return true;
431}
432
433/**
434 *  adds a Texture Coordinate
435 * @param u The u coordinate of the TextureCoordinate.
436 * @param v The y coordinate of the TextureCoordinate.
437
438   If a TextureCoordinate line is found this function will inject it into the TextureCoordinate-Array
439*/
440bool Model::addVertexTexture(float u, float v)
441{
442  PRINTF(5)("found vertex-Texture %f, %f\n", u, v);
443  this->vTexture->addEntry(u);
444  this->vTexture->addEntry(v);
445  this->texCoordCount++;
446  return true;
447}
448
449/**
450 *  parses a face-string
451 * @param faceString The String that will be parsed.
452
453   If a face line is found this function will add it to the glList.
454
455   String is different from the argument addFace, in this that the first Vertex/Normal/Texcoord is 1 instead of 0
456*/
457bool Model::addFace (const char* faceString)
458{
459  if (this->currentGroup->faceCount >0)
460    this->currentGroup->currentFace = this->currentGroup->currentFace->next = new ModelFace;
461
462  ModelFaceElement* tmpElem = this->currentGroup->currentFace->firstElem = new ModelFaceElement;
463  tmpElem->next = NULL;
464  while(strcmp (faceString, "\0"))
465    {
466      if (this->currentGroup->currentFace->vertexCount>0)
467          tmpElem = tmpElem->next = new ModelFaceElement;
468      tmpElem->next = NULL;
469
470      char tmpValue [50];
471      int tmpLen;
472      char* vertex = NULL;
473      char* texture = NULL;
474      char* normal = NULL;
475
476      sscanf (faceString, "%s", tmpValue);
477      tmpLen = strlen(tmpValue);
478      vertex = tmpValue;
479
480      if ((texture = strstr (vertex, "/")) != NULL)
481        {
482          texture[0] = '\0';
483          texture ++;
484
485          if ((normal = strstr (texture, "/")) !=NULL)
486            {
487              normal[0] = '\0';
488              normal ++;
489            }
490        }
491      if (vertex)
492        tmpElem->vertexNumber = atoi(vertex)-1;
493      if (texture)
494        tmpElem->texCoordNumber = atoi(texture)-1;
495      if (normal)
496        tmpElem->normalNumber = atoi(normal)-1;
497
498      faceString += tmpLen;
499      if (strcmp (faceString, "\0"))
500        faceString++;
501      this->currentGroup->currentFace->vertexCount++;
502    }
503
504  this->currentGroup->faceCount += this->currentGroup->currentFace->vertexCount -2;
505  this->faceCount += this->currentGroup->currentFace->vertexCount -2;
506}
507
508/**
509 *  adds a new Face
510 * @param faceElemCount the number of Vertices to add to the Face.
511 * @param type The information Passed with each Vertex
512*/
513bool Model::addFace(int faceElemCount, VERTEX_FORMAT type, ...)
514{
515  if (this->currentGroup->faceCount > 0)
516    this->currentGroup->currentFace = this->currentGroup->currentFace->next = new ModelFace;
517
518  ModelFaceElement* tmpElem = this->currentGroup->currentFace->firstElem = new ModelFaceElement;
519
520  va_list itemlist;
521  va_start (itemlist, type);
522
523  for (int i = 0; i < faceElemCount; i++)
524    {
525      if (this->currentGroup->currentFace->vertexCount > 0)
526        tmpElem = tmpElem->next = new ModelFaceElement;
527
528      tmpElem->vertexNumber = va_arg (itemlist, int);
529      if (type & TEXCOORD)
530        tmpElem->texCoordNumber = va_arg (itemlist, int);
531      if (type & NORMAL)
532        tmpElem->normalNumber = va_arg(itemlist, int);
533      this->currentGroup->currentFace->vertexCount++;
534    }
535  va_end(itemlist);
536
537  this->currentGroup->faceCount += this->currentGroup->currentFace->vertexCount - 2;
538  this->faceCount += this->currentGroup->currentFace->vertexCount -2;
539}
540
541/**
542 * Function that selects a material, if changed in the obj file.
543 * @param matString the Material that will be set.
544*/
545bool Model::setMaterial(const char* matString)
546{
547  if (this->currentGroup->faceCount > 0)
548    this->currentGroup->currentFace = this->currentGroup->currentFace->next = new ModelFace;
549
550  this->currentGroup->currentFace->material = this->findMaterialByName(matString);
551
552  if (this->currentGroup->faceCount == 0)
553    this->currentGroup->faceCount ++;
554}
555
556/**
557 * Function that selects a material, if changed in the obj file.
558 * @param mtl the Material that will be set.
559*/
560bool Model::setMaterial(Material* mtl)
561{
562  if (this->currentGroup->faceCount > 0)
563    this->currentGroup->currentFace = this->currentGroup->currentFace->next = new ModelFace;
564
565  this->currentGroup->currentFace->material = mtl;
566
567  if (this->currentGroup->faceCount == 0)
568    this->currentGroup->faceCount ++;
569}
570
571/**
572 *  A routine that is able to create normals.
573
574   The algorithm does the following:
575   1. It calculates creates Vectors for each normale, and sets them to zero.
576   2. It then Walks through a) all the Groups b) all the Faces c) all the FaceElements
577   3. It searches for a points two neighbours per Face, takes Vecotrs to them calculates FaceNormals and adds it to the Points Normal.
578   4. It goes through all the normale-Points and calculates the VertexNormale and includes it in the normals-Array.
579*/
580bool Model::buildVertexNormals ()
581{
582  PRINTF(4)("Normals are being calculated.\n");
583
584  Vector* normArray = new Vector [vertices->getCount()/3];
585  for (int i=0; i<vertices->getCount()/3;i++)
586    normArray[i] = Vector(.0,.0,.0);
587
588  int firstTouch;
589  int secondTouch;
590  Vector prevV;
591  Vector nextV;
592  Vector curV;
593
594  ModelGroup* tmpGroup = firstGroup;
595  while (tmpGroup)
596    {
597      ModelFace* tmpFace = tmpGroup->firstFace;
598      while (tmpFace)
599        {
600          if (tmpFace->firstElem)
601            {
602              ModelFaceElement* firstElem = tmpFace->firstElem;
603              ModelFaceElement* prevElem;
604              ModelFaceElement* curElem = firstElem;
605              ModelFaceElement* nextElem;
606              ModelFaceElement* lastElem;
607              // find last Element of the Chain. !! IMPORTANT:the last Element of the Chain must point to NULL, or it will resolv into an infinity-loop.
608              while (curElem)
609                {
610                  prevElem = curElem;
611                  curElem = curElem->next;
612                }
613              lastElem = prevElem;
614
615              curElem = firstElem;
616              for (int j=0; j<tmpFace->vertexCount; j++)
617                {
618                  if (!(nextElem = curElem->next))
619                    nextElem = firstElem;
620                  curElem->normalNumber = curElem->vertexNumber;
621
622                  curV = Vector (vertices->getArray()[curElem->vertexNumber*3], vertices->getArray()[curElem->vertexNumber*3+1], vertices->getArray()[curElem->vertexNumber*3+2]);
623                  prevV = Vector (vertices->getArray()[prevElem->vertexNumber*3], vertices->getArray()[prevElem->vertexNumber*3+1], vertices->getArray()[prevElem->vertexNumber*3+2]) - curV;
624                  nextV = Vector (vertices->getArray()[nextElem->vertexNumber*3], vertices->getArray()[nextElem->vertexNumber*3+1], vertices->getArray()[nextElem->vertexNumber*3+2]) - curV;
625                  normArray[curElem->vertexNumber] = normArray[curElem->vertexNumber] + nextV.cross(prevV);
626
627                  prevElem = curElem;
628                  curElem = curElem->next;
629                }
630            }
631          tmpFace = tmpFace->next;
632        }
633      tmpGroup = tmpGroup->next;
634    }
635
636  for (int i=0; i < vertices->getCount()/3;i++)
637    {
638      normArray[i].normalize();
639      PRINTF(5)("Found Normale number %d: (%f; %f, %f).\n", i, normArray[i].x, normArray[i].y, normArray[i].z);
640
641      this->addVertexNormal(normArray[i].x, normArray[i].y, normArray[i].z);
642
643    }
644  delete []normArray;
645}
646
647////////////
648// openGL //
649////////////
650/**
651 *  reads and includes the Faces/Materials into the openGL state Machine
652*/
653bool Model::importToDisplayList()
654{
655  // finalize the Arrays
656  this->vertices->finalizeArray();
657  this->vTexture->finalizeArray();
658  if (normals->getCount() == 0) // vertices-Array must be built for this
659    this->buildVertexNormals();
660  this->normals->finalizeArray();
661
662  this->currentGroup = this->firstGroup;
663
664  while (this->currentGroup != NULL)
665    {
666
667      // creating a glList for the Group
668      if ((this->currentGroup->listNumber = glGenLists(1)) == 0)
669        {
670          PRINTF(2)("glList could not be created for this Model\n");
671          return false;
672        }
673      glNewList (this->currentGroup->listNumber, GL_COMPILE);
674
675      // Putting Faces to GL
676      ModelFace* tmpFace = this->currentGroup->firstFace;
677      while (tmpFace != NULL)
678        {
679          if (tmpFace->vertexCount == 0 && tmpFace->material != NULL)
680            {
681              if (this->currentGroup->faceMode != -1)
682                glEnd();
683              this->currentGroup->faceMode = 0;
684              Material* tmpMat;
685              if (tmpFace->material != NULL)
686                {
687                  tmpFace->material->select();
688                  PRINTF(5)("using material %s for coming Faces.\n", tmpFace->material->getName());
689                }
690            }
691
692          else if (tmpFace->vertexCount == 3)
693            {
694              if (this->currentGroup->faceMode != 3)
695                {
696                  if (this->currentGroup->faceMode != -1)
697                    glEnd();
698                  glBegin(GL_TRIANGLES);
699                }
700
701              this->currentGroup->faceMode = 3;
702              PRINTF(5)("found triag.\n");
703            }
704
705          else if (tmpFace->vertexCount == 4)
706            {
707              if (this->currentGroup->faceMode != 4)
708                {
709                  if (this->currentGroup->faceMode != -1)
710                    glEnd();
711                  glBegin(GL_QUADS);
712                }
713              this->currentGroup->faceMode = 4;
714              PRINTF(5)("found quad.\n");
715            }
716
717          else if (tmpFace->vertexCount > 4)
718            {
719              if (this->currentGroup->faceMode != -1)
720                glEnd();
721              glBegin(GL_POLYGON);
722              PRINTF(5)("Polygon with %i faces found.", tmpFace->vertexCount);
723              this->currentGroup->faceMode = tmpFace->vertexCount;
724            }
725
726          ModelFaceElement* tmpElem = tmpFace->firstElem;
727          while (tmpElem != NULL)
728            {
729              //      PRINTF(2)("%s\n", tmpElem->value);
730              this->addGLElement(tmpElem);
731              tmpElem = tmpElem->next;
732            }
733          tmpFace = tmpFace->next;
734        }
735      glEnd();
736      glEndList();
737
738      this->currentGroup = this->currentGroup->next;
739    }
740}
741
742/**
743 *  reads and includes the Faces/Materials into the openGL state Machine
744*/
745bool Model::importToVertexArray()
746{
747  // finalize the Arrays
748  this->vertices->finalizeArray();
749  this->vTexture->finalizeArray();
750  if (normals->getCount() == 0) // vertices-Array must be built for this
751    this->buildVertexNormals();
752  this->normals->finalizeArray();
753
754  this->currentGroup = this->firstGroup;
755  glVertexPointer(3, GL_FLOAT, 0, this->vertices->getArray());
756  glNormalPointer(3, 0, this->normals->getArray());
757  glTexCoordPointer(2, GL_FLOAT, 0, this->vTexture->getArray());
758}
759
760
761
762/**
763 *  builds an array of triangles, that can later on be used for obb separation and octree separation
764 */
765bool Model::buildTriangleList()
766{
767  if( unlikely(this->triangles != NULL))
768    return true;
769  /* make sure, that all the arrays are finalized */
770  if( unlikely(!this->vertices->isFinalized()))
771    this->vertices->finalizeArray();
772  if( unlikely(!this->vTexture->isFinalized()))
773    this->vTexture->finalizeArray();
774  if( normals->getCount() == 0) // vertices-Array must be built for this
775    this->buildVertexNormals();
776  if( unlikely(!this->normals->isFinalized()))
777    this->normals->finalizeArray();
778
779
780  int index = 0;                   //!< the counter for the triangle array
781  ModelFaceElement* tmpElem;       //!< the temporary faceelement reference
782  ModelFace* tmpFace;              //!< the temporary face referece
783
784  /* count the number of triangles */
785  /* now iterate through all groups and build up the triangle list */
786  this->triangleCount = 0;
787  this->currentGroup = this->firstGroup;
788  while( this->currentGroup != NULL)
789  {
790    tmpFace = this->currentGroup->firstFace;
791    while( tmpFace != NULL)
792    {
793
794      /* if its a triangle just add it to the list */
795      if( tmpFace->vertexCount == 3)
796      {
797        ++this->triangleCount;
798      } /* if the polygon is a quad */
799      else if( tmpFace->vertexCount == 4)
800      {
801        this->triangleCount += 2;
802      }
803      else if( tmpFace->vertexCount > 4)
804      {
805        PRINTF(1)("This model (%s) got over 4 vertices per face <=> conflicts in the CD engine!\n", this->getName());
806      //exit(0);
807      }
808      tmpFace = tmpFace->next;
809    }
810    this->currentGroup = this->currentGroup->next;
811  }
812
813  PRINTF(3)("got %i triangles, %i vertices\n", this->triangleCount, this->vertexCount);
814
815
816  /* write MODELINFO structure */
817
818  /* allocate memory for the new triangle structures */
819  if( (this->triangles = new sTriangleExt[this->triangleCount]) == NULL)
820  {
821    PRINTF(1)("Could not allocate memory for triangle list\n");
822    return false;
823  }
824
825  /* now iterate through all groups and build up the triangle list */
826  this->currentGroup = this->firstGroup;
827  while( this->currentGroup != NULL)
828  {
829      // Putting Faces to GL
830    tmpFace = this->currentGroup->firstFace;
831    while( tmpFace != NULL)
832    {
833      tmpElem = tmpFace->firstElem;
834
835      /* if its a triangle just add it to the list */
836      if( tmpFace->vertexCount == 3)
837      {
838        for( int j = 0; j < 3; ++j)
839        {
840          this->triangles[index].indexToVertices[j] = (unsigned int)tmpElem->vertexNumber * 3;
841          this->triangles[index].indexToNormals[j] = (unsigned int)tmpElem->normalNumber * 3;
842          this->triangles[index].indexToTexCoor[j] = (unsigned int)tmpElem->texCoordNumber * 3;
843          tmpElem = tmpElem->next;
844        }
845        ++index;
846      } /* if the polygon is a quad */
847      else if( tmpFace->vertexCount == 4)
848      {
849
850        this->triangles[index].indexToVertices[0] = (unsigned int)tmpElem->vertexNumber * 3;
851        this->triangles[index].indexToNormals[0] = (unsigned int)tmpElem->normalNumber * 3;
852        this->triangles[index].indexToTexCoor[0] = (unsigned int)tmpElem->texCoordNumber * 3;
853
854        this->triangles[index + 1].indexToVertices[0] = (unsigned int)tmpElem->vertexNumber * 3;
855        this->triangles[index + 1].indexToNormals[0] = (unsigned int)tmpElem->normalNumber * 3;
856        this->triangles[index + 1].indexToTexCoor[0] = (unsigned int)tmpElem->texCoordNumber * 3;
857        tmpElem = tmpElem->next;
858
859        this->triangles[index].indexToVertices[1] = (unsigned int)tmpElem->vertexNumber * 3;
860        this->triangles[index].indexToNormals[1] = (unsigned int)tmpElem->normalNumber * 3;
861        this->triangles[index].indexToTexCoor[1] = (unsigned int)tmpElem->texCoordNumber * 3;
862        tmpElem = tmpElem->next;
863
864        this->triangles[index].indexToVertices[2] = (unsigned int)tmpElem->vertexNumber * 3;
865        this->triangles[index].indexToNormals[2] = (unsigned int)tmpElem->normalNumber * 3;
866        this->triangles[index].indexToTexCoor[2] = (unsigned int)tmpElem->texCoordNumber * 3;
867
868        this->triangles[index + 1].indexToVertices[2] = (unsigned int)tmpElem->vertexNumber * 3;
869        this->triangles[index + 1].indexToNormals[2] = (unsigned int)tmpElem->normalNumber * 3;
870        this->triangles[index + 1].indexToTexCoor[2] = (unsigned int)tmpElem->texCoordNumber * 3;
871        tmpElem = tmpElem->next;
872
873        this->triangles[index + 1].indexToVertices[1] = (unsigned int)tmpElem->vertexNumber * 3;
874        this->triangles[index + 1].indexToNormals[1] = (unsigned int)tmpElem->normalNumber * 3;
875        this->triangles[index + 1].indexToTexCoor[1] = (unsigned int)tmpElem->texCoordNumber * 3;
876
877        index += 2;
878      }
879      tmpFace = tmpFace->next;
880    }
881    this->currentGroup = this->currentGroup->next;
882  }
883  return true;
884}
885
886
887/**
888 *  Adds a Face-element (one vertex of a face) with all its information.
889 * @param elem The FaceElement to add to the OpenGL-environment.
890
891   It does this by searching:
892   1. The Vertex itself
893   2. The VertexNormale
894   3. The VertexTextureCoordinate
895   merging this information, the face will be drawn.
896*/
897bool Model::addGLElement (ModelFaceElement* elem)
898{
899  PRINTF(5)("importing grafical Element to openGL.\n");
900
901  if (elem->texCoordNumber != -1)
902    {
903      if (likely(elem->texCoordNumber < this->texCoordCount))
904        glTexCoord2fv(this->vTexture->getArray() + elem->texCoordNumber * 2);
905      else
906        PRINTF(2)("TextureCoordinate %d is not in the List (max: %d)\nThe Model might be incomplete\n",
907                  elem->texCoordNumber, this->texCoordCount);
908    }
909  if (elem->normalNumber != -1)
910    {
911    if (likely(elem->normalNumber < this->normalCount))
912      glNormal3fv(this->normals->getArray() + elem->normalNumber * 3);
913    else
914        PRINTF(2)("Normal %d is not in the List (max: %d)\nThe Model might be incomplete",
915                  elem->normalNumber, this->normalCount);
916    }
917  if (elem->vertexNumber != -1)
918    {
919      if (likely(elem->vertexNumber < this->vertexCount))
920          glVertex3fv(this->vertices->getArray() + elem->vertexNumber * 3);
921      else
922        PRINTF(2)("Vertex %d is not in the List (max: %d)\nThe Model might be incomplete",
923                  elem->vertexNumber, this->vertexCount);
924    }
925
926}
927
928/**
929 *  Includes a default model
930
931   This will inject a Cube, because this is the most basic model.
932*/
933void Model::cubeModel()
934{
935  this->addVertex (-0.5, -0.5, 0.5);
936  this->addVertex (0.5, -0.5, 0.5);
937  this->addVertex (-0.5, 0.5, 0.5);
938  this->addVertex (0.5, 0.5, 0.5);
939  this->addVertex (-0.5, 0.5, -0.5);
940  this->addVertex (0.5, 0.5, -0.5);
941  this->addVertex (-0.5, -0.5, -0.5);
942  this->addVertex (0.5, -0.5, -0.5);
943
944  this->addVertexTexture (0.0, 0.0);
945  this->addVertexTexture (1.0, 0.0);
946  this->addVertexTexture (0.0, 1.0);
947  this->addVertexTexture (1.0, 1.0);
948  this->addVertexTexture (0.0, 2.0);
949  this->addVertexTexture (1.0, 2.0);
950  this->addVertexTexture (0.0, 3.0);
951  this->addVertexTexture (1.0, 3.0);
952  this->addVertexTexture (0.0, 4.0);
953  this->addVertexTexture (1.0, 4.0);
954  this->addVertexTexture (2.0, 0.0);
955  this->addVertexTexture (2.0, 1.0);
956  this->addVertexTexture (-1.0, 0.0);
957  this->addVertexTexture (-1.0, 1.0);
958
959  this->addVertexNormal (0.0, 0.0, 1.0);
960  this->addVertexNormal (0.0, 0.0, 1.0);
961  this->addVertexNormal (0.0, 0.0, 1.0);
962  this->addVertexNormal (0.0, 0.0, 1.0);
963  this->addVertexNormal (0.0, 1.0, 0.0);
964  this->addVertexNormal (0.0, 1.0, 0.0);
965  this->addVertexNormal (0.0, 1.0, 0.0);
966  this->addVertexNormal (0.0, 1.0, 0.0);
967  this->addVertexNormal (0.0, 0.0, -1.0);
968  this->addVertexNormal (0.0, 0.0, -1.0);
969  this->addVertexNormal (0.0, 0.0, -1.0);
970  this->addVertexNormal (0.0, 0.0, -1.0);
971  this->addVertexNormal (0.0, -1.0, 0.0);
972  this->addVertexNormal (0.0, -1.0, 0.0);
973  this->addVertexNormal (0.0, -1.0, 0.0);
974  this->addVertexNormal (0.0, -1.0, 0.0);
975  this->addVertexNormal (1.0, 0.0, 0.0);
976  this->addVertexNormal (1.0, 0.0, 0.0);
977  this->addVertexNormal (1.0, 0.0, 0.0);
978  this->addVertexNormal (1.0, 0.0, 0.0);
979  this->addVertexNormal (-1.0, 0.0, 0.0);
980  this->addVertexNormal (-1.0, 0.0, 0.0);
981  this->addVertexNormal (-1.0, 0.0, 0.0);
982  this->addVertexNormal (-1.0, 0.0, 0.0);
983
984  this->addFace (4, VERTEX_TEXCOORD_NORMAL, 0,0,0, 1,1,1, 3,3,2, 2,2,3);
985  this->addFace (4, VERTEX_TEXCOORD_NORMAL, 2,2,4, 3,3,5, 5,5,6, 4,4,7);
986  this->addFace (4, VERTEX_TEXCOORD_NORMAL, 4,4,8, 5,5,9, 7,7,10, 6,6,11);
987  this->addFace (4, VERTEX_TEXCOORD_NORMAL, 6,6,12, 7,7,13, 1,9,14, 0,8,15);
988  this->addFace (4, VERTEX_TEXCOORD_NORMAL, 1,1,16, 7,10,17, 5,11,18, 3,3,19);
989  this->addFace (4, VERTEX_TEXCOORD_NORMAL, 6,12,20, 0,0,21, 2,2,22, 4,13,23);
990}
Note: See TracBrowser for help on using the repository browser.