From f44e5fb2fe0941bab31a229c1de883dcf1d37450 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Fri, 13 Aug 2021 10:04:44 +0200 Subject: [PATCH] Add support for `uint` as triangle indices for mesh updates API --- Source/Engine/Graphics/Mesh.cs | 101 +++++++++++++++++- Source/Engine/Graphics/Models/Mesh.cpp | 4 +- Source/Engine/Graphics/Models/Mesh.h | 4 +- Source/Engine/Graphics/Models/SkinnedMesh.cpp | 4 +- Source/Engine/Graphics/Models/SkinnedMesh.h | 15 ++- Source/Engine/Graphics/SkinnedMesh.cs | 38 ++++++- 6 files changed, 154 insertions(+), 12 deletions(-) diff --git a/Source/Engine/Graphics/Mesh.cs b/Source/Engine/Graphics/Mesh.cs index f96b4ce63..82491effd 100644 --- a/Source/Engine/Graphics/Mesh.cs +++ b/Source/Engine/Graphics/Mesh.cs @@ -144,7 +144,7 @@ namespace FlaxEngine if (colors != null && colors.Length != vertices.Length) throw new ArgumentOutOfRangeException(nameof(colors)); - if (Internal_UpdateMeshInt( + if (Internal_UpdateMeshUInt( __unmanagedPtr, vertices.Length, triangles.Length / 3, @@ -190,7 +190,100 @@ namespace FlaxEngine if (colors != null && colors.Count != vertices.Count) throw new ArgumentOutOfRangeException(nameof(colors)); - if (Internal_UpdateMeshInt( + if (Internal_UpdateMeshUInt( + __unmanagedPtr, + vertices.Count, + triangles.Count / 3, + Utils.ExtractArrayFromList(vertices), + Utils.ExtractArrayFromList(triangles), + Utils.ExtractArrayFromList(normals), + Utils.ExtractArrayFromList(tangents), + Utils.ExtractArrayFromList(uv), + Utils.ExtractArrayFromList(colors) + )) + throw new FlaxException("Failed to update mesh data."); + } + + /// + /// Updates the model mesh vertex and index buffer data. + /// Can be used only for virtual assets (see and ). + /// Mesh data will be cached and uploaded to the GPU with a delay. + /// + /// The mesh vertices positions. Cannot be null. + /// The mesh index buffer (clockwise triangles). Uses 32-bit stride buffer. Cannot be null. + /// The normal vectors (per vertex). + /// The normal vectors (per vertex). Use null to compute them from normal vectors. + /// The texture coordinates (per vertex). + /// The vertex colors (per vertex). + public void UpdateMesh(Vector3[] vertices, uint[] triangles, Vector3[] normals = null, Vector3[] tangents = null, Vector2[] uv = null, Color32[] colors = null) + { + // Validate state and input + if (!ParentModel.IsVirtual) + throw new InvalidOperationException("Only virtual models can be updated at runtime."); + if (vertices == null) + throw new ArgumentNullException(nameof(vertices)); + if (triangles == null) + throw new ArgumentNullException(nameof(triangles)); + if (triangles.Length == 0 || triangles.Length % 3 != 0) + throw new ArgumentOutOfRangeException(nameof(triangles)); + if (normals != null && normals.Length != vertices.Length) + throw new ArgumentOutOfRangeException(nameof(normals)); + if (tangents != null && tangents.Length != vertices.Length) + throw new ArgumentOutOfRangeException(nameof(tangents)); + if (tangents != null && normals == null) + throw new ArgumentException("If you specify tangents then you need to also provide normals for the mesh."); + if (uv != null && uv.Length != vertices.Length) + throw new ArgumentOutOfRangeException(nameof(uv)); + if (colors != null && colors.Length != vertices.Length) + throw new ArgumentOutOfRangeException(nameof(colors)); + + if (Internal_UpdateMeshUInt( + __unmanagedPtr, + vertices.Length, + triangles.Length / 3, + vertices, triangles, + normals, + tangents, + uv, + colors + )) + throw new FlaxException("Failed to update mesh data."); + } + + /// + /// Updates the model mesh vertex and index buffer data. + /// Can be used only for virtual assets (see and ). + /// Mesh data will be cached and uploaded to the GPU with a delay. + /// + /// The mesh vertices positions. Cannot be null. + /// The mesh index buffer (clockwise triangles). Uses 32-bit stride buffer. Cannot be null. + /// The normal vectors (per vertex). + /// The normal vectors (per vertex). Use null to compute them from normal vectors. + /// The texture coordinates (per vertex). + /// The vertex colors (per vertex). + public void UpdateMesh(List vertices, List triangles, List normals = null, List tangents = null, List uv = null, List colors = null) + { + // Validate state and input + if (!ParentModel.IsVirtual) + throw new InvalidOperationException("Only virtual models can be updated at runtime."); + if (vertices == null) + throw new ArgumentNullException(nameof(vertices)); + if (triangles == null) + throw new ArgumentNullException(nameof(triangles)); + if (triangles.Count == 0 || triangles.Count % 3 != 0) + throw new ArgumentOutOfRangeException(nameof(triangles)); + if (normals != null && normals.Count != vertices.Count) + throw new ArgumentOutOfRangeException(nameof(normals)); + if (tangents != null && tangents.Count != vertices.Count) + throw new ArgumentOutOfRangeException(nameof(tangents)); + if (tangents != null && normals == null) + throw new ArgumentException("If you specify tangents then you need to also provide normals for the mesh."); + if (uv != null && uv.Count != vertices.Count) + throw new ArgumentOutOfRangeException(nameof(uv)); + if (colors != null && colors.Count != vertices.Count) + throw new ArgumentOutOfRangeException(nameof(colors)); + + if (Internal_UpdateMeshUInt( __unmanagedPtr, vertices.Count, triangles.Count / 3, @@ -314,7 +407,7 @@ namespace FlaxEngine if (triangles.Length == 0 || triangles.Length % 3 != 0) throw new ArgumentOutOfRangeException(nameof(triangles)); - if (Internal_UpdateTrianglesInt( + if (Internal_UpdateTrianglesUInt( __unmanagedPtr, triangles.Length / 3, triangles @@ -338,7 +431,7 @@ namespace FlaxEngine if (triangles.Count == 0 || triangles.Count % 3 != 0) throw new ArgumentOutOfRangeException(nameof(triangles)); - if (Internal_UpdateTrianglesInt( + if (Internal_UpdateTrianglesUInt( __unmanagedPtr, triangles.Count / 3, Utils.ExtractArrayFromList(triangles) diff --git a/Source/Engine/Graphics/Models/Mesh.cpp b/Source/Engine/Graphics/Models/Mesh.cpp index ad64a3f61..3ae9b969f 100644 --- a/Source/Engine/Graphics/Models/Mesh.cpp +++ b/Source/Engine/Graphics/Models/Mesh.cpp @@ -608,7 +608,7 @@ ScriptingObject* Mesh::GetParentModel() return _model; } -bool Mesh::UpdateMeshInt(int32 vertexCount, int32 triangleCount, MonoArray* verticesObj, MonoArray* trianglesObj, MonoArray* normalsObj, MonoArray* tangentsObj, MonoArray* uvObj, MonoArray* colorsObj) +bool Mesh::UpdateMeshUInt(int32 vertexCount, int32 triangleCount, MonoArray* verticesObj, MonoArray* trianglesObj, MonoArray* normalsObj, MonoArray* tangentsObj, MonoArray* uvObj, MonoArray* colorsObj) { return ::UpdateMesh(this, (uint32)vertexCount, (uint32)triangleCount, verticesObj, trianglesObj, normalsObj, tangentsObj, uvObj, colorsObj); } @@ -618,7 +618,7 @@ bool Mesh::UpdateMeshUShort(int32 vertexCount, int32 triangleCount, MonoArray* v return ::UpdateMesh(this, (uint32)vertexCount, (uint32)triangleCount, verticesObj, trianglesObj, normalsObj, tangentsObj, uvObj, colorsObj); } -bool Mesh::UpdateTrianglesInt(int32 triangleCount, MonoArray* trianglesObj) +bool Mesh::UpdateTrianglesUInt(int32 triangleCount, MonoArray* trianglesObj) { return ::UpdateTriangles(this, triangleCount, trianglesObj); } diff --git a/Source/Engine/Graphics/Models/Mesh.h b/Source/Engine/Graphics/Models/Mesh.h index 4af23d3fe..483f15153 100644 --- a/Source/Engine/Graphics/Models/Mesh.h +++ b/Source/Engine/Graphics/Models/Mesh.h @@ -404,9 +404,9 @@ private: // Internal bindings API_FUNCTION(NoProxy) ScriptingObject* GetParentModel(); - API_FUNCTION(NoProxy) bool UpdateMeshInt(int32 vertexCount, int32 triangleCount, MonoArray* verticesObj, MonoArray* trianglesObj, MonoArray* normalsObj, MonoArray* tangentsObj, MonoArray* uvObj, MonoArray* colorsObj); + API_FUNCTION(NoProxy) bool UpdateMeshUInt(int32 vertexCount, int32 triangleCount, MonoArray* verticesObj, MonoArray* trianglesObj, MonoArray* normalsObj, MonoArray* tangentsObj, MonoArray* uvObj, MonoArray* colorsObj); API_FUNCTION(NoProxy) bool UpdateMeshUShort(int32 vertexCount, int32 triangleCount, MonoArray* verticesObj, MonoArray* trianglesObj, MonoArray* normalsObj, MonoArray* tangentsObj, MonoArray* uvObj, MonoArray* colorsObj); - API_FUNCTION(NoProxy) bool UpdateTrianglesInt(int32 triangleCount, MonoArray* trianglesObj); + API_FUNCTION(NoProxy) bool UpdateTrianglesUInt(int32 triangleCount, MonoArray* trianglesObj); API_FUNCTION(NoProxy) bool UpdateTrianglesUShort(int32 triangleCount, MonoArray* trianglesObj); API_FUNCTION(NoProxy) bool DownloadBuffer(bool forceGpu, MonoArray* resultObj, int32 typeI); }; diff --git a/Source/Engine/Graphics/Models/SkinnedMesh.cpp b/Source/Engine/Graphics/Models/SkinnedMesh.cpp index b5c67bff9..e75136cf2 100644 --- a/Source/Engine/Graphics/Models/SkinnedMesh.cpp +++ b/Source/Engine/Graphics/Models/SkinnedMesh.cpp @@ -418,9 +418,9 @@ bool UpdateMesh(SkinnedMesh* mesh, MonoArray* verticesObj, MonoArray* trianglesO return mesh->UpdateMesh(vertexCount, triangleCount, vb.Get(), ib); } -bool SkinnedMesh::UpdateMeshInt(MonoArray* verticesObj, MonoArray* trianglesObj, MonoArray* blendIndicesObj, MonoArray* blendWeightsObj, MonoArray* normalsObj, MonoArray* tangentsObj, MonoArray* uvObj) +bool SkinnedMesh::UpdateMeshUInt(MonoArray* verticesObj, MonoArray* trianglesObj, MonoArray* blendIndicesObj, MonoArray* blendWeightsObj, MonoArray* normalsObj, MonoArray* tangentsObj, MonoArray* uvObj) { - return ::UpdateMesh(this, verticesObj, trianglesObj, blendIndicesObj, blendWeightsObj, normalsObj, tangentsObj, uvObj); + return ::UpdateMesh(this, verticesObj, trianglesObj, blendIndicesObj, blendWeightsObj, normalsObj, tangentsObj, uvObj); } bool SkinnedMesh::UpdateMeshUShort(MonoArray* verticesObj, MonoArray* trianglesObj, MonoArray* blendIndicesObj, MonoArray* blendWeightsObj, MonoArray* normalsObj, MonoArray* tangentsObj, MonoArray* uvObj) diff --git a/Source/Engine/Graphics/Models/SkinnedMesh.h b/Source/Engine/Graphics/Models/SkinnedMesh.h index 108f36b33..462286b44 100644 --- a/Source/Engine/Graphics/Models/SkinnedMesh.h +++ b/Source/Engine/Graphics/Models/SkinnedMesh.h @@ -117,6 +117,19 @@ public: return UpdateMesh(vertexCount, triangleCount, vb, ib, false); } + /// + /// Updates the model mesh (used by the virtual models created with Init rather than Load). + /// + /// The amount of vertices in the vertex buffer. + /// The amount of triangles in the index buffer. + /// The vertex buffer data. + /// The index buffer in clockwise order. + /// True if failed, otherwise false. + FORCE_INLINE bool UpdateMesh(uint32 vertexCount, uint32 triangleCount, VB0SkinnedElementType* vb, uint32* ib) + { + return UpdateMesh(vertexCount, triangleCount, vb, ib, false); + } + /// /// Updates the model mesh (used by the virtual models created with Init rather than Load). /// @@ -245,7 +258,7 @@ private: // Internal bindings API_FUNCTION(NoProxy) ScriptingObject* GetParentModel(); - API_FUNCTION(NoProxy) bool UpdateMeshInt(MonoArray* verticesObj, MonoArray* trianglesObj, MonoArray* blendIndicesObj, MonoArray* blendWeightsObj, MonoArray* normalsObj, MonoArray* tangentsObj, MonoArray* uvObj); + API_FUNCTION(NoProxy) bool UpdateMeshUInt(MonoArray* verticesObj, MonoArray* trianglesObj, MonoArray* blendIndicesObj, MonoArray* blendWeightsObj, MonoArray* normalsObj, MonoArray* tangentsObj, MonoArray* uvObj); API_FUNCTION(NoProxy) bool UpdateMeshUShort(MonoArray* verticesObj, MonoArray* trianglesObj, MonoArray* blendIndicesObj, MonoArray* blendWeightsObj, MonoArray* normalsObj, MonoArray* tangentsObj, MonoArray* uvObj); API_FUNCTION(NoProxy) bool DownloadBuffer(bool forceGpu, MonoArray* resultObj, int32 typeI); }; diff --git a/Source/Engine/Graphics/SkinnedMesh.cs b/Source/Engine/Graphics/SkinnedMesh.cs index ea4cf283e..d6d77a01b 100644 --- a/Source/Engine/Graphics/SkinnedMesh.cs +++ b/Source/Engine/Graphics/SkinnedMesh.cs @@ -130,7 +130,43 @@ namespace FlaxEngine if (uv != null && uv.Length != vertices.Length) throw new ArgumentOutOfRangeException(nameof(uv)); - if (Internal_UpdateMeshInt(__unmanagedPtr, vertices, triangles, blendIndices, blendWeights, normals, tangents, uv)) + if (Internal_UpdateMeshUInt(__unmanagedPtr, vertices, triangles, blendIndices, blendWeights, normals, tangents, uv)) + throw new FlaxException("Failed to update mesh data."); + } + + /// + /// Updates the skinned model mesh vertex and index buffer data. + /// Can be used only for virtual assets (see and ). + /// Mesh data will be cached and uploaded to the GPU with a delay. + /// + /// The mesh vertices positions. Cannot be null. + /// The mesh index buffer (clockwise triangles). Uses 32-bit stride buffer. Cannot be null. + /// The skinned mesh blend indices buffer. Contains indices of the skeleton bones (up to 4 bones per vertex) to use for vertex position blending. Cannot be null. + /// The skinned mesh blend weights buffer (normalized). Contains weights per blend bone (up to 4 bones per vertex) of the skeleton bones to mix for vertex position blending. Cannot be null. + /// The normal vectors (per vertex). + /// The normal vectors (per vertex). Use null to compute them from normal vectors. + /// The texture coordinates (per vertex). + public void UpdateMesh(Vector3[] vertices, uint[] triangles, Int4[] blendIndices, Vector4[] blendWeights, Vector3[] normals = null, Vector3[] tangents = null, Vector2[] uv = null) + { + // Validate state and input + if (!ParentSkinnedModel.IsVirtual) + throw new InvalidOperationException("Only virtual skinned models can be updated at runtime."); + if (vertices == null) + throw new ArgumentNullException(nameof(vertices)); + if (triangles == null) + throw new ArgumentNullException(nameof(triangles)); + if (triangles.Length == 0 || triangles.Length % 3 != 0) + throw new ArgumentOutOfRangeException(nameof(triangles)); + if (normals != null && normals.Length != vertices.Length) + throw new ArgumentOutOfRangeException(nameof(normals)); + if (tangents != null && tangents.Length != vertices.Length) + throw new ArgumentOutOfRangeException(nameof(tangents)); + if (tangents != null && normals == null) + throw new ArgumentException("If you specify tangents then you need to also provide normals for the mesh."); + if (uv != null && uv.Length != vertices.Length) + throw new ArgumentOutOfRangeException(nameof(uv)); + + if (Internal_UpdateMeshUInt(__unmanagedPtr, vertices, triangles, blendIndices, blendWeights, normals, tangents, uv)) throw new FlaxException("Failed to update mesh data."); }