Code archives/3D Graphics - Maths/Cower.Math3D

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

Download source code

Cower.Math3D by N2005
Place this under mod/cower.mod/math3d.mod/math3d.bmx

Have fun.
Rem
	This software is written by Noel R. Cower
	<hooker.with.a.penis@gmail.com>
	
	Copyright (C) 2005 Noel Raymond Cower
EndRem

Rem bbdoc: 3D Maths
EndRem
Module Cower.Math3D

Import Brl.Math

Strict

Private

Const RAD_TO_DEGREE! = 180!/Pi
Const DEGREE_TO_RAD! = Pi/180!

Public

Rem bbdoc: Converts degrees to radians
End Rem
Function DegreeToRad!( d! )
	Return d*DEGREE_TO_RAD
End Function

Rem bbdoc: Converts radians to degrees
End Rem
Function RadToDegree!( r! )
	Return r*RAD_TO_DEGREE
End Function

Rem bbdoc: Gets the cotangent of an angle
End Rem
Function Cotangent!( A! )
	Return Tan( 90! - A )
End Function

Rem bbdoc: Gets the nearest power of two to an integer
End Rem
Function NearestPower:Int( i:Int )
	Local q:Int,r:Int=1
	While Not ( i < r And i > q )
		q=r
		r=q*2
	Wend
	Local da:Int=i-q
	Local db:Int=r-i
	If da > db Then
		Return r
	Else
		Return q
	EndIf
End Function

Rem bbdoc: Gets the slope of two points
End Rem
Function Slope!( x1!, y1!, x2!, y2! )
	Local m! = ( y1-y2 )/( x1-x2 )
	If m <= .0001! And m > 0! Then Return .0001!
	If m >= -.0001! And m < 0! Then Return -.0001!
	Return m
End Function

Rem bbdoc: Gets the Y intercept of two points
End Rem
Function YIntercept!( x1!, y1!, x2!, y2! )
	Return y1 - ( Slope( x1, y1, x2, y2 ) * x1 )
End Function

Rem bbdoc: Gets the Y value of X along the line made by two points
End Rem
Function ReturnedY!( x!, x1!, y1!, x2!, y2! )
	Return Slope( x1, y1, x2, y2 ) * x + YIntercept( x1, y1, x2, y2 )
End Function

