Merge pull request #350 from MihailRis/block-models-advanced
Improve block custom models
This commit is contained in:
commit
1aeaa667c9
@ -19,10 +19,10 @@
|
||||
#include "graphics/core/Atlas.hpp"
|
||||
#include "graphics/core/Font.hpp"
|
||||
#include "graphics/core/ImageData.hpp"
|
||||
#include "graphics/core/Model.hpp"
|
||||
#include "graphics/core/Shader.hpp"
|
||||
#include "graphics/core/Texture.hpp"
|
||||
#include "graphics/core/TextureAnimation.hpp"
|
||||
#include "graphics/commons/Model.hpp"
|
||||
#include "objects/rigging.hpp"
|
||||
#include "util/stringutil.hpp"
|
||||
#include "Assets.hpp"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#include "obj.hpp"
|
||||
|
||||
#include "graphics/core/Model.hpp"
|
||||
#include "graphics/commons/Model.hpp"
|
||||
#include "commons.hpp"
|
||||
|
||||
using namespace model;
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
#include "byte_utils.hpp"
|
||||
#include "util/data_io.hpp"
|
||||
#include "util/stringutil.hpp"
|
||||
#include "graphics/core/Model.hpp"
|
||||
#include "graphics/commons/Model.hpp"
|
||||
|
||||
inline constexpr int VERSION = 1;
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
#include "typedefs.hpp"
|
||||
#include "util/Buffer.hpp"
|
||||
#include "graphics/core/Model.hpp"
|
||||
#include "graphics/commons/Model.hpp"
|
||||
|
||||
/// See /doc/specs/vec3_model_spec.md
|
||||
namespace vec3 {
|
||||
|
||||
@ -219,19 +219,26 @@ void ContentLoader::loadBlock(
|
||||
}
|
||||
|
||||
// block model
|
||||
std::string modelName;
|
||||
root.at("model").get(modelName);
|
||||
if (auto model = BlockModel_from(modelName)) {
|
||||
std::string modelTypeName;
|
||||
root.at("model").get(modelTypeName);
|
||||
root.at("model-name").get(def.modelName);
|
||||
if (auto model = BlockModel_from(modelTypeName)) {
|
||||
if (*model == BlockModel::custom) {
|
||||
if (root.has("model-primitives")) {
|
||||
loadCustomBlockModel(def, root["model-primitives"]);
|
||||
} else {
|
||||
logger.error() << name << ": no 'model-primitives' found";
|
||||
def.customModelRaw = root["model-primitives"];
|
||||
} else if (def.modelName.empty()) {
|
||||
throw std::runtime_error(name + ": no 'model-primitives' or 'model-name' found");
|
||||
}
|
||||
for (uint i = 0; i < 6; i++) {
|
||||
std::string& texture = def.textureFaces[i];
|
||||
if (texture == TEXTURE_NOTFOUND) {
|
||||
texture = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
def.model = *model;
|
||||
} else if (!modelName.empty()) {
|
||||
logger.error() << "unknown model " << modelName;
|
||||
} else if (!modelTypeName.empty()) {
|
||||
logger.error() << "unknown model " << modelTypeName;
|
||||
def.model = BlockModel::none;
|
||||
}
|
||||
|
||||
@ -277,8 +284,6 @@ void ContentLoader::loadBlock(
|
||||
);
|
||||
aabb.b += aabb.a;
|
||||
def.hitboxes = {aabb};
|
||||
} else if (!def.modelBoxes.empty()) {
|
||||
def.hitboxes = def.modelBoxes;
|
||||
} else {
|
||||
def.hitboxes = {AABB()};
|
||||
}
|
||||
@ -350,61 +355,6 @@ void ContentLoader::loadBlock(
|
||||
}
|
||||
}
|
||||
|
||||
void ContentLoader::loadCustomBlockModel(Block& def, const dv::value& primitives) {
|
||||
if (primitives.has("aabbs")) {
|
||||
const auto& modelboxes = primitives["aabbs"];
|
||||
for (uint i = 0; i < modelboxes.size(); i++) {
|
||||
// Parse aabb
|
||||
const auto& boxarr = modelboxes[i];
|
||||
AABB modelbox;
|
||||
modelbox.a = glm::vec3(
|
||||
boxarr[0].asNumber(), boxarr[1].asNumber(), boxarr[2].asNumber()
|
||||
);
|
||||
modelbox.b = glm::vec3(
|
||||
boxarr[3].asNumber(), boxarr[4].asNumber(), boxarr[5].asNumber()
|
||||
);
|
||||
modelbox.b += modelbox.a;
|
||||
def.modelBoxes.push_back(modelbox);
|
||||
|
||||
if (boxarr.size() == 7) {
|
||||
for (uint j = 6; j < 12; j++) {
|
||||
def.modelTextures.emplace_back(boxarr[6].asString());
|
||||
}
|
||||
} else if (boxarr.size() == 12) {
|
||||
for (uint j = 6; j < 12; j++) {
|
||||
def.modelTextures.emplace_back(boxarr[j].asString());
|
||||
}
|
||||
} else {
|
||||
for (uint j = 6; j < 12; j++) {
|
||||
def.modelTextures.emplace_back("notfound");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (primitives.has("tetragons")) {
|
||||
const auto& modeltetragons = primitives["tetragons"];
|
||||
for (uint i = 0; i < modeltetragons.size(); i++) {
|
||||
// Parse tetragon to points
|
||||
const auto& tgonobj = modeltetragons[i];
|
||||
glm::vec3 p1(
|
||||
tgonobj[0].asNumber(), tgonobj[1].asNumber(), tgonobj[2].asNumber()
|
||||
);
|
||||
glm::vec3 xw(
|
||||
tgonobj[3].asNumber(), tgonobj[4].asNumber(), tgonobj[5].asNumber()
|
||||
);
|
||||
glm::vec3 yh(
|
||||
tgonobj[6].asNumber(), tgonobj[7].asNumber(), tgonobj[8].asNumber()
|
||||
);
|
||||
def.modelExtraPoints.push_back(p1);
|
||||
def.modelExtraPoints.push_back(p1 + xw);
|
||||
def.modelExtraPoints.push_back(p1 + xw + yh);
|
||||
def.modelExtraPoints.push_back(p1 + yh);
|
||||
|
||||
def.modelTextures.emplace_back(tgonobj[9].asString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ContentLoader::loadItem(
|
||||
ItemDef& def, const std::string& name, const fs::path& file
|
||||
) {
|
||||
|
||||
@ -42,7 +42,6 @@ class ContentLoader {
|
||||
GeneratorDef& def, const std::string& full, const std::string& name
|
||||
);
|
||||
|
||||
static void loadCustomBlockModel(Block& def, const dv::value& primitives);
|
||||
static void loadBlockMaterial(BlockMaterial& def, const fs::path& file);
|
||||
void loadBlock(
|
||||
Block& def, const std::string& name, const fs::path& file
|
||||
|
||||
@ -286,6 +286,21 @@ void Engine::loadAssets() {
|
||||
assets = std::move(new_assets);
|
||||
|
||||
if (content) {
|
||||
for (auto& [name, def] : content->blocks.getDefs()) {
|
||||
if (def->model == BlockModel::custom) {
|
||||
if (def->modelName.empty()) {
|
||||
assets->store(
|
||||
std::make_unique<model::Model>(
|
||||
ModelsGenerator::loadCustomBlockModel(
|
||||
def->customModelRaw, *assets, !def->shadeless
|
||||
)
|
||||
),
|
||||
name + ".model"
|
||||
);
|
||||
def->modelName = def->name + ".model";
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto& [name, def] : content->items.getDefs()) {
|
||||
assets->store(
|
||||
std::make_unique<model::Model>(
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
#include "ContentGfxCache.hpp"
|
||||
|
||||
#include "UiDocument.hpp"
|
||||
#include <string>
|
||||
|
||||
#include "UiDocument.hpp"
|
||||
#include "assets/Assets.hpp"
|
||||
#include "content/Content.hpp"
|
||||
#include "content/ContentPack.hpp"
|
||||
@ -10,15 +11,14 @@
|
||||
#include "maths/UVRegion.hpp"
|
||||
#include "voxels/Block.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
ContentGfxCache::ContentGfxCache(const Content* content, Assets* assets) : content(content) {
|
||||
ContentGfxCache::ContentGfxCache(const Content* content, Assets* assets)
|
||||
: content(content) {
|
||||
auto indices = content->getIndices();
|
||||
sideregions = std::make_unique<UVRegion[]>(indices->blocks.count() * 6);
|
||||
auto atlas = assets->get<Atlas>("blocks");
|
||||
|
||||
|
||||
const auto& blocks = indices->blocks.getIterable();
|
||||
for (uint i = 0; i < blocks.size(); i++) {
|
||||
for (blockid_t i = 0; i < blocks.size(); i++) {
|
||||
auto def = blocks[i];
|
||||
for (uint side = 0; side < 6; side++) {
|
||||
const std::string& tex = def->textureFaces[side];
|
||||
@ -28,13 +28,9 @@ ContentGfxCache::ContentGfxCache(const Content* content, Assets* assets) : conte
|
||||
sideregions[i * 6 + side] = atlas->get(TEXTURE_NOTFOUND);
|
||||
}
|
||||
}
|
||||
for (uint side = 0; side < def->modelTextures.size(); side++) {
|
||||
const std::string& tex = def->modelTextures[side];
|
||||
if (atlas->has(tex)) {
|
||||
def->modelUVs.push_back(atlas->get(tex));
|
||||
} else if (atlas->has(TEXTURE_NOTFOUND)) {
|
||||
def->modelUVs.push_back(atlas->get(TEXTURE_NOTFOUND));
|
||||
}
|
||||
if (def->model == BlockModel::custom) {
|
||||
models[def->rt.id] =
|
||||
assets->require<model::Model>(def->modelName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -44,3 +40,11 @@ ContentGfxCache::~ContentGfxCache() = default;
|
||||
const Content* ContentGfxCache::getContent() const {
|
||||
return content;
|
||||
}
|
||||
|
||||
const model::Model& ContentGfxCache::getModel(blockid_t id) const {
|
||||
const auto& found = models.find(id);
|
||||
if (found == models.end()) {
|
||||
throw std::runtime_error("model not found");
|
||||
}
|
||||
return found->second;
|
||||
}
|
||||
|
||||
@ -3,15 +3,24 @@
|
||||
#include "typedefs.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "graphics/commons/Model.hpp"
|
||||
|
||||
class Content;
|
||||
class Assets;
|
||||
struct UVRegion;
|
||||
|
||||
namespace model {
|
||||
struct Model;
|
||||
}
|
||||
|
||||
class ContentGfxCache {
|
||||
const Content* content;
|
||||
// array of block sides uv regions (6 per block)
|
||||
std::unique_ptr<UVRegion[]> sideregions;
|
||||
std::unordered_map<blockid_t, model::Model> models;
|
||||
public:
|
||||
ContentGfxCache(const Content* content, Assets* assets);
|
||||
~ContentGfxCache();
|
||||
@ -19,6 +28,8 @@ public:
|
||||
inline const UVRegion& getRegion(blockid_t id, int side) const {
|
||||
return sideregions[id * 6 + side];
|
||||
}
|
||||
|
||||
const model::Model& getModel(blockid_t id) const;
|
||||
|
||||
const Content* getContent() const;
|
||||
};
|
||||
|
||||
@ -36,7 +36,7 @@ void Mesh::addPlane(
|
||||
|
||||
vertices.push_back({pos-right-up, {uv.u1, uv.v1}, norm});
|
||||
vertices.push_back({pos+right+up, {uv.u2, uv.v2}, norm});
|
||||
vertices.push_back({pos-right+up, {uv.u1, uv.u2}, norm});
|
||||
vertices.push_back({pos-right+up, {uv.u1, uv.v2}, norm});
|
||||
}
|
||||
|
||||
void Mesh::addBox(const glm::vec3& pos, const glm::vec3& size) {
|
||||
@ -60,47 +60,24 @@ std::unique_ptr<ImageData> BlocksPreview::draw(
|
||||
}
|
||||
batch->flush();
|
||||
break;
|
||||
case BlockModel::custom:
|
||||
{
|
||||
glm::vec3 pmul = glm::vec3(size * 0.63f);
|
||||
glm::vec3 hitbox = glm::vec3();
|
||||
for (const auto& box : def.modelBoxes) {
|
||||
hitbox = glm::max(hitbox, box.size());
|
||||
}
|
||||
offset.y += (1.0f - hitbox).y * 0.5f;
|
||||
shader->uniformMatrix("u_apply", glm::translate(glm::mat4(1.0f), offset));
|
||||
for (size_t i = 0; i < def.modelBoxes.size(); i++) {
|
||||
const UVRegion (&boxtexfaces)[6] = {
|
||||
def.modelUVs[i * 6],
|
||||
def.modelUVs[i * 6 + 1],
|
||||
def.modelUVs[i * 6 + 2],
|
||||
def.modelUVs[i * 6 + 3],
|
||||
def.modelUVs[i * 6 + 4],
|
||||
def.modelUVs[i * 6 + 5]
|
||||
};
|
||||
batch->cube(
|
||||
def.modelBoxes[i].a * glm::vec3(1.0f, 1.0f, -1.0f) * pmul,
|
||||
def.modelBoxes[i].size() * pmul,
|
||||
boxtexfaces, glm::vec4(1.0f), !def.rt.emissive
|
||||
);
|
||||
}
|
||||
|
||||
auto& points = def.modelExtraPoints;
|
||||
glm::vec3 poff = glm::vec3(0.0f, 0.0f, 1.0f);
|
||||
|
||||
for (size_t i = 0; i < def.modelExtraPoints.size() / 4; i++) {
|
||||
const UVRegion& reg = def.modelUVs[def.modelBoxes.size() * 6 + i];
|
||||
|
||||
batch->vertex((points[i * 4 + 0] - poff) * pmul, glm::vec2(reg.u1, reg.v1), glm::vec4(1.0));
|
||||
batch->vertex((points[i * 4 + 1] - poff) * pmul, glm::vec2(reg.u2, reg.v1), glm::vec4(1.0));
|
||||
batch->vertex((points[i * 4 + 2] - poff) * pmul, glm::vec2(reg.u2, reg.v2), glm::vec4(1.0));
|
||||
batch->vertex((points[i * 4 + 0] - poff) * pmul, glm::vec2(reg.u1, reg.v1), glm::vec4(1.0));
|
||||
batch->vertex((points[i * 4 + 2] - poff) * pmul, glm::vec2(reg.u2, reg.v2), glm::vec4(1.0));
|
||||
batch->vertex((points[i * 4 + 3] - poff) * pmul, glm::vec2(reg.u1, reg.v2), glm::vec4(1.0));
|
||||
case BlockModel::custom:{
|
||||
glm::vec3 pmul = glm::vec3(size * 0.63f);
|
||||
glm::vec3 hitbox = glm::vec3(1.0f);
|
||||
glm::vec3 poff = glm::vec3(0.0f, 0.0f, 1.0f);
|
||||
offset.y += (1.0f - hitbox).y * 0.5f;
|
||||
shader->uniformMatrix("u_apply", glm::translate(glm::mat4(1.0f), offset));
|
||||
const auto& model = cache->getModel(def.rt.id);
|
||||
|
||||
for (const auto& mesh : model.meshes) {
|
||||
for (const auto& vertex : mesh.vertices) {
|
||||
float d = glm::dot(glm::normalize(vertex.normal), glm::vec3(0.2, 0.8, 0.4));
|
||||
d = 0.8f + d * 0.2f;
|
||||
batch->vertex((vertex.coord - poff)*pmul, vertex.uv, glm::vec4(d, d, d, 1.0f));
|
||||
}
|
||||
batch->flush();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BlockModel::xsprite: {
|
||||
shader->uniformMatrix("u_apply", glm::translate(glm::mat4(1.0f), offset));
|
||||
glm::vec3 right = glm::normalize(glm::vec3(1.f, 0.f, -1.f));
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#include "BlocksRenderer.hpp"
|
||||
|
||||
#include "graphics/core/Mesh.hpp"
|
||||
#include "graphics/commons/Model.hpp"
|
||||
#include "maths/UVRegion.hpp"
|
||||
#include "constants.hpp"
|
||||
#include "content/Content.hpp"
|
||||
@ -180,40 +181,6 @@ void BlocksRenderer::face(
|
||||
index(0, 1, 2, 0, 2, 3);
|
||||
}
|
||||
|
||||
void BlocksRenderer::tetragonicFace(
|
||||
const glm::vec3& coord,
|
||||
const glm::vec3& p1, const glm::vec3& p2,
|
||||
const glm::vec3& p3, const glm::vec3& p4,
|
||||
const glm::vec3& X, const glm::vec3& Y, const glm::vec3& Z,
|
||||
const UVRegion& texreg,
|
||||
bool lights
|
||||
) {
|
||||
const auto fp1 = (p1.x - 0.5f) * X + (p1.y - 0.5f) * Y + (p1.z - 0.5f) * Z;
|
||||
const auto fp2 = (p2.x - 0.5f) * X + (p2.y - 0.5f) * Y + (p2.z - 0.5f) * Z;
|
||||
const auto fp3 = (p3.x - 0.5f) * X + (p3.y - 0.5f) * Y + (p3.z - 0.5f) * Z;
|
||||
const auto fp4 = (p4.x - 0.5f) * X + (p4.y - 0.5f) * Y + (p4.z - 0.5f) * Z;
|
||||
|
||||
glm::vec4 tint(1.0f);
|
||||
if (lights) {
|
||||
auto dir = glm::cross(fp2 - fp1, fp3 - fp1);
|
||||
auto normal = glm::normalize(dir);
|
||||
|
||||
float d = glm::dot(normal, SUN_VECTOR);
|
||||
d = 0.8f + d * 0.2f;
|
||||
tint *= d;
|
||||
tint *= pickLight(coord);
|
||||
// debug normal
|
||||
// tint.x = normal.x * 0.5f + 0.5f;
|
||||
// tint.y = normal.y * 0.5f + 0.5f;
|
||||
// tint.z = normal.z * 0.5f + 0.5f;
|
||||
}
|
||||
vertex(coord + fp1, texreg.u1, texreg.v1, tint);
|
||||
vertex(coord + fp2, texreg.u2, texreg.v1, tint);
|
||||
vertex(coord + fp3, texreg.u2, texreg.v2, tint);
|
||||
vertex(coord + fp4, texreg.u1, texreg.v2, tint);
|
||||
index(0, 1, 3, 1, 2, 3);
|
||||
}
|
||||
|
||||
void BlocksRenderer::blockXSprite(
|
||||
int x, int y, int z,
|
||||
const glm::vec3& size,
|
||||
@ -319,29 +286,30 @@ void BlocksRenderer::blockCustomModel(
|
||||
Z = orient.axisZ;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < block->modelBoxes.size(); i++) {
|
||||
AABB box = block->modelBoxes[i];
|
||||
auto size = box.size();
|
||||
if (block->rotatable) {
|
||||
orient.transform(box);
|
||||
const auto& model = cache->getModel(block->rt.id);
|
||||
for (const auto& mesh : model.meshes) {
|
||||
if (vertexOffset + BlocksRenderer::VERTEX_SIZE * mesh.vertices.size() > capacity) {
|
||||
overflow = true;
|
||||
return;
|
||||
}
|
||||
int i = 0;
|
||||
for (const auto& vertex : mesh.vertices) {
|
||||
auto n =
|
||||
vertex.normal.x * X + vertex.normal.y * Y + vertex.normal.z * Z;
|
||||
float d = glm::dot(glm::normalize(n), SUN_VECTOR);
|
||||
d = 0.8f + d * 0.2f;
|
||||
const auto& vcoord = vertex.coord - 0.5f;
|
||||
vertexAO(
|
||||
coord + vcoord.x * X + vcoord.y * Y + vcoord.z * Z,
|
||||
vertex.uv.x,
|
||||
vertex.uv.y,
|
||||
glm::vec4(1, 1, 1, 1),
|
||||
glm::vec3(1, 0, 0),
|
||||
glm::vec3(0, 1, 0),
|
||||
n
|
||||
);
|
||||
indexBuffer[indexSize++] = indexOffset++;
|
||||
}
|
||||
glm::vec3 center_coord = coord - glm::vec3(0.5f) + box.center();
|
||||
faceAO(center_coord, X * size.x, Y * size.y, Z * size.z, block->modelUVs[i * 6 + 5], lights); // north
|
||||
faceAO(center_coord, -X * size.x, Y * size.y, -Z * size.z, block->modelUVs[i * 6 + 4], lights); // south
|
||||
faceAO(center_coord, X * size.x, -Z * size.z, Y * size.y, block->modelUVs[i * 6 + 3], lights); // top
|
||||
faceAO(center_coord, -X * size.x, -Z * size.z, -Y * size.y, block->modelUVs[i * 6 + 2], lights); // bottom
|
||||
faceAO(center_coord, -Z * size.z, Y * size.y, X * size.x, block->modelUVs[i * 6 + 1], lights); // west
|
||||
faceAO(center_coord, Z * size.z, Y * size.y, -X * size.x, block->modelUVs[i * 6 + 0], lights); // east
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < block->modelExtraPoints.size()/4; i++) {
|
||||
tetragonicFace(coord,
|
||||
block->modelExtraPoints[i * 4 + 0],
|
||||
block->modelExtraPoints[i * 4 + 1],
|
||||
block->modelExtraPoints[i * 4 + 2],
|
||||
block->modelExtraPoints[i * 4 + 3],
|
||||
X, Y, Z,
|
||||
block->modelUVs[block->modelBoxes.size()*6 + i], lights);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -82,16 +82,6 @@ class BlocksRenderer {
|
||||
const UVRegion& region,
|
||||
bool lights
|
||||
);
|
||||
void tetragonicFace(
|
||||
const glm::vec3& coord,
|
||||
const glm::vec3& p1, const glm::vec3& p2,
|
||||
const glm::vec3& p3, const glm::vec3& p4,
|
||||
const glm::vec3& X,
|
||||
const glm::vec3& Y,
|
||||
const glm::vec3& Z,
|
||||
const UVRegion& texreg,
|
||||
bool lights
|
||||
);
|
||||
void blockCube(
|
||||
const glm::ivec3& coord,
|
||||
const UVRegion(&faces)[6],
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
#include "ModelBatch.hpp"
|
||||
|
||||
#include "assets/assets_util.hpp"
|
||||
#include "graphics/commons/Model.hpp"
|
||||
#include "graphics/core/Mesh.hpp"
|
||||
#include "graphics/core/Model.hpp"
|
||||
#include "graphics/core/Atlas.hpp"
|
||||
#include "graphics/core/Texture.hpp"
|
||||
#include "assets/Assets.hpp"
|
||||
|
||||
@ -48,6 +48,60 @@ static inline UVRegion get_region_for(
|
||||
return texreg.region;
|
||||
}
|
||||
|
||||
model::Model ModelsGenerator::fromCustom(
|
||||
const Assets& assets,
|
||||
const std::vector<BoxModel>& modelBoxes,
|
||||
const std::vector<std::string>& modelTextures,
|
||||
const std::vector<glm::vec3>& points,
|
||||
bool lighting
|
||||
) {
|
||||
auto model = model::Model();
|
||||
for (size_t i = 0; i < modelBoxes.size(); i++) {
|
||||
auto& mesh = model.addMesh("blocks:" + modelTextures[i * 6]);
|
||||
mesh.lighting = lighting;
|
||||
const UVRegion boxtexfaces[6] = {
|
||||
get_region_for(modelTextures[i * 6], assets),
|
||||
get_region_for(modelTextures[i * 6 + 1], assets),
|
||||
get_region_for(modelTextures[i * 6 + 2], assets),
|
||||
get_region_for(modelTextures[i * 6 + 3], assets),
|
||||
get_region_for(modelTextures[i * 6 + 4], assets),
|
||||
get_region_for(modelTextures[i * 6 + 5], assets)
|
||||
};
|
||||
mesh.addBox(
|
||||
modelBoxes[i].center(), modelBoxes[i].size() * 0.5f, boxtexfaces
|
||||
);
|
||||
}
|
||||
glm::vec3 poff = glm::vec3(0.0f, 0.0f, 1.0f);
|
||||
glm::vec3 norm {0, 1, 0};
|
||||
for (size_t i = 0; i < points.size() / 4; i++) {
|
||||
auto texture = "blocks:" + modelTextures[modelBoxes.size() * 6 + i];
|
||||
|
||||
auto& mesh = model.addMesh(texture);
|
||||
mesh.lighting = lighting;
|
||||
|
||||
auto reg = get_region_for(texture, assets);
|
||||
mesh.vertices.push_back(
|
||||
{points[i * 4 + 0] - poff, glm::vec2(reg.u1, reg.v1), norm}
|
||||
);
|
||||
mesh.vertices.push_back(
|
||||
{points[i * 4 + 1] - poff, glm::vec2(reg.u2, reg.v1), norm}
|
||||
);
|
||||
mesh.vertices.push_back(
|
||||
{points[i * 4 + 2] - poff, glm::vec2(reg.u2, reg.v2), norm}
|
||||
);
|
||||
mesh.vertices.push_back(
|
||||
{points[i * 4 + 3] - poff, glm::vec2(reg.u1, reg.v1), norm}
|
||||
);
|
||||
mesh.vertices.push_back(
|
||||
{points[i * 4 + 4] - poff, glm::vec2(reg.u2, reg.v2), norm}
|
||||
);
|
||||
mesh.vertices.push_back(
|
||||
{points[i * 4 + 0] - poff, glm::vec2(reg.u1, reg.v2), norm}
|
||||
);
|
||||
}
|
||||
return model;
|
||||
}
|
||||
|
||||
model::Model ModelsGenerator::generate(
|
||||
const ItemDef& def, const Content& content, const Assets& assets
|
||||
) {
|
||||
@ -59,55 +113,7 @@ model::Model ModelsGenerator::generate(
|
||||
"blocks:" + blockDef.textureFaces.at(0), assets
|
||||
);
|
||||
} else if (blockDef.model == BlockModel::custom) {
|
||||
model = model::Model();
|
||||
for (size_t i = 0; i < blockDef.modelBoxes.size(); i++) {
|
||||
auto& mesh =
|
||||
model.addMesh("blocks:" + blockDef.modelTextures[i * 6]);
|
||||
mesh.lighting = !blockDef.shadeless;
|
||||
const UVRegion (&boxtexfaces)[6] = {
|
||||
get_region_for(blockDef.modelTextures[i * 6], assets),
|
||||
get_region_for(blockDef.modelTextures[i * 6 + 1], assets),
|
||||
get_region_for(blockDef.modelTextures[i * 6 + 2], assets),
|
||||
get_region_for(blockDef.modelTextures[i * 6 + 3], assets),
|
||||
get_region_for(blockDef.modelTextures[i * 6 + 4], assets),
|
||||
get_region_for(blockDef.modelTextures[i * 6 + 5], assets)
|
||||
};
|
||||
mesh.addBox(
|
||||
blockDef.modelBoxes[i].center(),
|
||||
blockDef.modelBoxes[i].size()*0.5f, boxtexfaces
|
||||
);
|
||||
}
|
||||
const auto& points = blockDef.modelExtraPoints;
|
||||
glm::vec3 poff = glm::vec3(0.0f, 0.0f, 1.0f);
|
||||
glm::vec3 norm {0, 1, 0};
|
||||
for (size_t i = 0; i < blockDef.modelExtraPoints.size() / 4; i++) {
|
||||
auto texture =
|
||||
"blocks:" +
|
||||
blockDef.modelTextures[blockDef.modelBoxes.size() * 6 + i];
|
||||
|
||||
auto& mesh = model.addMesh(texture);
|
||||
mesh.lighting = !blockDef.shadeless;
|
||||
|
||||
auto reg = get_region_for(texture, assets);
|
||||
mesh.vertices.push_back(
|
||||
{points[i * 4 + 0] - poff, glm::vec2(reg.u1, reg.v1), norm}
|
||||
);
|
||||
mesh.vertices.push_back(
|
||||
{points[i * 4 + 1] - poff, glm::vec2(reg.u2, reg.v1), norm}
|
||||
);
|
||||
mesh.vertices.push_back(
|
||||
{points[i * 4 + 2] - poff, glm::vec2(reg.u2, reg.v2), norm}
|
||||
);
|
||||
mesh.vertices.push_back(
|
||||
{points[i * 4 + 3] - poff, glm::vec2(reg.u1, reg.v1), norm}
|
||||
);
|
||||
mesh.vertices.push_back(
|
||||
{points[i * 4 + 4] - poff, glm::vec2(reg.u2, reg.v2), norm}
|
||||
);
|
||||
mesh.vertices.push_back(
|
||||
{points[i * 4 + 0] - poff, glm::vec2(reg.u1, reg.v2), norm}
|
||||
);
|
||||
}
|
||||
model = assets.require<model::Model>(blockDef.modelName);
|
||||
for (auto& mesh : model.meshes) {
|
||||
mesh.scale(glm::vec3(0.3f));
|
||||
}
|
||||
@ -135,3 +141,67 @@ model::Model ModelsGenerator::generate(
|
||||
return model::Model();
|
||||
}
|
||||
}
|
||||
|
||||
model::Model ModelsGenerator::loadCustomBlockModel(
|
||||
const dv::value& primitives, const Assets& assets, bool lighting
|
||||
) {
|
||||
std::vector<AABB> modelBoxes;
|
||||
std::vector<std::string> modelTextures;
|
||||
std::vector<glm::vec3> modelExtraPoints;
|
||||
|
||||
if (primitives.has("aabbs")) {
|
||||
const auto& modelboxes = primitives["aabbs"];
|
||||
for (uint i = 0; i < modelboxes.size(); i++) {
|
||||
// Parse aabb
|
||||
const auto& boxarr = modelboxes[i];
|
||||
AABB modelbox;
|
||||
modelbox.a = glm::vec3(
|
||||
boxarr[0].asNumber(), boxarr[1].asNumber(), boxarr[2].asNumber()
|
||||
);
|
||||
modelbox.b = glm::vec3(
|
||||
boxarr[3].asNumber(), boxarr[4].asNumber(), boxarr[5].asNumber()
|
||||
);
|
||||
modelbox.b += modelbox.a;
|
||||
modelBoxes.push_back(modelbox);
|
||||
|
||||
if (boxarr.size() == 7) {
|
||||
for (uint j = 6; j < 12; j++) {
|
||||
modelTextures.emplace_back(boxarr[6].asString());
|
||||
}
|
||||
} else if (boxarr.size() == 12) {
|
||||
for (uint j = 6; j < 12; j++) {
|
||||
modelTextures.emplace_back(boxarr[j].asString());
|
||||
}
|
||||
} else {
|
||||
for (uint j = 6; j < 12; j++) {
|
||||
modelTextures.emplace_back("notfound");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (primitives.has("tetragons")) {
|
||||
const auto& modeltetragons = primitives["tetragons"];
|
||||
for (uint i = 0; i < modeltetragons.size(); i++) {
|
||||
// Parse tetragon to points
|
||||
const auto& tgonobj = modeltetragons[i];
|
||||
glm::vec3 p1(
|
||||
tgonobj[0].asNumber(), tgonobj[1].asNumber(), tgonobj[2].asNumber()
|
||||
);
|
||||
glm::vec3 xw(
|
||||
tgonobj[3].asNumber(), tgonobj[4].asNumber(), tgonobj[5].asNumber()
|
||||
);
|
||||
glm::vec3 yh(
|
||||
tgonobj[6].asNumber(), tgonobj[7].asNumber(), tgonobj[8].asNumber()
|
||||
);
|
||||
modelExtraPoints.push_back(p1);
|
||||
modelExtraPoints.push_back(p1 + xw);
|
||||
modelExtraPoints.push_back(p1 + xw + yh);
|
||||
modelExtraPoints.push_back(p1 + yh);
|
||||
|
||||
modelTextures.emplace_back(tgonobj[9].asString());
|
||||
}
|
||||
}
|
||||
return fromCustom(
|
||||
assets, modelBoxes, modelTextures, modelExtraPoints, lighting
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,14 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include "graphics/core/Model.hpp"
|
||||
#include "graphics/commons/Model.hpp"
|
||||
#include "maths/aabb.hpp"
|
||||
#include "data/dv.hpp"
|
||||
|
||||
struct ItemDef;
|
||||
class Assets;
|
||||
class Content;
|
||||
struct Block;
|
||||
|
||||
class ModelsGenerator {
|
||||
public:
|
||||
static model::Model generate(
|
||||
const ItemDef& def, const Content& content, const Assets& assets
|
||||
);
|
||||
|
||||
static model::Model fromCustom(
|
||||
const Assets& assets,
|
||||
const std::vector<AABB>& modelBoxes,
|
||||
const std::vector<std::string>& modelTextures,
|
||||
const std::vector<glm::vec3>& points,
|
||||
bool lighting
|
||||
);
|
||||
|
||||
static model::Model loadCustomBlockModel(
|
||||
const dv::value& primitives, const Assets& assets, bool lighting
|
||||
);
|
||||
};
|
||||
|
||||
@ -31,12 +31,12 @@
|
||||
#include "world/Level.hpp"
|
||||
#include "world/LevelEvents.hpp"
|
||||
#include "world/World.hpp"
|
||||
#include "graphics/commons/Model.hpp"
|
||||
#include "graphics/core/Atlas.hpp"
|
||||
#include "graphics/core/Batch3D.hpp"
|
||||
#include "graphics/core/DrawContext.hpp"
|
||||
#include "graphics/core/LineBatch.hpp"
|
||||
#include "graphics/core/Mesh.hpp"
|
||||
#include "graphics/core/Model.hpp"
|
||||
#include "graphics/core/PostProcessing.hpp"
|
||||
#include "graphics/core/Shader.hpp"
|
||||
#include "graphics/core/Texture.hpp"
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <cmath>
|
||||
#include <glm/vec2.hpp>
|
||||
|
||||
struct UVRegion {
|
||||
float u1;
|
||||
@ -33,4 +34,10 @@ struct UVRegion {
|
||||
u2 = u1 + uvw * w;
|
||||
v2 = v1 + uvh * h;
|
||||
}
|
||||
|
||||
inline glm::vec2 apply(const glm::vec2& uv) {
|
||||
float w = getWidth();
|
||||
float h = getHeight();
|
||||
return glm::vec2(u1 + uv.x / w, v1 + uv.y / h);
|
||||
}
|
||||
};
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
#include "engine.hpp"
|
||||
#include "graphics/core/DrawContext.hpp"
|
||||
#include "graphics/core/LineBatch.hpp"
|
||||
#include "graphics/core/Model.hpp"
|
||||
#include "graphics/commons/Model.hpp"
|
||||
#include "graphics/render/ModelBatch.hpp"
|
||||
#include "logic/scripting/scripting.hpp"
|
||||
#include "maths/FrustumCulling.hpp"
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
#include "assets/Assets.hpp"
|
||||
#include "coders/json.hpp"
|
||||
#include "data/dv_util.hpp"
|
||||
#include "graphics/core/Model.hpp"
|
||||
#include "graphics/commons/Model.hpp"
|
||||
#include "graphics/render/ModelBatch.hpp"
|
||||
|
||||
#define GLM_ENABLE_EXPERIMENTAL
|
||||
|
||||
@ -114,12 +114,8 @@ Block::Block(std::string name, const std::string& texture)
|
||||
void Block::cloneTo(Block& dst) {
|
||||
dst.caption = caption;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
dst.textureFaces[i] = textureFaces[i];
|
||||
dst.textureFaces[i] = textureFaces[i];
|
||||
}
|
||||
dst.modelTextures = modelTextures;
|
||||
dst.modelBoxes = modelBoxes;
|
||||
dst.modelExtraPoints = modelExtraPoints;
|
||||
dst.modelUVs = modelUVs;
|
||||
dst.material = material;
|
||||
std::copy(&emission[0], &emission[3], dst.emission);
|
||||
dst.size = size;
|
||||
@ -143,7 +139,10 @@ void Block::cloneTo(Block& dst) {
|
||||
dst.inventorySize = inventorySize;
|
||||
dst.tickInterval = tickInterval;
|
||||
dst.overlayTexture = overlayTexture;
|
||||
dst.particles = std::make_unique<ParticlesPreset>(*particles);
|
||||
if (particles) {
|
||||
dst.particles = std::make_unique<ParticlesPreset>(*particles);
|
||||
}
|
||||
dst.customModelRaw = customModelRaw;
|
||||
}
|
||||
|
||||
static std::set<std::string, std::less<>> RESERVED_BLOCK_FIELDS {
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
#include <vector>
|
||||
#include <array>
|
||||
|
||||
#include "data/dv.hpp"
|
||||
#include "maths/UVRegion.hpp"
|
||||
#include "maths/aabb.hpp"
|
||||
#include "typedefs.hpp"
|
||||
@ -116,12 +117,6 @@ public:
|
||||
/// @brief Textures set applied to block sides
|
||||
std::array<std::string, 6> textureFaces; // -x,x, -y,y, -z,z
|
||||
|
||||
std::vector<std::string> modelTextures = {};
|
||||
std::vector<BoxModel> modelBoxes = {};
|
||||
// initially made for tetragons
|
||||
std::vector<glm::vec3> modelExtraPoints = {};
|
||||
std::vector<UVRegion> modelUVs = {}; // boxes' tex-UVs also there
|
||||
|
||||
/// @brief id of used BlockMaterial, may specify non-existing material
|
||||
std::string material = DEFAULT_MATERIAL;
|
||||
|
||||
@ -137,6 +132,11 @@ public:
|
||||
/// @brief Block model type
|
||||
BlockModel model = BlockModel::block;
|
||||
|
||||
/// @brief Custom model raw data
|
||||
dv::value customModelRaw = nullptr;
|
||||
|
||||
std::string modelName = "";
|
||||
|
||||
/// @brief Does the block passing lights into itself
|
||||
bool lightPassing = false;
|
||||
|
||||
|
||||
@ -597,8 +597,7 @@ glm::vec3 Chunks::rayCastToObstacle(
|
||||
if (def.obstacle) {
|
||||
if (!def.rt.solid) {
|
||||
const std::vector<AABB>& hitboxes =
|
||||
def.rotatable ? def.rt.hitboxes[voxel->state.rotation]
|
||||
: def.modelBoxes;
|
||||
def.rt.hitboxes[voxel->state.rotation];
|
||||
|
||||
scalar_t distance;
|
||||
glm::ivec3 norm;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user