using System; using System.Numerics; using System.Runtime.InteropServices; namespace Raylib_cs; /// /// Bone information /// [StructLayout(LayoutKind.Sequential)] public unsafe struct BoneInfo { /// /// Bone name (char[32]) /// public fixed sbyte Name[32]; /// /// Bone parent /// public int Parent; /// /// Bone name as string /// public string NameToString() { fixed (sbyte* name = Name) { return Utf8StringUtils.GetUTF8String(name); } } } /// /// Skeleton, animation bones hierarchy /// [StructLayout(LayoutKind.Sequential)] public unsafe struct ModelSkeleton { /// /// Number of bones /// public int BoneCount; /// /// Bones information (skeleton) /// public BoneInfo* Bones; /// /// Bones base transformation (Transform[]) /// public Transform* BindPose; public Span BindPoseAsSpan() { if (BindPose == null || BoneCount <= 0) { return Span.Empty; } return new Span(BindPose, BoneCount); } public Span BonesAsSpan() { if (Bones == null || BoneCount <= 0) { return Span.Empty; } return new Span(Bones, BoneCount); } } // Note: // Anim pose, an array of Transform[] // typedef Transform *ModelAnimPose; It's just a pointer array. /// /// Model type /// [StructLayout(LayoutKind.Sequential)] public unsafe struct Model { /// /// Local transform matrix /// public Matrix4x4 Transform; /// /// Number of meshes /// public int MeshCount; /// /// Number of materials /// public int MaterialCount; /// /// Meshes array (Mesh *) /// public Mesh* Meshes; /// /// Materials array (Material *) /// public Material* Materials; /// /// Mesh material number (int *) /// public int* MeshMaterial; /// /// Skeleton for animation /// public ModelSkeleton Skeleton; /// /// Current animation pose (Transform[]) /// public Transform* CurrentPose; /// /// Bones animated transformation matrices /// public Matrix4x4* BoneMatrices; /// /// Bones animated transformation matrices as span. Based on Skeleton.BoneCount length /// public Span BoneMatricesAsSpan() { if (BoneMatrices == null || Skeleton.BoneCount <= 0) { return Span.Empty; } return new Span(BoneMatrices, Skeleton.BoneCount); } /// /// Current animation pose as span. Based on Skeleton.BoneCount length /// public Span CurrentPoseAsSpan() { if (CurrentPose == null || Skeleton.BoneCount <= 0) { return Span.Empty; } return new Span(CurrentPose, Skeleton.BoneCount); } /// /// Mesh material number as span. Based on MaterialCount length /// public Span MeshMaterialAsSpan() { if (MeshMaterial == null || MaterialCount <= 0) { return Span.Empty; } return new Span(MeshMaterial, MaterialCount); } /// /// Meshes as span. based on MeshCount length /// public Span MeshesAsSpan() { if (Meshes == null || MeshCount <= 0) { return Span.Empty; } return new Span(Meshes, MeshCount); } } /// /// ModelAnimation, contains a full animation sequence /// [StructLayout(LayoutKind.Sequential)] public unsafe struct ModelAnimation { /// /// Animation name (char[32]) /// public fixed sbyte Name[32]; /// /// Number of bones /// public readonly int BoneCount; /// /// Number of animation key frames /// public readonly int KeyFrameCount; /// /// Animation sequence keyframe poses [keyframe][pose] /// public Transform** KeyframePoses; /// /// Animation sequence keyframe poses as span. Based on KeyFrameCount length /// public Span GetKeyFramePoseAsSpan(int frame) { if (KeyframePoses == null || frame < 0 || frame >= KeyFrameCount) { return Span.Empty; } var pose = KeyframePoses[frame]; if (pose == null || BoneCount <= 0) { return Span.Empty; } return new Span(KeyframePoses[frame], KeyFrameCount); } /// /// Animation name as string /// public string NameToString() { fixed (sbyte* name = Name) { return Utf8StringUtils.GetUTF8String(name); } } }