#include "DotScene.h"

//dot scene requires tinyxml, don't forget to either include it in the list
// of linked libraries or put the source files in yoru project.

//This method's purpose is to load in a blender scene and assign collision
//shapes and rigid bodies as appropriate.
void BlenderBullet::loadScene(){
  //load the Blender scene
  ::parseDotScene("scene1.scene", "General", mSceneMgr);
  
  //for each child in the scene - this is the child of the root where
  // parseDotScene loads them
  int n = mSceneMgr->getRootSceneNode()->numChildren();
  for(int i = 0; i < n; i++){

    //get the node object and cast it to a SceneNode
    Ogre::Node *nd = mSceneMgr->getRootSceneNode()->getChild(i);
    std::cout << "Node " << nd->getName() << std::endl;
    Ogre::SceneNode *snd = dynamic_cast<Ogre::SceneNode *>(nd);

    //was the cast successful?
    if(snd){  
      //iterate through each object attached to this node
      int m = snd->numAttachedObjects();
      for(int j = 0; j < m; j++){
        //get the object and try to cast it to an entity
        Ogre::MovableObject *obj = snd->getAttachedObject(j);
        std::cout << "\tEntity " << obj->getName() << std::endl;
        Ogre::Entity *ent = dynamic_cast<Ogre::Entity *>(obj);

        //was the cast successful?
        if(ent){
          //set up the shape and body variables
          OgreBulletCollisions::CollisionShape *shape = 0;
          OgreBulletDynamics::RigidBody *body =
            new OgreBulletDynamics::RigidBody(snd->getName(), m_world);
          
          if (snd->getName().compare("s_Ground") == 0){
            //if the object is the ground, make a PlaneCollisionShape
            shape =new OgreBulletCollisions::StaticPlaneCollisionShape(
              Ogre::Vector3::UNIT_Y, snd->getPosition().y);
            body->setStaticShape(shape, 0.1, 0.8);
          } //end ground

          else if(snd->getName().find("_S_") != Ogre::String::npos){
            //the object should be shaped like a sphere
            //figure out the bounding box for the entity
            Ogre::Sphere bound = ent->getWorldBoundingSphere();
            shape =  new OgreBulletCollisions::SphereCollisionShape(
              1.01*bound.getRadius());
          } //end sphere

          else if(snd->getName().find("_B_") != Ogre::String::npos){
            //the object should be shaped like a box
            Ogre::AxisAlignedBox bound = ent->getWorldBoundingBox();
            Ogre::Vector3 desiredSize = 1.01*(bound.getMaximum() - 
                                              bound.getMinimum());
            shape = new OgreBulletCollisions::BoxCollisionShape(
              desiredSize*snd->getScale());
          } //end box

          else if(snd->getName().find("_C_") != Ogre::String::npos){
            //the object should be shaped like a cylinder
            //note this is limited to one parallel to the Y-Axis,
            //you could have designations for CX, CY and CZ
            Ogre::Sphere bound = ent->getWorldBoundingSphere();
            Ogre::Vector3 desiredSize = bound.getRadius()*snd->getScale();
            shape = new OgreBulletCollisions::CylinderCollisionShape(
              desiredSize*1.01, Ogre::Vector3::UNIT_Y);
          } //end cylinder
          
          else {
            //otherwise make a convex surface
            Ogre::AxisAlignedBox bound = ent->getWorldBoundingBox();
            Ogre::Vector3 desiredSize = 1.01*(bound.getMaximum() - 
                                              bound.getMinimum());
            Ogre::Matrix4 transform= Ogre::Matrix4::IDENTITY;;
            transform.setScale(desiredSize*snd->getScale());
            
            OgreBulletCollisions::StaticMeshToShapeConverter makeShape(
              ent, transform);
            shape = makeShape.createConvexDecomposition();
          } //end other

          //static v. dynamic shapes
          if(snd->getName().find("s_") == 0){
            //This should be static geometry (doesn't move, but can be hit)
            body->setStaticShape(shape, 0.1, 0.8,
                                 snd->_getDerivedPosition());
          } //end static shape
          else {
            //This should be dynamic geometry
            body->setShape(snd, shape, 0.1, 0.8, 1, 
                           snd->_getDerivedPosition());
          } //end other (dynamic shape)
          
          //store them, but you might consider putting all four components
          //  scene node, entity, shape and body into an object
          m_bodies.push_back(body);
          m_shapes.push_back(shape);
        }  //end if (ent)
      } //end for each attached object
    } //end if (snd)
  } //end for each node
} //end loadScene