Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 5266 was 5218, checked in by bensch, 19 years ago

orxonox/trunk: more error-fixes… thanks Valgrind team :)

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