Friday, July 18, 2008

Second Life Physics Scripting - Pinball #15 - Flipper rotation and llSetPos problems

Spent a ton of time trying to get the flipper to rotate off axis.

At one point the llSetPos stopped working and I went back and created a test system to try and figure it out.



I kept calling llSetPos and nothing would move at all. This had to do with the requirement of calling llSetPos if you want to rotate off axis. Being my own worst enemy, I had done a test and changed some calls from llGetLocalPos to llGetPos. While there is no llSetLocalPos, the change from llGetLocalPos was what caused the problem. Since the flipper is a linked prim, the coordinates must be changed in local coordinates otherwise the world coordinates were off the map and nothing moved.

Then I also found the problem with the off axis rotation. Here is the final piece of code, with all of my debugs and junk code just so you can see how many interation tests went into it. This is from the link_message method outlined in the previous post.


// a rotation of 45 degrees around the z-axis
rotation z_45 = llEuler2Rot( <0, 0, -45 * DEG_TO_RAD> );
// the tilt of the table
rotation y_352 = llEuler2Rot( <0, 352 * DEG_TO_RAD, 0>);

// the original orientation of the flipper wedges is <0,0,1>
// i use -1 to point at the heal of the wedge
vector norm = <0,0,-1>;
// rotate that norm so it points towards the point of the wedge
norm = llVecNorm(norm * llGetLocalRot());
//norm = llVecNorm(norm * llGetRot());

// find the size of the wedge
vector sz = llList2Vector(llGetPrimitiveParams([PRIM_SIZE]),0);
llOwnerSay("size = "+(string)sz);
vector flipper_pos = llGetLocalPos();
vector offset = norm * (sz.z / 2);
vector rot_axis = flipper_pos + offset;
//vector rot_axis = start_pos + offset;

llOwnerSay("flipper pos="+(string) flipper_pos);
llOwnerSay("rot_axis ="+(string) rot_axis);
llMessageLinked(dbg_marker, 1,(string)rot_axis, NULL_KEY);
//llOwnerSay("distance from center to heal = "+(string)offset);
llOwnerSay("get rot = "+(string)llGetRot());
llOwnerSay("get local rot = "+(string)llGetLocalRot());
rotation new_rot = llGetLocalRot() * z_45; // compute global rotation
//new_rot = new_rot * norm;
// http://wiki.secondlife.com/wiki/Rotation
// find the rotated norm

vector rotated_offset = offset * new_rot;
llOwnerSay("new rot = "+(string)new_rot);
llSetRot(new_rot);

// ll wiki method
//vector rotatedOffset = offset * z_45; // rotate the offset to get the motion caused by the rotations
//vector newPos = llGetPos() + (offset - rotatedOffset) * llGetRot(); // move the prim position by the rotated offset amount
//rotation newRot = rot6X * llGetRot();

//llOwnerSay(" cur pos = "+(string)llGetLocalPos());
// lsl wiki solution
vector new_pos = rot_axis + ((flipper_pos - rot_axis) * z_45);
//vector new_pos = rot_axis + ((flipper_pos - rot_axis) * new_rot);
//vector new_pos = rot_axis + (offset * new_rot);
//vector new_pos = llGetLocalPos() - (offset * llGetLocalRot());
//vector newPos = llGetLocalPos() + (offset - rotatedOffset) * llGetRot()
//new_pos.x = new_pos.x + 2;
llOwnerSay(" new pos = "+(string) new_pos);
llSetPos(new_pos);
//llOwnerSay(" after = "+(string)llGetLocalPos());


After all that, the problem ended up being this one line.


vector new_pos = rot_axis + ((flipper_pos - rot_axis) * z_45);
//vector new_pos = rot_axis + ((flipper_pos - rot_axis) * new_rot);

As you can see I was multiplying the offset by the new_rot which includes some of the initial rotations of the flipper. When all I really had to do is rotate it by the z_45 which is the change in rotation. This doesn't include the slight rotation of the table, but I'll be adding that as well soon. For now I'm going to do some more work on this test block first.

This still doesn't work all that well and I don't think it will behave like a pinball machine because the inbetween stages will not hit the ball properly. I'm going to make this a lot more complicated and fold it into a timer method and try rotating in increments. Wish me luck.

No comments: