/*
===========================================================================

Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. 

This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").  

Doom 3 BFG Edition Source Code 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 3 of the License, or
(at your option) any later version.

Doom 3 BFG Edition Source Code 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.

You should have received a copy of the GNU General Public License
along with Doom 3 BFG Edition Source Code.  If not, see <http://www.gnu.org/licenses/>.

In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code.  If not, please request a copy in writing from id Software at the address below.

If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.

===========================================================================
*/

#include "Precompiled.h"
#include "globaldata.h"





#include <stdlib.h>

#include "i_system.h"

#include "doomdef.h"
#include "doomstat.h"

#include "r_local.h"
#include "r_sky.h"


// OPTIMIZE: closed two sided ::g->lines as single sided

// True if any of the ::g->segs textures might be visible.

// False if the back side is the same plane.



// angle to line origin

//
// regular wall
//










//
// R_RenderMaskedSegRange
//
void
R_RenderMaskedSegRange
( drawseg_t*	ds,
  int		x1,
  int		x2 )
{
    unsigned		index;
    postColumn_t*	col;
    int				lightnum;
    int				texnum;
    
    // Calculate light table.
    // Use different light tables
    //   for horizontal / vertical / diagonal. Diagonal?
    // OPTIMIZE: get rid of LIGHTSEGSHIFT globally
    ::g->curline = ds->curline;
    ::g->frontsector = ::g->curline->frontsector;
    ::g->backsector = ::g->curline->backsector;
    texnum = ::g->texturetranslation[::g->curline->sidedef->midtexture];
	
    lightnum = (::g->frontsector->lightlevel >> LIGHTSEGSHIFT)+::g->extralight;

    if (::g->curline->v1->y == ::g->curline->v2->y)
	lightnum--;
    else if (::g->curline->v1->x == ::g->curline->v2->x)
	lightnum++;

    if (lightnum < 0)		
	::g->walllights = ::g->scalelight[0];
    else if (lightnum >= LIGHTLEVELS)
	::g->walllights = ::g->scalelight[LIGHTLEVELS-1];
    else
	::g->walllights = ::g->scalelight[lightnum];

    ::g->maskedtexturecol = ds->maskedtexturecol;

    ::g->rw_scalestep = ds->scalestep;		
    ::g->spryscale = ds->scale1 + (x1 - ds->x1)*::g->rw_scalestep;
    ::g->mfloorclip = ds->sprbottomclip;
    ::g->mceilingclip = ds->sprtopclip;
    
    // find positioning
    if (::g->curline->linedef->flags & ML_DONTPEGBOTTOM)
    {
	::g->dc_texturemid = ::g->frontsector->floorheight > ::g->backsector->floorheight
	    ? ::g->frontsector->floorheight : ::g->backsector->floorheight;
	::g->dc_texturemid = ::g->dc_texturemid + ::g->s_textureheight[texnum] - ::g->viewz;
    }
    else
    {
	::g->dc_texturemid =::g->frontsector->ceilingheight < ::g->backsector->ceilingheight
	    ? ::g->frontsector->ceilingheight : ::g->backsector->ceilingheight;
	::g->dc_texturemid = ::g->dc_texturemid - ::g->viewz;
    }
    ::g->dc_texturemid += ::g->curline->sidedef->rowoffset;
			
    if (::g->fixedcolormap)
	::g->dc_colormap = ::g->fixedcolormap;
    
    // draw the columns
    for (::g->dc_x = x1 ; ::g->dc_x <= x2 ; ::g->dc_x++)
    {
	// calculate lighting
	if (::g->maskedtexturecol[::g->dc_x] != SHRT_MAX)
	{
	    if (!::g->fixedcolormap)
	    {
		index = ::g->spryscale>>LIGHTSCALESHIFT;

		if (index >=  MAXLIGHTSCALE )
		    index = MAXLIGHTSCALE-1;

		::g->dc_colormap = ::g->walllights[index];
	    }
			
	    ::g->sprtopscreen = ::g->centeryfrac - FixedMul(::g->dc_texturemid, ::g->spryscale);
	    ::g->dc_iscale = 0xffffffffu / (unsigned)::g->spryscale;
	    
	    // draw the texture
	    col = (postColumn_t *)( 
		(byte *)R_GetColumn(texnum,::g->maskedtexturecol[::g->dc_x]) -3);
			
	    R_DrawMaskedColumn (col);
	    ::g->maskedtexturecol[::g->dc_x] = SHRT_MAX;
	}
	::g->spryscale += ::g->rw_scalestep;
    }
	
}




