Skip to content

Commit 5b0070a

Browse files
committed
[Shell] blockstate resolver
1 parent fd7678d commit 5b0070a

7 files changed

Lines changed: 102 additions & 28 deletions

File tree

‎include/openminecraft-shell/data/block/om_block.hpp‎

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,49 @@
44
#include "openminecraft-shell/data/block/om_blockstate.hpp"
55
#include "openminecraft-shell/data/om_identifier.hpp"
66
#include <initializer_list>
7+
#include <set>
8+
#include <unordered_map>
9+
#include <unordered_set>
710
#include <utility>
811
#include <vector>
912
namespace openminecraftshell::data::block
1013
{
14+
struct OMBlockModelIdentifier
15+
{
16+
OMIdentifier location;
17+
int xrot = 0, yrot = 0, zrot = 0;
18+
bool uvlock = false;
19+
20+
OMBlockModelIdentifier() = default;
21+
22+
auto operator==(const OMBlockModelIdentifier ident) const -> bool
23+
{
24+
return location.namesp == ident.location.namesp && location.path == ident.location.path && xrot == ident.xrot &&
25+
yrot == ident.yrot && zrot == ident.zrot && uvlock == ident.uvlock;
26+
}
27+
};
28+
} // namespace openminecraftshell::data::block
29+
30+
namespace std
31+
{
32+
template <> struct hash<openminecraftshell::data::block::OMBlockModelIdentifier>
33+
{
34+
auto operator()(const openminecraftshell::data::block::OMBlockModelIdentifier &id) const noexcept -> std::size_t
35+
{
36+
std::size_t seed = 0;
37+
seed ^=
38+
std::hash<openminecraftshell::data::OMIdentifier>{}(id.location) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
39+
seed ^= std::hash<int>{}(id.xrot) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
40+
seed ^= std::hash<int>{}(id.yrot) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
41+
seed ^= std::hash<int>{}(id.zrot) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
42+
seed ^= std::hash<bool>{}(id.uvlock) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
43+
44+
return seed;
45+
}
46+
};
47+
} // namespace std
48+
namespace openminecraftshell::data::block
49+
{
1150
class OMBlock
1251
{
1352
public:
@@ -27,6 +66,7 @@ class OMBlock
2766

2867
const OMIdentifier name;
2968
std::vector<std::pair<OMBlockState, int>> states;
69+
std::unordered_map<OMBlockModelIdentifier, int> requiredModels;
3070
};
3171
} // namespace openminecraftshell::data::block
3272

