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
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"
[3196]17int verbose = 1; //! \todo should be GLOBAL
[3140]18using namespace std;
[2776]19
[2842]20/**
[3186]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??
[2842]24*/
[2748]25Object::Object ()
26{
[2765]27
[3195]28  this->initialize();
[2847]29
[3195]30  this->BoxObject();
[2765]31
[3195]32  this->importToGL ();
[3064]33
[3195]34  this->cleanup();
[2767]35}
36
[2842]37/**
[3186]38   \brief Crates a 3D-Object and loads in a File.
[2842]39   \param fileName file to parse and load (must be a .obj file)
40*/
[2773]41Object::Object(char* fileName)
42{
[3195]43  this->initialize();
[2773]44
[3195]45  this->importFile (fileName);
[2773]46
[3195]47  this->importToGL ();
[3064]48
[3195]49  this->cleanup();
[2773]50}
51
[2842]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*/
[2833]57Object::Object(char* fileName, float scaling)
[2767]58{
[3195]59  this->initialize();
60  this->scaleFactor = scaling;
[2833]61
[3195]62  this->importFile (fileName);
[2833]63
[3195]64  this->importToGL ();
[3064]65
[3195]66  this->cleanup();
[2767]67}
68
[2847]69/**
[3186]70   \brief deletes an Object.
71
72   Looks if any from object allocated space is still in use, and if so deleted it.
[2847]73*/
74Object::~Object()
75{
76  if (verbose >= 2)
[3066]77    printf ("Deleting display Lists.\n");
[3195]78  Group* walker = this->firstGroup;
[2850]79  while (walker != NULL)
80    {
81      glDeleteLists (walker->listNumber, 1);
[3066]82      Group* delWalker = walker;
[3063]83      walker = walker->next;
[3066]84      delete delWalker;
[3140]85    }
86
[3195]87  if (this->objPath)
88    delete []this->objPath;
89  if (this->objFileName)
90    delete []this->objFileName;
91  if (this->mtlFileName)
92    delete []this->mtlFileName;
[3140]93
94  if (verbose >=2)
95    printf("Deleting Materials.\n");
[3195]96  if (this->material)
97    delete this->material;
[2847]98}
99
[2833]100
[2842]101/**
[2851]102   \brief Draws the Objects of all Groups.
103   It does this by just calling the Lists that must have been created earlier.
[2842]104*/
[3063]105void Object::draw (void) const
[2748]106{
[2851]107  if (verbose >=2)
108    printf("drawing the 3D-Objects\n"); 
[3195]109  Group* walker = this->firstGroup;
[2850]110  while (walker != NULL)
111    {
[2851]112      if (verbose >= 3)
113        printf ("Drawing object %s\n", walker->name);
[2850]114      glCallList (walker->listNumber);
[3063]115      walker = walker->next;
[2850]116    }
[2748]117}
[2754]118
[2842]119/**
[2851]120   \brief Draws the Object number groupNumber
[3186]121   \param groupNumber The number of the group that will be displayed.
122
[2851]123   It does this by just calling the List that must have been created earlier.
124*/
[3063]125void Object::draw (int groupNumber) const 
[2851]126{
[3195]127  if (groupNumber >= this->groupCount)
[2852]128    {
[3063]129      if (verbose>=1)
[3195]130        printf ("You requested object number %i, but this File only contains of %i Objects.\n", groupNumber-1, this->groupCount);
[2852]131      return;
132    }
[2851]133  if (verbose >=2)
134    printf("drawing the requested 3D-Objects if found.\n"); 
[3195]135  Group* walker = this->firstGroup;
[2851]136  int counter = 0;
137  while (walker != NULL)
138    {
139      if (counter == groupNumber)
140        {
141          if (verbose >= 2)
[3063]142            printf ("Drawing object number %i named %s\n", counter, walker->name);
[2851]143          glCallList (walker->listNumber);
144          return;
145        }
146      ++counter;
[3063]147      walker = walker->next;
[2851]148    }
[3063]149  if (verbose >= 1)
[3195]150    printf("Object number %i in %s not Found.\n", groupNumber, this->objFileName);
[2851]151  return;
152
153}
[2852]154
155/**
[3063]156   \brief Draws the Object with a specific groupName
[3186]157   \param groupName The name of the group that will be displayed.
158
[2852]159   It does this by just calling the List that must have been created earlier.
160*/
[3063]161void Object::draw (char* groupName) const
[2851]162{
163  if (verbose >=2)
164    printf("drawing the requested 3D-Objects if found.\n"); 
[3195]165  Group* walker = this->firstGroup;
[2851]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        }
[3063]175      walker = walker->next;
[2851]176    }
177  if (verbose >= 2)
[3195]178    printf("Object Named %s in %s not Found.\n", groupName, this->objFileName);
[2851]179  return;
180}
181
[2852]182/**
183   \returns Count of the Objects in this File
184*/
[3063]185int Object::getGroupCount (void) const
[2852]186{
[3195]187  return this->groupCount;
[2852]188}
[2851]189
190/**
[3186]191    \brief initializes the Object.
192
193    This Function initializes all the needed arrays, Lists and clientStates.
194    It also defines default values.
[3066]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;
[3195]202  this->firstGroup = new Group;
203  this->currentGroup = this->firstGroup;
204  this->groupCount = 0;
[3066]205 
[3195]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();
[3066]212
[3195]213  this->vertices = new Array();
214  this->vTexture = new Array();
215  this->normals = new Array();
[3066]216
217  return true;
218}
219
220/**
[2850]221   \brief initializes a new Group object
[3186]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   
[2850]225*/
226bool Object::initGroup(Group* group)
227{
228  if (verbose >= 2)
229    printf("Adding new Group\n");
[2863]230  group->name = "";
[2850]231  group->faceMode = -1;
[2967]232  group->faceCount = 0; 
[3063]233  group->next = NULL;
[2850]234
[3063]235  group->firstFace = new Face;
[3195]236  this->initFace (group->firstFace);
[3063]237  group->currentFace = group->firstFace;
[2850]238}
239
240/**
[3066]241   \brief initializes a new Face. (sets default Values)
[3186]242   \param face The face to initialize
[2850]243*/
[3066]244bool Object::initFace (Face* face)
[2850]245{
[3066]246  face->vertexCount = 0;
[2967]247
[3066]248  face->firstElem = NULL;
249 
250  face->materialString = NULL;
251 
252  face->next = NULL;
253
254  return true;
[2850]255}
[2863]256
[2850]257/**
[3066]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{
[3068]263  if (verbose >=2)
264    printf("cleaning up the 3D-Object to save Memory.\n");
[3066]265
[3195]266  if (this->vertices)
267    delete this->vertices;
268  if (this->vTexture)
269    delete this->vTexture;
270  if (this->normals)
271    delete this->normals;
[3066]272
[3195]273  this->cleanupGroup(this->firstGroup);
[3066]274  return true; 
275}
276
277/**
[3068]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/**
[3186]297   \brief Cleans up all Faces starting from face until NULL is reached.
298   \param face the first face to clean.
[3068]299*/
300bool Object::cleanupFace (Face* face)
301{
302  if (verbose>=4)
303    printf ("Cleaning up Face\n");
304
305  if (face->materialString != NULL)
[3080]306      delete []face->materialString;
[3068]307  if (face->firstElem != NULL)
308    {
[3195]309      this->cleanupFaceElement(face->firstElem);
[3068]310      delete face->firstElem;
311    }
312     
313  if (face->next != NULL)
314    {
[3195]315      this->cleanupFace (face->next);
[3068]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    {
[3195]330      this->cleanupFaceElement (faceElem->next);
[3072]331      delete faceElem->next;
[3068]332    }
333}
334
335/**
[3066]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)
[3140]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    }
[3195]360  this->objPath = new char[name-fileName];
361  strncpy(this->objPath, fileName, name-fileName);
362  this->objPath[name-fileName] = '\0';
[3140]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 
[3195]371  if (this->material)
372    this->material->addTexturePath(this->objPath);
373  this->objFileName = new char[strlen(name)+1];
374  strcpy (this->objFileName, name);
[3140]375  this->readFromObjFile ();
[3066]376  return true;
377}
378
379/**
[2842]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*/
[3140]383bool Object::readFromObjFile (void)
[2754]384{
[3140]385  char* fileName = new char [strlen(objPath)+strlen(objFileName)+1];
[3195]386  if (this->objFileName != NULL && !strcmp(this->objFileName, ""))
[3140]387    return false;
[3195]388  strcpy(fileName, this->objPath);
389  strcat(fileName, this->objFileName);
[3140]390
391  ifstream* OBJ_FILE = new ifstream(fileName);
392  if (OBJ_FILE->fail())
[2775]393    {
[2804]394      if (verbose >=1)
[2821]395        printf ("unable to open .OBJ file: %s\n Loading Box Object instead.\n", fileName);
396      BoxObject();
[3195]397      OBJ_FILE->close();
[3140]398      delete []fileName;
[3195]399      delete OBJ_FILE;
[2775]400      return false;
401    }
[3140]402  if (verbose >=2)
403    printf ("Reading from opened file %s\n", fileName);
[2931]404  char Buffer[10000];
[2765]405  while(!OBJ_FILE->eof())
406    {
[2931]407      OBJ_FILE->getline(Buffer, 10000);
[2804]408      if (verbose >=4)
[3195]409        printf ("Read input line: %s\n", Buffer);
[2765]410     
411
412      // case vertice
413      if (!strncmp(Buffer, "v ", 2))
414        {
[3195]415          this->readVertex(Buffer+2);
[2765]416        }
417
418      // case face
419      else if (!strncmp(Buffer, "f ", 2))
420        {
[3195]421          this->readFace (Buffer+2);
[2765]422        }
[2776]423     
[3063]424      else if (!strncmp(Buffer, "mtllib ", 7))
[2776]425        {
[3195]426          this->readMtlLib (Buffer+7);
[2776]427        }
[2765]428
[3063]429      else if (!strncmp(Buffer, "usemtl ", 7))
[2769]430        {
[3195]431          this->readUseMtl (Buffer+7);
[2769]432        }
[2794]433
434      // case VertexNormal
[3063]435      else if (!strncmp(Buffer, "vn ", 3))
[3195]436        {
437          this->readVertexNormal(Buffer+3);
438        }
439     
[2848]440      // case VertexTextureCoordinate
[3063]441      else if (!strncmp(Buffer, "vt ", 3))
[3195]442        {
443          this->readVertexTexture(Buffer+3);
444        }
[2848]445      // case group
[3063]446      else if (!strncmp(Buffer, "g ", 2))
[2848]447        {
[3195]448          this->readGroup (Buffer+2);
[2848]449        }
[3195]450      else if (!strncmp(Buffer, "s ", 2)) //! \todo smoothing groups have to be implemented
[2995]451        {
[3069]452          if (verbose >= 2)
[3063]453            printf("smoothing groups not supportet yet. line: %s\n", Buffer);
[2995]454        }
[2765]455    }
[2846]456  OBJ_FILE->close();
[3195]457  delete OBJ_FILE;
[3140]458  delete []fileName;
[2863]459  return true;
[2765]460
[2767]461}
[2765]462
[2842]463/**
[3066]464   \brief parses a group String
[3186]465   \param groupString the new Group to create
466
[3066]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{
[3140]472  if (verbose >=3)
473    printf ("Read Group: %s.\n", groupString);
[3195]474  if (this->groupCount != 0 && this->currentGroup->faceCount>0)
[3066]475    {
476      //      finalizeGroup(currentGroup);
[3195]477      this->currentGroup = this->currentGroup->next = new Group;
478      this->initGroup(this->currentGroup);
[3066]479    }
[3140]480  // setting the group name if not default.
481  if (strcmp(groupString, "default"))
482    {
[3195]483      this->currentGroup->name = new char [strlen(groupString)+1];
484      strcpy(this->currentGroup->name, groupString);
[3140]485    }
[3195]486  ++this->groupCount;
[3066]487
488}
489
490/**
[2842]491   \brief parses a vertex-String
[3186]492   \param vertexString The String that will be parsed.
493
[2842]494   If a vertex line is found this function will inject it into the vertex-Array
495*/
[2767]496bool Object::readVertex (char* vertexString)
497{
[3071]498  float subbuffer1;
499  float subbuffer2;
500  float subbuffer3;
501  sscanf (vertexString, "%f %f %f", &subbuffer1, &subbuffer2, &subbuffer3);
[2804]502  if (verbose >= 3)
[3071]503    printf ("reading in a vertex: %f %f %f\n", &subbuffer1, &subbuffer2, &subbuffer3);
[3195]504  this->vertices->addEntry(subbuffer1*scaleFactor, subbuffer2*scaleFactor, subbuffer3*scaleFactor);
[2767]505  return true;
506}
507
[2842]508/**
509   \brief parses a face-string
[3186]510   \param faceString The String that will be parsed.
511
[2842]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*/
[2767]515bool Object::readFace (char* faceString)
516{
[3195]517  if (this->currentGroup->faceCount >0)
518    this->currentGroup->currentFace = this->currentGroup->currentFace->next = new Face;
519  this->initFace (this->currentGroup->currentFace);
[2767]520
[3195]521  FaceElement* tmpElem = this->currentGroup->currentFace->firstElem = new FaceElement;
[3068]522  tmpElem->next = NULL;
[2934]523  while(strcmp (faceString, "\0"))
[2767]524    {
[3195]525      if (this->currentGroup->currentFace->vertexCount>0)
[2934]526          tmpElem = tmpElem->next = new FaceElement;
527      tmpElem->next = NULL;
528
[3064]529      char tmpValue [50];
[3072]530      int tmpLen;
531      char* vertex = NULL;
532      char* texture = NULL;
533      char* normal = NULL;
534
[3063]535      sscanf (faceString, "%s", tmpValue);
[3072]536      tmpLen = strlen(tmpValue);
537      vertex = tmpValue;
[2934]538
[3072]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)
[3073]551        tmpElem->vertexNumber = atoi(vertex)-1;
[3072]552      else
[3073]553        tmpElem->vertexNumber = -1;
[3072]554      if (texture)
[3073]555        tmpElem->texCoordNumber = atoi(texture)-1;
[3072]556      else
[3073]557        tmpElem->texCoordNumber = -1;
[3072]558      if (normal)
[3073]559        tmpElem->normalNumber = atoi(normal)-1;
[3072]560      else
[3073]561        tmpElem->normalNumber = -1;
[3072]562
563      faceString += tmpLen;
[2934]564      if (strcmp (faceString, "\0"))
565        faceString++;
[3195]566      this->currentGroup->currentFace->vertexCount++;
[2934]567    }
568
[3195]569  this->currentGroup->faceCount += this->currentGroup->currentFace->vertexCount -2;
[2754]570}
[2768]571
[2842]572/**
573   \brief parses a vertexNormal-String
[3186]574   \param normalString The String that will be parsed.
575
[2842]576   If a vertexNormal line is found this function will inject it into the vertexNormal-Array
577*/
[2794]578bool Object::readVertexNormal (char* normalString)
579{
[3071]580  float subbuffer1;
581  float subbuffer2;
582  float subbuffer3;
583  sscanf (normalString, "%f %f %f", &subbuffer1, &subbuffer2, &subbuffer3);
[2804]584  if (verbose >=3 )
[3071]585    printf("found vertex-Normal %f, %f, %f\n", &subbuffer1,&subbuffer2,&subbuffer3);
[3195]586  this->normals->addEntry(subbuffer1, subbuffer2, subbuffer3);
[2794]587  return true;
588}
589
[2842]590/**
591   \brief parses a vertexTextureCoordinate-String
592   \param vTextureString The String that will be parsed.
[3186]593
594   If a vertexTextureCoordinate line is found,
595   this function will inject it into the vertexTexture-Array
[2842]596*/
[2820]597bool Object::readVertexTexture (char* vTextureString)
598{
[3071]599  float subbuffer1;
600  float subbuffer2;
601  sscanf (vTextureString, "%f %f", &subbuffer1, &subbuffer2);
[2820]602  if (verbose >=3 )
[3071]603    printf("found vertex-Texture %f, %f\n", &subbuffer1, &subbuffer2);
[3195]604  this->vTexture->addEntry(subbuffer1);
605  this->vTexture->addEntry(subbuffer2);
[2820]606  return true;
607}
608
[3066]609/**
610    \brief Function to read in a mtl File.
611    \param mtlFile The .mtl file to read
[3186]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
[2850]617*/
[3066]618bool Object::readMtlLib (char* mtlFile)
[2850]619{
[3195]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);
[3140]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())
[2850]632    {
[3066]633      if (verbose >= 1)
[3140]634        printf ("unable to open file: %s\n", fileName);
[3195]635      MTL_FILE->close();
[3140]636      delete []fileName;
[3195]637      delete MTL_FILE;
[3066]638      return false;
[2850]639    }
[3066]640  char Buffer[500];
641  Material* tmpMat = material;
642  while(!MTL_FILE->eof())
[2850]643    {
[3066]644      MTL_FILE->getline(Buffer, 500);
645      if (verbose >= 4)
646        printf("found line in mtlFile: %s\n", Buffer);
647     
[2863]648
[3066]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);
[2863]659
[3066]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        }
[3070]686      else if (!strncmp(Buffer, "Tf ", 3))
[3066]687        {
688          tmpMat->setTransparency(Buffer+3);
689        }
[3070]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     
[3066]708
709    }
[3195]710  MTL_FILE->close();
[3140]711  delete []fileName;
[3195]712  delete MTL_FILE;
[3066]713  return true;
[2850]714}
715
[3066]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)
[3063]721{
[3195]722  if (!this->mtlFileName)
[3066]723    {
724      if (verbose >= 1)
725        printf ("Not using new defined material, because no mtlFile found yet\n");
726      return false;
727    }
728     
[3195]729  if (this->currentGroup->faceCount >0)
730    this->currentGroup->currentFace = this->currentGroup->currentFace->next = new Face;
731  this->initFace (this->currentGroup->currentFace);
[3063]732 
[3195]733  this->currentGroup->currentFace->materialString = new char[strlen(matString)+1];
734  strcpy (this->currentGroup->currentFace->materialString, matString);
[3063]735 
[3195]736  if (this->currentGroup->faceCount == 0)
737    this->currentGroup->faceCount ++;
[3063]738
739}
740
[3066]741/**
742   \brief reads and includes the Faces/Materials into the openGL state Machine
743*/
[3063]744bool Object::importToGL (void)
745{
746
747  // finalize the Arrays
[3195]748  this->vertices->finalizeArray();
749  this->vTexture->finalizeArray();
[3075]750  if (normals->getCount() == 0) // vertices-Array must be uilt for this
[3195]751    this->buildVertexNormals();
752  this->normals->finalizeArray();
[3063]753
[3195]754  this->currentGroup = this->firstGroup;
[3063]755
[3195]756  while (this->currentGroup != NULL)
[3063]757    {
758
759      // creating a glList for the Group
[3195]760      if ((this->currentGroup->listNumber = glGenLists(1)) == 0)
[3063]761        {
762          printf ("list could not be created for this Object\n");
763          return false;
764        }
[3195]765      glNewList (this->currentGroup->listNumber, GL_COMPILE);
[3063]766
767      // Putting Faces to GL
[3195]768      Face* tmpFace = this->currentGroup->firstFace;
[3063]769      while (tmpFace != NULL)
770        {
[3065]771          if (tmpFace->vertexCount == 0 && tmpFace->materialString != NULL)
[3063]772            {
[3195]773              if (this->currentGroup->faceMode != -1)
[3065]774                glEnd();
[3195]775              this->currentGroup->faceMode = 0;
[3065]776              if (verbose >= 2)
777                printf ("using material %s for coming Faces.\n", tmpFace->materialString);
[3069]778              Material* tmpMat;
779              if ((tmpMat = material->search(tmpFace->materialString)) != NULL)
780                tmpMat->select();
[3065]781
782            }
783
784          else if (tmpFace->vertexCount == 3)
785            {
[3195]786              if (this->currentGroup->faceMode != 3)
[3063]787                {
[3195]788                  if (this->currentGroup->faceMode != -1)
[3063]789                    glEnd();
790                  glBegin(GL_TRIANGLES);
791                }
792             
[3195]793              this->currentGroup->faceMode = 3;
[3063]794              if (verbose >=3)
795                printf ("found triag.\n");
796            }
797         
798          else if (tmpFace->vertexCount == 4)
799            {
[3195]800              if (this->currentGroup->faceMode != 4)
[3063]801                {
[3195]802                  if (this->currentGroup->faceMode != -1)
[3063]803                    glEnd();
804                  glBegin(GL_QUADS);
805                }
[3195]806              this->currentGroup->faceMode = 4;
[3063]807              if (verbose >=3 )
808                printf ("found quad.\n");
809            }
810         
811          else if (tmpFace->vertexCount > 4)
812            {
[3195]813              if (this->currentGroup->faceMode != -1)
[3063]814                glEnd();
815              glBegin(GL_POLYGON);
816              if (verbose >=3)
817                printf ("Polygon with %i faces found.", tmpFace->vertexCount);
[3195]818              this->currentGroup->faceMode = tmpFace->vertexCount;
[3063]819            }
820         
821          FaceElement* tmpElem = tmpFace->firstElem;
822          while (tmpElem != NULL)
823            {
824              //      printf ("%s\n", tmpElem->value);
[3195]825              this->addGLElement(tmpElem);
[3063]826              tmpElem = tmpElem->next;
827            }
828          tmpFace = tmpFace->next;
829        }
830      glEnd();
831      glEndList();
[3195]832
833      this->currentGroup = this->currentGroup->next;
[3063]834    } 
835}
836
[3066]837/**
838   \brief Adds a Face-element (one vertex of a face) with all its information.
[3186]839   \param elem The FaceElement to add to the OpenGL-environment.
840
[3066]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.
[2842]846*/
[3072]847bool Object::addGLElement (FaceElement* elem)
[2776]848{
[3066]849  if (verbose >=3)
[3072]850    printf ("importing grafical Element to openGL.\n");
[3066]851
[3073]852  if (elem->texCoordNumber != -1)
[3195]853    glTexCoord2fv(this->vTexture->getArray() + elem->texCoordNumber * 2);
[3073]854  if (elem->normalNumber != -1)
[3195]855    glNormal3fv(this->normals->getArray() + elem->normalNumber * 3);
[3073]856  if (elem->vertexNumber != -1)
[3195]857    glVertex3fv(this->vertices->getArray() + elem->vertexNumber * 3);
[2769]858
[2776]859}
860
[3079]861/**
862   \brief A routine that is able to create normals.
[3186]863
[3079]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*/
[3075]870bool Object::buildVertexNormals ()
871{
[3081]872 
[3079]873  if (verbose >=2)
874    printf("Normals are being calculated.\n");
[3075]875
876  Vector* normArray = new Vector [vertices->getCount()/3];
[3079]877  for (int i=0; i<vertices->getCount()/3;i++)
[3075]878    normArray[i] = Vector(.0,.0,.0);
[3081]879 
[3075]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;
[3082]895              FaceElement* prevElem;
896              FaceElement* curElem = firstElem;
897              FaceElement* nextElem;
[3081]898              FaceElement* lastElem;
[3082]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.
[3081]900              while (curElem)
901                {
902                  prevElem = curElem;
903                  curElem = curElem->next;
904                }
905              lastElem = prevElem;
[3075]906             
[3081]907              curElem = firstElem;
908              for (int j=0; j<tmpFace->vertexCount; j++)
[3075]909                {
[3082]910                  if (!(nextElem = curElem->next))
911                    nextElem = firstElem;
[3075]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;
[3082]916                  nextV = Vector (vertices->getArray()[nextElem->vertexNumber*3], vertices->getArray()[nextElem->vertexNumber*3+1], vertices->getArray()[nextElem->vertexNumber*3+2]) - curV;
[3081]917                  normArray[curElem->vertexNumber] = normArray[curElem->vertexNumber] + nextV.cross(prevV);
[3075]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();
[3079]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
[3195]934      this->normals->addEntry(normArray[i].x, normArray[i].y, normArray[i].z);
[3075]935
936    }
[3080]937  delete []normArray; 
[3081]938 
[3075]939}
940
941
[2842]942/**
943   \brief Includes a default object
[3186]944
[2842]945   This will inject a Cube, because this is the most basic object.
946*/
[2821]947void Object::BoxObject(void)
948{
[3195]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");
[2967]957
[3195]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");
[3081]972
[3195]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");
[2821]997
[3083]998  /* normaleLess-testingMode
[3195]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");
[3083]1005  */
[3081]1006
[3195]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");
[3083]1013
[2821]1014}
Note: See TracBrowser for help on using the repository browser.