Scripted Object Rotation - Problems on 240-360 degrees
by Kuju Manila · in Torque Game Engine · 12/16/2006 (7:58 am) · 10 replies
Hello everyone.
I've been trying to create a simple script for the player to animate its turning (rotation) programmatically since it will be based on AI. However, trying to make it rotate on angles 240-360 degrees makes it wrong. It seems that whenever I set the transform's theta to mDegToRad(240 to 360 degrees), the transform begins back to some different angle. Can someone explain to me what's wrong?
The modified player code:
I've been trying to create a simple script for the player to animate its turning (rotation) programmatically since it will be based on AI. However, trying to make it rotate on angles 240-360 degrees makes it wrong. It seems that whenever I set the transform's theta to mDegToRad(240 to 360 degrees), the transform begins back to some different angle. Can someone explain to me what's wrong?
The modified player code:
datablock PlayerData(PlayerExample)
{
category = "Players";
renderFirstPerson = false;
shapeFile = "~/data/shapes/player/player.dts";
};
function PlayerData::create(%DB)
{
%obj = new Player() {
datablock = %DB;
myScheduledEvent = 0;
};
return %obj;
}
function PlayerExample::onAdd(%this, %obj)
{
//%this.MoveForward(%obj);
}
function PlayerExample::onRemove(%this, %obj)
{
}
function PlayerExample::onNewDataBlock(%this,%obj)
{
// Called when this PlayerData datablock is assigned to an object
}
function PlayerExample::MoveForward(%this, %obj)
{
%vector = VectorNormalize(%obj.getForwardVector());
%vector = VectorScale(%vector, 10.0);
%obj.setVelocity(%vector);
%obj.myScheduledEvent = %this.schedule(100, MoveForward, %obj);
}
function PlayerExample::Stop(%this, %obj)
{
cancel(%obj.myScheduledEvent);
}
function PlayerExample::AnimateRotate(%this, %obj, %degree)
{
echo("Target Degree = " @ %degree);
echo("Transform = " @ %obj.getTransform());
%curdegree = mRadToDeg(getWord(%obj.getTransform(), 6));
echo("Curdegree = " @ %curdegree);
if(mFloor(%curDegree) == mFloor(%degree))
{
cancel(%obj.myScheduledEvent);
//%obj.myScheduledEvent = %this.schedule(10, MoveForward, %obj);
return;
}
// Special case - Will not work correctly until the degree 240-360 is resolved.
//if(mFloor(%curdegree) == 0)
//{
//check a rotate starting from 360 degrees is shorter
// if((360-%degree) < %degree)
// {
// echo("Start from 360");
// %curdegree = 360;
// }
//}
if(%curdegree < %degree)
{
%curdegree = %curdegree + 1.0;
}
else if(%curdegree > %degree)
{
%curdegree = %curdegree - 1.0;
}
echo("New Curdegree = " @ %curdegree);
%transform = %obj.getPosition() SPC "0 0 1" SPC mDegToRad(%curdegree);
echo("New Transform = " @ %transform);
%obj.setTransform(%transform);
%obj.myScheduledEvent = %this.schedule(1, AnimateRotate, %obj, %degree);
}
function PlayerExample::onCollision(%colDB, %obj, %collidedDB, %collidedObj, %vec, %speed)
{
cancel(%obj.myScheduledEvent);
%colDB.AnimateRotate(%obj, 90);
}
#2
www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=9480
12/16/2006 (8:04 am)
Use my RotateShape resource instead, it implements all the changes you need and adds some nifty features.www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=9480
#3
I don't want to blame the error on the function mRadToDeg or mDegToRad which seems to what I see because I do rotating manually on the console:
any value of curdegree works.
12/16/2006 (9:03 pm)
I appreciate the resource. But I am more concerned of what I am doing wrong. So, I won't hit this wall again in case of I need this math again though, not on a "rotation" problem. You get what I mean? :)I don't want to blame the error on the function mRadToDeg or mDegToRad which seems to what I see because I do rotating manually on the console:
%obj.setTransform(%obj.getPosition() SPC "0 0 1" SPC mDegToRad(%curdegree));
any value of curdegree works.
#4
I think it because, according to the "brain" in the APP, going back in the other direction is the shortest distance.
When i need to go 360 or so, i rotate to 90 at the same pace, and do the rest to 360.
12/16/2006 (9:26 pm)
Well, if it helps, allot of times in some animation APPs rotating something 360 degrees, the item will rotate to 180 in the correct direction, and then the rest of the way in the wrong direction.I think it because, according to the "brain" in the APP, going back in the other direction is the shortest distance.
When i need to go 360 or so, i rotate to 90 at the same pace, and do the rest to 360.
#5
Good luck.
-tim
12/16/2006 (10:10 pm)
You'll find that you are not doing anything "wrong". Because of the way the engine is implemented, the interface is not as simple as it would seem and problems begin to show up around 240 degrees. The resource has code for one way to overcome this - there may be others. The resource represents the sum of my experiments in trying to provide smooth rotation for AI, exactly as you intend, so it should be what you need to evolve for the purpose.Good luck.
-tim
#6
12/17/2006 (3:54 am)
I see, so the engine do have some hocus pocus happening. At least, I now know I ain't doing wrong in the mathematical sense. Thanks. I guess I can move on now and read the resource.
#7
In TorqueScript, rotation values are required to be in radians, not degrees. To convert degrees into radians, TorqueScript provides two functions: mDegToRad() and mRadToDeg(). But I think it helps to first understand how they correlate. In degrees, a circle is a continuum from 0 to 360. In radians, (at least in Torque) a circle is a continuum from -3.14159 to 3.14159, but with its origin at 180 degrees, like in this picture:

