From 78171039a1230b22a314d669ac92d0b657d1e8d2 Mon Sep 17 00:00:00 2001 From: ecker Date: Thu, 28 May 2026 21:54:02 -0500 Subject: [PATCH] guh --- bin/data/config.json | 7 +- bin/data/entities/craeture.json | 5 +- bin/data/entities/craetureModel.json | 8 +- bin/data/entities/gui/hud/scripts/hud.lua | 2 +- bin/data/entities/playerModel.json | 4 +- bin/data/entities/scripts/craeture.lua | 9 +- bin/data/entities/scripts/player.lua | 27 ++-- engine/inc/uf/utils/debug/draw.h | 12 +- engine/inc/uf/utils/math/physics/structs.h | 1 + engine/inc/uf/utils/math/quaternion/pod.inl | 2 +- engine/inc/uf/utils/math/shapes.h | 21 ++- engine/inc/uf/utils/math/transform.h | 20 ++- .../inc/uf/utils/math/transform/transform.inl | 84 ++++------ engine/src/engine/ext/ext.cpp | 1 + engine/src/engine/ext/gui/behavior.cpp | 8 +- engine/src/engine/ext/player/behavior.cpp | 52 ++++--- engine/src/engine/ext/scene/behavior.cpp | 4 +- engine/src/engine/graph/animation.cpp | 145 ++++++++++++------ engine/src/engine/object/behavior.cpp | 12 +- engine/src/engine/object/behaviors/graph.cpp | 31 ++-- engine/src/ext/gltf/gltf.cpp | 2 + engine/src/ext/lua/usertypes/physics.cpp | 23 ++- engine/src/ext/lua/usertypes/transform.cpp | 30 ++-- engine/src/ext/openal/openal.cpp | 5 +- engine/src/utils/debug/draw.cpp | 26 ++-- engine/src/utils/math/physics/common.cpp | 15 +- .../math/physics/constraints/ballSocket.cpp | 7 +- .../math/physics/constraints/distance.cpp | 7 +- .../utils/math/physics/constraints/slider.cpp | 7 +- .../utils/math/physics/constraints/spring.cpp | 7 +- engine/src/utils/math/physics/impl.cpp | 2 +- .../utils/math/physics/narrowphase/aabb.cpp | 18 +++ .../utils/math/physics/narrowphase/epa.cpp | 6 +- .../utils/math/physics/narrowphase/gjk.cpp | 6 +- .../utils/math/physics/narrowphase/hull.cpp | 10 ++ .../utils/math/physics/narrowphase/mesh.cpp | 10 ++ .../utils/math/physics/narrowphase/obb.cpp | 50 ++++-- .../utils/math/physics/narrowphase/ray.cpp | 1 + .../utils/math/physics/narrowphase/sphere.cpp | 27 ++++ .../math/physics/narrowphase/triangle.cpp | 12 +- engine/src/utils/math/physics/solvers/ngs.cpp | 4 +- engine/src/utils/math/physics/tests.inl | 46 +++--- 42 files changed, 472 insertions(+), 304 deletions(-) diff --git a/bin/data/config.json b/bin/data/config.json index 5dd42b3e..05da5645 100644 --- a/bin/data/config.json +++ b/bin/data/config.json @@ -350,11 +350,12 @@ "max": 0.01 // 0.2 }, "debug draw": { - "static": true, - "dynamic": true, + "static": false, + "dynamic": false, "contacts": false, "constraints": true, - "rays": false + "rays": false, + "depthTest": false }, "fixed step": true, "substeps": 4 diff --git a/bin/data/entities/craeture.json b/bin/data/entities/craeture.json index 9110a3d5..2ca8465f 100644 --- a/bin/data/entities/craeture.json +++ b/bin/data/entities/craeture.json @@ -14,7 +14,8 @@ "position": [ -7, 0, -44 ], //"position": [ 0, 1.5, 21 ], //"position": [ 16.3489, 1.37972, -68.1571 ], - "scale": [ 0.3, 0.3, 0.3 ] + "scale": [ 0.09, 0.09, 0.09 ] + //"scale": [ 1, 1, 1 ] }, "system": { "hot reload": { @@ -31,7 +32,7 @@ } }, "physics": { - "ragdoll": true + "ragdoll": false } } /* diff --git a/bin/data/entities/craetureModel.json b/bin/data/entities/craetureModel.json index 58e30141..1fa91f17 100644 --- a/bin/data/entities/craetureModel.json +++ b/bin/data/entities/craetureModel.json @@ -4,7 +4,7 @@ "ignore": false, "import": "/model.json", "assets": [ - // "/player/bear.glb" + // "/player/pbear.glb" { "filename": "/player/bear/graph.json" } ], "behaviors": [], @@ -16,7 +16,7 @@ "axis": [ 0, 1, 0 ], "angle": 0 }, - // "scale": [ 0.35, 0.35, 0.35 ], + "scale": [ 0.09, 0.09, 0.09 ], "reference": "parent" }, "system": { @@ -33,7 +33,7 @@ } }, "exporter": { - "enabled": false, + "enabled": true, "unwrap": false, "optimize": false }, @@ -52,7 +52,7 @@ "skinned": true }, "animations": { - "animation": "idle" + "animation": "wank" } } } diff --git a/bin/data/entities/gui/hud/scripts/hud.lua b/bin/data/entities/gui/hud/scripts/hud.lua index 1e0d578d..2d5e4a70 100644 --- a/bin/data/entities/gui/hud/scripts/hud.lua +++ b/bin/data/entities/gui/hud/scripts/hud.lua @@ -163,7 +163,7 @@ ent:bind( "tick", function(self) for k, obj in pairs(children) do local transform = obj:getComponent("Transform") transform.orientation = orientation - transform.model = controllerCamera:getProjection() * Matrix4f.translate( transform.position ) * transform.orientation:matrix() * Matrix4f.scale( transform.scale ) --Matrix4f.scale( Vector3f( 1.7776 * 2, 2, 2 ) ) + -- controllerCamera:getProjection() * Matrix4f.translate( transform.position ) * transform.orientation:matrix() * Matrix4f.scale( transform.scale ) --Matrix4f.scale( Vector3f( 1.7776 * 2, 2, 2 ) ) end end ) diff --git a/bin/data/entities/playerModel.json b/bin/data/entities/playerModel.json index 70279e31..bcccdf3d 100644 --- a/bin/data/entities/playerModel.json +++ b/bin/data/entities/playerModel.json @@ -4,7 +4,7 @@ "ignore": false, "import": "/model.json", "assets": [ - // "/player/ben.glb" + // "/player/bear.glb" { "filename": "/player/bear/graph.json" } ], "behaviors": [ @@ -18,7 +18,7 @@ "axis": [ 0, 1, 0 ], "angle": 0 }, - "scale": [ 0.16, 0.16, 0.16 ] + "scale": [ 0.09, 0.09, 0.09 ] }, "metadata": { "track": true, diff --git a/bin/data/entities/scripts/craeture.lua b/bin/data/entities/scripts/craeture.lua index 91e8c971..a7db132f 100644 --- a/bin/data/entities/scripts/craeture.lua +++ b/bin/data/entities/scripts/craeture.lua @@ -16,14 +16,15 @@ local target_transform = nil local soundEmitter = ent -- on tick ent:bind( "tick", function(self) + axes = transform:axes() -- rotate to target if target_transform ~= nil then local target = (target_transform.position - transform.position):normalize() - local dot = transform.forward:dot( target ) + local dot = axes.forward:dot( target ) if dot < 1.0 then - local cross = Vector3f.cross( transform.forward, target ):normalize() - local axis = transform.up - local angle = Vector3f.signedAngle( transform.forward, target, axis ) + local cross = Vector3f.cross( axes.forward, target ):normalize() + local axis = axes.up + local angle = Vector3f.signedAngle( axes.forward, target, axis ) local rot = Quaternion.axisAngle( axis, angle * time.delta() * 4 ) if physicsBody:initialized() then diff --git a/bin/data/entities/scripts/player.lua b/bin/data/entities/scripts/player.lua index 707a61eb..9ad07016 100644 --- a/bin/data/entities/scripts/player.lua +++ b/bin/data/entities/scripts/player.lua @@ -75,11 +75,11 @@ end local useDistance = 6 local pullDistance = useDistance * 4 -local function tickFlashlight( transform, inputs ) +local function tickFlashlight( transform, axes, inputs ) -- update light position if light.enabled then local center = transform.position - local direction = transform.forward * 8 + local direction = axes.forward * 8 local offset = 0.25 local _, depth = physicsBody:rayCast(center, direction) depth = math.clamp(depth, 0, 0.5) @@ -132,12 +132,12 @@ local function onUse( payload ) playSound(validUse and "select" or "deny") end -local function tickUse( transform, inputs ) +local function tickUse( transform, axes, inputs ) -- trigger use if timers.use:elapsed() > 0.5 and inputs["E"] then timers.use:reset() local center = transform.position - local direction = transform.forward * useDistance + local direction = axes.forward * useDistance local prop, depth = physicsBody:rayCast(center, direction) local payload = { @@ -150,13 +150,13 @@ local function tickUse( transform, inputs ) end end -local function tickGravGun( transform, inputs ) +local function tickGravGun( transform, axes, inputs ) -- not holding anything if heldObject.uid == 0 then -- try and launch object in sights if inputs["mouse2"] then local center = transform.position - local direction = transform.forward * pullDistance + local direction = axes.forward * pullDistance 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") @@ -165,7 +165,7 @@ local function tickGravGun( transform, inputs ) local strength = 500 local distanceSquared = (heldObjectTransform.position - transform.position):magnitude() - heldObjectPhysicsBody:applyImpulse( transform.forward * -heldObjectPhysicsBody:getMass() * strength / distanceSquared ) + heldObjectPhysicsBody:applyImpulse( axes.forward * -heldObjectPhysicsBody:getMass() * strength / distanceSquared ) if timers.physcannon:elapsed() > 1.0 then timers.physcannon:reset() @@ -194,18 +194,18 @@ local function tickGravGun( transform, inputs ) heldObject.uid = 0 heldObjectPhysicsBody:enableGravity(true) - heldObjectPhysicsBody:applyImpulse( transform.forward * heldObjectPhysicsBody:getMass() * 50 ) + heldObjectPhysicsBody:applyImpulse( axes.forward * heldObjectPhysicsBody:getMass() * 50 ) playSound("phys_launch"..math.random(1,4)) else -- update rotation if heldObject.rotate then - --heldObjectTransform.orientation = Quaternion.lookAt( (heldObjectTransform.position - transform.position):normalize(), transform.up ) + --heldObjectTransform.orientation = Quaternion.lookAt( (heldObjectTransform.position - transform.position):normalize(), axes.up ) heldObjectTransform.orientation = cameraTransform:flatten().orientation end -- move held object - local forward = transform.forward * heldObject.distance + local forward = axes.forward * heldObject.distance if heldObject.smoothSpeed ~= 0 then local heldObjectFlattened = heldObjectTransform:flatten() @@ -252,15 +252,16 @@ ent:bind( "tick", function(self) -- eye transform local flattenedTransform = fixedCamera and transform:flatten() or cameraTransform:flatten() + local axes = flattenedTransform:axes() -- update flashlight - tickFlashlight( flattenedTransform, inputs ) + tickFlashlight( flattenedTransform, axes, inputs ) -- update use - tickUse( flattenedTransform, inputs ) + tickUse( flattenedTransform, axes, inputs ) -- update HOLP - tickGravGun( flattenedTransform, inputs ) + tickGravGun( flattenedTransform, axes, inputs ) -- get collision events --[[ diff --git a/engine/inc/uf/utils/debug/draw.h b/engine/inc/uf/utils/debug/draw.h index 27484b3f..3f246b47 100644 --- a/engine/inc/uf/utils/debug/draw.h +++ b/engine/inc/uf/utils/debug/draw.h @@ -8,12 +8,12 @@ namespace uf { namespace debug { void UF_API drawLine( const pod::Vector3f& start, const pod::Vector3f& end, const pod::Vector4f& color = { 1, 1, 1, 1 } ); - void UF_API drawAabb( pod::AABB aabb, pod::Transform<> transform = {} ); - void UF_API drawObb( pod::OBB obb, pod::Transform<> transform = {} ); - void UF_API drawSphere( pod::Sphere sphere, pod::Transform<> transform = {} ); - void UF_API drawCapsule( pod::Capsule capsule, pod::Transform<> transform = {} ); - void UF_API drawPlane( pod::Plane plane, pod::Transform<> transform = {} ); - void UF_API drawTriangle( pod::Triangle tri, pod::Transform<> transform = {} ); + void UF_API drawShape( const pod::AABB& aabb, const pod::Transform<>& transform = {} ); + void UF_API drawShape( const pod::OBB& obb, const pod::Transform<>& transform = {} ); + void UF_API drawShape( const pod::Sphere& sphere, const pod::Transform<>& transform = {} ); + void UF_API drawShape( const pod::Capsule& capsule, const pod::Transform<>& transform = {} ); + void UF_API drawShape( const pod::Plane& plane, const pod::Transform<>& transform = {} ); + void UF_API drawShape( const pod::Triangle& tri, const pod::Transform<>& transform = {} ); void UF_API addLine( const pod::Vector3f& start, const pod::Vector3f& end, const pod::Vector4f& color = { 1, 1, 1, 1 }, float ttl = 1.0f ); void UF_API draw( float dt = 0 ); diff --git a/engine/inc/uf/utils/math/physics/structs.h b/engine/inc/uf/utils/math/physics/structs.h index 48c50145..84277007 100644 --- a/engine/inc/uf/utils/math/physics/structs.h +++ b/engine/inc/uf/utils/math/physics/structs.h @@ -491,6 +491,7 @@ namespace pod { bool contacts = false; bool constraints = false; bool rays = false; + bool depthTest = true; } debugDraw; }; diff --git a/engine/inc/uf/utils/math/quaternion/pod.inl b/engine/inc/uf/utils/math/quaternion/pod.inl index 11762c4b..303ff95d 100644 --- a/engine/inc/uf/utils/math/quaternion/pod.inl +++ b/engine/inc/uf/utils/math/quaternion/pod.inl @@ -166,7 +166,7 @@ template pod::Quaternion uf::quaternion::unitVectors( const pod:: pod::Vector3t cross = uf::vector::cross(uNorm, vNorm); T s = sqrt((1 + dot) * 2); - return uf::quaternion::normalize({ + return uf::quaternion::normalize(pod::Quaternion<>{ .x = cross.x / s, .y = cross.y / s, .z = cross.z / s, diff --git a/engine/inc/uf/utils/math/shapes.h b/engine/inc/uf/utils/math/shapes.h index defa60ca..b5aeb693 100644 --- a/engine/inc/uf/utils/math/shapes.h +++ b/engine/inc/uf/utils/math/shapes.h @@ -3,22 +3,27 @@ #include #include +#define OBB_EXTENT_CENTER 0 + namespace pod { struct Plane { - alignas(16) pod::Vector3f normal; + pod::Vector3f normal; float offset; }; struct AABB { - alignas(16) pod::Vector3f min; - alignas(16) pod::Vector3f max; - // operator OBB() const { return OBB{ (min + max) * 0.5f, (min - max) * 0.5f }; } + pod::Vector3f min; + pod::Vector3f max; }; struct OBB { - alignas(16) pod::Vector3f center; - alignas(16) pod::Vector3f extent; - // operator AABB() const { return AABB{ center - extent, center + extent }; } + #if OBB_EXTENT_CENTER + pod::Vector3f extent; + pod::Vector3f center; + #else + pod::Vector3f center; + pod::Vector3f extent; + #endif }; struct Sphere { @@ -27,7 +32,7 @@ namespace pod { struct Capsule { float radius; - float halfHeight; + pod::Vector3f up; }; struct Ray { diff --git a/engine/inc/uf/utils/math/transform.h b/engine/inc/uf/utils/math/transform.h index f887f214..7e3178bd 100644 --- a/engine/inc/uf/utils/math/transform.h +++ b/engine/inc/uf/utils/math/transform.h @@ -21,29 +21,27 @@ namespace pod { typedef T type_t; pod::Vector3t position = {0, 0,0 }; - pod::Vector3t scale = {1, 1, 1}; - - pod::Vector3t up = {0, 1, 0}; - pod::Vector3t right = {1, 0, 0}; - pod::Vector3t forward = {0, 0, 1}; - pod::Quaternion orientation = {0, 0, 0, 1}; - - pod::Matrix4t model = uf::matrix::identity(); + pod::Vector3t scale = {1, 1, 1}; pod::Transform* reference = NULL; }; + + struct Axes { + pod::Vector3f right = { 1, 0, 0 }; + pod::Vector3f up = { 0, 1, 0 }; + pod::Vector3f forward = { 0, 0, 1 }; + }; } namespace uf { namespace transform { template pod::Transform& /*UF_API*/ initialize( pod::Transform& transform ); template pod::Transform /*UF_API*/ initialize(); + template pod::Axes /*UF_API*/ axes( const pod::Transform& transform, const pod::Vector3t& at = {} ); template pod::Transform& /*UF_API*/ lookAt( pod::Transform& transform, const pod::Vector3t& at ); template pod::Transform& /*UF_API*/ move( pod::Transform& transform, const pod::Vector3t& axis, pod::Math::num_t delta ); template pod::Transform& /*UF_API*/ move( pod::Transform& transform, const pod::Vector3t& delta ); - template pod::Transform& /*UF_API*/ reorient( pod::Transform& transform ); - template pod::Transform /*UF_API*/ reorient( const pod::Transform& transform ); template pod::Transform& /*UF_API*/ rotate( pod::Transform& transform, const pod::Vector3t& axis, pod::Math::num_t delta ); template pod::Transform& /*UF_API*/ rotate( pod::Transform& transform, const pod::Quaternion& quat ); template pod::Transform& /*UF_API*/ scale( pod::Transform& transform, const pod::Vector3t& factor ); @@ -52,7 +50,7 @@ namespace uf { template pod::Matrix4t /*UF_API*/ model( const pod::Transform& transform, bool flatten = false, size_t depth = SIZE_MAX ); template pod::Transform /*UF_API*/ fromMatrix( const pod::Matrix4t& matrix ); template pod::Transform& /*UF_API*/ reference( pod::Transform& transform, const pod::Transform& parent, bool reorient = true ); - template pod::Transform /*UF_API*/ interpolate( const pod::Transform& from, const pod::Transform& to, float factor, bool reorient = true ); + template pod::Transform /*UF_API*/ interpolate( const pod::Transform& from, const pod::Transform& to, float factor ); template pod::Transform /*UF_API*/ inverse(const pod::Transform& t); template pod::Vector3t /*UF_API*/ apply( const pod::Transform& transform, const pod::Vector3t& point ); template pod::Vector3t /*UF_API*/ applyInverse(const pod::Transform& t, const pod::Vector3t& worldPoint); diff --git a/engine/inc/uf/utils/math/transform/transform.inl b/engine/inc/uf/utils/math/transform/transform.inl index d08a73fc..914c99e8 100644 --- a/engine/inc/uf/utils/math/transform/transform.inl +++ b/engine/inc/uf/utils/math/transform/transform.inl @@ -2,13 +2,7 @@ template pod::Transform& /*UF_API*/ uf::transform::initialize( pod::Transform& transform ) { transform.position = {0, 0, 0}; transform.scale = {1, 1, 1}; - - transform.up = {0, 1, 0}; - transform.right = {1, 0, 0}; - transform.forward = {0, 0, 1}; - transform.orientation = {0, 0, 0, 1}; - transform.model = uf::matrix::identity(); transform.reference = nullptr; return transform; @@ -20,18 +14,27 @@ pod::Transform /*UF_API*/ uf::transform::initialize() { return uf::transform::initialize(transform); } +template +pod::Axes /*UF_API*/ uf::transform::axes( const pod::Transform& transform, const pod::Vector3t& at ) { + pod::Axes axes; + auto& q = transform.orientation; + axes.forward = { 2 * (q.x * q.z + q.w * q.y), 2 * (q.y * q.z - q.w * q.x), 1 - 2 * (q.x * q.x + q.y * q.y) }; + axes.up = { 2 * (q.x * q.y - q.w * q.z), 1 - 2 * (q.x * q.x + q.z * q.z), 2 * (q.y * q.z + q.w * q.x)}; + axes.right = { 1 - 2 * (q.y * q.y + q.z * q.z), 2 * (q.x * q.y + q.w * q.z), 2 * (q.x * q.z - q.w * q.y)}; + + if ( at != pod::Vector3f{} ) { + axes.forward = uf::vector::normalize( at - transform.position ); + axes.right = uf::vector::normalize(uf::vector::cross( axes.up, axes.forward )); + axes.up = uf::vector::normalize(uf::vector::cross( axes.forward, axes.right )); + } + + return axes; +} + template pod::Transform& /*UF_API*/ uf::transform::lookAt( pod::Transform& transform, const pod::Vector3t& at ) { - pod::Vector3t forward = uf::vector::normalize( at - transform.position ); - pod::Vector3t right = uf::vector::normalize(uf::vector::cross( transform.up, forward )); - pod::Vector3t up = uf::vector::normalize(uf::vector::cross( forward, right )); - - transform.up = up; - transform.right = right; - transform.forward = forward; - - transform.orientation = uf::quaternion::lookAt( forward, up ); - + auto axes = uf::transform::axes( transform, at ); + transform.orientation = uf::quaternion::lookAt( axes.forward, axes.up ); return transform; } @@ -47,32 +50,17 @@ pod::Transform& /*UF_API*/ uf::transform::move( pod::Transform& transform, return transform; } -template -pod::Transform& /*UF_API*/ uf::transform::reorient( pod::Transform& transform ) { - pod::Quaternion q = transform.orientation; - transform.forward = { 2 * (q.x * q.z + q.w * q.y), 2 * (q.y * q.z - q.w * q.x), 1 - 2 * (q.x * q.x + q.y * q.y) }; - transform.up = { 2 * (q.x * q.y - q.w * q.z), 1 - 2 * (q.x * q.x + q.z * q.z), 2 * (q.y * q.z + q.w * q.x)}; - transform.right = { 1 - 2 * (q.y * q.y + q.z * q.z), 2 * (q.x * q.y + q.w * q.z), 2 * (q.x * q.z - q.w * q.y)}; - return transform; -} - -template -pod::Transform /*UF_API*/ uf::transform::reorient( const pod::Transform& _transform ) { - pod::Transform transform = _transform; - return uf::transform::reorient(transform); -} - template pod::Transform& /*UF_API*/ uf::transform::rotate( pod::Transform& transform, const pod::Vector3t& axis, pod::Math::num_t delta ) { pod::Quaternion<> quat = uf::quaternion::axisAngle( axis, delta ); transform.orientation = uf::vector::normalize(uf::quaternion::multiply(quat, transform.orientation)); - return uf::transform::reorient(transform); + return transform; } template pod::Transform& /*UF_API*/ uf::transform::rotate( pod::Transform& transform, const pod::Quaternion& quat ) { transform.orientation = uf::vector::normalize(uf::quaternion::multiply(quat, transform.orientation)); - return uf::transform::reorient(transform); + return transform; } template @@ -98,12 +86,11 @@ pod::Transform /*UF_API*/ uf::transform::flatten( const pod::Transform& tr combined.position = pointer->position + uf::quaternion::rotate(pointer->orientation, combined.position * pointer->scale); combined.orientation = uf::quaternion::multiply( pointer->orientation, combined.orientation ); combined.scale = combined.scale * pointer->scale; - combined.model = pointer->model * combined.model; if ( pointer == pointer->reference ) break; pointer = pointer->reference; } - return uf::transform::reorient(combined); + return combined; } template @@ -112,8 +99,7 @@ pod::Matrix4t /*UF_API*/ uf::transform::model( const pod::Transform& trans pod::Transform flat = uf::transform::flatten(transform, depth); return uf::matrix::translate( uf::matrix::identity(), flat.position ) * uf::quaternion::matrix( flat.orientation ) * - uf::matrix::scale( uf::matrix::identity(), flat.scale ) * - flat.model; + uf::matrix::scale( uf::matrix::identity(), flat.scale ); } pod::Matrix4t matrix = uf::matrix::identity(); @@ -122,8 +108,7 @@ pod::Matrix4t /*UF_API*/ uf::transform::model( const pod::Transform& trans do { pod::Matrix4t modelMat = uf::matrix::translate( uf::matrix::identity(), pointer->position ) * uf::quaternion::matrix( pointer->orientation ) * - uf::matrix::scale( uf::matrix::identity(), pointer->scale ) * - pointer->model; + uf::matrix::scale( uf::matrix::identity(), pointer->scale ); matrix = modelMat * matrix; if ( pointer == pointer->reference ) break; @@ -136,29 +121,25 @@ pod::Matrix4t /*UF_API*/ uf::transform::model( const pod::Transform& trans template pod::Transform uf::transform::fromMatrix( const pod::Matrix4t& matrix ) { pod::Transform transform; - transform.position = uf::matrix::multiply( matrix, pod::Vector4f{ 0, 0, 0, 1 } ); + transform.position = uf::matrix::multiply( matrix, pod::Vector4f{ 0, 0, 0, 1 } ); transform.orientation = uf::quaternion::fromMatrix( matrix ); - transform.model = matrix; - return reorient( transform ); + // transform.scale = ...; + return transform; } template pod::Transform& /*UF_API*/ uf::transform::reference( pod::Transform& transform, const pod::Transform& parent, bool reorient ) { transform.reference = const_cast*>(&parent); - if ( !reorient ) { - return transform; - } - - transform.position = parent.position - transform.position; + if ( reorient ) transform.position = parent.position - transform.position; return transform; } template -pod::Transform /*UF_API*/ uf::transform::interpolate( const pod::Transform& from, const pod::Transform& to, float factor, bool reorient ) { +pod::Transform /*UF_API*/ uf::transform::interpolate( const pod::Transform& from, const pod::Transform& to, float factor ) { pod::Transform transform = to; transform.position = uf::vector::lerp( from.position, to.position, factor ); transform.orientation = uf::quaternion::slerp( from.orientation, to.orientation, factor ); - return reorient ? uf::transform::reorient( transform ) : transform; + return transform; } template @@ -183,7 +164,7 @@ pod::Transform uf::transform::inverse(const pod::Transform& t) { negPos.z * sInv.z }); - return uf::transform::reorient(inv); + return inv; } template @@ -221,7 +202,6 @@ ext::json::Value /*UF_API*/ uf::transform::encode( const pod::Transform& t, b json["position"] = uf::vector::encode(transform.position, settings); json["orientation"] = uf::vector::encode(transform.orientation, settings); json["scale"] = uf::vector::encode(transform.scale, settings); - json["model"] = uf::matrix::encode(transform.model, settings); return json; } @@ -237,8 +217,6 @@ pod::Transform& /*UF_API*/ uf::transform::decode( const ext::json::Value& _js T angle = json["rotation"]["angle"].as(); transform.orientation = uf::quaternion::axisAngle( axis, angle ); } - - transform.model = uf::matrix::decode(json["model"], transform.model); return transform; } diff --git a/engine/src/engine/ext/ext.cpp b/engine/src/engine/ext/ext.cpp index d9ebf522..2b0008a1 100644 --- a/engine/src/engine/ext/ext.cpp +++ b/engine/src/engine/ext/ext.cpp @@ -235,6 +235,7 @@ void UF_API uf::load( ext::json::Value& json ) { uf::physics::settings.debugDraw.contacts = configEnginePhysicsDebugDrawJson["contacts"].as( uf::physics::settings.debugDraw.contacts ); uf::physics::settings.debugDraw.constraints = configEnginePhysicsDebugDrawJson["constraints"].as( uf::physics::settings.debugDraw.constraints ); uf::physics::settings.debugDraw.rays = configEnginePhysicsDebugDrawJson["rays"].as( uf::physics::settings.debugDraw.rays ); + uf::physics::settings.debugDraw.depthTest = configEnginePhysicsDebugDrawJson["depthTest"].as( uf::physics::settings.debugDraw.depthTest ); } else if ( configEnginePhysicsDebugDrawJson.is() && configEnginePhysicsDebugDrawJson.as() ) { uf::physics::settings.debugDraw.mask = pod::Collider::CATEGORY_ALL; diff --git a/engine/src/engine/ext/gui/behavior.cpp b/engine/src/engine/ext/gui/behavior.cpp index cbafdb74..683e4be3 100644 --- a/engine/src/engine/ext/gui/behavior.cpp +++ b/engine/src/engine/ext/gui/behavior.cpp @@ -512,7 +512,7 @@ void ext::GuiBehavior::tick( uf::Object& self ) { for ( auto i = 0; i < uf::renderer::settings::maxViews; ++i ) { if ( metadata.mode == 1 ) { - uniforms.matrices[i].model = transform.model; + uniforms.matrices[i].model = uf::transform::model( transform ); } else if ( metadata.mode == 2 ) { auto& scene = uf::scene::getCurrentScene(); auto& controller = scene.getController(); @@ -523,14 +523,12 @@ void ext::GuiBehavior::tick( uf::Object& self ) { camera.getProjection(i) * uf::matrix::translate( uf::matrix::identity(), flatten.position ) * uf::matrix::scale( uf::matrix::identity(), flatten.scale ) * - uf::quaternion::matrix( flatten.orientation ) * - flatten.model; + uf::quaternion::matrix( flatten.orientation ); } else { uniforms.matrices[i].model = uf::matrix::translate( uf::matrix::identity(), flatten.position ) * uf::matrix::scale( uf::matrix::identity(), flatten.scale ) * - uf::quaternion::matrix( flatten.orientation ) * - flatten.model; + uf::quaternion::matrix( flatten.orientation ); } } diff --git a/engine/src/engine/ext/player/behavior.cpp b/engine/src/engine/ext/player/behavior.cpp index d6448460..f67dae72 100644 --- a/engine/src/engine/ext/player/behavior.cpp +++ b/engine/src/engine/ext/player/behavior.cpp @@ -126,10 +126,14 @@ void ext::PlayerBehavior::initialize( uf::Object& self ) { UF_BEHAVIOR_METADATA_BIND_SERIALIZER_HOOKS(metadata, metadataJson); } void ext::PlayerBehavior::tick( uf::Object& self ) { + auto& transform = this->getComponent>(); + auto& camera = this->getComponent(); auto& cameraTransform = camera.getTransform(); - - auto& transform = this->getComponent>(); + + auto cameraAxes = uf::transform::axes( cameraTransform ); + auto axes = uf::transform::axes( transform ); + auto& scene = uf::scene::getCurrentScene(); auto& metadata = this->getComponent(); @@ -296,7 +300,7 @@ void ext::PlayerBehavior::tick( uf::Object& self ) { uf::Object* pointer = NULL; float length = metadata.use.length; // pod::Vector3f center = transform.position + cameraTransform.position; - // pod::Vector3f direction = uf::vector::normalize( transform.forward + pod::Vector3f{ 0, cameraTransform.forward.y, 0 } ) * length; + // pod::Vector3f direction = uf::vector::normalize( axes.forward + pod::Vector3f{ 0, cameraAxes.forward.y, 0 } ) * length; auto flattened = uf::transform::flatten( cameraTransform ); pod::Vector3f center = flattened.position; pod::Vector3f direction = flattened.forward * length; @@ -385,10 +389,10 @@ void ext::PlayerBehavior::tick( uf::Object& self ) { metadata.system.menu = stats.menu; } - pod::Transform<> translator = transform; + pod::Axes translator = uf::transform::axes( transform ); #if UF_USE_OPENVR // use the orientation of our controller to determine our target - if ( ext::openvr::context ) { + /*if ( ext::openvr::context ) { bool useController = true; translator.orientation = uf::quaternion::multiply( transform.orientation, useController ? ext::openvr::controllerQuaternion( vr::Controller_Hand::Hand_Right ) : ext::openvr::hmdQuaternion() ); translator = uf::transform::reorient( translator ); @@ -401,17 +405,17 @@ void ext::PlayerBehavior::tick( uf::Object& self ) { translator.forward = uf::vector::normalize( translator.forward ); translator.right = uf::vector::normalize( translator.right ); - } else + } else*/ #endif // un-flatted if noclipped if ( metadata.camera.fixed ) { - translator = cameraTransform; + translator = uf::transform::axes( cameraTransform ); translator.forward.y = 0; translator.forward = uf::vector::normalize( translator.forward ); } else if ( stats.noclipped || physicsBody.gravity == pod::Vector3f{0,0,0} ){ - translator.forward.y += cameraTransform.forward.y; + translator.forward.y += cameraAxes.forward.y; translator.forward = uf::vector::normalize( translator.forward ); } @@ -452,12 +456,12 @@ void ext::PlayerBehavior::tick( uf::Object& self ) { physicsBody.velocity += target * std::clamp( speed.move * factor - uf::vector::dot( physicsBody.velocity, target ), 0.0f, speed.move * 10 * ONE_OVER_SIXTY /*uf::physics::time::delta*/ ); } - auto dot = uf::vector::dot( transform.forward, target ); + auto dot = uf::vector::dot( axes.forward, target ); if ( !metadata.movement.strafe && dot < 1.0f ) { - // auto cross = uf::vector::normalize( uf::vector::cross( transform.forward, target ) ); - // auto axis = cross == pod::Vector3f{0, 0, 0} ? transform.up : cross; - auto axis = transform.up; - float angle = uf::vector::signedAngle( transform.forward, target, axis ) * ONE_OVER_SIXTY /*uf::physics::time::delta*/ * 4; // speed.rotate; + // auto cross = uf::vector::normalize( uf::vector::cross( axes.forward, target ) ); + // auto axis = cross == pod::Vector3f{0, 0, 0} ? axes.up : cross; + auto axis = axes.up; + float angle = uf::vector::signedAngle( axes.forward, target, axis ) * ONE_OVER_SIXTY /*uf::physics::time::delta*/ * 4; // speed.rotate; if ( physicsBody.object ) uf::physics::applyRotation( physicsBody, axis, angle ); else uf::transform::rotate( transform, axis, angle ); @@ -510,39 +514,39 @@ 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 ( physicsBody.object ) uf::physics::applyRotation( physicsBody, transform.up, lookDelta.x ); else - uf::transform::rotate( transform, transform.up, lookDelta.x ); + if ( physicsBody.object ) uf::physics::applyRotation( physicsBody, axes.up, lookDelta.x ); else + uf::transform::rotate( transform, axes.up, lookDelta.x ); } else metadata.camera.limit.current.x -= lookDelta.x; } if ( lookDelta.y != 0 ) { 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 ( physicsBody.object && !physicsBody.shared ) uf::physics::applyRotation( physicsBody, cameraTransform.right, lookDelta.y ); else - uf::transform::rotate( cameraTransform, cameraTransform.right, lookDelta.y ); + // if ( physicsBody.object && !physicsBody.shared ) uf::physics::applyRotation( physicsBody, cameraAxes.right, lookDelta.y ); else + uf::transform::rotate( cameraTransform, cameraAxes.right, lookDelta.y ); } else metadata.camera.limit.current.y -= lookDelta.y; } } else if ( metadata.system.control ) { if ( keys.lookRight ^ keys.lookLeft ) { - if ( physicsBody.object ) uf::physics::applyRotation( physicsBody, transform.up, speed.rotate * (keys.lookRight ? 1 : -1) ); else - uf::transform::rotate( transform, transform.up, speed.rotate * (keys.lookRight ? 1 : -1) ); + if ( physicsBody.object ) uf::physics::applyRotation( physicsBody, axes.up, speed.rotate * (keys.lookRight ? 1 : -1) ); else + uf::transform::rotate( transform, axes.up, speed.rotate * (keys.lookRight ? 1 : -1) ); } if ( keys.lookUp ^ keys.lookDown ) { float direction = keys.lookUp ? 1 : -1; if ( metadata.camera.invert.y ) direction *= -1; - uf::transform::rotate( cameraTransform, cameraTransform.right, speed.rotate * direction ); + uf::transform::rotate( cameraTransform, cameraAxes.right, speed.rotate * direction ); } } } else { if ( keys.lookRight ^ keys.lookLeft ) { - // auto rotation = uf::quaternion::axisAngle( cameraTransform.up, uf::physics::time::delta * (keys.lookRight ? 1 : -1) ); + // auto rotation = uf::quaternion::axisAngle( cameraAxes.up, uf::physics::time::delta * (keys.lookRight ? 1 : -1) ); // cameraTransform.position = uf::quaternion::rotate( rotation, cameraTransform.position - transform.position ); } if ( keys.lookUp ^ keys.lookDown ) { - // if ( physicsBody.object && !physicsBody.shared ) uf::physics::applyRotation( physicsBody, cameraTransform.right, lookDelta.y ); else + // if ( physicsBody.object && !physicsBody.shared ) uf::physics::applyRotation( physicsBody, cameraAxes.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 ); + uf::transform::rotate( cameraTransform, cameraAxes.right, speed.rotate * direction ); } } { @@ -556,7 +560,7 @@ void ext::PlayerBehavior::tick( uf::Object& self ) { cameraTransform.reference = NULL; cameraTransform.position = transform.position + metadata.camera.offset; // cameraTransform.orientation = uf::vector::decode( metadataJson["camera"]["orientation"], uf::quaternion::identity() ); - cameraTransform = uf::transform::reorient( cameraTransform ); + cameraAxes = uf::transform::axes( cameraTransform ); } else { if ( metadata.camera.offset != pod::Vector3f{0,0,0} ) { //auto flattened = uf::transform::flatten( cameraTransform ); diff --git a/engine/src/engine/ext/scene/behavior.cpp b/engine/src/engine/ext/scene/behavior.cpp index 5b899874..513a889b 100644 --- a/engine/src/engine/ext/scene/behavior.cpp +++ b/engine/src/engine/ext/scene/behavior.cpp @@ -432,9 +432,7 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) { transform = uf::transform::reorient( transform ); */ } - transform = uf::transform::flatten( transform ); - transform.forward *= -1; - + transform = uf::transform::flatten( transform ); ext::al::listener( transform ); } #endif diff --git a/engine/src/engine/graph/animation.cpp b/engine/src/engine/graph/animation.cpp index 8e1d9138..b979fee1 100644 --- a/engine/src/engine/graph/animation.cpp +++ b/engine/src/engine/graph/animation.cpp @@ -82,8 +82,7 @@ namespace { return uf::matrix::translate( uf::matrix::identity(), transform.position ) * uf::quaternion::matrix(transform.orientation) * - uf::matrix::scale( uf::matrix::identity(), transform.scale ) * - transform.model; + uf::matrix::scale( uf::matrix::identity(), transform.scale ); } pod::Matrix4f worldMatrix( const pod::Graph& graph, int32_t index ) { pod::Matrix4f matrix = ::localMatrix( graph, index ); @@ -180,12 +179,15 @@ void uf::graph::updateAnimation( pod::Graph& graph, float delta ) { return; } + if ( graph.sequence.empty() ) goto UPDATE; if ( graph.settings.animations.override.a >= 0 ) goto OVERRIDE; { uf::stl::string name = graph.sequence.front(); pod::Animation* animation = &storage.animations.map[name]; // &graph.animations[name]; animation->cur += delta * graph.settings.animations.speed; // * graph.settings.animations.override.speed; + + // UF_MSG_DEBUG("entity={}, name={}, cur={}", graph.root.entity->getParent().getName(), name, animation->cur); if ( animation->end < animation->cur ) { animation->cur = graph.settings.animations.loop ? animation->cur - animation->end : 0; // go-to next animation @@ -243,6 +245,24 @@ void uf::graph::updateAnimation( pod::Graph& graph, pod::Node& node ) { auto& scene = uf::scene::getCurrentScene(); auto& storage = ::getGraphStorage( scene ); +#if 1 + if ( 0 <= node.skin && node.skin < graph.skins.size() ) { + pod::Matrix4f nodeMatrix = ::worldMatrix( graph, node.index ); + pod::Matrix4f inverseTransform = uf::matrix::inverse( nodeMatrix ); + + auto& name = graph.skins[node.skin]; + auto& skin = storage.skins[name]; + auto& joints = storage.joints[name]; + joints.resize( skin.joints.size() ); + for ( size_t i = 0; i < skin.joints.size(); ++i ) joints[i] = uf::matrix::identity(); + + if ( graph.settings.animations.override.a >= 0 || !graph.sequence.empty() ) { + for ( size_t i = 0; i < skin.joints.size(); ++i ) { + joints[i] = inverseTransform * (::worldMatrix(graph, skin.joints[i]) * skin.inverseBindMatrices[i]); + } + } + } +#else if ( 0 <= node.skin && node.skin < graph.skins.size() ) { pod::Matrix4f nodeMatrix = ::worldMatrix( graph, node.index ); pod::Matrix4f inverseTransform = uf::matrix::inverse( nodeMatrix ); @@ -276,6 +296,7 @@ void uf::graph::updateAnimation( pod::Graph& graph, pod::Node& node ) { joints[i] = inverseTransform * matrix * skin.inverseBindMatrices[i]; } } +#endif } // separate function in the event something later might need it @@ -308,8 +329,7 @@ uf::stl::vector uf::graph::obbFromSkin( const pod::Graph& graph, const auto& skin = storage.skins[skinName]; auto& mesh = storage.meshes[meshName]; - // store as min/max AABB - uf::stl::vector bounds(skin.joints.size(), { + uf::stl::vector aabbs(skin.joints.size(), { pod::Vector3f{ FLT_MAX, FLT_MAX, FLT_MAX }, pod::Vector3f{-FLT_MAX,-FLT_MAX,-FLT_MAX } }); @@ -325,24 +345,43 @@ uf::stl::vector uf::graph::obbFromSkin( const pod::Graph& graph, const auto joints = uf::mesh::fetchVertexAttribute( view, jointsView, i ); auto weights = uf::mesh::fetchVertexAttribute( view, weightView, i ); + int bestW = -1; + float maxWeight = 0.0f; for ( auto w = 0; w < 4; ++w ) { - if ( weights[w] <= wThresold ) continue; - uint16_t jointID = joints[w]; + if ( weights[w] > maxWeight ) { + maxWeight = weights[w]; + bestW = w; + } + } + + if ( bestW != -1 ) { + float weight = weights[bestW]; + uint16_t jointID = joints[bestW]; + + // transform from mesh => bone space pod::Vector3f localPos = uf::matrix::multiply( skin.inverseBindMatrices[jointID], pos ); - bounds[jointID].center = uf::vector::min( bounds[jointID].center, localPos ); - bounds[jointID].extent = uf::vector::max( bounds[jointID].extent, localPos ); + aabbs[jointID].min = uf::vector::min( aabbs[jointID].min, localPos ); + aabbs[jointID].max = uf::vector::max( aabbs[jointID].max, localPos ); } } } - // convert from min-max to center-extent - for ( auto& box : bounds ) { - auto extent = (box.extent - box.center) * 0.5f; - auto center = (box.extent + box.center) * 0.5f; - box = pod::OBB{ center, extent }; - } + uf::stl::vector bounds(skin.joints.size()); + for ( auto i = 0; i < skin.joints.size(); ++i ) { + auto& aabb = aabbs[i]; + bounds[i] = pod::OBB{ + .center = (aabb.max + aabb.min) * 0.5f, + .extent = (aabb.max - aabb.min) * 0.5f, + }; + // transform back from bone => mesh space + auto bindMatrix = uf::matrix::inverse( skin.inverseBindMatrices[i] ); + auto scale = uf::matrix::extractScale( bindMatrix ); + bounds[i].center = uf::matrix::multiply( bindMatrix, bounds[i].center, 1.0f ); + bounds[i].extent *= scale; + // UF_MSG_DEBUG("name={}, scale={}", graph.nodes[skin.joints[i]].name, uf::vector::toString( scale )); + } return bounds; } @@ -364,41 +403,59 @@ void uf::graph::rigRagdoll( pod::Graph& graph, pod::Node& node ) { for ( auto i = 0; i < skin.joints.size(); ++i ) { auto nodeID = skin.joints[i]; auto& node = graph.nodes[nodeID]; - if ( node.parent < 0 ) continue; + if ( node.parent < 0 ) continue; // root node, skip auto& entity = *node.entity; auto transform = uf::transform::flatten( entity.getComponent>() ); + // copy to modify in-place + auto bone = bones[nodeID]; + auto obb = bounds[i]; + // invalid bounds + bool useBone = obb.extent.x > 0; - auto& bone = bones[nodeID]; - auto& obb = bounds[i]; - - /* - auto boneCenter = uf::transform::apply( armatureTransform, (bone.end + bone.start) * 0.5f ); - auto offset = uf::transform::applyInverse( transform, boneCenter ); - auto orientation = uf::quaternion::identity(); - float length = uf::vector::norm( offset ) * 2.0f; - */ - // skip leaf bones that aren't assigned joints in the mesh - if ( obb.extent.x < 0 && node.children.empty() ) continue; - - auto targetShape = pod::ShapeType::OBB; + // skip leaf bones if they aren't used in the mesh + if ( !useBone && node.children.empty() ) continue; + // useBone = false; // disable for now + bool offsetByBodyTransform = true; // offset via physics body rather than in the shape itself + auto shapeType = pod::ShapeType::CAPSULE; // default to capsules + // transform bone into world space bone.start = uf::transform::apply( armatureTransform, bone.start ); bone.end = uf::transform::apply( armatureTransform, bone.end ); - + float length = uf::vector::distance( bone.start, bone.end ); // bone length in world-space + float thickness = /*useBone ? MAX( obb.extent.x, obb.extent.z ) :*/ length * 0.15f; // limb thickness + // transform into node space auto start = uf::transform::applyInverse( transform, bone.start ); auto end = uf::transform::applyInverse( transform, bone.end ); - float length = uf::vector::distance( bone.start, bone.end ); - auto offset = ( start + end ) * 0.5f; + auto dir = uf::vector::normalize( end - start ); + auto up = pod::Vector3f{0, 1, 0}; + + float mass = 0.0f; + + // valid bone, use boxes + if ( useBone ) shapeType = pod::ShapeType::OBB; + + // physics body transform offsets + auto offset = pod::Vector3f{}; auto orientation = uf::quaternion::identity(); - float mass = 100.0f; - + // offset position + if ( offsetByBodyTransform || shapeType != pod::ShapeType::OBB ) { + offset = /*useBone ? obb.center :*/ uf::vector::lerp( start, end, 0.5f ); + obb.center = {}; + } + // offset orientation + if ( offsetByBodyTransform || shapeType != pod::ShapeType::CAPSULE ) { + //orientation = uf::quaternion::unitVectors( up, dir ); + orientation = uf::matrix::extractRotation( uf::matrix::inverse( skin.inverseBindMatrices[nodeID] ) ); + } else { + up = dir; // set up direction to bone direction (for capsule) + } + + // create body auto& body = uf::physics::create( entity, mass, offset, orientation ); bodies[nodeID] = &body; - // "root" bone will try and parent to local origin /* if ( !isJoint[node.parent] ) { - targetShape = pod::ShapeType::SPHERE; // mark it as non-colliding uf::physics::setColliderCategory( body, pod::Collider::CATEGORY_NONE ); // make it heavier @@ -406,24 +463,14 @@ void uf::graph::rigRagdoll( pod::Graph& graph, pod::Node& node ) { } */ - switch ( targetShape ) { + switch ( shapeType ) { case pod::ShapeType::CAPSULE: { - auto up = pod::Vector3f{0, 1, 0}; - auto dir = uf::vector::normalize( end - start ); - float dot = uf::vector::dot( up, dir ); - if ( dot < -0.999f ) { - body.offsetOrientation = uf::quaternion::axisAngle( pod::Vector3f{1, 0, 0}, M_PI ); - } else if ( dot < 0.999f ) { - auto cross = uf::vector::normalize( uf::vector::cross( up, dir ) ); - body.offsetOrientation = uf::quaternion::axisAngle( cross, std::acos( dot ) ); - } - float radius = length * 0.15f; - float halfHeight = std::max( 0.01f, length - (radius * 2.0f) ) * 0.5f; - uf::physics::initialize( body, pod::Capsule{ radius, halfHeight } ); + float height = length - (thickness * 2); // subtract end-caps + uf::physics::initialize( body, pod::Capsule{ thickness, up * height * 0.5f } ); } break; case pod::ShapeType::AABB: case pod::ShapeType::OBB: { - uf::physics::initialize( body, pod::OBB{ pod::Vector3f{}, obb.extent * armatureTransform.scale } ); + uf::physics::initialize( body, obb ); } break; // should probably add a NONE shape default: diff --git a/engine/src/engine/object/behavior.cpp b/engine/src/engine/object/behavior.cpp index 22c36b67..0b2b5bc3 100644 --- a/engine/src/engine/object/behavior.cpp +++ b/engine/src/engine/object/behavior.cpp @@ -148,8 +148,11 @@ void uf::ObjectBehavior::initialize( uf::Object& self ) { offset = center; center = {}; } - + #if OBB_EXTENT_CENTER + uf::physics::initialize( body, pod::OBB{ .extent = extent, .center = center } ); + #else uf::physics::initialize( body, pod::OBB{ .center = center, .extent = extent } ); + #endif } else if ( 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} ); @@ -175,9 +178,12 @@ void uf::ObjectBehavior::initialize( uf::Object& self ) { uf::physics::initialize( body, pod::Sphere{ radius } ); } else if ( type == "capsule" ) { float radius = metadataJsonPhysics["radius"].as(); - float halfHeight = metadataJsonPhysics["height"].as() * 0.5f; + auto up = uf::vector::decode( metadataJsonPhysics["up"], pod::Vector3f{0,1,0} ); + if ( metadataJsonPhysics["height"].is() ) { + up *= metadataJsonPhysics["height"].as() * 0.5f; + } - uf::physics::initialize( body, pod::Capsule{ radius, halfHeight } ); + uf::physics::initialize( body, pod::Capsule{ radius, up } ); } else if ( type == "mesh" ) { // ... } else { diff --git a/engine/src/engine/object/behaviors/graph.cpp b/engine/src/engine/object/behaviors/graph.cpp index dfd0e8be..efba84bc 100644 --- a/engine/src/engine/object/behaviors/graph.cpp +++ b/engine/src/engine/object/behaviors/graph.cpp @@ -73,28 +73,33 @@ void uf::GraphBehavior::tick( uf::Object& self ) { auto& graph = this->getComponent(); if ( !graph.metadata["debug"]["draw"]["armature"].as(false) ) return; auto& transform = this->getComponent>(); + auto& scene = uf::scene::getCurrentScene(); + auto& storage = uf::graph::globalStorage ? uf::graph::storage : scene.getComponent(); for ( auto& node : graph.nodes ) { if ( node.skin < 0 || node.mesh < 0 ) continue; auto bones = uf::graph::collectBones( graph, node ); - for ( auto& bone : bones ) { + auto bounds = uf::graph::obbFromSkin( graph, node ); + auto& skinName = graph.skins[node.skin]; + auto& skin = storage.skins[skinName]; + for ( auto bone : bones ) { bone.start = uf::transform::apply( transform, bone.start ); bone.end = uf::transform::apply( transform, bone.end ); uf::debug::drawLine( bone.start, bone.end, pod::Vector4f{ 0, 1, 0, 1 } ); } - } + for ( auto obb : bounds ) { + uf::debug::drawShape( obb, transform ); + } + /* + for ( auto i = 0; i < skin.joints.size(); ++i ) { + auto nodeID = skin.joints[i]; + auto obb = bounds[i]; + auto bone = bones[nodeID]; - static bool hid = false; - if ( hid ) return; - hid = true; - this->process([&](uf::Entity* entity){ - if ( !entity->hasComponent() ) return; - auto& graphic = entity->getComponent(); - if ( !graphic.initialized ) return; - auto& descriptorSet = graphic.getDescriptorSet(); - descriptorSet.metadata.process = false; - uf::renderer::states::rebuild = true; - }); + uf::debug::drawShape( obb, transform ); + } + */ + } } void uf::GraphBehavior::render( uf::Object& self ) {} void uf::GraphBehavior::Metadata::serialize( uf::Object& self, uf::Serializer& serializer ) {} diff --git a/engine/src/ext/gltf/gltf.cpp b/engine/src/ext/gltf/gltf.cpp index 8dcacd67..d11531f0 100644 --- a/engine/src/ext/gltf/gltf.cpp +++ b/engine/src/ext/gltf/gltf.cpp @@ -99,11 +99,13 @@ namespace { } else { transform.scale = { 1, 1, 1 }; } + /* if ( node.matrix.size() == 16 ) { for ( size_t i = 0; i < node.matrix.size(); ++i ) transform.model[i] = node.matrix[i]; } else { transform.model = uf::matrix::identity(); } + */ if ( 0 <= parentIndex && parentIndex < graph.nodes.size() && nodeIndex != parentIndex ) { transform.reference = &graph.nodes[parentIndex].transform; } diff --git a/engine/src/ext/lua/usertypes/physics.cpp b/engine/src/ext/lua/usertypes/physics.cpp index 667ca13f..1cf7da8f 100644 --- a/engine/src/ext/lua/usertypes/physics.cpp +++ b/engine/src/ext/lua/usertypes/physics.cpp @@ -139,12 +139,18 @@ UF_LUA_REGISTER_USERTYPE_AND_COMPONENT(pod::OBB, []( pod::OBB& self, const pod::OBB& copy ) { return self = copy; }, - []( pod::OBB& self, const pod::Vector3f& center, const pod::Vector3f& extent ) { - return self = pod::OBB{ center, extent }; + #if OBB_EXTENT_CENTER + []( pod::OBB& self, const pod::Vector3f& extent, const pod::Vector3f& center ) { + return self = pod::OBB{ .extent = extent, .center = center }; } + #else + []( pod::OBB& self, const pod::Vector3f& center, const pod::Vector3f& extent ) { + return self = pod::OBB{ .center = center, .extent = extent }; + } + #endif ), - UF_LUA_REGISTER_USERTYPE_MEMBER(pod::OBB::center), - UF_LUA_REGISTER_USERTYPE_MEMBER(pod::OBB::extent) + UF_LUA_REGISTER_USERTYPE_MEMBER(pod::OBB::extent), + UF_LUA_REGISTER_USERTYPE_MEMBER(pod::OBB::center) ) UF_LUA_REGISTER_USERTYPE_AND_COMPONENT(pod::Sphere, sol::call_constructor, sol::initializers( @@ -168,12 +174,13 @@ UF_LUA_REGISTER_USERTYPE_AND_COMPONENT(pod::Capsule, []( pod::Capsule& self, const pod::Capsule& copy ) { return self = copy; }, - []( pod::Capsule& self, float radius, float height ) { - return self = pod::Capsule{ radius, height * 0.5f }; + []( pod::Capsule& self, float radius, pod::Vector3f up ) { + //if ( up == pod::Vector3f{} ) up = pod::Vector3f{0,1,0}; + return self = pod::Capsule{ .radius = radius, .up = up }; } ), UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Capsule::radius), - UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Capsule::halfHeight) + UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Capsule::up) ) UF_LUA_REGISTER_USERTYPE_AND_COMPONENT(pod::Plane, sol::call_constructor, sol::initializers( @@ -184,7 +191,7 @@ UF_LUA_REGISTER_USERTYPE_AND_COMPONENT(pod::Plane, return self = copy; }, []( pod::Plane& self, const pod::Vector3f& normal, float offset ) { - return self = pod::Plane{ normal, offset }; + return self = pod::Plane{ .normal = normal, .offset = offset }; } ), UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Plane::normal), diff --git a/engine/src/ext/lua/usertypes/transform.cpp b/engine/src/ext/lua/usertypes/transform.cpp index 0868d43c..7effb2a2 100644 --- a/engine/src/ext/lua/usertypes/transform.cpp +++ b/engine/src/ext/lua/usertypes/transform.cpp @@ -28,8 +28,8 @@ namespace binds { pod::Transform<> flatten( const pod::Transform<>& t ) { return uf::transform::flatten( t ); } - pod::Transform<> reorient( const pod::Transform<>& t ) { - return uf::transform::reorient( t ); + pod::Axes axes( const pod::Transform<>& t, sol::optional at ) { + return uf::transform::axes( t, at.value_or(pod::Vector3f{}) ); } pod::Transform<> getReference( pod::Transform<>& t ) { return t.reference ? *t.reference : t; @@ -54,8 +54,8 @@ namespace binds { pod::Transform<>& reference( pod::Transform<>& transform, const pod::Transform<>& parent, sol::optional reorient ) { return uf::transform::reference( transform, parent, reorient.value_or(true) ); } - pod::Transform<> interpolate( const pod::Transform<>& from, const pod::Transform<>& to, float factor, sol::optional reorient ) { - return uf::transform::interpolate( from, to, factor, reorient.value_or(true) ); + pod::Transform<> interpolate( const pod::Transform<>& from, const pod::Transform<>& to, float factor ) { + return uf::transform::interpolate( from, to, factor ); } pod::Transform<> inverse(const pod::Transform<>& t) { return uf::transform::inverse( t ); @@ -72,19 +72,29 @@ namespace binds { } #include +UF_LUA_REGISTER_USERTYPE_AND_COMPONENT(pod::Axes, + sol::call_constructor, sol::initializers( + []( pod::Axes& self ) { + return self = {}; + }, + []( pod::Axes& self, const pod::Axes& copy ) { + return self = copy; + } + ), + UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Axes::right), + UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Axes::up), + UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Axes::forward) +) + UF_LUA_REGISTER_USERTYPE_AND_COMPONENT(pod::Transform<>, UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Transform<>::position), - UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Transform<>::scale), - UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Transform<>::up), - UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Transform<>::right), - UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Transform<>::forward), UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Transform<>::orientation), - UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Transform<>::model), + UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Transform<>::scale), UF_LUA_REGISTER_USERTYPE_DEFINE(move, UF_LUA_C_FUN(::binds::move) ), UF_LUA_REGISTER_USERTYPE_DEFINE(rotate, UF_LUA_C_FUN(::binds::rotate)), UF_LUA_REGISTER_USERTYPE_DEFINE(flatten, UF_LUA_C_FUN(::binds::flatten)), - UF_LUA_REGISTER_USERTYPE_DEFINE(reorient, UF_LUA_C_FUN(::binds::reorient)), + UF_LUA_REGISTER_USERTYPE_DEFINE(axes, UF_LUA_C_FUN(::binds::axes)), UF_LUA_REGISTER_USERTYPE_DEFINE(getReference, UF_LUA_C_FUN(::binds::getReference)), UF_LUA_REGISTER_USERTYPE_DEFINE(setReference, UF_LUA_C_FUN(::binds::setReference)), UF_LUA_REGISTER_USERTYPE_DEFINE(unreference, UF_LUA_C_FUN(::binds::unreference)), diff --git a/engine/src/ext/openal/openal.cpp b/engine/src/ext/openal/openal.cpp index 44db20e3..70d9e5d9 100644 --- a/engine/src/ext/openal/openal.cpp +++ b/engine/src/ext/openal/openal.cpp @@ -210,8 +210,9 @@ void ext::al::close( uf::audio::Metadata& metadata ) { void ext::al::listener( const pod::Transform<>& transform ) { if ( uf::audio::muted ) return; - - float o[6] = { transform.forward.x, transform.forward.y, transform.forward.z, transform.up.x, transform.up.y, transform.up.z }; + auto axes = uf::transform::axes( transform ); + axes.forward *= -1; + float o[6] = { axes.forward.x, axes.forward.y, axes.forward.z, axes.up.x, axes.up.y, axes.up.z }; AL_CHECK_RESULT(alListener3f( AL_POSITION, transform.position.x, transform.position.y, transform.position.z )); AL_CHECK_RESULT(alListener3f( AL_VELOCITY, 0, 0, 0 )); AL_CHECK_RESULT(alListenerfv( AL_ORIENTATION, &o[0] )); diff --git a/engine/src/utils/debug/draw.cpp b/engine/src/utils/debug/draw.cpp index d6d36d63..4a8816eb 100644 --- a/engine/src/utils/debug/draw.cpp +++ b/engine/src/utils/debug/draw.cpp @@ -2,6 +2,7 @@ #include #include +#include namespace impl { struct Vertex { @@ -38,7 +39,8 @@ void uf::debug::drawLine( const pod::Vector3f& start, const pod::Vector3f& end, impl::lines.emplace_back( impl::Vertex{ start, color } ); impl::lines.emplace_back( impl::Vertex{ end, color } ); } -void uf::debug::drawAabb( pod::AABB aabb, pod::Transform<> transform ) { +// for some reason compiling these two and not even using them causes physics to break +void uf::debug::drawShape( const pod::AABB& aabb, const pod::Transform<>& transform ) { pod::Vector3f corners[8] = { {aabb.min.x, aabb.min.y, aabb.min.z}, {aabb.max.x, aabb.min.y, aabb.min.z}, {aabb.max.x, aabb.max.y, aabb.min.z}, {aabb.min.x, aabb.max.y, aabb.min.z}, @@ -56,7 +58,7 @@ void uf::debug::drawAabb( pod::AABB aabb, pod::Transform<> transform ) { uf::debug::drawLine( corners[0], corners[4] ); uf::debug::drawLine( corners[1], corners[5] ); uf::debug::drawLine( corners[2], corners[6] ); uf::debug::drawLine( corners[3], corners[7] ); } -void uf::debug::drawObb( pod::OBB obb, pod::Transform<> transform ) { +void uf::debug::drawShape( const pod::OBB& obb, const pod::Transform<>& transform ) { auto aabb = pod::AABB{ .min = obb.center - obb.extent, .max = obb.center + obb.extent, @@ -83,7 +85,7 @@ void uf::debug::drawObb( pod::OBB obb, pod::Transform<> transform ) { uf::debug::drawLine( corners[2], corners[6] ); uf::debug::drawLine( corners[3], corners[7] ); } -void uf::debug::drawSphere( pod::Sphere sphere, pod::Transform<> transform ) { +void uf::debug::drawShape( const pod::Sphere& sphere, const pod::Transform<>& transform ) { const int segments = 16; const float angleIncrement = (2.0f * M_PI) / segments; for ( auto i = 0; i < segments; ++i ) { @@ -109,12 +111,11 @@ void uf::debug::drawSphere( pod::Sphere sphere, pod::Transform<> transform ) { uf::debug::drawLine( transform.position + yz1, transform.position + yz2 ); } } -// for some reason compiling these two and not even using them causes physics to break -/* -void uf::debug::drawCapsule( pod::Capsule capsule, pod::Transform<> transform ) { - const pod::Vector3f up = uf::quaternion::rotate( transform.orientation, pod::Vector3f{0,1,0} ); - auto p1 = transform.position + up * capsule.halfHeight; - auto p2 = transform.position - up * capsule.halfHeight; + +void uf::debug::drawShape( const pod::Capsule& capsule, const pod::Transform<>& transform ) { + const pod::Vector3f up = uf::quaternion::rotate( transform.orientation, capsule.up ); + auto p1 = transform.position + up; + auto p2 = transform.position - up; const int segments = 16; const float angleIncrement = (2.0f * M_PI) / segments; @@ -160,7 +161,7 @@ void uf::debug::drawCapsule( pod::Capsule capsule, pod::Transform<> transform ) uf::debug::drawLine( p1 - rz, p2 - rz ); } // to-do: properly implement this -void uf::debug::drawPlane( pod::Plane plane, pod::Transform<> transform ) { +void uf::debug::drawShape( const pod::Plane& plane, const pod::Transform<>& transform ) { pod::Vector3f right = uf::quaternion::rotate(transform.orientation, pod::Vector3f{1, 0, 0}); pod::Vector3f forward = uf::quaternion::rotate(transform.orientation, pod::Vector3f{0, 0, 1}); @@ -178,8 +179,7 @@ void uf::debug::drawPlane( pod::Plane plane, pod::Transform<> transform ) { uf::debug::drawLine( p0, p2 ); uf::debug::drawLine( p1, p3 ); } -*/ -void uf::debug::drawTriangle( pod::Triangle tri, pod::Transform<> transform ) { +void uf::debug::drawShape( const pod::Triangle& tri, const pod::Transform<>& transform ) { pod::Vector3f v0 = uf::transform::apply(transform, tri.points[0]); pod::Vector3f v1 = uf::transform::apply(transform, tri.points[1]); pod::Vector3f v2 = uf::transform::apply(transform, tri.points[2]); @@ -219,7 +219,7 @@ void uf::debug::draw( float dt ) { graphic.material.device = &uf::renderer::device; // to-do: bin by descriptor instead of one global set - graphic.descriptor.depth.test = false; + graphic.descriptor.depth.test = uf::physics::settings.debugDraw.depthTest; graphic.descriptor.depth.write = false; graphic.descriptor.renderTarget = 1; // "forward"; graphic.descriptor.topology = uf::renderer::enums::PrimitiveTopology::LINE_LIST; diff --git a/engine/src/utils/math/physics/common.cpp b/engine/src/utils/math/physics/common.cpp index 94ca8829..5b88548f 100644 --- a/engine/src/utils/math/physics/common.cpp +++ b/engine/src/utils/math/physics/common.cpp @@ -612,10 +612,17 @@ pod::Vector3f impl::obbMax( const pod::OBB& obb ) { } // converts a min-max AABB to center-extents OBB pod::OBB impl::aabbToObb( const pod::AABB& aabb ) { +#if OBB_EXTENT_CENTER + return pod::OBB{ + .extent = impl::aabbExtent( aabb ), + .center = impl::aabbCenter( aabb ), + }; +#else return pod::OBB{ .center = impl::aabbCenter( aabb ), .extent = impl::aabbExtent( aabb ), }; +#endif } // converts a center-extents OBB to min-max AABB pod::AABB impl::obbToAabb( const pod::OBB& obb ) { @@ -655,7 +662,7 @@ pod::AABB impl::transformAabbToWorld( const pod::AABB& aabb, const pod::Transfor pod::Vector3f axes[3]; impl::boxAxes( axes, transform ); - pod::Vector3f center = uf::quaternion::rotate(transform.orientation, box.center) + transform.position; + pod::Vector3f center = uf::transform::apply( transform, box.center ); pod::Vector3f extent = impl::extentFromAxes( box, axes ); return { center - extent, center + extent }; @@ -664,11 +671,11 @@ pod::AABB impl::transformAabbToWorld( const pod::AABB& aabb, const pod::Transfor std::pair impl::getCapsuleSegment( const pod::PhysicsBody& body ) { const auto transform = impl::getTransform( body ); const auto& capsule = body.collider.capsule; - const pod::Vector3f up = uf::quaternion::rotate( transform.orientation, pod::Vector3f{0,1,0} ); + const pod::Vector3f up = uf::quaternion::rotate( transform.orientation, capsule.up ); // segment defines the cylinder axis only (ignore spherical ends) - auto p1 = transform.position + up * capsule.halfHeight; - auto p2 = transform.position - up * capsule.halfHeight; + auto p1 = transform.position + up; + auto p2 = transform.position - up; return { p1, p2 }; } // computes the AABB for a given body diff --git a/engine/src/utils/math/physics/constraints/ballSocket.cpp b/engine/src/utils/math/physics/constraints/ballSocket.cpp index fc8553f0..00940b93 100644 --- a/engine/src/utils/math/physics/constraints/ballSocket.cpp +++ b/engine/src/utils/math/physics/constraints/ballSocket.cpp @@ -14,11 +14,8 @@ void impl::solveBallSocketConstraint( pod::Constraint& constraint, float dt ) { auto tA = impl::getTransform( a ); auto tB = impl::getTransform( b ); - auto anchorA = joint.localAnchorA * tA.scale; - auto anchorB = joint.localAnchorB * tB.scale; - - auto rA = uf::quaternion::rotate( tA.orientation, anchorA ); - auto rB = uf::quaternion::rotate( tB.orientation, anchorB ); + auto rA = uf::quaternion::rotate( tA.orientation, joint.localAnchorA * tA.scale ); + auto rB = uf::quaternion::rotate( tB.orientation, joint.localAnchorB * tB.scale ); pod::Matrix3f K = {}; pod::Vector3f axes[3] = { {1,0,0}, {0,1,0}, {0,0,1} }; diff --git a/engine/src/utils/math/physics/constraints/distance.cpp b/engine/src/utils/math/physics/constraints/distance.cpp index 8b09405d..bc530972 100644 --- a/engine/src/utils/math/physics/constraints/distance.cpp +++ b/engine/src/utils/math/physics/constraints/distance.cpp @@ -11,11 +11,8 @@ void impl::solveDistanceConstraint( pod::Constraint& constraint, float dt ) { auto tA = impl::getTransform( a ); auto tB = impl::getTransform( b ); - auto anchorA = joint.localAnchorA * tA.scale; - auto anchorB = joint.localAnchorB * tB.scale; - - auto rA = uf::quaternion::rotate( tA.orientation, anchorA ); - auto rB = uf::quaternion::rotate( tB.orientation, anchorB ); + auto rA = uf::quaternion::rotate( tA.orientation, joint.localAnchorA * tA.scale ); + auto rB = uf::quaternion::rotate( tB.orientation, joint.localAnchorB * tB.scale ); auto pA = tA.position + rA; auto pB = tB.position + rB; diff --git a/engine/src/utils/math/physics/constraints/slider.cpp b/engine/src/utils/math/physics/constraints/slider.cpp index f9ced31b..0ff986e9 100644 --- a/engine/src/utils/math/physics/constraints/slider.cpp +++ b/engine/src/utils/math/physics/constraints/slider.cpp @@ -12,11 +12,8 @@ void impl::solveSliderConstraint( pod::Constraint& constraint, float dt ) { auto tA = impl::getTransform( a ); auto tB = impl::getTransform( b ); - auto anchorA = joint.localAnchorA * tA.scale; - auto anchorB = joint.localAnchorB * tB.scale; - - auto rA = uf::quaternion::rotate( tA.orientation, anchorA ); - auto rB = uf::quaternion::rotate( tB.orientation, anchorB ); + auto rA = uf::quaternion::rotate( tA.orientation, joint.localAnchorA * tA.scale ); + auto rB = uf::quaternion::rotate( tB.orientation, joint.localAnchorB * tB.scale ); auto pA = tA.position + rA; auto pB = tB.position + rB; diff --git a/engine/src/utils/math/physics/constraints/spring.cpp b/engine/src/utils/math/physics/constraints/spring.cpp index 15155661..6008f75d 100644 --- a/engine/src/utils/math/physics/constraints/spring.cpp +++ b/engine/src/utils/math/physics/constraints/spring.cpp @@ -11,11 +11,8 @@ void impl::solveSpringConstraint( pod::Constraint& constraint, float dt ) { auto tA = impl::getTransform( a ); auto tB = impl::getTransform( b ); - auto anchorA = joint.localAnchorA * tA.scale; - auto anchorB = joint.localAnchorB * tB.scale; - - auto rA = uf::quaternion::rotate( tA.orientation, anchorA ); - auto rB = uf::quaternion::rotate( tB.orientation, anchorB ); + auto rA = uf::quaternion::rotate( tA.orientation, joint.localAnchorA * tA.scale ); + auto rB = uf::quaternion::rotate( tB.orientation, joint.localAnchorB * tB.scale ); auto worldAnchorA = tA.position + rA; auto worldAnchorB = tB.position + rB; diff --git a/engine/src/utils/math/physics/impl.cpp b/engine/src/utils/math/physics/impl.cpp index 7dd31138..6f9585a5 100644 --- a/engine/src/utils/math/physics/impl.cpp +++ b/engine/src/utils/math/physics/impl.cpp @@ -377,7 +377,7 @@ void uf::physics::updateInertia( pod::PhysicsBody& body ) { } break; case pod::ShapeType::CAPSULE: { float r = body.collider.capsule.radius; - float h = body.collider.capsule.halfHeight * 2.0f; // full cyl height + float h = uf::vector::norm( body.collider.capsule.up ) * 2.0f; // full cyl height float Ixx = 0.25f * mass * r * r + (1.0f/12.0f) * mass * h * h; float Iyy = 0.5f * mass * r * r; diff --git a/engine/src/utils/math/physics/narrowphase/aabb.cpp b/engine/src/utils/math/physics/narrowphase/aabb.cpp index f31a7a81..7df5a53f 100644 --- a/engine/src/utils/math/physics/narrowphase/aabb.cpp +++ b/engine/src/utils/math/physics/narrowphase/aabb.cpp @@ -81,7 +81,25 @@ bool impl::aabbHull( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod:: void impl::drawAabb( const pod::PhysicsBody& body ) { const auto& aabb = body.bounds; auto transform = impl::getTransform( body ); +#if 0 uf::debug::drawAabb( aabb, transform ); +#else + pod::Vector3f corners[8] = { + {aabb.min.x, aabb.min.y, aabb.min.z}, {aabb.max.x, aabb.min.y, aabb.min.z}, + {aabb.max.x, aabb.max.y, aabb.min.z}, {aabb.min.x, aabb.max.y, aabb.min.z}, + {aabb.min.x, aabb.min.y, aabb.max.z}, {aabb.max.x, aabb.min.y, aabb.max.z}, + {aabb.max.x, aabb.max.y, aabb.max.z}, {aabb.min.x, aabb.max.y, aabb.max.z} + }; + + uf::debug::drawLine( corners[0], corners[1] ); uf::debug::drawLine( corners[1], corners[2] ); + uf::debug::drawLine( corners[2], corners[3] ); uf::debug::drawLine( corners[3], corners[0] ); + + uf::debug::drawLine( corners[4], corners[5] ); uf::debug::drawLine( corners[5], corners[6] ); + uf::debug::drawLine( corners[6], corners[7] ); uf::debug::drawLine( corners[7], corners[4] ); + + uf::debug::drawLine( corners[0], corners[4] ); uf::debug::drawLine( corners[1], corners[5] ); + uf::debug::drawLine( corners[2], corners[6] ); uf::debug::drawLine( corners[3], corners[7] ); +#endif } pod::PhysicsBody& uf::physics::initialize( pod::PhysicsBody& body, const pod::AABB& aabb ) { diff --git a/engine/src/utils/math/physics/narrowphase/epa.cpp b/engine/src/utils/math/physics/narrowphase/epa.cpp index 48b592cb..e57ea020 100644 --- a/engine/src/utils/math/physics/narrowphase/epa.cpp +++ b/engine/src/utils/math/physics/narrowphase/epa.cpp @@ -123,9 +123,9 @@ void impl::getSupportFace( const pod::PhysicsBody& body, const pod::Vector3f& di outPoly[0] = transform.position + uf::vector::normalize( dir ) * body.collider.sphere.radius; } break; case pod::ShapeType::CAPSULE: { - auto up = uf::quaternion::rotate( transform.orientation, pod::Vector3f{0,1,0} ); - auto p1 = transform.position + up * body.collider.capsule.halfHeight; - auto p2 = transform.position - up * body.collider.capsule.halfHeight; + auto up = uf::quaternion::rotate( transform.orientation, body.collider.capsule.up ); + auto p1 = transform.position + up; + auto p2 = transform.position - up; if ( std::fabs( uf::vector::dot( dir, up ) ) < 0.01f ) { outCount = 2; diff --git a/engine/src/utils/math/physics/narrowphase/gjk.cpp b/engine/src/utils/math/physics/narrowphase/gjk.cpp index 9152f4c1..94aa88e7 100644 --- a/engine/src/utils/math/physics/narrowphase/gjk.cpp +++ b/engine/src/utils/math/physics/narrowphase/gjk.cpp @@ -37,9 +37,9 @@ pod::Vector3f impl::support( const pod::PhysicsBody& body, const pod::Vector3f& return basePoint + tangent * 100000.0f; } break; case pod::ShapeType::CAPSULE: { - auto up = uf::quaternion::rotate( transform.orientation, pod::Vector3f{0,1,0} ); - auto p1 = transform.position + up * body.collider.capsule.halfHeight; - auto p2 = transform.position - up * body.collider.capsule.halfHeight; + auto up = uf::quaternion::rotate( transform.orientation, body.collider.capsule.up ); + auto p1 = transform.position + up; + auto p2 = transform.position - up; auto end = ( uf::vector::dot( dir, p1 ) > uf::vector::dot( dir, p2 ) ) ? p1 : p2; // get closest end return end + uf::vector::normalize( dir ) * body.collider.capsule.radius; } diff --git a/engine/src/utils/math/physics/narrowphase/hull.cpp b/engine/src/utils/math/physics/narrowphase/hull.cpp index 82d35b38..6332e6bd 100644 --- a/engine/src/utils/math/physics/narrowphase/hull.cpp +++ b/engine/src/utils/math/physics/narrowphase/hull.cpp @@ -92,6 +92,16 @@ void impl::drawHull( const pod::PhysicsBody& body ) { for ( size_t i = 0; i < totalTriangles; ++i ) { auto tri = uf::mesh::fetchTriangle( *meshData, i ); + #if 0 uf::debug::drawTriangle( tri, transform ); + #else + auto v0 = uf::transform::apply( transform, tri.points[0] ); + auto v1 = uf::transform::apply( transform, tri.points[1] ); + auto v2 = uf::transform::apply( transform, tri.points[2] ); + + uf::debug::drawLine( v0, v1 ); + uf::debug::drawLine( v1, v2 ); + uf::debug::drawLine( v2, v0 ); + #endif } } \ No newline at end of file diff --git a/engine/src/utils/math/physics/narrowphase/mesh.cpp b/engine/src/utils/math/physics/narrowphase/mesh.cpp index 47b08386..b0a1bdc6 100644 --- a/engine/src/utils/math/physics/narrowphase/mesh.cpp +++ b/engine/src/utils/math/physics/narrowphase/mesh.cpp @@ -200,7 +200,17 @@ void impl::drawMesh( const pod::PhysicsBody& body ) { for ( size_t i = 0; i < totalTriangles; ++i ) { auto tri = uf::mesh::fetchTriangle( *meshData, i ); + #if 0 uf::debug::drawTriangle( tri, transform ); + #else + auto v0 = uf::transform::apply( transform, tri.points[0] ); + auto v1 = uf::transform::apply( transform, tri.points[1] ); + auto v2 = uf::transform::apply( transform, tri.points[2] ); + + uf::debug::drawLine( v0, v1 ); + uf::debug::drawLine( v1, v2 ); + uf::debug::drawLine( v2, v0 ); + #endif } } diff --git a/engine/src/utils/math/physics/narrowphase/obb.cpp b/engine/src/utils/math/physics/narrowphase/obb.cpp index f700fb28..09e1dd5c 100644 --- a/engine/src/utils/math/physics/narrowphase/obb.cpp +++ b/engine/src/utils/math/physics/narrowphase/obb.cpp @@ -129,8 +129,8 @@ bool impl::obbObb( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Ma auto boxA = a.collider.obb; auto boxB = b.collider.obb; - boxA.center = uf::quaternion::rotate(tA.orientation, boxA.center) + tA.position; - boxB.center = uf::quaternion::rotate(tB.orientation, boxB.center) + tB.position; + boxA.center = uf::transform::apply( tA, boxA.center ); + boxB.center = uf::transform::apply( tB, boxB.center ); pod::Vector3f axesA[3]; pod::Vector3f axesB[3]; @@ -149,7 +149,7 @@ bool impl::obbAabb( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::M auto boxA = a.collider.obb; auto boxB = impl::aabbToObb( b.bounds ); - boxA.center = uf::quaternion::rotate(tA.orientation, boxA.center) + tA.position; + boxA.center = uf::transform::apply( tA, boxA.center ); pod::Vector3f axesA[3]; pod::Vector3f axesB[3]; @@ -164,7 +164,7 @@ bool impl::obbSphere( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod: auto tA = impl::getTransform( a ); auto box = a.collider.obb; - box.center = uf::quaternion::rotate(tA.orientation, box.center) + tA.position; + box.center = uf::transform::apply( tA, box.center ); auto sphereCenter = impl::getPosition( b ); float radius = b.collider.sphere.radius; @@ -212,7 +212,7 @@ bool impl::obbPlane( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod:: auto tA = impl::getTransform( a ); auto box = a.collider.obb; - box.center = uf::quaternion::rotate(tA.orientation, box.center) + tA.position; + box.center = uf::transform::apply( tA, box.center ); pod::Vector3f axesA[3]; impl::boxAxes( axesA, tA ); @@ -242,15 +242,20 @@ bool impl::obbCapsule( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod auto tA = impl::getTransform( a ); auto box = a.collider.obb; - box.center = uf::quaternion::rotate(tA.orientation, box.center) + tA.position; + box.center = uf::transform::apply( tA, box.center ); pod::Vector3f axesA[3]; impl::boxAxes( axesA, tA ); auto [p1, p2] = impl::getCapsuleSegment( b ); + pod::Vector3f cB = (p1 + p2) * 0.5f; - pod::Vector3f capAxis = uf::vector::normalize(p2 - p1); - float halfHeight = b.collider.capsule.halfHeight; + + pod::Vector3f segmentHalf = (p2 - p1) * 0.5f; + float halfHeight = uf::vector::norm(segmentHalf); + + pod::Vector3f capAxis = (halfHeight > EPS2) ? (segmentHalf / halfHeight) : pod::Vector3f{0, 1, 0}; + float radius = b.collider.capsule.radius; float minOverlap = FLT_MAX; @@ -264,7 +269,8 @@ bool impl::obbCapsule( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod float pA = uf::vector::dot(box.center, n); float rA = impl::projectExtents( box, n, axesA ); float pB = uf::vector::dot(cB, n); - float rB = halfHeight * std::fabs(uf::vector::dot(capAxis, n)) + radius; + + float rB = std::fabs(uf::vector::dot(segmentHalf, n)) + radius; float dist = std::fabs(pB - pA); float overlap = (rA + rB) - dist; @@ -301,7 +307,33 @@ bool impl::obbHull( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::M void impl::drawObb( const pod::PhysicsBody& body ) { const auto& obb = body.collider.obb; auto transform = impl::getTransform(body); +#if 0 uf::debug::drawObb( obb, transform ); +#else + auto aabb = pod::AABB{ + .min = obb.center - obb.extent, + .max = obb.center + obb.extent, + }; + pod::Vector3f corners[8] = { + {aabb.min.x, aabb.min.y, aabb.min.z}, {aabb.max.x, aabb.min.y, aabb.min.z}, + {aabb.max.x, aabb.max.y, aabb.min.z}, {aabb.min.x, aabb.max.y, aabb.min.z}, + {aabb.min.x, aabb.min.y, aabb.max.z}, {aabb.max.x, aabb.min.y, aabb.max.z}, + {aabb.max.x, aabb.max.y, aabb.max.z}, {aabb.min.x, aabb.max.y, aabb.max.z} + }; + + FOR_EACH( 8, { + corners[i] = uf::transform::apply(transform, corners[i]); + }); + + uf::debug::drawLine( corners[0], corners[1] ); uf::debug::drawLine( corners[1], corners[2] ); + uf::debug::drawLine( corners[2], corners[3] ); uf::debug::drawLine( corners[3], corners[0] ); + + uf::debug::drawLine( corners[4], corners[5] ); uf::debug::drawLine( corners[5], corners[6] ); + uf::debug::drawLine( corners[6], corners[7] ); uf::debug::drawLine( corners[7], corners[4] ); + + uf::debug::drawLine( corners[0], corners[4] ); uf::debug::drawLine( corners[1], corners[5] ); + uf::debug::drawLine( corners[2], corners[6] ); uf::debug::drawLine( corners[3], corners[7] ); +#endif } pod::PhysicsBody& uf::physics::initialize( pod::PhysicsBody& body, const pod::OBB& obb ) { diff --git a/engine/src/utils/math/physics/narrowphase/ray.cpp b/engine/src/utils/math/physics/narrowphase/ray.cpp index 9ce1da6f..11598336 100644 --- a/engine/src/utils/math/physics/narrowphase/ray.cpp +++ b/engine/src/utils/math/physics/narrowphase/ray.cpp @@ -326,6 +326,7 @@ pod::RayQuery uf::physics::rayCast( const pod::Ray& ray, const pod::World& world impl::queryBVH( dynamicBvh, ray, candidates ); if ( uf::physics::settings.useSplitBvhs ) impl::queryBVH( staticBvh, ray, candidates ); + for ( auto i : candidates ) { auto* b = bodies[i]; diff --git a/engine/src/utils/math/physics/narrowphase/sphere.cpp b/engine/src/utils/math/physics/narrowphase/sphere.cpp index 145af546..b90c2b68 100644 --- a/engine/src/utils/math/physics/narrowphase/sphere.cpp +++ b/engine/src/utils/math/physics/narrowphase/sphere.cpp @@ -71,7 +71,34 @@ bool impl::sphereHull( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod void impl::drawSphere( const pod::PhysicsBody& body ) { const auto& sphere = body.collider.sphere; auto transform = impl::getTransform(body); +#if 0 uf::debug::drawSphere( sphere, transform ); +#else + const int segments = 16; + const float angleIncrement = (2.0f * M_PI) / segments; + for ( auto i = 0; i < segments; ++i ) { + float theta1 = i * angleIncrement; + float theta2 = (i + 1) * angleIncrement; + + float c1 = std::cos(theta1) * sphere.radius; + float s1 = std::sin(theta1) * sphere.radius; + float c2 = std::cos(theta2) * sphere.radius; + float s2 = std::sin(theta2) * sphere.radius; + + pod::Vector3f xy1 = uf::quaternion::rotate(transform.orientation, pod::Vector3f{c1, s1, 0.0f}); + pod::Vector3f xy2 = uf::quaternion::rotate(transform.orientation, pod::Vector3f{c2, s2, 0.0f}); + + pod::Vector3f xz1 = uf::quaternion::rotate(transform.orientation, pod::Vector3f{c1, 0.0f, s1}); + pod::Vector3f xz2 = uf::quaternion::rotate(transform.orientation, pod::Vector3f{c2, 0.0f, s2}); + + pod::Vector3f yz1 = uf::quaternion::rotate(transform.orientation, pod::Vector3f{0.0f, c1, s1}); + pod::Vector3f yz2 = uf::quaternion::rotate(transform.orientation, pod::Vector3f{0.0f, c2, s2}); + + uf::debug::drawLine( transform.position + xy1, transform.position + xy2 ); + uf::debug::drawLine( transform.position + xz1, transform.position + xz2 ); + uf::debug::drawLine( transform.position + yz1, transform.position + yz2 ); + } +#endif } pod::PhysicsBody& uf::physics::initialize( pod::PhysicsBody& body, const pod::Sphere& sphere ) { diff --git a/engine/src/utils/math/physics/narrowphase/triangle.cpp b/engine/src/utils/math/physics/narrowphase/triangle.cpp index cae13a3f..ef6e8646 100644 --- a/engine/src/utils/math/physics/narrowphase/triangle.cpp +++ b/engine/src/utils/math/physics/narrowphase/triangle.cpp @@ -190,7 +190,7 @@ bool impl::triangleObb( const pod::TriangleWithNormal& tri, const pod::PhysicsBo auto transform = impl::getTransform( body ); auto box = body.collider.obb; - box.center = uf::quaternion::rotate(transform.orientation, box.center) + transform.position; + box.center = uf::transform::apply( transform, box.center ); pod::Vector3f axes[3]; impl::boxAxes( axes, transform ); @@ -358,7 +358,17 @@ bool impl::triangleHull( const pod::PhysicsBody& a, const pod::PhysicsBody& b, p void impl::drawTriangle( const pod::PhysicsBody& body ) { const auto& tri = body.collider.triangle; auto transform = impl::getTransform(body); +#if 0 uf::debug::drawTriangle( tri, transform ); +#else + auto v0 = uf::transform::apply( transform, tri.points[0] ); + auto v1 = uf::transform::apply( transform, tri.points[1] ); + auto v2 = uf::transform::apply( transform, tri.points[2] ); + + uf::debug::drawLine( v0, v1 ); + uf::debug::drawLine( v1, v2 ); + uf::debug::drawLine( v2, v0 ); +#endif } pod::PhysicsBody& uf::physics::initialize( pod::PhysicsBody& body, const pod::TriangleWithNormal& tri ) { diff --git a/engine/src/utils/math/physics/solvers/ngs.cpp b/engine/src/utils/math/physics/solvers/ngs.cpp index cd833d74..9db289dc 100644 --- a/engine/src/utils/math/physics/solvers/ngs.cpp +++ b/engine/src/utils/math/physics/solvers/ngs.cpp @@ -21,8 +21,8 @@ void impl::solvePositions( uf::stl::vector& manifolds, float dt, auto ctxA = impl::solverBodyContext( a ); auto ctxB = impl::solverBodyContext( b ); - auto rA = uf::quaternion::rotate( tA.orientation, c.localA ); - auto rB = uf::quaternion::rotate( tB.orientation, c.localB ); + auto rA = uf::quaternion::rotate( tA.orientation, c.localA * tA.scale ); + auto rB = uf::quaternion::rotate( tB.orientation, c.localB * tB.scale ); auto pA = tA.position + rA; auto pB = tB.position + rB; diff --git a/engine/src/utils/math/physics/tests.inl b/engine/src/utils/math/physics/tests.inl index b3eac673..ec144d7e 100644 --- a/engine/src/utils/math/physics/tests.inl +++ b/engine/src/utils/math/physics/tests.inl @@ -172,8 +172,8 @@ TEST(SpherePlane_NoCollision, { TEST(CapsuleCapsule_Collision, { pod::World world; uf::Object objA, objB; - auto& bodyA = uf::physics::create(world, objA, pod::Capsule{0.5f, 1.0f}, 1.0f); - auto& bodyB = uf::physics::create(world, objB, pod::Capsule{0.5f, 1.0f}, 1.0f); + auto& bodyA = uf::physics::create(world, objA, pod::Capsule{0.5f, pod::Vector3f{0,1,0}}, 1.0f); + auto& bodyB = uf::physics::create(world, objB, pod::Capsule{0.5f, pod::Vector3f{0,1,0}}, 1.0f); bodyA.transform->position = {0,0,0}; bodyB.transform->position = {0.8f,0,0}; // slight overlap @@ -384,7 +384,7 @@ TEST(PhysicsStep_StaticFriction_Slips, { TEST(CapsulePlane_Slope_StaticHold, { pod::World world; uf::Object objA, objB; - auto& bodyA = uf::physics::create(world, objA, pod::Capsule{0.5f,1.0f}, 1.0f); + auto& bodyA = uf::physics::create(world, objA, pod::Capsule{0.5f, pod::Vector3f{0, 1, 0}}, 1.0f); auto& bodyB = uf::physics::create(world, objB, pod::Plane{{0,1,1},0.0f}, 0.0f); // Place capsule on slope @@ -402,7 +402,7 @@ TEST(CapsulePlane_Slope_StaticHold, { TEST(CapsulePlane_Slope_Slip, { pod::World world; uf::Object objA, objB; - auto& bodyA = uf::physics::create(world, objA, pod::Capsule{0.5f,1.0f}, 1.0f); + auto& bodyA = uf::physics::create(world, objA, pod::Capsule{0.5f, pod::Vector3f{0, 1, 0}}, 1.0f); auto& bodyB = uf::physics::create(world, objB, pod::Plane{{0,1,1},0.0f}, 0.0f); bodyA.transform->position = {0,2,0}; @@ -417,7 +417,7 @@ TEST(CapsulePlane_Slope_Slip, { TEST(CapsulePlane_RestingContact, { pod::World world; uf::Object objA, objB; - auto& bodyA = uf::physics::create(world, objA, pod::Capsule{0.5f, 1.0f}, 1.0f); + auto& bodyA = uf::physics::create(world, objA, pod::Capsule{0.5f, pod::Vector3f{0,1,0}}, 1.0f); auto& bodyB = uf::physics::create(world, objB, pod::Plane{{0,1,0}, 0.0f}, 0.0f); bodyA.transform->position = {0, 1.5f, 0}; // halfHeight=1, radius=0.5, so "foot" at y=0 @@ -434,7 +434,7 @@ TEST(CapsuleAabb_RestingContact, { pod::World world; uf::Object objA, objB; - auto& bodyA = uf::physics::create(world, objA, pod::Capsule{0.5f, 1.0f}, 1.0f); + auto& bodyA = uf::physics::create(world, objA, pod::Capsule{0.5f, pod::Vector3f{0,1,0}}, 1.0f); auto& bodyB = uf::physics::create(world, objB, pod::AABB{{-5, -1, -5},{5, 0, 5}}, 0.0f); bodyA.transform->position = {0, 1.5f, 0}; @@ -450,7 +450,7 @@ TEST(CapsulePlane_Settling, { pod::World world; uf::Object objA, objB; - auto& bodyA = uf::physics::create(world, objA, pod::Capsule{0.5f, 1.0f}, 1.0f); + auto& bodyA = uf::physics::create(world, objA, pod::Capsule{0.5f, pod::Vector3f{0,1,0}}, 1.0f); auto& bodyB = uf::physics::create(world, objB, pod::Plane{{0,1,0},0.0f}, 0.0f); bodyA.transform->position = {0, 2.0f, 0}; // slightly above @@ -466,7 +466,7 @@ TEST(CapsulePlane_SlopeStaticFriction, { pod::World world; uf::Object objA, objB; - auto& bodyA = uf::physics::create(world, objA, pod::Capsule{0.5f, 1.0f}, 1.0f); + auto& bodyA = uf::physics::create(world, objA, pod::Capsule{0.5f, pod::Vector3f{0,1,0}}, 1.0f); auto& bodyB = uf::physics::create(world, objB, pod::Plane{{0,1,1},0.0f}, 0.0f); // 45° slope bodyA.transform->position = {0, 3.0f, 0}; @@ -484,7 +484,7 @@ TEST(CapsuleAabb_StepEdge, { pod::World world; uf::Object objA, objB; - auto& bodyA = uf::physics::create(world, objA, pod::Capsule{0.5f, 1.0f}, 1.0f); + auto& bodyA = uf::physics::create(world, objA, pod::Capsule{0.5f, pod::Vector3f{0,1,0}}, 1.0f); auto& bodyB = uf::physics::create(world, objB, pod::AABB{{0,-1,-5},{5,0,5}}, 0.0f); bodyA.transform->position = {0.25f, 1.5f, 0}; // Capsule foot half on, half off @@ -500,7 +500,7 @@ TEST(Diagnostic_CapsuleGrounding, { uf::Object objA, objFloor; // Capsule: radius 0.5, half-height 1.0 (total height 2.0 + end caps) - auto& bodyA = uf::physics::create(world, objA, pod::Capsule{0.5f, 1.0f}, 1.0f); + auto& bodyA = uf::physics::create(world, objA, pod::Capsule{0.5f, pod::Vector3f{0,1,0}}, 1.0f); // Test toggle: try both AABB floors and Plane floors. bool usePlane = true; @@ -519,7 +519,7 @@ TEST(CapsulePlane_ContactNormal, { pod::World world; uf::Object objA, objB; - auto& bodyA = uf::physics::create(world, objA, pod::Capsule{0.5f, 1.0f}, 1.0f); + auto& bodyA = uf::physics::create(world, objA, pod::Capsule{0.5f, pod::Vector3f{0,1,0}}, 1.0f); auto& bodyB = uf::physics::create(world, objB, pod::Plane{{0,1,0},0.0f}, 0.0f); bodyA.transform->position = {0,1.5f,0}; @@ -557,7 +557,7 @@ TEST(AabbPlane_RestingNoSink, { TEST(CapsuleSphere_Collision, { pod::World world; uf::Object objA, objB; - auto& bodyA = uf::physics::create(world, objA, pod::Capsule{0.5f,1.0f}, 1.0f); + auto& bodyA = uf::physics::create(world, objA, pod::Capsule{0.5f, pod::Vector3f{0, 1, 0}}, 1.0f); auto& bodyB = uf::physics::create(world, objB, pod::Sphere{0.5f}, 1.0f); bodyA.transform->position = {0,0,0}; @@ -575,7 +575,7 @@ TEST(CapsuleSphere_Collision, { TEST(CapsuleSphere_NoCollision, { pod::World world; uf::Object objA, objB; - auto& bodyA = uf::physics::create(world, objA, pod::Capsule{0.5f,1.0f}, 1.0f); + auto& bodyA = uf::physics::create(world, objA, pod::Capsule{0.5f, pod::Vector3f{0, 1, 0}}, 1.0f); auto& bodyB = uf::physics::create(world, objB, pod::Sphere{0.5f}, 1.0f); bodyA.transform->position = {0,0,0}; @@ -664,7 +664,7 @@ TEST(AabbCapsule_Collision, { pod::World world; uf::Object objA, objB; auto& bodyA = uf::physics::create(world, objA, pod::AABB{{-1,-1,-1},{1,1,1}}, 1.0f); - auto& bodyB = uf::physics::create(world, objB, pod::Capsule{0.5f,1.0f}, 1.0f); + auto& bodyB = uf::physics::create(world, objB, pod::Capsule{0.5f, pod::Vector3f{0, 1, 0}}, 1.0f); bodyA.transform->position = {0,0,0}; bodyB.transform->position = {0,0.5f,0}; // partially overlapping @@ -682,7 +682,7 @@ TEST(AabbCapsule_NoCollision, { pod::World world; uf::Object objA, objB; auto& bodyA = uf::physics::create(world, objA, pod::AABB{{-1,-1,-1},{1,1,1}}, 1.0f); - auto& bodyB = uf::physics::create(world, objB, pod::Capsule{0.5f,1.0f}, 1.0f); + auto& bodyB = uf::physics::create(world, objB, pod::Capsule{0.5f, pod::Vector3f{0, 1, 0}}, 1.0f); bodyA.transform->position = {0,0,0}; bodyB.transform->position = {0,5,0}; @@ -700,7 +700,7 @@ TEST(SphereCapsule_Collision, { pod::World world; uf::Object objA, objB; auto& bodyA = uf::physics::create(world, objA, pod::Sphere{0.5f}, 1.0f); - auto& bodyB = uf::physics::create(world, objB, pod::Capsule{0.5f,1.0f}, 1.0f); + auto& bodyB = uf::physics::create(world, objB, pod::Capsule{0.5f, pod::Vector3f{0, 1, 0}}, 1.0f); bodyA.transform->position = {0,0.0f,0}; bodyB.transform->position = {0,0.25f,0}; @@ -718,7 +718,7 @@ TEST(SphereCapsule_NoCollision, { pod::World world; uf::Object objA, objB; auto& bodyA = uf::physics::create(world, objA, pod::Sphere{0.5f}, 1.0f); - auto& bodyB = uf::physics::create(world, objB, pod::Capsule{0.5f,1.0f}, 1.0f); + auto& bodyB = uf::physics::create(world, objB, pod::Capsule{0.5f, pod::Vector3f{0, 1, 0}}, 1.0f); bodyA.transform->position = {0,5,0}; bodyB.transform->position = {0,0,0}; @@ -750,7 +750,7 @@ TEST(PlaneCapsule_Collision, { pod::World world; uf::Object objA, objB; auto& bodyA = uf::physics::create(world, objA, pod::Plane{{0,1,0},0.0f}, 0.0f); - auto& bodyB = uf::physics::create(world, objB, pod::Capsule{0.5f,1.0f}, 1.0f); + auto& bodyB = uf::physics::create(world, objB, pod::Capsule{0.5f, pod::Vector3f{0, 1, 0}}, 1.0f); bodyB.transform->position = {0,0.25f,0}; // foot intersecting @@ -767,7 +767,7 @@ TEST(PlaneCapsule_NoCollision, { pod::World world; uf::Object objA, objB; auto& bodyA = uf::physics::create(world, objA, pod::Plane{{0,1,0},0.0f}, 0.0f); - auto& bodyB = uf::physics::create(world, objB, pod::Capsule{0.5f,1.0f}, 1.0f); + auto& bodyB = uf::physics::create(world, objB, pod::Capsule{0.5f, pod::Vector3f{0, 1, 0}}, 1.0f); bodyB.transform->position = {0,5,0}; // far above @@ -1161,7 +1161,7 @@ TEST(TriangleCapsule_Collision_Overlap, { // Capsule aligned along Z axis, radius 0.2 pod::Capsule capsule; capsule.radius = 0.2f; - capsule.halfHeight = 1.0f; // segment lengt * 0.5fh + capsule.up = pod::Vector3f{0,1,0} * 1.0f; // segment lengt * 0.5fh // placed so capsule overlaps the tri plane auto& bodyA = uf::physics::create(world, objA, tri, 0.0f); auto& bodyB = uf::physics::create(world, objB, capsule, 0.0f); @@ -1191,7 +1191,7 @@ TEST(TriangleCapsule_Collision_NoOverlap, { pod::Capsule capsule; capsule.radius = 0.2f; - capsule.halfHeight = 1.0f * 0.5f; + capsule.up = pod::Vector3f{0,1,0} * 1.0f * 0.5f; // place it well above the tri plane auto& bodyA = uf::physics::create(world, objA, tri, 0.0f); auto& bodyB = uf::physics::create(world, objB, capsule, 0.0f); @@ -1216,7 +1216,7 @@ TEST(TriangleCapsule_Collision_Tangent, { pod::Capsule capsule; capsule.radius = 0.5f; - capsule.halfHeight = 1.0f * 0.5f; + capsule.up = pod::Vector3f{0,1,0} * 1.0f * 0.5f; auto& bodyA = uf::physics::create(world, objA, tri, 0.0f); auto& bodyB = uf::physics::create(world, objB, capsule, 0.0f); // place the capsule so its sphere-bottom just kisses the triangle @@ -1248,7 +1248,7 @@ TEST(TriangleCapsule_Collision_EdgeAlignment, { pod::Capsule capsule; capsule.radius = 0.1f; - capsule.halfHeight = 2.0f; // segment tall and skinn * 0.5fy + capsule.up = pod::Vector3f{0,1,0} * 2.0f; // segment tall and skinn * 0.5fy auto& bodyA = uf::physics::create(world, objA, tri, 0.0f); auto& bodyB = uf::physics::create(world, objB, capsule, 0.0f); // lay the capsule along edge (x-axis direction near tri’s base)