Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: merged branches/images back into the trunk.
merged with command: svn merge bensches/images/ trunk/ -r 3084:HEAD

Conflicts in configure/.ac

resolved in favor of branches/images (newer)

Mayor differences:

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