Code archives/3D Graphics - Maths/Vector 3D Math Library [v1.7]

This code has been declared by its author to be Public Domain code.

Download source code

Vector 3D Math Library [v1.7] by Chroma2004
Here's my conversion of the Vector3D functions from C++. I originally posted this in the archives over 2 years ago. I've recently perused the code and made some improvements. Hopefully you'll find this immensely useful because I know I have. Have fun!

-Last Updated on November 30, 2004

v1.0 initial release Sept 15, 2002
v1.1 fixed errors in crossproduct Sept 17, 2002
v1.2 cleaned up some functions July 15, 2004
v1.3 most functions return vectors now! July 22,2004
v1.4 added function AddVectorTimeStep for easier physics use - July 23, 2004
v1.5 vTmp was not a good idea for internal calcs - caused vector bleeding - fixed! - July 23, 2004
v1.6 changed ReverseVector to use 2 vectors for ease of use
v1.7 renamed and rearranged the code slightly
;// Vector Math Library v1.7
;// by Chroma

;// Last Update: November 30, 2004
;// Comments: Renamed and rearranged the code slightly


;----------------------------------------------------------------------;
;// Testing...
;// Remove ";--" in front of lines to see the Vectory Library test demo
;--Graphics 400,300,16,2
;--SetBuffer BackBuffer()
;--AppTitle "Vector 3D Math Library v1.7 - Vector Addition Test"

;// Create two test vectors
;--this.Vector = Vector()
;--that.Vector = Vector(1,2,3)

;// Loop
;--While Not KeyHit(1)
;--Cls

;--Vector_Add(this,this,that)
;--Vector_Show(this,10,10,"Test")

;--Flip
;--Wend
;--End
;//...End Test
;----------------------------------------------------------------------;


;// Tolerance
Const tol# = 0.001


;// Vector Type
Type Vector
	Field x#
	Field y#
	Field z#
End Type


