Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/branches/images/importer/object.cc @ 3128

Last change on this file since 3128 was 3127, checked in by bensch, 20 years ago

orxonox/branches/images: Implemented a Way to read in the Files from any Directory.

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