SyntaxBomb - Indie Coders

Languages & Coding => Blitz Code Archives => 3D Graphics - Maths => Topic started by: BlitzBot on June 29, 2017, 00:28:39

Title: [bmx] BMax Math Lib v3.0 by Chroma [ 1+ years ago ]
Post by: BlitzBot on June 29, 2017, 00:28:39
Title : BMax Math Lib v3.0
Author : Chroma
Posted : 1+ years ago

Description : This math lib is a drastic speed increase over previous libs.  I've done extensive speed testing in massive loops and went with the fastest method every time.  Creating and returning a local type inside a method is very inefficient and slow.  I gained about a 60-100% speed increase by eliminating it.  Give this math lib a shot, you'll notice the difference.

Updating Matrix soon and throwing in some other advanced functions for good measure.

Please post any errors or bugs.

Fixed 2 errors.  Thanks for pointing em out.


Code :
Code (blitzmax) Select
' BMax Math Lib v3.0
' by Chroma


' Internal Math Vars - Do Not Alter
Const Tol:Float = 0.0001
Global vTmp:TVector3 = New TVector3
Global qTmp:TQuaternion = New TQuaternion


' ----------
' ----------
' ----------


' Vector Class

Type TVector3

Field x:Double, y:Double, z:Double

' ----------

'Example1: v1:TVector3 = TVector3.Create(1,2,3)
Function Create:TVector3(x:Double = 0, y:Double = 0, z:Double = 0)
Local v:TVector3 = New TVector3
v.x = x
v.y = y
v.z = z
Return v
End Function

'Example1: v.Set(1,2,3)
Method Set(x:Double = 0, y:Double = 0, z:Double = 0)
self.x = x
self.y = y
self.z = z
End Method

' ----------

'Example: v1 = v1 + v2 is written v1.Add( v1, v2 )
Method Add(a:TVector3, b:TVector3)
self.x = a.x + b.x
self.y = a.y + b.y
self.z = a.z + b.z
End Method

'Example: v1 = v2 + 5 is written v1.AddScalar( v2, 5 )
Method AddScalar(a:TVector3, s:Double)
self.x = a.x + s
self.y = a.y + s
self.z = a.z + s
End Method

' ----------

'Example: v1 = v2 - v3 is written v1.Sub( v2, v3 )
Method Sub(a:TVector3, b:TVector3)
self.x = a.x - b.x
self.y = a.y - b.y
self.z = a.z - b.z
End Method

'Example: v1 = v2 - 5 is written v1.SubScalar( v2, 5 )
Method SubScalar(a:TVector3, s:Double)
self.x = a.x - s
self.y = a.y - s
self.z = a.z - s
End Method

' ----------

'Example: v1 = v2 * v3 is written v1.Mul( v2, v3 )
Method Mul(a:TVector3, b:TVector3)
self.x = a.x * b.x
self.y = a.y * b.y
self.z = a.z * b.z
End Method

'Example: v1 = v2 * 5 is written v1.MulScalar( v2, 5 )
Method MulScalar(a:TVector3, s:Double)
self.x = a.x * s
self.y = a.y * s
self.z = a.z * s
End Method

' ----------

'Example: v1 = v2 / v3 is written v1.Div( v2, v3 )
Method Div(a:TVector3, b:TVector3)
self.x = a.x / b.x
self.y = a.y / b.y
self.z = a.z / b.z
End Method

'Example: v1 = v2 / 5 is written v1.DivScalar( v2, 5 )
Method DivScalar(a:TVector3, s:Double)
self.x = a.x / s
self.y = a.y / s
self.z = a.z / s
End Method

' ----------

'Example: mag:Double = v.Magnitude()
Method Magnitude:Double()
Return Sqr(self.x * self.x + self.y * self.y + self.z * self.z)
End Method

'Example: v.Normalize()
Method Normalize()
Local mag:Double = self.Magnitude()
self.x :/ mag
self.y :/ mag
self.z :/ mag
If Abs(self.x) < Tol self.x = 0
If Abs(self.y) < Tol self.y = 0
If Abs(self.z) < Tol self.z = 0
End Method

' ----------

'Example: v1 = v2 ^ v3 is written v1.CrossProduct( v2, v3 )
Method CrossProduct(a:TVector3, b:TVector3)
self.x =  a.y * b.z - a.z * b.y
self.y = -a.x * b.z + a.z * b.x
self.z =  a.x * b.y - a.y * b.x
EndMethod

