#include "cssysdef.h" #include "csutil/sysfunc.h" #include "iutil/vfs.h" #include "csutil/cscolor.h" #include "cstool/csview.h" #include "cstool/initapp.h" #include "simple.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/texture.h" #include "iengine/mesh.h" #include "iengine/movable.h" #include "iengine/material.h" #include "imesh/thing.h" #include "imesh/object.h" #include "ivideo/graph3d.h" #include "ivideo/graph2d.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/event.h" CS_IMPLEMENT_APPLICATION // The global pointer to simple Simple* simple = 0; Simple::Simple (iObjectRegistry* object_reg) { Simple::object_reg = object_reg; } Simple::~Simple () { } bool Simple::Initialize () { if (!csInitializer::RequestPlugins (object_reg, CS_REQUEST_VFS, CS_REQUEST_OPENGL3D, CS_REQUEST_ENGINE, CS_REQUEST_FONTSERVER, CS_REQUEST_IMAGELOADER, CS_REQUEST_LEVELLOADER, CS_REQUEST_REPORTER, CS_REQUEST_REPORTERLISTENER, CS_REQUEST_END)) { csReport (object_reg, CS_REPORTER_SEVERITY_ERROR, "crystalspace.application.simple", "Can't initialize plugins!"); return false; } if (!csInitializer::SetupEventHandler( object_reg, EvHandler )) { csReport( object_reg, CS_REPORTER_SEVERITY_ERROR, "crystalspace.application.simple", "Cannot initialize event handler" ); return false; } // Check for commandline help. if (csCommandLineHelper::CheckHelp (object_reg)) { csCommandLineHelper::Help (object_reg); return false; } // The virtual clock. vc = CS_QUERY_REGISTRY (object_reg, iVirtualClock); if (!vc) { csReport (object_reg, CS_REPORTER_SEVERITY_ERROR, "crystalspace.application.simple", "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.simple", "No iEngine plugin!"); return false; } loader = CS_QUERY_REGISTRY (object_reg, iLoader); if (!loader) { csReport (object_reg, CS_REPORTER_SEVERITY_ERROR, "crystalspace.application.simple", "No iLoader plugin!"); return false; } g3d = CS_QUERY_REGISTRY (object_reg, iGraphics3D); if (!g3d) { csReport (object_reg, CS_REPORTER_SEVERITY_ERROR, "crystalspace.application.simple", "No iGraphics3D plugin!"); return false; } kbd = CS_QUERY_REGISTRY (object_reg, iKeyboardDriver); if (!kbd) { csReport (object_reg, CS_REPORTER_SEVERITY_ERROR, "crystalspace.application.simple", "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.simple", "Error opening system!"); return false; } csReport (object_reg, CS_REPORTER_SEVERITY_NOTIFY, "crystalspace.application.simple", "Simple Crystal Space Application version 0.1."); engine->SetLightingCacheMode( 0 ); if ( !loader->LoadTexture( "stone", "/lib/std/stone4.gif") ) { csReport (object_reg, CS_REPORTER_SEVERITY_ERROR, "crystalspace.application.simple", "Error loading 'stone4' texture!"); return false; } iMaterialWrapper* tm = engine->GetMaterialList()->FindByName( "stone" ); rotY = rotX = 0; room = engine->CreateSector( "room" ); csRef walls( engine->CreateSectorWallsMesh( room, "walls" ) ); csRef ts( SCF_QUERY_INTERFACE( walls->GetMeshObject(), iThingState) ); iThingFactoryState* ws = ts->GetFactory(); ws->AddInsideBox( csVector3(-5, 0 -5), csVector3(5,20,5) ); ws->SetPolygonMaterial (CS_POLYRANGE_LAST, tm); ws->SetPolygonTextureMapping (CS_POLYRANGE_LAST, 3); csRef light; iLightList* ll = room->GetLights(); light = engine->CreateLight (0, csVector3(-3, 5, 0), 10, csColor(1, 0, 0)); ll->Add(light); light = engine->CreateLight (0, csVector3(3, 5, 0), 10, csColor(0, 0, 1)); ll->Add(light); light = engine->CreateLight (0, csVector3(0, 5, -3), 10, csColor(0, 1, 0)); ll->Add(light); engine->Prepare (); view = csPtr( new csView(engine, g3d) ); view->GetCamera()->SetSector(room); view->GetCamera()->GetTransform().SetOrigin( csVector3(0, 5, -3) ); iGraphics2D* g2d = g3d->GetDriver2D(); view->SetRectangle( 0, 0, g2d->GetWidth(), g2d->GetHeight() ); return true; } void Simple::Start () { csDefaultRunLoop (object_reg); } void Simple::SetupFrame() { csTicks lasped = vc->GetElapsedTicks(); float speed = lasped/1000.0 * 0.03*20; iCamera* c = view->GetCamera(); if (kbd->GetKeyState (CSKEY_SHIFT)) { // If the user is holding down shift, the arrow keys will cause // the camera to strafe up, down, left or right from it's // current position. if (kbd->GetKeyState (CSKEY_RIGHT)) c->Move (CS_VEC_RIGHT * 4 * speed); if (kbd->GetKeyState (CSKEY_LEFT)) c->Move (CS_VEC_LEFT * 4 * speed); if (kbd->GetKeyState (CSKEY_UP)) c->Move (CS_VEC_UP * 4 * speed); if (kbd->GetKeyState (CSKEY_DOWN)) c->Move (CS_VEC_DOWN * 4 * speed); } else { // left and right cause the camera to rotate on the global Y // axis; page up and page down cause the camera to rotate on the // _camera's_ X axis (more on this in a second) and up and down // arrows cause the camera to go forwards and backwards. if (kbd->GetKeyState (CSKEY_RIGHT)) rotY += speed; if (kbd->GetKeyState (CSKEY_LEFT)) rotY -= speed; if (kbd->GetKeyState (CSKEY_PGUP)) rotX += speed; if (kbd->GetKeyState (CSKEY_PGDN)) rotX -= speed; if (kbd->GetKeyState (CSKEY_UP)) c->Move (CS_VEC_FORWARD * 4 * speed); if (kbd->GetKeyState (CSKEY_DOWN)) c->Move (CS_VEC_BACKWARD * 4 * speed); } // We now assign a new rotation transformation to the camera. You // can think of the rotation this way: starting from the zero // position, you first rotate "rotY" radians on your Y axis to get // the first rotation. From there you rotate "rotX" radians on the // your X axis to get the final rotation. We multiply the // individual rotations on each axis together to get a single // rotation matrix. The rotations are applied in right to left // order . csMatrix3 rot = csXRotMatrix3 (rotX) * csYRotMatrix3 (rotY); csOrthoTransform ot (rot, c->GetTransform().GetOrigin ()); c->SetTransform (ot); 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(0); } bool Simple::EvHandler( iEvent& ev ) { return simple ? simple->HandleEv( ev ) : false; } bool Simple::HandleEv( iEvent& ev ) { if (ev.Type == csevBroadcast && ev.Command.Code == cscmdProcess) { SetupFrame(); return true; } else if (ev.Type == csevBroadcast && ev.Command.Code == cscmdFinalProcess) { FinishFrame(); return true; } else if ( ev.Type == csevKeyboard && csKeyEventHelper::GetEventType( &ev ) == csKeyEventTypeDown && csKeyEventHelper::GetCookedCode( &ev ) == CSKEY_ESC ) { csRef q( CS_QUERY_REGISTRY(object_reg, iEventQueue) ); if (q) q->GetEventOutlet()->Broadcast( cscmdQuit ); return true; } return false; } /*---------------* * Main function *---------------*/ int main (int argc, char* argv[]) { iObjectRegistry* object_reg = csInitializer::CreateEnvironment (argc, argv); if (!object_reg) return -1; simple = new Simple (object_reg); if (simple->Initialize ()) simple->Start (); delete simple; simple = 0; csInitializer::DestroyApplication (object_reg); return 0; }