Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/graphics/importer/static_model.cc @ 6162

Last change on this file since 6162 was 6162, checked in by bensch, 18 years ago

orxonox/trunk: merged the spaceshipcontroll branche into the trunk
merged with command
svn merge -r6036:HEAD spaceshipcontrol/ ../trunk/
no conflicts

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