From: Daniel Karbach Date: Tue, 13 Oct 2015 12:38:30 +0000 (+0200) Subject: actually load shapes X-Git-Url: https://git.localhorst.tv/?a=commitdiff_plain;h=3a487f44c26f9bb9d1a1c831406b6497b2b3b425;p=blank.git actually load shapes load, not use :P --- diff --git a/assets b/assets index 0a3fe35..d49b4a9 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 0a3fe3553f0e6fe9a9cd8d8994c15c873d247e34 +Subproject commit d49b4a9e4d4b4afe6f483139f3c37db58376bfae diff --git a/src/app/Assets.hpp b/src/app/Assets.hpp index db0933f..b9d62e2 100644 --- a/src/app/Assets.hpp +++ b/src/app/Assets.hpp @@ -11,6 +11,7 @@ namespace blank { class ArrayTexture; class BlockTypeRegistry; class CubeMap; +class ShapeRegistry; class Sound; class Texture; class TextureIndex; @@ -23,6 +24,7 @@ public: void LoadBlockTypes(const std::string &set_name, BlockTypeRegistry &, TextureIndex &) const; CubeMap LoadCubeMap(const std::string &name) const; Font LoadFont(const std::string &name, int size) const; + void LoadShapes(const std::string &set_name, ShapeRegistry &) const; Sound LoadSound(const std::string &name) const; Texture LoadTexture(const std::string &name) const; void LoadTexture(const std::string &name, ArrayTexture &, int layer) const; diff --git a/src/app/app.cpp b/src/app/app.cpp index 4f2a6ec..eb3dac1 100644 --- a/src/app/app.cpp +++ b/src/app/app.cpp @@ -14,6 +14,8 @@ #include "../graphics/Texture.hpp" #include "../io/TokenStreamReader.hpp" #include "../model/bounds.hpp" +#include "../model/Shape.hpp" +#include "../model/ShapeRegistry.hpp" #include "../world/BlockType.hpp" #include "../world/BlockTypeRegistry.hpp" #include "../world/Entity.hpp" @@ -311,7 +313,7 @@ CuboidBounds slab_shape({{ -0.5f, -0.5f, -0.5f }, { 0.5f, 0.0f, 0.5f }}); } -void AssetLoader::LoadBlockTypes(const std::string &set_name, BlockTypeRegistry ®, TextureIndex &tex_index) const { +void AssetLoader::LoadBlockTypes(const string &set_name, BlockTypeRegistry ®, TextureIndex &tex_index) const { string full = data + set_name + ".types"; std::ifstream file(full); if (!file) { @@ -336,7 +338,17 @@ void AssetLoader::LoadBlockTypes(const std::string &set_name, BlockTypeRegistry type.visible = in.GetBool(); } else if (name == "texture") { in.ReadString(tex_name); - type.texture = tex_index.GetID(tex_name); + type.textures.push_back(tex_index.GetID(tex_name)); + } else if (name == "textures") { + in.Skip(Token::BRACKET_OPEN); + while (in.Peek().type != Token::BRACKET_CLOSE) { + in.ReadString(tex_name); + type.textures.push_back(tex_index.GetID(tex_name)); + if (in.Peek().type == Token::COMMA) { + in.Skip(Token::COMMA); + } + } + in.Skip(Token::BRACKET_CLOSE); } else if (name == "rgb_mod") { in.ReadVec(type.rgb_mod); } else if (name == "hsl_mod") { @@ -485,6 +497,23 @@ Font AssetLoader::LoadFont(const string &name, int size) const { return Font(full.c_str(), size); } +void AssetLoader::LoadShapes(const string &set_name, ShapeRegistry &shapes) const { + string full = data + set_name + ".shapes"; + std::ifstream file(full); + if (!file) { + throw std::runtime_error("failed to open shape file " + full); + } + TokenStreamReader in(file); + string shape_name; + while (in.HasMore()) { + in.ReadIdentifier(shape_name); + in.Skip(Token::EQUALS); + Shape &shape = shapes.Add(shape_name); + shape.Read(in); + in.Skip(Token::SEMICOLON); + } +} + Sound AssetLoader::LoadSound(const string &name) const { string full = sounds + name + ".wav"; return Sound(full.c_str()); diff --git a/src/client/InteractiveState.hpp b/src/client/InteractiveState.hpp index 8e7064e..86757a2 100644 --- a/src/client/InteractiveState.hpp +++ b/src/client/InteractiveState.hpp @@ -9,6 +9,7 @@ #include "../app/IntervalTimer.hpp" #include "../graphics/SkyBox.hpp" #include "../io/WorldSave.hpp" +#include "../model/ShapeRegistry.hpp" #include "../model/Skeletons.hpp" #include "../net/Packet.hpp" #include "../ui/HUD.hpp" @@ -58,6 +59,7 @@ public: private: MasterState &master; + ShapeRegistry shapes; BlockTypeRegistry block_types; WorldSave save; World world; diff --git a/src/client/client.cpp b/src/client/client.cpp index 7e8c04e..00966dc 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -48,6 +48,7 @@ void InitialState::Render(Viewport &viewport) { // TODO: this clutter is a giant mess InteractiveState::InteractiveState(MasterState &master, uint32_t player_id) : master(master) +, shapes() , block_types() , save(master.GetEnv().config.GetWorldPath(master.GetWorldConf().name, master.GetConfig().net.host)) , world(block_types, master.GetWorldConf()) @@ -65,6 +66,7 @@ InteractiveState::InteractiveState(MasterState &master, uint32_t player_id) save.Write(master.GetWorldConf()); } TextureIndex tex_index; + master.GetEnv().loader.LoadShapes("default", shapes); master.GetEnv().loader.LoadBlockTypes("default", block_types, tex_index); interface.SetInventorySlots(block_types.size() - 1); chunk_renderer.LoadTextures(master.GetEnv().loader, tex_index); diff --git a/src/model/Shape.cpp b/src/model/Shape.cpp deleted file mode 100644 index 7be434d..0000000 --- a/src/model/Shape.cpp +++ /dev/null @@ -1,152 +0,0 @@ -#include "Shape.hpp" - -#include "bounds.hpp" -#include "../io/TokenStreamReader.hpp" - -#include - -using namespace std; - - -namespace blank { - -Shape::Shape() -: bounds() -, vertices() -, indices() { - -} - - -void Shape::Read(TokenStreamReader &in) { - bounds.reset(); - vertices.clear(); - indices.clear(); - - string name; - while (in.HasMore()) { - in.ReadIdentifier(name); - in.Skip(Token::EQUALS); - if (name == "bounds") { - string bounds_class; - in.ReadIdentifier(bounds_class); - in.Skip(Token::BRACKET_OPEN); - if (bounds_class == "Cuboid") { - glm::vec3 min; - glm::vec3 max; - in.ReadVec(min); - in.Skip(Token::COMMA); - in.ReadVec(max); - bounds.reset(new CuboidBounds(AABB{min, max})); - } else if (bounds_class == "Stair") { - glm::vec3 min; - glm::vec3 max; - glm::vec2 split; - in.ReadVec(min); - in.Skip(Token::COMMA); - in.ReadVec(max); - in.Skip(Token::COMMA); - in.ReadVec(split); - bounds.reset(new StairBounds(AABB{min, max}, split)); - } else { - while (in.Peek().type != Token::BRACKET_CLOSE) { - in.Next(); - } - } - in.Skip(Token::BRACKET_CLOSE); - - } else if (name == "vertices") { - in.Skip(Token::ANGLE_BRACKET_OPEN); - while (in.HasMore() && in.Peek().type != Token::ANGLE_BRACKET_CLOSE) { - in.Skip(Token::ANGLE_BRACKET_OPEN); - Vertex vtx; - in.ReadVec(vtx.position); - in.Skip(Token::COMMA); - in.ReadVec(vtx.normal); - in.Skip(Token::COMMA); - in.ReadVec(vtx.tex_st); - in.Skip(Token::COMMA); - in.ReadNumber(vtx.tex_id); - if (in.Peek().type == Token::COMMA) { - in.Skip(Token::COMMA); - } - in.Skip(Token::ANGLE_BRACKET_CLOSE); - if (in.Peek().type == Token::COMMA) { - in.Skip(Token::COMMA); - } - } - - } else if (name == "indices") { - in.Skip(Token::ANGLE_BRACKET_OPEN); - while (in.HasMore() && in.Peek().type != Token::ANGLE_BRACKET_CLOSE) { - indices.push_back(in.GetULong()); - if (in.Peek().type == Token::COMMA) { - in.Skip(Token::COMMA); - } - } - - } else { - // try to skip, might fail though - while (in.Peek().type != Token::SEMICOLON) { - in.Next(); - } - } - in.Skip(Token::SEMICOLON); - } -} - -float Shape::TexR(const vector &tex_map, size_t off) noexcept { - if (off < tex_map.size()) { - return tex_map[off]; - } else if (!tex_map.empty()) { - return tex_map.back(); - } else { - return 0.0f; - } -} - -void Shape::Fill( - EntityMesh::Buffer &buf, - const vector &tex_map -) const { - for (const auto &vtx : vertices) { - buf.vertices.emplace_back(vtx.position); - buf.normals.emplace_back(vtx.normal); - buf.tex_coords.emplace_back(vtx.tex_st.s, vtx.tex_st.t, TexR(tex_map, vtx.tex_id)); - } - for (auto idx : indices) { - buf.indices.emplace_back(idx); - } -} - -void Shape::Fill( - EntityMesh::Buffer &buf, - const glm::mat4 &transform, - const vector &tex_map -) const { - for (const auto &vtx : vertices) { - buf.vertices.emplace_back(transform * glm::vec4(vtx.position, 1.0f)); - buf.normals.emplace_back(transform * glm::vec4(vtx.normal, 0.0f)); - buf.tex_coords.emplace_back(vtx.tex_st.s, vtx.tex_st.t, TexR(tex_map, vtx.tex_id)); - } - for (auto idx : indices) { - buf.indices.emplace_back(idx); - } -} - -void Shape::Fill( - BlockMesh::Buffer &buf, - const glm::mat4 &transform, - const vector &tex_map, - size_t idx_offset -) const { - for (const auto &vtx : vertices) { - buf.vertices.emplace_back(transform * glm::vec4(vtx.position, 1.0f)); - buf.tex_coords.emplace_back(vtx.tex_st.s, vtx.tex_st.t, TexR(tex_map, vtx.tex_id)); - } - for (auto idx : indices) { - buf.indices.emplace_back(idx_offset + idx); - } -} - -} diff --git a/src/model/Shape.hpp b/src/model/Shape.hpp index 2160270..ac4dc80 100644 --- a/src/model/Shape.hpp +++ b/src/model/Shape.hpp @@ -45,7 +45,7 @@ private: struct Vertex { glm::vec3 position; glm::vec3 normal; - glm::vec3 tex_st; + glm::vec2 tex_st; std::size_t tex_id; }; std::vector vertices; diff --git a/src/model/ShapeRegistry.hpp b/src/model/ShapeRegistry.hpp new file mode 100644 index 0000000..53db569 --- /dev/null +++ b/src/model/ShapeRegistry.hpp @@ -0,0 +1,29 @@ +#ifndef BLANK_MODEL_SHAPEREGISTRY_HPP_ +#define BLANK_MODEL_SHAPEREGISTRY_HPP_ + +#include "Shape.hpp" + +#include +#include + + +namespace blank { + +class ShapeRegistry { + +public: + ShapeRegistry(); + + Shape &Add(const std::string &); + + Shape &Get(const std::string &); + const Shape &Get(const std::string &) const; + +private: + std::map shapes; + +}; + +} + +#endif diff --git a/src/model/shape.cpp b/src/model/shape.cpp new file mode 100644 index 0000000..e88c0e1 --- /dev/null +++ b/src/model/shape.cpp @@ -0,0 +1,189 @@ +#include "Shape.hpp" +#include "ShapeRegistry.hpp" + +#include "bounds.hpp" +#include "../io/TokenStreamReader.hpp" + +#include + +using namespace std; + + +namespace blank { + +Shape::Shape() +: bounds() +, vertices() +, indices() { + +} + +void Shape::Read(TokenStreamReader &in) { + bounds.reset(); + vertices.clear(); + indices.clear(); + + string name; + in.Skip(Token::ANGLE_BRACKET_OPEN); + while (in.HasMore() && in.Peek().type != Token::ANGLE_BRACKET_CLOSE) { + in.ReadIdentifier(name); + in.Skip(Token::EQUALS); + if (name == "bounds") { + string bounds_class; + in.ReadIdentifier(bounds_class); + in.Skip(Token::PARENTHESIS_OPEN); + if (bounds_class == "Cuboid") { + glm::vec3 min; + glm::vec3 max; + in.ReadVec(min); + in.Skip(Token::COMMA); + in.ReadVec(max); + bounds.reset(new CuboidBounds(AABB{min, max})); + } else if (bounds_class == "Stair") { + glm::vec3 min; + glm::vec3 max; + glm::vec2 split; + in.ReadVec(min); + in.Skip(Token::COMMA); + in.ReadVec(max); + in.Skip(Token::COMMA); + in.ReadVec(split); + bounds.reset(new StairBounds(AABB{min, max}, split)); + } else { + while (in.Peek().type != Token::PARENTHESIS_CLOSE) { + in.Next(); + } + } + in.Skip(Token::PARENTHESIS_CLOSE); + + } else if (name == "vertices") { + in.Skip(Token::ANGLE_BRACKET_OPEN); + while (in.HasMore() && in.Peek().type != Token::ANGLE_BRACKET_CLOSE) { + in.Skip(Token::ANGLE_BRACKET_OPEN); + Vertex vtx; + in.ReadVec(vtx.position); + in.Skip(Token::COMMA); + in.ReadVec(vtx.normal); + in.Skip(Token::COMMA); + in.ReadVec(vtx.tex_st); + in.Skip(Token::COMMA); + in.ReadNumber(vtx.tex_id); + if (in.Peek().type == Token::COMMA) { + in.Skip(Token::COMMA); + } + in.Skip(Token::ANGLE_BRACKET_CLOSE); + if (in.Peek().type == Token::COMMA) { + in.Skip(Token::COMMA); + } + } + in.Skip(Token::ANGLE_BRACKET_CLOSE); + + } else if (name == "indices") { + in.Skip(Token::ANGLE_BRACKET_OPEN); + while (in.HasMore() && in.Peek().type != Token::ANGLE_BRACKET_CLOSE) { + indices.push_back(in.GetULong()); + if (in.Peek().type == Token::COMMA) { + in.Skip(Token::COMMA); + } + } + in.Skip(Token::ANGLE_BRACKET_CLOSE); + + } else { + // try to skip, might fail though + while (in.Peek().type != Token::SEMICOLON) { + in.Next(); + } + } + in.Skip(Token::SEMICOLON); + } + in.Skip(Token::ANGLE_BRACKET_CLOSE); +} + +float Shape::TexR(const vector &tex_map, size_t off) noexcept { + if (off < tex_map.size()) { + return tex_map[off]; + } else if (!tex_map.empty()) { + return tex_map.back(); + } else { + return 0.0f; + } +} + +void Shape::Fill( + EntityMesh::Buffer &buf, + const vector &tex_map +) const { + for (const auto &vtx : vertices) { + buf.vertices.emplace_back(vtx.position); + buf.normals.emplace_back(vtx.normal); + buf.tex_coords.emplace_back(vtx.tex_st.s, vtx.tex_st.t, TexR(tex_map, vtx.tex_id)); + } + for (auto idx : indices) { + buf.indices.emplace_back(idx); + } +} + +void Shape::Fill( + EntityMesh::Buffer &buf, + const glm::mat4 &transform, + const vector &tex_map +) const { + for (const auto &vtx : vertices) { + buf.vertices.emplace_back(transform * glm::vec4(vtx.position, 1.0f)); + buf.normals.emplace_back(transform * glm::vec4(vtx.normal, 0.0f)); + buf.tex_coords.emplace_back(vtx.tex_st.s, vtx.tex_st.t, TexR(tex_map, vtx.tex_id)); + } + for (auto idx : indices) { + buf.indices.emplace_back(idx); + } +} + +void Shape::Fill( + BlockMesh::Buffer &buf, + const glm::mat4 &transform, + const vector &tex_map, + size_t idx_offset +) const { + for (const auto &vtx : vertices) { + buf.vertices.emplace_back(transform * glm::vec4(vtx.position, 1.0f)); + buf.tex_coords.emplace_back(vtx.tex_st.s, vtx.tex_st.t, TexR(tex_map, vtx.tex_id)); + } + for (auto idx : indices) { + buf.indices.emplace_back(idx_offset + idx); + } +} + + +ShapeRegistry::ShapeRegistry() +: shapes() { + +} + +Shape &ShapeRegistry::Add(const string &name) { + auto result = shapes.emplace(name, Shape()); + if (result.second) { + return result.first->second; + } else { + throw runtime_error("duplicate shape " + name); + } +} + +Shape &ShapeRegistry::Get(const string &name) { + auto entry = shapes.find(name); + if (entry != shapes.end()) { + return entry->second; + } else { + throw runtime_error("unknown shape " + name); + } +} + +const Shape &ShapeRegistry::Get(const string &name) const { + auto entry = shapes.find(name); + if (entry != shapes.end()) { + return entry->second; + } else { + throw runtime_error("unknown shape " + name); + } +} + +} diff --git a/src/server/ServerState.cpp b/src/server/ServerState.cpp index fc0da82..23740be 100644 --- a/src/server/ServerState.cpp +++ b/src/server/ServerState.cpp @@ -19,6 +19,7 @@ ServerState::ServerState( const Config &config ) : env(env) +, shapes() , block_types() , world(block_types, wc) , generator(gc) @@ -28,6 +29,7 @@ ServerState::ServerState( , server(config.net, world, wc, ws) , loop_timer(16) { TextureIndex tex_index; + env.loader.LoadShapes("default", shapes); env.loader.LoadBlockTypes("default", block_types, tex_index); generator.LoadTypes(block_types); skeletons.LoadHeadless(); diff --git a/src/server/ServerState.hpp b/src/server/ServerState.hpp index 3a48514..bfefccf 100644 --- a/src/server/ServerState.hpp +++ b/src/server/ServerState.hpp @@ -5,6 +5,7 @@ #include "../ai/Spawner.hpp" #include "../app/IntervalTimer.hpp" #include "../app/State.hpp" +#include "../model/ShapeRegistry.hpp" #include "../model/Skeletons.hpp" #include "../world/BlockTypeRegistry.hpp" #include "../world/ChunkLoader.hpp" @@ -39,6 +40,7 @@ public: private: HeadlessEnvironment &env; + ShapeRegistry shapes; BlockTypeRegistry block_types; World world; Generator generator; diff --git a/src/standalone/MasterState.cpp b/src/standalone/MasterState.cpp index 68e49a9..c66c8fa 100644 --- a/src/standalone/MasterState.cpp +++ b/src/standalone/MasterState.cpp @@ -21,6 +21,7 @@ MasterState::MasterState( ) : config(config) , env(env) +, shapes() , block_types() , save(save) , world(block_types, wc) @@ -40,6 +41,7 @@ MasterState::MasterState( , preload(env, chunk_loader, chunk_renderer) , unload(env, world.Chunks(), save) { TextureIndex tex_index; + env.loader.LoadShapes("default", shapes); env.loader.LoadBlockTypes("default", block_types, tex_index); interface.SetInventorySlots(block_types.size() - 1); generator.LoadTypes(block_types); diff --git a/src/standalone/MasterState.hpp b/src/standalone/MasterState.hpp index 9e0b8e4..680bb5e 100644 --- a/src/standalone/MasterState.hpp +++ b/src/standalone/MasterState.hpp @@ -8,6 +8,7 @@ #include "UnloadState.hpp" #include "../ai/Spawner.hpp" #include "../graphics/SkyBox.hpp" +#include "../model/ShapeRegistry.hpp" #include "../model/Skeletons.hpp" #include "../ui/DirectInput.hpp" #include "../ui/HUD.hpp" @@ -62,6 +63,7 @@ public: private: Config &config; Environment &env; + ShapeRegistry shapes; BlockTypeRegistry block_types; const WorldSave &save; World world; diff --git a/src/world/BlockType.hpp b/src/world/BlockType.hpp index 4208d94..429bdaa 100644 --- a/src/world/BlockType.hpp +++ b/src/world/BlockType.hpp @@ -8,6 +8,7 @@ #include "../model/bounds.hpp" #include +#include namespace blank { @@ -17,7 +18,7 @@ namespace blank { struct BlockType { const CollisionBounds *shape; - float texture; + std::vector textures; glm::vec3 hsl_mod; glm::vec3 rgb_mod; glm::vec3 outline_color; diff --git a/src/world/block.cpp b/src/world/block.cpp index 727fcad..1a5d88d 100644 --- a/src/world/block.cpp +++ b/src/world/block.cpp @@ -71,7 +71,7 @@ std::ostream &operator <<(std::ostream &out, const Block::Turn &turn) { BlockType::BlockType() noexcept : shape(&DEFAULT_SHAPE) -, texture(0) +, textures() , hsl_mod(0.0f, 1.0f, 1.0f) , rgb_mod(1.0f, 1.0f, 1.0f) , outline_color(-1, -1, -1) @@ -105,7 +105,11 @@ void BlockType::FillEntityMesh( const glm::mat4 &transform, EntityMesh::Index idx_offset ) const noexcept { - shape->Vertices(buf, transform, texture, idx_offset); + if (textures.empty()) { + shape->Vertices(buf, transform, 0.0f, idx_offset); + } else { + shape->Vertices(buf, transform, textures[0], idx_offset); + } buf.hsl_mods.insert(buf.hsl_mods.end(), shape->VertexCount(), hsl_mod); buf.rgb_mods.insert(buf.rgb_mods.end(), shape->VertexCount(), rgb_mod); } @@ -115,7 +119,11 @@ void BlockType::FillBlockMesh( const glm::mat4 &transform, BlockMesh::Index idx_offset ) const noexcept { - shape->Vertices(buf, transform, texture, idx_offset); + if (textures.empty()) { + shape->Vertices(buf, transform, 0.0f, idx_offset); + } else { + shape->Vertices(buf, transform, textures[0], idx_offset); + } buf.hsl_mods.insert(buf.hsl_mods.end(), shape->VertexCount(), hsl_mod); buf.rgb_mods.insert(buf.rgb_mods.end(), shape->VertexCount(), rgb_mod); }