From a66f56ad9f992c73564d6493e3b5917087dcea10 Mon Sep 17 00:00:00 2001 From: ecker Date: Mon, 1 Sep 2025 23:16:43 -0500 Subject: [PATCH] refractor to try and minimize differences between reactphysics and internal physics engine (that i really need to optimize now), reverted some things with the graph system to get it to work again on scenes with more than one mesh (because for some reason instance IDs need to be global and i cant for the life of me figure out how to properly remap them) --- Makefile | 6 +- bin/data/config.json | 8 +- bin/data/entities/prop.json | 7 +- bin/data/entities/scripts/craeture.lua | 7 +- bin/data/entities/scripts/door.lua | 6 +- bin/data/entities/scripts/player.lua | 16 +- .../sourceengine/base_sourceengine.json | 4 +- .../scenes/sourceengine/mds_mcdonalds.json | 6 +- .../scenes/sourceengine/sourceengine.json | 4 +- bin/data/scenes/sourceengine/ss2_medsci1.json | 4 +- bin/exe/default/renderer | 2 +- engine/inc/uf/engine/graph/graph.h | 4 + engine/inc/uf/ext/reactphysics/reactphysics.h | 117 +++++--- engine/inc/uf/utils/math/physics/impl.h | 100 ++++-- engine/src/engine/ext/player/behavior.cpp | 99 +++--- engine/src/engine/graph/decode.cpp | 18 ++ engine/src/engine/graph/graph.cpp | 282 +++++++++-------- engine/src/engine/object/behavior.cpp | 68 ++--- engine/src/engine/object/object.cpp | 10 - engine/src/ext/gltf/gltf.cpp | 3 +- engine/src/ext/gltf/processPrimitives.inl | 21 +- engine/src/ext/lua/usertypes/physics.cpp | 60 ++-- engine/src/ext/reactphysics/reactphysics.cpp | 284 ++++++++---------- engine/src/ext/xatlas/xatlas.cpp | 102 ++++--- engine/src/utils/math/physics/aabb.inl | 14 +- engine/src/utils/math/physics/bvh.inl | 79 ++--- engine/src/utils/math/physics/capsule.inl | 10 +- engine/src/utils/math/physics/epa.inl | 2 +- engine/src/utils/math/physics/gjk.inl | 8 +- engine/src/utils/math/physics/helpers.inl | 73 +++-- engine/src/utils/math/physics/impl.cpp | 148 +++++---- engine/src/utils/math/physics/integration.inl | 22 +- engine/src/utils/math/physics/mesh.inl | 14 +- engine/src/utils/math/physics/plane.inl | 10 +- engine/src/utils/math/physics/ray.inl | 14 +- engine/src/utils/math/physics/solvers.inl | 14 +- engine/src/utils/math/physics/sphere.inl | 10 +- engine/src/utils/math/physics/triangle.inl | 20 +- 38 files changed, 881 insertions(+), 795 deletions(-) diff --git a/Makefile b/Makefile index b7379926..19a4ffdb 100644 --- a/Makefile +++ b/Makefile @@ -66,7 +66,7 @@ ifneq (,$(findstring win64,$(ARCH))) REQ_DEPS += meshoptimizer toml xatlas curl ffx:fsr dc:texconv # vall_e cpptrace # openvr # ncurses draco discord bullet ultralight-ux FLAGS += -march=native -g # -flto # -g endif - REQ_DEPS += $(RENDERER) json:nlohmann zlib luajit simd ctti gltf imgui fmt freetype openal ogg wav # reactphysics + REQ_DEPS += $(RENDERER) json:nlohmann zlib luajit reactphysics simd ctti gltf imgui fmt freetype openal ogg wav FLAGS += -DUF_ENV_WINDOWS -DUF_ENV_WIN64 -DWIN32_LEAN_AND_MEAN DEPS += -lgdi32 -ldwmapi LINKS += #-Wl,-subsystem,windows @@ -76,13 +76,13 @@ else ifneq (,$(findstring linux,$(ARCH))) REQ_DEPS += toml xatlas curl dc:texconv # meshoptimizer ffx:fsr cpptrace vall_e # ncurses openvr draco discord bullet ultralight-ux FLAGS += -march=native -g # -flto # -g endif - REQ_DEPS += $(RENDERER) json:nlohmann zlib luajit simd ctti gltf imgui fmt freetype openal ogg wav # reactphysics + REQ_DEPS += $(RENDERER) json:nlohmann zlib luajit reactphysics simd ctti gltf imgui fmt freetype openal ogg wav FLAGS += -DUF_ENV_LINUX -fPIC DEPS += -pthread -ldl -lX11 -lXrandr INCS := -I./dep/master/include $(INCS) else ifneq (,$(findstring dreamcast,$(ARCH))) FLAGS += -DUF_ENV_DREAMCAST # -DUF_LEAN_AND_MEAN # this apparently crashes - REQ_DEPS += opengl gldc json:nlohmann zlib lua simd ctti fmt freetype openal aldc ogg wav png # imgui # reactphysics + REQ_DEPS += opengl gldc json:nlohmann zlib lua reactphysics simd ctti fmt freetype openal aldc ogg wav png # imgui INCS := -I./dep/dreamcast/include $(INCS) endif diff --git a/bin/data/config.json b/bin/data/config.json index 1e000147..2028ab8e 100644 --- a/bin/data/config.json +++ b/bin/data/config.json @@ -117,7 +117,7 @@ "gui": true, "vsync": false, // vsync on vulkan side rather than engine-side "hdr": true, - "vxgi": true, + "vxgi": false, // true "culling": true, "bloom": true, "rt": false, @@ -359,7 +359,7 @@ }, "threads": { "workers" : "auto", - "frame limiter": "auto" + "frame limiter": 0 // "auto" }, "debug": { "framerate": { @@ -381,8 +381,8 @@ "auto validate": false }, "loader": { - "assert": true, - "async": true + "assert": true + //"async": true }, "hooks": { "defer lazy calls": true diff --git a/bin/data/entities/prop.json b/bin/data/entities/prop.json index a44b9326..b1987d11 100644 --- a/bin/data/entities/prop.json +++ b/bin/data/entities/prop.json @@ -6,12 +6,7 @@ "metadata": { "holdable": true, "physics": { - // "gravity": [ 0, -9.81, 0 ], - // "inertia": [10, 10, 10], - // "mass": 10, - - "type": "bounding box", - "recenter": false + "type": "bounding box" } } } \ No newline at end of file diff --git a/bin/data/entities/scripts/craeture.lua b/bin/data/entities/scripts/craeture.lua index e60feba8..c1a76bb5 100644 --- a/bin/data/entities/scripts/craeture.lua +++ b/bin/data/entities/scripts/craeture.lua @@ -2,7 +2,7 @@ local ent = ent local scene = entities.currentScene() local metadata = ent:getComponent("Metadata") local transform = ent:getComponent("Transform") -local physicsState = ent:getComponent("PhysicsState") +local physicsBody = ent:getComponent("PhysicsBody") local camera = ent:getComponent("Camera") local cameraTransform = camera:getTransform() @@ -12,7 +12,6 @@ local timers = { } if not timers.lookat:running() then timers.lookat:start(); end -local collider = ent:getComponent("PhysicsState") local target_transform = nil local soundEmitter = ent -- on tick @@ -27,8 +26,8 @@ ent:bind( "tick", function(self) local angle = Vector3f.signedAngle( transform.forward, target, axis ) local rot = Quaternion.axisAngle( axis, angle * time.delta() * 4 ) - if collider:hasBody() then - collider:applyRotation( rot ) + if physicsBody:hasBody() then + physicsBody:applyRotation( rot ) else transform:rotate( rot ) end diff --git a/bin/data/entities/scripts/door.lua b/bin/data/entities/scripts/door.lua index 5becc5cc..b9117e97 100644 --- a/bin/data/entities/scripts/door.lua +++ b/bin/data/entities/scripts/door.lua @@ -13,8 +13,8 @@ local targetAlpha = 1.57 local alpha = 0 local target = Vector3f(0,0,0) local transform = ent:getComponent("Transform") +local physicsBody = ent:getComponent("PhysicsBody") local metadata = ent:getComponent("Metadata") -local collider = ent:getComponent("PhysicsState") local speed = metadata["speed"] or 1.0 local normal = Vector3f(0,0,-1) @@ -88,8 +88,8 @@ ent:bind( "tick", function(self) end if state > 0 and rot ~= nil then - if collider:hasBody() then - collider:applyRotation( rot ) + if physicsBody:hasBody() then + physicsBody:applyRotation( rot ) else transform:rotate( rot ) end diff --git a/bin/data/entities/scripts/player.lua b/bin/data/entities/scripts/player.lua index 59473a67..4f30a3f8 100644 --- a/bin/data/entities/scripts/player.lua +++ b/bin/data/entities/scripts/player.lua @@ -2,7 +2,7 @@ local ent = ent local scene = entities.currentScene() local metadataJson = ent:getComponent("Metadata") local transform = ent:getComponent("Transform") -local physicsState = ent:getComponent("Physics") +local physicsBody = ent:getComponent("PhysicsBody") local camera = ent:getComponent("Camera") local cameraTransform = camera:getTransform() @@ -112,7 +112,7 @@ ent:bind( "tick", function(self) local direction = flattenedTransform.forward * 8 local offset = 0.25 - local _, depth = physicsState:rayCast( center, direction ) + local _, depth = physicsBody:rayCast( center, direction ) if depth >= 0.5 then depth = 0.5 elseif depth < 0 then @@ -142,7 +142,7 @@ ent:bind( "tick", function(self) local center = flattenedTransform.position local direction = flattenedTransform.forward * useDistance - local prop, depth = physicsState:rayCast( center, direction ) + local prop, depth = physicsBody:rayCast( center, direction ) local payload = { user = ent:uid(), uid = prop and prop:uid() or 0, @@ -164,10 +164,10 @@ ent:bind( "tick", function(self) ]] local center = flattenedTransform.position local direction = flattenedTransform.forward * pullDistance - local prop, depth = physicsState:rayCast( center, direction ) + local prop, depth = physicsBody:rayCast( center, direction ) if depth >= 0 and prop and not string.matched( prop:name(), "/^worldspawn/" ) then local heldObjectTransform = prop:getComponent("Transform") - local heldObjectPhysicsState = prop:getComponent("Physics") + local heldObjectPhysicsState = prop:getComponent("PhysicsBody") local strength = 500 local distanceSquared = (heldObjectTransform.position - flattenedTransform.position):magnitude() @@ -191,7 +191,7 @@ ent:bind( "tick", function(self) local prop = entities.get( heldObject.uid ) local heldObjectTransform = prop:getComponent("Transform") - local heldObjectPhysicsState = prop:getComponent("Physics") + local heldObjectPhysicsState = prop:getComponent("PhysicsBody") if mouse1 and timers.physcannon:elapsed() > 0.5 then timers.physcannon:reset() @@ -243,14 +243,14 @@ ent:addHook( "entity:Use.%UID%", function( payload ) heldObject.uid = payload.uid heldObject.distance = offset:norm() - prop:getComponent("Physics"):enableGravity(false) + prop:getComponent("PhysicsBody"):enableGravity(false) else validUse = not string.matched( prop:name(), "/^worldspawn/" ) end elseif heldObject.uid ~= 0 then validUse = true local prop = entities.get( heldObject.uid ) - local heldObjectPhysicsState = prop:getComponent("Physics") + local heldObjectPhysicsState = prop:getComponent("PhysicsBody") heldObjectPhysicsState:enableGravity(true) heldObjectPhysicsState:applyImpulse( heldObject.momentum ) diff --git a/bin/data/scenes/sourceengine/base_sourceengine.json b/bin/data/scenes/sourceengine/base_sourceengine.json index 9c359469..963a99c7 100644 --- a/bin/data/scenes/sourceengine/base_sourceengine.json +++ b/bin/data/scenes/sourceengine/base_sourceengine.json @@ -10,7 +10,7 @@ "tags": { // exact matches "worldspawn": { - "physics": { "type": "mesh", "static": true }, + "physics": { "type": "mesh", "static": true, "mass": 0 }, "grid": { "size": [8,1,8], "epsilon": 0.001, "cleanup": true, "print": true, "clip": true }, "optimize meshlets": { "simplify": 0.125, "print": false }, "unwrap mesh": true @@ -36,7 +36,7 @@ // "/^light_[^e]/": { "ignore": true }, // regexp matches - "/^worldspawn_/": { "physics": { "type": "mesh", "static": true } }, + // "/^worldspawn_/": { "physics": { "type": "mesh", "static": true } }, "/^func_door_/": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } }, "/^prop_door_/": { "action": "load", "payload": { "import": "/door.json", "metadata": { "angle":-1.570795, "normal": [-1,0,0] } } }, "/^prop_static/": { /*"action": "load", "payload": { "import": "/prop.json", "metadata": { "physics": { "gravity": [ 0, 0, 0 ] } } }*/ }, diff --git a/bin/data/scenes/sourceengine/mds_mcdonalds.json b/bin/data/scenes/sourceengine/mds_mcdonalds.json index 2084cb50..fbece77f 100644 --- a/bin/data/scenes/sourceengine/mds_mcdonalds.json +++ b/bin/data/scenes/sourceengine/mds_mcdonalds.json @@ -1,9 +1,9 @@ { "import": "./base_sourceengine.json", "assets": [ - // { "filename": "./models/mds_mcdonalds.glb" }, - { "filename": "./models/mds_mcdonalds/graph.json" }, - { "filename": "/burger.json", "delay": 1 } + // { "filename": "./models/mds_mcdonalds.glb" } + { "filename": "./models/mds_mcdonalds/graph.json" } + // { "filename": "/burger.json", "delay": 1 } ], "metadata": { "graph": { diff --git a/bin/data/scenes/sourceengine/sourceengine.json b/bin/data/scenes/sourceengine/sourceengine.json index feac6dec..95a20fe6 100644 --- a/bin/data/scenes/sourceengine/sourceengine.json +++ b/bin/data/scenes/sourceengine/sourceengine.json @@ -1,9 +1,9 @@ { // "import": "./rp_downtown_v2.json" - "import": "./ss2_medsci1.json" +// "import": "./ss2_medsci1.json" // "import": "./test_grid.json" // "import": "./sh2_mcdonalds.json" // "import": "./animal_crossing.json" -// "import": "./mds_mcdonalds.json" + "import": "./mds_mcdonalds.json" // "import": "./gm_construct.json" } \ No newline at end of file diff --git a/bin/data/scenes/sourceengine/ss2_medsci1.json b/bin/data/scenes/sourceengine/ss2_medsci1.json index 5c86088e..cf2e9a70 100644 --- a/bin/data/scenes/sourceengine/ss2_medsci1.json +++ b/bin/data/scenes/sourceengine/ss2_medsci1.json @@ -2,9 +2,9 @@ "import": "./base_sourceengine.json", "assets": [ // { "filename": "./models/ss2_medsci1.glb" } - // { "filename": "./models/ss2_medsci1/graph.json" } + { "filename": "./models/ss2_medsci1/graph.json" } // { "filename": "./models/ss2_medsci1_small.glb" } - { "filename": "./models/ss2_medsci1_small/graph.json" } + // { "filename": "./models/ss2_medsci1_small/graph.json" } // { "filename": "./models/ss2_medsci1_smallish.glb" } // { "filename": "./models/ss2_medsci1_smallish/graph.json" } ], diff --git a/bin/exe/default/renderer b/bin/exe/default/renderer index 91caa7c1..53395cff 100644 --- a/bin/exe/default/renderer +++ b/bin/exe/default/renderer @@ -1 +1 @@ -opengl \ No newline at end of file +vulkan \ No newline at end of file diff --git a/engine/inc/uf/engine/graph/graph.h b/engine/inc/uf/engine/graph/graph.h index e99d3bcf..b3f86aa5 100644 --- a/engine/inc/uf/engine/graph/graph.h +++ b/engine/inc/uf/engine/graph/graph.h @@ -29,6 +29,8 @@ namespace pod { // Render information uf::stl::vector primitives; // + uf::stl::vector instances; // ugh + uf::stl::vector drawCommands; // ugh uf::stl::vector meshes; // uf::stl::vector images; // @@ -79,8 +81,10 @@ namespace pod { // Local storage, used for save/load struct Storage { + uf::stl::KeyMap instances; // should be unused but is a counter for global instance IDs because I cannot for the life of me figure out a working way to remap otherwise uf::stl::KeyMap instanceAddresses; uf::stl::KeyMap> primitives; + uf::stl::KeyMap> drawCommands; // unused uf::stl::KeyMap meshes; uf::stl::KeyMap images; diff --git a/engine/inc/uf/ext/reactphysics/reactphysics.h b/engine/inc/uf/ext/reactphysics/reactphysics.h index 7903287d..f6b05545 100644 --- a/engine/inc/uf/ext/reactphysics/reactphysics.h +++ b/engine/inc/uf/ext/reactphysics/reactphysics.h @@ -5,6 +5,7 @@ #include #include #include +#include #if UF_USE_REACTPHYSICS #include @@ -12,23 +13,49 @@ namespace rp3d = reactphysics3d; namespace pod { - struct UF_API Physics { - size_t uid = 0; - uf::Object* object = NULL; - - bool shared = false; // share control of the transform both in-engine and bullet, set to true if you're directly modifying the transform + typedef uint32_t CollisionMask; + + struct PhysicsMaterial { + float restitution = 0.2f; + float staticFriction = 0.5f; + float dynamicFriction = 0.3f; + }; + + struct UF_API Collider { + pod::CollisionMask mask; + rp3d::RigidBody* body = NULL; rp3d::CollisionShape* shape = NULL; - rp3d::Collider* colliders = NULL; + }; + struct UF_API PhysicsBody { rp3d::PhysicsWorld* world = NULL; - + uf::Object* object = NULL; + pod::Transform<> transform = {}; - pod::Vector3f velocity; - pod::Vector3f acceleration; - pod::Quaternion<> angularVelocity; - pod::Quaternion<> angularAcceleration; + pod::Vector3f offset = {}; + bool isStatic = false; + + float mass = 1.0f; + float inverseMass = 1.0f; + + pod::Vector3f velocity = {}; + pod::Vector3f forceAccumulator = {}; + + pod::Vector3f angularVelocity = {}; + pod::Vector3f torqueAccumulator = {}; + + pod::Vector3f inertiaTensor = { 0, 0, 0 }; + pod::Vector3f inverseInertiaTensor = { 0, 0, 0 }; + + pod::Vector3f gravity = { 0.0f, -9.81f, 0.0f }; // an invalid gravity will fallback to world gravity + + pod::Collider collider; + pod::PhysicsMaterial material; + + + // to-do: do something about this struct { struct { pod::Transform<> transform = {}; @@ -38,19 +65,19 @@ namespace pod { pod::Quaternion<> angularAcceleration; } current, previous; } internal; - - - struct { - uint32_t flags = 0; - float mass = 0.0f; - float friction = 0.8f; - float restitution = 0.0f; - pod::Vector3f inertia = {0, 0, 0}; - pod::Vector3f gravity = {0, 0, 0}; - } stats; }; - typedef Physics PhysicsState; + struct Contact { + pod::Vector3f contact = {}; + pod::Vector3f normal = {}; + float penetration = 0; + }; + + struct RayQuery { + bool hit = false; + const pod::PhysicsBody* body; + pod::Contact contact = { pod::Vector3f{}, pod::Vector3f{}, FLT_MAX }; + }; } namespace ext { @@ -88,53 +115,53 @@ namespace ext { } // base collider creation - pod::PhysicsState& UF_API create( uf::Object& ); + pod::PhysicsBody& UF_API create( uf::Object&, float mass = 0.0f, const pod::Vector3f& = {} ); void UF_API destroy( uf::Object& ); - void UF_API destroy( pod::PhysicsState& ); + void UF_API destroy( pod::PhysicsBody& ); - void UF_API attach( pod::PhysicsState& ); - void UF_API detach( pod::PhysicsState& ); + void UF_API attach( pod::PhysicsBody& ); + void UF_API detach( pod::PhysicsBody& ); // collider for mesh (static or dynamic) - pod::PhysicsState& UF_API create( uf::Object&, const uf::Mesh&, bool ); + pod::PhysicsBody& UF_API create( uf::Object&, const uf::Mesh&, float mass = 0.0f, const pod::Vector3f& = {} ); // collider for boundingbox - pod::PhysicsState& UF_API create( uf::Object&, const pod::Vector3f& ); + pod::PhysicsBody& UF_API create( uf::Object&, const pod::AABB&, float mass = 0.0f, const pod::Vector3f& = {} ); + // collider for sphere + pod::PhysicsBody& UF_API create( uf::Object&, const pod::Sphere&, float mass = 0.0f, const pod::Vector3f& = {} ); + // collider for plane + pod::PhysicsBody& UF_API create( uf::Object&, const pod::Plane&, float mass = 0.0f, const pod::Vector3f& = {} ); // collider for capsule - pod::PhysicsState& UF_API create( uf::Object&, float, float ); + pod::PhysicsBody& UF_API create( uf::Object&, const pod::Capsule&, float mass = 0.0f, const pod::Vector3f& = {} ); // update mesh - void UF_API update( pod::PhysicsState&, const uf::Mesh&, bool ); + void UF_API update( pod::PhysicsBody&, const uf::Mesh&, bool ); // synchronize engine transforms to bullet transforms void UF_API syncTo( ext::reactphysics::WorldState& ); // synchronize bullet transforms to engine transforms void UF_API syncFrom( ext::reactphysics::WorldState&, float = 1 ); // apply impulse - void UF_API setImpulse( pod::PhysicsState&, const pod::Vector3f& = {} ); - void UF_API applyImpulse( pod::PhysicsState&, const pod::Vector3f& ); + void UF_API setImpulse( pod::PhysicsBody&, const pod::Vector3f& = {} ); + void UF_API applyImpulse( pod::PhysicsBody&, const pod::Vector3f& ); // directly move a transform - void UF_API applyMovement( pod::PhysicsState&, const pod::Vector3f& ); + void UF_API applyMovement( pod::PhysicsBody&, const pod::Vector3f& ); // directly apply a velocity - void UF_API setVelocity( pod::PhysicsState&, const pod::Vector3f& ); - void UF_API applyVelocity( pod::PhysicsState&, const pod::Vector3f& ); + void UF_API setVelocity( pod::PhysicsBody&, const pod::Vector3f& ); + void UF_API applyVelocity( pod::PhysicsBody&, const pod::Vector3f& ); // directly rotate a transform - void UF_API applyRotation( pod::PhysicsState&, const pod::Quaternion<>& ); - void UF_API applyRotation( pod::PhysicsState&, const pod::Vector3f&, float ); + void UF_API applyRotation( pod::PhysicsBody&, const pod::Quaternion<>& ); + void UF_API applyRotation( pod::PhysicsBody&, const pod::Vector3f&, float ); // ray casting - uf::Object* UF_API rayCast( const pod::Vector3f&, const pod::Vector3f& ); - uf::Object* UF_API rayCast( pod::PhysicsState&, const pod::Vector3f&, const pod::Vector3f& ); - uf::Object* UF_API rayCast( pod::PhysicsState&, const pod::Vector3f&, const pod::Vector3f&, float& ); - uf::Object* UF_API rayCast( const pod::Vector3f&, const pod::Vector3f&, uf::Object*, float& ); -// float UF_API rayCast( const pod::Vector3f&, const pod::Vector3f&, uf::Object*, uf::Object*& ); + pod::RayQuery UF_API rayCast( const pod::Ray& ray, const pod::PhysicsBody& body, float max ); // allows noclip - void UF_API activateCollision( pod::PhysicsState&, bool = true ); + void UF_API activateCollision( pod::PhysicsBody&, bool = true ); // - float UF_API getMass( pod::PhysicsState& ); - void UF_API setMass( pod::PhysicsState&, float ); + float UF_API getMass( pod::PhysicsBody& ); + void UF_API setMass( pod::PhysicsBody&, float ); } } namespace uf { diff --git a/engine/inc/uf/utils/math/physics/impl.h b/engine/inc/uf/utils/math/physics/impl.h index e454315c..a84d12af 100644 --- a/engine/inc/uf/utils/math/physics/impl.h +++ b/engine/inc/uf/utils/math/physics/impl.h @@ -62,9 +62,37 @@ namespace pod { typedef uint32_t CollisionMask; + struct Collider { + // what it is + enum CategoryMask : uint32_t { + CATEGORY_NONE = 0, + CATEGORY_STATIC = 1 << 0, + CATEGORY_DYNAMIC = 1 << 1, + CATEGORY_PLAYER = 1 << 2, + CATEGORY_NPC = 1 << 3, + CATEGORY_TRIGGER = 1 << 4, + CATEGORY_PROJECTILE = 1 << 5, + CATEGORY_CHARACTER = CATEGORY_PLAYER | CATEGORY_NPC, + CATEGORY_ALL = 0xFFFFFFFF + }; + // what it collides with + enum CollisionMask : uint32_t { + MASK_NONE = 0, + MASK_STATIC = CATEGORY_DYNAMIC | CATEGORY_PLAYER | CATEGORY_NPC | CATEGORY_PROJECTILE, + MASK_DYNAMIC = CATEGORY_STATIC | CATEGORY_DYNAMIC | CATEGORY_PLAYER | CATEGORY_NPC, + MASK_PLAYER = CATEGORY_STATIC | CATEGORY_DYNAMIC | CATEGORY_NPC | CATEGORY_PROJECTILE, + MASK_NPC = CATEGORY_STATIC | CATEGORY_DYNAMIC | CATEGORY_PLAYER | CATEGORY_PROJECTILE, + MASK_TRIGGER = CATEGORY_PLAYER | CATEGORY_NPC, + MASK_PROJECTILE = CATEGORY_STATIC | CATEGORY_DYNAMIC | CATEGORY_PLAYER | CATEGORY_NPC, + MASK_CHARACTER = MASK_PLAYER | MASK_NPC, + MASK_ALL = 0xFFFFFFFF + }; + pod::ShapeType type; - pod::CollisionMask mask = 0xFFFFFFFF; + pod::CollisionMask category = Collider::CATEGORY_ALL; + pod::CollisionMask mask = Collider::MASK_ALL; + union { pod::Sphere sphere; pod::AABB aabb; @@ -83,7 +111,7 @@ namespace pod { struct World; // forward declare - struct RigidBody { + struct PhysicsBody { pod::World* world = NULL; uf::Object* object = NULL; // pod::Transform<> transform = {}; @@ -105,6 +133,8 @@ namespace pod { pod::Vector3f inertiaTensor = { 1, 1, 1 }; pod::Vector3f inverseInertiaTensor = { 1, 1, 1 }; + pod::Vector3f gravity = { NAN, NAN, NAN }; // an invalid gravity will fallback to world gravity + pod::AABB bounds; pod::Collider collider; pod::PhysicsMaterial material; @@ -123,20 +153,20 @@ namespace pod { }; struct Manifold { - pod::RigidBody* a = NULL; - pod::RigidBody* b = NULL; + pod::PhysicsBody* a = NULL; + pod::PhysicsBody* b = NULL; float dt = 0; uf::stl::vector points; }; struct RayQuery { bool hit = false; - const pod::RigidBody* body; + const pod::PhysicsBody* body; pod::Contact contact = { pod::Vector3f{}, pod::Vector3f{}, FLT_MAX }; }; struct World { - uf::stl::vector bodies; + uf::stl::vector bodies; pod::Vector3f gravity = { 0, -9.81f, 0 }; pod::BVH bvh; @@ -168,38 +198,46 @@ namespace uf { void UF_API step( pod::World&, float dt ); void UF_API substep( pod::World&, float dt, int substeps ); - void UF_API setMass( pod::RigidBody& body, float mass = 0.0f ); - void UF_API setInertia( pod::RigidBody& body ); - void UF_API applyForce( pod::RigidBody& body, const pod::Vector3f& force ); - void UF_API applyForceAtPoint( pod::RigidBody body, const pod::Vector3f& force, const pod::Vector3f& point ); - void UF_API applyImpulse( pod::RigidBody& body, const pod::Vector3f& impulse ); - void UF_API applyTorque( pod::RigidBody& body, const pod::Vector3f& torque ); + void UF_API setMass( pod::PhysicsBody& body, float mass = 0.0f ); + void UF_API setColliderCategory( pod::PhysicsBody&, uint32_t category = pod::Collider::CATEGORY_ALL ); + void UF_API setColliderCategory( pod::PhysicsBody&, const uf::stl::string& ); + void UF_API setColliderMask( pod::PhysicsBody&, uint32_t mask = pod::Collider::MASK_ALL ); + void UF_API setColliderMask( pod::PhysicsBody&, const uf::stl::string& ); + void UF_API setGravity( pod::PhysicsBody&, const pod::Vector3f& = { NAN, NAN, NAN } ); + pod::Vector3f UF_API getGravity( pod::PhysicsBody& ); - void UF_API setVelocity( pod::RigidBody& body, const pod::Vector3f& velocity ); - void UF_API applyRotation( pod::RigidBody& body, const pod::Quaternion<>& q ); - void UF_API applyRotation( pod::RigidBody& body, const pod::Vector3f& axis, float angle ); + void UF_API updateInertia( pod::PhysicsBody& body ); + + void UF_API applyForce( pod::PhysicsBody& body, const pod::Vector3f& force ); + void UF_API applyForceAtPoint( pod::PhysicsBody body, const pod::Vector3f& force, const pod::Vector3f& point ); + void UF_API applyImpulse( pod::PhysicsBody& body, const pod::Vector3f& impulse ); + void UF_API applyTorque( pod::PhysicsBody& body, const pod::Vector3f& torque ); + + void UF_API setVelocity( pod::PhysicsBody& body, const pod::Vector3f& velocity ); + void UF_API applyRotation( pod::PhysicsBody& body, const pod::Quaternion<>& q ); + void UF_API applyRotation( pod::PhysicsBody& body, const pod::Vector3f& axis, float angle ); - pod::RigidBody& UF_API create( uf::Object&, float mass = 0.0f, const pod::Vector3f& = {} ); - pod::RigidBody& UF_API create( uf::Object& object, const pod::AABB& aabb, float mass = 0.0f, const pod::Vector3f& = {} ); - pod::RigidBody& UF_API create( uf::Object& object, const pod::Sphere& sphere, float mass = 0.0f, const pod::Vector3f& = {} ); - pod::RigidBody& UF_API create( uf::Object& object, const pod::Plane& plane, float mass = 0.0f, const pod::Vector3f& = {} ); - pod::RigidBody& UF_API create( uf::Object& object, const pod::Capsule& capsule, float mass = 0.0f, const pod::Vector3f& = {} ); - pod::RigidBody& UF_API create( uf::Object&, const uf::Mesh& mesh, float mass = 0.0f, const pod::Vector3f& = {} ); + pod::PhysicsBody& UF_API create( uf::Object&, float mass = 0.0f, const pod::Vector3f& = {} ); + pod::PhysicsBody& UF_API create( uf::Object& object, const pod::AABB& aabb, float mass = 0.0f, const pod::Vector3f& = {} ); + pod::PhysicsBody& UF_API create( uf::Object& object, const pod::Sphere& sphere, float mass = 0.0f, const pod::Vector3f& = {} ); + pod::PhysicsBody& UF_API create( uf::Object& object, const pod::Plane& plane, float mass = 0.0f, const pod::Vector3f& = {} ); + pod::PhysicsBody& UF_API create( uf::Object& object, const pod::Capsule& capsule, float mass = 0.0f, const pod::Vector3f& = {} ); + pod::PhysicsBody& UF_API create( uf::Object&, const uf::Mesh& mesh, float mass = 0.0f, const pod::Vector3f& = {} ); - pod::RigidBody& UF_API create( pod::World&, uf::Object&, float mass = 0.0f, const pod::Vector3f& = {} ); - pod::RigidBody& UF_API create( pod::World&, uf::Object& object, const pod::AABB& aabb, float mass = 0.0f, const pod::Vector3f& = {} ); - pod::RigidBody& UF_API create( pod::World&, uf::Object& object, const pod::Sphere& sphere, float mass = 0.0f, const pod::Vector3f& = {} ); - pod::RigidBody& UF_API create( pod::World&, uf::Object& object, const pod::Plane& plane, float mass = 0.0f, const pod::Vector3f& = {} ); - pod::RigidBody& UF_API create( pod::World&, uf::Object& object, const pod::Capsule& capsule, float mass = 0.0f, const pod::Vector3f& = {} ); - pod::RigidBody& UF_API create( pod::World&, uf::Object& object, const pod::TriangleWithNormal& tri, float mass = 0.0f, const pod::Vector3f& = {} ); - pod::RigidBody& UF_API create( pod::World&, uf::Object&, const uf::Mesh& mesh, float mass = 0.0f, const pod::Vector3f& = {} ); + pod::PhysicsBody& UF_API create( pod::World&, uf::Object&, float mass = 0.0f, const pod::Vector3f& = {} ); + pod::PhysicsBody& UF_API create( pod::World&, uf::Object& object, const pod::AABB& aabb, float mass = 0.0f, const pod::Vector3f& = {} ); + pod::PhysicsBody& UF_API create( pod::World&, uf::Object& object, const pod::Sphere& sphere, float mass = 0.0f, const pod::Vector3f& = {} ); + pod::PhysicsBody& UF_API create( pod::World&, uf::Object& object, const pod::Plane& plane, float mass = 0.0f, const pod::Vector3f& = {} ); + pod::PhysicsBody& UF_API create( pod::World&, uf::Object& object, const pod::Capsule& capsule, float mass = 0.0f, const pod::Vector3f& = {} ); + pod::PhysicsBody& UF_API create( pod::World&, uf::Object& object, const pod::TriangleWithNormal& tri, float mass = 0.0f, const pod::Vector3f& = {} ); + pod::PhysicsBody& UF_API create( pod::World&, uf::Object&, const uf::Mesh& mesh, float mass = 0.0f, const pod::Vector3f& = {} ); void UF_API destroy( uf::Object& ); - void UF_API destroy( pod::RigidBody& ); + void UF_API destroy( pod::PhysicsBody& ); - pod::RayQuery UF_API rayCast( const pod::Ray&, const pod::RigidBody&, float = FLT_MAX ); + pod::RayQuery UF_API rayCast( const pod::Ray&, const pod::PhysicsBody&, float = FLT_MAX ); pod::RayQuery UF_API rayCast( const pod::Ray&, const pod::World&, float = FLT_MAX ); - pod::RayQuery UF_API rayCast( const pod::Ray&, const pod::World&, const pod::RigidBody*, float = FLT_MAX ); + pod::RayQuery UF_API rayCast( const pod::Ray&, const pod::World&, const pod::PhysicsBody*, float = FLT_MAX ); } } } \ No newline at end of file diff --git a/engine/src/engine/ext/player/behavior.cpp b/engine/src/engine/ext/player/behavior.cpp index f211a76f..cd8d04b4 100644 --- a/engine/src/engine/ext/player/behavior.cpp +++ b/engine/src/engine/ext/player/behavior.cpp @@ -25,10 +25,6 @@ UF_BEHAVIOR_TRAITS_CPP(ext::PlayerBehavior, ticks = true, renders = false, multi void ext::PlayerBehavior::initialize( uf::Object& self ) { auto& transform = this->getComponent>(); -#if UF_USE_REACTPHYSICS - auto& collider = this->getComponent(); -#endif - auto& metadata = this->getComponent(); auto& metadataJson = this->getComponent(); @@ -133,16 +129,12 @@ void ext::PlayerBehavior::tick( uf::Object& self ) { auto& transform = this->getComponent>(); auto& scene = uf::scene::getCurrentScene(); -#if UF_USE_REACTPHYSICS - auto& physics = this->getComponent(); - auto& collider = this->getComponent(); -#else - auto& physics = this->getComponent(); -#endif auto& metadata = this->getComponent(); auto& metadataJson = this->getComponent(); + auto& physicsBody = this->getComponent(); + #if UF_ENTITY_METADATA_USE_JSON metadata.deserialize(self, metadataJson); #endif @@ -281,23 +273,24 @@ void ext::PlayerBehavior::tick( uf::Object& self ) { stats.floored = stats.noclipped; if ( !stats.floored ) { #if UF_USE_REACTPHYSICS - float t = -1; - uf::Object* hit = NULL; - pod::Vector3f center = transform.position + metadata.movement.floored.feet; + pod::Vector3f origin = transform.position + metadata.movement.floored.feet; pod::Vector3f direction = metadata.movement.floored.floor; - if ( !stats.floored && collider.body && (hit = uf::physics::impl::rayCast( collider, center, direction, t )) ) { - if ( metadata.movement.floored.print ) UF_MSG_DEBUG("Floored: {} | {}", hit->getName(), t); + pod::RayQuery query = uf::physics::impl::rayCast( pod::Ray{origin, direction}, physicsBody, 1.0f ); + + if ( query.hit ) { + if ( metadata.movement.floored.print ) UF_MSG_DEBUG("{}: {} | {}", query.contact.penetration, uf::string::toString(*query.body->object), uf::vector::toString(physicsBody.velocity)); stats.floored = true; + //if ( physicsBody.velocity.y < 0.0f ) physicsBody.velocity.y = 0.0f; } #else pod::Vector3f origin = transform.position + metadata.movement.floored.feet; pod::Vector3f direction = metadata.movement.floored.floor; - pod::RayQuery query = uf::physics::impl::rayCast( pod::Ray{origin, direction}, physics, 1.0f ); + pod::RayQuery query = uf::physics::impl::rayCast( pod::Ray{origin, direction}, physicsBody, 1.0f ); if ( query.hit ) { - if ( metadata.movement.floored.print ) UF_MSG_DEBUG("{}: {} | {}", query.contact.penetration, uf::string::toString(*query.body->object), uf::vector::toString(physics.velocity)); + if ( metadata.movement.floored.print ) UF_MSG_DEBUG("{}: {} | {}", query.contact.penetration, uf::string::toString(*query.body->object), uf::vector::toString(physicsBody.velocity)); stats.floored = true; - if ( physics.velocity.y < 0.0f ) physics.velocity.y = 0.0f; + //if ( physicsBody.velocity.y < 0.0f ) physicsBody.velocity.y = 0.0f; } #endif } @@ -346,9 +339,7 @@ void ext::PlayerBehavior::tick( uf::Object& self ) { } #endif -#if UF_USE_REACTPHYSICS - if ( collider.stats.gravity == pod::Vector3f{0,0,0} ) stats.noclipped = true; -#endif + if ( physicsBody.gravity == pod::Vector3f{0,0,0} ) stats.noclipped = true; { speed.rotate = metadata.movement.rotate * uf::physics::time::delta; @@ -363,7 +354,7 @@ void ext::PlayerBehavior::tick( uf::Object& self ) { speed.run *= 1.5; } if ( !stats.floored || stats.noclipped ) speed.friction = 1; - if ( stats.noclipped ) physics.velocity = {}; + if ( stats.noclipped ) physicsBody.velocity = {}; } if ( keys.running ) speed.move = speed.run; else if ( keys.walk ) speed.move = speed.walk; @@ -424,12 +415,10 @@ void ext::PlayerBehavior::tick( uf::Object& self ) { translator.forward.y = 0; translator.forward = uf::vector::normalize( translator.forward ); } - #if UF_USE_REACTPHYSICS - else if ( stats.noclipped || collider.stats.gravity == pod::Vector3f{0,0,0} ){ + else if ( stats.noclipped || physicsBody.gravity == pod::Vector3f{0,0,0} ){ translator.forward.y += cameraTransform.forward.y; translator.forward = uf::vector::normalize( translator.forward ); } - #endif if ( metadata.system.control ) { // noclip handler @@ -437,9 +426,19 @@ void ext::PlayerBehavior::tick( uf::Object& self ) { bool state = !stats.noclipped; metadata.system.noclipped = state; #if UF_USE_REACTPHYSICS - if ( collider.body ) { - collider.body->enableGravity(!state); - uf::physics::impl::activateCollision(collider, !state); + if ( physicsBody.object ) { + physicsBody.collider.body->enableGravity(!state); + uf::physics::impl::activateCollision(physicsBody, !state); + } + #else + if ( !state ) { + uf::physics::impl::setGravity( physicsBody ); + uf::physics::impl::setColliderCategory( physicsBody, "ALL"); + uf::physics::impl::setColliderMask( physicsBody, "ALL"); + } else { + uf::physics::impl::setGravity( physicsBody, pod::Vector3f{0,0,0}); + uf::physics::impl::setColliderCategory( physicsBody, "NONE"); + uf::physics::impl::setColliderMask( physicsBody, "NONE"); } #endif @@ -453,16 +452,16 @@ void ext::PlayerBehavior::tick( uf::Object& self ) { if ( keys.left ^ keys.right ) target += translator.right * (keys.right ? 1 : -1); target = uf::vector::normalize( target ); - physics.velocity *= { speed.friction, 1, speed.friction }; + physicsBody.velocity *= { speed.friction, 1, speed.friction }; stats.walking = (keys.forward ^ keys.backwards) || (keys.left ^ keys.right); if ( stats.walking ) { float factor = stats.floored ? 1.0f : speed.air; if ( stats.noclipped ) { - physics.velocity += target * speed.move; + physicsBody.velocity += target * speed.move; } else { - physics.velocity += target * std::clamp( speed.move * factor - uf::vector::dot( physics.velocity, target ), 0.0f, speed.move * 10 * uf::physics::time::delta ); + physicsBody.velocity += target * std::clamp( speed.move * factor - uf::vector::dot( physicsBody.velocity, target ), 0.0f, speed.move * 10 * uf::physics::time::delta ); } auto dot = uf::vector::dot( transform.forward, target ); @@ -472,18 +471,14 @@ void ext::PlayerBehavior::tick( uf::Object& self ) { auto axis = transform.up; float angle = uf::vector::signedAngle( transform.forward, target, axis ) * uf::physics::time::delta * 4; // speed.rotate; - #if UF_USE_REACTPHYSICS - if ( collider.body ) uf::physics::impl::applyRotation( collider, axis, angle ); else - #else - if ( physics.object ) uf::physics::impl::applyRotation( physics, axis, angle ); else - #endif + if ( physicsBody.object ) uf::physics::impl::applyRotation( physicsBody, axis, angle ); else uf::transform::rotate( transform, axis, angle ); } } if ( !stats.floored ) stats.walking = false; } TIMER(0.0625, stats.floored && keys.jump && !stats.noclipped ) { - physics.velocity += translator.up * metadata.movement.jump; + physicsBody.velocity += translator.up * metadata.movement.jump; } if ( stats.floored && keys.jump && stats.noclipped ) transform.position += translator.up * metadata.movement.jump * uf::physics::time::delta * 4.0f; if ( keys.crouch ) { @@ -527,11 +522,7 @@ void ext::PlayerBehavior::tick( uf::Object& self ) { if ( metadata.camera.invert.x ) lookDelta.x *= -1; metadata.camera.limit.current.x += lookDelta.x; if ( metadata.camera.limit.current.x != metadata.camera.limit.current.x || ( metadata.camera.limit.current.x < metadata.camera.limit.max.x && metadata.camera.limit.current.x > metadata.camera.limit.min.x ) ) { - #if UF_USE_REACTPHYSICS - if ( collider.body ) uf::physics::impl::applyRotation( collider, transform.up, lookDelta.x ); else - #else - if ( physics.object ) uf::physics::impl::applyRotation( physics, transform.up, lookDelta.x ); else - #endif + if ( physicsBody.object ) uf::physics::impl::applyRotation( physicsBody, transform.up, lookDelta.x ); else uf::transform::rotate( transform, transform.up, lookDelta.x ); } else metadata.camera.limit.current.x -= lookDelta.x; } @@ -539,19 +530,13 @@ void ext::PlayerBehavior::tick( uf::Object& self ) { if ( metadata.camera.invert.y ) lookDelta.y *= -1; metadata.camera.limit.current.y += lookDelta.y; if ( metadata.camera.limit.current.y != metadata.camera.limit.current.y || ( metadata.camera.limit.current.y < metadata.camera.limit.max.y && metadata.camera.limit.current.y > metadata.camera.limit.min.y ) ) { - #if UF_USE_REACTPHYSICS - // if ( collider.body && !collider.shared ) uf::physics::impl::applyRotation( collider, cameraTransform.right, lookDelta.y ); else - #endif + // if ( physicsBody.object && !physicsBody.shared ) uf::physics::impl::applyRotation( physicsBody, cameraTransform.right, lookDelta.y ); else uf::transform::rotate( cameraTransform, cameraTransform.right, lookDelta.y ); } else metadata.camera.limit.current.y -= lookDelta.y; } } else if ( metadata.system.control ) { if ( keys.lookRight ^ keys.lookLeft ) { - #if UF_USE_REACTPHYSICS - if ( collider.body ) uf::physics::impl::applyRotation( collider, transform.up, speed.rotate * (keys.lookRight ? 1 : -1) ); else - #else - if ( physics.object ) uf::physics::impl::applyRotation( physics, transform.up, speed.rotate * (keys.lookRight ? 1 : -1) ); else - #endif + if ( physicsBody.object ) uf::physics::impl::applyRotation( physicsBody, transform.up, speed.rotate * (keys.lookRight ? 1 : -1) ); else uf::transform::rotate( transform, transform.up, speed.rotate * (keys.lookRight ? 1 : -1) ); } if ( keys.lookUp ^ keys.lookDown ) { @@ -566,22 +551,16 @@ void ext::PlayerBehavior::tick( uf::Object& self ) { // cameraTransform.position = uf::quaternion::rotate( rotation, cameraTransform.position - transform.position ); } if ( keys.lookUp ^ keys.lookDown ) { - #if 0 - // if ( collider.body && !collider.shared ) uf::physics::impl::applyRotation( collider, cameraTransform.right, lookDelta.y ); else - #endif + // if ( physicsBody.object && !physicsBody.shared ) uf::physics::impl::applyRotation( physicsBody, cameraTransform.right, lookDelta.y ); else float direction = keys.lookUp ? 1 : -1; if ( metadata.camera.invert.y ) direction *= -1; uf::transform::rotate( cameraTransform, cameraTransform.right, speed.rotate * direction ); } } { - #if UF_USE_REACTPHYSICS - if ( collider.body ) uf::physics::impl::setVelocity( collider, physics.velocity ); else - #else - if ( physics.object ) uf::physics::impl::setVelocity( physics, physics.velocity ); else - #endif - transform.position += physics.velocity * uf::physics::time::delta; - // if ( uf::vector::magnitude( physics.velocity ) > 1.0e-6 ) UF_MSG_DEBUG("Velocity: {}", uf::vector::toString( physics.velocity )); + if ( physicsBody.object ) uf::physics::impl::setVelocity( physicsBody, physicsBody.velocity ); else + transform.position += physicsBody.velocity * uf::physics::time::delta; + // if ( uf::vector::magnitude( physicsBody.velocity ) > 1.0e-6 ) UF_MSG_DEBUG("Velocity: {}", uf::vector::toString( physicsBody.velocity )); } diff --git a/engine/src/engine/graph/decode.cpp b/engine/src/engine/graph/decode.cpp index 064afd40..21f5a977 100644 --- a/engine/src/engine/graph/decode.cpp +++ b/engine/src/engine/graph/decode.cpp @@ -8,6 +8,7 @@ #include #include #include +#include // it's too unstable right now to do multithreaded loading, perhaps there's a better way #if UF_USE_OPENGL @@ -414,6 +415,17 @@ void uf::graph::load( pod::Graph& graph, const uf::stl::string& filename, const graph.settings.stream.hash = graph.metadata["stream"]["hash"].as(graph.settings.stream.hash); graph.settings.stream.lastUpdate = graph.metadata["stream"]["lastUpdate"].as(graph.settings.stream.lastUpdate); } + // store offsets + { + size_t instances = 0; + for ( auto& key : storage.primitives.keys ) { + instances += storage.primitives.map[key].size(); + } + + graph.metadata["offsets"]["instances"] = instances; + graph.metadata["offsets"]["materials"] = storage.materials.keys.size(); + graph.metadata["offsets"]["joints"] = storage.joints.keys.size(); + } uf::stl::string key = graph.metadata["key"].as(""); if ( key != "" ) { @@ -429,6 +441,12 @@ void uf::graph::load( pod::Graph& graph, const uf::stl::string& filename, const // UF_MSG_DEBUG("{}", name); storage.primitives[name] = decodePrimitives( value, graph ); graph.primitives.emplace_back(name); + + uf::stl::vector drawCommands; + for ( auto& primitive : storage.primitives[name] ) { + drawCommands.emplace_back( primitive.drawCommand ); + } + storage.drawCommands[name] = std::move(drawCommands); }); UF_DEBUG_TIMER_MULTITRACE("Read primitives."); #if UF_ENV_DREAMCAST diff --git a/engine/src/engine/graph/graph.cpp b/engine/src/engine/graph/graph.cpp index 7c5adff4..a93263f0 100644 --- a/engine/src/engine/graph/graph.cpp +++ b/engine/src/engine/graph/graph.cpp @@ -790,6 +790,12 @@ void uf::graph::process( pod::Graph& graph ) { uf::stl::unordered_map lightmapIDs; uint32_t lightmapCount = 0; + for ( auto& name : graph.instances ) { + auto& instance = storage.instances[name]; + filenames[instance.auxID] = uf::string::replace(UF_GRAPH_DEFAULT_LIGHTMAP, "%i", std::to_string(instance.auxID)); + + lightmapCount = std::max( lightmapCount, instance.auxID + 1 ); + } for ( auto& name : graph.primitives ) { auto& primitives = storage.primitives[name]; for ( auto& primitive : primitives ) { @@ -863,6 +869,11 @@ void uf::graph::process( pod::Graph& graph ) { } } + for ( auto& name : graph.instances ) { + auto& instance = storage.instances[name]; + if ( lightmapIDs.count( instance.auxID ) == 0 ) continue; + instance.lightmapID = lightmapIDs[instance.auxID]; + } for ( auto& name : graph.primitives ) { auto& primitives = storage.primitives[name]; for ( auto& primitive : primitives ) { @@ -933,9 +944,10 @@ void uf::graph::process( pod::Graph& graph ) { // process nodes UF_DEBUG_TIMER_MULTITRACE("Processing nodes"); for ( auto index : graph.root.children ) { - UF_DEBUG_TIMER_MULTITRACE("Processing node: {}", graph.nodes[index].name); process( graph, index, *graph.root.entity ); - UF_DEBUG_TIMER_MULTITRACE("Processed node: {}", graph.nodes[index].name); + + auto& node = graph.nodes[index]; + if ( node.entity ) UF_DEBUG_TIMER_MULTITRACE("Processed node: {}", node.name); } // patch materials/textures @@ -1036,61 +1048,81 @@ void uf::graph::process( pod::Graph& graph ) { } } // remap instance variables - UF_DEBUG_TIMER_MULTITRACE("Remapping primitive"); - for ( auto& name : graph.primitives ) { - auto& primitives = storage.primitives[name]; - for ( auto& primitive : primitives ) { - auto& drawCommand = primitive.drawCommand; - auto& instance = primitive.instance; + UF_DEBUG_TIMER_MULTITRACE("Remapping instances"); + for ( auto& name : graph.instances ) { + auto& instance = storage.instances[name]; + + if ( 0 <= instance.materialID && instance.materialID < graph.materials.size() ) { + auto& keys = storage.materials.keys; + auto& indices = storage.materials.indices; + + if ( !(0 <= instance.materialID && instance.materialID < graph.materials.size()) ) continue; - // remap instance ID - if ( 0 <= drawCommand.instanceID && drawCommand.instanceID < graph.primitives.size() ) { - for ( auto key : storage.primitives.keys ) { - if ( key == name ) break; - drawCommand.instanceID += storage.primitives[key].size(); - } - } + auto& needle = graph.materials[instance.materialID]; + instance.materialID = indices[needle]; + } + if ( 0 <= instance.lightmapID && instance.lightmapID < graph.textures.size() ) { + auto& keys = storage.textures.keys; + auto& indices = storage.textures.indices; - if ( 0 <= instance.materialID && instance.materialID < graph.materials.size() ) { - auto& keys = storage.materials.keys; - auto& indices = storage.materials.indices; - - if ( !(0 <= instance.materialID && instance.materialID < graph.materials.size()) ) continue; + if ( !(0 <= instance.lightmapID && instance.lightmapID < graph.textures.size()) ) continue; - auto& needle = graph.materials[instance.materialID]; - instance.materialID = indices[needle]; - } - if ( 0 <= instance.lightmapID && instance.lightmapID < graph.textures.size() ) { - auto& keys = storage.textures.keys; - auto& indices = storage.textures.indices; + auto& needle = graph.textures[instance.lightmapID]; + instance.lightmapID = indices[needle]; + } + #if 0 + // i genuinely dont remember what this is used for - if ( !(0 <= instance.lightmapID && instance.lightmapID < graph.textures.size()) ) continue; - - auto& needle = graph.textures[instance.lightmapID]; - instance.lightmapID = indices[needle]; - } - #if 0 - // i genuinely dont remember what this is used for - - if ( 0 <= instance.imageID && instance.imageID < graph.images.size() ) { - auto& keys = storage.images.keys; - auto it = std::find( keys.begin(), keys.end(), graph.images[instance.imageID] ); - UF_ASSERT( it != keys.end() ); - instance.imageID = it - keys.begin(); - } - #endif - // remap a skinID as an actual jointID - if ( 0 <= instance.jointID && instance.jointID < graph.skins.size() ) { - auto& name = graph.skins[instance.jointID]; - instance.jointID = 0; - for ( auto key : storage.joints.keys ) { - if ( key == name ) break; - instance.jointID += storage.joints[key].size(); - } + if ( 0 <= instance.imageID && instance.imageID < graph.images.size() ) { + auto& keys = storage.images.keys; + auto it = std::find( keys.begin(), keys.end(), graph.images[instance.imageID] ); + UF_ASSERT( it != keys.end() ); + instance.imageID = it - keys.begin(); + } + #endif + // remap a skinID as an actual jointID + if ( 0 <= instance.jointID && instance.jointID < graph.skins.size() ) { + auto& name = graph.skins[instance.jointID]; + instance.jointID = 0; + for ( auto key : storage.joints.keys ) { + if ( key == name ) break; + auto& joints = storage.joints[key]; + instance.jointID += joints.size(); } } } + // remap draw commands +#if 0 + UF_DEBUG_TIMER_MULTITRACE("Remapping drawCommands"); + for ( auto& name : graph.drawCommands ) { + auto& drawCommands = storage.drawCommands[name]; + for ( auto& drawCommand : drawCommands ) { + if ( 0 <= drawCommand.instanceID && drawCommand.instanceID < graph.instances.size() ) { + auto& keys = storage.instances.keys; + auto& indices = storage.instances.indices; + + if ( !(0 <= drawCommand.instanceID && drawCommand.instanceID < graph.instances.size()) ) continue; + + auto& needle = graph.instances[drawCommand.instanceID]; + #if 1 + drawCommand.instanceID = indices[needle]; + #elif 1 + for ( size_t i = 0; i < keys.size(); ++i ) { + if ( keys[i] != needle ) continue; + drawCommand.instanceID = i; + break; + } + #else + auto it = std::find( keys.begin(), keys.end(), needle ); + UF_ASSERT( it != keys.end() ); + drawCommand.instanceID = it - keys.begin(); + #endif + } + } + } +#endif + if ( graphMetadataJson["debug"]["print"]["lights"].as() ) { UF_MSG_DEBUG("Lights: {}", graph.lights.size()); for ( auto& pair : graph.lights ) { @@ -1104,21 +1136,16 @@ void uf::graph::process( pod::Graph& graph ) { } } - #if 0 - if ( graphMetadataJson["debug"]["print"]["primitives"].as() ) { - UF_MSG_DEBUG("Instances: {}", graph.primitives.size()); - for ( auto& name : graph.primitives ) { - auto& primitive = storage.primitives[name]; - for ( auto& primitive : primitives ) { - auto& instance = primitive.instance; - UF_MSG_DEBUG("\tInstance: {} | {} | {}", name, - instance.materialID, - instance.lightmapID - ); - } + if ( graphMetadataJson["debug"]["print"]["instances"].as() ) { + UF_MSG_DEBUG("Instances: {}", graph.instances.size()); + for ( auto& name : graph.instances ) { + auto& instance = storage.instances[name]; + UF_MSG_DEBUG("\tInstance: {} | {} | {}", name, + instance.materialID, + instance.lightmapID + ); } } - #endif if ( graphMetadataJson["debug"]["print"]["materials"].as() ) { UF_MSG_DEBUG("Materials: {}", graph.materials.size()); for ( auto& name : graph.materials ) { @@ -1146,6 +1173,7 @@ void uf::graph::process( pod::Graph& graph ) { #endif uf::graph::reload(); + storage.instanceAddresses.keys = storage.instances.keys; UF_DEBUG_TIMER_MULTITRACE_END("Processed graph."); } void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent ) { @@ -1289,34 +1317,32 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent ) } } } - + // what a mess + node.object = storage.entities.keys.size(); + auto objectKeyName = ::objectKey( node ); + storage.entities[objectKeyName] = &entity; + auto& objectData = storage.objects[objectKeyName]; + auto model = uf::transform::model( transform ); + objectData.model = model; + objectData.previous = model; + // if ( 0 <= node.mesh && node.mesh < graph.meshes.size() ) { + auto model = uf::transform::model( transform ); auto& mesh = storage.meshes.map[graph.meshes[node.mesh]]; auto& primitives = storage.primitives.map[graph.primitives[node.mesh]]; - node.object = storage.entities.keys.size(); - auto objectKeyName = ::objectKey( node ); - storage.entities[objectKeyName] = &entity; - auto& objectData = storage.objects[objectKeyName]; - auto model = uf::transform::model( transform ); - objectData.model = model; - objectData.previous = model; - pod::Instance::Bounds bounds; - pod::DrawCommand* drawCommands = NULL; - if ( mesh.indirect.count && mesh.indirect.count <= primitives.size() ) { - auto& attribute = mesh.indirect.attributes.front(); - auto& buffer = mesh.buffers[mesh.isInterleaved(mesh.indirect.interleaved) ? mesh.indirect.interleaved : attribute.buffer]; - drawCommands = (pod::DrawCommand*) buffer.data(); - } // setup instances - for ( auto primitiveID = 0; primitiveID < primitives.size(); ++primitiveID ) { - auto& primitive = primitives[primitiveID]; - auto& instance = primitive.instance; - auto& drawCommand = primitive.drawCommand; - auto instanceID = primitiveID; + for ( auto i = 0; i < primitives.size(); ++i ) { + auto& primitive = primitives[i]; + + size_t instanceID = storage.instances.keys.size(); + auto instanceKeyName = graph.instances.emplace_back(std::to_string(instanceID)); + + auto& instance = storage.instances[instanceKeyName]; + instance = primitive.instance; instance.objectID = node.object; instance.jointID = graphMetadataJson["renderer"]["skinned"].as() ? 0 : -1; @@ -1324,8 +1350,13 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent ) bounds.min = uf::vector::min( bounds.min, instance.bounds.min ); bounds.max = uf::vector::max( bounds.max, instance.bounds.max ); - drawCommand.instanceID = instanceID; - if ( drawCommands ) drawCommands[primitiveID].instanceID = instanceID; + if ( mesh.indirect.count && mesh.indirect.count <= primitives.size() ) { + auto& attribute = mesh.indirect.attributes.front(); + auto& buffer = mesh.buffers[mesh.isInterleaved(mesh.indirect.interleaved) ? mesh.indirect.interleaved : attribute.buffer]; + pod::DrawCommand* drawCommands = (pod::DrawCommand*) buffer.data(); + auto& drawCommand = drawCommands[i]; + drawCommand.instanceID = instanceID; + } } #if !UF_GRAPH_EXTENDED if ( graphMetadataJson["renderer"]["render"].as() ) { @@ -1348,33 +1379,22 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent ) pod::Vector3f center = (max + min) * 0.5f; pod::Vector3f corner = uf::vector::abs(max - min) * 0.5f; - UF_MSG_DEBUG("{}: Center: {} | Corner: {}", node.name, uf::vector::toString( center ), uf::vector::toString( corner )); - UF_MSG_DEBUG("{}: Min: {} | Max: {}", node.name, uf::vector::toString( min ), uf::vector::toString( max )); - if ( ext::json::isNull( metadataJson["physics"]["center"] ) ) metadataJson["physics"]["center"] = uf::vector::encode( center ); if ( ext::json::isNull( metadataJson["physics"]["corner"] ) ) metadataJson["physics"]["corner"] = uf::vector::encode( corner ); if ( ext::json::isNull( metadataJson["physics"]["min"] ) ) metadataJson["physics"]["min"] = uf::vector::encode( min ); if ( ext::json::isNull( metadataJson["physics"]["max"] ) ) metadataJson["physics"]["max"] = uf::vector::encode( max ); } - #if !UF_GRAPH_EXTENDED - #if UF_USE_REACTPHYSICS if ( type == "mesh" ) { - auto& collider = entity.getComponent(); - collider.stats.mass = phyziks["mass"].as(collider.stats.mass); - collider.stats.friction = phyziks["friction"].as(collider.stats.friction); - collider.stats.restitution = phyziks["restitution"].as(collider.stats.restitution); - collider.stats.inertia = uf::vector::decode( phyziks["inertia"], collider.stats.inertia ); - collider.stats.gravity = uf::vector::decode( phyziks["gravity"], collider.stats.gravity ); + auto& physicsBody = entity.getComponent(); + float mass = phyziks["mass"].as(physicsBody.mass); + + physicsBody.material.staticFriction = phyziks["friction"].as(physicsBody.material.staticFriction); + physicsBody.material.restitution = phyziks["restitution"].as(physicsBody.material.restitution); + physicsBody.inertiaTensor = uf::vector::decode( phyziks["inertia"], physicsBody.inertiaTensor ); + physicsBody.gravity = uf::vector::decode( phyziks["gravity"], physicsBody.gravity ); - uf::physics::impl::create( entity.as(), mesh, !phyziks["static"].as(true) ); - } - #else - if ( type == "mesh" ) { - auto phyziks["mass"].as(collider.stats.mass); uf::physics::impl::create( entity.as(), mesh, mass ); } - #endif - #endif } } } @@ -1430,23 +1450,17 @@ void uf::graph::tick( uf::Object& object ) { } bool uf::graph::tick( pod::Graph::Storage& storage ) { bool rebuild = false; - uf::stl::vector instances; instances.reserve(storage.primitives.map.size()); + uf::stl::vector instances = storage.instances.flatten(); uf::stl::vector instanceAddresses = storage.instanceAddresses.flatten(); uf::stl::vector joints; joints.reserve(storage.joints.map.size()); uf::stl::vector objects = storage.objects.flatten(); - for ( auto& key : storage.primitives.keys ) { - for ( auto& primitive : storage.primitives.map[key] ) { - instances.emplace_back( primitive.instance ); - } - } - for ( auto& key : storage.joints.keys ) { auto& matrices = storage.joints.map[key]; joints.reserve( joints.size() + matrices.size() ); for ( auto& mat : matrices ) joints.emplace_back( mat ); } - + rebuild = storage.buffers.instance.update( (const void*) instances.data(), instances.size() * sizeof(pod::Instance) ) || rebuild; rebuild = storage.buffers.instanceAddresses.update( (const void*) instanceAddresses.data(), instanceAddresses.size() * sizeof(pod::Instance::Addresses) ) || rebuild; rebuild = storage.buffers.joint.update( (const void*) joints.data(), joints.size() * sizeof(pod::Matrix4f) ) || rebuild; @@ -1455,13 +1469,9 @@ bool uf::graph::tick( pod::Graph::Storage& storage ) { if ( ::newGraphAdded ) { uf::stl::vector materials = storage.materials.flatten(); uf::stl::vector textures = storage.textures.flatten(); - uf::stl::vector drawCommands; drawCommands.reserve(storage.primitives.map.size()); + uf::stl::vector drawCommands; drawCommands.reserve(storage.drawCommands.map.size()); - for ( auto& key : storage.primitives.keys ) { - for ( auto& primitive : storage.primitives.map[key] ) { - drawCommands.emplace_back( primitive.drawCommand ); - } - } + for ( auto& key : storage.drawCommands.keys ) drawCommands.insert( drawCommands.end(), storage.drawCommands.map[key].begin(), storage.drawCommands.map[key].end() ); rebuild = storage.buffers.drawCommands.update( (const void*) drawCommands.data(), drawCommands.size() * sizeof(pod::DrawCommand) ) || rebuild; rebuild = storage.buffers.material.update( (const void*) materials.data(), materials.size() * sizeof(pod::Material) ) || rebuild; @@ -1521,7 +1531,7 @@ void uf::graph::render( pod::Graph::Storage& storage ) { storage.buffers.camera.update( (const void*) &viewport, sizeof(pod::Camera::Viewports) ); #if UF_USE_VULKAN - if ( !renderMode || !renderMode->hasBuffer("camera") || renderMode->getType() == "Swapchain" ) return; // for some reason causes clang ASAN to cry + if ( !renderMode || !renderMode->hasBuffer("camera") || renderMode->getType() == "Swapchain" ) return; auto& buffer = renderMode->getBuffer("camera"); buffer.update( (const void*) &viewport, sizeof(pod::Camera::Viewports) ); #endif @@ -1929,7 +1939,6 @@ void uf::graph::reload( pod::Graph& graph, pod::Node& node ) { // bind mesh to physics state // to-do: figure out why the mesh just suddenly breaks when re-streamed in dreamcast (could just be the version of reactphysics) { - #if UF_USE_REACTPHYSICS auto phyziks = tag["physics"]; if ( !ext::json::isObject( phyziks ) ) phyziks = metadataJson["physics"]; else metadataJson["physics"] = phyziks; @@ -1937,39 +1946,22 @@ void uf::graph::reload( pod::Graph& graph, pod::Node& node ) { if ( ext::json::isObject( phyziks ) ) { uf::stl::string type = phyziks["type"].as(); if ( type == "mesh" ) { - bool exists = entity.hasComponent(); + bool exists = entity.hasComponent(); if ( exists ) { uf::physics::impl::destroy( entity ); } - auto& collider = entity.getComponent(); - collider.stats.mass = phyziks["mass"].as(collider.stats.mass); - collider.stats.friction = phyziks["friction"].as(collider.stats.friction); - collider.stats.restitution = phyziks["restitution"].as(collider.stats.restitution); - collider.stats.inertia = uf::vector::decode( phyziks["inertia"], collider.stats.inertia ); - collider.stats.gravity = uf::vector::decode( phyziks["gravity"], collider.stats.gravity ); + auto& physicsBody = entity.getComponent(); + float mass = phyziks["mass"].as(physicsBody.mass); + + physicsBody.material.staticFriction = phyziks["friction"].as(physicsBody.material.staticFriction); + physicsBody.material.restitution = phyziks["restitution"].as(physicsBody.material.restitution); + physicsBody.inertiaTensor = uf::vector::decode( phyziks["inertia"], physicsBody.inertiaTensor ); + physicsBody.gravity = uf::vector::decode( phyziks["gravity"], physicsBody.gravity ); - uf::physics::impl::create( entity, mesh, !phyziks["static"].as(true) ); + uf::physics::impl::create( entity.as(), mesh, mass ); } } - #else - auto phyziks = tag["physics"]; - if ( !ext::json::isObject( phyziks ) ) phyziks = metadataJson["physics"]; - else metadataJson["physics"] = phyziks; - - if ( ext::json::isObject( phyziks ) ) { - uf::stl::string type = phyziks["type"].as(); - if ( type == "mesh" ) { - bool exists = entity.hasComponent(); - if ( exists ) { - uf::physics::impl::destroy( entity ); - } - - auto mass = phyziks["mass"].as(0.0f); - uf::physics::impl::create( entity, mesh, mass ); - } - } - #endif } } void uf::graph::reload( pod::Graph& graph ) { @@ -2061,4 +2053,4 @@ void uf::graph::update( pod::Graph& graph, float delta ) { #endif uf::graph::updateAnimation( graph, delta ); -} \ No newline at end of file +} diff --git a/engine/src/engine/object/behavior.cpp b/engine/src/engine/object/behavior.cpp index 26006201..c962a204 100644 --- a/engine/src/engine/object/behavior.cpp +++ b/engine/src/engine/object/behavior.cpp @@ -131,29 +131,6 @@ void uf::ObjectBehavior::initialize( uf::Object& self ) { if ( ext::json::isObject(metadataJson["physics"]) ) { auto& metadataJsonPhysics = metadataJson["physics"]; - #if UF_USE_REACTPHYSICS - auto& collider = this->getComponent(); - collider.stats.flags = metadataJsonPhysics["flags"].as(collider.stats.flags); - collider.stats.mass = metadataJsonPhysics["mass"].as(collider.stats.mass); - collider.stats.restitution = metadataJsonPhysics["restitution"].as(collider.stats.restitution); - collider.stats.friction = metadataJsonPhysics["friction"].as(collider.stats.friction); - collider.stats.inertia = uf::vector::decode( metadataJsonPhysics["inertia"], collider.stats.inertia ); - collider.stats.gravity = uf::vector::decode( metadataJsonPhysics["gravity"], collider.stats.gravity ); - - if ( metadataJsonPhysics["type"].as() == "bounding box" ) { - pod::Vector3f center = uf::vector::decode( metadataJsonPhysics["center"], pod::Vector3f{} ); - pod::Vector3f corner = uf::vector::decode( metadataJsonPhysics["corner"], pod::Vector3f{0.5, 0.5, 0.5} ); - - if ( metadataJsonPhysics["recenter"].as(true) ) collider.transform.position = (center - transform.position); - - uf::physics::impl::create( *this, corner ); - } else if ( metadataJsonPhysics["type"].as() == "capsule" ) { - float radius = metadataJsonPhysics["radius"].as(); - float height = metadataJsonPhysics["height"].as(); - - uf::physics::impl::create( *this, radius, height ); - } - #else auto type = metadataJsonPhysics["type"].as(); float mass = metadataJsonPhysics["mass"].as(); @@ -162,6 +139,10 @@ void uf::ObjectBehavior::initialize( uf::Object& self ) { if ( type == "bounding box" || type == "aabb" ) { pod::Vector3f min = uf::vector::decode( metadataJsonPhysics["min"], pod::Vector3f{-0.5f, -0.5f, -0.5f} ); pod::Vector3f max = uf::vector::decode( metadataJsonPhysics["max"], pod::Vector3f{0.5f, 0.5f, 0.5f} ); + #if UF_USE_REACTPHYSICS + auto center = ( max + min ) * 0.5f; + if ( metadataJsonPhysics["recenter"].as(true) ) offset = (center - transform.position); + #endif uf::physics::impl::create( self, pod::AABB{ .min = min, .max = max }, mass, offset ); } else if ( type == "plane" ) { @@ -175,20 +156,39 @@ void uf::ObjectBehavior::initialize( uf::Object& self ) { uf::physics::impl::create( self, pod::Sphere{ radius }, mass, offset ); } else if ( type == "capsule" ) { float radius = metadataJsonPhysics["radius"].as(); - float height = metadataJsonPhysics["height"].as(); + float halfHeight = metadataJsonPhysics["height"].as() * 0.5f; - uf::physics::impl::create( self, pod::Capsule{ radius, height * 0.5f }, mass, offset ); + uf::physics::impl::create( self, pod::Capsule{ radius, halfHeight }, mass, offset ); } - if ( this->hasComponent() ) { - auto& body = this->getComponent(); + if ( this->hasComponent() ) { + auto& physicsBody = this->getComponent(); + + auto gravity = uf::vector::decode( metadataJsonPhysics["gravity"], physicsBody.gravity ); + auto category = metadataJsonPhysics["category"].as("ALL"); + auto mask = metadataJsonPhysics["mask"].as("ALL"); + + #if UF_USE_REACTPHYSICS + physicsBody.mass = mass; + physicsBody.gravity = gravity; + + physicsBody.material.restitution = metadataJsonPhysics["restitution"].as(physicsBody.material.restitution); + physicsBody.material.staticFriction = metadataJsonPhysics["friction"].as(physicsBody.material.staticFriction); + physicsBody.inertiaTensor = uf::vector::decode( metadataJsonPhysics["inertia"], physicsBody.inertiaTensor ); + #else + uf::physics::impl::setColliderCategory( physicsBody, category ); + uf::physics::impl::setColliderMask( physicsBody, mask ); + uf::physics::impl::setGravity( physicsBody, gravity ); + #endif + + physicsBody.velocity = uf::vector::decode( metadataJsonPhysics["velocity"], physicsBody.velocity ); + physicsBody.angularVelocity = uf::vector::decode( metadataJsonPhysics["angularVelocity"], physicsBody.angularVelocity ); if ( this->getName() == "Player" ) { - body.inertiaTensor = { FLT_MAX, FLT_MAX, FLT_MAX }; - body.inverseInertiaTensor = { 0.0f, 0.0f, 0.0f }; + physicsBody.inertiaTensor = { FLT_MAX, FLT_MAX, FLT_MAX }; + physicsBody.inverseInertiaTensor = { 0.0f, 0.0f, 0.0f }; } } - #endif } UF_BEHAVIOR_METADATA_BIND_SERIALIZER_HOOKS(metadata, metadataJson); @@ -232,10 +232,10 @@ void uf::ObjectBehavior::destroy( uf::Object& self ) { // this->deleteComponent(); } #if UF_USE_REACTPHYSICS - if ( this->hasComponent() ) { - auto& collider = this->getComponent(); - uf::physics::impl::detach( collider ); - // this->deleteComponent(); + if ( this->hasComponent() ) { + auto& physicsBody = this->getComponent(); + uf::physics::impl::detach( physicsBody ); + // this->deleteComponent(); } #endif if ( this->hasComponent() ) { diff --git a/engine/src/engine/object/object.cpp b/engine/src/engine/object/object.cpp index 0344c047..6f6677ac 100644 --- a/engine/src/engine/object/object.cpp +++ b/engine/src/engine/object/object.cpp @@ -345,16 +345,6 @@ bool uf::Object::load( const uf::Serializer& _json ) { } } } - // Set movement - #if UF_USE_REACTPHYSICS - if ( ext::json::isObject( json["physics"] ) && !this->hasComponent() ) { - auto& physics = this->getComponent(); - physics.velocity = uf::vector::decode( json["physics"]["linear"]["velocity"], physics.velocity ); - physics.acceleration = uf::vector::decode( json["physics"]["linear"]["acceleration"], physics.acceleration ); - physics.angularVelocity = uf::vector::decode( json["physics"]["rotational"]["velocity"], physics.angularVelocity ); - physics.angularAcceleration = uf::vector::decode( json["physics"]["rotational"]["acceleration"], physics.angularAcceleration ); - } - #endif // Load assets this->loadAssets( json ); diff --git a/engine/src/ext/gltf/gltf.cpp b/engine/src/ext/gltf/gltf.cpp index 7e551a4b..091ce053 100644 --- a/engine/src/ext/gltf/gltf.cpp +++ b/engine/src/ext/gltf/gltf.cpp @@ -253,7 +253,8 @@ void ext::gltf::load( pod::Graph& graph, const uf::stl::string& filename, const } // load meshes { - size_t masterAuxID = 0; + size_t masterInstanceID = 0; + graph.meshes.reserve(model.meshes.size()); storage.meshes.reserve(model.meshes.size()); diff --git a/engine/src/ext/gltf/processPrimitives.inl b/engine/src/ext/gltf/processPrimitives.inl index fcc59c18..3ed92421 100644 --- a/engine/src/ext/gltf/processPrimitives.inl +++ b/engine/src/ext/gltf/processPrimitives.inl @@ -383,18 +383,15 @@ if ( meshopt.should ) { primitives.reserve( meshlets.size() ); for ( auto& meshlet : meshlets ) { - // to-do: check against the meshlet's actual primitive information - auto& drawCommand = drawCommands.emplace_back(pod::DrawCommand{ - .indices = meshlet.indices.size(), - .instances = 1, - .indexID = indexID, - .vertexID = vertexID, - .instanceID = meshlet.primitive.drawCommand.instanceID, - .auxID = meshlet.primitive.drawCommand.auxID, - .materialID = meshlet.primitive.drawCommand.materialID, - .vertices = meshlet.vertices.size(), - }); - + meshlet.primitive.drawCommand.instances = 1; + meshlet.primitive.drawCommand.instanceID = ++masterInstanceID; // this doesn't matter...... + meshlet.primitive.drawCommand.indexID = indexID; + meshlet.primitive.drawCommand.indices = meshlet.indices.size(); + meshlet.primitive.drawCommand.vertexID = vertexID; + meshlet.primitive.drawCommand.vertices = meshlet.vertices.size(); + + drawCommands.emplace_back(meshlet.primitive.drawCommand); + primitives.emplace_back( meshlet.primitive ); indexID += meshlet.indices.size(); diff --git a/engine/src/ext/lua/usertypes/physics.cpp b/engine/src/ext/lua/usertypes/physics.cpp index f257b559..6b3602cc 100644 --- a/engine/src/ext/lua/usertypes/physics.cpp +++ b/engine/src/ext/lua/usertypes/physics.cpp @@ -1,54 +1,56 @@ #include -#if UF_USE_LUA && UF_USE_REACTPHYSICS +#if UF_USE_LUA #include namespace binds { - bool hasBody( pod::Physics& self ) { return self.body; } - pod::Vector3f& linearVelocity( pod::Physics& self ) { return self.velocity; } - pod::Quaternion<>& rotationalVelocity( pod::Physics& self ) { return self.angularVelocity; } + bool hasBody( pod::PhysicsBody& self ) { return !!self.object; } + pod::Vector3f& velocity( pod::PhysicsBody& self ) { return self.velocity; } + void setVelocity( pod::PhysicsBody& self, const pod::Vector3f& v ) { self.velocity = v; } + void applyVelocity( pod::PhysicsBody& self, const pod::Vector3f& v ) { self.velocity += v; } - void setLinearVelocity( pod::Physics& self, const pod::Vector3f& v ) { self.velocity = v; } - void setRotationalVelocity( pod::Physics& self, const pod::Quaternion<>& v ) { self.angularVelocity = v; } - - void enableGravity( pod::PhysicsState& state, bool s ) { - if ( !state.body ) return; - state.body->enableGravity(s); + void enableGravity( pod::PhysicsBody& state, bool s ) { + if ( !state.object ) return; + #if UF_USE_REACTPHYSICS + state.collider.body->enableGravity(s); + #else + if ( s ) { + uf::physics::impl::setGravity( state, pod::Vector3f{ 0, -9.81f, 0 } ); + } else { + uf::physics::impl::setGravity( state ); + } + #endif } - void applyRotation( pod::PhysicsState& state, const pod::Quaternion<>& q ) { + void applyRotation( pod::PhysicsBody& state, const pod::Quaternion<>& q ) { return uf::physics::impl::applyRotation( state, q ); } - std::tuple rayCast( pod::Physics& self, const pod::Vector3f& center, const pod::Vector3f& direction ) { - float depth = -1; - uf::Object* object = uf::physics::impl::rayCast(self, center, direction, depth); - + std::tuple rayCast( pod::PhysicsBody& self, const pod::Vector3f& center, const pod::Vector3f& direction ) { + pod::RayQuery query = uf::physics::impl::rayCast( pod::Ray{center, direction}, self, uf::vector::norm( direction ) ); + uf::Object* object = query.hit ? query.body->object : NULL; + float depth = query.hit ? query.contact.penetration : -1; return std::make_tuple( object, depth ); } } #include -UF_LUA_REGISTER_USERTYPE_AND_COMPONENT(pod::Physics, +UF_LUA_REGISTER_USERTYPE_AND_COMPONENT(pod::PhysicsBody, UF_LUA_REGISTER_USERTYPE_DEFINE( hasBody, UF_LUA_C_FUN(::binds::hasBody) ), - UF_LUA_REGISTER_USERTYPE_DEFINE( linearVelocity, UF_LUA_C_FUN(::binds::linearVelocity) ), - UF_LUA_REGISTER_USERTYPE_DEFINE( rotationalVelocity, UF_LUA_C_FUN(::binds::rotationalVelocity) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( velocity, UF_LUA_C_FUN(::binds::velocity) ), - UF_LUA_REGISTER_USERTYPE_DEFINE( setLinearVelocity, UF_LUA_C_FUN(::binds::setLinearVelocity) ), - UF_LUA_REGISTER_USERTYPE_DEFINE( setRotationalVelocity, UF_LUA_C_FUN(::binds::setRotationalVelocity) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( setVelocity, UF_LUA_C_FUN(::binds::setVelocity) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( applyVelocity, UF_LUA_C_FUN(::binds::applyVelocity) ), - UF_LUA_REGISTER_USERTYPE_DEFINE( setVelocity, UF_LUA_C_FUN(uf::physics::impl::setVelocity) ), - UF_LUA_REGISTER_USERTYPE_DEFINE( setImpulse, UF_LUA_C_FUN(uf::physics::impl::setImpulse) ), UF_LUA_REGISTER_USERTYPE_DEFINE( applyImpulse, UF_LUA_C_FUN(uf::physics::impl::applyImpulse) ), - UF_LUA_REGISTER_USERTYPE_DEFINE( applyMovement, UF_LUA_C_FUN(uf::physics::impl::applyMovement) ), - UF_LUA_REGISTER_USERTYPE_DEFINE( applyVelocity, UF_LUA_C_FUN(uf::physics::impl::applyVelocity) ), UF_LUA_REGISTER_USERTYPE_DEFINE( applyRotation, UF_LUA_C_FUN(::binds::applyRotation) ), UF_LUA_REGISTER_USERTYPE_DEFINE( enableGravity, UF_LUA_C_FUN(::binds::enableGravity) ), - UF_LUA_REGISTER_USERTYPE_DEFINE( activateCollision, UF_LUA_C_FUN(uf::physics::impl::activateCollision) ), + UF_LUA_REGISTER_USERTYPE_DEFINE( rayCast, UF_LUA_C_FUN(::binds::rayCast) ) + +// UF_LUA_REGISTER_USERTYPE_DEFINE( setImpulse, UF_LUA_C_FUN(uf::physics::impl::setImpulse) ), +// UF_LUA_REGISTER_USERTYPE_DEFINE( activateCollision, UF_LUA_C_FUN(uf::physics::impl::activateCollision) ), - UF_LUA_REGISTER_USERTYPE_DEFINE( rayCast, UF_LUA_C_FUN(::binds::rayCast) ), - - UF_LUA_REGISTER_USERTYPE_DEFINE( getMass, UF_LUA_C_FUN(uf::physics::impl::getMass) ), - UF_LUA_REGISTER_USERTYPE_DEFINE( setMass, UF_LUA_C_FUN(uf::physics::impl::setMass) ) +// UF_LUA_REGISTER_USERTYPE_DEFINE( getMass, UF_LUA_C_FUN(uf::physics::impl::getMass) ), +// UF_LUA_REGISTER_USERTYPE_DEFINE( setMass, UF_LUA_C_FUN(uf::physics::impl::setMass) ), ) #endif \ No newline at end of file diff --git a/engine/src/ext/reactphysics/reactphysics.cpp b/engine/src/ext/reactphysics/reactphysics.cpp index 5f5053e0..6df48a84 100644 --- a/engine/src/ext/reactphysics/reactphysics.cpp +++ b/engine/src/ext/reactphysics/reactphysics.cpp @@ -212,7 +212,7 @@ namespace { // allows showing collision models void debugDraw( uf::Object& object ) { auto& scene = uf::scene::getCurrentScene(); - auto& world = ext::reactphysics::globalStorage ? ::world : scene.getComponent(); + auto& world = /*ext::reactphysics::globalStorage ? ::world :*/ scene.getComponent(); static size_t oldCount = 0; uf::Mesh mesh; @@ -322,7 +322,7 @@ void ext::reactphysics::initialize( uf::Object& scene ) { // logger->addFileDestination("./data/logs/rp3d_log_.html", logLevel, rp3d::DefaultLogger::Format::HTML); // ::common.setLogger(::logger); - auto& world = ext::reactphysics::globalStorage ? ::world : scene.getComponent(); + auto& world = /*ext::reactphysics::globalStorage ? ::world :*/ scene.getComponent(); world = ::common.createPhysicsWorld(settings); // world->setEventListener(&::listener); @@ -340,7 +340,7 @@ void ext::reactphysics::tick( float delta ) { return ext::reactphysics::tick( uf::scene::getCurrentScene(), delta ); } void ext::reactphysics::tick( uf::Object& scene, float delta ) { - auto& world = ext::reactphysics::globalStorage ? ::world : scene.getComponent(); + auto& world = /*ext::reactphysics::globalStorage ? ::world :*/ scene.getComponent(); ext::reactphysics::syncTo( world ); static float accumulator = 0; @@ -360,15 +360,15 @@ void ext::reactphysics::terminate() { return ext::reactphysics::terminate( uf::scene::getCurrentScene() ); } void ext::reactphysics::terminate( uf::Object& scene ) { - auto& world = ext::reactphysics::globalStorage ? ::world : scene.getComponent(); + auto& world = /*ext::reactphysics::globalStorage ? ::world :*/ scene.getComponent(); if ( !world ) return; size_t count = world->getNbRigidBodies(); for ( size_t i = 0; i < count; ++i ) { auto* body = world->getRigidBody(i); if ( !body ) continue; uf::Object* object = (uf::Object*) body->getUserData(); if ( !object || !object->isValid() ) continue; - auto& state = object->getComponent(); // if ( !state.shared ) continue; - state.body = NULL; + auto& state = object->getComponent(); + state.collider.body = NULL; } ::common.destroyPhysicsWorld(world); @@ -376,22 +376,22 @@ void ext::reactphysics::terminate( uf::Object& scene ) { } // base collider creation -pod::PhysicsState& ext::reactphysics::create( uf::Object& object ) { - auto& state = object.getComponent(); +pod::PhysicsBody& ext::reactphysics::create( uf::Object& object, float mass, const pod::Vector3f& offset ) { + auto& state = object.getComponent(); state.world = ext::reactphysics::globalStorage ? ::world : uf::scene::getCurrentScene().getComponent(); - state.uid = object.getUid(); state.object = &object; + state.transform.position = offset; state.transform.reference = &object.getComponent>(); - state.shared = ext::reactphysics::shared; - - UF_MSG_DEBUG("Created physics state: {}", uf::string::toString( object )); + state.mass = mass; + state.isStatic = mass != 0.0f; + state.inverseMass = mass == 0.0f ? 0.0f : 1.0f / mass; return state; } void ext::reactphysics::destroy( uf::Object& object ) { - auto& state = object.getComponent(); + auto& state = object.getComponent(); ext::reactphysics::destroy( state ); auto uid = object.getUid(); @@ -403,14 +403,14 @@ void ext::reactphysics::destroy( uf::Object& object ) { ::triangleParts.erase( uid ); } } -void ext::reactphysics::destroy( pod::PhysicsState& state ) { +void ext::reactphysics::destroy( pod::PhysicsBody& state ) { ext::reactphysics::detach( state ); } -void ext::reactphysics::attach( pod::PhysicsState& state ) { - if ( !state.shape || !state.world ) return; +void ext::reactphysics::attach( pod::PhysicsBody& state ) { + if ( !state.collider.shape || !state.world ) return; // auto& scene = uf::scene::getCurrentScene(); - // auto& world = ext::reactphysics::globalStorage ? ::world : scene.getComponent(); + // auto& world = /*ext::reactphysics::globalStorage ? ::world :*/ scene.getComponent(); rp3d::Transform colliderTransform = rp3d::Transform::identity(); colliderTransform.setPosition( ::convert( state.transform.position ) ); @@ -419,77 +419,88 @@ void ext::reactphysics::attach( pod::PhysicsState& state ) { state.transform.position = {}; state.transform.orientation = {}; - state.body = state.world->createRigidBody( ::convert( *state.transform.reference ) ); + state.collider.body = state.world->createRigidBody( ::convert( *state.transform.reference ) ); - auto* collider = state.body->addCollider(state.shape, colliderTransform); + auto* collider = state.collider.body->addCollider(state.collider.shape, colliderTransform); collider->setCollisionCategoryBits(0xFF); collider->setCollideWithMaskBits(0xFF); - state.body->setUserData(state.object); - state.body->setMass(state.stats.mass); + state.collider.body->setUserData(state.object); + state.collider.body->setMass(state.mass); - if ( state.stats.mass != 0.0f ) { - state.body->setType(rp3d::BodyType::DYNAMIC); - state.body->updateLocalCenterOfMassFromColliders(); - state.body->updateMassPropertiesFromColliders(); + if ( state.mass != 0.0f ) { + state.collider.body->setType(rp3d::BodyType::DYNAMIC); + state.collider.body->updateLocalCenterOfMassFromColliders(); + state.collider.body->updateMassPropertiesFromColliders(); } else { - state.body->setType(rp3d::BodyType::STATIC); + state.collider.body->setType(rp3d::BodyType::STATIC); } - state.body->enableGravity(state.stats.gravity != pod::Vector3f{0,0,0}); + state.collider.body->enableGravity(state.gravity != pod::Vector3f{0,0,0}); // affects air speed, bad -// state.body->setLinearDamping(state.stats.friction); +// state.collider.body->setLinearDamping(state.material.staticFriction); auto& material = collider->getMaterial(); material.setBounciness(0); - state.body->setLocalInertiaTensor( ::convert( state.stats.inertia ) ); + state.collider.body->setLocalInertiaTensor( ::convert( state.inertiaTensor ) ); } -void ext::reactphysics::detach( pod::PhysicsState& state ) { - if ( !state.body || !state.world ) return; +void ext::reactphysics::detach( pod::PhysicsBody& state ) { + if ( !state.collider.body || !state.world ) return; // auto& scene = uf::scene::getCurrentScene(); - // auto& world = ext::reactphysics::globalStorage ? ::world : scene.getComponent(); + // auto& world = /*ext::reactphysics::globalStorage ? ::world :*/ scene.getComponent(); - state.world->destroyRigidBody(state.body); - state.body = NULL; + state.world->destroyRigidBody(state.collider.body); + state.collider.body = NULL; state = {}; // necessary if it gets reused } // collider for mesh (static or dynamic) -pod::PhysicsState& ext::reactphysics::create( uf::Object& object, const uf::Mesh& mesh, bool dynamic ) { +pod::PhysicsBody& ext::reactphysics::create( uf::Object& object, const uf::Mesh& mesh, float mass, const pod::Vector3f& offset ) { UF_ASSERT( mesh.index.count ); auto* rMesh = ::createTriangleMesh( mesh, object ); - auto& state = ext::reactphysics::create( object ); - state.shape = ::common.createConcaveMeshShape( rMesh ); - state.stats.mass = 0; + auto& state = ext::reactphysics::create( object, mass, offset ); + state.collider.shape = ::common.createConcaveMeshShape( rMesh ); + state.mass = 0; ext::reactphysics::attach( state ); - UF_MSG_DEBUG("Created physics state (mesh): {}", uf::string::toString( object )); - return state; } // collider for boundingbox -pod::PhysicsState& ext::reactphysics::create( uf::Object& object, const pod::Vector3f& extent ) { - auto& state = ext::reactphysics::create( object ); - state.shape = ::common.createBoxShape( rp3d::Vector3( abs(extent.x), abs(extent.y), abs(extent.z) ) ); +pod::PhysicsBody& ext::reactphysics::create( uf::Object& object, const pod::AABB& aabb, float mass, const pod::Vector3f& offset ) { + pod::Vector3f extent = ( aabb.max - aabb.min ) * 0.5f; + auto& state = ext::reactphysics::create( object, mass, offset ); + state.collider.shape = ::common.createBoxShape( rp3d::Vector3( abs(extent.x), abs(extent.y), abs(extent.z) ) ); + ext::reactphysics::attach( state ); + + return state; +} +// +pod::PhysicsBody& ext::reactphysics::create( uf::Object& object, const pod::Sphere& aabb, float mass, const pod::Vector3f& offset ) { + auto& state = ext::reactphysics::create( object, mass, offset ); + //state.collider.shape = ::common.createSphereShape( rp3d::Vector3( abs(extent.x), abs(extent.y), abs(extent.z) ) ); + ext::reactphysics::attach( state ); + + return state; +} +// +pod::PhysicsBody& ext::reactphysics::create( uf::Object& object, const pod::Plane& aabb, float mass, const pod::Vector3f& offset ) { + auto& state = ext::reactphysics::create( object, mass, offset ); + //state.collider.shape = ::common.createPlaneShape( rp3d::Vector3( abs(extent.x), abs(extent.y), abs(extent.z) ) ); ext::reactphysics::attach( state ); - UF_MSG_DEBUG("Created physics state (box): {}", uf::string::toString( object )); - return state; } // collider for capsule -pod::PhysicsState& ext::reactphysics::create( uf::Object& object, float radius, float height ) { - auto& state = ext::reactphysics::create( object ); - state.shape = ::common.createCapsuleShape( radius, height ); +pod::PhysicsBody& ext::reactphysics::create( uf::Object& object, const pod::Capsule& capsule, float mass, const pod::Vector3f& offset ) { + auto& state = ext::reactphysics::create( object, mass, offset ); + state.collider.shape = ::common.createCapsuleShape( capsule.radius, capsule.halfHeight * 2.0f ); ext::reactphysics::attach( state ); - UF_MSG_DEBUG("Created physics state (capsule): {} | {}, {}", uf::string::toString( object ), radius, height); - return state; } @@ -512,9 +523,9 @@ void ext::reactphysics::syncTo( ext::reactphysics::WorldState& world ) { for ( size_t i = 0; i < count; ++i ) { auto* body = world->getRigidBody(i); if ( !body ) continue; uf::Object* object = (uf::Object*) body->getUserData(); if ( !object || !object->isValid() ) continue; - auto& state = object->getComponent(); // if ( !state.shared ) continue; + auto& state = object->getComponent(); - if ( state.shared ) { + if ( true /*state\.shared*/ ) { if ( !ext::reactphysics::interpolate ) body->setTransform(::convert(state.transform)); body->setLinearVelocity( ::convert(state.velocity) ); body->setAngularVelocity( ::convertQ(state.angularVelocity) ); @@ -524,9 +535,9 @@ void ext::reactphysics::syncTo( ext::reactphysics::WorldState& world ) { switch ( ext::reactphysics::gravity::mode ) { case ext::reactphysics::gravity::Mode::PER_OBJECT: if ( body->isGravityEnabled() ) { #if RP3D_OLD - body->applyForceToCenterOfMass( ::convert(state.stats.gravity * mass) ); + body->applyForceToCenterOfMass( ::convert(state.gravity * mass) ); #else - body->applyLocalForceAtCenterOfMass( ::convert(state.stats.gravity * mass) ); + body->applyLocalForceAtCenterOfMass( ::convert(state.gravity * mass) ); #endif } break; case ext::reactphysics::gravity::Mode::UNIVERSAL: if ( mass > 0 ) { @@ -575,170 +586,131 @@ void ext::reactphysics::syncFrom( ext::reactphysics::WorldState& world, float in auto* body = world->getRigidBody(i); if ( !body ) continue; uf::Object* object = (uf::Object*) body->getUserData(); if ( !object || !object->isValid() ) continue; - auto& state = object->getComponent(); - - if ( !state.object ) { - state.object = object; - //continue; - } + auto& state = object->getComponent(); + if ( !state.object ) state.object = object; auto& transform = state.object->getComponent>(); - auto& physics = state.object->getComponent(); - - /* - transform.position = ::convert( body->getTransform().getPosition() ); - transform.orientation = ::convert( body->getTransform().getOrientation() ); - - // state transform is an offset, un-offset - if ( state.transform.reference ) transform.position -= state.transform.position; - - // transform = uf::transform::reorient( transform ); - */ state.internal.current.transform = ::convert( body->getTransform() ); state.internal.current.velocity = ::convert( body->getLinearVelocity() ); state.internal.current.angularVelocity = ::convertQ( body->getAngularVelocity() ); - physics.velocity = state.internal.current.velocity; - physics.angularVelocity = state.internal.current.angularVelocity; + state.velocity = state.internal.current.velocity; + state.angularVelocity = state.internal.current.angularVelocity; if ( !ext::reactphysics::interpolate ) { transform.position = state.internal.current.transform.position; transform.orientation = state.internal.current.transform.orientation; - // state transform is an offset, un-offset if ( state.transform.reference ) transform.position -= state.transform.position; - - // transform = uf::transform::reorient( transform ); } else { - // transform = uf::transform::interpolate( state.internal.previous.transform, state.internal.current.transform, interp ); - transform.position = state.internal.previous.transform.position * ( 1.0f - interp ) + state.internal.current.transform.position * interp; transform.orientation = uf::quaternion::slerp( state.internal.previous.transform.orientation, state.internal.current.transform.orientation, interp); + // state transform is an offset, un-offset if ( state.transform.reference ) transform.position -= state.transform.position; - - // physics.velocity = uf::vector::lerp( state.internal.previous.velocity, state.internal.current.velocity, interp ); - // physics.angularVelocity = uf::quaternion::slerp( state.internal.previous.angularVelocity, state.internal.current.angularVelocity, interp ); } } } // apply impulse -void ext::reactphysics::setImpulse( pod::PhysicsState& state, const pod::Vector3f& v ) { - if ( !state.body ) return; +void ext::reactphysics::setImpulse( pod::PhysicsBody& state, const pod::Vector3f& v ) { + if ( !state.collider.body ) return; #if !RP3D_OLD - state.body->resetForce(); - state.body->resetTorque(); + state.collider.body->resetForce(); + state.collider.body->resetTorque(); #endif - state.body->setLinearVelocity( ::convert(pod::Vector3f{}) ); - state.body->setAngularVelocity( ::convert(pod::Vector3f{}) ); + state.collider.body->setLinearVelocity( ::convert(pod::Vector3f{}) ); + state.collider.body->setAngularVelocity( ::convert(pod::Vector3f{}) ); // ext::reactphysics::applyImpulse( state, v ); } -void ext::reactphysics::applyImpulse( pod::PhysicsState& state, const pod::Vector3f& v ) { - if ( !state.body ) return; +void ext::reactphysics::applyImpulse( pod::PhysicsBody& state, const pod::Vector3f& v ) { + if ( !state.collider.body ) return; #if RP3D_OLD - state.body->applyForceToCenterOfMass( ::convert(v) ); + state.collider.body->applyForceToCenterOfMass( ::convert(v) ); #else - state.body->applyLocalForceAtCenterOfMass( ::convert(v) ); + state.collider.body->applyLocalForceAtCenterOfMass( ::convert(v) ); #endif } // directly move a transform -void ext::reactphysics::applyMovement( pod::PhysicsState& state, const pod::Vector3f& v ) { - if ( !state.body ) return; +void ext::reactphysics::applyMovement( pod::PhysicsBody& state, const pod::Vector3f& v ) { + if ( !state.collider.body ) return; - rp3d::Transform transform = state.body->getTransform(); + rp3d::Transform transform = state.collider.body->getTransform(); transform.setPosition( transform.getPosition() + ::convert(v) * uf::physics::time::delta ); - state.body->setTransform(transform); + state.collider.body->setTransform(transform); } // directly apply a velocity -void ext::reactphysics::setVelocity( pod::PhysicsState& state, const pod::Vector3f& v ) { - if ( !state.body ) return; - if ( state.shared ) { - auto& physics = state.object->getComponent(); - physics.velocity = v; - // return; - } - state.body->setLinearVelocity( ::convert(v) ); +void ext::reactphysics::setVelocity( pod::PhysicsBody& state, const pod::Vector3f& v ) { + if ( !state.collider.body ) return; + + state.velocity = v; + state.collider.body->setLinearVelocity( ::convert(v) ); } -void ext::reactphysics::applyVelocity( pod::PhysicsState& state, const pod::Vector3f& v ) { - if ( !state.body ) return; +void ext::reactphysics::applyVelocity( pod::PhysicsBody& state, const pod::Vector3f& v ) { + if ( !state.collider.body ) return; - if ( state.shared ) { - auto& physics = state.object->getComponent(); - physics.velocity += v; - // return; - } - state.body->setLinearVelocity( state.body->getLinearVelocity() + ::convert(v) ); + state.velocity += v; + state.collider.body->setLinearVelocity( state.collider.body->getLinearVelocity() + ::convert(v) ); } // directly rotate a transform -void ext::reactphysics::applyRotation( pod::PhysicsState& state, const pod::Quaternion<>& q ) { - if ( !state.body ) return; +void ext::reactphysics::applyRotation( pod::PhysicsBody& state, const pod::Quaternion<>& q ) { + if ( !state.collider.body ) return; - if ( state.shared ) { - auto& transform = state.object->getComponent>(); - uf::transform::rotate( transform, q ); - // return; - } - auto transform = state.body->getTransform(); + uf::transform::rotate( state.object->getComponent>(), q ); + + auto transform = state.collider.body->getTransform(); transform.setOrientation( transform.getOrientation() * ::convert( q ) ); - state.body->setTransform(transform); + state.collider.body->setTransform(transform); } -void ext::reactphysics::applyRotation( pod::PhysicsState& state, const pod::Vector3f& axis, float delta ) { +void ext::reactphysics::applyRotation( pod::PhysicsBody& state, const pod::Vector3f& axis, float delta ) { ext::reactphysics::applyRotation( state, uf::quaternion::axisAngle( axis, delta ) ); } // ray casting - -uf::Object* ext::reactphysics::rayCast( const pod::Vector3f& center, const pod::Vector3f& direction ) { - float depth = -1; - return rayCast( center, direction, NULL, depth ); -} - -uf::Object* ext::reactphysics::rayCast( pod::PhysicsState& state, const pod::Vector3f& center, const pod::Vector3f& direction ) { - float depth = -1; - return rayCast( center, direction, state.object, depth ); -} -uf::Object* ext::reactphysics::rayCast( pod::PhysicsState& state, const pod::Vector3f& center, const pod::Vector3f& direction, float& depth ) { - return rayCast( center, direction, state.object, depth ); -} - -uf::Object* ext::reactphysics::rayCast( const pod::Vector3f& center, const pod::Vector3f& direction, uf::Object* source, float& depth ) { +pod::RayQuery ext::reactphysics::rayCast( const pod::Ray& ray, const pod::PhysicsBody& body, float maxDistance ) { auto& scene = uf::scene::getCurrentScene(); - auto& world = ext::reactphysics::globalStorage ? ::world : scene.getComponent(); - depth = -1; + auto& world = /*ext::reactphysics::globalStorage ? ::world :*/ scene.getComponent(); - if ( !world ) return NULL; + pod::RayQuery query; + query.contact.penetration = maxDistance; + + if ( !world ) return query; ::RaycastCallback callback; - callback.source = source; - world->raycast( rp3d::Ray( ::convert( center ), ::convert( center + direction ) ), &callback ); - if ( !callback.isHit ) return NULL; - - depth = callback.raycastInfo.hitFraction; + callback.source = body.object; + world->raycast( rp3d::Ray( ::convert( ray.origin ), ::convert( ray.origin + ray.direction ) ), &callback ); + if ( !callback.isHit ) return query; + uf::Object* object = (uf::Object*) callback.raycastInfo.body->getUserData(); - return (uf::Object*) callback.raycastInfo.body->getUserData(); + query.hit = callback.isHit; + query.body = &object->getComponent(); + query.contact.contact = ray.origin + ray.direction * callback.raycastInfo.hitFraction; + query.contact.normal = ray.direction; + query.contact.penetration = callback.raycastInfo.hitFraction; + + return query; } // allows noclip -void ext::reactphysics::activateCollision( pod::PhysicsState& state, bool s ) { - if ( !state.body ) return; -// state.body->setIsActive(s); - auto colliders = state.body->getNbColliders(); +void ext::reactphysics::activateCollision( pod::PhysicsBody& state, bool s ) { + if ( !state.collider.body ) return; +// state.collider.body->setIsActive(s); + auto colliders = state.collider.body->getNbColliders(); for ( auto i = 0; i < colliders; ++i ) { - auto* collider = state.body->getCollider(i); + auto* collider = state.collider.body->getCollider(i); collider->setCollisionCategoryBits(s ? 0xFF : 0x00); collider->setCollideWithMaskBits(s ? 0xFF : 0x00); } } -float ext::reactphysics::getMass( pod::PhysicsState& state ) { - if ( !state.body ) return state.stats.mass; +float ext::reactphysics::getMass( pod::PhysicsBody& state ) { + if ( !state.collider.body ) return state.mass; - return (state.stats.mass = state.body->getMass()); + return (state.mass = state.collider.body->getMass()); } -void ext::reactphysics::setMass( pod::PhysicsState& state, float mass ) { - state.stats.mass = mass; - state.body->setMass(mass); +void ext::reactphysics::setMass( pod::PhysicsBody& state, float mass ) { + state.mass = mass; + state.collider.body->setMass(mass); } #endif \ No newline at end of file diff --git a/engine/src/ext/xatlas/xatlas.cpp b/engine/src/ext/xatlas/xatlas.cpp index d7e25e8d..7cf1f536 100644 --- a/engine/src/ext/xatlas/xatlas.cpp +++ b/engine/src/ext/xatlas/xatlas.cpp @@ -62,53 +62,79 @@ size_t ext::xatlas::unwrapExperimental( pod::Graph& graph ) { source = mesh; source.updateDescriptor(); - for (auto& view : source.makeViews({"position", "uv", "st", "index"})) { - auto pos = view["position"]; - auto uv = view["uv"]; - auto st = view["st"]; - auto idx = view["index"]; + uf::Mesh::Input vertexInput = mesh.vertex; - // Must have positions + indices - if (!pos.valid() || !idx.valid()) continue; - if (view.vertex.count == 0 || view.index.count == 0) continue; + uf::Mesh::Attribute positionAttribute; + uf::Mesh::Attribute uvAttribute; + uf::Mesh::Attribute stAttribute; + + for ( auto& attribute : mesh.vertex.attributes ) { + if ( attribute.descriptor.name == "position" ) positionAttribute = attribute; + else if ( attribute.descriptor.name == "uv" ) uvAttribute = attribute; + else if ( attribute.descriptor.name == "st" ) stAttribute = attribute; + } + UF_ASSERT( positionAttribute.descriptor.name == "position" && uvAttribute.descriptor.name == "uv" && stAttribute.descriptor.name == "st" ); + + if ( mesh.index.count ) { + uf::Mesh::Input indexInput = mesh.index; + uf::Mesh::Attribute indexAttribute = mesh.index.attributes.front(); - // Choose xatlas index format ::xatlas::IndexFormat indexType = ::xatlas::IndexFormat::UInt32; - switch (idx.attribute.descriptor.size) { + switch ( mesh.index.size ) { case sizeof(uint16_t): indexType = ::xatlas::IndexFormat::UInt16; break; case sizeof(uint32_t): indexType = ::xatlas::IndexFormat::UInt32; break; default: UF_EXCEPTION("unsupported index type"); break; } - // Get atlas target from indirect auxID or default 0 - size_t atlasID = 0; - if ( 0 <= view.indirectIndex ) { - auto* drawCommand = (pod::DrawCommand*) mesh.getBuffer(mesh.indirect).data(); - atlasID = drawCommand[view.indirectIndex].auxID; + if ( mesh.indirect.count ) { + auto& primitives = /*graph.storage*/storage.primitives[name]; + pod::DrawCommand* drawCommands = (pod::DrawCommand*) mesh.getBuffer(mesh.indirect).data(); + + for ( auto i = 0; i < mesh.indirect.count; ++i ) { + size_t atlasID = drawCommands[i].auxID; + + vertexInput = mesh.remapVertexInput( i ); + indexInput = mesh.remapIndexInput( i ); + + auto& atlas = atlases[atlasID]; + auto& entry = atlas.entries.emplace_back(); + entry.index = index; + entry.commandID = i; + + auto& decl = entry.decl; + + decl.vertexPositionData = static_cast(positionAttribute.pointer) + positionAttribute.stride * vertexInput.first; + decl.vertexPositionStride = positionAttribute.stride; + + decl.vertexUvData = static_cast(uvAttribute.pointer) + uvAttribute.stride * vertexInput.first; + decl.vertexUvStride = uvAttribute.stride; + + decl.vertexCount = vertexInput.count; + + decl.indexCount = indexInput.count; + decl.indexData = static_cast(indexAttribute.pointer) + indexAttribute.stride * indexInput.first; + decl.indexFormat = indexType; + } + } else { + size_t atlasID = 0; + auto& atlas = atlases[atlasID]; + auto& entry = atlas.entries.emplace_back(); + entry.index = index; + + auto& decl = entry.decl; + decl.vertexPositionData = static_cast(positionAttribute.pointer) + positionAttribute.stride * vertexInput.first; + decl.vertexPositionStride = positionAttribute.stride; + + decl.vertexUvData = static_cast(uvAttribute.pointer) + uvAttribute.stride * vertexInput.first; + decl.vertexUvStride = uvAttribute.stride; + + decl.vertexCount = vertexInput.count; + + decl.indexCount = indexInput.count; + decl.indexData = static_cast(indexAttribute.pointer) + indexAttribute.stride * indexInput.first; + decl.indexFormat = indexType; } - - auto& atlas = atlases[atlasID]; - auto& entry = atlas.entries.emplace_back(); - entry.index = index; - - auto& decl = entry.decl; - decl.vertexPositionData = pos.data(view.vertex.first); - decl.vertexPositionStride = pos.stride(); - - if ( uv.valid() ) { - decl.vertexUvData = uv.data(view.vertex.first); - decl.vertexUvStride = uv.stride(); - } else if ( st.valid() ) { - decl.vertexUvData = st.data(view.vertex.first); - decl.vertexUvStride = st.stride(); - } - - decl.vertexCount = view.vertex.count; - - decl.indexCount = view.index.count; - decl.indexData = idx.data(view.index.first); - decl.indexFormat = indexType; - } + } else UF_EXCEPTION("to-do: not require indices for meshes"); } ::xatlas::ChartOptions chartOptions{}; diff --git a/engine/src/utils/math/physics/aabb.inl b/engine/src/utils/math/physics/aabb.inl index 7836e90b..1f8a4c2b 100644 --- a/engine/src/utils/math/physics/aabb.inl +++ b/engine/src/utils/math/physics/aabb.inl @@ -27,7 +27,7 @@ namespace { }; } - std::pair getCapsuleSegment( const pod::RigidBody& body ) { + std::pair getCapsuleSegment( const pod::PhysicsBody& body ) { const auto transform = ::getTransform( body ); const auto& capsule = body.collider.u.capsule; const pod::Vector3f up = uf::quaternion::rotate( transform.orientation, pod::Vector3f{0,1,0} ); @@ -38,7 +38,7 @@ namespace { return { p1, p2 }; } - pod::AABB computeAABB( const pod::RigidBody& body ) { + pod::AABB computeAABB( const pod::PhysicsBody& body ) { const auto transform = ::getTransform( body ); switch ( body.collider.type ) { case pod::ShapeType::AABB: { @@ -197,7 +197,7 @@ namespace { return ( aabb.max - aabb.min ) * 0.5f; } - bool aabbAabb( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps ) { + bool aabbAabb( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) { ASSERT_COLLIDER_TYPES(AABB, AABB); const auto& A = a.bounds; @@ -257,19 +257,19 @@ namespace { return true; } - bool aabbSphere( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps ) { + bool aabbSphere( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) { ASSERT_COLLIDER_TYPES( AABB, SPHERE ); return ::sphereAabb( b, a, manifold, eps ); } - bool aabbPlane( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps ) { + bool aabbPlane( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) { ASSERT_COLLIDER_TYPES( AABB, PLANE ); return ::planeAabb( b, a, manifold, eps ); } - bool aabbCapsule( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps ) { + bool aabbCapsule( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) { ASSERT_COLLIDER_TYPES( AABB, CAPSULE ); return ::capsuleAabb( b, a, manifold, eps ); } - bool aabbMesh( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps ) { + bool aabbMesh( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) { ASSERT_COLLIDER_TYPES( AABB, MESH ); return ::meshAabb( b, a, manifold, eps ); } diff --git a/engine/src/utils/math/physics/bvh.inl b/engine/src/utils/math/physics/bvh.inl index bbdd7525..48fc3633 100644 --- a/engine/src/utils/math/physics/bvh.inl +++ b/engine/src/utils/math/physics/bvh.inl @@ -1,50 +1,54 @@ // BVH namespace { // collects a list of nodes that are overlapping with each other - void traverseNodePair( const pod::BVH& bvh, int leftID, int rightID, pod::BVH::pair_t& pairs ) { - const auto& left = bvh.nodes[leftID]; - const auto& right = bvh.nodes[rightID]; + void traverseNodePair( const pod::BVH& bvh, int indexA, int indexB, pod::BVH::pair_t& pairs ) { + const auto& nodeA = bvh.nodes[indexA]; + const auto& nodeB = bvh.nodes[indexB]; - if ( !::aabbOverlap( left.bounds, right.bounds ) ) return; + if ( !::aabbOverlap( nodeA.bounds, nodeB.bounds ) ) return; - if ( left.count > 0 && right.count > 0 ) { - for ( auto i = 0; i < left.count; ++i ) - for ( auto j = 0; j < right.count; ++j ) { - int a = bvh.indices[left.start + i]; - int b = bvh.indices[right.start + j]; - pairs.emplace_back(std::pair{a, b}); + if ( nodeA.count > 0 && nodeB.count > 0 ) { + for ( auto i = 0; i < nodeA.count; ++i ) + for ( auto j = 0; j < nodeB.count; ++j ) { + int indexA = bvh.indices[nodeA.start + i]; + int indexB = bvh.indices[nodeB.start + j]; + pairs.emplace_back(std::pair{indexA, indexB}); } return; } - if ( left.count == 0 ) { - ::traverseNodePair( bvh, left.left, rightID, pairs ); - ::traverseNodePair( bvh, left.right, rightID, pairs ); - } else if ( right.count == 0 ) { - ::traverseNodePair( bvh, leftID, right.left, pairs ); - ::traverseNodePair( bvh, leftID, right.right, pairs ); + if ( nodeA.count == 0 ) { + ::traverseNodePair( bvh, nodeA.left, indexB, pairs ); + ::traverseNodePair( bvh, nodeA.right, indexB, pairs ); + } else if ( nodeB.count == 0 ) { + ::traverseNodePair( bvh, indexA, nodeB.left, pairs ); + ::traverseNodePair( bvh, indexA, nodeB.right, pairs ); } } // collects a list of nodes from each BVH that are overlapping with each other (for mesh v mesh) - void traverseNodePair( const pod::BVH& a, int nodeA, const pod::BVH& b, int nodeB, pod::BVH::pair_t& pairs ) { - const auto& nA = a.nodes[nodeA]; - const auto& nB = b.nodes[nodeB]; + void traverseNodePair( const pod::BVH& bvhA, int indexA, const pod::BVH& bvhB, int indexB, pod::BVH::pair_t& pairs ) { + const auto& nodeA = bvhA.nodes[indexA]; + const auto& nodeB = bvhB.nodes[indexB]; - if ( !::aabbOverlap( nA.bounds, nB.bounds ) ) return; + if ( !::aabbOverlap( nodeA.bounds, nodeB.bounds ) ) return; - if ( nA.count > 0 && nB.count > 0 ) { - for ( auto i = 0; i < nA.count; i++ ) - for ( auto j = 0; j < nB.count; j++ ) - pairs.emplace_back(a.indices[nA.start+i], b.indices[nB.start+j]); + if ( nodeA.count > 0 && nodeB.count > 0 ) { + for ( auto i = 0; i < nodeA.count; i++ ) { + for ( auto j = 0; j < nodeB.count; j++ ) { + auto indexA = bvhA.indices[nodeA.start+i]; + auto indexB = bvhB.indices[nodeB.start+j]; + pairs.emplace_back(std::pair{indexA, indexB}); + } + } return; } - if ( nA.count == 0 ) { - ::traverseNodePair( a, nA.left, b , nodeB, pairs ); - ::traverseNodePair( a, nA.right, b , nodeB, pairs ); - } else { - ::traverseNodePair( a, nodeA, b, nB.left, pairs ); - ::traverseNodePair( a, nodeA, b, nB.right, pairs ); + if ( nodeA.count == 0 ) { + ::traverseNodePair( bvhA, nodeA.left, bvhB , indexB, pairs ); + ::traverseNodePair( bvhA, nodeA.right, bvhB , indexB, pairs ); + } else if ( nodeB.count == 0 ) { + ::traverseNodePair( bvhA, indexA, bvhB, nodeB.left, pairs ); + ::traverseNodePair( bvhA, indexA, bvhB, nodeB.right, pairs ); } } @@ -54,9 +58,14 @@ namespace { if ( node.count > 0 ) { for ( auto i = 0; i < node.count; ++i ) { for ( auto j = i + 1; j < node.count; ++j ) { - int a = bvh.indices[node.start + i]; - int b = bvh.indices[node.start + j]; - pairs.emplace_back(std::pair{a, b}); + int indexA = bvh.indices[node.start + i]; + int indexB = bvh.indices[node.start + j]; + + if ( !::aabbOverlap( bvh.nodes[indexA].bounds, bvh.nodes[indexB].bounds ) ) { + continue; + } + + pairs.emplace_back(std::pair{indexA, indexB}); } } return; @@ -113,7 +122,7 @@ namespace { return index; } - void buildBroadphaseBVH( pod::BVH& bvh, const uf::stl::vector& bodies, int capacity = 2 ) { + void buildBroadphaseBVH( pod::BVH& bvh, const uf::stl::vector& bodies, int capacity = 2 ) { bvh.indices.clear(); bvh.nodes.clear(); bvh.indices.reserve(bodies.size()); @@ -188,7 +197,7 @@ namespace { } } } - void queryBVH( const pod::BVH& bvh, const pod::RigidBody& body, uf::stl::vector& indices ) { + void queryBVH( const pod::BVH& bvh, const pod::PhysicsBody& body, uf::stl::vector& indices ) { return ::queryBVH( bvh, body.bounds, indices ); } diff --git a/engine/src/utils/math/physics/capsule.inl b/engine/src/utils/math/physics/capsule.inl index 798a60c5..861bfa19 100644 --- a/engine/src/utils/math/physics/capsule.inl +++ b/engine/src/utils/math/physics/capsule.inl @@ -1,5 +1,5 @@ namespace { - bool capsuleCapsule( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps ) { + bool capsuleCapsule( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) { ASSERT_COLLIDER_TYPES( CAPSULE, CAPSULE ); auto [ A1, A2 ] = ::getCapsuleSegment( a ); @@ -20,7 +20,7 @@ namespace { manifold.points.emplace_back(pod::Contact{ contact, normal, penetration }); return true; } - bool capsuleAabb( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps ) { + bool capsuleAabb( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) { ASSERT_COLLIDER_TYPES( CAPSULE, AABB ); const auto& capsule = a; const auto& box = b; @@ -43,7 +43,7 @@ namespace { manifold.points.emplace_back(pod::Contact{ contact, normal, penetration }); return true; } - bool capsulePlane( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps ) { + bool capsulePlane( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) { ASSERT_COLLIDER_TYPES( CAPSULE, PLANE ); const auto& capsule = a; const auto& plane = b; @@ -77,7 +77,7 @@ namespace { #endif return true; } - bool capsuleSphere( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps ) { + bool capsuleSphere( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) { ASSERT_COLLIDER_TYPES( CAPSULE, SPHERE ); const auto& capsule = a; const auto& sphere = b; @@ -102,7 +102,7 @@ namespace { manifold.points.emplace_back(pod::Contact{ contact, normal, penetration }); return true; } - bool capsuleMesh( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps ) { + bool capsuleMesh( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) { ASSERT_COLLIDER_TYPES( CAPSULE, MESH ); return meshCapsule( b, a, manifold, eps ); } diff --git a/engine/src/utils/math/physics/epa.inl b/engine/src/utils/math/physics/epa.inl index d26629c0..98a58564 100644 --- a/engine/src/utils/math/physics/epa.inl +++ b/engine/src/utils/math/physics/epa.inl @@ -77,7 +77,7 @@ namespace { } } - pod::Contact epa( const pod::RigidBody& a, const pod::RigidBody& b, const pod::Simplex& simplex, int maxIterations = 64, float eps = EPS(1.0e-4f) ) { + pod::Contact epa( const pod::PhysicsBody& a, const pod::PhysicsBody& b, const pod::Simplex& simplex, int maxIterations = 64, float eps = EPS(1.0e-4f) ) { UF_ASSERT( ::isValidSimplex(simplex) ); auto faces = ::initialPolytope(simplex); diff --git a/engine/src/utils/math/physics/gjk.inl b/engine/src/utils/math/physics/gjk.inl index 471c36c2..8f65a5f8 100644 --- a/engine/src/utils/math/physics/gjk.inl +++ b/engine/src/utils/math/physics/gjk.inl @@ -1,5 +1,5 @@ namespace { - pod::Vector3f support( const pod::RigidBody& body, const pod::Vector3f& dir ) { + pod::Vector3f support( const pod::PhysicsBody& body, const pod::Vector3f& dir ) { const auto transform = ::getTransform( body ); switch ( body.collider.type ) { case pod::ShapeType::SPHERE: { @@ -36,11 +36,11 @@ namespace { return {}; } - pod::Vector3f supportMinkowski( const pod::RigidBody& A, const pod::RigidBody& B, const pod::Vector3f& dir ) { + pod::Vector3f supportMinkowski( const pod::PhysicsBody& A, const pod::PhysicsBody& B, const pod::Vector3f& dir ) { return ::support( A, dir ) - ::support( B, -dir ); } - pod::SupportPoint supportMinkowskiDetailed( const pod::RigidBody& A, const pod::RigidBody& B, const pod::Vector3f& dir ) { + pod::SupportPoint supportMinkowskiDetailed( const pod::PhysicsBody& A, const pod::PhysicsBody& B, const pod::Vector3f& dir ) { auto pA = ::support( A, dir ); auto pB = ::support( B, -dir ); return { pA - pB, pA, pB }; @@ -149,7 +149,7 @@ namespace { return false; } - bool gjk( const pod::RigidBody& a, const pod::RigidBody& b, pod::Simplex& simplex, int maxIterations = 20, float eps = EPS(1e-6f) ) { + bool gjk( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Simplex& simplex, int maxIterations = 20, float eps = EPS(1e-6f) ) { auto dir = ::getPosition( b ) - ::getPosition( a ); if ( uf::vector::magnitude(dir) < eps ) dir = {1,0,0}; // fallback direction diff --git a/engine/src/utils/math/physics/helpers.inl b/engine/src/utils/math/physics/helpers.inl index 8a7c4e97..6d9d9ce8 100644 --- a/engine/src/utils/math/physics/helpers.inl +++ b/engine/src/utils/math/physics/helpers.inl @@ -1,40 +1,40 @@ // forward declare namespace { - bool aabbAabb( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); - bool aabbSphere( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); - bool aabbPlane( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); - bool aabbCapsule( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); - bool aabbMesh( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); + bool aabbAabb( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); + bool aabbSphere( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); + bool aabbPlane( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); + bool aabbCapsule( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); + bool aabbMesh( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); - bool sphereSphere( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); - bool sphereAabb( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); - bool spherePlane( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); - bool sphereCapsule( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); - bool sphereMesh( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); + bool sphereSphere( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); + bool sphereAabb( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); + bool spherePlane( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); + bool sphereCapsule( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); + bool sphereMesh( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); - bool planeAabb( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); - bool planeSphere( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); - bool planePlane( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); - bool planeCapsule( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); - bool planeMesh( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); + bool planeAabb( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); + bool planeSphere( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); + bool planePlane( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); + bool planeCapsule( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); + bool planeMesh( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); - bool capsuleCapsule( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); - bool capsuleAabb( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); - bool capsulePlane( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); - bool capsuleSphere( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); - bool capsuleMesh( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); + bool capsuleCapsule( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); + bool capsuleAabb( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); + bool capsulePlane( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); + bool capsuleSphere( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); + bool capsuleMesh( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); - bool meshAabb( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); - bool meshSphere( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); - bool meshPlane( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); - bool meshCapsule( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); - bool meshMesh( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); + bool meshAabb( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); + bool meshSphere( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); + bool meshPlane( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); + bool meshCapsule( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); + bool meshMesh( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); bool triangleTriangle( const pod::TriangleWithNormal& a, const pod::TriangleWithNormal& b, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); - bool triangleAabb( const pod::TriangleWithNormal& tri, const pod::RigidBody& body, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); - bool triangleSphere( const pod::TriangleWithNormal& tri, const pod::RigidBody& body, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); - bool trianglePlane( const pod::TriangleWithNormal& tri, const pod::RigidBody& body, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); - bool triangleCapsule( const pod::TriangleWithNormal& tri, const pod::RigidBody& body, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); + bool triangleAabb( const pod::TriangleWithNormal& tri, const pod::PhysicsBody& body, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); + bool triangleSphere( const pod::TriangleWithNormal& tri, const pod::PhysicsBody& body, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); + bool trianglePlane( const pod::TriangleWithNormal& tri, const pod::PhysicsBody& body, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); + bool triangleCapsule( const pod::TriangleWithNormal& tri, const pod::PhysicsBody& body, pod::Manifold& manifold, float eps = EPS(1.0e-6f) ); pod::Vector3f aabbCenter( const pod::AABB& aabb ); bool aabbOverlap( const pod::AABB& a, const pod::AABB& b, float eps = EPS(1.0e-6f) ); @@ -53,7 +53,7 @@ namespace { namespace { // create ID from pointers - uint64_t makePairKey( const pod::RigidBody& a, const pod::RigidBody& b ) { + uint64_t makePairKey( const pod::PhysicsBody& a, const pod::PhysicsBody& b ) { auto idA = reinterpret_cast(&a); auto idB = reinterpret_cast(&b); if ( idA > idB ) std::swap(idA, idB); // ensure consistent order @@ -62,18 +62,25 @@ namespace { // returns an absolute transform while also allowing offsetting the collision body // to-do: find a succint way to explain this madness - pod::Transform<> getTransform( const pod::RigidBody& body ) { + pod::Transform<> getTransform( const pod::PhysicsBody& body ) { pod::Transform<> t; t.position = body.offset; t.reference = body.transform; return uf::transform::flatten( t ); } - pod::Vector3f getPosition( const pod::RigidBody& body, bool useTransform = false ) { + pod::Vector3f getPosition( const pod::PhysicsBody& body, bool useTransform = false ) { if ( !useTransform ) return ::aabbCenter( body.bounds ); return ::getTransform( body ).position; } + bool shouldCollide( const pod::Collider& a, const pod::Collider& b ) { + return ( a.category & b.mask ) && ( b.category & a.mask ); + } + bool shouldCollide( const pod::PhysicsBody& a, const pod::PhysicsBody& b ) { + return ::shouldCollide( a.collider, b.collider ); + } + // normalizes the delta between two bodies / contacts by the distance (as it was already computed) if non-zero // a lot of collider v colliders use this semantic pod::Vector3f normalizeDelta( const pod::Vector3f& delta, float dist, float eps = EPS(1.0e-6), const pod::Vector3f& fallback = pod::Vector3f{0,1,0} ) { @@ -284,7 +291,7 @@ namespace { return ::closestPointOnTriangle( p, tri.points[0], tri.points[1], tri.points[2] ); } - pod::Vector3f orientNormalToAB( const pod::RigidBody& a, const pod::RigidBody& b, pod::Vector3f n ) { + pod::Vector3f orientNormalToAB( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Vector3f n ) { return uf::vector::normalize( uf::vector::dot( n, ::getPosition( b ) - ::getPosition( a ) ) < 0.0f ? -n : n ); } diff --git a/engine/src/utils/math/physics/impl.cpp b/engine/src/utils/math/physics/impl.cpp index 750c9bae..be2594b5 100644 --- a/engine/src/utils/math/physics/impl.cpp +++ b/engine/src/utils/math/physics/impl.cpp @@ -6,14 +6,18 @@ namespace { bool warmupSolver = true; - bool blockContactSolver = false; - bool psgContactSolver = true; - bool useGjk = false; + bool blockContactSolver = false; // blockNxN solver is flawed + bool psgContactSolver = true; // iterative solver is flawed + bool useGjk = false; // currently don't have a way to broadphase mesh => narrowphase tri via GJK bool fixedStep = true; - int substeps = 0; + int substeps = 4; - int solverIterations = 10; - float baumgarteCorrectionPercent = 0.005f; + // increasing these make things lag + int broadphaseBvhCapacity = 1; + int meshBvhCapacity = 1; + + int solverIterations = 5; + float baumgarteCorrectionPercent = 0.005f; // needs to be very small or the correction is too large float baumgarteCorrectionSlop = 0.001f; uf::stl::unordered_map manifoldsCache; } @@ -106,7 +110,7 @@ void uf::physics::impl::step( pod::World& world, float dt ) { uf::stl::vector> pairs; // create BVH - ::buildBroadphaseBVH(bvh, bodies); + ::buildBroadphaseBVH( bvh, bodies, ::broadphaseBvhCapacity ); // query for overlaps ::queryOverlaps( bvh, pairs ); // iterate overlaps @@ -114,6 +118,9 @@ void uf::physics::impl::step( pod::World& world, float dt ) { auto& a = *bodies[ia]; auto& b = *bodies[ib]; + // could be also pruned in the broadphase, but traversal needs to be agnostic between a BVH for bodies or a BVH for triangles + if ( !::shouldCollide( a, b ) ) continue; + pod::Manifold manifold; if ( ::generateContacts( a, b, manifold, dt ) ) { // bodies with meshes already reorient the normal to the triangle's center @@ -137,8 +144,6 @@ void uf::physics::impl::step( pod::World& world, float dt ) { } } -// for ( auto& m : manifolds ) for ( auto& c : m.points ) UF_MSG_DEBUG("contact={}, normal={}, depth={}", uf::vector::toString( c.point ), uf::vector::toString( c.normal ), c.penetration ); - // pass manifolds to solver ::solveContacts( manifolds, dt ); @@ -166,12 +171,50 @@ void uf::physics::impl::step( pod::World& world, float dt ) { } } -void uf::physics::impl::setMass( pod::RigidBody& body, float mass ) { +void uf::physics::impl::setMass( pod::PhysicsBody& body, float mass ) { body.mass = mass; body.inverseMass = 1.0f / mass; - uf::physics::impl::setInertia( body ); + uf::physics::impl::updateInertia( body ); } -void uf::physics::impl::setInertia( pod::RigidBody& body ) { + +void uf::physics::impl::setColliderCategory( pod::PhysicsBody& body, uint32_t category ) { + body.collider.category = category; +} +void uf::physics::impl::setColliderCategory( pod::PhysicsBody& body, const uf::stl::string& category ) { + auto c = uf::string::uppercase( category ); + if ( c == "NONE" ) return uf::physics::impl::setColliderCategory( body, pod::Collider::CATEGORY_NONE ); + if ( c == "STATIC" ) return uf::physics::impl::setColliderCategory( body, pod::Collider::CATEGORY_STATIC ); + if ( c == "DYNAMIC" ) return uf::physics::impl::setColliderCategory( body, pod::Collider::CATEGORY_DYNAMIC ); + if ( c == "PLAYER" ) return uf::physics::impl::setColliderCategory( body, pod::Collider::CATEGORY_PLAYER ); + if ( c == "NPC" ) return uf::physics::impl::setColliderCategory( body, pod::Collider::CATEGORY_NPC ); + if ( c == "TRIGGER" ) return uf::physics::impl::setColliderCategory( body, pod::Collider::CATEGORY_TRIGGER ); + if ( c == "PROJECTILE" ) return uf::physics::impl::setColliderCategory( body, pod::Collider::CATEGORY_PROJECTILE ); + if ( c == "CHARACTER" ) return uf::physics::impl::setColliderCategory( body, pod::Collider::CATEGORY_CHARACTER ); + if ( c == "ALL" ) return uf::physics::impl::setColliderCategory( body, pod::Collider::CATEGORY_ALL ); +} +void uf::physics::impl::setColliderMask( pod::PhysicsBody& body, uint32_t mask ) { + body.collider.mask = mask; +} +void uf::physics::impl::setColliderMask( pod::PhysicsBody& body, const uf::stl::string& mask ) { + auto m = uf::string::uppercase( mask ); + if ( m == "NONE" ) return uf::physics::impl::setColliderMask( body, pod::Collider::MASK_NONE ); + if ( m == "STATIC" ) return uf::physics::impl::setColliderMask( body, pod::Collider::MASK_STATIC ); + if ( m == "DYNAMIC" ) return uf::physics::impl::setColliderMask( body, pod::Collider::MASK_DYNAMIC ); + if ( m == "PLAYER" ) return uf::physics::impl::setColliderMask( body, pod::Collider::MASK_PLAYER ); + if ( m == "NPC" ) return uf::physics::impl::setColliderMask( body, pod::Collider::MASK_NPC ); + if ( m == "TRIGGER" ) return uf::physics::impl::setColliderMask( body, pod::Collider::MASK_TRIGGER ); + if ( m == "PROJECTILE" ) return uf::physics::impl::setColliderMask( body, pod::Collider::MASK_PROJECTILE ); + if ( m == "CHARACTER" ) return uf::physics::impl::setColliderCategory( body, pod::Collider::MASK_CHARACTER ); + if ( m == "ALL" ) return uf::physics::impl::setColliderMask( body, pod::Collider::MASK_ALL ); +} +void uf::physics::impl::setGravity( pod::PhysicsBody& body, const pod::Vector3f& gravity ) { + body.gravity = gravity; +} +pod::Vector3f uf::physics::impl::getGravity( pod::PhysicsBody& body ) { + return uf::vector::isValid( body.gravity ) ? body.gravity : body.world->gravity; +} + +void uf::physics::impl::updateInertia( pod::PhysicsBody& body ) { if ( body.isStatic || body.mass <= 0 ) { body.inverseInertiaTensor = {}; return; @@ -211,11 +254,11 @@ void uf::physics::impl::setInertia( pod::RigidBody& body ) { } break; } } -void uf::physics::impl::applyForce( pod::RigidBody& body, const pod::Vector3f& force ) { +void uf::physics::impl::applyForce( pod::PhysicsBody& body, const pod::Vector3f& force ) { if ( body.isStatic ) return; body.forceAccumulator += force; } -void uf::physics::impl::applyForceAtPoint( pod::RigidBody body, const pod::Vector3f& force, const pod::Vector3f& point ) { +void uf::physics::impl::applyForceAtPoint( pod::PhysicsBody body, const pod::Vector3f& force, const pod::Vector3f& point ) { if ( body.isStatic ) return; // linear force body.forceAccumulator += force; @@ -223,28 +266,28 @@ void uf::physics::impl::applyForceAtPoint( pod::RigidBody body, const pod::Vecto pod::Vector3f r = point - ::getPosition( body ); body.torqueAccumulator += uf::vector::cross( r, force ); } -void uf::physics::impl::applyImpulse( pod::RigidBody& body, const pod::Vector3f& impulse ) { +void uf::physics::impl::applyImpulse( pod::PhysicsBody& body, const pod::Vector3f& impulse ) { if ( body.isStatic ) return; body.velocity += impulse * body.inverseMass; } -void uf::physics::impl::applyTorque( pod::RigidBody& body, const pod::Vector3f& torque ) { +void uf::physics::impl::applyTorque( pod::PhysicsBody& body, const pod::Vector3f& torque ) { if ( body.isStatic ) return; body.torqueAccumulator += torque; } -void uf::physics::impl::setVelocity( pod::RigidBody& body, const pod::Vector3f& v ) { +void uf::physics::impl::setVelocity( pod::PhysicsBody& body, const pod::Vector3f& v ) { body.velocity = v; } -void uf::physics::impl::applyRotation( pod::RigidBody& body, const pod::Quaternion<>& q ) { +void uf::physics::impl::applyRotation( pod::PhysicsBody& body, const pod::Quaternion<>& q ) { uf::transform::rotate( *body.transform/*.reference*/, q ); } -void uf::physics::impl::applyRotation( pod::RigidBody& body, const pod::Vector3f& axis, float angle ) { +void uf::physics::impl::applyRotation( pod::PhysicsBody& body, const pod::Vector3f& axis, float angle ) { applyRotation( body, uf::quaternion::axisAngle( axis, angle ) ); } // body creation -pod::RigidBody& uf::physics::impl::create( pod::World& world, uf::Object& object, float mass, const pod::Vector3f& offset ) { +pod::PhysicsBody& uf::physics::impl::create( pod::World& world, uf::Object& object, float mass, const pod::Vector3f& offset ) { // bind to component - pod::RigidBody& body = object.getComponent(); + pod::PhysicsBody& body = object.getComponent(); // initial initialization body.world = &world; body.object = &object; @@ -254,71 +297,70 @@ pod::RigidBody& uf::physics::impl::create( pod::World& world, uf::Object& object body.inverseMass = mass == 0.0f ? 0.0f : 1.0f / mass; body.isStatic = mass == 0.0f; + if ( body.isStatic ) { + uf::physics::impl::setColliderCategory(body, "STATIC"); + uf::physics::impl::setColliderMask(body, "STATIC"); + } + // insert into world world.bodies.emplace_back(&body); return body; } -pod::RigidBody& uf::physics::impl::create( pod::World& world, uf::Object& object, const pod::AABB& aabb, float mass, const pod::Vector3f& offset ) { +pod::PhysicsBody& uf::physics::impl::create( pod::World& world, uf::Object& object, const pod::AABB& aabb, float mass, const pod::Vector3f& offset ) { auto& body = uf::physics::impl::create( world, object, mass, offset ); body.collider.type = pod::ShapeType::AABB; body.collider.u.aabb = aabb; body.bounds = ::computeAABB( body ); - uf::physics::impl::setInertia( body ); - UF_MSG_DEBUG("Creating body of type: {}, mass={}, min={}, max={}", "AABB", mass, uf::vector::toString(aabb.min), uf::vector::toString(aabb.max) ); + uf::physics::impl::updateInertia( body ); return body; } -pod::RigidBody& uf::physics::impl::create( pod::World& world, uf::Object& object, const pod::Sphere& sphere, float mass, const pod::Vector3f& offset ) { +pod::PhysicsBody& uf::physics::impl::create( pod::World& world, uf::Object& object, const pod::Sphere& sphere, float mass, const pod::Vector3f& offset ) { auto& body = uf::physics::impl::create( world, object, mass, offset ); body.collider.type = pod::ShapeType::SPHERE; body.collider.u.sphere = sphere; body.bounds = ::computeAABB( body ); - uf::physics::impl::setInertia( body ); - UF_MSG_DEBUG("Creating body of type={}, mass={}, radius={}", "SPHERE", mass, sphere.radius ); + uf::physics::impl::updateInertia( body ); return body; } -pod::RigidBody& uf::physics::impl::create( pod::World& world, uf::Object& object, const pod::Plane& plane, float mass, const pod::Vector3f& offset ) { +pod::PhysicsBody& uf::physics::impl::create( pod::World& world, uf::Object& object, const pod::Plane& plane, float mass, const pod::Vector3f& offset ) { auto& body = uf::physics::impl::create( world, object, mass, offset ); body.collider.type = pod::ShapeType::PLANE; body.collider.u.plane = plane; body.bounds = ::computeAABB( body ); - uf::physics::impl::setInertia( body ); - UF_MSG_DEBUG("Creating body of type={}, mass={}, normal={}, offset={}", "PLANE", mass, uf::vector::toString( plane.normal ), plane.offset ); + uf::physics::impl::updateInertia( body ); return body; } -pod::RigidBody& uf::physics::impl::create( pod::World& world, uf::Object& object, const pod::Capsule& capsule, float mass, const pod::Vector3f& offset ) { +pod::PhysicsBody& uf::physics::impl::create( pod::World& world, uf::Object& object, const pod::Capsule& capsule, float mass, const pod::Vector3f& offset ) { auto& body = uf::physics::impl::create( world, object, mass, offset ); body.collider.type = pod::ShapeType::CAPSULE; body.collider.u.capsule = capsule; body.bounds = ::computeAABB( body ); - uf::physics::impl::setInertia( body ); - UF_MSG_DEBUG("Creating body of type={}, mass={}, radius={}, height={}", "CAPSULE", mass, capsule.radius, capsule.halfHeight * 2.0f ); + uf::physics::impl::updateInertia( body ); return body; } -pod::RigidBody& uf::physics::impl::create( pod::World& world, uf::Object& object, const pod::TriangleWithNormal& tri, float mass, const pod::Vector3f& offset ) { +pod::PhysicsBody& uf::physics::impl::create( pod::World& world, uf::Object& object, const pod::TriangleWithNormal& tri, float mass, const pod::Vector3f& offset ) { auto& body = uf::physics::impl::create( world, object, mass, offset ); body.collider.type = pod::ShapeType::TRIANGLE; body.collider.u.triangle = tri; body.bounds = ::computeAABB( body ); - uf::physics::impl::setInertia( body ); - UF_MSG_DEBUG("Creating body of type={}, mass={}, point[0]={}, point[1]={}, point[2]={}", "TRIANGLE", mass, uf::vector::toString( tri.points[0] ), uf::vector::toString( tri.points[1] ), uf::vector::toString( tri.points[2] ) ); + uf::physics::impl::updateInertia( body ); return body; } -pod::RigidBody& uf::physics::impl::create( pod::World& world, uf::Object& object, const uf::Mesh& mesh, float mass, const pod::Vector3f& offset ) { +pod::PhysicsBody& uf::physics::impl::create( pod::World& world, uf::Object& object, const uf::Mesh& mesh, float mass, const pod::Vector3f& offset ) { auto& body = uf::physics::impl::create( world, object, mass, offset ); body.collider.type = pod::ShapeType::MESH; body.collider.u.mesh.mesh = &mesh; body.collider.u.mesh.bvh = new pod::BVH; - ::buildMeshBVH( *body.collider.u.mesh.bvh, mesh ); + ::buildMeshBVH( *body.collider.u.mesh.bvh, mesh, ::meshBvhCapacity ); body.bounds = ::computeAABB( body ); - uf::physics::impl::setInertia( body ); - UF_MSG_DEBUG("Creating body of type={}, mass={}, nodes={} indices={} ", "MESH", mass, body.collider.u.mesh.bvh->nodes.size(), body.collider.u.mesh.bvh->indices.size()); + uf::physics::impl::updateInertia( body ); return body; } -pod::RigidBody& uf::physics::impl::create( uf::Object& object, float mass, const pod::Vector3f& offset ) { +pod::PhysicsBody& uf::physics::impl::create( uf::Object& object, float mass, const pod::Vector3f& offset ) { // bind to scene // auto& root = object.getRootParent<>(); // in the event a scene is being initialized that is not the root scene, use the root parent instead // auto& world = root.getComponent(); @@ -327,38 +369,38 @@ pod::RigidBody& uf::physics::impl::create( uf::Object& object, float mass, const return create( world, object, mass, offset ); } -pod::RigidBody& uf::physics::impl::create( uf::Object& object, const pod::AABB& aabb, float mass, const pod::Vector3f& offset ) { +pod::PhysicsBody& uf::physics::impl::create( uf::Object& object, const pod::AABB& aabb, float mass, const pod::Vector3f& offset ) { auto& scene = uf::scene::getCurrentScene(); auto& world = scene.getComponent(); return create( world, object, aabb, mass, offset ); } -pod::RigidBody& uf::physics::impl::create( uf::Object& object, const pod::Sphere& sphere, float mass, const pod::Vector3f& offset ) { +pod::PhysicsBody& uf::physics::impl::create( uf::Object& object, const pod::Sphere& sphere, float mass, const pod::Vector3f& offset ) { auto& scene = uf::scene::getCurrentScene(); auto& world = scene.getComponent(); return create( world, object, sphere, mass, offset ); } -pod::RigidBody& uf::physics::impl::create( uf::Object& object, const pod::Plane& plane, float mass, const pod::Vector3f& offset ) { +pod::PhysicsBody& uf::physics::impl::create( uf::Object& object, const pod::Plane& plane, float mass, const pod::Vector3f& offset ) { auto& scene = uf::scene::getCurrentScene(); auto& world = scene.getComponent(); return create( world, object, plane, mass, offset ); } -pod::RigidBody& uf::physics::impl::create( uf::Object& object, const pod::Capsule& capsule, float mass, const pod::Vector3f& offset ) { +pod::PhysicsBody& uf::physics::impl::create( uf::Object& object, const pod::Capsule& capsule, float mass, const pod::Vector3f& offset ) { auto& scene = uf::scene::getCurrentScene(); auto& world = scene.getComponent(); return create( world, object, capsule, mass, offset ); } -pod::RigidBody& uf::physics::impl::create( uf::Object& object, const uf::Mesh& mesh, float mass, const pod::Vector3f& offset ) { +pod::PhysicsBody& uf::physics::impl::create( uf::Object& object, const uf::Mesh& mesh, float mass, const pod::Vector3f& offset ) { auto& scene = uf::scene::getCurrentScene(); auto& world = scene.getComponent(); return create( world, object, mesh, mass, offset ); } void uf::physics::impl::destroy( uf::Object& object ) { - if ( !object.hasComponent() ) return; + if ( !object.hasComponent() ) return; - return destroy( object.getComponent() ); + return destroy( object.getComponent() ); } -void uf::physics::impl::destroy( pod::RigidBody& body ) { +void uf::physics::impl::destroy( pod::PhysicsBody& body ) { auto& world = *body.world; // remove from world for ( auto it = world.bodies.begin(); it != world.bodies.end(); ++it ) { @@ -373,27 +415,23 @@ void uf::physics::impl::destroy( pod::RigidBody& body ) { } } -pod::RayQuery uf::physics::impl::rayCast( const pod::Ray& ray, const pod::RigidBody& body, float maxDistance ) { +pod::RayQuery uf::physics::impl::rayCast( const pod::Ray& ray, const pod::PhysicsBody& body, float maxDistance ) { return rayCast( ray, *body.world, &body, maxDistance ); } pod::RayQuery uf::physics::impl::rayCast( const pod::Ray& ray, const pod::World& world, float maxDistance ) { return rayCast( ray, world, NULL, maxDistance ); } -pod::RayQuery uf::physics::impl::rayCast( const pod::Ray& ray, const pod::World& world, const pod::RigidBody* body, float maxDistance ) { +pod::RayQuery uf::physics::impl::rayCast( const pod::Ray& ray, const pod::World& world, const pod::PhysicsBody* body, float maxDistance ) { pod::RayQuery rayHit; rayHit.contact.penetration = maxDistance; auto& bvh = world.bvh; auto& bodies = world.bodies; -#if 1 uf::stl::vector candidates; ::queryBVH( bvh, ray, candidates ); for ( auto i : candidates ) { -#else - for ( auto i = 0; i < bodies.size(); ++i ) { -#endif auto* b = bodies[i]; if ( body == b ) continue; switch ( b->collider.type ) { diff --git a/engine/src/utils/math/physics/integration.inl b/engine/src/utils/math/physics/integration.inl index 535f3f44..bc44bb05 100644 --- a/engine/src/utils/math/physics/integration.inl +++ b/engine/src/utils/math/physics/integration.inl @@ -1,5 +1,5 @@ namespace { - float computeEffectiveMass( pod::RigidBody& a, pod::RigidBody& b, const pod::Vector3f& rA, const pod::Vector3f& rB, const pod::Vector3f& n ) { + float computeEffectiveMass( pod::PhysicsBody& a, pod::PhysicsBody& b, const pod::Vector3f& rA, const pod::Vector3f& rB, const pod::Vector3f& n ) { float inverseMass = 0.0f; if ( !a.isStatic ) inverseMass += a.inverseMass; if ( !b.isStatic ) inverseMass += b.inverseMass; @@ -21,7 +21,7 @@ namespace { return result; } - void applyImpulseTo( pod::RigidBody& a, pod::RigidBody& b, const pod::Vector3f& rA, const pod::Vector3f& rB, const pod::Vector3f& impulse ) { + void applyImpulseTo( pod::PhysicsBody& a, pod::PhysicsBody& b, const pod::Vector3f& rA, const pod::Vector3f& rB, const pod::Vector3f& impulse ) { if ( !a.isStatic ) { a.velocity -= impulse * a.inverseMass; a.angularVelocity -= (uf::vector::cross(rA, impulse)) * a.inverseInertiaTensor; @@ -34,7 +34,7 @@ namespace { } } - void applyRollingResistance( pod::RigidBody& body, float dt ) { + void applyRollingResistance( pod::PhysicsBody& body, float dt ) { if ( body.isStatic ) return; float rollingFriction = 0.02f; // to-do: derive from material @@ -45,14 +45,14 @@ namespace { // body.angularVelocity *= -rollingFriction * dt; } - void bindManifold( pod::RigidBody& a, pod::RigidBody& b, pod::Manifold& manifold, float dt = 0 ) { + void bindManifold( pod::PhysicsBody& a, pod::PhysicsBody& b, pod::Manifold& manifold, float dt = 0 ) { manifold.a = &a; manifold.b = &b; manifold.dt = dt; manifold.points.clear(); } - bool generateContactsGjk( pod::RigidBody& a, pod::RigidBody& b, pod::Manifold& manifold, float dt ) { + bool generateContactsGjk( pod::PhysicsBody& a, pod::PhysicsBody& b, pod::Manifold& manifold, float dt ) { ::bindManifold( a, b, manifold, dt ); pod::Simplex simplex; @@ -66,7 +66,7 @@ namespace { return true; } - bool generateContacts( pod::RigidBody& a, pod::RigidBody& b, pod::Manifold& manifold, float dt ) { + bool generateContacts( pod::PhysicsBody& a, pod::PhysicsBody& b, pod::Manifold& manifold, float dt ) { if ( ::useGjk ) return generateContactsGjk( a, b, manifold, dt ); ::bindManifold( a, b, manifold, dt ); @@ -172,7 +172,7 @@ namespace { } } - void warmupContacts( pod::RigidBody& a, pod::RigidBody& b, const pod::Contact& c, float dt ) { + void warmupContacts( pod::PhysicsBody& a, pod::PhysicsBody& b, const pod::Contact& c, float dt ) { if ( !c.lifetime ) return; // too new // build relative offsets @@ -189,14 +189,14 @@ namespace { // UF_MSG_DEBUG("Warming, Pn={}, Pt={}, lifetime={}", uf::vector::toString(Pn), uf::vector::toString(Pt), c.lifetime ); } - void warmupManifold( pod::RigidBody& a, pod::RigidBody& b, const pod::Manifold& manifold, float dt ) { + void warmupManifold( pod::PhysicsBody& a, pod::PhysicsBody& b, const pod::Manifold& manifold, float dt ) { for ( auto& contact : manifold.points ) { ::warmupContacts( a, b, contact, dt ); } } // baumgarte position correction - void positionCorrection( pod::RigidBody& a, pod::RigidBody& b, const pod::Contact& contact ) { + void positionCorrection( pod::PhysicsBody& a, pod::PhysicsBody& b, const pod::Contact& contact ) { if ( ::baumgarteCorrectionPercent <= 0 ) return; float correctionMagnitude = std::max(contact.penetration - ::baumgarteCorrectionSlop, 0.0f) / (a.inverseMass + b.inverseMass) * ::baumgarteCorrectionPercent; @@ -206,7 +206,7 @@ namespace { if ( !b.isStatic ) b.transform/*.reference*/->position += correction * b.inverseMass; } - void integrate( pod::RigidBody& body, float dt ) { + void integrate( pod::PhysicsBody& body, float dt ) { // only integrate dynamic bodies if ( body.isStatic || body.mass == 0 ) return; @@ -214,7 +214,7 @@ namespace { // linear integration pod::Vector3f acceleration = body.forceAccumulator * body.inverseMass; - acceleration += world.gravity; // apply gravity + acceleration += uf::physics::impl::getGravity( body ); // apply gravity body.velocity += acceleration * dt; body.transform/*.reference*/->position += body.velocity * dt; diff --git a/engine/src/utils/math/physics/mesh.inl b/engine/src/utils/math/physics/mesh.inl index 6724e97f..b76a1ea3 100644 --- a/engine/src/utils/math/physics/mesh.inl +++ b/engine/src/utils/math/physics/mesh.inl @@ -13,7 +13,7 @@ normal = uf::quaternion::rotate( mesh.transform.orientation, normal ); // namespace { - bool meshAabb( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps ) { + bool meshAabb( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) { ASSERT_COLLIDER_TYPES( MESH, AABB ); const auto& mesh = a; @@ -36,7 +36,7 @@ namespace { } return hit; } - bool meshSphere( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps ) { + bool meshSphere( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) { ASSERT_COLLIDER_TYPES( MESH, SPHERE ); const auto& mesh = a; @@ -61,7 +61,7 @@ namespace { return hit; } // to-do - bool meshPlane( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps ) { + bool meshPlane( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) { ASSERT_COLLIDER_TYPES( MESH, PLANE ); const auto& mesh = a; @@ -85,7 +85,7 @@ namespace { return hit; } - bool meshCapsule( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps ) { + bool meshCapsule( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) { ASSERT_COLLIDER_TYPES( MESH, CAPSULE ); const auto& mesh = a; @@ -110,7 +110,7 @@ namespace { return hit; } // to-do - bool meshMesh( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps ) { + bool meshMesh( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) { ASSERT_COLLIDER_TYPES( MESH, MESH ); const auto& bvhA = *a.collider.u.mesh.bvh; @@ -123,16 +123,12 @@ namespace { pod::BVH::pair_t pairs; ::traverseNodePair(bvhA, 0, bvhB, 0, pairs); - UF_MSG_DEBUG("candidates={}", pairs.size()); - bool hit = false; // do collision per triangle for (auto [ idA, idB] : pairs ) { auto tA = ::fetchTriangle( meshA, idA, a ); // transform triangles to world space auto tB = ::fetchTriangle( meshB, idB, b ); - UF_MSG_DEBUG("triA={}, triB={}", idA, idB ); - if ( !::triangleTriangle( tA, tB, manifold, eps ) ) continue; hit = true; } diff --git a/engine/src/utils/math/physics/plane.inl b/engine/src/utils/math/physics/plane.inl index af69b20e..beace668 100644 --- a/engine/src/utils/math/physics/plane.inl +++ b/engine/src/utils/math/physics/plane.inl @@ -1,5 +1,5 @@ namespace { - bool planeAabb( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps ) { + bool planeAabb( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) { ASSERT_COLLIDER_TYPES( PLANE, AABB ); const auto& plane = a; @@ -21,7 +21,7 @@ namespace { manifold.points.emplace_back(pod::Contact{ contact, normal, penetration }); return true; } - bool planeSphere(const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps) { + bool planeSphere(const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps) { ASSERT_COLLIDER_TYPES(PLANE, SPHERE); const auto& plane = a; @@ -42,15 +42,15 @@ namespace { manifold.points.emplace_back(pod::Contact{ contact, normal, penetration }); return true; } - bool planePlane( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps ) { + bool planePlane( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) { ASSERT_COLLIDER_TYPES( PLANE, PLANE ); return false; } - bool planeCapsule( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps ) { + bool planeCapsule( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) { ASSERT_COLLIDER_TYPES( PLANE, CAPSULE ); return capsulePlane( b, a, manifold, eps ); } - bool planeMesh( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps ) { + bool planeMesh( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) { ASSERT_COLLIDER_TYPES( PLANE, MESH ); return meshPlane( b, a, manifold, eps ); } diff --git a/engine/src/utils/math/physics/ray.inl b/engine/src/utils/math/physics/ray.inl index cde1659b..12590527 100644 --- a/engine/src/utils/math/physics/ray.inl +++ b/engine/src/utils/math/physics/ray.inl @@ -48,7 +48,7 @@ namespace { return true; } - bool rayAabb( const pod::Ray& ray, const pod::RigidBody& body, pod::RayQuery& rayHit ) { + bool rayAabb( const pod::Ray& ray, const pod::PhysicsBody& body, pod::RayQuery& rayHit ) { float tMin = 0.0f; float tMax = FLT_MAX; @@ -74,7 +74,7 @@ namespace { } return true; } - bool raySphere( const pod::Ray& ray, const pod::RigidBody& body, pod::RayQuery& rayHit ) { + bool raySphere( const pod::Ray& ray, const pod::PhysicsBody& body, pod::RayQuery& rayHit ) { auto center = ::getPosition(body); float r = body.collider.u.sphere.radius; @@ -87,8 +87,6 @@ namespace { float disc = b*b - 4*a*c; - UF_MSG_DEBUG( "center={}, r={}, oc={}, a, b, c, disc", uf::vector::toString( center ), r, uf::vector::toString( oc ), a, b, c, disc ); - if ( disc < 0 ) return false; float sqrtDisc = std::sqrt(disc); @@ -97,8 +95,6 @@ namespace { float t = ( t0 >= 0 ) ? t0 : t1; - UF_MSG_DEBUG( "sqrtDisc={}, t0={}, t1={}, t={}, rayHit.contact.penetration={}", sqrtDisc, t0, t1, t, rayHit.contact.penetration ); - if ( t < 0 ) return false; // both behind ray // compare against current best hit @@ -112,7 +108,7 @@ namespace { rayHit.contact.penetration = t; return true; } - bool rayPlane( const pod::Ray& ray, const pod::RigidBody& body, pod::RayQuery& rayHit, float eps = EPS(1e-6f) ) { + bool rayPlane( const pod::Ray& ray, const pod::PhysicsBody& body, pod::RayQuery& rayHit, float eps = EPS(1e-6f) ) { auto& normal = body.collider.u.plane.normal; float offset = body.collider.u.plane.offset; @@ -131,7 +127,7 @@ namespace { rayHit.contact.penetration = t; return true; } - bool rayCapsule( const pod::Ray& ray, const pod::RigidBody& body, pod::RayQuery& rayHit ) { + bool rayCapsule( const pod::Ray& ray, const pod::PhysicsBody& body, pod::RayQuery& rayHit ) { auto [ p1, p2 ] = ::getCapsuleSegment( body ); float r = body.collider.u.capsule.radius; @@ -196,7 +192,7 @@ namespace { return true; } - bool rayMesh( const pod::Ray& r, const pod::RigidBody& body, pod::RayQuery& rayHit ) { + bool rayMesh( const pod::Ray& r, const pod::PhysicsBody& body, pod::RayQuery& rayHit ) { const uf::Mesh& meshData = *body.collider.u.mesh.mesh; const pod::BVH& bvh = *body.collider.u.mesh.bvh; diff --git a/engine/src/utils/math/physics/solvers.inl b/engine/src/utils/math/physics/solvers.inl index 0771c7f3..50621364 100644 --- a/engine/src/utils/math/physics/solvers.inl +++ b/engine/src/utils/math/physics/solvers.inl @@ -1,5 +1,5 @@ namespace { - void iterativeImpulseSolver( pod::RigidBody& a, pod::RigidBody& b, pod::Contact& contact, float dt ) { + void iterativeImpulseSolver( pod::PhysicsBody& a, pod::PhysicsBody& b, pod::Contact& contact, float dt ) { // relative positions from centers to contact point pod::Vector3f rA = contact.point - ::getPosition( a, true ); pod::Vector3f rB = contact.point - ::getPosition( b, true ); @@ -74,7 +74,7 @@ namespace { } template - void blockNxNSolver( pod::RigidBody& a, pod::RigidBody& b, pod::Manifold& manifold, float dt ) { + void blockNxNSolver( pod::PhysicsBody& a, pod::PhysicsBody& b, pod::Manifold& manifold, float dt ) { pod::Matrix K = {}; pod::Vector rhs = {}; pod::Vector lambda = {}; @@ -167,17 +167,17 @@ namespace { } } - void block2x2Solver( pod::RigidBody& a, pod::RigidBody& b, pod::Manifold& manifold, float dt ) { + void block2x2Solver( pod::PhysicsBody& a, pod::PhysicsBody& b, pod::Manifold& manifold, float dt ) { return ::blockNxNSolver<2>( a, b, manifold, dt ); } - void block3x3Solver( pod::RigidBody& a, pod::RigidBody& b, pod::Manifold& manifold, float dt ) { + void block3x3Solver( pod::PhysicsBody& a, pod::PhysicsBody& b, pod::Manifold& manifold, float dt ) { return ::blockNxNSolver<3>( a, b, manifold, dt ); } - void block4x4Solver( pod::RigidBody& a, pod::RigidBody& b, pod::Manifold& manifold, float dt ) { + void block4x4Solver( pod::PhysicsBody& a, pod::PhysicsBody& b, pod::Manifold& manifold, float dt ) { return ::blockNxNSolver<4>( a, b, manifold, dt ); } - void blockPGSSolver( pod::RigidBody& a, pod::RigidBody& b, pod::Manifold& manifold, float dt ) { + void blockPGSSolver( pod::PhysicsBody& a, pod::PhysicsBody& b, pod::Manifold& manifold, float dt ) { const int count = std::min( (int) manifold.points.size(), 4 ); // precompute inv mass float invMassA = ( a.isStatic ? 0.0f : a.inverseMass ); @@ -260,7 +260,7 @@ namespace { } } - void resolveManifold( pod::RigidBody& a, pod::RigidBody& b, pod::Manifold& manifold, float dt ) { + void resolveManifold( pod::PhysicsBody& a, pod::PhysicsBody& b, pod::Manifold& manifold, float dt ) { if ( ::blockContactSolver ) { if ( manifold.points.size() == 2 ) return ::block2x2Solver( a, b, manifold, dt ); if ( manifold.points.size() == 3 ) return ::block3x3Solver( a, b, manifold, dt ); diff --git a/engine/src/utils/math/physics/sphere.inl b/engine/src/utils/math/physics/sphere.inl index 0cd2e04d..6fdb12fb 100644 --- a/engine/src/utils/math/physics/sphere.inl +++ b/engine/src/utils/math/physics/sphere.inl @@ -1,5 +1,5 @@ namespace { - bool sphereSphere( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps ) { + bool sphereSphere( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) { ASSERT_COLLIDER_TYPES( SPHERE, SPHERE ); auto delta = ::getPosition( b ) - ::getPosition( a ); @@ -16,7 +16,7 @@ namespace { manifold.points.emplace_back(pod::Contact{ contact, normal, penetration }); return true; } - bool sphereAabb( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps ) { + bool sphereAabb( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) { ASSERT_COLLIDER_TYPES( SPHERE, AABB ); const auto& sphere = a; @@ -51,15 +51,15 @@ namespace { manifold.points.emplace_back(pod::Contact{ contact, normal, penetration }); return true; } - bool spherePlane( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps ) { + bool spherePlane( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) { ASSERT_COLLIDER_TYPES( SPHERE, PLANE ); return planeSphere( b, a, manifold, eps ); } - bool sphereCapsule( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps ) { + bool sphereCapsule( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) { ASSERT_COLLIDER_TYPES( SPHERE, CAPSULE ); return capsuleSphere( b, a, manifold, eps ); } - bool sphereMesh( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps ) { + bool sphereMesh( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) { ASSERT_COLLIDER_TYPES( SPHERE, MESH ); return meshSphere( b, a, manifold, eps ); } diff --git a/engine/src/utils/math/physics/triangle.inl b/engine/src/utils/math/physics/triangle.inl index f4404b20..46c6ae04 100644 --- a/engine/src/utils/math/physics/triangle.inl +++ b/engine/src/utils/math/physics/triangle.inl @@ -104,7 +104,7 @@ namespace { } // if body is a mesh, apply its transform to the triangles, else reorient the normal with respect to the body - pod::TriangleWithNormal fetchTriangle( const uf::Mesh& mesh, size_t triID, const pod::RigidBody& body ) { + pod::TriangleWithNormal fetchTriangle( const uf::Mesh& mesh, size_t triID, const pod::PhysicsBody& body ) { auto tri = ::fetchTriangle( mesh, triID ); auto transform = ::getTransform( body ); @@ -259,7 +259,7 @@ namespace { return true; } - bool triangleAabb( const pod::TriangleWithNormal& tri, const pod::RigidBody& body, pod::Manifold& manifold, float eps ) { + bool triangleAabb( const pod::TriangleWithNormal& tri, const pod::PhysicsBody& body, pod::Manifold& manifold, float eps ) { const auto& aabb = body; auto closest = ::closestPointOnTriangle( ::getPosition( aabb ), tri ); @@ -286,7 +286,7 @@ namespace { manifold.points.emplace_back(pod::Contact{ contact, normal, penetration }); return true; } - bool triangleSphere( const pod::TriangleWithNormal& tri, const pod::RigidBody& body, pod::Manifold& manifold, float eps ) { + bool triangleSphere( const pod::TriangleWithNormal& tri, const pod::PhysicsBody& body, pod::Manifold& manifold, float eps ) { const auto& sphere = body; float r = sphere.collider.u.sphere.radius; @@ -313,7 +313,7 @@ namespace { return true; } // to-do: implement - bool trianglePlane( const pod::TriangleWithNormal& tri, const pod::RigidBody& body, pod::Manifold& manifold, float eps ) { + bool trianglePlane( const pod::TriangleWithNormal& tri, const pod::PhysicsBody& body, pod::Manifold& manifold, float eps ) { const auto& plane = body; auto normal = plane.collider.u.plane.normal; float d = plane.collider.u.plane.offset; @@ -357,7 +357,7 @@ namespace { } return hit; } - bool triangleCapsule( const pod::TriangleWithNormal& tri, const pod::RigidBody& body, pod::Manifold& manifold, float eps ) { + bool triangleCapsule( const pod::TriangleWithNormal& tri, const pod::PhysicsBody& body, pod::Manifold& manifold, float eps ) { const auto& capsule = body; float r = capsule.collider.u.capsule.radius; @@ -386,23 +386,23 @@ namespace { return true; } - bool triangleTriangle( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps ) { + bool triangleTriangle( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) { ASSERT_COLLIDER_TYPES( TRIANGLE, TRIANGLE ); return ::triangleTriangle( a.collider.u.triangle, b.collider.u.triangle, manifold, eps ); } - bool triangleAabb( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps ) { + bool triangleAabb( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) { ASSERT_COLLIDER_TYPES( TRIANGLE, AABB ); return ::triangleAabb( a.collider.u.triangle, b, manifold, eps ); } - bool triangleSphere( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps ) { + bool triangleSphere( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) { ASSERT_COLLIDER_TYPES( TRIANGLE, SPHERE ); return ::triangleSphere( a.collider.u.triangle, b, manifold, eps ); } - bool trianglePlane( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps ) { + bool trianglePlane( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) { ASSERT_COLLIDER_TYPES( TRIANGLE, PLANE ); return ::trianglePlane( a.collider.u.triangle, b, manifold, eps ); } - bool triangleCapsule( const pod::RigidBody& a, const pod::RigidBody& b, pod::Manifold& manifold, float eps ) { + bool triangleCapsule( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) { ASSERT_COLLIDER_TYPES( TRIANGLE, CAPSULE ); return ::triangleCapsule( a.collider.u.triangle, b, manifold, eps ); }