From 9ec92f33a5397447c3a10a5ddac3c6ec0beb32b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tur=C3=A1nszki=20J=C3=A1nos?= Date: Wed, 28 Feb 2024 19:37:50 +0100 Subject: [PATCH] voxel occlusion testing --- .../ScriptingAPI-Documentation.md | 5 + WickedEngine/wiRenderer.cpp | 1 + WickedEngine/wiSprite_BindLua.cpp | 18 ++ WickedEngine/wiSprite_BindLua.h | 2 + WickedEngine/wiVersion.cpp | 4 +- WickedEngine/wiVoxelGrid.cpp | 247 ++++++++++++++---- WickedEngine/wiVoxelGrid.h | 14 +- WickedEngine/wiVoxelGrid_BindLua.cpp | 43 +++ WickedEngine/wiVoxelGrid_BindLua.h | 1 + 9 files changed, 285 insertions(+), 50 deletions(-) diff --git a/Content/Documentation/ScriptingAPI-Documentation.md b/Content/Documentation/ScriptingAPI-Documentation.md index 9e35325df5..babf54659a 100644 --- a/Content/Documentation/ScriptingAPI-Documentation.md +++ b/Content/Documentation/ScriptingAPI-Documentation.md @@ -179,6 +179,8 @@ Render images on the screen. - GetTexture() : Texture - SetMaskTexture(Texture texture) - GetMaskTexture() : Texture +- SetHidden(bool value) +- IsHidden() : bool #### ImageParams Specify Sprite properties, like position, size, etc. @@ -1765,6 +1767,9 @@ Path finding operations can be made by using a voxel grid and path queries. The - GetDebugColorExtent() : Vector -- returns color of debug visualization of voxel grid extents - SetDebugColorExtent(Vector color) -- set the color for debug visualization of voxel grid extents - GetMemorySize() : int -- returns the memory consumption of the voxel grid in bytes +- IsVisible(int observer_x,observer_y,observer_z, subject_x,subject_y,subject_z) : bool -- performs line of sight occlusion test from observer to subject voxel coordinates. Returns false if occlusion was found, true otherwise. +- IsVisible(AABB observer, subject) : bool -- performs line of sight occlusion test from observer to subject world space points. Returns false if occlusion was found, true otherwise. +- IsVisible(AABB observer, AABB subject) : bool -- performs line of sight occlusion test from observer world space point to subject AABB. Returns true if any of the AABB's touched voxels is visible, false otherwise. #### PathQuery - [constructor] PathQuery() diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index 216ff6d9ae..4f9ed058a7 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -7347,6 +7347,7 @@ void DrawDebugWorld( params.size = x.params.pixel_height; params.scaling = 1.0f / params.size * x.params.scaling; params.color = wi::Color::fromFloat4(x.params.color); + params.intensity = x.params.color.w > 1 ? x.params.color.w : 1; params.h_align = wi::font::WIFALIGN_CENTER; params.v_align = wi::font::WIFALIGN_CENTER; params.softness = 0.0f; diff --git a/WickedEngine/wiSprite_BindLua.cpp b/WickedEngine/wiSprite_BindLua.cpp index da7cc7c9b6..a057d4e604 100644 --- a/WickedEngine/wiSprite_BindLua.cpp +++ b/WickedEngine/wiSprite_BindLua.cpp @@ -15,6 +15,8 @@ namespace wi::lua lunamethod(Sprite_BindLua, GetTexture), lunamethod(Sprite_BindLua, SetMaskTexture), lunamethod(Sprite_BindLua, GetMaskTexture), + lunamethod(Sprite_BindLua, SetHidden), + lunamethod(Sprite_BindLua, IsHidden), { NULL, NULL } }; @@ -131,6 +133,22 @@ namespace wi::lua Luna::push(L, sprite.maskResource); return 1; } + int Sprite_BindLua::SetHidden(lua_State* L) + { + int argc = wi::lua::SGetArgCount(L); + if (argc < 1) + { + wi::lua::SError(L, "SetHidden(bool value) not enough arguments!"); + return 0; + } + sprite.SetHidden(wi::lua::SGetBool(L, 1)); + return 0; + } + int Sprite_BindLua::IsHidden(lua_State* L) + { + wi::lua::SSetBool(L, sprite.IsHidden()); + return 1; + } void Sprite_BindLua::Bind() { diff --git a/WickedEngine/wiSprite_BindLua.h b/WickedEngine/wiSprite_BindLua.h index e9ac30b41d..2d0babf809 100644 --- a/WickedEngine/wiSprite_BindLua.h +++ b/WickedEngine/wiSprite_BindLua.h @@ -25,6 +25,8 @@ namespace wi::lua int GetTexture(lua_State* L); int SetMaskTexture(lua_State* L); int GetMaskTexture(lua_State* L); + int SetHidden(lua_State* L); + int IsHidden(lua_State* L); static void Bind(); }; diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 4e10676cc4..2831c2950f 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wi::version // minor features, major updates, breaking compatibility changes const int minor = 71; // minor bug fixes, alterations, refactors, updates - const int revision = 383; + const int revision = 384; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision); @@ -50,7 +50,7 @@ All contributors: https://github.com/turanszkij/WickedEngine/graphs/contributors Patreon supporters --------------------------- -Nemerle, James Webb, Quifeng Jin, TheGameCreators, Joseph Goldin, Yuri, Sergey K, Yukawa Kanta, Dragon Josh, John, LurkingNinja, Bernardo Del Castillo, Invictus, Scott Hunt, Yazan Altaki, Tuan NV, Robert MacGregor, cybernescence, Alexander Dahlin, blueapples, Delhills, NI NI, Sherief, ktopoet, Justin Macklin, Cédric Fabre, TogetherTeam, Bartosz Boczula, Arne Koenig, Ivan Trajchev, nathants, Fahd Ahmed, Gabriel Jadderson, SAS_Controller, Dominik Madarász, Segfault, Mike amanfo, Dennis Brakhane, rookie, Peter Moore, therealjtgill, Nicolas Embleton, Desuuc, radino1977, Anthony Curtis, manni heck, Matthias Hölzl, Phyffer, Lucas Pinheiro, Tapkaara, gpman, Anthony Python, Gnowos, Klaus, slaughternaut, Paul Brain, Connor Greaves, Alexandr, Lee Bamber, MCAlarm MC2, Titoutan, Willow, Aldo, lokimx, K. Osterman, Nomad +Nemerle, James Webb, Quifeng Jin, TheGameCreators, Joseph Goldin, Yuri, Sergey K, Yukawa Kanta, Dragon Josh, John, LurkingNinja, Bernardo Del Castillo, Invictus, Scott Hunt, Yazan Altaki, Tuan NV, Robert MacGregor, cybernescence, Alexander Dahlin, blueapples, Delhills, NI NI, Sherief, ktopoet, Justin Macklin, Cédric Fabre, TogetherTeam, Bartosz Boczula, Arne Koenig, Ivan Trajchev, nathants, Fahd Ahmed, Gabriel Jadderson, SAS_Controller, Dominik Madarász, Segfault, Mike amanfo, Dennis Brakhane, rookie, Peter Moore, therealjtgill, Nicolas Embleton, Desuuc, radino1977, Anthony Curtis, manni heck, Matthias Hölzl, Phyffer, Lucas Pinheiro, Tapkaara, gpman, Anthony Python, Gnowos, Klaus, slaughternaut, Paul Brain, Connor Greaves, Alexandr, Lee Bamber, MCAlarm MC2, Titoutan, Willow, Aldo, lokimx, K. Osterman, Nomad, ykl )"; return credits; diff --git a/WickedEngine/wiVoxelGrid.cpp b/WickedEngine/wiVoxelGrid.cpp index 3b1a3cf8b5..7da5355cca 100644 --- a/WickedEngine/wiVoxelGrid.cpp +++ b/WickedEngine/wiVoxelGrid.cpp @@ -68,7 +68,7 @@ namespace wi XMVECTOR MAX = XMVectorMax(A, XMVectorMax(B, C)); MIN = XMVectorFloor(MIN); - MAX = XMVectorCeiling(MAX + XMVectorSet(0.5f, 0.5f, 0.5f, 0)); + MAX = XMVectorCeiling(MAX + XMVectorSet(0.0001f, 0.0001f, 0.0001f, 0)); MIN = XMVectorMax(MIN, XMVectorZero()); MAX = XMVectorMin(MAX, RESOLUTION); @@ -87,9 +87,9 @@ namespace wi const DirectX::BoundingBox voxel_aabb(XMFLOAT3(x + 0.5f, y + 0.5f, z + 0.5f), XMFLOAT3(0.5f, 0.5f, 0.5f)); if (voxel_aabb.Intersects(A, B, C)) { - const uint3 coord = uint3(x / 4u, y / 4u, z / 4u); + const uint3 macro_coord = uint3(x / 4u, y / 4u, z / 4u); const uint3 sub_coord = uint3(x % 4u, y % 4u, z % 4u); - const uint32_t idx = flatten3D(coord, resolution_div4); + const uint32_t idx = flatten3D(macro_coord, resolution_div4); const uint32_t bit = flatten3D(sub_coord, uint3(4, 4, 4)); const uint64_t mask = 1ull << bit; if (subtract) @@ -128,7 +128,7 @@ namespace wi XMVECTOR MAX = XMVectorMax(_MIN, _MAX); MIN = XMVectorFloor(MIN); - MAX = XMVectorCeiling(MAX + XMVectorSet(0.5f, 0.5f, 0.5f, 0)); + MAX = XMVectorCeiling(MAX + XMVectorSet(0.0001f, 0.0001f, 0.0001f, 0)); MIN = XMVectorMax(MIN, XMVectorZero()); MAX = XMVectorMin(MAX, RESOLUTION); @@ -148,23 +148,18 @@ namespace wi { for (uint32_t z = mini.z; z < maxi.z; ++z) { - wi::primitive::AABB voxel_aabb; - voxel_aabb.createFromHalfWidth(XMFLOAT3(x + 0.5f, y + 0.5f, z + 0.5f), XMFLOAT3(0.5f, 0.5f, 0.5f)); - if (voxel_aabb.intersects(aabb_src) != wi::primitive::AABB::INTERSECTION_TYPE::OUTSIDE) + const uint3 macro_coord = uint3(x / 4u, y / 4u, z / 4u); + const uint3 sub_coord = uint3(x % 4u, y % 4u, z % 4u); + const uint32_t idx = flatten3D(macro_coord, resolution_div4); + const uint32_t bit = flatten3D(sub_coord, uint3(4, 4, 4)); + const uint64_t mask = 1ull << bit; + if (subtract) { - const uint3 coord = uint3(x / 4u, y / 4u, z / 4u); - const uint3 sub_coord = uint3(x % 4u, y % 4u, z % 4u); - const uint32_t idx = flatten3D(coord, resolution_div4); - const uint32_t bit = flatten3D(sub_coord, uint3(4, 4, 4)); - const uint64_t mask = 1ull << bit; - if (subtract) - { - AtomicAnd(data + idx, ~mask); - } - else - { - AtomicOr(data + idx, mask); - } + AtomicAnd(data + idx, ~mask); + } + else + { + AtomicOr(data + idx, mask); } } } @@ -196,7 +191,7 @@ namespace wi XMVECTOR MAX = XMVectorMax(_MIN, _MAX); MIN = XMVectorFloor(MIN); - MAX = XMVectorCeiling(MAX + XMVectorSet(0.5f, 0.5f, 0.5f, 0)); + MAX = XMVectorCeiling(MAX + XMVectorSet(0.0001f, 0.0001f, 0.0001f, 0)); MIN = XMVectorMax(MIN, XMVectorZero()); MAX = XMVectorMin(MAX, RESOLUTION); @@ -218,9 +213,9 @@ namespace wi voxel_aabb.createFromHalfWidth(voxel_center_world, voxelSize); if (voxel_aabb.intersects(sphere)) { - const uint3 coord = uint3(x / 4u, y / 4u, z / 4u); + const uint3 macro_coord = uint3(x / 4u, y / 4u, z / 4u); const uint3 sub_coord = uint3(x % 4u, y % 4u, z % 4u); - const uint32_t idx = flatten3D(coord, resolution_div4); + const uint32_t idx = flatten3D(macro_coord, resolution_div4); const uint32_t bit = flatten3D(sub_coord, uint3(4, 4, 4)); const uint64_t mask = 1ull << bit; if (subtract) @@ -261,7 +256,7 @@ namespace wi XMVECTOR MAX = XMVectorMax(_MIN, _MAX); MIN = XMVectorFloor(MIN); - MAX = XMVectorCeiling(MAX + XMVectorSet(0.5f, 0.5f, 0.5f, 0)); + MAX = XMVectorCeiling(MAX + XMVectorSet(0.0001f, 0.0001f, 0.0001f, 0)); MIN = XMVectorMax(MIN, XMVectorZero()); MAX = XMVectorMin(MAX, RESOLUTION); @@ -297,9 +292,9 @@ namespace wi } if (intersects) { - const uint3 coord = uint3(x / 4u, y / 4u, z / 4u); + const uint3 macro_coord = uint3(x / 4u, y / 4u, z / 4u); const uint3 sub_coord = uint3(x % 4u, y % 4u, z % 4u); - const uint32_t idx = flatten3D(coord, resolution_div4); + const uint32_t idx = flatten3D(macro_coord, resolution_div4); const uint32_t bit = flatten3D(sub_coord, uint3(4, 4, 4)); const uint64_t mask = 1ull << bit; if (subtract) @@ -328,21 +323,22 @@ namespace wi XMStoreFloat3(&worldpos, uvw_to_world((XMLoadUInt3(&coord) + XMVectorReplicate(0.5f)) * XMLoadFloat3(&resolution_rcp), XMLoadFloat3(¢er), XMLoadUInt3(&resolution), XMLoadFloat3(&voxelSize))); return worldpos; } - bool VoxelGrid::check_voxel(XMUINT3 coord) const + bool VoxelGrid::check_voxel(const XMUINT3& coord) const { - if (coord.x >= resolution.x || coord.y >= resolution.y || coord.z >= resolution.z) - return false; + if (!is_coord_valid(coord)) + return false; // early exit when coord is not valid (outside of resolution) + const uint3 macro_coord = uint3(coord.x / 4u, coord.y / 4u, coord.z / 4u); + const uint idx = flatten3D(macro_coord, resolution_div4); + const uint64_t voxels_4x4_block = voxels[idx]; + if (voxels_4x4_block == 0) + return false; // early exit when whole block is empty uint3 sub_coord; sub_coord.x = coord.x % 4u; sub_coord.y = coord.y % 4u; sub_coord.z = coord.z % 4u; - coord.x /= 4u; - coord.y /= 4u; - coord.z /= 4u; - const uint idx = flatten3D(coord, resolution_div4); const uint bit = flatten3D(sub_coord, uint3(4, 4, 4)); const uint64_t mask = 1ull << bit; - return (voxels[idx] & mask) != 0ull; + return (voxels_4x4_block & mask) != 0ull; } bool VoxelGrid::check_voxel(const XMFLOAT3& worldpos) const { @@ -352,18 +348,13 @@ namespace wi { return coord.x < resolution.x && coord.y < resolution.y && coord.z < resolution.z; } - void VoxelGrid::set_voxel(XMUINT3 coord, bool value) + void VoxelGrid::set_voxel(const XMUINT3& coord, bool value) { - if (coord.x >= resolution.x || coord.y >= resolution.y || coord.z >= resolution.z) - return; - uint3 sub_coord; - sub_coord.x = coord.x % 4u; - sub_coord.y = coord.y % 4u; - sub_coord.z = coord.z % 4u; - coord.x /= 4u; - coord.y /= 4u; - coord.z /= 4u; - const uint idx = flatten3D(coord, resolution_div4); + if (!is_coord_valid(coord)) + return; // early exit when coord is not valid (outside of resolution) + const uint3 macro_coord = uint3(coord.x / 4u, coord.y / 4u, coord.z / 4u); + const uint3 sub_coord = uint3(coord.x % 4u, coord.y % 4u, coord.z % 4u); + const uint idx = flatten3D(macro_coord, resolution_div4); const uint bit = flatten3D(sub_coord, uint3(4, 4, 4)); const uint64_t mask = 1ull << bit; if (value) @@ -409,6 +400,131 @@ namespace wi set_voxelsize(XMFLOAT3(halfwidth.x / resolution.x, halfwidth.y / resolution.y, halfwidth.z / resolution.z)); } + bool VoxelGrid::is_visible(const XMUINT3& start, const XMUINT3& goal) const + { + const int dx = int(goal.x) - int(start.x); + const int dy = int(goal.y) - int(start.y); + const int dz = int(goal.z) - int(start.z); + + const int step = std::max(std::abs(dx), std::max(std::abs(dy), std::abs(dz))); + + const float x_incr = float(dx) / step; + const float y_incr = float(dy) / step; + const float z_incr = float(dz) / step; + + float x = float(start.x); + float y = float(start.y); + float z = float(start.z); + +#ifdef DEBUG_VOXEL_OCCLUSION + debug_subject_coords.push_back(goal); +#endif // DEBUG_VOXEL_OCCLUSION + + for (int i = 0; i < step; i++) + { + XMUINT3 coord = XMUINT3(uint32_t(std::round(x)), uint32_t(std::round(y)), uint32_t(std::round(z))); + if (coord.x == goal.x && coord.y == goal.y && coord.z == goal.z) + return true; + if (check_voxel(coord)) + { +#ifdef DEBUG_VOXEL_OCCLUSION + debug_occluded_coords.push_back(coord); +#endif // DEBUG_VOXEL_OCCLUSION + return false; + } +#ifdef DEBUG_VOXEL_OCCLUSION + debug_visible_coords.push_back(coord); +#endif // DEBUG_VOXEL_OCCLUSION + x += x_incr; + y += y_incr; + z += z_incr; + } + return true; + } + bool VoxelGrid::is_visible(const XMFLOAT3& observer, const XMFLOAT3& subject) const + { + XMUINT3 start = world_to_coord(observer); + XMUINT3 goal = world_to_coord(subject); + return is_visible(start, goal); + } + bool VoxelGrid::is_visible(const XMFLOAT3& observer, const AABB& subject) const + { + XMUINT3 start = world_to_coord(observer); + + const XMVECTOR CENTER = XMLoadFloat3(¢er); + const XMVECTOR RESOLUTION = XMLoadUInt3(&resolution); + const XMVECTOR RESOLUTION_RCP = XMLoadFloat3(&resolution_rcp); + const XMVECTOR VOXELSIZE_RCP = XMLoadFloat3(&voxelSize_rcp); + + XMVECTOR _MIN = XMLoadFloat3(&subject._min); + XMVECTOR _MAX = XMLoadFloat3(&subject._max); + + // world -> uvw space: + _MIN = world_to_uvw(_MIN, CENTER, RESOLUTION_RCP, VOXELSIZE_RCP); + _MAX = world_to_uvw(_MAX, CENTER, RESOLUTION_RCP, VOXELSIZE_RCP); + + // pixel space: + _MIN *= RESOLUTION; + _MAX *= RESOLUTION; + + // After changing spaces, need to minmax again: + XMVECTOR MIN = XMVectorMin(_MIN, _MAX); + XMVECTOR MAX = XMVectorMax(_MIN, _MAX); + + MIN = XMVectorFloor(MIN); + MAX = XMVectorCeiling(MAX + XMVectorSet(0.0001f, 0.0001f, 0.0001f, 0)); + + MIN = XMVectorMax(MIN, XMVectorZero()); + MAX = XMVectorMin(MAX, RESOLUTION); + + XMUINT3 mini, maxi; + XMStoreUInt3(&mini, MIN); + XMStoreUInt3(&maxi, MAX); + + wi::primitive::AABB aabb_src; + XMStoreFloat3(&aabb_src._min, MIN); + XMStoreFloat3(&aabb_src._max, MAX); + +#ifdef DEBUG_VOXEL_OCCLUSION + // In debug mode we visualize all tests and don't return early + bool result = false; + debug_subject_coords.clear(); + debug_occluded_coords.clear(); + debug_visible_coords.clear(); + for (uint32_t x = mini.x; x < maxi.x; ++x) + { + for (uint32_t y = mini.y; y < maxi.y; ++y) + { + for (uint32_t z = mini.z; z < maxi.z; ++z) + { + XMUINT3 goal = XMUINT3(x, y, z); + if (is_visible(start, goal)) + { + result = true; + } + } + } + } + return result; +#else + for (uint32_t x = mini.x; x < maxi.x; ++x) + { + for (uint32_t y = mini.y; y < maxi.y; ++y) + { + for (uint32_t z = mini.z; z < maxi.z; ++z) + { + XMUINT3 goal = XMUINT3(x, y, z); + if (is_visible(start, goal)) + { + return true; + } + } + } + } + return false; +#endif // DEBUG_VOXEL_OCCLUSION + } + void VoxelGrid::add(const VoxelGrid& other) { if (voxels.size() != other.voxels.size()) @@ -500,6 +616,9 @@ namespace wi if (x != 0) numVoxels += (uint32_t)countbits(x); } +#ifdef DEBUG_VOXEL_OCCLUSION + numVoxels += uint32_t(debug_subject_coords.size() + debug_visible_coords.size() + debug_occluded_coords.size()); +#endif // DEBUG_VOXEL_OCCLUSION if (numVoxels == 0) return; @@ -588,12 +707,48 @@ namespace wi C += P; C = XMVectorSetW(C, 1); XMStoreFloat4(&v.position, C); + v.color = debug_color; } std::memcpy((uint8_t*)mem.data + dst_offset, verts, sizeof(verts)); dst_offset += sizeof(verts); } } +#ifdef DEBUG_VOXEL_OCCLUSION + auto dbg_voxel = [&](const XMUINT3& coord, const XMFLOAT4& color) { + XMFLOAT3 pos = coord_to_world(coord); + XMVECTOR P = XMLoadFloat3(&pos); + Vertex verts[arraysize(cubeVerts)]; + std::memcpy(verts, cubeVerts, sizeof(cubeVerts)); + for (auto& v : verts) + { + XMVECTOR C = XMLoadFloat4(&v.position); + C *= VOXELSIZE; + C += P; + C = XMVectorSetW(C, 1); + XMStoreFloat4(&v.position, C); + v.color = color; + } + std::memcpy((uint8_t*)mem.data + dst_offset, verts, sizeof(verts)); + dst_offset += sizeof(verts); + }; + for (auto& coord : debug_subject_coords) + { + dbg_voxel(coord, XMFLOAT4(1, 1, 1, 0.25f)); + } + debug_subject_coords.clear(); + for (auto& coord : debug_visible_coords) + { + dbg_voxel(coord, XMFLOAT4(1, 1, 0, 0.125f)); + } + debug_visible_coords.clear(); + for (auto& coord : debug_occluded_coords) + { + dbg_voxel(coord, XMFLOAT4(1, 0, 0, 0.5f)); + } + debug_occluded_coords.clear(); +#endif // DEBUG_VOXEL_OCCLUSION + device->EventBegin("VoxelGrid::debugdraw", cmd); device->BindPipelineState(&pso, cmd); @@ -610,7 +765,7 @@ namespace wi MiscCB sb; sb.g_xTransform = ViewProjection; - sb.g_xColor = debug_color; + sb.g_xColor = XMFLOAT4(1, 1, 1, 1); device->BindDynamicConstantBuffer(sb, CBSLOT_RENDERER_MISC, cmd); device->Draw(arraysize(cubeVerts) * numVoxels, 0, cmd); diff --git a/WickedEngine/wiVoxelGrid.h b/WickedEngine/wiVoxelGrid.h index 3884ab076b..cd378cc9ad 100644 --- a/WickedEngine/wiVoxelGrid.h +++ b/WickedEngine/wiVoxelGrid.h @@ -37,16 +37,19 @@ namespace wi void inject_capsule(const wi::primitive::Capsule& capsule, bool subtract = false); XMUINT3 world_to_coord(const XMFLOAT3& worldpos) const; XMFLOAT3 coord_to_world(const XMUINT3& coord) const; - bool check_voxel(XMUINT3 coord) const; + bool check_voxel(const XMUINT3& coord) const; bool check_voxel(const XMFLOAT3& worldpos) const; bool is_coord_valid(const XMUINT3& coord) const; - void set_voxel(XMUINT3 coord, bool value); + void set_voxel(const XMUINT3& coord, bool value); void set_voxel(const XMFLOAT3& worldpos, bool value); size_t get_memory_size() const; void set_voxelsize(float size); void set_voxelsize(const XMFLOAT3& size); wi::primitive::AABB get_aabb() const; void from_aabb(const wi::primitive::AABB& aabb); + bool is_visible(const XMUINT3& observer, const XMUINT3& subject) const; + bool is_visible(const XMFLOAT3& observer, const XMFLOAT3& subject) const; + bool is_visible(const XMFLOAT3& observer, const wi::primitive::AABB& subject) const; void add(const VoxelGrid& other); void subtract(const VoxelGrid& other); void debugdraw(const XMFLOAT4X4& ViewProjection, wi::graphics::CommandList cmd) const; @@ -70,6 +73,13 @@ namespace wi P += center; return P; } + +//#define DEBUG_VOXEL_OCCLUSION +#ifdef DEBUG_VOXEL_OCCLUSION + mutable wi::vector debug_subject_coords; + mutable wi::vector debug_visible_coords; + mutable wi::vector debug_occluded_coords; +#endif // DEBUG_VOXEL_OCCLUSION }; } diff --git a/WickedEngine/wiVoxelGrid_BindLua.cpp b/WickedEngine/wiVoxelGrid_BindLua.cpp index 0c4c4f6ef8..b6477ad065 100644 --- a/WickedEngine/wiVoxelGrid_BindLua.cpp +++ b/WickedEngine/wiVoxelGrid_BindLua.cpp @@ -27,6 +27,7 @@ namespace wi::lua lunamethod(VoxelGrid_BindLua, GetMemorySize), lunamethod(VoxelGrid_BindLua, Add), lunamethod(VoxelGrid_BindLua, Subtract), + lunamethod(VoxelGrid_BindLua, IsVisible), { NULL, NULL } }; Luna::PropertyType VoxelGrid_BindLua::properties[] = { @@ -395,6 +396,48 @@ namespace wi::lua voxelgrid->subtract(*other->voxelgrid); return 0; } + int VoxelGrid_BindLua::IsVisible(lua_State* L) + { + int argc = wi::lua::SGetArgCount(L); + if (argc < 2) + { + wi::lua::SError(L, "VoxelGrid::IsVisible(Vector observer, Vector subject) not enough arguments!"); + wi::lua::SError(L, "VoxelGrid::IsVisible(Vector observer, AABB subject) not enough arguments!"); + return 0; + } + Vector_BindLua* observer = Luna::lightcheck(L, 1); + if (observer == nullptr) + { + if (argc < 6) + { + wi::lua::SError(L, "VoxelGrid::IsVisible(int observer_x,observer_y,observer_z, subject_x,subject_y,subject_z) not enough arguments!"); + return 0; + } + int observer_x = wi::lua::SGetInt(L, 1); + int observer_y = wi::lua::SGetInt(L, 2); + int observer_z = wi::lua::SGetInt(L, 3); + int subject_x = wi::lua::SGetInt(L, 4); + int subject_y = wi::lua::SGetInt(L, 5); + int subject_z = wi::lua::SGetInt(L, 6); + wi::lua::SSetBool(L, voxelgrid->is_visible(XMUINT3(uint32_t(observer_x), uint32_t(observer_y), uint32_t(observer_z)), XMUINT3(uint32_t(subject_x), uint32_t(subject_y), uint32_t(subject_z)))); + return 1; + } + Vector_BindLua* subject_vec = Luna::lightcheck(L, 2); + if (subject_vec == nullptr) + { + primitive::AABB_BindLua* aabb = Luna::lightcheck(L, 2); + if (aabb == nullptr) + { + wi::lua::SError(L, "VoxelGrid::IsVisible(Vector observer, Vector subject) second argument is not a Vector!"); + wi::lua::SError(L, "VoxelGrid::IsVisible(Vector observer, AABB subject) second argument is not an AABB!"); + return 0; + } + wi::lua::SSetBool(L, voxelgrid->is_visible(observer->GetFloat3(), aabb->aabb)); + return 1; + } + wi::lua::SSetBool(L, voxelgrid->is_visible(observer->GetFloat3(), subject_vec->GetFloat3())); + return 1; + } void VoxelGrid_BindLua::Bind() { diff --git a/WickedEngine/wiVoxelGrid_BindLua.h b/WickedEngine/wiVoxelGrid_BindLua.h index 129bbc96ac..186eb2f7b6 100644 --- a/WickedEngine/wiVoxelGrid_BindLua.h +++ b/WickedEngine/wiVoxelGrid_BindLua.h @@ -44,6 +44,7 @@ namespace wi::lua int GetMemorySize(lua_State* L); int Add(lua_State* L); int Subtract(lua_State* L); + int IsVisible(lua_State* L); static void Bind(); };