Files
UnrealEngine/Engine/Source/Programs/UnrealLightmass/Private/Launch/UnitTest.cpp
2025-05-18 13:04:45 +08:00

263 lines
7.9 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "UnitTest.h"
#include "LMkDOP.h"
#include "Math/LMOctree.h"
#include "UnrealLightmass.h"
#include "HAL/Runnable.h"
#include "HAL/RunnableThread.h"
#include "HAL/PlatformTime.h"
#include "HAL/PlatformProcess.h"
#include "Misc/Guid.h"
#include "LightmassScene.h"
namespace Lightmass
{
/** Defines how the light is stored in the scene's light octree. */
struct FTestOctreeSemantics
{
enum { MaxElementsPerLeaf = 16 };
enum { MinInclusiveElementsPerNode = 7 };
enum { MaxNodeDepth = 12 };
enum { LoosenessDenominator = 16 };
typedef TInlineAllocator<MaxElementsPerLeaf> ElementAllocator;
FORCEINLINE static FBoxCenterAndExtent GetBoundingBox(const float& Element)
{
return FBoxCenterAndExtent(FVector4f(0), FVector4f(Element));
}
FORCEINLINE static bool AreElementsEqual(const float& A,const float& B)
{
return A == B;
}
};
class FTestCollisionDataProvider
{
TkDOPTree<FTestCollisionDataProvider, uint16>& kDOP;
FVector4f Vertex;
public:
FTestCollisionDataProvider(TkDOPTree<FTestCollisionDataProvider, uint16>& InkDOP)
: kDOP(InkDOP)
, Vertex(0)
{
}
/**
* Given an index, returns the position of the vertex
*
* @param Index the index into the vertices array
*/
FORCEINLINE const FVector4f& GetVertex(uint16 Index) const
{
return Vertex;
}
/** Returns additional information. */
FORCEINLINE int32 GetItemIndex(uint16 MaterialIndex) const
{
return 0;
}
/**
* Returns the kDOPTree for this mesh
*/
FORCEINLINE const TkDOPTree<FTestCollisionDataProvider,uint16>& GetkDOPTree(void) const
{
return kDOP;
}
/**
* Returns the local to world for the component
*/
FORCEINLINE const FMatrix44f& GetLocalToWorld(void) const
{
return FMatrix44f::Identity;
}
/**
* Returns the world to local for the component
*/
FORCEINLINE const FMatrix44f GetWorldToLocal(void) const
{
return FMatrix44f::Identity;
}
/**
* Returns the local to world transpose adjoint for the component
*/
FORCEINLINE FMatrix44f GetLocalToWorldTransposeAdjoint(void) const
{
return FMatrix44f::Identity;
}
/**
* Returns the determinant for the component
*/
FORCEINLINE float GetDeterminant(void) const
{
return 0.0f;
}
};
class FTestRunnable : public FRunnable
{
bool bStop;
public:
virtual bool Init(void)
{
bStop = false;
return true;
}
virtual uint32 Run(void)
{
for (int32 i = 0; i < 10 && !bStop; i++)
{
UE_LOG(LogLightmass, Display, TEXT("Thread counter %d"), i);
FPlatformProcess::Sleep(1.0f);
}
UE_LOG(LogLightmass, Display, TEXT("Thread done!!"));
return 0;
}
virtual void Stop(void)
{
bStop = true;
}
virtual void Exit(void)
{
}
};
void TestLightmass()
{
UE_LOG(LogLightmass, Display, TEXT("\n\n"));
UE_LOG(LogLightmass, Display, TEXT("==============================================================================================="));
UE_LOG(LogLightmass, Display, TEXT("Running \"unit test\". This will take several seconds, and will end with an assertion."));
UE_LOG(LogLightmass, Display, TEXT("This is on purpose, as it's testing the callstack gathering..."));
UE_LOG(LogLightmass, Display, TEXT("==============================================================================================="));
UE_LOG(LogLightmass, Display, TEXT("\n\n"));
void* Buf = FMemory::Malloc(1024);
TArray<int32> TestArray;
TestArray.Add(5);
TArray<int32> ArrayCopy = TestArray;
FVector4f TestVectorA(1, 0, 0, 1);
FVector4f TestVectorB(1, 1, 1, 1);
FVector4f TestVector = TestVectorA + TestVectorB;
FString TestString = FString::Printf(TEXT("Copy has %d, Vector is [%.2f, %.2f, %.2f, %.2f]\n"), ArrayCopy[0], TestVector.X, TestVector.Y, TestVector.Z, TestVector.W);
printf("%s", TCHAR_TO_UTF8(*TestString));
FMemory::Free(Buf);
struct FAlignTester
{
uint8 A;
FMatrix44f M1;
uint8 B;
FMatrix44f M2;
uint8 C;
FVector4f V;
};
FAlignTester AlignTest;
checkf(((PTRINT)(&FMatrix44f::Identity) & 15) == 0, TEXT("Identity matrix unaligned"));
checkf(((PTRINT)(&AlignTest.M1) & 15) == 0, TEXT("First matrix unaligned"));
checkf(((PTRINT)(&AlignTest.M2) & 15) == 0, TEXT("Second matrix unaligned"));
checkf(((PTRINT)(&AlignTest.V) & 15) == 0, TEXT("Vector unaligned"));
FGuid Guid(1, 2, 3, 4);
UE_LOG(LogLightmass, Display, TEXT("Guid is %s"), *Guid.ToString());
TMap<FString, int32> TestMap;
TestMap.Add(FString(TEXT("Five")), 5);
TestMap.Add(TEXT("Ten"), 10);
UE_LOG(LogLightmass, Display, TEXT("Map[Five] = %d, Map[Ten] = %d"), TestMap.FindRef(TEXT("Five")), TestMap.FindRef(FString(TEXT("Ten"))));
FMatrix44f TestMatrix(FVector3f(0, 0, 0.1f), FVector3f(0, 1.0f, 0), FVector3f(0.9f, 0, 0), FVector3f(0, 0, 0));
UE_LOG(LogLightmass, Display, TEXT("Mat=\n [%0.2f, %0.2f, %0.2f, %0.2f]\n [%0.2f, %0.2f, %0.2f, %0.2f]\n [%0.2f, %0.2f, %0.2f, %0.2f]\n [%0.2f, %0.2f, %0.2f, %0.2f]"),
TestMatrix.M[0][0], TestMatrix.M[0][1], TestMatrix.M[0][2], TestMatrix.M[0][3],
TestMatrix.M[1][0], TestMatrix.M[1][1], TestMatrix.M[1][2], TestMatrix.M[1][3],
TestMatrix.M[2][0], TestMatrix.M[2][1], TestMatrix.M[2][2], TestMatrix.M[2][3],
TestMatrix.M[3][0], TestMatrix.M[3][1], TestMatrix.M[3][2], TestMatrix.M[3][3]
);
TestMatrix = TestMatrix.GetTransposed();
UE_LOG(LogLightmass, Display, TEXT("Transposed Mat=\n [%0.2f, %0.2f, %0.2f, %0.2f]\n [%0.2f, %0.2f, %0.2f, %0.2f]\n [%0.2f, %0.2f, %0.2f, %0.2f]\n [%0.2f, %0.2f, %0.2f, %0.2f]"),
TestMatrix.M[0][0], TestMatrix.M[0][1], TestMatrix.M[0][2], TestMatrix.M[0][3],
TestMatrix.M[1][0], TestMatrix.M[1][1], TestMatrix.M[1][2], TestMatrix.M[1][3],
TestMatrix.M[2][0], TestMatrix.M[2][1], TestMatrix.M[2][2], TestMatrix.M[2][3],
TestMatrix.M[3][0], TestMatrix.M[3][1], TestMatrix.M[3][2], TestMatrix.M[3][3]
);
TestMatrix = TestMatrix.GetTransposed().InverseFast();
UE_LOG(LogLightmass, Display, TEXT("Inverted Mat=\n [%0.2f, %0.2f, %0.2f, %0.2f]\n [%0.2f, %0.2f, %0.2f, %0.2f]\n [%0.2f, %0.2f, %0.2f, %0.2f]\n [%0.2f, %0.2f, %0.2f, %0.2f]"),
TestMatrix.M[0][0], TestMatrix.M[0][1], TestMatrix.M[0][2], TestMatrix.M[0][3],
TestMatrix.M[1][0], TestMatrix.M[1][1], TestMatrix.M[1][2], TestMatrix.M[1][3],
TestMatrix.M[2][0], TestMatrix.M[2][1], TestMatrix.M[2][2], TestMatrix.M[2][3],
TestMatrix.M[3][0], TestMatrix.M[3][1], TestMatrix.M[3][2], TestMatrix.M[3][3]
);
UE_LOG(LogLightmass, Display, TEXT("sizeof FDirectionalLight = %d, FLight = %d, FDirectionalLightData = %d"), sizeof(FDirectionalLight), sizeof(FLight), sizeof(FDirectionalLightData));
TOctree<float, FTestOctreeSemantics> TestOctree(FVector4f(0), 10.0f);
TestOctree.AddElement(5);
// kDOP test
TkDOPTree<FTestCollisionDataProvider, uint16> TestkDOP;
FTestCollisionDataProvider TestDataProvider(TestkDOP);
FHitResult TestResult;
FkDOPBuildCollisionTriangle<uint16> TestTri(0, FVector4f(0,0,0,0), FVector4f(1,1,1,0), FVector4f(2,2,2,0), INDEX_NONE, INDEX_NONE, INDEX_NONE, false, true);
TArray<FkDOPBuildCollisionTriangle<uint16> > TestTriangles;
TestTriangles.Add(TestTri);
TestkDOP.Build(TestTriangles);
UE_LOG(LogLightmass, Display, TEXT("\nStarting a thread"));
FTestRunnable* TestRunnable = new FTestRunnable;
// create a thread with the test runnable, and let it auto-delete itself
FRunnableThread* TestThread = FRunnableThread::Create(TestRunnable, TEXT("TestRunnable"));
double Start = FPlatformTime::Seconds();
UE_LOG(LogLightmass, Display, TEXT("\nWaiting 4 seconds"), Start);
FPlatformProcess::Sleep(4.0f);
UE_LOG(LogLightmass, Display, TEXT("%.2f seconds have passed, killing thread"), FPlatformTime::Seconds() - Start);
// wait for thread to end
double KillStart = FPlatformTime::Seconds();
TestRunnable->Stop();
TestThread->WaitForCompletion();
delete TestThread;
delete TestRunnable;
UE_LOG(LogLightmass, Display, TEXT("It took %.2f seconds to kill the thread [should be < 1 second]"), FPlatformTime::Seconds() - KillStart);
UE_LOG(LogLightmass, Display, TEXT("\n\n"));
checkf(5 == 2, TEXT("And boom goes the dynamite\n"));
}
} // namespace