Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 1780 → Rev 1781

/programs/demos/3dsheart/trunk/3DSheart.ASM
0,0 → 1,1984
;
; application : Deus Caritas Est - app shows three models shading
; compiler : FASM 1.65.13
; system : KolibriOS/MenuetOS
; author : macgub
; email : macgub3@wp.pl
; web : www.menuet.xt.pl
; Fell free to use this intro in your own distribution of KolibriOS/MenuetOS.
; Special greetings to all MenuetOS maniax in the world.
; I hope because my intros Christian Belive will be near to each of You.
 
 
; Some adjustments made by Madis Kalme
; madis.kalme@mail.ee
; I tried optimizing it a bit, but don't know if it was successful. The objects
; can be:
; 1) Read from a file (*.3DS standard)
; 2) Written in manually (at the end of the code)
SIZE_X equ 250
SIZE_Y equ 250
TIMEOUT equ 4
ROUND equ 10
TEX_X equ 512 ; texture width
TEX_Y equ 512 ; height
TEX_SHIFT equ 9 ; texture widith shifting
TEX equ SHIFTING ; TEX={SHIFTING | FLUENTLY}
FLUENTLY = 0
SHIFTING = 1
;CATMULL_SHIFT equ 8
NON = 0
MMX = 1
 
Ext = MMX ;Ext={ NON | MMX}
 
use32
org 0x0
db 'MENUET01' ; 8 byte id
dd 0x01 ; header version
dd START ; start of code
dd I_END ; size of image
dd I_END ; memory for app
dd I_END ; esp
dd 0x0 , 0x0 ; I_Param , I_Icon
 
START: ; start of execution
cld
; call alloc_buffer_mem
call read_from_file
call init_triangles_normals
call init_point_normals
call init_envmap
call draw_window
 
 
still:
mov eax,23 ; wait here for event with timeout
mov ebx,TIMEOUT
cmp [speed_flag],1
jne .skip
mov eax,11
.skip:
int 0x40
 
cmp eax,1 ; redraw request ?
je red
cmp eax,2 ; key in buffer ?
je key
cmp eax,3 ; button in buffer ?
je button
 
jmp noclose
 
red: ; redraw
call draw_window
jmp noclose
 
key: ; key
mov eax,2 ; just read it and ignore
int 0x40
jmp noclose
 
button: ; button
mov eax,17 ; get id
int 0x40
 
cmp ah,1 ; button id=1 ?
jne .ch_another
 
