Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Untested: multi-joint linkset animation

Jesrad Seraph
Nonsense
Join date: 11 Dec 2004
Posts: 1,463
11-04-2005 05:49
Since I'm not able to access SL in a way that would let me test this, I'm posting it now in the hope someone with good scripting skills can make use of it and make interesting content.

This is a set of two scripts: body and limb. Body goes in the root prim of your animated linkset, it needs a few modifications at the beginning (number of frames for each animation). Limb has to be slightly modified (limb, and base limb number where necessary) into a seperate version for each independently animated subset of child prims in your linkset (the script goes into each of the subset's prim).

Body script (loads the joints' positions, and their rotations for each animation frame, in either Euler/degree or Quaternion/radians format, from a notecard called "anims";). In this example there are two animations of 4 frames each.
*REMOVED, see below for working script*

Limb element script (gets its relevant joint position and rotations info from the body and uses this to calculate its own local rotation and local position for each frame). This example defines the limb number 0, and indicates it should be attached to limb number 4.
*REMOVED, see below for working script*

Here is an example anim file that I wanted to test in my mammoth. The joints' positions are the first vector of each line (one line = one limb subset). It has 2 animations of 4 frames each, for 8 different limb subsets (4 lower legs and 4 upper legs). Rotations are in Euler format (in degrees).
CODE

<6, 2, -10>!<0, 12, 0>!<0, 4, 0>!<0, -2, 0>!<0, 14, 0>!<-5, 0, 0>!<-12, 0, 0>!<-3, 0, 0>!<2, 0, 0>
<6, -2, -10>!<0, -2, 0>!<0, 14, 0>!<0, 12, 0>!<0, 4, 0>!<5, 0, 0>!<12, 0, 0>!<3, 0, 0>!<-2, 0, 0>
<-7, 2, -10>!<0, -2, 0>!<0, 14, 0>!<0, 12, 0>!<0, 4, 0>!<5, 0, 0>!<12, 0, 0>!<3, 0, 0>!<-2, 0, 0>
<-7, -2, -10>!<0, 12, 0>!<0, 4, 0>!<0, -2, 0>!<0, 14, 0>!<-5, 0, 0>!<-12, 0, 0>!<-3, 0, 0>!<2, 0, 0>
<6, 2, -2>!<0, -9, 0>!<0, -6, 0>!<0, 4, 0>!<0, 11, 0>!<-5, 0, 0>!<-12, 0, 0>!<-3, 0, 0>!<2, 0, 0>
<6, -2, -2>!<0, 4, 0>!<0, 11, 0>!<0, -9, 0>!<0, -6, 0>!<5, 0, 0>!<12, 0, 0>!<3, 0, 0>!<-2, 0, 0>
<-7, 2, -2>!<0, 4, 0>!<0, 11, 0>!<0, -9, 0>!<0, -6, 0>!<5, 0, 0>!<12, 0, 0>!<3, 0, 0>!<-2, 0, 0>
<-7, -2, -2>!<0, -9, 0>!<0, -6, 0>!<0, 4, 0>!<0, 11, 0>!<-5, 0, 0>!<-12, 0, 0>!<-3, 0, 0>!<2, 0, 0>


Important: you have to define limbs from end to body.
_____________________
Either Man can enjoy universal freedom, or Man cannot. If it is possible then everyone can act freely if they don't stop anyone else from doing same. If it is not possible, then conflict will arise anyway so punch those that try to stop you. In conclusion the only strategy that wins in all cases is that of doing what you want against all adversity, as long as you respect that right in others.
Jesrad Seraph
Nonsense
Join date: 11 Dec 2004
Posts: 1,463
11-04-2005 06:33
Note: to use send a link message with string "anim" and the number of the needed anim as the integer.
_____________________
Either Man can enjoy universal freedom, or Man cannot. If it is possible then everyone can act freely if they don't stop anyone else from doing same. If it is not possible, then conflict will arise anyway so punch those that try to stop you. In conclusion the only strategy that wins in all cases is that of doing what you want against all adversity, as long as you respect that right in others.
Zodiakos Absolute
With a a dash of lemon.
Join date: 6 Jun 2005
Posts: 282
11-04-2005 08:36
Would this work on avatar attachments as is? This could be very useful to create a complex moving tail...
Jesrad Seraph
Nonsense
Join date: 11 Dec 2004
Posts: 1,463
11-04-2005 14:00
Think additional, fully animated limbs like a second pair of legs.
_____________________
Either Man can enjoy universal freedom, or Man cannot. If it is possible then everyone can act freely if they don't stop anyone else from doing same. If it is not possible, then conflict will arise anyway so punch those that try to stop you. In conclusion the only strategy that wins in all cases is that of doing what you want against all adversity, as long as you respect that right in others.
Alain Talamasca
Levelheaded Nutcase
Join date: 21 Sep 2005
Posts: 393
11-04-2005 14:31
From: Jesrad Seraph
Think additional, fully animated limbs like a second pair of legs.


Or fold your Human legs up into a really uncomfortable pretzel, bend them backwards, add a big fat hairy spider body and 4 pairs of fully articulated legs...

Drider here we come!
_____________________
Alain Talamasca,
Ophidian Artisans - Fine Art for your Person, Home, and Business.
Pando (105, 79, 99)
Strife Onizuka
Moonchild
Join date: 3 Mar 2004
Posts: 5,887
11-04-2005 14:50
llGetRootRotation doesn't return what you want on attachments, there is currently no way to get the local rotation of the root prim on attachments from any prim other then the root prim.

It should also be noted that if the distance / rot change of the prim is too small the update will execute properly but the sim will not send the update to the clients.
_____________________
Truth is a river that is always splitting up into arms that reunite. Islanded between the arms, the inhabitants argue for a lifetime as to which is the main river.
- Cyril Connolly

Without the political will to find common ground, the continual friction of tactic and counter tactic, only creates suspicion and hatred and vengeance, and perpetuates the cycle of violence.
- James Nachtwey
Jesrad Seraph
Nonsense
Join date: 11 Dec 2004
Posts: 1,463
11-05-2005 04:50
So in attachments, one should substitute the llSetPrimitiveParams for a pair of llSetPos / llSetLocalRot, right ? I've noticed the "small update" thing, apparently rotations under 3 degrees are skipped.
_____________________
Either Man can enjoy universal freedom, or Man cannot. If it is possible then everyone can act freely if they don't stop anyone else from doing same. If it is not possible, then conflict will arise anyway so punch those that try to stop you. In conclusion the only strategy that wins in all cases is that of doing what you want against all adversity, as long as you respect that right in others.
Strife Onizuka
Moonchild
Join date: 3 Mar 2004
Posts: 5,887
11-05-2005 12:06
From: Jesrad Seraph
So in attachments, one should substitute the llSetPrimitiveParams for a pair of llSetPos / llSetLocalRot, right ? I've noticed the "small update" thing, apparently rotations under 3 degrees are skipped.


Nope, PRIM_ROTATE is the same as llSetRot
_____________________
Truth is a river that is always splitting up into arms that reunite. Islanded between the arms, the inhabitants argue for a lifetime as to which is the main river.
- Cyril Connolly

Without the political will to find common ground, the continual friction of tactic and counter tactic, only creates suspicion and hatred and vengeance, and perpetuates the cycle of violence.
- James Nachtwey
Jesrad Seraph
Nonsense
Join date: 11 Dec 2004
Posts: 1,463
12-14-2005 06:00
Tested Successfully ! IM me for a working example object.

Body script:
CODE

// Multiple-Joint Animation Set
//
// Author: Jesrad Seraph
// Modify and redistribute freely as long as you permit free modification and redistribution

integer unichan;
integer anim;
integer step;

integer listener;
integer max_listener = 1;
float rate = 0.4;

integer limbs; // number of limbs, one limb per line in "anims"

integer use_euler = FALSE; // whether anim file contains vectors in degrees or quaternion rotations

string animfile = "anims"; // file containing the anims (rotations) for each limb
// format: "j!r!r!r!r!..." one line per limb, 255 chars max
// j is the localpos of the joint, relative to either
// the superior joint, or the body if it's a main joint
// r's are the limb's rotations for each anim frame
// and can be Euler (in degrees) or quaternion rotations

// Always define first the base limbs, THEN whatever limbs that attach to these


list animframes = [2]; // number of frames for each animation

list animoffsets = [1]; // offset of each anim in frames list
// frame 0 is the building position

initchan()
{
unichan = (integer)llFrand(765765) - 800000;
llMessageLinked(LINK_ALL_OTHERS, unichan, "defchan", "");
}

default
{
state_entry()
{
limbs = 0;
llMessageLinked(LINK_ALL_OTHERS, 0, "reset", "");
llMessageLinked(LINK_ALL_OTHERS, use_euler, "euler", "");
llSleep(0.25);
llGetNotecardLine(animfile, limbs);
}

dataserver(key id, string data)
{
if (data != EOF)
{
llOwnerSay("Restoring limb " + (string)limbs);
llMessageLinked(LINK_ALL_OTHERS, limbs, "aninit", (key)data);
++limbs;
llSleep(0.8);
llGetNotecardLine(animfile, limbs);
} else {
initchan();
llInstantMessage(llGetOwner(), "I'm ready.");
}
}

link_message(integer part, integer num, string msg, key id)
{
if (msg == "anim")
{
llSetTimerEvent(rate);
listener = (listener + 1) % max_listener;
anim = num;
} else if (msg == "off")
{
llSetTimerEvent(0.0);
anim = 0;
llSay(unichan, "0");
}
}

timer()
{
listener = (listener + 1) % max_listener;
step = (step + 1) % llList2Integer(animframes, anim);
llSay(unichan + listener, (string)(step + llList2Integer(animoffsets, anim)) );
}
}


Limb:
CODE

// Multiple-joint limb animation script
//
// Author: Jesrad Seraph
// Modify and redistribute freely as long as you permit free modification and redistribution

integer handle;
integer use_euler = FALSE;

list my_limbs = [0]; // the limb number, and numbers of the joints it attaches to, from limb end to body

vector joint;
vector offset;

list animrot;
list animpos;

default
{
state_entry() { animrot = []; animpos = []; }

link_message(integer part, integer num, string msg, key id)
{
if (msg == "defchan")
{
llListenRemove(handle);
if (num != 0)
handle = llListen(num + (integer)llGetSubString(llGetScriptName(), -1, -1), "", "", "");
} else if (msg == "reset")
{
if (animrot != []) llSetPrimitiveParams([PRIM_POSITION, llList2Vector(animpos, 0), PRIM_ROTATION, llList2Rot(animrot, 0) / llGetRootRotation()]);
animrot = [];
animpos = [];
llListenRemove(handle);
} else if (msg == "dump")
{
llOwnerSay("Limb #" + (string)llList2Integer(my_limbs, 0));
llOwnerSay(llList2CSV(animrot));
llOwnerSay(llList2CSV(animpos));
} else if ((msg == "aninit") && (llListFindList(my_limbs, [num]) >= 0))
{
list temp = llParseString2List((string)id, ["!"], []);
list tpos;
list trot;
rotation ro;
integer n;
integer l = llGetListLength(temp);

if (animrot == [])
{
animrot = [llGetLocalRot()];
animpos = [llGetLocalPos()];
joint = (vector)llList2String(temp, 0);
offset = llGetLocalPos() - joint;

for (n=1; n<l; ++n)
{
if (use_euler) {
ro = llEuler2Rot(DEG_TO_RAD * (vector)llList2String(temp, n));
} else {
ro = (rotation)llList2String(temp, n);
}
animrot += [llGetLocalRot() * ro];
animpos += [offset * ro + joint];
}
} else {
trot = [llGetLocalRot()];
tpos = [llGetLocalPos()];
joint = (vector)llList2String(temp, 0);

for (n=1; n<l; ++n)
{
if (use_euler) {
ro = llEuler2Rot(DEG_TO_RAD * (vector)llList2String(temp, n));
} else {
ro = (rotation)llList2String(temp, n);
}
offset = llList2Vector(animpos, n) - joint;
trot += [llList2Rot(animrot, n) * ro];
tpos += [offset * ro + joint];
}
animrot = trot;
trot = [];
animpos = tpos;
tpos = [];
}
} else if (msg == "euler") use_euler = num;
}

listen(integer chan, string name, key id, string mesg)
{
integer step = (integer)mesg;
llSetPrimitiveParams([PRIM_POSITION, llList2Vector(animpos, step), PRIM_ROTATION, llList2Rot(animrot, step) / llGetRootRotation()]);
}
}
_____________________
Either Man can enjoy universal freedom, or Man cannot. If it is possible then everyone can act freely if they don't stop anyone else from doing same. If it is not possible, then conflict will arise anyway so punch those that try to stop you. In conclusion the only strategy that wins in all cases is that of doing what you want against all adversity, as long as you respect that right in others.