AABBTree* CollisionManager::getAABBTree(SceneObject* scno, int collisionBlockFlags) {
	SharedObjectTemplate* templateObject = scno->getObjectTemplate();

	if (templateObject == NULL)
		return NULL;

	if (!(templateObject->getCollisionActionBlockFlags() & collisionBlockFlags))
		return NULL;

	PortalLayout* portalLayout = templateObject->getPortalLayout();
	MeshAppearanceTemplate* mesh = NULL;

	if (portalLayout != NULL) {
		mesh = portalLayout->getMeshAppearanceTemplate(0);
	} else {
		AppearanceTemplate* appTemplate = templateObject->getAppearanceTemplate();

		if (appTemplate == NULL)
			return NULL;

		mesh = dynamic_cast<MeshAppearanceTemplate*>(appTemplate->getFirstMesh());
	}

	if (mesh == NULL)
		return NULL;

	return mesh->getAABBTree();
}
bool CollisionManager::checkLineOfSightWorldToCell(const Vector3& rayOrigin, const Vector3& rayEnd, float distance, CellObject* cellObject) {
	ManagedReference<SceneObject*> building = cellObject->getParent();

	if (building == NULL)
		return true;

	SharedObjectTemplate* objectTemplate = building->getObjectTemplate();
	PortalLayout* portalLayout = objectTemplate->getPortalLayout();

	if (portalLayout == NULL)
		return true;

	Ray ray = convertToModelSpace(rayOrigin, rayEnd, building);

	if (cellObject->getCellNumber() >= portalLayout->getAppearanceTemplatesSize())
		return true;

	MeshAppearanceTemplate* app = portalLayout->getMeshAppearanceTemplate(cellObject->getCellNumber());

	AABBTree* aabbTree = app->getAABBTree();

	if (aabbTree == NULL)
		return true;

	float intersectionDistance;
	Triangle* triangle = NULL;

	if (aabbTree->intersects(ray, distance, intersectionDistance, triangle, true))
		return false;

	return true;
}
bool CollisionManager::checkLineOfSightInParentCell(SceneObject* object, Vector3& endPoint) {
	ManagedReference<SceneObject*> parent = object->getParent();

	if (parent == NULL || !parent->isCellObject())
		return true;

	CellObject* cell = cast<CellObject*>( parent.get());

	SharedObjectTemplate* objectTemplate = parent->getRootParent().get()->getObjectTemplate();
	PortalLayout* portalLayout = objectTemplate->getPortalLayout();
	MeshAppearanceTemplate* appearanceMesh = NULL;

	if (portalLayout == NULL)
		return true;

	try {
		appearanceMesh = portalLayout->getMeshAppearanceTemplate(cell->getCellNumber());
	} catch (Exception& e) {
		return true;
	}

	if (appearanceMesh == NULL) {
		//info("null appearance mesh ");
		return true;
	}

	AABBTree* aabbTree = appearanceMesh->getAABBTree();

	if (aabbTree == NULL)
		return true;

	//switching Y<->Z, adding 0.1 to account floor
	Vector3 startPoint = object->getPosition();
	startPoint.set(startPoint.getX(), startPoint.getY(), startPoint.getZ() + 0.1f);

	endPoint.set(endPoint.getX(), endPoint.getY(), endPoint.getZ() + 0.1f);

	Vector3 dir = endPoint - startPoint;
	dir.normalize();

	float distance = endPoint.distanceTo(startPoint);
	float intersectionDistance;

	Ray ray(startPoint, dir);

	Triangle* triangle = NULL;

	//nothing in the middle
	if (aabbTree->intersects(ray, distance, intersectionDistance, triangle, true))
		return false;

	Ray ray2(endPoint, Vector3(0, -1, 0));

	//check if we are in the cell with dir (0, -1, 0)
	if (!aabbTree->intersects(ray2, 64000.f, intersectionDistance, triangle, true))
		return false;

	return true;
}
bool CollisionManager::checkLineOfSightInBuilding(SceneObject* object1, SceneObject* object2, SceneObject* building) {
	SharedObjectTemplate* objectTemplate = building->getObjectTemplate();
	PortalLayout* portalLayout = objectTemplate->getPortalLayout();

	if (portalLayout == NULL)
		return true;

	//we are in model space... in cells
	Vector3 rayOrigin = object1->getPosition();
	rayOrigin.set(rayOrigin.getX(), rayOrigin.getY(), rayOrigin.getZ() + 1.f);

	Vector3 rayEnd = object2->getPosition();
	rayEnd.set(rayEnd.getX(), rayEnd.getY(), rayEnd.getZ() + 1.f);

	Vector3 direction(Vector3(rayEnd - rayOrigin));
	direction.normalize();

	float distance = rayEnd.distanceTo(rayOrigin);
	float intersectionDistance;

	Ray ray(rayOrigin, direction);
	Triangle* triangle = NULL;

	// we check interior cells
	for (int i = 1; i < portalLayout->getAppearanceTemplatesSize(); ++i) {
		MeshAppearanceTemplate* app = portalLayout->getMeshAppearanceTemplate(i);

		AABBTree* aabbTree = app->getAABBTree();

		if (aabbTree == NULL)
			continue;

		if (aabbTree->intersects(ray, distance, intersectionDistance, triangle, true))
			return false;
	}

	return true;
}