brender-1997/pentprim/AWTMI.H
2022-05-03 14:31:40 -07:00

211 lines
7.3 KiB
C

/*
* Copyright (c) 1993-1995 Argonaut Technologies Limited. All rights reserved.
*
* $Id: AWTMI.H 1.3 1996/12/10 16:46:39 jon Exp $
*
* Triangle renderer for arbitrary width linear texture mapping
*/
void BR_ASM_CALL
FNAME(struct brp_block *block, union brp_vertex *a,union brp_vertex *b,union brp_vertex *c)
{
/* v[0] and v[1] contain the (fractional) screen coordinates */
/* And comp_x[C_W] contain the 3-space z-value */
/* (v[0]-width/2)*comp_x[C_W] gives the 3-space x-values */
/* Similarly for y */
int sxa,sxb,sxc,sya,syb,syc;
int dv_int;
int offset;
int grad;
br_fixed_ls g_divisor,dp1,dp2;
int dv_int_nocarry;
int dv_int_carry;
int v_int_current;
int direction;
/* Optimal sort of 3 elements? */
if (a->comp_x[C_SY]>b->comp_x[C_SY]) {
if (b->comp_x[C_SY]>c->comp_x[C_SY]) {
swap(union brp_vertex *,a,c);
} else {
if (a->comp_x[C_SY]>c->comp_x[C_SY]) {
swap(union brp_vertex *,a,b);
swap(union brp_vertex *,b,c);
} else {
swap(union brp_vertex *,a,b);
}
}
} else {
if (b->comp_x[C_SY]>c->comp_x[C_SY]) {
if (a->comp_x[C_SY]>c->comp_x[C_SY]) {
swap(union brp_vertex *,b,c);
swap(union brp_vertex *,a,b);
} else {
swap(union brp_vertex *,b,c);
}
}
}
sxa = sar16(a->comp_x[C_SX]);
sya = sar16(a->comp_x[C_SY]);
sxb = sar16(b->comp_x[C_SX]);
syb = sar16(b->comp_x[C_SY]);
sxc = sar16(c->comp_x[C_SX]);
syc = sar16(c->comp_x[C_SY]);
work.top.x = sxb-sxa;
work.top.y = syb-sya;
work.bot.x = sxc-sxb;
work.bot.y = syc-syb;
work.main.x = sxc-sxa;
work.main.y = syc-sya;
work.main.grad = work.main.x*_reciprocal[work.main.y];
work.main.d_f = work.main.grad << 16;
grad = sar16(work.main.grad);
work.main.d_i = grad+work.colour.stride_p;
work.top.grad = work.top.y ? work.top.x*_reciprocal[work.top.y] : 0;
work.top.d_f = work.top.grad << 16;
work.top.d_i = sar16(work.top.grad)+work.colour.stride_p;
work.main.f = work.top.f = 0x80000000;
offset = high16(a->comp_x[C_SX])+high16(a->comp_x[C_SY])*((int)work.colour.stride_p);
work.awsl.start = work.awsl.end = (char *)work.colour.base+offset*DBPP;
#if ZB
work.awsl.zstart = (char *)work.depth.base +offset*2;
#endif
work.top.count = syb-sya;
work.bot.f = 0x80000000;
work.bot.grad = work.bot.y ? work.bot.x*_reciprocal[work.bot.y] : 0;
work.bot.d_f = work.bot.grad << 16;
work.bot.d_i = sar16(work.bot.grad)+work.colour.stride_p;
work.bot.count = syc-syb;
g_divisor = work.top.x*work.main.y-work.main.x*work.top.y;
if (!g_divisor) return;
direction = work.top.count && work.top.grad>=work.main.grad ||
work.bot.count && work.bot.grad<work.main.grad;
#define PARAM_SETUP(param,p) {\
dp1 = b->p-a->p;\
dp2 = c->p-a->p;\
param.grad_x = SafeFixedMac2Div(dp1,work.main.y,-dp2,work.top.y,g_divisor);\
param.grad_y = SafeFixedMac2Div(dp2,work.top.x,-dp1,work.main.x,g_divisor);\
param.current = a->p+param.grad_x/2;\
param.d_nocarry = BrFixedToInt(work.main.grad)*param.grad_x+param.grad_y;\
param.d_carry = param.d_nocarry+param.grad_x;\
}
#define PARAM_SETUP_UNSIGNED(param,p) {\
dp1 = b->p-a->p;\
dp2 = c->p-a->p;\
param.grad_x = SafeFixedMac2Div(dp1,work.main.y,-dp2,work.top.y,g_divisor);\
param.grad_y = SafeFixedMac2Div(dp2,work.top.x,-dp1,work.main.x,g_divisor);\
param.current = (a->p+param.grad_x/2) ^ 0x80000000;\
param.d_nocarry = BrFixedToInt(work.main.grad)*param.grad_x+param.grad_y;\
param.d_carry = param.d_nocarry+param.grad_x;\
}
#if LIGHT
PARAM_SETUP(work.pi,comp_x[C_I]);
#endif
#if ZB
PARAM_SETUP_UNSIGNED(work.pz,comp_x[C_SZ]);
#endif
PARAM_SETUP(work.pu,comp_x[C_U]);
PARAM_SETUP(work.pv,comp_x[C_V]);
work.awsl.du_nocarry = work.pu.d_nocarry << 16;
work.awsl.dv_nocarry = work.pv.d_nocarry << 16;
work.awsl.du_carry = work.pu.d_carry << 16;
work.awsl.dv_carry = work.pv.d_carry << 16;
work.awsl.u_current = work.pu.current << 16;
work.awsl.v_current = work.pv.current << 16;
/*
* Per scan line increments
*/
if (powerof2(work.texture.width_p)) {
work.awsl.du_int_nocarry = (sar16(work.pu.d_nocarry) & work.texture.width_p-1)
-work.texture.width_p;
work.awsl.du_int_carry = (sar16(work.pu.d_carry) & work.texture.width_p-1)
-work.texture.width_p;
work.awsl.u_int_current = sar16(work.pu.current) & work.texture.width_p-1;
} else {
work.awsl.du_int_nocarry = sar16(work.pu.d_nocarry) % (int)work.texture.width_p;
work.awsl.du_int_carry = sar16(work.pu.d_carry) % (int)work.texture.width_p;
work.awsl.u_int_current = sar16(work.pu.current) % (int)work.texture.width_p;
if (work.awsl.du_int_nocarry>=0) work.awsl.du_int_nocarry -= work.texture.width_p;
if (work.awsl.du_int_carry>=0) work.awsl.du_int_carry -= work.texture.width_p;
if (work.awsl.u_int_current<0) work.awsl.u_int_current += work.texture.width_p;
}
if (powerof2(work.texture.height)) {
dv_int_nocarry = (sar16(work.pv.d_nocarry) & work.texture.height-1)
-work.texture.height;
dv_int_carry = (sar16(work.pv.d_carry) & work.texture.height-1)
-work.texture.height;
v_int_current = sar16(work.pv.current) & work.texture.height-1;
} else {
dv_int_nocarry = sar16(work.pv.d_nocarry) % (int)work.texture.height;
dv_int_carry = sar16(work.pv.d_carry) % (int)work.texture.height;
v_int_current = sar16(work.pv.current) % (int)work.texture.height;
if (dv_int_nocarry>=0) dv_int_nocarry -= work.texture.height;
if (dv_int_carry>=0) dv_int_carry -= work.texture.height;
if (v_int_current<0) v_int_current += work.texture.height;
}
work.awsl.dsource_nocarry = work.awsl.du_int_nocarry*SBPP+work.texture.stride_b*dv_int_nocarry;
work.awsl.dsource_carry = work.awsl.du_int_carry*SBPP+work.texture.stride_b*dv_int_carry;
work.awsl.source_current = (char *)work.texture.base + work.awsl.u_int_current*SBPP+work.texture.stride_b*v_int_current;
work.awsl.u_int_current += 0x8000;
if (direction) {
work.awsl.du = work.pu.grad_x << 16;
work.awsl.dv = work.pv.grad_x << 16;
work.awsl.du_int = sar16(work.pu.grad_x) % (int)work.texture.width_p;
if (powerof2(work.texture.height))
dv_int = (sar16(work.pv.grad_x) & work.texture.height-1)-work.texture.height;
else {
dv_int = sar16(work.pv.grad_x) % (int)work.texture.height;
if (dv_int>=0) dv_int -= work.texture.height;
}
} else {
work.awsl.du = -work.pu.grad_x << 16;
work.awsl.dv = -work.pv.grad_x << 16;
work.awsl.du_int = sar16(-work.pu.grad_x) % (int)work.texture.width_p;
if (powerof2(work.texture.height)) {
dv_int = (sar16(-work.pv.grad_x) & work.texture.height-1)-work.texture.height;
} else
dv_int = sar16(-work.pv.grad_x) % (int)work.texture.height;
if (dv_int>=0) dv_int -= work.texture.height;
}
if (work.awsl.du_int>=0) work.awsl.du_int -= work.texture.width_p;
work.awsl.dsource = work.awsl.du_int*SBPP+work.texture.stride_b*dv_int;
work.awsl.edge = &work.top;
ASSERT(work.awsl.source_current>=work.texture.base);
TNAME();
work.awsl.end = (char *)work.colour.base + high16(b->comp_x[C_SX])*DBPP+high16(b->comp_x[C_SY])*work.colour.stride_b;
work.awsl.edge = &work.bot;
ASSERT(work.awsl.source_current>=work.texture.base);
TNAME();
}