Initial import.
Initial import.

file:b/App.cpp (new)
--- /dev/null
+++ b/App.cpp
@@ -1,1 +1,272 @@
-
+#include "App.h"
+
+#include <OgreConfigFile.h>
+#include <OgreCamera.h>
+#include <OgreViewport.h>
+#include <OgreSceneManager.h>
+#include <OgreRenderWindow.h>
+#include <OgreOverlayManager.h>
+#include <OgreFont.h>
+#include <OgreFontManager.h>
+
+#include "DebugMain.h"
+
+App::App()
+  : _root(0),
+    _pluginsCfg(Ogre::StringUtil::BLANK),
+    _resourcesCfg(Ogre::StringUtil::BLANK),
+    _window(0),
+    _smgr(0),
+    _inputManager(0),
+    _mouse(0),
+    _keyboard(0),
+    _debugOverlay(0),
+    _quit(false),
+    _showDebug(false)
+{ }
+
+App::~App()
+{ 
+  Ogre::WindowEventUtilities::removeWindowEventListener(_window,this);
+  windowClosed(_window);
+
+  delete _root;
+
+  // Take down OIS
+  if(_inputManager)
+    {
+      if(_mouse)
+	{
+	  _inputManager->destroyInputObject(_mouse);
+	  _mouse=0;
+	}
+      
+      if(_keyboard)
+	{
+	  _inputManager->destroyInputObject(_keyboard);
+	  _keyboard=0;
+	}
+
+      OIS::InputManager::destroyInputSystem(_inputManager);
+      _inputManager=0;      
+    }
+}
+
+bool App::initialize()
+{
+  _pluginsCfg="plugins.cfg";
+  _root=new Ogre::Root(_pluginsCfg);
+
+  // Configure rendering
+  if(!(_root->restoreConfig() || _root->showConfigDialog()))
+    {
+      return false;
+    }
+
+  _window=_root->initialise(true,"OGRE Render Window");
+
+  Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(5);
+
+  loadResourcesFromConfigFile("resources.cfg");
+
+  Ogre::ResourceGroupManager::getSingleton().initialiseResourceGroup("KKEngine");
+  Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
+
+  /// Setup inputs
+  Ogre::LogManager::getSingletonPtr()->logMessage("**** Initializing OIS ****");
+  OIS::ParamList pl;
+  size_t windowHnd=0;
+  std::ostringstream windowHndStr;
+  _window->getCustomAttribute("WINDOW",&windowHnd);
+  windowHndStr << windowHnd;
+  pl.insert(std::make_pair(std::string("WINDOW"),windowHndStr.str()));
+
+  // Temporary hack to show the mouse cursor
+#ifdef OIS_WIN32_PLATFORM
+  pl.insert(std::make_pair(std::string("w32_mouse"), std::string("DISCL_FOREGROUND" )));
+  pl.insert(std::make_pair(std::string("w32_mouse"), std::string("DISCL_NONEXCLUSIVE")));
+  pl.insert(std::make_pair(std::string("w32_keyboard"), std::string("DISCL_FOREGROUND")));
+  pl.insert(std::make_pair(std::string("w32_keyboard"), std::string("DISCL_NONEXCLUSIVE")));
+#elif defined OIS_LINUX_PLATFORM
+  pl.insert(std::make_pair(std::string("x11_mouse_grab"), std::string("false")));
+  pl.insert(std::make_pair(std::string("x11_mouse_hide"), std::string("false")));
+  pl.insert(std::make_pair(std::string("x11_keyboard_grab"), std::string("false")));
+  pl.insert(std::make_pair(std::string("XAutoRepeatOn"), std::string("true")));
+#endif
+  
+  
+  _inputManager=OIS::InputManager::createInputSystem(pl);
+
+  // Keyboard
+  _keyboard=static_cast<OIS::Keyboard *>(_inputManager->createInputObject(OIS::OISKeyboard,true));
+  _keyboard->setEventCallback(this);
+  // Mouse
+  _mouse=static_cast<OIS::Mouse *>(_inputManager->createInputObject(OIS::OISMouse,true));
+  _mouse->setEventCallback(this);
+
+  windowResized(_window);
+  Ogre::WindowEventUtilities::addWindowEventListener(_window,this);
+  
+  // Setup scene manager
+  _smgr=_root->createSceneManager("DefaultSceneManager");
+
+  _viewport=_window->addViewport(0);
+
+  _debugOverlay=Ogre::OverlayManager::getSingletonPtr()->getByName("Debug");
+      
+  Ogre::FontManager::getSingleton().getByName("DebugFont")->load();
+  _debugHUDs.push_back(new DebugMain(_window));
+
+  return true;
+}
+
+bool App::run()
+{ 
+  if(!initialize())
+    return false;
+  setupScene();
+  // Render loop
+  _root->addFrameListener(this);
+  _root->startRendering();
+
+  return true;
+}
+
+Ogre::SceneManager* App::sceneMngr()
+{ return _smgr; }
+
+Ogre::Viewport* App::viewport()
+{ return _viewport; }
+
+OIS::Mouse* App::mouse()
+{ return _mouse; }
+  
+OIS::Keyboard* App::keyboard()
+{ return _keyboard; }
+
+Ogre::Camera* App::camera()
+{ return _viewport->getCamera(); }
+
+void App::windowResized(Ogre::RenderWindow *rw)
+{
+  unsigned int width, height, depth;
+  int left, top;
+  rw->getMetrics(width,height,depth,left,top);
+  
+  const OIS::MouseState &ms=_mouse->getMouseState();
+  ms.width=width;
+  ms.height=height;
+}
+
+void App::windowClosed(Ogre::RenderWindow *rw)
+{ 
+  if(rw=_window)
+    {
+      if(_inputManager)
+	{
+	  _inputManager->destroyInputObject(_mouse);
+	  _inputManager->destroyInputObject(_keyboard);
+	  
+	  OIS::InputManager::destroyInputSystem(_inputManager);
+	  _inputManager=0;
+	}
+    }
+}
+
+bool App::frameRenderingQueued(const Ogre::FrameEvent &evt)
+{
+  if(_window->isClosed())
+    return false;
+
+  // Capture input events
+  _keyboard->capture();
+  _mouse->capture();
+
+  if(_showDebug)
+    {
+      for(std::deque<DebugHUD*>::iterator iter=_debugHUDs.begin();
+	  iter!=_debugHUDs.end();
+	  iter++)
+	(*iter)->update();
+    }
+  
+  if(_quit) return false;
+
+  return true;
+}
+
+void App::quit()
+{
+  _quit=true;
+}
+
+void App::setupScene()
+{ }
+
+bool App::showDebug()
+{ 
+  return _showDebug;
+}
+
+void App::addDebugHUD(DebugHUD *hud)
+{
+  _debugHUDs.push_back(hud);
+}
+
+void App::loadResourcesFromConfigFile(Ogre::String configFile)
+{
+    // Setup resources
+  Ogre::ConfigFile cf;
+  cf.load(configFile);
+
+  Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();
+  Ogre::String secName, typeName, archName;
+  while(seci.hasMoreElements())
+    {
+      secName=seci.peekNextKey();
+      Ogre::ConfigFile::SettingsMultiMap *settings=seci.getNext();
+      Ogre::ConfigFile::SettingsMultiMap::iterator i;
+      for(i=settings->begin();i!=settings->end();++i)
+	{
+	  typeName=i->first;
+	  archName=i->second;
+	  Ogre::ResourceGroupManager::getSingleton().addResourceLocation(archName,typeName,secName);
+	}
+    }
+
+}
+
+bool App::keyPressed(const OIS::KeyEvent &e)
+{ return true; }
+
+bool App::keyReleased(const OIS::KeyEvent &e)
+{
+  switch(e.key)
+    {
+    case OIS::KC_ESCAPE:
+      quit();
+      return false;
+      break;
+    case OIS::KC_F3:
+      _showDebug=!_showDebug;
+      if(_showDebug)
+	_debugOverlay->show();
+      else
+	_debugOverlay->hide();
+      return false;
+      break;
+    default:
+      break;
+    }
+  return true;
+}
+
+bool App::mouseMoved(const OIS::MouseEvent &e)
+{ return true; }
+
+bool App::mousePressed(const OIS::MouseEvent &e, OIS::MouseButtonID mid)
+{ return true; }
+
+bool App::mouseReleased(const OIS::MouseEvent &e, OIS::MouseButtonID mid)
+{ return true; }
+

