From 0e981d742b1f6ac098b909661923937eedd272db Mon Sep 17 00:00:00 2001 From: LaG1924 <12997935+LaG1924@users.noreply.github.com> Date: Tue, 27 Mar 2018 15:46:39 +0500 Subject: Moved model parsing to startup stage and implemented model rotation --- src/AssetManager.cpp | 155 +++++++++++++++++++++++++++++++++++++++- src/AssetManager.hpp | 13 ++++ src/RendererSectionData.cpp | 169 ++++++++++---------------------------------- 3 files changed, 203 insertions(+), 134 deletions(-) diff --git a/src/AssetManager.cpp b/src/AssetManager.cpp index 8403700..bffc246 100644 --- a/src/AssetManager.cpp +++ b/src/AssetManager.cpp @@ -5,6 +5,7 @@ #include #include +#include #include "Texture.hpp" @@ -22,6 +23,7 @@ AssetManager::AssetManager() { LoadIds(); LoadTextureResources(); LoadBlockModels(); + ParseBlockModels(); } void AssetManager::LoadIds() { @@ -331,7 +333,7 @@ void AssetManager::LoadBlockModels() { faceData.uv = uv; } - BlockModel::ElementData::FaceDirection cullface = faceDir; + BlockModel::ElementData::FaceDirection cullface = BlockModel::ElementData::FaceDirection::none; if (face.find("cullface") != face.end()) { if (face["cullface"] == "down") cullface = BlockModel::ElementData::FaceDirection::down; @@ -374,7 +376,7 @@ void AssetManager::LoadBlockModels() { std::string modelName = dirEntry.path().stem().generic_string(); parseModel("block/" + modelName); - } + } } std::string AssetManager::GetAssetNameByBlockId(BlockId block) { @@ -385,4 +387,153 @@ std::string AssetManager::GetAssetNameByBlockId(BlockId block) { return it.first; } return "#NF"; +} + +void AssetManager::ParseBlockModels() { + std::string textureName; + + for (auto &modelIt : models) { + const auto &modelName = modelIt.first; + auto &model = modelIt.second; + + for (const auto& element : model.Elements) { + Vector t = element.to - element.from; + VectorF elementSize(VectorF(t.x, t.y, t.z) / 16.0f); + VectorF elementOrigin(VectorF(element.from.x, element.from.y, element.from.z) / 16.0f); + + glm::mat4 elementTransform; + + if (element.rotationAngle != 0) { + static const glm::vec3 xAxis(1.0f, 0.0f, 0.0f); + static const glm::vec3 yAxis(0.0f, 1.0f, 0.0f); + static const glm::vec3 zAxis(0.0f, 0.0f, 1.0f); + + const glm::vec3 *targetAxis = nullptr; + switch (element.rotationAxis) { + case BlockModel::ElementData::Axis::x: + targetAxis = &xAxis; + break; + case BlockModel::ElementData::Axis::y: + targetAxis = &yAxis; + break; + case BlockModel::ElementData::Axis::z: + targetAxis = &zAxis; + break; + } + + VectorF rotateOrigin(VectorF(element.rotationOrigin.x, element.rotationOrigin.y, element.rotationOrigin.z) / 16.0f); + + glm::mat4 rotationMat; + rotationMat = glm::translate(rotationMat, rotateOrigin.glm()); + + rotationMat = glm::rotate(rotationMat, glm::radians((float)element.rotationAngle), *targetAxis); + if (element.rotationRescale) { + glm::vec3 scaleFactor{ 1.0f,1.0f,1.0f }; + double coef = 1.0f / cos(glm::radians((double)element.rotationAngle)); + switch (element.rotationAxis) { + case BlockModel::ElementData::Axis::x: + scaleFactor.y *= coef; + scaleFactor.z *= coef; + break; + case BlockModel::ElementData::Axis::y: + scaleFactor.x *= coef; + scaleFactor.z *= coef; + break; + case BlockModel::ElementData::Axis::z: + scaleFactor.x *= coef; + scaleFactor.y *= coef; + break; + } + rotationMat = glm::scale(rotationMat, scaleFactor); + } + + rotationMat = glm::translate(rotationMat, -rotateOrigin.glm()); + + elementTransform = rotationMat * elementTransform; + } + + elementTransform = glm::translate(elementTransform, elementOrigin.glm()); + elementTransform = glm::scale(elementTransform, elementSize.glm()); + + for (const auto& face : element.faces) { + BlockModel::ParsedFace parsedFace; + parsedFace.visibility = face.second.cullface; + + glm::mat4 faceTransform; + switch (face.first) { + case BlockModel::ElementData::FaceDirection::down: + faceTransform = glm::translate(elementTransform, glm::vec3(0, 0, 0)); + faceTransform = glm::rotate(faceTransform, glm::radians(180.0f), glm::vec3(1.0f, 0, 0)); + faceTransform = glm::translate(faceTransform, glm::vec3(0, 0, -1)); + break; + case BlockModel::ElementData::FaceDirection::up: + faceTransform = glm::translate(elementTransform, glm::vec3(0.0f, 1.0f, 0.0f)); + break; + case BlockModel::ElementData::FaceDirection::north: + faceTransform = glm::translate(elementTransform, glm::vec3(0, 0, 1)); + faceTransform = glm::rotate(faceTransform, glm::radians(90.0f), glm::vec3(-1.0f, 0.0f, 0.0f)); + faceTransform = glm::rotate(faceTransform, glm::radians(90.0f), glm::vec3(0.0f, -1.0f, 0.0f)); + faceTransform = glm::translate(faceTransform, glm::vec3(0, 0, -1)); + faceTransform = glm::rotate(faceTransform, glm::radians(180.0f), glm::vec3(1, 0, 0.0f)); + faceTransform = glm::translate(faceTransform, glm::vec3(0, 0, -1.0f)); + break; + case BlockModel::ElementData::FaceDirection::south: + faceTransform = glm::translate(elementTransform, glm::vec3(1, 0, 0)); + faceTransform = glm::rotate(faceTransform, glm::radians(90.0f), glm::vec3(-1.0f, 0.0f, 0.0f)); + faceTransform = glm::rotate(faceTransform, glm::radians(90.0f), glm::vec3(0.0f, -1.0f, 0.0f)); + break; + case BlockModel::ElementData::FaceDirection::west: + faceTransform = glm::translate(elementTransform, glm::vec3(1, 0, 0)); + faceTransform = glm::rotate(faceTransform, glm::radians(90.0f), glm::vec3(0, 0.0f, 1.0f)); + faceTransform = glm::rotate(faceTransform, glm::radians(180.0f), glm::vec3(1.0f, 0.0f, 0.0f)); + faceTransform = glm::translate(faceTransform, glm::vec3(0, 0, -1)); + break; + case BlockModel::ElementData::FaceDirection::east: + faceTransform = glm::translate(elementTransform, glm::vec3(0, 0, 0)); + faceTransform = glm::rotate(faceTransform, glm::radians(90.0f), glm::vec3(0, 0.0f, 1.0f)); + break; + } + parsedFace.transform = faceTransform; + glm::vec4 texture; + textureName = face.second.texture; + if (model.Textures.empty()) { + texture = GetTextureByAssetName("minecraft/texture/blocks/tnt_side"); + } + else { + while (textureName[0] == '#') { + textureName.erase(0, 1); + auto textureIt = model.Textures.find(textureName); + textureName = textureIt != model.Textures.end() ? textureIt->second : "minecraft/texture/blocks/tnt_side"; + } + textureName.insert(0, "minecraft/textures/"); + texture = GetTextureByAssetName(textureName); + + if (!(face.second.uv == BlockModel::ElementData::FaceData::Uv{ 0,16,0,16 }) && !(face.second.uv == BlockModel::ElementData::FaceData::Uv{ 0,0,0,0 }) + && !(face.second.uv == BlockModel::ElementData::FaceData::Uv{ 0,0,16,16 })) { + double x = face.second.uv.x1; + double y = face.second.uv.x1; + double w = face.second.uv.x2 - face.second.uv.x1; + double h = face.second.uv.y2 - face.second.uv.y1; + x /= 16.0; + y /= 16.0; + w /= 16.0; + h /= 16.0; + double X = texture.x; + double Y = texture.y; + double W = texture.z; + double H = texture.w; + + texture = glm::vec4{ X + x * W, Y + y * H, w * W , h * H }; + } + } + parsedFace.texture = texture; + if (face.second.tintIndex) + parsedFace.color = glm::vec3(0.275, 0.63, 0.1); + else + parsedFace.color = glm::vec3(0, 0, 0); + + model.parsedFaces.push_back(parsedFace); + } + } + } } \ No newline at end of file diff --git a/src/AssetManager.hpp b/src/AssetManager.hpp index 37031be..c386f7c 100644 --- a/src/AssetManager.hpp +++ b/src/AssetManager.hpp @@ -6,6 +6,8 @@ #include #include +#include +#include #include "Vector.hpp" #include "Block.hpp" @@ -124,6 +126,15 @@ struct BlockModel { }; std::vector Elements; + + struct ParsedFace { + ElementData::FaceDirection visibility; + glm::mat4 transform; + glm::vec4 texture; + glm::vec3 color; + }; + + std::vector parsedFaces; }; inline bool operator==(const BlockModel::ElementData::FaceData::Uv &lhs, @@ -164,4 +175,6 @@ public: void LoadBlockModels(); std::string GetAssetNameByBlockId(BlockId block); + + void ParseBlockModels(); }; diff --git a/src/RendererSectionData.cpp b/src/RendererSectionData.cpp index f7f0baa..96d78e0 100644 --- a/src/RendererSectionData.cpp +++ b/src/RendererSectionData.cpp @@ -15,137 +15,42 @@ inline const BlockId& GetBlockId(int x, int y, int z, const std::array& visibility, std::string &textureName, RendererSectionData &data) { - glm::mat4 elementTransform, faceTransform; - for (const auto& element : model.Elements) { - Vector t = element.to - element.from; - VectorF elementSize(VectorF(t.x, t.y, t.z) / 16.0f); - VectorF elementOrigin(VectorF(element.from.x, element.from.y, element.from.z) / 16.0f); - elementTransform = transform; - - /*if (element.rotationAngle != 0) { - const glm::vec3 xAxis(1.0f, 0.0f, 0.0f); - const glm::vec3 yAxis(0.0f, 1.0f, 0.0f); - const glm::vec3 zAxis(0.0f, 0.0f, 1.0f); - const glm::vec3 *targetAxis = nullptr; - switch (element.rotationAxis) { - case BlockModel::ElementData::Axis::x: - targetAxis = &xAxis; - break; - case BlockModel::ElementData::Axis::y: - targetAxis = &yAxis; - break; - case BlockModel::ElementData::Axis::z: - targetAxis = &zAxis; - break; - } - VectorF rotateOrigin(VectorF(element.rotationOrigin.x, element.rotationOrigin.y, element.rotationOrigin.z) / 16.0f); - elementTransform = glm::translate(elementTransform, -rotateOrigin.glm()); - elementTransform = glm::rotate(elementTransform, glm::radians(float(45)), yAxis); - elementTransform = glm::translate(elementTransform, rotateOrigin.glm()); - }*/ - elementTransform = glm::translate(elementTransform, elementOrigin.glm()); - elementTransform = glm::scale(elementTransform, elementSize.glm()); - - for (const auto& face : element.faces) { - if (face.second.cullface != BlockModel::ElementData::FaceDirection::none) { - unsigned char visible = visibility[blockPos.y * 256 + blockPos.z * 16 + blockPos.x]; - - switch (face.second.cullface) { - case BlockModel::ElementData::FaceDirection::down: - if (visible >> 0 & 0x1) - continue; - break; - case BlockModel::ElementData::FaceDirection::up: - if (visible >> 1 & 0x1) - continue; - break; - case BlockModel::ElementData::FaceDirection::north: - if (visible >> 2 & 0x1) - continue; - break; - case BlockModel::ElementData::FaceDirection::south: - if (visible >> 3 & 0x1) - continue; - break; - case BlockModel::ElementData::FaceDirection::west: - if (visible >> 4 & 0x1) - continue; - break; - case BlockModel::ElementData::FaceDirection::east: - if (visible >> 5 & 0x1) - continue; - break; - } - } - - switch (face.first) { - case BlockModel::ElementData::FaceDirection::down: - faceTransform = glm::translate(elementTransform, glm::vec3(0, 0, 0)); - faceTransform = glm::rotate(faceTransform, glm::radians(180.0f), glm::vec3(1.0f, 0, 0)); - faceTransform = glm::translate(faceTransform, glm::vec3(0, 0, -1)); - break; - case BlockModel::ElementData::FaceDirection::up: - faceTransform = glm::translate(elementTransform, glm::vec3(0.0f, 1.0f, 0.0f)); - break; - case BlockModel::ElementData::FaceDirection::north: - faceTransform = glm::translate(elementTransform, glm::vec3(0, 0, 1)); - faceTransform = glm::rotate(faceTransform, glm::radians(90.0f), glm::vec3(-1.0f, 0.0f, 0.0f)); - faceTransform = glm::rotate(faceTransform, glm::radians(90.0f), glm::vec3(0.0f, -1.0f, 0.0f)); - faceTransform = glm::translate(faceTransform, glm::vec3(0, 0, -1)); - faceTransform = glm::rotate(faceTransform, glm::radians(180.0f), glm::vec3(1, 0, 0.0f)); - faceTransform = glm::translate(faceTransform, glm::vec3(0, 0, -1.0f)); - break; - case BlockModel::ElementData::FaceDirection::south: - faceTransform = glm::translate(elementTransform, glm::vec3(1, 0, 0)); - faceTransform = glm::rotate(faceTransform, glm::radians(90.0f), glm::vec3(-1.0f, 0.0f, 0.0f)); - faceTransform = glm::rotate(faceTransform, glm::radians(90.0f), glm::vec3(0.0f, -1.0f, 0.0f)); - break; - case BlockModel::ElementData::FaceDirection::west: - faceTransform = glm::translate(elementTransform, glm::vec3(1, 0, 0)); - faceTransform = glm::rotate(faceTransform, glm::radians(90.0f), glm::vec3(0, 0.0f, 1.0f)); - faceTransform = glm::rotate(faceTransform, glm::radians(180.0f), glm::vec3(1.0f, 0.0f, 0.0f)); - faceTransform = glm::translate(faceTransform, glm::vec3(0, 0, -1)); - break; - case BlockModel::ElementData::FaceDirection::east: - faceTransform = glm::translate(elementTransform, glm::vec3(0, 0, 0)); - faceTransform = glm::rotate(faceTransform, glm::radians(90.0f), glm::vec3(0, 0.0f, 1.0f)); - break; - } - data.models.push_back(faceTransform); - textureName = face.second.texture; - while (textureName[0] == '#') { - textureName.erase(0, 1); - textureName = model.Textures.find(textureName)->second; - } - textureName.insert(0, "minecraft/textures/"); - glm::vec4 texture = AssetManager::Instance().GetTextureByAssetName(textureName); - - if (!(face.second.uv == BlockModel::ElementData::FaceData::Uv{ 0,16,0,16 }) && !(face.second.uv == BlockModel::ElementData::FaceData::Uv{ 0,0,0,0 }) - && !(face.second.uv == BlockModel::ElementData::FaceData::Uv{ 0,0,16,16 })) { - double x = face.second.uv.x1; - double y = face.second.uv.x1; - double w = face.second.uv.x2 - face.second.uv.x1; - double h = face.second.uv.y2 - face.second.uv.y1; - x /= 16.0; - y /= 16.0; - w /= 16.0; - h /= 16.0; - double X = texture.x; - double Y = texture.y; - double W = texture.z; - double H = texture.w; - - texture = glm::vec4{ X + x * W, Y + y * H, w * W , h * H }; - } - data.textures.push_back(texture); - if (face.second.tintIndex) - data.colors.push_back(glm::vec3(0.275, 0.63, 0.1)); - else - data.colors.push_back(glm::vec3(0, 0, 0)); - data.lights.push_back(glm::vec2(light, skyLight)); - } - } +void AddFacesByBlockModel(RendererSectionData &data, const BlockModel &model, const glm::mat4 &transform, unsigned char visibility, unsigned char light, unsigned char skyLight) { + for (const auto &face : model.parsedFaces) { + if (face.visibility != BlockModel::ElementData::FaceDirection::none) { + switch (face.visibility) { + case BlockModel::ElementData::FaceDirection::down: + if (visibility >> 0 & 0x1) + continue; + break; + case BlockModel::ElementData::FaceDirection::up: + if (visibility >> 1 & 0x1) + continue; + break; + case BlockModel::ElementData::FaceDirection::north: + if (visibility >> 2 & 0x1) + continue; + break; + case BlockModel::ElementData::FaceDirection::south: + if (visibility >> 3 & 0x1) + continue; + break; + case BlockModel::ElementData::FaceDirection::west: + if (visibility >> 4 & 0x1) + continue; + break; + case BlockModel::ElementData::FaceDirection::east: + if (visibility >> 5 & 0x1) + continue; + break; + } + } + + data.models.push_back(transform * face.transform); + data.textures.push_back(face.texture); + data.colors.push_back(face.color); + data.lights.push_back(glm::vec2(light, skyLight)); + } } const BlockModel* GetInternalBlockModel(const BlockId& id, std::vector> &idModels) { @@ -279,7 +184,7 @@ RendererSectionData ParseSection(const SectionsData §ions) const BlockModel* model = GetInternalBlockModel(block, idModels); if (model) { - AddFacesByBlockModel(vec, *model, transform, light, skyLight, blockVisibility, textureName, data); + AddFacesByBlockModel(data, *model, transform, blockVisibility[y * 256 + z * 16 + x], light, skyLight); } else { transform = glm::translate(transform, glm::vec3(0, 1, 0)); -- cgit v1.2.3