Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/trunk/src/importer/model.cc @ 3467

Last change on this file since 3467 was 3454, checked in by bensch, 20 years ago

orxonox/trunk/importer: doxygen-tags

File size: 24.7 KB
RevLine 
[2823]1/*
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: ...
14*/
15
[3360]16#include "model.h"
[3427]17
[3400]18#include <math.h>
[3418]19#include <stdarg.h>
[3398]20
[3427]21#include "array.h"
22#include "../vector.h"
23
[3140]24using namespace std;
[2776]25
[2842]26/**
[3398]27   \brief Creates a 3D-Model.
[3186]28
[3398]29   This only initializes a 3D-Model, but does not cleanup the Faces.
[2842]30*/
[3398]31Model::Model(void)
[2748]32{
[3398]33  this->initialize();
34}
[2765]35
[3398]36/**
37   \brief Creates a 3D-Model of Primitive-Type type
38
39   if you want to just display a Cube/Sphere/Cylinder/... without any material.
40   
41   \todo implement Cube/Sphere/Cylinder/...
42*/
43Model::Model(PRIMITIVE type)
44{
[3195]45  this->initialize();
[2847]46
[3400]47  switch (type)
48    {
49    default:
50    case CUBE:
51      this->cubeModel();
52      break;
53    case SPHERE:
[3418]54      this->sphereModel();
[3400]55      break;
56    case CYLINDER:
[3426]57      this->cylinderModel();
[3400]58      break;
[2765]59
[3400]60    }
[3195]61  this->importToGL ();
[3064]62
[3195]63  this->cleanup();
[2767]64}
65
[2842]66/**
[3398]67   \brief Creates a 3D-Model. and assigns it a Name.
68*/
69Model::Model(char* modelName)
70{
71  this->initialize();
72  this->setName(modelName);
73}
74
75/**
[3360]76   \brief deletes an Model.
[3186]77
[3360]78   Looks if any from model allocated space is still in use, and if so deleted it.
[2847]79*/
[3398]80Model::~Model(void)
[2847]81{
[3397]82  PRINTF(3)("Deleting Model ");
[3396]83  if (this->name)
84    {
[3397]85      PRINT(3)("%s\n", this->name);
[3396]86      delete []this->name;
87    }
88  else
[3397]89      PRINT(3)("\n");
[3396]90
[3397]91  PRINTF(3)("Deleting display Lists.\n");
[3195]92  Group* walker = this->firstGroup;
[2850]93  while (walker != NULL)
94    {
95      glDeleteLists (walker->listNumber, 1);
[3066]96      Group* delWalker = walker;
[3063]97      walker = walker->next;
[3066]98      delete delWalker;
[3140]99    }
100
[3397]101  PRINTF(3)("Deleting Materials.\n");
[3195]102  if (this->material)
103    delete this->material;
[2847]104}
105
[2842]106/**
[3398]107   \brief Finalizes an Object. This can be done outside of the Class.
108*/
109void Model::finalize(void)
110{
111  this->importToGL ();
112 
113  this->cleanup();
114
115  this->finalized = true;
116}
117
118/**
[3360]119   \brief Draws the Models of all Groups.
[2851]120   It does this by just calling the Lists that must have been created earlier.
[2842]121*/
[3360]122void Model::draw (void) const
[2748]123{
[3360]124  PRINTF(2)("drawing the 3D-Models\n"); 
[3195]125  Group* walker = this->firstGroup;
[2850]126  while (walker != NULL)
127    {
[3360]128      PRINTF(3)("Drawing model %s\n", walker->name);
[2850]129      glCallList (walker->listNumber);
[3063]130      walker = walker->next;
[2850]131    }
[2748]132}
[2754]133
[2842]134/**
[3360]135   \brief Draws the Model number groupNumber
[3186]136   \param groupNumber The number of the group that will be displayed.
137
[2851]138   It does this by just calling the List that must have been created earlier.
139*/
[3360]140void Model::draw (int groupNumber) const 
[2851]141{
[3195]142  if (groupNumber >= this->groupCount)
[2852]143    {
[3360]144      PRINTF(1)("You requested model number %i, but this File only contains of %i Models.\n", groupNumber-1, this->groupCount);
[2852]145      return;
146    }
[3360]147  PRINTF(2)("drawing the requested 3D-Models if found.\n"); 
[3195]148  Group* walker = this->firstGroup;
[2851]149  int counter = 0;
150  while (walker != NULL)
151    {
152      if (counter == groupNumber)
153        {
[3360]154          PRINTF(2)("Drawing model number %i named %s\n", counter, walker->name);
[2851]155          glCallList (walker->listNumber);
156          return;
157        }
158      ++counter;
[3063]159      walker = walker->next;
[2851]160    }
[3396]161  PRINTF(1)("Model number %i in %s not Found.\n", groupNumber, this->name);
[2851]162  return;
163
164}
[2852]165
166/**
[3360]167   \brief Draws the Model with a specific groupName
[3186]168   \param groupName The name of the group that will be displayed.
169
[2852]170   It does this by just calling the List that must have been created earlier.
171*/
[3360]172void Model::draw (char* groupName) const
[2851]173{
[3360]174  PRINTF(2)("drawing the requested 3D-Models if found.\n"); 
[3195]175  Group* walker = this->firstGroup;
[2851]176  while (walker != NULL)
177    {
178      if (!strcmp(walker->name, groupName))
179        {
[3360]180          PRINTF(2)("Drawing model %s\n", walker->name);
[2851]181          glCallList (walker->listNumber);
182          return;
183        }
[3063]184      walker = walker->next;
[2851]185    }
[3396]186  PRINTF(1)("Model Named %s in %s not Found.\n", groupName, this->name);
[2851]187  return;
188}
189
[2852]190/**
[3360]191   \returns Count of the Models in this File
[2852]192*/
[3360]193int Model::getGroupCount (void) const
[2852]194{
[3195]195  return this->groupCount;
[2852]196}
[2851]197
198/**
[3360]199    \brief initializes the Model.
[3186]200
201    This Function initializes all the needed arrays, Lists and clientStates.
202    It also defines default values.
[3066]203*/
[3360]204bool Model::initialize (void)
[3066]205{
[3360]206  PRINTF(2)("new 3D-Model is being created\n"); 
[3066]207
[3396]208  this->name = NULL;
[3398]209  this->finalized = false;
[3066]210  // setting the start group;
[3195]211  this->firstGroup = new Group;
212  this->currentGroup = this->firstGroup;
213  this->groupCount = 0;
[3066]214 
[3195]215  this->initGroup (this->currentGroup);
216  this->scaleFactor = 1;
217  this->material = new Material();
[3066]218
[3195]219  this->vertices = new Array();
220  this->vTexture = new Array();
221  this->normals = new Array();
[3066]222
223  return true;
224}
225
[3454]226/**
227   \brief sets a name to the Model
228   \param name The name to set to this Model
229*/
[3398]230void Model::setName(const char* name)
231{
232  if (this->name) 
233    delete this->name;
234  this->name = new char[strlen(name)+1];
235  strcpy(this->name, name);
236}
[3066]237/**
[3360]238   \brief initializes a new Group model
[3186]239   \param group the group that should be initialized.
240   \todo Maybe Group should be a Class, because it does a lot of stuff
241   
[2850]242*/
[3360]243bool Model::initGroup(Group* group)
[2850]244{
[3207]245  PRINTF(3)("Adding new Group\n");
[2863]246  group->name = "";
[2850]247  group->faceMode = -1;
[2967]248  group->faceCount = 0; 
[3063]249  group->next = NULL;
[2850]250
[3063]251  group->firstFace = new Face;
[3195]252  this->initFace (group->firstFace);
[3063]253  group->currentFace = group->firstFace;
[2850]254}
255
256/**
[3066]257   \brief initializes a new Face. (sets default Values)
[3186]258   \param face The face to initialize
[2850]259*/
[3360]260bool Model::initFace (Face* face)
[2850]261{
[3066]262  face->vertexCount = 0;
[2967]263
[3066]264  face->firstElem = NULL;
265 
266  face->materialString = NULL;
267 
268  face->next = NULL;
269
270  return true;
[2850]271}
[2863]272
[2850]273/**
[3360]274   \brief finalizes an Model.
[3066]275   This funcion is needed, to delete all the Lists, and arrays that are no more needed because they are already imported into openGL. This will be applied at the end of the importing Process.
276*/
[3360]277bool Model::cleanup(void)
[3066]278{
[3360]279  PRINTF(3)("cleaning up the 3D-Model to save Memory.\n");
[3066]280
[3195]281  if (this->vertices)
282    delete this->vertices;
283  if (this->vTexture)
284    delete this->vTexture;
285  if (this->normals)
286    delete this->normals;
[3066]287
[3195]288  this->cleanupGroup(this->firstGroup);
[3066]289  return true; 
290}
291
292/**
[3068]293   \brief Cleans up all groups starting from group.
294   \param group the first Group to clean
295*/
[3360]296bool Model::cleanupGroup (Group* group)
[3068]297{
[3207]298  PRINTF(3)("Cleaning up group\n");
[3068]299  if (group->firstFace != NULL)
300    {
301      cleanupFace (group->firstFace);
302      delete group->firstFace;
303    }
304
305  if (group->next !=NULL)
306    cleanupGroup (group->next);
307  return true;
308}
309
310/**
[3186]311   \brief Cleans up all Faces starting from face until NULL is reached.
312   \param face the first face to clean.
[3068]313*/
[3360]314bool Model::cleanupFace (Face* face)
[3068]315{
[3207]316  PRINTF(3)("Cleaning up Face\n");
[3068]317
318  if (face->materialString != NULL)
[3080]319      delete []face->materialString;
[3068]320  if (face->firstElem != NULL)
321    {
[3195]322      this->cleanupFaceElement(face->firstElem);
[3068]323      delete face->firstElem;
324    }
325     
326  if (face->next != NULL)
327    {
[3195]328      this->cleanupFace (face->next);
[3068]329      delete face->next;
330    }
331     
332}
333
334
335/**
336   \brief Cleans up all FaceElements starting from faceElem.
337   \param faceElem the first FaceElement to clean.
338*/
[3360]339bool Model::cleanupFaceElement(FaceElement* faceElem)
[3068]340{
341  if (faceElem->next != NULL)
342    {
[3195]343      this->cleanupFaceElement (faceElem->next);
[3072]344      delete faceElem->next;
[3068]345    }
346}
347
348/**
[3066]349   \brief parses a group String
[3186]350   \param groupString the new Group to create
351
[3066]352   This function initializes a new Group.
[3360]353   With it you should be able to import .obj-files with more than one Models inside.
[3066]354*/
[3396]355bool Model::addGroup (char* groupString)
[3066]356{
[3207]357  PRINTF(3)("Read Group: %s.\n", groupString);
[3195]358  if (this->groupCount != 0 && this->currentGroup->faceCount>0)
[3066]359    {
360      //      finalizeGroup(currentGroup);
[3195]361      this->currentGroup = this->currentGroup->next = new Group;
362      this->initGroup(this->currentGroup);
[3066]363    }
[3140]364  // setting the group name if not default.
365  if (strcmp(groupString, "default"))
366    {
[3195]367      this->currentGroup->name = new char [strlen(groupString)+1];
368      strcpy(this->currentGroup->name, groupString);
[3140]369    }
[3195]370  ++this->groupCount;
[3066]371
372}
373
374/**
[2842]375   \brief parses a vertex-String
[3186]376   \param vertexString The String that will be parsed.
377
[2842]378   If a vertex line is found this function will inject it into the vertex-Array
379*/
[3396]380bool Model::addVertex (char* vertexString)
[2767]381{
[3071]382  float subbuffer1;
383  float subbuffer2;
384  float subbuffer3;
385  sscanf (vertexString, "%f %f %f", &subbuffer1, &subbuffer2, &subbuffer3);
[3207]386  PRINTF(3)("reading in a vertex: %f %f %f\n", &subbuffer1, &subbuffer2, &subbuffer3);
[3195]387  this->vertices->addEntry(subbuffer1*scaleFactor, subbuffer2*scaleFactor, subbuffer3*scaleFactor);
[2767]388  return true;
389}
390
[2842]391/**
[3400]392   \brief parses a vertex-String
393   \param x the X-coordinate of the Vertex to add.
394   \param y the Y-coordinate of the Vertex to add.
395   \param z the Z-coordinate of the Vertex to add.
396   
397*/
398bool Model::addVertex(const float x, const float y, const float z)
399{
400  PRINTF(4)("reading in a vertex: %f %f %f\n", x, y, z);
401  this->vertices->addEntry(x*scaleFactor, y*scaleFactor, z*scaleFactor);
402  return true;
403}
404
405/**
[2842]406   \brief parses a face-string
[3186]407   \param faceString The String that will be parsed.
408
[2842]409   If a face line is found this function will add it to the glList.
410*/
[3396]411bool Model::addFace (char* faceString)
[2767]412{
[3195]413  if (this->currentGroup->faceCount >0)
414    this->currentGroup->currentFace = this->currentGroup->currentFace->next = new Face;
415  this->initFace (this->currentGroup->currentFace);
[2767]416
[3195]417  FaceElement* tmpElem = this->currentGroup->currentFace->firstElem = new FaceElement;
[3068]418  tmpElem->next = NULL;
[2934]419  while(strcmp (faceString, "\0"))
[2767]420    {
[3195]421      if (this->currentGroup->currentFace->vertexCount>0)
[2934]422          tmpElem = tmpElem->next = new FaceElement;
423      tmpElem->next = NULL;
424
[3064]425      char tmpValue [50];
[3072]426      int tmpLen;
427      char* vertex = NULL;
428      char* texture = NULL;
429      char* normal = NULL;
430
[3063]431      sscanf (faceString, "%s", tmpValue);
[3072]432      tmpLen = strlen(tmpValue);
433      vertex = tmpValue;
[2934]434
[3072]435      if ((texture = strstr (vertex, "/")) != NULL)
436        {
437          texture[0] = '\0';
438          texture ++;
439         
440          if ((normal = strstr (texture, "/")) !=NULL)
441            {
442              normal[0] = '\0';
443              normal ++;
444            }     
445        }
446      if (vertex)
[3073]447        tmpElem->vertexNumber = atoi(vertex)-1;
[3072]448      else
[3073]449        tmpElem->vertexNumber = -1;
[3072]450      if (texture)
[3073]451        tmpElem->texCoordNumber = atoi(texture)-1;
[3072]452      else
[3073]453        tmpElem->texCoordNumber = -1;
[3072]454      if (normal)
[3073]455        tmpElem->normalNumber = atoi(normal)-1;
[3072]456      else
[3073]457        tmpElem->normalNumber = -1;
[3072]458
459      faceString += tmpLen;
[2934]460      if (strcmp (faceString, "\0"))
461        faceString++;
[3195]462      this->currentGroup->currentFace->vertexCount++;
[2934]463    }
464
[3195]465  this->currentGroup->faceCount += this->currentGroup->currentFace->vertexCount -2;
[2754]466}
[2768]467
[2842]468/**
[3418]469   \brief adds a new Face
470   \param faceElemCount the number of Vertices to add to the Face.
471   \param type 0: vertex only, 1: vertex and normal, 2: vertex and Texture, 3 vertex, normal and texture
[3400]472*/
[3418]473bool Model::addFace(const float faceElemCount, int type, ...)
[3400]474{
[3418]475   if (this->currentGroup->faceCount > 0)
476    this->currentGroup->currentFace = this->currentGroup->currentFace->next = new Face;
477  this->initFace (this->currentGroup->currentFace);
[3400]478
[3418]479  FaceElement* tmpElem = this->currentGroup->currentFace->firstElem = new FaceElement;
480  tmpElem->next = NULL;
481 
482  va_list itemlist;
483  va_start (itemlist, type);
484
485  for (int i = 0; i < faceElemCount; i++)
486    {
487      if (this->currentGroup->currentFace->vertexCount>0)
488          tmpElem = tmpElem->next = new FaceElement;
489      tmpElem->next = NULL;
490
491      tmpElem->vertexNumber = va_arg (itemlist, int) -1;
492      if (type >= 2)
493        tmpElem->texCoordNumber = va_arg (itemlist, int) -1;
494      if (type == 1 || type ==3)
495        tmpElem->normalNumber = va_arg(itemlist, int) -1;
496      this->currentGroup->currentFace->vertexCount++;
497    }
498  va_end(itemlist);
499
500  this->currentGroup->faceCount += this->currentGroup->currentFace->vertexCount - 2;
[3400]501}
502
503/**
[2842]504   \brief parses a vertexNormal-String
[3186]505   \param normalString The String that will be parsed.
506
[2842]507   If a vertexNormal line is found this function will inject it into the vertexNormal-Array
508*/
[3396]509bool Model::addVertexNormal (char* normalString)
[2794]510{
[3071]511  float subbuffer1;
512  float subbuffer2;
513  float subbuffer3;
514  sscanf (normalString, "%f %f %f", &subbuffer1, &subbuffer2, &subbuffer3);
[3207]515  PRINTF(3)("found vertex-Normal %f, %f, %f\n", &subbuffer1,&subbuffer2,&subbuffer3);
[3195]516  this->normals->addEntry(subbuffer1, subbuffer2, subbuffer3);
[2794]517  return true;
518}
519
[2842]520/**
[3400]521   \brief adds a VertexNormal.
522   \param x The x coordinate of the Normal.
523   \param y The y coordinate of the Normal.
524   \param z The z coordinate of the Normal.
525
526   If a vertexNormal line is found this function will inject it into the vertexNormal-Array
527*/
528bool Model::addVertexNormal(const float x, const float y, const float z)
529{
530  PRINTF(3)("found vertex-Normal %f, %f, %f\n", x, y, z);
531  this->normals->addEntry(x, y, z);
532}
533
534/**
[2842]535   \brief parses a vertexTextureCoordinate-String
536   \param vTextureString The String that will be parsed.
[3186]537
538   If a vertexTextureCoordinate line is found,
539   this function will inject it into the vertexTexture-Array
[2842]540*/
[3396]541bool Model::addVertexTexture (char* vTextureString)
[2820]542{
[3071]543  float subbuffer1;
544  float subbuffer2;
545  sscanf (vTextureString, "%f %f", &subbuffer1, &subbuffer2);
[3207]546  PRINTF(3)("found vertex-Texture %f, %f\n", &subbuffer1, &subbuffer2);
[3195]547  this->vTexture->addEntry(subbuffer1);
548  this->vTexture->addEntry(subbuffer2);
[2820]549  return true;
550}
551
[3066]552/**
[3400]553   \brief adds a Texture Coordinate
554   \param u The u coordinate of the TextureCoordinate.
555   \param v The y coordinate of the TextureCoordinate.
556
557   If a TextureCoordinate line is found this function will inject it into the TextureCoordinate-Array
558*/
559bool Model::addVertexTexture(const float u, const float v)
560{
561  PRINTF(3)("found vertex-Texture %f, %f\n", u, v);
562  this->vTexture->addEntry(u);
563  this->vTexture->addEntry(v);
564}
565
566/**
[3066]567   \brief Function that selects a material, if changed in the obj file.
568   \param matString the Material that will be set.
569*/
[3396]570bool Model::addUseMtl (char* matString)
[3063]571{
[3396]572  /*
[3195]573  if (!this->mtlFileName)
[3066]574    {
[3207]575      PRINTF(4)("Not using new defined material, because no mtlFile found yet\n");
[3066]576      return false;
577    }
[3396]578  */     
[3195]579  if (this->currentGroup->faceCount >0)
580    this->currentGroup->currentFace = this->currentGroup->currentFace->next = new Face;
581  this->initFace (this->currentGroup->currentFace);
[3063]582 
[3195]583  this->currentGroup->currentFace->materialString = new char[strlen(matString)+1];
584  strcpy (this->currentGroup->currentFace->materialString, matString);
[3063]585 
[3195]586  if (this->currentGroup->faceCount == 0)
587    this->currentGroup->faceCount ++;
[3063]588
589}
590
[3066]591/**
592   \brief reads and includes the Faces/Materials into the openGL state Machine
593*/
[3360]594bool Model::importToGL (void)
[3063]595{
596
597  // finalize the Arrays
[3195]598  this->vertices->finalizeArray();
599  this->vTexture->finalizeArray();
[3426]600  if (normals->getCount() == 0) // vertices-Array must be built for this
[3195]601    this->buildVertexNormals();
602  this->normals->finalizeArray();
[3063]603
[3195]604  this->currentGroup = this->firstGroup;
[3063]605
[3195]606  while (this->currentGroup != NULL)
[3063]607    {
608
609      // creating a glList for the Group
[3195]610      if ((this->currentGroup->listNumber = glGenLists(1)) == 0)
[3063]611        {
[3360]612          PRINTF(1)("list could not be created for this Model\n");
[3063]613          return false;
614        }
[3195]615      glNewList (this->currentGroup->listNumber, GL_COMPILE);
[3063]616
617      // Putting Faces to GL
[3195]618      Face* tmpFace = this->currentGroup->firstFace;
[3063]619      while (tmpFace != NULL)
620        {
[3065]621          if (tmpFace->vertexCount == 0 && tmpFace->materialString != NULL)
[3063]622            {
[3195]623              if (this->currentGroup->faceMode != -1)
[3065]624                glEnd();
[3195]625              this->currentGroup->faceMode = 0;
[3069]626              Material* tmpMat;
627              if ((tmpMat = material->search(tmpFace->materialString)) != NULL)
[3396]628                {
629                  tmpMat->select();
630                  PRINTF(2)("using material %s for coming Faces.\n", tmpFace->materialString);
631                }
632              else 
633                PRINTF(1)("material %s not found.\n", tmpFace->materialString);
[3065]634
[3396]635
[3065]636            }
637
638          else if (tmpFace->vertexCount == 3)
639            {
[3195]640              if (this->currentGroup->faceMode != 3)
[3063]641                {
[3195]642                  if (this->currentGroup->faceMode != -1)
[3063]643                    glEnd();
644                  glBegin(GL_TRIANGLES);
645                }
646             
[3195]647              this->currentGroup->faceMode = 3;
[3207]648              PRINTF(3)("found triag.\n");
[3063]649            }
650         
651          else if (tmpFace->vertexCount == 4)
652            {
[3195]653              if (this->currentGroup->faceMode != 4)
[3063]654                {
[3195]655                  if (this->currentGroup->faceMode != -1)
[3063]656                    glEnd();
657                  glBegin(GL_QUADS);
658                }
[3195]659              this->currentGroup->faceMode = 4;
[3207]660              PRINTF(3)("found quad.\n");
[3063]661            }
662         
663          else if (tmpFace->vertexCount > 4)
664            {
[3195]665              if (this->currentGroup->faceMode != -1)
[3063]666                glEnd();
667              glBegin(GL_POLYGON);
[3207]668              PRINTF(3)("Polygon with %i faces found.", tmpFace->vertexCount);
[3195]669              this->currentGroup->faceMode = tmpFace->vertexCount;
[3063]670            }
671         
672          FaceElement* tmpElem = tmpFace->firstElem;
673          while (tmpElem != NULL)
674            {
[3207]675              //      PRINTF(2)("%s\n", tmpElem->value);
[3195]676              this->addGLElement(tmpElem);
[3063]677              tmpElem = tmpElem->next;
678            }
679          tmpFace = tmpFace->next;
680        }
681      glEnd();
682      glEndList();
[3195]683
684      this->currentGroup = this->currentGroup->next;
[3063]685    } 
686}
687
[3066]688/**
689   \brief Adds a Face-element (one vertex of a face) with all its information.
[3186]690   \param elem The FaceElement to add to the OpenGL-environment.
691
[3066]692   It does this by searching:
693   1. The Vertex itself
694   2. The VertexNormale
695   3. The VertexTextureCoordinate
696   merging this information, the face will be drawn.
[2842]697*/
[3360]698bool Model::addGLElement (FaceElement* elem)
[2776]699{
[3207]700  PRINTF(3)("importing grafical Element to openGL.\n");
[3066]701
[3073]702  if (elem->texCoordNumber != -1)
[3195]703    glTexCoord2fv(this->vTexture->getArray() + elem->texCoordNumber * 2);
[3073]704  if (elem->normalNumber != -1)
[3195]705    glNormal3fv(this->normals->getArray() + elem->normalNumber * 3);
[3073]706  if (elem->vertexNumber != -1)
[3195]707    glVertex3fv(this->vertices->getArray() + elem->vertexNumber * 3);
[2769]708
[2776]709}
710
[3079]711/**
712   \brief A routine that is able to create normals.
[3186]713
[3079]714   The algorithm does the following:
715   1. It calculates creates Vectors for each normale, and sets them to zero.
716   2. It then Walks through a) all the Groups b) all the Faces c) all the FaceElements
717   3. It searches for a points two neighbours per Face, takes Vecotrs to them calculates FaceNormals and adds it to the Points Normal.
718   4. It goes through all the normale-Points and calculates the VertexNormale and includes it in the normals-Array.
719*/
[3360]720bool Model::buildVertexNormals ()
[3075]721{
[3081]722 
[3207]723  PRINTF(2)("Normals are being calculated.\n");
[3075]724
725  Vector* normArray = new Vector [vertices->getCount()/3];
[3079]726  for (int i=0; i<vertices->getCount()/3;i++)
[3075]727    normArray[i] = Vector(.0,.0,.0);
[3081]728 
[3075]729  int firstTouch;
730  int secondTouch;
731  Vector prevV;
732  Vector nextV;
733  Vector curV;
734
735  Group* tmpGroup = firstGroup;
736  while (tmpGroup)
737    {
738      Face* tmpFace = tmpGroup->firstFace;
739      while (tmpFace)
740        {
741          if (tmpFace->firstElem)
742            {
743              FaceElement* firstElem = tmpFace->firstElem;
[3082]744              FaceElement* prevElem;
745              FaceElement* curElem = firstElem;
746              FaceElement* nextElem;
[3081]747              FaceElement* lastElem;
[3082]748              // 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.
[3081]749              while (curElem)
750                {
751                  prevElem = curElem;
752                  curElem = curElem->next;
753                }
754              lastElem = prevElem;
[3075]755             
[3081]756              curElem = firstElem;
757              for (int j=0; j<tmpFace->vertexCount; j++)
[3075]758                {
[3082]759                  if (!(nextElem = curElem->next))
760                    nextElem = firstElem;
[3075]761                  curElem->normalNumber = curElem->vertexNumber;
762                 
763                  curV = Vector (vertices->getArray()[curElem->vertexNumber*3], vertices->getArray()[curElem->vertexNumber*3+1], vertices->getArray()[curElem->vertexNumber*3+2]);
764                  prevV = Vector (vertices->getArray()[prevElem->vertexNumber*3], vertices->getArray()[prevElem->vertexNumber*3+1], vertices->getArray()[prevElem->vertexNumber*3+2]) - curV;
[3082]765                  nextV = Vector (vertices->getArray()[nextElem->vertexNumber*3], vertices->getArray()[nextElem->vertexNumber*3+1], vertices->getArray()[nextElem->vertexNumber*3+2]) - curV;
[3081]766                  normArray[curElem->vertexNumber] = normArray[curElem->vertexNumber] + nextV.cross(prevV);
[3075]767
768                  prevElem = curElem;
769                  curElem = curElem->next;
770                }
771            }
772          tmpFace = tmpFace->next;
773        }
774      tmpGroup = tmpGroup->next;
775    }
776
777  for (int i=0; i<vertices->getCount()/3;i++)
778    {
779      normArray[i].normalize();
[3207]780      PRINTF(3)("Found Normale number %d: (%f; %f, %f).\n", i, normArray[i].x, normArray[i].y, normArray[i].z);
[3426]781     
[3195]782      this->normals->addEntry(normArray[i].x, normArray[i].y, normArray[i].z);
[3075]783
784    }
[3080]785  delete []normArray; 
[3081]786 
[3075]787}
788
789
[2842]790/**
[3360]791   \brief Includes a default model
[3186]792
[3360]793   This will inject a Cube, because this is the most basic model.
[2842]794*/
[3400]795void Model::cubeModel(void)
[2821]796{
[3396]797  this->addVertex ("-0.5 -0.5 0.5");
798  this->addVertex ("0.5 -0.5 0.5");
799  this->addVertex ("-0.5 0.5 0.5");
800  this->addVertex ("0.5 0.5 0.5");
801  this->addVertex ("-0.5 0.5 -0.5");
802  this->addVertex ("0.5 0.5 -0.5");
803  this->addVertex ("-0.5 -0.5 -0.5");
804  this->addVertex ("0.5 -0.5 -0.5");
[2967]805
[3396]806  this->addVertexTexture ("0.0 0.0");
807  this->addVertexTexture ("1.0 0.0");
808  this->addVertexTexture ("0.0 1.0");
809  this->addVertexTexture ("1.0 1.0");
810  this->addVertexTexture ("0.0 2.0");
811  this->addVertexTexture ("1.0 2.0");
812  this->addVertexTexture ("0.0 3.0");
813  this->addVertexTexture ("1.0 3.0");
814  this->addVertexTexture ("0.0 4.0");
815  this->addVertexTexture ("1.0 4.0");
816  this->addVertexTexture ("2.0 0.0");
817  this->addVertexTexture ("2.0 1.0");
818  this->addVertexTexture ("-1.0 0.0");
819  this->addVertexTexture ("-1.0 1.0");
[3081]820
[3396]821  this->addVertexNormal ("0.0 0.0 1.0");
822  this->addVertexNormal ("0.0 0.0 1.0");
823  this->addVertexNormal ("0.0 0.0 1.0");
824  this->addVertexNormal ("0.0 0.0 1.0");
825  this->addVertexNormal ("0.0 1.0 0.0");
826  this->addVertexNormal ("0.0 1.0 0.0");
827  this->addVertexNormal ("0.0 1.0 0.0");
828  this->addVertexNormal ("0.0 1.0 0.0");
829  this->addVertexNormal ("0.0 0.0 -1.0");
830  this->addVertexNormal ("0.0 0.0 -1.0");
831  this->addVertexNormal ("0.0 0.0 -1.0");
832  this->addVertexNormal ("0.0 0.0 -1.0");
833  this->addVertexNormal ("0.0 -1.0 0.0");
834  this->addVertexNormal ("0.0 -1.0 0.0");
835  this->addVertexNormal ("0.0 -1.0 0.0");
836  this->addVertexNormal ("0.0 -1.0 0.0");
837  this->addVertexNormal ("1.0 0.0 0.0");
838  this->addVertexNormal ("1.0 0.0 0.0");
839  this->addVertexNormal ("1.0 0.0 0.0");
840  this->addVertexNormal ("1.0 0.0 0.0");
841  this->addVertexNormal ("-1.0 0.0 0.0");
842  this->addVertexNormal ("-1.0 0.0 0.0");
843  this->addVertexNormal ("-1.0 0.0 0.0");
844  this->addVertexNormal ("-1.0 0.0 0.0");
[2821]845
[3083]846  /* normaleLess-testingMode
[3396]847  this->addFace ("1 2 4 3");
848  this->addFace ("3 4 6 5");
849  this->addFace ("5 6 8 7");
850  this->addFace ("7 8 2 1");
851  this->addFace ("2 8 6 4");
852  this->addFace ("7 1 3 5");
[3083]853  */
[3081]854
[3396]855  this->addFace ("1/1/1 2/2/2 4/4/3 3/3/4");
856  this->addFace ("3/3/5 4/4/6 6/6/7 5/5/8");
857  this->addFace ("5/5/9 6/6/10 8/8/11 7/7/12");
858  this->addFace ("7/7/13 8/8/14 2/10/15 1/9/16");
859  this->addFace ("2/2/17 8/11/18 6/12/19 4/4/20");
860  this->addFace ("7/13/21 1/1/22 3/3/23 5/14/24");
[3083]861
[2821]862}
[3400]863
[3454]864/**
865   \brief Builds a Sphere into the Model
866*/
[3418]867void Model::sphereModel()
868{
869  int detail = 30;
870  if (detail <= 0) detail = 1;
871  float df = (float)detail;
872  for (float i = 0.0; i < df/2; i+=1.0)
873    {
874      for (float j = 0.0; j < df; j+=1.0)
875      {
876        float vz = i/df *2.0*PI - PI/2.0;
877        this->addVertex(cos(j/df*2.0*PI) * cos(vz) ,
878                        sin(j/df*2.0*PI) * cos(vz),
879                        sin(vz));
880        //if (j==0.0)
881        //printf ("%f %f\n", vz, sin (vz));
882        if (i==0.0)
883                  printf("%f, %f\n", j/df*2.0*PI, cos(j/df*PI));
884      }
885    }
886  vertices->debug();
887  for (int i = 0; i < detail/2; i++)
888    for (int j = 1; j < detail; j++)
889      {
890        unsigned int v1,v2,v3,v4;
891        v1 = i*detail +j;
892
893        /*      if (j+1 == detail)
894          {
895            v2 = i*detail +1;
896            v3 = i*detail+detail + 1;
897          }
898          else*/
899          {
900            v2 = i*detail +j+1;
901            v3 = i*detail+detail + j+1;
902          }
903        v4 = i*detail+detail + j;
904        //printf("%i %i %i %i\n", v1, v2, v3, v4);
905        this->addFace(4, 0, v1, v2, v3, v4);
906      }
907}
908
[3426]909/**
910   \brief Creates a Cylinder.
911*/
912void Model::cylinderModel(void)
[3400]913{
[3426]914  unsigned int detail = 20;
915  float size = 1.0;
916
917  // check if devision by zero
918  if (detail <= 3)
919    detail = 3;
920  int count = 0;
921  // defining Points of the Cylinder.
922  for (float phi = 0.0; phi < 2.0*PI; phi += 2.0*PI/(float)detail)
[3400]923    {
[3426]924      this->addVertex(size*cos(phi), size*sin(phi), -size);
925      this->addVertex(size*cos(phi), size*sin(phi), size);
926      count ++;
[3400]927    }
[3426]928  this->addVertex(0, 0, -size);
929  this->addVertex(0, 0, size);
930
931 
932  if (count != detail)
933    cout << "calculation error, count should be " << detail << " but is " << count << endl;
934  vertices->debug();
935
936  // adding Faces
937  for (int i = 0; i < detail-1; i++)
938    {
939      int p1, p2, p3, p4;
940      p1 = 2*i+1;
941      p2 = 2*i+2;
942      if (i <= detail);
943      p3 = 2*i+4;
944      p4 = 2*i+3;
945      cout <<i+1 <<": "<< p1 <<" "<< p2 <<" "<< p3 <<" "<< p4 <<endl;
946      this->addFace(4, 0, p1, p2, p3, p4);
947      this->addFace(3, 0, p4, p1, 2*detail+1);
948      this->addFace(3, 0, p2, p3, 2*detail+2);
949    }
950  addFace(4,0, 2*detail-1, 2*detail, 2, 1);
951  this->addFace(3, 0, 1, 2*detail-1, 2*detail+1);
952  this->addFace(3, 0, 2*detail, 2, 2*detail+2);
953
[3400]954}
Note: See TracBrowser for help on using the repository browser.