Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 6032 was 6031, checked in by bensch, 19 years ago

orxonox/trunk: cleanup in the StaticModel class, as my idea changed

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