98 lines
4.4 KiB
C++
98 lines
4.4 KiB
C++
#include <array>
|
|
#include <memory>
|
|
#include <vector>
|
|
#include "graphics/Canvas.h"
|
|
#include "graphics/Graphics.h"
|
|
#include "graphics/Mesh.h"
|
|
#include "image/ImageData.h"
|
|
#include "zeroerr/assert.h"
|
|
#include "zeroerr/unittest.h"
|
|
|
|
TEST_CASE("graphics.skinPalette.largeJointMovesRenderedPixels") {
|
|
using namespace eve::graphics;
|
|
auto* gfx = Graphics::create();
|
|
REQUIRE(gfx != nullptr);
|
|
gfx->initHeadless(128, 128);
|
|
Canvas* canvas = gfx->newCanvas(128, 128);
|
|
REQUIRE(canvas != nullptr);
|
|
const float positions[] = {-0.2f, -0.2f, 0.5f, 0.2f, -0.2f, 0.5f, 0.f, 0.2f, 0.5f};
|
|
const uint32_t indices[] = {0, 1, 2, 2, 1, 0};
|
|
auto* mesh = gfx->newMeshFromArrays(positions, nullptr, nullptr, 3, indices, 6);
|
|
REQUIRE(mesh != nullptr);
|
|
const float weights[] = {1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0};
|
|
gfx->setMesh3DViewProj(glm::mat4(1.f));
|
|
std::vector<unsigned char> first;
|
|
for (int count : {129, 204, 1024, 4096, 204}) {
|
|
const uint16_t last = static_cast<uint16_t>(count - 1);
|
|
const uint16_t joints[] = {last, 0, 0, 0, last, 0, 0, 0, last, 0, 0, 0};
|
|
REQUIRE(gfx->setMeshSkinningData(mesh, joints, weights, 3));
|
|
std::vector<float> palette(size_t(count) * 16, 0.f);
|
|
for (int i = 0; i < count; ++i)
|
|
for (int j : {0, 5, 10, 15}) palette[size_t(i) * 16 + j] = 1.f;
|
|
for (float translation : {-0.5f, 0.5f}) {
|
|
palette[size_t(count - 1) * 16 + 12] = translation;
|
|
REQUIRE(mesh->setSkinPalette(palette.data(), count).ok());
|
|
gfx->begin3DFrameToCanvas(canvas);
|
|
gfx->drawMesh(mesh, glm::mat4(1.f), nullptr, Color(1.f, 0.2f, 0.1f, 1.f));
|
|
gfx->end3DFrameToCanvas();
|
|
std::unique_ptr<eve::image::ImageData> pixels(canvas->newImageData());
|
|
REQUIRE(pixels != nullptr);
|
|
const auto* data = static_cast<const unsigned char*>(pixels->getData());
|
|
const size_t size = 128u * 128u * 4u;
|
|
if (translation < 0)
|
|
first.assign(data, data + size);
|
|
else {
|
|
size_t changed = 0;
|
|
for (size_t i = 0; i < size; i += 4)
|
|
if (data[i] != first[i] || data[i + 1] != first[i + 1] || data[i + 2] != first[i + 2]) ++changed;
|
|
REQUIRE(changed > 200);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_CASE("graphics.skinPalette.influenceLimitChangesRenderedDeformation") {
|
|
using namespace eve::graphics;
|
|
auto* gfx = Graphics::create();
|
|
REQUIRE(gfx != nullptr);
|
|
gfx->initHeadless(128, 128);
|
|
Canvas* canvas = gfx->newCanvas(128, 128);
|
|
REQUIRE(canvas != nullptr);
|
|
const float positions[] = {-0.15f, -0.15f, 0.5f, 0.15f, -0.15f, 0.5f, 0.f, 0.15f, 0.5f};
|
|
const uint32_t indices[] = {0, 1, 2, 2, 1, 0};
|
|
Mesh* mesh = gfx->newMeshFromArrays(positions, nullptr, nullptr, 3, indices, 6);
|
|
REQUIRE(mesh != nullptr);
|
|
const uint16_t joints[] = {0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0};
|
|
const float weights[] = {.75f, .25f, 0.f, 0.f, .75f, .25f, 0.f, 0.f,
|
|
.75f, .25f, 0.f, 0.f};
|
|
REQUIRE(gfx->setMeshSkinningData(mesh, joints, weights, 3));
|
|
std::array<float, 32> palette{};
|
|
for (int bone = 0; bone < 2; ++bone)
|
|
for (int diagonal : {0, 5, 10, 15}) palette[static_cast<size_t>(bone) * 16 + diagonal] = 1.f;
|
|
palette[12] = -.45f;
|
|
palette[16 + 12] = .45f;
|
|
REQUIRE(mesh->setSkinPalette(palette.data(), 2).ok());
|
|
gfx->setMesh3DViewProj(glm::mat4(1.f));
|
|
|
|
std::vector<unsigned char> oneInfluence;
|
|
for (SkinInfluenceLimit limit : {SkinInfluenceLimit::One, SkinInfluenceLimit::Two}) {
|
|
gfx->setMesh3DSkinInfluenceLimit(limit);
|
|
gfx->begin3DFrameToCanvas(canvas);
|
|
gfx->drawMesh(mesh, glm::mat4(1.f), nullptr, Color(1.f, .2f, .1f, 1.f));
|
|
gfx->end3DFrameToCanvas();
|
|
std::unique_ptr<eve::image::ImageData> pixels(canvas->newImageData());
|
|
REQUIRE(pixels != nullptr);
|
|
const auto* data = static_cast<const unsigned char*>(pixels->getData());
|
|
if (limit == SkinInfluenceLimit::One) {
|
|
oneInfluence.assign(data, data + 128u * 128u * 4u);
|
|
} else {
|
|
size_t changed = 0;
|
|
for (size_t i = 0; i < oneInfluence.size(); i += 4)
|
|
if (data[i] != oneInfluence[i] || data[i + 1] != oneInfluence[i + 1] ||
|
|
data[i + 2] != oneInfluence[i + 2])
|
|
++changed;
|
|
REQUIRE(changed > 150);
|
|
}
|
|
}
|
|
}
|