I have just finished writing some rotation functions. I was going to use quaternions but couldn't figure them out for the life of me, so I wrote them in a way that made sense to me. You can also rotate object about any desired axis. Current list of functions:
Lowerlogic's Rotation Commands
Global/World Axis Rotation:
Rotate_GX(object number, angle)
Rotate_GY(object number, angle)
Rotate_GZ(object number, angle)
Local/Relative Axis Rotation:
Rotate_LX(object number, angle)
Rotate_LY(object number, angle)
Rotate_LZ(object number, angle)
Arbitrary Axis rotation:
Rotate_Axis(object number, axis_x, axis_y, axis_z, angle)
Align_Axes(object number, local_axis_x, local_axis_y, local_axis_z, global_axis_x, global_axis_y, global_axis_z)
Smooth_Align_Axes(object number, local_axis_x, local_axis_y, local_axis_z, global_axis_x, global_axis_y, global_axis_z,max_angle_turn_amount)
Angle_Axes(object number, local_axis_x, local_axis_y, local_axis_z, global_axis_x, global_axis_y, global_axis_z,desired_angle,flag)
Smooth_Angle_Axes(object number, local_axis_x, local_axis_y, local_axis_z, global_axis_x, global_axis_y, global_axis_z,desired_angle,flag,max_angle_turn_amount)
Orbit(object number,point_x,point_y,point_z, axis_x, axis_y, axis_z, angle)
Other Functions
AngleBetweenPoints(originX#, originY#, originZ#, point1X#, point1Y#, point1Z#, point2X#, point2Y#, point2Z#)
Get Angle Functions
Axis_Angle_X(object number,y_axis_x,y_axis_y,y_axis_z)
Axis_Angle_Y(object number,y_axis_x,y_axis_y,y_axis_z)
Axis_Angle_Z(object number,y_axis_x,y_axis_y,y_axis_z)
remstart
Lowerlogic's Rotation Commands
Global/World Axis Rotation:
Rotate_GX(object number, angle)
Rotate_GY(object number, angle)
Rotate_GZ(object number, angle)
Local/Relative Axis Rotation:
Rotate_LX(object number, angle)
Rotate_LY(object number, angle)
Rotate_LZ(object number, angle)
Arbitrary Axis rotation:
Rotate_Axis(object number, axis_x, axis_y, axis_z, angle)
Align_Axes(object number, local_axis_x, local_axis_y, local_axis_z, global_axis_x, global_axis_y, global_axis_z)
Smooth_Align_Axes(object number, local_axis_x, local_axis_y, local_axis_z, global_axis_x, global_axis_y, global_axis_z,max_angle_turn_amount)
Angle_Axes(object number, local_axis_x, local_axis_y, local_axis_z, global_axis_x, global_axis_y, global_axis_z,desired_angle,flag)
Smooth_Angle_Axes(object number, local_axis_x, local_axis_y, local_axis_z, global_axis_x, global_axis_y, global_axis_z,desired_angle,flag,max_angle_turn_amount)
Orbit(object number,point_x,point_y,point_z, axis_x, axis_y, axis_z, angle)
Other Functions
AngleBetweenPoints(originX#, originY#, originZ#, point1X#, point1Y#, point1Z#, point2X#, point2Y#, point2Z#)
Get Angle Functions
Axis_Angle_X(object number,y_axis_x,y_axis_y,y_axis_z)
Axis_Angle_Y(object number,y_axis_x,y_axis_y,y_axis_z)
Axis_Angle_Z(object number,y_axis_x,y_axis_y,y_axis_z)
remend
sync on
sync rate 0
cls
hide mouse
set display mode 1024,768,32
autocam off
rem make object to rotate
make object box 1,2,1,4
make object box 11,1,1,1
position object 11,0,1,-1
glue object to limb 11,1,0
rem make 3 boxes to show x/y/z world axes
make object box 2,1000,0.1,0.1
make object box 3,0.1,1000,0.1
make object box 4,0.1,0.1,1000
rem main loop
do
set cursor 0,0
rem camera
position camera 0,0,0
rotate camera cx#,cy#,0
move camera -6
mmx=mousemovex()
mmy=mousemovey()
if mouseclick()=0
cx#=cx#+mmy
cy#=cy#+mmx
else
cx2#=cx2#+mmy
cy2#=cy2#+mmx
endif
turn camera right cy2#
pitch camera down cx2#
` rotate object 1,object angle x(1)+(keystate(16)-keystate(30))*0.5,object angle y(1)+(keystate(17)-keystate(31))*0.5,object angle z(1)+(keystate(18)-keystate(32))*0.5
rem global rotation
rotate_GX(1,(keystate(16)-keystate(30))*0.5)
rotate_GY(1,(keystate(17)-keystate(31))*0.5)
rotate_GZ(1,(keystate(18)-keystate(32))*0.5)
rem arbitrary axis rotation
x#=camera position x():y#=camera position y():z#=camera position z()
move camera 1
nx#=camera position x()-x#:ny#=camera position y()-y#:nz#=camera position z()-z#
move camera -1
rotate_axis(1,nx#,ny#,nz#,(keystate(19)-keystate(33))*0.5)
dx#=camera position x()-object position x(1)
dy#=camera position y()-object position y(1)
dz#=camera position z()-object position z(1)
rem local axis rotation
rotate_LX(1,(keystate(20)-keystate(34))*0.5)
rotate_LY(1,(keystate(21)-keystate(35))*0.5)
rotate_LZ(1,(keystate(22)-keystate(36))*0.5)
orbit(1,x#,y#,z#,nx#,ny#,nz#,(keystate(23)-keystate(37))*0.5)
rem display
print "Rotation Controls:"
print "Global X Axis:Q/A"
print "Global Y Axis:W/S"
print "Global Z Axis:E/D"
print "Arbitrary Axis (The camera's view direction): R/F"
print "Local X Axis:T/G"
print "Local Y Axis:Y/H"
print "Local Z Axis:U/J"
print "Object angle X:",object angle x(1)
print "Object angle Y:",object angle y(1)
print "Object angle Z:",object angle z(1)
x#=object position x(1):y#=object position y(1):z#=object position z(1)
move object up 1,1
yx#=object position x(1)-x#:yy#=object position y(1)-y#:yz#=object position z(1)-z#
move object down 1,1
print "Angle between local y axis and global y axis:",AngleBetweenPoints(0,0,0,0,1,0,yx#,yy#,yz#)
print "Axis angle y(1,0,1,0):",Axis_Angle_Y(1,0,1,0)
print "Axis angle x(1,0,1,0):",Axis_Angle_X(1,0,1,0)
print "Axis angle z(1,0,1,0):",Axis_Angle_Z(1,0,1,0)
print "Angle restriction modes:"
print "1 - No Restrictions"
print "2 - Align Local Y Axis to Global Y Axis"
print "3 - FPS-like rotation"
print "4 - Turn to camera"
print "5 - Turn to camera with loose fps rotation restrictions"
for n=2 to 8
if keystate(n)=1
mode=n-2
endif
next n
if mode=1
Align_Axes(1,0,1,0,0,1,0)
endif
if mode=2
Rem if angle between local y axis and global y axis > 85 degrees, then rotate object such that it is 85 degrees
rem keeps the object from flipping at poles
Angle_Axes(1,0,1,0,0,1,0,85,1)
Rem always keep local x axis and global y axis perpendicular (no local z axis rotation)
Angle_Axes(1,1,0,0,0,1,0,90,0)
endif
if mode=3
Rem point the object at the camera
rem limit rotation to a max of 0.5 degrees.
Smooth_Align_Axes(1,0,0,1,dx#,dy#,dz#,0.5)
endif
if mode=4
Rem point the object at the camera
rem limit rotation to a max of 0.5 degrees.
Smooth_Align_Axes(1,0,0,1,dx#,dy#,dz#,0.5)
Rem if angle between local y axis and global y axis > 85 degrees, then try to rotate object such that it is 85 degrees
Smooth_Angle_Axes(1,0,1,0,0,1,0,85,1,0.2)
Rem try keep local x axis and global y axis perpendicular
Smooth_Angle_Axes(1,1,0,0,0,1,0,90,0,0.1)
endif
print "Mode:",mode+1
sync
loop
remstart Rotate_GX
This function rotates the given object around the global (world) x axis by
the given amount.
Param obj The object to rotate
Param amount# The angle to rotate the object by
remend
function rotate_GX(obj as integer,amount# as float)
rem get normal vectors for X, Y, and Z axes of the object
x#=object position x(obj):y#=object position y(obj):z#=object position z(obj)
move object right obj,1
xx#=object position x(obj)-x#:xy#=object position y(obj)-y#:xz#=object position z(obj)-z#
move object left obj,1:move object up obj,1
yx#=object position x(obj)-x#:yy#=object position y(obj)-y#:yz#=object position z(obj)-z#
move object down obj,1:move object obj,1
zx#=object position x(obj)-x#:zy#=object position y(obj)-y#:zz#=object position z(obj)-z#
move object obj,-1
rem rotate the vectors
xx1#=xx#
xy1#=xy#*cos(amount#)-xz#*sin(amount#)
xz1#=xz#*cos(amount#)+xy#*sin(amount#)
zx1#=zx#
zy1#=zy#*cos(amount#)-zz#*sin(amount#)
zz1#=zz#*cos(amount#)+zy#*sin(amount#)
rem calculate angle z
zr#=atanfull(xy1#,xx1#)
rem calculate angle y
xx2#=xx1#*cos(zr#)+xy1#*sin(zr#)
xy2#=xy1#*cos(zr#)-xx1#*sin(zr#)
xz2#=xz1#
zx2#=zx1#*cos(zr#)+zy1#*sin(zr#)
zy2#=zy1#*cos(zr#)-zx1#*sin(zr#)
zz2#=zz1#
yr#=atanfull(xx2#,xz2#)-90
rem calculate angle x
zx3#=zx2#*cos(yr#+90)-zz2#*sin(yr#+90)
zy3#=zy2#
xr#=atanfull(zy3#,zx3#)+180
if xr#+1>xr# and yr#+1>yr# and zr#+1>zr#
rotate object obj,xr#,yr#,zr#
endif
endfunction
remstart Rotate_GY
This function rotates the given object around the global (world) y axis by
the given amount.
Param obj The object to rotate
Param amount# The angle to rotate the object by
remend
function rotate_GY(obj,amount#)
rem get normal vectors for X, Y, and Z axes of the object
x#=object position x(obj):y#=object position y(obj):z#=object position z(obj)
move object right obj,1
xx#=object position x(obj)-x#:xy#=object position y(obj)-y#:xz#=object position z(obj)-z#
move object left obj,1:move object up obj,1
yx#=object position x(obj)-x#:yy#=object position y(obj)-y#:yz#=object position z(obj)-z#
move object down obj,1:move object obj,1
zx#=object position x(obj)-x#:zy#=object position y(obj)-y#:zz#=object position z(obj)-z#
move object obj,-1
rem rotate the vectors
xx1#=xx#*cos(amount#)+xz#*sin(amount#)
xy1#=xy#
xz1#=xz#*cos(amount#)-xx#*sin(amount#)
zx1#=zx#*cos(amount#)+zz#*sin(amount#)
zy1#=zy#
zz1#=zz#*cos(amount#)-zx#*sin(amount#)
rem calculate angle z
zr#=atanfull(xy1#,xx1#)
rem calculate angle y
xx2#=xx1#*cos(zr#)+xy1#*sin(zr#)
xy2#=xy1#*cos(zr#)-xx1#*sin(zr#)
xz2#=xz1#
zx2#=zx1#*cos(zr#)+zy1#*sin(zr#)
zy2#=zy1#*cos(zr#)-zx1#*sin(zr#)
zz2#=zz1#
yr#=atanfull(xx2#,xz2#)-90
rem calculate angle x
zx3#=zx2#*cos(yr#+90)-zz2#*sin(yr#+90)
zy3#=zy2#
xr#=atanfull(zy3#,zx3#)+180
if xr#+1>xr# and yr#+1>yr# and zr#+1>zr#
rotate object obj,xr#,yr#,zr#
endif
endfunction
remstart Rotate_GZ
This function rotates the given object around the global (world) z axis by
the given amount.
Param obj The object to rotate
Param amount# The angle to rotate the object by
remend
function rotate_GZ(obj,amount#)
rem Rotating around the global Z axis is trivial
rem as it is the first rotation anyway in the default ZYX rotation order
rotate object obj,object angle x(obj),object angle y(obj),object angle z(obj)+amount#
endfunction
remstart Rotate_axis
This function rotates the given object around the given axis by the given
amount. This function is called by many other functions.
Param obj The object to rotate
Param ax#,ay#,az# The x,y and z components of the rotation axis
Param amount# The angle to rotate the object by
remend
function rotate_axis(obj,ax#,ay#,az#,amount#)
rem get normal vectors for X, Y, and Z axes of the object
x#=object position x(obj):y#=object position y(obj):z#=object position z(obj)
move object right obj,1
xx#=object position x(obj)-x#:xy#=object position y(obj)-y#:xz#=object position z(obj)-z#
move object left obj,1:move object up obj,1
yx#=object position x(obj)-x#:yy#=object position y(obj)-y#:yz#=object position z(obj)-z#
move object down obj,1:move object obj,1
zx#=object position x(obj)-x#:zy#=object position y(obj)-y#:zz#=object position z(obj)-z#
move object obj,-1
rem rotate the vectors
rem 1) rotate space about the x axis so that the rotation axis lies in the xz plane
xangle#=atanfull(ay#,az#)
xx1#=xx#
xy1#=xy#*cos(xangle#)-xz#*sin(xangle#)
xz1#=xz#*cos(xangle#)+xy#*sin(xangle#)
zx1#=zx#
zy1#=zy#*cos(xangle#)-zz#*sin(xangle#)
zz1#=zz#*cos(xangle#)+zy#*sin(xangle#)
ax1#=ax#
ay1#=ay#*cos(xangle#)-az#*sin(xangle#)
az1#=az#*cos(xangle#)+ay#*sin(xangle#)
rem 2) rotate space about the y axis so that the rotation axis lies along the z axis
yangle#=-atanfull(ax1#,az1#)
xx2#=xx1#*cos(yangle#)+xz1#*sin(yangle#)
xy2#=xy1#
xz2#=xz1#*cos(yangle#)-xx1#*sin(yangle#)
zx2#=zx1#*cos(yangle#)+zz1#*sin(yangle#)
zy2#=zy1#
zz2#=zz1#*cos(yangle#)-zx1#*sin(yangle#)
ax2#=ax1#*cos(yangle#)+az1#*sin(yangle#)
ay2#=ay1#
az2#=az1#*cos(yangle#)-ax1#*sin(yangle#)
rem 3) perform the desired rotation by theta about the z axis
xx3#=xx2#*cos(amount#)-xy2#*sin(amount#)
xy3#=xy2#*cos(amount#)+xx2#*sin(amount#)
xz3#=xz2#
zx3#=zx2#*cos(amount#)-zy2#*sin(amount#)
zy3#=zy2#*cos(amount#)+zx2#*sin(amount#)
zz3#=zz2#
rem 4) Inverse of step 2
xx4#=xx3#*cos(-yangle#)+xz3#*sin(-yangle#)
xy4#=xy3#
xz4#=xz3#*cos(-yangle#)-xx3#*sin(-yangle#)
zx4#=zx3#*cos(-yangle#)+zz3#*sin(-yangle#)
zy4#=zy3#
zz4#=zz3#*cos(-yangle#)-zx3#*sin(-yangle#)
rem 5) Inverse of step 1
xx1#=xx4#
xy1#=xy4#*cos(-xangle#)-xz4#*sin(-xangle#)
xz1#=xz4#*cos(-xangle#)+xy4#*sin(-xangle#)
zx1#=zx4#
zy1#=zy4#*cos(-xangle#)-zz4#*sin(-xangle#)
zz1#=zz4#*cos(-xangle#)+zy4#*sin(-xangle#)
rem calculate angle z
zr#=atanfull(xy1#,xx1#)
rem calculate angle y
xx2#=xx1#*cos(zr#)+xy1#*sin(zr#)
xy2#=xy1#*cos(zr#)-xx1#*sin(zr#)
xz2#=xz1#
zx2#=zx1#*cos(zr#)+zy1#*sin(zr#)
zy2#=zy1#*cos(zr#)-zx1#*sin(zr#)
zz2#=zz1#
yr#=atanfull(xx2#,xz2#)-90
rem calculate angle x
zx3#=zx2#*cos(yr#+90)-zz2#*sin(yr#+90)
zy3#=zy2#
xr#=atanfull(zy3#,zx3#)+180
if xr#+1>xr# and yr#+1>yr# and zr#+1>zr#
rotate object obj,xr#,yr#,zr#
endif
endfunction
remstart Rotate_LX
This function rotates the given object around the object's local x axis by
the given amount. This function calls rotate_axis() to do the rotation.
Param obj The object to rotate
Param amount# The angle to rotate the object by
remend
function rotate_LX(obj as integer,amount# as float)
rem Rotating around the local X axis is trivial
rem as it is the last rotation anyway in the default ZYX rotation order
rotate object obj,object angle x(obj)+amount#,object angle y(obj),object angle z(obj)
endfunction
remstart Rotate_LY
This function rotates the given object around the object's local y axis by
the given amount. This function calls rotate_axis() to do the rotation.
Param obj The object to rotate
Param amount# The angle to rotate the object by
remend
function rotate_LY(obj as integer,amount# as float)
x#=object position x(obj):y#=object position y(obj):z#=object position z(obj)
move object up obj,1
yx#=object position x(obj)-x#:yy#=object position y(obj)-y#:yz#=object position z(obj)-z#
move object down obj,1
rotate_axis(obj,yx#,yy#,yz#,amount#)
endfunction
remstart Rotate_LZ
This function rotates the given object around the object's local z axis by
the given amount. This function calls rotate_axis() to do the rotation.
Param obj The object to rotate
Param amount# The angle to rotate the object by
remend
function rotate_LZ(obj as integer,amount# as float)
x#=object position x(obj):y#=object position y(obj):z#=object position z(obj)
move object obj,1
zx#=object position x(obj)-x#:zy#=object position y(obj)-y#:zz#=object position z(obj)-z#
move object obj,-1
rotate_axis(obj,zx#,zy#,zz#,amount#)
endfunction
remstart AngleBetweenPoints
This function takes an origin and 2 points and finds the angle between them
through the given origin.
Param originX#,originY#,originX# The point that is to be the origin
Param point1X#,point1Y#,point1Z# The first point
Param point2X#,point2Y#,point2Z# The second point
Return angle# The angle between the 2 points
remend
function AngleBetweenPoints(originX#, originY#, originZ#, point1X#, point1Y#, point1Z#, point2X#, point2Y#, point2Z#)
v1x#=point1X#-originX#
v1y#=point1Y#-originY#
v1z#=point1Z#-originZ#
v1#=sqrt(v1x#*v1x#+v1y#*v1y#+v1z#*v1z#)
v2x#=point2X#-originX#
v2y#=point2Y#-originY#
v2z#=point2Z#-originZ#
v2#=sqrt(v2x#*v2x#+v2y#*v2y#+v2z#*v2z#)
angle#=acos((v1x#*v2x#+v1y#*v2y#+v1z#*v2z#)/(v1#*v2#))
endfunction angle#
remstart Align_Axes
This function aligns an arbitrary axis local to the object to an arbitrary
global axis. When called every frame, the function effectively "locks" the
object so that it can only rotate around the given global axis.
Param obj The object to rotate
Param lx#,ly#,lz# The local axis
Param gx#,gy#,gz# The global axis
remend
function Align_Axes(obj,lx#,ly#,lz#,gx#,gy#,gz#)
x#=object position x(obj):y#=object position y(obj):z#=object position z(obj)
move object right obj,lx#:move object up obj,ly#:move object obj,lz#
glx#=object position x(obj)-x#:gly#=object position y(obj)-y#:glz#=object position z(obj)-z#
move object right obj,-lx#:move object up obj,-ly#:move object obj,-lz#
l#=sqrt(glx#^2+gly#^2+glz#^2)
g#=sqrt(gx#^2+gy#^2+gz#^2)
angle#=acos((glx#*gx#+gly#*gy#+glz#*gz#)/(l#*g#))
crosspx#=(gly# * gz# - glz# * gy#)
crosspy#=(glz# * gx# - glx# * gz#)
crosspz#=(glx# * gy# - gly# * gx#)
rotate_axis(obj,crosspx#,crosspy#,crosspz#,angle#)
endfunction
remstart Smooth_Align_Axes
This function aligns an arbitrary axis local to the object to an arbitrary
global axis. The function will rotate no more than the given maximum angle
so that the alignment can be smoothed out over multiple frames.
Param obj The object to rotate
Param lx#,ly#,lz# The local axis
Param gx#,gy#,gz# The global axis
Param max_angle# The maximum angle by which the object may be rotated
remend
function Smooth_Align_Axes(obj,lx#,ly#,lz#,gx#,gy#,gz#,max_angle#)
x#=object position x(obj):y#=object position y(obj):z#=object position z(obj)
move object right obj,lx#:move object up obj,ly#:move object obj,lz#
glx#=object position x(obj)-x#:gly#=object position y(obj)-y#:glz#=object position z(obj)-z#
move object right obj,-lx#:move object up obj,-ly#:move object obj,-lz#
l#=sqrt(glx#^2+gly#^2+glz#^2)
g#=sqrt(gx#^2+gy#^2+gz#^2)
angle#=acos((glx#*gx#+gly#*gy#+glz#*gz#)/(l#*g#))
if angle#>max_angle#
angle#=max_angle#
endif
if angle#<-max_angle#
angle#=-max_angle#
endif
crosspx#=(gly# * gz# - glz# * gy#)
crosspy#=(glz# * gx# - glx# * gz#)
crosspz#=(glx# * gy# - gly# * gx#)
rotate_axis(obj,crosspx#,crosspy#,crosspz#,angle#)
endfunction
remstart Angle_Axes
This function rotates the object such that the given local axis has an angle
equal to the given angle with the global axis. Al
Param obj The object to rotate
Param lx#,ly#,lz# The local axis
Param gx#,gy#,gz# The global axis
Param ang# The given angle to keep between the local and global
axes. Flag also uses it to provide more functionality.
Param flag Used to decide when to perform the actual rotation
Flag Usage:
If flag=0, the rotation will occur.
If flag<0, the rotation will occur if the angle between the axes is less
than the given angle.
If flag>0, the rotation will occur if the angle between the axes is
greater than the given angle.
remend
function Angle_Axes(obj,lx#,ly#,lz#,gx#,gy#,gz#,ang#,flag)
x#=object position x(obj):y#=object position y(obj):z#=object position z(obj)
move object right obj,lx#:move object up obj,ly#:move object obj,lz#
glx#=object position x(obj)-x#:gly#=object position y(obj)-y#:glz#=object position z(obj)-z#
move object right obj,-lx#:move object up obj,-ly#:move object obj,-lz#
l#=sqrt(glx#^2+gly#^2+glz#^2)
g#=sqrt(gx#^2+gy#^2+gz#^2)
angle#=acos((glx#*gx#+gly#*gy#+glz#*gz#)/(l#*g#))
angle#=angle#-ang#
if flag=0 or (flag<0 and angle#<0) or (flag>0 and angle#>0)
crosspx#=(gly# * gz# - glz# * gy#)
crosspy#=(glz# * gx# - glx# * gz#)
crosspz#=(glx# * gy# - gly# * gx#)
rotate_axis(obj,crosspx#,crosspy#,crosspz#,angle#)
endif
endfunction
remstart Angle_Axes
This function rotates the object such that the given local axis has an angle
equal to the given angle with the global axis. The function will rotate no
more than the given maximum angle so that the alignment can be smoothed out
over multiple frames.
Param obj The object to rotate
Param lx#,ly#,lz# The local axis
Param gx#,gy#,gz# The global axis
Param ang# The given angle to keep between the local and global
axes. Flag also uses it to provide more functionality.
Param flag Used to decide when to perform the actual rotation
Param max_angle# The maximum angle by which the object may be rotated
Flag Usage:
If flag=0, the rotation will occur.
If flag<0, the rotation will occur if the angle between the axes is less
than the given angle.
If flag>0, the rotation will occur if the angle between the axes is
greater than the given angle.
remend
function Smooth_Angle_Axes(obj,lx#,ly#,lz#,gx#,gy#,gz#,ang#,flag,max_angle#)
x#=object position x(obj):y#=object position y(obj):z#=object position z(obj)
move object right obj,lx#:move object up obj,ly#:move object obj,lz#
glx#=object position x(obj)-x#:gly#=object position y(obj)-y#:glz#=object position z(obj)-z#
move object right obj,-lx#:move object up obj,-ly#:move object obj,-lz#
l#=sqrt(glx#^2+gly#^2+glz#^2)
g#=sqrt(gx#^2+gy#^2+gz#^2)
angle#=acos((glx#*gx#+gly#*gy#+glz#*gz#)/(l#*g#))
angle#=angle#-ang#
if flag=0 or (flag<0 and angle#<0) or (flag>0 and angle#>0)
if angle#>max_angle#
angle#=max_angle#
endif
if angle#<-max_angle#
angle#=-max_angle#
endif
crosspx#=(gly# * gz# - glz# * gy#)
crosspy#=(glz# * gx# - glx# * gz#)
crosspz#=(glx# * gy# - gly# * gx#)
rotate_axis(obj,crosspx#,crosspy#,crosspz#,angle#)
endif
endfunction
function Axis_Angle_Y(obj,ayx#,ayy#,ayz#)
rem get normal vectors for X, Y, and Z axes of the object
x#=object position x(obj):y#=object position y(obj):z#=object position z(obj)
move object right obj,1
xx#=object position x(obj)-x#:xy#=object position y(obj)-y#:xz#=object position z(obj)-z#
move object left obj,1:move object up obj,1
yx#=object position x(obj)-x#:yy#=object position y(obj)-y#:yz#=object position z(obj)-z#
move object down obj,1:move object obj,1
zx#=object position x(obj)-x#:zy#=object position y(obj)-y#:zz#=object position z(obj)-z#
move object obj,-1
rem rotate the vectors
rem 1) rotate space about the x axis so that the rotation axis lies in the xz plane
xangle#=atanfull(ayy#,ayz#)
xx1#=xx#
xy1#=xy#*cos(xangle#)-xz#*sin(xangle#)
xz1#=xz#*cos(xangle#)+xy#*sin(xangle#)
zx1#=zx#
zy1#=zy#*cos(xangle#)-zz#*sin(xangle#)
zz1#=zz#*cos(xangle#)+zy#*sin(xangle#)
ayx1#=ayx#
ayy1#=ayy#*cos(xangle#)-ayz#*sin(xangle#)
ayz1#=ayz#*cos(xangle#)+ayy#*sin(xangle#)
rem 2) rotate space about the y axis so that the rotation axis lies along the z axis
yangle#=-atanfull(ayx1#,ayz1#)
xx2#=xx1#*cos(yangle#)+xz1#*sin(yangle#)
xy2#=xy1#
xz2#=xz1#*cos(yangle#)-xx1#*sin(yangle#)
zx2#=zx1#*cos(yangle#)+zz1#*sin(yangle#)
zy2#=zy1#
zz2#=zz1#*cos(yangle#)-zx1#*sin(yangle#)
ayx2#=ayx1#*cos(yangle#)+ayz1#*sin(yangle#)
ayy2#=ayy1#
ayz2#=ayz1#*cos(yangle#)-ayx1#*sin(yangle#)
rem 3) perform the desired rotation by theta about the z axis
xx3#=xx2#*cos(amount#)-xy2#*sin(amount#)
xy3#=xy2#*cos(amount#)+xx2#*sin(amount#)
xz3#=xz2#
zx3#=zx2#*cos(amount#)-zy2#*sin(amount#)
zy3#=zy2#*cos(amount#)+zx2#*sin(amount#)
zz3#=zz2#
angle#=wrapvalue(atanfull(zx3#,-zy3#))
endfunction angle#
function Axis_Angle_X(obj,ayx#,ayy#,ayz#)
rem get normal vectors for X, Y, and Z axes of the object
x#=object position x(obj):y#=object position y(obj):z#=object position z(obj)
move object right obj,1
xx#=object position x(obj)-x#:xy#=object position y(obj)-y#:xz#=object position z(obj)-z#
move object left obj,1:move object up obj,1
yx#=object position x(obj)-x#:yy#=object position y(obj)-y#:yz#=object position z(obj)-z#
move object down obj,1:move object obj,1
zx#=object position x(obj)-x#:zy#=object position y(obj)-y#:zz#=object position z(obj)-z#
move object obj,-1
rem rotate the vectors
rem 1) rotate space about the x axis so that the rotation axis lies in the xz plane
xangle#=atanfull(ayy#,ayz#)
xx1#=xx#
xy1#=xy#*cos(xangle#)-xz#*sin(xangle#)
xz1#=xz#*cos(xangle#)+xy#*sin(xangle#)
zx1#=zx#
zy1#=zy#*cos(xangle#)-zz#*sin(xangle#)
zz1#=zz#*cos(xangle#)+zy#*sin(xangle#)
ayx1#=ayx#
ayy1#=ayy#*cos(xangle#)-ayz#*sin(xangle#)
ayz1#=ayz#*cos(xangle#)+ayy#*sin(xangle#)
rem 2) rotate space about the y axis so that the rotation axis lies along the z axis
yangle#=-atanfull(ayx1#,ayz1#)
xx2#=xx1#*cos(yangle#)+xz1#*sin(yangle#)
xy2#=xy1#
xz2#=xz1#*cos(yangle#)-xx1#*sin(yangle#)
zx2#=zx1#*cos(yangle#)+zz1#*sin(yangle#)
zy2#=zy1#
zz2#=zz1#*cos(yangle#)-zx1#*sin(yangle#)
ayx2#=ayx1#*cos(yangle#)+ayz1#*sin(yangle#)
ayy2#=ayy1#
ayz2#=ayz1#*cos(yangle#)-ayx1#*sin(yangle#)
rem 3) perform the desired rotation by theta about the z axis
xx3#=xx2#*cos(amount#)-xy2#*sin(amount#)
xy3#=xy2#*cos(amount#)+xx2#*sin(amount#)
xz3#=xz2#
zx3#=zx2#*cos(amount#)-zy2#*sin(amount#)
zy3#=zy2#*cos(amount#)+zx2#*sin(amount#)
zz3#=zz2#
angle#=wrapvalue(-atanfull(zz3#,sqrt(zx3#^2+zy3#^2)))
endfunction angle#
function Axis_Angle_Z(obj,ayx#,ayy#,ayz#)
rem get normal vectors for X, Y, and Z axes of the object
x#=object position x(obj):y#=object position y(obj):z#=object position z(obj)
move object right obj,1
xx#=object position x(obj)-x#:xy#=object position y(obj)-y#:xz#=object position z(obj)-z#
move object left obj,1:move object up obj,1
yx#=object position x(obj)-x#:yy#=object position y(obj)-y#:yz#=object position z(obj)-z#
move object down obj,1:move object obj,1
zx#=object position x(obj)-x#:zy#=object position y(obj)-y#:zz#=object position z(obj)-z#
move object obj,-1
rem rotate the vectors
rem 1) rotate space about the x axis so that the rotation axis lies in the xz plane
xangle#=atanfull(ayy#,ayz#)
xx1#=xx#
xy1#=xy#*cos(xangle#)-xz#*sin(xangle#)
xz1#=xz#*cos(xangle#)+xy#*sin(xangle#)
zx1#=zx#
zy1#=zy#*cos(xangle#)-zz#*sin(xangle#)
zz1#=zz#*cos(xangle#)+zy#*sin(xangle#)
ayx1#=ayx#
ayy1#=ayy#*cos(xangle#)-ayz#*sin(xangle#)
ayz1#=ayz#*cos(xangle#)+ayy#*sin(xangle#)
rem 2) rotate space about the y axis so that the rotation axis lies along the z axis
yangle#=-atanfull(ayx1#,ayz1#)
xx2#=xx1#*cos(yangle#)+xz1#*sin(yangle#)
xy2#=xy1#
xz2#=xz1#*cos(yangle#)-xx1#*sin(yangle#)
zx2#=zx1#*cos(yangle#)+zz1#*sin(yangle#)
zy2#=zy1#
zz2#=zz1#*cos(yangle#)-zx1#*sin(yangle#)
ax2#=ax1#*cos(yangle#)+az1#*sin(yangle#)
ay2#=ay1#
az2#=az1#*cos(yangle#)-ax1#*sin(yangle#)
rem 1) rotate space about the z axis so that the rotation axis lies in the xz plane
zangle#=atanfull(zx2#,-zy2#)
xx3#=xx2#*cos(zangle#)+xy2#*sin(zangle#)
xy3#=xy2#*cos(zangle#)-xx2#*sin(zangle#)
xz3#=xz2#
zx3#=zx2#*cos(zangle#)+zy2#*sin(zangle#)
zy3#=zy2#*cos(zangle#)-zx2#*sin(zangle#)
zz3#=zz2#
rem 2) rotate space about the y axis so that the rotation axis lies along the z axis
xangle#=atanfull(zy3#,zz3#)
xx4#=xx3#
xy4#=xy3#*cos(xangle#)-xz3#*sin(xangle#)
xz4#=xz3#*cos(xangle#)+xy3#*sin(xangle#)
zx4#=zx3#
zy4#=zy3#*cos(xangle#)-zz3#*sin(xangle#)
zz4#=zz3#*cos(xangle#)+zy3#*sin(xangle#)
angle#=wrapvalue(atanfull(xy4#,xx4#))
endfunction angle#
function line3d(x#,y#,z#,x2#,y2#,z2#)
make object cube 1000,0
position object 1000,x#,y#,z#
x=object screen x(1000)
y=object screen y(1000)
position object 1000,x2#,y2#,z2#
line object screen x(1000),object screen y(1000),x,y
delete object 1000
endfunction
function Orbit(obj,px#,py#,pz#,ax#,ay#,az#,amount#)
dx#=object position x(obj)-px#
dy#=object position y(obj)-py#
dz#=object position z(obj)-pz#
rem get normal vectors for X, Y, and Z axes of the object
x#=object position x(obj):y#=object position y(obj):z#=object position z(obj)
move object right obj,1
xx#=object position x(obj)-x#:xy#=object position y(obj)-y#:xz#=object position z(obj)-z#
move object left obj,1:move object up obj,1
yx#=object position x(obj)-x#:yy#=object position y(obj)-y#:yz#=object position z(obj)-z#
move object down obj,1:move object obj,1
zx#=object position x(obj)-x#:zy#=object position y(obj)-y#:zz#=object position z(obj)-z#
move object obj,-1
rem rotate the vectors
rem 1) rotate space about the x axis so that the rotation axis lies in the xz plane
xangle#=atanfull(ay#,az#)
xx1#=xx#
xy1#=xy#*cos(xangle#)-xz#*sin(xangle#)
xz1#=xz#*cos(xangle#)+xy#*sin(xangle#)
zx1#=zx#
zy1#=zy#*cos(xangle#)-zz#*sin(xangle#)
zz1#=zz#*cos(xangle#)+zy#*sin(xangle#)
dx1#=dx#
dy1#=dy#*cos(xangle#)-dz#*sin(xangle#)
dz1#=dz#*cos(xangle#)+dy#*sin(xangle#)
ax1#=ax#
ay1#=ay#*cos(xangle#)-az#*sin(xangle#)
az1#=az#*cos(xangle#)+ay#*sin(xangle#)
rem 2) rotate space about the y axis so that the rotation axis lies along the z axis
yangle#=-atanfull(ax1#,az1#)
xx2#=xx1#*cos(yangle#)+xz1#*sin(yangle#)
xy2#=xy1#
xz2#=xz1#*cos(yangle#)-xx1#*sin(yangle#)
zx2#=zx1#*cos(yangle#)+zz1#*sin(yangle#)
zy2#=zy1#
zz2#=zz1#*cos(yangle#)-zx1#*sin(yangle#)
dx2#=dx1#*cos(yangle#)+dz1#*sin(yangle#)
dy2#=dy1#
dz2#=dz1#*cos(yangle#)-dx1#*sin(yangle#)
ax2#=ax1#*cos(yangle#)+az1#*sin(yangle#)
ay2#=ay1#
az2#=az1#*cos(yangle#)-ax1#*sin(yangle#)
rem 3) perform the desired rotation by theta about the z axis
xx3#=xx2#*cos(amount#)-xy2#*sin(amount#)
xy3#=xy2#*cos(amount#)+xx2#*sin(amount#)
xz3#=xz2#
zx3#=zx2#*cos(amount#)-zy2#*sin(amount#)
zy3#=zy2#*cos(amount#)+zx2#*sin(amount#)
zz3#=zz2#
dx3#=dx2#*cos(amount#)-dy2#*sin(amount#)
dy3#=dy2#*cos(amount#)+dx2#*sin(amount#)
dz3#=dz2#
rem 4) Inverse of step 2
xx4#=xx3#*cos(-yangle#)+xz3#*sin(-yangle#)
xy4#=xy3#
xz4#=xz3#*cos(-yangle#)-xx3#*sin(-yangle#)
zx4#=zx3#*cos(-yangle#)+zz3#*sin(-yangle#)
zy4#=zy3#
zz4#=zz3#*cos(-yangle#)-zx3#*sin(-yangle#)
dx4#=dx3#*cos(-yangle#)+dz3#*sin(-yangle#)
dy4#=dy3#
dz4#=dz3#*cos(-yangle#)-dx3#*sin(-yangle#)
rem 5) Inverse of step 1
xx1#=xx4#
xy1#=xy4#*cos(-xangle#)-xz4#*sin(-xangle#)
xz1#=xz4#*cos(-xangle#)+xy4#*sin(-xangle#)
zx1#=zx4#
zy1#=zy4#*cos(-xangle#)-zz4#*sin(-xangle#)
zz1#=zz4#*cos(-xangle#)+zy4#*sin(-xangle#)
ndx#=dx4#
ndy#=dy4#*cos(-xangle#)-dz4#*sin(-xangle#)
ndz#=dz4#*cos(-xangle#)+dy4#*sin(-xangle#)
position object obj,px#+ndx#,py#+ndy#,pz#+ndz#
rem calculate angle z
zr#=atanfull(xy1#,xx1#)
rem calculate angle y
xx2#=xx1#*cos(zr#)+xy1#*sin(zr#)
xy2#=xy1#*cos(zr#)-xx1#*sin(zr#)
xz2#=xz1#
zx2#=zx1#*cos(zr#)+zy1#*sin(zr#)
zy2#=zy1#*cos(zr#)-zx1#*sin(zr#)
zz2#=zz1#
yr#=atanfull(xx2#,xz2#)-90
rem calculate angle x
zx3#=zx2#*cos(yr#+90)-zz2#*sin(yr#+90)
zy3#=zy2#
xr#=atanfull(zy3#,zx3#)+180
if xr#+1>xr# and yr#+1>yr# and zr#+1>zr#
rotate object obj,xr#,yr#,zr#
endif
endfunction
Edit:Fixed a bug in some functions that caused the object the freak out when it was not positioned at (0,0,0), and added an Orbit() function, which takes an object, a position, and a direction, and the object will rotate around the axis defined by the point and direction.
Edit:Improved the functions so that they no longer use the cross product and dot product for normal global and location rotations, meaning that the bug where the object slowly turn due to floating point inaccuracies no longer exists. Also added functions that return the standard AxisAngleY,AxisAngleX, and AxisAngleZ, and the up direction can be specified on those as well.