an almost perfect ragdoll (has issues when you grab it)
This commit is contained in:
parent
6deb8795c5
commit
eec75781ba
6
bin/data/entities/ragdollLimb.json
Normal file
6
bin/data/entities/ragdollLimb.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "Ragdoll Limb",
|
||||
"metadata": {
|
||||
"holdable": true
|
||||
}
|
||||
}
|
||||
@ -11,6 +11,9 @@ local transform = ent:getComponent("Transform")
|
||||
local physicsBody = ent:getComponent("PhysicsBody")
|
||||
local metadata = ent:getComponent("Metadata")
|
||||
|
||||
|
||||
--transform.scale = Vector3f( 5, 5, 5 )
|
||||
local children = {}
|
||||
local bodies = {
|
||||
torso = { Vector3f(0, 1.0, 0), Vector3f(0.2, 0.3, 0.15), 20.0 },
|
||||
head = { Vector3f(0, 1.6, 0), Vector3f(0.15, 0.15, 0.15), 5.0 },
|
||||
@ -43,22 +46,30 @@ local constraints = {
|
||||
|
||||
for k, _ in pairs( bodies ) do
|
||||
position = bodies[k][1]
|
||||
box = OBB( position, bodies[k][2] )
|
||||
extent = bodies[k][2]
|
||||
mass = bodies[k][3]
|
||||
|
||||
child = ent:loadChild("./ragdollLimb.json", true)
|
||||
childTransform = child:getComponent("Transform")
|
||||
childTransform.position = position
|
||||
childTransform:setReference( transform )
|
||||
|
||||
body = physics.create( ent, mass, Vector3f() )
|
||||
body:asObb( box )
|
||||
body = physics.create( child, mass )
|
||||
body:asObb( OBB( Vector3f(), extent ) )
|
||||
body:setGravity( Vector3f( 0, 0, 0 ) )
|
||||
|
||||
children[k] = child
|
||||
bodies[k] = body
|
||||
end
|
||||
|
||||
for k, _ in pairs( constraints ) do
|
||||
bodyA = bodies[constraints[k][1]]
|
||||
bodyB = bodies[constraints[k][2]]
|
||||
|
||||
joint = constraints[k][3]
|
||||
axis = constraints[k][4]
|
||||
for k, _ in pairs( constraints ) do
|
||||
bodyA = bodies[ constraints[k][1] ]
|
||||
bodyB = bodies[ constraints[k][2] ]
|
||||
|
||||
joint = transform:apply( constraints[k][3] )
|
||||
axis = transform.orientation:rotate( constraints[k][4] )
|
||||
|
||||
swingLimit = constraints[k][5]
|
||||
twistLimit = constraints[k][6]
|
||||
|
||||
|
||||
@ -100,6 +100,8 @@ namespace uf {
|
||||
|
||||
void loadAssets( const uf::Serializer& );
|
||||
|
||||
uf::Entity& createChild( bool = true );
|
||||
|
||||
uf::Entity& loadChild( const uf::Serializer&, bool = true );
|
||||
uf::Entity* loadChildPointer( const uf::Serializer&, bool = true );
|
||||
std::size_t loadChildUid( const uf::Serializer&, bool = true );
|
||||
|
||||
@ -25,6 +25,8 @@ namespace uf {
|
||||
|
||||
void loadAssets( const uf::Serializer& );
|
||||
|
||||
uf::Object& createChild( bool = true );
|
||||
|
||||
uf::Object& loadChild( const uf::Serializer&, bool = true );
|
||||
uf::Object* loadChildPointer( const uf::Serializer&, bool = true );
|
||||
std::size_t loadChildUid( const uf::Serializer&, bool = true );
|
||||
|
||||
@ -444,27 +444,30 @@ bool uf::Object::load( const uf::Serializer& _json ) {
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
uf::Object& uf::Object::createChild( bool initialize ) {
|
||||
auto& entity = uf::instantiator::instantiate("Object");
|
||||
this->addChild( entity );
|
||||
return entity;
|
||||
}
|
||||
|
||||
uf::Object& uf::Object::loadChild( const uf::stl::string& f, bool initialize ) {
|
||||
auto& metadata = this->getComponent<uf::ObjectBehavior::Metadata>();
|
||||
auto& metadataJson = this->getComponent<uf::Serializer>();
|
||||
|
||||
uf::Serializer json;
|
||||
uf::stl::string filename = uf::io::resolveURI( f, metadata.system.root );
|
||||
if ( !json.readFromFile(filename) ) {
|
||||
if ( json.readFromFile(filename) ) {
|
||||
json["source"] = filename;
|
||||
json["root"] = uf::io::directory(filename);
|
||||
json["hot reload"]["mtime"] = uf::io::mtime(filename) + 10;
|
||||
} else {
|
||||
if ( !uf::Object::assertionLoad ) {
|
||||
UF_MSG_ERROR("assertionLoad is unset, loading empty entity");
|
||||
auto& entity = uf::instantiator::instantiate("Object");
|
||||
entity.getComponent<uf::ObjectBehavior::Metadata>().system.invalid = true;
|
||||
this->addChild(entity);
|
||||
} else {
|
||||
UF_EXCEPTION("Failed to load file: {}", filename);
|
||||
}
|
||||
}
|
||||
|
||||
json["source"] = filename;
|
||||
json["root"] = uf::io::directory(filename);
|
||||
json["hot reload"]["mtime"] = uf::io::mtime(filename) + 10;
|
||||
|
||||
return this->loadChild(json, initialize);
|
||||
}
|
||||
uf::Object& uf::Object::loadChild( const uf::Serializer& _json, bool initialize ) {
|
||||
|
||||
@ -93,6 +93,11 @@ namespace binds {
|
||||
static uf::Object null;
|
||||
return null;
|
||||
};
|
||||
uf::Object& create( sol::optional<bool> init ) {
|
||||
auto& entity = uf::instantiator::instantiate("Object");
|
||||
if ( init.value_or(true) ) entity.initialize();
|
||||
return entity;
|
||||
};
|
||||
uf::Object& currentScene() {
|
||||
return uf::scene::getCurrentScene().as<uf::Object>();
|
||||
};
|
||||
@ -157,8 +162,8 @@ namespace binds {
|
||||
double delta(){ return uf::physics::time::delta; };
|
||||
}
|
||||
namespace physics {
|
||||
pod::PhysicsBody& create( uf::Object& object, float mass = 0.0f, const pod::Vector3f& center = {} ) {
|
||||
return uf::physics::create( object, mass, center );
|
||||
pod::PhysicsBody& create( uf::Object& object, sol::optional<float> mass, sol::optional<pod::Vector3f> center ) {
|
||||
return uf::physics::create( object, mass.value_or(0.0f), center.value_or(pod::Vector3f{}) );
|
||||
}
|
||||
}
|
||||
namespace json {
|
||||
@ -228,6 +233,7 @@ void ext::lua::initialize() {
|
||||
{
|
||||
auto entities = state["entities"].get_or_create<sol::table>();
|
||||
entities.set("get", UF_LUA_C_FUN(::binds::entities::get));
|
||||
entities.set("create", UF_LUA_C_FUN(::binds::entities::create));
|
||||
entities.set("currentScene", UF_LUA_C_FUN(::binds::entities::currentScene));
|
||||
entities.set("controller", UF_LUA_C_FUN(::binds::entities::controller));
|
||||
entities.set("destroy", UF_LUA_C_FUN(::binds::entities::destroy));
|
||||
|
||||
@ -40,8 +40,8 @@ namespace binds {
|
||||
self.setProjection(matrix);
|
||||
}
|
||||
}
|
||||
void update( uf::Camera& self, bool force = true ) {
|
||||
self.update(force);
|
||||
void update( uf::Camera& self, sol::optional<bool> force ) {
|
||||
self.update(force.value_or(true));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -121,6 +121,11 @@ namespace binds {
|
||||
if ( type == "Metadata" ) {
|
||||
self.callHook( "object:Serialize.%UID%" );
|
||||
auto& metadata = self.getComponent<uf::Serializer>();
|
||||
if ( !ext::json::isObject( metadata ) ) {
|
||||
sol::table table( ext::lua::state, sol::create );
|
||||
return sol::make_object( ext::lua::state, table );
|
||||
}
|
||||
|
||||
auto decoded = ext::lua::decode( metadata );
|
||||
if ( decoded ) {
|
||||
sol::table table = decoded.value();
|
||||
@ -194,6 +199,9 @@ namespace binds {
|
||||
static uf::Object null;
|
||||
return null;
|
||||
}
|
||||
uf::Object& createChild( uf::Object& self, sol::optional<bool> init ) {
|
||||
return self.createChild( init.value_or( true ) );
|
||||
}
|
||||
uf::Object& addChild( uf::Object& self, uf::Object& child ) {
|
||||
self.addChild( child );
|
||||
return self;
|
||||
@ -202,8 +210,8 @@ namespace binds {
|
||||
self.removeChild( child );
|
||||
return self;
|
||||
}
|
||||
uf::Object& loadChild( uf::Object& self, const uf::stl::string& filename, bool init = true ) {
|
||||
auto* pointer = self.loadChildPointer( filename, init );
|
||||
uf::Object& loadChild( uf::Object& self, sol::optional<uf::stl::string> filename, sol::optional<bool> init ) {
|
||||
auto* pointer = self.loadChildPointer( filename.value_or(""), init.value_or(true) );
|
||||
if ( pointer ) return pointer->as<uf::Object>();
|
||||
static uf::Object null;
|
||||
return null;
|
||||
@ -255,12 +263,12 @@ namespace binds {
|
||||
ext::json::Value payload = uf::Serializer(table);
|
||||
self.lazyCallHook( name, payload );
|
||||
}
|
||||
void queueHook( uf::Object& self, const uf::stl::string& name, sol::table table, float delay = 0.0f ) {
|
||||
void queueHook( uf::Object& self, const uf::stl::string& name, sol::table table, sol::optional<float> delay ) {
|
||||
ext::json::Value payload = uf::Serializer(table);
|
||||
self.queueHook( name, payload, delay );
|
||||
self.queueHook( name, payload, delay.value_or(0.0f) );
|
||||
}
|
||||
uf::stl::string toString( uf::Object& self ) {
|
||||
return self.getName() + ": " + std::to_string( self.getUid() );
|
||||
return uf::string::toString( self );
|
||||
}
|
||||
|
||||
size_t getUid( const uf::Object& o ) { return o.getUid(); }
|
||||
@ -270,7 +278,7 @@ namespace binds {
|
||||
|
||||
UF_LUA_REGISTER_USERTYPE(uf::Object,
|
||||
sol::call_constructor, sol::initializers(
|
||||
[]( uf::Object& self, sol::object arg, bool init = true ){
|
||||
[]( uf::Object& self, sol::object arg, sol::optional<bool> init ){
|
||||
if ( arg.is<uf::stl::string>() ) {
|
||||
self.load( arg.as<uf::stl::string>() );
|
||||
} else if ( arg.is<sol::table>() ) {
|
||||
@ -280,7 +288,7 @@ UF_LUA_REGISTER_USERTYPE(uf::Object,
|
||||
self.load(json);
|
||||
}
|
||||
}
|
||||
if ( init ) self.initialize();
|
||||
if ( init.value_or(true) ) self.initialize();
|
||||
}
|
||||
),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( uid, UF_LUA_C_FUN(::binds::getUid) ),
|
||||
@ -295,6 +303,7 @@ UF_LUA_REGISTER_USERTYPE(uf::Object,
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( findByName, UF_LUA_C_FUN(::binds::findByName) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( globalFindByUid, UF_LUA_C_FUN(::binds::globalFindByUid) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( globalFindByName, UF_LUA_C_FUN(::binds::globalFindByName) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( createChild, UF_LUA_C_FUN(::binds::createChild) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( addChild, UF_LUA_C_FUN(::binds::addChild) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( removeChild, UF_LUA_C_FUN(::binds::removeChild) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( loadChild, UF_LUA_C_FUN(::binds::loadChild) ),
|
||||
|
||||
@ -29,6 +29,13 @@ namespace binds {
|
||||
return uf::physics::applyRotation( self, q );
|
||||
}
|
||||
|
||||
pod::Transform<> getTransform( pod::PhysicsBody& body ) {
|
||||
pod::Transform<> t;
|
||||
t.position = body.offset;
|
||||
t.reference = body.transform;
|
||||
return uf::transform::flatten( t );
|
||||
}
|
||||
|
||||
std::tuple<uf::Object*, float> rayCast( pod::PhysicsBody& self, const pod::Vector3f& center, const pod::Vector3f& direction ) {
|
||||
pod::RayQuery query = uf::physics::rayCast( pod::Ray{center, uf::vector::normalize( direction )}, self, uf::vector::norm( direction ) );
|
||||
uf::Object* object = query.hit ? query.body->object : NULL;
|
||||
@ -51,8 +58,8 @@ namespace binds {
|
||||
pod::PhysicsBody& asCapsule( pod::PhysicsBody& self, const pod::Capsule& shape ) {
|
||||
return uf::physics::initialize( self, shape );
|
||||
}
|
||||
pod::PhysicsBody& asMesh( pod::PhysicsBody& self, const uf::Mesh& shape, bool convex = false ) {
|
||||
return uf::physics::initialize( self, shape, convex );
|
||||
pod::PhysicsBody& asMesh( pod::PhysicsBody& self, const uf::Mesh& shape, sol::optional<bool> convex ) {
|
||||
return uf::physics::initialize( self, shape, convex.value_or(false) );
|
||||
}
|
||||
|
||||
pod::Constraint& constrain( pod::PhysicsBody& a, pod::PhysicsBody& b ) {
|
||||
@ -69,11 +76,11 @@ namespace binds {
|
||||
pod::Constraint& asBallSocket( pod::Constraint& self, const pod::Vector3f& joint ) {
|
||||
return uf::physics::constrainBallSocket( self, joint );
|
||||
}
|
||||
pod::Constraint& asConeTwist( pod::Constraint& self, const pod::Vector3f& joint, const pod::Vector3f& axis, float swingLimit = M_PI / 4.0f, float twistLimit = M_PI / 8.0f ) {
|
||||
return uf::physics::constrainConeTwist( self, joint, axis, swingLimit, twistLimit );
|
||||
pod::Constraint& asConeTwist( pod::Constraint& self, const pod::Vector3f& joint, const pod::Vector3f& axis, sol::optional<float> swingLimit, sol::optional<float> twistLimit ) {
|
||||
return uf::physics::constrainConeTwist( self, joint, axis, swingLimit.value_or(M_PI / 4.0f), twistLimit.value_or(M_PI / 8.0f) );
|
||||
}
|
||||
pod::Constraint& asDistance( pod::Constraint& self, const pod::Vector3f& pA, const pod::Vector3f& pB, bool isRope = false ) {
|
||||
return uf::physics::constrainDistance( self, pA, pB, isRope );
|
||||
pod::Constraint& asDistance( pod::Constraint& self, const pod::Vector3f& pA, const pod::Vector3f& pB, sol::optional<bool> isRope ) {
|
||||
return uf::physics::constrainDistance( self, pA, pB, isRope.value_or(false) );
|
||||
}
|
||||
pod::Constraint& asHinge( pod::Constraint& self, const pod::Vector3f& joint, const pod::Vector3f& axis ) {
|
||||
return uf::physics::constrainHinge( self, joint, axis );
|
||||
@ -198,6 +205,7 @@ UF_LUA_REGISTER_USERTYPE_AND_COMPONENT(pod::PhysicsBody,
|
||||
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( applyImpulse, UF_LUA_C_FUN(uf::physics::applyImpulse) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( applyRotation, UF_LUA_C_FUN(::binds::body::applyRotation) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( getTransform, UF_LUA_C_FUN(::binds::body::getTransform) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( setGravity, UF_LUA_C_FUN(::binds::body::setGravity) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( enableGravity, UF_LUA_C_FUN(::binds::body::enableGravity) ),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE( rayCast, UF_LUA_C_FUN(::binds::body::rayCast) ),
|
||||
|
||||
@ -47,6 +47,28 @@ namespace binds {
|
||||
pod::Matrix4f getModel( const pod::Transform<>& t ) {
|
||||
return uf::transform::model( t );
|
||||
}
|
||||
|
||||
pod::Transform<> fromMatrix( const pod::Matrix4f& matrix ) {
|
||||
return uf::transform::fromMatrix( matrix );
|
||||
}
|
||||
pod::Transform<>& reference( pod::Transform<>& transform, const pod::Transform<>& parent, sol::optional<bool> reorient ) {
|
||||
return uf::transform::reference( transform, parent, reorient.value_or(true) );
|
||||
}
|
||||
pod::Transform<> interpolate( const pod::Transform<>& from, const pod::Transform<>& to, float factor, sol::optional<bool> reorient ) {
|
||||
return uf::transform::interpolate( from, to, factor, reorient.value_or(true) );
|
||||
}
|
||||
pod::Transform<> inverse(const pod::Transform<>& t) {
|
||||
return uf::transform::inverse( t );
|
||||
}
|
||||
pod::Vector3f apply( const pod::Transform<>& transform, const pod::Vector3f& point ) {
|
||||
return uf::transform::apply( transform, point );
|
||||
}
|
||||
pod::Vector3f applyInverse(const pod::Transform<>& t, const pod::Vector3f& worldPoint) {
|
||||
return uf::transform::applyInverse( t, worldPoint );
|
||||
}
|
||||
pod::Transform<> relative(const pod::Transform<>& a, const pod::Transform<>& b) {
|
||||
return uf::transform::relative( a, b );
|
||||
}
|
||||
}
|
||||
|
||||
#include <uf/ext/lua/component.h>
|
||||
@ -67,6 +89,13 @@ UF_LUA_REGISTER_USERTYPE_AND_COMPONENT(pod::Transform<>,
|
||||
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(lookAt, UF_LUA_C_FUN(::binds::lookAt)),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE(getModel, UF_LUA_C_FUN(::binds::getModel))
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE(getModel, UF_LUA_C_FUN(::binds::getModel)),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE(fromMatrix, UF_LUA_C_FUN(::binds::fromMatrix)),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE(reference, UF_LUA_C_FUN(::binds::reference)),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE(interpolate, UF_LUA_C_FUN(::binds::interpolate)),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE(inverse, UF_LUA_C_FUN(::binds::inverse)),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE(apply, UF_LUA_C_FUN(::binds::apply)),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE(applyInverse, UF_LUA_C_FUN(::binds::applyInverse)),
|
||||
UF_LUA_REGISTER_USERTYPE_DEFINE(relative, UF_LUA_C_FUN(::binds::relative))
|
||||
)
|
||||
#endif
|
||||
Loading…
Reference in New Issue
Block a user