#include "PrimitiveFactory.h"

template<> PrimitiveFactory* Ogre::Singleton<PrimitiveFactory>::ms_Singleton = 0;

PrimitiveFactory::PrimitiveFactory(OgreNewt::World* world, Ogre::SceneManager* sceneManager, Ogre::String defaultMaterialName)
{
	this->world = world;
	this->sceneManager = sceneManager;
	this->defaultMaterialName = defaultMaterialName;

	generatedObjectCount = 0;
}

PrimitiveFactory::~PrimitiveFactory()
{
	for (BodyMap::iterator it = boxes.begin(); it != boxes.end(); it++)
	{
		delete it->second;
	}

	boxes.clear();

	for (BodyMap::iterator it = ellipsoids.begin(); it != ellipsoids.end(); it++)
	{
		delete it->second;
	}

	ellipsoids.clear();

	for (BodyMap::iterator it = cylinders.begin(); it != cylinders.end(); it++)
	{
		delete it->second;
	}

	cylinders.clear();

	for (BodyMap::iterator it = chamferCylinders.begin(); it != chamferCylinders.end(); it++)
	{
		delete it->second;
	}

	chamferCylinders.clear();

	for (BodyMap::iterator it = cones.begin(); it != cones.end(); it++)
	{
		delete it->second;
	}

	cones.clear();

	for (BodyMap::iterator it = convexHulls.begin(); it != convexHulls.end(); it++)
	{
		delete it->second;
	}

	convexHulls.clear();

	for (BodyMap::iterator it = treeCollisions.begin(); it != treeCollisions.end(); it++)
	{
		delete it->second;
	}

	treeCollisions.clear();
}

OgreNewt::Body* PrimitiveFactory::createBox(Ogre::String name, Ogre::String material, Ogre::Real mass, Ogre::Vector3 position, Ogre::Vector3 scale, Ogre::Quaternion orientation, OgreNewt::MaterialID* materialId, int objectId, Ogre::String mesh)
{
	Ogre::SceneNode* node = createNode(mesh, name, material, position, scale, orientation);
	
	return createBox(node, mass, materialId, objectId);
}

OgreNewt::Body* PrimitiveFactory::createBox(Ogre::SceneNode* sourceNode, float mass, OgreNewt::MaterialID* materialId, int objectId)
{
	if (sourceNode == NULL)
	{
		return NULL;
	}

	if (sourceNode->numAttachedObjects() == 0)
	{
		return NULL;
	}

	Ogre::MovableObject* attachedObject = sourceNode->getAttachedObject(0);

    Ogre::Vector3 position       = sourceNode->getPosition();
    Ogre::Vector3 size           = Ogre::Vector3::UNIT_SCALE;
    Ogre::Vector3 centerOffset   = Ogre::Vector3::ZERO;
    Ogre::Vector3 scale          = sourceNode->_getDerivedScale();
    Ogre::Vector3 dimensions     = scale;
    Ogre::Quaternion orientation = sourceNode->_getDerivedOrientation();

	Ogre::AxisAlignedBox boundingBox = attachedObject->getBoundingBox();
	Ogre::Vector3 padding = (boundingBox.getMaximum() - boundingBox.getMinimum()) * Ogre::MeshManager::getSingleton().getBoundsPaddingFactor() * 2;

	size = (boundingBox.getMaximum() - boundingBox.getMinimum()) - padding * 2;
	centerOffset = boundingBox.getMinimum() + padding + (size / 2.0f);
	dimensions = sourceNode->_getDerivedScale() * size;

    OgreNewt::ConvexCollisionPtr collision = OgreNewt::ConvexCollisionPtr(new OgreNewt::CollisionPrimitives::Box(world, size, objectId));
    OgreNewt::ConvexModifierCollision* modifiedCollision = new OgreNewt::ConvexModifierCollision(world, collision, objectId);

    Ogre::Matrix4 modifierMatrix;
    modifierMatrix.makeTransform(centerOffset, scale, Ogre::Quaternion::IDENTITY);

    modifiedCollision->setScalarMatrix(modifierMatrix);

    OgreNewt::ConvexCollisionPtr col(modifiedCollision);

    OgreNewt::Body* body = new OgreNewt::Body(world, col, objectId);

	if (materialId != NULL)
	{
		body->setMaterialGroupID(materialId);
	}

    Ogre::Vector3 inertia, offset;
    modifiedCollision->calculateInertialMatrix(inertia, offset);

    body->setMassMatrix(mass, inertia * mass);
    body->setCenterOfMass(offset);
    body->setStandardForceCallback();
    body->attachNode(sourceNode);
    body->setPositionOrientation(position, orientation);

	boxes.insert(std::make_pair(sourceNode->getName(), body));

	return body;
}

