Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: some comments, started implementing the Model::buildTriangleList() function, Array::getIndex now makes a value not reference comparison

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