Angles: entities "up" normal depending on its roll
Moderator: Moderators
I think the proper way to rotate an object would be to use matrix multiplication on its orientation vectors (upvector/leftvector) rather than trying to alter the objects angles.
You'd basically take the objects current orientation vectors, figure out what the axis and angle are of the rotation you want to perform, convert them to a rotation matrix, then multiply the matrix with the object's orientation vectors. Then the last step is to convert the new orientation vectors back to angles, which JV has already shown with the code for vectors_toangles.
Some info on matrices:
http://www.google.com/search?hl=en&q=ma ... ernion+faq
You'd basically take the objects current orientation vectors, figure out what the axis and angle are of the rotation you want to perform, convert them to a rotation matrix, then multiply the matrix with the object's orientation vectors. Then the last step is to convert the new orientation vectors back to angles, which JV has already shown with the code for vectors_toangles.
Some info on matrices:
http://www.google.com/search?hl=en&q=ma ... ernion+faq
New Gametypes for Medal of Honor
Capture-The-Flag | Freeze-Tag | Demolition
www.planetmedalofhonor.com/mefy
Capture-The-Flag | Freeze-Tag | Demolition
www.planetmedalofhonor.com/mefy
cool
but dont worry, thats just me, but if your sugesting what i think you are then i thought thats pretty much was jv was sugesting by the giving the code above. and ty for it jv
.
Im just messing now, its so hot i cant sleep so thought id come play with maths>..err:S
The code works nice, In a quick test i have a nice 90 degree spinning thing in the right directions now, i just have to work out how to deal with the direction vectors in less then 1 or 90 deg?, maybe thats what mefy is sugesting with the matrices. Then the unit vectors, direction vectors / orientation vectors. are they unit vectors right?..anyway..then convert them to angles.
alot of nice info on these pages:) It's like a museam!, cept without the coghing people and the ticket man, here is a "do not touch sign". no ift shop though:(.

