engine: sync editor rendering and ui changes
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
# ============================================================
|
||||
|
||||
set(MESH_TEST_SOURCES
|
||||
test_builtin_primitive_mesh.cpp
|
||||
test_mesh.cpp
|
||||
test_mesh_loader.cpp
|
||||
test_mesh_import_settings.cpp
|
||||
|
||||
107
tests/Resources/Mesh/test_builtin_primitive_mesh.cpp
Normal file
107
tests/Resources/Mesh/test_builtin_primitive_mesh.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <XCEngine/Core/Math/Vector3.h>
|
||||
#include <XCEngine/Resources/BuiltinResources.h>
|
||||
#include <XCEngine/Resources/Mesh/Mesh.h>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
using namespace XCEngine::Math;
|
||||
using namespace XCEngine::Resources;
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr float kAlignmentEpsilon = 1e-6f;
|
||||
|
||||
XCEngine::Core::uint32 GetIndexValue(const Mesh& mesh, XCEngine::Core::uint32 index) {
|
||||
if (mesh.IsUse32BitIndex()) {
|
||||
return static_cast<const XCEngine::Core::uint32*>(mesh.GetIndexData())[index];
|
||||
}
|
||||
|
||||
return static_cast<const XCEngine::Core::uint32>(
|
||||
static_cast<const XCEngine::Core::uint16*>(mesh.GetIndexData())[index]);
|
||||
}
|
||||
|
||||
float ComputeTriangleNormalAlignment(const Mesh& mesh, XCEngine::Core::uint32 triangleStartIndex) {
|
||||
const auto* vertices = static_cast<const StaticMeshVertex*>(mesh.GetVertexData());
|
||||
if (vertices == nullptr || triangleStartIndex + 2 >= mesh.GetIndexCount()) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
const XCEngine::Core::uint32 i0 = GetIndexValue(mesh, triangleStartIndex);
|
||||
const XCEngine::Core::uint32 i1 = GetIndexValue(mesh, triangleStartIndex + 1);
|
||||
const XCEngine::Core::uint32 i2 = GetIndexValue(mesh, triangleStartIndex + 2);
|
||||
if (i0 >= mesh.GetVertexCount() || i1 >= mesh.GetVertexCount() || i2 >= mesh.GetVertexCount()) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
const Vector3& p0 = vertices[i0].position;
|
||||
const Vector3& p1 = vertices[i1].position;
|
||||
const Vector3& p2 = vertices[i2].position;
|
||||
const Vector3 faceNormal = Vector3::Cross(p1 - p0, p2 - p0);
|
||||
if (faceNormal.SqrMagnitude() <= kAlignmentEpsilon) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
const Vector3 averagedVertexNormal =
|
||||
(vertices[i0].normal + vertices[i1].normal + vertices[i2].normal) / 3.0f;
|
||||
if (averagedVertexNormal.SqrMagnitude() <= kAlignmentEpsilon) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
return Vector3::Dot(faceNormal, averagedVertexNormal);
|
||||
}
|
||||
|
||||
float FindReferenceAlignment(const Mesh& mesh) {
|
||||
for (XCEngine::Core::uint32 index = 0; index + 2 < mesh.GetIndexCount(); index += 3) {
|
||||
const float alignment = ComputeTriangleNormalAlignment(mesh, index);
|
||||
if (std::abs(alignment) > kAlignmentEpsilon) {
|
||||
return alignment;
|
||||
}
|
||||
}
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
size_t CountTrianglesWithUnexpectedAlignment(const Mesh& mesh, float expectedSign) {
|
||||
size_t mismatchCount = 0u;
|
||||
for (XCEngine::Core::uint32 index = 0; index + 2 < mesh.GetIndexCount(); index += 3) {
|
||||
const float alignment = ComputeTriangleNormalAlignment(mesh, index);
|
||||
if (std::abs(alignment) <= kAlignmentEpsilon) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (alignment * expectedSign <= 0.0f) {
|
||||
++mismatchCount;
|
||||
}
|
||||
}
|
||||
|
||||
return mismatchCount;
|
||||
}
|
||||
|
||||
TEST(BuiltinPrimitiveMesh, SphereUsesSameTriangleWindingConventionAsCube) {
|
||||
LoadResult cubeResult = CreateBuiltinMeshResource(GetBuiltinPrimitiveMeshPath(BuiltinPrimitiveType::Cube));
|
||||
ASSERT_TRUE(cubeResult);
|
||||
ASSERT_NE(cubeResult.resource, nullptr);
|
||||
|
||||
LoadResult sphereResult = CreateBuiltinMeshResource(GetBuiltinPrimitiveMeshPath(BuiltinPrimitiveType::Sphere));
|
||||
ASSERT_TRUE(sphereResult);
|
||||
ASSERT_NE(sphereResult.resource, nullptr);
|
||||
|
||||
auto* cubeMesh = static_cast<Mesh*>(cubeResult.resource);
|
||||
auto* sphereMesh = static_cast<Mesh*>(sphereResult.resource);
|
||||
ASSERT_NE(cubeMesh, nullptr);
|
||||
ASSERT_NE(sphereMesh, nullptr);
|
||||
|
||||
const float cubeAlignment = FindReferenceAlignment(*cubeMesh);
|
||||
ASSERT_GT(std::abs(cubeAlignment), kAlignmentEpsilon);
|
||||
const float expectedSign = cubeAlignment > 0.0f ? 1.0f : -1.0f;
|
||||
|
||||
EXPECT_EQ(CountTrianglesWithUnexpectedAlignment(*cubeMesh, expectedSign), 0u);
|
||||
EXPECT_EQ(CountTrianglesWithUnexpectedAlignment(*sphereMesh, expectedSign), 0u);
|
||||
|
||||
delete cubeMesh;
|
||||
delete sphereMesh;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
Reference in New Issue
Block a user