Site hosted by Angelfire.com: Build your free website today!


sample.cpp
Links

Crystal Space

Crystal Space Tutorial Site

QuArK

polycount

Sample Code

mysimple.h
mysimple.cpp
mysimple.zip

/*
    Copyright (C) 2001 by M. Kohel
    modified by Andreas Busch to work with the current
    CVS-Version of CrystalSpace V0.95
*/

#include "cssysdef.h"
#include "cssys/sysfunc.h"
#include "iutil/vfs.h"
#include "csutil/cscolor.h"
#include "cstool/csview.h"
#include "cstool/initapp.h"
#include "./../include/mysimple.h"
#include "iutil/eventq.h"
#include "iutil/event.h"
#include "iutil/objreg.h"
#include "iutil/csinput.h"
#include "iutil/virtclk.h"
#include "iengine/sector.h"
#include "iengine/engine.h"
#include "iengine/camera.h"
#include "iengine/light.h"
#include "iengine/statlght.h"
#include "iengine/texture.h"
#include "iengine/mesh.h"
#include "iengine/movable.h"
#include "iengine/material.h"
#include "iengine/campos.h"
#include "imesh/thing/polygon.h"
#include "imesh/thing/thing.h"
#include "imesh/sprite3d.h"
#include "imesh/object.h"
#include "ivideo/graph3d.h"
#include "ivideo/graph2d.h"
#include "ivideo/txtmgr.h"
#include "ivideo/texture.h"
#include "ivideo/material.h"
#include "ivideo/fontserv.h"
#include "igraphic/imageio.h"
#include "imap/parser.h"
#include "ivaria/reporter.h"
#include "ivaria/stdrep.h"
#include "csutil/cmdhelp.h"
#include "csutil/debug.h"

//includes needed for collision detection
#include "ivaria/collider.h"
#include "igeom/polymesh.h"

#include "cstool/collider.h"

#include "igeom/objmodel.h"

CS_IMPLEMENT_APPLICATION

//-----------------------------------------------------------------------------

// The global pointer to simple
Simple *simple;

Simple::Simple ()
{
  engine        = NULL;
  loader        = NULL;
  g3d           = NULL;
  kbd           = NULL;
  vc            = NULL;
  view          = NULL;
  cdsys         = NULL;
  sprite1       = NULL;
  sprite2       = NULL;
  sprite3       = NULL;
  npc_collide1  = NULL;
  npc_collide2  = NULL;
  npc_collide3  = NULL;
  mesh_collider = NULL;
  forward       = true;
}
/*************************************************************
**
**
*************************************************************/
Simple::~Simple ()
{
}

/*************************************************************
**
**
*************************************************************/

