forked from Mirrorlandia_minetest/minetest
Add meshgen tests
This commit is contained in:
parent
753f03ff6a
commit
0d30a3071a
@ -44,6 +44,7 @@ set (UNITTEST_SRCS
|
||||
set (UNITTEST_CLIENT_SRCS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/mesh_compare.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_clientactiveobjectmgr.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_content_mapblock.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_eventmanager.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_gameui.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test_mesh_compare.cpp
|
||||
|
268
src/unittest/test_content_mapblock.cpp
Normal file
268
src/unittest/test_content_mapblock.cpp
Normal file
@ -0,0 +1,268 @@
|
||||
/*
|
||||
Minetest
|
||||
Copyright (C) 2023 Vitaliy Lobachevskiy
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "test.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
|
||||
#include "gamedef.h"
|
||||
#include "dummygamedef.h"
|
||||
#include "client/content_mapblock.h"
|
||||
#include "client/mapblock_mesh.h"
|
||||
#include "client/meshgen/collector.h"
|
||||
#include "mesh_compare.h"
|
||||
#include "util/directiontables.h"
|
||||
|
||||
namespace {
|
||||
|
||||
class MockGameDef : public DummyGameDef {
|
||||
public:
|
||||
IWritableItemDefManager *item_mgr() noexcept {
|
||||
return static_cast<IWritableItemDefManager *>(m_itemdef);
|
||||
}
|
||||
|
||||
NodeDefManager *node_mgr() noexcept {
|
||||
return const_cast<NodeDefManager *>(m_nodedef);
|
||||
}
|
||||
|
||||
content_t registerNode(ItemDefinition itemdef, ContentFeatures nodedef) {
|
||||
item_mgr()->registerItem(itemdef);
|
||||
return node_mgr()->set(nodedef.name, nodedef);
|
||||
}
|
||||
|
||||
void finalize() {
|
||||
node_mgr()->resolveCrossrefs();
|
||||
}
|
||||
|
||||
MeshMakeData makeSingleNodeMMD(bool smooth_lighting = true, bool for_shaders = true)
|
||||
{
|
||||
MeshMakeData data{ndef(), 1, for_shaders};
|
||||
data.setSmoothLighting(smooth_lighting);
|
||||
data.m_blockpos = {0, 0, 0};
|
||||
for (s16 x = -1; x <= 1; x++)
|
||||
for (s16 y = -1; y <= 1; y++)
|
||||
for (s16 z = -1; z <= 1; z++)
|
||||
data.m_vmanip.setNode({x, y, z}, {CONTENT_AIR, 0, 0});
|
||||
return data;
|
||||
}
|
||||
|
||||
content_t addSimpleNode(std::string name, u32 texture)
|
||||
{
|
||||
ItemDefinition itemdef;
|
||||
itemdef.type = ITEM_NODE;
|
||||
itemdef.name = "test:" + name;
|
||||
itemdef.description = name;
|
||||
|
||||
ContentFeatures f;
|
||||
f.name = itemdef.name;
|
||||
f.drawtype = NDT_NORMAL;
|
||||
f.solidness = 2;
|
||||
f.alpha = ALPHAMODE_OPAQUE;
|
||||
for (TileDef &tiledef : f.tiledef)
|
||||
tiledef.name = name + ".png";
|
||||
for (TileSpec &tile : f.tiles)
|
||||
tile.layers[0].texture_id = texture;
|
||||
|
||||
return registerNode(itemdef, f);
|
||||
}
|
||||
|
||||
content_t addLiquidSource(std::string name, u32 texture)
|
||||
{
|
||||
ItemDefinition itemdef;
|
||||
itemdef.type = ITEM_NODE;
|
||||
itemdef.name = "test:" + name + "_source";
|
||||
itemdef.description = name;
|
||||
|
||||
ContentFeatures f;
|
||||
f.name = itemdef.name;
|
||||
f.drawtype = NDT_LIQUID;
|
||||
f.solidness = 1;
|
||||
f.alpha = ALPHAMODE_BLEND;
|
||||
f.light_propagates = true;
|
||||
f.param_type = CPT_LIGHT;
|
||||
f.liquid_type = LIQUID_SOURCE;
|
||||
f.liquid_viscosity = 4;
|
||||
f.groups["liquids"] = 3;
|
||||
f.liquid_alternative_source = "test:" + name + "_source";
|
||||
f.liquid_alternative_flowing = "test:" + name + "_flowing";
|
||||
for (TileDef &tiledef : f.tiledef)
|
||||
tiledef.name = name + ".png";
|
||||
for (TileSpec &tile : f.tiles)
|
||||
tile.layers[0].texture_id = texture;
|
||||
|
||||
return registerNode(itemdef, f);
|
||||
}
|
||||
|
||||
content_t addLiquidFlowing(std::string name, u32 texture_top, u32 texture_side)
|
||||
{
|
||||
ItemDefinition itemdef;
|
||||
itemdef.type = ITEM_NODE;
|
||||
itemdef.name = "test:" + name + "_flowing";
|
||||
itemdef.description = name;
|
||||
|
||||
ContentFeatures f;
|
||||
f.name = itemdef.name;
|
||||
f.drawtype = NDT_FLOWINGLIQUID;
|
||||
f.solidness = 0;
|
||||
f.alpha = ALPHAMODE_BLEND;
|
||||
f.light_propagates = true;
|
||||
f.param_type = CPT_LIGHT;
|
||||
f.liquid_type = LIQUID_FLOWING;
|
||||
f.liquid_viscosity = 4;
|
||||
f.groups["liquids"] = 3;
|
||||
f.liquid_alternative_source = "test:" + name + "_source";
|
||||
f.liquid_alternative_flowing = "test:" + name + "_flowing";
|
||||
f.tiledef_special[0].name = name + "_top.png";
|
||||
f.tiledef_special[1].name = name + "_side.png";
|
||||
f.special_tiles[0].layers[0].texture_id = texture_top;
|
||||
f.special_tiles[1].layers[0].texture_id = texture_side;
|
||||
|
||||
return registerNode(itemdef, f);
|
||||
}
|
||||
};
|
||||
|
||||
void set_light_decode_table()
|
||||
{
|
||||
u8 table[LIGHT_SUN + 1] = {
|
||||
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
|
||||
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
|
||||
};
|
||||
memcpy(const_cast<u8 *>(light_decode_table), table, sizeof(table));
|
||||
}
|
||||
|
||||
class TestMapblockMeshGenerator : public TestBase {
|
||||
public:
|
||||
TestMapblockMeshGenerator() { TestManager::registerTestModule(this); }
|
||||
const char *getName() override { return "TestMapblockMeshGenerator"; }
|
||||
|
||||
void runTests(IGameDef *gamedef) override;
|
||||
void testSimpleNode();
|
||||
void testSurroundedNode();
|
||||
void testInterliquidSame();
|
||||
void testInterliquidDifferent();
|
||||
};
|
||||
|
||||
static TestMapblockMeshGenerator g_test_instance;
|
||||
|
||||
void TestMapblockMeshGenerator::runTests(IGameDef *gamedef)
|
||||
{
|
||||
set_light_decode_table();
|
||||
TEST(testSimpleNode);
|
||||
TEST(testSurroundedNode);
|
||||
TEST(testInterliquidSame);
|
||||
TEST(testInterliquidDifferent);
|
||||
}
|
||||
|
||||
namespace quad {
|
||||
constexpr float h = BS / 2.0f;
|
||||
const Quad zp{{{{-h, -h, h}, {0, 0, 1}, 0, {1, 1}}, {{h, -h, h}, {0, 0, 1}, 0, {0, 1}}, {{h, h, h}, {0, 0, 1}, 0, {0, 0}}, {{-h, h, h}, {0, 0, 1}, 0, {1, 0}}}};
|
||||
const Quad yp{{{{-h, h, -h}, {0, 1, 0}, 0, {0, 1}}, {{-h, h, h}, {0, 1, 0}, 0, {0, 0}}, {{h, h, h}, {0, 1, 0}, 0, {1, 0}}, {{h, h, -h}, {0, 1, 0}, 0, {1, 1}}}};
|
||||
const Quad xp{{{{h, -h, -h}, {1, 0, 0}, 0, {0, 1}}, {{h, h, -h}, {1, 0, 0}, 0, {0, 0}}, {{h, h, h}, {1, 0, 0}, 0, {1, 0}}, {{h, -h, h}, {1, 0, 0}, 0, {1, 1}}}};
|
||||
const Quad zn{{{{-h, -h, -h}, {0, 0, -1}, 0, {0, 1}}, {{-h, h, -h}, {0, 0, -1}, 0, {0, 0}}, {{h, h, -h}, {0, 0, -1}, 0, {1, 0}}, {{h, -h, -h}, {0, 0, -1}, 0, {1, 1}}}};
|
||||
const Quad yn{{{{-h, -h, -h}, {0, -1, 0}, 0, {0, 0}}, {{h, -h, -h}, {0, -1, 0}, 0, {1, 0}}, {{h, -h, h}, {0, -1, 0}, 0, {1, 1}}, {{-h, -h, h}, {0, -1, 0}, 0, {0, 1}}}};
|
||||
const Quad xn{{{{-h, -h, -h}, {-1, 0, 0}, 0, {1, 1}}, {{-h, -h, h}, {-1, 0, 0}, 0, {0, 1}}, {{-h, h, h}, {-1, 0, 0}, 0, {0, 0}}, {{-h, h, -h}, {-1, 0, 0}, 0, {1, 0}}}};
|
||||
}
|
||||
|
||||
void TestMapblockMeshGenerator::testSimpleNode()
|
||||
{
|
||||
MockGameDef gamedef;
|
||||
content_t stone = gamedef.addSimpleNode("stone", 42);
|
||||
gamedef.finalize();
|
||||
|
||||
MeshMakeData data = gamedef.makeSingleNodeMMD();
|
||||
data.m_vmanip.setNode({0, 0, 0}, {stone, 0, 0});
|
||||
|
||||
MeshCollector col{{}};
|
||||
MapblockMeshGenerator mg{&data, &col, nullptr};
|
||||
mg.generate();
|
||||
UASSERTEQ(std::size_t, col.prebuffers[0].size(), 1);
|
||||
UASSERTEQ(std::size_t, col.prebuffers[1].size(), 0);
|
||||
|
||||
auto &&buf = col.prebuffers[0][0];
|
||||
UASSERTEQ(u32, buf.layer.texture_id, 42);
|
||||
UASSERT(checkMeshEqual(buf.vertices, buf.indices, {quad::xn, quad::xp, quad::yn, quad::yp, quad::zn, quad::zp}));
|
||||
}
|
||||
|
||||
void TestMapblockMeshGenerator::testSurroundedNode()
|
||||
{
|
||||
MockGameDef gamedef;
|
||||
content_t stone = gamedef.addSimpleNode("stone", 42);
|
||||
content_t wood = gamedef.addSimpleNode("wood", 13);
|
||||
gamedef.finalize();
|
||||
|
||||
MeshMakeData data = gamedef.makeSingleNodeMMD();
|
||||
data.m_vmanip.setNode({0, 0, 0}, {stone, 0, 0});
|
||||
data.m_vmanip.setNode({1, 0, 0}, {wood, 0, 0});
|
||||
|
||||
MeshCollector col{{}};
|
||||
MapblockMeshGenerator mg{&data, &col, nullptr};
|
||||
mg.generate();
|
||||
UASSERTEQ(std::size_t, col.prebuffers[0].size(), 1);
|
||||
UASSERTEQ(std::size_t, col.prebuffers[1].size(), 0);
|
||||
|
||||
auto &&buf = col.prebuffers[0][0];
|
||||
UASSERTEQ(u32, buf.layer.texture_id, 42);
|
||||
UASSERT(checkMeshEqual(buf.vertices, buf.indices, {quad::xn, quad::yn, quad::yp, quad::zn, quad::zp}));
|
||||
}
|
||||
|
||||
void TestMapblockMeshGenerator::testInterliquidSame()
|
||||
{
|
||||
MockGameDef gamedef;
|
||||
auto water = gamedef.addLiquidSource("water", 42);
|
||||
gamedef.finalize();
|
||||
|
||||
MeshMakeData data = gamedef.makeSingleNodeMMD();
|
||||
data.m_vmanip.setNode({0, 0, 0}, {water, 0, 0});
|
||||
data.m_vmanip.setNode({1, 0, 0}, {water, 0, 0});
|
||||
|
||||
MeshCollector col{{}};
|
||||
MapblockMeshGenerator mg{&data, &col, nullptr};
|
||||
mg.generate();
|
||||
UASSERTEQ(std::size_t, col.prebuffers[0].size(), 1);
|
||||
UASSERTEQ(std::size_t, col.prebuffers[1].size(), 0);
|
||||
|
||||
auto &&buf = col.prebuffers[0][0];
|
||||
UASSERTEQ(u32, buf.layer.texture_id, 42);
|
||||
UASSERT(checkMeshEqual(buf.vertices, buf.indices, {quad::xn, quad::yn, quad::yp, quad::zn, quad::zp}));
|
||||
}
|
||||
|
||||
void TestMapblockMeshGenerator::testInterliquidDifferent()
|
||||
{
|
||||
MockGameDef gamedef;
|
||||
auto water = gamedef.addLiquidSource("water", 42);
|
||||
auto lava = gamedef.addLiquidSource("lava", 13);
|
||||
gamedef.finalize();
|
||||
|
||||
MeshMakeData data = gamedef.makeSingleNodeMMD();
|
||||
data.m_vmanip.setNode({0, 0, 0}, {water, 0, 0});
|
||||
data.m_vmanip.setNode({0, 0, 1}, {lava, 0, 0});
|
||||
|
||||
MeshCollector col{{}};
|
||||
MapblockMeshGenerator mg{&data, &col, nullptr};
|
||||
mg.generate();
|
||||
UASSERTEQ(std::size_t, col.prebuffers[0].size(), 1);
|
||||
UASSERTEQ(std::size_t, col.prebuffers[1].size(), 0);
|
||||
|
||||
auto &&buf = col.prebuffers[0][0];
|
||||
UASSERTEQ(u32, buf.layer.texture_id, 42);
|
||||
UASSERT(checkMeshEqual(buf.vertices, buf.indices, {quad::xn, quad::xp, quad::yn, quad::yp, quad::zn, quad::zp}));
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user