123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290 |
- /*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
- #include "Util/WhiteBoxTextureUtil.h"
- #include "WhiteBoxTestFixtures.h"
- #include "Rendering/Atom/WhiteBoxMeshAtomData.h"
- #include <AzCore/Casting/lossy_cast.h>
- #include <AzCore/Casting/numeric_cast.h>
- #include <AzCore/UnitTest/TestTypes.h>
- #include <AzCore/std/containers/array.h>
- #include <AzCore/std/containers/vector.h>
- #include <AzTest/AzTest.h>
- #include <AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h>
- #include <WhiteBox/WhiteBoxToolApi.h>
- #include <cmath>
- #include <iostream>
- #include <random>
- #include <vector>
- namespace UnitTest
- {
- std::random_device rd;
- std::mt19937 gen(rd());
- // rngs for the first and subsequent significant figures of the random numbers
- std::uniform_real_distribution<> rndFirstSigFig(1.0, 10.0);
- std::uniform_real_distribution<> rndOtherSigFigs(0.0, 1.0);
- // generate noise after the specified decimal place with the first significant
- // figure always being one decimal place after afterDecimalPlace
- float GenerateNoiseWithSignificantFigures(AZ::u32 afterDecimalPlace)
- {
- // number of significant figures of randomness to generate
- const double numSigFigs = 8;
- // scaling factor to push the noise back into the desired range
- const double sigFactor = std::pow(10.0, numSigFigs + afterDecimalPlace);
- // random value for first guaranteed significant digit
- const auto firstSigFig = azlossy_cast<AZ::u64>(rndFirstSigFig(gen)) * std::pow(10.0, numSigFigs - 1);
- // random value for the other significant digits
- const auto otherSigFigs = azlossy_cast<AZ::u64>(rndOtherSigFigs(gen) * std::pow(10.0, numSigFigs - 1));
- // unscaled random value with rndSigFigs significant figures
- const auto fixedLengthRandom = firstSigFig + otherSigFigs;
- // scaled random value to push the noise into the desired significant digit range
- const float noise = aznumeric_cast<float>(fixedLengthRandom / sigFactor);
- return noise;
- }
- // generates a vector of Vector3s with noise for in specified range decimal places
- std::vector<Vector3> GenerateNoiseForSignificantFigureRange(AZ::u32 startDecimalPlace, AZ::u32 endDecimalPlace)
- {
- std::vector<Vector3> noise(endDecimalPlace - startDecimalPlace + 1);
- for (AZ::u32 decimal = startDecimalPlace, i = 0; decimal <= endDecimalPlace; decimal++, i++)
- {
- float x = GenerateNoiseWithSignificantFigures(decimal);
- float y = GenerateNoiseWithSignificantFigures(decimal);
- float z = GenerateNoiseWithSignificantFigures(decimal);
- noise[i] = Vector3{x, y, z};
- }
- return noise;
- }
- // vector of noise vectors with between 3 and 6 significat figures
- const std::vector<Vector3> Noise = GenerateNoiseForSignificantFigureRange(3, 6);
- // noise source permutations to be applied to each test
- const std::vector<NoiseSource> Source = {
- NoiseSource::None, NoiseSource::XComponent, NoiseSource::YComponent, NoiseSource::ZComponent,
- NoiseSource::XYComponent, NoiseSource::XZComponent, NoiseSource::YZComponent, NoiseSource::XYZComponent};
- enum CubeVertex : AZ::u32
- {
- FrontTopLeft,
- FrontTopRight,
- BackTopLeft,
- BackTopRight,
- FrontBottomLeft,
- FrontBottomRight,
- BackBottomLeft,
- BackBottomRight
- };
- const std::vector<AZ::Vector3> UnitCube = {
- AZ::Vector3(-0.5f, 0.5f, 0.5f), // FrontTopLeft
- AZ::Vector3(0.5f, 0.5f, 0.5f), // FrontTopRight
- AZ::Vector3(-0.5f, -0.5f, 0.5f), // BackTopLeft
- AZ::Vector3(0.5f, -0.5f, 0.5f), // BackTopRight
- AZ::Vector3(-0.5f, 0.5f, -0.5f), // FrontBottomLeft
- AZ::Vector3(0.5f, 0.5f, -0.5f), // FrontBottomRight
- AZ::Vector3(-0.5f, -0.5f, -0.5f), // BackBottomLeft
- AZ::Vector3(0.5f, -0.5f, -0.5f) // BackBottomRight
- };
- // returns a vector with noise applied to it as determined by the source
- AZ::Vector3 GenerateNoiseyVector(const AZ::Vector3& in, const Vector3& noise, NoiseSource source)
- {
- switch (source)
- {
- case NoiseSource::None:
- return in;
- case NoiseSource::XComponent:
- return AZ::Vector3(in.GetX() + noise.x, in.GetY(), in.GetZ());
- case NoiseSource::YComponent:
- return AZ::Vector3(in.GetX(), in.GetY() + noise.y, in.GetZ());
- case NoiseSource::ZComponent:
- return AZ::Vector3(in.GetX(), in.GetY(), in.GetZ() + noise.z);
- case NoiseSource::XYComponent:
- return AZ::Vector3(in.GetX() + noise.x, in.GetY() + noise.y, in.GetZ());
- case NoiseSource::XZComponent:
- return AZ::Vector3(in.GetX() + noise.x, in.GetY(), in.GetZ() + noise.z);
- case NoiseSource::YZComponent:
- return AZ::Vector3(in.GetX(), in.GetY() + noise.y, in.GetZ() + noise.z);
- case NoiseSource::XYZComponent:
- return AZ::Vector3(in.GetX() + noise.x, in.GetY() + noise.y, in.GetZ() + noise.z);
- default:
- return in;
- }
- }
- // returns a quaternion with the specified rotation
- AZ::Quaternion GetQuaternionFromRotation(Rotation rotation)
- {
- static const AZ::Quaternion qXAxis = AZ::Quaternion::CreateFromAxisAngle(AZ::Vector3::CreateAxisX(), 45);
- static const AZ::Quaternion qZAxis = AZ::Quaternion::CreateFromAxisAngle(AZ::Vector3::CreateAxisZ(), 45);
- static const AZ::Quaternion qXZAxis = qXAxis + qZAxis;
- switch (rotation)
- {
- case Rotation::Identity:
- return AZ::Quaternion::CreateIdentity();
- case Rotation::XAxis:
- return qXAxis;
- case Rotation::ZAxis:
- return qZAxis;
- case Rotation::XZAxis:
- return qXZAxis;
- default:
- return AZ::Quaternion::CreateIdentity();
- }
- }
- TEST_P(WhiteBoxUVTestFixture, FrontFaceCorners)
- {
- using WhiteBox::CreatePlanarUVFromVertex;
- const auto& [noise, source, rotation] = GetParam();
- const AZ::Quaternion qRotation = GetQuaternionFromRotation(rotation);
- const AZ::Vector3 normal =
- GenerateNoiseyVector(qRotation.TransformVector(AZ::Vector3(0.0f, -1.0f, 0.0f)), noise, source);
- const AZ::Vector2 uv00 = CreatePlanarUVFromVertex(normal, UnitCube[FrontTopLeft]);
- const AZ::Vector2 uv10 = CreatePlanarUVFromVertex(normal, UnitCube[FrontTopRight]);
- const AZ::Vector2 uv01 = CreatePlanarUVFromVertex(normal, UnitCube[FrontBottomLeft]);
- const AZ::Vector2 uv11 = CreatePlanarUVFromVertex(normal, UnitCube[FrontBottomRight]);
- EXPECT_THAT(uv00, IsClose(AZ::Vector2(1.0f, 0.0f)));
- EXPECT_THAT(uv10, IsClose(AZ::Vector2(0.0f, 0.0f)));
- EXPECT_THAT(uv01, IsClose(AZ::Vector2(1.0f, 1.0f)));
- EXPECT_THAT(uv11, IsClose(AZ::Vector2(0.0f, 1.0f)));
- }
- TEST_P(WhiteBoxUVTestFixture, BackFaceCorners)
- {
- using WhiteBox::CreatePlanarUVFromVertex;
- const auto& [noise, source, rotation] = GetParam();
- const AZ::Quaternion qRotation = GetQuaternionFromRotation(rotation);
- const AZ::Vector3 normal =
- GenerateNoiseyVector(qRotation.TransformVector(AZ::Vector3(0.0f, 1.0f, 0.0f)), noise, source);
- const AZ::Vector2 uv00 = CreatePlanarUVFromVertex(normal, UnitCube[BackTopLeft]);
- const AZ::Vector2 uv10 = CreatePlanarUVFromVertex(normal, UnitCube[BackTopRight]);
- const AZ::Vector2 uv01 = CreatePlanarUVFromVertex(normal, UnitCube[BackBottomLeft]);
- const AZ::Vector2 uv11 = CreatePlanarUVFromVertex(normal, UnitCube[BackBottomRight]);
- EXPECT_THAT(uv00, IsClose(AZ::Vector2(1.0f, 0.0f)));
- EXPECT_THAT(uv10, IsClose(AZ::Vector2(0.0f, 0.0f)));
- EXPECT_THAT(uv01, IsClose(AZ::Vector2(1.0f, 1.0f)));
- EXPECT_THAT(uv11, IsClose(AZ::Vector2(0.0f, 1.0f)));
- }
- TEST_P(WhiteBoxUVTestFixture, LeftFaceCorners)
- {
- using WhiteBox::CreatePlanarUVFromVertex;
- const auto& [noise, source, rotation] = GetParam();
- const AZ::Quaternion qRotation = GetQuaternionFromRotation(rotation);
- const AZ::Vector3 normal =
- GenerateNoiseyVector(qRotation.TransformVector(AZ::Vector3(-1.0f, 0.0f, 0.0f)), noise, source);
- const AZ::Vector2 uv00 = CreatePlanarUVFromVertex(normal, UnitCube[FrontTopLeft]);
- const AZ::Vector2 uv10 = CreatePlanarUVFromVertex(normal, UnitCube[BackTopLeft]);
- const AZ::Vector2 uv01 = CreatePlanarUVFromVertex(normal, UnitCube[FrontBottomLeft]);
- const AZ::Vector2 uv11 = CreatePlanarUVFromVertex(normal, UnitCube[BackBottomLeft]);
- EXPECT_THAT(uv00, IsClose(AZ::Vector2(0.0f, 0.0f)));
- EXPECT_THAT(uv10, IsClose(AZ::Vector2(0.0f, 1.0f)));
- EXPECT_THAT(uv01, IsClose(AZ::Vector2(1.0f, 0.0f)));
- EXPECT_THAT(uv11, IsClose(AZ::Vector2(1.0f, 1.0f)));
- }
- TEST_P(WhiteBoxUVTestFixture, RightFaceCorners)
- {
- using WhiteBox::CreatePlanarUVFromVertex;
- const auto& [noise, source, rotation] = GetParam();
- const AZ::Quaternion qRotation = GetQuaternionFromRotation(rotation);
- const AZ::Vector3 normal =
- GenerateNoiseyVector(qRotation.TransformVector(AZ::Vector3(1.0f, 0.0f, 0.0f)), noise, source);
- const AZ::Vector2 uv00 = CreatePlanarUVFromVertex(normal, UnitCube[FrontTopRight]);
- const AZ::Vector2 uv10 = CreatePlanarUVFromVertex(normal, UnitCube[BackTopRight]);
- const AZ::Vector2 uv01 = CreatePlanarUVFromVertex(normal, UnitCube[FrontBottomRight]);
- const AZ::Vector2 uv11 = CreatePlanarUVFromVertex(normal, UnitCube[BackBottomRight]);
- EXPECT_THAT(uv00, IsClose(AZ::Vector2(0.0f, 0.0f)));
- EXPECT_THAT(uv10, IsClose(AZ::Vector2(0.0f, 1.0f)));
- EXPECT_THAT(uv01, IsClose(AZ::Vector2(1.0f, 0.0f)));
- EXPECT_THAT(uv11, IsClose(AZ::Vector2(1.0f, 1.0f)));
- }
- TEST_P(WhiteBoxUVTestFixture, TopFaceCorners)
- {
- using WhiteBox::CreatePlanarUVFromVertex;
- const auto& [noise, source, rotation] = GetParam();
- const AZ::Quaternion qRotation = GetQuaternionFromRotation(rotation);
- const AZ::Vector3 normal =
- GenerateNoiseyVector(qRotation.TransformVector(AZ::Vector3(0.0f, 0.0f, 1.0f)), noise, source);
- const AZ::Vector2 uv00 = CreatePlanarUVFromVertex(normal, UnitCube[FrontTopLeft]);
- const AZ::Vector2 uv10 = CreatePlanarUVFromVertex(normal, UnitCube[FrontTopRight]);
- const AZ::Vector2 uv01 = CreatePlanarUVFromVertex(normal, UnitCube[BackTopLeft]);
- const AZ::Vector2 uv11 = CreatePlanarUVFromVertex(normal, UnitCube[BackTopRight]);
- EXPECT_THAT(uv00, IsClose(AZ::Vector2(1.0f, 0.0f)));
- EXPECT_THAT(uv10, IsClose(AZ::Vector2(0.0f, 0.0f)));
- EXPECT_THAT(uv01, IsClose(AZ::Vector2(1.0f, 1.0f)));
- EXPECT_THAT(uv11, IsClose(AZ::Vector2(0.0f, 1.0f)));
- }
- TEST_P(WhiteBoxUVTestFixture, BottomFaceCorners)
- {
- using WhiteBox::CreatePlanarUVFromVertex;
- const auto& [noise, source, rotation] = GetParam();
- const AZ::Quaternion qRotation = GetQuaternionFromRotation(rotation);
- const AZ::Vector3 normal =
- GenerateNoiseyVector(qRotation.TransformVector(AZ::Vector3(0.0f, 0.0f, -1.0f)), noise, source);
- const AZ::Vector2 uv00 = CreatePlanarUVFromVertex(normal, UnitCube[FrontBottomLeft]);
- const AZ::Vector2 uv10 = CreatePlanarUVFromVertex(normal, UnitCube[FrontBottomRight]);
- const AZ::Vector2 uv01 = CreatePlanarUVFromVertex(normal, UnitCube[BackBottomLeft]);
- const AZ::Vector2 uv11 = CreatePlanarUVFromVertex(normal, UnitCube[BackBottomRight]);
- EXPECT_THAT(uv00, IsClose(AZ::Vector2(1.0f, 0.0f)));
- EXPECT_THAT(uv10, IsClose(AZ::Vector2(0.0f, 0.0f)));
- EXPECT_THAT(uv01, IsClose(AZ::Vector2(1.0f, 1.0f)));
- EXPECT_THAT(uv11, IsClose(AZ::Vector2(0.0f, 1.0f)));
- }
- // test with permutations of all noise values and sources with rotations around the x and z axis
- INSTANTIATE_TEST_CASE_P(
- , WhiteBoxUVTestFixture,
- ::testing::Combine(
- ::testing::ValuesIn(Noise), ::testing::ValuesIn(Source),
- ::testing::Values(Rotation::Identity, Rotation::XZAxis)));
- TEST(WhiteBoxRenderTest, WhiteBoxMeshAtomDataAabbIsInitializedToNull)
- {
- WhiteBox::WhiteBoxMeshAtomData atomData(WhiteBox::WhiteBoxFaces{});
- EXPECT_EQ(atomData.GetAabb(), AZ::Aabb::CreateNull());
- }
- } // namespace UnitTest
|