# Thread: 3D Vector Math include file.

1. ## 3D Vector Math include file.

i tested the ext floating point type but ist's too slow for my needs.

so here is what i use as include file.

currently i use 3D vectors as array

dim a(3) as single
dim b(3) as single
dim c(3) as single
dim d as single
a(1) = 1,2,3
b(1) = 2,3,4

VecCrossAB(c,a,b) ' c = a x b
VecSub(a,b) ' a -= b
VecAddAB(c,a,b) ' c = a + b
VecSubAB(c,a,b) ' c = a - b
VecMulS(a,123.45) ' a*=scalar
VecMulABS(a,b,123.45) ' a=b*scalar
d=Length(a) ' sqr(ax*ax + ay*ay + az*az)
d=VecDistanceAB(a,b) ' d = srq((az-bz)*(az-bz) + (ay-by)*(ay-by) + (ax-bx)*(ax-bx))
d=dot(a) ' d=ax*ax + ay*ay + az*az
d=dotAB(a,B) ' d=ax*bx + ay*by + az*bz
...

happy coding

Joshy
[code=thinbasic]' litle bit vector math
uses "OXYGEN"

Begin Const
%BUFFER_SET = 1
%BUFFER_COPY
%BUFFER_SUB
%BUFFER_SUBAB
%BUFFER_MULS
%BUFFER_MULABS
%BUFFER_DOT
%BUFFER_DOTAB
%BUFFER_DISTANCEAB2 ' squared
%BUFFER_DISTANCEAB
%BUFFER_LENGTH
%BUFFER_NORMALIZE2 ' v*=1/sqr(squared)
%BUFFER_CROSSAB
%BUFFER_SQRT
End Const

Dim src As String

'######################
' VecSet(R(),X,Y,Z)
'######################
src = "
mov edi,[esp+ 4] ; r()
mov eax,[esp+ 8]
mov [edi],eax ; r(1)=x
mov eax,[esp+12]
mov [edi+4],eax ; r(2)=y
mov eax,[esp+16]
mov [edi+8],eax ; r(3)=z

ret 16
"
O2_BUF %BUFFER_SET : O2_ASMO src
If Len(O2_ERROR) Then
MsgBox 0,O2_ERROR()+O2_VIEW (src)
Stop
End If

'######################
' VecCopy(R(),A())
' r()=a()
'######################
src = "
mov edi,[esp+ 4] ; r()
mov esi,[esp+ 8] ; a()

mov eax,[esi]
mov [edi],eax ; r(1)=a(1)
mov eax,[esi+4]
mov [edi+4],eax ; r(2)=a(2)
mov eax,[esi+8]
mov [edi+8],eax ; r(3)=a(3)

ret 8
"
O2_BUF %BUFFER_COPY : O2_ASMO src
If Len(O2_ERROR) Then
MsgBox 0,O2_ERROR()+O2_VIEW (src)
Stop
End If

'######################
' a()+=b()
'######################
src = "
mov edi,[esp+ 4] ; a()
mov esi,[esp+ 8] ; b()

fld dword [edi ]
fstp dword [edi ] ; ax+=bx

fld dword [edi+4]
fstp dword [edi+4] ; ay+=by

fld dword [edi+8]
fstp dword [edi+8] ; az+=bz

ret 8
"
If Len(O2_ERROR) Then
MsgBox 0,O2_ERROR()+O2_VIEW (src)
Stop
End If

'######################
' VecSub(A(),B())
' a()-=b()
'######################
src = "
mov edi,[esp+ 4] ; a()
mov esi,[esp+ 8] ; b()

fld dword [edi ]
fsub dword [esi ]
fstp dword [edi ] ; ax-=bx

fld dword [edi+4]
fsub dword [esi+4]
fstp dword [edi+4] ; ay-=by

fld dword [edi+8]
fsub dword [esi+8]
fstp dword [edi+8] ; az-=bz