;// Create a Vector
;// Example: this.Vector = Vector()
;// Example: this.Vector = Vector(1,2,3)
Function Vector.Vector(x#=0,y#=0,z#=0)
	v.Vector = New Vector
	v\x=x
	v\y=y
	v\z=z
	Return v
End Function 


;// Set a Vector with New Components
Function Vector_Set(v.Vector,x#,y#,z#)
	v\x = x
	v\y = y
	v\z = z
End Function


;// Vector Component Set
;// Example 1: Vector_SetX(this.Vector,1.0)
;// Example 2: this\x = 1.0
Function Vector_SetX(v.Vector,x#)
	v\x = x
End Function

Function Vector_SetY(v.Vector,y#)
	v\y = y
End Function

Function Vector_SetZ(v.Vector,z#)
	v\z = z
End Function


;// Vector Component Retrieval
;// Example 1: myvar# = Vector_GetX(this.Vector)
;// Example 2: myvar# = this\x
Function Vector_GetX#(v.Vector)
	Return v\x
End Function

Function Vector_GetY#(v.Vector)
	Return v\y
End Function

Function Vector_GetZ#(v.Vector)
	Return v\z
End Function


;// Vector Addition
;// Form of: Vector1 = Vector2 + Vector3
Function Vector_Add(v1.Vector,v2.Vector,v3.Vector)
	v1\x = v2\x + v3\x
	v1\y = v2\y + v3\y
	v1\z = v2\z + v3\z
End Function


;// Vector Scalar Addition
;// Form of: Vector1 = Vector2 + Scalar#
Function Vector_AddScalar(v1.Vector,v2.Vector,s#)
	v1\x = v2\x + s
	v1\y = v2\y + s
	v1\z = v2\z + s
End Function


;// Vector Addition * Time Step
;// Form of: Vector1 = Vector1 + Vector2 * Time_Step#
Function Vector_AddTimeStep(v1.Vector,v2.Vector,time_step#)
	v1\x = v1\x + v2\x * time_step
	v1\y = v1\y + v2\y * time_step
	v1\z = v1\z + v2\z * time_step
End Function


;// Vector Subtraction
;// Form of: Vector1 = Vector2 - Vector3
Function Vector_Subtract(v1.Vector,v2.Vector,v3.Vector)
	v1\x = v2\x - v3\x
	v1\y = v2\y - v3\y
	v1\z = v2\z - v3\z
End Function


;// Vector Scalar Subtraction
;// Form of: Vector1 = Vector2 - Scalar#
Function Vector_SubtractScalar.Vector(v1.Vector,v2.Vector,s#)
	v1\x = v2\x - s
	v1\y = v2\y - s
	v1\z = v2\z - s
End Function


;// Vector Scalar Multiplication
;// Form of: Vector1 = Vector2 * Scalar#
Function Vector_MultiplyScalar(v1.Vector,v2.Vector,s#)
	v1\x = v2\x * s
	v1\y = v2\y * s
	v1\z = v2\z * s
End Function


;// Vector Scalar Division
;// Form of: Vector1 = Vector1 / Scalar#
Function Vector_DivideScalar(v1.Vector,v2.Vector,s#)
	v1\x = v2\x / s
	v1\y = v2\y / s
	v1\z = v2\z / s
End Function


;// Cross Product
;// Form of: Vector1 = U.Vector |CrossProduct| V.Vector
Function Vector_CrossProduct(v1.Vector,u.Vector,v.Vector)
	v1\x =  u\y * v\z  -  u\z * v\y 
	v1\y = -u\x * v\z  +  u\z * v\x 
	v1\z =  u\x * v\y  -  u\y * v\x
End Function


;// Dot Product
Function Vector_DotProduct#(u.Vector,v.Vector)
	Return u\x * v\x + u\y * v\y + u\z * v\z
End Function


;// Magnitude
;// Example: this_magnitude# = Vector_Magnitude(this.Vector)
Function Vector_Magnitude#(v.Vector)
	Return Sqr(v\x * v\x + v\y * v\y + v\z * v\z)
End Function


;// Normalize
;// Example: Vector_Normalize(this.Vector)
Function Vector_Normalize(v.Vector)
	mag#=Sqr(v\x * v\x + v\y * v\y + v\z * v\z)
	v\x = v\x / mag
	v\y = v\y / mag
	v\z = v\z / mag
	If (Abs(v\x) < tol) v\x = 0.0
	If (Abs(v\y) < tol) v\y = 0.0
	If (Abs(v\z) < tol) v\z = 0.0
End Function


;// Reverse a Vector
;// Form of: Vector1 = -Vector2
;// Example: Vector_Reverse(this.Vector,that.Vector)
Function Vector_Reverse(v1.Vector,v2.Vector)
	v1\x = -v2\x
	v1\y = -v2\y
	v1\z = -v2\z
End Function


;// Reset a Vector to Zero
;// Example: Vector_Reset(this.Vector)
Function Vector_Reset(v.Vector)
	v\x = 0.0
	v\y = 0.0
	v\z = 0.0
End Function


;// Vector 1 is set to Vector 2
;// Example 1: Vector_Clone(this.Vector,that.Vector)
;// Example 2: this.Vector = that.Vector
Function Vector_Clone(v1.Vector,v2.Vector)
	v1\x = v2\x
	v1\y = v2\y
	v1\z = v2\z
End Function


;// Free a Vector
;// Example: Vector_Free(this.Vector)
Function Vector_Free(v.Vector)
	Delete v
End Function


;// PositionEntity Replacement for Vector Object
;// Example: Vector_PositionEntity MyEntity,v.vector
Function Vector_PositionEntity(ent,v.vector)
	PositionEntity ent,v\x,v\y,v\z
End Function


;// Show Vector Values
;// Place This Function After Renderworld
;// Example: Vector_Show(this.Vector,15,15,"Test")
Function Vector_Show(v.Vector,xpos,ypos,label$)
	Text xpos,ypos, label$ + "_X=" + v\x
	Text xpos,ypos + 15,label$ + "_Y=" + v\y
	Text xpos,ypos + 30,label$ + "_Z=" + v\z
End Function


;// Degrees To Radians Conversion
Function DegreesToRadians#(deg#)
	Return deg * Pi / 180.0
End Function


;// Radians To Degrees Conversion
Function RadiansToDegrees#(rad#)
	Return rad * 180.0 / Pi
End Function

Comments

LarsG2005
Hey Chroma..
I enhanced your code a little bit.. I hope you don't mind?!

Strict
'// Vector Math Library v0.9
'// by Chroma
'// rewritten, extended and OOP'ified for use in BlitzMax by LarsG

'// Last Update: June 23, 2005
'// Comments: Enhanced and OOP'ified by LarsG


'----------------------------------------------------------------------;
'// Testing...

Global vec1:TVectorF
Global vec2:TVectorF

'// Create two test vectors
vec1 = TVectorF.Create(1,2,3)
vec2 = TVectorF.Create()
Print "Vec1: "
Print vec1.show(", ")
Print "vec2 cloning vec1..."
vec2.clone(vec1)
Print "Vec2: "
Print vec2.show(", ")
Print "Adding vec2 to vec1..."
vec1.add(vec2)
Print "Vec1: "
Print vec1.Show(", ")
End
'//...End Test
'----------------------------------------------------------------------;


'// Vector Type Float (32 Bit)
Type TVectorF
	Field x:Float
	Field y:Float
	Field z:Float

	Const TOL:Float 	= 0.001
	
	'**** THE METHODS *****
	Function Create:TVectorF(x:Float=0, y:Float=0, z:Float=0)
		Local v:TVectorF	= New TVectorF
		v.x 				= x
		v.y					= y
		v.z					= z
		Return v
	EndFunction
	
	Method Set(x:Float, y:Float, z:Float)
		self.x = x
		self.y = y
		self.z = z
	EndMethod
	
	Method SetX(x:Float)
		self.x = x
	EndMethod
	
	Method SetY(y:Float)
		self.y = y
	EndMethod
	
	Method SetZ(z:Float)
		self.z = z
	EndMethod
	
	Method GetX:Float()
		Return self.x
	EndMethod
	
	Method GetY:Float()
		Return self.y
	EndMethod
	
	Method GetZ:Float()
		Return self.z
	EndMethod

	Method Add(plus:TVectorF)
		self.x :+ plus.x
		self.y :+ plus.y
		self.z :+ plus.z
	EndMethod
	
	Method AddScalar(scale:Float)
		self.x :+ scale
		self.y :+ scale
		self.z :+ scale
	EndMethod
	
	Method AddTimeStep(plus:TVectorF, tstep:Float)
		self.x :+ (plus.x * tstep)
		self.y :+ (plus.y * tstep)
		self.z :+ (plus.z * tstep)
	EndMethod
	
	Method Subtract(sub:TVectorF)
		self.x :- sub.x
		self.y :- sub.y
		self.z :- sub.z
	EndMethod
	
	Method SubtractScalar(scale:Float)
		self.x :- scale
		self.y :- scale
		self.z :- scale
	EndMethod

	Method SubtractTimeStep(sub:TVectorF, tstep:Float)
		self.x :- (sub.x * tstep)
		self.y :- (sub.y * tstep)
		self.z :- (sub.z * tstep)
	EndMethod

	Method DivideScalar(scale:Float)
		self.x :/ scale
		self.y :/ scale
		self.z :/ scale
	EndMethod
	
	Method CrossProduct(vec1:TVectorF, vec2:TVectorF)
		self.x =  vec1.y * vec2.z  -  vec1.z * vec2.y 
		self.y = -vec1.x * vec2.z  +  vec1.z * vec2.x 
		self.z =  vec1.x * vec2.y  -  vec1.y * vec2.x
	EndMethod
	
	Method DotProduct:Float(vec:TVectorF)
		Return vec.x * self.x + vec.y * self.y + vec.z * self.z
	EndMethod
	
	Method Magnitude:Float()
		Return Sqr(self.x * self.x + self.y * Self.y + self.z * self.z)
	EndMethod
	
	Method Normalize()
		Local magnitude:Float = self.Magnitude()
		self.x :/ magnitude
		self.y :/ magnitude
		self.z :/ magnitude
		If (Abs(self.x) < self.TOL) Then self.x = 0.0
		If (Abs(self.y) < self.TOL) Then self.y = 0.0
		If (Abs(self.z) < self.TOL) Then self.z = 0.0
	EndMethod
	
	Method Reverse(vec:TVectorF)
		self.x = -vec.x
		self.y = -vec.y
		self.z = -vec.z
	EndMethod
	
	Method Reset()
		self.x = 0
		self.y = 0
		self.z = 0
	EndMethod
	
	Method Clone(vec:TVectorF)
		' not sure if it's neccesary to do it this way..
		' oh well.. it's there anyway
		' maybe self = vec will do..
		self.x = vec.x
		self.y = vec.y
		self.z = vec.z
	EndMethod

	Method Show:String(sep:String)
		Return	String(self.x) + sep + ..
				String(self.y) + sep + ..
				String(self.z)
	EndMethod

EndType

'// Vector Type Double (64 Bit)
Type TVectorD
	Field x:Double
	Field y:Double
	Field z:Double

	Const TOL:Double 	= 0.001
	
	'**** THE METHODS *****
	Function Create:TVectorD(x:Double=0, y:Double=0, z:Double=0)
		Local v:TVectorD	= New TVectorD
		v.x 				= x
		v.y					= y
		v.z					= z
		Return v
	EndFunction
	
	Method Set(x:Double, y:Double, z:Double)
		self.x = x
		self.y = y
		self.z = z
	EndMethod
	
	Method SetX(x:Double)
		self.x = x
	EndMethod
	
	Method SetY(y:Double)
		self.y = y
	EndMethod
	
	Method SetZ(z:Double)
		self.z = z
	EndMethod
	
	Method GetX:Double()
		Return self.x
	EndMethod
	
	Method GetY:Double()
		Return self.y
	EndMethod
	
	Method GetZ:Double()
		Return self.z
	EndMethod

	Method Add(plus:TVectorD)
		self.x :+ plus.x
		self.y :+ plus.y
		self.z :+ plus.z
	EndMethod
	
	Method AddScalar(scale:Double)
		self.x :+ scale
		self.y :+ scale
		self.z :+ scale
	EndMethod
	
	Method AddTimeStep(plus:TVectorD, tstep:Double)
		self.x :+ (plus.x * tstep)
		self.y :+ (plus.y * tstep)
		self.z :+ (plus.z * tstep)
	EndMethod
	
	Method Subtract(sub:TVectorD)
		self.x :- sub.x
		self.y :- sub.y
		self.z :- sub.z
	EndMethod
	
	Method SubtractScalar(scale:Double)
		self.x :- scale
		self.y :- scale
		self.z :- scale
	EndMethod

	Method SubtractTimeStep(sub:TVectorD, tstep:Double)
		self.x :- (sub.x * tstep)
		self.y :- (sub.y * tstep)
		self.z :- (sub.z * tstep)
	EndMethod

	Method DivideScalar(scale:Double)
		self.x :/ scale
		self.y :/ scale
		self.z :/ scale
	EndMethod
	
	Method CrossProduct(vec1:TVectorD, vec2:TVectorD)
		self.x =  vec1.y * vec2.z  -  vec1.z * vec2.y 
		self.y = -vec1.x * vec2.z  +  vec1.z * vec2.x 
		self.z =  vec1.x * vec2.y  -  vec1.y * vec2.x
	EndMethod
	
	Method DotProduct:Double(vec:TVectorD)
		Return vec.x * self.x + vec.y * self.y + vec.z * self.z
	EndMethod
	
	Method Magnitude:Double()
		Return Sqr(self.x * self.x + self.y * Self.y + self.z * self.z)
	EndMethod
	
	Method Normalize()
		Local magnitude:Double = self.Magnitude()
		self.x :/ magnitude
		self.y :/ magnitude
		self.z :/ magnitude
		If (Abs(self.x) < self.TOL) Then self.x = 0.0
		If (Abs(self.y) < self.TOL) Then self.y = 0.0
		If (Abs(self.z) < self.TOL) Then self.z = 0.0
	EndMethod
	
	Method Reverse(vec:TVectorD)
		self.x = -vec.x
		self.y = -vec.y
		self.z = -vec.z
	EndMethod
	
	Method Reset()
		self.x = 0
		self.y = 0
		self.z = 0
	EndMethod
	
	Method Clone(vec:TVectorD)
		self.x = vec.x
		self.y = vec.y
		self.z = vec.z
	EndMethod

	Method Show:String(sep:String)
		Return	String(self.x) + sep + ..
				String(self.y) + sep + ..
				String(self.z)
	EndMethod

EndType



Braincell2005
Thanks. I will probably use some of this in my free stencil shadows library, incl your credits.


Chroma2005
I'm guessing that's it converted to BMax. Looks pretty nice. I personally would have substituted the word "self" for "this". :)

Just looking at your conversion makes me want to buy BMax right now...but I'm gonna wait until the OpenGL module is totally complete. I hate hacking graphics.


LarsG2005
Yeah.. I basically converted it.. and added the option of using Doubles as well..
Hope I got it right.. (seeing as I'm not very good at this kind of math.. just followed your calculations.. :P)

side note; cool that the code makes you want to buy BMax right away.. hehe.. and you should.. that way you can play with it, and make yourself familiar with it, until the 3D module is released.. :)


Chroma2005
Just bought bmax today and I'm finishing up my vector lib conversion...and it's looks pretty darn similar to yours. Nice job there LarsG. :)


Chroma2005
I took out the Reset command. Seems very unnecessary since you can just do a:

vPos.Set(0,0,0)

Also set the Set command to default x,y,z to 0. So you could also just do a:

vPos.Set()

Edit: Also took out the SetX,Y,Z and GetX,Y,Z since you can access them directly with something like:

vPos.x = 20
Local this:Float = vPos.x

Still tweaking here.


Code Archives Forum