‎include/openminecraft-shell/data/block/om_blockstate_resolver.hpp‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
#include "openminecraft-shell/data/block/om_block.hpp"
55
#include "openminecraft-shell/data/om_identifier.hpp"
66
#include "openminecraft-shell/data/om_model_precompiler.hpp"
7+
#include "openminecraft/io/json/om_io_ast_json.hpp"
78
#include "openminecraft/log/om_log_common.hpp"
9+
#include <memory>
810
namespace openminecraftshell::data::block
911
{
1012
class OMBlockstateResolver
@@ -19,6 +21,8 @@ class OMBlockstateResolver
1921
void resolve(OMBlock &);
2022

2123
private:
24+
void resolveModel(OMBlock &, std::shared_ptr<io::json::OMJsonNode>);
25+
2226
std::string root;
2327
OMModelPrecompiler &compiler;
2428
log::OMLogger logger;

‎include/openminecraft-shell/data/om_identifier.hpp‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ class OMIdentifier
1010
public:
1111
OMIdentifier(std::string np, std::string path);
1212
OMIdentifier(std::string);
13+
OMIdentifier() = default;
1314

1415
auto toPath() -> std::string;
1516

‎include/openminecraft-shell/data/om_model_precompiler.hpp‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <memory>
1515
#include <string>
1616
#include <tuple>
17+
#include <unordered_map>
1718
#include <vector>
1819
namespace openminecraftshell::data
1920
{
@@ -85,8 +86,8 @@ class OMModelPrecompiler : public openminecraft::renderer::common::wrap::OMVoxel
8586

8687
auto composeBlock(std::vector<int>, bool = true) -> int;
8788

88-
auto loadModelPart(OMIdentifier, bool = true) -> int;
89-
auto loadModelPartWithArgs(OMIdentifier, int, int, int, bool, bool = true) -> int;
89+
auto loadModelPart(OMIdentifier) -> int;
90+
auto loadModelPartWithArgs(OMIdentifier, int, int, int, bool) -> int;
9091

9192
auto queryNumParts(int bsid) -> int override;
9293
auto queryPartFaceEnabled(int bsid, int pid, openminecraft::renderer::common::wrap::OMVoxelFacing) -> bool override;
@@ -115,7 +116,7 @@ class OMModelPrecompiler : public openminecraft::renderer::common::wrap::OMVoxel
115116
OMTextureAtlas &textureAtlas;
116117
std::vector<OMModel> blockModels;
117118
std::vector<std::vector<OMModelPart>> modelParts;
118-
std::vector<bool> modelSoild;
119+
std::unordered_map<OMIdentifier, int> modelPartIdents;
119120
std::vector<bool> modelAmbientOcculusion;
120121
std::vector<bool> modelComplex;
121122
};
Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,32 @@
11
#include "openminecraft-shell/data/block/om_blockstate_resolver.hpp"
2+
#include "openminecraft-shell/data/block/om_block.hpp"
3+
#include "openminecraft-shell/data/om_identifier.hpp"
24
#include "openminecraft/vfs/om_vfs_base.hpp"
35
#include "openminecraft/io/json/om_io_ast_builder_json.hpp"
46

57
using namespace openminecraft::io;
68

79
namespace openminecraftshell::data::block
810
{
11+
void OMBlockstateResolver::resolveModel(OMBlock &blk, std::shared_ptr<io::json::OMJsonNode> node)
12+
{
13+
OMIdentifier ident(node->getMap()["model"]->getString());
14+
int xrot = node->getMap().count("x") ? node->getMap()["x"]->getNumber() : 0;
15+
int yrot = node->getMap().count("y") ? node->getMap()["y"]->getNumber() : 0;
16+
int zrot = node->getMap().count("z") ? node->getMap()["z"]->getNumber() : 0;
17+
bool uvlock = node->getMap().count("uvlock") ? node->getMap()["uvlock"]->getBoolean() : false;
18+
OMBlockModelIdentifier i = {ident, xrot, yrot, zrot, uvlock};
19+
if (blk.requiredModels.count(i))
20+
{
21+
return;
22+
}
23+
blk.requiredModels[i] = compiler.loadModelPartWithArgs(ident, xrot, yrot, zrot, uvlock);
24+
}
925
void OMBlockstateResolver::resolve(OMBlock &blk)
1026
{
27+
blk.states.clear();
28+
blk.requiredModels.clear();
29+
1130
auto ident = blk.name;
1231
auto ff = vfs::fsfetch(fmt::format("{}/{}/blockstates/{}.json", root, ident.namesp, ident.path));
1332
json::OMJsonAstBuilder bld(std::make_shared<json::OMJsonTokenIter>(ff));
@@ -17,12 +36,15 @@ void OMBlockstateResolver::resolve(OMBlock &blk)
1736
{
1837
for (auto &l : ll->getMap()["variants"]->getMap())
1938
{
20-
logger.warn("{}", l.first);
39+
resolveModel(blk, l.second);
2140
}
2241
}
23-
else
42+
else if (ll->getMap().count("multipart"))
2443
{
25-
logger.warn("multipart not supported!");
44+
for (auto &l : ll->getMap()["multipart"]->getArray())
45+
{
46+
resolveModel(blk, l->getMap()["apply"]);
47+
}
2648
}
2749
}
2850
} // namespace openminecraftshell::data::block

‎src/openminecraft/data/om_model_precompiler.cpp‎

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -273,9 +273,9 @@ auto OMModelPrecompiler::querySoild(int bsid) -> bool
273273
return blockModels[bsid].soild;
274274
}
275275

