Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/std/src/lib/graphics/importer/static_model.cc @ 7203

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

orxonox/trunk: compiles again, BUT well…. i do not expect it to run anymore

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