ret 8
"
O2_BUF %BUFFER_SUB: O2_ASMO src
If Len(O2_ERROR) Then
MsgBox 0,O2_ERROR()+O2_VIEW (src)
Stop
End If

'#######################
' r()=a()+b()
'#######################
src = "
mov eax,[esp+ 4] ; r()
mov esi,[esp+ 8] ; a()
mov edi,[esp+12] ; b()

fld dword [esi ]
fstp dword [eax ] ; rx = (ax+bx)

fld dword [esi+4]
fstp dword [eax+4] ; ry = (ay+by)

fld dword [esi+8]
fstp dword [eax+8] ; rz = (az+bz)

ret 12
"
If Len(O2_ERROR) Then
MsgBox 0,O2_ERROR()+O2_VIEW (src)
Stop
End If

'#######################
' VecSubAB(R(),A(),B())
' r()=a()-b()
'#######################
src = "
mov eax,[esp+ 4] ; r()
mov esi,[esp+ 8] ; a()
mov edi,[esp+12] ; b()

fld dword [esi ]
fsub dword [edi ]
fstp dword [eax ] ; rx = (ax-bx)

fld dword [esi+4]
fsub dword [edi+4]
fstp dword [eax+4] ; ry = (ay-by)

fld dword [esi+8]
fsub dword [edi+8]
fstp dword [eax+8] ; rz = (az-bz)

ret 12
"
O2_BUF %BUFFER_SUBAB: O2_ASMO src
If Len(O2_ERROR) Then
MsgBox 0,O2_ERROR()+O2_VIEW (src)
Stop
End If

'################
' VecMulS(A(),S)
' a()*=s
'################
src = ";
mov esi , [esp+4]
fld dword [esp+8] ; s

fmul dword [esi ] ;s*x,s
fstp dword [esi ] ; s

fmul dword [esi+4] ;s*y,s
fstp dword [esi+4] ;s

fmulp dword [esi+8] ;s*z
fstp dword [esi+8]

ret 8
"
O2_BUF %BUFFER_MULS : O2_ASMO src
If Len(O2_ERROR) Then
MsgBox 0,O2_ERROR()+O2_VIEW (src)
Stop
End If

'######################
' VecMulABS(R(),A(),S)
' r()=b()*s
'######################
src = "
mov edi , [esp+ 4] ; r()
mov esi , [esp+ 8] ; b()
fld dword [esp+12] ; s

fld dword [esi ] ; bx,s
fmul ; ax*s,s
fstp dword [edi ] ; s

fld dword [esi+4] ; by,s
fmul ; ay*s,s
fstp dword [edi+4] ; s

fld dword [esi+8] ; bz,s
fmulp ; az*s
fstp dword [edi+8]

ret 12
"
O2_BUF %BUFFER_MULABS : O2_ASMO src
If Len(O2_ERROR) Then
MsgBox 0,O2_ERROR()+O2_VIEW (src)
Stop
End If

'#######################
' s = VecDot(a())
' s = ax*ax+ay*ay+az*az
'#######################
src = ";
mov esi , [esp+4]
fld dword [esi ] ; (x)
fld st(0) ; (x),(x)
fmulp ; (x*x)
fld dword [esi+4] ; (y),(x*x)
fld st(0) ; (y),(y),(x*x)
fmulp ; (y*y),(x*x)
fld dword [esi+8] ; (z),(y*y),(x*x)
fld st(0) ; (z),(z),(y*y),(x*x)
fmulp ; (z*z),(y*y),(x*x)
faddp ; (z*z + y*y + x*x)
ret 4
"
O2_BUF %BUFFER_DOT : O2_ASMO src
If Len(O2_ERROR) Then
MsgBox 0,O2_ERROR()+O2_VIEW (src)
Stop
End If

