home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC Underground
/
UNDERGROUND.ISO
/
graphic
/
3dasm.asm
< prev
next >
Wrap
Assembly Source File
|
1995-07-28
|
16KB
|
512 lines
.286
w equ word ptr
b equ byte ptr
surfclen equ 200 ;maximum length of surface defined
Pointlen equ 4*100 ;length of point array
num_ar equ 30 ;maximum number of areas
num_cor equ 10 ;maximum number of corners
data segment ;external variables from Pascal segment
extrn vz:word ;total depth
extrn rotx:Word ;angle of rotation
extrn roty:Word
extrn rotz:word
extrn worldconst:dataptr ;array with points
extrn surfcconst:dataptr ;array with surface definitions
extrn lightsrc:word ;flag for light source shading
extrn sf_sort:word ;flag for surface sorting
extrn sf_shift:word ;flag for surface shift suppression
extrn Texture:Byte ;flag for textures
extrn Fill:Byte ;flag for fill / wireframe model
crotx dw 0 ;x, y and z angle as offset to
croty dw 0 ;specific sine value
crotz dw 0
rotx_x dw 0 ;x,y,z to x-rot
rotx_y dw 0
rotx_z dw 0
roty_x dw 0 ;to y-rot
roty_y dw 0
roty_z dw 0
rotz_x dw 0 ;to z-rot, final
rotz_y dw 0
rotz_z dw 0
startpoly dw 0 ;start of definition of current area
Point dw Pointlen dup (0);receives calculated coordinates
Pointptr dw 0 ;pointer in Point-Array
Point3d dw Pointlen dup (0) ;receives completed 3D-coordinates (texture)
mean dw num_ar*2 dup (0) ;list of mean z-values
meanptr dw 0 ;pointer in Mean-Array
n dw 0,0,0,0,0,0 ;normal vector 32 Bit
n_amnt dw 0 ;amount of normal vector
extrn sine:dataptr
data ends
extrn drawpol:near ;draws area as wireframe model
extrn fillpol:near ;fills area
extrn root:near ;calculates root of ax
getdelta macro ;calculates the two surface vectors
mov ax,poly3d[0] ;x: original corner
mov delta2[0],ax ;store temporarily in delta2
sub ax,poly3d[8] ;obtain difference to first point
mov delta1[0],ax ;and delta1 finished
mov ax,poly3d[2] ;y: original corner
mov delta2[2],ax ;store temporarily in delta2
sub ax,poly3d[10d] ;obtain difference to first point
mov delta1[2],ax ;and delta1 finished
mov ax,poly3d[4] ;z: original corner
mov delta2[4],ax ;store temporarily in delta2
sub ax,poly3d[12d] ;obtain difference to first point
mov delta1[4],ax ;and delta1 finished
mov bp,polyn ;select last point
dec bp
shl bp,3 ;8 bytes at a time
mov ax,poly3d[bp] ;get x
sub delta2[0],ax ;obtain difference
mov ax,poly3d[bp+2] ;get y
sub delta2[2],ax ;obtain difference
mov ax,poly3d[bp+4] ;get z
sub delta2[4],ax ;obtain difference
endm
setcoord macro source,offst ;sets calculated screencoord
.386
mov ax,source ;project coordinate
cwd
shld dx,ax,7
shl ax,7
idiv cx
add ax,offst ;middle of screen is 0/0/0
mov bx,Pointptr ;note in Point-Array
mov Point[bx],ax
add Pointptr,2 ;add array pointer
endm
z2cx macro tabofs ;moves z-coordinate to cx
mov cx,tabofs + 4
add cx,vz ;add z-translation
mov bx,meanptr ;note in Mean-Array
add mean[bx],cx
endm
xrot macro zcoord,qcoord ;rotates qcoord by x, stores in zcoord
.386
mov bp,crotx ;get angle
mov bx,[qcoord]
shl bx,3 ;x8, to align to point entries
mov Pointptr,bx
sub bx,[qcoord] ;insg. x6, to align to world entries
sub bx,[qcoord]
add bx,offset worldconst ;set to world
mov ax,[bx] ;get x
mov zcoord,ax ;and set unchanged
mov ax,[bx+2] ;get y
imul w ds:[bp+60d] ;*cos rotx
shrd ax,dx,14d
mov cx,ax ;store in cx
mov ax,[bx+4] ;get z
imul w ds:[bp] ;*-sin rotx
shrd ax,dx,14d
sub cx,ax
mov zcoord+2,cx ;y value finished and set
mov ax,[bx+2] ;get y
imul w ds:[bp] ;*sin rotx
shrd ax,dx,14d
mov cx,ax ;store in cx
mov ax,[bx+4] ;get z
imul w ds:[bp+60d] ;*cos rotx
shrd ax,dx,14d
add cx,ax
mov zcoord+4,cx
endm
yrot macro zcoord,qcoord ;rotates qcoord by y, stores in zcoord
mov bp,croty ;get angle
mov ax,qcoord+2 ;get y
mov zcoord+2,ax ;and set unchanged
mov ax,qcoord ;get x
imul w ds:[bp+60d] ;*cos roty
shrd ax,dx,14d
mov cx,ax ;store in cx
mov ax,qcoord+4 ;get z
imul w ds:[bp] ;*sin roty
shrd ax,dx,14d
add cx,ax
mov zcoord,cx ;x value finished and set
mov ax,qcoord ;get x
imul w ds:[bp] ;*-sin roty
shrd ax,dx,14d
mov cx,ax ;store in cx
mov ax,qcoord+4 ;get z
imul w ds:[bp+60d] ;*cos roty
shrd ax,dx,14d
sub ax,cx
mov zcoord+4,ax
endm
zrot macro zcoord,qcoord ;rotates qcoord by z, saves in zcoord
mov bx,Pointptr ;prepare entry in 3D-Point-Array
mov bp,crotz ;get angle
mov ax,qcoord+4 ;get z
mov zcoord+4,ax ;and set unchanged
mov Point3d[bx+4],ax ;also note in 3D-Array
mov ax,qcoord ;get x
imul w ds:[bp+60d] ;*cos rotz
shrd ax,dx,14d
mov cx,ax ;store in cx
mov ax,qcoord+2 ;get y
imul w ds:[bp] ;*-sin rotz
shrd ax,dx,14d
sub cx,ax
mov zcoord,cx ;x value finished and set
mov Point3d[bx],cx
mov ax,qcoord ;get x
imul w ds:[bp] ;*sin rotz
shrd ax,dx,14d
mov cx,ax ;store in cx
mov ax,qcoord+2 ;get y
imul w ds:[bp+60d] ;*cos rotz
shrd ax,dx,14d
add cx,ax
mov zcoord+2,cx
mov Point3d[bx+2],cx
endm
get_normal macro ;calculates normal vector of an area
mov ax,delta1[2] ;a2*b3
imul delta2[4]
shrd ax,dx,4
mov n[0],ax
mov ax,delta1[4] ;a3*b2
imul delta2[2]
shrd ax,dx,4
sub n[0],ax
mov ax,delta1[4] ;a3*b1
imul delta2[0]
shrd ax,dx,4
mov n[2],ax
mov ax,delta1[0] ;a1*b3
imul delta2[4]
shrd ax,dx,4
sub n[2],ax
mov ax,delta1[0] ;a1*b2
imul delta2[2]
shrd ax,dx,4
mov n[4],ax
mov ax,delta1[2]
imul delta2[0]
shrd ax,dx,4
sub n[4],ax ;cross product (=normal vector) finished
mov ax,n[0] ;x1 ^ 2
imul ax
mov bx,ax
mov cx,dx
mov ax,n[2] ;+x2 ^ 2
imul ax
add bx,ax
adc cx,dx
mov ax,n[4] ;+x3 ^ 2
imul ax
add ax,bx
adc dx,cx ;sum in dx:ax
push si
call root ;root in ax
pop si
mov n_amnt,ax ;amount of normal vector finished
endm
light macro ;determines brightness of an area
mov ax,n[0]
imul l[0] ;light vector * normal vector
mov bx,ax ;form sum in cx:bx
mov cx,dx
mov ax,n[2]
imul l[2]
add bx,ax
adc cx,dx
mov ax,n[4]
imul l[4]
add ax,bx ;scalar product finished in dx:ax
adc dx,cx
idiv l_amnt ;divide by l_amnt
mov bx,n_amnt ;and by n_amnt
cwd
shld dx,ax,5 ;values from -32 bis +32
shl ax,5d
mov bp,startpoly ;prepare addressing of surface color
idiv bx ;division by denominator
inc ax
or ax,ax
js turned_toward ;if cos α positive -> turned away from the light
xor ax,ax ;thus, no light
turned_toward:
sub b polycol,al ;cos<0 -> add to primary color
endm
code segment
assume cs:code,ds:data
public drawworld
public linecount
public polycol
public polyn
public poly2d
public poly3d
linecount dw 0
polycol dw 3 ;current surface color
polyn dw 0 ;number of existing corners
poly2d dw num_cor*4 dup (0) ;corners of polygon to be drawn
poly3d dw num_cor*4 dup (0) ;3D corners
public Txt_No
Txt_No dw 0 ;current texture number
public delta1,delta2
delta1 dw 0,0,0 ;plane vectors
delta2 dw 0,0,0
l dw 11d,11d,11d ;light vector
l_amnt dw 19d ;amount of light vector
drawworld proc pascal ;draws three-dimensional world
push ds
push es
push bp
lea si,surfcconst ;surfaces are addressed by si
mov meanptr,0 ;start in Mean-Array with 0
mov ax,ds:[rotx] ;get angle,
shl ax,1 ;convert as memory offset
add ax,offset sine
mov crotx,ax ;and store in help variables
mov ax,ds:[roty] ;exactly the same for y
shl ax,1
add ax,offset sine
mov croty,ax
mov ax,ds:[rotz] ;and z
shl ax,1
add ax,offset sine
mov crotz,ax
npoly: ;polygon loop
mov startpoly,si ;store for later use
add si,2 ;skip color
mov cx,[si] ;get number of corners
mov linecount,cx ;load counter
inc cx ;due to closed area
mov w polyn,cx ;enter in Point-Array
add si,2 ;move to actual coordinates
nline:
xrot rotx_x,si ;rotate coordinates by x
yrot roty_x,rotx_x ;by y
zrot rotz_x,roty_x ;and by z
z2cx rotz_x ;get z start
setcoord rotz_x,160 ;write coordinates
setcoord rotz_y,100
add si,2 ;next corner point
dec linecount ;advance line counter
je polyok ;all drawn -> terminate
jmp nline ;otherwise next line
polyok:
mov bx,meanptr ;calculate mean value:
mov ax,mean[bx] ;get sum
mov cx,polyn
dec cx
cwd
div cx ;and divide by number of corners
mov mean[bx],ax ;write back
mov ax,startpoly ;write "number" of area also
mov mean[bx+2],ax
add meanptr,4 ;continue
cmp w [si+2],0 ;polygons all finished ?
je finished
jmp npoly
finished:
cmp b sf_sort,0 ;sort surfaces ?
je no_quicksort
call quicksort pascal,0,bx ;sort field from 0 to current position
no_quicksort:
mov mean[bx+4],0 ;set termination
mov ax,cs ;set destination segment
mov es,ax
xor bx,bx ;start with first surface
npoly_draw:
lea di,poly2d ;destination:Poly-Array
mov bp,mean[bx+2] ;get pointer to color and points of surface
mov ax,ds:[bp] ;get color and set
mov polycol,ax
mov texture,0 ;Assumption: no texture
cmp ah,0ffh ;texture ?
jne no_texture
mov texture,1 ;yes, then set
mov b txt_no,al ;note number
no_texture:
mov b lightsrc,0 ;Assumption: no shading
cmp ah,0feh ;shading ?
jne no_lightsource
mov b lightsrc,1 ;yes, then set
no_lightsource:
add bp,2 ;position on number
mov cx,ds:[bp] ;get number of corners
mov polyn,cx ;write in Poly-Array
npoint:
add bp,2
mov si,ds:[bp] ;get pointer to actual point
shl si,3 ;3 word entry !
add si,offset Point ;and x/y from Point-Array to Poly-Coord.
mov ax,[si+Point3d-Point] ;3d-get x
mov es:[di+poly3d-poly2d],ax ;set 3d-x
mov ax,[si+Point3d-Point+2] ;3d-get y
mov es:[di+poly3d-poly2d+2],ax;set 3d-y
mov ax,[si+Point3d-Point+4] ;3d-get z
mov es:[di+poly3d-poly2d+4],ax;set 3d-z
movsw ;set 2D-coordinates
movsw
add di,4 ;next Poly2d entry
dec cx ;all corners ?
jne npoint
mov bp,polyn ;copy first corner to last
shl bp,3 ;position on first point
neg bp
mov ax,es:[di+bp] ;and copy
mov es:[di],ax
mov ax,es:[di+bp+2]
mov es:[di+2],ax
add di,poly3d-poly2d ;the same for 3d-coordinates
mov ax,es:[di+bp] ;and copy
mov es:[di],ax
mov ax,es:[di+bp+2]
mov es:[di+2],ax
mov ax,es:[di+bp+4]
mov es:[di+4],ax
cmp fill,1 ;fill surface ?
jne lines
getdelta ;yes, then calculate Delta1 and 2
cmp b lightsrc,0 ;light source ?
jne shade
jmp no_light
shade: ;yes,
push bx
get_normal ;then normal vector
light ;and calculate light
pop bx
no_light:
inc polyn ;increment number of corners
call fillpol ;draw surface
next:
add bx,4 ;locate next surface
cmp mean[bx],0 ;last ?
je _npoly_draw ;no, then continue
jmp npoly_draw
lines:
push bx
call drawpol ;draw polygon
pop bx
jmp next
_npoly_draw:
pop bp ;finished
pop es
pop ds
ret
drawworld endp
public quicksort
quicksort proc pascal down,up:word
;sorts Mean-Array according to Quicksort algorithm
local key:word
local left:word
push bx
mov bx,down ;find middle
add bx,up
shr bx,1
and bx,not 3 ;posit on blocks of 4
mov dx,mean[bx] ;get key
mov key,dx
mov ax,down ;initialize right and left with base values
mov si,ax
mov left,ax
mov ax,up
mov di,ax
mov dx,key
left_nearer:
cmp mean[si],dx ;greater than key -> continue searching
jbe left_on
add si,4 ;posit on next one
jmp left_nearer ;and check it
left_on:
cmp mean[di],dx ;less than key -> continue searching
jae right_on
sub di,4 ;posit on next one
jmp left_on ;and check it
right_on:
cmp si,di ;left <= right ?
jg end_schl ;no -> subarea sorted
mov eax,dword ptr mean[si] ;exchange mean values and positions
xchg eax,dword ptr mean[di]
mov dword ptr mean[si],eax
add si,4 ;continue moving pointer
sub di,4
end_schl:
cmp si,di ;left > right, then continue
jle left_nearer
mov left,si ;store left, due to recursion
cmp down,di ;down < right -> sort left subarea
jge right_finished
call quicksort pascal,down,di ;continue sorting recursive halves
right_finished:
mov si,left ;up > left -> sort right subarea
cmp up,si
jle left_finished
call quicksort pascal,si,up ;continue sorting recursive halves
left_finished:
pop bx
ret
quicksort endp
code ends
end