//************************************************************************** //** //** ## ## ## ## ## #### #### ### ### //** ## ## ## ## ## ## ## ## ## ## #### #### //** ## ## ## ## ## ## ## ## ## ## ## ## ## ## //** ## ## ######## ## ## ## ## ## ## ## ### ## //** ### ## ## ### ## ## ## ## ## ## //** # ## ## # #### #### ## ## //** //** $Id: d_aclip.cpp 1955 2007-01-10 21:19:55Z dj_jl $ //** //** Copyright (C) 1999-2006 Jānis Legzdiņš //** //** 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. //** //************************************************************************** //** //** clip routines for drawing Alias models directly to the screen //** //************************************************************************** // HEADER FILES ------------------------------------------------------------ #include "d_local.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- extern "C" { void D_Alias_clip_left(finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out, finalstvert_t *pst0, finalstvert_t *pst1, finalstvert_t *stout); void D_Alias_clip_right(finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out, finalstvert_t *pst0, finalstvert_t *pst1, finalstvert_t *stout); void D_Alias_clip_top(finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out, finalstvert_t *pst0, finalstvert_t *pst1, finalstvert_t *stout); void D_Alias_clip_bottom(finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out, finalstvert_t *pst0, finalstvert_t *pst1, finalstvert_t *stout); } // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static finalvert_t fv[2][8]; static finalstvert_t stv[2][8]; static auxvert_t av[8]; // CODE -------------------------------------------------------------------- //========================================================================== // // D_Alias_clip_z // // pfv0 is the unclipped vertex, pfv1 is the z-clipped vertex // //========================================================================== static void D_Alias_clip_z(finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out, finalstvert_t *pst0, finalstvert_t *pst1, finalstvert_t *stout) { float scale; auxvert_t *pav0, *pav1, avout; pav0 = &av[pfv0 - &fv[0][0]]; pav1 = &av[pfv1 - &fv[0][0]]; if (pfv0->v >= pfv1->v) { scale = (ALIAS_Z_CLIP_PLANE - pav0->fv[2]) / (pav1->fv[2] - pav0->fv[2]); avout.fv[0] = pav0->fv[0] + (pav1->fv[0] - pav0->fv[0]) * scale; avout.fv[1] = pav0->fv[1] + (pav1->fv[1] - pav0->fv[1]) * scale; avout.fv[2] = ALIAS_Z_CLIP_PLANE; stout->s = (int)(pst0->s + (pst1->s - pst0->s) * scale); stout->t = (int)(pst0->t + (pst1->t - pst0->t) * scale); out->r = (int)(pfv0->r + (pfv1->r - pfv0->r) * scale); out->g = (int)(pfv0->g + (pfv1->g - pfv0->g) * scale); out->b = (int)(pfv0->b + (pfv1->b - pfv0->b) * scale); } else { scale = (ALIAS_Z_CLIP_PLANE - pav1->fv[2]) / (pav0->fv[2] - pav1->fv[2]); avout.fv[0] = pav1->fv[0] + (pav0->fv[0] - pav1->fv[0]) * scale; avout.fv[1] = pav1->fv[1] + (pav0->fv[1] - pav1->fv[1]) * scale; avout.fv[2] = ALIAS_Z_CLIP_PLANE; stout->s = (int)(pst1->s + (pst0->s - pst1->s) * scale); stout->t = (int)(pst1->t + (pst0->t - pst1->t) * scale); out->r = (int)(pfv1->r + (pfv0->r - pfv1->r) * scale); out->g = (int)(pfv1->g + (pfv0->g - pfv1->g) * scale); out->b = (int)(pfv1->b + (pfv0->b - pfv1->b) * scale); } D_AliasProjectFinalVert(out, &avout); if (out->u < 0) out->flags |= ALIAS_LEFT_CLIP; if (out->v < 0) out->flags |= ALIAS_TOP_CLIP; if (out->u > viewwidth) out->flags |= ALIAS_RIGHT_CLIP; if (out->v > viewheight) out->flags |= ALIAS_BOTTOM_CLIP; } #if !USE_ASM_I386 //========================================================================== // // D_Alias_clip_left // //========================================================================== extern "C" void D_Alias_clip_left(finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out, finalstvert_t *pst0, finalstvert_t *pst1, finalstvert_t *stout) { float scale; if (pfv0->v >= pfv1->v) { scale = (float)(0 - pfv0->u) / (pfv1->u - pfv0->u); out->u = (int)(pfv0->u + (pfv1->u - pfv0->u)*scale + 0.5); out->v = (int)(pfv0->v + (pfv1->v - pfv0->v)*scale + 0.5); stout->s = (int)(pst0->s + (pst1->s - pst0->s)*scale + 0.5); stout->t = (int)(pst0->t + (pst1->t - pst0->t)*scale + 0.5); out->zi = (int)(pfv0->zi + (pfv1->zi - pfv0->zi)*scale + 0.5); out->r = (int)(pfv0->r + (pfv1->r - pfv0->r)*scale + 0.5); out->g = (int)(pfv0->g + (pfv1->g - pfv0->g)*scale + 0.5); out->b = (int)(pfv0->b + (pfv1->b - pfv0->b)*scale + 0.5); } else { scale = (float)(0 - pfv1->u) / (pfv0->u - pfv1->u); out->u = (int)(pfv1->u + (pfv0->u - pfv1->u)*scale + 0.5); out->v = (int)(pfv1->v + (pfv0->v - pfv1->v)*scale + 0.5); stout->s = (int)(pst1->s + (pst0->s - pst1->s)*scale + 0.5); stout->t = (int)(pst1->t + (pst0->t - pst1->t)*scale + 0.5); out->zi = (int)(pfv1->zi + (pfv0->zi - pfv1->zi)*scale + 0.5); out->r = (int)(pfv1->r + (pfv0->r - pfv1->r)*scale + 0.5); out->g = (int)(pfv1->g + (pfv0->g - pfv1->g)*scale + 0.5); out->b = (int)(pfv1->b + (pfv0->b - pfv1->b)*scale + 0.5); } } //========================================================================== // // D_Alias_clip_right // //========================================================================== extern "C" void D_Alias_clip_right(finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out, finalstvert_t *pst0, finalstvert_t *pst1, finalstvert_t *stout) { float scale; if (pfv0->v >= pfv1->v) { scale = (float)(viewwidth - pfv0->u) / (pfv1->u - pfv0->u); out->u = (int)(pfv0->u + (pfv1->u - pfv0->u)*scale + 0.5); out->v = (int)(pfv0->v + (pfv1->v - pfv0->v)*scale + 0.5); stout->s = (int)(pst0->s + (pst1->s - pst0->s)*scale + 0.5); stout->t = (int)(pst0->t + (pst1->t - pst0->t)*scale + 0.5); out->zi = (int)(pfv0->zi + (pfv1->zi - pfv0->zi)*scale + 0.5); out->r = (int)(pfv0->r + (pfv1->r - pfv0->r)*scale + 0.5); out->g = (int)(pfv0->g + (pfv1->g - pfv0->g)*scale + 0.5); out->b = (int)(pfv0->b + (pfv1->b - pfv0->b)*scale + 0.5); } else { scale = (float)(viewwidth - pfv1->u) / (pfv0->u - pfv1->u); out->u = (int)(pfv1->u + (pfv0->u - pfv1->u)*scale + 0.5); out->v = (int)(pfv1->v + (pfv0->v - pfv1->v)*scale + 0.5); stout->s = (int)(pst1->s + (pst0->s - pst1->s)*scale + 0.5); stout->t = (int)(pst1->t + (pst0->t - pst1->t)*scale + 0.5); out->zi = (int)(pfv1->zi + (pfv0->zi - pfv1->zi)*scale + 0.5); out->r = (int)(pfv1->r + (pfv0->r - pfv1->r)*scale + 0.5); out->g = (int)(pfv1->g + (pfv0->g - pfv1->g)*scale + 0.5); out->b = (int)(pfv1->b + (pfv0->b - pfv1->b)*scale + 0.5); } } //========================================================================== // // D_Alias_clip_top // //========================================================================== extern "C" void D_Alias_clip_top(finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out, finalstvert_t *pst0, finalstvert_t *pst1, finalstvert_t *stout) { float scale; if (pfv0->v >= pfv1->v) { scale = (float)(0 - pfv0->v) / (pfv1->v - pfv0->v); out->u = (int)(pfv0->u + (pfv1->u - pfv0->u)*scale + 0.5); out->v = (int)(pfv0->v + (pfv1->v - pfv0->v)*scale + 0.5); stout->s = (int)(pst0->s + (pst1->s - pst0->s)*scale + 0.5); stout->t = (int)(pst0->t + (pst1->t - pst0->t)*scale + 0.5); out->zi = (int)(pfv0->zi + (pfv1->zi - pfv0->zi)*scale + 0.5); out->r = (int)(pfv0->r + (pfv1->r - pfv0->r)*scale + 0.5); out->g = (int)(pfv0->g + (pfv1->g - pfv0->g)*scale + 0.5); out->b = (int)(pfv0->b + (pfv1->b - pfv0->b)*scale + 0.5); } else { scale = (float)(0 - pfv1->v) / (pfv0->v - pfv1->v); out->u = (int)(pfv1->u + (pfv0->u - pfv1->u)*scale + 0.5); out->v = (int)(pfv1->v + (pfv0->v - pfv1->v)*scale + 0.5); stout->s = (int)(pst1->s + (pst0->s - pst1->s)*scale + 0.5); stout->t = (int)(pst1->t + (pst0->t - pst1->t)*scale + 0.5); out->zi = (int)(pfv1->zi + (pfv0->zi - pfv1->zi)*scale + 0.5); out->r = (int)(pfv1->r + (pfv0->r - pfv1->r)*scale + 0.5); out->g = (int)(pfv1->g + (pfv0->g - pfv1->g)*scale + 0.5); out->b = (int)(pfv1->b + (pfv0->b - pfv1->b)*scale + 0.5); } } //========================================================================== // // D_Alias_clip_bottom // //========================================================================== extern "C" void D_Alias_clip_bottom(finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out, finalstvert_t *pst0, finalstvert_t *pst1, finalstvert_t *stout) { float scale; if (pfv0->v >= pfv1->v) { scale = (float)(viewheight - pfv0->v) / (pfv1->v - pfv0->v); out->u = (int)(pfv0->u + (pfv1->u - pfv0->u)*scale + 0.5); out->v = (int)(pfv0->v + (pfv1->v - pfv0->v)*scale + 0.5); stout->s = (int)(pst0->s + (pst1->s - pst0->s)*scale + 0.5); stout->t = (int)(pst0->t + (pst1->t - pst0->t)*scale + 0.5); out->zi = (int)(pfv0->zi + (pfv1->zi - pfv0->zi)*scale + 0.5); out->r = (int)(pfv0->r + (pfv1->r - pfv0->r)*scale + 0.5); out->g = (int)(pfv0->g + (pfv1->g - pfv0->g)*scale + 0.5); out->b = (int)(pfv0->b + (pfv1->b - pfv0->b)*scale + 0.5); } else { scale = (float)(viewheight - pfv1->v) / (pfv0->v - pfv1->v); out->u = (int)(pfv1->u + (pfv0->u - pfv1->u)*scale + 0.5); out->v = (int)(pfv1->v + (pfv0->v - pfv1->v)*scale + 0.5); stout->s = (int)(pst1->s + (pst0->s - pst1->s)*scale + 0.5); stout->t = (int)(pst1->t + (pst0->t - pst1->t)*scale + 0.5); out->zi = (int)(pfv1->zi + (pfv0->zi - pfv1->zi)*scale + 0.5); out->r = (int)(pfv1->r + (pfv0->r - pfv1->r)*scale + 0.5); out->g = (int)(pfv1->g + (pfv0->g - pfv1->g)*scale + 0.5); out->b = (int)(pfv1->b + (pfv0->b - pfv1->b)*scale + 0.5); } } #endif //========================================================================== // // D_AliasClip // //========================================================================== static int D_AliasClip(finalvert_t *in, finalvert_t *out, finalstvert_t *stin, finalstvert_t *stout, int flag, int count, void(*clip)(finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out, finalstvert_t *pst0, finalstvert_t *pst1, finalstvert_t *stout) ) { int i,j,k; int flags, oldflags; j = count-1; k = 0; for (i=0 ; i viewwidth) out[k].flags |= ALIAS_RIGHT_CLIP; if (out[k].v > viewheight) out[k].flags |= ALIAS_BOTTOM_CLIP; k++; } if (!flags) { out[k] = in[i]; stout[k] = stin[i]; k++; } } return k; } //========================================================================== // // VSoftwareDrawer::AliasClipTriangle // //========================================================================== void VSoftwareDrawer::AliasClipTriangle(mtriangle_t *ptri) { int i, k, pingpong; mtriangle_t mtri; unsigned clipflags; // copy vertexes fv[0][0] = pfinalverts[ptri->vertindex[0]]; fv[0][1] = pfinalverts[ptri->vertindex[1]]; fv[0][2] = pfinalverts[ptri->vertindex[2]]; stv[0][0] = pfinalstverts[ptri->stvertindex[0]]; stv[0][1] = pfinalstverts[ptri->stvertindex[1]]; stv[0][2] = pfinalstverts[ptri->stvertindex[2]]; // clip clipflags = fv[0][0].flags | fv[0][1].flags | fv[0][2].flags; if (clipflags & ALIAS_Z_CLIP) { for (i=0 ; i<3 ; i++) av[i] = pauxverts[ptri->vertindex[i]]; k = D_AliasClip(fv[0], fv[1], stv[0], stv[1], ALIAS_Z_CLIP, 3, D_Alias_clip_z); if (k == 0) return; pingpong = 1; clipflags = fv[1][0].flags | fv[1][1].flags | fv[1][2].flags; } else { pingpong = 0; k = 3; } if (clipflags & ALIAS_LEFT_CLIP) { k = D_AliasClip(fv[pingpong], fv[pingpong ^ 1], stv[pingpong], stv[pingpong ^ 1], ALIAS_LEFT_CLIP, k, D_Alias_clip_left); if (k == 0) return; pingpong ^= 1; } if (clipflags & ALIAS_RIGHT_CLIP) { k = D_AliasClip(fv[pingpong], fv[pingpong ^ 1], stv[pingpong], stv[pingpong ^ 1], ALIAS_RIGHT_CLIP, k, D_Alias_clip_right); if (k == 0) return; pingpong ^= 1; } if (clipflags & ALIAS_BOTTOM_CLIP) { k = D_AliasClip(fv[pingpong], fv[pingpong ^ 1], stv[pingpong], stv[pingpong ^ 1], ALIAS_BOTTOM_CLIP, k, D_Alias_clip_bottom); if (k == 0) return; pingpong ^= 1; } if (clipflags & ALIAS_TOP_CLIP) { k = D_AliasClip(fv[pingpong], fv[pingpong ^ 1], stv[pingpong], stv[pingpong ^ 1], ALIAS_TOP_CLIP, k, D_Alias_clip_top); if (k == 0) return; pingpong ^= 1; } for (i=0 ; i viewwidth) fv[pingpong][i].u = viewwidth; if (fv[pingpong][i].v < 0) fv[pingpong][i].v = 0; else if (fv[pingpong][i].v > viewheight) fv[pingpong][i].v = viewheight; fv[pingpong][i].flags = 0; } // draw triangles d_affinetridesc.ptriangles = &mtri; d_affinetridesc.pfinalverts = fv[pingpong]; d_affinetridesc.pstverts = stv[pingpong]; // FIXME: do all at once as trifan? mtri.vertindex[0] = 0; mtri.stvertindex[0] = 0; for (i=1 ; i