mov eax,-1 ; close this program
int 0x40
.ch_another:
cmp ah,2
jne .ch_another1
inc [r_flag]
cmp [r_flag],3
jne noclose
mov [r_flag],0
.ch_another1:
cmp ah,3
jne .ch_another2
inc [dr_flag]
cmp [dr_flag],3
jne noclose
mov [dr_flag],0
.ch_another2:
cmp ah,4 ; toggle speed
jne @f
inc [speed_flag]
cmp [speed_flag],2
jne noclose
mov [speed_flag],0
@@:
cmp ah,5
jne @f ;scale-
mov [scale],0.7
fninit
fld [sscale]
fmul [scale]
fstp [sscale]
call read_from_file
mov ax,[vect_x] ;-- last change
mov bx,[vect_y]
mov cx,[vect_z]
call add_vector
; call do_scale
@@:
cmp ah,6
jne @f ; scale+
mov [scale],1.3
fninit
fld [sscale]
fmul [scale]
fstp [sscale]
call read_from_file
mov ax,[vect_x]
mov bx,[vect_y]
mov cx,[vect_z]
call add_vector
call init_triangles_normals
call init_point_normals
@@:
cmp ah,7
jne @f
xor ax,ax ;add vector to object and rotary point
mov bx,-10
xor cx,cx
call add_vector
sub [vect_y],10
sub [yo],10
@@:
cmp ah,8
jne @f
xor ax,ax
xor bx,bx
mov cx,10
call add_vector
add [vect_z],10
add [zo],10
@@:
cmp ah,9
jne @f
mov ax,-10
xor bx,bx
xor cx,cx
call add_vector
sub [vect_x],10
sub [xo],10
@@:
cmp ah,10
jne @f
mov ax,10
xor bx,bx
xor cx,cx
call add_vector
add [vect_x],10
add [xo],10
@@:
cmp ah,11
jne @f
xor ax,ax
xor bx,bx
mov cx,-10
call add_vector
sub [vect_z],10
sub [zo],10
@@:
cmp ah,12
jne @f
xor ax,ax
mov bx,10
xor cx,cx
call add_vector
add [vect_y],10
add [yo],10
@@:
cmp ah,13 ; change main color -
jne @f ; - lead color setting
cmp [max_color_r],245
jge @f
add [max_color_r],10
call init_envmap
@@:
cmp ah,14
jne @f
cmp [max_color_g],245
jge @f
add [max_color_g],10
call init_envmap
@@:
cmp ah,15
jne @f
cmp [max_color_b],245
jge @f
add [max_color_b],10
call init_envmap
@@:
cmp ah,16 ; change main color
jne @f
cmp [max_color_r],10
jle @f
sub [max_color_r],10
call init_envmap
@@:
cmp ah,17
jne @f
cmp [max_color_g],10
jle @f
sub [max_color_g],10
call init_envmap
@@:
cmp ah,18
jne @f
cmp [max_color_b],10
jle @f
sub [max_color_b],10
call init_envmap
@@:
cmp ah,19
jne @f
inc [catmull_flag]
cmp [catmull_flag],2
jne @f
mov [catmull_flag],0
@@:
noclose:
 
call calculate_angle ; calculates sinus and cosinus
call copy_point_normals
; copy normals and rotate the copy using sin/cosbeta - best way
call rotate_point_normals
call calculate_colors
call copy_points
call rotate_points
call translate_perspective_points; translate from 3d to 2d
call clrscr ; clear the screen
cmp [dr_flag],2
je @f
cmp [catmull_flag],1 ;if env_mapping sort faces
je @f
@@:
call sort_triangles
@@:
call fill_Z_buffer
 
RDTSC
push eax
call draw_triangles ; draw all triangles from the list
 
RDTSC
sub eax,[esp]
sub eax,41
; lea esi,[debug_points]
; lea edi,[debug_points+6]
; lea ebx,[debug_vector1]
; call make_vector
; fninit
; fld [sinbeta_one]
; fimul [debug_dwd]
; fistp [debug_dd]
; movzx eax,[debug_dd]
 
 
mov ecx,10
.dc:
xor edx,edx
mov edi,10
div edi
add dl,30h
mov [STRdata+ecx-1],dl
loop .dc
pop eax
macro show
{
mov eax,7 ; put image
mov ebx,screen
mov ecx,SIZE_X shl 16 + SIZE_Y
mov edx,5 shl 16 + 20
int 0x40
}
show
mov eax,4 ; function 4 : write text to window
mov ebx,5*65536+23 ; [x start] *65536 + [y start]
mov ecx,-1
mov edx,STRdata ; pointer to text beginning
mov esi,10 ; text length
int 40h
 
 
 
jmp still
 
;--------------------------------------------------------------------------------
;-------------------------PROCEDURES---------------------------------------------
;--------------------------------------------------------------------------------
include "../../3DS/TEX3.INC"
include "../../3DS/FLAT_CAT.INC"
include "../../3DS/GRD_CAT.INC"
include "../../3DS/3DMATH.INC"
include "../../3DS/GRD3.INC"
include "../../3DS/FLAT3.INC"
 
 
;alloc_buffer_mem:
; mov eax,68
; mov ebx,5
; mov ecx,SIZE_X*SIZE_Y*3
; int 0x40
; mov [screen],eax
;ret
init_envmap:
 
.temp equ word [ebp-2]
push ebp
mov ebp,esp
sub esp,2
mov edi,envmap
fninit
 
