Calculating object rotation on a slope
#1

I'm writing some code that will calculate the RX, RY of a slope then apply those values to an object so that it will have the same rotation based on the slope. So here is the deal it works perfectly when the object has a Z Rotation at 0.0 but i'm looking for a way to get the correct RX, RY values when the Z Rotation is set to some other value. I'm not the greatest of math guys so I'm hoping someone might have a solution here is the code so far it uses MapAndreas to find the ZHeight to the north, south, east, west of the object center then uses some basic trig to get the slope angle.

Код:
		new Float:North[3], Float:South[3], Float:East[3], Float:West[3], Float:RXAngle, Float:RYAngle, Float:opposite, Float:hypotenuse;

		// Set slope positions
		North[0] = objects[ox];
		North[1] = objects[oy] + 1;

		South[0] = objects[ox];
		South[1] = objects[oy] - 1;

		East[0] = objects[ox] + 1;
		East[1] = objects[oy];

		West[0] = objects[ox] - 1;
		West[1] = objects[oy];

		// Use map andreas to get Z Values
		MapAndreas_FindZ_For2DCoord(North[0], North[1], North[2]);
		MapAndreas_FindZ_For2DCoord(South[0], South[1], South[2]);
		MapAndreas_FindZ_For2DCoord(East[0], East[1], East[2]);
		MapAndreas_FindZ_For2DCoord(West[0], West[1], West[2]);

		// Calculate Slope angles
		// North South RX
		hypotenuse = getdist3d(North[0], North[1], North[2], South[0], South[1], South[2]);
		opposite = getdist3d(North[0], North[1], North[2], North[0], North[1], South[2]);

		RXAngle = asin(floatdiv(opposite, hypotenuse));
		if(South[2] > North[2]) RXAngle *= -1;

		// West East RY
		hypotenuse = getdist3d(West[0], West[1], West[2], East[0], East[1], East[2]);
		opposite = getdist3d(West[0], West[1], West[2], West[0], West[1], East[2]);

		RYAngle = asin(floatdiv(opposite, hypotenuse));
		if(East[2] > West[2]) RYAngle *= -1;

		// Set object rotation
		objects[rx] = RXAngle;
		objects[ry] = RYAngle;
		
		SetObjectRot(objects[object_id], objects[rx], objects[ry], objects[rz]);
As can be seen there is no code for generating the correct rotation based on RZ rotation any ideas here?
Reply
#2

what slope bro?
Reply
#3

Quote:
Originally Posted by mastermax7777
Посмотреть сообщение
what slope bro?
Any sloped surface in the game, read the code before posting a 3 word reply thank-you.
Reply
#4

https://sampwiki.blast.hk/wiki/GetObjectRot

Uh.... is this what you mean 0_o

EDIT: Oh I understand now... sorry.
Reply
#5

Quote:
Originally Posted by BenzoAMG
Посмотреть сообщение
https://sampwiki.blast.hk/wiki/GetObjectRot

Uh.... is this what you mean 0_o
No. Basically, he means this: (I guess)
If there's a sloped terrain, he wants to create the object so that it automatically aligns itself along the slope.
Am I right or you want something else?
Reply
#6

Maths is definately not my strong point, but I assume you need to get the Z height of the 4 neighbouring coordinates and use higherside-lowerside to find the difference, then from that use some math functions to work out the x or y rotation of the object. Sin + Cos? Not sure.
Reply
#7

Well as I mentioned it does work fine when the object has a rotation of 0.0 on the RZ rotation, the problem comes into play when say you have an RZ that is not 0.0 in this case the RX and RY need to be re-recalculated to compensate for RZ rotation on the slope.
Reply
#8

Quote:
Originally Posted by ******
Посмотреть сообщение
Quaternions (and I can't help you more than that as I don't know them).
I was leaning in that direction as a solution but I'm in the same boat as you.
Reply
#9

You could convert from one euler angle sequence to another, rotate the object, convert back to the original sequence and apply the new rotation values to the object. That's how it's done in my object editor - no quaternions used at all. See the following function for example:

pawn Код:
EDIT_ObjectRotateZ(object, Float:rot_z)
{
    new
        Float:x,
        Float:y,
        Float:z,
        Float:sin[3],
        Float:cos[3];
    GetObjectRot(object, x, y, z);
    EDIT_FloatConvertValue(x, y, z, sin, cos);
    // Convert from one euler angle sequence (ZXY) to another and add the rotation
    EDIT_FloatConvertValue(asin(cos[0] * cos[1]), atan2(sin[0], cos[0] * sin[1]) + rot_z, atan2(cos[1] * cos[2] * sin[0] - sin[1] * sin[2], cos[2] * sin[1] - cos[1] * sin[0] * -sin[2]), sin, cos);
    // Convert back to the original euler angle sequence and apply the new rotation to the object
    SetObjectRot(object, asin(cos[0] * sin[1]), atan2(cos[0] * cos[1], sin[0]), atan2(cos[2] * sin[0] * sin[1] - cos[1] * sin[2], cos[1] * cos[2] + sin[0] * sin[1] * sin[2]));
    return 1;
}

EDIT_FloatConvertValue(Float:rot_x, Float:rot_y, Float:rot_z, Float:sin[3], Float:cos[3])
{
    sin[0] = floatsin(rot_x, degrees);
    sin[1] = floatsin(rot_y, degrees);
    sin[2] = floatsin(rot_z, degrees);
    cos[0] = floatcos(rot_x, degrees);
    cos[1] = floatcos(rot_y, degrees);
    cos[2] = floatcos(rot_z, degrees);
    return 1;
}
Reply
#10

I'll give it a shot thanks for the suggestion! I'll need to re-write these functions slightly but that isn't hard.

Edit - Works perfectly new functions....

Код:
stock ObjectRotateZ(Float:RX, Float:RY, Float:RZ, Float:rot_z, &Float:NewRX, &Float:NewRY, &Float:NewRZ)
{
	new
		Float:sinx,
		Float:siny,
		Float:sinz,
		Float:cosx,
		Float:cosy,
		Float:cosz;
		
    FloatConvertValue(RX, RY, RZ, sinx, siny, sinz, cosx, cosy, cosz);
    // Convert from one euler angle sequence (ZXY) to another and add the rotation
    FloatConvertValue(asin(cosx * cosy), atan2(sinx, cosx * siny) + rot_z, atan2(cosy * cosz * sinx - siny * sinz, cosz * siny - cosy * sinx * -sinz),
		sinx, siny, sinz, cosx, cosy, cosz);

    // Convert back to the original euler angle sequence and apply the new rotation to the object
    NewRX = asin(cosx * siny),
	NewRY = atan2(cosx * cosy, sinx),
	NewRZ = atan2(cosz * sinx * siny - cosy * sinz, cosy * cosz + sinx * siny * sinz);
    return 1;
}

stock FloatConvertValue(Float:rot_x, Float:rot_y, Float:rot_z, &Float:sinx, &Float:siny, &Float:sinz, &Float:cosx, &Float:cosy, &Float:cosz)
{
    sinx = floatsin(rot_x, degrees);
    siny = floatsin(rot_y, degrees);
    sinz = floatsin(rot_z, degrees);
    cosx = floatcos(rot_x, degrees);
    cosy = floatcos(rot_y, degrees);
    cosz = floatcos(rot_z, degrees);
    return 1;
}
Thanks again YJIET
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)