[DEV]armature need improvement ..constraints.. ?

basically this is self referencial, so , i guess should be more easy to add. (respect than the rigid body that need of a ton of obj)

the setup is basically self - made.

but you can shoose :
“elast” -> (elasticity …how many spring must have)
“inertia” -> (is the inverse of the friction, for many time the bone tent to bounce)

the setup current is to simulate the hair.

the only dependences that have is have to be another bone as parent.(really is not necessary but cut a lot of calculations)

the mechanism is very easy .
all is based in a vector global (dinWP) (we say that simulate a dynamic obj) that have also the velocity.
it limit indirectly also the rotation of bone .
since the vector cannot go over a range (maxDist) that is the half of the lengt of the bone.
and at the end , the bone , just align itself keep fix also the rotation one the Y axis since is used to_track_quat()

it should be pretty fast.

in a GUI , it can be a new constraints where you have to set only
elast and inertia (so , very easy)
what you think ?
it seem useful having a new constraints for bone as this ,or you thionk there already all necessary?

this is the code (must run from the armature)
[note that if you make a chain long not work too well, better 2 bone max ]


import bge
from mathutils import Matrix,Vector


def m(cont):
    own = cont.owner
    arm = own
    WT = arm.worldTransform
    
    
    
    if not "init" in arm:
        arm["init"] = 1
        arm["bones"] = []
        
        for i in [ "Bone.001", "Bone.002", ] :
            b2 = arm.channels[i]
            b1 = arm.channels[str(b2.bone.parent)]
            
            fix = b1.pose_matrix.inverted() * b2.pose_tail
            dinWP = (WT * b2.pose_tail)
            vel = Vector()
            m4Loc = b1.pose_matrix.inverted() * b2.pose_matrix
            elast = 0.001
            inertia = 0.99
            maxDist = b2.bone.length/2
            grav = Vector((0,0,-0.0027))
            const = [b1,b2,fix,m4Loc,elast,inertia,grav,maxDist]
            vars = [dinWP,vel]
            arm["bones"].append([const, vars])


        
        
    armWT = arm.worldTransform
    
    #armWT = arm.worldTransform
    for i in arm["bones"]:
        b1,b2,fix,m4Loc,elast,inertia,grav,maxDist = i[0]
        dinWP,vel = i[1]
        parMat = b1.pose_matrix
        
        fixAP = parMat * fix
        fixWP = armWT * fixAP
        vec = fixWP - dinWP
        
        if vec.magnitude > maxDist:
            dinWP += vec.normalized() * (vec.magnitude - maxDist)
        vec = fixWP - dinWP
        vel = (vel + (vec + grav)*elast)*inertia
        dinWP += vel
        dinAP = armWT.inverted() * dinWP
        dinBP = (parMat * m4Loc).inverted() * dinAP
        b2.rotation_quaternion = dinBP.to_track_quat("Y","Z")
        i[1] = [dinWP,vel]
    



this the blend

Attachments

armN3.blend (82.7 KB)

seem complex ?_? :slight_smile:
i have other , a lot worse :smiley:

some question :

works on armature is a hard since not there global coordinate for the bone (worldPosition and worldOrientation)
this mean that the minimal impact , (if you know a bit matrix etc) is having more code to write

1 - what about add worldPosition,worldOrientation as function (not as permanent attribute!) ?
(to calculate only when you call it)

this way , you can write :
pos = bone.worldPosition
ori = bone.worldOrientation

instead of :
pos = (armature.worldTransform * bone.pose_matrix).translation
ori = armature.worldTransform.to_3x3() * bone.pose_matrix.to_3x3()

note how naturally tent to become more long the code.
this mean if you make something a bit hard become a monster code

plus will be useful having some basic function of the game obj (the more powerfull) as :
getVectTo() #ever global
alignAxisTo() #ever global