mov dx,-256
.ie_ver:
mov cx,-256
.ie_hor:
mov .temp,cx
fild .temp
fmul st,st0
mov .temp,dx
fild .temp
fmul st,st0
faddp
fsqrt
mov .temp,254
fisubr .temp
fmul [env_const]
fistp .temp
mov ax,.temp
 
or ax,ax
jge .ie_ok1
xor ax,ax
jmp .ie_ok2
.ie_ok1:
cmp ax,254
jle .ie_ok2
mov ax,254
.ie_ok2:
push dx
mov bx,ax
mul [max_color_b]
shr ax,8
stosb
mov ax,bx
mul [max_color_g]
shr ax,8
stosb
mov ax,bx
mul [max_color_r]
shr ax,8
stosb
pop dx
 
inc cx
cmp cx,256
jne .ie_hor
 
inc dx
cmp dx,256
jne .ie_ver
 
mov esp,ebp
pop ebp
macro debug
{
mov edi,envmap
mov ecx,512*512*3/4
mov eax,0xffffffff
rep stosd
}
ret
calculate_colors:
fninit
xor ebx,ebx
movzx ecx,[points_count_var]
lea ecx,[ecx*3]
add ecx,ecx
.cc_again:
mov esi,light_vector
lea edi,[point_normals_rotated+ebx*2]
call dot_product
fcom [dot_min]
fstsw ax
sahf
ja .cc_ok1
ffree st
mov dword[points_color+ebx],0
mov word[points_color+ebx+4],0
add ebx,6
cmp ebx,ecx
jne .cc_again
jmp .cc_done
.cc_ok1:
fcom [dot_max]
fstsw ax
sahf
jb .cc_ok2
ffree st
mov dword[points_color+ebx],0 ; clear r,g,b
mov word[points_color+ebx+4],0
add ebx,6
cmp ebx,ecx
jne .cc_again
jmp .cc_done
.cc_ok2:
fld st
fld st
fimul [max_color_r]
fistp word[points_color+ebx] ;each color as word
fimul [max_color_g]
fistp word[points_color+ebx+2]
fimul [max_color_b]
fistp word[points_color+ebx+4]
add ebx,6
cmp ebx,ecx
jne .cc_again
.cc_done:
ret
copy_point_normals:
movzx ecx,[points_count_var]
shl ecx,2
inc ecx
mov esi,point_normals
mov edi,point_normals_rotated
rep movsd
ret
rotate_point_normals:
movzx ecx,[points_count_var]
mov ebx,point_normals_rotated
fninit ; for now only rotate around Z axle
.again_r:
cmp [r_flag],1
je .z_rot
cmp [r_flag],2
je .x_rot
 
.y_rot:
fld dword[ebx] ; x
fld [sinbeta]
fmul dword[ebx+8] ; z * sinbeta
fchs
fld [cosbeta]
fmul dword[ebx] ; x * cosbeta
faddp
fstp dword[ebx] ; new x
fmul [sinbeta] ; old x * sinbeta
fld [cosbeta]
fmul dword[ebx+8] ; z * cosbeta
faddp
fstp dword[ebx+8] ; new z
add ebx,12
loop .y_rot
jmp .end_rot
.z_rot:
fld dword[ebx] ;x
fld [sinbeta]
fmul dword[ebx+4] ;y
fld [cosbeta]
fmul dword[ebx] ;x
faddp
fstp dword[ebx] ;new x
fmul [sinbeta] ; sinbeta * old x
fchs
fld [cosbeta]
fmul dword[ebx+4] ; cosbeta * y
faddp
fstp dword[ebx+4] ; new y
add ebx,12
loop .z_rot
jmp .end_rot
.x_rot:
fld dword[ebx+4] ;y
fld [sinbeta]
fmul dword[ebx+8] ;z
fld [cosbeta]
fmul dword[ebx+4] ;y
faddp
fstp dword[ebx+4] ; new y
fmul [sinbeta] ; sinbeta * old y
fchs
fld [cosbeta]
fmul dword[ebx+8]
faddp
fstp dword[ebx+8]
add ebx,12
loop .x_rot
.end_rot:
ret
init_triangles_normals:
mov ebx,triangles_normals
mov ebp,triangles
@@:
push ebx
mov ebx,vectors
movzx esi,word[ebp] ; first point index
lea esi,[esi*3]
lea esi,[points+esi*2] ; esi - pointer to 1st 3d point
movzx edi,word[ebp+2] ; second point index
lea edi,[edi*3]
lea edi,[points+edi*2] ; edi - pointer to 2nd 3d point
call make_vector
add ebx,12
mov esi,edi
movzx edi,word[ebp+4] ; third point index
lea edi,[edi*3]
lea edi,[points+edi*2]
call make_vector
mov edi,ebx ; edi - pointer to 2nd vector
mov esi,ebx
sub esi,12 ; esi - pointer to 1st vector
pop ebx
call cross_product
mov edi,ebx
call normalize_vector
add ebp,6
add ebx,12
cmp dword[ebp],-1
jne @b
ret
 