file:b/App.h (new)
--- /dev/null
+++ b/App.h
@@ -1,1 +1,75 @@
+#ifndef APP_H_
+#define APP_H_
 
+#include <OgreRoot.h>
+#include <OgreWindowEventUtilities.h>
+#include <OgreOverlayElement.h>
+
+#include <OISEvents.h>
+#include <OISInputManager.h>
+#include <OISKeyboard.h>
+#include <OISMouse.h>
+
+#include <OgreOverlay.h>
+
+#include "DebugHUD.h"
+
+class App : public Ogre::WindowEventListener, public Ogre::FrameListener, public OIS::KeyListener, public OIS::MouseListener
+{
+public:
+  App();
+  ~App();
+
+  bool run();
+  void quit();
+
+protected:
+  Ogre::SceneManager* sceneMngr();
+  Ogre::Viewport* viewport();
+  OIS::Mouse* mouse();
+  OIS::Keyboard* keyboard();
+  Ogre::Camera* camera();
+
+  void windowResized(Ogre::RenderWindow *rw);
+  void windowClosed(Ogre::RenderWindow *rw);
+  bool frameRenderingQueued(const Ogre::FrameEvent &evt);
+  
+  virtual bool initialize();
+  virtual void setupScene();
+
+  void loadResourcesFromConfigFile(Ogre::String configFile);
+
+  void addDebugHUD(DebugHUD *hud);
+  bool showDebug();
+
+  /// OIS Inputs
+  // Keyboard
+  virtual bool keyPressed(const OIS::KeyEvent &e);
+  virtual bool keyReleased(const OIS::KeyEvent &e);
+  // Mouse
+  virtual bool mouseMoved(const OIS::MouseEvent &e);
+  virtual bool mousePressed(const OIS::MouseEvent &e, OIS::MouseButtonID mid);
+  virtual bool mouseReleased(const OIS::MouseEvent &e, OIS::MouseButtonID mid);
+
+private:
+  Ogre::Root *_root;
+  Ogre::String _pluginsCfg;
+  Ogre::String _resourcesCfg;
+  Ogre::RenderWindow *_window;
+  Ogre::SceneManager *_smgr;
+  Ogre::Viewport *_viewport;
+
+  OIS::InputManager *_inputManager;
+  OIS::Mouse *_mouse;
+  OIS::Keyboard *_keyboard;
+
+  Ogre::Overlay *_debugOverlay;
+
+  bool _quit;
+
+  std::deque<DebugHUD*> _debugHUDs;
+  bool _showDebug;
+};
+
+#endif // APP_H_
+

file:b/BulletApp.cpp (new)
--- /dev/null
+++ b/BulletApp.cpp
@@ -1,1 +1,77 @@
+#include "BulletApp.h"
 
+#include "DebugBullet.h"
+
+#include <BulletCollision/CollisionDispatch/btGhostObject.h>
+
+BulletApp::BulletApp()
+  : App(),
+    _world(0),
+    _broadphase(0),
+    _collisionConfig(0),
+    _dispatcher(0),
+    _solver(0),
+    _debugDrawer(0)
+{}
+
+BulletApp::~BulletApp()
+{
+  delete _debugDrawer;
+  
+  delete _world;
+
+  delete _solver;
+  delete _dispatcher;
+  delete _collisionConfig;
+  delete _broadphase;
+}
+
+void BulletApp::setGravity(btVector3 g)
+{
+  _world->setGravity(g);
+}
+
+btDynamicsWorld* BulletApp::world()
+{
+  return _world;
+}
+
+bool BulletApp::initialize()
+{
+  if(!App::initialize()) return false;
+
+  // Initialize bullet
+  _broadphase=new btDbvtBroadphase();
+  _collisionConfig=new btDefaultCollisionConfiguration();
+  _dispatcher=new btCollisionDispatcher(_collisionConfig);
+  _solver=new btSequentialImpulseConstraintSolver();
+
+  _world=new btDiscreteDynamicsWorld(_dispatcher,
+				     _broadphase,
+				     _solver,
+				     _collisionConfig);
+  
+  _broadphase->getOverlappingPairCache()->setInternalGhostPairCallback(new btGhostPairCallback());
+
+  // Initialize debug drawing
+  _debugDrawer=new BtOgre::DebugDrawer(sceneMngr()->getRootSceneNode(),_world);
+  _world->setDebugDrawer(_debugDrawer);
+
+  addDebugHUD(new DebugBullet(_world));
+
+  return true;
+}
+
+bool BulletApp::frameRenderingQueued(const Ogre::FrameEvent &evt)
+{
+  bool ret=App::frameRenderingQueued(evt);
+
+  _world->stepSimulation(evt.timeSinceLastFrame,100,1./150.);
+
+  _world->debugDrawWorld();
+  _debugDrawer->setDebugMode(showDebug());
+  _debugDrawer->step();
+
+  return ret;
+}
+

file:b/BulletApp.h (new)
--- /dev/null
+++ b/BulletApp.h
@@ -1,1 +1,38 @@
+#ifndef BULLETAPP_H_
+#define BULLETAPP_H_
 
+#include "App.h"
+
+#include <BtOgrePG.h>
+#include <BtOgreGP.h>
+#include <BtOgreExtras.h>
+
+#include <btBulletDynamicsCommon.h>
+
+class BulletApp : public App
+{
+public:
+  BulletApp();
+  ~BulletApp();
+
+  void setGravity(btVector3 g);
+
+protected:
+  bool initialize();
+
+  bool frameRenderingQueued(const Ogre::FrameEvent &evt);
+
+  btDynamicsWorld* world();
+
+private:
+  btDynamicsWorld *_world;
+  btDbvtBroadphase *_broadphase;
+  btDefaultCollisionConfiguration *_collisionConfig;
+  btCollisionDispatcher *_dispatcher;
+  btSequentialImpulseConstraintSolver *_solver;
+
+  BtOgre::DebugDrawer *_debugDrawer;
+};
+
+#endif // BULLETAPP_H_
+

