Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/trunk/importer/object.cc @ 3186

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

orxonox/trunk: mainly importer: doxygen Tags updated for real.

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