Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: valgrind mem-leak-recovered

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