void Simple::SetupFrame ()
{

  static csVector3 old_pos;
  static csVector3 real_old_pos;
  static long frame_number = 0;

  frame_number++;

  // First get elapsed time from the virtual clock.
  csTicks elapsed_time = vc->GetElapsedTicks ();

  // Now rotate the camera according to keyboard state
  float speed = (elapsed_time / 1000.0) * (0.03 * 20);


  // Move the mesh with the keys as avitar
  iMovable* movable2 = sprite2->GetMovable();
  movable2->SetSector( room );

  iCamera* c = view->GetCamera();

  if (kbd->GetKeyState (CSKEY_RIGHT))
  {
      movable2->GetTransform ().RotateThis (CS_VEC_ROT_RIGHT, 3 * speed);
      c->SetTransform(movable2->GetTransform() );
      c->Move (  csVector3( -2,1,0 ));
      c->GetTransform ().RotateThis (CS_VEC_ROT_LEFT, 80);
      movable2->UpdateMove();
  }

  if (kbd->GetKeyState (CSKEY_LEFT))
  {
      movable2->GetTransform ().RotateThis (CS_VEC_ROT_LEFT, 3 * speed);
      c->SetTransform(movable2->GetTransform() );
      c->Move (  csVector3( -2,1,0 ));
      c->GetTransform ().RotateThis (CS_VEC_ROT_LEFT, 80);
      movable2->UpdateMove();
  }

  if (kbd->GetKeyState (CSKEY_UP))
  {

      csVector3 new_pos = movable2->GetTransform ().This2Other(
                                                  csVector3(1,0,0) * 6 * speed);
      movable2->SetPosition ( new_pos );
      c->SetTransform(movable2->GetTransform() );
      c->Move (  csVector3( -2,1,0 ));
      c->GetTransform ().RotateThis (CS_VEC_ROT_LEFT, 80);
      movable2->UpdateMove();
  }

  if (kbd->GetKeyState (CSKEY_DOWN))
  {
      csVector3 new_pos = movable2->GetTransform ().This2Other(
                                                 csVector3(-1,0,0) * 6 * speed);
      movable2->SetPosition ( new_pos );
      c->SetTransform(movable2->GetTransform() );
      c->Move (  csVector3( -2,1,0 ));
      c->GetTransform ().RotateThis (CS_VEC_ROT_LEFT, 80);
      movable2->UpdateMove();
  }

  if (kbd->GetKeyState (119))
       c->Move (CS_VEC_FORWARD * 4 * speed);

  if (kbd->GetKeyState (115))
       c->Move (CS_VEC_BACKWARD * 4 * speed);

  if (kbd->GetKeyState (97))
       c->GetTransform ().RotateThis (CS_VEC_ROT_LEFT, speed);

  if (kbd->GetKeyState (100))
       c->GetTransform ().RotateThis (CS_VEC_ROT_RIGHT, speed);

  if (kbd->GetKeyState (CSKEY_PGUP))
      c->GetTransform ().RotateThis (CS_VEC_TILT_UP, speed);

  if (kbd->GetKeyState (CSKEY_PGDN))
      c->GetTransform ().RotateThis (CS_VEC_TILT_DOWN, speed);

  // Move the mesh as NPC
  iMovable* movable = sprite1->GetMovable();
  movable->SetSector( room );

  csVector3 npc_current_pos = movable->GetPosition();
  csVector3 current_pos = movable2->GetPosition();
  if( forward )
  {
      movable->SetPosition( npc_current_pos + csVector3( 3 * speed, 0, 0 ) );
  }
  else
  {
      movable->SetPosition( npc_current_pos + csVector3( -3 * speed, 0, 0 ) );
  }
  movable->UpdateMove();

  // Check for collision
  cdsys->ResetCollisionPairs ();
  csReversibleTransform ft1 = sprite1->GetMovable ()->GetFullTransform ();
  csReversibleTransform ft2 = sprite2->GetMovable ()->GetFullTransform ();

  //Begin CD code from walk test
  int i=0;
  int num_meshes = mesh_list->GetCount();

  bool cd1 = false;
  bool cd2 = false;

  for (i=0; i< num_meshes; i++ )
  {
      // JORRIT: if cd1 and cd2 are both true we can already stop the loop.
      if (cd1 && cd2) break;

      // JORRIT: get collider corresponding with this mesh.
      mesh_in_sector = mesh_list->Get(i);
      csColliderWrapper* cd_wrap = csColliderWrapper::GetColliderWrapper (mesh_in_sector->QueryObject ());
      if (!cd_wrap) continue;
      mesh_collider = cd_wrap->GetCollider ();
      // JORRIT: if mesh_collider is NULL we skip this iteration.
      if (!mesh_collider) continue;

      csReversibleTransform mesh_transform = mesh_in_sector->GetMovable ()->GetFullTransform ();

      // NPC mesh  - only check for first collisions
      // also make sure the mesh from the list is not the same sprite we are
      // checking collisions for
      if( ( cd1 == false ) && ( mesh_collider != npc_collide1 ) )
      {
	  // JORRIT: VERY WEIRD. THE OBJECTS HAVE TO BE REVERSED.
          cd1 = cdsys->Collide ( npc_collide1, &ft1, mesh_collider, &mesh_transform);

          // if after checking for a collision we found one print a debug
          // message stating what mesh we collided with
          if( cd1 )
          {
              printf("object 1 collided with: %s \n\n",
                      mesh_in_sector->QueryObject()->GetName() );
          }
      }

      // avitar mesh  - only check for first collisions
      // also make sure the mesh from the list is not the same sprite we are
      // checking collisions for
      if( ( cd2 == false ) && ( mesh_collider != npc_collide2 ) )
      {
	  // JORRIT: VERY WEIRD. THE OBJECTS HAVE TO BE REVERSED.
          cd2 = cdsys->Collide ( npc_collide2, &ft2, mesh_collider, &mesh_transform);

          // if after checking for a collision we found one print a debug
          // message stating what mesh we collided with
          if( cd2 )
          {
              printf("object 2 collided with: %s\n\n",
                      mesh_in_sector->QueryObject()->GetName() );
          }
      }

  }


  /* end code from walktest
  */

  // check for npc collisions, if collide reverse direction
  if ( cd1 )
  {
      if( forward )
      {
          forward = false;
	  movable->SetPosition( npc_current_pos + csVector3( 0, 0, -.5 ) );
	  movable->GetTransform ().LookAt ( csVector3( 0, -1.5, -100 ),
	                                    csVector3 (0, 1, 0));
      }
      else
      {
          forward = true;
	  movable->SetPosition( npc_current_pos + csVector3( 0, 0, .5 ) );
	  movable->GetTransform ().LookAt ( csVector3( 0, -1.5, 100 ),
	                                    csVector3 (0, 1, 0));
      }
      movable->UpdateMove();
  }

  // check for camera mesh collide, if collide set position back to position
  // before collide

  if( cd2 )
  {
      movable2->SetPosition( real_old_pos );
      movable2->UpdateMove();
  }
  else
  {
      // JORRIT: the below two lines are suspicious. Shouldn't
      // they be swapped? With the lines below old_pos
      // and real_old_pos will get the same value and I'm not
      // sure that is right.
      old_pos = current_pos;
      real_old_pos = old_pos;
  }

  // Tell 3D driver we're going to display 3D things.
  if (!g3d->BeginDraw (engine->GetBeginDrawFlags () | CSDRAW_3DGRAPHICS))
    return;

  // Tell the camera to render into the frame buffer.
  view->Draw ();
}
/*************************************************************
**
**
*************************************************************/

