home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 16
/
CD_ASCQ_16_0994.iso
/
news
/
vr386
/
matrixm.asm
< prev
next >
Wrap
Assembly Source File
|
1994-01-09
|
17KB
|
906 lines
TITLE MATRIXM - MATRIX ALGRBRA IN ASSEMBLER
COMMENT $
/* Contact: dstampe@sunee.waterloo.edu */
// Routines to do matrix math for the integer math library
// All code by Dave Stampe, last updated 23/12/93
/*
This code is part of the VR-386 project, created by Dave Stampe.
VR-386 is a desendent of REND386, created by Dave Stampe and
Bernie Roehl. Almost all the code has been rewritten by Dave
Stampre for VR-386.
Copyright (c) 1994 by Dave Stampe:
May be freely used to write software for release into the public domain
or for educational use; all commercial endeavours MUST contact Dave Stampe
(dstampe@psych.toronto.edu) for permission to incorporate any part of
this software or source code into their products! Usually there is no
charge for under 50-100 items for low-cost or shareware products, and terms
are reasonable. Any royalties are used for development, so equipment is
often acceptable payment.
ATTRIBUTION: If you use any part of this source code or the libraries
in your projects, you must give attribution to VR-386 and Dave Stampe,
and any other authors in your documentation, source code, and at startup
of your program. Let's keep the freeware ball rolling!
DEVELOPMENT: VR-386 is a effort to develop the process started by
REND386, improving programmer access by rewriting the code and supplying
a standard API. If you write improvements, add new functions rather
than rewriting current functions. This will make it possible to
include you improved code in the next API release. YOU can help advance
VR-386. Comments on the API are welcome.
CONTACT: dstampe@psych.toronto.edu
*/
NOTES ON MATRIX FORMATS:
Matrices are 32 bit [4][3] arrays, row major format.
They are a reduced homogenous matrix, with a rotational
and translational part (translational part = position).
No scaling is allowed if you want to use the fast inverse
supplied here.
Matrix multiplies are generally quite expensive: the 36 32-bit
multiplies take 60 microseconds on a 486/33! So use them sparingly.
OFFSETS IN MATRIX: (homogenaous)
[ 0 4 8 | 36 ]
[ 12 16 20 | 40 ]
[ 24 28 32 | 44 ]
$
.MODEL large
.DATA
;include 3dstruct.inc
; # define XFSC 536870912 /* 2**29 for shifting xform coeffs to long */
.CODE INTMATH
MULT29 MACRO a,b ; multiply <3.29> -> eax
mov eax,DWORD PTR a
imul DWORD PTR b
shrd eax,edx,29
adc eax,0
ENDM
MMULT29 MACRO a,b,c ; multiply 3 of <3.29> -> eax
mov eax,DWORD PTR a
imul DWORD PTR b
shrd eax,edx,29
adc eax,0
imul DWORD PTR c
shrd eax,edx,29
adc eax,0
ENDM
DOTPROD MACRO a,b,c,x,y,z,p ; dot product plus p, accum in ecx:ebx
mov eax,a ; result in eax
imul DWORD PTR x
mov ecx,edx
mov ebx,eax
mov eax,b
imul DWORD PTR y
add ebx,eax
adc ecx,edx
mov eax,c
imul DWORD PTR z
add eax,ebx
adc edx,ecx
shrd eax,edx,29
adc eax,p
ENDM
CROSSTERM MACRO a,x,b,y ; left-handed cross product (a*x-b*y) term
mov eax,b ; accum in ebx:ecx, result in eax
imul DWORD PTR y
mov ecx,edx
mov ebx,eax
mov eax,a
imul DWORD PTR x
sub eax,ebx
sbb edx,ecx
shrd eax,edx,29
adc eax,0
ENDM
;/***************** MATRIX-VECTOR OPERATIONS **************/
;/* rotate/translate XYZ by matrix */
;
;void matrix_point(MATRIX m, long *xp, long *yp, long *zp)
m equ [bp+8] ; arguments
xp equ [bp+12]
yp equ [bp+16]
zp equ [bp+20]
x equ [bp-4] ; locals
y equ [bp-8]
z equ [bp-12]
PUBLIC _matrix_point
_matrix_point proc far
.386
push ebp
mov ebp,esp
sub esp,16
push edi
push ecx
push edx
les bx,DWORD PTR xp
mov eax,es:[bx]
mov x,eax
les bx,DWORD PTR yp
mov eax,es:[bx]
mov y,eax
les bx,DWORD PTR zp
mov eax,es:[bx]
mov z,eax
les di,DWORD PTR m
DOTPROD es:[di], es:[di+4], es:[di+8], x, y, z, es:[di+36]
push eax ; x result
DOTPROD es:[di+12], es:[di+16], es:[di+20], x, y, z, es:[di+40]
push eax ; y result
DOTPROD es:[di+24], es:[di+28], es:[di+32], x, y, z, es:[di+44]
les di,DWORD PTR zp
mov es:[di],eax ; store z result
les di,DWORD PTR yp
pop DWORD PTR es:[di] ; store y result
les di,DWORD PTR xp
pop DWORD PTR es:[di] ; store x result
pop edx
pop ecx
pop edi
mov esp,ebp
pop ebp
ret
_matrix_point endp
; /* rotate XYZ by matrix */
;
;void matrix_rotate(MATRIX m, long *xp, long *yp, long *zp)
m equ [bp+8] ; arguments
xp equ [bp+12]
yp equ [bp+16]
zp equ [bp+20]
x equ [bp-4] ; locals
y equ [bp-8]
z equ [bp-12]
PUBLIC _matrix_rotate
_matrix_rotate proc far
.386
push ebp
mov ebp,esp
sub esp,16
push edi
push ecx
push edx
les bx,DWORD PTR xp
mov eax,es:[bx]
mov x,eax
les bx,DWORD PTR yp
mov eax,es:[bx]
mov y,eax
les bx,DWORD PTR zp
mov eax,es:[bx]
mov z,eax
les di,DWORD PTR m
DOTPROD es:[di], es:[di+4], es:[di+8], x, y, z, 0
push eax ; x result
DOTPROD es:[di+12], es:[di+16], es:[di+20], x, y, z, 0
push eax ; y result
DOTPROD es:[di+24], es:[di+28], es:[di+32], x, y, z, 0
les di,DWORD PTR zp
mov es:[di],eax ; store z result
les di,DWORD PTR yp
pop DWORD PTR es:[di] ; store y result
les di,DWORD PTR xp
pop DWORD PTR es:[di] ; store x result
pop edx
pop ecx
pop edi
mov esp,ebp
pop ebp
ret
_matrix_rotate endp
;/******************** MISC. VECTOR MATH ****************/
;
; /* replaces column N of a matrix with cross of other 2 */
; /* used to speed computations, repair matrix scaling */
; /* pointers into matrix: same segment! */
;void cross_product(long *c1, long *c2, long *c3);
c1 equ [bp+8] ; arguments
c2 equ [bp+12]
c3 equ [bp+16]
x1 equ DWORD PTR es:[di] ; parts of columns
x2 equ DWORD PTR es:[si]
y1 equ DWORD PTR es:[di+12]
y2 equ DWORD PTR es:[si+12]
z1 equ DWORD PTR es:[di+24]
z2 equ DWORD PTR es:[si+24]
PUBLIC _cross_product
_cross_product proc far
.386
push ebp
mov ebp,esp
push edx
push ecx
push esi
push edi
les di,DWORD PTR c1
mov si,WORD PTR c2
CROSSTERM y1,z2,y2,z1
push eax
CROSSTERM z1,x2,x1,z2
push eax
CROSSTERM x1,y2,x2,y1
les di,DWORD PTR c3 ; store new column
mov z1,eax
pop y1
pop x1
pop edi
pop esi
pop ecx
pop edx
mov esp,ebp
pop ebp
ret
_cross_product endp
;/****************** MATRIX MANIPULATION ***************/
; /* 3x3 section of matrixs: A*B->C */
;void matrix_mult(MATRIX a, MATRIX b, MATRIX c)
a equ [bp+8] ; arguments
b equ [bp+12]
c equ [bp+16]
r1 equ DWORD PTR [bp-4] ; locals
r2 equ DWORD PTR [bp-8] ; temp result allows A*B->A
r3 equ DWORD PTR [bp-12]
r4 equ DWORD PTR [bp-16]
r5 equ DWORD PTR [bp-20]
r6 equ DWORD PTR [bp-24]
r7 equ DWORD PTR [bp-28]
r8 equ DWORD PTR [bp-32]
r9 equ DWORD PTR [bp-36]
PUBLIC _matrix_mult
_matrix_mult proc far
.386
push ebp
mov ebp,esp
sub esp,40
push ds
push esi
push edi
push ecx
push edx
les si,DWORD PTR a ; pointers to source matrices
lds di,DWORD PTR b
DOTPROD es:[si],es:[si+4],es:[si+8],ds:[di],ds:[di+12],ds:[di+24],0
mov r1,eax
DOTPROD es:[si],es:[si+4],es:[si+8],ds:[di+4],ds:[di+16],ds:[di+28],0
mov r2,eax
DOTPROD es:[si],es:[si+4],es:[si+8],ds:[di+8],ds:[di+20],ds:[di+32],0
mov r3,eax
DOTPROD es:[si+12],es:[si+16],es:[si+20],ds:[di],ds:[di+12],ds:[di+24],0
mov r4,eax
DOTPROD es:[si+12],es:[si+16],es:[si+20],ds:[di+4],ds:[di+16],ds:[di+28],0
mov r5,eax
DOTPROD es:[si+12],es:[si+16],es:[si+20],ds:[di+8],ds:[di+20],ds:[di+32],0
mov r6,eax
DOTPROD es:[si+24],es:[si+28],es:[si+32],ds:[di],ds:[di+12],ds:[di+24],0
mov r7,eax
DOTPROD es:[si+24],es:[si+28],es:[si+32],ds:[di+4],ds:[di+16],ds:[di+28],0
mov r8,eax
DOTPROD es:[si+24],es:[si+28],es:[si+32],ds:[di+8],ds:[di+20],ds:[di+32],0
mov r9,eax
les di,DWORD PTR c ; store matrix
mov eax,r1
mov es:[di],eax
mov eax,r2
mov es:[di+4],eax
mov eax,r3
mov es:[di+8],eax
mov eax,r4
mov es:[di+12],eax
mov eax,r5
mov es:[di+16],eax
mov eax,r6
mov es:[di+20],eax
mov eax,r7
mov es:[di+24],eax
mov eax,r8
mov es:[di+28],eax
mov eax,r9
mov es:[di+32],eax
pop edx
pop ecx
pop edi
pop esi
pop ds
mov esp,ebp
pop ebp
ret
_matrix_mult endp
; /* full homogenous matrix multiply */
;
;void matrix_product(MATRIX a, MATRIX b, MATRIX c)
a equ [bp+8] ; arguments
b equ [bp+12]
c equ [bp+16]
r1 equ DWORD PTR [bp-4] ; locals
r2 equ DWORD PTR [bp-8] ; temp result allows A*B->A
r3 equ DWORD PTR [bp-12]
r4 equ DWORD PTR [bp-16]
r5 equ DWORD PTR [bp-20]
r6 equ DWORD PTR [bp-24]
r7 equ DWORD PTR [bp-28]
r8 equ DWORD PTR [bp-32]
r9 equ DWORD PTR [bp-36]
t1 equ DWORD PTR [bp-40] ; translation part of result
t2 equ DWORD PTR [bp-44]
t3 equ DWORD PTR [bp-48]
PUBLIC _matrix_product
_matrix_product proc far
.386
push ebp
mov ebp,esp
sub esp,52
push ds
push esi
push edi
push ecx
push edx
les si,DWORD PTR a ; pointers to source matrices
lds di,DWORD PTR b
DOTPROD es:[si],es:[si+4],es:[si+8],ds:[di],ds:[di+12],ds:[di+24],0
mov r1,eax
DOTPROD es:[si],es:[si+4],es:[si+8],ds:[di+4],ds:[di+16],ds:[di+28],0
mov r2,eax
DOTPROD es:[si],es:[si+4],es:[si+8],ds:[di+8],ds:[di+20],ds:[di+32],0
mov r3,eax
DOTPROD es:[si+12],es:[si+16],es:[si+20],ds:[di],ds:[di+12],ds:[di+24],0
mov r4,eax
DOTPROD es:[si+12],es:[si+16],es:[si+20],ds:[di+4],ds:[di+16],ds:[di+28],0
mov r5,eax
DOTPROD es:[si+12],es:[si+16],es:[si+20],ds:[di+8],ds:[di+20],ds:[di+32],0
mov r6,eax
DOTPROD es:[si+24],es:[si+28],es:[si+32],ds:[di],ds:[di+12],ds:[di+24],0
mov r7,eax
DOTPROD es:[si+24],es:[si+28],es:[si+32],ds:[di+4],ds:[di+16],ds:[di+28],0
mov r8,eax
DOTPROD es:[si+24],es:[si+28],es:[si+32],ds:[di+8],ds:[di+20],ds:[di+32],0
mov r9,eax
; translational part
DOTPROD es:[si],es:[si+4],es:[si+8],ds:[di+36],ds:[di+40],ds:[di+44],es:[si+36]
mov t1,eax
DOTPROD es:[si+12],es:[si+16],es:[si+20],ds:[di+36],ds:[di+40],ds:[di+44],es:[si+40]
mov t2,eax
DOTPROD es:[si+24],es:[si+28],es:[si+32],ds:[di+36],ds:[di+40],ds:[di+44],es:[si+44]
mov t3,eax
les di,DWORD PTR c ; store matrix
mov eax,r1
mov es:[di],eax
mov eax,r2
mov es:[di+4],eax
mov eax,r3
mov es:[di+8],eax
mov eax,r4
mov es:[di+12],eax
mov eax,r5
mov es:[di+16],eax
mov eax,r6
mov es:[di+20],eax
mov eax,r7
mov es:[di+24],eax
mov eax,r8
mov es:[di+28],eax
mov eax,r9
mov es:[di+32],eax
mov eax,t1
mov es:[di+36],eax
mov eax,t2
mov es:[di+40],eax
mov eax,t3
mov es:[di+44],eax
pop edx
pop ecx
pop edi
pop esi
pop ds
mov esp,ebp
pop ebp
ret
_matrix_product endp
;void matrix_transpose(MATRIX a, MATRIX b)
; /* generate inverse of rotate matrix (transpose) */
; /* ONLY WORKS FOR ORTHOGONAL UNSCALED MATRICES */
; /* will do self_transpose as well as copy */
a equ [bp+8] ; arguments
b equ [bp+12]
PUBLIC _matrix_transpose
_matrix_transpose proc far
.386
push ebp
mov ebp,esp
push ds
push esi
push edi
push edx
les si,DWORD PTR a ; pointers to source matrices
lds di,DWORD PTR b
mov eax,es:[si] ; copy diagonals
mov ds:[di],eax
mov eax,es:[si+16]
mov ds:[di+16],eax
mov eax,es:[si+32]
mov ds:[di+32],eax
mov eax,es:[si+4] ; swap others
mov edx,es:[si+12]
mov ds:[di+4],edx
mov ds:[di+12],eax
mov eax,es:[si+8]
mov edx,es:[si+24]
mov ds:[di+8],edx
mov ds:[di+24],eax
mov eax,es:[si+28]
mov edx,es:[si+20]
mov ds:[di+28],edx
mov ds:[di+20],eax
pop edx
pop edi
pop esi
pop ds
mov esp,ebp
pop ebp
ret
_matrix_transpose endp
;void inverse_matrix(MATRIX a, MATRIX b)
; /* old: Ax+b = c */
; /* b' = (1/A)(-b) */
; /* (1/A) = t(A) */
; /* new: (1/A)c+b' = x */
; basically, B = tr(A) | -At * tr(A)
a equ [bp+8] ; arguments
b equ [bp+12]
PUBLIC _inverse_matrix
_inverse_matrix proc far
.386
push ebp
mov ebp,esp
push ds
push ecx
push esi
push edi
push edx
les si,DWORD PTR a ; pointers to source matrices
lds di,DWORD PTR b
mov eax,es:[si] ; copy diagonals
mov ds:[di],eax
mov eax,es:[si+16]
mov ds:[di+16],eax
mov eax,es:[si+32]
mov ds:[di+32],eax
mov eax,es:[si+4] ; swap others
mov edx,es:[si+12]
mov ds:[di+4],edx
mov ds:[di+12],eax
mov eax,es:[si+8]
mov edx,es:[si+24]
mov ds:[di+8],edx
mov ds:[di+24],eax
mov eax,es:[si+28]
mov edx,es:[si+20]
mov ds:[di+28],edx
mov ds:[di+20],eax
; now, use B to convert translational part
DOTPROD ds:[di],ds:[di+4],ds:[di+8],es:[si+36],es:[si+40],es:[si+44],0
neg eax
mov ds:[di+36],eax
DOTPROD ds:[di+12],ds:[di+16],ds:[di+20],es:[si+36],es:[si+40],es:[si+44],0
neg eax
mov ds:[di+40],eax
DOTPROD ds:[di+24],ds:[di+28],ds:[di+32],es:[si+36],es:[si+40],es:[si+44],0
neg eax
mov ds:[di+44],eax
pop edx
pop edi
pop esi
pop ecx
pop ds
mov esp,ebp
pop ebp
ret
_inverse_matrix endp
;/*************** ANGLE/POSITION TO HOMOGENOUS MATRIX ************/
extrn _isine : PROC
extrn _icosine : PROC
MATRIXDECL MACRO rname ; SETS UP MATRIX COMPUTE
m equ [bp+8] ; arguments
rx equ [bp+12]
ry equ [bp+16]
rz equ [bp+20]
tx equ [bp+24]
ty equ [bp+28]
tz equ [bp+32]
sinx equ DWORD PTR [bp-4] ; locals
siny equ DWORD PTR [bp-8] ; temp result allows A*B->A
sinz equ DWORD PTR [bp-12]
cosx equ DWORD PTR [bp-16]
cosy equ DWORD PTR [bp-20]
cosz equ DWORD PTR [bp-24]
PUBLIC rname
rname proc far
.386
push ebp
mov ebp,esp
sub esp,30
push DWORD PTR rx ; trig evaluate
call _isine
add esp,4
mov sinx,eax
push DWORD PTR ry
call _isine
add esp,4
mov siny,eax
push DWORD PTR rz
call _isine
add esp,4
mov sinz,eax
push DWORD PTR rx
call _icosine
add esp,4
mov cosx,eax
push DWORD PTR ry
call _icosine
add esp,4
mov cosy,eax
push DWORD PTR rz
call _icosine
add esp,4
mov cosz,eax
push esi
push edi
les di,DWORD PTR m
mov eax,tx
mov es:[di+36],eax
mov eax,ty
mov es:[di+40],eax
mov eax,tz
mov es:[di+44],eax
ENDM
MATRIXEND MACRO rname
pop edi
pop esi
mov esp,ebp
pop ebp
ret
rname endp
ENDM
;void matrix_RXYZ(MATRIX m, long rx, long ry, long rz,
; long tx, long ty, long tz)
; /* a fast standard matrix compute */
MATRIXDECL _matrix_RXYZ
MULT29 cosz,cosy
mov es:[di],eax
MULT29 cosy,sinz
neg eax
mov es:[di+4],eax
mov eax,siny
mov es:[di+8],eax
MULT29 cosx,sinz
mov esi,eax
MMULT29 cosz,sinx,siny
add eax,esi
mov es:[di+12],eax
MMULT29 sinz,sinx,siny
mov esi,eax
MULT29 cosz,cosx
sub eax,esi
mov es:[di+16],eax
MULT29 cosy,sinx
neg eax
mov es:[di+20],eax
MMULT29 siny,cosz,cosx
mov esi,eax
MULT29 sinz,sinx
sub eax,esi
mov es:[di+24],eax
MULT29 cosz,sinx
mov esi,eax
MMULT29 cosx,sinz,siny
add eax,esi
mov es:[di+28],eax
MULT29 cosx,cosy
mov es:[di+32],eax
MATRIXEND _matrix_RXYZ
;void matrix_RYXZ(MATRIX m, long rx, long ry, long rz, Y
; long tx, long ty, long tz)
; /* a fast standard matrix compute */
MATRIXDECL _matrix_RYXZ
MULT29 cosz,cosy
mov esi,eax
MMULT29 sinz,sinx,siny
add eax,esi
mov es:[di],eax
MULT29 cosy,sinz
mov esi,eax
MMULT29 cosz,sinx,siny
sub eax,esi
mov es:[di+4],eax
MULT29 cosx,siny
mov es:[di+8],eax
MULT29 cosx,sinz
mov es:[di+12],eax
MULT29 cosz,cosx
mov es:[di+16],eax
mov eax,sinx
neg eax
mov es:[di+20],eax
MULT29 cosz,siny
mov esi,eax
MMULT29 cosy,sinz,sinx
sub eax,esi
mov es:[di+24],eax
MULT29 sinz,siny
mov esi,eax
MMULT29 cosz,cosy,sinx
add eax,esi
mov es:[di+28],eax
MULT29 cosx,cosy
mov es:[di+32],eax
MATRIXEND _matrix_RYXZ
;void matrix_RXZY(MATRIX m, long rx, long ry, long rz, Y
; long tx, long ty, long tz)
; /* a fast standard matrix compute */
MATRIXDECL _matrix_RXZY
MULT29 cosz,cosy
mov es:[di],eax
mov eax,sinz
neg eax
mov es:[di+4],eax
MULT29 cosz,siny
mov es:[di+8],eax
MULT29 sinx,siny
mov esi,eax
MMULT29 cosx,cosy,sinz
add eax,esi
mov es:[di+12],eax
MULT29 cosz,cosx
mov es:[di+16],eax
MULT29 cosy,sinx
mov esi,eax
MMULT29 cosx,sinz,siny
sub eax,esi
mov es:[di+20],eax
MULT29 cosx,siny
mov esi,eax
MMULT29 cosy,sinz,sinx
sub eax,esi
mov es:[di+24],eax
MULT29 cosz,sinx
mov es:[di+28],eax
MULT29 cosx,cosy
mov esi,eax
MMULT29 sinz,sinx,siny
add eax,esi
mov es:[di+32],eax
MATRIXEND _matrix_RXZY
end