But even that is not entirely correct. As shown in the next picture, in Torque the switch from negative radians to positive radians occurs at 240 degrees, not 180 degrees. I'm not sure why that is; perhaps someone else can explain the reasoning behind it:

So in TorqueScript, a rotation that falls between 0 and 240 degrees will be represented as a rotation of "0 0 1 ##" (where ## is a positive number between 0 and 4.18879), while a rotation that falls between 241 and 360 degrees will be represented as "0 0 1 -##" (where -## is a negative number between 0 and -2.09439).
So a complete rotation in Torquescript actually goes from -2.09439 to +4.18879, with the switch from positive to negative at the 240 degree mark.
If you don't follow this method, the engine starts doing some interesting things, usually by automatically switching negative numbers to positive numbers and vice-versa.
(minor edits)
12/17/2006 (8:55 am)
Here is an explanation I put together from a resource that I ended up not posting. Hope it helps some...In TorqueScript, rotation values are required to be in radians, not degrees. To convert degrees into radians, TorqueScript provides two functions: mDegToRad() and mRadToDeg(). But I think it helps to first understand how they correlate. In degrees, a circle is a continuum from 0 to 360. In radians, (at least in Torque) a circle is a continuum from -3.14159 to 3.14159, but with its origin at 180 degrees, like in this picture:

But even that is not entirely correct. As shown in the next picture, in Torque the switch from negative radians to positive radians occurs at 240 degrees, not 180 degrees. I'm not sure why that is; perhaps someone else can explain the reasoning behind it:

So in TorqueScript, a rotation that falls between 0 and 240 degrees will be represented as a rotation of "0 0 1 ##" (where ## is a positive number between 0 and 4.18879), while a rotation that falls between 241 and 360 degrees will be represented as "0 0 1 -##" (where -## is a negative number between 0 and -2.09439).
So a complete rotation in Torquescript actually goes from -2.09439 to +4.18879, with the switch from positive to negative at the 240 degree mark.
If you don't follow this method, the engine starts doing some interesting things, usually by automatically switching negative numbers to positive numbers and vice-versa.
(minor edits)
#8
Todd
12/17/2006 (9:50 am)
Rubes, this is really good to know. Thanks for posting this information.Todd
#9
(edit): Or at tleast that's what I remember seeing when debugging this. :o)
12/17/2006 (10:14 am)
@Rubes: I agree about the switching from positive to negative. But if you look carefully at the reource, I switched the %rz direction vector term rather than the angle because that is exactly what the engine will do if you do a getTransform at the boundary. So the resource seamlessly reflects what the engine is doing.(edit): Or at tleast that's what I remember seeing when debugging this. :o)
#10
12/17/2006 (1:25 pm)
@Tim: I haven't really looked at the resource, so I'm sure you're right.
Kuju Manila
Default Studio Name
Example Usage:
PlayerExample.AnimateRotate(MyInstantiatedPlayerExample, 90); //Rotate to 90 degrees.
*Assuming MyInstantiatedPlayerExample is the object's name.
Rotating it to 240 up to 360 is wrong.