to figure out what the axis and angle is the problem anyway , thats why use orientation vectors to work out where i want to look at, then convert them to angles using jv's code, then apply them angles to the plane. are am i heading down the wrong road in a caravan pulled by a robin reliant.You'd basically take the objects current orientation vectors, figure out what the axis and angle are of the rotation you want to perform, convert them to a rotation matrix,
but dont worry, thats just me, but if your sugesting what i think you are then i thought thats pretty much was jv was sugesting by the giving the code above. and ty for it jv
Im just messing now, its so hot i cant sleep so thought id come play with maths>..err:S
The code works nice, In a quick test i have a nice 90 degree spinning thing in the right directions now, i just have to work out how to deal with the direction vectors in less then 1 or 90 deg?, maybe thats what mefy is sugesting with the matrices. Then the unit vectors, direction vectors / orientation vectors. are they unit vectors right?..anyway..then convert them to angles.
alot of nice info on these pages:) It's like a museam!, cept without the coghing people and the ticket man, here is a "do not touch sign". no ift shop though:(.
Ya I kept the matrices out of there as to not make it more complicated than it already is
Still yes you can write the final coordinate system E as:
E = P * Y * R * I
Where P, Y, R are the rotation matrices for the p, y, r angles, * represents matrix multiplication and I is your base matrix, if it is { (1 0 0), (0 1 0), (0 0 1) } it may be omited.
Matrix multiplication is defined as:
A * B = C
A =
| a11 a12 a13 |
| a21 a22 a23 |
| a31 a32 a33 |
B =
| b11 b12 b13 |
| b21 b22 b23 |
| b31 b32 b33 |
Then C =
| (a11b11 + a12b21 + a13b31) (a11b12 + a12b22 + a13b32) (a11b13 + a12b23 + a13b33) |
| (a21b11 + a22b21 + a23b31) (a21b12 + a22b22 + a23b32) (a21b13 + a22b23 + a23b33) |
| (a31b11 + a32b21 + a33b31) (a31b12 + a32b22 + a33b32) (a31b13 + a32b23 + a33b33) |
Note that A * B != B * A, so order is important.
If you calc the matrix E all the way then its three columns will give you the unit vectors forward, left and up.
Now you only need to know P, Y and R, which are rotation matrices. Every rotation matrix has 2 fundamental properties:
Well they can be derived relatively easily, although it requires some knowledge of geometry.
Pardon my horrible drawing but it's supposed to show 2 orthogonal vectors x and y which are rotated by an angle 'a' to form vectors x',y'.
Then basic geometry says:
x' = x * cos(a) + y * sin(a)
y' = y * cos(a) - x * sin(a)
Which can be written in matrix form like this:
Where (x,y,z) is a vector of vectors.
A nicer form is:
Where [x' y' z'] and [x y z] are matrices, their columns formed by the entries of the vectors x',y',z' or x,y,z.
Hence the matrix Y is the matrix above.
Similar matrices can be derived for pitch and roll as well, and multiplying em all together (in the right order!) gives you a pile of crap aka the rotated coordinate system matrix E, which depends only on the values of p,y,r. I presume the game uses this matrix to calculate vertex locations etc for rotated objects.
Still yes you can write the final coordinate system E as:
E = P * Y * R * I
Where P, Y, R are the rotation matrices for the p, y, r angles, * represents matrix multiplication and I is your base matrix, if it is { (1 0 0), (0 1 0), (0 0 1) } it may be omited.
Matrix multiplication is defined as:
A * B = C
A =
| a11 a12 a13 |
| a21 a22 a23 |
| a31 a32 a33 |
B =
| b11 b12 b13 |
| b21 b22 b23 |
| b31 b32 b33 |
Then C =
| (a11b11 + a12b21 + a13b31) (a11b12 + a12b22 + a13b32) (a11b13 + a12b23 + a13b33) |
| (a21b11 + a22b21 + a23b31) (a21b12 + a22b22 + a23b32) (a21b13 + a22b23 + a23b33) |
| (a31b11 + a32b21 + a33b31) (a31b12 + a32b22 + a33b32) (a31b13 + a32b23 + a33b33) |
Note that A * B != B * A, so order is important.
If you calc the matrix E all the way then its three columns will give you the unit vectors forward, left and up.
Now you only need to know P, Y and R, which are rotation matrices. Every rotation matrix has 2 fundamental properties:
- If you square all entries in the matrix, then the sum of all squared entries in a single column will be 1; similarly the sum all squared entries in a single row will equal 1. This is because each matrix contains unit vectors which are mutually orthogonal.
- The matrix is anti-symmetrical, meaning that on each side of the main diagonal you will find the same entries, except with a - sign.
Well they can be derived relatively easily, although it requires some knowledge of geometry.
Code: Select all
y' ^ y
^ |
| |
| |
| | ___-> x'
||___---- ) yaw angle 'a'
---------------> x
Then basic geometry says:
x' = x * cos(a) + y * sin(a)
y' = y * cos(a) - x * sin(a)
Which can be written in matrix form like this:
Code: Select all
| x' | | cos(a) sin(a) 0 | | x |
| y' | = |-sin(a) cos(a) 0 | | y |
| z' | | 0 0 1 | | z |
A nicer form is:
Code: Select all
| cos(a) sin(a) 0 |
| x' y' z' | = |-sin(a) cos(a) 0 | | x y z |
| 0 0 1 |
Hence the matrix Y is the matrix above.
Code: Select all
Y =
| cos(a) sin(a) 0 |
|-sin(a) cos(a) 0 |
| 0 0 1 |
Last edited by jv_map on Thu Sep 22, 2005 12:53 pm, edited 2 times in total.
-
Rookie One.pl
- Site Admin
- Posts: 2752
- Joined: Fri Jan 31, 2003 7:49 pm
- Location: Nowa Wies Tworoska, Poland
- Contact:
I havent even struggled throguh Algebra 1 yet so this is like Einsteinium to me, so this advanced geometrical stuff is like ":o"
but hey, i'm coming back here after i get my mathematical education out of the sewers and i'll necro this post and say "That's wrong, it should be..."
jk.
^Yes, professor Vrijkorte
but hey, i'm coming back here after i get my mathematical education out of the sewers and i'll necro this post and say "That's wrong, it should be..."
Moderator
۞
Abyssus pro sapientia
Olympus pro Ignarus
۞
AND STUFF™ © 2006
۞
Abyssus pro sapientia
Olympus pro Ignarus
۞
AND STUFF™ © 2006
I think it would be great if Professor JV put this all together in a script
What Elgan could use is a thread for rotating an object around an arbitrary axis and angle, and then also three more threads to handle the special cases of doing a roll, pitch, or yaw rotation (which would just call the arbitrary case with the corresponding axis).
This matrix stuff is really fundamental to doing any 3d computer graphics so it's worth the time to figure out how it works. If you ever write your own 3d engine you'd be dealing with them a lot. OpenGL and Direct3d require you to provide matrices for various stuff.
What Elgan could use is a thread for rotating an object around an arbitrary axis and angle, and then also three more threads to handle the special cases of doing a roll, pitch, or yaw rotation (which would just call the arbitrary case with the corresponding axis).
This matrix stuff is really fundamental to doing any 3d computer graphics so it's worth the time to figure out how it works. If you ever write your own 3d engine you'd be dealing with them a lot. OpenGL and Direct3d require you to provide matrices for various stuff.
New Gametypes for Medal of Honor
Capture-The-Flag | Freeze-Tag | Demolition
www.planetmedalofhonor.com/mefy
Capture-The-Flag | Freeze-Tag | Demolition
www.planetmedalofhonor.com/mefy
Oh btw here is the method mefy suggested in case the aforementioned passer-by needs it and is too lazy to make it him/herself
I didn't make the special cases, as they're trivial anyway.
Use axisrotate to rotate any object about some axis defined by a vector. The angle of rotation is taken to be the length of the vector (so (0 0 0) corresponds to no rotation). The advantage of this is that you can add any number of small rotations together (by means of vector addition) and process the angles in one batch. Definately don't add rotations larger than ~5 degrees together, though. (if you want to do that you'll need slightly more advanced methods).
A simple example of a pitching aircraft
Good luck 
I didn't make the special cases, as they're trivial anyway.
Use axisrotate to rotate any object about some axis defined by a vector. The angle of rotation is taken to be the length of the vector (so (0 0 0) corresponds to no rotation). The advantage of this is that you can add any number of small rotations together (by means of vector addition) and process the angles in one batch. Definately don't add rotations larger than ~5 degrees together, though. (if you want to do that you'll need slightly more advanced methods).
Code: Select all
// a convenient way to invoke object rotation
// by jv_map
// rotates self around axis defined by vector local.axis in world space
// the angle of rotation is determined by the length of this vector (in radians, pi rad = 180 deg)
// rotation is right-handed (generally regarded as counter-clockwise,
// but it is clockwise when looking in the direction of the vector)
axisrotate local.axis:
// define this somewhere
level.PI = 3.1415926
// the angle of rotation
local.theta = vector_length local.axis
if(local.theta > 0.0)
{
// similar to vector_normalize but as the length is already known
// this saves a costly calculation
local.normal_axis = local.axis * (1.0 / local.theta)
local.cos_2 = waitthread cos (0.5 * local.theta)
local.sin_2 = waitthread sin (0.5 * local.theta)
// this is known as a quaternion representation
local.a = local.cos_2
local.b = local.sin_2 * local.normal_axis[0]
local.c = local.sin_2 * local.normal_axis[1]
local.d = local.sin_2 * local.normal_axis[2]
local.a2 = local.a * local.a
local.b2 = local.b * local.b
local.c2 = local.c * local.c
local.d2 = local.d * local.d
// make sure we're working with a unit quaternion
// (this should be the case automatically but in case there's a
// slight error in the sin or cos function this fixes it)
local.quat_length_squared = local.a2 + local.b2 + local.c2 + local.d2
local.quat_length = waitthread sqrt1 local.quat_length_squared
local.a = local.a / local.quat_length
local.b = local.b / local.quat_length
local.c = local.c / local.quat_length
local.d = local.d / local.quat_length
local.a2 = local.a2 / local.quat_length_squared
local.b2 = local.b2 / local.quat_length_squared
local.c2 = local.c2 / local.quat_length_squared
local.d2 = local.d2 / local.quat_length_squared
// these would be the fwd/lf/up vectors of the rotated system, if the initial rotation was zero (angles = (0 0 0))
// can't really explain this without major effort so best just believe it or look it up in a maths book (or wikipedia) ;)
local.rot[0] = ( (local.a2 + local.b2 - local.c2 - local.d2) (2 * local.a * local.d + 2 * local.b * local.c) (2 * local.b * local.d - 2 * local.a * local.c) )
local.rot[1] = ( (2 * local.b * local.c - 2 * local.a * local.d) (local.a2 - local.b2 + local.c2 - local.d2) (2 * local.a * local.b + 2 * local.c * local.d) )
local.rot[2] = ( (2 * local.a * local.c + 2 * local.b * local.d) (2 * local.c * local.d - 2 * local.a * local.b) (local.a2 - local.b2 - local.c2 + local.d2) )
// these are the vectors of the current coordinate system
local.fw = self.forwardvector
local.lf = self.leftvector
// (don't even need up as it is fully defined by fw and lf, but it can be included if you wish)
//local.up = self.upvector
// transform the current system to the rotated system by premultiplying
// with the above rotation matrix (fwd lf up)
local.new_fw = ( (local.rot[0][0] * local.fw[0] + local.rot[1][0] * local.fw[1] + local.rot[2][0] * local.fw[2]) (local.rot[0][1] * local.fw[0] + local.rot[1][1] * local.fw[1] + local.rot[2][1] * local.fw[2]) (local.rot[0][2] * local.fw[0] + local.rot[1][2] * local.fw[1] + local.rot[2][2] * local.fw[2]) )
local.new_lf = ( (local.rot[0][0] * local.lf[0] + local.rot[1][0] * local.lf[1] + local.rot[2][0] * local.lf[2]) (local.rot[0][1] * local.lf[0] + local.rot[1][1] * local.lf[1] + local.rot[2][1] * local.lf[2]) (local.rot[0][2] * local.lf[0] + local.rot[1][2] * local.lf[1] + local.rot[2][2] * local.lf[2]) )
// (don't even need up as it is fully defined by fw and lf, but it can be included if you wish)
//local.new_up = ( (local.rot[0][0] * local.up[0] + local.rot[1][0] * local.up[1] + local.rot[2][0] * local.up[2]) (local.rot[0][1] * local.up[0] + local.rot[1][1] * local.up[1] + local.rot[2][1] * local.up[2]) (local.rot[0][2] * local.up[0] + local.rot[1][2] * local.up[1] + local.rot[2][2] * local.up[2]) )
// yikes have to convert new coord system to silly angles
// this is somewhat sad as first thing mohaa does is
// probably convert the angles back to a coord system again
self.angles = waitthread vectors_toangles local.new_fw local.new_lf
}
end
// transforms vectors to angles (pitch,yaw,roll)
// unlike the script command vector_toangles this also accounts for roll properly
// returns angles in degrees
vectors_toangles local.vec_fwd local.vec_lf:
local.base_angles = vector_toangles local.vec_fwd
local.base_fwd = local.vec_fwd
local.base_lf = -1.0 * (angles_toleft local.base_angles)
local.base_up = vector_cross local.base_fwd local.base_lf
local.cos = local.vec_lf * local.base_lf
if(abs local.cos < 0.8)
{
local.roll_angle = waitthread arccos local.cos
if(local.vec_lf * local.base_up < 0.0)
{
local.roll_angle = -local.roll_angle
}
}
else
{
// arccos getting inaccurate here
// so just use arcsin instead
// (far more sensitive in this region)
local.sin = local.vec_lf * local.base_up
local.roll_angle = waitthread arcsin local.sin
if(local.cos < 0.0)
{
local.roll_angle = level.PI - local.roll_angle
}
}
// convert to degrees
local.roll_angle = local.roll_angle / level.PI * 180.0
local.angles = local.base_angles
local.angles[2] = local.roll_angle
end local.angles
// cheapest square-root approximation ever, but it almost overtakes light :)
// only usuable near x=1
sqrt1 local.x:
// McLaurin expansion
local.result = 0.5 + 0.5 * local.x - 0.125 * (local.x - 1.0) * (local.x - 1.0)
end local.result
// sin(x), x in rad
sin local.x:
end (waitthread cos(local.x - 0.5 * level.PI))
// cos(x), x in rad
cos local.x:
// reduce to [0,2pi]
if(local.x > 2.0 * level.PI)
{
local.x -= (int (local.x / (2.0 * level.PI))) * 2.0 * level.PI
}
else if(local.x < 0.0)
{
local.x += ((int ( -local.x / (2.0 * level.PI))) + 1) * 2.0 * level.PI
}
// reduce to [-pi,pi]
if(local.x > level.PI)
{
local.x -= 2.0 * level.PI
}
// 10th order Taylor series expansion
// should be sufficiently accurate
local.x2 = local.x * local.x
local.x4 = local.x2 * local.x2
local.x6 = local.x4 * local.x2
local.x8 = local.x6 * local.x2
local.x10 = local.x8 * local.x2
local.cosx = 1.0 - local.x2 / 2.0 + local.x4 / 24.0 - local.x6 / 720.0 + local.x8 / 40320.0 - local.x10 / 3628800.0
if(local.cosx > 1.0)
{
local.cosx = 1.0
}
else if(local.cosx < -1.0)
{
local.cosx = -1.0
}
end local.cosx
// inverse sin
// somewhat inaccurate near +-0.5PI
arcsin local.x:
if(local.x < -0.857 || local.x > 0.857)
{
// some empirical 9th order approximation
// I magically extracted this from the blue blue sky :)
local.x3 = local.x * local.x * local.x
local.x9 = local.x3 * local.x3 * local.x3
local.out = local.x + (0.5 * level.PI - 1.0) * local.x9
}
else
{
local.x2 = local.x * local.x
local.x3 = local.x2 * local.x
local.x5 = local.x3 * local.x2
// 5th order Taylor series expansion
local.out = local.x + 0.1667 * local.x3 + 0.075 * local.x5
}
end local.out
// inverse cos
arccos local.rad:
local.result = 0.5 * level.PI - (waitthread arcsin local.rad)
end local.result
Code: Select all
// self is your plane
self.angles = (....) // pick a nice set of angles
while(self)
{
waitthread axisrotate (self.leftvector * 0.04) // ~45 deg/s
waitframe
}
roll
Lots of people have tried to make a plane do a barrel roll and, as far as I know, no one has. The problem is that when the plane gets halfway through the roll it rolls back the way it came instead of going over. I tried for a couple of weeks, with spline paths, and never got it to work.
There is a problem with moving objects on three axis at the same time. With a lot of help, I managed to get a pair of doors to open on three axis, but I had to use a pair of script_origins to do it.
http://dynamic.gamespy.com/~map/mohaa/f ... php?t=7209
There is a problem with moving objects on three axis at the same time. With a lot of help, I managed to get a pair of doors to open on three axis, but I had to use a pair of script_origins to do it.
http://dynamic.gamespy.com/~map/mohaa/f ... php?t=7209
it's angles are set back by the splin i guess, u cud always create a path without a spline and script the movement.
or maybe you could use a spline, make a script object thing follow the spline instead of the plane. Then make the plane follow the object.
and jv thanx for the scripts, i didnt look at them yet as im doing other things for moh and playing fakk2:P. Will let you know how things go on when i try:D
or maybe you could use a spline, make a script object thing follow the spline instead of the plane. Then make the plane follow the object.
and jv thanx for the scripts, i didnt look at them yet as im doing other things for moh and playing fakk2:P. Will let you know how things go on when i try:D



