Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/branches/dave/src/object.cc @ 2860

Last change on this file since 2860 was 2860, checked in by dave, 20 years ago

orxonox/branches/dave: das level hat jetzt form angenommen, stand:nach der Convention vom Samstag….

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