Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk/importer: extended the draw function. Now you can draw one of the objects with the call to its name, or its number.

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