Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/newModel/src/lib/graphics/importer/static_model.cc @ 6020

Last change on this file since 6020 was 6020, checked in by bensch, 18 years ago

newModel: renaming

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