Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/height_map/src/lib/graphics/importer/static_model.cc @ 6472

Last change on this file since 6472 was 6472, checked in by bottac, 18 years ago

Added Class Tile to HeightMap (allows a primitive LOD Implementation).

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