// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
#pragma once
#if COMPILE_WITH_PHYSICS_COOKING
#include "Engine/Core/Types/DataContainer.h"
#include "Engine/Physics/CollisionData.h"
#include "Engine/Graphics/Models/ModelData.h"
#include "Engine/Content/Assets/ModelBase.h"
#include "Engine/Physics/PhysicsBackend.h"
#define CONVEX_VERTEX_MIN 8
#define CONVEX_VERTEX_MAX 255
///
/// Physical collision data cooking tools. Allows to bake heightfield, convex and triangle mesh colliders data.
///
class CollisionCooking
{
public:
struct CookingInput
{
int32 VertexCount = 0;
Float3* VertexData = nullptr;
int32 IndexCount = 0;
void* IndexData = nullptr;
bool Is16bitIndexData = false;
ConvexMeshGenerationFlags ConvexFlags = ConvexMeshGenerationFlags::None;
int32 ConvexVertexLimit = 255;
};
///
/// Collision data cooking input argument format.
///
struct Argument
{
CollisionDataType Type = CollisionDataType::None;
ModelData* OverrideModelData = nullptr;
AssetReference Model;
int32 ModelLodIndex = 0;
uint32 MaterialSlotsMask = MAX_uint32;
ConvexMeshGenerationFlags ConvexFlags = ConvexMeshGenerationFlags::None;
int32 ConvexVertexLimit = 255;
};
///
/// Attempts to cook a convex mesh from the provided mesh data. Assumes the input data is valid and contains vertex
/// positions. If the method returns false the resulting convex mesh will be in the output parameter.
///
/// The input.
/// The output.
/// True if failed, otherwise false.
static bool CookConvexMesh(CookingInput& input, BytesContainer& output);
///
/// Attempts to cook a triangle mesh from the provided mesh data. Assumes the input data is valid and contains vertex
/// positions as well as face indices. If the method returns false the resulting convex mesh will be in the output parameter.
///
/// The input.
/// The output.
/// True if failed, otherwise false.
static bool CookTriangleMesh(CookingInput& input, BytesContainer& output);
///
/// Cooks a heightfield. The results are written to the stream. To create a heightfield object there is an option to precompute some of calculations done while loading the heightfield data.
///
/// The heightfield columns count.
/// The heightfield rows count.
/// The heightfield data.
/// The user stream to output the cooked data.
/// True if failed, otherwise false.
static bool CookHeightField(int32 cols, int32 rows, const PhysicsBackend::HeightFieldSample* data, WriteStream& stream);
///
/// Cooks the collision from the model and prepares the data for the format.
///
/// The input argument descriptor.
/// The output options container.
/// The output data container.
/// True if failed, otherwise false.
static bool CookCollision(const Argument& arg, CollisionData::SerializedOptions& outputOptions, BytesContainer& outputData);
};
#endif