From ab8278e3b61e009253e34d13d6706da7702dbb6c Mon Sep 17 00:00:00 2001 From: Elisey Puzko Date: Fri, 23 Feb 2018 11:51:09 +0300 Subject: Bare-bones face detection for a block placement --- src/Block.hpp | 9 +++++++++ src/GameState.cpp | 46 ++++++++++++++++++++++++++++++++++++++++++++-- src/Render.cpp | 1 + src/Vector.hpp | 26 ++++++++++++++++++++++++++ src/World.cpp | 4 ++-- 5 files changed, 82 insertions(+), 4 deletions(-) diff --git a/src/Block.hpp b/src/Block.hpp index dfd6762..cd01f9a 100644 --- a/src/Block.hpp +++ b/src/Block.hpp @@ -19,6 +19,15 @@ struct BlockId { unsigned char state : 4; }; +enum BlockFacing { + Bottom = 0, + Top, + North, + South, + West, + East +}; + bool operator==(const BlockId& lhs, const BlockId &rhs); bool operator<(const BlockId& lhs, const BlockId &rhs); diff --git a/src/GameState.cpp b/src/GameState.cpp index 743a750..7498e17 100644 --- a/src/GameState.cpp +++ b/src/GameState.cpp @@ -586,12 +586,54 @@ void GameState::CancelDigging() { PUSH_EVENT("SendPacket", packet); } +#include + +BlockFacing detectHitFace(VectorF raycastHit, Vector selectedBlock) { + auto vec = VectorF(selectedBlock.x + .5, selectedBlock.y + .5, selectedBlock.z +.5) - raycastHit; + + // TODO: move these vectors to Vector.hpp + static const auto vecUp = VectorF(0, 1, 0); + static const auto vecRight = VectorF(1, 0, 0); + static const auto vecForward = VectorF(0, 0, -1); + + auto up = (vec.dot(vecUp))/(vec.GetLength()*vecUp.GetLength()); + auto down = -up; + auto right = (vec.dot(vecRight))/(vec.GetLength()*vecRight.GetLength()); + auto left = -right; + auto forward = (vec.dot(vecForward))/(vec.GetLength()*vecForward.GetLength()); + auto backward = -forward; + + // TODO: create a min/max function for the variable number of arguments + auto min = std::min( + std::min( + std::min( + std::min( + std::min(up, down), + right), + left), + forward), + backward); + + if (min == down) + return BlockFacing::Bottom; + else if (min == up) + return BlockFacing::Top; + else if (min == forward) + return BlockFacing::North; + else if (min == backward) + return BlockFacing::South; + else if (min == left) + return BlockFacing::West; + else return BlockFacing::East; +} + void GameState::PlaceBlock() { if (!isBlockSelected) - return; + return; + BlockFacing face = detectHitFace(raycastHit, selectedBlock); auto packetPlace = std::make_shared( - selectedBlock, 1, 0, 0.0, 0.0, 0.0); + selectedBlock, (unsigned char) face, 0, 0, 0, 0); auto packet = std::static_pointer_cast(packetPlace); PUSH_EVENT("SendPacket", packet); diff --git a/src/Render.cpp b/src/Render.cpp index cb05f65..c905bd9 100644 --- a/src/Render.cpp +++ b/src/Render.cpp @@ -211,6 +211,7 @@ void Render::HandleEvents() { break; } + case SDL_SCANCODE_SLASH: case SDL_SCANCODE_T: { if (!ImGui::GetIO().WantCaptureKeyboard) { auto state = GlobalState::GetState(); diff --git a/src/Vector.hpp b/src/Vector.hpp index 5795db2..aa79ef0 100644 --- a/src/Vector.hpp +++ b/src/Vector.hpp @@ -31,6 +31,24 @@ struct Vector3 { std::swap(z, rhs.z); } + T dot(const Vector3 &rhs) const { + return x*rhs.x + y*rhs.y + z*rhs.z; + } + + double cosBetween(const Vector3 &rhs) const { + return dot(rhs) / GetLength() / rhs.GetLength(); + } + + Vector3 normalize() { + auto length = GetLength(); + + return Vector3 ( + x / length, + y / length, + z / length + ); + } + Vector3 &operator=(Vector3 rhs) noexcept { rhs.swap(*this); return *this; @@ -68,6 +86,14 @@ struct Vector3 { ); } + Vector3 operator-() const { + return Vector3 ( + -x, + -y, + -z + ); + } + Vector3 operator*(const Vector3 &rhs) const { return Vector3( x * rhs.x, diff --git a/src/World.cpp b/src/World.cpp index f593bce..110b16b 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -142,12 +142,12 @@ RaycastResult World::Raycast(glm::vec3 position, glm::vec3 direction) { const float maxLen = 5.0; const float step = 0.01; glm::vec3 pos; - float len=0; + float len = 0; Vector blockPos = Vector(position.x,position.y,position.z); while (GetBlockId(blockPos) == BlockId{0, 0} && len <= maxLen) { pos = position + direction * len; len += step; - blockPos = Vector(floor(pos.x),floor(pos.y),floor(pos.z)); + blockPos = Vector(floor(pos.x), floor(pos.y), floor(pos.z)); } RaycastResult result; -- cgit v1.2.3