Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/graphics/importer/static_model_data.cc

Last change on this file was 10147, checked in by patrick, 17 years ago

merged the mount_point branche back to trunk to use the new std::* based obj file importer

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