Open jsantell opened 6 years ago
I'm new to IK in general (learning about it, and planning to use it on a project), but I have a keen interest in API design, so let me see if I can help.
I think the current API could be simpler. Building a chain seems to always involve the same steps (adding bones, creating joints, adding chain to ik system) and they don't seem to change. I'd suggest consolidating them inside a ik.createChain()
method. As an advantage, it would not prevent the developer from going full-advanced mode if they so desire.
// Going from the README example, the code below assumes
// we already have a `scene` with `pivot`, `movingTarget`, and
// a `bones` array with 10 bones.
const ik = new THREE.IK()
// Create chain from the `ik` instance
// Internally creates joints for each bone
// Automatically adds chain to IK system so `ik.add(chain)` isn't necessary
var chain = ik.createChain(...bones)
// Add a target to the chain
// If jointIndex is undefined, automatically uses last bone
chain.setTarget(movingTarget, jointIndex)
// Set a constraint for a given joint index
// If jointIndex is undefined, set constraint for the whole chain
chain.setConstraint(new THREE.IKBallConstraint(90), jointIndex)
chain.setTarget()
would also be called internally when connecting chains, as if I'm understanding correctly, the target of the parent chain is the other chain's first joint. I think chain1.connect(chain2)
looks good. If a different parent joint index is necessary, I don't think chain1.connect(chain2, jointIndex)
would be too difficult to understand.
I'd also replace ik.getRootBone()
with ik.root
, where root
is a getter. But that's purely semantic: scene.add(ik.root)
. Short and sweet. 😎
Let me know what you think.
Currently, THREE.IK is comprised of a root IK system,
IK
, which can contain several rootIKChain
s, each that may contain a tree ofIKChain
s, which store multipleIKJoint
s that wrapTHREE.Bone
and an optional constraint.Some general open questions:
IK/IKChain structure
IKChain
just contain multiple chains without being wrapped in anIK
system? If other solvers (#2) are implemented, would that be handled in anIK
class, with chains being implementation independent?IKChain
s attach new chains viaconnect()
. The subchain's base must be a joint in the parent chain to determine where this subchain is connected. The fullik library's API for this has you specify which joint index to connect the chain to, and the subchain's base has a separate joint from the parent's. This is probably the better solution.Constraints
IKBallConstraint
. There are open issues for additional constraints (https://github.com/jsantell/THREE.IK/issues/3), multiple constraints per joint (#5) and handling constraints with subbases (#6), but currently they are just instances that can take a joint, and transform it by some way. Because of this, they can be shared betweenIKJoint
s.General API
In general, the API is difficult to use and easy to get wrong. Issues:
ikchain.connect(otherChain)
probably should change to index-based and not share joints between chainsnew IKJoint(bone, { constraints })
is this how constraints should be defined?ikchain.add(joint, { target: target })
when adding a joint to a chain, the last joint needs a target, which makes this the end effector. This is a weird API, surely something could be better.needsUpdate
flag.