Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/graphics/importer/model.cc @ 5774

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

orxonox/trunk: stl in Model

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