Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

994 detect collisions for voxel vs voxel and voxel vs box #1282

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion core/include/cubos/core/geom/box.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ namespace cubos::core::geom
}

/// @brief Computes four corners of the box, one for each diagonal.
/// @param corners Array to store the three corners in.
/// @param corners Array to store the four corners in.
void corners4(glm::vec3 corners[4]) const
{
corners[0] = {halfSize.x, -halfSize.y, -halfSize.z};
Expand Down
1 change: 0 additions & 1 deletion core/src/geom/intersections.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,6 @@ bool cubos::core::geom::intersects(const Box& box1, const glm::mat4& localToWorl
}
}
}

return true;
}

Expand Down
1 change: 1 addition & 0 deletions engine/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ set(CUBOS_ENGINE_SOURCE
"src/collisions/interface/shapes/box.cpp"
"src/collisions/interface/raycast.cpp"
"src/collisions/interface/shapes/capsule.cpp"
"src/collisions/interface/shapes/voxel.cpp"
"src/collisions/broad_phase/plugin.cpp"
"src/collisions/broad_phase/sweep_and_prune.cpp"
"src/collisions/broad_phase/potentially_colliding_with.cpp"
Expand Down
97 changes: 97 additions & 0 deletions engine/include/cubos/engine/collisions/shapes/voxel.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/// @file
/// @brief Component @ref cubos::engine::VoxelCollisionShape.
/// @ingroup collisions-plugin

#pragma once

#include <glm/glm.hpp>

#include <cubos/core/geom/box.hpp>
#include <cubos/core/log.hpp>
#include <cubos/core/reflection/external/glm.hpp>
#include <cubos/core/reflection/reflect.hpp>

#include <cubos/engine/assets/asset.hpp>
#include <cubos/engine/voxels/grid.hpp>

namespace cubos::engine
{
/// @brief Component which adds a collision shape corresponding to a given voxel grid to an entity, used with a @ref
/// Collider component.
/// @ingroup collisions-plugin
class VoxelCollisionShape
joaomanita marked this conversation as resolved.
Show resolved Hide resolved
{

joaomanita marked this conversation as resolved.
Show resolved Hide resolved
public:
CUBOS_REFLECT;

/// @brief Struct which holds a sub-box of the voxel collision shape, and its shift from the center of the
/// shape.
/// @ingroup collisions-plugin
struct BoxShiftPair
{
cubos::core::geom::Box box;
glm::vec3 shift;
};

/// @brief Entities voxel grid.
Asset<VoxelGrid> grid;

/// @brief Constructs voxel shape with no grid.
VoxelCollisionShape() = default;

/// @brief Constructs voxel shape with voxel grid.
/// @param grid VoxelGrid given in constructor.
VoxelCollisionShape(Asset<VoxelGrid> grid)
{
setGrid(grid);
}

/// @brief Default destructor.
~VoxelCollisionShape() = default;

/// @brief Move constructor.
/// @param other VoxelCollisionShape to move.
VoxelCollisionShape(VoxelCollisionShape&& other) noexcept
{
this->grid = std::move(other.grid);
this->mBoxes = std::move(other.mBoxes);
}

/// @brief Copy constructor.
/// @param shape VoxelCollisionSHape to copy.
VoxelCollisionShape(const VoxelCollisionShape& shape)
{
this->grid = shape.grid;
this->mBoxes = shape.mBoxes;
}

/// @brief Sets the grid.
/// @param grid to set.
void setGrid(Asset<VoxelGrid>& grid)
{
this->grid = grid;
}

/// @brief Inserts a new @ref BoxShiftPair to the list of the class.
/// @param box Box to insert.
/// @param shift Shift vector of the box.
void insertBox(const cubos::core::geom::Box& box, const glm::vec3& shift)
{
BoxShiftPair pair;
pair.box = box;
pair.shift = shift;
this->mBoxes.push_back(pair);
}

/// @brief Getter for the list of @ref BoxShiftPair of the class.
std::vector<BoxShiftPair> getBoxes() const
{
return this->mBoxes;
}

private:
/// @brief List of pairs composing the shape.
std::vector<BoxShiftPair> mBoxes; ///< List of boxes.
};
} // namespace cubos::engine
1 change: 1 addition & 0 deletions engine/samples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ make_sample(DIR "render/main" ASSETS)
make_sample(DIR "render/shadows" ASSETS)
make_sample(DIR "imgui")
make_sample(DIR "collisions" ASSETS)
make_sample(DIR "voxel-shape-collisions" ASSETS)
make_sample(DIR "scene" ASSETS)
make_sample(DIR "voxels" ASSETS)
make_sample(DIR "gizmos")
Expand Down
Binary file not shown.
3 changes: 3 additions & 0 deletions engine/samples/voxel-shape-collisions/assets/car.grd.meta
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"id": "059c16e7-a439-44c7-9bdc-6e069dba0c75"
}
Binary file not shown.
3 changes: 3 additions & 0 deletions engine/samples/voxel-shape-collisions/assets/main.pal.meta
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"id": "1aa5e234-28cb-4386-99b4-39386b0fc215"
}
169 changes: 169 additions & 0 deletions engine/samples/voxel-shape-collisions/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
#include <glm/gtc/random.hpp>

