Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 4800 was 4800, checked in by patrick, 19 years ago

orxonox/trunk: found the problem, got the offsets wrong in the triangle vertices indexes. there are still some unfilled triangles, will work in this one now

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