'#######################
' s = VecDotAB(a(),b())
' s = ax*bx+ay*by+az*bz
'#######################
src = "
mov esi, [esp+4]
mov edi, [esp+8]
fld dword [edi ] ; (bx)
fmul dword [esi ] ; (ax*bx)
fld dword [edi+4] ; (by),(ax*bx)
fmul dword [esi+4] ; (ay*by),(ax*bx)
fld dword [edi+8] ; (bz),(ay*by),(ax*bx)
fmul dword [esi+8] ; (az*bz),(ay*by),(ax*bx)
faddp ; (az*bz + ay*by + ax*bx)
ret 8
"
O2_BUF %BUFFER_DOTAB : O2_ASMO src
If Len(O2_ERROR) Then
MsgBox 0,O2_ERROR()+O2_VIEW (src)
Stop
End If

'###########################
' s = VecDistanceAB2(a(),b())
' s = dot(a()-b())
'###########################
src = "
mov esi,[esp+4]
mov edi,[esp+8]

fld dword [esi ] ; (ax)
fsub dword [edi ] ; (ax-bx)
fld st(0) ; (ax-bx),(ax-bx)
fmulp ; (ax-bx)*(ax-bx)

fld dword [esi+4] ; (ay),(ax-bx)*(ax-bx)
fsub dword [edi+4] ; (ay-by),(ax-bx)*(ax-bx)
fld st(0) ; (ay-by),(ay-by),(ax-bx)*(ax-bx)
fmulp ; (ay-by)*(ay-by),(ax-bx)*(ax-bx)

fld dword [esi+8] ; (az),(ay-by)*(ay-by),(ax-bx)*(ax-bx)
fsub dword [edi+8] ; (az-bz),(ay-by)*(ay-by),(ax-bx)*(ax-bx)
fld st(0) ; (az-bz),(az-bz),(ay-by)*(ay-by),(ax-bx)*(ax-bx)
fmulp ; (az-bz)*(az-bz),(ay-by)*(ay-by),(ax-bx)*(ax-bx)

ret 8
"
O2_BUF %BUFFER_DISTANCEAB2 : O2_ASMO src
If Len(O2_ERROR) Then
MsgBox 0,O2_ERROR()+O2_VIEW (src)
Stop
End If

'############################
' s = VecDistanceAB(a(),b())
' s = Sqr(Distance2(a()-b())
'############################
src = "
mov esi,[esp+4]
mov edi,[esp+8]

fld dword [esi ] ; (ax)
fsub dword [edi ] ; (ax-bx)
fld st(0) ; (ax-bx),(ax-bx)
fmulp ; (ax-bx)*(ax-bx)

fld dword [esi+4] ; (ay),(ax-bx)*(ax-bx)
fsub dword [edi+4] ; (ay-by),(ax-bx)*(ax-bx)
fld st(0) ; (ay-by),(ay-by),(ax-bx)*(ax-bx)
fmulp ; (ay-by)*(ay-by),(ax-bx)*(ax-bx)

fld dword [esi+8] ; (az),(ay-by)*(ay-by),(ax-bx)*(ax-bx)
fsub dword [edi+8] ; (az-bz),(ay-by)*(ay-by),(ax-bx)*(ax-bx)
fld st(0) ; (az-bz),(az-bz),(ay-by)*(ay-by),(ax-bx)*(ax-bx)
fmulp ; (az-bz)*(az-bz),(ay-by)*(ay-by),(ax-bx)*(ax-bx)

