Showing posts with label llSetPos. Show all posts
Showing posts with label llSetPos. Show all posts

Tuesday, July 22, 2008

Second Life Physics Scripting - Pinball #17 - Flipper Rotations Working

Rotations, what a nightmare. A nightmare of my own making, but I finally got the problem solved and it looks like I mostly had confused myself, but after lots of reading and a thousand tests I finally got the flipper to rotate on the test table.



Here is the final code for the timer routine that rotates the flipper in x number of steps.


timer()
{
if (((rotation_tick>0) && (cur_rotation<max_rotation)) ||
((rotation_tick<0) && (cur_rotation>max_rotation)))

{
cur_rotation = cur_rotation + rotation_tick;

// what is currently pointing up in the z direction
// was originally in the -y direction.
if (!orig_axis_flag)
{
orig_axis_flag = TRUE;
orig_axis = llVecNorm(<0,-1,0> * llGetLocalRot());
}

// a rotation around the parents z normal
//rotation z_45 = make_quaternion(parent_norm,rotation_tick*DEG_TO_RAD);
rotation z_45 = llAxisAngle2Rot(orig_axis,rotation_tick*DEG_TO_RAD);

// we need to find the axis which is the heal of the wedge
// the original orientation of the flipper wedge 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());
// find the size of the wedge
vector sz = llList2Vector(llGetPrimitiveParams([PRIM_SIZE]),0);
// get the center location of the wedge
vector flipper_pos = llGetLocalPos();
// find the offset distance from the center
vector offset = norm * (sz.z / 2);
// add that offset to the flipper_pos to get the axis
vector rot_axis = flipper_pos + offset;

// calculate the new rotation by adding the z axis rotation
// z_45 is the old name it is really z_plusang
rotation new_rot = llGetLocalRot()*z_45;
// http://wiki.secondlife.com/wiki/Rotation
// set the new local rotation
llSetLocalRot(new_rot);

// lsl wiki solution for non center rotation
vector new_pos = rot_axis + ((flipper_pos - rot_axis) * z_45);
llSetPos(new_pos);
}
else
{
// stop the timer and wait for the off event
llSetTimerEvent(0);
}
} // timer

It turns out that the basic problem I was having was that I didn't think there was a llSetLocalRot because I already knew there wasn't a llSetLocalPos. So that final call to llSetLocalRot was llSetRot for the longest time and this added a little extra y rotation which caused the flipper to lean in the wrong direction. This was a ton of time to actually find this problem, but rotation can be like that and this is really just another bug in a long development process.

The crazy part is that I continued to work on this even though I knew the mechanic was not going to work. The flipper just takes too long to rotate each step and I don't want a flipper that only has two angles of bounce. Very annoying that there is a lot of work there and the api/engine doesn't support the mechanic I want to use, but then this is the way in software development. You have to make your designs fit the platforms you use and hope people make good platforms. SL is good, but there are a number of changes I would like to see made, but I don't think that is any different than any other api/platform.

I'd rather not see them do the kitchen sink stuff that was done with Java and basically ruined a very nice small system. Then again, they ignored the client side and just gave it up to flash which was a huge mistake that can't really be addressed at this point because now they made the foot print way too big to be a client side platform. I still love Java, I just think Schwartz badly mismanaged it just like he has mismanaged Sun. Sorry for the short rant.

So I think I'm going to use textures to do flippers flat near the back of the machine. We'll see how that turns out next.

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.