276-
auto OMModelPrecompiler::loadModelPart(OMIdentifier i, bool soild) -> int
276+
auto OMModelPrecompiler::loadModelPart(OMIdentifier i) -> int
277277
{
278-
return loadModelPartWithArgs(i, 0, 0, 0, false, soild);
278+
return loadModelPartWithArgs(i, 0, 0, 0, false);
279279
}
280280

281281
// INFO: General rorate function
@@ -314,17 +314,19 @@ auto rotateVoxelElement90(const glm::vec3 &from, const glm::vec3 &to, int i) ->
314314
return {newMin, newMax};
315315
}
316316

317-
auto OMModelPrecompiler::loadModelPartWithArgs(OMIdentifier i, int xrot, int yrot, int zrot, bool lockuv, bool soild)
318-
-> int
317+
auto OMModelPrecompiler::loadModelPartWithArgs(OMIdentifier i, int xrot, int yrot, int zrot, bool lockuv) -> int
319318
{
319+
logger.info("precompiling {}:{} @ {}, rot {} {} {}, uvlock {}", i.namesp, i.path, modelId, xrot, yrot, zrot,
320+
lockuv ? "true" : "false");
320321
modelParts.resize(modelId + 1);
321-
modelSoild.resize(modelId + 1);
322322
modelAmbientOcculusion.resize(modelId + 1);
323323
modelComplex.resize(modelId + 1);
324324

325325
modelComplex[modelId] = false;
326326
modelParts[modelId] = {};
327327

328+
modelPartIdents[i] = modelId;
329+
328330
auto prem = precompile(i);
329331
modelAmbientOcculusion[modelId] =
330332
prem->getMap().count("ambientocclusion") ? prem->getMap()["ambientocclusion"]->getBoolean() : true;
@@ -519,7 +521,6 @@ auto OMModelPrecompiler::loadModelPartWithArgs(OMIdentifier i, int xrot, int yro
519521
}
520522
}
521523

522-
modelSoild[modelId] = soild;
523524
modelId++;
524525
return modelId - 1;
525526
}
@@ -579,8 +580,14 @@ auto OMModelPrecompiler::precompile(OMIdentifier name, bool subsitute)
579580
}
580581
}
581582

583+
bool needToBeSpilt = true;
582584
for (auto &fce : elem->getMap()["faces"]->getMap())
583585
{
586+
if (!fce.second->getMap().count("tintindex"))
587+
{
588+
needToBeSpilt = false;
589+
}
590+
584591
auto text = fce.second->getMap()["texture"]->getString();
585592

586593
if (text[0] == '#' && tex.count(text.substr(1)))
@@ -607,6 +614,7 @@ auto OMModelPrecompiler::precompile(OMIdentifier name, bool subsitute)
607614
}
608615
}
609616
}
617+
modelComplex[modelId] = true;
610618
}
611619
}
612620
}