#include <cubos/core/geom/box.hpp>
#include <cubos/core/log.hpp>

#include <cubos/engine/assets/plugin.hpp>
#include <cubos/engine/collisions/collider.hpp>
#include <cubos/engine/collisions/colliding_with.hpp>
#include <cubos/engine/collisions/plugin.hpp>
#include <cubos/engine/collisions/shapes/box.hpp>
#include <cubos/engine/collisions/shapes/capsule.hpp>
#include <cubos/engine/collisions/shapes/voxel.hpp>
#include <cubos/engine/defaults/plugin.hpp>
#include <cubos/engine/fixed_step/plugin.hpp>
#include <cubos/engine/gizmos/plugin.hpp>
#include <cubos/engine/gizmos/target.hpp>
#include <cubos/engine/physics/plugin.hpp>
#include <cubos/engine/physics/solver/plugin.hpp>
#include <cubos/engine/render/camera/camera.hpp>
#include <cubos/engine/render/camera/draws_to.hpp>
#include <cubos/engine/render/camera/perspective.hpp>
#include <cubos/engine/render/defaults/plugin.hpp>
#include <cubos/engine/render/defaults/target.hpp>
#include <cubos/engine/render/picker/plugin.hpp>
#include <cubos/engine/render/tone_mapping/plugin.hpp>
#include <cubos/engine/render/voxels/grid.hpp>
#include <cubos/engine/render/voxels/palette.hpp>
#include <cubos/engine/settings/plugin.hpp>
#include <cubos/engine/settings/settings.hpp>
#include <cubos/engine/transform/plugin.hpp>
#include <cubos/engine/voxels/plugin.hpp>
#include <cubos/engine/window/plugin.hpp>

using cubos::core::geom::Box;
using cubos::core::io::Key;
using cubos::core::io::Modifiers;
using cubos::core::io::MouseButton;

using namespace cubos::engine;

static CUBOS_DEFINE_TAG(collisionsSampleUpdated);

struct State
{
CUBOS_ANONYMOUS_REFLECT(State);

bool collided = false;

Entity a;
Entity b;

glm::vec3 aRotationAxis;
glm::vec3 bRotationAxis;
};

/// [Get handles to assets]
static const Asset<VoxelGrid> CarAsset = AnyAsset("059c16e7-a439-44c7-9bdc-6e069dba0c75");
static const Asset<VoxelPalette> PaletteAsset = AnyAsset("1aa5e234-28cb-4386-99b4-39386b0fc215");
/// [Get handles to assets]

