Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

trunk: staticModel now uses vector instead of tArray (more portable)

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