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 ); }