fsqrt ; srq(distance2(a(),b())
ret 8
"
O2_BUF %BUFFER_DISTANCEAB : O2_ASMO src
If Len(O2_ERROR) Then
MsgBox 0,O2_ERROR()+O2_VIEW (src)
Stop
End If

'############################
' s = VecLength(a())
' s = sqr(ax*ax+ay*ay+az*az)
'############################
src = ";
mov esi , [esp+4]
fld dword [esi ] ; (x)
fld st(0) ; (x),(x)
fmulp ; (x*x)
fld dword [esi+4] ; (y),(x*x)
fld st(0) ; (y),(y),(x*x)
fmulp ; (y*y),(x*x)
fld dword [esi+8] ; (z),(y*y),(x*x)
fld st(0) ; (z),(z),(y*y),(x*x)
fmulp ; (z*z),(y*y),(x*x)
faddp ; (z*z + y*y + x*x)
fsqrt
ret 4
"
O2_BUF %BUFFER_LENGTH : O2_ASMO src
If Len(O2_ERROR) Then
MsgBox 0,O2_ERROR()+O2_VIEW (src)
Stop
End If

'############################
' s = VecNormlize2(a(),squared)
' a()*1/sqr(squared)
'############################
src = "
mov esi,[esp+4] ; a()
fld dword [esp+8] ; x*x+y*y+z*z
fsqrt ; sqr(x*x+y*y+z*z)
fld1 ; 1.0,sqr(x*x+y*y+z*z)
fdiv ; invsqr
fld dword [esi] ; x,invsqr
fmul ; x*invsqr,invsqr
fstp dword [esi] ; invsqr

fld dword [esi+4] ; y,invsqr
fmul ; y*invsqr,invsqr
fstp dword [esi+4] ; invsqr

fld dword [esi+8] ; z,invsqr
fmulp ; z*invsqr
fstp dword [esi+8]

ret 8
"
O2_BUF %BUFFER_NORMALIZE2 : O2_ASMO src
If Len(O2_ERROR) Then
MsgBox 0,O2_ERROR()+O2_VIEW (src)
Stop
End If

'############################
' s = SQRT(a)
'############################
src = "
fld dword [esp+4]
fsqrt
ret 4
"
O2_BUF %BUFFER_SQRT : O2_ASMO src
If Len(O2_ERROR) Then
MsgBox 0,O2_ERROR()+O2_VIEW (src)
Stop
End If

'#####################################
' VecCrossAB(r(),a(),b())
' r(1)=(a[Y] * b[Z]) - (a[Z] * b[Y])
' r(2)=(a[Z] * b[X]) - (a[X] * b[Z])
' r(3)=(a[X] * b[Y]) - (a[Y] * b[X])
'#####################################
src = "
mov edi , [esp+ 4] ; r()
mov eax , [esp+ 8] ; a()
mov esi , [esp+12] ; b()

fld dword [esi+4] ; by
fld dword [eax+8] ; az ,by
fmulp ; az*by
fld dword [esi+8] ; bz ,az*by
fld dword [eax+4] ; ay ,bz ,az*by
fmulp ; ay*bz,az*by
fsub ; ay*bz-az*by
fstp dword [edi ] ; rx=ay*bz-az*by

fld dword [esi+8] ; bz
fld dword [eax ] ; ax,bz
fmulp ; ax*bz
fld dword [esi ] ; bx,ax*bz
fld dword [eax+8] ; az,bx,ax*bz
fmulp ; az*bx,ax*bz
fsub ; az*bx-ax*bz
fstp dword [edi+4] ; ry=az*bx-ax*bz

fld dword [esi ] ; bx
fld dword [eax+4] ; ay,bx
fmulp ; ay*bx
fld dword [esi+4] ; by,ay*bx
fld dword [eax ] ; ax,by,ay*bx
fmulp ; ax*by,ay*bx
fsub ; ax*by-ay*bx
fstp dword [edi+8] ; rz=ax*by-ay*bx
ffree st(2)
ffree st(1)
ffree st(0)
ret 12
"
O2_BUF %BUFFER_CROSSAB : O2_ASMO src
If Len(O2_ERROR) Then
MsgBox 0,O2_ERROR()+O2_VIEW (src)
Stop
End If

Declare Sub VecSet (ByRef a() As Single, ByVal x As Single,ByVal y As Single,ByVal z As Single) At O2_BUF %BUFFER_SET
Declare Sub VecCopy (ByRef a() As Single, ByRef b() As Single) At O2_BUF %BUFFER_COPY
Declare Sub VecAdd (ByRef a() As Single, ByRef b() As Single) At O2_BUF %BUFFER_ADD
Declare Sub VecSub (ByRef a() As Single, ByRef b() As Single) At O2_BUF %BUFFER_SUB
Declare Sub VecAddAB (ByRef r() As Single, ByRef a() As Single, ByRef b() As Single) At O2_BUF %BUFFER_ADDAB
Declare Sub VecSubAB (ByRef r() As Single, ByRef a() As Single, ByRef b() As Single) At O2_BUF %BUFFER_SUBAB
Declare Function VecMulS (ByRef a() As Single, ByVal s As Single) As Single At O2_BUF %BUFFER_MULS
Declare Function VecMulAS (ByRef r() As Single, ByRef a() As Single, ByVal s As Single) As Single At O2_BUF %BUFFER_MULABS
Declare Function VecDot (ByRef a() As Single) As Single At O2_BUF %BUFFER_DOT
Declare Function VecDotAB (ByRef a() As Single,ByRef b() As Single) As Single At O2_BUF %BUFFER_DOTAB
Declare Function VecDistanceAB2(ByRef a() As Single,ByRef b() As Single) As Single At O2_BUF %BUFFER_DISTANCEAB2
Declare Function VecDistanceAB (ByRef a() As Single,ByRef b() As Single) As Single At O2_BUF %BUFFER_DISTANCEAB
Declare Function VecLength (ByRef a() As Single) As Single At O2_BUF %BUFFER_LENGTH
Declare Sub VecNormalize2 (ByRef a() As Single,ByVal Lenght2 As Single) As Single At O2_BUF %BUFFER_NORMALIZE2
Declare Sub VecCrossAB (ByRef r() As Single, ByRef a() As Single, ByRef b() As Single) At O2_BUF %BUFFER_CROSSAB
Declare Function Sqrt (ByVal v As Single) As Single At O2_BUF %BUFFER_SQRT

Sub VecNormalize(ByRef a() As Single)
Local s As Single
s=VecDot(a)
If s=0 Then Return
VecNormalize2(a,s)
End Sub

Function VecCos(ByRef a() As Single, ByRef b() As Single) As Single
Dim l1,l2 As Single
l1 = VecDot(a) ' x*0=0
If l1=0 Then Return 0
l2 = VecDot(b) ' y*0=0
If l2=0 Then Return 0
l2 = SQRT(l1)*SQRT(l2)
l1 = VecDot(a,b)
Return l1/l2 ' acos(l1/l2)
End Function
[/code]

2. ## Re: 3D Vector Math include file.

Very very nice usage of Oxygen.

Charles will be happy

3. ## Re: 3D Vector Math include file.

Thanks Joshy!

Looking at your code I have just realised that it would be useful to be able to generate DLLs with exportable assembler functions (as well as BASIC). So I am going to add this facility to Oxygen now.

proposed syntax for an exported label:

MyAsmFunction: alias "MyAsmFunction" export

Charles

4. ## Re: 3D Vector Math include file.

Looks like the function call from interpreter to inline assembler functions are very slow.
I wrote a short test raytracer program where you can switch between interpreter
vector math and the inline assembler math.

But both results was near 46 seconds for one ray per pixel and a scene with 3 spheres.

Normaly the inline assembler math should be 10-100 times faster as the interpreter math.

Joshy

(i hat closed source codes )

5. ## Re: 3D Vector Math include file.

Hi Joshy,

Ray tracing sounds hard work for an interpreter!

If you would like to post your test ray tracer here, I will try to accelerate it with Oxygen Basic and see whether we can get it to run at an acceptable speed.

Charles

6. ## Re: 3D Vector Math include file.

One observation on your Assembler functions:

The esi and edi registers normally need to be preserved. ThinBasic does this already but in a general DLL this would be a necessity for STDCALL or CDECL calls. For these vector functions I would use the ecx and edx registers instead.

Charles

#### Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
•