Rem bbdoc: 4-by-4 homogenous matrix class
about:
Keep in mind that aside from Translate and Scale, all methods
will return a new matrix with the requested operations performed.
End Rem
Type Matrix
	Field m00! = 1, m01! = 0, m02! = 0, m03! = 0
	Field m10! = 0, m11! = 1, m12! = 0, m13! = 0
	Field m20! = 0, m21! = 0, m22! = 1, m23! = 0
	Field m30! = 0, m31! = 0, m32! = 0, m33! = 1
	
	Rem bbdoc: Copies the Matrix class
	End Rem
	Method Copy:Matrix( )
		Local i:Matrix = New Matrix
		MemCopy( Varptr i.m00, Varptr m00, 64 )
		Return i
	End Method
	
	Rem bbdoc: Sets the translation elements of the matrix
	End Rem
	Method Translate( x!, y!, z! )
		m03 = x
		m13 = y
		m23 = z
	End Method
	
	Rem bbdoc: Gets the translation elements of the matrix
	End Rem
	Method GetTranslation( x! Var, y! Var, z! Var )
		x = m03
		y = m13
		z = m23
	End Method
	
	Rem bbdoc: Scales the rotation elements of the matrix
	End Rem
	Method Scale( x!, y!, z! )
		m00 :* x
		m10 :* x
		m20 :* x
		
		m01 :* y
		m11 :* y
		m21 :* y
		
		m02 :* z
		m12 :* z
		m22 :* z
	End Method
	
	Rem bbdoc: Transforms the matrix by another matrix
	End Rem
	Method TransformMat:Matrix( i:Matrix )
		Local r:Matrix = New Matrix
		
		r.m00 = m00 * i.m00 + m01 * i.m10 + m02 * i.m20 + m03 * i.m30
		r.m01 = m00 * i.m01 + m01 * i.m11 + m02 * i.m21 + m03 * i.m31
		r.m02 = m00 * i.m02 + m01 * i.m12 + m02 * i.m22 + m03 * i.m32
		r.m03 = m00 * i.m03 + m01 * i.m13 + m02 * i.m23 + m03 * i.m33
		
		r.m10 = m10 * i.m00 + m11 * i.m10 + m12 * i.m20 + m13 * i.m30
		r.m11 = m10 * i.m01 + m11 * i.m11 + m12 * i.m21 + m13 * i.m31
		r.m12 = m10 * i.m02 + m11 * i.m12 + m12 * i.m22 + m13 * i.m32
		r.m13 = m10 * i.m03 + m11 * i.m13 + m12 * i.m23 + m13 * i.m33
		
		r.m20 = m20 * i.m00 + m21 * i.m10 + m22 * i.m20 + m23 * i.m30
		r.m21 = m20 * i.m01 + m21 * i.m11 + m22 * i.m21 + m23 * i.m31
		r.m22 = m20 * i.m02 + m21 * i.m12 + m22 * i.m22 + m23 * i.m32
		r.m23 = m20 * i.m03 + m21 * i.m13 + m22 * i.m23 + m23 * i.m33
		
		r.m30 = m30 * i.m00 + m31 * i.m10 + m32 * i.m20 + m33 * i.m30
		r.m31 = m30 * i.m01 + m31 * i.m11 + m32 * i.m21 + m33 * i.m31
		r.m32 = m30 * i.m02 + m31 * i.m12 + m32 * i.m22 + m33 * i.m32
		r.m33 = m30 * i.m03 + m31 * i.m13 + m32 * i.m23 + m33 * i.m33
		
		Return r
	End Method
	
	Rem bbdoc: Transforms a vector by the matrix
	End Rem
	Method TransformVec:Vector3( i:Vector3, addTranslation:Int = 0 )
		Local r:Vector3 = New Vector3
		Local w! = 1.0/( m30 + m31 + m32 + m33 )
		
		addTranslation = Min( Max( addTranslation, 0 ), 1 )
		
		r.x = ( ( m00*i.x ) + ( m01*i.y ) + ( m02*i.z ) + m03 * addTranslation ) * w
		r.y = ( ( m10*i.x ) + ( m11*i.y ) + ( m12*i.z ) + m13 * addTranslation ) * w
		r.z = ( ( m20*i.x ) + ( m21*i.y ) + ( m22*i.z ) + m23 * addTranslation ) * w
		
		Return r
	End Method
	
	Rem bbdoc: Adds two matrices
	End Rem
	Method Add:Matrix( i:Matrix )
		Local a:Double Ptr = GetPtr( )
		Local b:Double Ptr = GetPtr( )
		Local r:Matrix = New Matrix
		Local c:Double Ptr = r.GetPtr( )
		For Local n:Int = 0 To 15
			c[n]=a[n]+b[n]
		Next
		Return r
	End Method
	
	Rem bbdoc: Subtracts two matrices
	End Rem
	Method Subtract:Matrix( i:Matrix )
	 Local a:Double Ptr = GetPtr( )
		Local b:Double Ptr = GetPtr( )
		Local r:Matrix = New Matrix
		Local c:Double Ptr = r.GetPtr( )
		For Local n:Int = 0 To 15
			c[n]=a[n]-b[n]
		Next
		Return r
	End Method
	
	Rem bbdoc: Transposes the matrix
	End Rem
	Method Transpose:Matrix( )
	 Local x:Int,y:Int
	 Local r:Matrix = New Matrix
	 Local a:Double Ptr = GetPtr( )
	 Local b:Double Ptr = r.GetPtr( )
	 For x = 0 To 3
		 For y = 0 To 3
			 b[x*4+y] = a[y*4+x]
		 Next
	 Next
	 Return r
	End Method
	
	Rem bbdoc: Returns a pointer to the first matrix element
	End Rem
	Method GetPtr:Double Ptr( )
		Return Varptr m00
	End Method
	
	Rem bbdoc: Returns an array made from the elements of the matrix
	End Rem
	Method ToArray:Double[]( )
		Local r:Double[16]
		MemCopy( Varptr r[0], GetPtr( ), 64 )
		Return r
	End Method
	
	Rem bbdoc: Creates a matrix from an array of Doubles
	End Rem
	Function FromArray:Matrix( arr:Double[] )
		Return FromPtr( Varptr arr[0] )
	End Function
	
	Rem bbdoc: Creates an array from a pointer to an array of Doubles
	End Rem
	Function FromPtr:Matrix( arr:Double Ptr )
		Local r:Matrix = New Matrix
		Local p:Double Ptr = r.GetPtr( )
		MemCopy( p, arr, 64 )
		Return r
	End Function
