kolibrios/programs/develop/libraries/TinyGL/asm_fork/clip.asm
IgorA 51fcac25ee optimize, clean code
git-svn-id: svn://kolibrios.org@8063 a494cfbc-eb01-0410-851d-a64ba20cac60
2020-09-16 06:59:01 +00:00

1138 lines
27 KiB
NASM
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

; fill triangle profile
; #define PROFILE
CLIP_XMIN equ (1<<0)
CLIP_XMAX equ (1<<1)
CLIP_YMIN equ (1<<2)
CLIP_YMAX equ (1<<3)
CLIP_ZMIN equ (1<<4)
CLIP_ZMAX equ (1<<5)
align 16
proc gl_transform_to_viewport uses eax ebx ecx, context:dword,v:dword
mov eax,[context]
mov ebx,[v]
; coordinates
fld1
fdiv dword[ebx+GLVertex.pc+offs_W] ;st0 = 1/v.pc.W
fld dword[ebx+GLVertex.pc+offs_X] ;st0 = v.pc.X
fmul st0,st1
fmul dword[eax+GLContext.viewport+offs_vpor_scale+offs_X]
fadd dword[eax+GLContext.viewport+offs_vpor_trans+offs_X]
fistp dword[ebx+GLVertex.zp] ;v.zp.x = st0, st0 = st1
fld dword[ebx+GLVertex.pc+offs_Y] ;st0 = v.pc.Y
fmul st0,st1
fmul dword[eax+GLContext.viewport+offs_vpor_scale+offs_Y]
fadd dword[eax+GLContext.viewport+offs_vpor_trans+offs_Y]
fistp dword[ebx+GLVertex.zp+offs_zbup_y] ;v.zp.y = st0, st0 = st1
fld dword[ebx+GLVertex.pc+offs_Z] ;st0 = v.pc.Z
fmulp
fmul dword[eax+GLContext.viewport+offs_vpor_scale+offs_Z]
fadd dword[eax+GLContext.viewport+offs_vpor_trans+offs_Z]
fistp dword[ebx+GLVertex.zp+offs_zbup_z] ;v.zp.z = st0, st0 = st1
; color
cmp dword[eax+GLContext.lighting_enabled],0 ;if (context.lighting_enabled)
je @f
lea ecx,[ebx+GLVertex.zp+offs_zbup_b]
push ecx
add ecx,offs_zbup_g-offs_zbup_b
push ecx
add ecx,offs_zbup_r-offs_zbup_g
push ecx
stdcall RGBFtoRGBI, dword[ebx+GLVertex.color],dword[ebx+GLVertex.color+4],dword[ebx+GLVertex.color+8]
jmp .end_if
align 4
@@:
; no need to convert to integer if no lighting : take current color
mov ecx,[eax+GLContext.longcurrent_color]
mov dword[ebx+GLVertex.zp+offs_zbup_r],ecx
mov ecx,[eax+GLContext.longcurrent_color+4]
mov dword[ebx+GLVertex.zp+offs_zbup_g],ecx
mov ecx,[eax+GLContext.longcurrent_color+8]
mov dword[ebx+GLVertex.zp+offs_zbup_b],ecx
.end_if:
; texture
cmp dword[eax+GLContext.texture_2d_enabled],0
je @f
mov eax,[eax+GLContext.current_texture] ;eax = &context.current_texture
mov eax,[eax] ;eax = context.current_texture
;[eax+offs_text_images] = im = &context.current_texture.images[0]
fild dword[eax+offs_text_images+offs_imag_s_bound]
fmul dword[ebx+GLVertex.tex_coord+offs_X]
fistp dword[ebx+GLVertex.zp+offs_zbup_s]
;v.zp.s=(int)(v.tex_coord.X * im.s_bound)
fild dword[eax+offs_text_images+offs_imag_t_bound]
fmul dword[ebx+GLVertex.tex_coord+offs_Y]
fistp dword[ebx+GLVertex.zp+offs_zbup_t]
;v.zp.t=(int)(v.tex_coord.Y * im.t_bound)
@@:
ret
endp
align 16
proc gl_add_select1 uses eax ebx ecx, context:dword, z1:dword,z2:dword,z3:dword
mov eax,[z1]
mov ebx,eax
cmp [z2],eax
jge @f
mov eax,[z2]
@@:
cmp [z3],eax
jge @f
mov eax,[z3]
@@:
cmp [z2],ebx
jle @f
mov ebx,[z2]
@@:
cmp [z3],ebx
jle @f
mov ebx,[z3]
@@:
mov ecx,0xffffffff
sub ecx,ebx
push ecx
mov ecx,0xffffffff
sub ecx,eax
push ecx
stdcall gl_add_select, [context] ;,0xffffffff-eax,0xffffffff-ebx
ret
endp
; point
align 16
proc gl_draw_point uses eax ebx, context:dword, p0:dword
mov ebx,[p0]
cmp dword[ebx+GLVertex.clip_code],0 ;if (p0.clip_code == 0)
jne @f
mov eax,[context]
cmp dword[eax+GLContext.render_mode],GL_SELECT
jne .els
stdcall gl_add_select, eax,dword[ebx+GLVertex.zp+offs_zbup_z],dword[ebx+GLVertex.zp+offs_zbup_z] ;p0.zp.z,p0.zp.z
jmp @f
align 4
.els:
add ebx,GLVertex.zp
stdcall ZB_plot, dword[eax+GLContext.zb],ebx
@@:
ret
endp
; line
;input:
;q - регистр с адресом вершины для интерполяции
;p0 - регистр с адресом 1-й вершины
;p1 - регистр с адресом 2-й вершины
;t - float
macro interpolate q, p0, p1, t
{
fld dword[t]
; интерполяция по координатам
fld dword[p1+GLVertex.pc]
fsub dword[p0+GLVertex.pc]
fmul st0,st1
fadd dword[p0+GLVertex.pc]
fstp dword[q+GLVertex.pc] ;q.pc.X = p0.pc.X + (p1.pc.X - p0.pc.X) * t
fld dword[p1+GLVertex.pc+offs_Y]
fsub dword[p0+GLVertex.pc+offs_Y]
fmul st0,st1
fadd dword[p0+GLVertex.pc+offs_Y]
fstp dword[q+GLVertex.pc+offs_Y]
fld dword[p1+GLVertex.pc+offs_Z]
fsub dword[p0+GLVertex.pc+offs_Z]
fmul st0,st1
fadd dword[p0+GLVertex.pc+offs_Z]
fstp dword[q+GLVertex.pc+offs_Z]
fld dword[p1+GLVertex.pc+offs_W]
fsub dword[p0+GLVertex.pc+offs_W]
fmul st0,st1
fadd dword[p0+GLVertex.pc+offs_W]
fstp dword[q+GLVertex.pc+offs_W]
; интерполяция по цвету
fld dword[p1+GLVertex.color]
fsub dword[p0+GLVertex.color]
fmul st0,st1
fadd dword[p0+GLVertex.color]
fstp dword[q+GLVertex.color]
fld dword[p1+GLVertex.color+4]
fsub dword[p0+GLVertex.color+4]
fmul st0,st1
fadd dword[p0+GLVertex.color+4]
fstp dword[q+GLVertex.color+4]
fld dword[p1+GLVertex.color+8]
fsub dword[p0+GLVertex.color+8]
fmulp
fadd dword[p0+GLVertex.color+8]
fstp dword[q+GLVertex.color+8]
}
;
; Line Clipping
;
; Line Clipping algorithm from 'Computer Graphics', Principles and
; Practice
; tmin,tmax -> &float
align 16
proc ClipLine1 uses ebx, denom:dword,num:dword,tmin:dword,tmax:dword
fld dword[denom]
ftst
fstsw ax
sahf
jbe .els_0 ;if (denom>0)
fld dword[num]
fxch st1
fdivp ;t=num/denom
mov ebx,[tmax]
fcom dword[ebx]
fstsw ax
sahf
ja .r0_f1 ;if (t>*tmax) return 0
mov ebx,[tmin]
fcom dword[ebx]
fstsw ax
sahf
jbe .r1_f1 ;if (t>*tmin) *tmin=t
fstp dword[ebx]
jmp .r1
align 4
.els_0: ;else if (denom<0)
jae .els_1
fld dword[num]
fxch st1
fdivp ;t=num/denom
mov ebx,[tmin]
fcom dword[ebx]
fstsw ax
sahf
jb .r0_f1 ;if (t<*tmin) return 0
mov ebx,[tmax]
fcom dword[ebx]
fstsw ax
sahf
jae .r1_f1
fstp dword[ebx] ;if (t<*tmin) *tmax=t
jmp .r1
align 4
.els_1: ;else if (num>0)
ffree st0 ;denom
fincstp
fld dword[num]
ftst
fstsw ax
sahf
ja .r0_f1 ;if (num>0) return 0
jmp .r1_f1
align 4
.r0_f1: ;return 0 & free st0
ffree st0
fincstp
.r0: ;return 0
xor eax,eax
jmp .end_f
align 4
.r1_f1: ;return 1 & free st0
ffree st0
fincstp
.r1: ;return 1
xor eax,eax
inc eax
.end_f:
ret
endp
align 16
proc gl_draw_line, context:dword, p1:dword, p2:dword
locals
d_x dd ?
d_y dd ?
d_z dd ?
d_w dd ?
x1 dd ?
y1 dd ?
z1 dd ?
w1 dd ?
q1 GLVertex ?
q2 GLVertex ?
tmin dd ? ;ebp-8
tmax dd ? ;ebp-4
endl
pushad
mov edx,[context]
mov edi,[p1]
mov esi,[p2]
cmp dword[edi+GLVertex.clip_code],0
jne .els_i
cmp dword[esi+GLVertex.clip_code],0
jne .els_i
;if ( (p1.clip_code | p2.clip_code) == 0)
cmp dword[edx+GLContext.render_mode],GL_SELECT ;if (context.render_mode == GL_SELECT)
jne .els_1
stdcall gl_add_select1, edx,dword[edi+GLVertex.zp+offs_zbup_z],\
dword[esi+GLVertex.zp+offs_zbup_z],dword[esi+GLVertex.zp+offs_zbup_z]
jmp .end_f
align 4
.els_1:
add edi,GLVertex.zp
add esi,GLVertex.zp
push esi
push edi
push dword[edx+GLContext.zb]
cmp dword[edx+GLContext.depth_test],0
je .els_2
;if (context.depth_test)
call ZB_line_z ;, dword[edx+GLContext.zb],edi,esi
jmp .end_f
align 4
.els_2:
call ZB_line ;, dword[edx+GLContext.zb],edi,esi
jmp .end_f
align 4
.els_i:
;else if ( (p1.clip_code & p2.clip_code) != 0 )
mov eax,[edi+GLVertex.clip_code]
and eax,[esi+GLVertex.clip_code]
or eax,eax
jnz .end_f
.els_0:
fld dword[esi+GLVertex.pc+offs_X]
fsub dword[edi+GLVertex.pc+offs_X]
fstp dword[d_x] ;d_x = p2.pc.X - p1.pc.X
fld dword[esi+GLVertex.pc+offs_Y]
fsub dword[edi+GLVertex.pc+offs_Y]
fstp dword[d_y] ;d_y = p2.pc.Y - p1.pc.Y
fld dword[esi+GLVertex.pc+offs_Z]
fsub dword[edi+GLVertex.pc+offs_Z]
fstp dword[d_z] ;d_z = p2.pc.Z - p1.pc.Z
fld dword[esi+GLVertex.pc+offs_W]
fsub dword[edi+GLVertex.pc+offs_W]
fstp dword[d_w] ;d_w = p2.pc.W - p1.pc.W
mov eax,[edi+GLVertex.pc+offs_X]
mov [x1],eax ;x1 = p1.pc.X
mov eax,[edi+GLVertex.pc+offs_Y]
mov [y1],eax ;y1 = p1.pc.Y
mov eax,[edi+GLVertex.pc+offs_Z]
mov [z1],eax ;z1 = p1.pc.Z
mov eax,[edi+GLVertex.pc+offs_W]
mov [w1],eax ;w1 = p1.pc.W
mov dword[tmin],0.0
mov dword[tmax],1.0
lea eax,[ebp-4]
push eax ;толкаем в стек адрес &tmax
sub eax,4
push eax ;толкаем в стек адрес &tmin
fld dword[x1]
fadd dword[w1]
fchs
fstp dword[esp-4]
fld dword[d_x]
fadd dword[d_w]
fstp dword[esp-8]
sub esp,8
call ClipLine1 ;d_x+d_w,-x1-w1,&tmin,&tmax
bt eax,0
jnc .end_f
sub esp,8 ;толкаем в стек адреса переменных &tmin и &tmax
fld dword[x1]
fsub dword[w1]
fstp dword[esp-4]
fld dword[d_w]
fsub dword[d_x]
fstp dword[esp-8]
sub esp,8
call ClipLine1 ;-d_x+d_w,x1-w1,&tmin,&tmax
bt eax,0
jnc .end_f
sub esp,8 ;толкаем в стек адреса переменных &tmin и &tmax
fld dword[y1]
fadd dword[w1]
fchs
fstp dword[esp-4]
fld dword[d_y]
fadd dword[d_w]
fstp dword[esp-8]
sub esp,8
call ClipLine1 ;d_y+d_w,-y1-w1,&tmin,&tmax
bt eax,0
jnc .end_f
sub esp,8 ;толкаем в стек адреса переменных &tmin и &tmax
fld dword[y1]
fsub dword[w1]
fstp dword[esp-4]
fld dword[d_w]
fsub dword[d_y]
fstp dword[esp-8]
sub esp,8
call ClipLine1 ;-d_y+d_w,y1-w1,&tmin,&tmax
bt eax,0
jnc .end_f
sub esp,8 ;толкаем в стек адреса переменных &tmin и &tmax
fld dword[z1]
fadd dword[w1]
fchs
fstp dword[esp-4]
fld dword[d_z]
fadd dword[d_w]
fstp dword[esp-8]
sub esp,8
call ClipLine1 ;d_z+d_w,-z1-w1,&tmin,&tmax
bt eax,0
jnc .end_f
sub esp,8 ;толкаем в стек адреса переменных &tmin и &tmax
fld dword[z1]
fsub dword[w1]
fstp dword[esp-4]
fld dword[d_w]
fsub dword[d_z]
fstp dword[esp-8]
sub esp,8
call ClipLine1 ;-d_z+d_w,z1-w1,&tmin,&tmax
bt eax,0
jnc .end_f
lea eax,[ebp-8-2*sizeof.GLVertex] ;eax = &q1
interpolate eax,edi,esi,tmin
stdcall gl_transform_to_viewport, edx,eax
add eax,sizeof.GLVertex ;eax = &q2
interpolate eax,edi,esi,tmax
stdcall gl_transform_to_viewport, edx,eax
sub eax,sizeof.GLVertex ;eax = &q1
lea ebx,[eax+GLVertex.zp+offs_zbup_b]
push ebx
add ebx,offs_zbup_g-offs_zbup_b
push ebx
add ebx,offs_zbup_r-offs_zbup_g
push ebx
stdcall RGBFtoRGBI, dword[eax+GLVertex.color],dword[eax+GLVertex.color+4],dword[eax+GLVertex.color+8]
add eax,sizeof.GLVertex ;eax = &q2
lea ebx,[eax+GLVertex.zp+offs_zbup_b]
push ebx
add ebx,offs_zbup_g-offs_zbup_b
push ebx
add ebx,offs_zbup_r-offs_zbup_g
push ebx
stdcall RGBFtoRGBI, dword[eax+GLVertex.color],dword[eax+GLVertex.color+4],dword[eax+GLVertex.color+8]
add eax,GLVertex.zp ;eax = &q2.zp
push eax
sub eax,sizeof.GLVertex ;eax = &q1.zp
push eax
push dword[edx+GLContext.zb]
cmp dword[edx+GLContext.depth_test],0
je .els_3
call ZB_line_z ;(context.zb,&q1.zp,&q2.zp)
jmp .end_f
align 4
.els_3:
call ZB_line ;(context.zb,&q1.zp,&q2.zp)
.end_f:
popad
ret
endp
; triangle
;
; Clipping
;
; We clip the segment [a,b] against the 6 planes of the normal volume.
; We compute the point 'c' of intersection and the value of the parameter 't'
; of the intersection if x=a+t(b-a).
;
; sign: 0 -> '-', 1 -> '+'
macro clip_func sign,dir,dir1,dir2
{
locals
t dd ?
d_X dd ?
d_Y dd ?
d_Z dd ?
d_W dd ?
endl
mov edx,[a]
mov ebx,[b]
mov ecx,[c]
fld dword[ebx+offs_X]
fsub dword[edx+offs_X]
fstp dword[d_X] ;d_X = (b.X - a.X)
fld dword[ebx+offs_Y]
fsub dword[edx+offs_Y]
fstp dword[d_Y] ;d_Y = (b.Y - a.Y)
fld dword[ebx+offs_Z]
fsub dword[edx+offs_Z]
fstp dword[d_Z] ;d_Z = (b.Z - a.Z)
fld dword[ebx+offs_W]
fsub dword[edx+offs_W]
fst dword[d_W] ;d_W = (b.W - a.W)
if sign eq 0
fadd dword[d#dir]
else
fsub dword[d#dir]
end if
ftst
fstsw ax
sahf
jne @f
fldz
fst dword[t] ;t=0
jmp .e_zero
align 4
@@: ;else
fld dword[edx+offs#dir]
if sign eq 0
fchs
end if
fsub dword[edx+offs_W]
fdiv st0,st1
fst dword[t] ;t = ( sign a.dir - a.W) / den
.e_zero:
fmul dword[d#dir1] ;st0 = t * d.dir1
fadd dword[edx+offs#dir1]
fstp dword[ecx+offs#dir1] ;c.dir1 = a.dir1 + t * d.dir1
ffree st0
fincstp
fld dword[t]
fmul dword[d#dir2] ;st0 = t * d.dir2
fadd dword[edx+offs#dir2]
fstp dword[ecx+offs#dir2] ;c.dir2 = a.dir2 + t * d.dir2
fld dword[t]
fmul dword[d_W]
fadd dword[edx+offs_W]
fst dword[ecx+offs_W] ;c.W = a.W + t * d_W
if sign eq 0
fchs
end if
fstp dword[ecx+offs#dir] ;c.dir = sign c.W
mov eax,[t]
}
align 16
proc clip_xmin uses ebx ecx edx, c:dword, a:dword, b:dword
clip_func 0,_X,_Y,_Z
ret
endp
align 16
proc clip_xmax uses ebx ecx edx, c:dword, a:dword, b:dword
clip_func 1,_X,_Y,_Z
ret
endp
align 16
proc clip_ymin uses ebx ecx edx, c:dword, a:dword, b:dword
clip_func 0,_Y,_X,_Z
ret
endp
align 16
proc clip_ymax uses ebx ecx edx, c:dword, a:dword, b:dword
clip_func 1,_Y,_X,_Z
ret
endp
align 16
proc clip_zmin uses ebx ecx edx, c:dword, a:dword, b:dword
clip_func 0,_Z,_X,_Y
ret
endp
align 16
proc clip_zmax uses ebx ecx edx, c:dword, a:dword, b:dword
clip_func 1,_Z,_X,_Y
ret
endp
align 4
clip_proc dd clip_xmin,clip_xmax, clip_ymin,clip_ymax, clip_zmin,clip_zmax
;input:
;edi - q
align 16
proc updateTmp uses eax ecx edx, context:dword, p0:dword, p1:dword, t:dword
mov edx,[context]
mov eax,[p0]
cmp dword[edx+GLContext.current_shade_model],GL_SMOOTH ;if (context.current_shade_model == GL_SMOOTH)
jne .els_0
mov ecx,[p1]
fld dword[ecx+GLVertex.color]
fsub dword[eax+GLVertex.color]
fmul dword[t]
fadd dword[eax+GLVertex.color]
fstp dword[edi+GLVertex.color] ;q.color.v[0]=p0.color.v[0] + (p1.color.v[0]-p0.color.v[0])*t
fld dword[ecx+GLVertex.color+4]
fsub dword[eax+GLVertex.color+4]
fmul dword[t]
fadd dword[eax+GLVertex.color+4]
fstp dword[edi+GLVertex.color+4] ;q.color.v[1]=p0.color.v[1] + (p1.color.v[1]-p0.color.v[1])*t
fld dword[ecx+GLVertex.color+8]
fsub dword[eax+GLVertex.color+8]
fmul dword[t]
fadd dword[eax+GLVertex.color+8]
fstp dword[edi+GLVertex.color+8] ;q.color.v[2]=p0.color.v[2] + (p1.color.v[2]-p0.color.v[2])*t
jmp @f
align 4
.els_0:
mov ecx,[eax+GLVertex.color]
mov [edi+GLVertex.color],ecx ;q.color.v[0]=p0.color.v[0]
mov ecx,[eax+GLVertex.color+4]
mov [edi+GLVertex.color+4],ecx ;q.color.v[1]=p0.color.v[1]
mov ecx,[eax+GLVertex.color+8]
mov [edi+GLVertex.color+8],ecx ;q.color.v[2]=p0.color.v[2]
@@:
cmp dword[edx+GLContext.texture_2d_enabled],0 ;if (context.texture_2d_enabled)
je @f
mov ecx,[p1]
fld dword[ecx+GLVertex.tex_coord+offs_X]
fsub dword[eax+GLVertex.tex_coord+offs_X]
fmul dword[t]
fadd dword[eax+GLVertex.tex_coord+offs_X]
fstp dword[edi+GLVertex.tex_coord+offs_X] ;q.tex_coord.X=p0.tex_coord.X + (p1.tex_coord.X-p0.tex_coord.X)*t
fld dword[ecx+GLVertex.tex_coord+offs_Y]
fsub dword[eax+GLVertex.tex_coord+offs_Y]
fmul dword[t]
fadd dword[eax+GLVertex.tex_coord+offs_Y]
fstp dword[edi+GLVertex.tex_coord+offs_Y] ;q.tex_coord.Y=p0.tex_coord.Y + (p1.tex_coord.Y-p0.tex_coord.Y)*t
@@:
stdcall gl_clipcode, [edi+GLVertex.pc+offs_X],[edi+GLVertex.pc+offs_Y],\
[edi+GLVertex.pc+offs_Z],[edi+GLVertex.pc+offs_W]
mov dword[edi+GLVertex.clip_code],eax
or eax,eax ;if (q.clip_code==0)
jnz @f
stdcall gl_transform_to_viewport,[context],edi
lea eax,[edi+GLVertex.zp+offs_zbup_b]
push eax
add eax,offs_zbup_g-offs_zbup_b
push eax
add eax,offs_zbup_r-offs_zbup_g
push eax
stdcall RGBFtoRGBI, dword[edi+GLVertex.color],dword[edi+GLVertex.color+4],dword[edi+GLVertex.color+8]
@@:
ret
endp
align 16
proc gl_draw_triangle, context:dword, p0:dword, p1:dword, p2:dword
locals
cc rd 3
front dd ?
norm dd ? ;float
endl
pushad
mov ebx,[p0]
mov ecx,[p1]
mov edx,[p2]
mov edi,[ebx+GLVertex.clip_code]
mov dword[cc],edi
mov eax,[ecx+GLVertex.clip_code]
mov dword[cc+4],eax
or edi,eax
mov eax,[edx+GLVertex.clip_code]
mov dword[cc+8],eax
or edi,eax ;co = cc[0] | cc[1] | cc[2]
; we handle the non clipped case here to go faster
;or edi,___ - было выше
jnz .els_0
;if (co==0)
mov edi,dword[edx+GLVertex.zp+offs_zbup_x]
sub edi,dword[ebx+GLVertex.zp+offs_zbup_x]
mov dword[norm],edi ;p2.x-p0.x
fild dword[norm]
mov edi,dword[ecx+GLVertex.zp+offs_zbup_y]
sub edi,dword[ebx+GLVertex.zp+offs_zbup_y]
mov dword[norm],edi ;p1.y-p0.y
fimul dword[norm]
fchs
mov edi,dword[ecx+GLVertex.zp+offs_zbup_x]
sub edi,dword[ebx+GLVertex.zp+offs_zbup_x]
mov dword[norm],edi ;p1.x-p0.x
fild dword[norm]
mov edi,dword[edx+GLVertex.zp+offs_zbup_y]
sub edi,dword[ebx+GLVertex.zp+offs_zbup_y]
mov dword[norm],edi ;p2.y-p0.y
fimul dword[norm]
faddp
;st0 = (p1.zp.x-p0.zp.x)*(p2.zp.y-p0.zp.y) - (p2.zp.x-p0.zp.x)*(p1.zp.y-p0.zp.y)
mov dword[front],0
ftst
fstsw ax
ffree st0
fincstp
sahf
je .end_f
jae @f
inc dword[front] ;front = norm < 0.0
@@:
mov edi,[context]
mov eax,dword[edi+GLContext.current_front_face]
xor dword[front],eax ;front ^= context.current_front_face
; back face culling
cmp dword[edi+GLContext.cull_face_enabled],0
je .els_1
; most used case first
cmp dword[edi+GLContext.current_cull_face],GL_BACK
jne @f
cmp dword[front],0
je .end_f
stdcall dword[edi+GLContext.draw_triangle_front], edi,ebx,ecx,edx
jmp .end_f
align 4
@@:
cmp dword[edi+GLContext.current_cull_face],GL_FRONT
jne .end_f
cmp dword[front],0
jne .end_f
stdcall dword[edi+GLContext.draw_triangle_back], edi,ebx,ecx,edx
jmp .end_f
align 4
.els_1:
; no culling
cmp dword[front],0
je @f
stdcall dword[edi+GLContext.draw_triangle_front], edi,ebx,ecx,edx
jmp .end_f
align 4
@@:
stdcall dword[edi+GLContext.draw_triangle_back], edi,ebx,ecx,edx
jmp .end_f
align 4
.els_0:
;eax = cc[2]
and eax,[cc]
and eax,[cc+4] ;eax = c_and = cc[0] & cc[1] & cc[2]
or eax,eax ;if (c_and==0)
jnz .end_f
stdcall gl_draw_triangle_clip, [context],ebx,ecx,edx,0
.end_f:
popad
ret
endp
align 16
proc gl_draw_triangle_clip, context:dword, p0:dword, p1:dword, p2:dword, clip_bit:dword
locals
co dd ?
cc rd 3
edge_flag_tmp dd ?
clip_mask dd ?
q rd 3 ;GLVertex*
tmp1 GLVertex ?
tmp2 GLVertex ?
endl
pushad
mov ebx,[p0]
mov ecx,[p1]
mov edx,[p2]
mov edi,[ebx+GLVertex.clip_code]
mov [cc],edi
mov eax,[ecx+GLVertex.clip_code]
mov [cc+4],eax
or edi,eax
mov eax,[edx+GLVertex.clip_code]
mov [cc+8],eax
or edi,eax
mov [co],edi ;co = cc[0] | cc[1] | cc[2]
or edi,edi ;if (co == 0)
jnz .els_0
stdcall gl_draw_triangle, [context],ebx,ecx,edx
jmp .end_f
align 4
.els_0:
;eax = cc[2]
and eax,[cc]
and eax,[cc+4] ;c_and = cc[0] & cc[1] & cc[2]
; the triangle is completely outside
or eax,eax ;if (c_and!=0) return
jnz .end_f
; find the next direction to clip
.cycle_0: ;while (clip_bit < 6 && (co & (1 << clip_bit)) == 0)
cmp dword[clip_bit],6
jge .cycle_0_end
xor eax,eax
inc eax
mov ecx,[clip_bit]
shl eax,cl
and eax,[co]
or eax,eax
jnz .cycle_0_end
inc dword[clip_bit]
jmp .cycle_0
align 4
.cycle_0_end:
; this test can be true only in case of rounding errors
cmp dword[clip_bit],6
if 0
jne @f
; printf("Error:\n");
; printf("%f %f %f %f\n",p0->pc.X,p0->pc.Y,p0->pc.Z,p0->pc.W);
; printf("%f %f %f %f\n",p1->pc.X,p1->pc.Y,p1->pc.Z,p1->pc.W);
; printf("%f %f %f %f\n",p2->pc.X,p2->pc.Y,p2->pc.Z,p2->pc.W);
jmp .end_f
@@:
end if
if 1
je .end_f
end if
xor eax,eax
inc eax
mov ecx,[clip_bit]
shl eax,cl
mov [clip_mask],eax ;1 << clip_bit
mov edi,[cc]
xor edi,[cc+4]
xor edi,[cc+8]
and eax,edi ;eax = co1 = (cc[0] ^ cc[1] ^ cc[2]) & clip_mask
mov ecx,[p1] ;востанавливаем после shl ___,cl
or eax,eax ;if (co1)
jz .els_1
; one point outside
mov eax,[cc]
and eax,[clip_mask]
or eax,eax ;if (cc[0] & clip_mask)
jz .els_2
;q[0]=p0 q[1]=p1 q[2]=p2
mov [q],ebx
mov [q+4],ecx
mov [q+8],edx
jmp .els_2_end
align 4
.els_2:
mov eax,[cc+4]
and eax,[clip_mask]
or eax,eax ;else if (cc[1] & clip_mask)
jz .els_3
;q[0]=p1 q[1]=p2 q[2]=p0
mov [q],ecx
mov [q+4],edx
mov [q+8],ebx
jmp .els_2_end
align 4
.els_3:
;q[0]=p2 q[1]=p0 q[2]=p1
mov [q],edx
mov [q+4],ebx
mov [q+8],ecx
.els_2_end:
mov ebx,[q]
add ebx,GLVertex.pc
mov ecx,[q+4]
add ecx,GLVertex.pc
mov edx,[q+8]
add edx,GLVertex.pc
lea eax,[clip_proc]
mov edi,[clip_bit]
lea eax,[eax+4*edi]
lea edi,[ebp-(2*sizeof.GLVertex)+GLVertex.pc]
stdcall dword[eax],edi,ebx,ecx ;clip_proc[clip_bit](&tmp1.pc,&q[0].pc,&q[1].pc)
sub edi,GLVertex.pc
sub ebx,GLVertex.pc
sub ecx,GLVertex.pc
stdcall updateTmp,[context],ebx,ecx,eax ;(c,&tmp1,q[0],q[1],tt)
add ebx,GLVertex.pc
lea eax,[clip_proc]
mov edi,[clip_bit]
lea eax,[eax+4*edi]
lea edi,[ebp-sizeof.GLVertex+GLVertex.pc]
stdcall dword[eax],edi,ebx,edx ;clip_proc[clip_bit](&tmp2.pc,&q[0].pc,&q[2].pc)
sub edi,GLVertex.pc
sub ebx,GLVertex.pc
sub edx,GLVertex.pc
stdcall updateTmp,[context],ebx,edx,eax ;(c,&tmp2,q[0],q[2],tt)
mov eax,[ebx+GLVertex.edge_flag]
mov [tmp1.edge_flag],eax ;q[0].edge_flag
mov eax,[edx+GLVertex.edge_flag]
mov [edge_flag_tmp],eax ;q[2].edge_flag
mov dword[edx+GLVertex.edge_flag],0 ;q[2].edge_flag=0
mov eax,[clip_bit]
inc eax
push eax ;для вызова нижней функции
lea edi,[ebp-2*sizeof.GLVertex]
stdcall gl_draw_triangle_clip,[context],edi,ecx,edx,eax ;gl_draw_triangle_clip(c,&tmp1,q[1],q[2],clip_bit+1)
mov dword[tmp2.edge_flag],0
mov dword[tmp1.edge_flag],0
mov eax,[edge_flag_tmp]
mov [edx+GLVertex.edge_flag],eax ;q[2].edge_flag=edge_flag_tmp
push edx
push edi
add edi,sizeof.GLVertex ;edi = &tmp2
stdcall gl_draw_triangle_clip,[context],edi ;gl_draw_triangle_clip(c,&tmp2,&tmp1,q[2],clip_bit+1)
jmp .end_f
align 4
.els_1:
; two points outside
mov eax,[cc]
and eax,[clip_mask]
cmp eax,0 ;if (cc[0] & clip_mask)==0
jne .els_4
;q[0]=p0 q[1]=p1 q[2]=p2
mov [q],ebx
mov [q+4],ecx
mov [q+8],edx
jmp .els_4_end
align 4
.els_4:
mov eax,[cc+4]
and eax,[clip_mask]
cmp eax,0 ;else if (cc[1] & clip_mask)==0
jne .els_5
;q[0]=p1 q[1]=p2 q[2]=p0
mov [q],ecx
mov [q+4],edx
mov [q+8],ebx
jmp .els_4_end
align 4
.els_5:
;q[0]=p2 q[1]=p0 q[2]=p1
mov [q],edx
mov [q+4],ebx
mov [q+8],ecx
.els_4_end:
mov ebx,[q]
add ebx,GLVertex.pc
mov ecx,[q+4]
add ecx,GLVertex.pc
mov edx,[q+8]
add edx,GLVertex.pc
lea eax,[clip_proc]
mov edi,[clip_bit]
lea eax,[eax+4*edi]
lea edi,[ebp-(2*sizeof.GLVertex)+GLVertex.pc]
stdcall dword[eax],edi,ebx,ecx ;clip_proc[clip_bit](&tmp1.pc,&q[0].pc,&q[1].pc)
sub edi,GLVertex.pc
stdcall updateTmp,[context],[q],[q+4],eax
lea eax,[clip_proc]
mov edi,[clip_bit]
lea eax,[eax+4*edi]
lea edi,[ebp-sizeof.GLVertex+GLVertex.pc]
stdcall dword[eax],edi,ebx,edx ;clip_proc[clip_bit](&tmp2.pc,&q[0].pc,&q[2].pc)
sub edi,GLVertex.pc
stdcall updateTmp,[context],[q],[q+8],eax
mov dword[tmp1.edge_flag],1
mov eax,[edx+GLVertex.edge_flag-GLVertex.pc]
mov dword[tmp2.edge_flag],eax ;tmp2.edge_flag = q[2].edge_flag
mov eax,[clip_bit]
inc eax
push eax
push edi
sub edi,sizeof.GLVertex
stdcall gl_draw_triangle_clip,[context],[q],edi ;gl_draw_triangle_clip(c,q[0],&tmp1,&tmp2,clip_bit+1)
.end_f:
popad
ret
endp
align 16
proc gl_draw_triangle_select uses eax, context:dword, p0:dword,p1:dword,p2:dword
mov eax,[p2]
push dword[eax+GLVertex.zp+offs_Z]
mov eax,[p1]
push dword[eax+GLVertex.zp+offs_Z]
mov eax,[p0]
push dword[eax+GLVertex.zp+offs_Z]
stdcall gl_add_select1, [context] ;,p0.zp.z, p1.zp.z, p2.zp.z
ret
endp
if PROFILE eq 1
count_triangles dd ?
count_triangles_textured dd ?
count_pixels dd ?
end if
align 16
proc gl_draw_triangle_fill, context:dword, p0:dword,p1:dword,p2:dword
pushad
if PROFILE eq 1
; int norm;
; assert(p0->zp.x >= 0 && p0->zp.x < c->zb->xsize);
; assert(p0->zp.y >= 0 && p0->zp.y < c->zb->ysize);
; assert(p1->zp.x >= 0 && p1->zp.x < c->zb->xsize);
; assert(p1->zp.y >= 0 && p1->zp.y < c->zb->ysize);
; assert(p2->zp.x >= 0 && p2->zp.x < c->zb->xsize);
; assert(p2->zp.y >= 0 && p2->zp.y < c->zb->ysize);
; norm=(p1->zp.x-p0->zp.x)*(p2->zp.y-p0->zp.y)-
; (p2->zp.x-p0->zp.x)*(p1->zp.y-p0->zp.y);
; count_pixels+=abs(norm)/2;
inc dword[count_triangles]
end if
mov ebx,[p1]
add ebx,GLVertex.zp
mov ecx,[p2]
add ecx,GLVertex.zp
mov edx,[context]
cmp dword[edx+GLContext.texture_2d_enabled],0
je .els_i
;if (context.texture_2d_enabled)
if PROFILE eq 1
inc dword[count_triangles_textured]
end if
mov eax,[edx+GLContext.current_texture]
mov eax,[eax] ;переход по указателю
;так как offs_text_images+offs_imag_pixmap = 0 то context.current_texture.images[0].pixmap = [eax]
stdcall ZB_setTexture, [edx+GLContext.zb], [eax],\
[eax+offs_imag_s_bound],[eax+offs_imag_t_bound],[eax+offs_imag_xsize_log2]
mov eax,[p0]
add eax,GLVertex.zp
push ecx
push ebx
push eax
push dword[edx+GLContext.zb]
cmp dword[edx+GLContext.matrix_model_projection_no_w_transform],0
je @f
call ZB_fillTriangleMappingPerspective
jmp .end_f
align 4
@@:
call ZB_fillTriangleMapping
jmp .end_f
align 4
.els_i:
mov eax,[p0]
add eax,GLVertex.zp
cmp dword[edx+GLContext.current_shade_model],GL_SMOOTH
jne .els
;else if (context.current_shade_model == GL_SMOOTH)
stdcall ZB_fillTriangleSmooth, dword[edx+GLContext.zb],eax,ebx,ecx
jmp .end_f
align 4
.els:
stdcall ZB_fillTriangleFlat, dword[edx+GLContext.zb],eax,ebx,ecx
.end_f:
popad
ret
endp
; Render a clipped triangle in line mode
align 16
proc gl_draw_triangle_line uses eax ebx ecx edx, context:dword, p0:dword,p1:dword,p2:dword
mov edx,[context]
cmp dword[edx+GLContext.depth_test],0
je .els
lea ecx,[ZB_line_z]
jmp @f
align 4
.els:
lea ecx,[ZB_line]
@@:
;if (p0.edge_flag) ZB_line_z(context.zb,&p0.zp,&p1.zp)
mov eax,[p0]
cmp dword[eax+GLVertex.edge_flag],0
je @f
lea ebx,[eax+GLVertex.zp]
mov eax,[p1]
add eax,GLVertex.zp
stdcall ecx,dword[edx+GLContext.zb],ebx,eax
@@:
;if (p1.edge_flag) ZB_line_z(context.zb,&p1.zp,&p2.zp)
mov eax,[p1]
cmp dword[eax+GLVertex.edge_flag],0
je @f
lea ebx,[eax+GLVertex.zp]
mov eax,[p2]
add eax,GLVertex.zp
stdcall ecx,dword[edx+GLContext.zb],ebx,eax
@@:
;if (p2.edge_flag) ZB_line_z(context.zb,&p2.zp,&p0.zp);
mov eax,[p2]
cmp dword[eax+GLVertex.edge_flag],0
je @f
lea ebx,[eax+GLVertex.zp]
mov eax,[p0]
add eax,GLVertex.zp
stdcall ecx,dword[edx+GLContext.zb],ebx,eax
@@:
ret
endp
; Render a clipped triangle in point mode
align 16
proc gl_draw_triangle_point uses eax edx, context:dword, p0:dword,p1:dword,p2:dword
mov edx,[context]
mov eax,[p0]
cmp dword[eax+GLVertex.edge_flag],0
je @f
lea eax,[eax+GLVertex.zp]
stdcall ZB_plot,dword[edx+GLContext.zb],eax
@@:
mov eax,[p1]
cmp dword[eax+GLVertex.edge_flag],0
je @f
lea eax,[eax+GLVertex.zp]
stdcall ZB_plot,dword[edx+GLContext.zb],eax
@@:
mov eax,[p2]
cmp dword[eax+GLVertex.edge_flag],0
je @f
lea eax,[eax+GLVertex.zp]
stdcall ZB_plot,dword[edx+GLContext.zb],eax
@@:
ret
endp