Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/graphics/importer/static_model.cc @ 7711

Last change on this file since 7711 was 7711, checked in by patrick, 18 years ago

trunk: merged the cd branche back to trunk

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