Sorry for the unhelpful subject line, but after way way way too long (off and on for a couple years) I finally created my own set of free flight rotation commands. These are purely math based and easy to control. The command set the DBC comes with is nice, but gives you pretty useless Angle commands and your hands are tied, since you can't really do a whole lot without those.
The downsides to this system:
Object Angle X(),Y(),and Z() as well as Move Object no longer work. I am working on a function that will return the pitch, yaw, and roll offsets between the object and the two points.
I'll be posting the functions shortly, but while I\\\'m working on support functions, I wanted to know what functions would be necessary/desirable from you guys.
Ones I assume will be necessary (other than actual rotation commands):
-Find PYR offset
-Point Object
-Move Object
-Return Heading data
Anything else?
And I know there are other (probably better) solutions to this method, but they all seemed like they made things more complicated than they should be. This was an attempt at a purely math based one (though there are 3 limbs required, but they don't do anything but sit there and help with calculations).
[EDIT]
Here's the function set. I'm a little disappointed though. While it seems to work like a charm, it does create issues if you want the camera to interact with it. Maybe people here have some ideas?
To use it, use the function
X axis limb=FFR_PrepObject(Object Number, X offset#, Y offset#, Z offset#)
Basically, the way this works is it sets up a local coordinate axis for the object and then uses some basic vector math to figure out what the global rotation values are for the local rotations (so Pitch is done by rotating around the local X axis which is some combination of the other axes). In order to make it work I had to use FIX OBJECT PIVOT in the functions, making it's angle and orientation data useless. Had I not, it would get stuck at the 90 degree marks. Basically, instead of Euler rotation (DBC's native set) which uses a mix of local and global rotation axes, this will use purely global rotation axes.
The Prep function will:
Add 4 Limbs: 1 at the new origin (Object Position + the offsets given in the function call) and 3 offset from the new origin at 1 unit in each direction (so one limb is 1 unit to the right, one is 1 unit forward, and one is 1 unit up). The function returns the limb number of the X axis limb. Store this value as it is required for all other functions.
The other functions are:
FFR_PitchObject(ObjNum,XLimb,angle#)
FFR_YawObject(ObjNum,XLimb,angle#)
FFR_RollObject(ObjNum,XLimb,angle#)
FFR_FindAngle#(ObjNum,XLimb,X#,Y#,Z#) : this function will determine the pitch, yaw, and roll angles from the object's new origin to the given point.
FFR_MoveObject(ObjNum,XLimb,distance#): This will move the object along its heading. This is included since the FIX OBJECT PIVOT command is being used, thus rendering the MOVE OBJECT command useless.
FFR_PointObject(ObjNum,XLimb,X#,Y#,Z#): (A little buggy) This will point the object at the given point.
FFR_GetHeading(ObjNum,XLimb): This will load the components of the local z axis (the one that points forward) into the array FFR_Heading# in slots 1 (x), 2(y), and 3(z).
FFR_SetCam(ObjNum,XLimb): This positions the camera at the local origin and (should) rotate it to point forward. Unfortunately, the camera rotation math is buggy.
FFR_CameraRoll(ObjNum,XLimb): This is part of the SetCam system. It will zrotate the camera until it is rolled correctly with the object's orientation. I had hoped that you could position the camera at the origin, point it at the z axis limb, and the rotate it but rotating it seemed to mess up the POINT CAMERA function.
These are included as well:
VectorDotProduct(x1#,y1#,z1#,x2#,y2#,z2#): Will return the value of vector <x1#,y1#,z1#> dotted with vector <x2#,y2#,z2#>
VectorCrossProduct(x1#,y1#,z1#,x2#,y2#,z2#): Will return the value of the cross product of vectors <x1#,y1#,z1#> and <x2#,y2#,z2#>. The three components turned into a unit vector, multiplied by 255 and combined using the RGB command. The computed color value is returned. To get the data out, use the RGBR, RGBG, and RGBB commands for the X, Y, and Z components of the result and then divide each by 255.
REM This will generate the necessary reference objects for the local coordinate system.
REM They become limbs N+1,N+2,N+3
REM They are positioned at +1=1 unit to the right (X) +2=1 Unit Up (Y) +3=1 Unit Forward (Z)
FUNCTION FFR_PrepObject(ObjectNumber,Xo#,Yo#,Zo#)
make object plain 65535,1,1
POSITION OBJECT 65535,0,0,0
Make Mesh From Object 2,65535
Make Mesh From Object 3,65535
Make Mesh From Object 4,65535
Make Mesh From Object 5,65535
ROTATE OBJECT ObjectNumber,0,0,0
Perform Checklist for Object Limbs ObjectNumber
TotalLimbs=Checklist Quantity()
Add Limb ObjectNumber,TotalLimbs+1,2
Add Limb ObjectNumber,TotalLimbs+2,3
Add Limb ObjectNumber,TotalLimbs+3,4
Add Limb ObjectNumber,TotalLimbs+4,5
Offset Limb ObjectNumber,TotalLimbs+1,Xo#+1,Yo#,Zo#
Offset Limb ObjectNumber,TotalLimbs+2,Xo#,Yo#+1,Zo#
Offset Limb ObjectNumber,TotalLimbs+3,Xo#,Yo#,Zo#+1
Offset Limb ObjectNumber,TotalLimbs+4,Xo#,Yo#,Zo#
` Offset Limb ObjectNumber,TotalLimbs+2,0,1,0
` Offset Limb ObjectNumber,TotalLimbs+3,0,0,1
HIDE LIMB ObjectNumber,TotalLimbs+1
HIDE LIMB ObjectNumber,TotalLimbs+2
HIDE LIMB ObjectNumber,TotalLimbs+3
HIDE LIMB ObjectNumber,TotalLimbs+4
HIDE LIMB ObjectNumber,8
HIDE LIMB ObjectNumber,9
HIDE LIMB ObjectNumber,10
HIDE LIMB ObjectNumber,11
DELETE OBJECT 65535
INC TotalLimbs
ENDFUNCTION TotalLimbs
FUNCTION FFR_PitchObject(ObjNum,Xlimb,angle#)
X#=Limb Position X(ObjNum,XLimb+3) : Y#=Limb Position Y(ObjNum,XLimb+3) : Z#=Limb Position Z(ObjNum,XLimb+3)
aX#=Object Angle X(ObjNum) : aY#=OBJECT ANGLE Y(ObjNum) : aZ#=OBJECT ANGLE Z(ObjNum)
rotate object objnum,0,0,0
REM Establish local coordinate axes
XAxisX#=Limb Position X(ObjNum,Xlimb)-Limb Position X(ObjNum,XLimb+3) : IF abs(XAxisX#)<0.001 then XAxisX#=0.0
XAxisY#=Limb Position Y(ObjNum,Xlimb)-Limb Position Y(ObjNum,XLimb+3) : IF abs(XAxisY#)<0.001 then XAxisY#=0.0
XAxisZ#=Limb Position Z(ObjNum,Xlimb)-Limb Position Z(ObjNum,XLimb+3) : IF abs(XAxisZ#)<0.001 then XAxisZ#=0.0
YAxisX#=Limb Position X(ObjNum,Xlimb+1)-Limb Position X(ObjNum,XLimb+3) : IF abs(YAxisX#)<0.001 then YAxisX#=0.0 : `0
YAxisY#=Limb Position Y(ObjNum,Xlimb+1)-Limb Position Y(ObjNum,XLimb+3) : IF abs(YAxisY#)<0.001 then YAxisY#=0.0 : `0
YAxisZ#=Limb Position Z(ObjNum,Xlimb+1)-Limb Position Z(ObjNum,XLimb+3) : IF abs(YAxisZ#)<0.001 then YAxisZ#=0.0 : `-1
ZAxisX#=Limb Position X(ObjNum,Xlimb+2)-Limb Position X(ObjNum,XLimb+3) : IF abs(ZAxisX#)<0.001 then ZAxisX#=0.0 : `0
ZAxisY#=Limb Position Y(ObjNum,Xlimb+2)-Limb Position Y(ObjNum,XLimb+3) : IF abs(ZAxisY#)<0.001 then ZAxisY#=0.0 : `1
ZAxisZ#=Limb Position Z(ObjNum,Xlimb+2)-Limb Position Z(ObjNum,XLimb+3) : IF abs(ZAxisZ#)<0.001 then ZAxisZ#=0.0 : `0
Xrot#=wrapvalue(angle#*XaxisX#)
Yrot#=wrapvalue(angle#*XAxisY#)
Zrot#=wrapvalue(angle#*XAxisZ#)
ROTATE OBJECT ObjNum,Xrot#,Yrot#,Zrot#
fix object pivot ObjNum
FFR_Pitch#(objnum)=FFR_Pitch#(objnum)+angle#
ENDFUNCTION
FUNCTION FFR_YawObject(ObjNum,Xlimb,angle#)
X#=Limb Position X(ObjNum,XLimb+3) : Y#=Limb Position Y(ObjNum,XLimb+3) : Z#=Limb Position Z(ObjNum,XLimb+3)
aX#=Object Angle X(ObjNum) : aY#=OBJECT ANGLE Y(ObjNum) : aZ#=OBJECT ANGLE Z(ObjNum)
rotate object objnum,0,0,0
REM Establish local coordinate axes
XAxisX#=Limb Position X(ObjNum,Xlimb)-Limb Position X(ObjNum,XLimb+3) : IF abs(XAxisX#)<0.001 then XAxisX#=0.0
XAxisY#=Limb Position Y(ObjNum,Xlimb)-Limb Position Y(ObjNum,XLimb+3) : IF abs(XAxisY#)<0.001 then XAxisY#=0.0
XAxisZ#=Limb Position Z(ObjNum,Xlimb)-Limb Position Z(ObjNum,XLimb+3) : IF abs(XAxisZ#)<0.001 then XAxisZ#=0.0
YAxisX#=Limb Position X(ObjNum,Xlimb+1)-Limb Position X(ObjNum,XLimb+3) : IF abs(YAxisX#)<0.001 then YAxisX#=0.0 : `0
YAxisY#=Limb Position Y(ObjNum,Xlimb+1)-Limb Position Y(ObjNum,XLimb+3) : IF abs(YAxisY#)<0.001 then YAxisY#=0.0 : `0
YAxisZ#=Limb Position Z(ObjNum,Xlimb+1)-Limb Position Z(ObjNum,XLimb+3) : IF abs(YAxisZ#)<0.001 then YAxisZ#=0.0 : `-1
ZAxisX#=Limb Position X(ObjNum,Xlimb+2)-Limb Position X(ObjNum,XLimb+3) : IF abs(ZAxisX#)<0.001 then ZAxisX#=0.0 : `0
ZAxisY#=Limb Position Y(ObjNum,Xlimb+2)-Limb Position Y(ObjNum,XLimb+3) : IF abs(ZAxisY#)<0.001 then ZAxisY#=0.0 : `1
ZAxisZ#=Limb Position Z(ObjNum,Xlimb+2)-Limb Position Z(ObjNum,XLimb+3) : IF abs(ZAxisZ#)<0.001 then ZAxisZ#=0.0 : `0
Xrot#=wrapvalue(angle#*YaxisX#)
Yrot#=wrapvalue(angle#*YAxisY#)
Zrot#=wrapvalue(angle#*YAxisZ#)
ROTATE OBJECT ObjNum,Xrot#,Yrot#,Zrot#
fix object pivot objnum
FFR_Yaw#(objnum)=FFR_Yaw#(objnum)+angle#
ENDFUNCTION
FUNCTION FFR_RollObject(ObjNum,Xlimb,angle#)
X#=Limb Position X(ObjNum,XLimb+3) : Y#=Limb Position Y(ObjNum,XLimb+3) : Z#=Limb Position Z(ObjNum,XLimb+3)
aX#=Object Angle X(ObjNum) : aY#=OBJECT ANGLE Y(ObjNum) : aZ#=OBJECT ANGLE Z(ObjNum)
rotate object objnum,0,0,0
REM Establish local coordinate axes
XAxisX#=Limb Position X(ObjNum,Xlimb)-Limb Position X(ObjNum,XLimb+3) : IF abs(XAxisX#)<0.001 then XAxisX#=0.0
XAxisY#=Limb Position Y(ObjNum,Xlimb)-Limb Position Y(ObjNum,XLimb+3) : IF abs(XAxisY#)<0.001 then XAxisY#=0.0
XAxisZ#=Limb Position Z(ObjNum,Xlimb)-Limb Position Z(ObjNum,XLimb+3) : IF abs(XAxisZ#)<0.001 then XAxisZ#=0.0
YAxisX#=Limb Position X(ObjNum,Xlimb+1)-Limb Position X(ObjNum,XLimb+3) : IF abs(YAxisX#)<0.001 then YAxisX#=0.0 : `0
YAxisY#=Limb Position Y(ObjNum,Xlimb+1)-Limb Position Y(ObjNum,XLimb+3) : IF abs(YAxisY#)<0.001 then YAxisY#=0.0 : `0
YAxisZ#=Limb Position Z(ObjNum,Xlimb+1)-Limb Position Z(ObjNum,XLimb+3) : IF abs(YAxisZ#)<0.001 then YAxisZ#=0.0 : `-1
ZAxisX#=Limb Position X(ObjNum,Xlimb+2)-Limb Position X(ObjNum,XLimb+3) : IF abs(ZAxisX#)<0.001 then ZAxisX#=0.0 : `0
ZAxisY#=Limb Position Y(ObjNum,Xlimb+2)-Limb Position Y(ObjNum,XLimb+3) : IF abs(ZAxisY#)<0.001 then ZAxisY#=0.0 : `1
ZAxisZ#=Limb Position Z(ObjNum,Xlimb+2)-Limb Position Z(ObjNum,XLimb+3) : IF abs(ZAxisZ#)<0.001 then ZAxisZ#=0.0 : `0
Xrot#=wrapvalue(angle#*ZaxisX#)
Yrot#=wrapvalue(angle#*ZAxisY#)
Zrot#=wrapvalue(angle#*ZAxisZ#)
ROTATE OBJECT ObjNum,Xrot#,Yrot#,Zrot#
fix object pivot objnum
FFR_Roll#(objnum)=FFR_Roll#(objnum)+angle#
ENDFUNCTION
FUNCTION FFR_FindAngle#(ObjNum,Xlimb,X#,Y#,Z#)
REM Establish local coordinate axes
XAxisX#=Limb Position X(ObjNum,Xlimb)-Limb Position X(ObjNum,XLimb+3) : IF abs(XAxisX#)<0.001 then XAxisX#=0.0
XAxisY#=Limb Position Y(ObjNum,Xlimb)-Limb Position Y(ObjNum,XLimb+3) : IF abs(XAxisY#)<0.001 then XAxisY#=0.0
XAxisZ#=Limb Position Z(ObjNum,Xlimb)-Limb Position Z(ObjNum,XLimb+3) : IF abs(XAxisZ#)<0.001 then XAxisZ#=0.0
YAxisX#=Limb Position X(ObjNum,Xlimb+1)-Limb Position X(ObjNum,XLimb+3) : IF abs(YAxisX#)<0.001 then YAxisX#=0.0 : `0
YAxisY#=Limb Position Y(ObjNum,Xlimb+1)-Limb Position Y(ObjNum,XLimb+3) : IF abs(YAxisY#)<0.001 then YAxisY#=0.0 : `0
YAxisZ#=Limb Position Z(ObjNum,Xlimb+1)-Limb Position Z(ObjNum,XLimb+3) : IF abs(YAxisZ#)<0.001 then YAxisZ#=0.0 : `-1
ZAxisX#=Limb Position X(ObjNum,Xlimb+2)-Limb Position X(ObjNum,XLimb+3) : IF abs(ZAxisX#)<0.001 then ZAxisX#=0.0 : `0
ZAxisY#=Limb Position Y(ObjNum,Xlimb+2)-Limb Position Y(ObjNum,XLimb+3) : IF abs(ZAxisY#)<0.001 then ZAxisY#=0.0 : `1
ZAxisZ#=Limb Position Z(ObjNum,Xlimb+2)-Limb Position Z(ObjNum,XLimb+3) : IF abs(ZAxisZ#)<0.001 then ZAxisZ#=0.0 : `0
v2x#=X#-Limb Position X(ObjNum,XLimb+3)
v2y#=Y#-Limb Position Y(ObjNum,XLimb+3)
v2z#=Z#-Limb Position Z(ObjNum,XLimb+3)
mag2#=((v2x#^2)+(v2y#^2)+(v2z#^2))^(.5)
REM Make v2 a unit vector
v2x#=v2x#/mag2#
v2y#=v2y#/mag2#
v2z#=v2z#/mag2#
REM Caculate Zl#*v2# to find the distance of the heading along the vector to the point
r#=(ZAxisX#*v2x#)+(ZAxisY#*v2y#)+(ZAxisZ#*v2z#)
REM The angle between them will be cos-1 of r#
angle#=acos(r#)
REM This is the angle BUT it is at an odd angle
REM To turn it back into global X,Y,Z coordinates, we need some more math
REM By using the cross product on the two vectors, we will get a vector that is perpendicular to both of the vectors. This will need to become a unit vector
crs=VectorCrossProduct#(ZAxisX#,ZAxisY#,ZAxisZ#,v2x#,v2y#,v2z#)
cx#=(rgbr(crs)+.)/255.0
cy#=(rgbg(crs)+.)/255.0
cz#=(rgbb(crs)+.)/255.0
REM this vector is the axis of rotation for the angle
REM Thus, we will now multiply the angle by the components to get the angle differences in X,Y,Z
ax#=angle#*cx#
ay#=angle#*cy#
az#=angle#*cz#
REM This doesn't mean too much though, so lets turn it into PYR data
P#=VectorDotProduct#(ax#,ay#,az#,XAxisX#,XAxisY#,XAxisZ#)
Y#=VectorDotProduct#(ax#,ay#,az#,YAxisX#,YAxisY#,YAxisZ#)
R#=VectorDotProduct#(ax#,ay#,az#,ZAxisX#,ZAxisY#,ZAxisZ#)
REM Output
FFR_PitchDiff#(0)=P#
FFR_YawDiff#(0)=Y#
FFR_RollDiff#(0)=R#
ENDFUNCTION
REM Move Object Clone
FUNCTION FFR_MoveObject(ObjNum,Xlimb,d#)
X1#=Limb Position X(ObjNum,XLimb+3) : Y1#=Limb Position Y(ObjNum,XLimb+3) : Z1#=Limb Position Z(ObjNum,XLimb+3)
REM Get Heading Data
ZAxisX#=Limb Position X(ObjNum,Xlimb+2)-Limb Position X(ObjNum,XLimb+3) : IF abs(ZAxisX#)<0.001 then ZAxisX#=0.0 : `0
ZAxisY#=Limb Position Y(ObjNum,Xlimb+2)-Limb Position Y(ObjNum,XLimb+3) : IF abs(ZAxisY#)<0.001 then ZAxisY#=0.0 : `1
ZAxisZ#=Limb Position Z(ObjNum,Xlimb+2)-Limb Position Z(ObjNum,XLimb+3) : IF abs(ZAxisZ#)<0.001 then ZAxisZ#=0.0 : `0
REM Calculate the position change
dX#=d#*ZAxisX#
dY#=d#*ZAxisY#
dZ#=d#*ZAxisZ#
POSITION OBJECT ObjNum,X1#+dX#,Y1#+dY#,Z1#+dZ#
ENDFUNCTION
REM Point Object Clone
FUNCTION FFR_PointObject(ObjNum,XLimb,X#,Y#,Z#)
FFR_FindAngle#(ObjNum,XLimb,X#,Y#,Z#)
FFR_PitchObject(ObjNum,XLimb,FFR_PitchDiff#(0))
FFR_YawObject(ObjNum,XLimb,FFR_YawDiff#(0))
FFR_RollObject(ObjNum,XLimb,FFR_RollDiff#(0))
ENDFUNCTION
REM This loads FFR_Heading#() with the heading unit vector (the object's local Z axis)
FUNCTION FFR_GetHeading(ObjNum,XLimb)
REM Get Heading Data
ZAxisX#=Limb Position X(ObjNum,Xlimb+2)-Limb Position X(ObjNum,XLimb+3) : IF abs(ZAxisX#)<0.001 then ZAxisX#=0.0 : `0
ZAxisY#=Limb Position Y(ObjNum,Xlimb+2)-Limb Position Y(ObjNum,XLimb+3) : IF abs(ZAxisY#)<0.001 then ZAxisY#=0.0 : `1
ZAxisZ#=Limb Position Z(ObjNum,Xlimb+2)-Limb Position Z(ObjNum,XLimb+3) : IF abs(ZAxisZ#)<0.001 then ZAxisZ#=0.0 : `0
FFR_Heading#(1)=ZAxisX#
FFR_Heading#(2)=ZAxisY#
FFR_Heading#(3)=ZAxisZ#
ENDFUNCTION
FUNCTION FFR_SetCam(ObjNum,XLimb)
set camera rotation xyz
POSITION CAMERA Limb Position X(objnum,XLimb+3),Limb Position Y(objnum,XLimb+3),Limb Position Z(objnum,XLimb+3)
ROTATE CAMERA wrapvalue(FFR_Pitch#(ObjNum)),wrapvalue(FFR_Yaw#(ObjNum)),wrapvalue(FFR_Roll#(ObjNum))
POINT CAMERA Limb Position X(objnum,XLimb+2),Limb Position Y(objnum,XLimb+2),Limb Position Z(objnum,XLimb+2)
X#=Camera Angle X() : Y#=Camera Angle Y()
Z#=FFR_CameraRoll(ObjNum,XLimb)
ROTATE CAMERA X#,Y#,Z#
ENDFUNCTION
REM This assumes that the camera is already pointing towards the heading direction and is positioned at the origin
FUNCTION FFR_CameraRoll(ObjNum,XLimb)
YAxisX#=Limb Position X(ObjNum,Xlimb+1)-Limb Position X(ObjNum,XLimb+3) : IF abs(YAxisX#)<0.001 then YAxisX#=0.0 : `0
YAxisY#=Limb Position Y(ObjNum,Xlimb+1)-Limb Position Y(ObjNum,XLimb+3) : IF abs(YAxisY#)<0.001 then YAxisY#=0.0 : `0
YAxisZ#=Limb Position Z(ObjNum,Xlimb+1)-Limb Position Z(ObjNum,XLimb+3) : IF abs(YAxisZ#)<0.001 then YAxisZ#=0.0 : `-1
Cx1#=Camera Position X() : Cy1#=Camera Position Y() : Cz1#=Camera Position Z()
PITCH CAMERA UP 90
MOVE CAMERA 1
Cx2#=Camera Position X() : Cy2#=Camera Position Y() : Cz2#=Camera Position Z()
Cx#=Cx2#-Cx1# : Cy#=Cy2#-Cy1# : Cz#=Cz2#-Cz1#
MOVE CAMERA -1
PITCH CAMERA DOWN 90
REM Calculate angle
d#=VectorDotProduct#(YAxisX#,YAxisY#,YAxisZ#,Cx#,Cy#,Cz#)
angle#=acos(d#)
text 0,0,str$(angle#)
text 0,20,str$(WrapValue(FFR_Roll#(objnum)))
REM Problem: Angle math gives ABS only. Need method to determine if +/-
IF WrapValue(FFR_Roll#(objnum))<=180
angle#=angle#
ELSE
angle#=0-angle#
ENDIF
ZRotate Camera wrapvalue(angle#)
ENDFUNCTION wrapvalue(angle#)
FUNCTION VectorDotProduct#(x1#,y1#,z1#,x2#,y2#,z2#)
RetVal#=(x1#*x2#)+(y1#*y2#)+(z1#*z2#)
ENDFUNCTION RetVal#
FUNCTION VectorCrossProduct#(x1#,y1#,z1#,x2#,y2#,z2#)
rx#=(y1#*z2#-y2#*z1#)
ry#=(x2#*z1#-x1#*z2#)
rz#=(x1#*y2#-x2#*y1#)
mag#=((rx#^2)+(ry#^2)+(rz#^2))^(.5)
rx#=rx#/mag#
ry#=ry#/mag#
rz#=rz#/mag#
REM Consider the components as percentages of 255 for easy transport
R=(rx#*255) : G=(ry#*255) : B=(ry#*255)
REM Package data in 1 color number
RetVal=rgb(R,G,B)
ENDFUNCTION RetVal
EDIT2
I solved the FFR_PointObject problem. It was in the functions FFR_FindAngle#() and the VectorCrossProduct#(). Here is the updated function:
FUNCTION FFR_FindAngle#(ObjNum,Xlimb,X#,Y#,Z#)
REM Establish local coordinate axes
XAxisX#=Limb Position X(ObjNum,Xlimb)-Limb Position X(ObjNum,XLimb+3) : IF abs(XAxisX#)<0.001 then XAxisX#=0.0
XAxisY#=Limb Position Y(ObjNum,Xlimb)-Limb Position Y(ObjNum,XLimb+3) : IF abs(XAxisY#)<0.001 then XAxisY#=0.0
XAxisZ#=Limb Position Z(ObjNum,Xlimb)-Limb Position Z(ObjNum,XLimb+3) : IF abs(XAxisZ#)<0.001 then XAxisZ#=0.0
YAxisX#=Limb Position X(ObjNum,Xlimb+1)-Limb Position X(ObjNum,XLimb+3) : IF abs(YAxisX#)<0.001 then YAxisX#=0.0 : `0
YAxisY#=Limb Position Y(ObjNum,Xlimb+1)-Limb Position Y(ObjNum,XLimb+3) : IF abs(YAxisY#)<0.001 then YAxisY#=0.0 : `0
YAxisZ#=Limb Position Z(ObjNum,Xlimb+1)-Limb Position Z(ObjNum,XLimb+3) : IF abs(YAxisZ#)<0.001 then YAxisZ#=0.0 : `-1
ZAxisX#=Limb Position X(ObjNum,Xlimb+2)-Limb Position X(ObjNum,XLimb+3) : IF abs(ZAxisX#)<0.001 then ZAxisX#=0.0 : `0
ZAxisY#=Limb Position Y(ObjNum,Xlimb+2)-Limb Position Y(ObjNum,XLimb+3) : IF abs(ZAxisY#)<0.001 then ZAxisY#=0.0 : `1
ZAxisZ#=Limb Position Z(ObjNum,Xlimb+2)-Limb Position Z(ObjNum,XLimb+3) : IF abs(ZAxisZ#)<0.001 then ZAxisZ#=0.0 : `0
v2x#=X#-Limb Position X(ObjNum,XLimb+3)
v2y#=Y#-Limb Position Y(ObjNum,XLimb+3)
v2z#=Z#-Limb Position Z(ObjNum,XLimb+3)
mag2#=((v2x#^2)+(v2y#^2)+(v2z#^2))^(.5)
REM Make v2 a unit vector
v2x#=v2x#/mag2#
v2y#=v2y#/mag2#
v2z#=v2z#/mag2#
REM Caculate Zl#*v2# to find the distance of the heading along the vector to the point
r#=(ZAxisX#*v2x#)+(ZAxisY#*v2y#)+(ZAxisZ#*v2z#)
REM The angle between them will be cos-1 of r#
angle#=acos(r#)
REM This is the angle BUT it is at an odd angle
REM To turn it back into global X,Y,Z coordinates, we need some more math
REM By using the cross product on the two vectors, we will get a vector that is perpendicular to both of the vectors. This will need to become a unit vector
crs=VectorCrossProduct#(ZAxisX#,ZAxisY#,ZAxisZ#,v2x#,v2y#,v2z#)
cx#=(rgbr(crs)-127.)/127.0
cy#=(rgbg(crs)-127.)/127.0
cz#=(rgbb(crs)-127.)/127.0
REM this vector is the axis of rotation for the angle
REM Thus, we will now multiply the angle by the components to get the angle differences in X,Y,Z
ax#=angle#*cx#
ay#=angle#*cy#
az#=angle#*cz#
REM This doesn't mean too much though, so lets turn it into PYR data
P#=VectorDotProduct#(ax#,ay#,az#,XAxisX#,XAxisY#,XAxisZ#)
Y#=VectorDotProduct#(ax#,ay#,az#,YAxisX#,YAxisY#,YAxisZ#)
R#=VectorDotProduct#(ax#,ay#,az#,ZAxisX#,ZAxisY#,ZAxisZ#)
REM Output
FFR_PitchDiff#(0)=P#
FFR_YawDiff#(0)=Y#
FFR_RollDiff#(0)=R#
ENDFUNCTION
VectorCrossProduct#() will still return a color value. However, instead of each unit vector component being multiplied by 255, it is multiplied by 127, and then added to 127. This way, it will preserve negative values. To unpackage it, just take the RGBR,RGBG,and RGBB values, subtract 127, then divide by 127.
Great Quote:
"Time...LINE??? Time isn't made out of lines...it is made out of circles. That is why clocks are round!" -Caboose