Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: so, ResourceManager now operates on BaseObjects. If this is better, i do not know, but at least it is more intuitive, i think

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