Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/branches/nico/importer/object.cc @ 3108

Last change on this file since 3108 was 2995, checked in by bensch, 20 years ago

orxonox/trunk: merged branches/osX back into the Trunk.
Conflicts resolved in Favor of trunk in all the Makefiles, and fixed many strange entries in configure.ac
merged with command: svn merge branches/osX/ trunk/ -r 2887:HEAD
AND most Important of all: change back to AUTOMAKE-1.7

File size: 18.8 KB
Line 
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
16#include "object.h"
17
18/**
19   \brief Creates a 3D-Object, but does not load any 3D-models
20   pretty useless
21*/
22Object::Object ()
23{
24
25  initialize();
26
27  BoxObject();
28
29  finalize();
30}
31
32/**
33   \brief Crates a 3D-Object and loads in a File
34   \param fileName file to parse and load (must be a .obj file)
35*/
36Object::Object(char* fileName)
37{
38  initialize();
39
40  importFile (fileName);
41
42  finalize();
43}
44
45/**
46   \brief Crates a 3D-Object, loads in a File and scales it.
47   \param fileName file to parse and load (must be a .obj file)
48   \param scaling The factor that the object will be scaled with.
49*/
50Object::Object(char* fileName, float scaling)
51{
52  initialize();
53  scaleFactor = scaling;
54
55  importFile (fileName);
56
57  finalize();
58}
59
60/**
61   \brief deletes an Object
62*/
63Object::~Object()
64{
65  if (verbose >= 2)
66    printf ("Deleting display List.\n");
67  Group* walker = firstGroup;
68  while (walker != NULL)
69    {
70      glDeleteLists (walker->listNumber, 1);
71      Group* lastWalker = walker;
72      walker = walker->nextGroup;
73      delete lastWalker;
74    } 
75}
76
77/**
78    \brief initializes the Object
79    This Function initializes all the needed arrays, Lists and clientStates
80*/
81bool Object::initialize (void)
82{
83  if (verbose >=3)
84    printf("new 3D-Object is being created\n"); 
85
86  // setting the start group;
87  firstGroup = new Group;
88  currentGroup = firstGroup;
89  groupCount = 0;
90 
91  initGroup (firstGroup);
92  mtlFileName = "";
93  scaleFactor = 1;
94  material = new Material();
95
96  //  glEnableClientState (GL_VERTEX_ARRAY);
97  //  glEnableClientState (GL_NORMAL_ARRAY);
98  //  glEnableClientState (GL_TEXTURE_COORD_ARRAY);
99
100
101  return true;
102}
103
104/**
105   \brief Imports a obj file and handles the the relative location
106   \param fileName The file to import
107*/
108bool Object::importFile (char* fileName)
109{
110  if (verbose >=3)
111    printf("preparing to read in file: %s\n", fileName);   
112  objFileName = fileName;
113  this->readFromObjFile (objFileName);
114  return true;
115}
116
117/**
118  \brief finalizes an Object.
119   This funcion is needed, to close the glList and all the other lists.
120*/
121bool Object::finalize(void)
122{
123  //  if (verbose >=3)
124    printf("finalizing the 3D-Object\n"); 
125  finalizeGroup (currentGroup);
126  if (material != NULL)
127    delete material;
128  return true;
129}
130
131/**
132   \brief Draws the Objects of all Groups.
133   It does this by just calling the Lists that must have been created earlier.
134*/
135void Object::draw (void)
136{
137  if (verbose >=2)
138    printf("drawing the 3D-Objects\n"); 
139  Group* walker = firstGroup;
140  while (walker != NULL)
141    {
142      if (verbose >= 3)
143        printf ("Drawing object %s\n", walker->name);
144      glCallList (walker->listNumber);
145      walker = walker->nextGroup;
146    }
147}
148
149/**
150   \brief Draws the Object number groupNumber
151   It does this by just calling the List that must have been created earlier.
152   \param groupNumber The number of the group that will be displayed.
153*/
154void Object::draw (int groupNumber)
155{
156  if (groupNumber >= groupCount)
157    {
158      if (verbose>=2)
159        printf ("You requested object number %i, but this File only contains of %i Objects.\n", groupNumber-1, groupCount);
160      return;
161    }
162  if (verbose >=2)
163    printf("drawing the requested 3D-Objects if found.\n"); 
164  Group* walker = firstGroup;
165  int counter = 0;
166  while (walker != NULL)
167    {
168      if (counter == groupNumber)
169        {
170          if (verbose >= 2)
171            printf ("Drawing object number %s named %s\n", counter, walker->name);
172          glCallList (walker->listNumber);
173          return;
174        }
175      ++counter;
176      walker = walker->nextGroup;
177    }
178  if (verbose >= 2)
179    printf("Object number %i in %s not Found.\n", groupNumber, objFileName);
180  return;
181
182}
183
184/**
185   \brief Draws the Object with a specific groupname
186   It does this by just calling the List that must have been created earlier.
187   \param groupName The name of the group that will be displayed.
188*/
189void Object::draw (char* groupName)
190{
191  if (verbose >=2)
192    printf("drawing the requested 3D-Objects if found.\n"); 
193  Group* walker = firstGroup;
194  while (walker != NULL)
195    {
196      if (!strcmp(walker->name, groupName))
197        {
198          if (verbose >= 2)
199            printf ("Drawing object %s\n", walker->name);
200          glCallList (walker->listNumber);
201          return;
202        }
203      walker = walker->nextGroup;
204    }
205  if (verbose >= 2)
206    printf("Object Named %s in %s not Found.\n", groupName, objFileName);
207  return;
208}
209
210/**
211   \returns Count of the Objects in this File
212*/
213int Object::getGroupCount (void)
214{
215  return groupCount;
216}
217
218/**
219   \brief initializes a new Group object
220*/
221bool Object::initGroup(Group* group)
222{
223  if (verbose >= 2)
224    printf("Adding new Group\n");
225  group->name = "";
226  group->faceMode = -1;
227  group->faceCount = 0; 
228  group->nextGroup = NULL;
229  if ((group->listNumber = glGenLists(1)) == 0 )
230    {
231      printf ("list could not be created for this Object\n");
232      return false;
233    }
234 
235  if (groupCount == 0)
236    {
237      group->firstVertex = 0;
238      group->firstNormal = 0;
239      group->firstVertexTexture = 0;
240    }
241  else
242    {
243      group->firstVertex = currentGroup->firstVertex + currentGroup->vertices->getCount()/3;
244      group->firstNormal = currentGroup->firstNormal + currentGroup->normals->getCount()/3;
245      group->firstVertexTexture = currentGroup->firstVertexTexture + currentGroup->vTexture->getCount()/2;
246    }
247  if (verbose >=2)
248    printf ("Creating new Arrays, with starting points v:%i, vt:%i, vn:%i .\n", group->firstVertex, group->firstVertexTexture, group->firstNormal);
249  group->vertices = new Array();
250  group->normals = new Array();
251  group->vTexture = new Array();
252
253  glNewList (group->listNumber, GL_COMPILE);
254}
255
256/**
257   \brief finalizes a Group.
258   \param group the group to finalize.
259*/
260bool Object::finalizeGroup(Group* group)
261{
262  if (verbose >=2)
263    printf ("Finalize group %s.\n", group->name);
264  glEnd();
265  glEndList();
266}
267
268/**
269   \brief deletes the Arrays of the Group to save space.
270   \param group the group to delete the arrays from.
271*/
272bool Object::cleanupGroup(Group* group)
273{
274  if (verbose >=2)
275    printf ("cleaning up group %s.\n", group->name);
276 
277  delete group->vertices;
278  delete group->normals;
279  delete group->vTexture;
280}
281
282/**
283   \brief Reads in the .obj File and sets all the Values.
284   This function does read the file, parses it for the occurence of things like vertices, faces and so on, and executes the specific tasks
285   \param fileName the File that will be parsed (.obj-file)
286*/
287bool Object::readFromObjFile (char* fileName)
288{
289  OBJ_FILE = new ifstream(fileName);
290  if (!OBJ_FILE->is_open())
291    {
292      if (verbose >=1)
293        printf ("unable to open .OBJ file: %s\n Loading Box Object instead.\n", fileName);
294      BoxObject();
295      return false;
296    }
297  objFileName = fileName;
298  char Buffer[10000];
299  while(!OBJ_FILE->eof())
300    {
301      OBJ_FILE->getline(Buffer, 10000);
302      if (verbose >=4)
303        printf ("Read input line: %s\n",Buffer);
304     
305
306      // case vertice
307      if (!strncmp(Buffer, "v ", 2))
308        {
309          readVertex(Buffer+2);
310        }
311
312      // case face
313      else if (!strncmp(Buffer, "f ", 2))
314        {
315          readFace (Buffer+2);
316        }
317     
318      else if (!strncmp(Buffer, "mtllib", 6))
319        {
320          readMtlLib (Buffer+7);
321        }
322
323      else if (!strncmp(Buffer, "usemtl", 6))
324        {
325          readUseMtl (Buffer+7);
326        }
327
328      // case VertexNormal
329      else if (!strncmp(Buffer, "vn ", 2))
330      {
331        readVertexNormal(Buffer+3);
332      }
333
334      // case VertexTextureCoordinate
335      else if (!strncmp(Buffer, "vt ", 2))
336      {
337        readVertexTexture(Buffer+3);
338      }
339      // case group
340      else if (!strncmp(Buffer, "g", 1))
341        {
342          readGroup (Buffer+2);
343        }
344      else if (!strncmp(Buffer, "s", 1))
345        {
346          if (verbose >= 1)
347            printf("smoothing groups not suportet yet. line: %s\n", Buffer);
348        }
349    }
350  OBJ_FILE->close();
351  return true;
352
353}
354
355/**
356   \brief parses a vertex-String
357   If a vertex line is found this function will inject it into the vertex-Array
358   \param vertexString The String that will be parsed.
359*/
360bool Object::readVertex (char* vertexString)
361{
362  readingVertices = true;
363  char subbuffer1[20];
364  char subbuffer2[20];
365  char subbuffer3[20];
366  sscanf (vertexString, "%s %s %s", subbuffer1, subbuffer2, subbuffer3);
367  if (verbose >= 3)
368    printf ("reading in a vertex: %s %s %s\n", subbuffer1, subbuffer2, subbuffer3);
369  currentGroup->vertices->addEntry(atof(subbuffer1)*scaleFactor, atof(subbuffer2)*scaleFactor, atof(subbuffer3)*scaleFactor);
370  return true;
371}
372
373/**
374   \brief parses a face-string
375   If a face line is found this function will add it to the glList.
376   The function makes a difference between QUADS and TRIANGLES, and will if changed re-open, set and re-close the gl-processe.
377   \param faceString The String that will be parsed.
378*/
379bool Object::readFace (char* faceString)
380{
381  // finalize the Arrays;
382  if (readingVertices == true)
383    {
384      currentGroup->vertices->finalizeArray();
385      //      glVertexPointer(3, GL_FLOAT, 0, currentGroup->vertices->getArray());
386      currentGroup->normals->finalizeArray();
387      //      glNormalPointer(GL_FLOAT, 0, currentGroup->normals->getArray());
388      currentGroup->vTexture->finalizeArray();
389    }
390
391  readingVertices = false;
392  currentGroup->faceCount++;
393
394  int elemCount = 0;
395 
396  FaceElement* firstElem = new FaceElement;
397  FaceElement* tmpElem = firstElem;
398
399 
400  while(strcmp (faceString, "\0"))
401    {
402      if (elemCount>0)
403          tmpElem = tmpElem->next = new FaceElement;
404      tmpElem->next = NULL;
405
406
407      sscanf (faceString, "%s", tmpElem->value);
408      faceString += strlen(tmpElem->value);
409      if (strcmp (faceString, "\0"))
410        faceString++;
411      elemCount++;
412
413
414    }
415 
416 
417  if (elemCount == 3)
418    {
419      if (currentGroup->faceMode != 3)
420        {
421          if (currentGroup->faceMode != -1)
422            glEnd();
423          glBegin(GL_TRIANGLES);
424        }
425     
426      currentGroup->faceMode = 3;
427      if (verbose >=3)
428        printf ("found triag.\n");
429    }
430 
431  else if (elemCount == 4)
432    {
433      if (currentGroup->faceMode != 4)
434        {
435          if (currentGroup->faceMode != -1)
436            glEnd();
437          glBegin(GL_QUADS);
438        }
439      currentGroup->faceMode = 4;
440      if (verbose >=3 )
441        printf ("found quad.\n");
442    }
443 
444  else if (elemCount > 4)
445    {
446      if (currentGroup->faceMode != -1)
447        glEnd();
448      glBegin(GL_POLYGON);
449      if (verbose >=3)
450        printf ("Polygon with %i faces found.", elemCount);
451      currentGroup->faceMode = elemCount;
452    }
453
454  tmpElem = firstElem;
455  FaceElement* delElem;
456  while (tmpElem != NULL)
457    {
458      //      printf ("%s\n", tmpElem->value);
459      addGLElement(tmpElem->value);
460      delElem = tmpElem;
461      tmpElem = tmpElem->next;
462      delete delElem;
463    }
464
465}
466
467/**
468   \brief Adds a Face-element (one vertex of a face) with all its information.
469   It does this by searching:
470   1. The Vertex itself
471   2. The VertexNormale
472   3. The VertexTextureCoordinate
473   merging this information, the face will be drawn.
474
475*/
476bool Object::addGLElement (char* elementString)
477{
478  if (verbose >=3)
479    printf ("importing grafical Element to openGL\n");
480  char* vertex = elementString;
481
482  char* texture;
483  if ((texture = strstr (vertex, "/")) != NULL)
484    {
485      texture[0] = '\0';
486      texture ++;
487      if (verbose>=3)
488        printf ("includeing texture #%i, and mapping it to group texture #%i, textureArray has %i entries.\n", atoi(texture), (atoi(texture)-1 - currentGroup->firstVertexTexture)*2, currentGroup->vTexture->getCount());
489      glTexCoord2fv(currentGroup->vTexture->getArray()+(atoi(texture)-1 - currentGroup->firstVertexTexture)*2);
490
491      char* normal;
492      if ((normal = strstr (texture, "/")) !=NULL)
493        {
494          normal[0] = '\0';
495          normal ++;
496          //glArrayElement(atoi(vertex)-1);
497          glNormal3fv(currentGroup->normals->getArray() +(atoi(normal)-1 - currentGroup->firstNormal)*3);
498        }
499    }
500  if (verbose>=3)
501    printf ("includeing vertex #%i, and mapping it to group vertex #%i, vertexArray has %i entries.\n", atoi(vertex), (atoi(vertex)-1 - currentGroup->firstVertex)*3, currentGroup->vertices->getCount());
502  glVertex3fv(currentGroup->vertices->getArray() +(atoi(vertex)-1 - currentGroup->firstVertex)*3);
503
504}
505
506/**
507   \brief parses a vertexNormal-String
508   If a vertexNormal line is found this function will inject it into the vertexNormal-Array
509   \param normalString The String that will be parsed.
510*/
511bool Object::readVertexNormal (char* normalString)
512{
513  readingVertices = true;
514  char subbuffer1[20];
515  char subbuffer2[20];
516  char subbuffer3[20];
517  sscanf (normalString, "%s %s %s", subbuffer1, subbuffer2, subbuffer3);
518  if (verbose >=3 )
519    printf("found vertex-Normal %s, %s, %s\n", subbuffer1,subbuffer2,subbuffer3);
520  currentGroup->normals->addEntry(atof(subbuffer1), atof(subbuffer2), atof(subbuffer3));
521  return true;
522}
523
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*/
529bool Object::readVertexTexture (char* vTextureString)
530{
531  readingVertices = true;
532  char subbuffer1[20];
533  char subbuffer2[20];
534  sscanf (vTextureString, "%s %s", subbuffer1, subbuffer2);
535  if (verbose >=3 )
536    printf("found vertex-Texture %s, %s\n", subbuffer1,subbuffer2);
537  currentGroup->vTexture->addEntry(atof(subbuffer1));
538  currentGroup->vTexture->addEntry(atof(subbuffer2));
539  return true;
540}
541
542/**
543   \brief parses a group String
544   This function initializes a new Group.
545   With it you should be able to import .obj-files with more than one Objects inside.
546   \param groupString the new Group to create
547*/
548bool Object::readGroup (char* groupString)
549{
550  // setting the group name if not default.
551  if (strcmp(currentGroup->name, "default"))
552    {
553      currentGroup->name = (char*) malloc ( strlen(groupString) * sizeof (char));
554      strcpy(currentGroup->name, groupString);
555    }
556  if (groupCount != 0 && currentGroup->faceCount>0)
557    {
558      Group* newGroup = new Group;
559      finalizeGroup(currentGroup);
560      currentGroup->nextGroup = newGroup;
561      initGroup(newGroup);
562      cleanupGroup(currentGroup); // deletes the arrays of the group; must be after initGroup.
563      currentGroup = newGroup; // must be after init see initGroup for more info
564    }
565
566  ++groupCount;
567
568}
569
570/**
571    \brief Function to read in a mtl File.
572    this Function parses all Lines of an mtl File
573    \param mtlFile The .mtl file to read
574*/
575bool Object::readMtlLib (char* mtlFile)
576{
577  MTL_FILE = new ifstream (mtlFile);
578  if (!MTL_FILE->is_open())
579    {
580      if (verbose >= 1)
581        printf ("unable to open file: %s\n", mtlFile);
582      return false;
583    }
584  mtlFileName = mtlFile;
585  if (verbose >=2)
586    printf ("Opening mtlFile: %s\n", mtlFileName);
587  char Buffer[500];
588  Material* tmpMat = material;
589  while(!MTL_FILE->eof())
590    {
591      MTL_FILE->getline(Buffer, 500);
592      if (verbose >= 4)
593        printf("found line in mtlFile: %s\n", Buffer);
594     
595
596      // create new Material
597      if (!strncmp(Buffer, "newmtl ", 2))
598        {
599          tmpMat = tmpMat->addMaterial(Buffer+7);
600          //      printf ("%s, %p\n", tmpMat->getName(), tmpMat);
601        }
602      // setting a illumMode
603      else if (!strncmp(Buffer, "illum", 5))
604        {
605          tmpMat->setIllum(Buffer+6);
606
607        }
608      // setting Diffuse Color
609      else if (!strncmp(Buffer, "Kd", 2))
610        {
611          tmpMat->setDiffuse(Buffer+3);
612        }
613      // setting Ambient Color
614      else if (!strncmp(Buffer, "Ka", 2))
615        {
616          tmpMat->setAmbient(Buffer+3);
617        }
618      // setting Specular Color
619      else if (!strncmp(Buffer, "Ks", 2))
620        {
621          tmpMat->setSpecular(Buffer+3);
622        }
623      // setting The Specular Shininess
624      else if (!strncmp(Buffer, "Ns", 2))
625        {
626          tmpMat->setShininess(Buffer+3);
627        }
628      // setting up transparency
629      else if (!strncmp(Buffer, "d", 1))
630        {
631          tmpMat->setTransparency(Buffer+2);
632        }
633      else if (!strncpy(Buffer, "Tf", 2))
634        {
635          tmpMat->setTransparency(Buffer+3);
636        }
637
638    }
639  return true;
640}
641
642/**
643   \brief Function that selects a material, if changed in the obj file.
644   \param matString the Material that will be set.
645*/
646bool Object::readUseMtl (char* matString)
647{
648  if (!strcmp (mtlFileName, ""))
649    {
650      if (verbose >= 1)
651        printf ("Not using new defined material, because no mtlFile found yet\n");
652      return false;
653    }
654     
655  if (currentGroup->faceMode != -1)
656    glEnd();
657  currentGroup->faceMode = 0;
658  if (verbose >= 2)
659    printf ("using material %s for coming Faces.\n", matString);
660  material->search(matString)->select();
661}
662
663/**
664   \brief Includes a default object
665   This will inject a Cube, because this is the most basic object.
666*/
667void Object::BoxObject(void)
668{
669  readVertex ("-0.500000 -0.500000 0.500000");
670  readVertex ("0.500000 -0.500000 0.500000");
671  readVertex ("-0.500000 0.500000 0.500000");
672  readVertex ("0.500000 0.500000 0.500000");
673  readVertex ("-0.500000 0.500000 -0.500000");
674  readVertex ("0.500000 0.500000 -0.500000");
675  readVertex ("-0.500000 -0.500000 -0.500000");
676  readVertex ("0.500000 -0.500000 -0.500000");
677
678  readVertexTexture ("0.000000 0.000000");
679  readVertexTexture ("1.000000 0.000000");
680  readVertexTexture ("0.000000 1.000000");
681  readVertexTexture ("1.000000 1.000000");
682  readVertexTexture ("0.000000 2.000000");
683  readVertexTexture ("1.000000 2.000000");
684  readVertexTexture ("0.000000 3.000000");
685  readVertexTexture ("1.000000 3.000000");
686  readVertexTexture ("0.000000 4.000000");
687  readVertexTexture ("1.000000 4.000000");
688  readVertexTexture ("2.000000 0.000000");
689  readVertexTexture ("2.000000 1.000000");
690  readVertexTexture ("-1.000000 0.000000");
691  readVertexTexture ("-1.000000 1.000000");
692 
693  readVertexNormal ("0.000000 0.000000 1.000000");
694  readVertexNormal ("0.000000 0.000000 1.000000");
695  readVertexNormal ("0.000000 0.000000 1.000000");
696  readVertexNormal ("0.000000 0.000000 1.000000");
697  readVertexNormal ("0.000000 1.000000 0.000000");
698  readVertexNormal ("0.000000 1.000000 0.000000");
699  readVertexNormal ("0.000000 1.000000 0.000000");
700  readVertexNormal ("0.000000 1.000000 0.000000");
701  readVertexNormal ("0.000000 0.000000 -1.000000");
702  readVertexNormal ("0.000000 0.000000 -1.000000");
703  readVertexNormal ("0.000000 0.000000 -1.000000");
704  readVertexNormal ("0.000000 0.000000 -1.000000");
705  readVertexNormal ("0.000000 -1.000000 0.000000");
706  readVertexNormal ("0.000000 -1.000000 0.000000");
707  readVertexNormal ("0.000000 -1.000000 0.000000");
708  readVertexNormal ("0.000000 -1.000000 0.000000");
709  readVertexNormal ("1.000000 0.000000 0.000000");
710  readVertexNormal ("1.000000 0.000000 0.000000");
711  readVertexNormal ("1.000000 0.000000 0.000000");
712  readVertexNormal ("1.000000 0.000000 0.000000");
713  readVertexNormal ("-1.000000 0.000000 0.000000");
714  readVertexNormal ("-1.000000 0.000000 0.000000");
715  readVertexNormal ("-1.000000 0.000000 0.000000");
716  readVertexNormal ("-1.000000 0.000000 0.000000");
717
718  readFace ("1/1/1 2/2/2 4/4/3 3/3/4");
719  readFace ("3/3/5 4/4/6 6/6/7 5/5/8");
720  readFace ("5/5/9 6/6/10 8/8/11 7/7/12");
721  readFace ("7/7/13 8/8/14 2/10/15 1/9/16");
722  readFace ("2/2/17 8/11/18 6/12/19 4/4/20");
723  readFace ("7/13/21 1/1/22 3/3/23 5/14/24");
724}
Note: See TracBrowser for help on using the repository browser.