End Type

Rem bbdoc: Three-component vector class
about:
Keep in mind that aside from Dot, Magnitude, Normalize, Floor, and Ceil,
all methods will return a new Vector3 with the requested operations performed.
End Rem
Type Vector3
	Rem bbdoc: X component
	End Rem
	Field x!
	Rem bbdoc: Y component
	End Rem
	Field y!
	Rem bbdoc: Z component
	End Rem
	Field z!
	
	Rem bbdoc: Adds a vector
	End Rem
	Method Add:Vector3( i:Vector3 )
		Local r:Vector3 = New Vector3
		r.x = x+i.x
		r.y = y+i.y
		r.z = z+i.z
		Return r
	End Method
	
	Rem bbdoc: Subtracts a vector
	End Rem
	Method Subtract:Vector3( i:Vector3 )
		Local r:Vector3 = New Vector3
		r.x = x-i.x
		r.y = y-i.y
		r.z = z-i.z
		Return r
	End Method
	
	Rem bbdoc: Multiplies a vector with another vector
	End Rem
	Method Multiply:Vector3( i:Vector3 )
		Local r:Vector3 = New Vector3
		r.x = x*i.x
		r.y = y*i.y
		r.z = z*i.z
		Return r
	End Method
	
	Rem bbdoc: Divides a vector by another vector
	End Rem
	Method Divide:Vector3( i:Vector3 )
		Local r:Vector3 = New Vector3
		r.x = x/i.x
		r.y = y/i.y
		r.z = z/i.z
		Return r
	End Method
	
	Rem bbdoc: Scales a vector by a scalar
	End Rem
	Method Scale:Vector3( i:Double )
		Local r:Vector3 = New Vector3
		r.x = x*i
		r.y = y*i
		r.z = z*i
		Return r
	End Method
	
	Rem bbdoc: Gets the dot product of two vectors (Self and another)
	End Rem
	Method Dot:Double( i:Vector3 )
		Return x*i.x+y*i.y+z*i.z
	End Method
	
	Rem bbdoc: Gets the magnitude of the vector
	End Rem
	Method Magnitude:Double( )
		Return Sqr( x*x + y*y + z*z )
	End Method
	
	Rem bbdoc: Normalizes the vector
	End Rem
	Method Normalize( )
		Local s:Double = 1.0 / Magnitude( )
		x:*s
		y:*s
		z:*s
	End Method
	
	Rem bbdoc: Gets the cross product of two vectors (Self and another)
	End Rem
	Method Cross:Vector3( i:Vector3 )
		Local r:Vector3 = New Vector3
		r.x = y*i.z - z*i.y
		r.y = x*i.z - z*i.x
		r.z = x*i.y - y*i.x
		Return r
	End Method
	
	Rem bbdoc: Returns a reflection vector
	End Rem
	Method Reflect:Vector3( i:Vector3 )
		Local f:Double = 2*Dot( i )
		Return Subtract( i.Scale( f ) )
	End Method
	
	Rem bbdoc: Returns a quaternion containing the rotation between two vectors
	End Rem
	Method RotationTo:Quaternion( dest:Vector3 )
		' Based on the Axiom engine's Vector3.GetRotationTo method code
		' Which is in turn based on Stan Melax's article in Game Programming Gems
		Local q:Quaternion = New Quaternion
		
		Local v0:Vector3 = Vector3.Create( x, y, z )
		Local v1:Vector3 = New Vector3
	 
		Local c:Vector3 = v0.Cross( v1 )
		Local d:Double = v0.Dot( v1 )
		
		If d >= 1.0 Then Return New Quaternion
	 
		Local s:Double = Sqr( ( 1+d ) * 2 )
		Local inverse:Double = 1.0 / s
		
		q.x = c.x * inverse
		q.y = c.y * inverse
		q.z = c.z * inverse
		q.w = s*.5
	 
		Return q
	End Method
	
	Rem bbdoc: Floors a vector
	End Rem
	Method Floor( i:Vector3 )
		If i.x < x Then x = i.x
		If i.y < y Then y = i.y
		If i.z < z Then z = i.z
	End Method
	
	Rem bbdoc: Ceils a vector
	End Rem
	Method Ceil( i:Vector3 )
		If i.x > x Then x = i.x
		If i.y > y Then y = i.y
		If i.z > z Then z = i.z
	End Method
	
	Rem bbdoc: Returns a pointer to the first component of the vector
	End Rem
	Method GetPtr:Double Ptr( )
		Return Varptr x
	End Method
	
	Rem bbdoc: Converts the vector to a Double array
	End Rem
	Method ToArray:Double[]( )
		Local r:Double[3]
		MemCopy( Varptr r[0], GetPtr( ), 12 )
		Return r
	End Method
	
	Rem bbdoc: Copies the Vector3 class
	End Rem
	Method Copy:Vector3( )
		Local i:Vector3 = New Vector3
		MemCopy( i.GetPtr( ), GetPtr( ), 12 )
		Return i
	End Method
	
	Rem bbdoc: Creates a new vector
	End Rem
	Function Create:Vector3( x!, y!, z! )
		Local i:Vector3 = New Vector3
		i.x = x
		i.y = y
		i.z = z
		Return i
	End Function
	
	Rem bbdoc: Creates a vector from an array of Doubles
	End Rem
	Function FromArray:Vector3( arr:Double[] )
		Return FromPtr( Varptr arr[0] )
	End Function
	
	Rem bbdoc: Creates a vector from a pointer to a Double array
	End Rem
	Function FromPtr:Vector3( arr:Double Ptr )
		Local r:Vector3 = New Vector3
		Local p:Double Ptr = r.GetPtr( )
		MemCopy( p, arr, 12 )
		Return r
	End Function
