Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/height_map/src/lib/graphics/importer/static_model.cc @ 6529

Last change on this file since 6529 was 6529, checked in by bottac, 18 years ago

Some bugs fixed

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