LumixEngine/src/renderer/model.h

234 lines
4.4 KiB
C++

#pragma once
#include "engine/array.h"
#include "engine/flag_set.h"
#include "engine/geometry.h"
#include "engine/hash_map.h"
#include "engine/math.h"
#include "engine/string.h"
#include "engine/math.h"
#include "engine/resource.h"
#include "gpu/gpu.h"
#include "renderer.h"
struct lua_State;
namespace Lumix
{
class Material;
struct Mesh;
class Model;
struct Pose;
class Renderer;
class InputMemoryStream;
struct LUMIX_RENDERER_API RayCastModelHit
{
bool is_hit;
float t;
DVec3 origin;
Vec3 dir;
Mesh* mesh;
EntityPtr entity;
ComponentType component_type;
};
struct LUMIX_RENDERER_API Mesh
{
enum class AttributeSemantic : u8
{
POSITION,
NORMAL,
TANGENT,
BITANGENT,
COLOR0,
COLOR1,
INDICES,
WEIGHTS,
TEXCOORD0,
TEXCOORD1,
INSTANCE0,
INSTANCE1,
INSTANCE2,
COUNT,
NONE = 0xff
};
struct RenderData
{
gpu::BufferHandle vertex_buffer_handle;
u32 vb_stride;
gpu::BufferHandle index_buffer_handle;
gpu::DataType index_type;
int indices_count;
};
struct Skin
{
Vec4 weights;
i16 indices[4];
};
enum Type : u8
{
RIGID,
SKINNED,
LAST_TYPE
};
enum Flags : u8
{
INDICES_16_BIT = 1 << 0
};
Mesh(Material* mat,
const gpu::VertexDecl& vertex_decl,
u8 vb_stride,
const char* name,
const AttributeSemantic* semantics,
Renderer& renderer,
IAllocator& allocator);
void setMaterial(Material* material, Model& model, Renderer& renderer);
bool areIndices16() const { return flags.isSet(Flags::INDICES_16_BIT); }
Type type;
Array<u8> indices;
Array<Vec3> vertices;
Array<Skin> skin;
FlagSet<Flags, u8> flags;
u32 sort_key;
u8 layer;
String name;
Material* material;
gpu::VertexDecl vertex_decl;
AttributeSemantic attributes_semantic[gpu::VertexDecl::MAX_ATTRIBUTES];
RenderData* render_data;
static u32 s_last_sort_key;
};
struct LODMeshIndices
{
int from;
int to;
};
class LUMIX_RENDERER_API Model final : public Resource
{
public:
using BoneMap = HashMap<u32, int, HashFuncDirect<u32>>;
#pragma pack(1)
struct FileHeader
{
u32 magic;
u32 version;
};
#pragma pack()
enum class FileVersion : u32
{
LATEST // keep this last
};
struct LOD
{
int from_mesh;
int to_mesh;
float distance;
};
struct Bone
{
enum { MAX_COUNT = 196 };
explicit Bone(IAllocator& allocator)
: name(allocator)
, parent_idx(-1)
{
}
String name;
LocalRigidTransform transform;
LocalRigidTransform relative_transform;
LocalRigidTransform inv_bind_transform;
int parent_idx;
};
static const ResourceType TYPE;
public:
Model(const Path& path, ResourceManager& resource_manager, Renderer& renderer, IAllocator& allocator);
~Model();
ResourceType getType() const override { return TYPE; }
LODMeshIndices getLODMeshIndices(float squared_distance) const
{
int i = 0;
while (squared_distance >= m_lods[i].distance) ++i;
return {m_lods[i].from_mesh, m_lods[i].to_mesh};
}
Mesh& getMesh(u32 index) { return m_meshes[index]; }
const Mesh& getMesh(u32 index) const { return m_meshes[index]; }
int getMeshCount() const { return m_meshes.size(); }
int getBoneCount() const { return m_bones.size(); }
const Bone& getBone(u32 i) const { return m_bones[i]; }
int getFirstNonrootBoneIndex() const { return m_first_nonroot_bone_index; }
BoneMap::const_iterator getBoneIndex(u32 hash) const { return m_bone_map.find(hash); }
void getPose(Pose& pose);
void getRelativePose(Pose& pose);
float getBoundingRadius() const { return m_bounding_radius; }
RayCastModelHit castRay(const Vec3& origin, const Vec3& dir, const Pose* pose);
const AABB& getAABB() const { return m_aabb; }
const LOD* getLODs() const { return m_lods; }
LOD* getLODs() { return m_lods; }
void onBeforeReady() override;
bool isSkinned() const;
static void registerLuaAPI(lua_State* L);
public:
static const u32 FILE_MAGIC = 0x5f4c4d4f; // == '_LM2'
static const u32 MAX_LOD_COUNT = 4;
private:
Model(const Model&);
void operator=(const Model&);
bool parseBones(InputMemoryStream& file);
bool parseMeshes(InputMemoryStream& file, FileVersion version);
bool parseLODs(InputMemoryStream& file);
int getBoneIdx(const char* name);
void unload() override;
bool load(u64 size, const u8* mem) override;
private:
IAllocator& m_allocator;
Renderer& m_renderer;
Array<Mesh> m_meshes;
Array<Bone> m_bones;
LOD m_lods[MAX_LOD_COUNT];
float m_bounding_radius;
BoneMap m_bone_map;
AABB m_aabb;
int m_first_nonroot_bone_index;
};
} // namespace Lumix