Quantcast
Viewing all articles
Browse latest Browse all 1449

[VB6] - 3D rotation as a basis change

I propose a way to change the 3D coordinate basis.

The bases are expressed as a triad of perpendicular vectors.

Since in my case these vectors are all of length 1 and are perpendicular, this topic it's not about a "true" basis change but only the one useful for a 3D rotation.


The World basis (which is implicit) is composed of 3 vectors X,Y,Z of which only one direction has value 1 and all the others 0
WorldBase X = 1, 0, 0
WorldBase Y = 0, 1, 0
WorldBase Z = 0, 0, 1


This class allows you to provide a transformation basis formed by 3 perpendicular vectors.
It can be provided by directly entering these three vectors (Already normalized)

SetBasisNormalized

or by providing only two Vectors (preferably but not necessarily perpendicular)

SetBasisXY and SetBasisXZ

Once the transformation basis is provided, it is possible to transform a vector from one basis to another with the subs:

ToBasis and ToWorld.

ToBasis (WorldPosition , [out] BasePosition)
ToWorld (BasePosition , [out] WorldPosition)



For example, if you had to perform a rotation along the Z axis, it will be sufficient to give as baseX a vector that has X=cos(ang), Y=sin(ang) and as baseZ a vector that only has the value Z = 1
Code:

BX.X = Cos( A )
BX.Y = Sin( A )
BX.Z = 0

BZ.X = 0
BZ.Y = 0
BZ.Z = 1

SetBasisXZ  BX,BZ



NOTE:
To specify the center of rotation, proceed as follows:
- The Center of Rotation must first be subtracted from the vector to be transformed.
- The transformation is applied.
- The Center of Rotation is added to the result of the transformation.


Another example:
You want your object to point to the Camera vector.
(Shortening)

VectorUP = Vector ( 0 , 1, 0 )
BASIS.SetBasisXY CameraPos - CameraLookAt , VectorUP
BASIS.ToBasis VectorIn - ObjCenter, TransformedV
TransformedV = TransformedV + ObjCenter




I hope it can be useful to someone.

(PS: in case you have a better idea you can express it here but to develop the discussion on it, in case, you are required to start a new thread, Thanks)



MODULE:
Code:

Option Explicit

Public Type tVec3
    X            As Double
    Y            As Double
    Z            As Double
EndType

Public Function DOT3(A As tVec3, B As tVec3) As Double
    DOT3 = A.X * B.X + A.Y * B.Y + A.Z * B.Z
End Function

Public Function CROSS3(A As tVec3, B As tVec3) As tVec3
    With CROSS3
        .X = A.Y * B.Z - A.Z * B.Y
        .Y = A.Z * B.X - A.X * B.Z
        .Z = A.X * B.Y - A.Y * B.X
    End With
End Function

Public Function LEN32(V As tVec3) As Double
    With V
        LEN32 = (.X * .X + .Y * .Y + .Z * .Z)
    End With
End Function

Public Function Normalize3(V As tVec3) As tVec3
    Dim D        As Double
    With V
        D = (.X * .X + .Y * .Y + .Z * .Z)
        If D Then
            D = 1# / Sqr(D)
            Normalize3.X = .X * D
            Normalize3.Y = .Y * D
            Normalize3.Z = .Z * D
        End If
    End With
End Function

CLASS:
Code:

Option Explicit

Private BaseX    As tVec3
Private BaseY    As tVec3
Private BaseZ    As tVec3

Friend Sub GetBasis(bX As tVec3, bY As tVec3, bZ As tVec3)
    bX = BaseX
    bY = BaseY
    bZ = BaseZ
End Sub

Friend Function GetBaseZ() As tVec3
    GetBaseZ = BaseZ
End Function

Friend Sub SetBasisNormalized(baX As tVec3, baY As tVec3, baZ As tVec3)
    BaseX = baX
    BaseY = baY
    BaseZ = baZ
End Sub

Friend Sub SetBasisXY(bX As tVec3, bY As tVec3)
    BaseX = bX
    BaseY = bY
    If LEN32(BaseX) <> 1# Then BaseX = Normalize3(BaseX)
    If LEN32(BaseY) <> 1# Then BaseY = Normalize3(BaseY)
    BaseZ = Normalize3(CROSS3(BaseX, BaseY))
    If DOT3(BaseX, BaseY) <> 0 Then
        BaseY = Normalize3(CROSS3(BaseZ, BaseX))
    End If
End Sub

Friend Sub SetBasisXZ(bX As tVec3, bZ As tVec3)
    BaseX = bX
    BaseZ = bZ
    If LEN32(BaseX) <> 1# Then BaseX = Normalize3(BaseX)
    If LEN32(BaseZ) <> 1# Then BaseZ = Normalize3(BaseZ)
    BaseY = Normalize3(CROSS3(BaseZ, BaseX))
    If DOT3(BaseX, BaseZ) <> 0 Then
        BaseZ = Normalize3(CROSS3(BaseX, BaseY))
    End If
End Sub

Friend Sub ToBasis(V As tVec3, vOUT As tVec3)
    'Equivalent to MAT3x3 MUL
    '    vOUT.X = DOT3(V, BaseX)
    '    vOUT.Y = DOT3(V, BaseY)
    '    vOUT.Z = DOT3(V, BaseZ)
    ' SAME:
    vOUT.X = V.X * BaseX.X + V.Y * BaseX.Y + V.Z * BaseX.Z
    vOUT.Y = V.X * BaseY.X + V.Y * BaseY.Y + V.Z * BaseY.Z
    vOUT.Z = V.X * BaseZ.X + V.Y * BaseZ.Y + V.Z * BaseZ.Z
End Sub

Friend Sub ToWorld(V As tVec3, vOUT As tVec3)
    '    Vout = MUL3(BaseX, V.X)
    '    Vout = SUM3(Vout, MUL3(BaseY, V.Y))
    '    Vout = SUM3(Vout, MUL3(BaseZ, V.Z))
    'SAME:
    vOUT.X = BaseX.X * V.X + BaseY.X * V.Y + BaseZ.X * V.Z
    vOUT.Y = BaseX.Y * V.X + BaseY.Y * V.Y + BaseZ.Y * V.Z
    vOUT.Z = BaseX.Z * V.X + BaseY.Z * V.Y + BaseZ.Z * V.Z
End Sub


Viewing all articles
Browse latest Browse all 1449

Trending Articles