Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: static definitions

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