Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 3191 was 3190, checked in by bensch, 20 years ago

orxonox/trunk/importer: closing file when fail.

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