Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk/importer: included groups to filereader

File size: 15.2 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 Object
134   It does this by just calling the List that must have been created earlier.
135*/
136void Object::draw (void)
137{
138  if (verbose >=3)
139    printf("drawing the 3D-Object\n"); 
140  Group* walker = firstGroup;
141  while (walker != NULL)
142    {
143      glCallList (walker->listNumber);
144      walker = walker->nextGroup;
145    }
146}
147
148/**
149   \brief initializes a new Group object
150*/
151bool Object::initGroup(Group* group)
152{
153  if (verbose >= 2)
154    printf("Adding new Group\n");
155  group->faceMode = -1;
156  if ((group->listNumber = glGenLists(1)) == 0 )
157    {
158      printf ("list could not be created for this Object\n");
159      return false;
160    }
161
162  if (groupCount == 0)
163    {
164      group->firstVertex = 0;
165      group->firstNormal = 0;
166      group->firstNormal = 0;
167    }
168  else
169    {
170      group->firstVertex = currentGroup->firstVertex + currentGroup->vertices->getCount()/3;
171      group->firstNormal = currentGroup->firstNormal + currentGroup->normals->getCount()/3;
172      group->firstVertexTexture = currentGroup->firstVertexTexture + currentGroup->vTexture->getCount()/2;
173    }
174
175  group->vertices = new Array();
176  group->normals = new Array();
177  group->vTexture = new Array();
178
179  glNewList (group->listNumber, GL_COMPILE);
180}
181
182/**
183   \brief finalizes a Group.
184*/
185bool Object::finalizeGroup(Group* group)
186{
187  glEnd();
188  glEndList();
189 
190  delete group->vertices;
191  delete group->normals;
192  delete group->vTexture;
193}
194/**
195   \brief Reads in the .obj File and sets all the Values.
196   This function does read the file, parses it for the occurence of things like vertices, faces and so on, and executes the specific tasks
197   \param fileName the File that will be parsed (.obj-file)
198*/
199bool Object::readFromObjFile (char* fileName)
200{
201  OBJ_FILE = new ifstream(fileName);
202  if (!OBJ_FILE->is_open())
203    {
204      if (verbose >=1)
205        printf ("unable to open .OBJ file: %s\n Loading Box Object instead.\n", fileName);
206      BoxObject();
207      return false;
208    }
209  objFileName = fileName;
210  char Buffer[500];
211  while(!OBJ_FILE->eof())
212    {
213      OBJ_FILE->getline(Buffer, 500);
214      if (verbose >=4)
215        printf ("Read input line: %s\n",Buffer);
216     
217
218      // case vertice
219      if (!strncmp(Buffer, "v ", 2))
220        {
221          readVertex(Buffer+2);
222        }
223
224      // case face
225      else if (!strncmp(Buffer, "f ", 2))
226        {
227          readFace (Buffer+2);
228        }
229     
230      else if (!strncmp(Buffer, "mtllib", 6))
231        {
232          readMtlLib (Buffer+7);
233        }
234
235      else if (!strncmp(Buffer, "usemtl", 6))
236        {
237          readUseMtl (Buffer+7);
238        }
239
240      // case VertexNormal
241      else if (!strncmp(Buffer, "vn ", 2))
242      {
243        readVertexNormal(Buffer+3);
244      }
245
246      // case VertexTextureCoordinate
247      else if (!strncmp(Buffer, "vt ", 2))
248      {
249        readVertexTexture(Buffer+3);
250      }
251      // case group
252      else if (!strncmp(Buffer, "g", 1))
253        {
254          readGroup (Buffer+2);
255        }
256    }
257  OBJ_FILE->close();
258
259}
260
261/**
262   \brief parses a vertex-String
263   If a vertex line is found this function will inject it into the vertex-Array
264   \param vertexString The String that will be parsed.
265*/
266bool Object::readVertex (char* vertexString)
267{
268  readingVertices = true;
269  char subbuffer1[20];
270  char subbuffer2[20];
271  char subbuffer3[20];
272  sscanf (vertexString, "%s %s %s", subbuffer1, subbuffer2, subbuffer3);
273  if (verbose >= 3)
274    printf ("reading in a vertex: %s %s %s\n", subbuffer1, subbuffer2, subbuffer3);
275  currentGroup->vertices->addEntry(atof(subbuffer1)*scaleFactor, atof(subbuffer2)*scaleFactor, atof(subbuffer3)*scaleFactor);
276  return true;
277}
278
279/**
280   \brief parses a face-string
281   If a face line is found this function will add it to the glList.
282   The function makes a difference between QUADS and TRIANGLES, and will if changed re-open, set and re-close the gl-processe.
283   \param faceString The String that will be parsed.
284*/
285bool Object::readFace (char* faceString)
286{
287  // finalize the Arrays;
288  if (readingVertices == true)
289    {
290      currentGroup->vertices->finalizeArray();
291      glVertexPointer(3, GL_FLOAT, 0, currentGroup->vertices->getArray());
292      currentGroup->normals->finalizeArray();
293      glNormalPointer(GL_FLOAT, 0, currentGroup->normals->getArray());
294      currentGroup->vTexture->finalizeArray();
295    }
296
297  readingVertices = false;
298  char subbuffer1[20];
299  char subbuffer2[20];
300  char subbuffer3[20];
301  char subbuffer4[20] ="";
302  sscanf (faceString, "%s %s %s %s", subbuffer1, subbuffer2, subbuffer3, subbuffer4);
303  if (!strcmp(subbuffer4, ""))
304    {
305      if (currentGroup->faceMode != 3)
306        {
307          if (currentGroup->faceMode != -1)
308            glEnd();
309          glBegin(GL_TRIANGLES);
310        }
311     
312      currentGroup->faceMode = 3;
313      if (verbose >=3)
314        printf ("found triag: %s, %s, %s\n", subbuffer1, subbuffer2, subbuffer3);
315      addGLElement(subbuffer1);
316      addGLElement(subbuffer2);
317      addGLElement(subbuffer3);
318      return true;
319    }
320  else
321    {
322      if (currentGroup->faceMode != 4)
323        {
324          if (currentGroup->faceMode != -1)
325            glEnd();
326          glBegin(GL_QUADS);
327        }
328      currentGroup->faceMode = 4;
329      if (verbose >=3 )
330        printf ("found quad: %s, %s, %s, %s\n", subbuffer1, subbuffer2, subbuffer3, subbuffer4);
331      addGLElement(subbuffer1);
332      addGLElement(subbuffer2);
333      addGLElement(subbuffer3);
334      addGLElement(subbuffer4);
335      return true;
336    }
337}
338
339/**
340   \brief Adds a Face-element (one vertex of a face) with all its information.
341   It does this by searching:
342   1. The Vertex itself
343   2. The VertexNormale
344   3. The VertexTextureCoordinate
345   merging this information, the face will be drawn.
346
347*/
348bool Object::addGLElement (char* elementString)
349{
350  if (verbose >=3)
351    printf ("importing grafical Element.... including to openGL\n");
352  char* vertex = elementString;
353
354  char* texture;
355  texture = strstr (vertex, "/");
356  texture[0] = '\0';
357  texture ++;
358  glTexCoord2fv(currentGroup->vTexture->getArray()+(atoi(texture)-1 - currentGroup->firstVertexTexture)*2);
359
360  char* normal;
361  if ((normal = strstr (texture, "/")) !=NULL)
362    {
363      normal[0] = '\0';
364      normal ++;
365      //glArrayElement(atoi(vertex)-1);
366      glNormal3fv(currentGroup->normals->getArray() +(atoi(normal)-1 - currentGroup->firstNormal)*3);
367    }
368  glVertex3fv(currentGroup->vertices->getArray() +(atoi(vertex)-1 - currentGroup->firstVertex)*3);
369
370}
371
372/**
373   \brief parses a vertexNormal-String
374   If a vertexNormal line is found this function will inject it into the vertexNormal-Array
375   \param normalString The String that will be parsed.
376*/
377bool Object::readVertexNormal (char* normalString)
378{
379  readingVertices = true;
380  char subbuffer1[20];
381  char subbuffer2[20];
382  char subbuffer3[20];
383  sscanf (normalString, "%s %s %s", subbuffer1, subbuffer2, subbuffer3);
384  if (verbose >=3 )
385    printf("found vertex-Normal %s, %s, %s\n", subbuffer1,subbuffer2,subbuffer3);
386  currentGroup->normals->addEntry(atof(subbuffer1), atof(subbuffer2), atof(subbuffer3));
387  return true;
388}
389
390/**
391   \brief parses a vertexTextureCoordinate-String
392   If a vertexTextureCoordinate line is found this function will inject it into the vertexTexture-Array
393   \param vTextureString The String that will be parsed.
394*/
395bool Object::readVertexTexture (char* vTextureString)
396{
397  readingVertices = true;
398  char subbuffer1[20];
399  char subbuffer2[20];
400  sscanf (vTextureString, "%s %s", subbuffer1, subbuffer2);
401  if (verbose >=3 )
402    printf("found vertex-Texture %s, %s\n", subbuffer1,subbuffer2);
403  currentGroup->vTexture->addEntry(atof(subbuffer1));
404  currentGroup->vTexture->addEntry(atof(subbuffer2));
405  return true;
406}
407
408/**
409   \brief parses a group String
410   This function initializes a new Group.
411   With it you should be able to import .obj-files with more than one Objects inside.
412   \param groupString the new Group to create
413*/
414bool Object::readGroup (char* groupString)
415{
416  //  printf ("test\n");
417  if (!strcmp(groupString, "default"))
418    {
419      if (groupCount != 0)
420        {
421          Group* newGroup = new Group;
422          finalizeGroup(currentGroup);
423          currentGroup->nextGroup = newGroup;
424          initGroup(newGroup);
425          currentGroup = newGroup; // must be after init see initGroup for more info
426        }
427      ++groupCount;
428    }
429  else
430    {
431      currentGroup->name = groupString;
432    }
433}
434
435/**
436    \brief Function to read in a mtl File.
437    this Function parses all Lines of an mtl File
438    \param mtlFile The .mtl file to read
439*/
440bool Object::readMtlLib (char* mtlFile)
441{
442  MTL_FILE = new ifstream (mtlFile);
443  if (!MTL_FILE->is_open())
444    {
445      if (verbose >= 1)
446        printf ("unable to open file: %s\n", mtlFile);
447      return false;
448    }
449  mtlFileName = mtlFile;
450  if (verbose >=2)
451    printf ("Opening mtlFile: %s\n", mtlFileName);
452  char Buffer[500];
453  Material* tmpMat = material;
454  while(!MTL_FILE->eof())
455    {
456      MTL_FILE->getline(Buffer, 500);
457      if (verbose >= 4)
458        printf("found line in mtlFile: %s\n", Buffer);
459     
460
461      // create new Material
462      if (!strncmp(Buffer, "newmtl ", 2))
463        {
464          tmpMat = tmpMat->addMaterial(Buffer+7);
465          //      printf ("%s, %p\n", tmpMat->getName(), tmpMat);
466        }
467      // setting a illumMode
468      else if (!strncmp(Buffer, "illum", 5))
469        {
470          tmpMat->setIllum(Buffer+6);
471
472        }
473      // setting Diffuse Color
474      else if (!strncmp(Buffer, "Kd", 2))
475        {
476          tmpMat->setDiffuse(Buffer+3);
477        }
478      // setting Ambient Color
479      else if (!strncmp(Buffer, "Ka", 2))
480        {
481          tmpMat->setAmbient(Buffer+3);
482        }
483      // setting Specular Color
484      else if (!strncmp(Buffer, "Ks", 2))
485        {
486          tmpMat->setSpecular(Buffer+3);
487        }
488      // setting The Specular Shininess
489      else if (!strncmp(Buffer, "Ns", 2))
490        {
491          tmpMat->setShininess(Buffer+3);
492        }
493      // setting up transparency
494      else if (!strncmp(Buffer, "d", 1))
495        {
496          tmpMat->setTransparency(Buffer+2);
497        }
498      else if (!strncpy(Buffer, "Tf", 2))
499        {
500          tmpMat->setTransparency(Buffer+3);
501        }
502
503    }
504  return true;
505}
506
507/**
508   \brief Function that selects a material, if changed in the obj file.
509   \param matString the Material that will be set.
510*/
511
512bool Object::readUseMtl (char* matString)
513{
514  if (!strcmp (mtlFileName, ""))
515    {
516      if (verbose >= 1)
517        printf ("Not using new defined material, because no mtlFile found yet\n");
518      return false;
519    }
520     
521  if (currentGroup->faceMode != -1)
522    glEnd();
523  currentGroup->faceMode = 0;
524  if (verbose >= 2)
525    printf ("using material %s for coming Faces.\n", matString);
526  material->search(matString)->select();
527}
528
529/**
530   \brief Includes a default object
531   This will inject a Cube, because this is the most basic object.
532*/
533void Object::BoxObject(void)
534{
535  readVertex ("-0.500000 -0.500000 0.500000");
536  readVertex ("0.500000 -0.500000 0.500000");
537  readVertex ("-0.500000 0.500000 0.500000");
538  readVertex ("0.500000 0.500000 0.500000");
539  readVertex ("-0.500000 0.500000 -0.500000");
540  readVertex ("0.500000 0.500000 -0.500000");
541  readVertex ("-0.500000 -0.500000 -0.500000");
542  readVertex ("0.500000 -0.500000 -0.500000");
543  readVertexTexture ("0.000000 0.000000");
544  readVertexTexture ("1.000000 0.000000");
545  readVertexTexture ("0.000000 1.000000");
546  readVertexTexture ("1.000000 1.000000");
547  readVertexTexture ("0.000000 2.000000");
548  readVertexTexture ("1.000000 2.000000");
549  readVertexTexture ("0.000000 3.000000");
550  readVertexTexture ("1.000000 3.000000");
551  readVertexTexture ("0.000000 4.000000");
552  readVertexTexture ("1.000000 4.000000");
553  readVertexTexture ("2.000000 0.000000");
554  readVertexTexture ("2.000000 1.000000");
555  readVertexTexture ("-1.000000 0.000000");
556  readVertexTexture ("-1.000000 1.000000");
557 
558  readVertexNormal ("0.000000 0.000000 1.000000");
559  readVertexNormal ("0.000000 0.000000 1.000000");
560  readVertexNormal ("0.000000 0.000000 1.000000");
561  readVertexNormal ("0.000000 0.000000 1.000000");
562  readVertexNormal ("0.000000 1.000000 0.000000");
563  readVertexNormal ("0.000000 1.000000 0.000000");
564  readVertexNormal ("0.000000 1.000000 0.000000");
565  readVertexNormal ("0.000000 1.000000 0.000000");
566  readVertexNormal ("0.000000 0.000000 -1.000000");
567  readVertexNormal ("0.000000 0.000000 -1.000000");
568  readVertexNormal ("0.000000 0.000000 -1.000000");
569  readVertexNormal ("0.000000 0.000000 -1.000000");
570  readVertexNormal ("0.000000 -1.000000 0.000000");
571  readVertexNormal ("0.000000 -1.000000 0.000000");
572  readVertexNormal ("0.000000 -1.000000 0.000000");
573  readVertexNormal ("0.000000 -1.000000 0.000000");
574  readVertexNormal ("1.000000 0.000000 0.000000");
575  readVertexNormal ("1.000000 0.000000 0.000000");
576  readVertexNormal ("1.000000 0.000000 0.000000");
577  readVertexNormal ("1.000000 0.000000 0.000000");
578  readVertexNormal ("-1.000000 0.000000 0.000000");
579  readVertexNormal ("-1.000000 0.000000 0.000000");
580  readVertexNormal ("-1.000000 0.000000 0.000000");
581  readVertexNormal ("-1.000000 0.000000 0.000000");
582
583  readFace ("1/1/1 2/2/2 4/4/3 3/3/4");
584  readFace ("3/3/5 4/4/6 6/6/7 5/5/8");
585  readFace ("5/5/9 6/6/10 8/8/11 7/7/12");
586  readFace ("7/7/13 8/8/14 2/10/15 1/9/16");
587  readFace ("2/2/17 8/11/18 6/12/19 4/4/20");
588  readFace ("7/13/21 1/1/22 3/3/23 5/14/24");
589}
Note: See TracBrowser for help on using the repository browser.