PRetty good collision detection but there is still some small bug I don't know about
This commit is contained in:
		| @@ -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() { | ||||
|   | ||||
| @@ -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; | ||||
| } | ||||
| @@ -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; | ||||
|   }; | ||||
| } | ||||
| @@ -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()) { | ||||
|   | ||||
| @@ -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 | ||||
|  | ||||
|       /** | ||||
|   | ||||
| @@ -33,6 +33,10 @@ DawnGame * SceneItemComponent::getGame() { | ||||
|   return this->item->scene->game; | ||||
| } | ||||
|  | ||||
| ScenePhysicsManager * SceneItemComponent::getPhysics() { | ||||
|   return this->item->scene->physics; | ||||
| } | ||||
|  | ||||
| void SceneItemComponent::onStart() { | ||||
|    | ||||
| } | ||||
|   | ||||
| @@ -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. | ||||
|        */ | ||||
|   | ||||
| @@ -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; | ||||
| } | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -11,7 +11,7 @@ CubeCollider::CubeCollider(SceneItem *item) : Collider3D(item) { | ||||
|    | ||||
| } | ||||
|  | ||||
| bool_t CubeCollider::raycast( | ||||
| bool_t CubeCollider::performRaycast( | ||||
|   struct Collider3DRayResult *result, | ||||
|   struct Ray3D ray | ||||
| ) { | ||||
|   | ||||
| @@ -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; | ||||
|   }; | ||||
| } | ||||
| @@ -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; | ||||
|   } | ||||
| } | ||||
| @@ -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; | ||||
|   } | ||||
| } | ||||
| @@ -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>(); | ||||
|       } | ||||
|   | ||||
| @@ -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>(); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user