Skip to content

Commit

Permalink
Merge branch '1330-add-active-component-for-all-kinds-of-disabling-pu…
Browse files Browse the repository at this point in the history
…rposes' of https://github.com/GameDevTecnico/cubos into 1330-add-active-component-for-all-kinds-of-disabling-purposes
  • Loading branch information
RodrigoVintem committed Nov 12, 2024
2 parents 48b1308 + c7cce47 commit 6a10308
Show file tree
Hide file tree
Showing 19 changed files with 826 additions and 64 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- Collision detection with VoxelCollisionShapes (#994, **@joaomanita**).

### Added

- Allow identifying assets in code from their path (#1177. **@GalaxyCrush**).
- Added an Audio asset (#230, **@Dageus**, **@diogomsmiranda**).

Expand Down
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 @@ -76,6 +76,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
95 changes: 95 additions & 0 deletions engine/include/cubos/engine/collisions/shapes/voxel.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/// @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/reflection/reflect.hpp>

#include <cubos/engine/api.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 CUBOS_ENGINE_API VoxelCollisionShape
{
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"
}
219 changes: 219 additions & 0 deletions engine/samples/voxel-shape-collisions/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
#include <glm/gtc/random.hpp>

#include <cubos/core/geom/box.hpp>
#include <cubos/core/tel/logging.hpp>

#include <cubos/engine/assets/plugin.hpp>
#include <cubos/engine/collisions/collider.hpp>
#include <cubos/engine/collisions/colliding_with.hpp>
#include <cubos/engine/collisions/contact_manifold.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 DebugDraw
{
CUBOS_ANONYMOUS_REFLECT(DebugDraw);

bool normal = true;
bool points = true;
bool manifoldPolygon = true;
};

struct State
{
CUBOS_ANONYMOUS_REFLECT(State);

bool collided = false;

Entity a;
Entity b;

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

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

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

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

cubos.resource<State>();
cubos.resource<DebugDraw>();

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})
.add(PerspectiveCamera{.fovY = 60.0F})
.add(LocalToWorld{})
.add(Position{{-50.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);
});

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

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.system("render collision manifolds")
.after(collisionsTag)
.after(gizmosDrawTag)
.call([](Gizmos& gizmos, const DebugDraw& draw,
Query<Entity, const Position&, const ContactManifold&, Entity, const Position&> query) {
for (auto [ent1, pos1, manifold, ent2, pos2] : query)
{

if (draw.normal)
{
glm::vec3 origin = ent1 == manifold.entity ? pos1.vec : pos2.vec;
gizmos.color({0.0F, 1.0F, 0.0F});
gizmos.drawArrow("arrow", origin, manifold.normal, 0.1F, 0.5F, 0.7F, 0.05F, Gizmos::Space::World);
}

if (draw.manifoldPolygon && manifold.points.size() > 1)
{
cubos::engine::ContactPointData start = manifold.points.back();
for (const cubos::engine::ContactPointData& end : manifold.points)
{
gizmos.color({1.0F, 1.0F, 0.0F});
gizmos.drawArrow("line", start.globalOn1, end.globalOn1 - start.globalOn1, 1.0F, 1.2F, 1.0F,
0.05F, Gizmos::Space::World);
start = end;
}
}

if (draw.points)
{
for (auto point : manifold.points)
{
gizmos.color({0.0F, 0.0F, 1.0F});
gizmos.drawArrow("point", point.globalOn1, glm::vec3(0.02F, 0.02F, 0.02F), 1.0F, 1.0F, 1.0F,
0.05F, Gizmos::Space::World);

gizmos.color({1.0F, 0.0F, 1.0F});
gizmos.drawArrow("point", point.globalOn2, glm::vec3(0.02F, 0.02F, 0.02F), 1.0F, 1.0F, 1.0F,
0.05F, Gizmos::Space::World);
}
}
}
});

cubos.run();
return 0;
}
4 changes: 2 additions & 2 deletions engine/src/assets/asset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ AnyAsset::AnyAsset(const AnyAsset& other)
}

AnyAsset::AnyAsset(AnyAsset&& other) noexcept
: pathOrId(other.pathOrId)
: pathOrId(std::move(other.pathOrId))
, mId(other.mId)
, mRefCount(other.mRefCount)
, mVersion(other.mVersion)
Expand Down Expand Up @@ -95,7 +95,7 @@ AnyAsset& AnyAsset::operator=(AnyAsset&& other) noexcept
}

this->decRef();
pathOrId = other.pathOrId;
pathOrId = std::move(other.pathOrId);
mId = other.mId;
mRefCount = other.mRefCount;
mVersion = other.mVersion;
Expand Down
Loading

0 comments on commit 6a10308

Please sign in to comment.