Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 3096 was 3093, checked in by bensch, 20 years ago

orxonox/branches/images: moved things to where they belong

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