PDA

View Full Version : lscript question - "Align Pitch" in scripting?



delfeld
03-07-2009, 05:43 PM
I can't seem to get "Align Pitch" working the same way in lscript as I can when mousing around Layout.

My general process is:

* load an object with skelegons
* convert skelegons to bones
* select a bone
o record pivot rotation
o align pitch


I can script everything correctly (I think) up to aligning the pitch. I can't seem to get this right in scripting.

In lscript,

* I grab the mesh's overall rotation
* Then, for each bone, I set the rest rotation with RecordPivotRotation().
* I then apply the mesh's rotation to each bone, but it doesn't seem to have an effect - the object ends up twisted beyond recognition.

I've attached a series of 4 objects at various points of bone alignment:

1. the Modeler object
2. the object freshly brought into Layout
3. the object after the manual process in Layout (described earlier)
4. the object, mangled by the lscript (described earlier)

Any help?

delfeld
03-13-2009, 11:04 AM
*sigh*

All my toughest problems don't have answers.

GregMalick
03-13-2009, 11:35 AM
Post the code & I'll take a look.

delfeld
03-13-2009, 11:43 AM
This is it, warts and all. Please note that there are a lot of different attempts, so you can't assume that just because something commented/uncommented that it is needed/unneeded. I basically do not know how to get this to work.


generic
{
// set frame to edit in
currTime = 0;

// Create Mesh Object Agent from first object.
mesh = Mesh();
EnableIK;
ParentInPlace(true);

// if no bones, then create from skelegons
if(mesh.bone() == nil)
{
SkelegonsToBones();

// if no bones now, then exit
if(mesh.bone() == nil)
{
info("No skelegons or bones in this object: " + mesh.name);
return;
}
}

// enter bone edit mode
// EditBones();

// Create Bone Object Agent from first bone in
// from mesh Object Agent.

// select the first bone
bone = mesh.bone();
// tempParent = bone.parent;

// get mesh's default rotation
meshRot = mesh.getRotation(currTime);
info(meshRot);

// Cycle through all bones until a bone value == 'nil'.while(bone)
while(bone != nil)
{
// Display some of the current bone’s
// values on frame 0, by accessing bone Object Agent.
// info("Bone Name: ", bone);

// set next's parent to the mesh to keep from deforming.
// boneNext = bone.next();
// SelectByName(boneNext.name);
// ParentItem(tempParent);

// select the current bone
SelectByName(bone.name);
//BoneActive();

// reset the bone's rest position to the current position
RecordPivotRotation();

// realign rotation to the mesh's rotation.
//Generic_BT_AlignPitch();
BoneRestRotation(meshRot.h, meshRot.p, meshRot.b);
// (Heading, Pitch, Bank)
//info(bone.getRotation(currTime).h, mesh.getRotation(currTime).p, bone.getRotation(currTime).b);
// BoneRestRotation(bone.getRotation(currTime).h, mesh.getRotation(currTime).p, bone.getRotation(currTime).b);
//Generic_BT_BonesOFF;
// SelectByName(boneNext.name);
// ParentItem(bone);

// NextFrame;
// PreviousFrame;
// RedrawNow;
// RefreshNow;

// pause
//info("Bone Name: ", bone);

// Cycle to next bone. If no bone is available, bone will equal ‘nil’.
bone = bone.next();

// bone = bone.SelectChild();
// if(bone = nil)
// {
// bone = bone.NextSibling();
// if(bone = nil)
// {
// bone = parBone.NextSibling();
// }
// }
}

//ModCommand_BoneWeights;
}

GregMalick
03-13-2009, 05:28 PM
Well one thing may be that the AlignPitch command automatically moves to the next child bone. That may be causing some grief. The manual also says that IK should be disabled and Bones turned off. It says an easy way to do this is to use Bone Edit Mode. Looks like you're turning on IK and have commented out EditBones(); Then again, you've commented out the AlignPitch.


So you're doing BoneRestRotation(meshRot.h, meshRot.p, meshRot.b);
for all bones based on the mesh. From your original comment, I think you want AlignPitch.

Another issue is whether you want all bones aligned to their parent. That means you would need to set up a recursive function since parents can have multiple children.

Personally I'd get this working on the simplest model you can... a Null and a couple bones.

delfeld
03-17-2009, 10:05 AM
Though I already tried the solution(s) you suggested, I tried them again. No luck.

The while-loop actually steps through each bone, selecting the next one in each loop. This will step through all the bones in an object, in no particular order. It is not recursive, but is a way in which LW provides for making sure you can reach each bone.

This may actually be a problem (so I will test it soon). That is, is it necessary to process the bones in a specific, bone-tree order?

I accidentally tried something that corrected one bone. I converted skelegons to bones, then selected one bone, then ran the script. The rotation was correct, but when I grabbed one of the rotation handles, all three axes reverted to their pre-script position. Is this a clue?

faulknermano
03-19-2009, 07:16 PM
i am having trouble understanding what 'aligning pitch' really does. what is this script supposed to achieve?

delfeld
03-20-2009, 07:43 AM
It is supposed to destroy gymbol locking. Actually, "Align Pitch" comes after reseting the pivot rotations; it resets the axes of a bone to be in the same direction as the object's axes.

A bone starts out in standard world space. Each bone starts out with +y = up, +z = forward, and +x = right (I believe). From there, the bone is rotated to point in the correct direction for controlling whatever needs controlling. That is, an arm bone has to be rotated to point along the arm. This is all fairly intuitive in Modeler with "skelegons".

The problem comes when bringing the object into Layout. You have to convert skelegons into bones, which (because of the formula LW uses to transform rotations) does not correctly orient the bones. That is, the bones *look* like they are oriented correctly, but the actual axes of each bone is messed up. Quite often, you will find that two axes are pointing the same direction (+y = +z, also called gymbol lock). To correct this, you use the "Record pivot rotation", which realigns the bones correctly and stores the rotation as the base rotation. However, this is done using the global axes, so you have to use "Align Pitch" to shift the orientation to the object's axes.

The problem is that this works in Layout's IDE, but not in Layout's lscript; I need an lscript solution for a project I am working on.

faulknermano
03-20-2009, 07:50 PM
I see: I didn't realise the Record Pivot Rotation did not fit the bill. If it's not too much to ask, could you provide a test scene that I could re-test your script on?

delfeld
03-21-2009, 09:37 AM
There is a test scene in the ZIP file in the first message in this thread.

faulknermano
03-23-2009, 04:25 AM
hi delfeld. firstly, i tried the pre-bone scene and converted skelegons. then one-by-one i Record Pivot Rotation. I got _almost_ the same scene as your manual_results, _except_ for the orientation of the bank. in my scene, the bank orientation faced +z, while you manual_results.lws faced -z. but other than that my pitch and heading aligns straight down the bone, just like your manual_results.lws. sorry if i'm being dense; is there a fundamental mistake with my own attempt?

(i'm sure i can help with this script, but i need to know what this script is exactly going to do)

delfeld
03-23-2009, 07:31 AM
faulknermano, thanks for checking out the scene.

The script is self-explanatory - there really is not much to this script.