Thanks both.
I found a video about using SkeletonIK: https://godotengine.org/article/skeleton-inverse-kinematic
Had to watch it a couple of times to figure stuff out, and I still missed the .start()
call to make it actually work, but got there in the end.
As TwistedTwigleg points out, the lack of joint constraints causes unnatural positions - that will be an issue, but one I can probably defer to later.
Anyway, here's the test script I currently have, attached to the inherited scene created when opening the .dae file
extends Spatial
var Limbs = {}
onready var Skel = get_node("RootNode/Skeleton")
var Targets = Spatial.new()
func _ready():
Limbs["Left Arm"] = _createIkLimb("Left Arm" ,"lShldrBend","lHand")
Limbs["Right Arm"] = _createIkLimb("Right Arm","rShldrBend","rHand")
Limbs["Left Leg"] = _createIkLimb("Left Leg" ,"lThighBend","lFoot")
Limbs["Right Leg"] = _createIkLimb("Right Leg","rThighBend","rFoot")
for LimbName in Limbs:
Skel.add_child(Limbs[LimbName])
self.add_child(Targets)
for i in range(10):
Targets.add_child(_createRandomTarget())
func _createIkLimb(Name,From,To):
var Limb = SkeletonIK.new()
Limb.set_meta("name",Name)
Limb.set_root_bone(From)
Limb.set_tip_bone(To)
return Limb
func _createRandomTarget():
var Target = CSGSphere.new()
Target.set_radius(0.05)
var x = rand_range(-1,0.5)*2 # ???
var y = rand_range(0,1)*2
var z = rand_range(0,0.2)
Target.set_translation(Vector3(x,y,z))
return Target
func _selectTarget():
return Targets.get_child( rand_range(0,Targets.get_child_count()) )
func _process(delta):
if Input.is_action_just_pressed("ui_left"):
pose("Left Arm",_selectTarget())
if Input.is_action_just_pressed("ui_right"):
pose("Right Arm",_selectTarget())
if Input.is_action_just_pressed("ui_down"):
pose("Left Leg",_selectTarget())
pose("Right Leg",_selectTarget())
func pose(LimbName,Target):
Limbs[LimbName].set_target_node(Target.get_path())
Limbs[LimbName].start(true)