Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/new_class_id/src/lib/graphics/importer/static_model_data.cc @ 9829

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

new static_model_data added

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