AABBox<float> CollisionConvexHullShape::toAABBox(const PhysicsTransform &physicsTransform) const
	{
		if(!lastTransform.equals(physicsTransform))
		{
			const Quaternion<float> &orientation = physicsTransform.getOrientation();
			Point3<float> min(std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max());
			Point3<float> max(-std::numeric_limits<float>::max(), -std::numeric_limits<float>::max(), -std::numeric_limits<float>::max());
			const std::vector<Point3<float>> &convexHullShapePoints = convexHullShape->getPoints();
			for (const auto &convexHullShapePoint : convexHullShapePoints)
			{
				const Point3<float> point = orientation.rotatePoint(convexHullShapePoint);

				min.X = std::min(min.X, point.X);
				min.Y = std::min(min.Y, point.Y);
				min.Z = std::min(min.Z, point.Z);

				max.X = std::max(max.X, point.X);
				max.Y = std::max(max.Y, point.Y);
				max.Z = std::max(max.Z, point.Z);
			}

			const Point3<float> &position = physicsTransform.getPosition();

			lastAABBox = AABBox<float>(min + position, max + position);
			lastTransform = physicsTransform;
		}
		return lastAABBox;
	}
	ConvexHull3D<float> CollisionConvexHullShape::transformConvexHull(const ConvexHull3D<float> &convexHullToTransform, const PhysicsTransform &physicsTransform) const
	{
		std::map<unsigned int, Point3<float>> transformedIndexedPoints;
		for(std::map<unsigned int, Point3<float>>::const_iterator it = convexHullToTransform.getIndexedPoints().begin(); it!=convexHullToTransform.getIndexedPoints().end(); ++it)
		{
			transformedIndexedPoints[it->first] = physicsTransform.transform(it->second);
		}

		return ConvexHull3D<float>(transformedIndexedPoints, convexHullToTransform.getIndexedTriangles());
	}
	AABBox<float> CollisionConvexHullShape::toAABBox(const PhysicsTransform &physicsTransform) const
	{
		const Point3<float> &pos = physicsTransform.getPosition();
		const Matrix3<float> &orientation = physicsTransform.getOrientationMatrix();

		//build AABBox
		Point3<float> min(std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max());
		Point3<float> max(-std::numeric_limits<float>::max(), -std::numeric_limits<float>::max(), -std::numeric_limits<float>::max());
		const std::vector<Point3<float>> &convexHullPoints = convexHull.getPoints();
		for(std::vector<Point3<float>>::const_iterator it=convexHullPoints.begin(); it!=convexHullPoints.end(); ++it)
		{
			const Point3<float> point = orientation * (*it);

			if(min.X > point.X)
			{
				min.X = point.X;
			}
			if(min.Y > point.Y)
			{
				min.Y = point.Y;
			}
			if(min.Z > point.Z)
			{
				min.Z = point.Z;
			}

			if(max.X < point.X)
			{
				max.X = point.X;
			}
			if(max.Y < point.Y)
			{
				max.Y = point.Y;
			}
			if(max.Z < point.Z)
			{
				max.Z = point.Z;
			}
		}

		return AABBox<float>(min + pos, max + pos);
	}
	AABBox<float> CollisionCompoundShape::toAABBox(const PhysicsTransform &physicsTransform) const
	{
		Point3<float> rotatedTranslation = physicsTransform.getOrientation().rotatePoint(Point3<float>(localizedShapes[0]->translation));
		Point3<float> finalPosition = physicsTransform.getPosition().translate(rotatedTranslation.toVector());
		PhysicsTransform shapeWorldTransform(finalPosition, physicsTransform.getOrientation());
		AABBox<float> globalCompoundBox = localizedShapes[0]->shape->toAABBox(shapeWorldTransform);

		for(unsigned int i=1; i<localizedShapes.size(); ++i)
		{
			rotatedTranslation = physicsTransform.getOrientation().rotatePoint(Point3<float>(localizedShapes[i]->translation));
			finalPosition = physicsTransform.getPosition().translate(rotatedTranslation.toVector());
			shapeWorldTransform.setPosition(finalPosition);

			AABBox<float> compoundBox = localizedShapes[i]->shape->toAABBox(shapeWorldTransform);

			globalCompoundBox = globalCompoundBox.merge(compoundBox);
		}

		return globalCompoundBox;
	}
	std::unique_ptr<CollisionConvexObject3D, ObjectDeleter> CollisionConvexHullShape::toConvexObject(const PhysicsTransform &physicsTransform) const
	{
		Transform<float> transform = physicsTransform.toTransform();
        auto convexHullWithMargin = std::shared_ptr<ConvexHull3D<float>>(dynamic_cast<ConvexHull3D<float>*>(convexHullShape->toConvexObject(transform).release()));

        void *memPtr = getObjectsPool()->allocate(sizeof(CollisionConvexHullObject));

		if(!convexHullShapeReduced)
		{ //impossible to compute convex hull without margin => use convex hull with margin and set a margin of 0.0
			#ifdef _DEBUG
            	assert(getInnerMargin()==0.0f);
    		#endif
            const std::shared_ptr<ConvexHull3D<float>> &convexHullWithoutMargin(convexHullWithMargin);

            auto *collisionObjectPtr = new (memPtr) CollisionConvexHullObject(getInnerMargin(), convexHullWithMargin, convexHullWithoutMargin);
            return std::unique_ptr<CollisionConvexHullObject, ObjectDeleter>(collisionObjectPtr);
		}

        auto convexHullWithoutMargin = std::shared_ptr<ConvexHull3D<float>>(dynamic_cast<ConvexHull3D<float>*>(convexHullShapeReduced->toConvexObject(transform).release()));

        auto *collisionObjectPtr = new (memPtr) CollisionConvexHullObject(getInnerMargin(), convexHullWithMargin, convexHullWithoutMargin);
        return std::unique_ptr<CollisionConvexHullObject, ObjectDeleter>(collisionObjectPtr);
	}