file:b/CMakeLists.txt (new)
--- /dev/null
+++ b/CMakeLists.txt
@@ -1,1 +1,70 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(kkengine)
 
+SET(CMAKE_MODULE_PATH "/usr/lib64/OGRE/cmake/;${CMAKE_CURRENT_SOURCE_DIR}/cmake;${CMAKE_MODULE_PATH}")
+
+FIND_PACKAGE(OGRE REQUIRED)
+FIND_PACKAGE(OIS REQUIRED)
+FIND_PACKAGE(Bullet REQUIRED)
+FIND_PACKAGE(BtOgre REQUIRED)
+FIND_PACKAGE(TinyXML2 REQUIRED)
+
+SET(SRCS
+  App.cpp
+  BulletApp.cpp
+  DebugHUD.cpp
+  DebugMain.cpp
+  DebugBullet.cpp
+  DotSceneLoader.cpp
+  DotSceneSubloader.cpp
+  DotScene.cpp
+  DotSceneCollection.cpp
+  DotSceneBulletSubloader.cpp
+  DotSceneBulletCollection.cpp
+  )
+
+SET(HEADERS
+    App.h
+    BulletApp.h
+    DebugHUD.h
+    DebugMain.h
+    DebugBullet.h
+    DotSceneLoader.h
+    DotSceneSubloader.h
+    DotScene.h
+    DotSceneCollection.h
+    DotSceneBulletSubloader.h
+    DotSceneBulletCollection.h
+    )
+
+SET(DATAS
+  media/overlays/debug.overlay
+  media/overlays/debugmain.overlay
+  media/overlays/debugbullet.overlay
+  media/fonts/DebugFont.fontdef
+  media/fonts/times.ttf
+  )
+
+SET(CMAKE_MODULES
+  cmake/FindKKEngine.cmake
+  cmake/FindBtOgre.cmake
+  cmake/FindTinyXML2.cmake)
+
+INCLUDE_DIRECTORIES(${OGRE_INCLUDE_DIRS} ${OIS_INCLUDE_DIRS} ${BTOGRE_INCLUDE_DIRS} ${BULLET_INCLUDE_DIRS} ${TINYXML2_INCLUDE_DIRS})
+
+ADD_LIBRARY(kkengine SHARED ${SRCS})
+TARGET_LINK_LIBRARIES(kkengine ${OGRE_LIBRARIES} ${OIS_LIBRARIES} ${BTOGRE_LIBRARIES} ${BULLET_LIBRARIES} ${TINYXML2_LIBRARIES} procps)
+
+FOREACH(DATA ${DATAS})
+  CONFIGURE_FILE(${DATA} ${CMAKE_CURRENT_BINARY_DIR}/${DATA} COPYONLY)
+
+  GET_FILENAME_COMPONENT(DATA_DIRNAME ${DATA} PATH)
+  INSTALL(FILES ${DATA}   DESTINATION share/kkengine/${DATA_DIRNAME})
+ENDFOREACH(DATA)
+
+
+INSTALL(TARGETS kkengine LIBRARY DESTINATION lib)
+INSTALL(FILES ${HEADERS} DESTINATION include/kkengine)
+INSTALL(FILES ${CMAKE_MODULES} DESTINATION share/kkengine/cmake)
+
+

file:b/DebugBullet.cpp (new)
--- /dev/null
+++ b/DebugBullet.cpp
@@ -1,1 +1,46 @@
+#include "DebugBullet.h"
 
+#include <OgreOverlayManager.h>
+#include <OgreOverlayContainer.h>
+#include <OgreStringConverter.h>
+
+DebugBullet::DebugBullet(btDynamicsWorld *world)
+  : DebugHUD("Bullet"),_world(world)
+{ 
+  _objectsDebug=Ogre::OverlayManager::getSingletonPtr()->getOverlayElement("Debug/Bullet/Objects");
+  _activeDebug=Ogre::OverlayManager::getSingletonPtr()->getOverlayElement("Debug/Bullet/Active");
+  _sleepingDebug=Ogre::OverlayManager::getSingletonPtr()->getOverlayElement("Debug/Bullet/Sleeping");
+
+}
+
+void DebugBullet::update()
+{
+  DebugHUD::update();
+
+  int total=_world->getNumCollisionObjects();
+  _objectsDebug->setCaption(Ogre::StringConverter::toString(total));
+
+  int active=0;
+  int sleeping=0;
+  btCollisionObjectArray objects=_world->getCollisionObjectArray();
+  for(int i=0;i<total;i++)
+    {
+      switch(objects[i]->getActivationState())
+	{
+	case ACTIVE_TAG:
+	case DISABLE_DEACTIVATION:
+	  active++;
+	  break;
+	case ISLAND_SLEEPING:
+	case WANTS_DEACTIVATION:
+	case DISABLE_SIMULATION:
+	  sleeping++;
+	  break;
+	}
+    }
+
+  _activeDebug->setCaption(Ogre::StringConverter::toString(active));
+  _sleepingDebug->setCaption(Ogre::StringConverter::toString(sleeping));
+}
+
+

file:b/DebugBullet.h (new)
--- /dev/null
+++ b/DebugBullet.h
@@ -1,1 +1,26 @@
+#ifndef DEBUGBULLET_H_
+#define DEBUGBULLET_H_
 
+#include <OgreOverlayElement.h>
+
+#include <btBulletDynamicsCommon.h>
+
+#include "DebugHUD.h"
+
+class DebugBullet : public DebugHUD
+{
+public:
+  DebugBullet(btDynamicsWorld *world);
+
+  void update();
+
+private:
+  btDynamicsWorld *_world;
+
+  Ogre::OverlayElement *_objectsDebug;
+  Ogre::OverlayElement *_activeDebug;
+  Ogre::OverlayElement *_sleepingDebug;
+};
+
+#endif // DEBUGBULLET_H_
+

file:b/DebugHUD.cpp (new)
--- /dev/null
+++ b/DebugHUD.cpp
@@ -1,1 +1,36 @@
+#include "DebugHUD.h"
 
+#include <OgreOverlayManager.h>
+#include <OgreOverlayContainer.h>
+
+DebugHUD::DebugHUD(Ogre::String panelName)
+  : _panelName(panelName)
+{ 
+  createPanel();
+}
+
+void DebugHUD::update()
+{
+  //fixCaptions();
+}
+
+void DebugHUD::createPanel()
+{
+  Ogre::OverlayContainer *container=(Ogre::OverlayContainer*)Ogre::OverlayManager::getSingletonPtr()->cloneOverlayElementFromTemplate(_panelName,"Debug");
+  
+  Ogre::Overlay *overlay=Ogre::OverlayManager::getSingletonPtr()->getByName("Debug");
+  overlay->add2D(container);
+}
+
+void DebugHUD::fixCaptions()
+{
+  Ogre::OverlayContainer *container=(Ogre::OverlayContainer*)Ogre::OverlayManager::getSingletonPtr()->getOverlayElement("Debug/"+_panelName);
+
+  Ogre::OverlayContainer::ChildIterator iter=container->getChildIterator();
+  while(iter.hasMoreElements())
+    {
+      Ogre::OverlayElement *element=iter.getNext();
+      element->setCaption(element->getCaption());
+    }
+}
+

