I took the working code from MiniB3D for aligning the z axis, then I swapped the matrix rows to add correct calculation for x and y. It's pretty powerful because you can specify a roll value for any axis, and the rate/smoothing works as well.
However, this is extremely bloated and does not seem to work with scaling:
Method AlignToVector(dir:TVec3,axis=3,rate#=1.0,roll_value#=0.0)
Local pitch#,yaw#,roll#,dist#
Local i:TVec3,j:TVec3,k:TVec3
dist#=Sqr(dir.x#*dir.x#+dir.z#*dir.z#)
pitch#=ATan2(-dir.y#,dist#)
yaw#=ATan2(-dir.x#,dir.z#)
roll#=roll_value
If rate=1.0
SetRotation vec3(pitch,yaw,roll),1
Else
Select axis
Case 1
i:TVec3=mat.i()
k:TVec3=mat.k()
mat.kx=i.x
mat.ky=i.y
mat.kz=i.z
mat.ix=k.x
mat.iy=k.y
mat.iz=k.z
mat.jx:*-1.0
mat.jy:*-1.0
mat.jz:*-1.0
Case 2
j:TVec3=mat.j()
k:TVec3=mat.k()
mat.kx=j.x
mat.ky=j.y
mat.kz=j.z
mat.jx=k.x
mat.jy=k.y
mat.jz=k.z
mat.ix:*-1.0
mat.iy:*-1.0
mat.iz:*-1.0
EndSelect
quaternion=mat.rotation().slerp(vec3(pitch,yaw,roll).toquat(),rate)
SetRotation quaternion.toeuler(),1
EndIf
Select axis
Case 1
i:TVec3=mat.i()
k:TVec3=mat.k()
mat.kx=i.x
mat.ky=i.y
mat.kz=i.z
mat.ix=k.x
mat.iy=k.y
mat.iz=k.z
mat.jx:*-1.0
mat.jy:*-1.0
mat.jz:*-1.0
Case 2
j:TVec3=mat.j()
k:TVec3=mat.k()
mat.kx=j.x
mat.ky=j.y
mat.kz=j.z
mat.jx=k.x
mat.jy=k.y
mat.jz=k.z
mat.ix:*-1.0
mat.iy:*-1.0
mat.iz:*-1.0
Case 3
Return
EndSelect
quaternion=TFormQuat(mat.rotation(),Null,parent)
SetRotation quaternion.toeuler()
EndMethod
|