OgreNewt::Body* PrimitiveFactory::getBox(Ogre::String name)
{
	for (BodyMap::iterator it = boxes.begin(); it != boxes.end(); it++)
	{
		if (it->second->getOgreNode()->getName() == name)
		{
			return it->second;
		}
	}

	return NULL;
}

OgreNewt::Body* PrimitiveFactory::createEllipsoid(Ogre::String name, Ogre::String material, Ogre::Real mass, Ogre::Vector3 position, Ogre::Vector3 scale, Ogre::Quaternion orientation, OgreNewt::MaterialID* materialId, int objectId, Ogre::String mesh)
{
	Ogre::SceneNode* node = createNode(mesh, name, material, position, scale, orientation);

	return createEllipsoid(node, mass, materialId, objectId);
}

OgreNewt::Body* PrimitiveFactory::createEllipsoid(Ogre::SceneNode* sourceNode, float mass, OgreNewt::MaterialID* materialId, int objectId)
{
	if (sourceNode == NULL)
	{
		return NULL;
	}

	if (sourceNode->numAttachedObjects() == 0)
	{
		return NULL;
	}

	Ogre::MovableObject* attachedObject = sourceNode->getAttachedObject(0);

    Ogre::Vector3 position       = sourceNode->getPosition();
    Ogre::Vector3 size           = Ogre::Vector3::UNIT_SCALE;
    Ogre::Vector3 centerOffset   = Ogre::Vector3::ZERO;
    Ogre::Vector3 scale          = sourceNode->_getDerivedScale();
    Ogre::Vector3 dimensions     = scale;
    Ogre::Quaternion orientation = sourceNode->_getDerivedOrientation();

	Ogre::AxisAlignedBox boundingBox = attachedObject->getBoundingBox();
	Ogre::Vector3 padding = (boundingBox.getMaximum() - boundingBox.getMinimum()) * Ogre::MeshManager::getSingleton().getBoundsPaddingFactor() * 2;

	size = (boundingBox.getMaximum() - boundingBox.getMinimum()) - padding * 2.0f;
	centerOffset = boundingBox.getMinimum() + padding + (size / 2.0f);
	dimensions = sourceNode->_getDerivedScale() * size;

    OgreNewt::ConvexCollisionPtr collision = OgreNewt::ConvexCollisionPtr(new OgreNewt::CollisionPrimitives::Ellipsoid(world, size / 2.0f, objectId));
    OgreNewt::ConvexModifierCollision* modifiedCollision = new OgreNewt::ConvexModifierCollision(world, collision, objectId);

    Ogre::Matrix4 modifierMatrix;
    modifierMatrix.makeTransform(centerOffset, scale, Ogre::Quaternion::IDENTITY);

    modifiedCollision->setScalarMatrix(modifierMatrix);

    OgreNewt::ConvexCollisionPtr col(modifiedCollision);

    OgreNewt::Body* body = new OgreNewt::Body(world, col, objectId);

	if (materialId != NULL)
	{
		body->setMaterialGroupID(materialId);
	}

    Ogre::Vector3 inertia, offset;
    modifiedCollision->calculateInertialMatrix(inertia, offset);

    body->setMassMatrix(mass, inertia * mass);
    body->setCenterOfMass(offset);
    body->setStandardForceCallback();
    body->attachNode(sourceNode);
    body->setPositionOrientation(position, orientation);

	ellipsoids.insert(std::make_pair(sourceNode->getName(), body));

	return body;
}

OgreNewt::Body* PrimitiveFactory::getEllipsoid(Ogre::String name)
{
	for (BodyMap::iterator it = ellipsoids.begin(); it != ellipsoids.end(); it++)
	{
		if (it->second->getOgreNode()->getName() == name)
		{
			return it->second;
		}
	}

	return NULL;
}

OgreNewt::Body* PrimitiveFactory::createCylinder(Ogre::String name, Ogre::String material, Ogre::Real mass, Ogre::Vector3 position, float radius, float height, Ogre::Quaternion orientation, OgreNewt::MaterialID* materialId, int objectId, Ogre::String mesh)
{
	Ogre::Vector3 scale(radius * 2, height, radius * 2);

	Ogre::SceneNode* node = createNode(mesh, name, material, position, scale, orientation);

	return createCylinder(node, mass, materialId, objectId);
}