file:b/DebugHUD.h (new)
--- /dev/null
+++ b/DebugHUD.h
@@ -1,1 +1,23 @@
+#ifndef DEBUGHUD_H_
+#define DEBUGHUD_H_
 
+#include <OgreString.h>
+
+class DebugHUD
+{
+public:
+  DebugHUD(Ogre::String panelName);
+
+  virtual void update();
+
+protected:
+  void createPanel();
+
+private:
+  Ogre::String _panelName;
+
+  void fixCaptions();
+};
+
+#endif // DEBUGHUD_H_
+

file:b/DebugMain.cpp (new)
--- /dev/null
+++ b/DebugMain.cpp
@@ -1,1 +1,36 @@
+#include "DebugMain.h"
 
+#include <OgreOverlayManager.h>
+#include <OgreOverlayContainer.h>
+#include <OgreStringConverter.h>
+
+#include <proc/readproc.h>
+
+DebugMain::DebugMain(Ogre::RenderWindow *window)
+  : DebugHUD("TopBar"),_window(window)
+{ 
+  _fpsDebug=Ogre::OverlayManager::getSingletonPtr()->getOverlayElement("Debug/TopBar/FPS");
+  _vmDebug=Ogre::OverlayManager::getSingletonPtr()->getOverlayElement("Debug/TopBar/VM");
+}
+
+void DebugMain::update()
+{
+  DebugHUD::update();
+
+  // FPS
+  Ogre::Real fps=_window->getAverageFPS();
+  _fpsDebug->setCaption(Ogre::StringConverter::toString(roundf(fps)));
+
+  // Memory info
+  struct proc_t usage;
+  look_up_our_self(&usage);
+  long pagesize = sysconf(_SC_PAGE_SIZE);
+
+  unsigned long rss = usage.rss*pagesize/1024;
+  unsigned long total = usage.vsize*pagesize/1024;
+
+  _vmDebug->setCaption(Ogre::StringConverter::toString(rss)+" kb / "+Ogre::StringConverter::toString(total)+" kb");
+
+}
+
+

file:b/DebugMain.h (new)
--- /dev/null
+++ b/DebugMain.h
@@ -1,1 +1,24 @@
+#ifndef DEBUGMAIN_H_
+#define DEBUGMAIN_H_
 
+#include <OgreRenderWindow.h>
+#include <OgreOverlayElement.h>
+
+#include "DebugHUD.h"
+
+class DebugMain : public DebugHUD
+{
+public:
+  DebugMain(Ogre::RenderWindow *window);
+
+  void update();
+
+private:
+  Ogre::RenderWindow *_window;
+
+  Ogre::OverlayElement *_fpsDebug;
+  Ogre::OverlayElement *_vmDebug;
+};
+
+#endif // DEBUGMAIN_H_
+

file:b/DotScene.cpp (new)
--- /dev/null
+++ b/DotScene.cpp
@@ -1,1 +1,43 @@
+#include "DotScene.h"
 
+
+#include <OgreMovableObject.h>
+
+DotScene::DotScene()
+{ }
+
+void DotScene::addSceneNode(Ogre::SceneNode *node)
+{
+  _nodes[node->getName()]=node;
+
+  Ogre::SceneNode::ObjectIterator iter=node->getAttachedObjectIterator();
+  
+  while(iter.hasMoreElements())
+    {
+      Ogre::MovableObject *object=iter.getNext();
+
+      if(object->getMovableType()=="Camera")
+	_cameras[object->getName()]=(Ogre::Camera*)object;
+}
+
+}
+Ogre::SceneNode* DotScene::getSceneNode(Ogre::String name)
+{
+  return _nodes[name];
+}
+
+Ogre::Camera* DotScene::getCamera(Ogre::String name)
+{
+  return _cameras[name];
+}
+
+void DotScene::addCollection(int id,DotSceneCollection *collection)
+{
+  _collections[id]=collection;
+}
+
+DotSceneCollection* DotScene::collection(int id)
+{
+  return _collections[id];
+}
+

file:b/DotScene.h (new)
--- /dev/null
+++ b/DotScene.h
@@ -1,1 +1,29 @@
+#ifndef DOTSCENE_H_
+#define DOTSCENE_H_
 
+#include <OgreSceneNode.h>
+
+#include <map>
+
+#include "DotSceneCollection.h"
+
+class DotScene
+{
+public:
+  DotScene();
+
+  void addSceneNode(Ogre::SceneNode *node);
+  Ogre::SceneNode* getSceneNode(Ogre::String name);
+  Ogre::Camera* getCamera(Ogre::String name);
+
+  void addCollection(int id,DotSceneCollection *collection);
+  DotSceneCollection* collection(int id);
+private:
+  std::map<Ogre::String,Ogre::SceneNode *> _nodes;
+  std::map<Ogre::String,Ogre::Camera *> _cameras;
+
+  std::map<int,DotSceneCollection *> _collections;
+};
+
+#endif // DOTSCENE_H_
+

--- /dev/null
+++ b/DotSceneBulletCollection.cpp
@@ -1,1 +1,26 @@
+#include "DotSceneBulletCollection.h"
 
+DotSceneBulletCollection::DotSceneBulletCollection()
+  : DotSceneCollection()
+{ }
+
+void DotSceneBulletCollection::addRigidBody(Ogre::String name,btRigidBody *body)
+{
+  _rigidBodies[name]=body;
+}
+
+btRigidBody* DotSceneBulletCollection::getRigidBody(Ogre::String name)
+{
+  return _rigidBodies[name];
+}
+
+void DotSceneBulletCollection::addSensor(Ogre::String name,btGhostObject *body)
+{
+  _sensors[name]=body;
+}
+
+btGhostObject* DotSceneBulletCollection::getSensor(Ogre::String name)
+{
+  return _sensors[name];
+}
+

--- /dev/null
+++ b/DotSceneBulletCollection.h
@@ -1,1 +1,28 @@
+#ifndef DOTSCENEBULLETCOLLECTION_H_
+#define DOTSCENEBULLETCOLLECTION_H_
 
+#include "DotSceneCollection.h"
+
+#include <btBulletDynamicsCommon.h>
+#include <BulletCollision/CollisionDispatch/btGhostObject.h>
+
+#include <OgreString.h>
+
+class DotSceneBulletCollection : public DotSceneCollection
+{
+public:
+  DotSceneBulletCollection();
+
+  void addRigidBody(Ogre::String name,btRigidBody *body);
+  btRigidBody* getRigidBody(Ogre::String name);
+
+  void addSensor(Ogre::String name,btGhostObject *body);
+  btGhostObject* getSensor(Ogre::String name);
+
+private:
+  std::map<Ogre::String,btRigidBody *> _rigidBodies;
+  std::map<Ogre::String,btGhostObject *> _sensors;
+};
+
+#endif // DOTSCENEBULLETCOLLECTION_H_
+

--- /dev/null
+++ b/DotSceneBulletSubloader.cpp
@@ -1,1 +1,112 @@
+#include "DotSceneBulletSubloader.h"
 
