Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/graphics/importer/static_model.cc @ 6075

Last change on this file since 6075 was 6072, checked in by bensch, 19 years ago

orxonox/trunk: valgrind sweep

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