init_point_normals:
.x equ dword [ebp-4]
.y equ dword [ebp-8]
.z equ dword [ebp-12]
.point_number equ word [ebp-26]
.hit_faces equ word [ebp-28]
 
fninit
mov ebp,esp
sub esp,28
mov edi,point_normals
mov .point_number,0
.ipn_loop:
mov .hit_faces,0
mov .x,0
mov .y,0
mov .z,0
mov esi,triangles
xor ecx,ecx ; ecx - triangle number
.ipn_check_face:
xor ebx,ebx ; ebx - 'position' in one triangle
.ipn_check_vertex:
movzx eax,word[esi+ebx] ; eax - point_number
cmp ax,.point_number
jne .ipn_next_vertex
push esi
mov esi,ecx
lea esi,[esi*3]
lea esi,[triangles_normals+esi*4]
; shl esi,2
; add esi,triangles_normals
 
fld .x
fadd dword[esi+vec_x]
fstp .x
fld .y
fadd dword[esi+vec_y]
fstp .y
fld .z
fadd dword[esi+vec_z]
fstp .z
pop esi
inc .hit_faces
jmp .ipn_next_face
.ipn_next_vertex:
add ebx,2
cmp ebx,6
jne .ipn_check_vertex
.ipn_next_face:
add esi,6
inc ecx
cmp cx,[triangles_count_var]
jne .ipn_check_face
 
fld .x
fidiv .hit_faces
fstp dword[edi+vec_x]
fld .y
fidiv .hit_faces
fstp dword[edi+vec_y]
fld .z
fidiv .hit_faces
fstp dword[edi+vec_z]
call normalize_vector
add edi,12 ;type vector 3d
inc .point_number
mov dx,.point_number
cmp dx,[points_count_var]
jne .ipn_loop
 
mov esp,ebp
ret
 
add_vector:
mov ebp,points
@@:
add word[ebp],ax
add word[ebp+2],bx
add word[ebp+4],cx
add ebp,6
cmp dword[ebp],-1
jne @b
ret
;do_scale:
; fninit
; mov ebp,points
; .next_sc:
; fld1
; fsub [scale]
; fld st
; fimul [xo]
; fld [scale]
; fimul word[ebp] ;x
; faddp
; fistp word[ebp]
; fld st
; fimul [yo]
; fld [scale]
; fimul word[ebp+2]
; faddp
; fistp word[ebp+2]
; fimul [zo]
; fld [scale]
; fimul word[ebp+4]
; faddp
; fistp word[ebp+4]
; add ebp,6
; cmp dword[ebp],-1
; jne .next_sc
;ret
sort_triangles:
mov esi,triangles
mov edi,triangles_with_z
mov ebp,points_rotated
 