+#include <BtOgrePG.h>
+#include <BtOgreGP.h>
+
+#include <OgreEntity.h>
+#include <OgreMeshManager.h>
+
+#include <BulletCollision/CollisionDispatch/btGhostObject.h>
+
+#include <iostream>
+using namespace std;
+
+DotSceneBulletSubloader::DotSceneBulletSubloader(btDynamicsWorld *world)
+  : DotSceneSubloader(),_world(world)
+{ }
+
+DotSceneCollection *DotSceneBulletSubloader::newCollection()
+{
+  _collection=new DotSceneBulletCollection();
+  return _collection;
+}
+
+void DotSceneBulletSubloader::processEntity(tinyxml2::XMLElement *entityElement,Ogre::SceneNode *node)
+{
+  DotSceneSubloader::processEntity(entityElement,node);
+
+  Ogre::String name=entityElement->Attribute("name");
+  Ogre::Entity* entity=(Ogre::Entity*)node->getAttachedObject(name);
+  
+  if(entityElement->Attribute("physics_type"))
+    {
+      Ogre::String physics_type=entityElement->Attribute("physics_type");
+
+      // Setup the shape
+      Ogre::String collisionPrim=entityElement->Attribute("collisionPrim");
+      btCollisionShape *shape;
+      if(collisionPrim=="triangle_mesh")
+	{
+	  BtOgre::StaticMeshToShapeConverter meshConverter(entity);
+	  shape=meshConverter.createTrimesh();
+
+	}
+      else // Box is the default shape
+	{
+	  Ogre::Vector3 halfBoundingBox=entity->getBoundingBox().getHalfSize();
+	  // Ogre pads the bounding box of meshes. This unpads it.
+	  halfBoundingBox/=(1+2*Ogre::MeshManager::getSingleton().getBoundsPaddingFactor());
+	  shape=new btBoxShape(BtOgre::Convert::toBullet(halfBoundingBox));
+	}
+
+      // Determine any collision filters
+      int collisionFilterMask=btBroadphaseProxy::AllFilter;
+
+      tinyxml2::XMLNode *nodeNode=entityElement->Parent();
+      tinyxml2::XMLElement *user_dataElement=nodeNode->FirstChildElement("user_data");
+      while(user_dataElement)
+	{
+	  // collisionFilterMask
+	  if(user_dataElement->Attribute("name","collisionFilterMask"))
+	    {
+	      collisionFilterMask=0;
+	      Ogre::String user_data=user_dataElement->Attribute("value");
+	      std::replace(user_data.begin(),user_data.end(),',',' ');
+	      std::istringstream iss(user_data);
+	      while(iss)
+		{
+		  int mask;
+		  iss >> mask;
+		  collisionFilterMask|=mask;
+		};
+	    }
+	  user_dataElement=user_dataElement->NextSiblingElement("user_data");
+	};
+      
+
+      // Setup the collision object
+      if(physics_type=="SENSOR") // Sensors are basically ghost objects
+	{
+	  btGhostObject *ghostObject=new btGhostObject();
+	  ghostObject->setCollisionShape(shape);
+	  ghostObject->setWorldTransform(btTransform(BtOgre::Convert::toBullet(node->getOrientation()),
+						     BtOgre::Convert::toBullet(node->getPosition())  ));
+	  ghostObject->setCollisionFlags(ghostObject->getCollisionFlags() | btCollisionObject::CF_NO_CONTACT_RESPONSE);
+	  _world->addCollisionObject(ghostObject,btBroadphaseProxy::DefaultFilter,collisionFilterMask);
+	  _collection->addSensor(name,ghostObject);
+
+	  node->setVisible(false);
+	}
+      else // Assume everything else is some kind of a rigid body
+	{
+	  btScalar mass;
+	  btVector3 inertia;
+	  if(physics_type=="RIGID_BODY")
+	    {
+	      mass=entityElement->FloatAttribute("mass");
+	      shape->calculateLocalInertia(mass,inertia);
+	    }
+	  else // Default is static (physics_type=="STATIC")
+	    {
+	      mass=0;
+	      inertia=btVector3(0,0,0);
+	    }
+	  BtOgre::RigidBodyState *state=new BtOgre::RigidBodyState(node);
+	  btRigidBody *body=new btRigidBody(mass,state,shape,inertia);
+	  
+	  _world->addRigidBody(body,btBroadphaseProxy::DefaultFilter,collisionFilterMask);
+	  _collection->addRigidBody(name,body);
+	}
+    }
+}
+

--- /dev/null
+++ b/DotSceneBulletSubloader.h
@@ -1,1 +1,27 @@
+#ifndef DOTSCENEBULLETSUBLOADER_H_
+#define DOTSCENEBULLETSUBLOADER_H_
 
+#include "DotSceneSubloader.h"
+#include "DotSceneBulletCollection.h"
+
+#include <btBulletDynamicsCommon.h>
+
+#define SUBLOADER_BULLET 1
+
+class DotSceneBulletSubloader : public DotSceneSubloader
+{
+public:
+  DotSceneBulletSubloader(btDynamicsWorld *world);
+
+  virtual DotSceneCollection* newCollection();
+
+  void processEntity(tinyxml2::XMLElement *entityElement,Ogre::SceneNode *node);
+
+private:
+  btDynamicsWorld *_world;
+
+  DotSceneBulletCollection *_collection;
+};
+
+#endif // DOTSCENEBULLETSUBLOADER_H_
+

--- /dev/null
+++ b/DotSceneCollection.cpp
@@ -1,1 +1,5 @@
+#include "DotSceneCollection.h"
 
+DotSceneCollection::DotSceneCollection()
+{ }
+

--- /dev/null
+++ b/DotSceneCollection.h
@@ -1,1 +1,11 @@
+#ifndef DOTSCENECOLLECTION_H_
+#define DOTSCENECOLLECTION_H_
 
+class DotSceneCollection
+{
+public:
+  DotSceneCollection();
+};
+
+#endif // DOTSCENECOLLECTION_H_
+

