;---------------------------Module-Header------------------------------; ; Module Name: so_prim.asm ; ; xform routines. ; ; Created: 10/14/1996 ; Author: Otto Berkes [ottob] ; ; Copyright (c) 1996 Microsoft Corporation ;----------------------------------------------------------------------; .386 .model small,pascal assume cs:FLAT,ds:FLAT,es:FLAT,ss:FLAT assume fs:nothing,gs:nothing .xlist include gli386.inc .list PROFILE = 0 include profile.inc .data extrn ___glClipCodes :DWORD extrn ___glOne:DWORD extrn ___glHalf:DWORD extrn ___glZero:DWORD ;------------------------------------------------------------------------------------------ ; Internal definitions: ; _R_ = 0 _G_ = 4 _B_ = 8 _A_ = 12 _X_ = 0 _Y_ = 4 _Z_ = 8 _W_ = 12 ;------------------------------------------------------------------------------------------ ; pdLast is passed as parameter ; pdLast equ [ebp+8] ; ; Temporary data ; gc equ -4[ebp] pa equ -8[ebp] .code extrn @__glNormalize@8:NEAR ;------------------------------------------------------------------------------------------ ; Makes clip code for frustum clip planes ; General case ; ; Input: ; edx = pointer to POLYARRAY ; ecx = pointer to graphics context ; pdLast = pointer to the last vertex ; pa = pointer to POLYARRAY ; gc = pointer to graphics context ; ReuseClipCode if set to 1, new clip code is combined using OR with existing one ; ; Returns: ; eax = andClipCodes for POLYARRAY ; PAClipCheckFrustum MACRO ReuseClipCode mov edx, DWORD PTR [edx+PA_pd0] vertexLoop: mov esi, DWORD PTR [edx+PD_clip+_W_] ; esi = clipW or esi, esi ; if (clipW == 0) go to special case jz @WEqZero fld ___glOne fdiv DWORD PTR [edx+PD_clip+_W_] ; start division ; edi will accumulate index to clip table ; bit 6 - 1 if clipW < 0 ; bit 5 - 1 if clipX < 0 ; bit 4 - 1 if abs(clipX) < abs(clipW) ; bit 3 - 1 if clipY < 0 ; bit 2 - 1 if abs(clipY) < abs(clipW) ; bit 1 - 1 if clipZ < 0 ; bit 0 - 1 if abs(clipZ) < abs(clipW) xor edi, edi add esi, esi ; esi = abs(clipW) shifted left 1 bit mov ebx, [edx+PD_clip+_X_] ; ebx = clipX adc edi, edi ; edi = sign clipW add esi, 1 ; X-W bit should be set when X-W <= 0 !!! add ebx, ebx ; ebx = abs(clipX) shifted left 1 bit adc edi, edi ; edi = edi << 1 + sign(clipX) sub ebx, esi adc edi, edi ; edi = edi << 1 + sign(abs(clipX) - abs(clipW)) mov ebx, [edx+PD_clip+_Y_] mov ecx, pa add ebx, ebx adc edi, edi ; edi = edi << 1 + sign(clipY) sub ebx, esi adc edi, edi ; edi = edi << 1 + sign(abs(clipY) - abs(clipW)) mov ebx, [edx+PD_clip+_Z_] add edx, sizeof_POLYDATA ; advance vertex ptr add ebx, ebx ; edi = edi << 1 + sign(clipZ) adc edi, edi sub ebx, esi adc edi, edi ; edi = edi << 1 + sign(abs(clipZ) - abs(clipW)) mov esi, [ecx+PA_orClipCodes] ; get prim OR code mov ebx, [ecx+PA_andClipCodes] ; get prim AND code mov ecx, ___glClipCodes[edi*4] ; ecx = clip code mov edi, pa if ReuseClipCode eq 1 or ecx, [edx+PD_clipCode-sizeof_POLYDATA] ; update vertex clip code endif mov [edx+PD_clipCode-sizeof_POLYDATA], ecx ; store vertex clip code or esi, ecx ; compute prim OR and ebx, ecx ; " " AND mov [edi+PA_orClipCodes], esi ; store prim OR mov [edi+PA_andClipCodes], ebx ; store prim AND mov ebx, gc mov edi, pdLast ;; Save invW in window.w: fstp DWORD PTR [edx+PD_window+_W_ - sizeof_POLYDATA] or ecx, ecx jnz @Done fld DWORD PTR [edx+PD_clip+_X_ - sizeof_POLYDATA] fmul DWORD PTR [ebx+GC_VIEWPORT_xScale] fld DWORD PTR [edx+PD_clip+_Y_ - sizeof_POLYDATA] fmul DWORD PTR [ebx+GC_VIEWPORT_yScale] fld DWORD PTR [edx+PD_clip+_Z_ - sizeof_POLYDATA] fmul DWORD PTR [ebx+GC_VIEWPORT_zScale] ; z y x fxch st(2) ; x y z fmul DWORD PTR [edx+PD_window+_W_ - sizeof_POLYDATA] ; X y z fxch st(1) ; y X z fmul DWORD PTR [edx+PD_window+_W_ - sizeof_POLYDATA] ; Y X z fxch st(2) ; z X Y fmul DWORD PTR [edx+PD_window+_W_ - sizeof_POLYDATA] ; Z X Y fxch st(1) ; X Z Y fadd DWORD PTR [ebx+GC_VIEWPORT_xCenter] ; x Z Y fxch st(2) ; Y Z x fadd DWORD PTR [ebx+GC_VIEWPORT_yCenter] ; y Z x fxch st(1) ; Z y x fadd DWORD PTR [ebx+GC_VIEWPORT_zCenter] ; z y x fxch st(2) ; x y z fstp DWORD PTR [edx+PD_window+_X_ - sizeof_POLYDATA] fstp DWORD PTR [edx+PD_window+_Y_ - sizeof_POLYDATA] fstp DWORD PTR [edx+PD_window+_Z_ - sizeof_POLYDATA] @Done: cmp edx, edi ; pd > pdLast? jbe vertexLoop ; yes -> process next vertex @Exit: mov edx, pa pop edi pop esi pop ebx mov esp, ebp pop ebp mov eax, [edx + PA_andClipCodes] ; return value ret 4 ; ; W == 0 ; @WEqZero: xor edi, edi mov ebx, [edx+PD_clip+_X_] ; ebx = clipX add ebx, ebx ; ebx = abs(clipX) shifted left 1 bit adc edi, edi ; edi = edi << 1 + sign(clipX) add edi, edi ; edi = edi << 1 mov ebx, [edx+PD_clip+_Y_] mov ecx, pa add ebx, ebx adc edi, edi ; edi = edi << 1 + sign(clipY) add edi, edi ; edi = edi << 1 mov ebx, [edx+PD_clip+_Z_] add edx, sizeof_POLYDATA ; advance vertex ptr add ebx, ebx ; edi = edi << 1 + sign(clipZ) adc edi, edi add edi, edi ; edi = edi << 1 mov esi, [ecx+PA_orClipCodes] ; get prim OR code mov ebx, [ecx+PA_andClipCodes] ; get prim AND code mov ecx, ___glClipCodes[edi*4] ; ecx = clip code mov edi, pa if ReuseClipCode eq 1 or ecx, [edx+PD_clipCode-sizeof_POLYDATA] ; update vertex clip code endif mov [edx+PD_clipCode-sizeof_POLYDATA], ecx ; store vertex clip code or esi, ecx ; compute prim OR and ebx, ecx ; " " AND mov [edi+PA_orClipCodes], esi ; store prim OR mov [edi+PA_andClipCodes], ebx ; store prim AND mov ebx, gc mov edi, pdLast ;; Save invW in window.w: mov DWORD PTR [edx+PD_window+_W_ - sizeof_POLYDATA], 0 or ecx, ecx jnz @Done mov ecx, DWORD PTR [ebx+GC_VIEWPORT_xCenter] mov ebx, DWORD PTR [ebx+GC_VIEWPORT_yCenter] mov DWORD PTR [edx+PD_window+_X_ - sizeof_POLYDATA], ecx mov ecx, DWORD PTR [ebx+GC_VIEWPORT_zCenter] mov DWORD PTR [edx+PD_window+_Y_ - sizeof_POLYDATA], ebx mov DWORD PTR [edx+PD_window+_Z_ - sizeof_POLYDATA], ecx jmp @Done ENDM ;------------------------------------------------------------------------------------------ ; Make clip code for frustum clip planes ; General case ; ; Prototype: ; GLuint FASTCALL PAClipCheckFrustum(__GLcontext *gc, POLYARRAY *pa, ; POLYDATA *pdLast); ; Input: ; edx = pa pointer to POLYARRAY ; ecx = gc pointer to graphics context ; [esp+4] = pointer to the last vertex ; andClipCodes for POLYARRAY is set to -1 ; orClipCodes for POLYARRAY is set to 0 ; ; Returns: ; andClipCodes for POLYARRAY ; @PAClipCheckFrustum@12 PROC NEAR push ebp mov ebp, esp sub esp, 12 mov DWORD PTR pa, edx mov DWORD PTR gc, ecx push ebx push esi push edi PAClipCheckFrustum 0 @PAClipCheckFrustum@12 ENDP ;------------------------------------------------------------------------------------------ ; Makes clip code for frustum clip planes ; Case when vertices have W == 1.0 ; ; Input: ; edx = pa pointer to POLYARRAY ; ecx = gc pointer to graphics context ; pa = pointer to POLYARRAY ; gc = pointer to graphics context ; pdLast = pointer to the last vertex ; ReuseClipCode if set to 1, new clip code is combined using OR with existing one ; ; Returns: ; eax = andClipCodes for POLYARRAY ; PAClipCheckFrustumWOne MACRO ReuseClipCode mov edx, DWORD PTR [edx+PA_pd0] vertexLoop: ; edi will accumulate index to clip table ; bit 6 - 1 if clipW < 0 --- always 0 for this case ; bit 5 - 1 if clipX < 0 ; bit 4 - 1 if abs(clipX) < abs(clipW) ; bit 3 - 1 if clipY < 0 ; bit 2 - 1 if abs(clipY) < abs(clipW) ; bit 1 - 1 if clipZ < 0 ; bit 0 - 1 if abs(clipZ) < abs(clipW) xor edi, edi mov ebx, [edx+PD_clip+_X_] ; ebx = clipX mov esi, (__FLOAT_ONE*2) + 1 add ebx, ebx ; ebx = abs(clipX) shifted left 1 bit adc edi, edi ; edi = edi << 1 + sign(clipX) sub ebx, esi adc edi, edi ; edi = edi << 1 + sign(abs(clipX) - abs(clipW)) mov ebx, [edx+PD_clip+_Y_] mov ecx, pa add ebx, ebx adc edi, edi ; edi = edi << 1 + sign(clipY) sub ebx, esi adc edi, edi ; edi = edi << 1 + sign(abs(clipY) - abs(clipW)) mov ebx, [edx+PD_clip+_Z_] add edx, sizeof_POLYDATA ; advance vertex ptr add ebx, ebx ; edi = edi << 1 + sign(clipZ) adc edi, edi sub ebx, esi adc edi, edi ; edi = edi << 1 + sign(abs(clipZ) - abs(clipW)) mov esi, [ecx+PA_orClipCodes] ; get prim OR code mov ebx, [ecx+PA_andClipCodes] ; get prim AND code mov ecx, ___glClipCodes[edi*4] ; ecx = clip code mov edi, pa if ReuseClipCode eq 1 or ecx, [edx+PD_clipCode-sizeof_POLYDATA] ; update vertex clip code endif mov [edx+PD_clipCode-sizeof_POLYDATA], ecx ; store vertex clip code or esi, ecx ; compute prim OR and ebx, ecx ; " " AND mov [edi+PA_orClipCodes], esi ; store prim OR mov [edi+PA_andClipCodes], ebx ; store prim AND mov ebx, gc mov edi, pdLast ;; Save invW in window.w: mov DWORD PTR [edx+PD_window+_W_ - sizeof_POLYDATA], __FLOAT_ONE or ecx, ecx jnz @Done fld DWORD PTR [edx+PD_clip+_X_ - sizeof_POLYDATA] fmul DWORD PTR [ebx+GC_VIEWPORT_xScale] fld DWORD PTR [edx+PD_clip+_Y_ - sizeof_POLYDATA] fmul DWORD PTR [ebx+GC_VIEWPORT_yScale] fld DWORD PTR [edx+PD_clip+_Z_ - sizeof_POLYDATA] fmul DWORD PTR [ebx+GC_VIEWPORT_zScale] ; z y x fxch st(2) ; x y z fadd DWORD PTR [ebx+GC_VIEWPORT_xCenter] ; x y z fxch st(1) ; y x z fadd DWORD PTR [ebx+GC_VIEWPORT_yCenter] ; y x z fxch st(2) ; z x y fadd DWORD PTR [ebx+GC_VIEWPORT_zCenter] ; z x y fxch st(1) ; x z y fstp DWORD PTR [edx+PD_window+_X_ - sizeof_POLYDATA] fstp DWORD PTR [edx+PD_window+_Z_ - sizeof_POLYDATA] fstp DWORD PTR [edx+PD_window+_Y_ - sizeof_POLYDATA] @Done: cmp edx, edi ; pd > pdLast? jbe vertexLoop ; yes -> process next vertex @Exit: mov edx, pa pop edi pop esi pop ebx mov esp, ebp pop ebp mov eax, [edx + PA_andClipCodes] ; return value ret 4 ENDM ;------------------------------------------------------------------------------------------ ; Makes clip code for frustum clip planes ; Case when vertices have W == 1.0 ; ; Prototype: ; GLuint FASTCALL PAClipCheckFrustumWOne(__GLcontext *gc, POLYARRAY *pa, ; POLYDATA *pdLast); ; Input: ; edx = pa pointer to POLYARRAY ; ecx = gc pointer to graphics context ; [esp+4] = pointer to the last vertex ; andClipCodes for POLYARRAY is set to -1 ; orClipCodes for POLYARRAY is set to 0 ; ; Returns: ; eax = andClipCodes for POLYARRAY ; @PAClipCheckFrustumWOne@12 PROC NEAR push ebp mov ebp, esp sub esp, 12 mov DWORD PTR pa, edx mov DWORD PTR gc, ecx push ebx push esi push edi PAClipCheckFrustumWOne 0 @PAClipCheckFrustumWOne@12 ENDP ;------------------------------------------------------------------------------------------ ; Makes clip code for frustum clip planes ; Case when vertices have W == 1.0 and Z == 0.0 ; ; Input: ; edx = pa pointer to POLYARRAY ; ecx = gc pointer to graphics context ; pa = pointer to POLYARRAY ; gc = pointer to graphics context ; pdLast = pointer to the last vertex ; ReuseClipCode if set to 1, new clip code is combined using OR with existing one ; ; Returns: ; eax = andClipCodes for POLYARRAY ; PAClipCheckFrustum2D MACRO ReuseClipCode mov edx, DWORD PTR [edx+PA_pd0] vertexLoop: ; edi will accumulate index to clip table ; bit 6 - 1 if clipW < 0 --- always 0 for this case ; bit 5 - 1 if clipX < 0 ; bit 4 - 1 if abs(clipX) < abs(clipW) ; bit 3 - 1 if clipY < 0 ; bit 2 - 1 if abs(clipY) < abs(clipW) ; bit 1 - 1 if clipZ < 0 ; bit 0 - 1 if abs(clipZ) < abs(clipW) xor edi, edi mov ebx, [edx+PD_clip+_X_] ; ebx = clipX mov esi, (__FLOAT_ONE*2) + 1 add ebx, ebx ; ebx = abs(clipX) shifted left 1 bit adc edi, edi ; edi = edi << 1 + sign(clipX) sub ebx, esi adc edi, edi ; edi = edi << 1 + sign(abs(clipX) - abs(clipW)) mov ebx, [edx+PD_clip+_Y_] mov ecx, pa add ebx, ebx adc edi, edi ; edi = edi << 1 + sign(clipY) sub ebx, esi adc edi, edi ; edi = edi << 1 + sign(abs(clipY) - abs(clipW)) add edx, sizeof_POLYDATA ; advance vertex ptr add edi, edi ; sign(clipZ) = 0 lea edi, [edi+edi+1] ; sign(abs(clipZ) - abs(clipW)) = 0 mov esi, [ecx+PA_orClipCodes] ; get prim OR code mov ebx, [ecx+PA_andClipCodes] ; get prim AND code mov ecx, ___glClipCodes[edi*4] ; ecx = clip code mov edi, pa if ReuseClipCode eq 1 or ecx, [edx+PD_clipCode-sizeof_POLYDATA] ; update vertex clip code endif mov [edx+PD_clipCode-sizeof_POLYDATA], ecx ; store vertex clip code or esi, ecx ; compute prim OR and ebx, ecx ; " " AND mov [edi+PA_orClipCodes], esi ; store prim OR mov [edi+PA_andClipCodes], ebx ; store prim AND mov ebx, gc mov edi, pdLast ;; Save invW in window.w: mov DWORD PTR [edx+PD_window+_W_ - sizeof_POLYDATA], __FLOAT_ONE or ecx, ecx jnz @Done fld DWORD PTR [edx+PD_clip+_X_ - sizeof_POLYDATA] fmul DWORD PTR [ebx+GC_VIEWPORT_xScale] fld DWORD PTR [edx+PD_clip+_Y_ - sizeof_POLYDATA] fmul DWORD PTR [ebx+GC_VIEWPORT_yScale] fxch st(1) ; x y fadd DWORD PTR [ebx+GC_VIEWPORT_xCenter] ; x y fxch st(1) ; y x fadd DWORD PTR [ebx+GC_VIEWPORT_yCenter] ; y x fxch st(1) ; x y mov ecx, DWORD PTR [ebx+GC_VIEWPORT_zCenter] mov DWORD PTR [edx+PD_window+_Z_ - sizeof_POLYDATA], ecx fstp DWORD PTR [edx+PD_window+_X_ - sizeof_POLYDATA] fstp DWORD PTR [edx+PD_window+_Y_ - sizeof_POLYDATA] @Done: cmp edx, edi ; pd > pdLast? jbe vertexLoop ; yes -> process next vertex @Exit: mov edx, pa pop edi pop esi pop ebx mov esp, ebp pop ebp mov eax, [edx + PA_andClipCodes] ; return value ret 4 ENDM ;------------------------------------------------------------------------------------------ ; Makes clip code for frustum clip planes ; Case when vertices have W == 1.0 ; ; Prototype: ; GLuint FASTCALL PAClipCheckFrustum2D(__GLcontext *gc, POLYARRAY *pa, ; POLYDATA *pdLast); ; Input: ; edx = pa pointer to POLYARRAY ; ecx = gc pointer to graphics context ; [esp+4] = pointer to the last vertex ; andClipCodes for POLYARRAY is set to -1 ; orClipCodes for POLYARRAY is set to 0 ; ; Returns: ; eax = andClipCodes for POLYARRAY ; @PAClipCheckFrustum2D@12 PROC NEAR push ebp mov ebp, esp sub esp, 12 xor eax, eax mov pa, edx mov [edx+PA_orClipCodes], eax ; PA orClipCodes = 0 dec eax push ebx mov [edx+PA_andClipCodes], eax ; PA andClipCodes = -1 push esi mov DWORD PTR gc, ecx push edi PAClipCheckFrustum2D 0 @PAClipCheckFrustum2D@12 ENDP ;------------------------------------------------------------------------------------------ ; Makes clip code for user planes ; ; Input: ; edx = pa ; ecx = gc ; pdLast = pointer to the last vertex ; ReuseClipCode if set to 1, new clip code is combined using OR with existing one ; PAClipCheckUser MACRO ReuseClipCode result equ -16[ebp] cwSave equ -20[ebp] cwTemp equ -24[ebp] clipPlaneMask equ -28[ebp] firstPlane equ -32[ebp] ;; We have to turn on rounding with double precision. There is ;; too much error in the dot product otherwise (test with tlogo). fnstcw WORD PTR cwSave mov edi, DWORD PTR cwSave and edi, 0f0ffh or edi, 00200h mov cwTemp, edi fldcw WORD PTR cwTemp mov edi, pdLast ; edi will store POLYARRAY pointer mov edx, DWORD PTR [edx+PA_pd0] mov esi, DWORD PTR [ecx+GC_STATE_enablesClipPlanes] ; esi = clipPlaneMask mov ebx, [ecx+GC_STATE_clipPlanes0] ; ebx points to the current user plane or esi, esi jz @Exit1 ; No user planes mov clipPlaneMask, esi ; save clipPlaneMask mov firstPlane, ebx ; save pointer to the first clip plane @vertexLoop: mov esi, clipPlaneMask ; reload clipPlaneMask xor eax, eax ; prepare clip code mov ecx, __GL_CLIP_USER0 ; ecx stores __GL_CLIP_USER bits mov ebx, firstPlane ; reload pointer to the first clip plane @doAnotherPlane: test esi, 1 ; if (clipPlanesMask & 1 == 0) skip the plane je SHORT @noClipTest ; ; Dot the vertex clip coordinate against the clip plane and see ; if the sign is negative. If so, then the point is out. ; ; if (x * plane->x + y * plane->y + z * plane->z + w * plane->w < ; __glZero) ; fld DWORD PTR [ebx+_X_] fmul DWORD PTR [edx+PD_eye+_X_] fld DWORD PTR [ebx+_Y_] fmul DWORD PTR [edx+PD_eye+_Y_] fld DWORD PTR [ebx+_Z_] fmul DWORD PTR [edx+PD_eye+_Z_] ; z y x fxch ST(2) ; x y z faddp ST(1), ST(0) ; xy z fld DWORD PTR [ebx+_W_] ; w xy z fmul DWORD PTR [edx+PD_eye+_W_] fxch ST(2) ; z xy w faddp ST(1), ST(0) ; zxy w faddp ST(1), ST(0) ; zxyw fstp DWORD PTR result cmp result, 0 jge @noClipTest or eax, ecx ; code |= bit; @noClipTest: add ecx, ecx ; bit <<= 1; add ebx, 16 ; plane++; shr esi, 1 ; clipPlanesMask >>= 1; jne SHORT @doAnotherPlane if ReuseClipCode eq 1 or [edx+PD_clipCode], eax ; store vertex clip code else mov [edx+PD_clipCode], eax ; store vertex clip code endif add edx, sizeof_POLYDATA ; advance vertex ptr cmp edx, edi jbe @vertexLoop ; process next vertex ;; restore FP state: fldcw WORD PTR cwSave @Exit1: ENDM ;------------------------------------------------------------------------------------------- ; Make clip code when user clip planes are present ; ; Prototype: ; GLuint FASTCALL PAClipCheckFrustumAll(__GLcontext *gc, POLYARRAY *pa, ; POLYDATA *pdLast); ; Input: ; edx = pa pointer to POLYARRAY ; ecx = gc pointer to graphics context ; [esp+4] = pointer to the last vertex ; andClipCodes for POLYARRAY is set to -1 ; orClipCodes for POLYARRAY is set to 0 ; ; Returns: ; eax = andClipCodes for POLYARRAY ; @PAClipCheckAll@12 PROC NEAR push ebp mov ebp, esp sub esp, 32 mov DWORD PTR pa, edx mov DWORD PTR gc, ecx push ebx push esi push edi PAClipCheckUser 0 ; Check user clip planes first mov edx, pa PAClipCheckFrustum 1 ; Check frustum clip planes. We have to use OR when ; updating vertex clip code @PAClipCheckAll@12 ENDP ;-------------------------------------------------------------------------------------------- pd equ -4[ebp] pdLast equ -8[ebp] @PolyArrayPropagateSameColor@8 PROC NEAR push ebp mov eax, DWORD PTR [edx+PA_pdNextVertex] mov ebp, esp sub eax, sizeof_POLYDATA sub esp, 8 mov DWORD PTR pdLast, eax push ebx push esi mov ebx, DWORD PTR [edx+PA_pd0] push edi ; EAX = pdLast = pa->pdNextVertex-1; ; EBX = pd = pa->pd0; mov DWORD PTR pd, ebx ; if (pd > pdLast) cmp eax, ebx jb @Done mov eax, [edx+PA_flags] lea edi, DWORD PTR [ebx+PD_colors0] ; if (pa->flags & POLYARRAY_CLAMP_COLOR) { test eax, POLYARRAY_CLAMP_COLOR je @ClampDone mov eax, [edi+_R_] mov ebx, [ecx+GC_redVertexScale] sub ebx, eax mov [ecx+GC_redClampTable], eax shr eax, 31 add ebx, ebx mov edx, [edi+_G_] adc eax, eax mov ebx, [ecx+GC_greenVertexScale] sub ebx, edx mov eax, [4*eax+ecx+GC_redClampTable] mov [ecx+GC_greenClampTable], edx shr edx, 31 add ebx, ebx mov [edi+_R_], eax adc edx, edx mov eax, [edi+_B_] mov ebx, [ecx+GC_blueVertexScale] sub ebx, eax mov edx, [4*edx+ecx+GC_greenClampTable] mov [ecx+GC_blueClampTable], eax shr eax, 31 add ebx, ebx mov [edi+_G_], edx adc eax, eax mov edx, [edi+_A_] mov ebx, [ecx+GC_alphaVertexScale] sub ebx, edx mov eax, [4*eax+ecx+GC_blueClampTable] mov [ecx+GC_alphaClampTable], edx shr edx, 31 add ebx, ebx adc edx, edx mov [edi+_B_], eax mov edx, [4*edx+ecx+GC_alphaClampTable] mov [edi+_A_], edx @ClampDone: ;; Register usage. ;; EAX: r, EBX: g, ECX: b, EDX: a ;; ESI: &pdLast->colors[0] ;; EDI: &pd->colors[0] mov edi, pd mov esi, pdLast lea edi, [edi+PD_colors0+sizeof_POLYDATA] lea esi, [esi+PD_colors0] mov eax, [edi+_R_-sizeof_POLYDATA] cmp edi, esi ja @Done mov ebx, [edi+_G_-sizeof_POLYDATA] mov ecx, [edi+_B_-sizeof_POLYDATA] mov edx, [edi+_A_-sizeof_POLYDATA] @DoLoop: mov [edi+_R_], eax mov [edi+_G_], ebx mov [edi+_B_], ecx mov [edi+_A_], edx add edi, sizeof_POLYDATA cmp edi, esi jbe @DoLoop @Done: pop edi pop esi pop ebx mov esp, ebp pop ebp ret 0 @PolyArrayPropagateSameColor@8 ENDP ;------------------------------------------------------------------------ ; Copy cached non lit color from GC to a polydata ; ; Input: ; PDreg - register with POLYDATA address ; GCreg - register with GC address ; GC_LIGHT_value - front or back light (0 or 1) ; face - 0 for front face, 1 for back face ; tmpreg1, ; tmpreg2 - temporary registers ; COPY_CACHED_NON_LIT MACRO PDreg, GCreg, GC_LIGHT_value, face, tmpreg1, tmpreg2 mov eax, [ebx+GC_LIGHT_value+MATERIAL_cachedNonLit+_R_] mov ecx, [ebx+GC_LIGHT_value+MATERIAL_cachedNonLit+_G_] mov [esi+PD_colors0+(face*16)+_R_], eax mov [esi+PD_colors0+(face*16)+_G_], ecx mov eax, [ebx+GC_LIGHT_value+MATERIAL_cachedNonLit+_B_] mov ecx, [ebx+GC_LIGHT_value+MATERIAL_alpha] mov [esi+PD_colors0+(face*16)+_B_], eax mov [esi+PD_colors0+(face*16)+_A_], ecx ENDM ;------------------------------------------------------------------------ ; No lights case ; POLYARRAYZIPPYCALCRGBCOLOR0 MACRO GC_LIGHT_value, face push ebp mov ebp, esp sub esp, 56 push ebx push esi push edi mov esi, pdFirst mov edi, pdLast mov ebx, ecx ; ebx = gc ; ; for (pd = pdFirst; pd <= pdLast; pd++) ; @lightVertexLoop: COPY_CACHED_NON_LIT , , GC_LIGHT_value, face, , add esi, sizeof_POLYDATA cmp edi, esi jae @lightVertexLoop pop edi pop esi pop ebx mov esp, ebp pop ebp ret 12 ENDM ;------------------------------------------------------------------------ ; Parameters: ; ; ecx - GC ; NUMBER_OF_LIGHTS - 1 for one light, 2 for more than one light ; pdFirst equ 12[ebp] pdLast equ 16[ebp] pd equ pdFirst face equ -4[ebp] nonBack equ -4[ebp] nxi equ DWORD PTR -8[ebp] nyi equ DWORD PTR -12[ebp] nzi equ DWORD PTR -16[ebp] n1 equ DWORD PTR -20[ebp] n2 equ DWORD PTR -24[ebp] ifx equ -28[ebp] msm equ -32[ebp] baseEmissiveAmbientR equ DWORD PTR -36[ebp] baseEmissiveAmbientG equ DWORD PTR -40[ebp] baseEmissiveAmbientB equ DWORD PTR -44[ebp] rsi equ DWORD PTR -48[ebp] gsi equ DWORD PTR -52[ebp] bsi equ DWORD PTR -56[ebp] ;; ;; We will handle infinite lights with special cases for front and ;; back faces. ;; POLYARRAYZIPPYCALCRGBCOLOR MACRO GC_LIGHT_value, LIGHTSOURCE_value, face, NUMBER_OF_LIGHTS ;; GL_LIGHT_value = GL_LIGHT_front or GC_LIGHT_back ;; LIGHTSOURCE_value = LIGHTSOURCE_front or LIGHTSOURCE_back ;; face = __GL_FRONTFACE or __GL_BACKFACE push ebp mov ebp, esp sub esp, 56 if NUMBER_OF_LIGHTS eq 2 xor eax, eax endif push ebx push esi push edi ;; NOTE: esi, ebx held constant in this routine. ;; esi = pd ;; ebx = gc mov esi, pdFirst mov ebx, ecx ;; Start the vertex-processing loop ;; ;; for (pd = pdFirst; pd <= pdLast; pd++) @lightVertexLoop: ;; If normal has not changed for this vertex, use the previously computed color. ;; if (!(pd->flags & POLYDATA_NORMAL_VALID)) mov edx, [esi+PD_flags] test edx, POLYDATA_NORMAL_VALID jne @normalIsValid mov eax, [(face*16) + esi + (PD_colors0 - sizeof_POLYDATA)+_R_] mov ecx, [(face*16) + esi + (PD_colors0 - sizeof_POLYDATA)+_G_] mov [(face*16) + esi + PD_colors0+_R_], eax mov [(face*16) + esi + PD_colors0+_G_], ecx mov eax, [(face*16) + esi + (PD_colors0 - sizeof_POLYDATA)+_B_] mov ecx, [(face*16) + esi + (PD_colors0 - sizeof_POLYDATA)+_A_] mov [(face*16) + esi + PD_colors0+_B_], eax mov [(face*16) + esi + PD_colors0+_A_], ecx ;; loop to next pd mov edi, pdLast add esi, sizeof_POLYDATA if NUMBER_OF_LIGHTS eq 2 xor eax, eax endif cmp edi, esi jae @lightVertexLoop jmp @lightsDone @normalIsValid: if NUMBER_OF_LIGHTS eq 2 mov nonBack, eax endif mov edi, [ebx+GC_LIGHT_sources] if face eq __GL_FRONTFACE else mov eax, [esi+PD_normal+_X_] mov ecx, [esi+PD_normal+_Y_] mov edx, [esi+PD_normal+_Z_] xor eax, 80000000h xor ecx, 80000000h xor edx, 80000000h mov nxi, eax mov nyi, ecx mov nzi, edx endif if NUMBER_OF_LIGHTS eq 2 test edi, edi je @lightSourcesDone @lightSourcesLoop: endif ;; for (lsm = gc->light.sources; lsm; lsm = lsm->next) ;; edi = lsm (light source pointer) ;; n1 = nxi * lsm->unitVPpli.x + nyi * lsm->unitVPpli.y + ;; nzi * lsm->unitVPpli.z; if face eq __GL_FRONTFACE fld DWORD PTR [esi+PD_normal+_X_] fmul DWORD PTR [edi+LIGHTSOURCE_unitVPpli+_X_] fld DWORD PTR [esi+PD_normal+_Y_] fmul DWORD PTR [edi+LIGHTSOURCE_unitVPpli+_Y_] fld DWORD PTR [esi+PD_normal+_Z_] fmul DWORD PTR [edi+LIGHTSOURCE_unitVPpli+_Z_] else fld nxi fmul DWORD PTR [edi+LIGHTSOURCE_unitVPpli+_X_] fld nyi fmul DWORD PTR [edi+LIGHTSOURCE_unitVPpli+_Y_] fld nzi fmul DWORD PTR [edi+LIGHTSOURCE_unitVPpli+_Z_] endif fxch ST(2) faddp ST(1), ST faddp ST(1), ST fstp n1 ;; if (__GL_FLOAT_GTZ(n1)) if NUMBER_OF_LIGHTS eq 2 mov ecx, nonBack endif cmp n1, 0 jg @f if NUMBER_OF_LIGHTS eq 2 mov edi, [edi+LIGHTSOURCE_next] test edi, edi je @lightSourcesDone jmp @lightSourcesLoop else COPY_CACHED_NON_LIT , , GC_LIGHT_value, face, , ;; loop to next pd mov edi, pdLast add esi, sizeof_POLYDATA cmp edi, esi jae @lightVertexLoop jmp @lightsDone endif @@: if NUMBER_OF_LIGHTS eq 2 test ecx, ecx ; Has lighting been computed jne @f endif fld DWORD PTR [ebx+GC_LIGHT_value+MATERIAL_cachedEmissiveAmbient+_B_] if NUMBER_OF_LIGHTS eq 2 inc ecx endif fld DWORD PTR [ebx+GC_LIGHT_value+MATERIAL_cachedEmissiveAmbient+_G_] if NUMBER_OF_LIGHTS eq 2 mov nonBack, ecx endif fld DWORD PTR [ebx+GC_LIGHT_value+MATERIAL_cachedEmissiveAmbient+_R_] @@: ;; n2 = (nxi * lsm->hHat.x + nyi * lsm->hHat.y + nzi * lsm->hHat.z) ;; - msm_threshold; if face eq __GL_FRONTFACE fld DWORD PTR [esi+PD_normal+_X_] fmul DWORD PTR [edi+LIGHTSOURCE_hHat+_X_] fld DWORD PTR [esi+PD_normal+_Y_] fmul DWORD PTR [edi+LIGHTSOURCE_hHat+_Y_] fxch ST(1) fsub DWORD PTR [ebx+GC_LIGHT_value+MATERIAL_threshold] fld DWORD PTR [esi+PD_normal+_Z_] fmul DWORD PTR [edi+LIGHTSOURCE_hHat+_Z_] else fld nxi fmul DWORD PTR [edi+LIGHTSOURCE_hHat+_X_] fld nyi fmul DWORD PTR [edi+LIGHTSOURCE_hHat+_Y_] fxch ST(1) fsub DWORD PTR [ebx+GC_LIGHT_value+MATERIAL_threshold] fld nzi fmul DWORD PTR [edi+LIGHTSOURCE_hHat+_Z_] endif fxch ST(2) faddp ST(1), ST faddp ST(1), ST fstp n2 ;; if (__GL_FLOAT_GEZ(n2)) mov eax, n2 or eax, eax js @noSpecularEffect ;; ifx = (GLint)(n2 * msm_scale + __glHalf); fld n2 fmul DWORD PTR [ebx+GC_LIGHT_value+MATERIAL_scale] mov edx, __FLOAT_ONE ;; Note: we don't have to do this add since we can assume that rounding ;; enabled: ;; fadd ___glHalf mov ecx, [ebx+GC_LIGHT_value+MATERIAL_specTable] fistp DWORD PTR ifx ;; if (ifx < __GL_SPEC_LOOKUP_TABLE_SIZE ) mov eax, ifx cmp eax, __GL_SPEC_LOOKUP_TABLE_SIZE jge @specularSaturate ;; n2 = msm_specTable[ifx]; mov edx, DWORD PTR [ecx+eax*4] @specularSaturate: mov n2, edx fld n2 fmul DWORD PTR [edi+LIGHTSOURCE_value+LIGHTSOURCEPERMATERIAL_specular+_R_] fld n2 fmul DWORD PTR [edi+LIGHTSOURCE_value+LIGHTSOURCEPERMATERIAL_specular+_G_] fld n2 fmul DWORD PTR [edi+LIGHTSOURCE_value+LIGHTSOURCEPERMATERIAL_specular+_B_] fxch ST(2) ; r g b R G B faddp ST(3), ST ; g b R G B faddp ST(3), ST ; b R G B faddp ST(3), ST ; R G B @noSpecularEffect: ;; now handle diffuse affect: fld n1 fmul DWORD PTR [edi+LIGHTSOURCE_value+LIGHTSOURCEPERMATERIAL_diffuse+_R_] fld n1 fmul DWORD PTR [edi+LIGHTSOURCE_value+LIGHTSOURCEPERMATERIAL_diffuse+_G_] fld n1 fmul DWORD PTR [edi+LIGHTSOURCE_value+LIGHTSOURCEPERMATERIAL_diffuse+_B_] fxch ST(2) ; r g b R G B faddp ST(3), ST ; g b R G B if NUMBER_OF_LIGHTS eq 2 mov edi, [edi+LIGHTSOURCE_next] endif faddp ST(3), ST ; b R G B if NUMBER_OF_LIGHTS eq 2 test edi, edi endif faddp ST(3), ST ; R G B if NUMBER_OF_LIGHTS eq 2 jne @lightSourcesLoop @lightSourcesDone: mov eax, nonBack test eax,eax jne @f COPY_CACHED_NON_LIT , , GC_LIGHT_value, face, , ;; loop to next pd mov edi, pdLast add esi, sizeof_POLYDATA xor eax, eax cmp edi, esi jae @lightVertexLoop jmp @lightsDone @@: endif ; NUMBER_OF_LIGHTS eq 2 ;; OK, we had some lighting for this vertex. Now, handle clamping: fstp rsi mov eax, [ebx+GC_redVertexScale] fstp gsi mov edx, rsi fstp bsi mov ecx, [ebx+GC_greenVertexScale] mov edi, gsi sub eax, edx sub ecx, edi or eax, edx or ecx, edi mov edx, [ebx+GC_blueVertexScale] or eax, ecx mov edi, bsi or eax, edi sub edx, edi or eax, edx jns @noClamp mov eax, rsi mov ecx, [ebx+GC_redVertexScale] sub ecx, eax mov [ebx+GC_redClampTable], eax shr eax, 31 add ecx, ecx mov edx, gsi adc eax, eax mov ecx, [ebx+GC_greenVertexScale] sub ecx, edx mov eax, [4*eax+ebx+GC_redClampTable] mov [ebx+GC_greenClampTable], edx shr edx, 31 add ecx, ecx mov rsi, eax adc edx, edx mov eax, bsi mov ecx, [ebx+GC_blueVertexScale] sub ecx, eax mov edx, [4*edx+ebx+GC_greenClampTable] mov [ebx+GC_blueClampTable], eax shr eax, 31 add ecx, ecx mov gsi, edx adc eax, eax mov eax, [4*eax+ebx+GC_blueClampTable] mov bsi, eax @noClamp: ;; store colors mov eax, [ebx+GC_LIGHT_value+MATERIAL_alpha] mov ecx, rsi mov edx, gsi mov edi, bsi mov [esi+PD_colors0+(face*16)+_A_], eax mov [esi+PD_colors0+(face*16)+_R_], ecx mov [esi+PD_colors0+(face*16)+_G_], edx mov [esi+PD_colors0+(face*16)+_B_], edi ;; loop to next pd mov edi, pdLast add esi, sizeof_POLYDATA xor eax, eax cmp edi, esi jae @lightVertexLoop @lightsDone: pop edi pop esi pop ebx mov esp, ebp pop ebp ret 12 ENDM ;-------------------------------------------------------------------------------- @PolyArrayZippyCalcRGBColorFront@20 PROC NEAR POLYARRAYZIPPYCALCRGBCOLOR GC_LIGHT_front, LIGHTSOURCE_front, __GL_FRONTFACE, 2 @PolyArrayZippyCalcRGBColorFront@20 ENDP @PolyArrayZippyCalcRGBColorBack@20 PROC NEAR POLYARRAYZIPPYCALCRGBCOLOR GC_LIGHT_back, LIGHTSOURCE_back, __GL_BACKFACE, 2 @PolyArrayZippyCalcRGBColorBack@20 ENDP ; ; Functions for the one light source ; @PolyArrayZippyCalcRGBColorFront1@20 PROC NEAR POLYARRAYZIPPYCALCRGBCOLOR GC_LIGHT_front, LIGHTSOURCE_front, __GL_FRONTFACE, 1 @PolyArrayZippyCalcRGBColorFront1@20 ENDP @PolyArrayZippyCalcRGBColorBack1@20 PROC NEAR POLYARRAYZIPPYCALCRGBCOLOR GC_LIGHT_back, LIGHTSOURCE_back, __GL_BACKFACE, 1 @PolyArrayZippyCalcRGBColorBack1@20 ENDP ; ; Functions for the no light sources ; @PolyArrayZippyCalcRGBColorFront0@20 PROC NEAR POLYARRAYZIPPYCALCRGBCOLOR0 GC_LIGHT_front, __GL_FRONTFACE @PolyArrayZippyCalcRGBColorFront0@20 ENDP @PolyArrayZippyCalcRGBColorBack0@20 PROC NEAR POLYARRAYZIPPYCALCRGBCOLOR0 GC_LIGHT_back, __GL_BACKFACE @PolyArrayZippyCalcRGBColorBack0@20 ENDP ;-------------------------------------------------------------------------------- ; void FASTCALL PolyArrayZippyCalcRGBColor(__GLcontext* gc, int face, POLYARRAY* pa, ; POLYDATA* pdFirst, POLYDATA* pdLast) ; ; Input: ; ecx = gc ; edx = face (0 - front, 1 - back) ; [esp+4] = pa ; [esp+8] = pdFirst ; [esp+12] = pdLast ; @PolyArrayZippyCalcRGBColor@20 PROC NEAR push edi mov edi, [ecx+GC_LIGHT_sources] or edi, edi jz @noLights cmp [edi+LIGHTSOURCE_next], 0 jne @multipleLights ; ; one lignt case ; pop edi test edx, edx je @PolyArrayZippyCalcRGBColorFront1@20 jmp @PolyArrayZippyCalcRGBColorBack1@20 @noLights: pop edi test edx, edx je @PolyArrayZippyCalcRGBColorFront0@20 jmp @PolyArrayZippyCalcRGBColorBack0@20 @multipleLights: pop edi test edx, edx je @PolyArrayZippyCalcRGBColorFront@20 jmp @PolyArrayZippyCalcRGBColorBack@20 @PolyArrayZippyCalcRGBColor@20 ENDP ;-------------------------------------------------------------------------------- ; void FASTCALL PolyArrayZippyCalcRGBColor(__GLcontext* gc, int face, POLYARRAY* pa, ; POLYDATA* pdFirst, POLYDATA* pdLast) ; ; Input: ; ecx = gc ; edx = face (0 - front, 1 - back) ; [esp+4] = pa ; [esp+8] = pdFirst ; [esp+12] = pdLast ; emissiveAmbientR equ DWORD PTR -60[ebp] emissiveAmbientG equ DWORD PTR -64[ebp] emissiveAmbientB equ DWORD PTR -68[ebp] colorMaterialChange equ -72[ebp] alpha equ DWORD PTR -76[ebp] ri equ DWORD PTR -80[ebp] gi equ DWORD PTR -84[ebp] bi equ DWORD PTR -88[ebp] diffuseSpecularR equ DWORD PTR -92[ebp] diffuseSpecularG equ DWORD PTR -96[ebp] diffuseSpecularB equ DWORD PTR -100[ebp] @PolyArrayFastCalcRGBColor@20 PROC NEAR mov eax, [ecx+GC_LIGHT_front+MATERIAL_colorMaterialChange] test edx, edx je @f mov eax, [ecx+GC_LIGHT_back+MATERIAL_colorMaterialChange] @@: test eax, eax je @PolyArrayZippyCalcRGBColor@20 push ebp mov ebp, esp sub esp, 100 test edx, edx push ebx mov ebx, ecx push esi ;; if (face == __GL_FRONTFACE) ;; msm = &gc->light.front; ;; else ;; msm = &gc->light.back; lea ecx, DWORD PTR [ebx+GC_LIGHT_front] je short @f lea ecx, DWORD PTR [ebx+GC_LIGHT_back] @@: push edi mov DWORD PTR face, edx mov msm, ecx mov eax, [ecx+MATERIAL_colorMaterialChange] mov colorMaterialChange, eax test eax, __GL_MATERIAL_AMBIENT jne @baseEmissiveSimple mov eax, [ecx+MATERIAL_cachedEmissiveAmbient+_R_] mov edx, [ecx+MATERIAL_cachedEmissiveAmbient+_G_] mov baseEmissiveAmbientR, eax mov emissiveAmbientR, eax mov baseEmissiveAmbientG, edx mov emissiveAmbientG, edx mov eax, [ecx+MATERIAL_cachedEmissiveAmbient+_B_] mov esi, pdFirst mov edi, pdLast mov baseEmissiveAmbientB, eax cmp edi, esi mov emissiveAmbientB, eax jb @lightsDone jmp @baseEmissiveDone @baseEmissiveSimple: mov eax, [ecx+MATERIAL_paSceneColor+_R_] mov edx, [ecx+MATERIAL_paSceneColor+_G_] mov baseEmissiveAmbientR, eax mov emissiveAmbientR, eax mov baseEmissiveAmbientG, edx mov emissiveAmbientG, edx mov eax, [ecx+MATERIAL_paSceneColor+_B_] mov esi, pdFirst mov edi, pdLast mov baseEmissiveAmbientB, eax cmp edi, esi mov emissiveAmbientB, eax jb @lightsDone @baseEmissiveDone: ; If there is no emissive or ambient color material change, this ; will be the emissive and ambient components. ; ; emissiveAmbientI.r = baseEmissiveAmbient.r; ; emissiveAmbientI.g = baseEmissiveAmbient.g; ; emissiveAmbientI.b = baseEmissiveAmbient.b; ;; ;; ;; Vertex loop follows: ;; ;; ;; for (pd = pdFirst; pd <= pdLast; pd++) @lightVertexLoop: ;; If normal has not changed for this vertex, use the previously ;; computed color. ;; [if !(pd->flags & (POLYDATA_NORMAL_VALID | POLYDATA_COLOR_VALID))] mov edx, [esi+PD_flags] test edx, POLYDATA_NORMAL_VALID OR POLYDATA_COLOR_VALID jne @normalOrColorIsValid mov eax, face shl eax, 4 lea edi, [eax + esi + PD_colors0] lea esi, [eax + esi + (PD_colors0 - sizeof_POLYDATA)] movsd movsd movsd movsd mov esi, pd mov edi, pdLast add esi, sizeof_POLYDATA cmp edi, esi mov pd, esi jae @lightVertexLoop jmp @lightsDone @normalOrColorIsValid: ;; if (pd->flags & POLYDATA_COLOR_VALID) ;; ri = pd->colors[0].r * gc->oneOverRedVertexScale; ;; gi = pd->colors[0].g * gc->oneOverGreenVertexScale; ;; bi = pd->colors[0].b * gc->oneOverBlueVertexScale; ;; alpha = pd->colors[0].a; test edx, POLYDATA_COLOR_VALID je @usePreviousColors mov eax, [esi+PD_colors0+_A_] mov alpha, eax mov eax, colorMaterialChange fld DWORD PTR [esi+PD_colors0+_R_] fmul DWORD PTR [ebx+GC_oneOverRedVertexScale] fld DWORD PTr [esi+PD_colors0+_G_] fmul DWORD PTR [ebx+GC_oneOverGreenVertexScale] fld DWORD PTR [esi+PD_colors0+_B_] fmul DWORD PTR [ebx+GC_oneOverBlueVertexScale] ;; b g r fxch ST(2) ;; r g b fstp ri fstp gi fstp bi ;; FPU stack empty test eax, __GL_MATERIAL_AMBIENT je @noMaterialAmbient ;; ;; Handle ambient color changes: ;; ;; if (msm_colorMaterialChange & __GL_MATERIAL_AMBIENT) { ;; emissiveAmbient.r = baseEmissiveAmbient.r + ri * lm_ambient.r; ;; emissiveAmbient.g = baseEmissiveAmbient.g + gi * lm_ambient.g; ;; emissiveAmbient.b = baseEmissiveAmbient.b + bi * lm_ambient.b; ;; } fld ri fmul DWORD PTR [ebx+GC_STATE_lightModelAmbient+_R_] fld gi mov edi, [ebx+GC_LIGHT_sources] fmul DWORD PTR [ebx+GC_STATE_lightModelAmbient+_G_] fld bi test edi, edi fmul DWORD PTR [ebx+GC_STATE_lightModelAmbient+_B_] ; b g r fxch ST(1) ; g b r fadd baseEmissiveAmbientG ; G b r fxch ST(1) ; b G r fadd baseEmissiveAmbientB ; B G r fxch ST(2) ; r G B fadd baseEmissiveAmbientR ; R G B jne @ambientLoop fstp emissiveAmbientR ;; If we don't have to process fstp emissiveAmbientG ;; the lights, pop the FPU stack fstp emissiveAmbientB ;; and continue jmp @emissiveAmbientDone @ambientLoop: ;; Add per-light per-material ambient values. ;; We will start with the current basEmissiveAmbient values ;; already on the stack. ;; for (lsm = gc->light.sources; lsm; lsm = lsm->next) { ;; emissiveAmbientI.r += ri * lsm->state.ambient.r; ;; emissiveAmbientI.g += gi * lsm->stats.ambient.g; ;; emissiveAmbientI.b += bi * lsm->state.ambient.b; ;; } mov edx, [edi+LIGHTSOURCE_state] ; lss fld ri fmul DWORD PTR [edx+LIGHTSOURCESTATE_ambient+_R_] fld gi fmul DWORD PTR [edx+LIGHTSOURCESTATE_ambient+_G_] fld bi fmul DWORD PTR [edx+LIGHTSOURCESTATE_ambient+_B_] ;; b g r R G B fxch ST(2) ;; r g b R G B faddp ST(3), ST(0) mov edi, [edi+LIGHTSOURCE_next] faddp ST(3), ST(0) test edi, edi faddp ST(3), ST(0) jne @ambientLoop ;; There are no lights, so pop the emissive result at this point ;; and continue: fstp emissiveAmbientR fstp emissiveAmbientG fstp emissiveAmbientB jmp @emissiveAmbientDone @noMaterialAmbient: ;; ;; Handle emissive material changes if needed: ;; test eax, __GL_MATERIAL_EMISSIVE je @emissiveAmbientDone ;; emissiveAmbientR = baseEmissiveAmbientR + pd->colors[0].r; ;; emissiveAmbientG = baseEmissiveAmbientG + pd->colors[0].g; ;; emissiveAmbientB = baseEmissiveAmbientB + pd->colors[0].b; fld baseEmissiveAmbientR fadd DWORD PTR [esi+PD_colors0+_R_] fld baseEmissiveAmbientG fadd DWORD PTR [esi+PD_colors0+_G_] fld baseEmissiveAmbientB fadd DWORD PTR [esi+PD_colors0+_B_] ; b g r fxch ST(2) ; r g b fstp emissiveAmbientR fstp emissiveAmbientG fstp emissiveAmbientB @emissiveAmbientDone: @usePreviousColors: ;; ;; OK, we're done handling emissive and diffuse color changes, or ;; we're simply using the previous values. Now, handle portion of ;; lighting which depends on the vertex normals (diffuse + specular): ;; ;; if (pd->flags & POLYDATA_NORMAL_VALID) mov edx, [esi+PD_flags] test edx, POLYDATA_NORMAL_VALID je @normalNotValid mov eax, face ;; if (face == __GL_FRONTFACE) mov ecx, [esi+PD_normal+_X_] mov edx, [esi+PD_normal+_Y_] mov esi, [esi+PD_normal+_Z_] test eax, eax je @notBackFace ;; negate the floating-point normal values xor ecx, 80000000h xor edx, 80000000h xor esi, 80000000h @notBackFace: mov nxi, ecx mov nyi, edx mov nzi, esi jmp @calcColor @normalNotValid: ;; if (!(msm_colorMaterialChange & (__GL_MATERIAL_SPECULAR | __GL_MATERIAL_DIFFUSE))) ;; goto store_color; test eax, __GL_MATERIAL_SPECULAR OR __GL_MATERIAL_DIFFUSE je @storeColor @calcColor: fld ___glZero mov esi, [ebx+GC_LIGHT_sources] fld ___glZero test esi, esi fld ___glZero je @lightSourcesDone @lightSourcesLoop: ;; for (lsm = gc->light.sources; lsm; lsm = lsm->next) mov eax, face ;; lspmm = &lsm->front + face; lea ecx, [esi+LIGHTSOURCE_front] test eax, eax je @f lea ecx, [esi+LIGHTSOURCE_back] @@: ;; esi = lsm ;; ecx = lspmm ;; n1 = nxi * lsm->unitVPpli.x + nyi * lsm->unitVPpli.y + ;; nzi * lsm->unitVPpli.z; fld nxi mov edi, msm fmul DWORD PTR [esi+LIGHTSOURCE_unitVPpli+_X_] fld nyi fmul DWORD PTR [esi+LIGHTSOURCE_unitVPpli+_Y_] fld nzi fmul DWORD PTR [esi+LIGHTSOURCE_unitVPpli+_Z_] fxch ST(2) faddp ST(1), ST faddp ST(1), ST fstp n1 ;; if (__GL_FLOAT_GTZ(n1)) mov eax, n1 cmp eax, 0 jg @f mov esi, [esi+LIGHTSOURCE_next] test esi, esi jne @lightSourcesLoop jmp @lightSourcesDone @@: ;; n2 = (nxi * lsm->hHat.x + nyi * lsm->hHat.y + nzi * lsm->hHat.z) ;; - msm_threshold; fld nxi fmul DWORD PTR [esi+LIGHTSOURCE_hHat+_X_] fld nyi fmul DWORD PTR [esi+LIGHTSOURCE_hHat+_Y_] fxch ST(1) fsub DWORD PTR [edi+MATERIAL_threshold] fld nzi fmul DWORD PTR [esi+LIGHTSOURCE_hHat+_Z_] fxch ST(2) faddp ST(1), ST faddp ST(1), ST fstp n2 ;; if (__GL_FLOAT_GEZ(n2)) mov eax, n2 or eax, eax js @noSpecularEffect ;; ifx = (GLint)(n2 * msm_scale + __glHalf); fld n2 fmul DWORD PTR [edi+MATERIAL_scale] mov edx, __FLOAT_ONE ;; Note: we don't have to do this add since we can assume that rounding ;; enabled: ;; fadd ___glHalf mov edi, [edi+MATERIAL_specTable] fistp DWORD PTR ifx ;; if (ifx < __GL_SPEC_LOOKUP_TABLE_SIZE ) mov eax, ifx cmp eax, __GL_SPEC_LOOKUP_TABLE_SIZE jge @specularSaturate ;; n2 = msm_specTable[ifx]; mov edx, DWORD PTR [edi+eax*4] @specularSaturate: mov eax, colorMaterialChange mov n2, edx test eax, __GL_MATERIAL_SPECULAR je @noSpecularMaterialChange fld n2 mov edx, [esi+LIGHTSOURCE_state] fmul ri fld n2 fmul gi fld n2 fmul bi ; b g r fxch ST(2) ; r g b fmul DWORD PTR [edx+LIGHTSOURCESTATE_specular+_R_] fxch ST(1) ; g r b fmul DWORD PTR [edx+LIGHTSOURCESTATE_specular+_G_] fxch ST(2) ; b r g fmul DWORD PTR [edx+LIGHTSOURCESTATE_specular+_B_] fxch ST(1) ; r b g R G B faddp ST(3), ST(0) ; b g R G B fxch ST(1) ; g b R G B faddp ST(3), ST(0) ; b R G B faddp ST(3), ST(0) ; R G B jmp short @noSpecularEffect @noSpecularMaterialChange: fld n2 fmul DWORD PTR [ecx+LIGHTSOURCEPERMATERIAL_specular+_R_] fld n2 fmul DWORD PTR [ecx+LIGHTSOURCEPERMATERIAL_specular+_G_] fld n2 fmul DWORD PTR [ecx+LIGHTSOURCEPERMATERIAL_specular+_B_] fxch ST(2) ; r g b R G B faddp ST(3), ST ; g b R G B faddp ST(3), ST ; b R G B faddp ST(3), ST ; R G B @noSpecularEffect: ;; now handle diffuse affect: mov eax, colorMaterialChange test eax, __GL_MATERIAL_DIFFUSE je @noDiffuseMaterialChange fld n1 mov edx, [esi+LIGHTSOURCE_state] fmul ri fld n1 fmul gi fld n1 fmul bi ; b g r fxch ST(2) ; r g b fmul DWORD PTR [edx+LIGHTSOURCESTATE_diffuse+_R_] fxch ST(1) ; g r b fmul DWORD PTR [edx+LIGHTSOURCESTATE_diffuse+_G_] fxch ST(2) ; b r g fmul DWORD PTR [edx+LIGHTSOURCESTATE_diffuse+_B_] fxch ST(1) ; r b g R G B faddp ST(3), ST(0) ; b g R G B fxch ST(1) ; g b R G B faddp ST(3), ST(0) ; b R G B faddp ST(3), ST(0) ; R G B jmp short @lightSourcesDone @noDiffuseMaterialChange: fld n1 fmul DWORD PTR [ecx+LIGHTSOURCEPERMATERIAL_diffuse+_R_] fld n1 fmul DWORD PTR [ecx+LIGHTSOURCEPERMATERIAL_diffuse+_G_] fld n1 fmul DWORD PTR [ecx+LIGHTSOURCEPERMATERIAL_diffuse+_B_] fxch ST(2) ; r g b R G B faddp ST(3), ST ; g b R G B mov esi, [esi+LIGHTSOURCE_next] faddp ST(3), ST ; b R G B test esi, esi faddp ST(3), ST ; R G B jne @lightSourcesLoop @lightSourcesDone: fst diffuseSpecularR fadd emissiveAmbientR ; R g b fxch ST(1) ; g R b fst diffuseSpecularG fadd emissiveAmbientG ; G R b fxch ST(2) ; b R G fst diffuseSpecularB fadd emissiveAmbientB ; B R G fxch ST(1) ; R B G fstp rsi mov eax, [ebx+GC_redVertexScale] fstp bsi mov ecx, [ebx+GC_greenVertexScale] fstp gsi mov edx, rsi jmp short @handleClamp @storeColor: ;; Now add emissiveAmbient (on FP stack) and diffuseSpecular. ;; Interleave with start of clamping: fld emissiveAmbientR mov eax, [ebx+GC_redVertexScale] fadd diffuseSpecularR mov ecx, [ebx+GC_greenVertexScale] fld emissiveAmbientG fadd diffuseSpecularG fld emissiveAmbientB fadd diffuseSpecularB fxch ST(2) ; r g b fstp rsi fstp gsi mov edx, rsi fstp bsi @handleClamp: ;; handle clamping: mov edi, gsi sub eax, edx sub ecx, edi or eax, edx or ecx, edi mov edx, [ebx+GC_blueVertexScale] or eax, ecx mov edi, bsi or eax, edi sub edx, edi or eax, edx jns @noClamp mov eax, rsi mov ecx, [ebx+GC_redVertexScale] sub ecx, eax mov [ebx+GC_redClampTable], eax shr eax, 31 add ecx, ecx mov edx, gsi adc eax, eax mov ecx, [ebx+GC_greenVertexScale] sub ecx, edx mov eax, [4*eax+ebx+GC_redClampTable] mov [ebx+GC_greenClampTable], edx shr edx, 31 add ecx, ecx mov rsi, eax adc edx, edx mov eax, bsi mov ecx, [ebx+GC_blueVertexScale] sub ecx, eax mov edx, [4*edx+ebx+GC_greenClampTable] mov [ebx+GC_blueClampTable], eax shr eax, 31 add ecx, ecx mov gsi, edx adc eax, eax mov eax, [4*eax+ebx+GC_blueClampTable] mov bsi, eax @noClamp: ;; ecx = pd->colors[face] mov edx, msm mov eax, face mov esi, pd shl eax, 4 lea ecx, [esi+PD_colors0] mov edi, colorMaterialChange add ecx, eax test edi, __GL_MATERIAL_DIFFUSE je @noAlphaChange mov edx, alpha mov eax, [ebx+GC_alphaVertexScale] test edx, edx jns @f xor edx, edx @@: sub eax, edx jge @alphaDone mov edx, [ebx+GC_alphaVertexScale] jmp short @alphaDone @noAlphaChange: mov edx, [edx+MATERIAL_alpha] @alphaDone: mov edi, pdLast add esi, sizeof_POLYDATA ;; store colors mov [ecx+_A_], edx mov eax, rsi mov edx, gsi mov [ecx+_R_], eax mov pd, esi mov eax, bsi mov [ecx+_G_], edx mov [ecx+_B_], eax ;; loop to next pd cmp edi, esi jae @lightVertexLoop @lightsDone: pop edi pop esi pop ebx mov esp, ebp pop ebp ret 12 @PolyArrayFastCalcRGBColor@20 ENDP END