Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: some more stability in triangle count calculation

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