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.
This commit is contained in:
yyc12345 2024-10-29 15:12:00 +08:00
parent 4d04b38d52
commit 73cda9f905
3 changed files with 150 additions and 30 deletions

View File

@ -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
/// <summary>The representation of invalid raw pointer.</summary>
internal static readonly IntPtr INVALID_PTR = IntPtr.Zero;
/// <summary>The representation of invalid CK_ID.</summary>
@ -35,10 +37,54 @@ namespace BMapSharp.BMapWrapper {
Console.WriteLine(msg);
}
#endregion
#region Help Functions
private static void StructAssigner<T>(IntPtr pstruct, uint count, IEnumerable<T> iem) {
var stride = Marshal.SizeOf<T>();
var itor = iem.GetEnumerator();
for (uint i = 0; i < count; ++i) {
BMapException.ThrowIfFailed(itor.MoveNext());
Marshal.StructureToPtr<T>(itor.Current, pstruct, false);
pstruct += stride;
}
}
internal static void VxVector3Assigner(IntPtr pstruct, uint count, IEnumerable<VxVector3> iem)
=> StructAssigner<VxVector3>(pstruct, count, iem);
internal static void VxVector2Assigner(IntPtr pstruct, uint count, IEnumerable<VxVector2> iem)
=> StructAssigner<VxVector2>(pstruct, count, iem);
internal static void CKFaceIndicesAssigner(IntPtr pstruct, uint count, IEnumerable<CKFaceIndices> iem)
=> StructAssigner<CKFaceIndices>(pstruct, count, iem);
internal static void CKShortFaceIndicesAssigner(IntPtr pstruct, uint count, IEnumerable<CKShortFaceIndices> iem)
=> StructAssigner<CKShortFaceIndices>(pstruct, count, iem); // TODO: There is a padding bug!!!
private static IEnumerable<T> StructIterator<T>(IntPtr pstruct, uint count) {
var stride = Marshal.SizeOf<T>();
for (uint i = 0; i < count; ++i) {
yield return Marshal.PtrToStructure<T>(pstruct);
pstruct += stride;
}
}
internal static IEnumerable<VxVector3> VxVector3Iterator(IntPtr pstruct, uint count)
=> StructIterator<VxVector3>(pstruct, count);
internal static IEnumerable<VxVector2> VxVector2Iterator(IntPtr pstruct, uint count)
=> StructIterator<VxVector2>(pstruct, count);
internal static IEnumerable<CKFaceIndices> CKFaceIndicesIterator(IntPtr pstruct, uint count)
=> StructIterator<CKFaceIndices>(pstruct, count);
internal static IEnumerable<CKShortFaceIndices> CKShortFaceIndicesIterator(IntPtr pstruct, uint count)
=> StructIterator<CKShortFaceIndices>(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<BM3dObject> 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<BMGroup>(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()) { }
}
}

View File

@ -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. */

View File

@ -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 ? "<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());
// }
}