End Type

Rem bbdoc: Quaternion class.
about:
A lot of code in this class is based off of that in the
<a href="http://www.axiom3d.org">Axiom engine</a>.<br/><br/>
Aside from Magnitude, Normalize, and Dot, all methods will
return a new Quaternion with the requested operations performed.
End Rem
Type Quaternion
	Rem bbdoc: W component
	End Rem
	Field w!=1
	Rem bbdoc: X component
	End Rem
	Field x!=0
	Rem bbdoc: Y component
	End Rem
	Field y!=0
	Rem bbdoc: Z component
	End Rem
	Field z!=0
	
	Rem bbdoc: Gets the magnitude of the quaternion
	End Rem
	Method Magnitude:Double( )
		Return Sqr( w*w + x*x + y*y + z*z )
	End Method
	
	Rem bbdoc: Normalizes a quaternion
	End Rem
	Method Normalize( )
		Local s:Double = 1.0 / Magnitude( )
		w:*s
		x:*s
		y:*s
		z:*s
	End Method
	
	Rem bbdoc: Multiplies a quaternion
	End Rem
	Method MultiplyQuat:Quaternion( i:Quaternion )
		Local r:Quaternion = New Quaternion
		
		r.w = w*i.w - x*i.x - y*i.y - z*i.z
		r.x = w*i.x - x*i.w - y*i.z - z*i.y
		r.y = w*i.y - y*i.w - z*i.x - x*i.z
		r.z = w*i.z - z*i.w - x*i.y - y*i.x
		
		Return r
	End Method
	
	Rem bbdoc: Multiplies a vector
	End Rem
	Method MultiplyVec:Vector3( i:Vector3 )
		Local a:Vector3,b:Vector3,c:Vector3=Vector3.FromArray( [x,y,z] )
		a=c.Cross( i )
		b=c.Cross( a )
		a.Scale( 2*w )
		b.Scale( 2 )
		
		Return i.Add( a.Add( b ) )
	End Method
	
	Rem bbdoc: Scales the quaternion
	End Rem
	Method Scale:Quaternion( f:Double )
		Local r:Quaternion = New Quaternion
		r.w = w*f
		r.x = x*f
		r.y = y*f
		r.z = z*f
		Return r
	End Method
	
	Rem bbdoc: Adds the quaternion
	End Rem
	Method Add:Quaternion( i:Quaternion )
		Local r:Quaternion = New Quaternion
		r.w = w+i.w
		r.x = x+i.x
		r.y = y+i.y
		r.z = z+i.z
		Return r
	End Method
	
	Rem bbdoc: Subtracts the quaternion
	End Rem
	Method Subtract:Quaternion( i:Quaternion )
		Local r:Quaternion = New Quaternion
		r.w = w+i.w
		r.x = x+i.x
		r.y = y+i.y
		r.z = z+i.z
		Return r
	End Method
	
	Rem bbdoc: Gets the dot product of two quaternions (Self and another)
	End Rem
	Method Dot:Double( i:Quaternion )
		Return w*i.w + x*i.x + y*i.y + z*i.z
	End Method
	
	Rem bbdoc: Gets the quaternion slerp of two quaternions
	End Rem
	Function Slerp:Quaternion( time:Double, a:Quaternion, b:Quaternion, useShortest = False )
		' Based off of code in Axiom
		Local cs:Double = a.Dot( b )
		Local angle:Double = ACos( cs )
		
		If Abs(angle) < .0001 Then Return a.Copy( )
		
		Local sn:Double = Sin( angle )
		Local iSin:Double = 1.0/sn
		Local co1:Double = Sin( ( 1.0-time ) * angle ) * iSin
		Local co2:Double = Sin( time * angle ) * iSin
		
		Local r:Quaternion
		
		If cs < .0 And useShortest > 0 Then
			co1 = -co1
			r = a.Scale( co1 ).Add( b.Scale( co2 ) )
			r.Normalize( )
		Else
			r = a.Scale( co1 ).Add( b.Scale( co2 ) )
		EndIf
		
		Return r
	End Function
	
	Rem bbdoc: Creates a quaternion from an angle and an axis
	End Rem
	Function FromAngleAxis:Quaternion( a:Double, ax:Vector3 )
		' Based off of code in Axiom
		Local r:Quaternion = New Quaternion
		
		Local ha:Double = .5*a
		Local sn:Double = Sin( ha )
		
		r.w = Cos( ha )
		r.x = sn*ax.x
		r.y = sn*ax.y
		r.z = sn*ax.z
		
		Return r
	End Function
	
	Rem bbdoc: Blank
	End Rem
	Function Squad:Quaternion( t:Double, p:Quaternion, a:Quaternion, b:Quaternion, q:Quaternion, useShortest = False )
		' Based off of code in Axiom
		Local time:Double = 2*t*( 1.0-t )
		
		Local slerpA:Quaternion = Slerp( t, p, q, useShortest )
		Local slerpB:Quaternion = Slerp( t, a, b )
		
		Return Slerp( time, slerpA, slerpB )
	End Function
	
	Rem bbdoc: Sets @angle to the angle of the quaternion and @ax to the axis.
	End Rem
	Method ToAngleAxis( angle:Double Var, ax:Vector3 Var )
		' Based off of code in Axiom
		Local sqrLen:Double = x*x + y*y + z*z
		
		If sqrLen > 0 Then
			angle = 2 * ACos( w )
			Local invLength:Double = 1.0 / Sqr( sqrLen )
			ax.x = x * invLength
			ax.y = y * invLength
			ax.z = z * invLength
		Else
			angle = 0
			ax.x = 1
			ax.y = 0
			ax.z = 0
		EndIf
	End Method
	
	Rem bbdoc: Returns a matrix made from the quaternion
	End Rem
	Method ToMatrix:Matrix( )
		' Based off of code in Axiom
		Local m:Matrix = New Matrix
		
		Local tx! = 2*x
		Local ty! = 2*y
		Local tz! = 2*z
		Local twx! = tx*w
		Local twy! = ty*w
		Local twz! = tz*w
		Local txx! = tx*x
		Local txy! = ty*x
		Local txz! = tz*x
		Local tyy! = ty*y
		Local tyz! = tz*y
		Local tzz! = tz*z
		
		m.m00 = 1.0-(tyy+tzz)
		m.m01 = txy-twz
		m.m02 = txz+twy
		m.m10 = txy+twz
		m.m11 = 1.0-(txx+tzz)
		m.m12 = tyz-twx
		m.m20 = txz-twy
		m.m21 = tyz+twx
		m.m22 = 1.0-(txx+tyy)
		
		Return m
	End Method
	
	Rem bbdoc: Returns the inverse of the quaternion
	End Rem
	Method Inverse:Quaternion( )
		Local norm:Double = Dot( Self )
		If norm > 0 Then
			Local r:Quaternion = New Quaternion
			Local inorm:Double = 1.0 / norm
			r.w = w * inorm
			r.x = -x * inorm
			r.y = -y * inorm
			r.z = -z * inorm
			Return r
		EndIf
		
		Return Quaternion.Zero( )
	End Method
	
	Rem bbdoc: Returns the axises of the quaternion
	End Rem
	Method ToAxes( xAxis:Vector3 Var, yAxis:Vector3 Var, zAxis:Vector3 Var )
		xAxis = New Vector3
		yAxis = New Vector3
		zAxis = New Vector3
		
		Local rot:Matrix = ToMatrix( )
		
		xAxis.x = rot.m00
		xAxis.y = rot.m10
		xAxis.z = rot.m20
		
		yAxis.x = rot.m01
		yAxis.y = rot.m11
		yAxis.z = rot.m21
		
		zAxis.x = rot.m02
		zAxis.y = rot.m12
		zAxis.z = rot.m22
	End Method
	
	Rem bbdoc: Creates a quaternion from axises
	End Rem
	Method FromAxes( xAxis:Vector3, yAxis:Vector3, zAxis:Vector3 )
		Local rot:Matrix = New Matrix
		
		rot.m00 = xAxis.x
		rot.m10 = xAxis.y
		rot.m20 = xAxis.z
		
		rot.m01 = yAxis.x
		rot.m11 = yAxis.y
		rot.m21 = yAxis.z
		
		rot.m02 = zAxis.x
		rot.m12 = zAxis.y
		rot.m22 = zAxis.z
		
		Local q:Quaternion = FromRotationMatrix( rot )
		MemCopy( GetPtr( ), q.GetPtr( ), 16 )
	End Method
	
	Rem bbdoc: Creates a quaternion from a matrix
	End Rem
	Function FromRotationMatrix:Quaternion( mat:Matrix )
		Local this:Quaternion = New Quaternion
		
		Local trace:Double = mat.m00 + mat.m11 + mat.m22
		Local root:Double = 0
		
		If trace > 0 Then
			root = Sqr( trace + 1 )
			this.w = .5 * root
			root = .5 / root
			this.x = ( mat.m21-mat.m12 ) * root
			this.y = ( mat.m02-mat.m20 ) * root
			this.z = ( mat.m10-mat.m01 ) * root
		Else
			Local p:Double Ptr = mat.GetPtr( )
			Local i:Int = 0
			If mat.m11 > mat.m00 Then i=1
			If mat.m22 > p[i*4+i] Then i=2
			
			Local j:Int = _next( i )
			Local k:Int = _next( j )
			
			root = Sqr( p[i*4+i] - p[j*4+j] - p[k*4+k] + 1.0 )
			
			Local aq:Double Ptr = this.GetPtr( )
			aq[i] = .5 * root
			this.w = .5 / root
			aq[j] = (p[j+i*4] + p[i+j*4])*root
			aq[k] = (p[k+i*4] + p[i+k*4])*root
		EndIf
		
		Return this
		
		Function _next( i:Int )
			Select i
				Case 0
					Return 1
				Case 1
					Return 2
				Case 2
					Return 0
			End Select
		End Function
	End Function
	
	Rem bbdoc: Blank
	End Rem
	Method Log:Quaternion( )
		Local r:Quaternion = Quaternion.Zero( )
		If Abs( w ) < 1.0 Then
			Local angle:Double = ACos( w )
			Local sn:Double = Sin( angle )
			
			If Abs( sn ) > .0001 Then
				Local co:Double = angle / sn
				r.x = co*x
				r.y = co*y
				r.z = co*z
			Else
				r.x = x
				r.y = y
				r.z = z
			EndIf
		EndIf
		
		Return r
	End Method
	
	Rem bbdoc: Gets a zero-ed quaternion
	End Rem
	Function Zero:Quaternion( )
		Return Create( 0, 0, 0, 0 )
	End Function
	
	Rem bbdoc: Creates a new quaternion
	End Rem
	Function Create:Quaternion( w! = 1, x! = 0, y! = 0, z! = 0 )
		Local r:Quaternion = New Quaternion
		r.w = w; r.x = x; r.y = y; r.z = z
		Return r
	End Function
	
	Rem bbdoc: Converts the quaternion to a Double array
	End Rem
	Method ToArray:Double[]( )
		Local r:Double[4]
		MemCopy( Varptr r[0], GetPtr( ), 16 )
		Return r
	End Method
	
	Rem bbdoc: Returns a Double pointer to the first component of the quaternion
	End Rem
	Method GetPtr:Double Ptr( )
		Return Varptr w
	End Method
	
	Rem bbdoc: Creates a quaternion from an array
	End Rem
	Function FromArray:Quaternion( arr:Double[] )
		Return FromPtr( Varptr arr[0] )
	End Function
	
	Rem bbdoc: Creates a quaternion from a pointer to a Double array
	End Rem
	Function FromPtr:Quaternion( arr:Double Ptr )
		Local r:Quaternion = New Quaternion
		MemCopy( r.GetPtr( ), arr, 16 )
		Return r
	End Function
	
	Rem bbdoc: Copies the quaternion class
	End Rem
	Method Copy:Quaternion( )
		Local r:Quaternion = New Quaternion
		MemCopy( r.GetPtr( ), GetPtr( ), 16 )
		Return r
	End Method
