PDA

View Full Version : How do I mirror the motions of bones from one side of the body to the other?



White Knight
09-23-2004, 05:54 AM
When animating, say a walk-cycle.

How do I mirror the motions from the bones of one side of the body over to the other side?
It's kind of tedious doing everything twice.


Since I'm new to this, please explain as thorough as possible. =o)

Kindly,

White Knight.

Axis3d
09-24-2004, 08:58 AM
You could use the Graph Editor to copy certain bone channels and paste them onto other bones.

faulknermano
09-25-2004, 06:58 AM
(i was thinking about using keyframer, but i dont think it has mirroring.)

anyway, i use this script, especially for the explicit purpose of mirroring keyframes. select two items only. first item is the SOURCE item whose keyframes you wish to mirror, and the second item, the one you wish to copy to. i forgot if the script requires that no keyframes exist on the second item (or allows only one keyframe at frame zero).



@warnings


activePosRot: val
{
return(val);
}

generic
{

mirrorPos = integer(recall("MIRRORPOS",1));
mirrorx = integer(recall("MIRRORX",0));
mirrory = integer(recall("MIRRORY",0));
mirrorz = integer(recall("MIRRORZ",0));

mirrorRot = integer(recall("MIRRORROT",1));
mirrorh = integer(recall("MIRRORH",0));
mirrorp = integer(recall("MIRRORP",0));
mirrorb = integer(recall("MIRRORB",0));
s = Scene().getSelect();

if(!s)
error("<br>Select two items.");

if(s.size() < 2)
error("<br>Select two items only.");

target = s[1];
source = s[2];


reqbegin("Mirror Channel Keys");

ctlsep();
b0 = ctlcheckbox("Use Position",mirrorPos);
ctlsep();
b1 = ctlchoice("X",mirrorx,@"Mirror X","Copy X","Bypass X"@);
b2 = ctlchoice("Y",mirrory,@"Mirror Y","Copy Y","Bypass Y"@);
b3 = ctlchoice("Z",mirrorz,@"Mirror Z","Copy Z","Bypass Z"@);

ctlsep();
c0 = ctlcheckbox("Use Rotation",mirrorRot);
ctlsep();
c1 = ctlchoice("H",mirrorh,@"Mirror H","Copy H","Bypass H"@);
c2 = ctlchoice("P",mirrorp,@"Mirror P","Copy P","Bypass P"@);
c3 = ctlchoice("B",mirrorb,@"Mirror B","Copy B","Bypass B"@);

ctlsep();
ctltext("[email protected]","");

ctlactive(b0,"activePosRot",b1,b2,b3);
ctlactive(c0,"activePosRot",c1,c2,c3);

return if(!reqpost());

mirrorPos = getvalue(b0);
mirrorx = getvalue(b1);
mirrory = getvalue(b2);
mirrorz = getvalue(b3);

mirrorRot = getvalue(c0);
mirrorh = getvalue(c1);
mirrorp = getvalue(c2);
mirrorb = getvalue(c3);


store("MIRRORPOS",mirrorPos);
store("MIRRORROT",mirrorRot);
store("MIRRORX",mirrorx);
store("MIRRORY",mirrory);
store("MIRRORZ",mirrorz);

store("MIRRORH",mirrorh);
store("MIRRORP",mirrorp);
store("MIRRORB",mirrorb);


reqend();

// get source channels

tc = target.firstChannel();
while(tc)
{
if(tc.name == "Position.X")
tx = tc;
if(tc.name == "Position.Y")
ty = tc;
if(tc.name == "Position.Z")
tz = tc;

if(tc.name == "Rotation.H")
th = tc;
if(tc.name == "Rotation.P")
tp = tc;
if(tc.name == "Rotation.B")
tb = tc;

tc = target.nextChannel();
}

sc = source.firstChannel();
while(sc)
{
if(sc.name == "Position.X")
sx = sc;
if(sc.name == "Position.Y")
sy = sc;
if(sc.name == "Position.Z")
sz = sc;

if(sc.name == "Rotation.H")
sh = sc;
if(sc.name == "Rotation.P")
sp = sc;
if(sc.name == "Rotation.B")
sb = sc;

sc = source.nextChannel();
}

// get info frmo source


for(i=1;i<=6;i++) // per channel
{
if(i == 1)
{
if(!mirrorPos)
continue;
if(mirrorx == 3)
continue;
chan = sx;
tchan = tx;
if(mirrorx == 1)
multiplier = -(1.0);
else
multiplier = 1.0;
}
if(i == 2)
{
if(!mirrorPos)
continue;
if(mirrory == 3)
continue;

chan = sy;
tchan = ty;
if(mirrory == 1)
multiplier = -(1.0);
else
multiplier = 1.0;
}
if(i == 3)
{
if(!mirrorPos)
continue;
if(mirrorz == 3)
continue;

chan = sz;
tchan = tz;
if(mirrorz == 1)
multiplier = -(1.0);
else
multiplier = 1.0;
}
if(i == 4)
{
if(!mirrorRot)
continue;
if(mirrorh == 3)
continue;

chan = sh;
tchan = th;
if(mirrorh == 1)
multiplier = -(1.0);
else
multiplier = 1.0;
}
if(i == 5)
{
if(!mirrorRot)
continue;
if(mirrorp == 3)
continue;

chan = sp;
tchan = tp;
if(mirrorp == 1)
multiplier = -(1.0);
else
multiplier = 1.0;
}
if(i == 6)
{
if(!mirrorRot)
continue;
if(mirrorb == 3)
continue;

chan = sb;
tchan = tb;
if(mirrorb == 1)
multiplier = -(1.0);
else
multiplier = 1.0;
}

kcount = chan.keyCount;
for(j=1;j<=kcount;j++) // per key
{
kf = chan.keys[j];
kfTime = chan.getKeyTime(kf);
kfValue = chan.getKeyValue(kf) * multiplier;
newKey = tchan.createKey(kfTime,kfValue);
if(string(chan.getKeyCurve(kf)) != "1" && string(chan.getKeyCurve(kf)) != "2" && string(chan.getKeyCurve(kf)) != "4" && string(chan.getKeyCurve(kf)) != "5" && string(chan.getKeyCurve(kf)) != "6")
{
kfCurve = nil;
}
if(string(chan.getKeyCurve(kf)) == "0")
{
kfCurve = nil;
}
else
kfCurve = chan.getKeyCurve(kf);

if(kfCurve == CHAN_TCB)
{
t = chan.getKeyTension(kf);
c = chan.getKeyContinuity(kf);
b = chan.getKeyBias(kf);
tchan.setKeyCurve(newKey,CHAN_TCB);
tchan.setKeyTension(newKey,t);
tchan.setKeyContinuity(newKey,c);
tchan.setKeyBias(newKey,b);
continue;
}
if(kfCurve == CHAN_HERMITE)
{
(h1,h2,h3,h4) = chan.getKeyHermite(kf);
tchan.setKeyCurve(newKey,CHAN_HERMITE);
tchan.setKeyHermite(newKey,h1*multiplier,h2*multip lier,h3*multiplier,h4*multiplier);
continue;
}
if(kfCurve == CHAN_LINEAR)
{
tchan.setKeyCurve(newKey,CHAN_LINEAR);
continue;
}

if(kfCurve == CHAN_STEPPED)
{
tchan.setKeyCurve(newKey,CHAN_STEPPED);
continue;
}
if(kfCurve == nil)
{
tchan.setKeyCurve(newKey,CHAN_BEZIER);
(h1,h2,h3,h4) = chan.getKeyHermite(kf);
tchan.setKeyHermite(newKey,h1,h2*multiplier,h3,h4* multiplier);
}

}
}
}