Code: Select all
; 05.10.03 by Froggerprogger
;
; >>>>>>>>>> VECTOR-PROCEDURES 1.1 <<<<<<<<<<<
;
; These procedures handle 3D-FLOAT-vectors
;
; How To Use:
; - The vector-coordinates are stored in a structure named .VectorF containing .x .y .z
; - To create a new vector declare a variable of type VectorF - e.g. Vector1.VectorF,
; then call Vec_Define() or Vec_DefinePTL() (or set .x .y .z manually)
; - Use the functions Vec_Acc(), Vec_Add(), Vec_AddXYZ(), Vec_Copy(), Vec_GetLength()
; Vec_GetPan(), Vec_GetTilt(), Vec_Normalize(), Vec_Rotate(), Vec_RotateXYZ()
; Vec_SetLength(), Vec_Stretch(), Vec_Sub(), Vec_SubXYZ()
; - All Procedures request POINTERS to your vector-structure, so overgive e.g. @MyVector
;
; Changes from 1.0 to 1.1:
; - replace Peek/Poke by Structures inside all procedures
; - renamed Vec_DefineEx() to Vec_DefinePTL()
; - new functions: Vec_AddXYZ(), Vec_SubXYZ(), Vec_Copy(), Vec_SetLength(), Vec_RotateXYZ()
;- START OF INCLUDECODE >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Structure VectorF
x.f
y.f
z.f
EndStructure
#Deg2Rad = 0.01745329
#Rad2Deg = 57.2957795
Declare.l Vec_Acc(*Vec1.VectorF, *Vec2.VectorF, *VecResult.VectorF)
Declare.l Vec_Add(*Vec1.VectorF, *Vec2.VectorF, *VecResult.VectorF)
Declare.l Vec_AddXYZ(*Vec1.VectorF, x.f, y.f, z.f, *VecResult.VectorF)
Declare.l Vec_Copy(*Vec1.VectorF, *VecResult.VectorF)
Declare.l Vec_Define(*Vec1.VectorF, x.f, y.f, z.f)
Declare.l Vec_DefinePTL(*Vec1.VectorF, Pan.f, Tilt.f, length.f)
Declare.f Vec_GetLength(*Vec1.VectorF)
Declare.f Vec_GetPan(*Vec1.VectorF)
Declare.f Vec_GetTilt(*Vec1.VectorF)
Declare.l Vec_Normalize(*Vec1.VectorF, *VecResult.VectorF)
Declare.l Vec_Rotate(*Vec1.VectorF, Pan.f, Tilt.f, *VecResult.VectorF)
Declare.l Vec_RotateXYZ(*Vec1.VectorF, Pan.f, Tilt.f, x.f, y.f, z.f, *VecResult.VectorF)
Declare.l Vec_SetLength(*Vec1.VectorF, length.f, *VecResult.VectorF)
Declare.l Vec_Stretch(*Vec1.VectorF, factor.f, *VecResult.VectorF)
Declare.l Vec_Sub(*Vec1.VectorF, *Vec2.VectorF, *VecResult.VectorF)
Declare.l Vec_SubXYZ(*Vec1.VectorF, x.f, y.f, z.f, *VecResult.VectorF)
;-
;- Vec_Acc : Multiplies all components of Vec2 with their complements of Vec1 and stores
;- the result in VecResult.
;- If *VecResult is 0, the result is stored in Vec1
;- returns a pointer to the resulting vector
;- This procedure is good to use for acceleration.
Procedure.l Vec_Acc(*Vec1.VectorF, *Vec2.VectorF, *VecResult.VectorF)
If *VecResult
*VecResult\x = *Vec1\x * *Vec2\x
*VecResult\y = *Vec1\y * *Vec2\y
*VecResult\z = *Vec1\z * *Vec2\z
ProcedureReturn *VecResult
Else
*Vec1\x = *Vec1\x * *Vec2\x
*Vec1\y = *Vec1\y * *Vec2\y
*Vec1\z = *Vec1\z * *Vec2\z
ProcedureReturn *Vec1
EndIf
EndProcedure
;-
;- Vec_Add : Adds Vec1 to the Vec2 and stores the result in the 3rd given vector (VecResult).
;- If *VecResult is 0, the result is stored in Vec1
;- returns a pointer to the resulting vector
Procedure.l Vec_Add(*Vec1.VectorF, *Vec2.VectorF, *VecResult.VectorF)
If *VecResult
*VecResult\x = *Vec1\x + *Vec2\x
*VecResult\y = *Vec1\y + *Vec2\y
*VecResult\z = *Vec1\z + *Vec2\z
ProcedureReturn *VecResult
Else
*Vec1\x = *Vec1\x + *Vec2\x
*Vec1\y = *Vec1\y + *Vec2\y
*Vec1\z = *Vec1\z + *Vec2\z
ProcedureReturn *Vec1
EndIf
EndProcedure
;-
;- Vec_AddXYZ : Adds x, y and z to Vec1 and stores the result in the 2nd given vector (VecResult).
;- If *VecResult is 0, the result is stored in Vec1
;- returns a pointer to the resulting vector
Procedure.l Vec_AddXYZ(*Vec1.VectorF, x.f, y.f, z.f, *VecResult.VectorF)
If *VecResult
*VecResult\x = *Vec1\x + x
*VecResult\y = *Vec1\y + y
*VecResult\z = *Vec1\z + z
ProcedureReturn *VecResult
Else
*Vec1\x = *Vec1\x + x
*Vec1\y = *Vec1\y + y
*Vec1\z = *Vec1\z + z
ProcedureReturn *Vec1
EndIf
EndProcedure
;-
;- Vec_Copy : Copies Vec1's coordinates to VecResult
;- returns a pointer to VecResult
Procedure.l Vec_Copy(*Vec1.VectorF, *VecResult.VectorF)
*VecResult\x = *Vec1\x
*VecResult\y = *Vec1\y
*VecResult\z = *Vec1\z
ProcedureReturn *VecResult
EndProcedure
;-
;- Vec_Define : Sets the specified xyz-coordinates for the given vector of type VektorF
;- So it's the same as vector\x = x : vector\y = y : vector\z = z
;- returns a pointer to the defined vector
Procedure.l Vec_Define(*Vec1.VectorF, x.f, y.f, z.f)
*Vec1\x = x
*Vec1\y = y
*Vec1\z = z
ProcedureReturn *Vec1
EndProcedure
;-
;- Vec_DefinePTL : Calculates and sets the coordinates for the given vector of type VektorF
;- and requests the values Pan, Tilt and Length for therefore.
;- length should be positive
;- Pan should be between 0 and 360 degrees (but need not)
;- Tilt should be between -90 and 90 degrees (but need not)
;- returns a pointer to the defined vector
Procedure.l Vec_DefinePTL(*Vec1.VectorF, Pan.f, Tilt.f, length.f)
*Vec1\x = length * Cos(Tilt * #Deg2Rad) * Cos(-1*Pan * #Deg2Rad)
*Vec1\y = length * Sin(Tilt * #Deg2Rad)
*Vec1\z = length * Cos(Tilt * #Deg2Rad) * Sin(-1*Pan * #Deg2Rad)
ProcedureReturn *Vec1
EndProcedure
;-
;- Vec_GetLength : Returns the length of the vector. This is always > 0
Procedure.f Vec_GetLength(*Vec1.VectorF)
Protected x1.f, y1.f, z1.f
x1 = *Vec1\x
y1 = *Vec1\y
z1 = *Vec1\z
ProcedureReturn Sqr(x1*x1+y1*y1+z1*z1)
EndProcedure
;-
;- Vec_GetPan : Returns the angle between the vector and the x/y-plane,
;- which is between 0 and 360 degrees.
;- (positive z => Vec_GetPan > 180, negative z => Vec_GetPan < 180)
Procedure.f Vec_GetPan(*Vec1.VectorF)
Protected x1.f, z1.f, temp.f
x1 = *Vec1\x
z1 = *Vec1\z
temp = ATan(z1 / x1) * #Rad2Deg
If z1 <= 0
If temp <= 0
temp * -1
Else
temp = 180 - temp
EndIf
Else
If temp < 0
temp = 180 - temp
Else
temp = 360 - temp
EndIf
EndIf
ProcedureReturn temp
EndProcedure
;-
;- Vec_GetTilt : Returns the smallest angle between the vector and the x/z-plane.
;- So it lays between -90 and +90 degrees.
Procedure.f Vec_GetTilt(*Vec1.VectorF)
Protected x1.f, y1.f, z1.f, temp1.f, temp2.f
x1 = *Vec1\x
y1 = *Vec1\y
z1 = *Vec1\z
temp1 = Sqr(x1*x1+z1*z1)
If temp1 = 0 : ProcedureReturn 0 : EndIf
temp2 = ATan(y1 / temp1) * #Rad2Deg
ProcedureReturn temp2
EndProcedure
;-
;- Vec_Normalize : Normalizes a vector to the length 1 without changing Pan and Tilt.
;- The result is stored in VecResult
;- If *VecResult is 0, the result is stored in Vec1
;- returns a pointer to the resulting vector
Procedure.l Vec_Normalize(*Vec1.VectorF, *VecResult.VectorF)
Protected x1.f, y1.f, z1.f, length.f
x1 = *Vec1\x
y1 = *Vec1\y
z1 = *Vec1\z
length.f = Sqr(x1*x1+y1*y1+z1*z1)
If *VecResult
*VecResult\x = x1 / length
*VecResult\y = y1 / length
*VecResult\z = z1 / length
ProcedureReturn *VecResult
Else
*Vec1\x = x1 / length
*Vec1\y = y1 / length
*Vec1\z = z1 / length
ProcedureReturn *Vec1
EndIf
EndProcedure
;-
;- Vec_Rotate : Rotates Vec1 with the given Pan and Tilt-values and stores the result
;- in VecResult.
;- If *VecResult is 0, the result is stored in Vec1
;- returns a pointer to the resulting vector
Procedure.l Vec_Rotate(*Vec1.VectorF, Pan.f, Tilt.f, *VecResult.VectorF)
Protected oldLength.f, oldPan.f, oldTilt.f
oldLength = Vec_GetLength(*Vec1)
oldPan = Vec_GetPan(*Vec1)
oldTilt = Vec_GetTilt(*Vec1)
If *VecResult
ProcedureReturn Vec_DefinePTL(*VecResult, oldPan + Pan, oldTilt + Tilt, oldLength)
Else
ProcedureReturn Vec_DefinePTL(*Vec1, oldPan + Pan, oldTilt + Tilt, oldLength)
EndIf
EndProcedure
;-
;- Vec_RotateXYZ : Rotates Vec1 with the given Pan and Tilt-values around the by *Vec2
;- specified rotation center and stores the result in VecResult.
;- If *VecResult is 0, the result is stored in Vec1
;- returns a pointer to the resulting vector
Procedure.l Vec_RotateXYZ(*Vec1.VectorF, Pan.f, Tilt.f, x.f, y.f, z.f, *VecResult.VectorF)
Protected oldLength.f, oldPan.f, oldTilt.f, Vec_temp.VectorF
Vec_SubXYZ(*Vec1, x, y, z, @Vec_temp)
oldLength = Vec_GetLength(@Vec_temp)
oldPan = Vec_GetPan(@Vec_temp)
oldTilt = Vec_GetTilt(@Vec_temp)
If *VecResult
ProcedureReturn Vec_AddXYZ(Vec_DefinePTL(*VecResult, oldPan + Pan, oldTilt + Tilt, oldLength), x, y, z, #False)
Else
ProcedureReturn Vec_AddXYZ(Vec_DefinePTL(*Vec1, oldPan + Pan, oldTilt + Tilt, oldLength), x, y, z, #False)
EndIf
EndProcedure
;-
;- Vec_SetLength : Sets the given vector to the specified length and stores the result in
;- VecResult.
;- if *VecResult is 0, the result is stored in Vec1
;- returns a pointer to the resulting vector
Procedure.l Vec_SetLength(*Vec1.VectorF, length.f, *VecResult.VectorF)
Protected x1.f, y1.f, z1.f, originallength.f
x1 = *Vec1\x
y1 = *Vec1\y
z1 = *Vec1\z
originallength.f = Sqr(x1*x1+y1*y1+z1*z1)
If *VecResult
*VecResult\x = x1 / originallength * length
*VecResult\y = y1 / originallength * length
*VecResult\z = z1 / originallength * length
ProcedureReturn *VecResult
Else
*Vec1\x = x1 / originallength * length
*Vec1\y = y1 / originallength * length
*Vec1\z = z1 / originallength * length
ProcedureReturn *Vec1
EndIf
EndProcedure
;-
;- Vec_Strech : Stretches Vec1 by the given factor and stores the result in the 2nd given vector (VecResult).
;- If *VecResult is 0, the result is stored in Vec1
;- returns a pointer to the resulting vector
Procedure.l Vec_Stretch(*Vec1.VectorF, factor.f, *VecResult.VectorF)
If *VecResult
*VecResult\x = *Vec1\x * factor
*VecResult\y = *Vec1\y * factor
*VecResult\z = *Vec1\z * factor
ProcedureReturn *VecResult
Else
*Vec1\x = *Vec1\x * factor
*Vec1\y = *Vec1\y * factor
*Vec1\z = *Vec1\z * factor
ProcedureReturn *Vec1
EndIf
EndProcedure
;-
;- Vec_Sub : Subtrahates Vec2 from Vec1 and stores the result in the 3rd given vector (VecResult).
;- If *VecResult is 0, the result is stored in Vec1
;- returns a pointer to the resulting vector
Procedure.l Vec_Sub(*Vec1.VectorF, *Vec2.VectorF, *VecResult.VectorF)
If *VecResult
*VecResult\x = *Vec1\x - *Vec2\x
*VecResult\y = *Vec1\y - *Vec2\y
*VecResult\z = *Vec1\z - *Vec2\z
ProcedureReturn *VecResult
Else
*Vec1\x = *Vec1\x - *Vec2\x
*Vec1\y = *Vec1\y - *Vec2\y
*Vec1\z = *Vec1\z - *Vec2\z
ProcedureReturn *Vec1
EndIf
EndProcedure
;-
;- Vec_SubXYZ : Subtrahates x, y and z from Vec1 and stores the result in the 2nd given vector (VecResult).
;- If *VecResult is 0, the result is stored in Vec1
;- returns a pointer to the resulting vector
Procedure.l Vec_SubXYZ(*Vec1.VectorF, x.f, y.f, z.f, *VecResult.VectorF)
If *VecResult
*VecResult\x = *Vec1\x - x
*VecResult\y = *Vec1\y - y
*VecResult\z = *Vec1\z - z
ProcedureReturn *VecResult
Else
*Vec1\x = *Vec1\x - x
*Vec1\y = *Vec1\y - y
*Vec1\z = *Vec1\z - z
ProcedureReturn *Vec1
EndIf
EndProcedure
;- END OF INCLUDECODE <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
;-
;- Examples
;-
Global Vector1.VectorF
Global Vector2.VectorF
Global Vector3.VectorF
Procedure Showvector(*Vec1.VectorF)
PrintN(" X : "+ LSet(StrF(*Vec1\x), 10)+ " Y : "+LSet(StrF(*Vec1\y),10)+ " Z : "+LSet(StrF(*Vec1\z),10))
PrintN(" Pan : "+ LSet(StrF(Vec_GetPan(*Vec1)), 10)+" Tilt : "+LSet(StrF(Vec_GetTilt(*Vec1)),10)+" Length : "+LSet(StrF(Vec_GetLength(*Vec1)),10))
PrintN("")
EndProcedure
OpenConsole()
PrintN("Define Vector 1 by x=1, y=2, z=3")
Vec_Define(@Vector1, 1, 2, 3) ; x = 1 : y = 2 : z = 3
Showvector(@Vector1)
PrintN("Define Vector 2 by pan = 80 : tilt = 70 : length = 100")
Vec_DefinePTL(@Vector2, 80, 70, 100) ; pan = 80 : tilt = 70 : length = 100
Showvector(@Vector2)
PrintN("Add 10, 10, 10 to Vector2 and then Vector 2 to Vector1")
Vec_Add(@Vector1, Vec_AddXYZ(@Vector2, 10, 10, 10,0), 0)
Showvector(@Vector1)
PrintN("Normalize Vector1 and store result in Vector3")
Vec_Normalize(@Vector1, @Vector3)
Showvector(@Vector3)
PrintN("Stretch Vector3 by factor 32")
Vec_Stretch(@Vector3, 32, 0)
Showvector(@Vector3)
PrintN("Rotate Vector3 by +32 Pan and -31 Tilt")
Vec_Rotate(@Vector3, 32, -31, 0)
Showvector(@Vector3)
Input()
CloseConsole()