End Type

Rem bbdoc: Plane class
End Rem
Type Plane
	Field norm:Vector3, d!
	
	Method New( )
		norm = Vector3.Create( 0, 1, 0 )
		d = 1
	End Method
	
	Rem bbdoc: Gets the distance from a vector to the plane
	End Rem
	Method Distance!( p:Vector3 )
		Return norm.Dot( p ) + d
	End Method
	
	Rem bbdoc: Returns which side of the plane a vector is on
	End Rem
	Method Side( p:Vector3 )
		Local di:Double = Distance( p )
		
		If di > 0 Then
			Return 1
		ElseIf di < 0 Then
			Return -1
		EndIf
		Return 0
	End Method
	
	Rem bbdoc: Gets the plane normal vector
	End Rem
	Method GetNormal:Vector3( )
		Return norm.Copy( )
	End Method
	
	Rem bbdoc: Creates a new plane
	End Rem
	Function Create:Plane( normal:Vector3, d! )
		Local i:Plane = New Plane
		i.norm = normal.Copy( )
		i.d = d
		Return i
	End Function
	
	Rem bbdoc: Creates a plane from an array of Doubles
	End Rem
	Function FromArray:Plane( arr:Double[] )
		Return FromPtr( Varptr arr[0] )
	End Function
	
	Rem bbdoc: Creates a plane from a pointer to an array of Doubles
	End Rem
	Function FromPtr:Plane( arr:Double Ptr )
		Local i:Plane = New Plane
		i.norm = Vector3.FromPtr( arr )
		i.d = arr[3]
		Return i
	End Function
	
	'' Can't do a standard memory copy for Planes, as they have a Vector3 reference
	Rem bbdoc: Copies the Plane class
	End Rem
	Method Copy:Plane( )
		Local i:Plane = New Plane
		i.d = d
		i.norm = norm.Copy( )
		Return i
	End Method
