Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/collision_detection/src/lib/graphics/importer/model.cc @ 6177

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

orxonox/trunk: new ModelInfo-member in AbstractModel

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 "stdlibincl.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 *  deletes a ModelFace
71*/
72ModelFace::~ModelFace()
73{
74  PRINTF(5)("Cleaning up Face\n");
75
76  if (this->firstElem != NULL)
77    delete this->firstElem;
78
79  if (this->next != NULL)
80    delete this->next;
81}
82
83/**
84 *  Creates a new ModelGroup
85*/
86ModelGroup::ModelGroup()
87{
88  PRINTF(4)("Adding new Group\n");
89  this->name = "";
90  this->faceMode = -1;
91  this->faceCount = 0;
92  this->next = NULL;
93  this->listNumber = 0;
94
95  this->firstFace = new ModelFace;
96  this->currentFace = this->firstFace;
97}
98
99/**
100 *  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  // deleting the glList
109  if (this->listNumber != 0)
110    glDeleteLists(this->listNumber, 1);
111
112  if (this->name[0] != '\0')
113    delete[] this->name;
114
115  if (this->next !=NULL)
116    delete this->next;
117
118}
119
120/**
121 *  cleans up a ModelGroup
122
123   actually does the same as the delete Operator, but does not delete the predecessing group
124*/
125void ModelGroup::cleanup()
126{
127  PRINTF(5)("Cleaning up group\n");
128  if (this->firstFace)
129    delete this->firstFace;
130  this->firstFace = NULL;
131  if (this->next)
132    this->next->cleanup();
133}
134
135
136/////////////
137/// MODEL ///
138/////////////
139/**
140 *  Creates a 3D-Model.
141
142   assigns it a Name and a Type
143*/
144Model::Model(const char* modelName, MODEL_TYPE type)
145{
146  PRINTF(4)("new 3D-Model is being created\n");
147  this->setName(modelName);
148  this->type = type;
149
150  this->finalized = false;
151  // setting the start group;
152  this->currentGroup = this->firstGroup = new ModelGroup;
153  this->groupCount = 0;
154  this->vertexCount = 0;
155  this->normalCount = 0;
156  this->texCoordCount = 0;
157  this->faceCount = 0;
158  this->triangleCount = 0;
159  this->triangles = NULL;
160
161  this->scaleFactor = 1;
162
163  this->vertices = new tArray<GLfloat>();
164  this->vTexture = new tArray<GLfloat>();
165  this->normals = new tArray<GLfloat>();
166
167  this->materialList = new tList<ModelMaterial>;
168
169  if (this->type == MODEL_VERTEX_ARRAY)
170    glEnableClientState(GL_VERTEX_ARRAY | GL_NORMAL_ARRAY | GL_TEXTURE_COORD_ARRAY);
171}
172
173/**
174 *  deletes an Model.
175
176   Looks if any from model allocated space is still in use, and if so deleted it.
177*/
178Model::~Model()
179{
180  PRINTF(4)("Deleting Model ");
181  if (this->getName())
182    {
183      PRINT(4)("%s\n", this->getName());
184    }
185  else
186      PRINT(4)("\n");
187
188  PRINTF(5)("Deleting display Lists.\n");
189  delete this->firstGroup;
190
191  // deleting Arrays (if not allready done by finalize)
192  this->deleteArrays();
193
194  // deleting the MaterialList
195  PRINTF(5)("Deleting Materials.\n");
196
197  tIterator<ModelMaterial>* tmpIt = this->materialList->getIterator();
198  ModelMaterial* modMat = tmpIt->firstElement();
199  //! @todo do we really have to delete this material??
200  while(modMat != NULL)
201  {
202    if (!modMat->external)
203      delete modMat->material;
204    delete modMat;
205    modMat = tmpIt->nextElement();
206  }
207  delete tmpIt;
208  delete materialList;
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.numVertices = this->vertexCount;
227  this->pModelInfo.pVertices = this->vertices->getArray();
228  this->pModelInfo.numTriangles = this->triangleCount;
229  this->pModelInfo.pTriangles = this->triangles;
230  this->pModelInfo.numNormals = this->normalCount;
231  this->pModelInfo.pNormals = this->normals->getArray();
232  this->pModelInfo.numTexCoor = this->vTexture->getCount();
233  this->pModelInfo.pTexCoor = this->vTexture->getArray();
234
235  this->finalized = true;
236}
237
238//////////
239// DRAW //
240//////////
241/**
242 *  Draws the Models of all Groups.
243   It does this by just calling the Lists that must have been created earlier.
244*/
245void Model::draw () const
246{
247
248  PRINTF(4)("drawing the 3D-Models\n");
249  ModelGroup* tmpGroup = this->firstGroup;
250  while (tmpGroup != NULL)
251    {
252      PRINTF(5)("Drawing model %s\n", tmpGroup->name);
253      glCallList (tmpGroup->listNumber);
254      tmpGroup = tmpGroup->next;
255    }
256
257
258/*  const GLfloat* pVertices = NULL;
259  const GLfloat* pNorm = NULL;
260
261  glBegin(GL_TRIANGLES);
262  for( int i = 0; i < this->triangleCount; ++i)
263  {
264    //printf("int i = %i\n", i);
265    pNorm = &this->normals->getArray()[this->triangles[i].indexToNormals[0]];
266    pVertices = &this->vertices->getArray()[this->triangles[i].indexToVertices[0]];
267    glNormal3f(pNorm[0], pNorm[1], pNorm[2]);
268    glVertex3f(pVertices[0], pVertices[1], pVertices[2]);
269
270    pNorm = &this->normals->getArray()[this->triangles[i].indexToNormals[1]];
271    pVertices = &this->vertices->getArray()[this->triangles[i].indexToVertices[1]];
272    glNormal3f(pNorm[0], pNorm[1], pNorm[2]);
273    glVertex3f(pVertices[0], pVertices[1], pVertices[2]);
274
275    pNorm = &this->normals->getArray()[this->triangles[i].indexToNormals[2]];
276    pVertices = &this->vertices->getArray()[this->triangles[i].indexToVertices[2]];
277    glNormal3f(pNorm[0], pNorm[1], pNorm[2]);
278    glVertex3f(pVertices[0], pVertices[1], pVertices[2]);
279
280  }
281  glEnd();*/
282}
283
284/**
285 *  Draws the Model number groupNumber
286 * @param groupNumber The number of the group that will be displayed.
287
288   It does this by just calling the List that must have been created earlier.
289*/
290void Model::draw (int groupNumber) const
291{
292  if (groupNumber >= this->groupCount)
293    {
294      PRINTF(2)("You requested model number %i, but this File only contains of %i Models.\n", groupNumber-1, this->groupCount);
295      return;
296    }
297  PRINTF(4)("drawing the requested 3D-Models if found.\n");
298  ModelGroup* tmpGroup = this->firstGroup;
299  int counter = 0;
300  while (tmpGroup != NULL)
301    {
302      if (counter == groupNumber)
303        {
304          PRINTF(4)("Drawing model number %i named %s\n", counter, tmpGroup->name);
305          glCallList (tmpGroup->listNumber);
306          return;
307        }
308      ++counter;
309      tmpGroup = tmpGroup->next;
310    }
311  PRINTF(2)("Model number %i in %s not Found.\n", groupNumber, this->getName());
312  return;
313
314}
315
316/**
317 *  Draws the Model with a specific groupName
318 * @param groupName The name of the group that will be displayed.
319
320   It does this by just calling the List that must have been created earlier.
321*/
322void Model::draw (char* groupName) const
323{
324  PRINTF(4)("drawing the requested 3D-Models if found.\n");
325  ModelGroup* tmpGroup = this->firstGroup;
326  while (tmpGroup != NULL)
327    {
328      if (!strcmp(tmpGroup->name, groupName))
329        {
330          PRINTF(4)("Drawing model %s\n", tmpGroup->name);
331          glCallList (tmpGroup->listNumber);
332          return;
333        }
334      tmpGroup = tmpGroup->next;
335    }
336  PRINTF(2)("Model Named %s in %s not Found.\n", groupName, this->getName());
337  return;
338}
339
340//////////
341// INIT //
342//////////
343/**
344 *  deletes all the arrays
345*/
346bool Model::deleteArrays()
347{
348  if (this->vertices)
349    delete this->vertices;
350  if (this->vTexture)
351    delete this->vTexture;
352  if (this->normals)
353    delete this->normals;
354  if (this->triangles)
355    delete[] this->triangles;
356
357  this->vertices = NULL;
358  this->vTexture = NULL;
359  this->normals = NULL;
360  this->triangles = NULL;
361  this->triangleCount = 0;
362}
363
364/**
365 *  finalizes an Model.
366 * This funcion is needed, to delete all the Lists, and arrays that are no more
367 * needed because they are already imported into openGL.
368 * This will be applied at the end of the importing Process.
369*/
370bool Model::cleanup()
371{
372  PRINTF(4)("cleaning up the 3D-Model to save Memory.\n");
373  this->firstGroup->cleanup();
374  return true;
375}
376
377//////////
378// MESH //
379//////////
380/**
381 * adds a new Material to the Material List
382 * @param material the Material to add
383 * @returns the added material
384 *
385 * this also tells this Model, that all the Materials are handled externally
386 * with this option set the Materials will not be deleted with the Model.
387 */
388Material* Model::addMaterial(Material* material)
389{
390  if (material == NULL)
391    return NULL;
392  ModelMaterial* modMat = new ModelMaterial;
393  modMat->external = true;
394  modMat->material = material;
395  this->materialList->add(modMat);
396  return modMat->material;
397}
398
399/**
400 *  adds a new Material to the Material List
401 * @param materialName the name of the Material to add
402 * @returns the added material
403*/
404Material* Model::addMaterial(const char* materialName)
405{
406  ModelMaterial* modMat = new ModelMaterial;
407  modMat->external = false;
408  modMat->material = new Material(materialName);
409
410  // adding material to the List of materials
411  this->materialList->add(modMat);
412  return modMat->material;
413}
414
415/**
416 *  finds a Material by its name and returns it
417 * @param materialName the Name of the material to search for.
418 * @returns the Material if found, NULL otherwise
419*/
420Material* Model::findMaterialByName(const char* materialName)
421{
422  tIterator<ModelMaterial>* tmpIt = this->materialList->getIterator();
423  ModelMaterial* modMat = tmpIt->firstElement();
424  while(modMat != NULL)
425    {
426      if (!strcmp(modMat->material->getName(), materialName))
427        {
428          delete tmpIt;
429          return modMat->material;
430        }
431      modMat = tmpIt->nextElement();
432    }
433  delete tmpIt;
434  return NULL;
435}
436
437/**
438 *  parses a group String
439 * @param groupString the new Group to create
440
441   This function initializes a new Group.
442   With it you should be able to create Models with more than one SubModel inside
443*/
444bool Model::addGroup(const char* groupString)
445{
446  PRINTF(5)("Read Group: %s.\n", groupString);
447  if (this->groupCount != 0 && this->currentGroup->faceCount > 0)
448    {
449      // finalizeGroup(currentGroup);
450      this->currentGroup = this->currentGroup->next = new ModelGroup;
451    }
452  // setting the group name if not default.
453  if (strcmp(groupString, "default"))
454    {
455      this->currentGroup->name = new char [strlen(groupString)+1];
456      strcpy(this->currentGroup->name, groupString);
457    }
458  ++this->groupCount;
459}
460
461/**
462 *  parses a vertex-String
463 * @param vertexString The String that will be parsed.
464
465   If a vertex line is found this function will inject it into the vertex-Array
466*/
467bool Model::addVertex (const char* vertexString)
468{
469  float subbuffer1;
470  float subbuffer2;
471  float subbuffer3;
472  sscanf (vertexString, "%f %f %f", &subbuffer1, &subbuffer2, &subbuffer3);
473  this->vertices->addEntry(subbuffer1*scaleFactor, subbuffer2*scaleFactor, subbuffer3*scaleFactor);
474  this->vertexCount++;
475  return true;
476}
477
478/**
479 *  parses a vertex-String
480 * @param x the X-coordinate of the Vertex to add.
481 * @param y the Y-coordinate of the Vertex to add.
482 * @param z the Z-coordinate of the Vertex to add.
483
484*/
485bool Model::addVertex(float x, float y, float z)
486{
487  PRINTF(5)("reading in a vertex: %f %f %f\n", x, y, z);
488  this->vertices->addEntry(x*scaleFactor, y*scaleFactor, z*scaleFactor);
489  this->vertexCount++;
490  return true;
491}
492
493/**
494 *  parses a vertexNormal-String
495 * @param normalString The String that will be parsed.
496
497   If a vertexNormal line is found this function will inject it into the vertexNormal-Array
498*/
499bool Model::addVertexNormal (const char* normalString)
500{
501  float subbuffer1;
502  float subbuffer2;
503  float subbuffer3;
504  sscanf (normalString, "%f %f %f", &subbuffer1, &subbuffer2, &subbuffer3);
505  this->normals->addEntry(subbuffer1, subbuffer2, subbuffer3);
506  this->normalCount++;
507  return true;
508}
509
510/**
511 *  adds a VertexNormal.
512 * @param x The x coordinate of the Normal.
513 * @param y The y coordinate of the Normal.
514 * @param z The z coordinate of the Normal.
515
516   If a vertexNormal line is found this function will inject it into the vertexNormal-Array
517*/
518bool Model::addVertexNormal(float x, float y, float z)
519{
520  PRINTF(5)("found vertex-Normal %f, %f, %f\n", x, y, z);
521  this->normals->addEntry(x, y, z);
522  this->normalCount++;
523  return true;
524}
525
526/**
527 *  parses a vertexTextureCoordinate-String
528 * @param vTextureString The String that will be parsed.
529
530   If a vertexTextureCoordinate line is found,
531   this function will inject it into the vertexTexture-Array
532
533   !! WARNING THIS IS DIFFERNT FROM addVervexTexture(float, float); because it changes the second entry to 1-v !!
534*/
535bool Model::addVertexTexture (const char* vTextureString)
536{
537  float subbuffer1;
538  float subbuffer2;
539  sscanf (vTextureString, "%f %f", &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)("This model (%s) got over 4 vertices per face <=> conflicts in the CD engine!\n", this->getName());
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  /* write MODELINFO structure */
930
931  /* allocate memory for the new triangle structures */
932  if( (this->triangles = new sTriangleExt[this->triangleCount]) == NULL)
933  {
934    PRINTF(1)("Could not allocate memory for triangle list\n");
935    return false;
936  }
937
938  /* now iterate through all groups and build up the triangle list */
939  this->currentGroup = this->firstGroup;
940  while( this->currentGroup != NULL)
941  {
942      // Putting Faces to GL
943    tmpFace = this->currentGroup->firstFace;
944    while( tmpFace != NULL)
945    {
946      tmpElem = tmpFace->firstElem;
947
948      /* if its a triangle just add it to the list */
949      if( tmpFace->vertexCount == 3)
950      {
951        for( int j = 0; j < 3; ++j)
952        {
953          this->triangles[index].indexToVertices[j] = (unsigned int)tmpElem->vertexNumber * 3;
954          this->triangles[index].indexToNormals[j] = (unsigned int)tmpElem->normalNumber * 3;
955          this->triangles[index].indexToTexCoor[j] = (unsigned int)tmpElem->texCoordNumber * 3;
956          tmpElem = tmpElem->next;
957        }
958        ++index;
959      } /* if the polygon is a quad */
960      else if( tmpFace->vertexCount == 4)
961      {
962
963        this->triangles[index].indexToVertices[0] = (unsigned int)tmpElem->vertexNumber * 3;
964        this->triangles[index].indexToNormals[0] = (unsigned int)tmpElem->normalNumber * 3;
965        this->triangles[index].indexToTexCoor[0] = (unsigned int)tmpElem->texCoordNumber * 3;
966
967        this->triangles[index + 1].indexToVertices[0] = (unsigned int)tmpElem->vertexNumber * 3;
968        this->triangles[index + 1].indexToNormals[0] = (unsigned int)tmpElem->normalNumber * 3;
969        this->triangles[index + 1].indexToTexCoor[0] = (unsigned int)tmpElem->texCoordNumber * 3;
970        tmpElem = tmpElem->next;
971
972        this->triangles[index].indexToVertices[1] = (unsigned int)tmpElem->vertexNumber * 3;
973        this->triangles[index].indexToNormals[1] = (unsigned int)tmpElem->normalNumber * 3;
974        this->triangles[index].indexToTexCoor[1] = (unsigned int)tmpElem->texCoordNumber * 3;
975        tmpElem = tmpElem->next;
976
977        this->triangles[index].indexToVertices[2] = (unsigned int)tmpElem->vertexNumber * 3;
978        this->triangles[index].indexToNormals[2] = (unsigned int)tmpElem->normalNumber * 3;
979        this->triangles[index].indexToTexCoor[2] = (unsigned int)tmpElem->texCoordNumber * 3;
980
981        this->triangles[index + 1].indexToVertices[2] = (unsigned int)tmpElem->vertexNumber * 3;
982        this->triangles[index + 1].indexToNormals[2] = (unsigned int)tmpElem->normalNumber * 3;
983        this->triangles[index + 1].indexToTexCoor[2] = (unsigned int)tmpElem->texCoordNumber * 3;
984        tmpElem = tmpElem->next;
985
986        this->triangles[index + 1].indexToVertices[1] = (unsigned int)tmpElem->vertexNumber * 3;
987        this->triangles[index + 1].indexToNormals[1] = (unsigned int)tmpElem->normalNumber * 3;
988        this->triangles[index + 1].indexToTexCoor[1] = (unsigned int)tmpElem->texCoordNumber * 3;
989
990        index += 2;
991      }
992      tmpFace = tmpFace->next;
993    }
994    this->currentGroup = this->currentGroup->next;
995  }
996  return true;
997}
998
999
1000/**
1001 *  Adds a Face-element (one vertex of a face) with all its information.
1002 * @param elem The FaceElement to add to the OpenGL-environment.
1003
1004   It does this by searching:
1005   1. The Vertex itself
1006   2. The VertexNormale
1007   3. The VertexTextureCoordinate
1008   merging this information, the face will be drawn.
1009*/
1010bool Model::addGLElement (ModelFaceElement* elem)
1011{
1012  PRINTF(5)("importing grafical Element to openGL.\n");
1013
1014  if (elem->texCoordNumber != -1)
1015    {
1016      if (likely(elem->texCoordNumber < this->texCoordCount))
1017        glTexCoord2fv(this->vTexture->getArray() + elem->texCoordNumber * 2);
1018      else
1019        PRINTF(2)("TextureCoordinate %d is not in the List (max: %d)\nThe Model might be incomplete\n",
1020                  elem->texCoordNumber, this->texCoordCount);
1021    }
1022  if (elem->normalNumber != -1)
1023    {
1024    if (likely(elem->normalNumber < this->normalCount))
1025      glNormal3fv(this->normals->getArray() + elem->normalNumber * 3);
1026    else
1027        PRINTF(2)("Normal %d is not in the List (max: %d)\nThe Model might be incomplete",
1028                  elem->normalNumber, this->normalCount);
1029    }
1030  if (elem->vertexNumber != -1)
1031    {
1032      if (likely(elem->vertexNumber < this->vertexCount))
1033          glVertex3fv(this->vertices->getArray() + elem->vertexNumber * 3);
1034      else
1035        PRINTF(2)("Vertex %d is not in the List (max: %d)\nThe Model might be incomplete",
1036                  elem->vertexNumber, this->vertexCount);
1037    }
1038
1039}
1040
1041/**
1042 *  Includes a default model
1043
1044   This will inject a Cube, because this is the most basic model.
1045*/
1046void Model::cubeModel()
1047{
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  this->addVertex (0.5, -0.5, -0.5);
1056
1057  this->addVertexTexture (0.0, 0.0);
1058  this->addVertexTexture (1.0, 0.0);
1059  this->addVertexTexture (0.0, 1.0);
1060  this->addVertexTexture (1.0, 1.0);
1061  this->addVertexTexture (0.0, 2.0);
1062  this->addVertexTexture (1.0, 2.0);
1063  this->addVertexTexture (0.0, 3.0);
1064  this->addVertexTexture (1.0, 3.0);
1065  this->addVertexTexture (0.0, 4.0);
1066  this->addVertexTexture (1.0, 4.0);
1067  this->addVertexTexture (2.0, 0.0);
1068  this->addVertexTexture (2.0, 1.0);
1069  this->addVertexTexture (-1.0, 0.0);
1070  this->addVertexTexture (-1.0, 1.0);
1071
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, 0.0, 1.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, 1.0, 0.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, 0.0, -1.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 (0.0, -1.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  this->addVertexNormal (-1.0, 0.0, 0.0);
1096
1097  this->addFace (4, VERTEX_TEXCOORD_NORMAL, 0,0,0, 1,1,1, 3,3,2, 2,2,3);
1098  this->addFace (4, VERTEX_TEXCOORD_NORMAL, 2,2,4, 3,3,5, 5,5,6, 4,4,7);
1099  this->addFace (4, VERTEX_TEXCOORD_NORMAL, 4,4,8, 5,5,9, 7,7,10, 6,6,11);
1100  this->addFace (4, VERTEX_TEXCOORD_NORMAL, 6,6,12, 7,7,13, 1,9,14, 0,8,15);
1101  this->addFace (4, VERTEX_TEXCOORD_NORMAL, 1,1,16, 7,10,17, 5,11,18, 3,3,19);
1102  this->addFace (4, VERTEX_TEXCOORD_NORMAL, 6,12,20, 0,0,21, 2,2,22, 4,13,23);
1103}
Note: See TracBrowser for help on using the repository browser.