Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: new PRINTF() implemented in Material and Array

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