Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: the important interface functions are now implemented directly in abstract model.

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