Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/branches/images/importer/object.cc @ 3087

Last change on this file since 3087 was 3084, checked in by bensch, 20 years ago

orxonox/branches: added branche images for the Implementation of differen Image-File formats. libpng, libjpg and so on will be included here.

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