home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC Interdit
/
pc-interdit.iso
/
graph
/
3dasm.asm
< prev
next >
Wrap
Assembly Source File
|
1994-10-17
|
15KB
|
513 lines
w equ word ptr
b equ byte ptr
surfclen equ 200 ;longueur maximale de la définition des faces
PointsT equ 4*100 ;taille du tableau des points
nb_su equ 30 ;nombre maximal de faces
nb_som equ 10 ;nombre maximal de sommets
data segment ;variables externes de la partie Pascal
extrn vz:word ;profondeur général
extrn rotx:Word ;angles de rotation
extrn roty:Word
extrn rotz:word
extrn worldconst:dataptr ;tableau des points
extrn surfcconst:dataptr ;tableau des définitions des faces
extrn lightsrc:word ;indicateur pour effet de lumière
extrn su_sort:word ;indicateur pour tri des faces
extrn su_cacher:word ;indicateur pour traitement des faces cachées
extrn Texture:Byte ;indicateur pour textures
extrn Remplir:Byte ;indicateur pour remplissage/fil de fer
crotx dw 0 ;angle x, y et z comme offset
croty dw 0 ;sur la valeur du sinus
crotz dw 0
rotx_x dw 0 ;x, y, z après rotation x
rotx_y dw 0
rotx_z dw 0
roty_x dw 0 ;après rotation y
roty_y dw 0
roty_z dw 0
rotz_x dw 0 ;après rotation z, définitif
rotz_y dw 0
rotz_z dw 0
startpoly dw 0 ;début de la déf de la face courante
Points dw PointsT dup (0) ;mémorise les coordonnées calculées
Pointsptr dw 0 ;pointe sur le tableau de points
Points3d dw PointsT dup (0) ;mémorise les coordonnées 3D (texture)
moyen dw nb_su*2 dup (0) ;répertoire des valeurs moyennes de z
moyenptr dw 0 ;pointeur dans le tableau "moyen"
n dw 0,0,0,0,0,0 ;vecteur normal 32 bits
n_long dw 0 ;longueur du vecteur normal
extrn sinus:dataptr
data ends
extrn drawpol:near ;dessine une face en fil de fer
extrn fillpol:near ;remplit une face
extrn racine:near ;calcule la racine de ax
getdelta macro ;calcule les deux vecteurs compris dans le plan de la face
mov ax,poly3d[0] ;x: sommet de départ
mov delta2[0],ax ;sauvegarde temporaire en delta2
sub ax,poly3d[8] ;différence avec le premier point
mov delta1[0],ax ; delta1 terminé
mov ax,poly3d[2] ;y: sommet de départ
mov delta2[2],ax ;sauvegarde temporaire en delta2
sub ax,poly3d[10d];différence avec le premier point
mov delta1[2],ax ; delta1 terminé
mov ax,poly3d[4] ;z: sommet de départ
mov delta2[4],ax ;sauvegarde temporaire en delta2
sub ax,poly3d[12d];différence avec le premier point
mov delta1[4],ax ; delta1 terminé
mov bp,polyn ;sélectionne le dernier point
dec bp
shl bp,3 ; 8 octets à chaque fois
mov ax,poly3d[bp] ;lit x
sub delta2[0],ax ;forme la différence
mov ax,poly3d[bp+2] ;lit y
sub delta2[2],ax ;forme la différence
mov ax,poly3d[bp+4] ;lit z
sub delta2[4],ax ;forme la différence
endm
setcoord macro source,offst ;fixe les coord d'écran calculées
.386
mov ax,source ;projette les coordonnées
cwd
shld dx,ax,7
shl ax,7
idiv cx
add ax,offst ;centre de l'écran = 0,0,0
mov bx,Pointsptr ;report dans le tableau des points
mov Points[bx],ax
add Pointsptr,2 ;déplace le pointeur sur le tableau
endm
z2cx macro tabofs ;lit en cx la coordonnée z
mov cx,tabofs + 4
add cx,vz ;ajoute la translation z
mov bx,moyenptr ;report dans le tableau moyen
add moyen[bx],cx
endm
xrot macro dcoord,scoord ;rotation de scoord autour de x, résultat en dcoord
.386
mov bp,crotx ;charge l'angle
mov bx,[scoord]
shl bx,3 ;x8, pour alignemt sur entrée de points
mov Pointsptr,bx
sub bx,[scoord] ;en tout x6, pour alignement sur entrées espace
sub bx,[scoord]
add bx,offset worldconst
mov ax,[bx] ;lit x
mov dcoord,ax ;qui reste inchangé
mov ax,[bx+2] ;lit y
imul w ds:[bp+60d];*cos rotx
shrd ax,dx,14d
mov cx,ax ;mémorise en cx
mov ax,[bx+4] ;lit z
imul w ds:[bp] ;*-sin rotx
shrd ax,dx,14d
sub cx,ax
mov dcoord+2,cx ;y terminé et stocké
mov ax,[bx+2] ;lit y
imul w ds:[bp] ;*sin rotx
shrd ax,dx,14d
mov cx,ax ;mémorise en cx
mov ax,[bx+4] ;lit z
imul w ds:[bp+60d] ;*cos rotx
shrd ax,dx,14d
add cx,ax
mov dcoord+4,cx
endm
yrot macro dcoord,scoord ;rotation de scoord autour de y, résultat en dcoord
mov bp,croty ;lit l'angle
mov ax,scoord+2 ;et y
mov dcoord+2,ax ;y reste inchangé
mov ax,scoord ;lit x
imul w ds:[bp+60d] ;*cos roty
shrd ax,dx,14d
mov cx,ax ;mémorise en cx
mov ax,scoord+4 ;lit z
imul w ds:[bp] ;*sin roty
shrd ax,dx,14d
add cx,ax
mov dcoord,cx ;x terminé et stocké
mov ax,scoord ;lit x
imul w ds:[bp] ;*-sin roty
shrd ax,dx,14d
mov cx,ax ;mémorise en cx
mov ax,scoord+4 ;lit z
imul w ds:[bp+60d];*cos roty
shrd ax,dx,14d
sub ax,cx
mov dcoord+4,ax
endm
zrot macro dcoord,scoord ;rotation de scoord autour de z, résultat en dcoord
mov bx,Pointsptr ;prépare le report dans le tableau de points 3D
mov bp,crotz ;lit l'angle
mov ax,scoord+4 ;lit z
mov dcoord+4,ax ;et le laisse inchangé
mov Points3d[bx+4],ax ;report également dans tableau 3D
mov ax,scoord ;lit x
imul w ds:[bp+60d];*cos rotz
shrd ax,dx,14d
mov cx,ax ;mémorise en cx
mov ax,scoord+2 ;lit y
imul w ds:[bp] ;*-sin rotz
shrd ax,dx,14d
sub cx,ax
mov dcoord,cx ;x terminé et stocké
mov Points3d[bx],cx
mov ax,scoord ;lit x
imul w ds:[bp] ;*sin rotz
shrd ax,dx,14d
mov cx,ax ;mémorise en cx
mov ax,scoord+2 ;lit y
imul w ds:[bp+60d];*cos rotz
shrd ax,dx,14d
add cx,ax
mov dcoord+2,cx
mov Points3d[bx+2],cx
endm
get_normal macro ;calcule le vecteur normal d'une face
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 ; produit vectoriel (=vecteur normal) calculé
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 ;somme en dx:ax
push si
call racine ;racine en ax
pop si
mov n_long,ax ;longueur du vecteur normal calculée
endm
light macro ;détermine la luminosité d'une face
mov ax,n[0]
imul l[0] ;vecteur de la lumière * vecteur normal
mov bx,ax ;somme en 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 ;produit scalaire en dx:ax
adc dx,cx
idiv l_long ;division par l_long
mov bx,n_long ;et par n_long
cwd
shld dx,ax,5 ;valeurs de -32 à +32
shl ax,5d
mov bp,startpoly ;prépare l'adressage de la couleur de surface
idiv bx ;division par numérateur
inc ax
or ax,ax
js danslumiere ;si cos A positif -> lumière partante
xor ax,ax ;donc pas d'éclairage
danslumiere:
sub b polycol,al ;cos<0 -> addition à la couleur de base
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 ;couleur de face courante
polyn dw 0 ;nombre de sommets effectivement présents
poly2d dw nb_som*4 dup (0) ;sommets du polygone à desssiner
poly3d dw nb_som*4 dup (0) ;sommets 3D
public Txt_Nr
Txt_Nr dw 0 ;numéro de la texture courante
public delta1,delta2
delta1 dw 0,0,0 ;vecteurs de plans
delta2 dw 0,0,0
l dw 11d,11d,11d ;vecteur lumière
l_long dw 19d ;longueur du vecteur lumière
drawworld proc pascal ;dessine un espace tridimensionnel
push ds
push es
push bp
lea si,surfcconst ;faces adressées par si
mov moyenptr,0 ;on commence par 0 dans le tableau moyen
mov ax,ds:[rotx] ;lit l'angle,
shl ax,1 ;convertit en offset mémoire
add ax,offset sinus
mov crotx,ax ;et stocke dans variables auxiliaires
mov ax,ds:[roty] ;idem pour y
shl ax,1
add ax,offset sinus
mov croty,ax
mov ax,ds:[rotz] ;et z
shl ax,1
add ax,offset sinus
mov crotz,ax
npoly: ;boucle des polygones
mov startpoly,si ;sauve pour usage ultérieur
add si,2 ;passe par-dessus la couleur
mov cx,[si] ;lit le nombre de sommets
mov linecount,cx ;charge le compteur
inc cx ;à cause des faces fermées
mov w polyn,cx ;report dans le tableau des points
add si,2 ;on continue par les coordonnées proprement dites
nline:
xrot rotx_x,si ;rotation des coordonnées autour de x
yrot roty_x,rotx_x;autour de y
zrot rotz_x,roty_x;et de z
z2cx rotz_x ;lit début z
setcoord rotz_x,160 ;enregistre les coordonnées
setcoord rotz_y,100
add si,2 ;sommet suivant
dec linecount ;diminue le compteur de ligne
je polyok ;tout dessiné ? -> fini
jmp nline ;sinon ligne suivante
polyok:
mov bx,moyenptr ;calcule la valeur moyenne :
mov ax,moyen[bx] ;lit la somme
mov cx,polyn
dec cx
cwd
div cx ;et la divise par le nombre de sommets
mov moyen[bx],ax ;puis enregistre le résultat
mov ax,startpoly ;avec le "numéro" de la face
mov moyen[bx+2],ax
add moyenptr,4 ;on continue
cmp w [si+2],0 ;tous les polygones traités ?
je fini
jmp npoly
fini:
cmp b su_sort,0 ;trier les faces ?
je no_quicksort
call quicksort pascal,0,bx ;trie le champ de 0 à la position actuelle
no_quicksort:
mov moyen[bx+4],0 ;terminaison
mov ax,cs ;segment de destination
mov es,ax
xor bx,bx ;on commence par la première face
npoly_draw:
lea di,poly2d ;destination : tableau Poly
mov bp,moyen[bx+2] ;lit pointeur sur couleur et points de la face
mov ax,ds:[bp] ;lit et fixe la couleur
mov polycol,ax
mov texture,0 ;a priori : pas de texture
cmp ah,0ffh ;texture ?
jne no_textur
mov texture,1 ;oui, on la fixe
mov b txt_nr,al ;prend note du n°
no_textur:
mov b lightsrc,0 ;a priori : pas d'ombre
cmp ah,0feh ;ombre ?
jne no_sourcelum
mov b lightsrc,1 ;oui, on la fixe
no_sourcelum:
add bp,2 ;se positionne sur le nombre
mov cx,ds:[bp] ;lit le nombre de sommets
mov polyn,cx ;l'enregistre dans le tableau Poly
npoint:
add bp,2
mov si,ds:[bp] ;pointe sur les points effectifs
shl si,3 ;3 entrées Word !
add si,offset Points ;et x,y du tableau des points en coord Poly
mov ax,[si+Points3d-Points] ;lit 3d-x
mov es:[di+poly3d-poly2d],ax ;fixe 3d-x
mov ax,[si+Points3d-Points+2] ;lit 3d-y
mov es:[di+poly3d-poly2d+2],ax;fixe 3d-y
mov ax,[si+Points3d-Points+4] ;lit 3d-z
mov es:[di+poly3d-poly2d+4],ax;fixe 3d-z
movsw ;fixe les coordonnées 2D
movsw
add di,4 ;entrée suivante Poly2d
dec cx ;tous les sommets ?
jne npoint
mov bp,polyn ;copie le premier sommet sur le dernier
shl bp,3 ;se positionne sur le premier point
neg bp
mov ax,es:[di+bp] ;et effectue la copie
mov es:[di],ax
mov ax,es:[di+bp+2]
mov es:[di+2],ax
add di,poly3d-poly2d ;idem pour les coordonnées 3d
mov ax,es:[di+bp] ;effectue la copie
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 Remplir,1 ;remplir la face ?
jne lines
getdelta ;oui alors on calcule Delta1 et 2
cmp b lightsrc,0 ;source de lumière ?
jne delombre
jmp no_lumiere
delombre: ;oui
push bx
get_normal ;alos calcule le vecteur normal
light ;et la luminosité
pop bx
no_lumiere:
inc polyn ;incrémente le nombre de sommets
call fillpol ;dessine la face
next:
add bx,4 ;cap sur la face suivante
cmp moyen[bx],0 ;est-ce la dernière ?
je _npoly_draw ;non on continue
jmp npoly_draw
lines:
push bx
call drawpol ;dessine le polygone
pop bx
jmp next
_npoly_draw:
pop bp ;c'est terminé
pop es
pop ds
ret
drawworld endp
public quicksort
quicksort proc pascal bas,haut:word
;trie le tableau moyen avec l'algorithme Quicksort
local cle:word
local gauche:word
push bx
mov bx,bas ;trouve le milieu
add bx,haut
shr bx,1
and bx,not 3 ;positionnement sur groupe de 4
mov dx,moyen[bx] ;lit la clé
mov cle,dx
mov ax,bas ;initialise droite et gauche avec valeurs de base
mov si,ax
mov gauche,ax
mov ax,haut
mov di,ax
mov dx,cle
gauche_pluspres:
cmp moyen[si],dx ;plus grand que clé -> on continue la recherche
jbe a_gauche
add si,4 ;position suivante
jmp gauche_pluspres ;on la teste
a_gauche:
cmp moyen[di],dx ;plus petit que la clé -> on continue la recherche
jae a_droite
sub di,4 ;position suivante
jmp a_gauche ;on la teste
a_droite:
cmp si,di ;gauche <= droite ?
jg finbou ;non -> partie triée
mov eax,dword ptr moyen[si] ;échange les valeurs moyennes et les positions
xchg eax,dword ptr moyen[di]
mov dword ptr moyen[si],eax
add si,4 ;avance le pointeur
sub di,4
finbou:
cmp si,di ;gauche > droite , alors on continue
jle gauche_pluspres
mov gauche,si ;sauve gauche à cause récursion
cmp bas,di ;bas < droite -> partie gauche triée
jge droite_fini
call quicksort pascal,bas,di;diviser par deux récursivt, poursuivre le tri
droite_fini:
mov si,gauche ;haut > gauche -> partie droite triée
cmp haut,si
jle gauche_fini
call quicksort pascal,si,haut ;diviser par deux récursivt, poursuivre le tri
gauche_fini:
pop bx
ret
quicksort endp
code ends
end