Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: orxonox now renders again the old way with glLists, additionaly there is now this triangle list created in background

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