Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: some minor include stuff

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