Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk/importer: closing file when fail.

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      OBJ_FILE->close();
398      return false;
399    }
400  if (verbose >=2)
401    printf ("Reading from opened file %s\n", fileName);
402  char Buffer[10000];
403  while(!OBJ_FILE->eof())
404    {
405      OBJ_FILE->getline(Buffer, 10000);
406      if (verbose >=4)
407        printf ("Read input line: %s\n",Buffer);
408     
409
410      // case vertice
411      if (!strncmp(Buffer, "v ", 2))
412        {
413          readVertex(Buffer+2);
414        }
415
416      // case face
417      else if (!strncmp(Buffer, "f ", 2))
418        {
419          readFace (Buffer+2);
420        }
421     
422      else if (!strncmp(Buffer, "mtllib ", 7))
423        {
424          readMtlLib (Buffer+7);
425        }
426
427      else if (!strncmp(Buffer, "usemtl ", 7))
428        {
429          readUseMtl (Buffer+7);
430        }
431
432      // case VertexNormal
433      else if (!strncmp(Buffer, "vn ", 3))
434      {
435        readVertexNormal(Buffer+3);
436      }
437
438      // case VertexTextureCoordinate
439      else if (!strncmp(Buffer, "vt ", 3))
440      {
441        readVertexTexture(Buffer+3);
442      }
443      // case group
444      else if (!strncmp(Buffer, "g ", 2))
445        {
446          readGroup (Buffer+2);
447        }
448      else if (!strncmp(Buffer, "s ", 2))
449        {
450          if (verbose >= 2)
451            printf("smoothing groups not supportet yet. line: %s\n", Buffer);
452        }
453    }
454  OBJ_FILE->close();
455  delete []fileName;
456  return true;
457
458}
459
460/**
461   \brief parses a group String
462   \param groupString the new Group to create
463
464   This function initializes a new Group.
465   With it you should be able to import .obj-files with more than one Objects inside.
466*/
467bool Object::readGroup (char* groupString)
468{
469  if (verbose >=3)
470    printf ("Read Group: %s.\n", groupString);
471  if (groupCount != 0 && currentGroup->faceCount>0)
472    {
473      //      finalizeGroup(currentGroup);
474      currentGroup = currentGroup->next = new Group;
475      initGroup(currentGroup);
476    }
477  // setting the group name if not default.
478  if (strcmp(groupString, "default"))
479    {
480      currentGroup->name = new char [strlen(groupString)+1];
481      strcpy(currentGroup->name, groupString);
482    }
483  ++groupCount;
484
485}
486
487/**
488   \brief parses a vertex-String
489   \param vertexString The String that will be parsed.
490
491   If a vertex line is found this function will inject it into the vertex-Array
492*/
493bool Object::readVertex (char* vertexString)
494{
495  float subbuffer1;
496  float subbuffer2;
497  float subbuffer3;
498  sscanf (vertexString, "%f %f %f", &subbuffer1, &subbuffer2, &subbuffer3);
499  if (verbose >= 3)
500    printf ("reading in a vertex: %f %f %f\n", &subbuffer1, &subbuffer2, &subbuffer3);
501  vertices->addEntry(subbuffer1*scaleFactor, subbuffer2*scaleFactor, subbuffer3*scaleFactor);
502  return true;
503}
504
505/**
506   \brief parses a face-string
507   \param faceString The String that will be parsed.
508
509   If a face line is found this function will add it to the glList.
510   The function makes a difference between QUADS and TRIANGLES, and will if changed re-open, set and re-close the gl-processe.
511*/
512bool Object::readFace (char* faceString)
513{
514  if (currentGroup->faceCount >0)
515    currentGroup->currentFace = currentGroup->currentFace->next = new Face;
516  initFace (currentGroup->currentFace);
517
518  FaceElement* tmpElem = currentGroup->currentFace->firstElem = new FaceElement;
519  tmpElem->next = NULL;
520  while(strcmp (faceString, "\0"))
521    {
522      if (currentGroup->currentFace->vertexCount>0)
523          tmpElem = tmpElem->next = new FaceElement;
524      tmpElem->next = NULL;
525
526      char tmpValue [50];
527      int tmpLen;
528      char* vertex = NULL;
529      char* texture = NULL;
530      char* normal = NULL;
531
532      sscanf (faceString, "%s", tmpValue);
533      tmpLen = strlen(tmpValue);
534      vertex = tmpValue;
535
536      if ((texture = strstr (vertex, "/")) != NULL)
537        {
538          texture[0] = '\0';
539          texture ++;
540         
541          if ((normal = strstr (texture, "/")) !=NULL)
542            {
543              normal[0] = '\0';
544              normal ++;
545            }     
546        }
547      if (vertex)
548        tmpElem->vertexNumber = atoi(vertex)-1;
549      else
550        tmpElem->vertexNumber = -1;
551      if (texture)
552        tmpElem->texCoordNumber = atoi(texture)-1;
553      else
554        tmpElem->texCoordNumber = -1;
555      if (normal)
556        tmpElem->normalNumber = atoi(normal)-1;
557      else
558        tmpElem->normalNumber = -1;
559
560      faceString += tmpLen;
561      if (strcmp (faceString, "\0"))
562        faceString++;
563      currentGroup->currentFace->vertexCount++;
564    }
565
566  currentGroup->faceCount += currentGroup->currentFace->vertexCount -2;
567}
568
569/**
570   \brief parses a vertexNormal-String
571   \param normalString The String that will be parsed.
572
573   If a vertexNormal line is found this function will inject it into the vertexNormal-Array
574*/
575bool Object::readVertexNormal (char* normalString)
576{
577  float subbuffer1;
578  float subbuffer2;
579  float subbuffer3;
580  sscanf (normalString, "%f %f %f", &subbuffer1, &subbuffer2, &subbuffer3);
581  if (verbose >=3 )
582    printf("found vertex-Normal %f, %f, %f\n", &subbuffer1,&subbuffer2,&subbuffer3);
583  normals->addEntry(subbuffer1, subbuffer2, subbuffer3);
584  return true;
585}
586
587/**
588   \brief parses a vertexTextureCoordinate-String
589   \param vTextureString The String that will be parsed.
590
591   If a vertexTextureCoordinate line is found,
592   this function will inject it into the vertexTexture-Array
593*/
594bool Object::readVertexTexture (char* vTextureString)
595{
596  float subbuffer1;
597  float subbuffer2;
598  sscanf (vTextureString, "%f %f", &subbuffer1, &subbuffer2);
599  if (verbose >=3 )
600    printf("found vertex-Texture %f, %f\n", &subbuffer1, &subbuffer2);
601  vTexture->addEntry(subbuffer1);
602  vTexture->addEntry(subbuffer2);
603  return true;
604}
605
606/**
607    \brief Function to read in a mtl File.
608    \param mtlFile The .mtl file to read
609
610    This Function parses all Lines of an mtl File.
611    The reason for it not to be in the materials-class is,
612    that a material does not have to be able to read itself in from a File.
613
614*/
615bool Object::readMtlLib (char* mtlFile)
616{
617  mtlFileName = new char [strlen(mtlFile)+1];
618  strcpy(mtlFileName, mtlFile);
619  char* fileName = new char [strlen(objPath) + strlen(mtlFileName)+1];
620  strcpy(fileName, objPath);
621  strcat(fileName, mtlFileName);
622 
623
624  if (verbose >=2)
625    printf ("Opening mtlFile: %s\n", fileName);
626
627  ifstream* MTL_FILE = new ifstream (fileName);
628  if (MTL_FILE->fail())
629    {
630      if (verbose >= 1)
631        printf ("unable to open file: %s\n", fileName);
632      delete []fileName;
633      MTL_FILE->close();
634      return false;
635    }
636  char Buffer[500];
637  Material* tmpMat = material;
638  while(!MTL_FILE->eof())
639    {
640      MTL_FILE->getline(Buffer, 500);
641      if (verbose >= 4)
642        printf("found line in mtlFile: %s\n", Buffer);
643     
644
645      // create new Material
646      if (!strncmp(Buffer, "newmtl ", 7))
647        {
648          tmpMat = tmpMat->addMaterial(Buffer+7);
649          //      printf ("%s, %p\n", tmpMat->getName(), tmpMat);
650        }
651      // setting a illumMode
652      else if (!strncmp(Buffer, "illum ", 6))
653        {
654          tmpMat->setIllum(Buffer+6);
655
656        }
657      // setting Diffuse Color
658      else if (!strncmp(Buffer, "Kd ", 3))
659        {
660          tmpMat->setDiffuse(Buffer+3);
661        }
662      // setting Ambient Color
663      else if (!strncmp(Buffer, "Ka ", 3))
664        {
665          tmpMat->setAmbient(Buffer+3);
666        }
667      // setting Specular Color
668      else if (!strncmp(Buffer, "Ks ", 3))
669        {
670          tmpMat->setSpecular(Buffer+3);
671        }
672      // setting The Specular Shininess
673      else if (!strncmp(Buffer, "Ns ", 3))
674        {
675          tmpMat->setShininess(Buffer+3);
676        }
677      // setting up transparency
678      else if (!strncmp(Buffer, "d ", 2))
679        {
680          tmpMat->setTransparency(Buffer+2);
681        }
682      else if (!strncmp(Buffer, "Tf ", 3))
683        {
684          tmpMat->setTransparency(Buffer+3);
685        }
686     
687      else if (!strncmp(Buffer, "map_Kd ", 7))
688        {
689          tmpMat->setDiffuseMap(Buffer+7);
690        }
691      else if (!strncmp(Buffer, "map_Ka ", 7))
692        {
693          tmpMat->setAmbientMap(Buffer+7);
694        }
695      else if (!strncmp(Buffer, "map_Ks ", 7))
696        {
697          tmpMat->setSpecularMap(Buffer+7);
698        }
699      else if (!strncmp(Buffer, "bump ", 5))
700        {
701          tmpMat->setBump(Buffer+7);
702        }
703     
704
705    }
706  delete []fileName;
707  return true;
708}
709
710/**
711   \brief Function that selects a material, if changed in the obj file.
712   \param matString the Material that will be set.
713*/
714bool Object::readUseMtl (char* matString)
715{
716  if (!mtlFileName)
717    {
718      if (verbose >= 1)
719        printf ("Not using new defined material, because no mtlFile found yet\n");
720      return false;
721    }
722     
723  if (currentGroup->faceCount >0)
724    currentGroup->currentFace = currentGroup->currentFace->next = new Face;
725  initFace (currentGroup->currentFace);
726 
727  currentGroup->currentFace->materialString = new char[strlen(matString)+1];
728  strcpy (currentGroup->currentFace->materialString, matString);
729 
730  if (currentGroup->faceCount == 0)
731    currentGroup->faceCount ++;
732
733}
734
735/**
736   \brief reads and includes the Faces/Materials into the openGL state Machine
737*/
738bool Object::importToGL (void)
739{
740
741  // finalize the Arrays
742  vertices->finalizeArray();
743  vTexture->finalizeArray();
744  if (normals->getCount() == 0) // vertices-Array must be uilt for this
745    buildVertexNormals();
746  normals->finalizeArray();
747
748  currentGroup = firstGroup;
749
750  while (currentGroup != NULL)
751    {
752
753      // creating a glList for the Group
754      if ((currentGroup->listNumber = glGenLists(1)) == 0)
755        {
756          printf ("list could not be created for this Object\n");
757          return false;
758        }
759      glNewList (currentGroup->listNumber, GL_COMPILE);
760
761      // Putting Faces to GL
762      Face* tmpFace = currentGroup->firstFace;
763      while (tmpFace != NULL)
764        {
765          if (tmpFace->vertexCount == 0 && tmpFace->materialString != NULL)
766            {
767              if (currentGroup->faceMode != -1)
768                glEnd();
769              currentGroup->faceMode = 0;
770              if (verbose >= 2)
771                printf ("using material %s for coming Faces.\n", tmpFace->materialString);
772              Material* tmpMat;
773              if ((tmpMat = material->search(tmpFace->materialString)) != NULL)
774                tmpMat->select();
775
776            }
777
778          else if (tmpFace->vertexCount == 3)
779            {
780              if (currentGroup->faceMode != 3)
781                {
782                  if (currentGroup->faceMode != -1)
783                    glEnd();
784                  glBegin(GL_TRIANGLES);
785                }
786             
787              currentGroup->faceMode = 3;
788              if (verbose >=3)
789                printf ("found triag.\n");
790            }
791         
792          else if (tmpFace->vertexCount == 4)
793            {
794              if (currentGroup->faceMode != 4)
795                {
796                  if (currentGroup->faceMode != -1)
797                    glEnd();
798                  glBegin(GL_QUADS);
799                }
800              currentGroup->faceMode = 4;
801              if (verbose >=3 )
802                printf ("found quad.\n");
803            }
804         
805          else if (tmpFace->vertexCount > 4)
806            {
807              if (currentGroup->faceMode != -1)
808                glEnd();
809              glBegin(GL_POLYGON);
810              if (verbose >=3)
811                printf ("Polygon with %i faces found.", tmpFace->vertexCount);
812              currentGroup->faceMode = tmpFace->vertexCount;
813            }
814         
815          FaceElement* tmpElem = tmpFace->firstElem;
816          while (tmpElem != NULL)
817            {
818              //      printf ("%s\n", tmpElem->value);
819              addGLElement(tmpElem);
820              tmpElem = tmpElem->next;
821            }
822          tmpFace = tmpFace->next;
823        }
824      glEnd();
825      glEndList();
826      currentGroup = currentGroup->next;
827    } 
828}
829
830/**
831   \brief Adds a Face-element (one vertex of a face) with all its information.
832   \param elem The FaceElement to add to the OpenGL-environment.
833
834   It does this by searching:
835   1. The Vertex itself
836   2. The VertexNormale
837   3. The VertexTextureCoordinate
838   merging this information, the face will be drawn.
839*/
840bool Object::addGLElement (FaceElement* elem)
841{
842  if (verbose >=3)
843    printf ("importing grafical Element to openGL.\n");
844
845  if (elem->texCoordNumber != -1)
846    glTexCoord2fv(vTexture->getArray() + elem->texCoordNumber * 2);
847  if (elem->normalNumber != -1)
848    glNormal3fv(normals->getArray() + elem->normalNumber * 3);
849  if (elem->vertexNumber != -1)
850    glVertex3fv(vertices->getArray() + elem->vertexNumber * 3);
851
852}
853
854/**
855   \brief A routine that is able to create normals.
856
857   The algorithm does the following:
858   1. It calculates creates Vectors for each normale, and sets them to zero.
859   2. It then Walks through a) all the Groups b) all the Faces c) all the FaceElements
860   3. It searches for a points two neighbours per Face, takes Vecotrs to them calculates FaceNormals and adds it to the Points Normal.
861   4. It goes through all the normale-Points and calculates the VertexNormale and includes it in the normals-Array.
862*/
863bool Object::buildVertexNormals ()
864{
865 
866  if (verbose >=2)
867    printf("Normals are being calculated.\n");
868
869  Vector* normArray = new Vector [vertices->getCount()/3];
870  for (int i=0; i<vertices->getCount()/3;i++)
871    normArray[i] = Vector(.0,.0,.0);
872 
873  int firstTouch;
874  int secondTouch;
875  Vector prevV;
876  Vector nextV;
877  Vector curV;
878
879  Group* tmpGroup = firstGroup;
880  while (tmpGroup)
881    {
882      Face* tmpFace = tmpGroup->firstFace;
883      while (tmpFace)
884        {
885          if (tmpFace->firstElem)
886            {
887              FaceElement* firstElem = tmpFace->firstElem;
888              FaceElement* prevElem;
889              FaceElement* curElem = firstElem;
890              FaceElement* nextElem;
891              FaceElement* lastElem;
892              // 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.
893              while (curElem)
894                {
895                  prevElem = curElem;
896                  curElem = curElem->next;
897                }
898              lastElem = prevElem;
899             
900              curElem = firstElem;
901              for (int j=0; j<tmpFace->vertexCount; j++)
902                {
903                  if (!(nextElem = curElem->next))
904                    nextElem = firstElem;
905                  curElem->normalNumber = curElem->vertexNumber;
906                 
907                  curV = Vector (vertices->getArray()[curElem->vertexNumber*3], vertices->getArray()[curElem->vertexNumber*3+1], vertices->getArray()[curElem->vertexNumber*3+2]);
908                  prevV = Vector (vertices->getArray()[prevElem->vertexNumber*3], vertices->getArray()[prevElem->vertexNumber*3+1], vertices->getArray()[prevElem->vertexNumber*3+2]) - curV;
909                  nextV = Vector (vertices->getArray()[nextElem->vertexNumber*3], vertices->getArray()[nextElem->vertexNumber*3+1], vertices->getArray()[nextElem->vertexNumber*3+2]) - curV;
910                  normArray[curElem->vertexNumber] = normArray[curElem->vertexNumber] + nextV.cross(prevV);
911
912                  prevElem = curElem;
913                  curElem = curElem->next;
914                }
915            }
916          tmpFace = tmpFace->next;
917        }
918      tmpGroup = tmpGroup->next;
919    }
920
921  for (int i=0; i<vertices->getCount()/3;i++)
922    {
923      normArray[i].normalize();
924      if (verbose >=3)
925        printf ("Found Normale number %d: (%f; %f, %f).\n", i, normArray[i].x, normArray[i].y, normArray[i].z);
926
927      normals->addEntry(normArray[i].x, normArray[i].y, normArray[i].z);
928
929    }
930  delete []normArray; 
931 
932}
933
934
935/**
936   \brief Includes a default object
937
938   This will inject a Cube, because this is the most basic object.
939*/
940void Object::BoxObject(void)
941{
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  readVertex ("-0.5 -0.5 -0.5");
949  readVertex ("0.5 -0.5 -0.5");
950
951  readVertexTexture ("0.0 0.0");
952  readVertexTexture ("1.0 0.0");
953  readVertexTexture ("0.0 1.0");
954  readVertexTexture ("1.0 1.0");
955  readVertexTexture ("0.0 2.0");
956  readVertexTexture ("1.0 2.0");
957  readVertexTexture ("0.0 3.0");
958  readVertexTexture ("1.0 3.0");
959  readVertexTexture ("0.0 4.0");
960  readVertexTexture ("1.0 4.0");
961  readVertexTexture ("2.0 0.0");
962  readVertexTexture ("2.0 1.0");
963  readVertexTexture ("-1.0 0.0");
964  readVertexTexture ("-1.0 1.0");
965
966  readVertexNormal ("0.0 0.0 1.0");
967  readVertexNormal ("0.0 0.0 1.0");
968  readVertexNormal ("0.0 0.0 1.0");
969  readVertexNormal ("0.0 0.0 1.0");
970  readVertexNormal ("0.0 1.0 0.0");
971  readVertexNormal ("0.0 1.0 0.0");
972  readVertexNormal ("0.0 1.0 0.0");
973  readVertexNormal ("0.0 1.0 0.0");
974  readVertexNormal ("0.0 0.0 -1.0");
975  readVertexNormal ("0.0 0.0 -1.0");
976  readVertexNormal ("0.0 0.0 -1.0");
977  readVertexNormal ("0.0 0.0 -1.0");
978  readVertexNormal ("0.0 -1.0 0.0");
979  readVertexNormal ("0.0 -1.0 0.0");
980  readVertexNormal ("0.0 -1.0 0.0");
981  readVertexNormal ("0.0 -1.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  readVertexNormal ("-1.0 0.0 0.0");
989  readVertexNormal ("-1.0 0.0 0.0");
990
991  /* normaleLess-testingMode
992  readFace ("1 2 4 3");
993  readFace ("3 4 6 5");
994  readFace ("5 6 8 7");
995  readFace ("7 8 2 1");
996  readFace ("2 8 6 4");
997  readFace ("7 1 3 5");
998  */
999
1000  readFace ("1/1/1 2/2/2 4/4/3 3/3/4");
1001  readFace ("3/3/5 4/4/6 6/6/7 5/5/8");
1002  readFace ("5/5/9 6/6/10 8/8/11 7/7/12");
1003  readFace ("7/7/13 8/8/14 2/10/15 1/9/16");
1004  readFace ("2/2/17 8/11/18 6/12/19 4/4/20");
1005  readFace ("7/13/21 1/1/22 3/3/23 5/14/24");
1006
1007}
Note: See TracBrowser for help on using the repository browser.