Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: physicsInterface fixed

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