Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/trunk/src/importer/object.cc @ 3202

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

orxonox/trunk: moved importer into the Trunk, now no merging is needed anymore.

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