'Example1: dotp:double = v1.DotProduct( v2 )
Method DotProduct:Double( a:TVector3 )
Return self.x * a.x + self.y * a.y + self.z * a.z
End Method

' ----------

'Returns Inverse Instance of a Vector
Method Inverse:TVector3()
vTmp.x = -self.x
vTmp.y = -self.y
vTmp.z = -self.z
Return vTmp
End Method

' Example: v.GetVecFromQuat( q )
Method GetVecFromQuat(a:TQuaternion)
self.x = a.x
self.y = a.y
self.z = a.z
End Method

'Example: v.MakeEulerFromQuat( q )
Method MakeEulerFromQuat(q:TQuaternion)
Local r11#, r21#, r31#, r32#, r33#, r12#, r13#
Local q00#, q11#, q22#, q33#
Local tmp#

q00 = q.n * q.n
q11 = q.x * q.x
q22 = q.y * q.y
q33 = q.z * q.z

r11 = q00 + q11 - q22 - q33
r21 = 2 * (q.x*q.y + q.n*q.z)
r31 = 2 * (q.x*q.z - q.n*q.y)
r32 = 2 * (q.y*q.z + q.n*q.x)
r33 = q00 - q11 - q22 + q33

tmp = Abs(r31)
If (tmp > 0.999999)
r12 = 2 * (q.x*q.y - q.n*q.z)
r13 = 2 * (q.x*q.z + q.n*q.y)

self.x = RadiansToDegrees(0.0) ' roll
self.y = RadiansToDegrees( Float (-(Pi/2) * r31/tmp)) ' pitch
self.z = RadiansToDegrees( Float ATan2(-r12, -r31*r13))' yaw
Else
self.x = RadiansToDegrees( Float ATan2(r32, r33)) ' roll
self.y = RadiansToDegrees( Float ASin(-r31)) ' pitch
self.z = RadiansToDegrees( Float ATan2(r21, r11)) ' yaw
EndIf
End Method

' ----------

'Example: vPos.AddTimeStep( vVel, dt )
Method AddTimeStep(a:TVector3, timestep:Float)
self.x :+ a.x * timestep
self.y :+ a.y * timestep
self.z :+ a.z * timestep
End Method

'Example: vVel.AddGravity(  , dt )
Method AddGravity(g:Float = 9.8, timestep:Float)
self.y :- g * timestep
End Method

'Example1: v.Show("v",5,5)
Method Show(cap:String, xpos:Int, ypos:Int, spc:Int = 12)
DrawText cap + "_x:" + self.x,xpos,ypos
DrawText cap + "_y:" + self.y,xpos,ypos + spc
DrawText cap + "_z:" + self.z,xpos,ypos + spc * 2
End Method

End Type


' ----------
' ----------
' ----------


' Quaternion Class

Type TQuaternion

Field n:Double, x:Double, y:Double, z:Double

' ----------

Function Create:TQuaternion(n:Double = 1.0, x:Double = 0, y:Double = 0, z:Double = 0)
Local q:TQuaternion = New TQuaternion
q.n = n
q.x = x
q.y = y
q.z = z
Return q
End Function

' ----------

' Example: q1=q2+q3 would be q1.Add( q2, q3 )
Method Add(a:TQuaternion, b:TQuaternion)
self.n = a.n + b.n
self.x = a.x + b.x
self.y = a.y + b.y
self.z = a.z + b.z
End Method

' ----------

' Example: q1=q2-q3 would be q1.Sub( q2, q3 )
Method Sub(a:TQuaternion, b:TQuaternion)
self.n = a.n - b.n
self.x = a.x - b.x
self.y = a.y - b.y
self.z = a.z - b.z
End Method

' ----------

' Example: q1=q2*q3 would be q1.Mul( q2, q3 )
Method Mul(a:TQuaternion, b:TQuaternion)
self.n = a.n * b.n - a.x * b.x - a.y * b.y - a.z * b.z
self.x = a.n * b.x + a.x * b.n + a.y * b.z - a.z * b.y
self.y = a.n * b.y + a.y * b.n + a.z * b.x - a.x * b.z
self.z = a.n * b.y + a.y * b.n + a.z * b.x - a.x * b.z
End Method