OgreNewt::Body* PrimitiveFactory::createCylinder(Ogre::SceneNode* sourceNode, float mass, OgreNewt::MaterialID* materialId, int objectId)
{
	if (sourceNode == NULL)
	{
		return NULL;
	}

	if (sourceNode->numAttachedObjects() == 0)
	{
		return NULL;
	}

	Ogre::MovableObject* attachedObject = sourceNode->getAttachedObject(0);

    Ogre::Vector3 position       = sourceNode->getPosition();
    Ogre::Vector3 size           = Ogre::Vector3::UNIT_SCALE;
    Ogre::Vector3 centerOffset   = Ogre::Vector3::ZERO;
    Ogre::Vector3 scale          = sourceNode->_getDerivedScale();
    Ogre::Vector3 dimensions     = scale;
    Ogre::Quaternion orientation = sourceNode->_getDerivedOrientation();

	Ogre::AxisAlignedBox boundingBox = attachedObject->getBoundingBox();
	Ogre::Vector3 padding = (boundingBox.getMaximum() - boundingBox.getMinimum()) * Ogre::MeshManager::getSingleton().getBoundsPaddingFactor() * 2;

	size = (boundingBox.getMaximum() - boundingBox.getMinimum()) - padding;
	centerOffset = boundingBox.getMinimum() + ((boundingBox.getMaximum() - boundingBox.getMinimum()) / 2.0f);
	dimensions = sourceNode->_getDerivedScale() * size;

	float radius = ((size.x > size.z) ? size.x : size.z) / 2.0f;
    float height = size.y;

    OgreNewt::ConvexCollisionPtr collision = OgreNewt::ConvexCollisionPtr(new OgreNewt::CollisionPrimitives::Cylinder(world, radius, height, objectId));
    OgreNewt::ConvexModifierCollision* modifiedCollision = new OgreNewt::ConvexModifierCollision(world, collision, objectId);

	Ogre::Quaternion rotation(Ogre::Degree(90), Ogre::Vector3::UNIT_Z);
    Ogre::Vector3 rotatedScale(scale.y, scale.x, scale.z);

    Ogre::Matrix4 modifierMatrix;
    modifierMatrix.makeTransform(centerOffset, rotatedScale, rotation);

    modifiedCollision->setScalarMatrix(modifierMatrix);

    OgreNewt::ConvexCollisionPtr col(modifiedCollision);

    OgreNewt::Body* body = new OgreNewt::Body(world, col, objectId);

	if (materialId != NULL)
	{
		body->setMaterialGroupID(materialId);
	}

    Ogre::Vector3 inertia, offset;
    modifiedCollision->calculateInertialMatrix(inertia, offset);

    body->setMassMatrix(mass, inertia * mass);
    body->setCenterOfMass(offset);
    body->setStandardForceCallback();
    body->attachNode(sourceNode);
    body->setPositionOrientation(position, orientation);

	cylinders.insert(std::make_pair(sourceNode->getName(), body));

	return body;
}

OgreNewt::Body* PrimitiveFactory::getCylinder(Ogre::String name)
{
	for (BodyMap::iterator it = cylinders.begin(); it != cylinders.end(); it++)
	{
		if (it->second->getOgreNode()->getName() == name)
		{
			return it->second;
		}
	}

	return NULL;
}

OgreNewt::Body* PrimitiveFactory::createChamferCylinder(Ogre::String name, Ogre::String material, Ogre::Real mass, Ogre::Vector3 position, float radius, float height, Ogre::Quaternion orientation, OgreNewt::MaterialID* materialId, int objectId, Ogre::String mesh)
{
	Ogre::Vector3 scale(radius, height, radius);

	Ogre::SceneNode* node = createNode(mesh, name, material, position, scale, orientation);

	return createChamferCylinder(node, mass, materialId, objectId);
}

