Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/branches/parenting/src/world.cc @ 3309

Last change on this file since 3309 was 3309, checked in by patrick, 19 years ago

orxonox/branches/parenting: added a second worldentity just to test the lists - working but not drawing since there is no model loaded. including second object (importer) results in SEGFAULT

File size: 18.6 KB
Line 
1
2/*
3   orxonox - the future of 3D-vertical-scrollers
4
5   Copyright (C) 2004 orx
6
7   This program is free software; you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation; either version 2, or (at your option)
10   any later version.
11
12   ### File Specific:
13   main-programmer: Patrick Boenzli
14   co-programmer: Christian Meyer
15*/
16
17#include "world.h"
18#include "world_entity.h"
19#include "collision.h"
20#include "track.h"
21#include "player.h"
22#include "command_node.h"
23#include "camera.h"
24#include "environment.h"
25#include "p_node.h"
26#include "null_parent.h"
27
28using namespace std;
29
30
31/**
32    \brief create a new World
33   
34    This creates a new empty world!
35*/
36World::World (char* name)
37{
38  this->setClassName ("World");
39  this->worldName = name;
40  this->debugWorldNr = -1;
41  this->entities = new tList<WorldEntity>();
42}
43
44World::World (int worldID)
45{
46  this->debugWorldNr = worldID;
47  this->worldName = NULL;
48  this->entities = new tList<WorldEntity>();
49}
50
51/**
52    \brief remove the World from memory
53   
54    delete everything explicitly, that isn't contained in the parenting tree!
55    things contained in the tree are deleted automaticaly
56*/
57World::~World ()
58{
59  printf("World::~World() - deleting current world\n");
60  CommandNode* cn = Orxonox::getInstance()->getLocalInput();
61  cn->unbind(this->localPlayer);
62  cn->reset();
63  this->localCamera->destroy();
64
65  this->nullParent->destroy ();
66
67  /*
68  WorldEntity* entity = entities->enumerate(); 
69  while( entity != NULL )
70    {
71      entity->destroy();
72      entity = entities->nextElement();
73    }
74  this->entities->destroy();
75  */
76
77  /* FIX the parent list has to be cleared - not possible if we got the old list also*/
78
79
80  //delete this->entities;
81  //delete this->localCamera;
82  /* this->localPlayer hasn't to be deleted explicitly, it is
83     contained in entities*/
84}
85
86
87ErrorMessage World::init()
88{
89  this->bPause = false;
90  CommandNode* cn = Orxonox::getInstance()->getLocalInput();
91  cn->addToWorld(this);
92  cn->enable(true);
93
94  /* this is only for test purposes */
95  this->debug ();
96}
97
98ErrorMessage World::start()
99{
100  printf("World::start() - starting current World: nr %i\n", this->debugWorldNr);
101  this->bQuitOrxonox = false;
102  this->bQuitCurrentGame = false;
103  this->mainLoop();
104}
105
106ErrorMessage World::stop()
107{
108  printf("World::stop() - got stop signal\n");
109  this->bQuitCurrentGame = true;
110}
111
112ErrorMessage World::pause()
113{
114  this->isPaused = true;
115}
116
117ErrorMessage World::resume()
118{
119  this->isPaused = false;
120}
121
122void World::destroy()
123{
124
125}
126
127void World::load()
128{
129  if(this->debugWorldNr != -1)
130    {
131      switch(this->debugWorldNr)
132        {
133          /*
134            this loads the hard-coded debug world. this only for simplicity and will be
135            removed by a reald world-loader, which interprets a world-file.
136            if you want to add an own debug world, just add a case DEBUG_WORLD_[nr] and
137            make whatever you want...
138           */
139        case DEBUG_WORLD_0:
140          {
141            this->nullParent = new NullParent ();
142            this->nullParent->setName ("NullParent");
143
144            // create some path nodes
145            this->pathnodes = new Vector[6];
146            this->pathnodes[0] = Vector(0, 0, 0);
147            this->pathnodes[1] = Vector(1000, 0, 0);
148            //      this->pathnodes[2] = Vector(-100, 140, 0);
149            //      this->pathnodes[3] = Vector(0, 180, 0);
150            //      this->pathnodes[4] = Vector(100, 140, 0);
151            //      this->pathnodes[5] = Vector(100, 40, 0);
152           
153            // create the tracks
154            this->tracklen = 2;
155            this->track = new Track[2];
156            for( int i = 0; i < this->tracklen; i++)
157              {
158                this->track[i] = Track( i, (i+1)%this->tracklen, &this->pathnodes[i], &this->pathnodes[(i+1)%this->tracklen]);
159              }
160            // !\todo old track-system has to be removed
161
162            // create a player
163            WorldEntity* myPlayer = new Player();
164            myPlayer->setName ("player");
165            this->spawn(myPlayer);
166            this->localPlayer = myPlayer;           
167
168            // bind input
169            Orxonox *orx = Orxonox::getInstance();
170            orx->getLocalInput()->bind (myPlayer);
171           
172            // bind camera
173            this->localCamera = new Camera(this);
174            this->localCamera->setName ("camera");
175            this->getCamera()->bind (myPlayer);
176            this->localPlayer->addChild (this->localCamera);
177           
178
179            Vector* es = new Vector (50, 0, 5);
180            Quaternion* qs = new Quaternion ();
181            WorldEntity* env = new Environment();
182            env->setName ("env");
183            this->spawn(env, es, qs);
184
185
186            break;
187          }
188        case DEBUG_WORLD_1:
189          {
190            this->nullParent = new NullParent ();
191
192            // create some path nodes
193            this->pathnodes = new Vector[6];
194            this->pathnodes[0] = Vector(0, 0, 0);
195            this->pathnodes[1] = Vector(20, 10, 10);
196            this->pathnodes[2] = Vector(40, 0, 10);
197            this->pathnodes[3] = Vector(60, 10, 0);
198            this->pathnodes[4] = Vector(80, 20, 10);
199            this->pathnodes[5] = Vector(30, 50, 0);
200           
201            // create the tracks
202            this->tracklen = 6;
203            this->track = new Track[6];
204            for( int i = 0; i < this->tracklen; i++)
205              {
206                this->track[i] = Track( i, (i+1)%this->tracklen, &this->pathnodes[i], &this->pathnodes[(i+1)%this->tracklen]);
207              }
208
209            // create a player
210            WorldEntity* myPlayer = new Player();
211            myPlayer->setName ("player");
212            this->spawn(myPlayer);
213            this->localPlayer = myPlayer;           
214           
215            // bind input
216            Orxonox *orx = Orxonox::getInstance();
217            orx->getLocalInput()->bind (myPlayer);
218           
219            // bind camera
220            this->localCamera = new Camera (this);
221            this->localCamera->setName ("camera");
222            this->getCamera()->bind (myPlayer); 
223            this->localPlayer->addChild (this->localCamera);
224            break;
225          }
226        default:
227          printf("World::load() - no world with ID %i found", this->debugWorldNr );
228        }
229    }
230  else if(this->worldName != NULL)
231    {
232
233    }
234
235  // initialize debug coord system
236  objectList = glGenLists(1);
237  glNewList (objectList, GL_COMPILE);
238  glLoadIdentity();
239  glColor3f(1.0,0,0);
240  glBegin(GL_QUADS);
241
242  int sizeX = 100;
243  int sizeY = 80;
244  float length = 1000;
245  float width = 200;
246  float widthX = float (length /sizeX);
247  float widthY = float (width /sizeY);
248 
249  float height [sizeX][sizeY];
250  Vector normal_vectors[sizeX][sizeY];
251 
252 
253  for ( int i = 0; i<sizeX-1; i+=1)
254    for (int j = 0; j<sizeY-1;j+=1)
255      //height[i][j] = rand()/20046 + (j-25)*(j-25)/30;
256#ifdef __WIN32__
257      height[i][j]=(sin((float)j/3)*rand()*i/182400)*.5;
258#else
259      height[i][j]=(sin((float)j/3)*rand()*(long)i/6282450500.0)*.5;
260#endif
261
262  //Die Hügel ein wenig glätten
263  for (int h=1; h<2;h++)
264    for (int i=1;i<sizeX-2 ;i+=1 )
265      for(int j=1;j<sizeY-2;j+=1)
266        height[i][j]=(height[i+1][j]+height[i][j+1]+height[i-1][j]+height[i][j-1])/4;
267 
268  //Berechnung von normalen Vektoren
269 
270  for(int i=1;i<sizeX-2;i+=1)
271    for(int j=1;j<sizeY-2 ;j+=1)
272      {
273        Vector v1 = Vector (widthX*(1),      widthY*(j)  ,      height[i][j]);
274        Vector v2 = Vector (widthX*(i-1),    widthY*(j)  ,      height[i-1][j]);
275        Vector v3 = Vector (widthX*(i),      widthY*(j+1),      height[i][j+1]);
276        Vector v4 = Vector (widthX*(i+1),    widthY*(j),        height[i+1][j]);
277        Vector v5 = Vector (widthX*(i),      widthY*(j-1),      height[i][j-1]);
278       
279        Vector c1 = v2 - v1;
280        Vector c2 = v3 - v1;
281        Vector c3=  v4 - v1;
282        Vector c4 = v5 - v1;
283        Vector zero = Vector (0,0,0);
284        normal_vectors[i][j]=c1.cross(v4-v2)+c2.cross(v1-v3)+c3.cross(v2-v4)+c4.cross(v3-v1);
285        normal_vectors[i][j].normalize();
286      }
287
288  int snowheight=3;
289  for ( int i = 0; i<sizeX; i+=1)
290    for (int j = 0; j<sizeY;j+=1)
291      {   
292        Vector v1 = Vector (widthX*(i),      widthY*(j)  -width/2,      height[i][j]-20 );
293        Vector v2 = Vector (widthX*(i+1),    widthY*(j)  -width/2,      height[i+1][j]-20);
294        Vector v3 = Vector (widthX*(i+1),    widthY*(j+1)-width/2,    height[i+1][j+1]-20);
295        Vector v4 = Vector (widthX*(i),      widthY*(j+1)-width/2,    height[i][j+1]-20);
296        float a[3];
297        if(height[i][j]<snowheight){
298          a[0]=0;
299          a[1]=1.0-height[i][j]/10-.3;
300          a[2]=0;
301          glMaterialfv(GL_FRONT,GL_DIFFUSE,a);
302        }
303        else{
304            a[0]=1.0;
305            a[1]=1.0;
306            a[2]=1.0;
307            glMaterialfv(GL_FRONT,GL_DIFFUSE,a);
308           
309        }
310        glNormal3f(normal_vectors[i][j].x, normal_vectors[i][j].y, normal_vectors[i][j].z);
311        glVertex3f(v1.x, v1.y, v1.z);
312        if(height[i+1][j]<snowheight){
313          a[0]=0;
314          a[1] =1.0-height[i+1][j]/10-.3;
315          a[2]=0;
316          glMaterialfv(GL_FRONT,GL_DIFFUSE,a);
317        }
318        else{
319          a[0]=1.0;
320          a[1]=1.0;
321          a[2]=1.0;
322          glMaterialfv(GL_FRONT,GL_DIFFUSE,a);
323         
324        }
325        glNormal3f(normal_vectors[i+1][j].x, normal_vectors[i+1][j].y, normal_vectors[i+1][j].z);
326        glVertex3f(v2.x, v2.y, v2.z);
327        if(height[i+1][j+1]<snowheight){
328          a[0]=0;
329          a[1] =1.0-height[i+1][j+1]/10-.3;
330          a[2]=0;
331          glMaterialfv(GL_FRONT,GL_DIFFUSE,a);
332        }
333        else{
334          a[0]=1.0;
335          a[1]=1.0;
336          a[2]=1.0;
337          glMaterialfv(GL_FRONT,GL_DIFFUSE,a);
338         
339         
340        }
341        glNormal3f(normal_vectors[i+1][j+1].x, normal_vectors[i+1][j+1].y, normal_vectors[i+1][j+1].z);
342        glVertex3f(v3.x, v3.y, v3.z);
343        if(height[i][j+1]<snowheight){
344          a[0]=0;
345          a[1] =1.0-height[i+1][j+1]/10-.3;
346          a[2]=0;
347          glMaterialfv(GL_FRONT,GL_DIFFUSE,a);
348        }
349        else{
350          a[0]=1.0;
351          a[1]=1.0;
352          a[2]=1.0;
353          glMaterialfv(GL_FRONT,GL_DIFFUSE,a);
354        }
355        glNormal3f(normal_vectors[i][j+1].x, normal_vectors[i][j+1].y, normal_vectors[i][j+1].z);
356        glVertex3f(v4.x, v4.y, v4.z);
357       
358      }
359  glEnd();
360  /* 
361  glBegin(GL_LINES);
362  for( float x = -128.0; x < 128.0; x += 25.0)
363    {
364      for( float y = -128.0; y < 128.0; y += 25.0)
365        {
366          glColor3f(1,0,0);
367          glVertex3f(x,y,-128.0);
368          glVertex3f(x,y,0.0);
369          glColor3f(0.5,0,0);
370          glVertex3f(x,y,0.0);
371          glVertex3f(x,y,128.0);
372        }
373    }
374  for( float y = -128.0; y < 128.0; y += 25.0)
375    {
376      for( float z = -128.0; z < 128.0; z += 25.0)
377        {
378          glColor3f(0,1,0);
379          glVertex3f(-128.0,y,z);
380          glVertex3f(0.0,y,z);
381          glColor3f(0,0.5,0);
382          glVertex3f(0.0,y,z);
383          glVertex3f(128.0,y,z);
384        }
385    }
386  for( float x = -128.0; x < 128.0; x += 25.0)
387    {
388      for( float z = -128.0; z < 128.0; z += 25.0)
389        {
390          glColor3f(0,0,1);
391          glVertex3f(x,-128.0,z);
392          glVertex3f(x,0.0,z);
393          glColor3f(0,0,0.5);
394          glVertex3f(x,0.0,z);
395          glVertex3f(x,128.0,z);
396        }
397     
398    }
399  */ 
400  //draw track
401  glBegin(GL_LINES);
402  glColor3f(0,1,1);
403  for( int i = 0; i < tracklen; i++)
404    {
405      glVertex3f(pathnodes[i].x,pathnodes[i].y,pathnodes[i].z);
406      glVertex3f(pathnodes[(i+1)%tracklen].x,pathnodes[(i+1)%tracklen].y,pathnodes[(i+1)%tracklen].z);
407    }
408  glEnd();
409  glEndList();
410}
411
412
413/**
414    \brief checks for collisions
415   
416    This method runs through all WorldEntities known to the world and checks for collisions
417    between them. In case of collisions the collide() method of the corresponding entities
418    is called.
419*/
420void World::collide ()
421{
422  /*
423  List *a, *b;
424  WorldEntity *aobj, *bobj;
425   
426  a = entities;
427 
428  while( a != NULL)
429    {
430      aobj = a->nextElement();
431      if( aobj->bCollide && aobj->collisioncluster != NULL)
432        {
433          b = a->nextElement();
434          while( b != NULL )
435            {
436              bobj = b->nextElement();
437              if( bobj->bCollide && bobj->collisioncluster != NULL )
438                {
439                  unsigned long ahitflg, bhitflg;
440                  if( check_collision ( &aobj->place, aobj->collisioncluster,
441                                        &ahitflg, &bobj->place, bobj->collisioncluster,
442                                        &bhitflg) );
443                  {
444                    aobj->collide (bobj, ahitflg, bhitflg);
445                    bobj->collide (aobj, bhitflg, ahitflg);
446                  }
447                }
448              b = b->nextElement();
449            }
450        }
451      a = a->enumerate();
452    }
453  */
454}
455
456/**
457    \brief runs through all entities calling their draw() methods
458*/
459void World::draw ()
460{
461  // draw entities
462  WorldEntity* entity;
463  entity = this->entities->enumerate();
464  while( entity != NULL ) 
465    { 
466      if( entity->bDraw ) entity->draw();
467      entity = this->entities->nextElement();
468    } 
469 
470  // draw debug coord system
471  glCallList (objectList);
472
473
474}
475
476/**
477    \brief updates Placements and notifies entities when they left the
478    world
479   
480    This runs trough all WorldEntities and maps Locations to Placements
481    if they are bound, checks whether they left the level boundaries
482    and calls appropriate functions.
483*/
484void World::update ()
485{
486  /*
487  //List<WorldEntity> *l;
488  WorldEntity* entity;
489  Location* loc;
490  Placement* plc;
491  Uint32 t;
492 
493  //  l = entities->enumerate();
494  entity = this->entities->enumerate();
495  while( entity != NULL )
496    {
497
498     
499      if( !entity->isFree() )
500        {
501          loc = entity->getLocation();
502          plc = entity->getPlacement();
503          t = loc->part;
504         
505          if( t >= tracklen )
506            {
507              printf("An entity is out of the game area\n");
508              entity->leftWorld ();
509            }
510          else
511            {
512              while( track[t].mapCoords( loc, plc) )
513                {
514                  track[t].postLeave (entity);
515                  if( loc->part >= tracklen )
516                    {
517                      printf("An entity has left the game area\n");
518                      entity->leftWorld ();
519                      break;
520                    }
521                  track[loc->part].postEnter (entity);
522                }
523            }
524        }
525      else
526        {
527        }
528     
529      entity = entities->nextElement();
530    }
531  */ 
532}
533
534/**
535    \brief relays the passed time since the last frame to entities and Track parts
536    \param deltaT: the time passed since the last frame in milliseconds
537*/
538void World::timeSlice (Uint32 deltaT)
539{
540  //List<WorldEntity> *l;
541  WorldEntity* entity;
542  float seconds = deltaT / 1000.0;
543 
544  this->nullParent->update (seconds);
545  //this->nullParent->processTick (seconds);
546
547  entity = entities->enumerate(); 
548  while( entity != NULL) 
549    { 
550      entity->tick (seconds);
551      entity = entities->nextElement();
552    }
553
554  //for( int i = 0; i < tracklen; i++) track[i].tick (seconds);
555}
556
557/**
558   \brief removes level data from memory
559*/
560void World::unload()
561{
562  if( pathnodes) delete []pathnodes;
563  if( track) delete []pathnodes;
564}
565
566
567
568/**
569   \brief calls the correct mapping function to convert a given "look at"-Location to a
570   Camera Placement
571*/
572void World::calcCameraPos (Location* loc, Placement* plc)
573{
574  track[loc->part].mapCamera (loc, plc);
575}
576
577
578void World::setTrackLen(Uint32 len)
579{
580  this->tracklen = len;
581}
582
583int World::getTrackLen()
584{
585  return this->tracklen;
586}
587
588
589
590/**
591   \brief function to put your own debug stuff into it. it can display informations about
592   the current class/procedure
593*/
594void World::debug()
595{
596  printf ("World::debug() - starting debug\n");
597  PNode* p1 = new NullParent ();
598  PNode* p2 = new PNode (new Vector(2, 2, 2), p1);
599  PNode* p3 = new PNode (new Vector(4, 4, 4), p1);
600  PNode* p4 = new PNode (new Vector(6, 6, 6), p2);
601
602  p1->debug ();
603  p2->debug ();
604  p3->debug ();
605  p4->debug ();
606
607  p1->shiftCoor (new Vector(-1, -1, -1));
608
609  printf("World::debug() - shift\n");
610  p1->debug ();
611  p2->debug ();
612  p3->debug ();
613  p4->debug ();
614 
615  p1->update (1);
616
617  printf ("World::debug() - update\n");
618  p1->debug ();
619  p2->debug ();
620  p3->debug ();
621  p4->debug ();
622
623  p2->shiftCoor (new Vector(-1, -1, -1));
624  p1->update (2);
625
626  p1->debug ();
627  p2->debug ();
628  p3->debug ();
629  p4->debug ();
630
631  p2->setAbsCoor (new Vector(1,2,3));
632
633
634 p1->update (2);
635
636  p1->debug ();
637  p2->debug ();
638  p3->debug ();
639  p4->debug ();
640
641  p1->destroy ();
642 
643 
644  /*
645  WorldEntity* entity;
646  printf("counting all entities\n");
647  printf("World::debug() - enumerate()\n");
648  entity = entities->enumerate(); 
649  while( entity != NULL )
650    {
651      if( entity->bDraw ) printf("got an entity\n");
652      entity = entities->nextElement();
653    }
654  */
655}
656
657
658/*
659  \brief main loop of the world: executing all world relevant function
660
661  in this loop we synchronize (if networked), handle input events, give the heart-beat to
662  all other member-entities of the world (tick to player, enemies etc.), checking for
663  collisions drawing everything to the screen.
664*/
665void World::mainLoop()
666{
667  this->lastFrame = SDL_GetTicks ();
668  printf("World::mainLoop() - Entering main loop\n");
669  while( !this->bQuitOrxonox && !this->bQuitCurrentGame) /* \todo implement pause */
670    {
671      // Network
672      this->synchronize ();
673      // Process input
674      this->handleInput ();
675      if( this->bQuitCurrentGame || this->bQuitOrxonox)
676        {
677          printf("World::mainLoop() - leaving loop earlier...\n");
678          break;
679        }
680      // Process time
681      this->timeSlice ();
682      // Process collision
683      this->collision ();
684      // Draw
685      this->display ();
686 
687      for( int i = 0; i < 10000000; i++) {}
688    }
689  printf("World::mainLoop() - Exiting the main loop\n");
690}
691
692/**
693   \brief synchronize local data with remote data
694*/
695void World::synchronize ()
696{
697  // Get remote input
698  // Update synchronizables
699}
700
701/**
702   \brief run all input processing
703
704   the command node is the central input event dispatcher. the node uses the even-queue from
705   sdl and has its own event-passing-queue.
706*/
707void World::handleInput ()
708{
709  // localinput
710  CommandNode* cn = Orxonox::getInstance()->getLocalInput();
711  cn->process();
712  // remoteinput
713}
714
715/**
716   \brief advance the timeline
717
718   this calculates the time used to process one frame (with all input handling, drawing, etc)
719   the time is mesured in ms and passed to all world-entities and other classes that need
720   a heart-beat.
721*/
722void World::timeSlice ()
723{
724  Uint32 currentFrame = SDL_GetTicks();
725  if(!this->bPause)
726    {
727      Uint32 dt = currentFrame - this->lastFrame;
728     
729      if(dt > 0)
730        {
731          float fps = 1000/dt;
732          printf("fps = %f\n", fps);
733        }
734      else
735        {
736          /* the frame-rate is limited to 100 frames per second, all other things are for
737             nothing.
738          */
739          printf("fps = 1000 - frame rate is adjusted\n");
740          SDL_Delay(10);
741          dt = 10;
742        }
743      this->timeSlice (dt);
744      this->update ();
745      this->localCamera->timeSlice(dt);
746    }
747  this->lastFrame = currentFrame;
748}
749
750
751/**
752   \brief compute collision detection
753*/
754void World::collision ()
755{
756  this->collide ();
757}
758
759
760/**
761   \brief render the current frame
762   
763   clear all buffers and draw the world
764*/
765void World::display ()
766{
767  // clear buffer
768  glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
769  // set camera
770  this->localCamera->apply ();
771  // draw world
772  this->draw();
773  // draw HUD
774  // flip buffers
775  SDL_GL_SwapBuffers();
776}
777
778/**
779   \brief give back active camera
780   
781   this passes back the actualy active camera
782   \todo ability to define more than one camera or camera-places
783*/
784Camera* World::getCamera()
785{
786  return this->localCamera;
787}
788
789
790/**
791   \brief add and spawn a new entity to this world
792   \param entity to be added
793*/
794void World::spawn(WorldEntity* entity)
795{
796  if( this->nullParent != NULL && entity->parent == NULL)
797    this->nullParent->addChild (entity);
798
799  this->entities->add (entity);
800
801  entity->postSpawn ();
802}
803
804
805/**
806   \brief add and spawn a new entity to this world
807   \param entity to be added
808   \param location where to add
809*/
810void World::spawn(WorldEntity* entity, Vector* absCoor, Quaternion* absDir)
811{
812  entity->setAbsCoor (absCoor);
813  entity->setAbsDir (absDir);
814 
815  if( this->nullParent != NULL && entity->parent == NULL)
816    this->nullParent->addChild (entity);
817
818  this->entities->add (entity);
819
820  entity->postSpawn ();
821}
822
823
824
825/*
826  \brief commands that the world must catch
827  \returns false if not used by the world
828*/
829bool World::command(Command* cmd)
830{
831  return false;
832}
833
Note: See TracBrowser for help on using the repository browser.