Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 5113 was 5111, checked in by bensch, 19 years ago

orxonox/trunk: reverted the last steps, because they created a huge pack of seg-faults

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->nextElement();
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; this->triangleCount = 0;
358}
359
360/**
361 *  finalizes an Model.
362 * This funcion is needed, to delete all the Lists, and arrays that are no more
363 * needed because they are already imported into openGL.
364 * This will be applied at the end of the importing Process.
365*/
366bool Model::cleanup()
367{
368  PRINTF(4)("cleaning up the 3D-Model to save Memory.\n");
369  this->firstGroup->cleanup();
370  return true;
371}
372
373//////////
374// MESH //
375//////////
376/**
377 *  adds a new Material to the Material List
378 * @param material the Material to add
379 * @returns the added material
380 *
381 * this also tells this Model, that all the Materials are handled externally
382 * with this option set the Materials will not be deleted with the Model.
383 * !! -> NO MATERIALS GET DELETED WITH ONE CALL TO THIS FUNCTION !!
384*/
385Material* Model::addMaterial(Material* material)
386{
387  this->materialList->add(material);
388  this->materialsExtern = true;
389  return material;
390}
391
392/**
393 *  adds a new Material to the Material List
394 * @param materialName the name of the Material to add
395 * @returns the added material
396*/
397Material* Model::addMaterial(const char* materialName)
398{
399  Material* newMat = new Material();
400  newMat->setName(materialName);
401
402  // adding material to the List of materials
403  this->materialList->add(newMat);
404  return newMat;
405}
406
407/**
408 *  finds a Material by its name and returns it
409 * @param materialName the Name of the material to search for.
410 * @returns the Material if found, NULL otherwise
411*/
412Material* Model::findMaterialByName(const char* materialName)
413{
414  tIterator<Material>* tmpIt = this->materialList->getIterator();
415  Material* material = tmpIt->nextElement();
416  while(material)
417    {
418      if (!strcmp(material->getName(), materialName))
419        {
420          delete tmpIt;
421          return material;
422        }
423      material = tmpIt->nextElement();
424    }
425  delete tmpIt;
426  return NULL;
427}
428
429/**
430 *  parses a group String
431 * @param groupString the new Group to create
432
433   This function initializes a new Group.
434   With it you should be able to create Models with more than one SubModel inside
435*/
436bool Model::addGroup(const char* groupString)
437{
438  PRINTF(5)("Read Group: %s.\n", groupString);
439  if (this->groupCount != 0 && this->currentGroup->faceCount > 0)
440    {
441      //      finalizeGroup(currentGroup);
442      this->currentGroup = this->currentGroup->next = new ModelGroup;
443    }
444  // setting the group name if not default.
445  if (strcmp(groupString, "default"))
446    {
447      this->currentGroup->name = new char [strlen(groupString)+1];
448      strcpy(this->currentGroup->name, groupString);
449    }
450  ++this->groupCount;
451}
452
453/**
454 *  parses a vertex-String
455 * @param vertexString The String that will be parsed.
456
457   If a vertex line is found this function will inject it into the vertex-Array
458*/
459bool Model::addVertex (const char* vertexString)
460{
461  float subbuffer1;
462  float subbuffer2;
463  float subbuffer3;
464  sscanf (vertexString, "%f %f %f", &subbuffer1, &subbuffer2, &subbuffer3);
465  PRINTF(5)("reading in a vertex: %f %f %f\n", &subbuffer1, &subbuffer2, &subbuffer3);
466  this->vertices->addEntry(subbuffer1*scaleFactor, subbuffer2*scaleFactor, subbuffer3*scaleFactor);
467  this->vertexCount++;
468  return true;
469}
470
471/**
472 *  parses a vertex-String
473 * @param x the X-coordinate of the Vertex to add.
474 * @param y the Y-coordinate of the Vertex to add.
475 * @param z the Z-coordinate of the Vertex to add.
476
477*/
478bool Model::addVertex(float x, float y, float z)
479{
480  PRINTF(5)("reading in a vertex: %f %f %f\n", x, y, z);
481  this->vertices->addEntry(x*scaleFactor, y*scaleFactor, z*scaleFactor);
482  this->vertexCount++;
483  return true;
484}
485
486/**
487 *  parses a vertexNormal-String
488 * @param normalString The String that will be parsed.
489
490   If a vertexNormal line is found this function will inject it into the vertexNormal-Array
491*/
492bool Model::addVertexNormal (const char* normalString)
493{
494  float subbuffer1;
495  float subbuffer2;
496  float subbuffer3;
497  sscanf (normalString, "%f %f %f", &subbuffer1, &subbuffer2, &subbuffer3);
498  PRINTF(5)("found vertex-Normal %f, %f, %f\n", &subbuffer1,&subbuffer2,&subbuffer3);
499  this->normals->addEntry(subbuffer1, subbuffer2, subbuffer3);
500  this->normalCount++;
501  return true;
502}
503
504/**
505 *  adds a VertexNormal.
506 * @param x The x coordinate of the Normal.
507 * @param y The y coordinate of the Normal.
508 * @param z The z coordinate of the Normal.
509
510   If a vertexNormal line is found this function will inject it into the vertexNormal-Array
511*/
512bool Model::addVertexNormal(float x, float y, float z)
513{
514  PRINTF(5)("found vertex-Normal %f, %f, %f\n", x, y, z);
515  this->normals->addEntry(x, y, z);
516  this->normalCount++;
517  return true;
518}
519
520/**
521 *  parses a vertexTextureCoordinate-String
522 * @param vTextureString The String that will be parsed.
523
524   If a vertexTextureCoordinate line is found,
525   this function will inject it into the vertexTexture-Array
526
527   !! WARNING THIS IS DIFFERNT FROM addVervexTexture(float, float); because it changes the second entry to 1-v !!
528*/
529bool Model::addVertexTexture (const char* vTextureString)
530{
531  float subbuffer1;
532  float subbuffer2;
533  sscanf (vTextureString, "%f %f", &subbuffer1, &subbuffer2);
534  PRINTF(5)("found vertex-Texture %f, %f\n", &subbuffer1, &subbuffer2);
535  this->vTexture->addEntry(subbuffer1);
536  this->vTexture->addEntry(1 - subbuffer2);
537  this->texCoordCount++;
538  return true;
539}
540
541/**
542 *  adds a Texture Coordinate
543 * @param u The u coordinate of the TextureCoordinate.
544 * @param v The y coordinate of the TextureCoordinate.
545
546   If a TextureCoordinate line is found this function will inject it into the TextureCoordinate-Array
547*/
548bool Model::addVertexTexture(float u, float v)
549{
550  PRINTF(5)("found vertex-Texture %f, %f\n", u, v);
551  this->vTexture->addEntry(u);
552  this->vTexture->addEntry(v);
553  this->texCoordCount++;
554  return true;
555}
556
557/**
558 *  parses a face-string
559 * @param faceString The String that will be parsed.
560
561   If a face line is found this function will add it to the glList.
562
563   String is different from the argument addFace, in this that the first Vertex/Normal/Texcoord is 1 instead of 0
564*/
565bool Model::addFace (const char* faceString)
566{
567  if (this->currentGroup->faceCount >0)
568    this->currentGroup->currentFace = this->currentGroup->currentFace->next = new ModelFace;
569
570  ModelFaceElement* tmpElem = this->currentGroup->currentFace->firstElem = new ModelFaceElement;
571  tmpElem->next = NULL;
572  while(strcmp (faceString, "\0"))
573    {
574      if (this->currentGroup->currentFace->vertexCount>0)
575          tmpElem = tmpElem->next = new ModelFaceElement;
576      tmpElem->next = NULL;
577
578      char tmpValue [50];
579      int tmpLen;
580      char* vertex = NULL;
581      char* texture = NULL;
582      char* normal = NULL;
583
584      sscanf (faceString, "%s", tmpValue);
585      tmpLen = strlen(tmpValue);
586      vertex = tmpValue;
587
588      if ((texture = strstr (vertex, "/")) != NULL)
589        {
590          texture[0] = '\0';
591          texture ++;
592
593          if ((normal = strstr (texture, "/")) !=NULL)
594            {
595              normal[0] = '\0';
596              normal ++;
597            }
598        }
599      if (vertex)
600        tmpElem->vertexNumber = atoi(vertex)-1;
601      if (texture)
602        tmpElem->texCoordNumber = atoi(texture)-1;
603      if (normal)
604        tmpElem->normalNumber = atoi(normal)-1;
605
606      faceString += tmpLen;
607      if (strcmp (faceString, "\0"))
608        faceString++;
609      this->currentGroup->currentFace->vertexCount++;
610    }
611
612  this->currentGroup->faceCount += this->currentGroup->currentFace->vertexCount -2;
613  this->faceCount += this->currentGroup->currentFace->vertexCount -2;
614}
615
616/**
617 *  adds a new Face
618 * @param faceElemCount the number of Vertices to add to the Face.
619 * @param type The information Passed with each Vertex
620*/
621bool Model::addFace(int faceElemCount, VERTEX_FORMAT type, ...)
622{
623  if (this->currentGroup->faceCount > 0)
624    this->currentGroup->currentFace = this->currentGroup->currentFace->next = new ModelFace;
625
626  ModelFaceElement* tmpElem = this->currentGroup->currentFace->firstElem = new ModelFaceElement;
627
628  va_list itemlist;
629  va_start (itemlist, type);
630
631  for (int i = 0; i < faceElemCount; i++)
632    {
633      if (this->currentGroup->currentFace->vertexCount > 0)
634        tmpElem = tmpElem->next = new ModelFaceElement;
635
636      tmpElem->vertexNumber = va_arg (itemlist, int);
637      if (type & TEXCOORD)
638        tmpElem->texCoordNumber = va_arg (itemlist, int);
639      if (type & NORMAL)
640        tmpElem->normalNumber = va_arg(itemlist, int);
641      this->currentGroup->currentFace->vertexCount++;
642    }
643  va_end(itemlist);
644
645  this->currentGroup->faceCount += this->currentGroup->currentFace->vertexCount - 2;
646  this->faceCount += this->currentGroup->currentFace->vertexCount -2;
647}
648
649/**
650 *  Function that selects a material, if changed in the obj file.
651 * @param matString the Material that will be set.
652*/
653bool Model::setMaterial(const char* matString)
654{
655  if (this->currentGroup->faceCount > 0)
656    this->currentGroup->currentFace = this->currentGroup->currentFace->next = new ModelFace;
657
658  this->currentGroup->currentFace->material = this->findMaterialByName(matString);
659
660  if (this->currentGroup->faceCount == 0)
661    this->currentGroup->faceCount ++;
662}
663
664/**
665 *  Function that selects a material, if changed in the obj file.
666 * @param mtl the Material that will be set.
667*/
668bool Model::setMaterial(Material* mtl)
669{
670  if (this->currentGroup->faceCount > 0)
671    this->currentGroup->currentFace = this->currentGroup->currentFace->next = new ModelFace;
672
673  this->currentGroup->currentFace->material = mtl;
674
675  if (this->currentGroup->faceCount == 0)
676    this->currentGroup->faceCount ++;
677}
678
679/**
680 *  A routine that is able to create normals.
681
682   The algorithm does the following:
683   1. It calculates creates Vectors for each normale, and sets them to zero.
684   2. It then Walks through a) all the Groups b) all the Faces c) all the FaceElements
685   3. It searches for a points two neighbours per Face, takes Vecotrs to them calculates FaceNormals and adds it to the Points Normal.
686   4. It goes through all the normale-Points and calculates the VertexNormale and includes it in the normals-Array.
687*/
688bool Model::buildVertexNormals ()
689{
690  PRINTF(4)("Normals are being calculated.\n");
691
692  Vector* normArray = new Vector [vertices->getCount()/3];
693  for (int i=0; i<vertices->getCount()/3;i++)
694    normArray[i] = Vector(.0,.0,.0);
695
696  int firstTouch;
697  int secondTouch;
698  Vector prevV;
699  Vector nextV;
700  Vector curV;
701
702  ModelGroup* tmpGroup = firstGroup;
703  while (tmpGroup)
704    {
705      ModelFace* tmpFace = tmpGroup->firstFace;
706      while (tmpFace)
707        {
708          if (tmpFace->firstElem)
709            {
710              ModelFaceElement* firstElem = tmpFace->firstElem;
711              ModelFaceElement* prevElem;
712              ModelFaceElement* curElem = firstElem;
713              ModelFaceElement* nextElem;
714              ModelFaceElement* lastElem;
715              // 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.
716              while (curElem)
717                {
718                  prevElem = curElem;
719                  curElem = curElem->next;
720                }
721              lastElem = prevElem;
722
723              curElem = firstElem;
724              for (int j=0; j<tmpFace->vertexCount; j++)
725                {
726                  if (!(nextElem = curElem->next))
727                    nextElem = firstElem;
728                  curElem->normalNumber = curElem->vertexNumber;
729
730                  curV = Vector (vertices->getArray()[curElem->vertexNumber*3], vertices->getArray()[curElem->vertexNumber*3+1], vertices->getArray()[curElem->vertexNumber*3+2]);
731                  prevV = Vector (vertices->getArray()[prevElem->vertexNumber*3], vertices->getArray()[prevElem->vertexNumber*3+1], vertices->getArray()[prevElem->vertexNumber*3+2]) - curV;
732                  nextV = Vector (vertices->getArray()[nextElem->vertexNumber*3], vertices->getArray()[nextElem->vertexNumber*3+1], vertices->getArray()[nextElem->vertexNumber*3+2]) - curV;
733                  normArray[curElem->vertexNumber] = normArray[curElem->vertexNumber] + nextV.cross(prevV);
734
735                  prevElem = curElem;
736                  curElem = curElem->next;
737                }
738            }
739          tmpFace = tmpFace->next;
740        }
741      tmpGroup = tmpGroup->next;
742    }
743
744  for (int i=0; i < vertices->getCount()/3;i++)
745    {
746      normArray[i].normalize();
747      PRINTF(5)("Found Normale number %d: (%f; %f, %f).\n", i, normArray[i].x, normArray[i].y, normArray[i].z);
748
749      this->addVertexNormal(normArray[i].x, normArray[i].y, normArray[i].z);
750
751    }
752  delete []normArray;
753}
754
755////////////
756// openGL //
757////////////
758/**
759 *  reads and includes the Faces/Materials into the openGL state Machine
760*/
761bool Model::importToDisplayList()
762{
763  // finalize the Arrays
764  this->vertices->finalizeArray();
765  this->vTexture->finalizeArray();
766  if (normals->getCount() == 0) // vertices-Array must be built for this
767    this->buildVertexNormals();
768  this->normals->finalizeArray();
769
770  this->currentGroup = this->firstGroup;
771
772  while (this->currentGroup != NULL)
773    {
774
775      // creating a glList for the Group
776      if ((this->currentGroup->listNumber = glGenLists(1)) == 0)
777        {
778          PRINTF(2)("glList could not be created for this Model\n");
779          return false;
780        }
781      glNewList (this->currentGroup->listNumber, GL_COMPILE);
782
783      // Putting Faces to GL
784      ModelFace* tmpFace = this->currentGroup->firstFace;
785      while (tmpFace != NULL)
786        {
787          if (tmpFace->vertexCount == 0 && tmpFace->material != NULL)
788            {
789              if (this->currentGroup->faceMode != -1)
790                glEnd();
791              this->currentGroup->faceMode = 0;
792              Material* tmpMat;
793              if (tmpFace->material != NULL)
794                {
795                  tmpFace->material->select();
796                  PRINTF(5)("using material %s for coming Faces.\n", tmpFace->material->getName());
797                }
798            }
799
800          else if (tmpFace->vertexCount == 3)
801            {
802              if (this->currentGroup->faceMode != 3)
803                {
804                  if (this->currentGroup->faceMode != -1)
805                    glEnd();
806                  glBegin(GL_TRIANGLES);
807                }
808
809              this->currentGroup->faceMode = 3;
810              PRINTF(5)("found triag.\n");
811            }
812
813          else if (tmpFace->vertexCount == 4)
814            {
815              if (this->currentGroup->faceMode != 4)
816                {
817                  if (this->currentGroup->faceMode != -1)
818                    glEnd();
819                  glBegin(GL_QUADS);
820                }
821              this->currentGroup->faceMode = 4;
822              PRINTF(5)("found quad.\n");
823            }
824
825          else if (tmpFace->vertexCount > 4)
826            {
827              if (this->currentGroup->faceMode != -1)
828                glEnd();
829              glBegin(GL_POLYGON);
830              PRINTF(5)("Polygon with %i faces found.", tmpFace->vertexCount);
831              this->currentGroup->faceMode = tmpFace->vertexCount;
832            }
833
834          ModelFaceElement* tmpElem = tmpFace->firstElem;
835          while (tmpElem != NULL)
836            {
837              //      PRINTF(2)("%s\n", tmpElem->value);
838              this->addGLElement(tmpElem);
839              tmpElem = tmpElem->next;
840            }
841          tmpFace = tmpFace->next;
842        }
843      glEnd();
844      glEndList();
845
846      this->currentGroup = this->currentGroup->next;
847    }
848}
849
850/**
851 *  reads and includes the Faces/Materials into the openGL state Machine
852*/
853bool Model::importToVertexArray()
854{
855  // finalize the Arrays
856  this->vertices->finalizeArray();
857  this->vTexture->finalizeArray();
858  if (normals->getCount() == 0) // vertices-Array must be built for this
859    this->buildVertexNormals();
860  this->normals->finalizeArray();
861
862  this->currentGroup = this->firstGroup;
863  glVertexPointer(3, GL_FLOAT, 0, this->vertices->getArray());
864  glNormalPointer(3, 0, this->normals->getArray());
865  glTexCoordPointer(2, GL_FLOAT, 0, this->vTexture->getArray());
866}
867
868
869
870/**
871 *  builds an array of triangles, that can later on be used for obb separation and octree separation
872 */
873bool Model::buildTriangleList()
874{
875  if( unlikely(this->triangles != NULL))
876    return true;
877  /* make sure, that all the arrays are finalized */
878  if( unlikely(!this->vertices->isFinalized()))
879    this->vertices->finalizeArray();
880  if( unlikely(!this->vTexture->isFinalized()))
881    this->vTexture->finalizeArray();
882  if( normals->getCount() == 0) // vertices-Array must be built for this
883    this->buildVertexNormals();
884  if( unlikely(!this->normals->isFinalized()))
885    this->normals->finalizeArray();
886
887
888  int index = 0;                   //!< the counter for the triangle array
889  ModelFaceElement* tmpElem;       //!< the temporary faceelement reference
890  ModelFace* tmpFace;              //!< the temporary face referece
891
892  /* count the number of triangles */
893  /* now iterate through all groups and build up the triangle list */
894  this->triangleCount = 0;
895  this->currentGroup = this->firstGroup;
896  while( this->currentGroup != NULL)
897  {
898    tmpFace = this->currentGroup->firstFace;
899    while( tmpFace != NULL)
900    {
901
902      /* if its a triangle just add it to the list */
903      if( tmpFace->vertexCount == 3)
904      {
905        ++this->triangleCount;
906      } /* if the polygon is a quad */
907      else if( tmpFace->vertexCount == 4)
908      {
909        this->triangleCount += 2;
910      }
911      else if( tmpFace->vertexCount > 4)
912      {
913        PRINTF(1)("NASTY NASTY: More than 4 vertices for a face, there will be errors in the triangles information!\n");
914      //exit(0);
915      }
916      tmpFace = tmpFace->next;
917    }
918    this->currentGroup = this->currentGroup->next;
919  }
920
921  PRINTF(3)("got %i triangles, %i vertices\n", this->triangleCount, this->vertexCount);
922
923
924  /* allocate memory for the new triangle structures */
925  if( (this->triangles = new sTriangleExt[this->triangleCount]) == NULL)
926  {
927    PRINTF(1)("Could not allocate memory for triangle list\n");
928    return false;
929  }
930
931
932  /* now iterate through all groups and build up the triangle list */
933  this->currentGroup = this->firstGroup;
934  while( this->currentGroup != NULL)
935  {
936      // Putting Faces to GL
937    tmpFace = this->currentGroup->firstFace;
938    while( tmpFace != NULL)
939    {
940      tmpElem = tmpFace->firstElem;
941
942      /* if its a triangle just add it to the list */
943      if( tmpFace->vertexCount == 3)
944      {
945        for( int j = 0; j < 3; ++j)
946        {
947          this->triangles[index].indexToVertices[j] = (unsigned int)tmpElem->vertexNumber * 3;
948          this->triangles[index].indexToNormals[j] = (unsigned int)tmpElem->normalNumber * 3;
949          this->triangles[index].indexToTexCoor[j] = (unsigned int)tmpElem->texCoordNumber * 3;
950          tmpElem = tmpElem->next;
951        }
952        ++index;
953      } /* if the polygon is a quad */
954      else if( tmpFace->vertexCount == 4)
955      {
956
957        this->triangles[index].indexToVertices[0] = (unsigned int)tmpElem->vertexNumber * 3;
958        this->triangles[index].indexToNormals[0] = (unsigned int)tmpElem->normalNumber * 3;
959        this->triangles[index].indexToTexCoor[0] = (unsigned int)tmpElem->texCoordNumber * 3;
960
961        this->triangles[index + 1].indexToVertices[0] = (unsigned int)tmpElem->vertexNumber * 3;
962        this->triangles[index + 1].indexToNormals[0] = (unsigned int)tmpElem->normalNumber * 3;
963        this->triangles[index + 1].indexToTexCoor[0] = (unsigned int)tmpElem->texCoordNumber * 3;
964        tmpElem = tmpElem->next;
965
966        this->triangles[index].indexToVertices[1] = (unsigned int)tmpElem->vertexNumber * 3;
967        this->triangles[index].indexToNormals[1] = (unsigned int)tmpElem->normalNumber * 3;
968        this->triangles[index].indexToTexCoor[1] = (unsigned int)tmpElem->texCoordNumber * 3;
969        tmpElem = tmpElem->next;
970
971        this->triangles[index].indexToVertices[2] = (unsigned int)tmpElem->vertexNumber * 3;
972        this->triangles[index].indexToNormals[2] = (unsigned int)tmpElem->normalNumber * 3;
973        this->triangles[index].indexToTexCoor[2] = (unsigned int)tmpElem->texCoordNumber * 3;
974
975        this->triangles[index + 1].indexToVertices[2] = (unsigned int)tmpElem->vertexNumber * 3;
976        this->triangles[index + 1].indexToNormals[2] = (unsigned int)tmpElem->normalNumber * 3;
977        this->triangles[index + 1].indexToTexCoor[2] = (unsigned int)tmpElem->texCoordNumber * 3;
978        tmpElem = tmpElem->next;
979
980        this->triangles[index + 1].indexToVertices[1] = (unsigned int)tmpElem->vertexNumber * 3;
981        this->triangles[index + 1].indexToNormals[1] = (unsigned int)tmpElem->normalNumber * 3;
982        this->triangles[index + 1].indexToTexCoor[1] = (unsigned int)tmpElem->texCoordNumber * 3;
983
984        index += 2;
985      }
986      tmpFace = tmpFace->next;
987    }
988    this->currentGroup = this->currentGroup->next;
989  }
990  return true;
991}
992
993
994/**
995 *  Adds a Face-element (one vertex of a face) with all its information.
996 * @param elem The FaceElement to add to the OpenGL-environment.
997
998   It does this by searching:
999   1. The Vertex itself
1000   2. The VertexNormale
1001   3. The VertexTextureCoordinate
1002   merging this information, the face will be drawn.
1003*/
1004bool Model::addGLElement (ModelFaceElement* elem)
1005{
1006  PRINTF(5)("importing grafical Element to openGL.\n");
1007
1008  if (elem->texCoordNumber != -1)
1009    {
1010      if (likely(elem->texCoordNumber < this->texCoordCount))
1011        glTexCoord2fv(this->vTexture->getArray() + elem->texCoordNumber * 2);
1012      else
1013        PRINTF(2)("TextureCoordinate %d is not in the List (max: %d)\nThe Model might be incomplete\n",
1014                  elem->texCoordNumber, this->texCoordCount);
1015    }
1016  if (elem->normalNumber != -1)
1017    {
1018    if (likely(elem->normalNumber < this->normalCount))
1019      glNormal3fv(this->normals->getArray() + elem->normalNumber * 3);
1020    else
1021        PRINTF(2)("Normal %d is not in the List (max: %d)\nThe Model might be incomplete",
1022                  elem->normalNumber, this->normalCount);
1023    }
1024  if (elem->vertexNumber != -1)
1025    {
1026      if (likely(elem->vertexNumber < this->vertexCount))
1027          glVertex3fv(this->vertices->getArray() + elem->vertexNumber * 3);
1028      else
1029        PRINTF(2)("Vertex %d is not in the List (max: %d)\nThe Model might be incomplete",
1030                  elem->vertexNumber, this->vertexCount);
1031    }
1032
1033}
1034
1035/**
1036 *  Includes a default model
1037
1038   This will inject a Cube, because this is the most basic model.
1039*/
1040void Model::cubeModel()
1041{
1042  this->addVertex (-0.5, -0.5, 0.5);
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
1051  this->addVertexTexture (0.0, 0.0);
1052  this->addVertexTexture (1.0, 0.0);
1053  this->addVertexTexture (0.0, 1.0);
1054  this->addVertexTexture (1.0, 1.0);
1055  this->addVertexTexture (0.0, 2.0);
1056  this->addVertexTexture (1.0, 2.0);
1057  this->addVertexTexture (0.0, 3.0);
1058  this->addVertexTexture (1.0, 3.0);
1059  this->addVertexTexture (0.0, 4.0);
1060  this->addVertexTexture (1.0, 4.0);
1061  this->addVertexTexture (2.0, 0.0);
1062  this->addVertexTexture (2.0, 1.0);
1063  this->addVertexTexture (-1.0, 0.0);
1064  this->addVertexTexture (-1.0, 1.0);
1065
1066  this->addVertexNormal (0.0, 0.0, 1.0);
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, 1.0, 0.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, 0.0, -1.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, -1.0, 0.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 (1.0, 0.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
1091  this->addFace (4, VERTEX_TEXCOORD_NORMAL, 0,0,0, 1,1,1, 3,3,2, 2,2,3);
1092  this->addFace (4, VERTEX_TEXCOORD_NORMAL, 2,2,4, 3,3,5, 5,5,6, 4,4,7);
1093  this->addFace (4, VERTEX_TEXCOORD_NORMAL, 4,4,8, 5,5,9, 7,7,10, 6,6,11);
1094  this->addFace (4, VERTEX_TEXCOORD_NORMAL, 6,6,12, 7,7,13, 1,9,14, 0,8,15);
1095  this->addFace (4, VERTEX_TEXCOORD_NORMAL, 1,1,16, 7,10,17, 5,11,18, 3,3,19);
1096  this->addFace (4, VERTEX_TEXCOORD_NORMAL, 6,12,20, 0,0,21, 2,2,22, 4,13,23);
1097
1098}
Note: See TracBrowser for help on using the repository browser.