diff --git a/.gitignore b/.gitignore index 1dfd2a2a3..55057c5a2 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ Debug/src/**/*.o Debug/voxel_engine /build +/screenshots /world /worlds/**/* diff --git a/src/frontend/gui/panels.h b/src/frontend/gui/panels.h index 3524576fe..9480719fe 100644 --- a/src/frontend/gui/panels.h +++ b/src/frontend/gui/panels.h @@ -93,7 +93,8 @@ namespace gui { void back(); void clearHistory(); void reset(); - + +//FIXME "gui::PagesControl::current() returns Page by-value! (can initiate unexpected behaviour)") Page current(); }; } diff --git a/src/logic/PlayerController.cpp b/src/logic/PlayerController.cpp index acd72244d..f731f9e25 100644 --- a/src/logic/PlayerController.cpp +++ b/src/logic/PlayerController.cpp @@ -110,7 +110,7 @@ void CameraControl::update(PlayerInput& input, float delta) { vec3 PlayerController::selectedBlockPosition; vec3 PlayerController::selectedPointPosition; -vec3 PlayerController::selectedBlockNormal; +ivec3 PlayerController::selectedBlockNormal; int PlayerController::selectedBlockId = -1; int PlayerController::selectedBlockStates = 0; @@ -192,7 +192,8 @@ void PlayerController::updateInteraction(){ Lighting* lighting = level->lighting; Camera* camera = player->camera; vec3 end; - vec3 norm; + ivec3 iend; + ivec3 norm; bool xkey = Events::pressed(keycode::X); bool lclick = Events::jactive(BIND_PLAYER_ATTACK) || @@ -203,7 +204,7 @@ void PlayerController::updateInteraction(){ if (xkey) { maxDistance *= 20.0f; } - vec3 iend; + voxel* vox = chunks->rayCast(camera->position, camera->front, maxDistance, @@ -215,9 +216,9 @@ void PlayerController::updateInteraction(){ selectedBlockPosition = iend; selectedPointPosition = end; selectedBlockNormal = norm; - int x = (int)iend.x; - int y = (int)iend.y; - int z = (int)iend.z; + int x = iend.x; + int y = iend.y; + int z = iend.z; uint8_t states = 0; Block* def = contentIds->getBlockDef(player->choosenBlock); @@ -250,9 +251,9 @@ void PlayerController::updateInteraction(){ } if (rclick){ if (block->model != BlockModel::xsprite){ - x = (int)(iend.x)+(int)(norm.x); - y = (int)(iend.y)+(int)(norm.y); - z = (int)(iend.z)+(int)(norm.z); + x = (iend.x)+(norm.x); + y = (iend.y)+(norm.y); + z = (iend.z)+(norm.z); } vox = chunks->get(x, y, z); if (vox && (block = contentIds->getBlockDef(vox->id))->replaceable) { diff --git a/src/logic/PlayerController.h b/src/logic/PlayerController.h index a2f7ccf95..158b0b87e 100644 --- a/src/logic/PlayerController.h +++ b/src/logic/PlayerController.h @@ -37,7 +37,7 @@ class PlayerController { void updateInteraction(); public: static glm::vec3 selectedBlockPosition; - static glm::vec3 selectedBlockNormal; + static glm::ivec3 selectedBlockNormal; static glm::vec3 selectedPointPosition; static int selectedBlockId; static int selectedBlockStates; diff --git a/src/maths/rays.cpp b/src/maths/rays.cpp new file mode 100644 index 000000000..450fdf753 --- /dev/null +++ b/src/maths/rays.cpp @@ -0,0 +1,351 @@ + +#include "rays.h" +#include "aabb.h" + +#include "glm/glm.hpp" + +std::unordered_map Rays::raysBoxCache_ = {}; +const rayvec3 X_AXIS = rayvec3(1,0,0), Y_AXIS = rayvec3(0,1,0), Z_AXIS = rayvec3(0,0,1); + +//make faces from AABB +AABBFaces::AABBFaces(const rayvec3& parentBoxPos, const AABB& parentBox){ + rayvec3 pbMin = parentBox.min(), // every face is min-point and opposite corner point + pbMax = parentBox.max(), + pbRealPos = parentBoxPos + pbMin; + rayvec2 yzMax = rayvec2(parentBoxPos.y + pbMax.y, parentBoxPos.z + pbMax.z ), + xzMax = rayvec2(parentBoxPos.x + pbMax.x, parentBoxPos.z + pbMax.z ), + xyMax = rayvec2(parentBoxPos.x + pbMax.x, parentBoxPos.y + pbMax.y ); + faces[0] = {pbRealPos, yzMax}; //in order of AABBFaces::KINDS_ORDER! + + faces[1] = {parentBoxPos + rayvec3(pbMax.x, pbMin.y, pbMin.z), yzMax}; + + faces[2] = {pbRealPos, xzMax}; + + faces[3] = {parentBoxPos + rayvec3(pbMin.x, pbMax.y, pbMin.z), xzMax}; + + faces[4] = {pbRealPos, xyMax}; + + faces[5] = {parentBoxPos + rayvec3(pbMin.x, pbMin.y, pbMax.z), xyMax}; +} + +template <> +RayRelation Rays::rayIntersectAAFace( + const rayvec3& rayOrigin, + const rayvec3& rayDir, + const rayvec3& faceMin, + const rayvec2& faceOppositeCorner, //y and z global coords of opposite corner + rayvec3& intersectPoint_ret + ){ + if (fabs(glm::dot(rayDir, X_AXIS)) < 1.0E-8){ //precision + return RayRelation::Parallel; + } + + glm::float64 rayCoef = (faceMin.x - rayOrigin.x) / (rayDir.x); + intersectPoint_ret = {faceMin.x, + rayCoef*rayDir.y + rayOrigin.y, + rayCoef*rayDir.z + rayOrigin.z}; + + if (rayDir.x > 0){ + if (intersectPoint_ret.y >= faceMin.y + && intersectPoint_ret.y <= faceOppositeCorner[0] + && intersectPoint_ret.z >= faceMin.z + && intersectPoint_ret.z <= faceOppositeCorner[1]){ + return RayRelation::Intersect; + } + } + else{ + if (intersectPoint_ret.y <= faceMin.y + && intersectPoint_ret.y >= faceOppositeCorner[0] + && intersectPoint_ret.z <= faceMin.z + && intersectPoint_ret.z >= faceOppositeCorner[1]){ + return RayRelation::Intersect; + } + } + return RayRelation::None; +} + +template <> +RayRelation Rays::rayIntersectAAFace( + const rayvec3& rayOrigin, + const rayvec3& rayDir, + const rayvec3& faceMin, + const rayvec2& faceOppositeCorner, //x and z global coords of opposite corner + rayvec3& intersectPoint_ret + ){ + if (fabs(glm::dot(rayDir, Y_AXIS)) < 1.0E-8){ //precision + return RayRelation::Parallel; + } + + glm::float64 rayCoef = (faceMin.y - rayOrigin.y) / (rayDir.y); + intersectPoint_ret = {rayCoef*rayDir.x + rayOrigin.x, + faceMin.y, + rayCoef*rayDir.z + rayOrigin.z}; + + if (rayDir.y > 0){ + if (intersectPoint_ret.x >= faceMin.x //Face-hit check + && intersectPoint_ret.x <= faceOppositeCorner[0] + && intersectPoint_ret.z >= faceMin.z + && intersectPoint_ret.z <= faceOppositeCorner[1] ){ + return RayRelation::Intersect; + } + } + else{ + if (intersectPoint_ret.x <= faceMin.x //Face-hit check for negative dir. + && intersectPoint_ret.x >= faceOppositeCorner[0] + && intersectPoint_ret.z <= faceMin.z + && intersectPoint_ret.z >= faceOppositeCorner[1]){ + return RayRelation::Intersect; + } + } + return RayRelation::None; +} + +template <> +RayRelation Rays::rayIntersectAAFace( + const rayvec3& rayOrigin, + const rayvec3& rayDir, + const rayvec3& faceMin, + const rayvec2& faceOppositeCorner, //x and y global coords of opposite corner + rayvec3& intersectPoint_ret + ){ + if (fabs(glm::dot(rayDir, Z_AXIS)) < 1.0E-8){ //precision + return RayRelation::Parallel; + } + + glm::float64 rayCoef = (faceMin.z - rayOrigin.z) / (rayDir.z); + intersectPoint_ret = {rayCoef*rayDir.x + rayOrigin.x, + rayCoef*rayDir.y + rayOrigin.y, + faceMin.z}; + + if (rayDir.z > 0){ + if (intersectPoint_ret.x >= faceMin.x //Face-hit check + && intersectPoint_ret.x <= faceOppositeCorner[0] + && intersectPoint_ret.y >= faceMin.y + && intersectPoint_ret.y <= faceOppositeCorner[1] ){ + return RayRelation::Intersect; + } + } + else{ + if (intersectPoint_ret.x <= faceMin.x //Face-hit check + && intersectPoint_ret.x >= faceOppositeCorner[0] + && intersectPoint_ret.y <= faceMin.y + && intersectPoint_ret.y >= faceOppositeCorner[1] ){ + return RayRelation::Intersect; + } + } + return RayRelation::None; +} + +double Rays::updateNormal( + double newDistApprox, + const glm::ivec3& newNormal, + double currentDistApprox, + glm::ivec3& normal_ret + ){ + if (newDistApprox < currentDistApprox){ + currentDistApprox = newDistApprox; + normal_ret = newNormal; + } + return currentDistApprox; + } + +template <> +RayRelation Rays::isRayIntersectsAAFace( + const rayvec3& rayOrigin, + const rayvec3& rayDir, + const rayvec3& faceMin, + const rayvec2& faceOppositeCorner, + glm::ivec3& normal_ret, + double& currentDistApprox + ){ + if (fabs(glm::dot(rayDir, X_AXIS)) < 1.0E-8){ //precision of "parallelity" + return RayRelation::Parallel; + } + + glm::float64 rayCoef = (faceMin.x - rayOrigin.x); + rayvec3 intersectPointMult = {faceMin.x * rayDir.x, + rayCoef*rayDir.y + rayOrigin.y * rayDir.x, + rayCoef*rayDir.z + rayOrigin.z * rayDir.x}; + + if (rayDir.x > 0){ + if (intersectPointMult.y >= faceMin.y * rayDir.x //Face-hit check + && intersectPointMult.y <= faceOppositeCorner[0] * rayDir.x + && intersectPointMult.z >= faceMin.z * rayDir.x + && intersectPointMult.z <= faceOppositeCorner[1] * rayDir.x){ + currentDistApprox = updateNormal(fabs(rayCoef * rayDir.y * rayDir.z), -X_AXIS, currentDistApprox, normal_ret); + return RayRelation::Intersect; + } + } + else{ + if (intersectPointMult.y <= faceMin.y * rayDir.x //Face-hit check for negative dir. + && intersectPointMult.y >= faceOppositeCorner[0] * rayDir.x + && intersectPointMult.z <= faceMin.z * rayDir.x + && intersectPointMult.z >= faceOppositeCorner[1] * rayDir.x){ + currentDistApprox = updateNormal(fabs(rayCoef * rayDir.y * rayDir.z), X_AXIS, currentDistApprox, normal_ret); + return RayRelation::Intersect; + } + } + return RayRelation::None; +} + +template <> +RayRelation Rays::isRayIntersectsAAFace( + const rayvec3& rayOrigin, + const rayvec3& rayDir, + const rayvec3& faceMin, + const rayvec2& faceOppositeCorner, + glm::ivec3& normal_ret, + double& currentDistApprox + ){ + if (fabs(glm::dot(rayDir, Y_AXIS)) < 1.0E-8){ //precision of "parallelity" + return RayRelation::Parallel; + } + + glm::float64 rayCoef = (faceMin.y - rayOrigin.y); + rayvec3 intersectPointMult = {rayCoef*rayDir.x + rayOrigin.x * rayDir.y, + faceMin.y * rayDir.y, + rayCoef*rayDir.z + rayOrigin.z * rayDir.y}; + + if (rayDir.y > 0){ + if (intersectPointMult.x >= faceMin.x * rayDir.y //Face-hit check + && intersectPointMult.x <= faceOppositeCorner[0] * rayDir.y + && intersectPointMult.z >= faceMin.z * rayDir.y + && intersectPointMult.z <= faceOppositeCorner[1] * rayDir.y){ + currentDistApprox = updateNormal(fabs(rayCoef * rayDir.x * rayDir.z), -Y_AXIS, currentDistApprox, normal_ret); + return RayRelation::Intersect; + } + } + else{ + if (intersectPointMult.x <= faceMin.x * rayDir.y //Face-hit check for negative dir. + && intersectPointMult.x >= faceOppositeCorner[0] * rayDir.y + && intersectPointMult.z <= faceMin.z * rayDir.y + && intersectPointMult.z >= faceOppositeCorner[1] * rayDir.y){ + currentDistApprox = updateNormal(fabs(rayCoef * rayDir.x * rayDir.z), Y_AXIS, currentDistApprox, normal_ret); + return RayRelation::Intersect; + } + } + return RayRelation::None; +} + +template <> +RayRelation Rays::isRayIntersectsAAFace( + const rayvec3& rayOrigin, + const rayvec3& rayDir, + const rayvec3& faceMin, + const rayvec2& faceOppositeCorner, + glm::ivec3& normal_ret, + double& currentDistApprox + ){ + if (fabs(glm::dot(rayDir, Z_AXIS)) < 1.0E-8){ //precision of "parallelity" + return RayRelation::Parallel; + } + + glm::float64 rayCoef = (faceMin.z - rayOrigin.z); + rayvec3 intersectPointMult = {rayCoef*rayDir.x + rayOrigin.x * rayDir.z, + rayCoef*rayDir.y + rayOrigin.y * rayDir.z, + faceMin.z * rayDir.z}; + + if (rayDir.z > 0){ + if (intersectPointMult.x >= faceMin.x * rayDir.z //Face-hit check + && intersectPointMult.x <= faceOppositeCorner[0] * rayDir.z + && intersectPointMult.y >= faceMin.y * rayDir.z + && intersectPointMult.y <= faceOppositeCorner[1] * rayDir.z){ + currentDistApprox = updateNormal(fabs(rayCoef * rayDir.x * rayDir.y), -Z_AXIS, currentDistApprox, normal_ret); + return RayRelation::Intersect; + } + } + else{ + if (intersectPointMult.x <= faceMin.x * rayDir.z //Face-hit check + && intersectPointMult.x >= faceOppositeCorner[0] * rayDir.z + && intersectPointMult.y <= faceMin.y * rayDir.z + && intersectPointMult.y >= faceOppositeCorner[1] * rayDir.z){ + currentDistApprox = updateNormal(fabs(rayCoef * rayDir.x * rayDir.y), Z_AXIS, currentDistApprox, normal_ret); + return RayRelation::Intersect; + } + } + return RayRelation::None; +} + +RayRelation Rays::rayIntersectAABB( + const rayvec3& rayOrigin, + const rayvec3& rayDir, + const rayvec3& boxPos, + const AABB& box, + float maxDist, + rayvec3& pointIn_ret, + rayvec3& pointOut_ret, + glm::ivec3& normal_ret){ + if constexpr (IS_RAYS_BOX_CACHE_ON){ + + if (raysBoxCache_.find(boxPos) != raysBoxCache_.end()){ + const AABBFaces& boxFaces = raysBoxCache_[boxPos]; + return rayIntersectAABBFaces(rayOrigin, rayDir, boxFaces, maxDist, pointIn_ret, pointOut_ret, normal_ret); + } else { + const AABBFaces& boxFaces = AABBFaces(boxPos, box); + raysBoxCache_[boxPos] = boxFaces; + return rayIntersectAABBFaces(rayOrigin, rayDir, boxFaces, maxDist, pointIn_ret, pointOut_ret, normal_ret); + } + + } else { + const AABBFaces& boxFaces = AABBFaces(boxPos, box); + return rayIntersectAABBFaces(rayOrigin, rayDir, boxFaces, maxDist, pointIn_ret, pointOut_ret, normal_ret); + } + +} + +RayRelation Rays::rayIntersectAABBFaces( + const rayvec3& rayOrigin, + const rayvec3& rayDir, + const AABBFaces& boxFaces, + float maxDist, + rayvec3& pointIn_ret, + rayvec3& pointOut_ret, + glm::ivec3& normal_ret){//TODO: points returning + RayRelation rel; + double faceDistApprox = maxDist; + unsigned char intersectedCount = 0; //this code is very uncomfortable, DONT LEARN IT! + rel = isRayIntersectsAAFace( + rayOrigin, rayDir, boxFaces.faces[0].first, boxFaces.faces[0].second, normal_ret, faceDistApprox + ); + if (rel > RayRelation::None){ + ++intersectedCount; + } + + rel = isRayIntersectsAAFace( + rayOrigin, rayDir, boxFaces.faces[1].first, boxFaces.faces[1].second, normal_ret, faceDistApprox + ); + if (rel > RayRelation::None){ + ++intersectedCount; + } + + rel = isRayIntersectsAAFace( + rayOrigin, rayDir, boxFaces.faces[2].first, boxFaces.faces[2].second, normal_ret, faceDistApprox + ); + if (rel > RayRelation::None){ + ++intersectedCount; + } + + rel = isRayIntersectsAAFace( + rayOrigin, rayDir, boxFaces.faces[3].first, boxFaces.faces[3].second, normal_ret, faceDistApprox + ); + if (rel > RayRelation::None){ + ++intersectedCount; + } + + rel = isRayIntersectsAAFace( + rayOrigin, rayDir, boxFaces.faces[4].first, boxFaces.faces[4].second, normal_ret, faceDistApprox + ); + if (rel > RayRelation::None){ + ++intersectedCount; + } + + rel = isRayIntersectsAAFace( + rayOrigin, rayDir, boxFaces.faces[5].first, boxFaces.faces[5].second, normal_ret, faceDistApprox + ); + if (rel > RayRelation::None){ + ++intersectedCount; + } + + if (intersectedCount > 0) return RayRelation::Intersect; + return RayRelation::None; +} \ No newline at end of file diff --git a/src/maths/rays.h b/src/maths/rays.h new file mode 100644 index 000000000..bf6c7e766 --- /dev/null +++ b/src/maths/rays.h @@ -0,0 +1,97 @@ +#ifndef MATHS_RAYS_H_ +#define MATHS_RAYS_H_ + +// #include "../typedefs.h" +#include "aabb.h" +#include "glm/glm.hpp" + +#include + +typedef glm::highp_dvec3 rayvec3; +typedef glm::highp_dvec2 rayvec2; + +enum class RayRelation{ + Embed=2, Intersect=1, Parallel=0, None=0 +}; +enum class AAFaceKind : unsigned char{ + Xperp=0, Yperp=1, Zperp=2 //perpendicular faces to corresponding axis +}; + +const unsigned char AABBFACES_COUNT = 6; + +class AABBFaces{ +public: + std::array, AABBFACES_COUNT> faces; // every face is min-point and opposite corner point + + static constexpr std::array KINDS_ORDER = { + AAFaceKind::Xperp, AAFaceKind::Xperp, + AAFaceKind::Yperp, AAFaceKind::Yperp, + AAFaceKind::Zperp, AAFaceKind::Zperp}; + + AABBFaces(){}; + AABBFaces(const rayvec3& parentBoxPos, const AABB& parentBox); + +}; + +template<> +struct std::hash{ + std::size_t operator()(const rayvec3& r) const noexcept{ + return std::hash{}(r.x) ^ (std::hash{}(r.y) << 1) ^ (std::hash{}(r.z) << 2); + } +}; + +class Rays{ +protected: + static const bool IS_RAYS_BOX_CACHE_ON = false; + static std::unordered_map raysBoxCache_; //[boxPos]: faces array + +public: + +template +static RayRelation rayIntersectAAFace( + const rayvec3& rayOrigin, + const rayvec3& rayDir, + const rayvec3& faceMin, + const rayvec2& faceOppositeCorner, + rayvec3& intersectPoint_ret + ); + +static double updateNormal( + double newDistApprox, + const glm::ivec3& newNormal, + double currentDistApprox, + glm::ivec3& normal_ret + ); + +//optimized, not returns intersectPoint coordinates +template +static RayRelation isRayIntersectsAAFace( + const rayvec3& rayOrigin, + const rayvec3& rayDir, + const rayvec3& faceMin, + const rayvec2& faceOppositeCorner, + glm::ivec3& normal_ret, + double& currentDistApprox + ); + +static RayRelation rayIntersectAABB( + const rayvec3& rayOrigin, + const rayvec3& rayDir, + const rayvec3& boxPos, + const AABB& box, + float maxDist, + rayvec3& pointIn_ret, + rayvec3& pointOut_ret, + glm::ivec3& normal_ret); + +static RayRelation rayIntersectAABBFaces( + const rayvec3& rayOrigin, + const rayvec3& rayDir, + const AABBFaces& boxFaces, + float maxDist, + rayvec3& pointIn_ret, + rayvec3& pointOut_ret, + glm::ivec3& normal_ret); +}; + +#endif // SRC_VOXNATHS_H_ diff --git a/src/util/timeutil.cpp b/src/util/timeutil.cpp index 7cee8e9f8..e299bec11 100644 --- a/src/util/timeutil.cpp +++ b/src/util/timeutil.cpp @@ -1,5 +1,7 @@ #include "timeutil.h" +#include + using std::chrono::high_resolution_clock; using std::chrono::duration_cast; using std::chrono::microseconds; @@ -11,6 +13,12 @@ int64_t timeutil::Timer::stop() { return duration_cast(high_resolution_clock::now()-start).count(); } +timeutil::ScopeLogTimer::ScopeLogTimer(long long id) : scopeid_(id) {} + +timeutil::ScopeLogTimer::~ScopeLogTimer() { + std::cout << "Scope "<< scopeid_ <<" finished in "<< ScopeLogTimer::stop() << " micros. \n"; +} + float timeutil::time_value(float hour, float minute, float second) { return (hour + (minute + second / 60.0f) / 60.0f) / 24.0f; } diff --git a/src/util/timeutil.h b/src/util/timeutil.h index 02939e725..786d2a91b 100644 --- a/src/util/timeutil.h +++ b/src/util/timeutil.h @@ -12,6 +12,19 @@ namespace timeutil { int64_t stop(); }; +/* Timer that stops and prints time when destructor called + * @example: + * { // some scope (custom, function, if/else, cycle etc.) + * timeutil::ScopeLogTimer scopeclock(); + * ... + * } */ + class ScopeLogTimer : public Timer{ + long long scopeid_; + public: + ScopeLogTimer(long long id); + ~ScopeLogTimer(); + }; + float time_value(float hour, float minute, float second); void from_value(float value, int& hour, int& minute, int& second); } diff --git a/src/voxels/Chunks.cpp b/src/voxels/Chunks.cpp index 80dc646a3..497bb0826 100644 --- a/src/voxels/Chunks.cpp +++ b/src/voxels/Chunks.cpp @@ -10,11 +10,14 @@ #include "../graphics/Mesh.h" #include "../maths/voxmaths.h" +#include "../maths/aabb.h" +#include "../maths/rays.h" #include #include using glm::vec3; +using glm::ivec3; using std::shared_ptr; Chunks::Chunks(int w, int d, @@ -45,7 +48,7 @@ Chunks::~Chunks(){ } voxel* Chunks::get(int x, int y, int z){ - x -= ox * CHUNK_W; + x -= ox * CHUNK_W; z -= oz * CHUNK_D; int cx = x / CHUNK_W; int cy = y / CHUNK_H; @@ -55,7 +58,7 @@ voxel* Chunks::get(int x, int y, int z){ if (z < 0) cz--; if (cx < 0 || cy < 0 || cz < 0 || cx >= w || cy >= 1 || cz >= d) return nullptr; - shared_ptr chunk = chunks[(cy * d + cz) * w + cx]; + shared_ptr chunk = chunks[cz * w + cx]; // chunks is 2D-array if (chunk == nullptr) return nullptr; int lx = x - cx * CHUNK_W; @@ -174,13 +177,13 @@ void Chunks::set(int x, int y, int z, int id, uint8_t states){ if (lz == CHUNK_D-1 && (chunk = getChunk(cx+ox, cz+oz+1))) chunk->setModified(true); } - +#include "../util/timeutil.h" voxel* Chunks::rayCast(vec3 start, vec3 dir, float maxDist, vec3& end, - vec3& norm, - vec3& iend) { + ivec3& norm, + ivec3& iend) { float px = start.x; float py = start.y; float pz = start.z; @@ -194,9 +197,9 @@ voxel* Chunks::rayCast(vec3 start, int iy = floor(py); int iz = floor(pz); - float stepx = (dx > 0.0f) ? 1.0f : -1.0f; - float stepy = (dy > 0.0f) ? 1.0f : -1.0f; - float stepz = (dz > 0.0f) ? 1.0f : -1.0f; + int stepx = (dx > 0.0f) ? 1 : -1; + int stepy = (dy > 0.0f) ? 1 : -1; + int stepz = (dz > 0.0f) ? 1 : -1; constexpr float infinity = std::numeric_limits::infinity(); @@ -212,71 +215,37 @@ voxel* Chunks::rayCast(vec3 start, float tyMax = (tyDelta < infinity) ? tyDelta * ydist : infinity; float tzMax = (tzDelta < infinity) ? tzDelta * zdist : infinity; - int steppedIndex = -1; + int steppedIndex = -1; + + while (t <= maxDist){ + voxel* voxel = get(ix, iy, iz); + if (!voxel){ return nullptr; } - while (t <= maxDist){ - voxel* voxel = get(ix, iy, iz); - const Block* def = nullptr; - if (voxel == nullptr || (def = contentIds->getBlockDef(voxel->id))->selectable){ + const Block* def = contentIds->getBlockDef(voxel->id); + if (def->selectable){ + timeutil::ScopeLogTimer lg((long long)def); end.x = px + t * dx; end.y = py + t * dy; end.z = pz + t * dz; + iend.x = ix; + iend.y = iy; + iend.z = iz; - // TODO: replace this dumb solution with something better - if (def && !def->rt.solid) { - const int gridSize = BLOCK_AABB_GRID * 2; + if (!def->rt.solid) { const AABB& box = def->rotatable ? def->rt.hitboxes[voxel->rotation()] : def->hitbox; - const int subs = gridSize; - iend = vec3(ix, iy, iz); - end -= iend; - int six = end.x * gridSize; - int siy = end.y * gridSize; - int siz = end.z * gridSize; - float stxMax = (txDelta < infinity) ? txDelta * xdist : infinity; - float styMax = (tyDelta < infinity) ? tyDelta * ydist : infinity; - float stzMax = (tzDelta < infinity) ? tzDelta * zdist : infinity; - for (int i = 0; i < subs*2; i++) { - end.x = six / float(gridSize); - end.y = siy / float(gridSize); - end.z = siz / float(gridSize); - if (box.inside(end)) { - end += iend; - norm.x = norm.y = norm.z = 0.0f; - if (steppedIndex == 0) norm.x = -stepx; - if (steppedIndex == 1) norm.y = -stepy; - if (steppedIndex == 2) norm.z = -stepz; - return voxel; - } - if (stxMax < styMax) { - if (stxMax < stzMax) { - six += stepx; - stxMax += txDelta; - steppedIndex = 0; - } else { - siz += stepz; - stzMax += tzDelta; - steppedIndex = 2; - } - } else { - if (styMax < stzMax) { - siy += stepy; - styMax += tyDelta; - steppedIndex = 1; - } else { - siz += stepz; - stzMax += tzDelta; - steppedIndex = 2; - } - } + rayvec3 in, out; // <- now not used, but for future... + if (Rays::rayIntersectAABB(start, dir, iend, box, maxDist, in, out, norm) > RayRelation::None){ + return voxel; } + } else { iend.x = ix; iend.y = iy; iend.z = iz; - norm.x = norm.y = norm.z = 0.0f; + norm.x = norm.y = norm.z = 0; if (steppedIndex == 0) norm.x = -stepx; if (steppedIndex == 1) norm.y = -stepy; if (steppedIndex == 2) norm.z = -stepz; @@ -316,7 +285,7 @@ voxel* Chunks::rayCast(vec3 start, end.x = px + t * dx; end.y = py + t * dy; end.z = pz + t * dz; - norm.x = norm.y = norm.z = 0.0f; + norm.x = norm.y = norm.z = 0; return nullptr; } @@ -336,7 +305,7 @@ void Chunks::translate(int dx, int dz){ } for (int z = 0; z < d; z++){ for (int x = 0; x < w; x++){ - shared_ptr chunk = chunks[z * d + x]; + shared_ptr chunk = chunks[z * w + x]; int nx = x - dx; int nz = z - dz; if (chunk == nullptr) @@ -351,9 +320,7 @@ void Chunks::translate(int dx, int dz){ chunksSecond[nz * w + nx] = chunk; } } - shared_ptr* ctemp = chunks; - chunks = chunksSecond; - chunksSecond = ctemp; + std::swap(chunks, chunksSecond); ox += dx; oz += dz; diff --git a/src/voxels/Chunks.h b/src/voxels/Chunks.h index 687499f22..78ed84bb4 100644 --- a/src/voxels/Chunks.h +++ b/src/voxels/Chunks.h @@ -48,8 +48,8 @@ class Chunks { glm::vec3 dir, float maxLength, glm::vec3& end, - glm::vec3& norm, - glm::vec3& iend); + glm::ivec3& norm, + glm::ivec3& iend); const AABB* isObstacle(float x, float y, float z);