void Simple::FinishFrame ()
{
  g3d->FinishDraw ();
  g3d->Print (NULL);
}
/*************************************************************
**
**
*************************************************************/
bool Simple::HandleEvent (iEvent& ev)
{
  if (ev.Type == csevBroadcast && ev.Command.Code == cscmdProcess)
  {
    simple->SetupFrame ();
    return true;
  }
  else if (ev.Type == csevBroadcast && ev.Command.Code == cscmdFinalProcess)
  {
    simple->FinishFrame ();
    return true;
  }
  else if (ev.Type == csevKeyDown && ev.Key.Code == CSKEY_ESC)
  {
    csRef q = CS_QUERY_REGISTRY (object_reg, iEventQueue);
    if (q)
    {
      q->GetEventOutlet()->Broadcast (cscmdQuit);
    }
    return true;
  }
  else if (ev.Type == csevKeyDown && ev.Key.Code == 'l')
  {
    csDebuggingGraph::Dump (NULL);
    engine->DeleteAll ();
    csDebuggingGraph::Dump (NULL);
    csDebuggingGraph::Clear (NULL);
    LoadMap ();
    return true;
  }

  return false;
}
/*************************************************************
**
**
*************************************************************/

bool Simple::SimpleEventHandler (iEvent& ev)
{
  return simple->HandleEvent (ev);
}
/*************************************************************
**
**
*************************************************************/