OgreNewt::Body* PrimitiveFactory::createChamferCylinder(Ogre::SceneNode* sourceNode, float mass, OgreNewt::MaterialID* materialId, int objectId)
{
	if (sourceNode == NULL)
	{
		return NULL;
	}

	if (sourceNode->numAttachedObjects() == 0)
	{
		return NULL;
	}

	Ogre::MovableObject* attachedObject = sourceNode->getAttachedObject(0);

    Ogre::Vector3 position       = sourceNode->getPosition();
    Ogre::Vector3 size           = Ogre::Vector3::UNIT_SCALE;
    Ogre::Vector3 centerOffset   = Ogre::Vector3::ZERO;
    Ogre::Vector3 scale          = sourceNode->_getDerivedScale();
    Ogre::Vector3 dimensions     = scale;
    Ogre::Quaternion orientation = sourceNode->_getDerivedOrientation();

	Ogre::AxisAlignedBox boundingBox = attachedObject->getBoundingBox();
	Ogre::Vector3 padding = (boundingBox.getMaximum() - boundingBox.getMinimum()) * Ogre::MeshManager::getSingleton().getBoundsPaddingFactor() * 2;

	size = (boundingBox.getMaximum() - boundingBox.getMinimum()) - padding * 2.0f;
	centerOffset = boundingBox.getMinimum() + padding + (size / 2.0f);
	dimensions = sourceNode->_getDerivedScale() * size;

	float radius = ((size.x > size.z) ? size.x : size.z) / 2.0f;
    float height = size.y;

    OgreNewt::ConvexCollisionPtr collision = OgreNewt::ConvexCollisionPtr(new OgreNewt::CollisionPrimitives::ChamferCylinder(world, radius, height, objectId));
    OgreNewt::ConvexModifierCollision* modifiedCollision = new OgreNewt::ConvexModifierCollision(world, collision, objectId);

	Ogre::Quaternion rotation(Ogre::Degree(90), Ogre::Vector3::UNIT_Z);
    Ogre::Vector3 rotatedScale(scale.y, scale.x, scale.z);

    Ogre::Matrix4 modifierMatrix;
    modifierMatrix.makeTransform(centerOffset, rotatedScale, rotation);

    modifiedCollision->setScalarMatrix(modifierMatrix);

    OgreNewt::ConvexCollisionPtr col(modifiedCollision);

    OgreNewt::Body* body = new OgreNewt::Body(world, col, objectId);

	if (materialId != NULL)
	{
		body->setMaterialGroupID(materialId);
	}

    Ogre::Vector3 inertia, offset;
    modifiedCollision->calculateInertialMatrix(inertia, offset);

    body->setMassMatrix(mass, inertia * mass);
    body->setCenterOfMass(offset);
    body->setStandardForceCallback();
    body->attachNode(sourceNode);
    body->setPositionOrientation(position, orientation);

	chamferCylinders.insert(std::make_pair(sourceNode->getName(), body));

	return body;
}

OgreNewt::Body* PrimitiveFactory::getChamferCylinder(Ogre::String name)
{
	for (BodyMap::iterator it = chamferCylinders.begin(); it != chamferCylinders.end(); it++)
	{
		if (it->second->getOgreNode()->getName() == name)
		{
			return it->second;
		}
	}

	return NULL;
}

OgreNewt::Body* PrimitiveFactory::createCone(Ogre::String name, Ogre::String material, Ogre::Real mass, Ogre::Vector3 position, float radius, float height, Ogre::Quaternion orientation, OgreNewt::MaterialID* materialId, int objectId, Ogre::String mesh)
{
	Ogre::Vector3 scale(radius, height, radius);

	Ogre::SceneNode* node = createNode(mesh, name, material, position, scale, orientation);

	return createCone(node, mass, materialId, objectId);
}

