Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 5260 was 5218, checked in by bensch, 19 years ago

orxonox/trunk: more error-fixes… thanks Valgrind team :)

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