//
// R_RenderSegLoop
// Draws zero, one, or two textures (and possibly a masked
//  texture) for walls.
// Can draw or mark the starting pixel of floor and ceiling
//  textures.
// CALLED: CORE LOOPING ROUTINE.
//

void R_RenderSegLoop (void)
{
    angle_t		angle;
    unsigned		index;
    int			yl;
    int			yh;
    int			mid;
    fixed_t		texturecolumn;
    int			top;
    int			bottom;

    texturecolumn = 0;				// shut up compiler warning
	
    for ( ; ::g->rw_x < ::g->rw_stopx ; ::g->rw_x++)
    {
		// mark floor / ceiling areas
		yl = (::g->topfrac+HEIGHTUNIT-1)>>HEIGHTBITS;

		// no space above wall?
		if (yl < ::g->ceilingclip[::g->rw_x]+1)
			yl = ::g->ceilingclip[::g->rw_x]+1;
		
		if (::g->markceiling)
		{
			top = ::g->ceilingclip[::g->rw_x]+1;
			bottom = yl-1;

			if (bottom >= ::g->floorclip[::g->rw_x])
				bottom = ::g->floorclip[::g->rw_x]-1;

			if (top <= bottom)
			{
				::g->ceilingplane->top[::g->rw_x] = top;
				::g->ceilingplane->bottom[::g->rw_x] = bottom;
			}
		}
		
		yh = ::g->bottomfrac>>HEIGHTBITS;

		if (yh >= ::g->floorclip[::g->rw_x])
			yh = ::g->floorclip[::g->rw_x]-1;

		if (::g->markfloor)
		{
			top = yh+1;
			bottom = ::g->floorclip[::g->rw_x]-1;
			if (top <= ::g->ceilingclip[::g->rw_x])
				top = ::g->ceilingclip[::g->rw_x]+1;
			if (top <= bottom)
			{
				::g->floorplane->top[::g->rw_x] = top;
				::g->floorplane->bottom[::g->rw_x] = bottom;
			}
		}
		
	// texturecolumn and lighting are independent of wall tiers
	if (::g->segtextured)
	{
	    // calculate texture offset
	    angle = (::g->rw_centerangle + ::g->xtoviewangle[::g->rw_x])>>ANGLETOFINESHIFT;
	    texturecolumn = ::g->rw_offset-FixedMul(finetangent[angle],::g->rw_distance);
	    texturecolumn >>= FRACBITS;
	    // calculate lighting
	    index = ::g->rw_scale>>LIGHTSCALESHIFT;

	    if (index >=  MAXLIGHTSCALE )
			index = MAXLIGHTSCALE-1;

	    ::g->dc_colormap = ::g->walllights[index];
	    ::g->dc_x = ::g->rw_x;
	    ::g->dc_iscale = 0xffffffffu / (unsigned)::g->rw_scale;
	}
	
	// draw the wall tiers
	if (::g->midtexture)
	{
	    // single sided line
	    ::g->dc_yl = yl;
	    ::g->dc_yh = yh;
	    ::g->dc_texturemid = ::g->rw_midtexturemid;
	    ::g->dc_source = R_GetColumn(::g->midtexture,texturecolumn);
	    colfunc ( ::g->dc_colormap, ::g->dc_source );
	    ::g->ceilingclip[::g->rw_x] = ::g->viewheight;
	    ::g->floorclip[::g->rw_x] = -1;
	}
	else
	{
	    // two sided line
	    if (::g->toptexture)
	    {
			// top wall
			mid = ::g->pixhigh>>HEIGHTBITS;
			::g->pixhigh += ::g->pixhighstep;

			if (mid >= ::g->floorclip[::g->rw_x])
				mid = ::g->floorclip[::g->rw_x]-1;

			if (mid >= yl)
			{
				::g->dc_yl = yl;
				::g->dc_yh = mid;
				::g->dc_texturemid = ::g->rw_toptexturemid;
				::g->dc_source = R_GetColumn(::g->toptexture,texturecolumn);
				colfunc ( ::g->dc_colormap, ::g->dc_source );
				::g->ceilingclip[::g->rw_x] = mid;
			}
			else
				::g->ceilingclip[::g->rw_x] = yl-1;
		}
	    else
	    {
			// no top wall
			if (::g->markceiling)
				::g->ceilingclip[::g->rw_x] = yl-1;
		}
			
	    if (::g->bottomtexture)
	    {
			// bottom wall
			mid = (::g->pixlow+HEIGHTUNIT-1)>>HEIGHTBITS;
			::g->pixlow += ::g->pixlowstep;

			// no space above wall?
			if (mid <= ::g->ceilingclip[::g->rw_x])
				mid = ::g->ceilingclip[::g->rw_x]+1;
			
			if (mid <= yh)
			{
				::g->dc_yl = mid;
				::g->dc_yh = yh;
				::g->dc_texturemid = ::g->rw_bottomtexturemid;
				::g->dc_source = R_GetColumn(::g->bottomtexture,
							texturecolumn);
				colfunc ( ::g->dc_colormap, ::g->dc_source );
				::g->floorclip[::g->rw_x] = mid;
			}
			else
				::g->floorclip[::g->rw_x] = yh+1;
	    }
	    else
	    {
			// no bottom wall
			if (::g->markfloor)
				::g->floorclip[::g->rw_x] = yh+1;
			}
			
			if (::g->maskedtexture)
			{
				// save texturecol
				//  for backdrawing of masked mid texture
				::g->maskedtexturecol[::g->rw_x] = texturecolumn;
			}
		}
		
		::g->rw_scale += ::g->rw_scalestep;
		::g->topfrac += ::g->topstep;
		::g->bottomfrac += ::g->bottomstep;
    }
}




