Skip to content

Commit

Permalink
capsule voxelization
Browse files Browse the repository at this point in the history
  • Loading branch information
turanszkij committed Feb 24, 2024
1 parent c3f3bad commit e22ce3e
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 3 deletions.
1 change: 1 addition & 0 deletions Content/Documentation/ScriptingAPI-Documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -1745,6 +1745,7 @@ Tracks a physics pick drag operation. Use it with `phyiscs.PickDrag()` function.
- InjectTriangle(Vector a,b,c, opt bool subtract = false) -- voxelizes triangle, and either adds it to the voxels (default), or removes voxels
- InjectAABB(AABB aabb, opt bool subtract = false) -- voxelizes axis aligned bounding box, and either adds it to the voxels (default), or removes voxels
- InjectSphere(Sphere sphere, opt bool subtract = false) -- voxelizes sphere, and either adds it to the voxels (default), or removes voxels
- InjectCapsule(Capsule capsule, opt bool subtract = false) -- voxelizes capsule, and either adds it to the voxels (default), or removes voxels
- WorldToCoord(Vector pos) : int x,y,z -- converts a position in world space to voxel coordinate
- CoordToWorld(int x,y,z) : Vector -- converts voxel coordinate to world space position
- CheckVoxel(Vector pos) : bool -- returns false if voxel is empty, true if it's valid
Expand Down
1 change: 1 addition & 0 deletions Content/scripts/pathfinding.lua
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ voxelgrid.InjectAABB(AABB(Vector(4, 0, 0.8), Vector(8, voxelsize.GetY() * 2, 5))
voxelgrid.InjectAABB(AABB(Vector(4, 0, 3), Vector(8, voxelsize.GetY() * 3.5, 7)))
voxelgrid.InjectAABB(AABB(Vector(4, 0, 6), Vector(8, voxelsize.GetY() * 4.5, 7)))
voxelgrid.InjectSphere(Sphere(Vector(-4.8,1.6,-2.5), 1.6))
voxelgrid.InjectCapsule(Capsule(Vector(4.8,-0.6,-2.5), Vector(2, 1, 1), 0.4))

-- If teapot model can be loaded, then load it and voxelize it too:
local scene = Scene()
Expand Down
6 changes: 3 additions & 3 deletions WickedEngine/wiScene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5843,10 +5843,10 @@ namespace wi::scene
break;
case ColliderComponent::Shape::Capsule:
{
AABB aabb = collider.capsule.getAABB();
Capsule capsule = collider.capsule;
// TODO: fix heap allocating lambda capture!
wi::jobsystem::Execute(ctx, [&voxelgrid, subtract, aabb](wi::jobsystem::JobArgs args) {
voxelgrid.inject_aabb(aabb, subtract);
wi::jobsystem::Execute(ctx, [&voxelgrid, subtract, capsule](wi::jobsystem::JobArgs args) {
voxelgrid.inject_capsule(capsule, subtract);
});
}
break;
Expand Down
70 changes: 70 additions & 0 deletions WickedEngine/wiVoxelGrid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,76 @@ namespace wi
}
}
}
void VoxelGrid::inject_capsule(const wi::primitive::Capsule& capsule, bool subtract)
{
const XMVECTOR CENTER = XMLoadFloat3(&center);
const XMVECTOR RESOLUTION = XMLoadUInt3(&resolution);
const XMVECTOR RESOLUTION_RCP = XMLoadFloat3(&resolution_rcp);
const XMVECTOR VOXELSIZE_RCP = XMLoadFloat3(&voxelSize_rcp);

AABB aabb = capsule.getAABB();

XMVECTOR _MIN = XMLoadFloat3(&aabb._min);
XMVECTOR _MAX = XMLoadFloat3(&aabb._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.5f, 0.5f, 0.5f, 0));

MIN = XMVectorMax(MIN, XMVectorZero());
MAX = XMVectorMin(MAX, RESOLUTION);

XMUINT3 mini, maxi;
XMStoreUInt3(&mini, MIN);
XMStoreUInt3(&maxi, MAX);

volatile long long* data = (volatile long long*)voxels.data();
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)
{
wi::primitive::AABB voxel_aabb;
XMUINT3 voxel_center_coord = XMUINT3(x, y, z);
XMFLOAT3 voxel_center_world = coord_to_world(voxel_center_coord);
voxel_aabb.createFromHalfWidth(voxel_center_world, voxelSize);
for (int c = 0; c < 8; ++c)
{
// This capsule-box test can fail if capsule doesn't contain any of the corners,
// but it intersects with the cube. But for now this simple method is used.
if (capsule.intersects(voxel_aabb.corner(c)))
{
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);
}
}
}
}
}
}
}

XMUINT3 VoxelGrid::world_to_coord(const XMFLOAT3& worldpos) const
{
Expand Down
1 change: 1 addition & 0 deletions WickedEngine/wiVoxelGrid.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ namespace wi
void inject_triangle(XMVECTOR A, XMVECTOR B, XMVECTOR C, bool subtract = false);
void inject_aabb(const wi::primitive::AABB& aabb, bool subtract = false);
void inject_sphere(const wi::primitive::Sphere& sphere, bool subtract = false);
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;
Expand Down
23 changes: 23 additions & 0 deletions WickedEngine/wiVoxelGrid_BindLua.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ namespace wi::lua
lunamethod(VoxelGrid_BindLua, InjectTriangle),
lunamethod(VoxelGrid_BindLua, InjectAABB),
lunamethod(VoxelGrid_BindLua, InjectSphere),
lunamethod(VoxelGrid_BindLua, InjectCapsule),
lunamethod(VoxelGrid_BindLua, WorldToCoord),
lunamethod(VoxelGrid_BindLua, CoordToWorld),
lunamethod(VoxelGrid_BindLua, CheckVoxel),
Expand Down Expand Up @@ -156,6 +157,28 @@ namespace wi::lua
voxelgrid->inject_sphere(sphere->sphere, subtract);
return 0;
}
int VoxelGrid_BindLua::InjectCapsule(lua_State* L)
{
int argc = wi::lua::SGetArgCount(L);
if (argc < 1)
{
wi::lua::SError(L, "VoxelGrid::InjectCapsule(Capsule capsule, opt bool subtract = false) not enough arguments!");
return 0;
}
primitive::Capsule_BindLua* capsule = Luna<primitive::Capsule_BindLua>::lightcheck(L, 1);
if (capsule == nullptr)
{
wi::lua::SError(L, "VoxelGrid::InjectCapsule(Capsule capsule, opt bool subtract = false) first argument is not a Vector!");
return 0;
}
bool subtract = false;
if (argc > 1)
{
subtract = wi::lua::SGetBool(L, 2);
}
voxelgrid->inject_capsule(capsule->capsule, subtract);
return 0;
}
int VoxelGrid_BindLua::WorldToCoord(lua_State* L)
{
int argc = wi::lua::SGetArgCount(L);
Expand Down
1 change: 1 addition & 0 deletions WickedEngine/wiVoxelGrid_BindLua.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ namespace wi::lua
int InjectTriangle(lua_State* L);
int InjectAABB(lua_State* L);
int InjectSphere(lua_State* L);
int InjectCapsule(lua_State* L);
int WorldToCoord(lua_State* L);
int CoordToWorld(lua_State* L);
int CheckVoxel(lua_State* L);
Expand Down

0 comments on commit e22ce3e

Please sign in to comment.