OgreNewt::Body* PrimitiveFactory::createCone(Ogre::SceneNode* sourceNode, float mass, OgreNewt::MaterialID* materialId, int objectId)
{
	if (sourceNode == NULL)
	{
		return NULL;
	}

	if (sourceNode->numAttachedObjects() == 0)
	{
		return NULL;
	}

	Ogre::MovableObject* attachedObject = sourceNode->getAttachedObject(0);

    Ogre::Vector3 position       = sourceNode->getPosition();
    Ogre::Vector3 size           = Ogre::Vector3::UNIT_SCALE;
    Ogre::Vector3 centerOffset   = Ogre::Vector3::ZERO;
    Ogre::Vector3 scale          = sourceNode->_getDerivedScale();
    Ogre::Vector3 dimensions     = scale;
    Ogre::Quaternion orientation = sourceNode->_getDerivedOrientation();

	Ogre::AxisAlignedBox boundingBox = attachedObject->getBoundingBox();
	Ogre::Vector3 padding = (boundingBox.getMaximum() - boundingBox.getMinimum()) * Ogre::MeshManager::getSingleton().getBoundsPaddingFactor() * 2;

	size = (boundingBox.getMaximum() - boundingBox.getMinimum()) - padding * 2.0f;
	centerOffset = boundingBox.getMinimum() + padding + (size / 2.0f);
	dimensions = sourceNode->_getDerivedScale() * size;

	float radius = ((size.x > size.z) ? size.x : size.z) / 2.0f;
    float height = size.y;

    OgreNewt::ConvexCollisionPtr collision = OgreNewt::ConvexCollisionPtr(new OgreNewt::CollisionPrimitives::Cone(world, radius, height, objectId));
    OgreNewt::ConvexModifierCollision* modifiedCollision = new OgreNewt::ConvexModifierCollision(world, collision, objectId);

	Ogre::Quaternion rotation(Ogre::Degree(90), Ogre::Vector3::UNIT_Z);
    Ogre::Vector3 rotatedScale(scale.y, scale.x, scale.z);

    Ogre::Matrix4 modifierMatrix;
    modifierMatrix.makeTransform(centerOffset, rotatedScale, rotation);

    modifiedCollision->setScalarMatrix(modifierMatrix);

    OgreNewt::ConvexCollisionPtr col(modifiedCollision);

    OgreNewt::Body* body = new OgreNewt::Body(world, col, objectId);

	if (materialId != NULL)
	{
		body->setMaterialGroupID(materialId);
	}

    Ogre::Vector3 inertia, offset;
    modifiedCollision->calculateInertialMatrix(inertia, offset);

    body->setMassMatrix(mass, inertia * mass);
    body->setCenterOfMass(offset);
    body->setStandardForceCallback();
    body->attachNode(sourceNode);
    body->setPositionOrientation(position, orientation);

	cones.insert(std::make_pair(sourceNode->getName(), body));

	return body;
}

OgreNewt::Body* PrimitiveFactory::getCone(Ogre::String name)
{
	for (BodyMap::iterator it = cones.begin(); it != cones.end(); it++)
	{
		if (it->second->getOgreNode()->getName() == name)
		{
			return it->second;
		}
	}

	return NULL;
}

OgreNewt::Body* PrimitiveFactory::createConvexHull(Ogre::String mesh, Ogre::String name, Ogre::String material, Ogre::Real mass, Ogre::Vector3 position, Ogre::Vector3 scale, Ogre::Quaternion orientation, OgreNewt::MaterialID* materialId, int objectId)
{
	Ogre::SceneNode* node = createNode(mesh, name, material, position, scale, orientation);

	return createConvexHull(node, mass, materialId, objectId);
}

OgreNewt::Body* PrimitiveFactory::createConvexHull(Ogre::SceneNode* sourceNode, float mass, OgreNewt::MaterialID* materialId, int objectId)
{
	if (sourceNode == NULL)
	{
		return NULL;
	}

	if (sourceNode->numAttachedObjects() == 0)
	{
		return NULL;
	}

	Ogre::MovableObject* attachedObject = sourceNode->getAttachedObject(0);

    Ogre::Vector3 position       = sourceNode->getPosition();
    Ogre::Vector3 size           = Ogre::Vector3::UNIT_SCALE;
    Ogre::Vector3 centerOffset   = Ogre::Vector3::ZERO;
    Ogre::Vector3 scale          = sourceNode->_getDerivedScale();
    Ogre::Vector3 dimensions     = scale;
    Ogre::Quaternion orientation = sourceNode->_getDerivedOrientation();

	Ogre::AxisAlignedBox boundingBox = attachedObject->getBoundingBox();
    Ogre::Vector3 padding = (boundingBox.getMaximum() - boundingBox.getMinimum()) * Ogre::MeshManager::getSingleton().getBoundsPaddingFactor() * 2;

    size = (boundingBox.getMaximum() - boundingBox.getMinimum()) - padding * 2.0f;
    centerOffset = boundingBox.getMinimum() + padding + (size / 2.0f);
    dimensions = sourceNode->_getDerivedScale() * size;

    Ogre::Entity* entity = static_cast<Ogre::Entity*>(attachedObject);

    OgreNewt::ConvexCollisionPtr collision = OgreNewt::ConvexCollisionPtr(new OgreNewt::CollisionPrimitives::ConvexHull(world, entity, objectId));
    
    OgreNewt::Body* body = new OgreNewt::Body(world, collision, objectId);

	if (materialId != NULL)
	{
		body->setMaterialGroupID(materialId);
	}

    Ogre::Vector3 inertia, offset;
    collision->calculateInertialMatrix(inertia, offset);

    body->setMassMatrix(mass, inertia * mass);
    body->setCenterOfMass(offset);
    body->setStandardForceCallback();
    body->attachNode(sourceNode);
    body->setPositionOrientation(position, orientation);

	convexHulls.insert(std::make_pair(sourceNode->getName(), body));

	return body;
}

