Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: removed stupid included in base_object.h
this should lead to faster compile-times

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