guh
This commit is contained in:
parent
e434f33092
commit
78171039a1
@ -350,11 +350,12 @@
|
|||||||
"max": 0.01 // 0.2
|
"max": 0.01 // 0.2
|
||||||
},
|
},
|
||||||
"debug draw": {
|
"debug draw": {
|
||||||
"static": true,
|
"static": false,
|
||||||
"dynamic": true,
|
"dynamic": false,
|
||||||
"contacts": false,
|
"contacts": false,
|
||||||
"constraints": true,
|
"constraints": true,
|
||||||
"rays": false
|
"rays": false,
|
||||||
|
"depthTest": false
|
||||||
},
|
},
|
||||||
"fixed step": true,
|
"fixed step": true,
|
||||||
"substeps": 4
|
"substeps": 4
|
||||||
|
|||||||
@ -14,7 +14,8 @@
|
|||||||
"position": [ -7, 0, -44 ],
|
"position": [ -7, 0, -44 ],
|
||||||
//"position": [ 0, 1.5, 21 ],
|
//"position": [ 0, 1.5, 21 ],
|
||||||
//"position": [ 16.3489, 1.37972, -68.1571 ],
|
//"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": {
|
"system": {
|
||||||
"hot reload": {
|
"hot reload": {
|
||||||
@ -31,7 +32,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"physics": {
|
"physics": {
|
||||||
"ragdoll": true
|
"ragdoll": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
"ignore": false,
|
"ignore": false,
|
||||||
"import": "/model.json",
|
"import": "/model.json",
|
||||||
"assets": [
|
"assets": [
|
||||||
// "/player/bear.glb"
|
// "/player/pbear.glb"
|
||||||
{ "filename": "/player/bear/graph.json" }
|
{ "filename": "/player/bear/graph.json" }
|
||||||
],
|
],
|
||||||
"behaviors": [],
|
"behaviors": [],
|
||||||
@ -16,7 +16,7 @@
|
|||||||
"axis": [ 0, 1, 0 ],
|
"axis": [ 0, 1, 0 ],
|
||||||
"angle": 0
|
"angle": 0
|
||||||
},
|
},
|
||||||
// "scale": [ 0.35, 0.35, 0.35 ],
|
"scale": [ 0.09, 0.09, 0.09 ],
|
||||||
"reference": "parent"
|
"reference": "parent"
|
||||||
},
|
},
|
||||||
"system": {
|
"system": {
|
||||||
@ -33,7 +33,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"exporter": {
|
"exporter": {
|
||||||
"enabled": false,
|
"enabled": true,
|
||||||
"unwrap": false,
|
"unwrap": false,
|
||||||
"optimize": false
|
"optimize": false
|
||||||
},
|
},
|
||||||
@ -52,7 +52,7 @@
|
|||||||
"skinned": true
|
"skinned": true
|
||||||
},
|
},
|
||||||
"animations": {
|
"animations": {
|
||||||
"animation": "idle"
|
"animation": "wank"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -163,7 +163,7 @@ ent:bind( "tick", function(self)
|
|||||||
for k, obj in pairs(children) do
|
for k, obj in pairs(children) do
|
||||||
local transform = obj:getComponent("Transform")
|
local transform = obj:getComponent("Transform")
|
||||||
transform.orientation = orientation
|
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
|
||||||
end )
|
end )
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
"ignore": false,
|
"ignore": false,
|
||||||
"import": "/model.json",
|
"import": "/model.json",
|
||||||
"assets": [
|
"assets": [
|
||||||
// "/player/ben.glb"
|
// "/player/bear.glb"
|
||||||
{ "filename": "/player/bear/graph.json" }
|
{ "filename": "/player/bear/graph.json" }
|
||||||
],
|
],
|
||||||
"behaviors": [
|
"behaviors": [
|
||||||
@ -18,7 +18,7 @@
|
|||||||
"axis": [ 0, 1, 0 ],
|
"axis": [ 0, 1, 0 ],
|
||||||
"angle": 0
|
"angle": 0
|
||||||
},
|
},
|
||||||
"scale": [ 0.16, 0.16, 0.16 ]
|
"scale": [ 0.09, 0.09, 0.09 ]
|
||||||
},
|
},
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"track": true,
|
"track": true,
|
||||||
|
|||||||
@ -16,14 +16,15 @@ local target_transform = nil
|
|||||||
local soundEmitter = ent
|
local soundEmitter = ent
|
||||||
-- on tick
|
-- on tick
|
||||||
ent:bind( "tick", function(self)
|
ent:bind( "tick", function(self)
|
||||||
|
axes = transform:axes()
|
||||||
-- rotate to target
|
-- rotate to target
|
||||||
if target_transform ~= nil then
|
if target_transform ~= nil then
|
||||||
local target = (target_transform.position - transform.position):normalize()
|
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
|
if dot < 1.0 then
|
||||||
local cross = Vector3f.cross( transform.forward, target ):normalize()
|
local cross = Vector3f.cross( axes.forward, target ):normalize()
|
||||||
local axis = transform.up
|
local axis = axes.up
|
||||||
local angle = Vector3f.signedAngle( transform.forward, target, axis )
|
local angle = Vector3f.signedAngle( axes.forward, target, axis )
|
||||||
local rot = Quaternion.axisAngle( axis, angle * time.delta() * 4 )
|
local rot = Quaternion.axisAngle( axis, angle * time.delta() * 4 )
|
||||||
|
|
||||||
if physicsBody:initialized() then
|
if physicsBody:initialized() then
|
||||||
|
|||||||
@ -75,11 +75,11 @@ end
|
|||||||
local useDistance = 6
|
local useDistance = 6
|
||||||
local pullDistance = useDistance * 4
|
local pullDistance = useDistance * 4
|
||||||
|
|
||||||
local function tickFlashlight( transform, inputs )
|
local function tickFlashlight( transform, axes, inputs )
|
||||||
-- update light position
|
-- update light position
|
||||||
if light.enabled then
|
if light.enabled then
|
||||||
local center = transform.position
|
local center = transform.position
|
||||||
local direction = transform.forward * 8
|
local direction = axes.forward * 8
|
||||||
local offset = 0.25
|
local offset = 0.25
|
||||||
local _, depth = physicsBody:rayCast(center, direction)
|
local _, depth = physicsBody:rayCast(center, direction)
|
||||||
depth = math.clamp(depth, 0, 0.5)
|
depth = math.clamp(depth, 0, 0.5)
|
||||||
@ -132,12 +132,12 @@ local function onUse( payload )
|
|||||||
playSound(validUse and "select" or "deny")
|
playSound(validUse and "select" or "deny")
|
||||||
end
|
end
|
||||||
|
|
||||||
local function tickUse( transform, inputs )
|
local function tickUse( transform, axes, inputs )
|
||||||
-- trigger use
|
-- trigger use
|
||||||
if timers.use:elapsed() > 0.5 and inputs["E"] then
|
if timers.use:elapsed() > 0.5 and inputs["E"] then
|
||||||
timers.use:reset()
|
timers.use:reset()
|
||||||
local center = transform.position
|
local center = transform.position
|
||||||
local direction = transform.forward * useDistance
|
local direction = axes.forward * useDistance
|
||||||
local prop, depth = physicsBody:rayCast(center, direction)
|
local prop, depth = physicsBody:rayCast(center, direction)
|
||||||
|
|
||||||
local payload = {
|
local payload = {
|
||||||
@ -150,13 +150,13 @@ local function tickUse( transform, inputs )
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function tickGravGun( transform, inputs )
|
local function tickGravGun( transform, axes, inputs )
|
||||||
-- not holding anything
|
-- not holding anything
|
||||||
if heldObject.uid == 0 then
|
if heldObject.uid == 0 then
|
||||||
-- try and launch object in sights
|
-- try and launch object in sights
|
||||||
if inputs["mouse2"] then
|
if inputs["mouse2"] then
|
||||||
local center = transform.position
|
local center = transform.position
|
||||||
local direction = transform.forward * pullDistance
|
local direction = axes.forward * pullDistance
|
||||||
local prop, depth = physicsBody:rayCast( center, direction )
|
local prop, depth = physicsBody:rayCast( center, direction )
|
||||||
if depth >= 0 and prop and not string.matched( prop:name(), "/^worldspawn/" ) then
|
if depth >= 0 and prop and not string.matched( prop:name(), "/^worldspawn/" ) then
|
||||||
local heldObjectTransform = prop:getComponent("Transform")
|
local heldObjectTransform = prop:getComponent("Transform")
|
||||||
@ -165,7 +165,7 @@ local function tickGravGun( transform, inputs )
|
|||||||
local strength = 500
|
local strength = 500
|
||||||
local distanceSquared = (heldObjectTransform.position - transform.position):magnitude()
|
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
|
if timers.physcannon:elapsed() > 1.0 then
|
||||||
timers.physcannon:reset()
|
timers.physcannon:reset()
|
||||||
|
|
||||||
@ -194,18 +194,18 @@ local function tickGravGun( transform, inputs )
|
|||||||
|
|
||||||
heldObject.uid = 0
|
heldObject.uid = 0
|
||||||
heldObjectPhysicsBody:enableGravity(true)
|
heldObjectPhysicsBody:enableGravity(true)
|
||||||
heldObjectPhysicsBody:applyImpulse( transform.forward * heldObjectPhysicsBody:getMass() * 50 )
|
heldObjectPhysicsBody:applyImpulse( axes.forward * heldObjectPhysicsBody:getMass() * 50 )
|
||||||
|
|
||||||
playSound("phys_launch"..math.random(1,4))
|
playSound("phys_launch"..math.random(1,4))
|
||||||
else
|
else
|
||||||
-- update rotation
|
-- update rotation
|
||||||
if heldObject.rotate then
|
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
|
heldObjectTransform.orientation = cameraTransform:flatten().orientation
|
||||||
end
|
end
|
||||||
|
|
||||||
-- move held object
|
-- move held object
|
||||||
local forward = transform.forward * heldObject.distance
|
local forward = axes.forward * heldObject.distance
|
||||||
if heldObject.smoothSpeed ~= 0 then
|
if heldObject.smoothSpeed ~= 0 then
|
||||||
local heldObjectFlattened = heldObjectTransform:flatten()
|
local heldObjectFlattened = heldObjectTransform:flatten()
|
||||||
|
|
||||||
@ -252,15 +252,16 @@ ent:bind( "tick", function(self)
|
|||||||
|
|
||||||
-- eye transform
|
-- eye transform
|
||||||
local flattenedTransform = fixedCamera and transform:flatten() or cameraTransform:flatten()
|
local flattenedTransform = fixedCamera and transform:flatten() or cameraTransform:flatten()
|
||||||
|
local axes = flattenedTransform:axes()
|
||||||
|
|
||||||
-- update flashlight
|
-- update flashlight
|
||||||
tickFlashlight( flattenedTransform, inputs )
|
tickFlashlight( flattenedTransform, axes, inputs )
|
||||||
|
|
||||||
-- update use
|
-- update use
|
||||||
tickUse( flattenedTransform, inputs )
|
tickUse( flattenedTransform, axes, inputs )
|
||||||
|
|
||||||
-- update HOLP
|
-- update HOLP
|
||||||
tickGravGun( flattenedTransform, inputs )
|
tickGravGun( flattenedTransform, axes, inputs )
|
||||||
|
|
||||||
-- get collision events
|
-- get collision events
|
||||||
--[[
|
--[[
|
||||||
|
|||||||
@ -8,12 +8,12 @@
|
|||||||
namespace uf {
|
namespace uf {
|
||||||
namespace debug {
|
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 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 drawShape( const pod::AABB& aabb, const pod::Transform<>& transform = {} );
|
||||||
void UF_API drawObb( pod::OBB obb, pod::Transform<> transform = {} );
|
void UF_API drawShape( const pod::OBB& obb, const pod::Transform<>& transform = {} );
|
||||||
void UF_API drawSphere( pod::Sphere sphere, pod::Transform<> transform = {} );
|
void UF_API drawShape( const pod::Sphere& sphere, const pod::Transform<>& transform = {} );
|
||||||
void UF_API drawCapsule( pod::Capsule capsule, pod::Transform<> transform = {} );
|
void UF_API drawShape( const pod::Capsule& capsule, const pod::Transform<>& transform = {} );
|
||||||
void UF_API drawPlane( pod::Plane plane, pod::Transform<> transform = {} );
|
void UF_API drawShape( const pod::Plane& plane, const pod::Transform<>& transform = {} );
|
||||||
void UF_API drawTriangle( pod::Triangle tri, 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 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 );
|
void UF_API draw( float dt = 0 );
|
||||||
|
|||||||
@ -491,6 +491,7 @@ namespace pod {
|
|||||||
bool contacts = false;
|
bool contacts = false;
|
||||||
bool constraints = false;
|
bool constraints = false;
|
||||||
bool rays = false;
|
bool rays = false;
|
||||||
|
bool depthTest = true;
|
||||||
} debugDraw;
|
} debugDraw;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -166,7 +166,7 @@ template<typename T> pod::Quaternion<T> uf::quaternion::unitVectors( const pod::
|
|||||||
pod::Vector3t<T> cross = uf::vector::cross(uNorm, vNorm);
|
pod::Vector3t<T> cross = uf::vector::cross(uNorm, vNorm);
|
||||||
T s = sqrt((1 + dot) * 2);
|
T s = sqrt((1 + dot) * 2);
|
||||||
|
|
||||||
return uf::quaternion::normalize({
|
return uf::quaternion::normalize(pod::Quaternion<>{
|
||||||
.x = cross.x / s,
|
.x = cross.x / s,
|
||||||
.y = cross.y / s,
|
.y = cross.y / s,
|
||||||
.z = cross.z / s,
|
.z = cross.z / s,
|
||||||
|
|||||||
@ -3,22 +3,27 @@
|
|||||||
#include <uf/config.h>
|
#include <uf/config.h>
|
||||||
#include <uf/utils/math/vector.h>
|
#include <uf/utils/math/vector.h>
|
||||||
|
|
||||||
|
#define OBB_EXTENT_CENTER 0
|
||||||
|
|
||||||
namespace pod {
|
namespace pod {
|
||||||
struct Plane {
|
struct Plane {
|
||||||
alignas(16) pod::Vector3f normal;
|
pod::Vector3f normal;
|
||||||
float offset;
|
float offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AABB {
|
struct AABB {
|
||||||
alignas(16) pod::Vector3f min;
|
pod::Vector3f min;
|
||||||
alignas(16) pod::Vector3f max;
|
pod::Vector3f max;
|
||||||
// operator OBB() const { return OBB{ (min + max) * 0.5f, (min - max) * 0.5f }; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct OBB {
|
struct OBB {
|
||||||
alignas(16) pod::Vector3f center;
|
#if OBB_EXTENT_CENTER
|
||||||
alignas(16) pod::Vector3f extent;
|
pod::Vector3f extent;
|
||||||
// operator AABB() const { return AABB{ center - extent, center + extent }; }
|
pod::Vector3f center;
|
||||||
|
#else
|
||||||
|
pod::Vector3f center;
|
||||||
|
pod::Vector3f extent;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Sphere {
|
struct Sphere {
|
||||||
@ -27,7 +32,7 @@ namespace pod {
|
|||||||
|
|
||||||
struct Capsule {
|
struct Capsule {
|
||||||
float radius;
|
float radius;
|
||||||
float halfHeight;
|
pod::Vector3f up;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Ray {
|
struct Ray {
|
||||||
|
|||||||
@ -21,29 +21,27 @@ namespace pod {
|
|||||||
typedef T type_t;
|
typedef T type_t;
|
||||||
|
|
||||||
pod::Vector3t<T> position = {0, 0,0 };
|
pod::Vector3t<T> position = {0, 0,0 };
|
||||||
pod::Vector3t<T> scale = {1, 1, 1};
|
|
||||||
|
|
||||||
pod::Vector3t<T> up = {0, 1, 0};
|
|
||||||
pod::Vector3t<T> right = {1, 0, 0};
|
|
||||||
pod::Vector3t<T> forward = {0, 0, 1};
|
|
||||||
|
|
||||||
pod::Quaternion<T> orientation = {0, 0, 0, 1};
|
pod::Quaternion<T> orientation = {0, 0, 0, 1};
|
||||||
|
pod::Vector3t<T> scale = {1, 1, 1};
|
||||||
pod::Matrix4t<T> model = uf::matrix::identity();
|
|
||||||
|
|
||||||
pod::Transform<T>* reference = NULL;
|
pod::Transform<T>* 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 uf {
|
||||||
namespace transform {
|
namespace transform {
|
||||||
template<typename T> pod::Transform<T>& /*UF_API*/ initialize( pod::Transform<T>& transform );
|
template<typename T> pod::Transform<T>& /*UF_API*/ initialize( pod::Transform<T>& transform );
|
||||||
template<typename T> pod::Transform<T> /*UF_API*/ initialize();
|
template<typename T> pod::Transform<T> /*UF_API*/ initialize();
|
||||||
|
template<typename T> pod::Axes /*UF_API*/ axes( const pod::Transform<T>& transform, const pod::Vector3t<T>& at = {} );
|
||||||
template<typename T> pod::Transform<T>& /*UF_API*/ lookAt( pod::Transform<T>& transform, const pod::Vector3t<T>& at );
|
template<typename T> pod::Transform<T>& /*UF_API*/ lookAt( pod::Transform<T>& transform, const pod::Vector3t<T>& at );
|
||||||
template<typename T> pod::Transform<T>& /*UF_API*/ move( pod::Transform<T>& transform, const pod::Vector3t<T>& axis, pod::Math::num_t delta );
|
template<typename T> pod::Transform<T>& /*UF_API*/ move( pod::Transform<T>& transform, const pod::Vector3t<T>& axis, pod::Math::num_t delta );
|
||||||
template<typename T> pod::Transform<T>& /*UF_API*/ move( pod::Transform<T>& transform, const pod::Vector3t<T>& delta );
|
template<typename T> pod::Transform<T>& /*UF_API*/ move( pod::Transform<T>& transform, const pod::Vector3t<T>& delta );
|
||||||
template<typename T> pod::Transform<T>& /*UF_API*/ reorient( pod::Transform<T>& transform );
|
|
||||||
template<typename T> pod::Transform<T> /*UF_API*/ reorient( const pod::Transform<T>& transform );
|
|
||||||
template<typename T> pod::Transform<T>& /*UF_API*/ rotate( pod::Transform<T>& transform, const pod::Vector3t<T>& axis, pod::Math::num_t delta );
|
template<typename T> pod::Transform<T>& /*UF_API*/ rotate( pod::Transform<T>& transform, const pod::Vector3t<T>& axis, pod::Math::num_t delta );
|
||||||
template<typename T> pod::Transform<T>& /*UF_API*/ rotate( pod::Transform<T>& transform, const pod::Quaternion<T>& quat );
|
template<typename T> pod::Transform<T>& /*UF_API*/ rotate( pod::Transform<T>& transform, const pod::Quaternion<T>& quat );
|
||||||
template<typename T> pod::Transform<T>& /*UF_API*/ scale( pod::Transform<T>& transform, const pod::Vector3t<T>& factor );
|
template<typename T> pod::Transform<T>& /*UF_API*/ scale( pod::Transform<T>& transform, const pod::Vector3t<T>& factor );
|
||||||
@ -52,7 +50,7 @@ namespace uf {
|
|||||||
template<typename T> pod::Matrix4t<T> /*UF_API*/ model( const pod::Transform<T>& transform, bool flatten = false, size_t depth = SIZE_MAX );
|
template<typename T> pod::Matrix4t<T> /*UF_API*/ model( const pod::Transform<T>& transform, bool flatten = false, size_t depth = SIZE_MAX );
|
||||||
template<typename T> pod::Transform<T> /*UF_API*/ fromMatrix( const pod::Matrix4t<T>& matrix );
|
template<typename T> pod::Transform<T> /*UF_API*/ fromMatrix( const pod::Matrix4t<T>& matrix );
|
||||||
template<typename T> pod::Transform<T>& /*UF_API*/ reference( pod::Transform<T>& transform, const pod::Transform<T>& parent, bool reorient = true );
|
template<typename T> pod::Transform<T>& /*UF_API*/ reference( pod::Transform<T>& transform, const pod::Transform<T>& parent, bool reorient = true );
|
||||||
template<typename T> pod::Transform<T> /*UF_API*/ interpolate( const pod::Transform<T>& from, const pod::Transform<T>& to, float factor, bool reorient = true );
|
template<typename T> pod::Transform<T> /*UF_API*/ interpolate( const pod::Transform<T>& from, const pod::Transform<T>& to, float factor );
|
||||||
template<typename T> pod::Transform<T> /*UF_API*/ inverse(const pod::Transform<T>& t);
|
template<typename T> pod::Transform<T> /*UF_API*/ inverse(const pod::Transform<T>& t);
|
||||||
template<typename T> pod::Vector3t<T> /*UF_API*/ apply( const pod::Transform<T>& transform, const pod::Vector3t<T>& point );
|
template<typename T> pod::Vector3t<T> /*UF_API*/ apply( const pod::Transform<T>& transform, const pod::Vector3t<T>& point );
|
||||||
template<typename T> pod::Vector3t<T> /*UF_API*/ applyInverse(const pod::Transform<T>& t, const pod::Vector3t<T>& worldPoint);
|
template<typename T> pod::Vector3t<T> /*UF_API*/ applyInverse(const pod::Transform<T>& t, const pod::Vector3t<T>& worldPoint);
|
||||||
|
|||||||
@ -2,13 +2,7 @@ template<typename T>
|
|||||||
pod::Transform<T>& /*UF_API*/ uf::transform::initialize( pod::Transform<T>& transform ) {
|
pod::Transform<T>& /*UF_API*/ uf::transform::initialize( pod::Transform<T>& transform ) {
|
||||||
transform.position = {0, 0, 0};
|
transform.position = {0, 0, 0};
|
||||||
transform.scale = {1, 1, 1};
|
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.orientation = {0, 0, 0, 1};
|
||||||
transform.model = uf::matrix::identity();
|
|
||||||
transform.reference = nullptr;
|
transform.reference = nullptr;
|
||||||
|
|
||||||
return transform;
|
return transform;
|
||||||
@ -20,18 +14,27 @@ pod::Transform<T> /*UF_API*/ uf::transform::initialize() {
|
|||||||
return uf::transform::initialize(transform);
|
return uf::transform::initialize(transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
pod::Axes /*UF_API*/ uf::transform::axes( const pod::Transform<T>& transform, const pod::Vector3t<T>& 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<typename T>
|
template<typename T>
|
||||||
pod::Transform<T>& /*UF_API*/ uf::transform::lookAt( pod::Transform<T>& transform, const pod::Vector3t<T>& at ) {
|
pod::Transform<T>& /*UF_API*/ uf::transform::lookAt( pod::Transform<T>& transform, const pod::Vector3t<T>& at ) {
|
||||||
pod::Vector3t<T> forward = uf::vector::normalize( at - transform.position );
|
auto axes = uf::transform::axes( transform, at );
|
||||||
pod::Vector3t<T> right = uf::vector::normalize(uf::vector::cross( transform.up, forward ));
|
transform.orientation = uf::quaternion::lookAt( axes.forward, axes.up );
|
||||||
pod::Vector3t<T> 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 );
|
|
||||||
|
|
||||||
return transform;
|
return transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,32 +50,17 @@ pod::Transform<T>& /*UF_API*/ uf::transform::move( pod::Transform<T>& transform,
|
|||||||
return transform;
|
return transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
pod::Transform<T>& /*UF_API*/ uf::transform::reorient( pod::Transform<T>& transform ) {
|
|
||||||
pod::Quaternion<T> 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<typename T>
|
|
||||||
pod::Transform<T> /*UF_API*/ uf::transform::reorient( const pod::Transform<T>& _transform ) {
|
|
||||||
pod::Transform<T> transform = _transform;
|
|
||||||
return uf::transform::reorient(transform);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
pod::Transform<T>& /*UF_API*/ uf::transform::rotate( pod::Transform<T>& transform, const pod::Vector3t<T>& axis, pod::Math::num_t delta ) {
|
pod::Transform<T>& /*UF_API*/ uf::transform::rotate( pod::Transform<T>& transform, const pod::Vector3t<T>& axis, pod::Math::num_t delta ) {
|
||||||
pod::Quaternion<> quat = uf::quaternion::axisAngle( axis, delta );
|
pod::Quaternion<> quat = uf::quaternion::axisAngle( axis, delta );
|
||||||
transform.orientation = uf::vector::normalize(uf::quaternion::multiply(quat, transform.orientation));
|
transform.orientation = uf::vector::normalize(uf::quaternion::multiply(quat, transform.orientation));
|
||||||
return uf::transform::reorient(transform);
|
return transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
pod::Transform<T>& /*UF_API*/ uf::transform::rotate( pod::Transform<T>& transform, const pod::Quaternion<T>& quat ) {
|
pod::Transform<T>& /*UF_API*/ uf::transform::rotate( pod::Transform<T>& transform, const pod::Quaternion<T>& quat ) {
|
||||||
transform.orientation = uf::vector::normalize(uf::quaternion::multiply(quat, transform.orientation));
|
transform.orientation = uf::vector::normalize(uf::quaternion::multiply(quat, transform.orientation));
|
||||||
return uf::transform::reorient(transform);
|
return transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@ -98,12 +86,11 @@ pod::Transform<T> /*UF_API*/ uf::transform::flatten( const pod::Transform<T>& tr
|
|||||||
combined.position = pointer->position + uf::quaternion::rotate(pointer->orientation, combined.position * pointer->scale);
|
combined.position = pointer->position + uf::quaternion::rotate(pointer->orientation, combined.position * pointer->scale);
|
||||||
combined.orientation = uf::quaternion::multiply( pointer->orientation, combined.orientation );
|
combined.orientation = uf::quaternion::multiply( pointer->orientation, combined.orientation );
|
||||||
combined.scale = combined.scale * pointer->scale;
|
combined.scale = combined.scale * pointer->scale;
|
||||||
combined.model = pointer->model * combined.model;
|
|
||||||
|
|
||||||
if ( pointer == pointer->reference ) break;
|
if ( pointer == pointer->reference ) break;
|
||||||
pointer = pointer->reference;
|
pointer = pointer->reference;
|
||||||
}
|
}
|
||||||
return uf::transform::reorient(combined);
|
return combined;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@ -112,8 +99,7 @@ pod::Matrix4t<T> /*UF_API*/ uf::transform::model( const pod::Transform<T>& trans
|
|||||||
pod::Transform<T> flat = uf::transform::flatten(transform, depth);
|
pod::Transform<T> flat = uf::transform::flatten(transform, depth);
|
||||||
return uf::matrix::translate( uf::matrix::identity(), flat.position ) *
|
return uf::matrix::translate( uf::matrix::identity(), flat.position ) *
|
||||||
uf::quaternion::matrix( flat.orientation ) *
|
uf::quaternion::matrix( flat.orientation ) *
|
||||||
uf::matrix::scale( uf::matrix::identity(), flat.scale ) *
|
uf::matrix::scale( uf::matrix::identity(), flat.scale );
|
||||||
flat.model;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pod::Matrix4t<T> matrix = uf::matrix::identity();
|
pod::Matrix4t<T> matrix = uf::matrix::identity();
|
||||||
@ -122,8 +108,7 @@ pod::Matrix4t<T> /*UF_API*/ uf::transform::model( const pod::Transform<T>& trans
|
|||||||
do {
|
do {
|
||||||
pod::Matrix4t<T> modelMat = uf::matrix::translate( uf::matrix::identity(), pointer->position ) *
|
pod::Matrix4t<T> modelMat = uf::matrix::translate( uf::matrix::identity(), pointer->position ) *
|
||||||
uf::quaternion::matrix( pointer->orientation ) *
|
uf::quaternion::matrix( pointer->orientation ) *
|
||||||
uf::matrix::scale( uf::matrix::identity(), pointer->scale ) *
|
uf::matrix::scale( uf::matrix::identity(), pointer->scale );
|
||||||
pointer->model;
|
|
||||||
matrix = modelMat * matrix;
|
matrix = modelMat * matrix;
|
||||||
|
|
||||||
if ( pointer == pointer->reference ) break;
|
if ( pointer == pointer->reference ) break;
|
||||||
@ -136,29 +121,25 @@ pod::Matrix4t<T> /*UF_API*/ uf::transform::model( const pod::Transform<T>& trans
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
pod::Transform<T> uf::transform::fromMatrix( const pod::Matrix4t<T>& matrix ) {
|
pod::Transform<T> uf::transform::fromMatrix( const pod::Matrix4t<T>& matrix ) {
|
||||||
pod::Transform<T> transform;
|
pod::Transform<T> transform;
|
||||||
transform.position = uf::matrix::multiply<float>( 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.orientation = uf::quaternion::fromMatrix( matrix );
|
||||||
transform.model = matrix;
|
// transform.scale = ...;
|
||||||
return reorient( transform );
|
return transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
pod::Transform<T>& /*UF_API*/ uf::transform::reference( pod::Transform<T>& transform, const pod::Transform<T>& parent, bool reorient ) {
|
pod::Transform<T>& /*UF_API*/ uf::transform::reference( pod::Transform<T>& transform, const pod::Transform<T>& parent, bool reorient ) {
|
||||||
transform.reference = const_cast<pod::Transform<T>*>(&parent);
|
transform.reference = const_cast<pod::Transform<T>*>(&parent);
|
||||||
if ( !reorient ) {
|
if ( reorient ) transform.position = parent.position - transform.position;
|
||||||
return transform;
|
|
||||||
}
|
|
||||||
|
|
||||||
transform.position = parent.position - transform.position;
|
|
||||||
return transform;
|
return transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
pod::Transform<T> /*UF_API*/ uf::transform::interpolate( const pod::Transform<T>& from, const pod::Transform<T>& to, float factor, bool reorient ) {
|
pod::Transform<T> /*UF_API*/ uf::transform::interpolate( const pod::Transform<T>& from, const pod::Transform<T>& to, float factor ) {
|
||||||
pod::Transform transform = to;
|
pod::Transform transform = to;
|
||||||
transform.position = uf::vector::lerp( from.position, to.position, factor );
|
transform.position = uf::vector::lerp( from.position, to.position, factor );
|
||||||
transform.orientation = uf::quaternion::slerp( from.orientation, to.orientation, factor );
|
transform.orientation = uf::quaternion::slerp( from.orientation, to.orientation, factor );
|
||||||
return reorient ? uf::transform::reorient( transform ) : transform;
|
return transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@ -183,7 +164,7 @@ pod::Transform<T> uf::transform::inverse(const pod::Transform<T>& t) {
|
|||||||
negPos.z * sInv.z
|
negPos.z * sInv.z
|
||||||
});
|
});
|
||||||
|
|
||||||
return uf::transform::reorient(inv);
|
return inv;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@ -221,7 +202,6 @@ ext::json::Value /*UF_API*/ uf::transform::encode( const pod::Transform<T>& t, b
|
|||||||
json["position"] = uf::vector::encode(transform.position, settings);
|
json["position"] = uf::vector::encode(transform.position, settings);
|
||||||
json["orientation"] = uf::vector::encode(transform.orientation, settings);
|
json["orientation"] = uf::vector::encode(transform.orientation, settings);
|
||||||
json["scale"] = uf::vector::encode(transform.scale, settings);
|
json["scale"] = uf::vector::encode(transform.scale, settings);
|
||||||
json["model"] = uf::matrix::encode(transform.model, settings);
|
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,8 +217,6 @@ pod::Transform<T>& /*UF_API*/ uf::transform::decode( const ext::json::Value& _js
|
|||||||
T angle = json["rotation"]["angle"].as<T>();
|
T angle = json["rotation"]["angle"].as<T>();
|
||||||
transform.orientation = uf::quaternion::axisAngle( axis, angle );
|
transform.orientation = uf::quaternion::axisAngle( axis, angle );
|
||||||
}
|
}
|
||||||
|
|
||||||
transform.model = uf::matrix::decode<T, 4, 4>(json["model"], transform.model);
|
|
||||||
return transform;
|
return transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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.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.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.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<bool>() && configEnginePhysicsDebugDrawJson.as<bool>() ) {
|
} else if ( configEnginePhysicsDebugDrawJson.is<bool>() && configEnginePhysicsDebugDrawJson.as<bool>() ) {
|
||||||
uf::physics::settings.debugDraw.mask = pod::Collider::CATEGORY_ALL;
|
uf::physics::settings.debugDraw.mask = pod::Collider::CATEGORY_ALL;
|
||||||
|
|||||||
@ -512,7 +512,7 @@ void ext::GuiBehavior::tick( uf::Object& self ) {
|
|||||||
|
|
||||||
for ( auto i = 0; i < uf::renderer::settings::maxViews; ++i ) {
|
for ( auto i = 0; i < uf::renderer::settings::maxViews; ++i ) {
|
||||||
if ( metadata.mode == 1 ) {
|
if ( metadata.mode == 1 ) {
|
||||||
uniforms.matrices[i].model = transform.model;
|
uniforms.matrices[i].model = uf::transform::model( transform );
|
||||||
} else if ( metadata.mode == 2 ) {
|
} else if ( metadata.mode == 2 ) {
|
||||||
auto& scene = uf::scene::getCurrentScene();
|
auto& scene = uf::scene::getCurrentScene();
|
||||||
auto& controller = scene.getController();
|
auto& controller = scene.getController();
|
||||||
@ -523,14 +523,12 @@ void ext::GuiBehavior::tick( uf::Object& self ) {
|
|||||||
camera.getProjection(i) *
|
camera.getProjection(i) *
|
||||||
uf::matrix::translate( uf::matrix::identity(), flatten.position ) *
|
uf::matrix::translate( uf::matrix::identity(), flatten.position ) *
|
||||||
uf::matrix::scale( uf::matrix::identity(), flatten.scale ) *
|
uf::matrix::scale( uf::matrix::identity(), flatten.scale ) *
|
||||||
uf::quaternion::matrix( flatten.orientation ) *
|
uf::quaternion::matrix( flatten.orientation );
|
||||||
flatten.model;
|
|
||||||
} else {
|
} else {
|
||||||
uniforms.matrices[i].model =
|
uniforms.matrices[i].model =
|
||||||
uf::matrix::translate( uf::matrix::identity(), flatten.position ) *
|
uf::matrix::translate( uf::matrix::identity(), flatten.position ) *
|
||||||
uf::matrix::scale( uf::matrix::identity(), flatten.scale ) *
|
uf::matrix::scale( uf::matrix::identity(), flatten.scale ) *
|
||||||
uf::quaternion::matrix( flatten.orientation ) *
|
uf::quaternion::matrix( flatten.orientation );
|
||||||
flatten.model;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -126,10 +126,14 @@ void ext::PlayerBehavior::initialize( uf::Object& self ) {
|
|||||||
UF_BEHAVIOR_METADATA_BIND_SERIALIZER_HOOKS(metadata, metadataJson);
|
UF_BEHAVIOR_METADATA_BIND_SERIALIZER_HOOKS(metadata, metadataJson);
|
||||||
}
|
}
|
||||||
void ext::PlayerBehavior::tick( uf::Object& self ) {
|
void ext::PlayerBehavior::tick( uf::Object& self ) {
|
||||||
|
auto& transform = this->getComponent<pod::Transform<>>();
|
||||||
|
|
||||||
auto& camera = this->getComponent<uf::Camera>();
|
auto& camera = this->getComponent<uf::Camera>();
|
||||||
auto& cameraTransform = camera.getTransform();
|
auto& cameraTransform = camera.getTransform();
|
||||||
|
|
||||||
auto& transform = this->getComponent<pod::Transform<>>();
|
auto cameraAxes = uf::transform::axes( cameraTransform );
|
||||||
|
auto axes = uf::transform::axes( transform );
|
||||||
|
|
||||||
auto& scene = uf::scene::getCurrentScene();
|
auto& scene = uf::scene::getCurrentScene();
|
||||||
|
|
||||||
auto& metadata = this->getComponent<ext::PlayerBehavior::Metadata>();
|
auto& metadata = this->getComponent<ext::PlayerBehavior::Metadata>();
|
||||||
@ -296,7 +300,7 @@ void ext::PlayerBehavior::tick( uf::Object& self ) {
|
|||||||
uf::Object* pointer = NULL;
|
uf::Object* pointer = NULL;
|
||||||
float length = metadata.use.length;
|
float length = metadata.use.length;
|
||||||
// pod::Vector3f center = transform.position + cameraTransform.position;
|
// 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 );
|
auto flattened = uf::transform::flatten( cameraTransform );
|
||||||
pod::Vector3f center = flattened.position;
|
pod::Vector3f center = flattened.position;
|
||||||
pod::Vector3f direction = flattened.forward * length;
|
pod::Vector3f direction = flattened.forward * length;
|
||||||
@ -385,10 +389,10 @@ void ext::PlayerBehavior::tick( uf::Object& self ) {
|
|||||||
metadata.system.menu = stats.menu;
|
metadata.system.menu = stats.menu;
|
||||||
}
|
}
|
||||||
|
|
||||||
pod::Transform<> translator = transform;
|
pod::Axes translator = uf::transform::axes( transform );
|
||||||
#if UF_USE_OPENVR
|
#if UF_USE_OPENVR
|
||||||
// use the orientation of our controller to determine our target
|
// use the orientation of our controller to determine our target
|
||||||
if ( ext::openvr::context ) {
|
/*if ( ext::openvr::context ) {
|
||||||
bool useController = true;
|
bool useController = true;
|
||||||
translator.orientation = uf::quaternion::multiply( transform.orientation, useController ? ext::openvr::controllerQuaternion( vr::Controller_Hand::Hand_Right ) : ext::openvr::hmdQuaternion() );
|
translator.orientation = uf::quaternion::multiply( transform.orientation, useController ? ext::openvr::controllerQuaternion( vr::Controller_Hand::Hand_Right ) : ext::openvr::hmdQuaternion() );
|
||||||
translator = uf::transform::reorient( translator );
|
translator = uf::transform::reorient( translator );
|
||||||
@ -401,17 +405,17 @@ void ext::PlayerBehavior::tick( uf::Object& self ) {
|
|||||||
|
|
||||||
translator.forward = uf::vector::normalize( translator.forward );
|
translator.forward = uf::vector::normalize( translator.forward );
|
||||||
translator.right = uf::vector::normalize( translator.right );
|
translator.right = uf::vector::normalize( translator.right );
|
||||||
} else
|
} else*/
|
||||||
#endif
|
#endif
|
||||||
// un-flatted if noclipped
|
// un-flatted if noclipped
|
||||||
|
|
||||||
if ( metadata.camera.fixed ) {
|
if ( metadata.camera.fixed ) {
|
||||||
translator = cameraTransform;
|
translator = uf::transform::axes( cameraTransform );
|
||||||
translator.forward.y = 0;
|
translator.forward.y = 0;
|
||||||
translator.forward = uf::vector::normalize( translator.forward );
|
translator.forward = uf::vector::normalize( translator.forward );
|
||||||
}
|
}
|
||||||
else if ( stats.noclipped || physicsBody.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.y += cameraAxes.forward.y;
|
||||||
translator.forward = uf::vector::normalize( translator.forward );
|
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*/ );
|
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 ) {
|
if ( !metadata.movement.strafe && dot < 1.0f ) {
|
||||||
// auto cross = uf::vector::normalize( uf::vector::cross( transform.forward, target ) );
|
// auto cross = uf::vector::normalize( uf::vector::cross( axes.forward, target ) );
|
||||||
// auto axis = cross == pod::Vector3f{0, 0, 0} ? transform.up : cross;
|
// auto axis = cross == pod::Vector3f{0, 0, 0} ? axes.up : cross;
|
||||||
auto axis = transform.up;
|
auto axis = axes.up;
|
||||||
float angle = uf::vector::signedAngle( transform.forward, target, axis ) * ONE_OVER_SIXTY /*uf::physics::time::delta*/ * 4; // speed.rotate;
|
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
|
if ( physicsBody.object ) uf::physics::applyRotation( physicsBody, axis, angle ); else
|
||||||
uf::transform::rotate( transform, axis, angle );
|
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;
|
if ( metadata.camera.invert.x ) lookDelta.x *= -1;
|
||||||
metadata.camera.limit.current.x += lookDelta.x;
|
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 ( 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
|
if ( physicsBody.object ) uf::physics::applyRotation( physicsBody, axes.up, lookDelta.x ); else
|
||||||
uf::transform::rotate( transform, transform.up, lookDelta.x );
|
uf::transform::rotate( transform, axes.up, lookDelta.x );
|
||||||
} else metadata.camera.limit.current.x -= lookDelta.x;
|
} else metadata.camera.limit.current.x -= lookDelta.x;
|
||||||
}
|
}
|
||||||
if ( lookDelta.y != 0 ) {
|
if ( lookDelta.y != 0 ) {
|
||||||
if ( metadata.camera.invert.y ) lookDelta.y *= -1;
|
if ( metadata.camera.invert.y ) lookDelta.y *= -1;
|
||||||
metadata.camera.limit.current.y += lookDelta.y;
|
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 ( 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
|
// if ( physicsBody.object && !physicsBody.shared ) uf::physics::applyRotation( physicsBody, cameraAxes.right, lookDelta.y ); else
|
||||||
uf::transform::rotate( cameraTransform, cameraTransform.right, lookDelta.y );
|
uf::transform::rotate( cameraTransform, cameraAxes.right, lookDelta.y );
|
||||||
} else metadata.camera.limit.current.y -= lookDelta.y;
|
} else metadata.camera.limit.current.y -= lookDelta.y;
|
||||||
}
|
}
|
||||||
} else if ( metadata.system.control ) {
|
} else if ( metadata.system.control ) {
|
||||||
if ( keys.lookRight ^ keys.lookLeft ) {
|
if ( keys.lookRight ^ keys.lookLeft ) {
|
||||||
if ( physicsBody.object ) uf::physics::applyRotation( physicsBody, transform.up, speed.rotate * (keys.lookRight ? 1 : -1) ); else
|
if ( physicsBody.object ) uf::physics::applyRotation( physicsBody, axes.up, speed.rotate * (keys.lookRight ? 1 : -1) ); else
|
||||||
uf::transform::rotate( transform, transform.up, speed.rotate * (keys.lookRight ? 1 : -1) );
|
uf::transform::rotate( transform, axes.up, speed.rotate * (keys.lookRight ? 1 : -1) );
|
||||||
}
|
}
|
||||||
if ( keys.lookUp ^ keys.lookDown ) {
|
if ( keys.lookUp ^ keys.lookDown ) {
|
||||||
float direction = keys.lookUp ? 1 : -1;
|
float direction = keys.lookUp ? 1 : -1;
|
||||||
if ( metadata.camera.invert.y ) direction *= -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 {
|
} else {
|
||||||
if ( keys.lookRight ^ keys.lookLeft ) {
|
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 );
|
// cameraTransform.position = uf::quaternion::rotate( rotation, cameraTransform.position - transform.position );
|
||||||
}
|
}
|
||||||
if ( keys.lookUp ^ keys.lookDown ) {
|
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;
|
float direction = keys.lookUp ? 1 : -1;
|
||||||
if ( metadata.camera.invert.y ) direction *= -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.reference = NULL;
|
||||||
cameraTransform.position = transform.position + metadata.camera.offset;
|
cameraTransform.position = transform.position + metadata.camera.offset;
|
||||||
// cameraTransform.orientation = uf::vector::decode( metadataJson["camera"]["orientation"], uf::quaternion::identity() );
|
// cameraTransform.orientation = uf::vector::decode( metadataJson["camera"]["orientation"], uf::quaternion::identity() );
|
||||||
cameraTransform = uf::transform::reorient( cameraTransform );
|
cameraAxes = uf::transform::axes( cameraTransform );
|
||||||
} else {
|
} else {
|
||||||
if ( metadata.camera.offset != pod::Vector3f{0,0,0} ) {
|
if ( metadata.camera.offset != pod::Vector3f{0,0,0} ) {
|
||||||
//auto flattened = uf::transform::flatten( cameraTransform );
|
//auto flattened = uf::transform::flatten( cameraTransform );
|
||||||
|
|||||||
@ -432,9 +432,7 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
|
|||||||
transform = uf::transform::reorient( transform );
|
transform = uf::transform::reorient( transform );
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
transform = uf::transform::flatten( transform );
|
transform = uf::transform::flatten( transform );
|
||||||
transform.forward *= -1;
|
|
||||||
|
|
||||||
ext::al::listener( transform );
|
ext::al::listener( transform );
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -82,8 +82,7 @@ namespace {
|
|||||||
return
|
return
|
||||||
uf::matrix::translate( uf::matrix::identity(), transform.position ) *
|
uf::matrix::translate( uf::matrix::identity(), transform.position ) *
|
||||||
uf::quaternion::matrix(transform.orientation) *
|
uf::quaternion::matrix(transform.orientation) *
|
||||||
uf::matrix::scale( uf::matrix::identity(), transform.scale ) *
|
uf::matrix::scale( uf::matrix::identity(), transform.scale );
|
||||||
transform.model;
|
|
||||||
}
|
}
|
||||||
pod::Matrix4f worldMatrix( const pod::Graph& graph, int32_t index ) {
|
pod::Matrix4f worldMatrix( const pod::Graph& graph, int32_t index ) {
|
||||||
pod::Matrix4f matrix = ::localMatrix( graph, index );
|
pod::Matrix4f matrix = ::localMatrix( graph, index );
|
||||||
@ -180,12 +179,15 @@ void uf::graph::updateAnimation( pod::Graph& graph, float delta ) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ( graph.sequence.empty() ) goto UPDATE;
|
if ( graph.sequence.empty() ) goto UPDATE;
|
||||||
if ( graph.settings.animations.override.a >= 0 ) goto OVERRIDE;
|
if ( graph.settings.animations.override.a >= 0 ) goto OVERRIDE;
|
||||||
{
|
{
|
||||||
uf::stl::string name = graph.sequence.front();
|
uf::stl::string name = graph.sequence.front();
|
||||||
pod::Animation* animation = &storage.animations.map[name]; // &graph.animations[name];
|
pod::Animation* animation = &storage.animations.map[name]; // &graph.animations[name];
|
||||||
animation->cur += delta * graph.settings.animations.speed; // * graph.settings.animations.override.speed;
|
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 ) {
|
if ( animation->end < animation->cur ) {
|
||||||
animation->cur = graph.settings.animations.loop ? animation->cur - animation->end : 0;
|
animation->cur = graph.settings.animations.loop ? animation->cur - animation->end : 0;
|
||||||
// go-to next animation
|
// go-to next animation
|
||||||
@ -243,6 +245,24 @@ void uf::graph::updateAnimation( pod::Graph& graph, pod::Node& node ) {
|
|||||||
auto& scene = uf::scene::getCurrentScene();
|
auto& scene = uf::scene::getCurrentScene();
|
||||||
auto& storage = ::getGraphStorage( scene );
|
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() ) {
|
if ( 0 <= node.skin && node.skin < graph.skins.size() ) {
|
||||||
pod::Matrix4f nodeMatrix = ::worldMatrix( graph, node.index );
|
pod::Matrix4f nodeMatrix = ::worldMatrix( graph, node.index );
|
||||||
pod::Matrix4f inverseTransform = uf::matrix::inverse( nodeMatrix );
|
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];
|
joints[i] = inverseTransform * matrix * skin.inverseBindMatrices[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// separate function in the event something later might need it
|
// separate function in the event something later might need it
|
||||||
@ -308,8 +329,7 @@ uf::stl::vector<pod::OBB> uf::graph::obbFromSkin( const pod::Graph& graph, const
|
|||||||
auto& skin = storage.skins[skinName];
|
auto& skin = storage.skins[skinName];
|
||||||
auto& mesh = storage.meshes[meshName];
|
auto& mesh = storage.meshes[meshName];
|
||||||
|
|
||||||
// store as min/max AABB
|
uf::stl::vector<pod::AABB> aabbs(skin.joints.size(), {
|
||||||
uf::stl::vector<pod::OBB> bounds(skin.joints.size(), {
|
|
||||||
pod::Vector3f{ FLT_MAX, FLT_MAX, FLT_MAX },
|
pod::Vector3f{ FLT_MAX, FLT_MAX, FLT_MAX },
|
||||||
pod::Vector3f{-FLT_MAX,-FLT_MAX,-FLT_MAX }
|
pod::Vector3f{-FLT_MAX,-FLT_MAX,-FLT_MAX }
|
||||||
});
|
});
|
||||||
@ -325,24 +345,43 @@ uf::stl::vector<pod::OBB> uf::graph::obbFromSkin( const pod::Graph& graph, const
|
|||||||
auto joints = uf::mesh::fetchVertexAttribute<pod::Vector4us>( view, jointsView, i );
|
auto joints = uf::mesh::fetchVertexAttribute<pod::Vector4us>( view, jointsView, i );
|
||||||
auto weights = uf::mesh::fetchVertexAttribute<pod::Vector4f>( view, weightView, i );
|
auto weights = uf::mesh::fetchVertexAttribute<pod::Vector4f>( view, weightView, i );
|
||||||
|
|
||||||
|
int bestW = -1;
|
||||||
|
float maxWeight = 0.0f;
|
||||||
for ( auto w = 0; w < 4; ++w ) {
|
for ( auto w = 0; w < 4; ++w ) {
|
||||||
if ( weights[w] <= wThresold ) continue;
|
if ( weights[w] > maxWeight ) {
|
||||||
uint16_t jointID = joints[w];
|
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 );
|
pod::Vector3f localPos = uf::matrix::multiply( skin.inverseBindMatrices[jointID], pos );
|
||||||
|
|
||||||
bounds[jointID].center = uf::vector::min( bounds[jointID].center, localPos );
|
aabbs[jointID].min = uf::vector::min( aabbs[jointID].min, localPos );
|
||||||
bounds[jointID].extent = uf::vector::max( bounds[jointID].extent, localPos );
|
aabbs[jointID].max = uf::vector::max( aabbs[jointID].max, localPos );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert from min-max to center-extent
|
uf::stl::vector<pod::OBB> bounds(skin.joints.size());
|
||||||
for ( auto& box : bounds ) {
|
for ( auto i = 0; i < skin.joints.size(); ++i ) {
|
||||||
auto extent = (box.extent - box.center) * 0.5f;
|
auto& aabb = aabbs[i];
|
||||||
auto center = (box.extent + box.center) * 0.5f;
|
bounds[i] = pod::OBB{
|
||||||
box = pod::OBB{ center, extent };
|
.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;
|
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 ) {
|
for ( auto i = 0; i < skin.joints.size(); ++i ) {
|
||||||
auto nodeID = skin.joints[i];
|
auto nodeID = skin.joints[i];
|
||||||
auto& node = graph.nodes[nodeID];
|
auto& node = graph.nodes[nodeID];
|
||||||
if ( node.parent < 0 ) continue;
|
if ( node.parent < 0 ) continue; // root node, skip
|
||||||
auto& entity = *node.entity;
|
auto& entity = *node.entity;
|
||||||
auto transform = uf::transform::flatten( entity.getComponent<pod::Transform<>>() );
|
auto transform = uf::transform::flatten( entity.getComponent<pod::Transform<>>() );
|
||||||
|
// 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];
|
// skip leaf bones if they aren't used in the mesh
|
||||||
auto& obb = bounds[i];
|
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 boneCenter = uf::transform::apply( armatureTransform, (bone.end + bone.start) * 0.5f );
|
auto shapeType = pod::ShapeType::CAPSULE; // default to capsules
|
||||||
auto offset = uf::transform::applyInverse( transform, boneCenter );
|
// transform bone into world space
|
||||||
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;
|
|
||||||
bone.start = uf::transform::apply( armatureTransform, bone.start );
|
bone.start = uf::transform::apply( armatureTransform, bone.start );
|
||||||
bone.end = uf::transform::apply( armatureTransform, bone.end );
|
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 start = uf::transform::applyInverse( transform, bone.start );
|
||||||
auto end = uf::transform::applyInverse( transform, bone.end );
|
auto end = uf::transform::applyInverse( transform, bone.end );
|
||||||
float length = uf::vector::distance( bone.start, bone.end );
|
auto dir = uf::vector::normalize( end - start );
|
||||||
auto offset = ( start + end ) * 0.5f;
|
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();
|
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 );
|
auto& body = uf::physics::create( entity, mass, offset, orientation );
|
||||||
bodies[nodeID] = &body;
|
bodies[nodeID] = &body;
|
||||||
|
|
||||||
|
|
||||||
// "root" bone will try and parent to local origin
|
// "root" bone will try and parent to local origin
|
||||||
/*
|
/*
|
||||||
if ( !isJoint[node.parent] ) {
|
if ( !isJoint[node.parent] ) {
|
||||||
targetShape = pod::ShapeType::SPHERE;
|
|
||||||
// mark it as non-colliding
|
// mark it as non-colliding
|
||||||
uf::physics::setColliderCategory( body, pod::Collider::CATEGORY_NONE );
|
uf::physics::setColliderCategory( body, pod::Collider::CATEGORY_NONE );
|
||||||
// make it heavier
|
// 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: {
|
case pod::ShapeType::CAPSULE: {
|
||||||
auto up = pod::Vector3f{0, 1, 0};
|
float height = length - (thickness * 2); // subtract end-caps
|
||||||
auto dir = uf::vector::normalize( end - start );
|
uf::physics::initialize( body, pod::Capsule{ thickness, up * height * 0.5f } );
|
||||||
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 } );
|
|
||||||
} break;
|
} break;
|
||||||
case pod::ShapeType::AABB:
|
case pod::ShapeType::AABB:
|
||||||
case pod::ShapeType::OBB: {
|
case pod::ShapeType::OBB: {
|
||||||
uf::physics::initialize( body, pod::OBB{ pod::Vector3f{}, obb.extent * armatureTransform.scale } );
|
uf::physics::initialize( body, obb );
|
||||||
} break;
|
} break;
|
||||||
// should probably add a NONE shape
|
// should probably add a NONE shape
|
||||||
default:
|
default:
|
||||||
|
|||||||
@ -148,8 +148,11 @@ void uf::ObjectBehavior::initialize( uf::Object& self ) {
|
|||||||
offset = center;
|
offset = center;
|
||||||
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 } );
|
uf::physics::initialize( body, pod::OBB{ .center = center, .extent = extent } );
|
||||||
|
#endif
|
||||||
} else if ( type == "aabb" ) {
|
} else if ( type == "aabb" ) {
|
||||||
pod::Vector3f min = uf::vector::decode( metadataJsonPhysics["min"], pod::Vector3f{-0.5f, -0.5f, -0.5f} );
|
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} );
|
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 } );
|
uf::physics::initialize( body, pod::Sphere{ radius } );
|
||||||
} else if ( type == "capsule" ) {
|
} else if ( type == "capsule" ) {
|
||||||
float radius = metadataJsonPhysics["radius"].as<float>();
|
float radius = metadataJsonPhysics["radius"].as<float>();
|
||||||
float halfHeight = metadataJsonPhysics["height"].as<float>() * 0.5f;
|
auto up = uf::vector::decode( metadataJsonPhysics["up"], pod::Vector3f{0,1,0} );
|
||||||
|
if ( metadataJsonPhysics["height"].is<float>() ) {
|
||||||
|
up *= metadataJsonPhysics["height"].as<float>() * 0.5f;
|
||||||
|
}
|
||||||
|
|
||||||
uf::physics::initialize( body, pod::Capsule{ radius, halfHeight } );
|
uf::physics::initialize( body, pod::Capsule{ radius, up } );
|
||||||
} else if ( type == "mesh" ) {
|
} else if ( type == "mesh" ) {
|
||||||
// ...
|
// ...
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -73,28 +73,33 @@ void uf::GraphBehavior::tick( uf::Object& self ) {
|
|||||||
auto& graph = this->getComponent<pod::Graph>();
|
auto& graph = this->getComponent<pod::Graph>();
|
||||||
if ( !graph.metadata["debug"]["draw"]["armature"].as<bool>(false) ) return;
|
if ( !graph.metadata["debug"]["draw"]["armature"].as<bool>(false) ) return;
|
||||||
auto& transform = this->getComponent<pod::Transform<>>();
|
auto& transform = this->getComponent<pod::Transform<>>();
|
||||||
|
auto& scene = uf::scene::getCurrentScene();
|
||||||
|
auto& storage = uf::graph::globalStorage ? uf::graph::storage : scene.getComponent<pod::Graph::Storage>();
|
||||||
for ( auto& node : graph.nodes ) {
|
for ( auto& node : graph.nodes ) {
|
||||||
if ( node.skin < 0 || node.mesh < 0 ) continue;
|
if ( node.skin < 0 || node.mesh < 0 ) continue;
|
||||||
auto bones = uf::graph::collectBones( graph, node );
|
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.start = uf::transform::apply( transform, bone.start );
|
||||||
bone.end = uf::transform::apply( transform, bone.end );
|
bone.end = uf::transform::apply( transform, bone.end );
|
||||||
|
|
||||||
uf::debug::drawLine( bone.start, bone.end, pod::Vector4f{ 0, 1, 0, 1 } );
|
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;
|
uf::debug::drawShape( obb, transform );
|
||||||
if ( hid ) return;
|
}
|
||||||
hid = true;
|
*/
|
||||||
this->process([&](uf::Entity* entity){
|
}
|
||||||
if ( !entity->hasComponent<uf::Graphic>() ) return;
|
|
||||||
auto& graphic = entity->getComponent<uf::Graphic>();
|
|
||||||
if ( !graphic.initialized ) return;
|
|
||||||
auto& descriptorSet = graphic.getDescriptorSet();
|
|
||||||
descriptorSet.metadata.process = false;
|
|
||||||
uf::renderer::states::rebuild = true;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
void uf::GraphBehavior::render( uf::Object& self ) {}
|
void uf::GraphBehavior::render( uf::Object& self ) {}
|
||||||
void uf::GraphBehavior::Metadata::serialize( uf::Object& self, uf::Serializer& serializer ) {}
|
void uf::GraphBehavior::Metadata::serialize( uf::Object& self, uf::Serializer& serializer ) {}
|
||||||
|
|||||||
@ -99,11 +99,13 @@ namespace {
|
|||||||
} else {
|
} else {
|
||||||
transform.scale = { 1, 1, 1 };
|
transform.scale = { 1, 1, 1 };
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
if ( node.matrix.size() == 16 ) {
|
if ( node.matrix.size() == 16 ) {
|
||||||
for ( size_t i = 0; i < node.matrix.size(); ++i ) transform.model[i] = node.matrix[i];
|
for ( size_t i = 0; i < node.matrix.size(); ++i ) transform.model[i] = node.matrix[i];
|
||||||
} else {
|
} else {
|
||||||
transform.model = uf::matrix::identity();
|
transform.model = uf::matrix::identity();
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
if ( 0 <= parentIndex && parentIndex < graph.nodes.size() && nodeIndex != parentIndex ) {
|
if ( 0 <= parentIndex && parentIndex < graph.nodes.size() && nodeIndex != parentIndex ) {
|
||||||
transform.reference = &graph.nodes[parentIndex].transform;
|
transform.reference = &graph.nodes[parentIndex].transform;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -139,12 +139,18 @@ UF_LUA_REGISTER_USERTYPE_AND_COMPONENT(pod::OBB,
|
|||||||
[]( pod::OBB& self, const pod::OBB& copy ) {
|
[]( pod::OBB& self, const pod::OBB& copy ) {
|
||||||
return self = copy;
|
return self = copy;
|
||||||
},
|
},
|
||||||
[]( pod::OBB& self, const pod::Vector3f& center, const pod::Vector3f& extent ) {
|
#if OBB_EXTENT_CENTER
|
||||||
return self = pod::OBB{ center, extent };
|
[]( 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,
|
UF_LUA_REGISTER_USERTYPE_AND_COMPONENT(pod::Sphere,
|
||||||
sol::call_constructor, sol::initializers(
|
sol::call_constructor, sol::initializers(
|
||||||
@ -168,12 +174,13 @@ UF_LUA_REGISTER_USERTYPE_AND_COMPONENT(pod::Capsule,
|
|||||||
[]( pod::Capsule& self, const pod::Capsule& copy ) {
|
[]( pod::Capsule& self, const pod::Capsule& copy ) {
|
||||||
return self = copy;
|
return self = copy;
|
||||||
},
|
},
|
||||||
[]( pod::Capsule& self, float radius, float height ) {
|
[]( pod::Capsule& self, float radius, pod::Vector3f up ) {
|
||||||
return self = pod::Capsule{ radius, height * 0.5f };
|
//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::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,
|
UF_LUA_REGISTER_USERTYPE_AND_COMPONENT(pod::Plane,
|
||||||
sol::call_constructor, sol::initializers(
|
sol::call_constructor, sol::initializers(
|
||||||
@ -184,7 +191,7 @@ UF_LUA_REGISTER_USERTYPE_AND_COMPONENT(pod::Plane,
|
|||||||
return self = copy;
|
return self = copy;
|
||||||
},
|
},
|
||||||
[]( pod::Plane& self, const pod::Vector3f& normal, float offset ) {
|
[]( 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),
|
UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Plane::normal),
|
||||||
|
|||||||
@ -28,8 +28,8 @@ namespace binds {
|
|||||||
pod::Transform<> flatten( const pod::Transform<>& t ) {
|
pod::Transform<> flatten( const pod::Transform<>& t ) {
|
||||||
return uf::transform::flatten( t );
|
return uf::transform::flatten( t );
|
||||||
}
|
}
|
||||||
pod::Transform<> reorient( const pod::Transform<>& t ) {
|
pod::Axes axes( const pod::Transform<>& t, sol::optional<pod::Vector3f> at ) {
|
||||||
return uf::transform::reorient( t );
|
return uf::transform::axes( t, at.value_or(pod::Vector3f{}) );
|
||||||
}
|
}
|
||||||
pod::Transform<> getReference( pod::Transform<>& t ) {
|
pod::Transform<> getReference( pod::Transform<>& t ) {
|
||||||
return t.reference ? *t.reference : 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<bool> reorient ) {
|
pod::Transform<>& reference( pod::Transform<>& transform, const pod::Transform<>& parent, sol::optional<bool> reorient ) {
|
||||||
return uf::transform::reference( transform, parent, reorient.value_or(true) );
|
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<bool> reorient ) {
|
pod::Transform<> interpolate( const pod::Transform<>& from, const pod::Transform<>& to, float factor ) {
|
||||||
return uf::transform::interpolate( from, to, factor, reorient.value_or(true) );
|
return uf::transform::interpolate( from, to, factor );
|
||||||
}
|
}
|
||||||
pod::Transform<> inverse(const pod::Transform<>& t) {
|
pod::Transform<> inverse(const pod::Transform<>& t) {
|
||||||
return uf::transform::inverse( t );
|
return uf::transform::inverse( t );
|
||||||
@ -72,19 +72,29 @@ namespace binds {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#include <uf/ext/lua/component.h>
|
#include <uf/ext/lua/component.h>
|
||||||
|
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_AND_COMPONENT(pod::Transform<>,
|
||||||
UF_LUA_REGISTER_USERTYPE_MEMBER(pod::Transform<>::position),
|
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<>::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(move, UF_LUA_C_FUN(::binds::move) ),
|
||||||
UF_LUA_REGISTER_USERTYPE_DEFINE(rotate, UF_LUA_C_FUN(::binds::rotate)),
|
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(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(getReference, UF_LUA_C_FUN(::binds::getReference)),
|
||||||
UF_LUA_REGISTER_USERTYPE_DEFINE(setReference, UF_LUA_C_FUN(::binds::setReference)),
|
UF_LUA_REGISTER_USERTYPE_DEFINE(setReference, UF_LUA_C_FUN(::binds::setReference)),
|
||||||
UF_LUA_REGISTER_USERTYPE_DEFINE(unreference, UF_LUA_C_FUN(::binds::unreference)),
|
UF_LUA_REGISTER_USERTYPE_DEFINE(unreference, UF_LUA_C_FUN(::binds::unreference)),
|
||||||
|
|||||||
@ -210,8 +210,9 @@ void ext::al::close( uf::audio::Metadata& metadata ) {
|
|||||||
|
|
||||||
void ext::al::listener( const pod::Transform<>& transform ) {
|
void ext::al::listener( const pod::Transform<>& transform ) {
|
||||||
if ( uf::audio::muted ) return;
|
if ( uf::audio::muted ) return;
|
||||||
|
auto axes = uf::transform::axes( transform );
|
||||||
float o[6] = { transform.forward.x, transform.forward.y, transform.forward.z, transform.up.x, transform.up.y, transform.up.z };
|
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_POSITION, transform.position.x, transform.position.y, transform.position.z ));
|
||||||
AL_CHECK_RESULT(alListener3f( AL_VELOCITY, 0, 0, 0 ));
|
AL_CHECK_RESULT(alListener3f( AL_VELOCITY, 0, 0, 0 ));
|
||||||
AL_CHECK_RESULT(alListenerfv( AL_ORIENTATION, &o[0] ));
|
AL_CHECK_RESULT(alListenerfv( AL_ORIENTATION, &o[0] ));
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <uf/engine/scene/scene.h>
|
#include <uf/engine/scene/scene.h>
|
||||||
#include <uf/engine/graph/graph.h>
|
#include <uf/engine/graph/graph.h>
|
||||||
|
#include <uf/utils/math/physics.h>
|
||||||
|
|
||||||
namespace impl {
|
namespace impl {
|
||||||
struct Vertex {
|
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{ start, color } );
|
||||||
impl::lines.emplace_back( impl::Vertex{ end, 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] = {
|
pod::Vector3f corners[8] = {
|
||||||
{aabb.min.x, aabb.min.y, aabb.min.z}, {aabb.max.x, aabb.min.y, aabb.min.z},
|
{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.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[0], corners[4] ); uf::debug::drawLine( corners[1], corners[5] );
|
||||||
uf::debug::drawLine( corners[2], corners[6] ); uf::debug::drawLine( corners[3], corners[7] );
|
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{
|
auto aabb = pod::AABB{
|
||||||
.min = obb.center - obb.extent,
|
.min = obb.center - obb.extent,
|
||||||
.max = 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] );
|
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 int segments = 16;
|
||||||
const float angleIncrement = (2.0f * M_PI) / segments;
|
const float angleIncrement = (2.0f * M_PI) / segments;
|
||||||
for ( auto i = 0; i < segments; ++i ) {
|
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 );
|
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::drawShape( const pod::Capsule& capsule, const pod::Transform<>& transform ) {
|
||||||
void uf::debug::drawCapsule( pod::Capsule capsule, pod::Transform<> transform ) {
|
const pod::Vector3f up = uf::quaternion::rotate( transform.orientation, capsule.up );
|
||||||
const pod::Vector3f up = uf::quaternion::rotate( transform.orientation, pod::Vector3f{0,1,0} );
|
auto p1 = transform.position + up;
|
||||||
auto p1 = transform.position + up * capsule.halfHeight;
|
auto p2 = transform.position - up;
|
||||||
auto p2 = transform.position - up * capsule.halfHeight;
|
|
||||||
|
|
||||||
const int segments = 16;
|
const int segments = 16;
|
||||||
const float angleIncrement = (2.0f * M_PI) / segments;
|
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 );
|
uf::debug::drawLine( p1 - rz, p2 - rz );
|
||||||
}
|
}
|
||||||
// to-do: properly implement this
|
// 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 right = uf::quaternion::rotate(transform.orientation, pod::Vector3f{1, 0, 0});
|
||||||
pod::Vector3f forward = uf::quaternion::rotate(transform.orientation, pod::Vector3f{0, 0, 1});
|
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( p0, p2 );
|
||||||
uf::debug::drawLine( p1, p3 );
|
uf::debug::drawLine( p1, p3 );
|
||||||
}
|
}
|
||||||
*/
|
void uf::debug::drawShape( const pod::Triangle& tri, const pod::Transform<>& transform ) {
|
||||||
void uf::debug::drawTriangle( pod::Triangle tri, pod::Transform<> transform ) {
|
|
||||||
pod::Vector3f v0 = uf::transform::apply(transform, tri.points[0]);
|
pod::Vector3f v0 = uf::transform::apply(transform, tri.points[0]);
|
||||||
pod::Vector3f v1 = uf::transform::apply(transform, tri.points[1]);
|
pod::Vector3f v1 = uf::transform::apply(transform, tri.points[1]);
|
||||||
pod::Vector3f v2 = uf::transform::apply(transform, tri.points[2]);
|
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;
|
graphic.material.device = &uf::renderer::device;
|
||||||
|
|
||||||
// to-do: bin by descriptor instead of one global set
|
// 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.depth.write = false;
|
||||||
graphic.descriptor.renderTarget = 1; // "forward";
|
graphic.descriptor.renderTarget = 1; // "forward";
|
||||||
graphic.descriptor.topology = uf::renderer::enums::PrimitiveTopology::LINE_LIST;
|
graphic.descriptor.topology = uf::renderer::enums::PrimitiveTopology::LINE_LIST;
|
||||||
|
|||||||
@ -612,10 +612,17 @@ pod::Vector3f impl::obbMax( const pod::OBB& obb ) {
|
|||||||
}
|
}
|
||||||
// converts a min-max AABB to center-extents OBB
|
// converts a min-max AABB to center-extents OBB
|
||||||
pod::OBB impl::aabbToObb( const pod::AABB& aabb ) {
|
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{
|
return pod::OBB{
|
||||||
.center = impl::aabbCenter( aabb ),
|
.center = impl::aabbCenter( aabb ),
|
||||||
.extent = impl::aabbExtent( aabb ),
|
.extent = impl::aabbExtent( aabb ),
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
// converts a center-extents OBB to min-max AABB
|
// converts a center-extents OBB to min-max AABB
|
||||||
pod::AABB impl::obbToAabb( const pod::OBB& obb ) {
|
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];
|
pod::Vector3f axes[3];
|
||||||
impl::boxAxes( axes, transform );
|
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 );
|
pod::Vector3f extent = impl::extentFromAxes( box, axes );
|
||||||
|
|
||||||
return { center - extent, center + extent };
|
return { center - extent, center + extent };
|
||||||
@ -664,11 +671,11 @@ pod::AABB impl::transformAabbToWorld( const pod::AABB& aabb, const pod::Transfor
|
|||||||
std::pair<pod::Vector3f, pod::Vector3f> impl::getCapsuleSegment( const pod::PhysicsBody& body ) {
|
std::pair<pod::Vector3f, pod::Vector3f> impl::getCapsuleSegment( const pod::PhysicsBody& body ) {
|
||||||
const auto transform = impl::getTransform( body );
|
const auto transform = impl::getTransform( body );
|
||||||
const auto& capsule = body.collider.capsule;
|
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)
|
// segment defines the cylinder axis only (ignore spherical ends)
|
||||||
auto p1 = transform.position + up * capsule.halfHeight;
|
auto p1 = transform.position + up;
|
||||||
auto p2 = transform.position - up * capsule.halfHeight;
|
auto p2 = transform.position - up;
|
||||||
return { p1, p2 };
|
return { p1, p2 };
|
||||||
}
|
}
|
||||||
// computes the AABB for a given body
|
// computes the AABB for a given body
|
||||||
|
|||||||
@ -14,11 +14,8 @@ void impl::solveBallSocketConstraint( pod::Constraint& constraint, float dt ) {
|
|||||||
auto tA = impl::getTransform( a );
|
auto tA = impl::getTransform( a );
|
||||||
auto tB = impl::getTransform( b );
|
auto tB = impl::getTransform( b );
|
||||||
|
|
||||||
auto anchorA = joint.localAnchorA * tA.scale;
|
auto rA = uf::quaternion::rotate( tA.orientation, joint.localAnchorA * tA.scale );
|
||||||
auto anchorB = joint.localAnchorB * tB.scale;
|
auto rB = uf::quaternion::rotate( tB.orientation, joint.localAnchorB * tB.scale );
|
||||||
|
|
||||||
auto rA = uf::quaternion::rotate( tA.orientation, anchorA );
|
|
||||||
auto rB = uf::quaternion::rotate( tB.orientation, anchorB );
|
|
||||||
|
|
||||||
pod::Matrix3f K = {};
|
pod::Matrix3f K = {};
|
||||||
pod::Vector3f axes[3] = { {1,0,0}, {0,1,0}, {0,0,1} };
|
pod::Vector3f axes[3] = { {1,0,0}, {0,1,0}, {0,0,1} };
|
||||||
|
|||||||
@ -11,11 +11,8 @@ void impl::solveDistanceConstraint( pod::Constraint& constraint, float dt ) {
|
|||||||
auto tA = impl::getTransform( a );
|
auto tA = impl::getTransform( a );
|
||||||
auto tB = impl::getTransform( b );
|
auto tB = impl::getTransform( b );
|
||||||
|
|
||||||
auto anchorA = joint.localAnchorA * tA.scale;
|
auto rA = uf::quaternion::rotate( tA.orientation, joint.localAnchorA * tA.scale );
|
||||||
auto anchorB = joint.localAnchorB * tB.scale;
|
auto rB = uf::quaternion::rotate( tB.orientation, joint.localAnchorB * tB.scale );
|
||||||
|
|
||||||
auto rA = uf::quaternion::rotate( tA.orientation, anchorA );
|
|
||||||
auto rB = uf::quaternion::rotate( tB.orientation, anchorB );
|
|
||||||
|
|
||||||
auto pA = tA.position + rA;
|
auto pA = tA.position + rA;
|
||||||
auto pB = tB.position + rB;
|
auto pB = tB.position + rB;
|
||||||
|
|||||||
@ -12,11 +12,8 @@ void impl::solveSliderConstraint( pod::Constraint& constraint, float dt ) {
|
|||||||
auto tA = impl::getTransform( a );
|
auto tA = impl::getTransform( a );
|
||||||
auto tB = impl::getTransform( b );
|
auto tB = impl::getTransform( b );
|
||||||
|
|
||||||
auto anchorA = joint.localAnchorA * tA.scale;
|
auto rA = uf::quaternion::rotate( tA.orientation, joint.localAnchorA * tA.scale );
|
||||||
auto anchorB = joint.localAnchorB * tB.scale;
|
auto rB = uf::quaternion::rotate( tB.orientation, joint.localAnchorB * tB.scale );
|
||||||
|
|
||||||
auto rA = uf::quaternion::rotate( tA.orientation, anchorA );
|
|
||||||
auto rB = uf::quaternion::rotate( tB.orientation, anchorB );
|
|
||||||
|
|
||||||
auto pA = tA.position + rA;
|
auto pA = tA.position + rA;
|
||||||
auto pB = tB.position + rB;
|
auto pB = tB.position + rB;
|
||||||
|
|||||||
@ -11,11 +11,8 @@ void impl::solveSpringConstraint( pod::Constraint& constraint, float dt ) {
|
|||||||
auto tA = impl::getTransform( a );
|
auto tA = impl::getTransform( a );
|
||||||
auto tB = impl::getTransform( b );
|
auto tB = impl::getTransform( b );
|
||||||
|
|
||||||
auto anchorA = joint.localAnchorA * tA.scale;
|
auto rA = uf::quaternion::rotate( tA.orientation, joint.localAnchorA * tA.scale );
|
||||||
auto anchorB = joint.localAnchorB * tB.scale;
|
auto rB = uf::quaternion::rotate( tB.orientation, joint.localAnchorB * tB.scale );
|
||||||
|
|
||||||
auto rA = uf::quaternion::rotate( tA.orientation, anchorA );
|
|
||||||
auto rB = uf::quaternion::rotate( tB.orientation, anchorB );
|
|
||||||
|
|
||||||
auto worldAnchorA = tA.position + rA;
|
auto worldAnchorA = tA.position + rA;
|
||||||
auto worldAnchorB = tB.position + rB;
|
auto worldAnchorB = tB.position + rB;
|
||||||
|
|||||||
@ -377,7 +377,7 @@ void uf::physics::updateInertia( pod::PhysicsBody& body ) {
|
|||||||
} break;
|
} break;
|
||||||
case pod::ShapeType::CAPSULE: {
|
case pod::ShapeType::CAPSULE: {
|
||||||
float r = body.collider.capsule.radius;
|
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 Ixx = 0.25f * mass * r * r + (1.0f/12.0f) * mass * h * h;
|
||||||
float Iyy = 0.5f * mass * r * r;
|
float Iyy = 0.5f * mass * r * r;
|
||||||
|
|||||||
@ -81,7 +81,25 @@ bool impl::aabbHull( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::
|
|||||||
void impl::drawAabb( const pod::PhysicsBody& body ) {
|
void impl::drawAabb( const pod::PhysicsBody& body ) {
|
||||||
const auto& aabb = body.bounds;
|
const auto& aabb = body.bounds;
|
||||||
auto transform = impl::getTransform( body );
|
auto transform = impl::getTransform( body );
|
||||||
|
#if 0
|
||||||
uf::debug::drawAabb( aabb, transform );
|
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 ) {
|
pod::PhysicsBody& uf::physics::initialize( pod::PhysicsBody& body, const pod::AABB& aabb ) {
|
||||||
|
|||||||
@ -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;
|
outPoly[0] = transform.position + uf::vector::normalize( dir ) * body.collider.sphere.radius;
|
||||||
} break;
|
} break;
|
||||||
case pod::ShapeType::CAPSULE: {
|
case pod::ShapeType::CAPSULE: {
|
||||||
auto up = uf::quaternion::rotate( transform.orientation, pod::Vector3f{0,1,0} );
|
auto up = uf::quaternion::rotate( transform.orientation, body.collider.capsule.up );
|
||||||
auto p1 = transform.position + up * body.collider.capsule.halfHeight;
|
auto p1 = transform.position + up;
|
||||||
auto p2 = transform.position - up * body.collider.capsule.halfHeight;
|
auto p2 = transform.position - up;
|
||||||
|
|
||||||
if ( std::fabs( uf::vector::dot( dir, up ) ) < 0.01f ) {
|
if ( std::fabs( uf::vector::dot( dir, up ) ) < 0.01f ) {
|
||||||
outCount = 2;
|
outCount = 2;
|
||||||
|
|||||||
@ -37,9 +37,9 @@ pod::Vector3f impl::support( const pod::PhysicsBody& body, const pod::Vector3f&
|
|||||||
return basePoint + tangent * 100000.0f;
|
return basePoint + tangent * 100000.0f;
|
||||||
} break;
|
} break;
|
||||||
case pod::ShapeType::CAPSULE: {
|
case pod::ShapeType::CAPSULE: {
|
||||||
auto up = uf::quaternion::rotate( transform.orientation, pod::Vector3f{0,1,0} );
|
auto up = uf::quaternion::rotate( transform.orientation, body.collider.capsule.up );
|
||||||
auto p1 = transform.position + up * body.collider.capsule.halfHeight;
|
auto p1 = transform.position + up;
|
||||||
auto p2 = transform.position - up * body.collider.capsule.halfHeight;
|
auto p2 = transform.position - up;
|
||||||
auto end = ( uf::vector::dot( dir, p1 ) > uf::vector::dot( dir, p2 ) ) ? p1 : p2; // get closest end
|
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;
|
return end + uf::vector::normalize( dir ) * body.collider.capsule.radius;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -92,6 +92,16 @@ void impl::drawHull( const pod::PhysicsBody& body ) {
|
|||||||
|
|
||||||
for ( size_t i = 0; i < totalTriangles; ++i ) {
|
for ( size_t i = 0; i < totalTriangles; ++i ) {
|
||||||
auto tri = uf::mesh::fetchTriangle( *meshData, i );
|
auto tri = uf::mesh::fetchTriangle( *meshData, i );
|
||||||
|
#if 0
|
||||||
uf::debug::drawTriangle( tri, transform );
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -200,7 +200,17 @@ void impl::drawMesh( const pod::PhysicsBody& body ) {
|
|||||||
|
|
||||||
for ( size_t i = 0; i < totalTriangles; ++i ) {
|
for ( size_t i = 0; i < totalTriangles; ++i ) {
|
||||||
auto tri = uf::mesh::fetchTriangle( *meshData, i );
|
auto tri = uf::mesh::fetchTriangle( *meshData, i );
|
||||||
|
#if 0
|
||||||
uf::debug::drawTriangle( tri, transform );
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -129,8 +129,8 @@ bool impl::obbObb( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Ma
|
|||||||
auto boxA = a.collider.obb;
|
auto boxA = a.collider.obb;
|
||||||
auto boxB = b.collider.obb;
|
auto boxB = b.collider.obb;
|
||||||
|
|
||||||
boxA.center = uf::quaternion::rotate(tA.orientation, boxA.center) + tA.position;
|
boxA.center = uf::transform::apply( tA, boxA.center );
|
||||||
boxB.center = uf::quaternion::rotate(tB.orientation, boxB.center) + tB.position;
|
boxB.center = uf::transform::apply( tB, boxB.center );
|
||||||
|
|
||||||
pod::Vector3f axesA[3];
|
pod::Vector3f axesA[3];
|
||||||
pod::Vector3f axesB[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 boxA = a.collider.obb;
|
||||||
auto boxB = impl::aabbToObb( b.bounds );
|
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 axesA[3];
|
||||||
pod::Vector3f axesB[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 tA = impl::getTransform( a );
|
||||||
auto box = a.collider.obb;
|
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 );
|
auto sphereCenter = impl::getPosition( b );
|
||||||
float radius = b.collider.sphere.radius;
|
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 tA = impl::getTransform( a );
|
||||||
auto box = a.collider.obb;
|
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];
|
pod::Vector3f axesA[3];
|
||||||
impl::boxAxes( axesA, tA );
|
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 tA = impl::getTransform( a );
|
||||||
auto box = a.collider.obb;
|
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];
|
pod::Vector3f axesA[3];
|
||||||
impl::boxAxes( axesA, tA );
|
impl::boxAxes( axesA, tA );
|
||||||
|
|
||||||
auto [p1, p2] = impl::getCapsuleSegment( b );
|
auto [p1, p2] = impl::getCapsuleSegment( b );
|
||||||
|
|
||||||
pod::Vector3f cB = (p1 + p2) * 0.5f;
|
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 radius = b.collider.capsule.radius;
|
||||||
|
|
||||||
float minOverlap = FLT_MAX;
|
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 pA = uf::vector::dot(box.center, n);
|
||||||
float rA = impl::projectExtents( box, n, axesA );
|
float rA = impl::projectExtents( box, n, axesA );
|
||||||
float pB = uf::vector::dot(cB, n);
|
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 dist = std::fabs(pB - pA);
|
||||||
float overlap = (rA + rB) - dist;
|
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 ) {
|
void impl::drawObb( const pod::PhysicsBody& body ) {
|
||||||
const auto& obb = body.collider.obb;
|
const auto& obb = body.collider.obb;
|
||||||
auto transform = impl::getTransform(body);
|
auto transform = impl::getTransform(body);
|
||||||
|
#if 0
|
||||||
uf::debug::drawObb( obb, transform );
|
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 ) {
|
pod::PhysicsBody& uf::physics::initialize( pod::PhysicsBody& body, const pod::OBB& obb ) {
|
||||||
|
|||||||
@ -326,6 +326,7 @@ pod::RayQuery uf::physics::rayCast( const pod::Ray& ray, const pod::World& world
|
|||||||
impl::queryBVH( dynamicBvh, ray, candidates );
|
impl::queryBVH( dynamicBvh, ray, candidates );
|
||||||
if ( uf::physics::settings.useSplitBvhs ) impl::queryBVH( staticBvh, ray, candidates );
|
if ( uf::physics::settings.useSplitBvhs ) impl::queryBVH( staticBvh, ray, candidates );
|
||||||
|
|
||||||
|
|
||||||
for ( auto i : candidates ) {
|
for ( auto i : candidates ) {
|
||||||
auto* b = bodies[i];
|
auto* b = bodies[i];
|
||||||
|
|
||||||
|
|||||||
@ -71,7 +71,34 @@ bool impl::sphereHull( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod
|
|||||||
void impl::drawSphere( const pod::PhysicsBody& body ) {
|
void impl::drawSphere( const pod::PhysicsBody& body ) {
|
||||||
const auto& sphere = body.collider.sphere;
|
const auto& sphere = body.collider.sphere;
|
||||||
auto transform = impl::getTransform(body);
|
auto transform = impl::getTransform(body);
|
||||||
|
#if 0
|
||||||
uf::debug::drawSphere( sphere, transform );
|
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 ) {
|
pod::PhysicsBody& uf::physics::initialize( pod::PhysicsBody& body, const pod::Sphere& sphere ) {
|
||||||
|
|||||||
@ -190,7 +190,7 @@ bool impl::triangleObb( const pod::TriangleWithNormal& tri, const pod::PhysicsBo
|
|||||||
|
|
||||||
auto transform = impl::getTransform( body );
|
auto transform = impl::getTransform( body );
|
||||||
auto box = body.collider.obb;
|
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];
|
pod::Vector3f axes[3];
|
||||||
impl::boxAxes( axes, transform );
|
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 ) {
|
void impl::drawTriangle( const pod::PhysicsBody& body ) {
|
||||||
const auto& tri = body.collider.triangle;
|
const auto& tri = body.collider.triangle;
|
||||||
auto transform = impl::getTransform(body);
|
auto transform = impl::getTransform(body);
|
||||||
|
#if 0
|
||||||
uf::debug::drawTriangle( tri, transform );
|
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 ) {
|
pod::PhysicsBody& uf::physics::initialize( pod::PhysicsBody& body, const pod::TriangleWithNormal& tri ) {
|
||||||
|
|||||||
@ -21,8 +21,8 @@ void impl::solvePositions( uf::stl::vector<pod::Manifold>& manifolds, float dt,
|
|||||||
auto ctxA = impl::solverBodyContext( a );
|
auto ctxA = impl::solverBodyContext( a );
|
||||||
auto ctxB = impl::solverBodyContext( b );
|
auto ctxB = impl::solverBodyContext( b );
|
||||||
|
|
||||||
auto rA = uf::quaternion::rotate( tA.orientation, c.localA );
|
auto rA = uf::quaternion::rotate( tA.orientation, c.localA * tA.scale );
|
||||||
auto rB = uf::quaternion::rotate( tB.orientation, c.localB );
|
auto rB = uf::quaternion::rotate( tB.orientation, c.localB * tB.scale );
|
||||||
|
|
||||||
auto pA = tA.position + rA;
|
auto pA = tA.position + rA;
|
||||||
auto pB = tB.position + rB;
|
auto pB = tB.position + rB;
|
||||||
|
|||||||
@ -172,8 +172,8 @@ TEST(SpherePlane_NoCollision, {
|
|||||||
TEST(CapsuleCapsule_Collision, {
|
TEST(CapsuleCapsule_Collision, {
|
||||||
pod::World world;
|
pod::World world;
|
||||||
uf::Object objA, objB;
|
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::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};
|
bodyA.transform->position = {0,0,0};
|
||||||
bodyB.transform->position = {0.8f,0,0}; // slight overlap
|
bodyB.transform->position = {0.8f,0,0}; // slight overlap
|
||||||
@ -384,7 +384,7 @@ TEST(PhysicsStep_StaticFriction_Slips, {
|
|||||||
TEST(CapsulePlane_Slope_StaticHold, {
|
TEST(CapsulePlane_Slope_StaticHold, {
|
||||||
pod::World world;
|
pod::World world;
|
||||||
uf::Object objA, objB;
|
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);
|
auto& bodyB = uf::physics::create(world, objB, pod::Plane{{0,1,1},0.0f}, 0.0f);
|
||||||
|
|
||||||
// Place capsule on slope
|
// Place capsule on slope
|
||||||
@ -402,7 +402,7 @@ TEST(CapsulePlane_Slope_StaticHold, {
|
|||||||
TEST(CapsulePlane_Slope_Slip, {
|
TEST(CapsulePlane_Slope_Slip, {
|
||||||
pod::World world;
|
pod::World world;
|
||||||
uf::Object objA, objB;
|
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);
|
auto& bodyB = uf::physics::create(world, objB, pod::Plane{{0,1,1},0.0f}, 0.0f);
|
||||||
|
|
||||||
bodyA.transform->position = {0,2,0};
|
bodyA.transform->position = {0,2,0};
|
||||||
@ -417,7 +417,7 @@ TEST(CapsulePlane_Slope_Slip, {
|
|||||||
TEST(CapsulePlane_RestingContact, {
|
TEST(CapsulePlane_RestingContact, {
|
||||||
pod::World world;
|
pod::World world;
|
||||||
uf::Object objA, objB;
|
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);
|
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
|
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;
|
pod::World world;
|
||||||
uf::Object objA, objB;
|
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);
|
auto& bodyB = uf::physics::create(world, objB, pod::AABB{{-5, -1, -5},{5, 0, 5}}, 0.0f);
|
||||||
|
|
||||||
bodyA.transform->position = {0, 1.5f, 0};
|
bodyA.transform->position = {0, 1.5f, 0};
|
||||||
@ -450,7 +450,7 @@ TEST(CapsulePlane_Settling, {
|
|||||||
pod::World world;
|
pod::World world;
|
||||||
uf::Object objA, objB;
|
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);
|
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
|
bodyA.transform->position = {0, 2.0f, 0}; // slightly above
|
||||||
@ -466,7 +466,7 @@ TEST(CapsulePlane_SlopeStaticFriction, {
|
|||||||
pod::World world;
|
pod::World world;
|
||||||
uf::Object objA, objB;
|
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
|
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};
|
bodyA.transform->position = {0, 3.0f, 0};
|
||||||
@ -484,7 +484,7 @@ TEST(CapsuleAabb_StepEdge, {
|
|||||||
pod::World world;
|
pod::World world;
|
||||||
uf::Object objA, objB;
|
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);
|
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
|
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;
|
uf::Object objA, objFloor;
|
||||||
|
|
||||||
// Capsule: radius 0.5, half-height 1.0 (total height 2.0 + end caps)
|
// 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.
|
// Test toggle: try both AABB floors and Plane floors.
|
||||||
bool usePlane = true;
|
bool usePlane = true;
|
||||||
@ -519,7 +519,7 @@ TEST(CapsulePlane_ContactNormal, {
|
|||||||
pod::World world;
|
pod::World world;
|
||||||
uf::Object objA, objB;
|
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);
|
auto& bodyB = uf::physics::create(world, objB, pod::Plane{{0,1,0},0.0f}, 0.0f);
|
||||||
|
|
||||||
bodyA.transform->position = {0,1.5f,0};
|
bodyA.transform->position = {0,1.5f,0};
|
||||||
@ -557,7 +557,7 @@ TEST(AabbPlane_RestingNoSink, {
|
|||||||
TEST(CapsuleSphere_Collision, {
|
TEST(CapsuleSphere_Collision, {
|
||||||
pod::World world;
|
pod::World world;
|
||||||
uf::Object objA, objB;
|
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);
|
auto& bodyB = uf::physics::create(world, objB, pod::Sphere{0.5f}, 1.0f);
|
||||||
|
|
||||||
bodyA.transform->position = {0,0,0};
|
bodyA.transform->position = {0,0,0};
|
||||||
@ -575,7 +575,7 @@ TEST(CapsuleSphere_Collision, {
|
|||||||
TEST(CapsuleSphere_NoCollision, {
|
TEST(CapsuleSphere_NoCollision, {
|
||||||
pod::World world;
|
pod::World world;
|
||||||
uf::Object objA, objB;
|
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);
|
auto& bodyB = uf::physics::create(world, objB, pod::Sphere{0.5f}, 1.0f);
|
||||||
|
|
||||||
bodyA.transform->position = {0,0,0};
|
bodyA.transform->position = {0,0,0};
|
||||||
@ -664,7 +664,7 @@ TEST(AabbCapsule_Collision, {
|
|||||||
pod::World world;
|
pod::World world;
|
||||||
uf::Object objA, objB;
|
uf::Object objA, objB;
|
||||||
auto& bodyA = uf::physics::create(world, objA, pod::AABB{{-1,-1,-1},{1,1,1}}, 1.0f);
|
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};
|
bodyA.transform->position = {0,0,0};
|
||||||
bodyB.transform->position = {0,0.5f,0}; // partially overlapping
|
bodyB.transform->position = {0,0.5f,0}; // partially overlapping
|
||||||
@ -682,7 +682,7 @@ TEST(AabbCapsule_NoCollision, {
|
|||||||
pod::World world;
|
pod::World world;
|
||||||
uf::Object objA, objB;
|
uf::Object objA, objB;
|
||||||
auto& bodyA = uf::physics::create(world, objA, pod::AABB{{-1,-1,-1},{1,1,1}}, 1.0f);
|
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};
|
bodyA.transform->position = {0,0,0};
|
||||||
bodyB.transform->position = {0,5,0};
|
bodyB.transform->position = {0,5,0};
|
||||||
@ -700,7 +700,7 @@ TEST(SphereCapsule_Collision, {
|
|||||||
pod::World world;
|
pod::World world;
|
||||||
uf::Object objA, objB;
|
uf::Object objA, objB;
|
||||||
auto& bodyA = uf::physics::create(world, objA, pod::Sphere{0.5f}, 1.0f);
|
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};
|
bodyA.transform->position = {0,0.0f,0};
|
||||||
bodyB.transform->position = {0,0.25f,0};
|
bodyB.transform->position = {0,0.25f,0};
|
||||||
@ -718,7 +718,7 @@ TEST(SphereCapsule_NoCollision, {
|
|||||||
pod::World world;
|
pod::World world;
|
||||||
uf::Object objA, objB;
|
uf::Object objA, objB;
|
||||||
auto& bodyA = uf::physics::create(world, objA, pod::Sphere{0.5f}, 1.0f);
|
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};
|
bodyA.transform->position = {0,5,0};
|
||||||
bodyB.transform->position = {0,0,0};
|
bodyB.transform->position = {0,0,0};
|
||||||
@ -750,7 +750,7 @@ TEST(PlaneCapsule_Collision, {
|
|||||||
pod::World world;
|
pod::World world;
|
||||||
uf::Object objA, objB;
|
uf::Object objA, objB;
|
||||||
auto& bodyA = uf::physics::create(world, objA, pod::Plane{{0,1,0},0.0f}, 0.0f);
|
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
|
bodyB.transform->position = {0,0.25f,0}; // foot intersecting
|
||||||
|
|
||||||
@ -767,7 +767,7 @@ TEST(PlaneCapsule_NoCollision, {
|
|||||||
pod::World world;
|
pod::World world;
|
||||||
uf::Object objA, objB;
|
uf::Object objA, objB;
|
||||||
auto& bodyA = uf::physics::create(world, objA, pod::Plane{{0,1,0},0.0f}, 0.0f);
|
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
|
bodyB.transform->position = {0,5,0}; // far above
|
||||||
|
|
||||||
@ -1161,7 +1161,7 @@ TEST(TriangleCapsule_Collision_Overlap, {
|
|||||||
// Capsule aligned along Z axis, radius 0.2
|
// Capsule aligned along Z axis, radius 0.2
|
||||||
pod::Capsule capsule;
|
pod::Capsule capsule;
|
||||||
capsule.radius = 0.2f;
|
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
|
// placed so capsule overlaps the tri plane
|
||||||
auto& bodyA = uf::physics::create(world, objA, tri, 0.0f);
|
auto& bodyA = uf::physics::create(world, objA, tri, 0.0f);
|
||||||
auto& bodyB = uf::physics::create(world, objB, capsule, 0.0f);
|
auto& bodyB = uf::physics::create(world, objB, capsule, 0.0f);
|
||||||
@ -1191,7 +1191,7 @@ TEST(TriangleCapsule_Collision_NoOverlap, {
|
|||||||
|
|
||||||
pod::Capsule capsule;
|
pod::Capsule capsule;
|
||||||
capsule.radius = 0.2f;
|
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
|
// place it well above the tri plane
|
||||||
auto& bodyA = uf::physics::create(world, objA, tri, 0.0f);
|
auto& bodyA = uf::physics::create(world, objA, tri, 0.0f);
|
||||||
auto& bodyB = uf::physics::create(world, objB, capsule, 0.0f);
|
auto& bodyB = uf::physics::create(world, objB, capsule, 0.0f);
|
||||||
@ -1216,7 +1216,7 @@ TEST(TriangleCapsule_Collision_Tangent, {
|
|||||||
|
|
||||||
pod::Capsule capsule;
|
pod::Capsule capsule;
|
||||||
capsule.radius = 0.5f;
|
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& bodyA = uf::physics::create(world, objA, tri, 0.0f);
|
||||||
auto& bodyB = uf::physics::create(world, objB, capsule, 0.0f);
|
auto& bodyB = uf::physics::create(world, objB, capsule, 0.0f);
|
||||||
// place the capsule so its sphere-bottom just kisses the triangle
|
// place the capsule so its sphere-bottom just kisses the triangle
|
||||||
@ -1248,7 +1248,7 @@ TEST(TriangleCapsule_Collision_EdgeAlignment, {
|
|||||||
|
|
||||||
pod::Capsule capsule;
|
pod::Capsule capsule;
|
||||||
capsule.radius = 0.1f;
|
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& bodyA = uf::physics::create(world, objA, tri, 0.0f);
|
||||||
auto& bodyB = uf::physics::create(world, objB, capsule, 0.0f);
|
auto& bodyB = uf::physics::create(world, objB, capsule, 0.0f);
|
||||||
// lay the capsule along edge (x-axis direction near tri’s base)
|
// lay the capsule along edge (x-axis direction near tri’s base)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user