Add Mesh::UpdateMesh methods similar to C# API
This commit is contained in:
@@ -10,6 +10,127 @@
|
||||
#include "Engine/Serialization/MemoryReadStream.h"
|
||||
#include <ThirdParty/mono-2.0/mono/metadata/appdomain.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
template<typename IndexType>
|
||||
bool UpdateMesh(Mesh* mesh, uint32 vertexCount, uint32 triangleCount, Vector3* vertices, IndexType* triangles, Vector3* normals, Vector3* tangents, Vector2* uvs, Color32* colors)
|
||||
{
|
||||
auto model = mesh->GetModel();
|
||||
CHECK_RETURN(model && model->IsVirtual(), true);
|
||||
CHECK_RETURN(triangles && vertices, true);
|
||||
|
||||
// Pack mesh data into vertex buffers
|
||||
Array<VB1ElementType> vb1;
|
||||
Array<VB2ElementType> vb2;
|
||||
vb1.Resize(vertexCount);
|
||||
if (normals)
|
||||
{
|
||||
if (tangents)
|
||||
{
|
||||
for (uint32 i = 0; i < vertexCount; i++)
|
||||
{
|
||||
const Vector3 normal = normals[i];
|
||||
const Vector3 tangent = tangents[i];
|
||||
|
||||
// Calculate bitangent sign
|
||||
Vector3 bitangent = Vector3::Normalize(Vector3::Cross(normal, tangent));
|
||||
byte sign = static_cast<byte>(Vector3::Dot(Vector3::Cross(bitangent, normal), tangent) < 0.0f ? 1 : 0);
|
||||
|
||||
// Set tangent frame
|
||||
vb1[i].Tangent = Float1010102(tangent * 0.5f + 0.5f, sign);
|
||||
vb1[i].Normal = Float1010102(normal * 0.5f + 0.5f, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint32 i = 0; i < vertexCount; i++)
|
||||
{
|
||||
const Vector3 normal = normals[i];
|
||||
|
||||
// Calculate tangent
|
||||
Vector3 c1 = Vector3::Cross(normal, Vector3::UnitZ);
|
||||
Vector3 c2 = Vector3::Cross(normal, Vector3::UnitY);
|
||||
Vector3 tangent;
|
||||
if (c1.LengthSquared() > c2.LengthSquared())
|
||||
tangent = c1;
|
||||
else
|
||||
tangent = c2;
|
||||
|
||||
// Calculate bitangent sign
|
||||
Vector3 bitangent = Vector3::Normalize(Vector3::Cross(normal, tangent));
|
||||
byte sign = static_cast<byte>(Vector3::Dot(Vector3::Cross(bitangent, normal), tangent) < 0.0f ? 1 : 0);
|
||||
|
||||
// Set tangent frame
|
||||
vb1[i].Tangent = Float1010102(tangent * 0.5f + 0.5f, sign);
|
||||
vb1[i].Normal = Float1010102(normal * 0.5f + 0.5f, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set default tangent frame
|
||||
const auto n = Float1010102(Vector3::UnitZ);
|
||||
const auto t = Float1010102(Vector3::UnitX);
|
||||
for (uint32 i = 0; i < vertexCount; i++)
|
||||
{
|
||||
vb1[i].Normal = n;
|
||||
vb1[i].Tangent = t;
|
||||
}
|
||||
}
|
||||
if (uvs)
|
||||
{
|
||||
for (uint32 i = 0; i < vertexCount; i++)
|
||||
vb1[i].TexCoord = Half2(uvs[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto v = Half2(0, 0);
|
||||
for (uint32 i = 0; i < vertexCount; i++)
|
||||
vb1[i].TexCoord = v;
|
||||
}
|
||||
{
|
||||
auto v = Half2(0, 0);
|
||||
for (uint32 i = 0; i < vertexCount; i++)
|
||||
vb1[i].LightmapUVs = v;
|
||||
}
|
||||
if (colors)
|
||||
{
|
||||
vb2.Resize(vertexCount);
|
||||
for (uint32 i = 0; i < vertexCount; i++)
|
||||
vb2[i].Color = colors[i];
|
||||
}
|
||||
|
||||
return mesh->UpdateMesh(vertexCount, triangleCount, (VB0ElementType*)vertices, vb1.Get(), vb2.HasItems() ? vb2.Get() : nullptr, triangles);
|
||||
}
|
||||
|
||||
template<typename IndexType>
|
||||
bool UpdateMesh(Mesh* mesh, uint32 vertexCount, uint32 triangleCount, MonoArray* verticesObj, MonoArray* trianglesObj, MonoArray* normalsObj, MonoArray* tangentsObj, MonoArray* uvObj, MonoArray* colorsObj)
|
||||
{
|
||||
ASSERT((uint32)mono_array_length(verticesObj) >= vertexCount);
|
||||
ASSERT((uint32)mono_array_length(trianglesObj) / 3 >= triangleCount);
|
||||
auto vertices = (Vector3*)(void*)mono_array_addr_with_size(verticesObj, sizeof(Vector3), 0);
|
||||
auto triangles = (IndexType*)(void*)mono_array_addr_with_size(trianglesObj, sizeof(IndexType), 0);
|
||||
const auto normals = normalsObj ? (Vector3*)(void*)mono_array_addr_with_size(normalsObj, sizeof(Vector3), 0) : nullptr;
|
||||
const auto tangents = tangentsObj ? (Vector3*)(void*)mono_array_addr_with_size(tangentsObj, sizeof(Vector3), 0) : nullptr;
|
||||
const auto uvs = uvObj ? (Vector2*)(void*)mono_array_addr_with_size(uvObj, sizeof(Vector2), 0) : nullptr;
|
||||
const auto colors = colorsObj ? (Color32*)(void*)mono_array_addr_with_size(colorsObj, sizeof(Color32), 0) : nullptr;
|
||||
return UpdateMesh<IndexType>(mesh, vertexCount, triangleCount, vertices, triangles, normals, tangents, uvs, colors);
|
||||
}
|
||||
|
||||
template<typename IndexType>
|
||||
bool UpdateTriangles(Mesh* mesh, int32 triangleCount, MonoArray* trianglesObj)
|
||||
{
|
||||
const auto model = mesh->GetModel();
|
||||
ASSERT(model && model->IsVirtual() && trianglesObj);
|
||||
|
||||
// Get buffer data
|
||||
ASSERT((int32)mono_array_length(trianglesObj) / 3 >= triangleCount);
|
||||
auto ib = (IndexType*)(void*)mono_array_addr_with_size(trianglesObj, sizeof(IndexType), 0);
|
||||
|
||||
return mesh->UpdateTriangles(triangleCount, ib);
|
||||
}
|
||||
}
|
||||
|
||||
bool Mesh::UpdateMesh(uint32 vertexCount, uint32 triangleCount, VB0ElementType* vb0, VB1ElementType* vb1, VB2ElementType* vb2, void* ib, bool use16BitIndices)
|
||||
{
|
||||
Unload();
|
||||
@@ -31,6 +152,16 @@ bool Mesh::UpdateMesh(uint32 vertexCount, uint32 triangleCount, VB0ElementType*
|
||||
return failed;
|
||||
}
|
||||
|
||||
bool Mesh::UpdateMesh(uint32 vertexCount, uint32 triangleCount, Vector3* vertices, uint16* triangles, Vector3* normals, Vector3* tangents, Vector2* uvs, Color32* colors)
|
||||
{
|
||||
return ::UpdateMesh<uint16>(this, vertexCount, triangleCount, vertices, triangles, normals, tangents, uvs, colors);
|
||||
}
|
||||
|
||||
bool Mesh::UpdateMesh(uint32 vertexCount, uint32 triangleCount, Vector3* vertices, uint32* triangles, Vector3* normals, Vector3* tangents, Vector2* uvs, Color32* colors)
|
||||
{
|
||||
return ::UpdateMesh<uint32>(this, vertexCount, triangleCount, vertices, triangles, normals, tangents, uvs, colors);
|
||||
}
|
||||
|
||||
bool Mesh::UpdateTriangles(uint32 triangleCount, void* ib, bool use16BitIndices)
|
||||
{
|
||||
// Cache data
|
||||
@@ -384,108 +515,9 @@ ScriptingObject* Mesh::GetParentModel()
|
||||
return _model;
|
||||
}
|
||||
|
||||
template<typename IndexType>
|
||||
bool UpdateMesh(Mesh* mesh, uint32 vertexCount, uint32 triangleCount, MonoArray* verticesObj, MonoArray* trianglesObj, MonoArray* normalsObj, MonoArray* tangentsObj, MonoArray* uvObj, MonoArray* colorsObj)
|
||||
{
|
||||
auto model = mesh->GetModel();
|
||||
ASSERT(model && model->IsVirtual() && verticesObj && trianglesObj);
|
||||
|
||||
// Get buffers data
|
||||
ASSERT((uint32)mono_array_length(verticesObj) >= vertexCount);
|
||||
ASSERT((uint32)mono_array_length(trianglesObj) / 3 >= triangleCount);
|
||||
auto vb0 = (Vector3*)(void*)mono_array_addr_with_size(verticesObj, sizeof(Vector3), 0);
|
||||
auto ib = (IndexType*)(void*)mono_array_addr_with_size(trianglesObj, sizeof(IndexType), 0);
|
||||
Array<VB1ElementType> vb1;
|
||||
Array<VB2ElementType> vb2;
|
||||
vb1.Resize(vertexCount);
|
||||
if (normalsObj)
|
||||
{
|
||||
const auto normals = (Vector3*)(void*)mono_array_addr_with_size(normalsObj, sizeof(Vector3), 0);
|
||||
if (tangentsObj)
|
||||
{
|
||||
const auto tangents = (Vector3*)(void*)mono_array_addr_with_size(tangentsObj, sizeof(Vector3), 0);
|
||||
for (uint32 i = 0; i < vertexCount; i++)
|
||||
{
|
||||
// Peek normal and tangent
|
||||
const Vector3 normal = normals[i];
|
||||
const Vector3 tangent = tangents[i];
|
||||
|
||||
// Calculate bitangent sign
|
||||
Vector3 bitangent = Vector3::Normalize(Vector3::Cross(normal, tangent));
|
||||
byte sign = static_cast<byte>(Vector3::Dot(Vector3::Cross(bitangent, normal), tangent) < 0.0f ? 1 : 0);
|
||||
|
||||
// Set tangent frame
|
||||
vb1[i].Tangent = Float1010102(tangent * 0.5f + 0.5f, sign);
|
||||
vb1[i].Normal = Float1010102(normal * 0.5f + 0.5f, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint32 i = 0; i < vertexCount; i++)
|
||||
{
|
||||
// Peek normal
|
||||
const Vector3 normal = normals[i];
|
||||
|
||||
// Calculate tangent
|
||||
Vector3 c1 = Vector3::Cross(normal, Vector3::UnitZ);
|
||||
Vector3 c2 = Vector3::Cross(normal, Vector3::UnitY);
|
||||
Vector3 tangent;
|
||||
if (c1.LengthSquared() > c2.LengthSquared())
|
||||
tangent = c1;
|
||||
else
|
||||
tangent = c2;
|
||||
|
||||
// Calculate bitangent sign
|
||||
Vector3 bitangent = Vector3::Normalize(Vector3::Cross(normal, tangent));
|
||||
byte sign = static_cast<byte>(Vector3::Dot(Vector3::Cross(bitangent, normal), tangent) < 0.0f ? 1 : 0);
|
||||
|
||||
// Set tangent frame
|
||||
vb1[i].Tangent = Float1010102(tangent * 0.5f + 0.5f, sign);
|
||||
vb1[i].Normal = Float1010102(normal * 0.5f + 0.5f, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto n = Float1010102(Vector3::UnitZ);
|
||||
const auto t = Float1010102(Vector3::UnitX);
|
||||
for (uint32 i = 0; i < vertexCount; i++)
|
||||
{
|
||||
vb1[i].Normal = n;
|
||||
vb1[i].Tangent = t;
|
||||
}
|
||||
}
|
||||
if (uvObj)
|
||||
{
|
||||
const auto uvs = (Vector2*)(void*)mono_array_addr_with_size(uvObj, sizeof(Vector2), 0);
|
||||
for (uint32 i = 0; i < vertexCount; i++)
|
||||
vb1[i].TexCoord = Half2(uvs[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto v = Half2(0, 0);
|
||||
for (uint32 i = 0; i < vertexCount; i++)
|
||||
vb1[i].TexCoord = v;
|
||||
}
|
||||
{
|
||||
auto v = Half2(0, 0);
|
||||
for (uint32 i = 0; i < vertexCount; i++)
|
||||
vb1[i].LightmapUVs = v;
|
||||
}
|
||||
if (colorsObj)
|
||||
{
|
||||
vb2.Resize(vertexCount);
|
||||
const auto colors = (Color32*)(void*)mono_array_addr_with_size(colorsObj, sizeof(Color32), 0);
|
||||
for (uint32 i = 0; i < vertexCount; i++)
|
||||
vb2[i].Color = colors[i];
|
||||
}
|
||||
|
||||
return mesh->UpdateMesh(vertexCount, triangleCount, (VB0ElementType*)vb0, vb1.Get(), vb2.HasItems() ? vb2.Get() : nullptr, ib);
|
||||
}
|
||||
|
||||
bool Mesh::UpdateMeshInt(int32 vertexCount, int32 triangleCount, MonoArray* verticesObj, MonoArray* trianglesObj, MonoArray* normalsObj, MonoArray* tangentsObj, MonoArray* uvObj, MonoArray* colorsObj)
|
||||
{
|
||||
return ::UpdateMesh<int32>(this, (uint32)vertexCount, (uint32)triangleCount, verticesObj, trianglesObj, normalsObj, tangentsObj, uvObj, colorsObj);
|
||||
return ::UpdateMesh<uint32>(this, (uint32)vertexCount, (uint32)triangleCount, verticesObj, trianglesObj, normalsObj, tangentsObj, uvObj, colorsObj);
|
||||
}
|
||||
|
||||
bool Mesh::UpdateMeshUShort(int32 vertexCount, int32 triangleCount, MonoArray* verticesObj, MonoArray* trianglesObj, MonoArray* normalsObj, MonoArray* tangentsObj, MonoArray* uvObj, MonoArray* colorsObj)
|
||||
@@ -493,22 +525,9 @@ bool Mesh::UpdateMeshUShort(int32 vertexCount, int32 triangleCount, MonoArray* v
|
||||
return ::UpdateMesh<uint16>(this, (uint32)vertexCount, (uint32)triangleCount, verticesObj, trianglesObj, normalsObj, tangentsObj, uvObj, colorsObj);
|
||||
}
|
||||
|
||||
template<typename IndexType>
|
||||
bool UpdateTriangles(Mesh* mesh, int32 triangleCount, MonoArray* trianglesObj)
|
||||
{
|
||||
auto model = mesh->GetModel();
|
||||
ASSERT(model && model->IsVirtual() && trianglesObj);
|
||||
|
||||
// Get buffer data
|
||||
ASSERT((int32)mono_array_length(trianglesObj) / 3 >= triangleCount);
|
||||
auto ib = (IndexType*)(void*)mono_array_addr_with_size(trianglesObj, sizeof(IndexType), 0);
|
||||
|
||||
return mesh->UpdateTriangles(triangleCount, ib);
|
||||
}
|
||||
|
||||
bool Mesh::UpdateTrianglesInt(int32 triangleCount, MonoArray* trianglesObj)
|
||||
{
|
||||
return ::UpdateTriangles<int32>(this, triangleCount, trianglesObj);
|
||||
return ::UpdateTriangles<uint32>(this, triangleCount, trianglesObj);
|
||||
}
|
||||
|
||||
bool Mesh::UpdateTrianglesUShort(int32 triangleCount, MonoArray* trianglesObj)
|
||||
|
||||
@@ -218,7 +218,7 @@ public:
|
||||
/// <param name="vb2">The third vertex buffer data.</param>
|
||||
/// <param name="ib">The index buffer in clockwise order.</param>
|
||||
/// <returns>True if failed, otherwise false.</returns>
|
||||
FORCE_INLINE bool UpdateMesh(uint32 vertexCount, uint32 triangleCount, VB0ElementType* vb0, VB1ElementType* vb1, VB2ElementType* vb2, int32* ib)
|
||||
FORCE_INLINE bool UpdateMesh(uint32 vertexCount, uint32 triangleCount, VB0ElementType* vb0, VB1ElementType* vb1, VB2ElementType* vb2, uint32* ib)
|
||||
{
|
||||
return UpdateMesh(vertexCount, triangleCount, vb0, vb1, vb2, ib, false);
|
||||
}
|
||||
@@ -240,6 +240,8 @@ public:
|
||||
|
||||
/// <summary>
|
||||
/// Updates the model mesh (used by the virtual models created with Init rather than Load).
|
||||
/// Can be used only for virtual assets (see <see cref="Asset.IsVirtual"/> and <see cref="Content.CreateVirtualAsset{T}"/>).
|
||||
/// Mesh data will be cached and uploaded to the GPU with a delay.
|
||||
/// </summary>
|
||||
/// <param name="vertexCount">The amount of vertices in the vertex buffer.</param>
|
||||
/// <param name="triangleCount">The amount of triangles in the index buffer.</param>
|
||||
@@ -251,6 +253,38 @@ public:
|
||||
/// <returns>True if failed, otherwise false.</returns>
|
||||
bool UpdateMesh(uint32 vertexCount, uint32 triangleCount, VB0ElementType* vb0, VB1ElementType* vb1, VB2ElementType* vb2, void* ib, bool use16BitIndices);
|
||||
|
||||
/// <summary>
|
||||
/// Updates the model mesh (used by the virtual models created with Init rather than Load).
|
||||
/// Can be used only for virtual assets (see <see cref="Asset.IsVirtual"/> and <see cref="Content.CreateVirtualAsset{T}"/>).
|
||||
/// Mesh data will be cached and uploaded to the GPU with a delay.
|
||||
/// </summary>
|
||||
/// <param name="vertexCount">The amount of vertices in the vertex buffer.</param>
|
||||
/// <param name="triangleCount">The amount of triangles in the index buffer.</param>
|
||||
/// <param name="vertices">The mesh vertices positions. Cannot be null.</param>
|
||||
/// <param name="triangles">The mesh index buffer (clockwise triangles). Uses 32-bit stride buffer. Cannot be null.</param>
|
||||
/// <param name="normals">The normal vectors (per vertex).</param>
|
||||
/// <param name="tangents">The normal vectors (per vertex). Use null to compute them from normal vectors.</param>
|
||||
/// <param name="uvs">The texture coordinates (per vertex).</param>
|
||||
/// <param name="colors">The vertex colors (per vertex).</param>
|
||||
/// <returns>True if failed, otherwise false.</returns>
|
||||
bool UpdateMesh(uint32 vertexCount, uint32 triangleCount, Vector3* vertices, uint16* triangles, Vector3* normals = nullptr, Vector3* tangents = nullptr, Vector2* uvs = nullptr, Color32* colors = nullptr);
|
||||
|
||||
/// <summary>
|
||||
/// Updates the model mesh (used by the virtual models created with Init rather than Load).
|
||||
/// Can be used only for virtual assets (see <see cref="Asset.IsVirtual"/> and <see cref="Content.CreateVirtualAsset{T}"/>).
|
||||
/// Mesh data will be cached and uploaded to the GPU with a delay.
|
||||
/// </summary>
|
||||
/// <param name="vertexCount">The amount of vertices in the vertex buffer.</param>
|
||||
/// <param name="triangleCount">The amount of triangles in the index buffer.</param>
|
||||
/// <param name="vertices">The mesh vertices positions. Cannot be null.</param>
|
||||
/// <param name="triangles">The mesh index buffer (clockwise triangles). Uses 32-bit stride buffer. Cannot be null.</param>
|
||||
/// <param name="normals">The normal vectors (per vertex).</param>
|
||||
/// <param name="tangents">The normal vectors (per vertex). Use null to compute them from normal vectors.</param>
|
||||
/// <param name="uvs">The texture coordinates (per vertex).</param>
|
||||
/// <param name="colors">The vertex colors (per vertex).</param>
|
||||
/// <returns>True if failed, otherwise false.</returns>
|
||||
bool UpdateMesh(uint32 vertexCount, uint32 triangleCount, Vector3* vertices, uint32* triangles, Vector3* normals = nullptr, Vector3* tangents = nullptr, Vector2* uvs = nullptr, Color32* colors = nullptr);
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
@@ -259,7 +293,7 @@ public:
|
||||
/// <param name="triangleCount">The amount of triangles in the index buffer.</param>
|
||||
/// <param name="ib">The index buffer.</param>
|
||||
/// <returns>True if failed, otherwise false.</returns>
|
||||
FORCE_INLINE bool UpdateTriangles(uint32 triangleCount, int32* ib)
|
||||
FORCE_INLINE bool UpdateTriangles(uint32 triangleCount, uint32* ib)
|
||||
{
|
||||
return UpdateTriangles(triangleCount, ib, false);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user