Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/height_map/src/lib/graphics/importer/model.cc @ 6014

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