Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk/importer: this→pointers implemented in classes object, material, array, pathlist

File size: 25.9 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  this->initialize();
28
29  this->BoxObject();
30
31  this->importToGL ();
32
33  this->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  this->initialize();
43
44  this->importFile (fileName);
45
46  this->importToGL ();
47
48  this->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  this->initialize();
59  this->scaleFactor = scaling;
60
61  this->importFile (fileName);
62
63  this->importToGL ();
64
65  this->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 = this->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 (this->objPath)
87    delete []this->objPath;
88  if (this->objFileName)
89    delete []this->objFileName;
90  if (this->mtlFileName)
91    delete []this->mtlFileName;
92
93  if (verbose >=2)
94    printf("Deleting Materials.\n");
95  if (this->material)
96    delete this->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 = this->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 >= this->groupCount)
127    {
128      if (verbose>=1)
129        printf ("You requested object number %i, but this File only contains of %i Objects.\n", groupNumber-1, this->groupCount);
130      return;
131    }
132  if (verbose >=2)
133    printf("drawing the requested 3D-Objects if found.\n"); 
134  Group* walker = this->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, this->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 = this->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, this->objFileName);
178  return;
179}
180
181/**
182   \returns Count of the Objects in this File
183*/
184int Object::getGroupCount (void) const
185{
186  return this->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  this->firstGroup = new Group;
202  this->currentGroup = this->firstGroup;
203  this->groupCount = 0;
204 
205  this->initGroup (this->currentGroup);
206  this->objPath = NULL;
207  this->objFileName = NULL;
208  this->mtlFileName = NULL;
209  this->scaleFactor = 1;
210  this->material = new Material();
211
212  this->vertices = new Array();
213  this->vTexture = new Array();
214  this->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  this->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 (this->vertices)
266    delete this->vertices;
267  if (this->vTexture)
268    delete this->vTexture;
269  if (this->normals)
270    delete this->normals;
271
272  this->cleanupGroup(this->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      this->cleanupFaceElement(face->firstElem);
309      delete face->firstElem;
310    }
311     
312  if (face->next != NULL)
313    {
314      this->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      this->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  this->objPath = new char[name-fileName];
360  strncpy(this->objPath, fileName, name-fileName);
361  this->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 (this->material)
371    this->material->addTexturePath(this->objPath);
372  this->objFileName = new char[strlen(name)+1];
373  strcpy (this->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 (this->objFileName != NULL && !strcmp(this->objFileName, ""))
386    return false;
387  strcpy(fileName, this->objPath);
388  strcat(fileName, this->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      OBJ_FILE->close();
397      delete []fileName;
398      delete OBJ_FILE;
399      return false;
400    }
401  if (verbose >=2)
402    printf ("Reading from opened file %s\n", fileName);
403  char Buffer[10000];
404  while(!OBJ_FILE->eof())
405    {
406      OBJ_FILE->getline(Buffer, 10000);
407      if (verbose >=4)
408        printf ("Read input line: %s\n", Buffer);
409     
410
411      // case vertice
412      if (!strncmp(Buffer, "v ", 2))
413        {
414          this->readVertex(Buffer+2);
415        }
416
417      // case face
418      else if (!strncmp(Buffer, "f ", 2))
419        {
420          this->readFace (Buffer+2);
421        }
422     
423      else if (!strncmp(Buffer, "mtllib ", 7))
424        {
425          this->readMtlLib (Buffer+7);
426        }
427
428      else if (!strncmp(Buffer, "usemtl ", 7))
429        {
430          this->readUseMtl (Buffer+7);
431        }
432
433      // case VertexNormal
434      else if (!strncmp(Buffer, "vn ", 3))
435        {
436          this->readVertexNormal(Buffer+3);
437        }
438     
439      // case VertexTextureCoordinate
440      else if (!strncmp(Buffer, "vt ", 3))
441        {
442          this->readVertexTexture(Buffer+3);
443        }
444      // case group
445      else if (!strncmp(Buffer, "g ", 2))
446        {
447          this->readGroup (Buffer+2);
448        }
449      else if (!strncmp(Buffer, "s ", 2)) //! \todo smoothing groups have to be implemented
450        {
451          if (verbose >= 2)
452            printf("smoothing groups not supportet yet. line: %s\n", Buffer);
453        }
454    }
455  OBJ_FILE->close();
456  delete OBJ_FILE;
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 (this->groupCount != 0 && this->currentGroup->faceCount>0)
474    {
475      //      finalizeGroup(currentGroup);
476      this->currentGroup = this->currentGroup->next = new Group;
477      this->initGroup(this->currentGroup);
478    }
479  // setting the group name if not default.
480  if (strcmp(groupString, "default"))
481    {
482      this->currentGroup->name = new char [strlen(groupString)+1];
483      strcpy(this->currentGroup->name, groupString);
484    }
485  ++this->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  this->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 (this->currentGroup->faceCount >0)
517    this->currentGroup->currentFace = this->currentGroup->currentFace->next = new Face;
518  this->initFace (this->currentGroup->currentFace);
519
520  FaceElement* tmpElem = this->currentGroup->currentFace->firstElem = new FaceElement;
521  tmpElem->next = NULL;
522  while(strcmp (faceString, "\0"))
523    {
524      if (this->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      this->currentGroup->currentFace->vertexCount++;
566    }
567
568  this->currentGroup->faceCount += this->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  this->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  this->vTexture->addEntry(subbuffer1);
604  this->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  this->mtlFileName = new char [strlen(mtlFile)+1];
620  strcpy(this->mtlFileName, mtlFile);
621  char* fileName = new char [strlen(objPath) + strlen(this->mtlFileName)+1];
622  strcpy(fileName, this->objPath);
623  strcat(fileName, this->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      MTL_FILE->close();
635      delete []fileName;
636      delete MTL_FILE;
637      return false;
638    }
639  char Buffer[500];
640  Material* tmpMat = material;
641  while(!MTL_FILE->eof())
642    {
643      MTL_FILE->getline(Buffer, 500);
644      if (verbose >= 4)
645        printf("found line in mtlFile: %s\n", Buffer);
646     
647
648      // create new Material
649      if (!strncmp(Buffer, "newmtl ", 7))
650        {
651          tmpMat = tmpMat->addMaterial(Buffer+7);
652          //      printf ("%s, %p\n", tmpMat->getName(), tmpMat);
653        }
654      // setting a illumMode
655      else if (!strncmp(Buffer, "illum ", 6))
656        {
657          tmpMat->setIllum(Buffer+6);
658
659        }
660      // setting Diffuse Color
661      else if (!strncmp(Buffer, "Kd ", 3))
662        {
663          tmpMat->setDiffuse(Buffer+3);
664        }
665      // setting Ambient Color
666      else if (!strncmp(Buffer, "Ka ", 3))
667        {
668          tmpMat->setAmbient(Buffer+3);
669        }
670      // setting Specular Color
671      else if (!strncmp(Buffer, "Ks ", 3))
672        {
673          tmpMat->setSpecular(Buffer+3);
674        }
675      // setting The Specular Shininess
676      else if (!strncmp(Buffer, "Ns ", 3))
677        {
678          tmpMat->setShininess(Buffer+3);
679        }
680      // setting up transparency
681      else if (!strncmp(Buffer, "d ", 2))
682        {
683          tmpMat->setTransparency(Buffer+2);
684        }
685      else if (!strncmp(Buffer, "Tf ", 3))
686        {
687          tmpMat->setTransparency(Buffer+3);
688        }
689     
690      else if (!strncmp(Buffer, "map_Kd ", 7))
691        {
692          tmpMat->setDiffuseMap(Buffer+7);
693        }
694      else if (!strncmp(Buffer, "map_Ka ", 7))
695        {
696          tmpMat->setAmbientMap(Buffer+7);
697        }
698      else if (!strncmp(Buffer, "map_Ks ", 7))
699        {
700          tmpMat->setSpecularMap(Buffer+7);
701        }
702      else if (!strncmp(Buffer, "bump ", 5))
703        {
704          tmpMat->setBump(Buffer+7);
705        }
706     
707
708    }
709  MTL_FILE->close();
710  delete []fileName;
711  delete MTL_FILE;
712  return true;
713}
714
715/**
716   \brief Function that selects a material, if changed in the obj file.
717   \param matString the Material that will be set.
718*/
719bool Object::readUseMtl (char* matString)
720{
721  if (!this->mtlFileName)
722    {
723      if (verbose >= 1)
724        printf ("Not using new defined material, because no mtlFile found yet\n");
725      return false;
726    }
727     
728  if (this->currentGroup->faceCount >0)
729    this->currentGroup->currentFace = this->currentGroup->currentFace->next = new Face;
730  this->initFace (this->currentGroup->currentFace);
731 
732  this->currentGroup->currentFace->materialString = new char[strlen(matString)+1];
733  strcpy (this->currentGroup->currentFace->materialString, matString);
734 
735  if (this->currentGroup->faceCount == 0)
736    this->currentGroup->faceCount ++;
737
738}
739
740/**
741   \brief reads and includes the Faces/Materials into the openGL state Machine
742*/
743bool Object::importToGL (void)
744{
745
746  // finalize the Arrays
747  this->vertices->finalizeArray();
748  this->vTexture->finalizeArray();
749  if (normals->getCount() == 0) // vertices-Array must be uilt for this
750    this->buildVertexNormals();
751  this->normals->finalizeArray();
752
753  this->currentGroup = this->firstGroup;
754
755  while (this->currentGroup != NULL)
756    {
757
758      // creating a glList for the Group
759      if ((this->currentGroup->listNumber = glGenLists(1)) == 0)
760        {
761          printf ("list could not be created for this Object\n");
762          return false;
763        }
764      glNewList (this->currentGroup->listNumber, GL_COMPILE);
765
766      // Putting Faces to GL
767      Face* tmpFace = this->currentGroup->firstFace;
768      while (tmpFace != NULL)
769        {
770          if (tmpFace->vertexCount == 0 && tmpFace->materialString != NULL)
771            {
772              if (this->currentGroup->faceMode != -1)
773                glEnd();
774              this->currentGroup->faceMode = 0;
775              if (verbose >= 2)
776                printf ("using material %s for coming Faces.\n", tmpFace->materialString);
777              Material* tmpMat;
778              if ((tmpMat = material->search(tmpFace->materialString)) != NULL)
779                tmpMat->select();
780
781            }
782
783          else if (tmpFace->vertexCount == 3)
784            {
785              if (this->currentGroup->faceMode != 3)
786                {
787                  if (this->currentGroup->faceMode != -1)
788                    glEnd();
789                  glBegin(GL_TRIANGLES);
790                }
791             
792              this->currentGroup->faceMode = 3;
793              if (verbose >=3)
794                printf ("found triag.\n");
795            }
796         
797          else if (tmpFace->vertexCount == 4)
798            {
799              if (this->currentGroup->faceMode != 4)
800                {
801                  if (this->currentGroup->faceMode != -1)
802                    glEnd();
803                  glBegin(GL_QUADS);
804                }
805              this->currentGroup->faceMode = 4;
806              if (verbose >=3 )
807                printf ("found quad.\n");
808            }
809         
810          else if (tmpFace->vertexCount > 4)
811            {
812              if (this->currentGroup->faceMode != -1)
813                glEnd();
814              glBegin(GL_POLYGON);
815              if (verbose >=3)
816                printf ("Polygon with %i faces found.", tmpFace->vertexCount);
817              this->currentGroup->faceMode = tmpFace->vertexCount;
818            }
819         
820          FaceElement* tmpElem = tmpFace->firstElem;
821          while (tmpElem != NULL)
822            {
823              //      printf ("%s\n", tmpElem->value);
824              this->addGLElement(tmpElem);
825              tmpElem = tmpElem->next;
826            }
827          tmpFace = tmpFace->next;
828        }
829      glEnd();
830      glEndList();
831
832      this->currentGroup = this->currentGroup->next;
833    } 
834}
835
836/**
837   \brief Adds a Face-element (one vertex of a face) with all its information.
838   \param elem The FaceElement to add to the OpenGL-environment.
839
840   It does this by searching:
841   1. The Vertex itself
842   2. The VertexNormale
843   3. The VertexTextureCoordinate
844   merging this information, the face will be drawn.
845*/
846bool Object::addGLElement (FaceElement* elem)
847{
848  if (verbose >=3)
849    printf ("importing grafical Element to openGL.\n");
850
851  if (elem->texCoordNumber != -1)
852    glTexCoord2fv(this->vTexture->getArray() + elem->texCoordNumber * 2);
853  if (elem->normalNumber != -1)
854    glNormal3fv(this->normals->getArray() + elem->normalNumber * 3);
855  if (elem->vertexNumber != -1)
856    glVertex3fv(this->vertices->getArray() + elem->vertexNumber * 3);
857
858}
859
860/**
861   \brief A routine that is able to create normals.
862
863   The algorithm does the following:
864   1. It calculates creates Vectors for each normale, and sets them to zero.
865   2. It then Walks through a) all the Groups b) all the Faces c) all the FaceElements
866   3. It searches for a points two neighbours per Face, takes Vecotrs to them calculates FaceNormals and adds it to the Points Normal.
867   4. It goes through all the normale-Points and calculates the VertexNormale and includes it in the normals-Array.
868*/
869bool Object::buildVertexNormals ()
870{
871 
872  if (verbose >=2)
873    printf("Normals are being calculated.\n");
874
875  Vector* normArray = new Vector [vertices->getCount()/3];
876  for (int i=0; i<vertices->getCount()/3;i++)
877    normArray[i] = Vector(.0,.0,.0);
878 
879  int firstTouch;
880  int secondTouch;
881  Vector prevV;
882  Vector nextV;
883  Vector curV;
884
885  Group* tmpGroup = firstGroup;
886  while (tmpGroup)
887    {
888      Face* tmpFace = tmpGroup->firstFace;
889      while (tmpFace)
890        {
891          if (tmpFace->firstElem)
892            {
893              FaceElement* firstElem = tmpFace->firstElem;
894              FaceElement* prevElem;
895              FaceElement* curElem = firstElem;
896              FaceElement* nextElem;
897              FaceElement* lastElem;
898              // 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.
899              while (curElem)
900                {
901                  prevElem = curElem;
902                  curElem = curElem->next;
903                }
904              lastElem = prevElem;
905             
906              curElem = firstElem;
907              for (int j=0; j<tmpFace->vertexCount; j++)
908                {
909                  if (!(nextElem = curElem->next))
910                    nextElem = firstElem;
911                  curElem->normalNumber = curElem->vertexNumber;
912                 
913                  curV = Vector (vertices->getArray()[curElem->vertexNumber*3], vertices->getArray()[curElem->vertexNumber*3+1], vertices->getArray()[curElem->vertexNumber*3+2]);
914                  prevV = Vector (vertices->getArray()[prevElem->vertexNumber*3], vertices->getArray()[prevElem->vertexNumber*3+1], vertices->getArray()[prevElem->vertexNumber*3+2]) - curV;
915                  nextV = Vector (vertices->getArray()[nextElem->vertexNumber*3], vertices->getArray()[nextElem->vertexNumber*3+1], vertices->getArray()[nextElem->vertexNumber*3+2]) - curV;
916                  normArray[curElem->vertexNumber] = normArray[curElem->vertexNumber] + nextV.cross(prevV);
917
918                  prevElem = curElem;
919                  curElem = curElem->next;
920                }
921            }
922          tmpFace = tmpFace->next;
923        }
924      tmpGroup = tmpGroup->next;
925    }
926
927  for (int i=0; i<vertices->getCount()/3;i++)
928    {
929      normArray[i].normalize();
930      if (verbose >=3)
931        printf ("Found Normale number %d: (%f; %f, %f).\n", i, normArray[i].x, normArray[i].y, normArray[i].z);
932
933      this->normals->addEntry(normArray[i].x, normArray[i].y, normArray[i].z);
934
935    }
936  delete []normArray; 
937 
938}
939
940
941/**
942   \brief Includes a default object
943
944   This will inject a Cube, because this is the most basic object.
945*/
946void Object::BoxObject(void)
947{
948  this->readVertex ("-0.5 -0.5 0.5");
949  this->readVertex ("0.5 -0.5 0.5");
950  this->readVertex ("-0.5 0.5 0.5");
951  this->readVertex ("0.5 0.5 0.5");
952  this->readVertex ("-0.5 0.5 -0.5");
953  this->readVertex ("0.5 0.5 -0.5");
954  this->readVertex ("-0.5 -0.5 -0.5");
955  this->readVertex ("0.5 -0.5 -0.5");
956
957  this->readVertexTexture ("0.0 0.0");
958  this->readVertexTexture ("1.0 0.0");
959  this->readVertexTexture ("0.0 1.0");
960  this->readVertexTexture ("1.0 1.0");
961  this->readVertexTexture ("0.0 2.0");
962  this->readVertexTexture ("1.0 2.0");
963  this->readVertexTexture ("0.0 3.0");
964  this->readVertexTexture ("1.0 3.0");
965  this->readVertexTexture ("0.0 4.0");
966  this->readVertexTexture ("1.0 4.0");
967  this->readVertexTexture ("2.0 0.0");
968  this->readVertexTexture ("2.0 1.0");
969  this->readVertexTexture ("-1.0 0.0");
970  this->readVertexTexture ("-1.0 1.0");
971
972  this->readVertexNormal ("0.0 0.0 1.0");
973  this->readVertexNormal ("0.0 0.0 1.0");
974  this->readVertexNormal ("0.0 0.0 1.0");
975  this->readVertexNormal ("0.0 0.0 1.0");
976  this->readVertexNormal ("0.0 1.0 0.0");
977  this->readVertexNormal ("0.0 1.0 0.0");
978  this->readVertexNormal ("0.0 1.0 0.0");
979  this->readVertexNormal ("0.0 1.0 0.0");
980  this->readVertexNormal ("0.0 0.0 -1.0");
981  this->readVertexNormal ("0.0 0.0 -1.0");
982  this->readVertexNormal ("0.0 0.0 -1.0");
983  this->readVertexNormal ("0.0 0.0 -1.0");
984  this->readVertexNormal ("0.0 -1.0 0.0");
985  this->readVertexNormal ("0.0 -1.0 0.0");
986  this->readVertexNormal ("0.0 -1.0 0.0");
987  this->readVertexNormal ("0.0 -1.0 0.0");
988  this->readVertexNormal ("1.0 0.0 0.0");
989  this->readVertexNormal ("1.0 0.0 0.0");
990  this->readVertexNormal ("1.0 0.0 0.0");
991  this->readVertexNormal ("1.0 0.0 0.0");
992  this->readVertexNormal ("-1.0 0.0 0.0");
993  this->readVertexNormal ("-1.0 0.0 0.0");
994  this->readVertexNormal ("-1.0 0.0 0.0");
995  this->readVertexNormal ("-1.0 0.0 0.0");
996
997  /* normaleLess-testingMode
998  this->readFace ("1 2 4 3");
999  this->readFace ("3 4 6 5");
1000  this->readFace ("5 6 8 7");
1001  this->readFace ("7 8 2 1");
1002  this->readFace ("2 8 6 4");
1003  this->readFace ("7 1 3 5");
1004  */
1005
1006  this->readFace ("1/1/1 2/2/2 4/4/3 3/3/4");
1007  this->readFace ("3/3/5 4/4/6 6/6/7 5/5/8");
1008  this->readFace ("5/5/9 6/6/10 8/8/11 7/7/12");
1009  this->readFace ("7/7/13 8/8/14 2/10/15 1/9/16");
1010  this->readFace ("2/2/17 8/11/18 6/12/19 4/4/20");
1011  this->readFace ("7/13/21 1/1/22 3/3/23 5/14/24");
1012
1013}
Note: See TracBrowser for help on using the repository browser.