Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/graphics/importer/model.cc @ 5969

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

orxonox/trunk: rescale of the screen-size should reload Models too on windows

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