' Example: q1=q2*2 would be q1.MulScalar( q2, 2 )
Method MulScalar( a:TQuaternion, s:Double )
self.n = a.n * s
self.x = a.x * s
self.y = a.y * s
self.z = a.z * s
End Method

' ----------

' Example: q1=q2/2 would be q1.DivS( q2, 2 )
Method DivScalar(a:TQuaternion, s:Double )
self.n = a.n / s
self.x = a.x / s
self.y = a.y / s
self.z = a.z / s
End Method

' ----------

' Example: Local qmag:Double = q.Magnitude()
Method Magnitude:Double( a:TQuaternion )
Return Sqr( a.n * a.n + a.x * a.x + a.y * a.y + a.z * a.z )
End Method

' ----------

'Returns Inverse Instance of a Quaternion
Method Inverse:TQuaternion()
qTmp.n =  self.n
qTmp.x = -self.x
qTmp.y = -self.y
qTmp.z = -self.z
Return qTmp
End Method

' ----------

'Example: q.MakeQuatFromEuler( pitch, yaw, roll )
Method MakeQuatFromEuler(x:Float, y:Float, z:Float)
Local roll:Float = DegreesToRadians(x)
Local pitch:Float = DegreesToRadians(y)
Local yaw:Float = DegreesToRadians(z)

Local cyaw#, cpitch#, croll#, syaw#, spitch#, sroll#
Local cyawcpitch#, syawspitch#, cyawspitch#, syawcpitch#

cyaw = Cos(0.5 * yaw)
cpitch = Cos(0.5 * pitch)
croll = Cos(0.5 * roll)
syaw = Sin(0.5 * yaw)
spitch = Sin(0.5 * pitch)
sroll = Sin(0.5 * roll)

cyawcpitch = cyaw*cpitch
syawspitch = syaw*spitch
cyawspitch = cyaw*spitch
syawcpitch = syaw*cpitch

self.n = Float (cyawcpitch * croll + syawspitch * sroll)
self.x = Float (cyawcpitch * sroll - syawspitch * croll)
self.y = Float (cyawspitch * croll + syawcpitch * sroll)
self.z = Float (syawcpitch * croll - cyawspitch * sroll)
End Method

' ----------


Method Show(cap:String = "", xpos:Int, ypos:Int, spc:Int = 12)
DrawText cap + "_w:" + self.n,xpos,ypos
DrawText cap + "_x:" + self.x,xpos,ypos + spc
DrawText cap + "_y:" + self.y,xpos,ypos + spc * 2
DrawText cap + "_z:" + self.z,xpos,ypos + spc * 3
End Method

End Type



' ----------
' ----------
' ----------

' Matrix Class

Type TMatrix

Field e11:Double, e12:Double, e13:Double
Field e21:Double, e22:Double, e23:Double
Field e31:Double, e32:Double, e33:Double

' ----------

Function Create:TMatrix(e11!=0, e12!=0, e13!=0, e21!=0, e22!=0, e23!=0, e31!=0, e32!=0, e33!=0)
Local m:TMatrix = New TMatrix
m.e11 = e11
m.e12 = e12
m.e13 = e13
m.e21 = e21
m.e22 = e22
m.e23 = e23
m.e31 = e31
m.e32 = e32
m.e33 = e33
Return m
End Function

' ----------


' ----------


End Type


' ----------
' ----------
' ----------


' Degrees To Radians Conversion
Function DegreesToRadians:Float(deg:Float)
Return deg * Pi / 180.0
End Function

' Radians To Degrees Conversion
Function RadiansToDegrees:Float(rad:Float)
Return rad * 180.0 / Pi
End Function


Comments :


DaMaul(Posted 1+ years ago)

 Hi, this is great :)But could you delete the old version as I managed to discover that before this!


DaMaul(Posted 1+ years ago)

 By the way, I believe there's a couple of small errors in this. This line:Function Create:TQuaternion(w:Double = 1.0, x:Double = 0, y:Double = 0, z:Double = 0)Should be:Function Create:TQuaternion(n:Double = 1.0, x:Double = 0, y:Double = 0, z:Double = 0)And also the line ( in the method "AddGravity" ):self.y :- g * time_stepShould be:self.y :- g * timestepCheers!


bradford6(Posted 1+ years ago)

 very nice. Question: Would using Floats instead of Doubles increase speed?


DJWoodgate(Posted 1+ years ago)

 Yes, but not by much.