End Type

Rem bbdoc: Rectangle class
End Rem
Type Rectangle
	Rem bbdoc: X component
	End Rem
	Field x!
	Rem bbdoc: Y component
	End Rem
	Field y!
	Rem bbdoc: Width component
	End Rem
	Field w!
	Rem bbdoc: Height component
	End Rem
	Field h!
	
	Rem bbdoc: Whether or not the rectangle intersects with another rectangle
	End Rem
	Method Intersects( other:Rectangle )
		If x > other.x+other.w Or..
			x+w < other.x Or..
			y > other.y+other.h Or..
			y+h < other.y Then Return 0
		Return 1
	End Method
	
	Rem bbdoc: Returns whether or not @p is inside the rectangle
	End Rem
	Method PointInside( p:Vector2 )
		If p.x < x+w And p.y < y+h And p.x > x And p.y > y Then Return 1
		Return 0
	End Method
End Type

Rem bbdoc: Vector2 class
End Rem
Type Vector2
	Rem bbdoc: X component
	End Rem
	Field x!
	Rem bbdoc: Y component
	End Rem
	Field y!
	
	Rem bbdoc: Returns the magnitude of the point
	End Rem
	Method Magnitude!( )
		Return Sqr( x*x + y*y )
	End Method
	
	Rem bbdoc: Returns the difference of two points
	End Rem
	Method Subtract:Vector2( i:Vector2 )
		Return Create( x-i.x, y-i.y )
	End Method
	
	Rem bbdoc: Returns the sum of two points
	End Rem
	Method Add:Vector2( i:Vector2 )
		Return Create( x+i.x, y+i.y )
	End Method
	
	Rem bbdoc: Returns the product of two points
	End Rem
	Method Multiply:Vector2( i:Vector2 )
		Return Create( x*i.x, y*i.y )
	End Method
	
	Rem bbdoc: Returns the divisor of two points
	End Rem
	Method Divide:Vector2( i:Vector2 )
		Return Create( x/i.x, y/i.y )
	End Method
	
	Rem bbdoc: Creates a new point
	End Rem
	Function Create:Vector2( x!, y! )
		Local i:Vector2 = New Vector2
		i.x = x
		i.y = y
		Return i
	End Function
	
	Rem bbdoc: Copies the point
	End Rem
	Method Copy:Vector2( )
		Return Create( x, y )
	End Method
End Type

Comments

Warren2005
Nice one, Noel! This should be useful when the 3D module hits...


N2005
Thanks, skid.


Dubious Drewski2005
That is quite extensive too. Very nice.


Code Archives Forum