From 6ca492b204c205f0b6b09ebc4414637d14c5ccce Mon Sep 17 00:00:00 2001 From: Salvage <29021710+Saalvage@users.noreply.github.com> Date: Tue, 10 Dec 2024 03:55:38 +0100 Subject: [PATCH] WIP work --- AssimpNet/AssimpContext.cs | 41 ++++---- AssimpNet/AssimpNet.csproj | 2 +- AssimpNet/Bone.cs | 2 +- AssimpNet/ExportDataBlob.cs | 10 +- AssimpNet/MemoryHelper.cs | 116 ++------------------- AssimpNet/Scene.cs | 4 +- AssimpNet/Unmanaged/UnmanagedStructures.cs | 14 +-- 7 files changed, 49 insertions(+), 140 deletions(-) diff --git a/AssimpNet/AssimpContext.cs b/AssimpNet/AssimpContext.cs index d8ba7ed..8979bde 100755 --- a/AssimpNet/AssimpContext.cs +++ b/AssimpNet/AssimpContext.cs @@ -176,21 +176,27 @@ public Scene ImportFileFromStream(Stream stream, string formatHint = null) /// The imported scene /// Thrown if the stream is not valid (null or write-only). /// Thrown if the context has already been disposed of. - public Scene ImportFileFromStream(Stream stream, PostProcessSteps postProcessFlags, string formatHint = null) + public unsafe Scene ImportFileFromStream(Stream stream, PostProcessSteps postProcessFlags, string formatHint = null) { CheckDisposed(); if(stream == null || stream.CanRead != true) throw new AssimpException(nameof(stream), "Can't read from the stream it's null or write-only"); - IntPtr ptr = IntPtr.Zero; + AiScene* ptr = null; PrepareImport(); + var bytes = MemoryHelper.ReadStreamFully(stream, 0); + try { - ptr = AssimpLibrary.Instance.ImportFileFromStream(stream, PostProcessSteps.None, formatHint, m_propStore); + fixed (byte* buffer = bytes) + { + ptr = AssimpLibrary.aiImportFileFromMemoryWithProperties(buffer, (uint)bytes.Length, PostProcessSteps.None, + formatHint, m_propStore); + } - if(ptr == IntPtr.Zero) + if (ptr == null) throw new AssimpException("Error importing file: " + AssimpLibrary.Instance.GetErrorString()); TransformScene(ptr); @@ -203,9 +209,9 @@ public Scene ImportFileFromStream(Stream stream, PostProcessSteps postProcessFla { CleanupImport(); - if(ptr != IntPtr.Zero) + if(ptr != null) { - AssimpLibrary.Instance.ReleaseImport(ptr); + AssimpLibrary.aiReleaseImport(ptr); } } } @@ -264,11 +270,11 @@ public unsafe Scene ImportFile(string file, PostProcessSteps postProcessFlags) if(ptr == null) throw new AssimpException("Error importing file: " + AssimpLibrary.Instance.GetErrorString()); - TransformScene(new(ptr)); + TransformScene(ptr); - ptr = (AiScene*)ApplyPostProcessing(new(ptr), postProcessFlags); + ptr = (AiScene*)ApplyPostProcessing(ptr, postProcessFlags); - return Scene.FromUnmanagedScene(new(ptr)); + return Scene.FromUnmanagedScene(ptr); } finally { @@ -276,7 +282,7 @@ public unsafe Scene ImportFile(string file, PostProcessSteps postProcessFlags) if(ptr != null) { - AssimpLibrary.Instance.ReleaseImport(new(ptr)); + AssimpLibrary.aiReleaseImport(ptr); } } } @@ -1013,7 +1019,7 @@ private void BuildMatrix() } //Transforms the root node of the scene and writes it back to the native structure - private bool TransformScene(IntPtr scene) + private unsafe bool TransformScene(AiScene* scene) { BuildMatrix(); @@ -1021,11 +1027,10 @@ private bool TransformScene(IntPtr scene) { if(!m_scaleRot.IsIdentity) { - AiScene aiScene = MemoryHelper.MarshalStructure(scene); - if(aiScene.RootNode == IntPtr.Zero) + if(scene->RootNode == IntPtr.Zero) return false; - IntPtr matrixPtr = aiScene.RootNode + MemoryHelper.SizeOf(); //Skip over Node Name + IntPtr matrixPtr = scene->RootNode + MemoryHelper.SizeOf(); //Skip over Node Name Matrix4x4 matrix = MemoryHelper.Read(matrixPtr); //Get the root transform matrix = matrix * m_scaleRot; //Transform @@ -1044,14 +1049,14 @@ private bool TransformScene(IntPtr scene) return false; } - private IntPtr ApplyPostProcessing(IntPtr scene, PostProcessSteps postProcessFlags) + private unsafe AiScene* ApplyPostProcessing(AiScene* scene, PostProcessSteps postProcessFlags) { - if(postProcessFlags == PostProcessSteps.None || scene == IntPtr.Zero) + if(postProcessFlags == PostProcessSteps.None || scene == null) return scene; - scene = AssimpLibrary.Instance.ApplyPostProcessing(scene, postProcessFlags); + scene = AssimpLibrary.aiApplyPostProcessing(scene, postProcessFlags); - if(scene == IntPtr.Zero) + if(scene == null) { string error = AssimpLibrary.Instance.GetErrorString(); throw new AssimpException(error.Length == 0 diff --git a/AssimpNet/AssimpNet.csproj b/AssimpNet/AssimpNet.csproj index e82def5..3cac855 100755 --- a/AssimpNet/AssimpNet.csproj +++ b/AssimpNet/AssimpNet.csproj @@ -10,7 +10,7 @@ true Nicholas Woodfield, Salvage - 5.4.3.0 + 5.4.3.1 License.txt Copyright © 2012-2020 Nicholas Woodfield, © 2024 Salvage logo.png diff --git a/AssimpNet/Bone.cs b/AssimpNet/Bone.cs index 84d4d7b..ebe7ce3 100755 --- a/AssimpNet/Bone.cs +++ b/AssimpNet/Bone.cs @@ -154,7 +154,7 @@ public static void FreeNative(IntPtr nativeValue, bool freeNative) int numWeights = MemoryHelper.Read(nativeValue + MemoryHelper.SizeOf()); IntPtr weightsPtr = nativeValue + MemoryHelper.SizeOf() + sizeof(uint); - if(aiBone.NumWeights > 0 && aiBone.Weights != IntPtr.Zero) + if(aiBone.NumWeights > 0 && aiBone.Weights != null) MemoryHelper.FreeMemory(aiBone.Weights); if(freeNative) diff --git a/AssimpNet/ExportDataBlob.cs b/AssimpNet/ExportDataBlob.cs index 60f9c9b..03befb7 100755 --- a/AssimpNet/ExportDataBlob.cs +++ b/AssimpNet/ExportDataBlob.cs @@ -77,18 +77,18 @@ public sealed class ExportDataBlob /// Creates a new ExportDataBlob. /// /// Unmanaged structure. - internal ExportDataBlob(ref AiExportDataBlob dataBlob) + internal unsafe ExportDataBlob(ref AiExportDataBlob dataBlob) { m_name = dataBlob.Name.GetString(); - if(dataBlob.Size.ToUInt32() > 0 && dataBlob.Data != IntPtr.Zero) - m_data = MemoryHelper.FromNativeArray(dataBlob.Data, (int) dataBlob.Size.ToUInt32()); + if(dataBlob.Size.ToUInt32() > 0 && dataBlob.Data != null) + m_data = MemoryHelper.FromNativeArray(dataBlob.Data, (int)dataBlob.Size.ToUInt32()); m_next = null; - if(dataBlob.NextBlob != IntPtr.Zero) + if(dataBlob.NextBlob != null) { - AiExportDataBlob nextBlob = MemoryHelper.MarshalStructure(dataBlob.NextBlob); + AiExportDataBlob nextBlob = *dataBlob.NextBlob; m_next = new ExportDataBlob(ref nextBlob); } } diff --git a/AssimpNet/MemoryHelper.cs b/AssimpNet/MemoryHelper.cs index 2acc67c..94de1a8 100755 --- a/AssimpNet/MemoryHelper.cs +++ b/AssimpNet/MemoryHelper.cs @@ -63,7 +63,7 @@ public static IntPtr ToNativeArray(IReadOnlyCollection return IntPtr.Zero; bool isNativeBlittable = IsNativeBlittable(managedColl); - int sizeofNative = (isNativeBlittable) ? SizeOf() : MarshalSizeOf(); + int sizeofNative = SizeOf(); //If the pointer is a void** we need to step by the pointer size, otherwise it's just a void* and step by the type size. int stride = (arrayOfPointers) ? IntPtr.Size : sizeofNative; @@ -218,9 +218,9 @@ public static IntPtr ToNativeArray(List managedArray) where T : struct /// Pointer to unmanaged memory /// Number of elements to read /// Managed array - public static T[] FromNativeArray(IntPtr nativeArray, int length) where T : struct + public static unsafe T[] FromNativeArray(void* nativeArray, int length) where T : struct { - if(nativeArray == IntPtr.Zero || length == 0) + if(nativeArray == null || length == 0) return Array.Empty(); T[] managedArray = new T[length]; @@ -305,118 +305,22 @@ public static IntPtr ToNativePointer(Managed managedValue) /// Unmanaged type /// Pointer to unmanaged memory /// The marshaled managed value - public static Managed FromNativePointer(IntPtr ptr) + public static unsafe Managed FromNativePointer(Native* ptr) where Managed : class, IMarshalable, new() where Native : struct { - if(ptr == IntPtr.Zero) + if(ptr == null) return null; Managed managedValue = Activator.CreateInstance(); - //Marshal pointer to structure - Native nativeValue; - - if(managedValue.IsNativeBlittable) - { - Read(ptr, out nativeValue); - } - else - { - MarshalStructure(ptr, out nativeValue); - } - //Populate managed value - managedValue.FromNative(nativeValue); + managedValue.FromNative(*ptr); return managedValue; } - /// - /// Convienence method for marshaling a pointer to a structure. Only use if the type is not blittable, otherwise - /// use the read methods for blittable types. - /// - /// Struct type - /// Pointer to marshal - /// The marshaled structure - public static void MarshalStructure(IntPtr ptr, out T value) where T : struct - { - if(ptr == IntPtr.Zero) - value = default(T); - - Type type = typeof(T); - - INativeCustomMarshaler marshaler; - if (HasNativeCustomMarshaler(type, out marshaler)) - { - value = (T)marshaler.MarshalNativeToManaged(ptr); - return; - } - - value = Marshal.PtrToStructure(ptr); - } - - /// - /// Convienence method for marshaling a pointer to a structure. Only use if the type is not blittable, otherwise - /// use the read methods for blittable types. - /// - /// Struct type - /// Pointer to marshal - /// The marshaled structure - public static T MarshalStructure(IntPtr ptr) where T : struct - { - if(ptr == IntPtr.Zero) - return default(T); - - Type type = typeof(T); - - INativeCustomMarshaler marshaler; - if (HasNativeCustomMarshaler(type, out marshaler)) - return (T) marshaler.MarshalNativeToManaged(ptr); - - return Marshal.PtrToStructure(ptr); - } - - /// - /// Convienence method for marshaling a structure to a pointer. Only use if the type is not blittable, otherwise - /// use the write methods for blittable types. - /// - /// Struct type - /// Struct to marshal - /// Pointer to unmanaged chunk of memory which must be allocated prior to this call - public static void MarshalPointer(in T value, IntPtr ptr) where T : struct - { - if (ptr == IntPtr.Zero) - return; - - INativeCustomMarshaler marshaler; - if (HasNativeCustomMarshaler(typeof(T), out marshaler)) - { - marshaler.MarshalManagedToNative((object)value, ptr); - return; - } - - Marshal.StructureToPtr(value, ptr, true); - } - - /// - /// Computes the size of the struct type using Marshal SizeOf. Only use if the type is not blittable, thus requiring marshaling by the runtime, - /// (e.g. has MarshalAs attributes), otherwise use the SizeOf methods for blittable types. - /// - /// Struct type - /// Size of the struct in bytes. - public static unsafe int MarshalSizeOf() where T : struct - { - Type type = typeof(T); - - INativeCustomMarshaler marshaler; - if (HasNativeCustomMarshaler(type, out marshaler)) - return marshaler.NativeDataSize; - - return Marshal.SizeOf(); - } - #endregion #region Memory Interop (Shared code from other Projects) @@ -559,9 +463,9 @@ public static unsafe void CopyMemory(IntPtr pDest, IntPtr pSrc, int sizeInBytesT /// Array to store the copied data /// Zero-based element index to start writing data to in the element array. /// Number of elements to copy - public static unsafe void Read(IntPtr pSrc, T[] data, int startIndexInArray, int count) where T : struct + public static unsafe void Read(void* pSrc, T[] data, int startIndexInArray, int count) where T : struct { - ReadOnlySpan src = new ReadOnlySpan(pSrc.ToPointer(), count); + ReadOnlySpan src = new ReadOnlySpan(pSrc, count); Span dst = new Span(data, startIndexInArray, count); src.CopyTo(dst); } @@ -583,9 +487,9 @@ public static unsafe T Read(IntPtr pSrc) where T : struct /// Struct type /// Pointer to memory location /// The read value. - public static unsafe void Read(IntPtr pSrc, out T value) where T : struct + public static unsafe void Read(T* pSrc, out T value) where T : struct { - value = Unsafe.ReadUnaligned(pSrc.ToPointer()); + value = Unsafe.ReadUnaligned(pSrc); } /// diff --git a/AssimpNet/Scene.cs b/AssimpNet/Scene.cs index defc96c..db8c299 100755 --- a/AssimpNet/Scene.cs +++ b/AssimpNet/Scene.cs @@ -273,9 +273,9 @@ public static IntPtr ToUnmanagedScene(Scene scene) /// /// The unmanaged scene data /// The managed scene, or null if the pointer is NULL - public static Scene FromUnmanagedScene(IntPtr scenePtr) + public static unsafe Scene FromUnmanagedScene(AiScene* scenePtr) { - if(scenePtr == IntPtr.Zero) + if(scenePtr == null) return null; return MemoryHelper.FromNativePointer(scenePtr); diff --git a/AssimpNet/Unmanaged/UnmanagedStructures.cs b/AssimpNet/Unmanaged/UnmanagedStructures.cs index c7c981c..d021b0e 100755 --- a/AssimpNet/Unmanaged/UnmanagedStructures.cs +++ b/AssimpNet/Unmanaged/UnmanagedStructures.cs @@ -408,7 +408,7 @@ public static string GetFormatHint(in AiTexture aiTex) /// Represents an aiFace struct. /// [StructLayout(LayoutKind.Sequential)] - public struct AiFace + public unsafe struct AiFace { /// /// Number of indices in the face. @@ -418,14 +418,14 @@ public struct AiFace /// /// unsigned int*, array of indices. /// - public IntPtr Indices; + public uint* Indices; } /// /// Represents an aiBone struct. /// [StructLayout(LayoutKind.Sequential)] - public struct AiBone + public unsafe struct AiBone { /// /// Name of the bone. @@ -450,7 +450,7 @@ public struct AiBone /// /// VertexWeight*, array of vertex weights. /// - public IntPtr Weights; + public VertexWeight* Weights; /// /// Matrix that transforms the vertex from mesh to bone space in bind pose @@ -1137,7 +1137,7 @@ public struct AiExportFormatDesc /// blobs represent auxillary files produced by the exporter (e.g. material files) and are named accordingly. /// [StructLayout(LayoutKind.Sequential)] - public struct AiExportDataBlob + public unsafe struct AiExportDataBlob { /// /// size_t, size of the data in bytes. @@ -1147,7 +1147,7 @@ public struct AiExportDataBlob /// /// void*, the data. /// - public IntPtr Data; + public void* Data; /// /// AiString, name of the blob. @@ -1157,7 +1157,7 @@ public struct AiExportDataBlob /// /// aiExportDataBlob*, pointer to the next blob in the chain. /// - public IntPtr NextBlob; + public AiExportDataBlob* NextBlob; } ///