Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 8266 was 7732, checked in by patrick, 18 years ago

orxonox: removed a memory leak

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