Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/trunk/src/object.cc @ 3194

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

orxonox/trunk/src: merged importer into src again

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