Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 5216 was 5216, checked in by bensch, 19 years ago

orxonox/trunk: more fixes due to valgrind

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