; ; Функции нужные для отображения воксельного объекта через библиотеку tinygl ; normal_gran_z1 equ -1.0 normal_gran_z0 equ 1.0 normal_gran_y1 equ -1.0 normal_gran_y0 equ 1.0 normal_gran_x1 equ -1.0 normal_gran_x0 equ 1.0 ;марос коректировки вектора нормали для закругления крайних вокселей macro normal_gran param, gran { mov dword[param],0.0 bt dword[edi+vox_ogl_planes],vox_ogl_gran_#gran jnc @f mov dword[param],normal_gran_#gran @@: } ;марос коректировки вектора нормали для диагонального сглаживания вокселей ;диагональные воксели после этого сглаживания смотрятся не степеньками а сплошной плоскостью macro normal_gran_2 param, gran2, gran1 { bt dword[edi+vox_ogl_planes],vox_ogl_gran_#gran2 jnc @f mov dword[param],normal_gran_#gran1 ;поставить 0.0 в dword[param] если нужно не сильное сглаживание @@: } vox_ogl_x0 equ 0 vox_ogl_y0 equ 4 vox_ogl_z0 equ 8 vox_ogl_x1 equ 12 vox_ogl_y1 equ 16 vox_ogl_z1 equ 20 vox_ogl_color equ 24 vox_ogl_zoom equ 28 vox_ogl_planes equ 30 vox_ogl_size equ 34 def_del_planes equ 63 ;номера битов, которые указывают на то какие есть соседние воксели ;нужно для отсечения внутренних граней между соседними вокселями ;а еще нужно для задания векторов нормалей, что-бы воксели были сглаженными (закругленными) vox_ogl_gran_z1 equ 1 vox_ogl_gran_z0 equ 0 vox_ogl_gran_y1 equ 3 vox_ogl_gran_y0 equ 2 vox_ogl_gran_x1 equ 5 vox_ogl_gran_x0 equ 4 vox_ogl_gran_y1z1 equ 7 vox_ogl_gran_y0z0 equ 6 vox_ogl_gran_x1z1 equ 9 vox_ogl_gran_x0z0 equ 8 vox_ogl_gran_y0z1 equ 11 vox_ogl_gran_y1z0 equ 10 vox_ogl_gran_x0z1 equ 13 vox_ogl_gran_x1z0 equ 12 vox_ogl_gran_x1y1 equ 15 vox_ogl_gran_x0y0 equ 14 vox_ogl_gran_x0y1 equ 17 vox_ogl_gran_x1y0 equ 16 vox_offs_tree_table equ 4 vox_offs_data equ 12 ;description: ; создание воксельного объекта для показа в 3d графике ;input: align 4 proc buf_vox_obj_create_3d, v_obj:dword, p_mem:dword, coord_x:dword,\ coord_y:dword, k_scale:dword cmp [k_scale],0 jl .end_f pushad mov edi,[p_mem] mov dword[edi],0 ;count voxels mov ecx,[k_scale] mov ebx,[coord_x] mov edx,[coord_y] mov edi,[v_obj] add edi,vox_offs_data xor esi,esi stdcall create_sub_vox_obj_3d, [v_obj],[p_mem],[k_scale] ; (1) ; сортировка вокселей по координатам x,y,z ; mov edi,[p_mem] mov ecx,dword[edi] ;inc ecx add edi,4 sub edi,vox_ogl_size stdcall pole_fl_sort, edi, ecx ;отсечение соседних граней для ускорения отрисовки mov edi,[p_mem] mov ecx,dword[edi] dec ecx add edi,4 align 4 .cycle_0: mov ax,word[edi+vox_ogl_zoom] cmp ax,word[edi+vox_ogl_size+vox_ogl_zoom] jne @f mov eax,dword[edi+vox_ogl_x0] cmp eax,dword[edi+vox_ogl_size+vox_ogl_x0] jne @f mov eax,dword[edi+vox_ogl_y0] cmp eax,dword[edi+vox_ogl_size+vox_ogl_y0] jne @f mov eax,dword[edi+vox_ogl_z0] inc eax ;увеличиваем высоту, для будущего сравнения cmp eax,dword[edi+vox_ogl_size+vox_ogl_z0] jne @f ;если по высоте воксели различается на 1 координату, то соседние высоту и низ отсекаем btr dword[edi+vox_ogl_planes],vox_ogl_gran_z1 ;верх отсекаем btr dword[edi+vox_ogl_size+vox_ogl_planes],vox_ogl_gran_z0 ;низ отсекаем @@: add edi,vox_ogl_size loop .cycle_0 push ebx edx esi ;диагональные соседние воксели mov edi,[p_mem] mov ecx,dword[edi] dec ecx add edi,4 mov ebx,ecx ;inc ebx ;??? cmp esi,ebx -> jge @f imul ebx,vox_ogl_size add ebx,edi align 4 .cycle_3: mov dx,word[edi+vox_ogl_zoom] mov esi,edi align 4 .cycle_4: add esi,vox_ogl_size cmp esi,ebx jg @f cmp dx,word[esi+vox_ogl_zoom] jne .cycle_4 mov eax,dword[edi+vox_ogl_x0] cmp eax,dword[esi+vox_ogl_x0] jne @f mov eax,dword[edi+vox_ogl_y0] inc eax ; y+ cmp eax,dword[esi+vox_ogl_y0] jl @f jne .cycle_4 mov eax,dword[edi+vox_ogl_z0] inc eax ; z+ cmp eax,dword[esi+vox_ogl_z0] jne .cycle_4 ;если по высоте воксели различается на 1 координату bts dword[edi+vox_ogl_planes],vox_ogl_gran_y1z1 ; bts dword[esi+vox_ogl_planes],vox_ogl_gran_y0z0 ; @@: add edi,vox_ogl_size loop .cycle_3 ; *** mov edi,[p_mem] mov ecx,dword[edi] dec ecx add edi,4 align 4 .cycle_7: mov dx,word[edi+vox_ogl_zoom] mov esi,edi align 4 .cycle_8: add esi,vox_ogl_size cmp esi,ebx jg @f cmp dx,word[esi+vox_ogl_zoom] jne .cycle_8 mov eax,dword[edi+vox_ogl_x0] cmp eax,dword[esi+vox_ogl_x0] jne @f mov eax,dword[edi+vox_ogl_y0] inc eax ; y+ cmp eax,dword[esi+vox_ogl_y0] jl @f jne .cycle_8 mov eax,dword[edi+vox_ogl_z0] dec eax ; z- cmp eax,dword[esi+vox_ogl_z0] jne .cycle_8 ;если по высоте воксели различается на 1 координату bts dword[edi+vox_ogl_planes],vox_ogl_gran_y1z0 ; bts dword[esi+vox_ogl_planes],vox_ogl_gran_y0z1 ; @@: add edi,vox_ogl_size loop .cycle_7 pop esi edx ebx ; (2) ; сортировка вокселей по координатам x,z,y ; mov edi,[p_mem] mov ecx,dword[edi] add edi,4 sub edi,vox_ogl_size stdcall pole_fl_sort_zxy, edi, ecx ;отсечение соседних граней для ускорения отрисовки mov edi,[p_mem] mov ecx,dword[edi] dec ecx add edi,4 align 4 .cycle_1: mov ax,word[edi+vox_ogl_zoom] cmp ax,word[edi+vox_ogl_size+vox_ogl_zoom] jne @f mov eax,dword[edi+vox_ogl_z0] cmp eax,dword[edi+vox_ogl_size+vox_ogl_z0] jne @f mov eax,dword[edi+vox_ogl_x0] cmp eax,dword[edi+vox_ogl_size+vox_ogl_x0] jne @f mov eax,dword[edi+vox_ogl_y0] inc eax ;увеличиваем высоту, для будущего сравнения cmp eax,dword[edi+vox_ogl_size+vox_ogl_y0] jne @f ;если по высоте воксели различается на 1 координату, то соседние высоту и низ отсекаем btr dword[edi+vox_ogl_planes],vox_ogl_gran_y1 ;верх отсекаем btr dword[edi+vox_ogl_size+vox_ogl_planes],vox_ogl_gran_y0 ;низ отсекаем @@: add edi,vox_ogl_size loop .cycle_1 push ebx edx esi ;диагональные соседние воксели mov edi,[p_mem] mov ecx,dword[edi] dec ecx add edi,4 mov ebx,ecx ;inc ebx ;??? cmp esi,ebx -> jge @f imul ebx,vox_ogl_size add ebx,edi align 4 .cycle_11: mov dx,word[edi+vox_ogl_zoom] mov esi,edi align 4 .cycle_12: add esi,vox_ogl_size cmp esi,ebx jg @f cmp dx,word[esi+vox_ogl_zoom] jne .cycle_12 mov eax,dword[edi+vox_ogl_z0] cmp eax,dword[esi+vox_ogl_z0] jne @f mov eax,dword[edi+vox_ogl_x0] inc eax ; x+ cmp eax,dword[esi+vox_ogl_x0] jl @f jne .cycle_12 mov eax,dword[edi+vox_ogl_y0] inc eax ; y+ cmp eax,dword[esi+vox_ogl_y0] jne .cycle_12 ;если по высоте воксели различается на 1 координату bts dword[edi+vox_ogl_planes],vox_ogl_gran_x1y1 ; bts dword[esi+vox_ogl_planes],vox_ogl_gran_x0y0 ; @@: add edi,vox_ogl_size loop .cycle_11 ; *** mov edi,[p_mem] mov ecx,dword[edi] dec ecx add edi,4 align 4 .cycle_15: mov dx,word[edi+vox_ogl_zoom] mov esi,edi align 4 .cycle_16: add esi,vox_ogl_size cmp esi,ebx jg @f cmp dx,word[esi+vox_ogl_zoom] jne .cycle_16 mov eax,dword[edi+vox_ogl_z0] cmp eax,dword[esi+vox_ogl_z0] jne @f mov eax,dword[edi+vox_ogl_x0] inc eax ; x+ cmp eax,dword[esi+vox_ogl_x0] jl @f jne .cycle_16 mov eax,dword[edi+vox_ogl_y0] dec eax ; y- cmp eax,dword[esi+vox_ogl_y0] jne .cycle_16 ;если по высоте воксели различается на 1 координату bts dword[edi+vox_ogl_planes],vox_ogl_gran_x1y0 ; bts dword[esi+vox_ogl_planes],vox_ogl_gran_x0y1 ; @@: add edi,vox_ogl_size loop .cycle_15 pop esi edx ebx ; (3) ; сортировка вокселей по координатам y,z,x ; mov edi,[p_mem] mov ecx,dword[edi] add edi,4 sub edi,vox_ogl_size stdcall pole_fl_sort_yzx, edi, ecx ;отсечение соседних граней для ускорения отрисовки mov edi,[p_mem] mov ecx,dword[edi] dec ecx add edi,4 align 4 .cycle_2: mov ax,word[edi+vox_ogl_zoom] cmp ax,word[edi+vox_ogl_size+vox_ogl_zoom] jne @f mov eax,dword[edi+vox_ogl_y0] cmp eax,dword[edi+vox_ogl_size+vox_ogl_y0] jne @f mov eax,dword[edi+vox_ogl_z0] cmp eax,dword[edi+vox_ogl_size+vox_ogl_z0] jne @f mov eax,dword[edi+vox_ogl_x0] inc eax ;увеличиваем высоту, для будущего сравнения cmp eax,dword[edi+vox_ogl_size+vox_ogl_x0] jne @f ;если по высоте воксели различается на 1 координату, то соседние высоту и низ отсекаем btr dword[edi+vox_ogl_planes],vox_ogl_gran_x1 ;верх отсекаем btr dword[edi+vox_ogl_size+vox_ogl_planes],vox_ogl_gran_x0 ;низ отсекаем @@: add edi,vox_ogl_size loop .cycle_2 push ebx edx esi ;диагональные соседние воксели mov edi,[p_mem] mov ecx,dword[edi] dec ecx add edi,4 mov ebx,ecx ;inc ebx ;??? cmp esi,ebx -> jge @f imul ebx,vox_ogl_size add ebx,edi align 4 .cycle_5: mov dx,word[edi+vox_ogl_zoom] mov esi,edi align 4 .cycle_6: add esi,vox_ogl_size cmp esi,ebx jg @f cmp dx,word[esi+vox_ogl_zoom] jne .cycle_6 mov eax,dword[edi+vox_ogl_y0] cmp eax,dword[esi+vox_ogl_y0] jne @f mov eax,dword[edi+vox_ogl_z0] inc eax ; z+ cmp eax,dword[esi+vox_ogl_z0] jl @f jne .cycle_6 mov eax,dword[edi+vox_ogl_x0] inc eax ; x+ cmp eax,dword[esi+vox_ogl_x0] jne .cycle_6 ;если по высоте воксели различается на 1 координату bts dword[edi+vox_ogl_planes],vox_ogl_gran_x1z1 ; bts dword[esi+vox_ogl_planes],vox_ogl_gran_x0z0 ; @@: add edi,vox_ogl_size loop .cycle_5 ; *** mov edi,[p_mem] mov ecx,dword[edi] dec ecx add edi,4 align 4 .cycle_9: mov dx,word[edi+vox_ogl_zoom] mov esi,edi align 4 .cycle_10: add esi,vox_ogl_size cmp esi,ebx jg @f cmp dx,word[esi+vox_ogl_zoom] jne .cycle_10 mov eax,dword[edi+vox_ogl_y0] cmp eax,dword[esi+vox_ogl_y0] jne @f mov eax,dword[edi+vox_ogl_z0] inc eax ; z+ cmp eax,dword[esi+vox_ogl_z0] jl @f jne .cycle_10 mov eax,dword[edi+vox_ogl_x0] dec eax ; x- cmp eax,dword[esi+vox_ogl_x0] jne .cycle_10 ;если по высоте воксели различается на 1 координату bts dword[edi+vox_ogl_planes],vox_ogl_gran_x0z1 ; bts dword[esi+vox_ogl_planes],vox_ogl_gran_x1z0 ; @@: add edi,vox_ogl_size loop .cycle_9 pop esi edx ebx ;преобразование координат во float stdcall vox_obj_3d_recalc, [p_mem] popad .end_f: ret endp ;input: ; ebx - coord_x ; edx - coord_y ; esi - coord_z ; ecx - уровень текушего узла ; edi - указатель на данные воксельного объекта align 4 proc create_sub_vox_obj_3d, v_obj:dword, p_mem:dword, k_scale:dword cmp byte[edi+3],0 ;смотрим есть ли поддеревья je .sub_trees ;добавляем узел, который содержит дочерние узлы, при этом дочерние мелкие и не попадают на вывод cmp ecx,0 jne @f push ecx mov eax,[p_mem] inc dword[eax] ;увеличиваем счетчик вокселей на 1 mov eax,[eax] imul eax,vox_ogl_size ;умножаем на размер данных о вокселе add eax,4-vox_ogl_size ;число вокселей 4 байта add eax,[p_mem] mov [eax+vox_ogl_x0],ebx mov [eax+vox_ogl_y0],edx mov [eax+vox_ogl_z0],esi sub ecx,[k_scale] mov word[eax+vox_ogl_zoom],cx mov dword[eax+vox_ogl_planes],def_del_planes mov ecx,dword[edi] and ecx,0xffffff mov [eax+vox_ogl_color],ecx pop ecx @@: ;рекурсивный перебор поддеревьев push edx ;вход внутрь узла dec ecx mov eax,1 cmp ecx,1 jl @f shl eax,cl @@: add edx,eax ;коректировка высоты под воксель нижнего уровня mov ah,byte[edi+3] add edi,4 mov al,8 .cycle: bt ax,8 ;тестируем только ah jnc .c_next push eax ebx edx esi stdcall vox_corect_coords_pl, [v_obj],1 stdcall create_sub_vox_obj_3d, [v_obj], [p_mem],[k_scale] pop esi edx ebx eax .c_next: shr ah,1 dec al jnz .cycle ;выход из узла inc ecx pop edx jmp .end_f .sub_trees: cmp ecx,0 jl .end_0 ;не рисуем очень маленькие воксели ;cmp ecx,1 ;jl @f ;квадрат больше текущего масштаба ;stdcall vox_draw_square_1g, [buf_i],[buf_z],eax ;jmp .end_0 ;@@: ;квадрат текущего масштаба push ecx mov eax,[p_mem] inc dword[eax] ;увеличиваем счетчик вокселей на 1 mov eax,[eax] imul eax,vox_ogl_size ;умножаем на размер данных о вокселе add eax,4-vox_ogl_size ;число вокселей 4 байта add eax,[p_mem] mov [eax+vox_ogl_x0],ebx mov [eax+vox_ogl_y0],edx mov [eax+vox_ogl_z0],esi cmp ecx,1 jl @f ;квадрат больше текущего масштаба shr dword[eax+vox_ogl_x0],cl shr dword[eax+vox_ogl_y0],cl shr dword[eax+vox_ogl_z0],cl @@: sub ecx,[k_scale] mov word[eax+vox_ogl_zoom],cx mov dword[eax+vox_ogl_planes],def_del_planes mov ecx,dword[edi] and ecx,0xffffff mov [eax+vox_ogl_color],ecx pop ecx .end_0: add edi,4 .end_f: ret endp ;description: ; в OpenGL требуются координаты float ; преобразование координат из int во float, align 4 proc vox_obj_3d_recalc uses eax ebx ecx, p_mem:dword ;получаем координаты в пределах от 0 до 1 в дробном виде mov eax,[p_mem] mov ecx,dword[eax] add eax,4 finit align 4 @@: fild word[eax+vox_ogl_zoom] fld1 ; размер кубической грани без учета масштаба fscale ; st0=1*2^st1 или размер кубической грани с учетом масштаба fxch ;coord x fild dword[eax+vox_ogl_x0] fscale fst dword[eax+vox_ogl_x0] fadd st0,st2 ;добавляем ко второй точке размер масштабированной кубической грани fstp dword[eax+vox_ogl_x1] ;coord y fild dword[eax+vox_ogl_y0] fscale fst dword[eax+vox_ogl_y0] fadd st0,st2 fstp dword[eax+vox_ogl_y1] ;coord z fild dword[eax+vox_ogl_z0] fscale fst dword[eax+vox_ogl_z0] fadd st0,st2 fstp dword[eax+vox_ogl_z1] ;goto next voxel add eax,vox_ogl_size ffree st0 fincstp ffree st0 fincstp loop @b ;отнимаем от каждой координаты по 0.5 для центровки объекта по центру экрана mov eax,[p_mem] mov ecx,dword[eax] add eax,4 fld1 ;st0=1 fchs ;st0=-1 fld1 ;st0=1 st1=-1 fscale ;st0=1*2^st1 или 1*2^-1=1/2=0.5 align 4 @@: ;coord x fld dword[eax+vox_ogl_x0] fsub st0,st1 ;-0.5 fstp dword[eax+vox_ogl_x0] fld dword[eax+vox_ogl_x1] fsub st0,st1 ;-0.5 fstp dword[eax+vox_ogl_x1] ;coord y fld dword[eax+vox_ogl_y0] fsub st0,st1 ;-0.5 fstp dword[eax+vox_ogl_y0] fld dword[eax+vox_ogl_y1] fsub st0,st1 ;-0.5 fstp dword[eax+vox_ogl_y1] ;coord z fld dword[eax+vox_ogl_z0] fsub st0,st1 ;-0.5 fstp dword[eax+vox_ogl_z0] fld dword[eax+vox_ogl_z1] fsub st0,st1 ;-0.5 fstp dword[eax+vox_ogl_z1] ;goto next voxel add eax,vox_ogl_size loop @b ffree st0 fincstp ffree st0 fincstp ret endp ;Сортировка вектора a[1..n] методом Флойда align 4 proc pole_fl_sort, a:dword, n:dword pushad mov ecx,dword[a] ;Формировать исходное частично упорядоченное дерево mov eax,dword[n] shr eax,1 @@: ;for(i=n/2; i>=2; i--) stdcall pole_fl_surface, ecx,eax,[n] ;(a,i,n) dec eax cmp eax,2 jge @b ;Выполнить процедуру всплытия Флойда для каждого поддерева mov eax,dword[n] @@: ;for(i=n; i>=2; i--){ stdcall pole_fl_surface, ecx,1,eax ;(a,1,i) ;Поместить найденный максимальный элемент в конец списка stdcall swap_cell, ecx,1,eax ;меняем местами a[1] <-> a[i] dec eax cmp eax,2 jge @b popad ret endp ;Процедура всплытия Флойда по дереву a[1..k] align 4 proc pole_fl_surface, a:dword, i:dword, k:dword pushad ;edx -> ... ;edi -> m ;esi -> j mov eax,dword[a] mov ebx,dword[i] mov ecx,dword[k] stdcall copy_cell, eax, -1,ebx ;copy=a[i]; mov edi,ebx shl edi,1 ;m=2*i где edi=m .cycle_b: ;while (m<=k) { cmp edi,ecx jg .cycle_e jne @f ;if (m==k) j=m; mov esi,edi jmp .else_e @@: ;else if (pole_compare_cells_bm(a[m],a[m+1])) j=m; mov edx,edi inc edx stdcall pole_compare_cells_bm, eax, edi,edx cmp dl,0 je @f mov esi,edi jmp .else_e @@: ;else j=m+1; mov esi,edi inc esi .else_e: ;if (pole_compare_cells_bm(a[j],copy)) { stdcall pole_compare_cells_bm, eax, esi,-1 cmp dl,0 je .cycle_e ;} else break; //выход из цикла stdcall copy_cell, eax, ebx,esi ;a[i]=a[j]; mov ebx,esi ;i=j; mov edi,ebx shl edi,1 ;m=2*i; jmp .cycle_b .cycle_e: ;значения многих регистров уже не важны т. к. конец функции stdcall copy_cell, eax, ebx,-1 ;a[i]=copy; popad ret endp ;output: ; dl align 4 proc pole_compare_cells_bm uses eax ebx ecx, p_mem:dword, i0:dword, i1:dword mov eax,[i0] ;eax -> cell[i0] imul eax,vox_ogl_size add eax,[p_mem] mov ebx,[i1] ;ebx -> cell[i1] cmp ebx,0 jl .copy imul ebx,vox_ogl_size add ebx,[p_mem] jmp @f .copy: mov ebx,mem_copy_32 @@: mov cx,word[ebx+vox_ogl_zoom] ;zoom cmp word[eax+vox_ogl_zoom],cx jle @f ;zoom0>zoom1 mov dl,1 jmp .fun_e @@: jne .r_0 ;if zoom0<zoom1 return 0 mov ecx,dword[ebx+vox_ogl_x0] ;coord x cmp dword[eax+vox_ogl_x0],ecx jle @f ;x0>x1 mov dl,1 jmp .fun_e @@: jne .r_0 ;if x0<x1 return 0 mov ecx,dword[ebx+vox_ogl_y0] ;coord y cmp dword[eax+vox_ogl_y0],ecx jle @f ;y0>y1 mov dl,1 jmp .fun_e @@: jne .r_0 ;if y0<y1 return 0 mov ecx,dword[ebx+vox_ogl_z0] ;coord z cmp dword[eax+vox_ogl_z0],ecx jle @f ;z0>z1 mov dl,1 jmp .fun_e @@: .r_0: xor dl,dl .fun_e: ret endp if 0 ;пока не нужно, но работало правильно ;Сортировка вектора a[1..n] методом Флойда align 4 proc pole_fl_sort_xzy, a:dword, n:dword pushad mov ecx,dword[a] ;Формировать исходное частично упорядоченное дерево mov eax,dword[n] shr eax,1 @@: ;for(i=n/2; i>=2; i--) stdcall pole_fl_surface_xzy, ecx,eax,[n] ;(a,i,n) dec eax cmp eax,2 jge @b ;Выполнить процедуру всплытия Флойда для каждого поддерева mov eax,dword[n] @@: ;for(i=n; i>=2; i--){ stdcall pole_fl_surface_xzy, ecx,1,eax ;(a,1,i) ;Поместить найденный максимальный элемент в конец списка stdcall swap_cell, ecx,1,eax ;меняем местами a[1] <-> a[i] dec eax cmp eax,2 jge @b popad ret endp ;Процедура всплытия Флойда по дереву a[1..k] align 4 proc pole_fl_surface_xzy, a:dword, i:dword, k:dword pushad ;edx -> ... ;edi -> m ;esi -> j mov eax,dword[a] mov ebx,dword[i] mov ecx,dword[k] stdcall copy_cell, eax, -1,ebx ;copy=a[i]; mov edi,ebx shl edi,1 ;m=2*i где edi=m .cycle_b: ;while (m<=k) { cmp edi,ecx jg .cycle_e jne @f ;if (m==k) j=m; mov esi,edi jmp .else_e @@: ;else if (pole_compare_bm_xzy(a[m],a[m+1])) j=m; mov edx,edi inc edx stdcall pole_compare_bm_xzy, eax, edi,edx cmp dl,0 je @f mov esi,edi jmp .else_e @@: ;else j=m+1; mov esi,edi inc esi .else_e: ;if (pole_compare_bm_xzy(a[j],copy)) { stdcall pole_compare_bm_xzy, eax, esi,-1 cmp dl,0 je .cycle_e ;} else break; //выход из цикла stdcall copy_cell, eax, ebx,esi ;a[i]=a[j]; mov ebx,esi ;i=j; mov edi,ebx shl edi,1 ;m=2*i; jmp .cycle_b .cycle_e: ;значения многих регистров уже не важны т. к. конец функции stdcall copy_cell, eax, ebx,-1 ;a[i]=copy; popad ret endp ;output: ; dl align 4 proc pole_compare_bm_xzy uses eax ebx ecx, p_mem:dword, i0:dword, i1:dword mov eax,[i0] ;eax -> cell[i0] imul eax,vox_ogl_size add eax,[p_mem] mov ebx,[i1] ;ebx -> cell[i1] cmp ebx,0 jl .copy imul ebx,vox_ogl_size add ebx,[p_mem] jmp @f .copy: mov ebx,mem_copy_32 @@: mov cx,word[ebx+vox_ogl_zoom] ;zoom cmp word[eax+vox_ogl_zoom],cx jle @f ;zoom0>zoom1 mov dl,1 jmp .fun_e @@: jne .r_0 ;if zoom0<zoom1 return 0 mov ecx,dword[ebx+vox_ogl_x0] ;coord x cmp dword[eax+vox_ogl_x0],ecx jle @f ;x0>x1 mov dl,1 jmp .fun_e @@: jne .r_0 ;if x0<x1 return 0 mov ecx,dword[ebx+vox_ogl_z0] ;coord z cmp dword[eax+vox_ogl_z0],ecx jle @f ;z0>z1 mov dl,1 jmp .fun_e @@: jne .r_0 ;if z0<z1 return 0 mov ecx,dword[ebx+vox_ogl_y0] ;coord y cmp dword[eax+vox_ogl_y0],ecx jle @f ;y0>y1 mov dl,1 jmp .fun_e @@: .r_0: xor dl,dl .fun_e: ret endp end if ;Сортировка вектора a[1..n] методом Флойда align 4 proc pole_fl_sort_zxy, a:dword, n:dword pushad mov ecx,dword[a] ;Формировать исходное частично упорядоченное дерево mov eax,dword[n] shr eax,1 @@: ;for(i=n/2; i>=2; i--) stdcall pole_fl_surface_zxy, ecx,eax,[n] ;(a,i,n) dec eax cmp eax,2 jge @b ;Выполнить процедуру всплытия Флойда для каждого поддерева mov eax,dword[n] @@: ;for(i=n; i>=2; i--){ stdcall pole_fl_surface_zxy, ecx,1,eax ;(a,1,i) ;Поместить найденный максимальный элемент в конец списка stdcall swap_cell, ecx,1,eax ;меняем местами a[1] <-> a[i] dec eax cmp eax,2 jge @b popad ret endp ;Процедура всплытия Флойда по дереву a[1..k] align 4 proc pole_fl_surface_zxy, a:dword, i:dword, k:dword pushad ;edx -> ... ;edi -> m ;esi -> j mov eax,dword[a] mov ebx,dword[i] mov ecx,dword[k] stdcall copy_cell, eax, -1,ebx ;copy=a[i]; mov edi,ebx shl edi,1 ;m=2*i где edi=m .cycle_b: ;while (m<=k) { cmp edi,ecx jg .cycle_e jne @f ;if (m==k) j=m; mov esi,edi jmp .else_e @@: ;else if (pole_compare_bm_xzy(a[m],a[m+1])) j=m; mov edx,edi inc edx stdcall pole_compare_bm_zxy, eax, edi,edx cmp dl,0 je @f mov esi,edi jmp .else_e @@: ;else j=m+1; mov esi,edi inc esi .else_e: ;if (pole_compare_bm_xzy(a[j],copy)) { stdcall pole_compare_bm_zxy, eax, esi,-1 cmp dl,0 je .cycle_e ;} else break; //выход из цикла stdcall copy_cell, eax, ebx,esi ;a[i]=a[j]; mov ebx,esi ;i=j; mov edi,ebx shl edi,1 ;m=2*i; jmp .cycle_b .cycle_e: ;значения многих регистров уже не важны т. к. конец функции stdcall copy_cell, eax, ebx,-1 ;a[i]=copy; popad ret endp ;output: ; dl align 4 proc pole_compare_bm_zxy uses eax ebx ecx, p_mem:dword, i0:dword, i1:dword mov eax,[i0] ;eax -> cell[i0] imul eax,vox_ogl_size add eax,[p_mem] mov ebx,[i1] ;ebx -> cell[i1] cmp ebx,0 jl .copy imul ebx,vox_ogl_size add ebx,[p_mem] jmp @f .copy: mov ebx,mem_copy_32 @@: mov cx,word[ebx+vox_ogl_zoom] ;zoom cmp word[eax+vox_ogl_zoom],cx jle @f ;zoom0>zoom1 mov dl,1 jmp .fun_e @@: jne .r_0 ;if zoom0<zoom1 return 0 mov ecx,dword[ebx+vox_ogl_z0] ;coord z cmp dword[eax+vox_ogl_z0],ecx jle @f ;z0>z1 mov dl,1 jmp .fun_e @@: jne .r_0 ;if z0<z1 return 0 mov ecx,dword[ebx+vox_ogl_x0] ;coord x cmp dword[eax+vox_ogl_x0],ecx jle @f ;x0>x1 mov dl,1 jmp .fun_e @@: jne .r_0 ;if x0<x1 return 0 mov ecx,dword[ebx+vox_ogl_y0] ;coord y cmp dword[eax+vox_ogl_y0],ecx jle @f ;y0>y1 mov dl,1 jmp .fun_e @@: .r_0: xor dl,dl .fun_e: ret endp ;Сортировка вектора a[1..n] методом Флойда align 4 proc pole_fl_sort_yzx, a:dword, n:dword pushad mov ecx,dword[a] ;Формировать исходное частично упорядоченное дерево mov eax,dword[n] shr eax,1 @@: ;for(i=n/2; i>=2; i--) stdcall pole_fl_surface_yzx, ecx,eax,[n] ;(a,i,n) dec eax cmp eax,2 jge @b ;Выполнить процедуру всплытия Флойда для каждого поддерева mov eax,dword[n] @@: ;for(i=n; i>=2; i--){ stdcall pole_fl_surface_yzx, ecx,1,eax ;(a,1,i) ;Поместить найденный максимальный элемент в конец списка stdcall swap_cell, ecx,1,eax ;меняем местами a[1] <-> a[i] dec eax cmp eax,2 jge @b popad ret endp ;Процедура всплытия Флойда по дереву a[1..k] align 4 proc pole_fl_surface_yzx, a:dword, i:dword, k:dword pushad ;edx -> ... ;edi -> m ;esi -> j mov eax,dword[a] mov ebx,dword[i] mov ecx,dword[k] stdcall copy_cell, eax, -1,ebx ;copy=a[i]; mov edi,ebx shl edi,1 ;m=2*i где edi=m .cycle_b: ;while (m<=k) { cmp edi,ecx jg .cycle_e jne @f ;if (m==k) j=m; mov esi,edi jmp .else_e @@: ;else if (pole_compare_bm_yzx(a[m],a[m+1])) j=m; mov edx,edi inc edx stdcall pole_compare_bm_yzx, eax, edi,edx cmp dl,0 je @f mov esi,edi jmp .else_e @@: ;else j=m+1; mov esi,edi inc esi .else_e: ;if (pole_compare_bm_yzx(a[j],copy)) { stdcall pole_compare_bm_yzx, eax, esi,-1 cmp dl,0 je .cycle_e ;} else break; //выход из цикла stdcall copy_cell, eax, ebx,esi ;a[i]=a[j]; mov ebx,esi ;i=j; mov edi,ebx shl edi,1 ;m=2*i; jmp .cycle_b .cycle_e: ;значения многих регистров уже не важны т. к. конец функции stdcall copy_cell, eax, ebx,-1 ;a[i]=copy; popad ret endp ;output: ; dl align 4 proc pole_compare_bm_yzx uses eax ebx ecx, p_mem:dword, i0:dword, i1:dword mov eax,[i0] ;eax -> cell[i0] imul eax,vox_ogl_size add eax,[p_mem] mov ebx,[i1] ;ebx -> cell[i1] cmp ebx,0 jl .copy imul ebx,vox_ogl_size add ebx,[p_mem] jmp @f .copy: mov ebx,mem_copy_32 @@: mov cx,word[ebx+vox_ogl_zoom] ;zoom cmp word[eax+vox_ogl_zoom],cx jle @f ;zoom0>zoom1 mov dl,1 jmp .fun_e @@: jne .r_0 ;if zoom0<zoom1 return 0 mov ecx,dword[ebx+vox_ogl_y0] ;coord y cmp dword[eax+vox_ogl_y0],ecx jle @f ;y0>y1 mov dl,1 jmp .fun_e @@: jne .r_0 ;if y0<y1 return 0 mov ecx,dword[ebx+vox_ogl_z0] ;coord z cmp dword[eax+vox_ogl_z0],ecx jle @f ;z0>z1 mov dl,1 jmp .fun_e @@: jne .r_0 ;if z0<z1 return 0 mov ecx,dword[ebx+vox_ogl_x0] ;coord x cmp dword[eax+vox_ogl_x0],ecx jle @f ;x0>x1 mov dl,1 jmp .fun_e @@: .r_0: xor dl,dl .fun_e: ret endp align 4 proc copy_cell uses ecx edi esi, p_mem:dword, i0:dword, i1:dword mov esi,[i1] cmp esi,0 jl .copy_0 imul esi,vox_ogl_size add esi,[p_mem] jmp @f .copy_0: mov esi,mem_copy_32 @@: mov edi,[i0] cmp edi,0 jl .copy_1 imul edi,vox_ogl_size add edi,[p_mem] jmp @f .copy_1: mov edi,mem_copy_32 @@: if vox_ogl_size eq 34 mov ecx,8 ;ecx=32/4 cld rep movsd movsw else vox_ogl_size не равно 34 ! end if ret endp align 4 proc swap_cell uses eax ebx ecx edi esi, p_mem:dword, i0:dword, i1:dword mov esi,[i0] imul esi,vox_ogl_size add esi,[p_mem] mov edi,[i1] imul edi,vox_ogl_size add edi,[p_mem] if vox_ogl_size eq 34 ;vox_ogl_size = 34 = 32 + 2 mov ecx,8 ;ecx=32/4 cld @@: mov eax,dword[edi] mov ebx,dword[esi] mov dword[edi],ebx mov dword[esi],eax add esi,4 add edi,4 loop @b mov ax,word[edi] mov bx,word[esi] mov word[edi],bx mov word[esi],ax else vox_ogl_size не равно 34 ! end if ret endp align 4 mem_copy_32 rb vox_ogl_size ;функция для коректировки координат ;направления осей координат в вокселе: ;*z ;| ;+-* x ;input: ; al - номер узла в дереве (от 1 до 8) ; ebx - координата x ; edx - координата y ; esi - координата z ; ecx - уровень текушего узла ;output: ; ebx - новая координата x ; edx - новая координата y ; esi - новая координата z align 4 proc vox_corect_coords_pl, v_obj:dword, v_size:dword cmp ecx,0 jl .end_f ;для ускорения отрисовки push eax edi and eax,15 ;выделяем номер узла в дереве mov edi,[v_obj] add edi,vox_offs_tree_table add edi,8 sub edi,eax mov eax,[v_size] cmp ecx,1 jl @f shl eax,cl @@: bt word[edi],0 ;test voxel coord x jnc @f add ebx,eax @@: bt word[edi],2 ;test voxel coord z jnc @f sub edx,eax @@: bt word[edi],1 ;test voxel coord y jc @f mov eax,1 cmp ecx,1 jl .end_0 shl eax,cl .end_0: add esi,eax ;меняем глубину для буфера z @@: pop edi eax .end_f: ret endp align 4 p1 dd ? p2 dd ? align 4 proc draw_voxels_3d uses ebx ecx edx edi, p_mem:dword locals v_count dd ? endl mov edi,[p_mem] cmp edi,0 je .end_f mov eax,dword[edi] mov dword[v_count],eax add edi,4 bt word[opt_cube_box],0 jnc @f ;рисование рамки stdcall [glColor3ub],128,128,128 stdcall [glBegin],GL_LINE_STRIP stdcall [glVertex3f], -0.5, -0.5, -0.5 stdcall [glVertex3f], -0.5, 0.5, -0.5 stdcall [glVertex3f], 0.5, 0.5, -0.5 stdcall [glVertex3f], 0.5, -0.5, -0.5 stdcall [glVertex3f], -0.5, -0.5, -0.5 stdcall [glVertex3f], -0.5, -0.5, 0.5 stdcall [glVertex3f], -0.5, 0.5, 0.5 stdcall [glVertex3f], 0.5, 0.5, 0.5 stdcall [glVertex3f], 0.5, -0.5, 0.5 stdcall [glVertex3f], -0.5, -0.5, 0.5 stdcall [glEnd] stdcall [glBegin],GL_LINES stdcall [glVertex3f], -0.5, 0.5, -0.5 stdcall [glVertex3f], -0.5, 0.5, 0.5 stdcall [glVertex3f], 0.5, 0.5, -0.5 stdcall [glVertex3f], 0.5, 0.5, 0.5 stdcall [glVertex3f], 0.5, -0.5, -0.5 stdcall [glVertex3f], 0.5, -0.5, 0.5 stdcall [glEnd] @@: ;рисование объекта stdcall [glBegin],GL_QUADS .cycle_0: cmp dword[v_count],1 jl .cycle_1 stdcall [glColor3ub],[edi+vox_ogl_color+2],[edi+vox_ogl_color+1],[edi+vox_ogl_color] bt word[edi+vox_ogl_planes],vox_ogl_gran_z1 jnc .e_gran_z1 ;передняя грань Normal(0.0,0.0,normal_gran_z1) normal_gran p1,x0 normal_gran_2 p1,x0z1,x1 normal_gran p2,y0 normal_gran_2 p2,y0z1,y1 stdcall [glNormal3f], [p1],[p2],normal_gran_z1 stdcall [glVertex3f],[edi+vox_ogl_x0],[edi+vox_ogl_y0],[edi+vox_ogl_z1] normal_gran p1,x1 normal_gran_2 p1,x1z1,x0 ;normal_gran p2,y0 ;normal_gran_2 p2,y0z1,y1 stdcall [glNormal3f], [p1],[p2],normal_gran_z1 stdcall [glVertex3f],[edi+vox_ogl_x1],[edi+vox_ogl_y0],[edi+vox_ogl_z1] ;normal_gran p1,x1 ;normal_gran_2 p1,x1z1,x0 normal_gran p2,y1 normal_gran_2 p2,y1z1,y0 stdcall [glNormal3f], [p1],[p2],normal_gran_z1 stdcall [glVertex3f],[edi+vox_ogl_x1],[edi+vox_ogl_y1],[edi+vox_ogl_z1] normal_gran p1,x0 normal_gran_2 p1,x0z1,x1 ;normal_gran p2,y1 ;normal_gran_2 p2,y1z1,y0 stdcall [glNormal3f], [p1],[p2],normal_gran_z1 stdcall [glVertex3f],[edi+vox_ogl_x0],[edi+vox_ogl_y1],[edi+vox_ogl_z1] .e_gran_z1: bt word[edi+vox_ogl_planes],vox_ogl_gran_y0 jnc .e_gran_y0 ;верхняя грань Normal(0.0,normal_gran_y0,0.0) normal_gran p1,x0 normal_gran_2 p1,x0y0,x1 normal_gran p2,z0 normal_gran_2 p2,y0z0,z1 stdcall [glNormal3f], [p1],normal_gran_y0,[p2] stdcall [glVertex3f],[edi+vox_ogl_x0],[edi+vox_ogl_y0],[edi+vox_ogl_z0] normal_gran p1,x1 normal_gran_2 p1,x1y0,x0 ;normal_gran p2,z0 ;normal_gran_2 p2,y0z0,z1 stdcall [glNormal3f], [p1],normal_gran_y0,[p2] stdcall [glVertex3f],[edi+vox_ogl_x1],[edi+vox_ogl_y0],[edi+vox_ogl_z0] ;normal_gran p1,x1 ;normal_gran_2 p1,x1y0,x0 normal_gran p2,z1 normal_gran_2 p2,y0z1,z0 stdcall [glNormal3f], [p1],normal_gran_y0,[p2] stdcall [glVertex3f],[edi+vox_ogl_x1],[edi+vox_ogl_y0],[edi+vox_ogl_z1] normal_gran p1,x0 normal_gran_2 p1,x0y0,x1 ;normal_gran p2,z1 ;normal_gran_2 p2,y0z1,z0 stdcall [glNormal3f], [p1],normal_gran_y0,[p2] stdcall [glVertex3f],[edi+vox_ogl_x0],[edi+vox_ogl_y0],[edi+vox_ogl_z1] .e_gran_y0: bt word[edi+vox_ogl_planes],vox_ogl_gran_y1 jnc .e_gran_y1 ;нижняя грань Normal(0.0,normal_gran_y1,0.0) normal_gran p1,x0 normal_gran_2 p1,x0y1,x1 normal_gran p2,z1 normal_gran_2 p2,y1z1,z0 stdcall [glNormal3f], [p1],normal_gran_y1,[p2] stdcall [glVertex3f],[edi+vox_ogl_x0],[edi+vox_ogl_y1],[edi+vox_ogl_z1] normal_gran p1,x1 normal_gran_2 p1,x1y1,x0 ;normal_gran p2,z1 ;normal_gran_2 p2,y1z1,z0 stdcall [glNormal3f], [p1],normal_gran_y1,[p2] stdcall [glVertex3f],[edi+vox_ogl_x1],[edi+vox_ogl_y1],[edi+vox_ogl_z1] ;normal_gran p1,x1 ;normal_gran_2 p1,x1y1,x0 normal_gran p2,z0 normal_gran_2 p2,y1z0,z1 stdcall [glNormal3f], [p1],normal_gran_y1,[p2] stdcall [glVertex3f],[edi+vox_ogl_x1],[edi+vox_ogl_y1],[edi+vox_ogl_z0] normal_gran p1,x0 normal_gran_2 p1,x0y1,x1 ;normal_gran p2,z0 ;normal_gran_2 p2,y1z0,z1 stdcall [glNormal3f], [p1],normal_gran_y1,[p2] stdcall [glVertex3f],[edi+vox_ogl_x0],[edi+vox_ogl_y1],[edi+vox_ogl_z0] .e_gran_y1: bt word[edi+vox_ogl_planes],vox_ogl_gran_x0 jnc .e_gran_x0 ;левая грань Normal(normal_gran_x0,0.0,0.0) normal_gran p1,y0 normal_gran_2 p1,x0y0,y1 normal_gran p2,z1 normal_gran_2 p2,x0z1,z0 stdcall [glNormal3f], normal_gran_x0,[p1],[p2] stdcall [glVertex3f],[edi+vox_ogl_x0],[edi+vox_ogl_y0],[edi+vox_ogl_z1] normal_gran p1,y1 normal_gran_2 p1,x0y1,y0 ;normal_gran p2,z1 ;normal_gran_2 p2,x0z1,z0 stdcall [glNormal3f], normal_gran_x0,[p1],[p2] stdcall [glVertex3f],[edi+vox_ogl_x0],[edi+vox_ogl_y1],[edi+vox_ogl_z1] ;normal_gran p1,y1 ;normal_gran_2 p1,x0y1,y0 normal_gran p2,z0 normal_gran_2 p2,x0z0,z1 stdcall [glNormal3f], normal_gran_x0,[p1],[p2] stdcall [glVertex3f],[edi+vox_ogl_x0],[edi+vox_ogl_y1],[edi+vox_ogl_z0] normal_gran p1,y0 normal_gran_2 p1,x0y0,y1 ;normal_gran p2,z0 ;normal_gran_2 p2,x0z0,z1 stdcall [glNormal3f], normal_gran_x0,[p1],[p2] stdcall [glVertex3f],[edi+vox_ogl_x0],[edi+vox_ogl_y0],[edi+vox_ogl_z0] .e_gran_x0: bt word[edi+vox_ogl_planes],vox_ogl_gran_x1 jnc .e_gran_x1 ;правая грань Normal(normal_gran_x1,0.0,0.0) normal_gran p1,y0 normal_gran_2 p1,x1y0,y1 normal_gran p2,z1 normal_gran_2 p2,x1z1,z0 stdcall [glNormal3f], normal_gran_x1,[p1],[p2] stdcall [glVertex3f],[edi+vox_ogl_x1],[edi+vox_ogl_y0],[edi+vox_ogl_z1] ;normal_gran p1,y0 ;normal_gran_2 p1,x1y0,y1 normal_gran p2,z0 normal_gran_2 p2,x1z0,z1 stdcall [glNormal3f], normal_gran_x1,[p1],[p2] stdcall [glVertex3f],[edi+vox_ogl_x1],[edi+vox_ogl_y0],[edi+vox_ogl_z0] normal_gran p1,y1 normal_gran_2 p1,x1y1,y0 ;normal_gran p2,z0 ;normal_gran_2 p2,x1z0,z1 stdcall [glNormal3f], normal_gran_x1,[p1],[p2] stdcall [glVertex3f],[edi+vox_ogl_x1],[edi+vox_ogl_y1],[edi+vox_ogl_z0] ;normal_gran p1,y1 ;normal_gran_2 p1,x1y1,y0 normal_gran p2,z1 normal_gran_2 p2,x1z1,z0 stdcall [glNormal3f], normal_gran_x1,[p1],[p2] stdcall [glVertex3f],[edi+vox_ogl_x1],[edi+vox_ogl_y1],[edi+vox_ogl_z1] .e_gran_x1: bt word[edi+vox_ogl_planes],vox_ogl_gran_z0 jnc .e_gran_z0 ;задняя грань Normal(0.0,0.0,normal_gran_z0) normal_gran p1,x0 normal_gran_2 p1,x0z0,x1 normal_gran p2,y1 normal_gran_2 p2,y1z0,y0 stdcall [glNormal3f], [p1],[p2],normal_gran_z0 stdcall [glVertex3f],[edi+vox_ogl_x0],[edi+vox_ogl_y1],[edi+vox_ogl_z0] normal_gran p1,x1 normal_gran_2 p1,x1z0,x0 ;normal_gran p2,y1 ;normal_gran_2 p2,y1z0,y0 stdcall [glNormal3f], [p1],[p2],normal_gran_z0 stdcall [glVertex3f],[edi+vox_ogl_x1],[edi+vox_ogl_y1],[edi+vox_ogl_z0] ;normal_gran p1,x1 ;normal_gran_2 p1,x1z0,x0 normal_gran p2,y0 normal_gran_2 p2,y0z0,y1 stdcall [glNormal3f], [p1],[p2],normal_gran_z0 stdcall [glVertex3f],[edi+vox_ogl_x1],[edi+vox_ogl_y0],[edi+vox_ogl_z0] normal_gran p1,x0 normal_gran_2 p1,x0z0,x1 ;normal_gran p2,y0 ;normal_gran_2 p2,y0z0,y1 stdcall [glNormal3f], [p1],[p2],normal_gran_z0 stdcall [glVertex3f],[edi+vox_ogl_x0],[edi+vox_ogl_y0],[edi+vox_ogl_z0] .e_gran_z0: ;goto next voxel add edi,vox_ogl_size dec dword[v_count] jmp .cycle_0 .cycle_1: stdcall [glEnd] .end_f: ret endp