Code: Select all
; ################################################################### ;
;/ (VMQ) - Vector Matrix Quaternion
;/ By: Matt Greene (aka Legider)
;/ Contact: http://www.devend.com or matt@devend.com
;/ Notes: Here are some functions for handling the rather important
;/ and common maths used in 3d engines. This file may change
;/ over time if I decide to add new functions or fix/edit
;/ some old ones. If you have any suggestions or comments
;/ then please feel free to contact me. Anyone can use this
;/ file any way they wish, but if you could just mention my
;/ name if you decide to, I would appreciate it.
; ################################################################### ;
; ################################################################### ;
;/
;/ Structures
;/
; ################################################################### ;
Structure Matrix4
W1.f
X1.f
Y1.f
Z1.f
W2.f
X2.f
Y2.f
Z2.f
W3.f
X3.f
Y3.f
Z3.f
W4.f
X4.f
Y4.f
Z4.f
EndStructure
Structure QUATERNION
X.f
Y.f
Z.f
w.f
EndStructure
Structure Vector
X.f
Y.f
Z.f
EndStructure
; ################################################################### ;
;/
;/ Vector Maths
;/
; ################################################################### ;
Procedure LEG_Vector_Add(*ReturnVector.Vector, *V1.Vector, *V2.Vector)
*ReturnVector\X = *V1\X + *V2\X
*ReturnVector\Y = *V1\Y + *V2\Y
*ReturnVector\Z = *V1\Z + *V2\Z
EndProcedure
;/
Procedure LEG_Vector_Subtract(*ReturnVector.Vector, *V1.Vector, *V2.Vector)
*ReturnVector\X = *V1\X - *V2\X
*ReturnVector\Y = *V1\Y - *V2\Y
*ReturnVector\Z = *V1\Z - *V2\Z
EndProcedure
;/
Procedure LEG_Vector_CrossProduct(*ReturnVector.Vector, *V1.Vector, *V2.Vector)
*ReturnVector\X = *V1\Y * *V2\Z - *V2\Y * *V1\Z
*ReturnVector\Y = *V1\Z * *V2\X - *V2\Z * *V1\X
*ReturnVector\Z = *V1\X * *V2\Y - *V2\X * *V1\Y
EndProcedure
;/
Procedure.f LEG_Vector_DotProduct(*V1.Vector, *V2.Vector)
ProcedureReturn (*V1\X * *V2\X) + (*V1\Y * *V2\Y) + (*V1\Z * *V2\Z)
EndProcedure
;/
Procedure.f LEG_Vector_Length(X.f, Y.f, Z.f)
ProcedureReturn Sqr(X * X + Y * Y + Z * Z)
EndProcedure
;/
Procedure LEG_Vector_Normalize(*NormVector.Vector)
length.f = LEG_Vector_Length(*NormVector\X, *NormVector\Y, *NormVector\Z)
*NormVector\X = *NormVector\X / length
*NormVector\Y = *NormVector\Y / length
*NormVector\Z = *NormVector\Z / length
EndProcedure
; ################################################################### ;
;/
;/ Matrix Maths
;/
; ################################################################### ;
Procedure LEG_Matrix_Multiply(*NewMatrix.Matrix4, *M.Matrix4, *L.Matrix4)
*NewMatrix\W1 = *M\W1 * *L\W1 + *M\X1 * *L\W2 + *M\Y1 * *L\W3 + *M\Z1 * *L\W4
*NewMatrix\X1 = *M\W2 * *L\W1 + *M\X2 * *L\W2 + *M\Y2 * *L\W3 + *M\Z2 * *L\W4
*NewMatrix\Y1 = *M\W3 * *L\W1 + *M\X3 * *L\W2 + *M\Y3 * *L\W3 + *M\Z3 * *L\W4
*NewMatrix\Z1 = *M\W4 * *L\W1 + *M\X4 * *L\W2 + *M\Y4 * *L\W3 + *M\Z4 * *L\W4
*NewMatrix\W2 = *M\W1 * *L\X1 + *M\X1 * *L\X2 + *M\Y1 * *L\X3 + *M\Z1 * *L\X4
*NewMatrix\X2 = *M\W2 * *L\X1 + *M\X2 * *L\X2 + *M\Y2 * *L\X3 + *M\Z2 * *L\X4
*NewMatrix\Y2 = *M\W3 * *L\X1 + *M\X3 * *L\X2 + *M\Y3 * *L\X3 + *M\Z3 * *L\X4
*NewMatrix\Z2 = *M\W4 * *L\X1 + *M\X4 * *L\X2 + *M\Y4 * *L\X3 + *M\Z4 * *L\X4
*NewMatrix\W3 = *M\W1 * *L\Y1 + *M\X1 * *L\Y2 + *M\Y1 * *L\Y3 + *M\Z1 * *L\Y4
*NewMatrix\X3 = *M\W2 * *L\Y1 + *M\X2 * *L\Y2 + *M\Y2 * *L\Y3 + *M\Z2 * *L\Y4
*NewMatrix\Y3 = *M\W3 * *L\Y1 + *M\X3 * *L\Y2 + *M\Y3 * *L\Y3 + *M\Z3 * *L\Y4
*NewMatrix\Z3 = *M\W4 * *L\Y1 + *M\X4 * *L\Y2 + *M\Y4 * *L\Y3 + *M\Z4 * *L\Y4
*NewMatrix\W4 = *M\W1 * *L\Z1 + *M\X1 * *L\Z2 + *M\Y1 * *L\Z3 + *M\Z1 * *L\Z4
*NewMatrix\X4 = *M\W2 * *L\Z1 + *M\X2 * *L\Z2 + *M\Y2 * *L\Z3 + *M\Z2 * *L\Z4
*NewMatrix\Y4 = *M\W3 * *L\Z1 + *M\X3 * *L\Z2 + *M\Y3 * *L\Z3 + *M\Z3 * *L\Z4
*NewMatrix\Z4 = *M\W4 * *L\Z1 + *M\X4 * *L\Z2 + *M\Y4 * *L\Z3 + *M\Z4 * *L\Z4
EndProcedure
;/
Procedure LEG_Matrix_FromEuler(angle_x.f, angle_y.f, angle_z.f)
DefType.f A,b,C,D,E,f,AD,BD
A = Cos(angle_x)
b = Sin(angle_x)
C = Cos(angle_y)
D = Sin(angle_y)
E = Cos(angle_z)
f = Sin(angle_z)
AD = A * D
BD = b * D
ReturnMatrix\W1 = C * E
ReturnMatrix\X1 = -C * f
ReturnMatrix\Y1 = D
ReturnMatrix\W2 = BD * E + A * f
ReturnMatrix\X2 = -BD * f + A * E
ReturnMatrix\Y2 = -b * C
ReturnMatrix\W3 = -AD * E + b * f
ReturnMatrix\X3 = AD * f + b * E
ReturnMatrix\Y3 = A * C
ReturnMatrix\Z1 = 0
ReturnMatrix\Z2 = 0
ReturnMatrix\Z3 = 0
ReturnMatrix\W4 = 0
ReturnMatrix\X4 = 0
ReturnMatrix\Y4 = 0
ReturnMatrix\Z4 = 1
EndProcedure
; ################################################################### ;
;/
;/ Quaternion Maths
;/
; ################################################################### ;
Procedure.f LEG_Quaternion_Length(*TempQuat.QUATERNION)
ProcedureReturn Sqr(Pow(*TempQuat\X,2) + Pow(*TempQuat\Y,2) + Pow(*TempQuat\Z,2) + Pow(*TempQuat\w,2))
EndProcedure
;/
Procedure LEG_Quaternion_Conjugate(*NewQuat.QUATERNION, *Quat1.QUATERNION)
*NewQuat\X = -1 * *Quat1\X
*NewQuat\Y = -1 * *Quat1\Y
*NewQuat\Z = -1 * *Quat1\Z
*NewQuat\w = *Quat1\w
EndProcedure
;/
Procedure LEG_Quaternion_Multiply(*NewQuat.QUATERNION, *Quat1.QUATERNION, *Quat2.QUATERNION)
*NewQuat\w = *Quat1\w * *Quat2\w - *Quat1\X * *Quat2\X - *Quat1\Y * *Quat2\Y - *Quat1\Z * *Quat2\Z
*NewQuat\X = *Quat1\w * *Quat2\X + *Quat1\X * *Quat2\w + *Quat1\Y * *Quat2\Z - *Quat1\Z * *Quat2\Y
*NewQuat\Y = *Quat1\w * *Quat2\Y + *Quat1\Y * *Quat2\w + *Quat1\Z * *Quat2\X - *Quat1\X * *Quat2\Z
*NewQuat\Z = *Quat1\w * *Quat2\Z + *Quat1\Z * *Quat2\w + *Quat1\X * *Quat2\Y - *Quat1\Y * *Quat2\X
EndProcedure
;/
Procedure LEG_Quaternion_Normalize(*TempQuat.QUATERNION)
TEMP_length.f = LEG_Quaternion_Length(*TempQuat)
*TempQuat\X = *TempQuat\X / TEMP_length
*TempQuat\Y = *TempQuat\Y / TEMP_length
*TempQuat\Z = *TempQuat\Z / TEMP_length
*TempQuat\w = *TempQuat\w / TEMP_length
EndProcedure
;/
Procedure LEG_Quaternion_FromEuler(*TempQuat.QUATERNION, Yaw.f, Pitch.f, Roll.f)
If Yaw = 0 And Pitch = 0 And Roll = 0
*TempQuat\X = 0
*TempQuat\Y = 0
*TempQuat\Z = 0
*TempQuat\w = 1
ProcedureReturn 0
EndIf
Roll = (Roll * 0.01745329) / 2
Pitch = (Pitch * 0.01745329) / 2
Yaw = (Yaw * 0.01745329) / 2
cosRoll.f = Cos(Roll)
cosPitch.f = Cos(Pitch)
cosYaw.f = Cos(Yaw)
sinRoll.f = Sin(Roll)
sinPitch.f = Sin(Pitch)
sinYaw.f = Sin(Yaw)
cosPitchYaw.f = cosPitch * cosYaw
sinPitchYaw.f = sinPitch * sinYaw
*TempQuat\X = sinRoll * cosPitchYaw - cosRoll * sinPitchYaw
*TempQuat\Y = cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw
*TempQuat\Z = cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw
*TempQuat\w = cosRoll * cosPitchYaw + sinRoll * sinPitchYaw
LEG_Quaternion_Normalize(*TempQuat)
EndProcedure
;/
Procedure LEG_Quaternion_FromAngleAxis(*TempQuat.QUATERNION, X.f, Y.f, Z.f, angleDegrees.f)
If X = 0 And Y = 0 And Z = 0
*TempQuat\X = 0
*TempQuat\Y = 0
*TempQuat\Z = 0
*TempQuat\w = 1
ProcedureReturn 0
EndIf
TEMP_sum.f = X * X + Y * Y + Z * Z
TEMP_length.f = Sqr(TEMP_sum)
TEMP_angle.f = angleDegrees * 0.01745329
TEMP_angle = TEMP_angle / 2
TEMP_scale.f = Sin(TEMP_angle)
*TempQuat\X = TEMP_scale * X / TEMP_sum
*TempQuat\Y = TEMP_scale * Y / TEMP_sum
*TempQuat\Z = TEMP_scale * Z / TEMP_sum
*TempQuat\w = Cos(TEMP_angle)
LEG_Quaternion_Normalize(*TempQuat)
EndProcedure
BTW, I have prefixed all the functions with LEG_ to lessen the chance of conflict, as I will do with all my public code (since my nickname is Legider).