make_triangle_with_z: ;makes list with triangles and z position
movzx eax,word[esi]
lea eax,[eax*3]
movzx ecx,word[ebp+eax*2+4]
 
movzx eax,word[esi+2]
lea eax,[eax*3]
add cx,word[ebp+eax*2+4]
 
movzx eax,word[esi+4]
lea eax,[eax*3]
add cx,word[ebp+eax*2+4]
 
mov ax,cx
; cwd
; idiv word[i3]
movsd ; store vertex coordinates
movsw
stosw ; middle vertex coordinate 'z' in triangles_with_z list
cmp dword[esi],-1
jne make_triangle_with_z
movsd ; copy end mark
mov eax,4
lea edx,[edi-8-trizdd]
mov [high],edx
call quicksort
mov eax,4
mov edx,[high]
call insertsort
jmp end_sort
 
quicksort:
mov ecx,edx
sub ecx,eax
cmp ecx,32
jc .exit
lea ecx,[eax+edx]
shr ecx,4
lea ecx,[ecx*8-4]; i
mov ebx,[trizdd+eax]; trizdd[l]
mov esi,[trizdd+ecx]; trizdd[i]
mov edi,[trizdd+edx]; trizdd[h]
cmp ebx,esi
jg @f ; direction NB! you need to negate these to invert the order
if Ext=NON
mov [trizdd+eax],esi
mov [trizdd+ecx],ebx
mov ebx,[trizdd+eax-4]
mov esi,[trizdd+ecx-4]
mov [trizdd+eax-4],esi
mov [trizdd+ecx-4],ebx
mov ebx,[trizdd+eax]
mov esi,[trizdd+ecx]
else
movq mm0,[trizdq+eax-4]
movq mm1,[trizdq+ecx-4]
movq [trizdq+ecx-4],mm0
movq [trizdq+eax-4],mm1
xchg ebx,esi
end if
@@:
cmp ebx,edi
jg @f ; direction
if Ext=NON
mov [trizdd+eax],edi
mov [trizdd+edx],ebx
mov ebx,[trizdd+eax-4]
mov edi,[trizdd+edx-4]
mov [trizdd+eax-4],edi
mov [trizdd+edx-4],ebx
mov ebx,[trizdd+eax]
mov edi,[trizdd+edx]
else
movq mm0,[trizdq+eax-4]
movq mm1,[trizdq+edx-4]
movq [trizdq+edx-4],mm0
movq [trizdq+eax-4],mm1
xchg ebx,edi
end if
@@:
cmp esi,edi
jg @f ; direction
if Ext=NON
mov [trizdd+ecx],edi
mov [trizdd+edx],esi
mov esi,[trizdd+ecx-4]
mov edi,[trizdd+edx-4]
mov [trizdd+ecx-4],edi
mov [trizdd+edx-4],esi
else
movq mm0,[trizdq+ecx-4]
movq mm1,[trizdq+edx-4]
movq [trizdq+edx-4],mm0
movq [trizdq+ecx-4],mm1
; xchg ebx,esi
end if
@@:
mov ebp,eax ; direction
add ebp,8 ; j
if Ext=NON
mov esi,[trizdd+ebp]
mov edi,[trizdd+ecx]
mov [trizdd+ebp],edi
mov [trizdd+ecx],esi
mov esi,[trizdd+ebp-4]
mov edi,[trizdd+ecx-4]
mov [trizdd+ecx-4],esi
mov [trizdd+ebp-4],edi
else
movq mm0,[trizdq+ebp-4]
movq mm1,[trizdq+ecx-4]
movq [trizdq+ecx-4],mm0
movq [trizdq+ebp-4],mm1
end if
mov ecx,edx ; i; direction
mov ebx,[trizdd+ebp]; trizdd[j]
.loop:
sub ecx,8 ; direction
cmp [trizdd+ecx],ebx
jl .loop ; direction
@@:
add ebp,8 ; direction
cmp [trizdd+ebp],ebx
jg @b ; direction
cmp ebp,ecx