‎src/openminecraft/renderer/entrypoint_testrenderer.cpp‎

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -113,37 +113,35 @@ OMTestRenderer::OMTestRenderer(OMRenderer *renderer, std::function<OMRendererTex
113113

114114
voxelHandler = new data::OMModelPrecompiler("/external", textureAtlas);
115115
blockstateResolver = new data::block::OMBlockstateResolver("/external", *voxelHandler);
116-
voxelHandler->composeBlock({voxelHandler->loadModelPart(data::OMIdentifier("minecraft:block/air"), false)}, false);
116+
voxelHandler->composeBlock({voxelHandler->loadModelPart(data::OMIdentifier("minecraft:block/air"))}, false);
117117
voxelHandler->composeBlock({voxelHandler->loadModelPart(data::OMIdentifier("minecraft:block/stone"))});
118118
voxelHandler->composeBlock({voxelHandler->loadModelPart(data::OMIdentifier("minecraft:block/cobblestone"))});
119119
voxelHandler->composeBlock({voxelHandler->loadModelPart(data::OMIdentifier("minecraft:block/coal_ore"))});
120120
voxelHandler->composeBlock({voxelHandler->loadModelPart(data::OMIdentifier("minecraft:block/iron_ore"))});
121121
voxelHandler->composeBlock({voxelHandler->loadModelPart(data::OMIdentifier("minecraft:block/dirt"))});
122122
voxelHandler->composeBlock({voxelHandler->loadModelPart(data::OMIdentifier("minecraft:block/copper_ore"))});
123-
voxelHandler->composeBlock(
124-
{voxelHandler->loadModelPart(data::OMIdentifier("minecraft:block/tall_grass_bottom"), false)}, false);
125-
voxelHandler->composeBlock(
126-
{voxelHandler->loadModelPart(data::OMIdentifier("minecraft:block/tall_grass_top"), false)}, false);
127-
voxelHandler->composeBlock({voxelHandler->loadModelPart(data::OMIdentifier("minecraft:block/oak_stairs"), false)},
123+
voxelHandler->composeBlock({voxelHandler->loadModelPart(data::OMIdentifier("minecraft:block/tall_grass_bottom"))},
128124
false);
125+
voxelHandler->composeBlock({voxelHandler->loadModelPart(data::OMIdentifier("minecraft:block/tall_grass_top"))},
126+
false);
127+
voxelHandler->composeBlock({voxelHandler->loadModelPart(data::OMIdentifier("minecraft:block/oak_stairs"))}, false);
129128
voxelHandler->composeBlock(
130-
{voxelHandler->loadModelPart(data::OMIdentifier("minecraft:block/spruce_door_bottom_left"), false)}, false);
131-
voxelHandler->composeBlock(
132-
{voxelHandler->loadModelPart(data::OMIdentifier("minecraft:block/spruce_door_top_left"), false)}, false);
129+
{voxelHandler->loadModelPart(data::OMIdentifier("minecraft:block/spruce_door_bottom_left"))}, false);
133130
voxelHandler->composeBlock(
134-
{voxelHandler->loadModelPart(data::OMIdentifier("minecraft:block/acacia_sign_rot_0"), false)}, false);
131+
{voxelHandler->loadModelPart(data::OMIdentifier("minecraft:block/spruce_door_top_left"))}, false);
132+
voxelHandler->composeBlock({voxelHandler->loadModelPart(data::OMIdentifier("minecraft:block/acacia_sign_rot_0"))},
133+
false);
135134
voxelHandler->composeBlock(
136-
{voxelHandler->loadModelPartWithArgs(data::OMIdentifier("minecraft:block/oak_button"), 0, 0, 0, false, false)},
137-
false);
135+
{voxelHandler->loadModelPartWithArgs(data::OMIdentifier("minecraft:block/oak_button"), 0, 0, 0, false)}, false);
138136
voxelHandler->composeBlock(
139-
{voxelHandler->loadModelPartWithArgs(data::OMIdentifier("minecraft:block/oak_shelf"), 0, 90, 0, false, false),
140-
voxelHandler->loadModelPartWithArgs(data::OMIdentifier("minecraft:block/oak_shelf_unpowered"), 0, 90, 0, false,
137+
{voxelHandler->loadModelPartWithArgs(data::OMIdentifier("minecraft:block/oak_shelf"), 0, 90, 0, false),
138+
voxelHandler->loadModelPartWithArgs(data::OMIdentifier("minecraft:block/oak_shelf_unpowered"), 0, 90, 0,
141139
false)},
142140
false);
143141
voxelHandler->composeBlock({voxelHandler->loadModelPart(data::OMIdentifier("minecraft:block/grass_block"))});
144142
voxelHandler->composeBlock(
145-
{voxelHandler->loadModelPart(data::OMIdentifier("minecraft:block/acacia_fence_gate_open"), false)}, false);
146-
voxelHandler->composeBlock({voxelHandler->loadModelPart(data::OMIdentifier("minecraft:block/rail"), false)}, false);
143+
{voxelHandler->loadModelPart(data::OMIdentifier("minecraft:block/acacia_fence_gate_open"))}, false);
144+
voxelHandler->composeBlock({voxelHandler->loadModelPart(data::OMIdentifier("minecraft:block/rail"))}, false);
147145

148146
data::block::OMBlock blk(data::OMIdentifier("minecraft:acacia_button"));
149147
blockstateResolver->resolve(blk);

0 commit comments

Comments
 (0)