Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/spaceshipcontrol/src/lib/graphics/importer/static_model.cc @ 6046

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

orxonox/branches/controll: Should compile on windows again

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