Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

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

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