int main()
{
auto cubos = Cubos();

cubos.plugin(defaultsPlugin);
cubos.tag(gizmosDrawTag).after(toneMappingTag);

cubos.resource<State>();

cubos.startupSystem("setup camera").call([](Commands commands) {
auto targetEnt = commands.create().add(RenderTargetDefaults{}).add(GizmosTarget{}).entity();
commands.create()
.relatedTo(targetEnt, DrawsTo{})
.add(Camera{.zNear = 0.1F, .zFar = 100.0F})
joaomanita marked this conversation as resolved.
Show resolved Hide resolved
.add(PerspectiveCamera{.fovY = 60.0F})
.add(LocalToWorld{})
.add(Position{{-35.0F, 1.5F, 0.0F}})
.add(Rotation::lookingAt({3.0F, -1.0F, 0.0F}, glm::vec3{0.0F, 1.0F, 0.0F}));
});

cubos.startupSystem("configure Assets").tagged(settingsTag).call([](Settings& settings) {
settings.setString("assets.io.path", SAMPLE_ASSETS_FOLDER);
});

/// [Set palette]
cubos.startupSystem("set palette").call([](RenderPalette& palette) { palette.asset = PaletteAsset; });
/// [Set palette]

cubos.startupSystem("create colliders").tagged(assetsTag).call([](State& state, Commands commands, Assets& assets) {
auto car = assets.read(CarAsset);
glm::vec3 offset = glm::vec3(car->size().x, car->size().y, car->size().z) / -2.0F;
state.a = commands.create()
.add(Collider{})
.add(RenderVoxelGrid{CarAsset, offset})
.add(VoxelCollisionShape(CarAsset))
.add(LocalToWorld{})
.add(Position{glm::vec3{0.0F, 0.0F, -30.0F}})
.add(Rotation{})
.add(PhysicsBundle{.mass = 500.0F, .velocity = {0.0F, 0.0F, 1.0F}})
.entity();
state.aRotationAxis = glm::sphericalRand(1.0F);

state.b = commands.create()
.add(Collider{})
.add(RenderVoxelGrid{CarAsset, offset})
.add(VoxelCollisionShape(CarAsset))
.add(LocalToWorld{})
.add(Position{glm::vec3{0.0F, 0.0F, 10.0F}})
.add(Rotation{})
.add(PhysicsBundle{.mass = 500.0F, .velocity = {0.0F, 0.0F, -1.0F}})
.entity();
state.bRotationAxis = glm::sphericalRand(1.0F);
});

cubos.system("move colliders")
.before(transformUpdateTag)
.call([](State& state, Query<Position&, Rotation&, Velocity&> query) {
auto [aPos, aRot, aVel] = *query.at(state.a);
auto [bPos, bRot, bVel] = *query.at(state.b);

aRot.quat = glm::rotate(aRot.quat, 0.001F, state.aRotationAxis);
aVel.vec += glm::vec3{0.0F, 0.0F, 0.01F};

bRot.quat = glm::rotate(bRot.quat, 0.001F, state.bRotationAxis);
bVel.vec -= glm::vec3{0.0F, 0.0F, 0.01F};
});

cubos.tag(collisionsSampleUpdated);

cubos.system("render voxel")
.after(collisionsSampleUpdated)
.call([](Gizmos& gizmos, Query<const LocalToWorld&, const Collider&, const VoxelCollisionShape&> query) {
for (auto [localToWorld, collider, shape] : query)
{
for (const auto box : shape.getBoxes())
{
// Get the current position from the localToWorld matrix
glm::mat4 pos = localToWorld.mat; // Store the matrix

// Create a translation matrix for the shift
glm::mat4 shiftMatrix = glm::translate(glm::mat4(1.0F), -box.shift);

// Combine the matrices (note: order matters)
pos = pos * shiftMatrix;
auto size = box.box.halfSize * 2.0F;
glm::mat4 transform = glm::scale(pos * collider.transform, size);
gizmos.drawWireBox("subboxes", transform);
}
}
});

cubos.system("render")
.after(collisionsSampleUpdated)
.call([](Gizmos& gizmos, Query<const LocalToWorld&, const Collider&> query) {
for (auto [localToWorld, collider] : query)
{
auto size = collider.localAABB.box().halfSize * 2.0F;
glm::mat4 transform = glm::scale(localToWorld.mat * collider.transform, size);
gizmos.color({1.0F, 1.0F, 1.0F});
gizmos.drawWireBox("local AABB", transform);

gizmos.color({1.0F, 0.0F, 0.0F});
gizmos.drawWireBox("world AABB", collider.worldAABB.min(), collider.worldAABB.max());
}
});

cubos.run();
return 0;
}
2 changes: 2 additions & 0 deletions engine/src/collisions/interface/plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@
#include <cubos/engine/collisions/contact_manifold.hpp>
#include <cubos/engine/collisions/shapes/box.hpp>
#include <cubos/engine/collisions/shapes/capsule.hpp>
#include <cubos/engine/collisions/shapes/voxel.hpp>

void cubos::engine::interfaceCollisionsPlugin(Cubos& cubos)
{
cubos.component<Collider>();
cubos.component<BoxCollisionShape>();
cubos.component<CapsuleCollisionShape>();
cubos.component<VoxelCollisionShape>();

cubos.relation<CollidingWith>();
cubos.relation<ContactManifold>();
Expand Down
10 changes: 10 additions & 0 deletions engine/src/collisions/interface/shapes/voxel.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#include <cubos/core/ecs/reflection.hpp>

#include <cubos/engine/collisions/shapes/voxel.hpp>

CUBOS_REFLECT_IMPL(cubos::engine::VoxelCollisionShape)
{
return core::ecs::TypeBuilder<VoxelCollisionShape>("cubos::engine::VoxelCollisionShape")
.withField("grid", &VoxelCollisionShape::grid)
.build();
}
Loading
Loading