//
// R_StoreWallRange
// A wall segment will be drawn
//  between start and stop pixels (inclusive).
//
void
R_StoreWallRange
( int	start,
  int	stop )
{
    fixed_t		hyp;
    fixed_t		sineval;
    angle_t		distangle, offsetangle;
    fixed_t		vtop;
    int			lightnum;

    // don't overflow and crash
    if (::g->ds_p == &::g->drawsegs[MAXDRAWSEGS])
	return;		
		
#ifdef RANGECHECK
    if (start >=::g->viewwidth || start > stop)
	I_Error ("Bad R_RenderWallRange: %i to %i", start , stop);
#endif
    
    ::g->sidedef = ::g->curline->sidedef;
    ::g->linedef = ::g->curline->linedef;

    // mark the segment as visible for auto map
    ::g->linedef->flags |= ML_MAPPED;
    
    // calculate ::g->rw_distance for scale calculation
    ::g->rw_normalangle = ::g->curline->angle + ANG90;
	offsetangle = abs((int)(::g->rw_normalangle-::g->rw_angle1));
    
    if (offsetangle > ANG90)
	offsetangle = ANG90;

    distangle = ANG90 - offsetangle;
    hyp = R_PointToDist (::g->curline->v1->x, ::g->curline->v1->y);
    sineval = finesine[distangle>>ANGLETOFINESHIFT];
    ::g->rw_distance = FixedMul (hyp, sineval);
		
	
    ::g->ds_p->x1 = ::g->rw_x = start;
    ::g->ds_p->x2 = stop;
    ::g->ds_p->curline = ::g->curline;
    ::g->rw_stopx = stop+1;
    
    // calculate scale at both ends and step
	extern angle_t GetViewAngle();
    ::g->ds_p->scale1 = ::g->rw_scale = 
	R_ScaleFromGlobalAngle (GetViewAngle() + ::g->xtoviewangle[start]);
    
    if (stop > start )
    {
	::g->ds_p->scale2 = R_ScaleFromGlobalAngle (GetViewAngle() + ::g->xtoviewangle[stop]);
	::g->ds_p->scalestep = ::g->rw_scalestep = 
	    (::g->ds_p->scale2 - ::g->rw_scale) / (stop-start);
    }
    else
    {
	// UNUSED: try to fix the stretched line bug
#if 0
	if (::g->rw_distance < FRACUNIT/2)
	{
	    fixed_t		trx,try;
	    fixed_t		gxt,gyt;

	extern fixed_t GetViewX(); extern fixed_t GetViewY(); 
	    trx = ::g->curline->v1->x - GetViewX();
	    try = ::g->curline->v1->y - GetVewY();
			
	    gxt = FixedMul(trx,::g->viewcos); 
	    gyt = -FixedMul(try,::g->viewsin); 
	    ::g->ds_p->scale1 = FixedDiv(::g->projection, gxt-gyt) << ::g->detailshift;
	}
#endif
	::g->ds_p->scale2 = ::g->ds_p->scale1;
    }
    
    // calculate texture boundaries
    //  and decide if floor / ceiling marks are needed
    ::g->worldtop = ::g->frontsector->ceilingheight - ::g->viewz;
    ::g->worldbottom = ::g->frontsector->floorheight - ::g->viewz;
	
    ::g->midtexture = ::g->toptexture = ::g->bottomtexture = ::g->maskedtexture = 0;
    ::g->ds_p->maskedtexturecol = NULL;
	
    if (!::g->backsector)
    {
	// single sided line
	::g->midtexture = ::g->texturetranslation[::g->sidedef->midtexture];
	// a single sided line is terminal, so it must mark ends
	::g->markfloor = ::g->markceiling = true;
	if (::g->linedef->flags & ML_DONTPEGBOTTOM)
	{
	    vtop = ::g->frontsector->floorheight +
		::g->s_textureheight[::g->sidedef->midtexture];
	    // bottom of texture at bottom
	    ::g->rw_midtexturemid = vtop - ::g->viewz;	
	}
	else
	{
	    // top of texture at top
	    ::g->rw_midtexturemid = ::g->worldtop;
	}
	::g->rw_midtexturemid += ::g->sidedef->rowoffset;

	::g->ds_p->silhouette = SIL_BOTH;
	::g->ds_p->sprtopclip = ::g->screenheightarray;
	::g->ds_p->sprbottomclip = ::g->negonearray;
	::g->ds_p->bsilheight = MAXINT;
	::g->ds_p->tsilheight = MININT;
    }
    else
    {
	// two sided line
	::g->ds_p->sprtopclip = ::g->ds_p->sprbottomclip = NULL;
	::g->ds_p->silhouette = 0;
	
	if (::g->frontsector->floorheight > ::g->backsector->floorheight)
	{
	    ::g->ds_p->silhouette = SIL_BOTTOM;
	    ::g->ds_p->bsilheight = ::g->frontsector->floorheight;
	}
	else if (::g->backsector->floorheight > ::g->viewz)
	{
	    ::g->ds_p->silhouette = SIL_BOTTOM;
	    ::g->ds_p->bsilheight = MAXINT;
	    // ::g->ds_p->sprbottomclip = ::g->negonearray;
	}
	
	if (::g->frontsector->ceilingheight < ::g->backsector->ceilingheight)
	{
	    ::g->ds_p->silhouette |= SIL_TOP;
	    ::g->ds_p->tsilheight = ::g->frontsector->ceilingheight;
	}
	else if (::g->backsector->ceilingheight < ::g->viewz)
	{
	    ::g->ds_p->silhouette |= SIL_TOP;
	    ::g->ds_p->tsilheight = MININT;
	    // ::g->ds_p->sprtopclip = ::g->screenheightarray;
	}
		
	if (::g->backsector->ceilingheight <= ::g->frontsector->floorheight)
	{
	    ::g->ds_p->sprbottomclip = ::g->negonearray;
	    ::g->ds_p->bsilheight = MAXINT;
	    ::g->ds_p->silhouette |= SIL_BOTTOM;
	}
	
	if (::g->backsector->floorheight >= ::g->frontsector->ceilingheight)
	{
	    ::g->ds_p->sprtopclip = ::g->screenheightarray;
	    ::g->ds_p->tsilheight = MININT;
	    ::g->ds_p->silhouette |= SIL_TOP;
	}
	
	::g->worldhigh = ::g->backsector->ceilingheight - ::g->viewz;
	::g->worldlow = ::g->backsector->floorheight - ::g->viewz;
		
	// hack to allow height changes in outdoor areas
	if (::g->frontsector->ceilingpic == ::g->skyflatnum 
	    && ::g->backsector->ceilingpic == ::g->skyflatnum)
	{
	    ::g->worldtop = ::g->worldhigh;
	}
	
			
	if (::g->worldlow != ::g->worldbottom 
	    || ::g->backsector->floorpic != ::g->frontsector->floorpic
	    || ::g->backsector->lightlevel != ::g->frontsector->lightlevel)
	{
	    ::g->markfloor = true;
	}
	else
	{
	    // same plane on both ::g->sides
	    ::g->markfloor = false;
	}
	
			
	if (::g->worldhigh != ::g->worldtop 
	    || ::g->backsector->ceilingpic != ::g->frontsector->ceilingpic
	    || ::g->backsector->lightlevel != ::g->frontsector->lightlevel)
	{
	    ::g->markceiling = true;
	}
	else
	{
	    // same plane on both ::g->sides
	    ::g->markceiling = false;
	}
	
	if (::g->backsector->ceilingheight <= ::g->frontsector->floorheight
	    || ::g->backsector->floorheight >= ::g->frontsector->ceilingheight)
	{
	    // closed door
	    ::g->markceiling = ::g->markfloor = true;
	}
	

	if (::g->worldhigh < ::g->worldtop)
	{
	    // top texture
	    ::g->toptexture = ::g->texturetranslation[::g->sidedef->toptexture];
	    if (::g->linedef->flags & ML_DONTPEGTOP)
	    {
		// top of texture at top
		::g->rw_toptexturemid = ::g->worldtop;
	    }
	    else
	    {
		vtop =
		    ::g->backsector->ceilingheight
		    + ::g->s_textureheight[::g->sidedef->toptexture];
		
		// bottom of texture
		::g->rw_toptexturemid = vtop - ::g->viewz;	
	    }
	}
	if (::g->worldlow > ::g->worldbottom)
	{
	    // bottom texture
	    ::g->bottomtexture = ::g->texturetranslation[::g->sidedef->bottomtexture];

	    if (::g->linedef->flags & ML_DONTPEGBOTTOM )
	    {
		// bottom of texture at bottom
		// top of texture at top
		::g->rw_bottomtexturemid = ::g->worldtop;
	    }
	    else	// top of texture at top
		::g->rw_bottomtexturemid = ::g->worldlow;
	}
	::g->rw_toptexturemid += ::g->sidedef->rowoffset;
	::g->rw_bottomtexturemid += ::g->sidedef->rowoffset;
	
	// allocate space for masked texture tables
	if (::g->sidedef->midtexture)
	{
	    // masked ::g->midtexture
	    ::g->maskedtexture = true;
	    ::g->ds_p->maskedtexturecol = ::g->maskedtexturecol = ::g->lastopening - ::g->rw_x;
	    ::g->lastopening += ::g->rw_stopx - ::g->rw_x;
	}
    }
    
    // calculate ::g->rw_offset (only needed for textured ::g->lines)
    ::g->segtextured = ::g->midtexture | ::g->toptexture | ::g->bottomtexture | ::g->maskedtexture;

    if (::g->segtextured)
    {
		offsetangle = ::g->rw_normalangle-::g->rw_angle1;
		
		if (offsetangle > ANG180)
			offsetangle = -offsetangle; // ALANHACK UNSIGNED

		if (offsetangle > ANG90)
			offsetangle = ANG90;

		sineval = finesine[offsetangle >>ANGLETOFINESHIFT];
		::g->rw_offset = FixedMul (hyp, sineval);

		if (::g->rw_normalangle-::g->rw_angle1 < ANG180)
			::g->rw_offset = -::g->rw_offset;

		::g->rw_offset += ::g->sidedef->textureoffset + ::g->curline->offset;
		::g->rw_centerangle = ANG90 + GetViewAngle() - ::g->rw_normalangle;
		
		// calculate light table
		//  use different light tables
		//  for horizontal / vertical / diagonal
		// OPTIMIZE: get rid of LIGHTSEGSHIFT globally
		if (!::g->fixedcolormap)
		{
			lightnum = (::g->frontsector->lightlevel >> LIGHTSEGSHIFT)+::g->extralight;

			if (::g->curline->v1->y == ::g->curline->v2->y)
			lightnum--;
			else if (::g->curline->v1->x == ::g->curline->v2->x)
			lightnum++;

			if (lightnum < 0)		
			::g->walllights = ::g->scalelight[0];
			else if (lightnum >= LIGHTLEVELS)
			::g->walllights = ::g->scalelight[LIGHTLEVELS-1];
			else
			::g->walllights = ::g->scalelight[lightnum];
		}
    }
    
    // if a floor / ceiling plane is on the wrong side
    //  of the view plane, it is definitely invisible
    //  and doesn't need to be marked.
    
  
    if (::g->frontsector->floorheight >= ::g->viewz)
    {
	// above view plane
	::g->markfloor = false;
    }
    
    if (::g->frontsector->ceilingheight <= ::g->viewz 
	&& ::g->frontsector->ceilingpic != ::g->skyflatnum)
    {
	// below view plane
	::g->markceiling = false;
    }

    
    // calculate incremental stepping values for texture edges
    ::g->worldtop >>= 4;
    ::g->worldbottom >>= 4;
	
    ::g->topstep = -FixedMul (::g->rw_scalestep, ::g->worldtop);
    ::g->topfrac = (::g->centeryfrac>>4) - FixedMul (::g->worldtop, ::g->rw_scale);

    ::g->bottomstep = -FixedMul (::g->rw_scalestep,::g->worldbottom);
    ::g->bottomfrac = (::g->centeryfrac>>4) - FixedMul (::g->worldbottom, ::g->rw_scale);
	
    if (::g->backsector)
    {	
	::g->worldhigh >>= 4;
	::g->worldlow >>= 4;

	if (::g->worldhigh < ::g->worldtop)
	{
	    ::g->pixhigh = (::g->centeryfrac>>4) - FixedMul (::g->worldhigh, ::g->rw_scale);
	    ::g->pixhighstep = -FixedMul (::g->rw_scalestep,::g->worldhigh);
	}
	
	if (::g->worldlow > ::g->worldbottom)
	{
	    ::g->pixlow = (::g->centeryfrac>>4) - FixedMul (::g->worldlow, ::g->rw_scale);
	    ::g->pixlowstep = -FixedMul (::g->rw_scalestep,::g->worldlow);
	}
    }
    
    // render it
	 if (::g->markceiling)
		 ::g->ceilingplane = R_CheckPlane (::g->ceilingplane, ::g->rw_x, ::g->rw_stopx-1);

	 if (::g->markfloor)
		 ::g->floorplane = R_CheckPlane (::g->floorplane, ::g->rw_x, ::g->rw_stopx-1);

    R_RenderSegLoop ();

    
    // save sprite clipping info
    if ( ((::g->ds_p->silhouette & SIL_TOP) || ::g->maskedtexture)
	 && !::g->ds_p->sprtopclip)
    {
	memcpy (::g->lastopening, ::g->ceilingclip+start, 2*(::g->rw_stopx-start));
	::g->ds_p->sprtopclip = ::g->lastopening - start;
	::g->lastopening += ::g->rw_stopx - start;
    }
    
    if ( ((::g->ds_p->silhouette & SIL_BOTTOM) || ::g->maskedtexture)
	 && !::g->ds_p->sprbottomclip)
    {
	memcpy (::g->lastopening, ::g->floorclip+start, 2*(::g->rw_stopx-start));
	::g->ds_p->sprbottomclip = ::g->lastopening - start;
	::g->lastopening += ::g->rw_stopx - start;	
    }

    if (::g->maskedtexture && !(::g->ds_p->silhouette&SIL_TOP))
    {
	::g->ds_p->silhouette |= SIL_TOP;
	::g->ds_p->tsilheight = MININT;
    }
    if (::g->maskedtexture && !(::g->ds_p->silhouette&SIL_BOTTOM))
    {
	::g->ds_p->silhouette |= SIL_BOTTOM;
	::g->ds_p->bsilheight = MAXINT;
    }
    ::g->ds_p++;
}


