Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 4804 was 4804, checked in by patrick, 19 years ago

orxonox/trunk: introduced the modelInfo struct which contains refereces to all data a model needs, this will serve as an interface

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