Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/graphics/importer/vertex_list_model.cc @ 6008

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

orxonox/trunk: some more functionality in the abstractModel class

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