Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/graphics/importer/static_model_data.cc @ 10055

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

orxonox/trunk: merged the new_class_id branche back to the trunk.
merged with command:
svn merge https://svn.orxonox.net/orxonox/branches/new_class_id trunk -r9683:HEAD
no conflicts… puh..

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