#include "ExampleApplication.h" #include #include using std::runtime_error; // ExampleApplication.h has done a "using namespace ogre" // This class simply gives us a torch attached to our camera. class MyExampleFrameListener : public ExampleFrameListener { protected: SceneNode *mCameraNode; public: MyExampleFrameListener( RenderWindow* win, Camera* cam, SceneNode *camnode ) : ExampleFrameListener( win, cam ) { mCameraNode = camnode; } // Overidden to move scene node rather than the camera itself. void moveCamera() { // Make all the changes to the camera // Note that YAW direction is around a fixed axis (freelook style) rather than a natural YAW //(e.g. airplane) mCameraNode->yaw(mRotX, Node::TS_WORLD); mCameraNode->pitch(mRotY); mCameraNode->translate(mTranslateVector, Node::TS_LOCAL); } }; // Lua bound functions must be static, however to call methods on the application object you need // a pointer or reference to it. Options to this would be a singleton, or passing a // pointer to Lua code which then can be passed back. Here I do a very simple version of a // singleton. // Despite being static, it does not stop us making the bound functions methods of the application // and able to access the protected member "g_application" (which is also static). // Static methods, can only access static members, unless you have a pointer to an object, a replacement // for "this" basically. This is exactly what g_application is. class LuaSceneApp : public ExampleApplication { protected: lua_State *L; SceneNode *mCameraNode; static LuaSceneApp *g_application; public: static int CreateSceneObject( lua_State * ); LuaSceneApp(); ~LuaSceneApp() { lua_close( L ); } protected: void createScene(void) { mSceneMgr->setAmbientLight( ColourValue( .1, .1, .1 ) ); loadScene( "/home/nigel/Blender/meshes.lua" ); Light* pLight = mSceneMgr->createLight("CameraLight"); pLight->setPosition(0.0f, 0.0f, 0.0f); pLight->setDiffuseColour( ColourValue( 0.6f, 0.6f, 0.6f ) ); mCameraNode->createChildSceneNode( "CameraLightNode" )->attachObject( pLight ); } void createCamera() { // Create the camera mCamera = mSceneMgr->createCamera("PlayerCam"); mCameraNode = mSceneMgr->getRootSceneNode()->createChildSceneNode( "CameraNode" ); mCameraNode->attachObject( mCamera ); mCameraNode->setPosition(Vector3(0,0,200)); // Look back along -Z mCamera->lookAt(Vector3(0,0,100)); mCamera->setNearClipDistance(1); } void createFrameListener(void) { mFrameListener= new MyExampleFrameListener(mWindow, mCamera, mCameraNode); mFrameListener->showDebugOverlay(true); mRoot->addFrameListener(mFrameListener); } void runScript( const char *filename ) { if(luaL_loadfile( L, filename ) || lua_pcall( L, 0, 0, 0 )) { const char *errorstr = lua_tostring( L, -1 ); lua_pop( L, 1 ); // The lua GC will not be run before the // exception constructor, so the string // will still be there. throw runtime_error( errorstr ); } return; } void runScriptStr( const char *source ) { if(luaL_loadstring( L, source ) || lua_pcall( L, 0, 0, 0 )) { const char *errorstr = lua_tostring( L, -1 ); lua_pop( L, 1 ); // The lua GC will not be run before the // exception constructor, so the string // will still be there. throw runtime_error( errorstr ); } return; } void loadScene( const char *filename ) { runScript( filename ); const char *loader = "print 'Loading scene...'\n"; runScriptStr( loader ); runScript( "loader.lua" ); } }; // List of functions we are exposing to Lua static const luaL_Reg luaAPI[] = { { "CreateSceneObject", LuaSceneApp::CreateSceneObject }, { NULL, NULL }, }; LuaSceneApp* LuaSceneApp::g_application = NULL; // Here in the application start up, we crank up Lua, and register // any functions we want bound. Opening the Lua libraries is not // strictly necessary. Do you trust where the Lua scriptes came from? LuaSceneApp::LuaSceneApp() { assert( !g_application ); g_application = this; L = lua_open(); luaL_register( L, "Ogre", luaAPI ); luaL_openlibs( L ); } Vector3 lua_toVector3( lua_State *L, int index ) { // table at 'index' with 3 numbers, at index'es 1,2,and 3, are x,y and zed Vector3 vec; lua_pushnumber( L, 1 ); lua_gettable( L, index ); vec.x = lua_tonumber( L, -1 ); lua_pop( L, 1 ); lua_pushnumber( L, 2 ); lua_gettable( L, index ); vec.y = lua_tonumber( L, -1 ); lua_pop( L, 1 ); lua_pushnumber( L, 3 ); lua_gettable( L, index ); vec.z = lua_tonumber( L, -1 ); lua_pop( L, 1 ); return vec; } Quaternion lua_toQuaternion( lua_State *L, int index ) { // table at 'index' with 4 numbers, at index'es 1, 2, 3 and 4, // are w, x, y and zed float w, x, y, z; lua_pushnumber( L, 1 ); lua_gettable( L, index ); w = lua_tonumber( L, -1 ); lua_pop( L, 1 ); lua_pushnumber( L, 2 ); lua_gettable( L, index ); x = lua_tonumber( L, -1 ); lua_pop( L, 1 ); lua_pushnumber( L, 3 ); lua_gettable( L, index ); y = lua_tonumber( L, -1 ); lua_pop( L, 1 ); lua_pushnumber( L, 4 ); lua_gettable( L, index ); z = lua_tonumber( L, -1 ); lua_pop( L, 1 ); return Quaternion( w, x, y, z ); } int LuaSceneApp::CreateSceneObject( lua_State *L ) { assert( g_application ); // Params, name, filename, location, rotation // location and scale are tables with 3 numbers. // Rotation is the same but with 4. const char *name; const char *filename; name = luaL_checkstring( L, 1 ); filename = luaL_checkstring( L, 2 ); LogManager::getSingleton().stream() << name << " " << filename; luaL_checktype( L, 3, LUA_TTABLE ); Vector3 location = lua_toVector3( L, 3); luaL_checktype( L, 4, LUA_TTABLE ); Quaternion rotation = lua_toQuaternion( L, 4); luaL_checktype( L, 5, LUA_TTABLE ); Vector3 scale = lua_toVector3( L, 5); LogManager::getSingleton().stream() << "Loc: " << location << " Rot: " << rotation << " Scale: " << scale; Entity *entity = g_application->mSceneMgr->createEntity( name, filename ); SceneNode *node = g_application->mSceneMgr->getRootSceneNode()->createChildSceneNode( name ); node->attachObject( entity ); node->setPosition( location ); node->setOrientation( rotation ); node->setScale( scale ); lua_pop( L, 4 ); return 0; } #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 #define WIN32_LEAN_AND_MEAN #include "windows.h" INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT ) #else int main(int argc, char **argv) #endif { LuaSceneApp app; try { app.go(); } catch( std::exception& e ) // This catches "Ogre::Exception" too. { #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 MessageBox( NULL, e.what(), "An exception has occurred!", MB_OK | MB_ICONERROR | MB_TASKMODAL); #else fprintf(stderr, "An exception has occurred: %s\n", e.what()); #endif } return 0; }