OgreNewt::Body* PrimitiveFactory::getConvexHull(Ogre::String name)
{
	for (BodyMap::iterator it = convexHulls.begin(); it != convexHulls.end(); it++)
	{
		if (it->second->getOgreNode()->getName() == name)
		{
			return it->second;
		}
	}

	return NULL;
}

OgreNewt::Body* PrimitiveFactory::createTreeCollision(Ogre::String mesh, Ogre::String name, Ogre::String material, Ogre::Vector3 position, Ogre::Vector3 scale, Ogre::Quaternion orientation, OgreNewt::MaterialID* materialId, int objectId, bool optimize)
{
	Ogre::SceneNode* node = createNode(mesh, name, material, position, scale, orientation);

	return createTreeCollision(node, materialId, objectId, optimize);
}

OgreNewt::Body* PrimitiveFactory::createTreeCollision(Ogre::SceneNode* sourceNode, OgreNewt::MaterialID* materialId, int objectId, bool optimize)
{
	if (sourceNode == NULL)
	{
		return NULL;
	}

	if (sourceNode->numAttachedObjects() == 0)
	{
		return NULL;
	}

    Ogre::Vector3 position       = sourceNode->_getDerivedPosition();
    Ogre::Quaternion orientation = sourceNode->_getDerivedOrientation();

	OgreNewt::Body* body = NULL;

	for (int i = 0; i < sourceNode->numAttachedObjects(); i++)
	{
		Ogre::MovableObject* attachedObject = sourceNode->getAttachedObject(i);
		Ogre::Entity* entity = static_cast<Ogre::Entity*>(attachedObject);

		OgreNewt::CollisionPtr collision = OgreNewt::CollisionPtr(new OgreNewt::CollisionPrimitives::TreeCollision(world, entity, optimize, objectId));
	    
		body = new OgreNewt::Body(world, collision, objectId);

		if (materialId != NULL)
		{
			body->setMaterialGroupID(materialId);
		}

		body->attachNode(sourceNode);
		body->setPositionOrientation(position, orientation);

		treeCollisions.insert(std::make_pair(sourceNode->getName() + (i > 0 ? "_"+Ogre::StringConverter::toString(i) : ""), body));
	}

	return body;
}

OgreNewt::Body* PrimitiveFactory::getTreeCollision(Ogre::String name)
{
	for (BodyMap::iterator it = treeCollisions.begin(); it != treeCollisions.end(); it++)
	{
		if (it->second->getOgreNode()->getName() == name)
		{
			return it->second;
		}
	}

	return NULL;
}

OgreNewt::Body* PrimitiveFactory::getBody(Ogre::String name)
{
	OgreNewt::Body* body;

	if ((body = getBox(name)) != NULL)
	{
		return body;
	}

	if ((body = getEllipsoid(name)) != NULL)
	{
		return body;
	}

	if ((body = getCylinder(name)) != NULL)
	{
		return body;
	}

	if ((body = getChamferCylinder(name)) != NULL)
	{
		return body;
	}

	if ((body = getCone(name)) != NULL)
	{
		return body;
	}

	if ((body = getConvexHull(name)) != NULL)
	{
		return body;
	}

	if ((body = getTreeCollision(name)) != NULL)
	{
		return body;
	}

	return NULL;
}

Ogre::SceneNode* PrimitiveFactory::createNode(Ogre::String mesh, Ogre::String name, Ogre::String material, Ogre::Vector3 position, Ogre::Vector3 scale, Ogre::Quaternion orientation)
{
	if (name == "")
	{
		name = "FactoryObject" + Ogre::StringConverter::toString(generatedObjectCount++);
	}

	Ogre::Entity* entity = sceneManager->createEntity(name, mesh);

	if (material != "")
	{
		entity->setMaterialName(material);
	}

	entity->setCastShadows(true);
	
	Ogre::SceneNode* node = sceneManager->getRootSceneNode()->createChildSceneNode(name);

	node->attachObject(entity);
	node->setScale(scale);
	node->setPosition(position);
	node->setOrientation(orientation);

	return node;
}

PrimitiveFactory* PrimitiveFactory::getSingletonPtr(void)
{
    return ms_Singleton;
}

PrimitiveFactory& PrimitiveFactory::getSingleton(void)
{  
    assert(ms_Singleton);
	return (*ms_Singleton);
}
