Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk/importer: better checking of objectCount

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