!= is <>
? x:y is IIf
i made a few matrix methods in xojo but later i continue in c#
because the matrix library is more complex and ready to use there.
if you want to rotate around a point x,y you move all to 0,0
means translate vectors via subtract, turn it via rotation matrix and push them the same distance back.
you need a angle in radians, and a distance in compare to scale something.
Xojo
Vec3 Class
Public Shared Function Point(x As Double, y As Double, z As Double) As Vec3
Return New Vec3(x,y,z,1.0)
End Function
Public Shared Function Vector(x As Double, y As Double, z As Double) As Vec3
Return New Vec3(x,y,z,0.0)
End Function
Public Shared Function Add(a1 as Vec3, a2 as Vec3) As Vec3
Return New Vec3(a1.x + a2.x, a1.y + a2.y, a1.z + a2.z, a1.w + a2.w)
End Function
Public Shared Function Subtract(a1 as Vec3, a2 as Vec3) As Vec3
Return New Vec3(a1.x - a2.x, a1.y - a2.y, a1.z - a2.z, a1.w - a2.w)
End Function
Public Shared Function Negating(a as Vec3) As Vec3
Return New Vec3(-a.x, -a.y, -a.z, -a.w)
End Function
Public Shared Function MultiplyingByScalar(a As Vec3, scalar As Double) As Vec3
Return New Vec3(a.x * scalar, a.y * scalar, a.z * scalar, a.w * scalar)
End Function
Public Shared Function DividingByScalar(a As Vec3, scalar As Double) As Vec3
Return New Vec3(a.x / scalar, a.y / scalar, a.z / scalar, a.w / scalar)
End Function
Public Shared Function Magnitute(a as Vec3) As Double
Return Sqrt((a.x * a.x) + (a.y * a.y) + (a.z * a.z) + (a.w * a.w))
End Function
Public Shared Function Normalize(a As Vec3) As Vec3
Var magnitute As Double = Magnitute(a)
If magnitute = 0.0 Then
Return New Vec3(0.0, 0.0, 0.0, 0.0)
Else
Return New Vec3(a.x / magnitute, a.y / magnitute, a.z / magnitute, a.w / magnitute)
End If
End Function
Public Shared Function DotProduct(a as Vec3, b as Vec3) As Double
'auch als Scalar Produkt genannt
Return (a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w)
End Function
Public Shared Function CrossProduct(a as Vec3, b as Vec3) As Vec3
Return Vec3.Vector(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x)
End Function
Public Shared Function Length(a as Vec3) As Double
Return Magnitute(a)
End Function
Public Shared Function Reflect(v As Vec3, n As Vec3, bounce As Double) As Vec3
'https://www.3dkingdoms.com/weekly/weekly.php?a=2
' Vnew = bounce * ( -2*(V dot N)*N + V )
' where bounce=0.0 means no bounce, and bounce=1.0 means no loss of speed.
Var dotproduct As Double = DotProduct(v, n)
Return Vec3.Add(Vec3.MultiplyingByScalar(Vec3.MultiplyingByScalar(n, -2.0 * dotproduct), bounce),v)
End Function
Public Sub Constructor()
Self.x = 0.0
Self.y = 0.0
Self.z = 0.0
Self.w = 0.0
End Sub
Public Sub Constructor(x As Double, y As Double, z As Double, w As Double)
Self.x = x
Self.y = y
Self.z = z
Self.w = w
End Sub
Public Sub Debug()
System.DebugLog "X = " + x.ToString + " Y = " + y.ToString + " Z = " + z.ToString
End Sub
Public Property x As Double = 0
Public Property y As Double = 0
Public Property w As Double = 0
Public Property z As Double = 0
Xojo
Ray Class
Private Sub Constructor()
End Sub
Public Sub Constructor(origin As Vec3, direction As Vec3)
Self.Origin = Vec3.Point(origin.x, origin.y, origin.z) 'a point
Self.Direction = Vec3.Vector(direction.x, direction.y, direction.z) 'a vector
End Sub
Public Property Origin As Vec3
Public Property Direction As Vec3
Public Shared Function Position(ray As Ray, t As Double) As Vec3
' t = time
Var totalDistance As Vec3 = Vec3.MultiplyingByScalar(ray.Direction, t)
Return Vec3.Add(ray.Origin, totalDistance)
End Function
Public Shared Function Transform(ray As Ray, m(, ) As Double) As Ray
Var ray2 As New Ray(Vec3.Point(0,0,0),Vec3.Vector(0,0,0))
ray2.Origin = MatrixMultiplyTuple(m, ray.Origin)
ray2.Direction = MatrixMultiplyTuple(m, ray.Direction)
Return ray2
End Function
Xojo
MatrixModule
Public Function Matrix4x4() As double(,)
'Row, Column
'0-3, 0-3
Var m(3,3) As Double
Return m
'eine 3x5 Matrix hat 3 Reihen und 5 Spalten
End Function
Public Function MatrixCustomized(rows As Integer, columns As Integer) As double(,)
'Row, Column
Var m(-1, -1) As Double
m.ResizeTo(rows-1, columns-1)
Return m
'eine 3x5 Matrix hat 3 Reihen und 5 Spalten
End Function
Public Sub MatrixDebug(m(, ) As Double)
System.DebugLog "Debug Matrix"
For row As Integer = 0 To 3
Var rowStr As String = "row (" + row.ToString + ")"
For col As Integer = 0 To 3
rowStr = rowStr + " , " + Str(m(row,col))
Next
System.DebugLog rowStr
Next
End Sub
Public Function MatrixEquality(a(, ) As Double, b(, ) As Double) As Boolean
'Gleichheit prüfen
Var equality As Boolean = True
For row As Integer = 0 To 3
For col As Integer = 0 To 3
If Equal(a(row, col), b(row, col)) Then
Else
equality = False
Exit
End If
Next
If equality = False Then Exit
Next
Return equality
End Function
Public Sub MatrixIdentity(m(, ) As Double)
For row As Integer = 0 To 3
For col As Integer = 0 To 3
m(row,col) = 0.0
Next
Next
'diagonal 1
m(0, 0) = 1.0
m(1, 1) = 1.0
m(2, 2) = 1.0
m(3, 3) = 1.0
End Sub
Public Function MatrixMultiply(a(, ) As Double, b(, ) As Double) As Double(,)
Var c(3,3) As Double
For row As Integer = 0 To 3
For col As Integer = 0 To 3
c(row,col) = a(row, 0) * b(0, col) + a(row, 1) * b(1, col) + a(row, 2) * b(2, col) + a(row, 3) * b(3, col)
Next
Next
Return c
End Function
Public Function MatrixMultiplyTuple(m(, ) As Double, v As Vec3) As Vec3
Var vout As New Vec3
' immer eine Reihe der Matrix mit einer Spalte des Tuple
vout.x = Vec3.DotProduct(New vec3(m(0,0),m(0,1),m(0,2),m(0,3)), v)
vout.y = Vec3.DotProduct(New vec3(m(1,0),m(1,1),m(1,2),m(1,3)), v)
vout.z = Vec3.DotProduct(New vec3(m(2,0),m(2,1),m(2,2),m(2,3)), v)
vout.w = Vec3.DotProduct(New vec3(m(3,0),m(3,1),m(3,2),m(3,3)), v)
Return vout
End Function
Public Function MatrixRotationX(radians As Double) As Double(,)
' drehen um die X Achse
Var m(-1,-1) As Double = Matrix4x4()
MatrixIdentity(m)
m(1,1)=Cos(radians)
m(1,2)=-Sin(radians)
m(2,1)=Sin(radians)
m(2,2)=Cos(radians)
Return m
End Function
Public Function MatrixRotationY(radians As Double) As Double(,)
' drehen um die Y Achse
Var m(-1,-1) As Double = Matrix4x4()
MatrixIdentity(m)
m(0,0)=Cos(radians)
m(0,2)=Sin(radians)
m(2,0)=-Sin(radians)
m(2,2)= Cos(radians)
Return m
End Function
Public Function MatrixRotationZ(radians As Double) As Double(,)
' drehen um die Z Achse
Var m(-1,-1) As Double = Matrix4x4()
MatrixIdentity(m)
m(0,0)= Cos(radians)
m(0,1)=-Sin(radians)
m(1,0)= Sin(radians)
m(1,1)= Cos(radians)
Return m
End Function
Public Function MatrixScaling(x As Double, y As Double, z As Double) As double(,)
' zum scalieren
Var m(-1,-1) As Double = Matrix4x4()
MatrixIdentity(m)
m(0,0)=x
m(1,1)=y
m(2,2)=z
Return m
End Function
Public Function MatrixShearing(xy As Double, xz As Double, yx As Double, yz As Double, zx As Double, zy As Double) As Double(,)
Var m(-1,-1) As Double = Matrix4x4()
MatrixIdentity(m)
m(0,1)= xy
m(0,2)= xz
m(1,0)= yx
m(1,2)= yz
m(2,0)= zx
m(2,1)= zy
Return m
End Function
Public Function MatrixTranslation(x As Double, y As Double, z As Double) As double(,)
' zum verschieben
Var m(-1,-1) As Double = Matrix4x4()
MatrixIdentity(m)
m(0,3)=x
m(1,3)=y
m(2,3)=z
Return m
End Function
Public Function MatrixTranspose(a(, ) As Double) As Double(,)
'rows into columns and columns into rows
Var m(3,3) As Double
For row As Integer = 0 To 3
For col As Integer = 0 To 3
m(col, row) = a(row, col)
Next
Next
Return m
End Function
Protected Property EPSILON As Double = 0.00001
Public Function Clamp(x As double, _min As Double, _max As Double) As Double
If (x < _min) Then Return _min
If (x > _max) Then Return _max
Return x
End Function
Public Function DegreesToRadians(degrees As Double) As Double
Return degrees * Math.PI / 180.0
End Function
Public Function Equal(a As Double, b As Double) As Boolean
If Abs(a-b)<EPSILON Then
Return True
Else
Return False
End If
End Function
Math Module
Public Property PI As Double = 3.14159265359