PRetty good collision detection but there is still some small bug I don't know about

This commit is contained in:
2023-02-24 23:37:27 -08:00
parent d5fdc29cb4
commit b32c7e8af6
15 changed files with 124 additions and 43 deletions

View File

@ -40,10 +40,13 @@ void Transform::updateLocalTransformFromLocalValues() {
}
void Transform::updateWorldTransformFromLocalTransform() {
glm::mat4 newWorld(1.0f);
auto parent = this->getParent();
if(parent != nullptr) newWorld = parent->getWorldTransform();
this->transformWorld = newWorld * transformLocal;
if(parent != nullptr) {
auto newWorld = parent->getWorldTransform();
this->transformWorld = newWorld * transformLocal;
} else {
this->transformWorld = transformLocal;
}
}
void Transform::updateLocalTransformFromWorldTransform() {
@ -128,7 +131,7 @@ void Transform::setLocalTransform(glm::mat4 transform) {
}
glm::vec3 Transform::getWorldPosition() {
return glm::vec3(this->transformWorld[3]);
return glm::inverse(this->transformWorld)[3];
}
glm::mat4 Transform::getWorldTransform() {

View File

@ -5,13 +5,32 @@
#include "ScenePhysicsManager.hpp"
#include "scene/Scene.hpp"
#include "scene/components/physics/3d/Collider3D.hpp"
using namespace Dawn;
ScenePhysicsManager::ScenePhysicsManager() {
ScenePhysicsManager::ScenePhysicsManager(Scene *scene) {
this->scene = scene;
}
void ScenePhysicsManager::update() {
}
std::vector<struct Collider3DRayResult> ScenePhysicsManager::raycast3DAll(
struct Ray3D ray
) {
// TODO: Optimize the crap out of this.
struct Collider3DRayResult result;
auto colliders = scene->findComponents<Collider3D>();
std::vector<struct Collider3DRayResult> results;
auto itCollider = colliders.begin();
while(itCollider != colliders.end()) {
if((*itCollider)->raycast(&result, ray)) {
results.push_back(result);
}
++itCollider;
}
return results;
}

View File

@ -5,7 +5,7 @@
#pragma once
#include "dawnlibs.hpp"
#include "scene/SceneItem.hpp"
#include "physics/3d/Ray3D.hpp"
typedef int64_t scenechunk_t;
@ -13,17 +13,22 @@ typedef int64_t scenechunk_t;
namespace Dawn {
class Scene;
class Collider3D;
struct Collider3DRayResult;
class ScenePhysicsManager {
protected:
std::map<scenechunk_t, std::vector<SceneItem*>> chunkItems;
std::map<SceneItem*, std::vector<scenechunk_t>> itemChunks;
Scene *scene;
// std::map<scenechunk_t, std::vector<SceneItem*>> chunkItems;
// std::map<SceneItem*, std::vector<scenechunk_t>> itemChunks;
public:
ScenePhysicsManager();
ScenePhysicsManager(Scene *scene);
void update();
std::vector<struct Collider3DRayResult> raycast3DAll(struct Ray3D ray);
friend class Scene;
};
}

View File

@ -12,9 +12,9 @@ using namespace Dawn;
Scene::Scene(DawnGame *game) {
assertNotNull(game);
this->game = game;
this->nextId = 0;
this->physics = new ScenePhysicsManager(this);
}
void Scene::update() {
@ -30,6 +30,7 @@ void Scene::update() {
#if DAWN_DEBUG_BUILD
this->debugGrid();
this->debugOrigin();
this->debugHitboxes();
#endif
// TODO: Cleanup old scene items
@ -44,6 +45,8 @@ SceneItem * Scene::createSceneItem() {
}
Scene::~Scene() {
delete this->physics;
// Early cleanup without disposing.
auto it = this->items.begin();
while(it != this->items.end()) {

View File

@ -7,6 +7,7 @@
#include "event/Event.hpp"
#include "asset/Asset.hpp"
#include "scene/debug/SceneDebugLine.hpp"
#include "physics/ScenePhysicsManager.hpp"
namespace Dawn {
class DawnGame;
@ -27,6 +28,7 @@ namespace Dawn {
public:
DawnGame *game;
ScenePhysicsManager *physics;
Event<> eventSceneUpdate;
Event<> eventSceneUnpausedUpdate;
@ -139,6 +141,7 @@ namespace Dawn {
void debugCube(struct SceneDebugCube cube);
void debugOrigin();
void debugGrid();
void debugHitboxes();
#endif
/**

View File

@ -33,6 +33,10 @@ DawnGame * SceneItemComponent::getGame() {
return this->item->scene->game;
}
ScenePhysicsManager * SceneItemComponent::getPhysics() {
return this->item->scene->physics;
}
void SceneItemComponent::onStart() {
}

View File

@ -52,6 +52,13 @@ namespace Dawn {
*/
DawnGame * getGame();
/**
* Shorthand to return the physics manager that the scene this item
* belongs to, belongs to.
* @return The scene physics manager.
*/
ScenePhysicsManager * getPhysics();
/**
* Same as init, but intended for your subclass to override.
*/

View File

@ -9,4 +9,14 @@ using namespace Dawn;
Collider3D::Collider3D(SceneItem *item) : SceneItemComponent(item) {
}
}
bool_t Collider3D::raycast(
struct Collider3DRayResult *result,
struct Ray3D ray
) {
assertNotNull(result);
if(!this->performRaycast(result, ray)) return false;
result->collider = this;
return true;
}

View File

@ -12,6 +12,7 @@ namespace Dawn {
glm::vec3 point;
float_t distance;
glm::vec3 normal;
Collider3D *collider;
};
enum Collider3DType {
@ -20,6 +21,14 @@ namespace Dawn {
class Collider3D : public SceneItemComponent {
protected:
/**
* Internal per-collider raycast implementation. Same arguments as
* Collider3D::raycast()
*/
virtual bool_t performRaycast(
struct Collider3DRayResult *result,
struct Ray3D ray
) = 0;
public:
Collider3D(SceneItem *item);
@ -31,10 +40,7 @@ namespace Dawn {
* @param ray The ray to cast against.
* @return True if the ray intercepts this collider, otherwise false.
*/
virtual bool_t raycast(
struct Collider3DRayResult *result,
struct Ray3D ray
) = 0;
bool_t raycast(struct Collider3DRayResult *result, struct Ray3D ray);
/**
* Returns which type of collider this is. Useful for performing dynamic

View File

@ -11,7 +11,7 @@ CubeCollider::CubeCollider(SceneItem *item) : Collider3D(item) {
}
bool_t CubeCollider::raycast(
bool_t CubeCollider::performRaycast(
struct Collider3DRayResult *result,
struct Ray3D ray
) {

View File

@ -9,17 +9,18 @@
namespace Dawn {
class CubeCollider : public Collider3D {
protected:
bool_t performRaycast(
struct Collider3DRayResult *result,
struct Ray3D ray
) override;
public:
glm::vec3 min = glm::vec3(-0.5f, -0.5f, -0.5f);
glm::vec3 max = glm::vec3(0.5f, 0.5f, 0.5f);
CubeCollider(SceneItem *item);
bool_t raycast(
struct Collider3DRayResult *result,
struct Ray3D ray
) override;
enum Collider3DType getColliderType() override;
};
}

View File

@ -7,6 +7,8 @@
#include "display/shader/SimpleTexturedShader.hpp"
#include "scene/components/display/Camera.hpp"
#include "scene/Scene.hpp"
#include "scene/components/physics/3d/Collider3D.hpp"
#include "scene/components/physics/3d/CubeCollider.hpp"
using namespace Dawn;
@ -140,4 +142,24 @@ void Scene::debugGrid() {
line.v0 = glm::vec3(-s, 0, z), line.v1 = glm::vec3(s, 0, z);
this->debugLine(line);
}
}
void Scene::debugHitboxes() {
auto colliders = this->findComponents<Collider3D>();
auto itColliders = colliders.begin();
while(itColliders != colliders.end()) {
auto c = *itColliders;
switch(c->getColliderType()) {
case COLLIDER3D_TYPE_CUBE:
auto asCube = dynamic_cast<CubeCollider*>(c);
this->debugCube((struct SceneDebugCube){
.min = asCube->min,
.max = asCube->max,
.color = COLOR_BLUE,
.transform = asCube->transform->getWorldTransform()
});
break;
}
++itColliders;
}
}

View File

@ -28,18 +28,19 @@ void TicTacToeGame::onSceneUpdate() {
if(camera == nullptr) return;
struct Ray3D ray;
ray.origin = glm::vec3(1,2,3);
ray.origin = camera->transform->getWorldPosition();
ray.direction = camera->getRayDirectionFromScreenSpace(mouse);
std::cout << "World " << ray.origin.x << ", " << ray.origin.y << ", " << ray.origin.z << std::endl;
auto collider = getScene()->findComponent<CubeCollider>();
if(collider == nullptr) return;
struct Collider3DRayResult result;
auto test = collider->raycast(&result, ray);
if(test) {
getScene()->debugRay((struct SceneDebugRay){ .start = result.point, .direction = result.normal, .color = COLOR_BLUE });
} else {
getScene()->debugRay((struct SceneDebugRay){ .start = ray.origin, .direction = ray.direction });
auto results = getPhysics()->raycast3DAll(ray);
auto itResult = results.begin();
while(itResult != results.end()) {
auto result = *itResult;
getScene()->debugRay((struct SceneDebugRay){
.start = result.point,
.direction = result.normal,
.color = COLOR_BLUE
});
++itResult;
}
}

View File

@ -9,7 +9,7 @@
#include "scene/components/display/MeshHost.hpp"
#include "scene/components/display/MeshRenderer.hpp"
#include "scene/components/display/material/SimpleTexturedMaterial.hpp"
#include "scene/components/physics/2d/BoxCollider.hpp"
#include "scene/components/physics/3d/CubeCollider.hpp"
#include "components/TicTacToeTile.hpp"
namespace Dawn {
@ -28,7 +28,7 @@ namespace Dawn {
MeshRenderer *meshRenderer;
SimpleTexturedMaterial *material;
TicTacToeTile *ticTacToe;
BoxCollider *boxCollider;
CubeCollider *collider;
TicTacToeTilePrefab(Scene *s, sceneitemid_t i) :
SceneItemPrefab<TicTacToeTilePrefab>(s,i)
@ -52,9 +52,9 @@ namespace Dawn {
sprite->setSize(glm::vec2(1, 1));
sprite->setTile(0x01);
boxCollider = this->addComponent<BoxCollider>();
boxCollider->min = glm::vec2();
boxCollider->max = glm::vec2(1, 1);
collider = this->addComponent<CubeCollider>();
collider->min = glm::vec3(-0.5f, -0.5f, -0.1f);
collider->max = glm::vec3( 0.5f, 0.5f, 0.1f);
ticTacToe = this->addComponent<TicTacToeTile>();
}

View File

@ -19,7 +19,8 @@ namespace Dawn {
camera = Camera::create(this);
// camera->transform->lookAt(glm::vec3(0, 0, 5), glm::vec3(0, 0, 0));
// camera->type = CAMERA_TYPE_ORTHONOGRAPHIC;
camera->transform->lookAt(glm::vec3(1, 2, 3), glm::vec3(0, 0, 0));
// camera->transform->lookAt(glm::vec3(1, 2, 3), glm::vec3(0, 0, 0));
camera->transform->lookAt(glm::vec3(0, 0, 3), glm::vec3(0, 0, 0));
float_t s = 2.0f;
camera->orthoTop = s;
@ -29,10 +30,6 @@ namespace Dawn {
camera->orthoLeft = -s * ratio;
camera->orthoRight = s * ratio;
auto cube = SimpleSpinningCubePrefab::create(this);
// TriangleMesh::createTriangleMesh(&cube->meshHost->mesh);
// SphereMesh::createSphere(&cube->meshHost->mesh, 1.0f, 16, 16);
auto gameItem = this->createSceneItem();
auto game = gameItem->addComponent<TicTacToeGame>();