From 73cda9f905e6be2f72e13a7d048f738deae2a5ca Mon Sep 17 00:00:00 2001 From: yyc12345 Date: Tue, 29 Oct 2024 15:12:00 +0800 Subject: [PATCH] feat: update BMapSharp - add struct assigner and iterator but still has bugs (struct padding issue) - add function bindings for BM3dObject and BMGroup. - add basic ctor and dtor for BMMeshTrans. --- .../BMapSharp/BMapSharp/BMapWrapper.cs | 127 ++++++++++++++++-- .../BMapSharp/BMapSharp/VirtoolsTypes.cs | 12 ++ .../BMapSharp/BMapSharpTestbench/Program.cs | 41 +++--- 3 files changed, 150 insertions(+), 30 deletions(-) diff --git a/BMapBindings/BMapSharp/BMapSharp/BMapWrapper.cs b/BMapBindings/BMapSharp/BMapSharp/BMapWrapper.cs index be32901..60d25f2 100644 --- a/BMapBindings/BMapSharp/BMapSharp/BMapWrapper.cs +++ b/BMapBindings/BMapSharp/BMapSharp/BMapWrapper.cs @@ -1,5 +1,4 @@ using System; -using System.Reflection.Metadata.Ecma335; using System.Runtime.InteropServices; using BMapSharp.VirtoolsTypes; @@ -23,6 +22,9 @@ namespace BMapSharp.BMapWrapper { } public static class Utils { + + #region Constant Values + /// The representation of invalid raw pointer. internal static readonly IntPtr INVALID_PTR = IntPtr.Zero; /// The representation of invalid CK_ID. @@ -35,10 +37,54 @@ namespace BMapSharp.BMapWrapper { Console.WriteLine(msg); } + #endregion + + #region Help Functions + + private static void StructAssigner(IntPtr pstruct, uint count, IEnumerable iem) { + var stride = Marshal.SizeOf(); + var itor = iem.GetEnumerator(); + for (uint i = 0; i < count; ++i) { + BMapException.ThrowIfFailed(itor.MoveNext()); + Marshal.StructureToPtr(itor.Current, pstruct, false); + pstruct += stride; + } + } + internal static void VxVector3Assigner(IntPtr pstruct, uint count, IEnumerable iem) + => StructAssigner(pstruct, count, iem); + internal static void VxVector2Assigner(IntPtr pstruct, uint count, IEnumerable iem) + => StructAssigner(pstruct, count, iem); + internal static void CKFaceIndicesAssigner(IntPtr pstruct, uint count, IEnumerable iem) + => StructAssigner(pstruct, count, iem); + internal static void CKShortFaceIndicesAssigner(IntPtr pstruct, uint count, IEnumerable iem) + => StructAssigner(pstruct, count, iem); // TODO: There is a padding bug!!! + + private static IEnumerable StructIterator(IntPtr pstruct, uint count) { + var stride = Marshal.SizeOf(); + for (uint i = 0; i < count; ++i) { + yield return Marshal.PtrToStructure(pstruct); + pstruct += stride; + } + } + internal static IEnumerable VxVector3Iterator(IntPtr pstruct, uint count) + => StructIterator(pstruct, count); + internal static IEnumerable VxVector2Iterator(IntPtr pstruct, uint count) + => StructIterator(pstruct, count); + internal static IEnumerable CKFaceIndicesIterator(IntPtr pstruct, uint count) + => StructIterator(pstruct, count); + internal static IEnumerable CKShortFaceIndicesIterator(IntPtr pstruct, uint count) + => StructIterator(pstruct, count); // TODO: There is a padding bug!!! + + #endregion + + #region End User Exposed + private static readonly BMapGuard Singleton = new BMapGuard(); public static bool IsBMapAvailable() { return !Singleton.IsInvalid; } + + #endregion } public abstract class AbstractPointer : SafeHandle { @@ -49,8 +95,8 @@ namespace BMapSharp.BMapWrapper { public override bool IsInvalid => this.handle == Utils.INVALID_PTR; protected override bool ReleaseHandle() => throw new NotImplementedException(); - protected bool isValid() => this.handle != Utils.INVALID_PTR; - protected IntPtr getPointer() => this.handle; + internal bool isValid() => this.handle != Utils.INVALID_PTR; + internal IntPtr getPointer() => this.handle; // protected AbstractPointer(IntPtr raw_pointer) : base(raw_pointer, true) {} @@ -87,10 +133,8 @@ namespace BMapSharp.BMapWrapper { // #endregion #region Misc - public override int GetHashCode() => this.handle.GetHashCode(); public override string ToString() => this.handle.ToString(); - #endregion } @@ -105,9 +149,9 @@ namespace BMapSharp.BMapWrapper { protected override bool ReleaseHandle() => throw new NotImplementedException(); private readonly uint m_CKID; - protected bool isValid() => this.handle != Utils.INVALID_PTR && m_CKID != Utils.INVALID_CKID; - protected IntPtr getPointer() => this.handle; - protected uint getCKID() => m_CKID; + internal bool isValid() => this.handle != Utils.INVALID_PTR && m_CKID != Utils.INVALID_CKID; + internal IntPtr getPointer() => this.handle; + internal uint getCKID() => m_CKID; // private uint m_CKID; @@ -156,15 +200,11 @@ namespace BMapSharp.BMapWrapper { internal BMObject(IntPtr raw_pointer, uint ckid) : base(raw_pointer, ckid) { } public string GetName() { - BMapException.ThrowIfFailed(BMap.BMObject_GetName( - this.getPointer(), this.getCKID(), out string out_name - )); + BMapException.ThrowIfFailed(BMap.BMObject_GetName(getPointer(), getCKID(), out string out_name)); return out_name; } public void SetName(string name) { - BMapException.ThrowIfFailed(BMap.BMObject_SetName( - this.getPointer(), this.getCKID(), name - )); + BMapException.ThrowIfFailed(BMap.BMObject_SetName(getPointer(), getCKID(), name)); } } @@ -182,10 +222,56 @@ namespace BMapSharp.BMapWrapper { public class BM3dObject : BMObject { internal BM3dObject(IntPtr raw_pointer, uint ckid) : base(raw_pointer, ckid) { } + + public VxMatrix GetWorldMatrix() { + BMapException.ThrowIfFailed(BMap.BM3dObject_GetWorldMatrix(getPointer(), getCKID(), out VxMatrix out_mat)); + return out_mat; + } + + public void SetWorldMatrix(VxMatrix mat) { + BMapException.ThrowIfFailed(BMap.BM3dObject_SetWorldMatrix(getPointer(), getCKID(), mat)); + } + + public BMMesh GetCurrentMesh() { + BMapException.ThrowIfFailed(BMap.BM3dObject_GetCurrentMesh(getPointer(), getCKID(), out uint out_meshid)); + if (out_meshid == Utils.INVALID_CKID) return null; + else return new BMMesh(getPointer(), out_meshid); + } + + public void SetCurrentMesh(BMMesh mesh) { + uint meshid = (mesh is null) ? Utils.INVALID_CKID : mesh.getCKID(); + BMapException.ThrowIfFailed(BMap.BM3dObject_SetCurrentMesh(getPointer(), getCKID(), meshid)); + } + + public bool GetVisibility() { + BMapException.ThrowIfFailed(BMap.BM3dObject_GetVisibility(getPointer(), getCKID(), out bool out_isVisible)); + return out_isVisible; + } + + public void SetVisibility(bool visb) { + BMapException.ThrowIfFailed(BMap.BM3dObject_SetVisibility(getPointer(), getCKID(), visb)); + } } public class BMGroup : BMObject { internal BMGroup(IntPtr raw_pointer, uint ckid) : base(raw_pointer, ckid) { } + + public void AddObject(BM3dObject member) { + BMapException.ThrowIfFailed(BMap.BMGroup_AddObject(getPointer(), getCKID(), member.getCKID())); + } + + public uint GetObjectCount() { + BMapException.ThrowIfFailed(BMap.BMGroup_GetObjectCount(getPointer(), getCKID(), out uint out_count)); + return out_count; + } + + public IEnumerable GetObjects() { + var size = GetObjectCount(); + for (uint i = 0; i < size; ++i) { + BMapException.ThrowIfFailed(BMap.BMGroup_GetObject(getPointer(), getCKID(), i, out uint out_objid)); + yield return new BM3dObject(getPointer(), out_objid); + } + } } public sealed class BMFileReader : AbstractPointer { @@ -272,4 +358,17 @@ namespace BMapSharp.BMapWrapper { public BMGroup CreateGroup() => createCKObject(BMap.BMFile_CreateGroup, (bmf, id) => new BMGroup(bmf, id)); } + public sealed class BMMeshTrans : AbstractPointer { + private static IntPtr allocateHandle() { + BMapException.ThrowIfFailed(BMap.BMMeshTrans_New(out IntPtr out_trans)); + return out_trans; + } + protected override bool ReleaseHandle() { + return BMap.BMMeshTrans_Delete(this.getPointer()); + } + public BMMeshTrans() : base(allocateHandle()) { } + + + } + } diff --git a/BMapBindings/BMapSharp/BMapSharp/VirtoolsTypes.cs b/BMapBindings/BMapSharp/BMapSharp/VirtoolsTypes.cs index 416fe0c..df4374a 100644 --- a/BMapBindings/BMapSharp/BMapSharp/VirtoolsTypes.cs +++ b/BMapBindings/BMapSharp/BMapSharp/VirtoolsTypes.cs @@ -166,6 +166,18 @@ namespace BMapSharp.VirtoolsTypes { } } + [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Ansi)] + public struct CKShortFaceIndices { + [MarshalAs(UnmanagedType.U2)] + public ushort I1, I2, I3; + + public CKShortFaceIndices(ushort i1 = 0, ushort i2 = 0, ushort i3 = 0) { + I1 = i1; + I2 = i2; + I3 = i3; + } + } + public enum CK_TEXTURE_SAVEOPTIONS : uint { CKTEXTURE_RAWDATA = 0, /**< Save raw data inside file. The bitmap is saved in a raw 32 bit per pixel format. */ CKTEXTURE_EXTERNAL = 1, /**< Store only the file name for the texture. The bitmap file must be present in the bitmap paths when loading the composition. */ diff --git a/BMapBindings/BMapSharp/BMapSharpTestbench/Program.cs b/BMapBindings/BMapSharp/BMapSharpTestbench/Program.cs index 7bd5376..e92efcf 100644 --- a/BMapBindings/BMapSharp/BMapSharpTestbench/Program.cs +++ b/BMapBindings/BMapSharp/BMapSharpTestbench/Program.cs @@ -23,30 +23,39 @@ namespace BMapSharpTestbench { string[] encodings = ["cp1252", "gb2312"]; using (var reader = new BMapSharp.BMapWrapper.BMFileReader(file_name, temp_folder, texture_folder, encodings)) { - Console.WriteLine("===== Groups ====="); - foreach (var gp in reader.GetGroups()) { - Console.WriteLine(gp.GetName()); - } + // Console.WriteLine("===== Groups ====="); + // foreach (var gp in reader.GetGroups()) { + // Console.WriteLine(gp.GetName()); + // foreach (var gp_item in gp.GetObjects()) { + // Console.WriteLine($"\t{gp_item.GetName()}"); + // } + // } Console.WriteLine("===== 3dObjects ====="); foreach (var obj in reader.Get3dObjects()) { Console.WriteLine(obj.GetName()); + + var current_mesh = obj.GetCurrentMesh(); + var mesh_name = current_mesh is null ? "" : current_mesh.GetName(); + Console.WriteLine($"\tMesh: {mesh_name}"); + Console.WriteLine($"\tVisibility: {obj.GetVisibility()}"); + Console.WriteLine($"\tMatrix: {obj.GetWorldMatrix().ToManaged()}"); } - Console.WriteLine("===== Meshes ====="); - foreach (var mesh in reader.GetMeshes()) { - Console.WriteLine(mesh.GetName()); - } + // Console.WriteLine("===== Meshes ====="); + // foreach (var mesh in reader.GetMeshes()) { + // Console.WriteLine(mesh.GetName()); + // } - Console.WriteLine("===== Materials ====="); - foreach (var mtl in reader.GetMaterials()) { - Console.WriteLine(mtl.GetName()); - } + // Console.WriteLine("===== Materials ====="); + // foreach (var mtl in reader.GetMaterials()) { + // Console.WriteLine(mtl.GetName()); + // } - Console.WriteLine("===== Textures ====="); - foreach (var tex in reader.GetTextures()) { - Console.WriteLine(tex.GetName()); - } + // Console.WriteLine("===== Textures ====="); + // foreach (var tex in reader.GetTextures()) { + // Console.WriteLine(tex.GetName()); + // } }