X-Git-Url: http://git.localhorst.tv/?a=blobdiff_plain;f=src%2Fmodel%2Fshape.cpp;h=4943e6377c3525d0c21b0144f7a3384f74dd8f76;hb=7e782291e0ce39eb2d4e8c1df28f682c313e6f8d;hp=c2d82613eff27d416fe7697d0a07da81eca183ed;hpb=f417749fb09718cde2faad77e8430cf175c68374;p=blank.git diff --git a/src/model/shape.cpp b/src/model/shape.cpp index c2d8261..4943e63 100644 --- a/src/model/shape.cpp +++ b/src/model/shape.cpp @@ -1,478 +1,255 @@ #include "Shape.hpp" -#include "shapes.hpp" +#include "ShapeRegistry.hpp" + +#include "bounds.hpp" +#include "../io/TokenStreamReader.hpp" + +#include + +using namespace std; namespace blank { -void Shape::Vertices( - EntityModel::Buffer &out, - float tex_offset -) const { - for (const auto &pos : vtx_pos) { - out.vertices.emplace_back(pos); - } - for (const auto &coord : vtx_tex_coords) { - out.tex_coords.emplace_back(coord.x, coord.y, coord.z + tex_offset); - } - for (const auto &nrm : vtx_nrm) { - out.normals.emplace_back(nrm); +Shape::Shape() +: bounds() +, vertices() +, indices() +, fill({ false, false, false, false, false, false }) { + +} + +void Shape::Read(TokenStreamReader &in) { + bounds.reset(); + vertices.clear(); + indices.clear(); + fill = { false, false, false, false, false, false }; + + 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); + } + vertices.push_back(vtx); + } + 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 if (name == "fill") { + in.Skip(Token::BRACKET_OPEN); + fill.face[Block::FACE_UP] = in.GetBool(); + in.Skip(Token::COMMA); + fill.face[Block::FACE_DOWN] = in.GetBool(); + in.Skip(Token::COMMA); + fill.face[Block::FACE_RIGHT] = in.GetBool(); + in.Skip(Token::COMMA); + fill.face[Block::FACE_LEFT] = in.GetBool(); + in.Skip(Token::COMMA); + fill.face[Block::FACE_FRONT] = in.GetBool(); + in.Skip(Token::COMMA); + fill.face[Block::FACE_BACK] = in.GetBool(); + in.Skip(Token::BRACKET_CLOSE); + + } else { + // try to skip, might fail though + while (in.HasMore() && in.Peek().type != Token::SEMICOLON) { + in.Next(); + } + } + in.Skip(Token::SEMICOLON); } - for (auto idx : vtx_idx) { - out.indices.emplace_back(idx); + 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::Vertices( - EntityModel::Buffer &out, - const glm::mat4 &transform, - float tex_offset, - EntityModel::Index idx_offset +void Shape::Fill( + EntityMesh::Buffer &buf, + const vector &tex_map ) const { - for (const auto &pos : vtx_pos) { - out.vertices.emplace_back(transform * glm::vec4(pos, 1.0f)); + 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 (const auto &coord : vtx_tex_coords) { - out.tex_coords.emplace_back(coord.x, coord.y, coord.z + tex_offset); - } - for (const auto &nrm : vtx_nrm) { - out.normals.emplace_back(transform * glm::vec4(nrm, 0.0f)); - } - for (auto idx : vtx_idx) { - out.indices.emplace_back(idx_offset + idx); + for (auto idx : indices) { + buf.indices.emplace_back(idx); } } -void Shape::Vertices( - BlockModel::Buffer &out, +void Shape::Fill( + EntityMesh::Buffer &buf, const glm::mat4 &transform, - float tex_offset, - BlockModel::Index idx_offset + const vector &tex_map ) const { - for (const auto &pos : vtx_pos) { - out.vertices.emplace_back(transform * glm::vec4(pos, 1.0f)); - } - for (const auto &coord : vtx_tex_coords) { - out.tex_coords.emplace_back(coord.x, coord.y, coord.z + tex_offset); + 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 : vtx_idx) { - out.indices.emplace_back(idx_offset + idx); + for (auto idx : indices) { + buf.indices.emplace_back(idx); } } -void Shape::Outline( - OutlineModel::Buffer &out, - const OutlineModel::Position &elem_offset, - OutlineModel::Index idx_offset +void Shape::Fill( + BlockMesh::Buffer &buf, + const glm::mat4 &transform, + const vector &tex_map, + size_t idx_offset ) const { - for (const auto &pos : out_pos) { - out.vertices.emplace_back(elem_offset + pos); + 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 : out_idx) { - out.indices.emplace_back(idx_offset + idx); + for (auto idx : indices) { + buf.indices.emplace_back(idx_offset + idx); } } -void Shape::SetShape( - const EntityModel::Positions &pos, - const EntityModel::Normals &nrm, - const EntityModel::Indices &idx -) { - vtx_pos = pos; - vtx_nrm = nrm; - vtx_idx = idx; -} - -void Shape::SetTexture( - const BlockModel::TexCoords &tex_coords -) { - vtx_tex_coords = tex_coords; -} - -void Shape::SetOutline( - const OutlineModel::Positions &pos, - const OutlineModel::Indices &idx -) { - out_pos = pos; - out_idx = idx; -} - - -NullShape::NullShape() -: Shape() { - -} - -bool NullShape::Intersects( - const Ray &, - const glm::mat4 &, - float &, glm::vec3 & -) const noexcept { - return false; +size_t Shape::OutlineCount() const noexcept { + if (bounds) { + return bounds->OutlineCount(); + } else { + return 0; + } } -bool NullShape::Intersects( - const glm::mat4 &, - const AABB &, - const glm::mat4 &, - float &, - glm::vec3 & -) const noexcept { - return false; +size_t Shape::OutlineIndexCount() const noexcept { + if (bounds) { + return bounds->OutlineIndexCount(); + } else { + return 0; + } } - -CuboidShape::CuboidShape(const AABB &b) -: Shape() -, bb(b) { - bb.Adjust(); - SetShape({ - { bb.min.x, bb.min.y, bb.max.z }, // front - { bb.max.x, bb.min.y, bb.max.z }, - { bb.min.x, bb.max.y, bb.max.z }, - { bb.max.x, bb.max.y, bb.max.z }, - { bb.min.x, bb.min.y, bb.min.z }, // back - { bb.min.x, bb.max.y, bb.min.z }, - { bb.max.x, bb.min.y, bb.min.z }, - { bb.max.x, bb.max.y, bb.min.z }, - { bb.min.x, bb.max.y, bb.min.z }, // top - { bb.min.x, bb.max.y, bb.max.z }, - { bb.max.x, bb.max.y, bb.min.z }, - { bb.max.x, bb.max.y, bb.max.z }, - { bb.min.x, bb.min.y, bb.min.z }, // bottom - { bb.max.x, bb.min.y, bb.min.z }, - { bb.min.x, bb.min.y, bb.max.z }, - { bb.max.x, bb.min.y, bb.max.z }, - { bb.min.x, bb.min.y, bb.min.z }, // left - { bb.min.x, bb.min.y, bb.max.z }, - { bb.min.x, bb.max.y, bb.min.z }, - { bb.min.x, bb.max.y, bb.max.z }, - { bb.max.x, bb.min.y, bb.min.z }, // right - { bb.max.x, bb.max.y, bb.min.z }, - { bb.max.x, bb.min.y, bb.max.z }, - { bb.max.x, bb.max.y, bb.max.z }, - }, { - { 0.0f, 0.0f, 1.0f }, // front - { 0.0f, 0.0f, 1.0f }, - { 0.0f, 0.0f, 1.0f }, - { 0.0f, 0.0f, 1.0f }, - { 0.0f, 0.0f, -1.0f }, // back - { 0.0f, 0.0f, -1.0f }, - { 0.0f, 0.0f, -1.0f }, - { 0.0f, 0.0f, -1.0f }, - { 0.0f, 1.0f, 0.0f }, // top - { 0.0f, 1.0f, 0.0f }, - { 0.0f, 1.0f, 0.0f }, - { 0.0f, 1.0f, 0.0f }, - { 0.0f, -1.0f, 0.0f }, // bottom - { 0.0f, -1.0f, 0.0f }, - { 0.0f, -1.0f, 0.0f }, - { 0.0f, -1.0f, 0.0f }, - { -1.0f, 0.0f, 0.0f }, // left - { -1.0f, 0.0f, 0.0f }, - { -1.0f, 0.0f, 0.0f }, - { -1.0f, 0.0f, 0.0f }, - { 1.0f, 0.0f, 0.0f }, // right - { 1.0f, 0.0f, 0.0f }, - { 1.0f, 0.0f, 0.0f }, - { 1.0f, 0.0f, 0.0f }, - }, { - 0, 1, 2, 2, 1, 3, // front - 4, 5, 6, 6, 5, 7, // back - 8, 9, 10, 10, 9, 11, // top - 12, 13, 14, 14, 13, 15, // bottom - 16, 17, 18, 18, 17, 19, // left - 20, 21, 22, 22, 21, 23, // right - }); - SetTexture({ - { 0.0f, 1.0f, 0.0f }, // front - { 1.0f, 1.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f }, - { 1.0f, 0.0f, 0.0f }, - { 1.0f, 1.0f, 0.0f }, // back - { 1.0f, 0.0f, 0.0f }, - { 0.0f, 1.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f }, // top - { 0.0f, 1.0f, 0.0f }, - { 1.0f, 0.0f, 0.0f }, - { 1.0f, 1.0f, 0.0f }, - { 1.0f, 0.0f, 0.0f }, // bottom - { 0.0f, 0.0f, 0.0f }, - { 1.0f, 1.0f, 0.0f }, - { 0.0f, 1.0f, 0.0f }, - { 0.0f, 1.0f, 0.0f }, // left - { 1.0f, 1.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f }, - { 1.0f, 0.0f, 0.0f }, - { 1.0f, 1.0f, 0.0f }, // right - { 1.0f, 0.0f, 0.0f }, - { 0.0f, 1.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f }, - }); - SetOutline({ - { bb.min.x, bb.min.y, bb.min.z }, // back - { bb.max.x, bb.min.y, bb.min.z }, - { bb.min.x, bb.max.y, bb.min.z }, - { bb.max.x, bb.max.y, bb.min.z }, - { bb.min.x, bb.min.y, bb.max.z }, // front - { bb.max.x, bb.min.y, bb.max.z }, - { bb.min.x, bb.max.y, bb.max.z }, - { bb.max.x, bb.max.y, bb.max.z }, - }, { - 0, 1, 1, 3, 3, 2, 2, 0, // back - 4, 5, 5, 7, 7, 6, 6, 4, // front - 0, 4, 1, 5, 2, 6, 3, 7, // sides - }); +void Shape::Outline(OutlineMesh::Buffer &out) const { + if (bounds) { + bounds->Outline(out); + } } -bool CuboidShape::Intersects( +bool Shape::Intersects( const Ray &ray, const glm::mat4 &M, - float &dist, glm::vec3 &normal + float &dist, + glm::vec3 &normal ) const noexcept { - return Intersection(ray, bb, M, &dist, &normal); + if (bounds) { + return bounds->Intersects(ray, M, dist, normal); + } else { + return false; + } } -bool CuboidShape::Intersects( +bool Shape::Intersects( const glm::mat4 &M, const AABB &box, const glm::mat4 &box_M, float &depth, glm::vec3 &normal ) const noexcept { - return Intersection(bb, M, box, box_M, depth, normal); + if (bounds) { + return bounds->Intersects(M, box, box_M, depth, normal); + } else { + return false; + } } -StairShape::StairShape(const AABB &bb, const glm::vec2 &clip) -: Shape() -, top({ { bb.min.x, clip.y, bb.min.z }, { bb.max.x, bb.max.y, clip.x } }) -, bot({ bb.min, { bb.max.x, clip.y, bb.max.z } }) { - SetShape({ - { top.min.x, top.min.y, top.max.z }, // front, upper - { top.max.x, top.min.y, top.max.z }, - { top.min.x, top.max.y, top.max.z }, - { top.max.x, top.max.y, top.max.z }, - { bot.min.x, bot.min.y, bot.max.z }, // front, lower - { bot.max.x, bot.min.y, bot.max.z }, - { bot.min.x, bot.max.y, bot.max.z }, - { bot.max.x, bot.max.y, bot.max.z }, - { bot.min.x, bot.min.y, bot.min.z }, // back - { bot.min.x, top.max.y, bot.min.z }, - { top.max.x, bot.min.y, bot.min.z }, - { top.max.x, top.max.y, bot.min.z }, - { top.min.x, top.max.y, top.min.z }, // top, upper - { top.min.x, top.max.y, top.max.z }, - { top.max.x, top.max.y, top.min.z }, - { top.max.x, top.max.y, top.max.z }, - { bot.min.x, bot.max.y, top.max.z }, // top, lower - { bot.min.x, bot.max.y, bot.max.z }, - { bot.max.x, bot.max.y, top.max.z }, - { bot.max.x, bot.max.y, bot.max.z }, - { bot.min.x, bot.min.y, bot.min.z }, // bottom - { bot.max.x, bot.min.y, bot.min.z }, - { bot.min.x, bot.min.y, bot.max.z }, - { bot.max.x, bot.min.y, bot.max.z }, - { top.min.x, top.min.y, top.min.z }, // left, upper - { top.min.x, top.min.y, top.max.z }, - { top.min.x, top.max.y, top.min.z }, - { top.min.x, top.max.y, top.max.z }, - { bot.min.x, bot.min.y, bot.min.z }, // left, lower - { bot.min.x, bot.min.y, bot.max.z }, - { bot.min.x, bot.max.y, bot.min.z }, - { bot.min.x, bot.max.y, bot.max.z }, - { top.max.x, top.min.y, top.min.z }, // right, upper - { top.max.x, top.max.y, top.min.z }, - { top.max.x, top.min.y, top.max.z }, - { top.max.x, top.max.y, top.max.z }, - { bot.max.x, bot.min.y, bot.min.z }, // right, lower - { bot.max.x, bot.max.y, bot.min.z }, - { bot.max.x, bot.min.y, bot.max.z }, - { bot.max.x, bot.max.y, bot.max.z }, - }, { - { 0.0f, 0.0f, 1.0f }, // front x2 - { 0.0f, 0.0f, 1.0f }, - { 0.0f, 0.0f, 1.0f }, - { 0.0f, 0.0f, 1.0f }, - { 0.0f, 0.0f, 1.0f }, - { 0.0f, 0.0f, 1.0f }, - { 0.0f, 0.0f, 1.0f }, - { 0.0f, 0.0f, 1.0f }, - { 0.0f, 0.0f, -1.0f }, // back - { 0.0f, 0.0f, -1.0f }, - { 0.0f, 0.0f, -1.0f }, - { 0.0f, 0.0f, -1.0f }, - { 0.0f, 1.0f, 0.0f }, // top x2 - { 0.0f, 1.0f, 0.0f }, - { 0.0f, 1.0f, 0.0f }, - { 0.0f, 1.0f, 0.0f }, - { 0.0f, 1.0f, 0.0f }, - { 0.0f, 1.0f, 0.0f }, - { 0.0f, 1.0f, 0.0f }, - { 0.0f, 1.0f, 0.0f }, - { 0.0f, -1.0f, 0.0f }, // bottom - { 0.0f, -1.0f, 0.0f }, - { 0.0f, -1.0f, 0.0f }, - { 0.0f, -1.0f, 0.0f }, - { -1.0f, 0.0f, 0.0f }, // left x2 - { -1.0f, 0.0f, 0.0f }, - { -1.0f, 0.0f, 0.0f }, - { -1.0f, 0.0f, 0.0f }, - { -1.0f, 0.0f, 0.0f }, - { -1.0f, 0.0f, 0.0f }, - { -1.0f, 0.0f, 0.0f }, - { -1.0f, 0.0f, 0.0f }, - { 1.0f, 0.0f, 0.0f }, // right x2 - { 1.0f, 0.0f, 0.0f }, - { 1.0f, 0.0f, 0.0f }, - { 1.0f, 0.0f, 0.0f }, - { 1.0f, 0.0f, 0.0f }, - { 1.0f, 0.0f, 0.0f }, - { 1.0f, 0.0f, 0.0f }, - { 1.0f, 0.0f, 0.0f }, - }, { - 0, 1, 2, 2, 1, 3, // front, upper - 4, 5, 6, 6, 5, 7, // front, lower - 8, 9, 10, 10, 9, 11, // back - 12, 13, 14, 14, 13, 15, // top, upper - 16, 17, 18, 18, 17, 19, // top, lower - 20, 21, 22, 22, 21, 23, // bottom - 24, 25, 26, 26, 25, 27, // left, upper - 28, 29, 30, 30, 29, 31, // left, lower - 32, 33, 34, 34, 33, 35, // right, upper - 36, 37, 38, 38, 37, 39, // right, lower - }); - SetTexture({ - { 0.0f, 0.5f, 0.0f }, // front, upper - { 1.0f, 0.5f, 0.0f }, - { 0.0f, 0.0f, 0.0f }, - { 1.0f, 0.0f, 0.0f }, - { 0.0f, 1.0f, 0.0f }, // front, lower - { 1.0f, 1.0f, 0.0f }, - { 0.0f, 0.5f, 0.0f }, - { 1.0f, 0.5f, 0.0f }, - { 1.0f, 1.0f, 0.0f }, // back - { 1.0f, 0.0f, 0.0f }, - { 0.0f, 1.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.0f }, // top, upper - { 0.0f, 0.5f, 0.0f }, - { 1.0f, 0.0f, 0.0f }, - { 1.0f, 0.5f, 0.0f }, - { 0.0f, 0.5f, 0.0f }, // top, lower - { 0.0f, 1.0f, 0.0f }, - { 1.0f, 0.5f, 0.0f }, - { 1.0f, 1.0f, 0.0f }, - { 1.0f, 0.0f, 0.0f }, // bottom - { 0.0f, 0.0f, 0.0f }, - { 1.0f, 1.0f, 0.0f }, - { 0.0f, 1.0f, 0.0f }, - { 0.0f, 0.5f, 0.0f }, // left, upper - { 0.5f, 0.5f, 0.0f }, - { 0.0f, 0.0f, 0.0f }, - { 0.5f, 0.0f, 0.0f }, - { 0.0f, 1.0f, 0.0f }, // left, lower - { 1.0f, 1.0f, 0.0f }, - { 0.0f, 0.5f, 0.0f }, - { 1.0f, 0.5f, 0.0f }, - { 1.0f, 0.5f, 0.0f }, // right, upper - { 1.0f, 0.0f, 0.0f }, - { 0.5f, 0.5f, 0.0f }, - { 0.5f, 0.0f, 0.0f }, - { 1.0f, 1.0f, 0.0f }, // right, lower - { 1.0f, 0.5f, 0.0f }, - { 0.0f, 1.0f, 0.0f }, - { 0.0f, 0.5f, 0.0f }, - }); - SetOutline({ - { bot.min.x, bot.min.y, bot.min.z }, // bottom - { bot.max.x, bot.min.y, bot.min.z }, - { bot.min.x, bot.min.y, bot.max.z }, - { bot.max.x, bot.min.y, bot.max.z }, - { bot.min.x, bot.max.y, top.max.z }, // middle - { bot.max.x, bot.max.y, top.max.z }, - { bot.min.x, bot.max.y, bot.max.z }, - { bot.max.x, bot.max.y, bot.max.z }, - { top.min.x, top.max.y, top.min.z }, // top - { top.max.x, top.max.y, top.min.z }, - { top.min.x, top.max.y, top.max.z }, - { top.max.x, top.max.y, top.max.z }, - }, { - 0, 1, 1, 3, 3, 2, 2, 0, // bottom - 4, 5, 5, 7, 7, 6, 6, 4, // middle - 8, 9, 9, 11, 11, 10, 10 , 8, // top - 0, 8, 4, 10, 2, 6, // verticals, btf - 1, 9, 5, 11, 3, 7, - }); -} +ShapeRegistry::ShapeRegistry() +: shapes() { -bool StairShape::Intersects( - const Ray &ray, - const glm::mat4 &M, - float &dist, - glm::vec3 &norm -) const noexcept { - float top_dist, bot_dist; - glm::vec3 top_norm, bot_norm; - bool top_hit = Intersection(ray, top, M, &top_dist, &top_norm); - bool bot_hit = Intersection(ray, bot, M, &bot_dist, &bot_norm); +} - if (top_hit) { - if (bot_hit) { - if (top_dist < bot_dist) { - dist = top_dist; - norm = top_norm; - return true; - } else { - dist = bot_dist; - norm = bot_norm; - return true; - } - } else { - dist = top_dist; - norm = top_norm; - return true; - } - } else if (bot_hit) { - dist = bot_dist; - norm = bot_norm; - return true; +Shape &ShapeRegistry::Add(const string &name) { + auto result = shapes.emplace(name, Shape()); + if (result.second) { + return result.first->second; } else { - return false; + throw runtime_error("duplicate shape " + name); } } -bool StairShape::Intersects( - const glm::mat4 &M, - const AABB &box, - const glm::mat4 &box_M, - float &dist, - glm::vec3 &normal -) const noexcept { - bool top_hit, bot_hit; - float top_dist, bot_dist; - glm::vec3 top_normal, bot_normal; - - top_hit = Intersection(bot, M, box, box_M, top_dist, top_normal); - bot_hit = Intersection(top, M, box, box_M, bot_dist, bot_normal); +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); + } +} - if (top_hit) { - if (bot_hit && bot_dist < top_dist) { - dist = bot_dist; - normal = bot_normal; - return true; - } else { - dist = top_dist; - normal = top_normal; - return true; - } - return true; - } else if (bot_hit) { - dist = bot_dist; - normal = bot_normal; - return true; +const Shape &ShapeRegistry::Get(const string &name) const { + auto entry = shapes.find(name); + if (entry != shapes.end()) { + return entry->second; } else { - return false; + throw runtime_error("unknown shape " + name); } }