iCollider* Simple::InitCollider (csRef mesh)
{
  csRef polmesh = SCF_QUERY_INTERFACE ( mesh->GetMeshObject (),
                                                iPolygonMesh);
  if (polmesh)
  {
    csColliderWrapper* wrap = new csColliderWrapper
        (mesh->QueryObject (), cdsys, polmesh);
    wrap->DecRef ();
    return wrap->GetCollider ();
  }
  else
  {
    csReport (object_reg, CS_REPORTER_SEVERITY_ERROR,
        "crystalspace.application.mysimple",
        "Object doesn't support collision detection!");
    return NULL;
  }
}
/*************************************************************
**
**
*************************************************************/

bool Simple::LoadMap ()
{
  // Set VFS current directory to the level we want to load.
  csRef VFS = CS_QUERY_REGISTRY (object_reg, iVFS);
  VFS->Mount ("/lev/mysimple", "$.$/mysimple.zip");
  VFS->ChDir ("/lev/mysimple");

  // Load the level file which is called 'world'.
  if (!loader->LoadMapFile ("world"))
  {
    csReport (object_reg, CS_REPORTER_SEVERITY_ERROR,
    	"crystalspace.application.mysimple",
    	"Couldn't load level!");
    return false;
  }

  // Find the starting position in this level.
  csVector3 pos (0, 0, 0);
  if (engine->GetCameraPositions ()->GetCount () > 0)
  {
    printf("found sector\n");
    // There is a valid starting position defined in the level file.
    iCameraPosition* campos = engine->GetCameraPositions ()->Get (0);
    room = engine->GetSectors ()->FindByName (campos->GetSector ());
    pos = campos->GetPosition ();
  }
  else
  {
    printf("defaulted sector\n");
    // We didn't find a valid starting position. So we default
    // to going to room called 'room' at position (0,0,0).
    room = engine->GetSectors ()->FindByName ("room");
  }

  if(!room)
  {
    csReport (object_reg, CS_REPORTER_SEVERITY_ERROR,
    	"crystalspace.application.mysimple",
      	"Can't find a valid starting position!");
    return false;
  }

  view->GetCamera ()->SetSector (room);
  view->GetCamera ()->GetTransform ().SetOrigin (pos);

  return true;
}
/*************************************************************
**
**
*************************************************************/
bool Simple::Initialize (iObjectRegistry* object_reg)
{
  Simple::object_reg = object_reg;
  csDebuggingGraph::SetupGraph (object_reg);

  if (!csInitializer::RequestPlugins (object_reg,
  	CS_REQUEST_VFS,
	CS_REQUEST_SOFTWARE3D,
	CS_REQUEST_ENGINE,
	CS_REQUEST_FONTSERVER,
	CS_REQUEST_IMAGELOADER,
	CS_REQUEST_LEVELLOADER,
	CS_REQUEST_REPORTER,
	CS_REQUEST_REPORTERLISTENER,
        CS_REQUEST_PLUGIN("crystalspace.collisiondetection.rapid",
	                  iCollideSystem),
	CS_REQUEST_END))
  {
    csReport (object_reg, CS_REPORTER_SEVERITY_ERROR,
    	"crystalspace.application.mysimple",
	"Can't initialize plugins!");
    return false;
  }

  if (!csInitializer::SetupEventHandler (object_reg, SimpleEventHandler))
  {
    csReport (object_reg, CS_REPORTER_SEVERITY_ERROR,
    	"crystalspace.application.mysimple",
	"Can't initialize event handler!");
    return false;
  }

  // Check for commandline help.
  if (csCommandLineHelper::CheckHelp (object_reg))
  {
    csCommandLineHelper::Help (object_reg);
    return false;
  }

  // The collision detection system.
  cdsys = CS_QUERY_REGISTRY (object_reg, iCollideSystem);

  if (!cdsys)
  {
      csReport (object_reg, CS_REPORTER_SEVERITY_ERROR,
	        "crystalspace.application.mysimple",
	        "Can't find the collision detection system!");

      return false;
  }

  // The virtual clock.
  vc = CS_QUERY_REGISTRY (object_reg, iVirtualClock);
  if (!vc)
  {
    csReport (object_reg, CS_REPORTER_SEVERITY_ERROR,
    	"crystalspace.application.mysimple",
	"Can't find the virtual clock!");
    return false;
  }

  // Find the pointer to engine plugin
  engine = CS_QUERY_REGISTRY (object_reg, iEngine);
  if (!engine)
  {
    csReport (object_reg, CS_REPORTER_SEVERITY_ERROR,
    	"crystalspace.application.mysimple",
	"No iEngine plugin!");
    return false;
  }

  loader = CS_QUERY_REGISTRY (object_reg, iLoader);
  if (!loader)
  {
    csReport (object_reg, CS_REPORTER_SEVERITY_ERROR,
    	"crystalspace.application.mysimple",
    	"No iLoader plugin!");
    return false;
  }

  g3d = CS_QUERY_REGISTRY (object_reg, iGraphics3D);
  if (!g3d)
  {
    csReport (object_reg, CS_REPORTER_SEVERITY_ERROR,
    	"crystalspace.application.mysimple",
    	"No iGraphics3D plugin!");
    return false;
  }

  kbd = CS_QUERY_REGISTRY (object_reg, iKeyboardDriver);
  if (!kbd)
  {
    csReport (object_reg, CS_REPORTER_SEVERITY_ERROR,
    	"crystalspace.application.mysimple",
    	"No iKeyboardDriver plugin!");
    return false;
  }

  // Open the main system. This will open all the previously loaded plug-ins.
  if (!csInitializer::OpenApplication (object_reg))
  {
    csReport (object_reg, CS_REPORTER_SEVERITY_ERROR,
    	"crystalspace.application.mysimple",
    	"Error opening system!");
    return false;
  }

  view = csPtr (new csView (engine, g3d));
  iGraphics2D* g2d = g3d->GetDriver2D ();
  view->SetRectangle (0, 0, g2d->GetWidth (), g2d->GetHeight ());

  if (!LoadMap ()) return false;

  mesh_list = room->GetMeshes();

  // Load a texture for our sprite.
  csRef txtmgr = g3d->GetTextureManager ();

  iTextureWrapper* txt = loader->LoadTexture ("knightskin",
                                              "/lev/mysimple/evilknight.jpg",
					      CS_TEXTURE_3D, txtmgr, true);

  iTextureWrapper* txt2 = loader->LoadTexture ("knightskin2",
                                              "/lev/mysimple/knight.jpg",
					      CS_TEXTURE_3D, txtmgr, true);

  if ( (txt == NULL) || (txt2 == NULL ) )
  {
       csReport (object_reg, CS_REPORTER_SEVERITY_ERROR,
		 "crystalspace.application.mysimple",
		 "Error loading texture!");

      return false;
  }

  // Make a separate material from the good knight's texture
  iMaterialWrapper* mat = engine->CreateMaterial("goodknight_mat", txt2 );

  // Now prepare the engine with all the defined materials
  engine->Prepare ();

  // Load a sprite template from disk (*loader.spr can wrap binary or other sprite formats)
  csRef imeshfact = loader->LoadMeshObjectFactory (
      "/lev/mysimple/knightloader.spr");

  if( imeshfact == NULL )
  {
      csReport( object_reg, CS_REPORTER_SEVERITY_ERROR,
                "crystalspace.application.mysimple",
		"Error loading knight mesh object factory!");
  }

  // Create the sprite with there predefined textures
  sprite1 = engine->CreateMeshWrapper( imeshfact,
                                      "MySprite1",
  			              room,
				      csVector3( -5, -1.5, 5 ) );

  sprite2 = engine->CreateMeshWrapper( imeshfact,
                                      "MySprite2",
  			              room,
				      csVector3( -.25, -1.5, 0 ) );

  sprite3 = engine->CreateMeshWrapper( imeshfact,
                                      "MySprite3",
  			              room,
				      csVector3( -20, -1.5, 0 ) );

  csMatrix3 m;
  m.Identity ();
  m *= 1.;

  sprite1->GetMovable()->SetTransform(m);

  sprite1->GetMovable()->GetTransform ().LookAt( csVector3( 0, -1.5, 100 ),
                                                 csVector3 (0, 1, 0));
  sprite1->GetMovable()->UpdateMove();

  csRef spstate1 = SCF_QUERY_INTERFACE( sprite1->GetMeshObject(),
                                                 iSprite3DState);

  spstate1->SetAction ("run");

  sprite2->GetMovable()->SetTransform(m);
  sprite2->GetMovable()->UpdateMove();

  csRef spstate2 = SCF_QUERY_INTERFACE( sprite2->GetMeshObject(),
                                                 iSprite3DState);

  // Assign the good knight's material explicitly to sprite1 state
  spstate2->SetMaterialWrapper( mat );

  spstate2->SetAction ("point");

  sprite3->GetMovable()->SetTransform(m);
  sprite3->GetMovable()->UpdateMove();

  csRef spstate3 = SCF_QUERY_INTERFACE( sprite3->GetMeshObject(),
                                                 iSprite3DState);
  spstate3->SetAction ("point");

  npc_collide1 = InitCollider (sprite1);
  if (!npc_collide1) return false;

  npc_collide2 = InitCollider (sprite2);
  if (!npc_collide2) return false;

  npc_collide3 = InitCollider (sprite3);
  if (!npc_collide3) return false;

  // The following two calls are not needed since CS_ZBUF_USE and
  // ObjectRenderPriority are the defaults, but the show how you can
  // do this.
  sprite1->SetZBufMode( CS_ZBUF_USE );
  sprite1->SetRenderPriority( engine->GetObjectRenderPriority() );

  sprite1->DeferUpdateLighting( CS_NLIGHT_STATIC|CS_NLIGHT_DYNAMIC, 10 );
  sprite2->DeferUpdateLighting( CS_NLIGHT_STATIC|CS_NLIGHT_DYNAMIC, 10 );
  sprite3->DeferUpdateLighting( CS_NLIGHT_STATIC|CS_NLIGHT_DYNAMIC, 10 );


  // get all meshes is the sector and create colliders for them
  // the colliders will be stored in csColliderWrapper's.
  mesh_list = room->GetMeshes();

  int i=0;
  int num_meshes = mesh_list->GetCount();

  for (i=0; i < num_meshes; i++ )
  {
      mesh_in_sector = mesh_list->Get(i);

      if( mesh_in_sector->QueryObject()->GetID() !=
          sprite2->QueryObject()->GetID() )
      {

          mesh_collider = InitCollider( mesh_in_sector );
          if (!mesh_collider)
          {
              printf("InitCollider error\n");
          }
      }
   }

  sprite1->DecRef();
  sprite2->DecRef();
  sprite3->DecRef();

   return true;
}
/*************************************************************
**
**
*************************************************************/

void Simple::Start ()
{
  csDefaultRunLoop (object_reg);
}

/*---------------------------------------------------------------------*
 * Main function
 *---------------------------------------------------------------------*/
int main (int argc, char* argv[])
{
  iObjectRegistry* object_reg = csInitializer::CreateEnvironment (argc, argv);
  if (!object_reg) return false;

  simple = new Simple ();

  if (simple->Initialize (object_reg))
    simple->Start ();

  delete simple;

  csInitializer::DestroyApplication (object_reg);

  return 0;
}