application/ holds the frame loop. Application owns the profiler, the GPU device, the window, canvas and debug UI, and drives an ApplicationDelegate (wantsFrame, processFrame, drawFrame) instead of being a base class. It is configured with ApplicationOptions (window size, identity, platform context, resource directory, debug interface) and has an explicit start/step/finish lifecycle driven by run(). Each frame it paints the decorations around the delegate's drawing; ImGui renders last. SessionRecorder records an Application's raw input through the window tap and its frame profile, and saves them with the environment as one directory for bug reports and replays. Each src/ directory is its own library, linked only to what its headers use: GraphicApplicationInputLayer, -Diagnostics, -Gpu, -BackendContract, -Backend (the platform for the build target), -Window, -Canvas, -Decorations, -DebugUI, and GraphicApplication on top. Only Window can see the backend. graphic_application_resources() copies the shared fonts next to an executable. The old Graphics module is removed. WidgetApplication becomes a delegate that owns its Application; widgets receive an InputView whose origin and button visibility the update manager chooses, instead of mutating shared input state. The Widgets debug overlay (DebugManager and its global gDebugWidget) and the per-widget debug state it read are removed. Consumers use typed text styles and image handles. The color wheel moves from Canvas into the color picker widget; Math gains Vec2::angle() and Vec2::rotated() for it. Duplicate per-module font copies are removed. The port's MODULES_BUILD_* gates are replaced by ANDROID checks, and the generic app id is set directly until the root desktop-entry helpers land. GraphicApplication/.clang-format inherits the root style and requires braces on every control-statement body.
118 lines
3.2 KiB
C++
118 lines
3.2 KiB
C++
|
|
#include "ComplexNumbers.hpp"
|
|
|
|
#include "UnitTest++/UnitTest++.h"
|
|
|
|
using namespace tp;
|
|
|
|
SUITE(Math) {
|
|
TEST(ComplexNumber) {
|
|
CHECK((ComplexCart{ 3, 4 }.mod() == 5));
|
|
CHECK((abs(ComplexCart{ 1, 1 }.arg() - 0.7853981633974483) < 0.001));
|
|
CHECK((ComplexCart{ 3, 4 }.norm2() == 25));
|
|
|
|
{
|
|
ComplexCart cn{ 3, 4 };
|
|
ComplexCart expected{ 0.12, -0.16 };
|
|
auto val = cn.reciprocal();
|
|
CHECK((val == expected));
|
|
}
|
|
|
|
{
|
|
ComplexCart cn{ 3, 4 };
|
|
ComplexCart expected{ 3, -4 };
|
|
CHECK((cn.conjugate() == expected));
|
|
}
|
|
|
|
{
|
|
ComplexCart cn1{ 3, 4 };
|
|
ComplexCart cn2{ 1, 2 };
|
|
ComplexCart expected{ -5, 10 };
|
|
CHECK((cn1 * cn2 == expected));
|
|
}
|
|
|
|
{
|
|
ComplexRad c1{ 5, 7 };
|
|
ComplexRad c2{ 10, 3 };
|
|
ComplexCart tmp1 = (c1 * c2).cart();
|
|
ComplexCart tmp2 = (c1.cart() * c2.cart());
|
|
CHECK((tmp1 - tmp2).mod() < 0.001);
|
|
}
|
|
}
|
|
}
|
|
|
|
int main() { return UnitTest::RunAllTests(); }
|
|
|
|
#include "Color.hpp"
|
|
#include "Noise.hpp"
|
|
|
|
#include <cmath>
|
|
|
|
SUITE(TileableNoise) {
|
|
TEST(NoiseTilesAcrossItsPeriod) {
|
|
const TileableNoise noise(7);
|
|
for (int index = 0; index < 20; index++) {
|
|
const halnf x = 0.37f * (halnf) index;
|
|
const halnf y = 1.13f + 0.21f * (halnf) index;
|
|
CHECK_CLOSE(noise.gradient(x, y, 8, 4), noise.gradient(x + 8, y, 8, 4), 1e-5f);
|
|
CHECK_CLOSE(noise.gradient(x, y, 8, 4), noise.gradient(x, y + 4, 8, 4), 1e-5f);
|
|
}
|
|
}
|
|
|
|
TEST(NoiseIsZeroOnLatticeAndBounded) {
|
|
const TileableNoise noise(3);
|
|
CHECK_CLOSE(0.0f, noise.gradient(2, 5, 16, 16), 1e-6f);
|
|
halnf low = 0;
|
|
halnf high = 0;
|
|
for (int y = 0; y < 64; y++) {
|
|
for (int x = 0; x < 64; x++) {
|
|
const halnf value = noise.gradient((halnf) x * 0.13f, (halnf) y * 0.17f, 16, 16);
|
|
low = std::min(low, value);
|
|
high = std::max(high, value);
|
|
}
|
|
}
|
|
CHECK(low >= -1.0f && high <= 1.0f);
|
|
CHECK(high - low > 0.8f);
|
|
}
|
|
|
|
TEST(SeedsChangeThePattern) {
|
|
const TileableNoise a(1);
|
|
const TileableNoise b(2);
|
|
halnf difference = 0;
|
|
for (int index = 0; index < 32; index++)
|
|
difference += std::fabs(a.gradient(0.3f * index, 0.7f, 32, 32) - b.gradient(0.3f * index, 0.7f, 32, 32));
|
|
CHECK(difference > 1);
|
|
}
|
|
|
|
TEST(FractalStaysTileableAtEveryOctave) {
|
|
const TileableNoise noise(5);
|
|
const halnf weights[] = { 1, 0.5f, 0.25f, 0.125f };
|
|
CHECK_CLOSE(noise.fractal(0.4f, 0.6f, 4, weights, 4), noise.fractal(4.4f, 4.6f, 4, weights, 4), 1e-5f);
|
|
}
|
|
}
|
|
|
|
SUITE(DisplayGamma) {
|
|
TEST(GammaRoundTripsAndMatchesReferenceTable) {
|
|
CHECK_CLOSE(169.0f / 16384.0f, gammaToLinear(0.125f), 2e-4f);
|
|
CHECK_CLOSE(6367.0f / 16384.0f, linearToGamma(0.125f), 2e-4f);
|
|
for (halnf value = 0; value <= 1.0f; value += 0.05f)
|
|
CHECK_CLOSE(value, linearToGamma(gammaToLinear(value)), 1e-5f);
|
|
CHECK_EQUAL(0.0f, gammaToLinear(-1));
|
|
CHECK_EQUAL(1.0f, linearToGamma(2));
|
|
}
|
|
}
|
|
|
|
SUITE(Vec2) {
|
|
TEST(AngleIsMeasuredFromThePositiveXAxis) {
|
|
CHECK_CLOSE(0.0f, Vec2F(2, 0).angle(), 1e-6f);
|
|
CHECK_CLOSE(1.5707963f, Vec2F(0, 3).angle(), 1e-6f);
|
|
CHECK_CLOSE(-1.5707963f, Vec2F(0, -1).angle(), 1e-6f);
|
|
}
|
|
|
|
TEST(RotatedTurnsCounterClockwiseAndKeepsLength) {
|
|
const Vec2F turned = Vec2F(1, 0).rotated(1.5707963f);
|
|
CHECK_CLOSE(0.0f, turned.x, 1e-6f);
|
|
CHECK_CLOSE(1.0f, turned.y, 1e-6f);
|
|
CHECK_CLOSE(Vec2F(3, 4).length(), Vec2F(3, 4).rotated(0.7f).length(), 1e-5f);
|
|
}
|
|
}
|