Here's code to handle transformations. Do a search for my code to handle Blitz3D-style quaternions.
Global TFORMEDVALUE_X#
Global TFORMEDVALUE_Y#
Global TFORMEDVALUE_Z#
Global TFORMEDVALUE_W#
Function TFormedX#()
Return TFORMEDVALUE_X
End Function
Function TFormedY#()
Return TFORMEDVALUE_Y
End Function
Function TFormedZ#()
Return TFORMEDVALUE_Z
End Function
Function TFormedW#()
Return TFORMEDVALUE_W
End Function
Function TFormPoint(x#,y#,z#,src:tentity,dst:tentity)
TFORMEDVALUE_X=x
TFORMEDVALUE_Y=y
TFORMEDVALUE_Z=z
If src=dst Return
'Transform from source to common parent
If src<>Null
If src.matrixchanged src.UpdateMatrix()
mat00#=src.matrix[0,0]
mat10#=src.matrix[1,0]
mat20#=src.matrix[2,0]
mat01#=src.matrix[0,1]
mat11#=src.matrix[1,1]
mat21#=src.matrix[2,1]
mat02#=src.matrix[0,2]
mat12#=src.matrix[1,2]
mat22#=src.matrix[2,2]
x=x*src.scalex
y=y*src.scaley
z=z*src.scalez
TFORMEDVALUE_X#=x#*mat00#+y*mat10#+z*mat20#
TFORMEDVALUE_y#=x#*mat01#+y*mat11#+z*mat21#
TFORMEDVALUE_z#=x#*mat02#+y*mat12#+z*mat22#
TFORMEDVALUE_x#=TFORMEDVALUE_x#+src.x
TFORMEDVALUE_y#=TFORMEDVALUE_y#+src.y
TFORMEDVALUE_z#=TFORMEDVALUE_z#+src.z
If src.parent<>Null
tformpoint(TFORMEDVALUE_X,TFORMEDVALUE_Y,TFORMEDVALUE_Z,src.parent,Null)
EndIf
EndIf
'Transform from common parent to destination
While dst<>Null
If dst.matrixchanged dst.UpdateMatrix()
x=TFORMEDVALUE_x-dst.x
y=TFORMEDVALUE_y-dst.y
z=TFORMEDVALUE_z-dst.z
qx#=dst.qx
qy#=dst.qy
qz#=dst.qz
qw#=-dst.qw
mat00=(1.0-2.0*qx#*qx#-2.0*qz#*qz#)
mat10=-(2.0*qz#*qy#-2.0*qw#*qx#)
mat20=-(2.0*qx#*qy#+2.0*qw#*qz#)
mat01=-(2.0*qz#*qy#+2.0*qw#*qx#)
mat11=(1.0-2.0*qy#*qy#-2.0*qx#*qx#)
mat21=-(2.0*qw#*qy#-2.0*qx#*qz#)
mat02=2.0*qw#*qz#-2.0*qx#*qy#
mat12=2.0*qx#*qz#+2.0*qw#*qy#
mat22=1.0-2.0*qz#*qz#-2.0*qy#*qy#
TFORMEDVALUE_X#=x#*mat00#+y*mat10#+z*mat20#
TFORMEDVALUE_y#=x#*mat01#+y*mat11#+z*mat21#
TFORMEDVALUE_z#=x#*mat02#+y*mat12#+z*mat22#
TFORMEDVALUE_X#=TFORMEDVALUE_X/dst.scalex
TFORMEDVALUE_Y#=TFORMEDVALUE_Y/dst.scaley
TFORMEDVALUE_Z#=TFORMEDVALUE_Z/dst.scalez
dst=dst.parent
If dst=Null Exit
Wend
End Function
Function TFormVector(x#,y#,z#,src:tentity,dst:tentity)
TFORMEDVALUE_X=x
TFORMEDVALUE_Y=y
TFORMEDVALUE_Z=z
If src=dst Return
If src<>Null
If src.matrixchanged src.UpdateMatrix()
mat00#=src.matrix[0,0]
mat10#=src.matrix[1,0]
mat20#=src.matrix[2,0]
mat01#=src.matrix[0,1]
mat11#=src.matrix[1,1]
mat21#=src.matrix[2,1]
mat02#=src.matrix[0,2]
mat12#=src.matrix[1,2]
mat22#=src.matrix[2,2]
x=x*src.scalex
y=y*src.scaley
z=z*src.scalez
TFORMEDVALUE_X#=x#*mat00#+y*mat10#+z*mat20#
TFORMEDVALUE_y#=x#*mat01#+y*mat11#+z*mat21#
TFORMEDVALUE_z#=x#*mat02#+y*mat12#+z*mat22#
TFORMEDVALUE_x#=TFORMEDVALUE_x#
TFORMEDVALUE_y#=TFORMEDVALUE_y#
TFORMEDVALUE_z#=TFORMEDVALUE_z#
If src.parent<>Null
tformpoint(TFORMEDVALUE_X,TFORMEDVALUE_Y,TFORMEDVALUE_Z,src.parent,Null)
EndIf
EndIf
While dst<>Null
If dst.matrixchanged dst.UpdateMatrix()
x=TFORMEDVALUE_x
y=TFORMEDVALUE_y
z=TFORMEDVALUE_z
qx#=dst.qx
qy#=dst.qy
qz#=dst.qz
qw#=-dst.qw
mat00=(1.0-2.0*qx#*qx#-2.0*qz#*qz#)
mat10=-(2.0*qz#*qy#-2.0*qw#*qx#)
mat20=-(2.0*qx#*qy#+2.0*qw#*qz#)
mat01=-(2.0*qz#*qy#+2.0*qw#*qx#)
mat11=(1.0-2.0*qy#*qy#-2.0*qx#*qx#)
mat21=-(2.0*qw#*qy#-2.0*qx#*qz#)
mat02=2.0*qw#*qz#-2.0*qx#*qy#
mat12=2.0*qx#*qz#+2.0*qw#*qy#
mat22=1.0-2.0*qz#*qz#-2.0*qy#*qy#
TFORMEDVALUE_X#=x#*mat00#+y*mat10#+z*mat20#
TFORMEDVALUE_y#=x#*mat01#+y*mat11#+z*mat21#
TFORMEDVALUE_z#=x#*mat02#+y*mat12#+z*mat22#
TFORMEDVALUE_X#=TFORMEDVALUE_X/dst.scalex
TFORMEDVALUE_Y#=TFORMEDVALUE_Y/dst.scaley
TFORMEDVALUE_Z#=TFORMEDVALUE_Z/dst.scalez
dst=dst.parent
If dst=Null Exit
Wend
End Function
Function TFormNormal(x#,y#,z#,src:tentity,dst:tentity)
TFORMEDVALUE_X=x
TFORMEDVALUE_Y=y
TFORMEDVALUE_Z=z
If src=dst Return
If src<>Null
If src.matrixchanged src.UpdateMatrix()
mat00#=src.matrix[0,0]
mat10#=src.matrix[1,0]
mat20#=src.matrix[2,0]
mat01#=src.matrix[0,1]
mat11#=src.matrix[1,1]
mat21#=src.matrix[2,1]
mat02#=src.matrix[0,2]
mat12#=src.matrix[1,2]
mat22#=src.matrix[2,2]
TFORMEDVALUE_X#=x#*mat00#+y*mat10#+z*mat20#
TFORMEDVALUE_y#=x#*mat01#+y*mat11#+z*mat21#
TFORMEDVALUE_z#=x#*mat02#+y*mat12#+z*mat22#
TFORMEDVALUE_x#=TFORMEDVALUE_x#
TFORMEDVALUE_y#=TFORMEDVALUE_y#
TFORMEDVALUE_z#=TFORMEDVALUE_z#
If src.parent<>Null
tformpoint(TFORMEDVALUE_X,TFORMEDVALUE_Y,TFORMEDVALUE_Z,src.parent,Null)
EndIf
EndIf
While dst<>Null
If dst.matrixchanged dst.UpdateMatrix()
x=TFORMEDVALUE_x
y=TFORMEDVALUE_y
z=TFORMEDVALUE_z
qx#=dst.qx
qy#=dst.qy
qz#=dst.qz
qw#=-dst.qw
mat00=(1.0-2.0*qx#*qx#-2.0*qz#*qz#)
mat10=-(2.0*qz#*qy#-2.0*qw#*qx#)
mat20=-(2.0*qx#*qy#+2.0*qw#*qz#)
mat01=-(2.0*qz#*qy#+2.0*qw#*qx#)
mat11=(1.0-2.0*qy#*qy#-2.0*qx#*qx#)
mat21=-(2.0*qw#*qy#-2.0*qx#*qz#)
mat02=2.0*qw#*qz#-2.0*qx#*qy#
mat12=2.0*qx#*qz#+2.0*qw#*qy#
mat22=1.0-2.0*qz#*qz#-2.0*qy#*qy#
TFORMEDVALUE_X#=x#*mat00#+y*mat10#+z*mat20#
TFORMEDVALUE_y#=x#*mat01#+y*mat11#+z*mat21#
TFORMEDVALUE_z#=x#*mat02#+y*mat12#+z*mat22#
dst=dst.parent
If dst=Null Exit
Wend
End Function
Update the entity matrix:
Method UpdateMatrix()
matrixchanged=False
matrix[0,0]=(1.0-2.0*qx#*qx#-2.0*qz#*qz#)
matrix[1,0]=-(2.0*qz#*qy#-2.0*qw#*qx#)
matrix[2,0]=-(2.0*qx#*qy#+2.0*qw#*qz#)
matrix[0,1]=-(2.0*qz#*qy#+2.0*qw#*qx#)
matrix[1,1]=(1.0-2.0*qy#*qy#-2.0*qx#*qx#)
matrix[2,1]=-(2.0*qw#*qy#-2.0*qx#*qz#)
matrix[0,2]=2.0*qw#*qz#-2.0*qx#*qy#
matrix[1,2]=2.0*qx#*qz#+2.0*qw#*qy#
matrix[2,2]=1.0-2.0*qz#*qz#-2.0*qy#*qy#
EndMethod