Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/new_class_id/src/lib/graphics/importer/static_model.cc @ 9715

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

renamed newclassid to classid and newobjectlist to objectlist

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