--- /dev/null
+++ b/DotSceneLoader.cpp
@@ -1,1 +1,259 @@
-
+#include "DotSceneLoader.h"
+
+#include <OgreLogManager.h>
+#include <OgreSceneNode.h>
+#include <OgreEntity.h>
+#include <OgreLight.h>
+
+#include <iostream>
+using namespace std;
+
+#define PROCESS_ELEMENT1(name,Name) \
+  if(name##Element) \
+    { \
+      process##Name(name##Element); \
+      for(std::map<int,DotSceneSubloader*>::iterator iter=_subloaders.begin(); \
+      iter!=_subloaders.end(); \
+      iter++) \
+	{ \
+	  iter->second->process##Name(name##Element); \
+	} \
+    }
+
+#define PROCESS_ELEMENT2(name,Name,arg)		\
+  if(name##Element) \
+    { \
+      process##Name(name##Element,arg);	\
+      for(std::map<int,DotSceneSubloader*>::iterator iter=_subloaders.begin(); \
+      iter!=_subloaders.end(); \
+      iter++) \
+	{ \
+	  iter->second->process##Name(name##Element,arg);	\
+	} \
+    }
+
+
+DotSceneLoader::DotSceneLoader(Ogre::SceneManager *sceneMngr,Ogre::Viewport *viewport,bool blender2ogrefix)
+  :_sceneMngr(sceneMngr),_viewport(viewport),_blender2ogrefix(blender2ogrefix),_scene(0)
+{ }
+
+void DotSceneLoader::addSubloader(int id,DotSceneSubloader *subloader)
+{
+  _subloaders[id]=subloader;
+}
+
+DotScene* DotSceneLoader::loadScene(Ogre::String file)
+{
+  Ogre::LogManager::getSingleton().stream() << "Loading .scene file " << file;
+
+  tinyxml2::XMLDocument doc;
+  int result=doc.LoadFile(file.c_str());
+  if(result!=tinyxml2::XML_NO_ERROR)
+    {
+      Ogre::LogManager::getSingleton().stream() << "Error loading .scene file.";
+      return 0;
+    }
+
+  tinyxml2::XMLElement *scene=doc.RootElement();
+  if(strcmp(scene->Name(),"scene")!=0)
+    {
+      Ogre::LogManager::getSingleton().stream() << "Not a valid .scene XML document.";
+      return 0; 
+    }
+
+  // Create a new dot scene, with collections
+  _scene=new DotScene();
+  for(std::map<int,DotSceneSubloader*>::iterator iter=_subloaders.begin();
+      iter!=_subloaders.end();
+      iter++)
+    {
+      _scene->addCollection(iter->first,iter->second->newCollection());
+    }
+
+  // Now process nodes
+  tinyxml2::XMLElement *nodesElement = scene->FirstChildElement("nodes");
+  PROCESS_ELEMENT1(nodes,Nodes)
+
+  tinyxml2::XMLElement *environmentElement = scene->FirstChildElement("environment");
+  PROCESS_ELEMENT1(environment,Environment)
+
+  return _scene;
+}
+
+void DotSceneLoader::processNodes(tinyxml2::XMLElement *nodesElement)
+{
+  tinyxml2::XMLElement *nodeElement=nodesElement->FirstChildElement("node");
+  while(nodeElement)
+    {
+      PROCESS_ELEMENT1(node,Node);
+      nodeElement=nodeElement->NextSiblingElement();
+    };
+}
+
+void DotSceneLoader::processEnvironment(tinyxml2::XMLElement *environmentElement)
+{
+  // Background colour
+  tinyxml2::XMLElement *colourBackgroundElement=environmentElement->FirstChildElement("colourBackground");
+  if(colourBackgroundElement)
+    {
+      _viewport->setBackgroundColour(parseColour(colourBackgroundElement));
+    }
+
+  // Ambient colour
+  tinyxml2::XMLElement *colourAmbientElement=environmentElement->FirstChildElement("colourAmbient");
+  if(colourAmbientElement)
+    {
+      _sceneMngr->setAmbientLight(parseColour(colourAmbientElement));
+    }
+}
+
+
+void DotSceneLoader::processNode(tinyxml2::XMLElement *nodeElement)
+{
+  Ogre::String name=nodeElement->Attribute("name");
+  Ogre::LogManager::getSingleton().stream() << "Creating node " << name;
+  
+  Ogre::SceneNode *node=_sceneMngr->getRootSceneNode()->createChildSceneNode(name);
+  
+  // Process position
+  tinyxml2::XMLElement *positionElement=nodeElement->FirstChildElement("position");
+  if(positionElement)
+    node->setPosition(parseVector3(positionElement));
+  
+  // Process rotation
+  tinyxml2::XMLElement *rotationElement=nodeElement->FirstChildElement("rotation");
+  if(rotationElement)
+    node->setOrientation(parseQuaternion(rotationElement));
+  
+  // Process scale
+  tinyxml2::XMLElement *scaleElement=nodeElement->FirstChildElement("scale");
+  if(scaleElement)
+    node->setScale(parseVector3(scaleElement));
+
+  node->setInitialState();
+  
+  // Load an entity
+  tinyxml2::XMLElement *entityElement=nodeElement->FirstChildElement("entity");
+  PROCESS_ELEMENT2(entity,Entity,node)
+  
+  // Load a camera
+  tinyxml2::XMLElement *cameraElement=nodeElement->FirstChildElement("camera");
+  PROCESS_ELEMENT2(camera,Camera,node)
+  
+  // Load a light
+  tinyxml2::XMLElement *lightElement=nodeElement->FirstChildElement("light");
+  PROCESS_ELEMENT2(light,Light,node)
+  
+  // Save this node
+  _scene->addSceneNode(node);
+}
+
+void DotSceneLoader::processEntity(tinyxml2::XMLElement *entityElement,Ogre::SceneNode *node)
+{ 
+  Ogre::String entityName=entityElement->Attribute("name");
+  Ogre::String entityMesh=entityElement->Attribute("meshFile");
+
+  Ogre::Entity *entity=_sceneMngr->createEntity(entityName,entityMesh);
+
+  node->attachObject(entity);
+}
+
+void DotSceneLoader::processCamera(tinyxml2::XMLElement *cameraElement,Ogre::SceneNode *node)
+{
+  Ogre::String name=cameraElement->Attribute("name");
+  Ogre::String projectionType=cameraElement->Attribute("projectionType");
+  Ogre::Radian fov(cameraElement->FloatAttribute("fov"));
+
+  Ogre::Camera *camera=_sceneMngr->createCamera(name);
+  camera->setFOVy(fov);
+
+  if(projectionType=="perspective")
+    camera->setProjectionType(Ogre::PT_PERSPECTIVE);
+  else if(projectionType=="orthographic")
+    camera->setProjectionType(Ogre::PT_ORTHOGRAPHIC);
+
+  tinyxml2::XMLElement *clippingElement=cameraElement->FirstChildElement("clipping");
+  if(clippingElement)
+    {
+      Ogre::Real near=clippingElement->FloatAttribute("near");
+      camera->setNearClipDistance(near);
+
+      Ogre::Real far=clippingElement->FloatAttribute("far");
+      camera->setFarClipDistance(far);
+    }
+
+  if(_blender2ogrefix)
+    camera->pitch(Ogre::Radian(-Ogre::Math::PI/2));
+
+  node->attachObject(camera);
+}
+
+void DotSceneLoader::processLight(tinyxml2::XMLElement *lightElement,Ogre::SceneNode *node)
+{
+  Ogre::String name=lightElement->Attribute("name");
+  Ogre::String type=lightElement->Attribute("type");
+
+  // Create the light
+  Ogre::Light *light = _sceneMngr->createLight(name);
+ 
+  if(type=="directional")
+    light->setType(Ogre::Light::LT_DIRECTIONAL);
+
+  tinyxml2::XMLElement *colourDiffuseElement = lightElement->FirstChildElement("colourDiffuse");
+  if(colourDiffuseElement)
+    light->setDiffuseColour(parseColour(colourDiffuseElement));
+ 
+  tinyxml2::XMLElement *colourSpecularElement = lightElement->FirstChildElement("colourSpecular");
+  if(colourSpecularElement)
+    light->setSpecularColour(parseColour(colourSpecularElement));
+
+  tinyxml2::XMLElement *lightAttenuationElement = lightElement->FirstChildElement("lightAttenuation");
+  if(lightAttenuationElement)
+    {
+      Ogre::Real range=lightAttenuationElement->FloatAttribute("range");
+      Ogre::Real constant=lightAttenuationElement->FloatAttribute("constant");
+      Ogre::Real linear=lightAttenuationElement->FloatAttribute("linear");
+      Ogre::Real quadratic=lightAttenuationElement->FloatAttribute("quadratic");
+      light->setAttenuation(range, constant, linear, quadratic);
+    }
+
+  tinyxml2::XMLElement *directionElement = lightElement->FirstChildElement("direction");
+  if(directionElement)
+    {
+      if(_blender2ogrefix)
+	light->setDirection(Ogre::Vector3(0,-1,0));
+      else
+	light->setDirection(parseVector3(directionElement));
+    }
+
+  tinyxml2::XMLElement *positionElement = lightElement->FirstChildElement("position");
+  if(positionElement)
+    light->setPosition(parseVector3(positionElement));
+
+  node->attachObject(light);
+}
+
+Ogre::Vector3 DotSceneLoader::parseVector3(tinyxml2::XMLElement *vectorElement)
+{    
+  return Ogre::Vector3(vectorElement->FloatAttribute("x"),
+		       vectorElement->FloatAttribute("y"),
+		       vectorElement->FloatAttribute("z"));
+}
+
+Ogre::Quaternion DotSceneLoader::parseQuaternion(tinyxml2::XMLElement *quaternionElement)
+{
+  return Ogre::Quaternion(quaternionElement->FloatAttribute("qw"),
+			  quaternionElement->FloatAttribute("qx"),
+			  quaternionElement->FloatAttribute("qy"),
+			  quaternionElement->FloatAttribute("qz"));
+  
+}
+
+Ogre::ColourValue DotSceneLoader::parseColour(tinyxml2::XMLElement *colourElement)
+{
+  return Ogre::ColourValue(colourElement->FloatAttribute("r"),
+			   colourElement->FloatAttribute("g"),
+			   colourElement->FloatAttribute("b"),
+			   colourElement->FloatAttribute("a"));
+}
+

file:b/DotSceneLoader.h (new)
--- /dev/null
+++ b/DotSceneLoader.h
@@ -1,1 +1,49 @@
+#ifndef DOTSCENELOADER_H_
+#define DOTSCENELOADER_H_
 
+#include <OgreString.h>
+#include <OgreSceneManager.h>
+#include <OgreViewport.h>
+
+#include <tinyxml2.h>
+
+#include "DotScene.h"
+#include "DotSceneSubloader.h"
+
+class DotSceneLoader
+{
+public:
+  DotSceneLoader(Ogre::SceneManager *sceneMngr,Ogre::Viewport *viewport,bool blender2ogrefix=false);
+
+  void addSubloader(int id,DotSceneSubloader *subloader);
+
+  DotScene* loadScene(Ogre::String file);
+
+protected:
+  void processNodes(tinyxml2::XMLElement *nodesElement);
+  void processEnvironment(tinyxml2::XMLElement *environmentElement);
+
+  void processNode(tinyxml2::XMLElement *nodeElement);
+
+  void processEntity(tinyxml2::XMLElement *entityElement,Ogre::SceneNode *node);
+  void processCamera(tinyxml2::XMLElement *cameraElement,Ogre::SceneNode *node);
+  void processLight(tinyxml2::XMLElement *lightElement,Ogre::SceneNode *node);
+
+  Ogre::Vector3 parseVector3(tinyxml2::XMLElement *vectorElement);
+  Ogre::Quaternion parseQuaternion(tinyxml2::XMLElement *quaternionElement);
+  Ogre::ColourValue parseColour(tinyxml2::XMLElement *colourElement);
+
+
+private:
+  Ogre::SceneManager *_sceneMngr;
+  Ogre::Viewport *_viewport;
+
+  bool _blender2ogrefix;
+
+  DotScene *_scene;
+
+  std::map<int,DotSceneSubloader*> _subloaders;
+};
+
+#endif // DOTSCENELOADER_H_
+

--- /dev/null
+++ b/DotSceneSubloader.cpp
@@ -1,1 +1,25 @@
+#include "DotSceneSubloader.h"
 
+DotSceneSubloader::DotSceneSubloader()
+{ }
+
+DotSceneCollection* DotSceneSubloader::newCollection()
+{
+  return 0;
+}
+
+void DotSceneSubloader::processNodes(tinyxml2::XMLElement *nodesElement)
+{ }
+void DotSceneSubloader::processEnvironment(tinyxml2::XMLElement *environmentElement)
+{ }
+
+void DotSceneSubloader::processNode(tinyxml2::XMLElement *nodeElement)
+{ }
+
+void DotSceneSubloader::processEntity(tinyxml2::XMLElement *entityElement,Ogre::SceneNode *node)
+{ }
+void DotSceneSubloader::processCamera(tinyxml2::XMLElement *cameraElement,Ogre::SceneNode *node)
+{ }
+void DotSceneSubloader::processLight(tinyxml2::XMLElement *lightElement,Ogre::SceneNode *node)
+{ }
+

--- /dev/null
+++ b/DotSceneSubloader.h
@@ -1,1 +1,27 @@
+#ifndef DOTSCENESUBLOADER_H_
+#define DOTSCENESUBLOADER_H_
 
+#include <tinyxml2.h>
+
+#include "DotScene.h"
+#include "DotSceneCollection.h"
+
+class DotSceneSubloader 
+{
+public:
+  DotSceneSubloader();
+
+  virtual DotSceneCollection* newCollection();
+
+  virtual void processNodes(tinyxml2::XMLElement *nodesElement);
+  virtual void processEnvironment(tinyxml2::XMLElement *environmentElement);
+
+  virtual void processNode(tinyxml2::XMLElement *nodeElement);
+
+  virtual void processEntity(tinyxml2::XMLElement *entityElement,Ogre::SceneNode *node);
+  virtual void processCamera(tinyxml2::XMLElement *cameraElement,Ogre::SceneNode *node);
+  virtual void processLight(tinyxml2::XMLElement *lightElement,Ogre::SceneNode *node);
+};
+
+#endif // DOTSCENESUBLOADER_H_
+

--- /dev/null
+++ b/cmake/FindBtOgre.cmake
@@ -1,1 +1,29 @@
+# - Find BtOgre
+# Find the native BtOgre includes and library
+#
+#   BTOGRE_DIR          - Set this to installed location of BtOgre
+#   BTOGRE_FOUND        - True if BtOgre found.
+#   BTOGRE_INCLUDE_DIRS - where to find includes
+#   BTOGRE_LIBRARIES    - List of libraries when using BtOgre.
+#
 
+IF( BTOGRE_INCLUDE_DIRS )
+    # Already in cache, be silent
+    SET( BTOGRE_FIND_QUIETLY TRUE )
+ENDIF( BTOGRE_INCLUDE_DIRS )
+
+# Look for the includes
+FIND_PATH( BTOGRE_INCLUDE_DIRS "BtOgrePG.h"
+  "${BTOGRE_DIR}/include")
+
+# Look for the libraries
+FIND_LIBRARY( BTOGRE_LIBRARIES "BtOgre"
+  "${BTOGRE_DIR}/lib")
+
+# handle the QUIETLY and REQUIRED arguments and set BTOGRE_FOUND to TRUE if
+# all listed variables are TRUE
+INCLUDE( "FindPackageHandleStandardArgs" )
+FIND_PACKAGE_HANDLE_STANDARD_ARGS( "BtOgre" DEFAULT_MSG BTOGRE_INCLUDE_DIRS BTOGRE_LIBRARIES )
+
+MARK_AS_ADVANCED( BTOGRE_INCLUDE_DIRS BTOGRE_LIBRARIES )
+

--- /dev/null
+++ b/cmake/FindKKEngine.cmake
@@ -1,1 +1,37 @@
+# - Find KKEngine
+# Find the native KKEngine includes and library
+#
+#   KKENGINE_DIR          - Set this to installed location of KKEngine
+#   KKENGINE_FOUND        - True if KKEngine found.
+#   KKENGINE_INCLUDE_DIRS - Where to find includes.
+#   KKENGINE_LIBRARIES    - List of libraries when using KKEngine.
+#   KKENGINE_DATA         - Path to where the data of KKEngine is located.
+#
 
+SET(KKENGINE_DIR "${KKENGINE_DIR}/")
+
+IF( KKENGINE_INCLUDE_DIRS )
+    # Already in cache, be silent
+    SET( KKENGINE_FIND_QUIETLY TRUE )
+ENDIF( KKENGINE_INCLUDE_DIRS )
+
+# Look for the includes
+FIND_PATH( KKENGINE_INCLUDE_DIRS "kkengine/App.h"
+  "${KKENGINE_DIR}/include" )
+
+# Look for the libraries
+FIND_LIBRARY( KKENGINE_LIBRARIES "kkengine"
+  "${KKENGINE_DIR}/lib" )
+
+# Look for the data
+FIND_PATH( KKENGINE_DATA "media/overlays/debug.overlay"
+  "${KKENGINE_DIR}/share/kkengine" )
+
+
+# handle the QUIETLY and REQUIRED arguments and set KKENGINE_FOUND to TRUE if
+# all listed variables are TRUE
+INCLUDE( "FindPackageHandleStandardArgs" )
+FIND_PACKAGE_HANDLE_STANDARD_ARGS( "KKEngine" DEFAULT_MSG KKENGINE_INCLUDE_DIRS KKENGINE_LIBRARIES KKENGINE_DATA )
+
+MARK_AS_ADVANCED( KKENGINE_INCLUDE_DIRS KKENGINE_LIBRARIES KKENGINE_DATA )
+

--- /dev/null
+++ b/cmake/FindKKEngine.cmake~
@@ -1,1 +1,28 @@
+# - Find BtOgre
+# Find the native BtOgre includes and library
+#
+#   BTOGRE_FOUND       - True if BtOgre found.
+#   BTOGRE_INCLUDE_DIR - where to find includes
+#   BTOGRE_LIBRARIES   - List of libraries when using BtOgre.
+#
 
+IF( BTOGRE_INCLUDE_DIR )
+    # Already in cache, be silent
+    SET( BtOgre_FIND_QUIETLY TRUE )
+ENDIF( BTOGRE_INCLUDE_DIR )
+
+# Look for the includes
+FIND_PATH( BTOGRE_INCLUDE_DIR "BtOgrePG.h"
+  "${BtOgre_DIR}/include")
+
+# Look for the libraries
+FIND_LIBRARY( BTOGRE_LIBRARIES "BtOgre"
+  "${BtOgre_DIR}/lib")
+
+# handle the QUIETLY and REQUIRED arguments and set BTOGRE_FOUND to TRUE if
+# all listed variables are TRUE
+INCLUDE( "FindPackageHandleStandardArgs" )
+FIND_PACKAGE_HANDLE_STANDARD_ARGS( "BtOgre" DEFAULT_MSG BTOGRE_INCLUDE_DIR BTOGRE_LIBRARIES )
+
+MARK_AS_ADVANCED( BTOGRE_INCLUDE_DIR BTOGRE_LIBRARIES )
+

--- /dev/null
+++ b/cmake/FindTinyXML2.cmake
@@ -1,1 +1,12 @@
+# - Try to find TinyXML-2
+# Once done this will define
+#  TINYXML2_FOUND - System has TinyXML2
+#  TINYXML2_INCLUDE_DIRS - The TinyXML2 include directories
+#  TINYXML2_LIBRARIES - The libraries needed to use TinyXML2
+#  TINYXML2_DEFINITIONS - Compiler switches required for using TinyXML2
 
+FIND_PACKAGE(PkgConfig)
+PKG_CHECK_MODULES(TINYXML2 REQUIRED tinyxml2)
+
+MARK_AS_ADVANCED(TINYXML2_INCLUDE_DIRS TINYXML2_LIBRARIES )
+

--- /dev/null
+++ b/media/fonts/DebugFont.fontdef
@@ -1,1 +1,8 @@
+DebugFont
+{
+	type		truetype
+	source		times.ttf
+	size		16
+	resolution	72
+}
 

Binary files /dev/null and b/media/fonts/times.ttf differ

--- /dev/null
+++ b/media/overlays/debug.overlay
@@ -1,1 +1,13 @@
+template element TextArea(Debug/Template/BasicText)
+{
+	metrics_mode pixels
+	font_name DebugFont
+	char_height 16
+}
 
+
+Debug
+{
+}
+
+

--- /dev/null
+++ b/media/overlays/debugbullet.overlay
@@ -1,1 +1,64 @@
+template container Panel(Bullet)
+{
+	metrics_mode pixels
+	left 0
+	top 30
+	width 100
+	height 100
 
+	element TextArea(Bullet/ObjectsLabel) : Debug/Template/BasicText
+	{
+		left 10
+		top 10
+		width 100
+		height 10
+		caption # Objects:
+	}
+
+	element TextArea(Bullet/Objects) : Debug/Template/BasicText
+	{
+		left 75
+		top 10
+		width 100
+		height 10
+		caption 100
+	}
+
+	element TextArea(Bullet/ActiveLabel) : Debug/Template/BasicText
+	{
+		left 10
+		top 25
+		width 100
+		height 10
+		caption # Active:
+	}
+
+	element TextArea(Bullet/Active) : Debug/Template/BasicText
+	{
+		left 75
+		top 25
+		width 100
+		height 10
+		caption 100
+	}
+
+	element TextArea(Bullet/SleepingLabel) : Debug/Template/BasicText
+	{
+		left 10
+		top 40
+		width 100
+		height 10
+		caption # Sleeping:
+	}
+
+	element TextArea(Bullet/Sleeping) : Debug/Template/BasicText
+	{
+		left 75
+		top 40
+		width 100
+		height 10
+		caption 100
+	}
+
+}
+

--- /dev/null
+++ b/media/overlays/debugmain.overlay
@@ -1,1 +1,44 @@
+template container Panel(TopBar)
+{
+	left 0
+	top 0
+	width 1
+	height 1
 
+	element TextArea(TopBar/FPSLabel) : Debug/Template/BasicText
+	{
+		left 10
+		top 10
+		width 100
+		height 10
+		caption FPS:
+	}
+
+	element TextArea(TopBar/FPS) : Debug/Template/BasicText
+	{
+		left 40
+		top 10
+		width 100
+		height 10
+		caption 100
+	}
+
+	element TextArea(TopBar/VMLabel) : Debug/Template/BasicText
+	{
+		left 100
+		top 10
+		width 100
+		height 10
+		caption Memory:
+	}
+
+	element TextArea(TopBar/VM) : Debug/Template/BasicText
+	{
+		left 150
+		top 10
+		width 100
+		height 10
+		caption 100
+	}
+}
+