📄 r_drawa.pas
字号:
//100%
{$ALIGN 8}{$MINENUMSIZE 4}
{----------------------------------------------------------------------------}
{ }
{ File(s): r_drawa.asm }
{ }
{ Initial conversion by : Carl Kenner (carl_kenner@hotmail.com) }
{ Initial conversion on : 25-Feb-2002 }
{ }
{ This File contains part of convertion of Quake2 source to ObjectPascal. }
{ More information about this project can be found at: }
{ http://www.sulaco.co.za/quake2/ }
{ }
{ Copyright (C) 1997-2001 Id Software, Inc. }
{ }
{ This program is free software; you can redistribute it and/or }
{ modify it under the terms of the GNU General Public License }
{ as published by the Free Software Foundation; either version 2 }
{ of the License, or (at your option) any later version. }
{ }
{ This program is distributed in the hope that it will be useful, }
{ but WITHOUT ANY WARRANTY; without even the implied warranty of }
{ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. }
{ }
{ See the GNU General Public License for more details. }
{ }
{----------------------------------------------------------------------------}
{ Updated on : }
{ Updated by : }
{ }
{----------------------------------------------------------------------------}
{ * Still dependent (to compile correctly) on: }
{ none }
{----------------------------------------------------------------------------}
{ * TODO: }
{ Test it!!!! }
{----------------------------------------------------------------------------}
unit r_drawa;
{$DEFINE NODEPEND}
interface
procedure R_ClipEdge;
implementation
uses Windows,
r_rast,
r_local,
{$IFNDEF NODEPEND}rw_Imp,
{$ENDIF}qasm_inc,
d_if_inc,
r_varsa;
{$DEFINE id386}
{$IFDEF id386}
{$IFDEF NODEPEND}
var
fpu_ceil_cw, fpu_chop_cw, fpu_full_cw, fpu_cw, fpu_pushed_cw: Word;
fpu_sp24_cw, fpu_sp24_ceil_cw: Word;
// CAK - This function calculates the floating point control words
// CAK - needed for various floating point modes (rounding, truncating, etc.)
// CAK - and stores them in the variables.
// CAK - This function doesn't actually change the floating point control word
// CAK - in the Maths coprocessor, or do anything harmful.
procedure Sys_SetFPCW; assembler;
asm
xor eax, eax // CAK eax = 0
fnstcw word ptr fpu_cw // CAK fpu_cw = Maths Coprocessor's Floating Point Control Word
mov ax, word ptr fpu_cw // CAK ax = fpu_cw
and ah, 0f0h
or ah, 003h // round to nearest mode, extended precision
mov fpu_full_cw, ax
and ah, 0f0h
or ah, 00fh // RTZ/truncate/chop mode, extended precision
mov fpu_chop_cw, ax
and ah, 0f0h
or ah, 00bh // ceil mode, extended precision
mov fpu_ceil_cw, ax
and ah, 0f0h // round to nearest, 24-bit single precision
mov fpu_sp24_cw, ax
and ah, 0f0h // ceil mode, 24-bit single precision
or ah, 008h //
mov fpu_sp24_ceil_cw, ax
end;
{$ENDIF}
// !!! if these are changed, they must be changed in r_draw.c too !!!
const
FULLY_CLIPPED_CACHED = $80000000;
FRAMECOUNT_MASK = $7FFFFFFF;
var
Ld0: Single = 0.0;
Ld1: Single = 0.0;
Lstack: LongInt = 0;
Lfp_near_clip: Single = NEAR_CLIP;
Lceilv0: LongInt = 0;
Lv: LongInt = 0;
Lu0: LongInt = 0;
Lv0: LongInt = 0;
Lzi0: LongInt = 0;
//----------------------------------------------------------------------
// edge clipping code
//----------------------------------------------------------------------
const
pv0 = 4 + 12;
pv1 = 8 + 12;
clip = 12 + 12;
// align 4
procedure R_ClipEdge; assembler;
label
Lemit, Lcliploop, Lcontinue, LCalcFirst, LCalcSecond;
label
LTransformAndProject, LPop5AndDone, LDoPop, Ldone;
label
LSide0, LSide1, LSideDone, LNotFirst, LDoFirst;
label
LSetRemove, LFindInsertLoop, LInsertFound;
label
LP0, LP1, LP2, LP4, LP5;
label
Lp1_, Lp2_, Lp3_;
label
Ltestright, Ltestright2, LNoClip;
label
LClampP0, LClampP1, LClampP2, LClampP3;
asm
push esi // preserve register variables
push edi
push ebx
mov ds:dword ptr[Lstack],esp // for clearing the stack later
// float d0, d1, f;
// mvertex_t clipvert;
mov ebx,ds:dword ptr[clip+esp]
mov esi,ds:dword ptr[pv0+esp]
mov edx,ds:dword ptr[pv1+esp]
// if (clip)
// {
test ebx,ebx
jz Lemit
// do
// {
Lcliploop:
// d0 = DotProduct (pv0->position, clip->normal) - clip->dist;
// d1 = DotProduct (pv1->position, clip->normal) - clip->dist;
fld ds:dword ptr[mv_position+0+esi]
fmul ds:dword ptr[cp_normal+0+ebx]
fld ds:dword ptr[mv_position+4+esi]
fmul ds:dword ptr[cp_normal+4+ebx]
fld ds:dword ptr[mv_position+8+esi]
fmul ds:dword ptr[cp_normal+8+ebx]
fxch st(1)
faddp st(2),st(0) // d0mul2 | d0add0
fld ds:dword ptr[mv_position+0+edx]
fmul ds:dword ptr[cp_normal+0+ebx]
fld ds:dword ptr[mv_position+4+edx]
fmul ds:dword ptr[cp_normal+4+ebx]
fld ds:dword ptr[mv_position+8+edx]
fmul ds:dword ptr[cp_normal+8+ebx]
fxch st(1)
faddp st(2),st(0) // d1mul2 | d1add0 | d0mul2 | d0add0
fxch st(3) // d0add0 | d1add0 | d0mul2 | d1mul2
faddp st(2),st(0) // d1add0 | dot0 | d1mul2
faddp st(2),st(0) // dot0 | dot1
fsub ds:dword ptr[cp_dist+ebx] // d0 | dot1
fxch st(1) // dot1 | d0
fsub ds:dword ptr[cp_dist+ebx] // d1 | d0
fxch st(1)
fstp ds:dword ptr[Ld0]
fstp ds:dword ptr[Ld1]
// if (d0 >= 0)
// {
mov eax,ds:dword ptr[Ld0]
mov ecx,ds:dword ptr[Ld1]
or ecx,eax
js Lp2_
// both points are unclipped
Lcontinue:
//
// R_ClipEdge (&clipvert, pv1, clip->next);
// return;
// }
// } while ((clip = clip->next) != NULL);
mov ebx,ds:dword ptr[cp_next+ebx]
test ebx,ebx
jnz Lcliploop
// }
//// add the edge
// R_EmitEdge (pv0, pv1);
Lemit:
//
// set integer rounding to ceil mode, set to single precision
//
// FIXME: do away with by manually extracting integers from floats?
// FIXME: set less often
fldcw ds:word ptr[fpu_ceil_cw]
// edge_t *edge, *pcheck;
// int u_check;
// float u, u_step;
// vec3_t local, transformed;
// float *world;
// int v, v2, ceilv0;
// float scale, lzi0, u0, v0;
// int side;
// if (r_lastvertvalid)
// {
cmp ds:dword ptr[r_lastvertvalid],0
jz LCalcFirst
// u0 = r_u1;
// v0 = r_v1;
// lzi0 = r_lzi1;
// ceilv0 = r_ceilv1;
mov eax,ds:dword ptr[r_lzi1]
mov ecx,ds:dword ptr[r_u1]
mov ds:dword ptr[Lzi0],eax
mov ds:dword ptr[Lu0],ecx
mov ecx,ds:dword ptr[r_v1]
mov eax,ds:dword ptr[r_ceilv1]
mov ds:dword ptr[Lv0],ecx
mov ds:dword ptr[Lceilv0],eax
jmp LCalcSecond
// }
LCalcFirst:
// else
// {
// world = &pv0->position[0];
call LTransformAndProject // v0 | lzi0 | u0
fst ds:dword ptr[Lv0]
fxch st(2) // u0 | lzi0 | v0
fstp ds:dword ptr[Lu0] // lzi0 | v0
fstp ds:dword ptr[Lzi0] // v0
// ceilv0 = (int)(v0 - 2000) + 2000; // ceil(v0);
fistp ds:dword ptr[Lceilv0]
// }
LCalcSecond:
// world = &pv1->position[0];
mov esi,edx
call LTransformAndProject // v1 | lzi1 | u1
fld ds:dword ptr[Lu0] // u0 | v1 | lzi1 | u1
fxch st(3) // u1 | v1 | lzi1 | u0
fld ds:dword ptr[Lzi0] // lzi0 | u1 | v1 | lzi1 | u0
fxch st(3) // lzi1 | u1 | v1 | lzi0 | u0
fld ds:dword ptr[Lv0] // v0 | lzi1 | u1 | v1 | lzi0 | u0
fxch st(3) // v1 | lzi1 | u1 | v0 | lzi0 | u0
// r_ceilv1 = (int)(r_v1 - 2000) + 2000; // ceil(r_v1);
fist ds:dword ptr[r_ceilv1]
fldcw ds:word ptr[fpu_chop_cw] // put back normal floating-point state
fst ds:dword ptr[r_v1]
fxch st(4) // lzi0 | lzi1 | u1 | v0 | v1 | u0
// if (r_lzi1 > lzi0)
// lzi0 = r_lzi1;
fcom st(1)
fnstsw ax
test ah,1
jz LP0
fstp st(0)
fld st(0)
LP0:
fxch st(1) // lzi1 | lzi0 | u1 | v0 | v1 | u0
fstp ds:dword ptr[r_lzi1] // lzi0 | u1 | v0 | v1 | u0
fxch st(1)
fst ds:dword ptr[r_u1]
fxch st(1)
// if (lzi0 > r_nearzi) // for mipmap finding
// r_nearzi = lzi0;
fcom ds:dword ptr[r_nearzi]
fnstsw ax
test ah,045h
jnz LP1
fst ds:dword ptr[r_nearzi]
LP1:
// // for right edges, all we want is the effect on 1/z
// if (r_nearzionly)
// return;
mov eax,ds:dword ptr[r_nearzionly]
test eax,eax
jz LP2
LPop5AndDone:
mov eax,ds:dword ptr[cacheoffset]
mov edx,ds:dword ptr[r_framecount]
cmp eax,07FFFFFFFh
jz LDoPop
and edx,offset FRAMECOUNT_MASK
or edx,offset FULLY_CLIPPED_CACHED
mov ds:dword ptr[cacheoffset],edx
LDoPop:
fstp st(0) // u1 | v0 | v1 | u0
fstp st(0) // v0 | v1 | u0
fstp st(0) // v1 | u0
fstp st(0) // u0
fstp st(0)
jmp Ldone
LP2:
// // create the edge
// if (ceilv0 == r_ceilv1)
// return; // horizontal edge
mov ebx,ds:dword ptr[Lceilv0]
mov edi,ds:dword ptr[_edge_p] // CAK - the var not the type
mov ecx,ds:dword ptr[r_ceilv1]
mov edx,edi
mov esi,ds:dword ptr[r_pedge]
add edx,offset et_size
cmp ebx,ecx
jz LPop5AndDone
mov eax,ds:dword ptr[r_pedge]
mov ds:dword ptr[et_owner+edi],eax
// side = ceilv0 > r_ceilv1;
//
// edge->nearzi = lzi0;
fstp ds:dword ptr[et_nearzi+edi] // u1 | v0 | v1 | u0
// if (side == 1)
// {
jc LSide0
LSide1:
// // leading edge (go from p2 to p1)
// u_step = ((u0 - r_u1) / (v0 - r_v1));
fsubp st(3),st(0) // v0 | v1 | u0-u1
fsub st(0),st(1) // v0-v1 | v1 | u0-u1
fdivp st(2),st(0) // v1 | ustep
// r_emitted = 1;
mov ds:dword ptr[r_emitted],1
// edge = edge_p++;
mov ds:dword ptr[_edge_p],edx
// pretouch next edge
mov eax,ds:dword ptr[edx]
// v2 = ceilv0 - 1;
// v = r_ceilv1;
mov eax,ecx
lea ecx,ds:dword ptr[-1+ebx]
mov ebx,eax
// edge->surfs[0] = 0;
// edge->surfs[1] = surface_p - surfaces;
mov eax,ds:dword ptr[surface_p]
mov esi,ds:dword ptr[surfaces]
sub edx,edx
sub eax,esi
shr eax,offset SURF_T_SHIFT
mov ds:dword ptr[et_surfs+edi],edx
mov ds:dword ptr[et_surfs+2+edi],eax
sub esi,esi
// u = r_u1 + ((float)v - r_v1) * u_step;
mov ds:dword ptr[Lv],ebx
fild ds:dword ptr[Lv] // v | v1 | ustep
fsubrp st(1),st(0) // v-v1 | ustep
fmul st(0),st(1) // (v-v1)*ustep | ustep
fadd ds:dword ptr[r_u1] // u | ustep
jmp LSideDone
// }
LSide0:
// else
// {
// // trailing edge (go from p1 to p2)
// u_step = ((r_u1 - u0) / (r_v1 - v0));
fsub st(0),st(3) // u1-u0 | v0 | v1 | u0
fxch st(2) // v1 | v0 | u1-u0 | u0
fsub st(0),st(1) // v1-v0 | v0 | u1-u0 | u0
fdivp st(2),st(0) // v0 | ustep | u0
// r_emitted = 1;
mov ds:dword ptr[r_emitted],1
// edge = edge_p++;
mov ds:dword ptr[_edge_p],edx
// pretouch next edge
mov eax,ds:dword ptr[edx]
// v = ceilv0;
// v2 = r_ceilv1 - 1;
dec ecx
// edge->surfs[0] = surface_p - surfaces;
// edge->surfs[1] = 0;
mov eax,ds:dword ptr[surface_p]
mov esi,ds:dword ptr[surfaces]
sub edx,edx
sub eax,esi
shr eax,offset SURF_T_SHIFT
mov ds:dword ptr[et_surfs+2+edi],edx
mov ds:dword ptr[et_surfs+edi],eax
mov esi,1
// u = u0 + ((float)v - v0) * u_step;
mov ds:dword ptr[Lv],ebx
fild ds:dword ptr[Lv] // v | v0 | ustep | u0
fsubrp st(1),st(0) // v-v0 | ustep | u0
fmul st(0),st(1) // (v-v0)*ustep | ustep | u0
faddp st(2),st(0) // ustep | u
fxch st(1) // u | ustep
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -