Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/graphics/importer/model.cc @ 5212

Last change on this file since 5212 was 5211, checked in by bensch, 19 years ago

orxonox/trunk: valgrind mem-leak-recovered

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