⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 r_edge.c

📁 Quake 2 Source code for students by Theerthan You can also download from idsoftwares.com
💻 C
📖 第 1 页 / 共 2 页
字号:
void R_GenerateSpans (void)
{
	edge_t			*edge;
	surf_t			*surf;

// clear active surfaces to just the background surface
	surfaces[1].next = surfaces[1].prev = &surfaces[1];
	surfaces[1].last_u = edge_head_u_shift20;

// generate spans
	for (edge=edge_head.next ; edge != &edge_tail; edge=edge->next)
	{			
		if (edge->surfs[0])
		{
		// it has a left surface, so a surface is going away for this span
			surf = &surfaces[edge->surfs[0]];

			R_TrailingEdge (surf, edge);

			if (!edge->surfs[1])
				continue;
		}

		R_LeadingEdge (edge);
	}

	R_CleanupSpan ();
}

#endif	// !id386


/*
==============
R_GenerateSpansBackward
==============
*/
void R_GenerateSpansBackward (void)
{
	edge_t			*edge;

// clear active surfaces to just the background surface
	surfaces[1].next = surfaces[1].prev = &surfaces[1];
	surfaces[1].last_u = edge_head_u_shift20;

// generate spans
	for (edge=edge_head.next ; edge != &edge_tail; edge=edge->next)
	{			
		if (edge->surfs[0])
			R_TrailingEdge (&surfaces[edge->surfs[0]], edge);

		if (edge->surfs[1])
			R_LeadingEdgeBackwards (edge);
	}

	R_CleanupSpan ();
}


/*
==============
R_ScanEdges

Input: 
newedges[] array
	this has links to edges, which have links to surfaces

Output:
Each surface has a linked list of its visible spans
==============
*/
void R_ScanEdges (void)
{
	int		iv, bottom;
	byte	basespans[MAXSPANS*sizeof(espan_t)+CACHE_SIZE];
	espan_t	*basespan_p;
	surf_t	*s;

	basespan_p = (espan_t *)
			((long)(basespans + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
	max_span_p = &basespan_p[MAXSPANS - r_refdef.vrect.width];

	span_p = basespan_p;

// clear active edges to just the background edges around the whole screen
// FIXME: most of this only needs to be set up once
	edge_head.u = r_refdef.vrect.x << 20;
	edge_head_u_shift20 = edge_head.u >> 20;
	edge_head.u_step = 0;
	edge_head.prev = NULL;
	edge_head.next = &edge_tail;
	edge_head.surfs[0] = 0;
	edge_head.surfs[1] = 1;
	
	edge_tail.u = (r_refdef.vrectright << 20) + 0xFFFFF;
	edge_tail_u_shift20 = edge_tail.u >> 20;
	edge_tail.u_step = 0;
	edge_tail.prev = &edge_head;
	edge_tail.next = &edge_aftertail;
	edge_tail.surfs[0] = 1;
	edge_tail.surfs[1] = 0;
	
	edge_aftertail.u = -1;		// force a move
	edge_aftertail.u_step = 0;
	edge_aftertail.next = &edge_sentinel;
	edge_aftertail.prev = &edge_tail;

// FIXME: do we need this now that we clamp x in r_draw.c?
	edge_sentinel.u = 2000 << 24;		// make sure nothing sorts past this
	edge_sentinel.prev = &edge_aftertail;

//	
// process all scan lines
//
	bottom = r_refdef.vrectbottom - 1;

	for (iv=r_refdef.vrect.y ; iv<bottom ; iv++)
	{
		current_iv = iv;
		fv = (float)iv;

	// mark that the head (background start) span is pre-included
		surfaces[1].spanstate = 1;

		if (newedges[iv])
		{
			R_InsertNewEdges (newedges[iv], edge_head.next);
		}

		(*pdrawfunc) ();

	// flush the span list if we can't be sure we have enough spans left for
	// the next scan
		if (span_p > max_span_p)
		{
			D_DrawSurfaces ();

		// clear the surface span pointers
			for (s = &surfaces[1] ; s<surface_p ; s++)
				s->spans = NULL;

			span_p = basespan_p;
		}

		if (removeedges[iv])
			R_RemoveEdges (removeedges[iv]);

		if (edge_head.next != &edge_tail)
			R_StepActiveU (edge_head.next);
	}

// do the last scan (no need to step or sort or remove on the last scan)

	current_iv = iv;
	fv = (float)iv;

// mark that the head (background start) span is pre-included
	surfaces[1].spanstate = 1;

	if (newedges[iv])
		R_InsertNewEdges (newedges[iv], edge_head.next);

	(*pdrawfunc) ();

// draw whatever's left in the span list
	D_DrawSurfaces ();
}


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

SURFACE FILLING

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

msurface_t		*pface;
surfcache_t		*pcurrentcache;
vec3_t			transformed_modelorg;
vec3_t			world_transformed_modelorg;
vec3_t			local_modelorg;

/*
=============
D_MipLevelForScale
=============
*/
int D_MipLevelForScale (float scale)
{
	int		lmiplevel;

	if (scale >= d_scalemip[0] )
		lmiplevel = 0;
	else if (scale >= d_scalemip[1] )
		lmiplevel = 1;
	else if (scale >= d_scalemip[2] )
		lmiplevel = 2;
	else
		lmiplevel = 3;

	if (lmiplevel < d_minmip)
		lmiplevel = d_minmip;

	return lmiplevel;
}


/*
==============
D_FlatFillSurface

Simple single color fill with no texture mapping
==============
*/
void D_FlatFillSurface (surf_t *surf, int color)
{
	espan_t	*span;
	byte	*pdest;
	int		u, u2;
	
	for (span=surf->spans ; span ; span=span->pnext)
	{
		pdest = (byte *)d_viewbuffer + r_screenwidth*span->v;
		u = span->u;
		u2 = span->u + span->count - 1;
		for ( ; u <= u2 ; u++)
			pdest[u] = color;
	}
}


/*
==============
D_CalcGradients
==============
*/
void D_CalcGradients (msurface_t *pface)
{
	mplane_t	*pplane;
	float		mipscale;
	vec3_t		p_temp1;
	vec3_t		p_saxis, p_taxis;
	float		t;

	pplane = pface->plane;

	mipscale = 1.0 / (float)(1 << miplevel);

	TransformVector (pface->texinfo->vecs[0], p_saxis);
	TransformVector (pface->texinfo->vecs[1], p_taxis);

	t = xscaleinv * mipscale;
	d_sdivzstepu = p_saxis[0] * t;
	d_tdivzstepu = p_taxis[0] * t;

	t = yscaleinv * mipscale;
	d_sdivzstepv = -p_saxis[1] * t;
	d_tdivzstepv = -p_taxis[1] * t;

	d_sdivzorigin = p_saxis[2] * mipscale - xcenter * d_sdivzstepu -
			ycenter * d_sdivzstepv;
	d_tdivzorigin = p_taxis[2] * mipscale - xcenter * d_tdivzstepu -
			ycenter * d_tdivzstepv;

	VectorScale (transformed_modelorg, mipscale, p_temp1);

	t = 0x10000*mipscale;
	sadjust = ((fixed16_t)(DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) -
			((pface->texturemins[0] << 16) >> miplevel)
			+ pface->texinfo->vecs[0][3]*t;
	tadjust = ((fixed16_t)(DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) -
			((pface->texturemins[1] << 16) >> miplevel)
			+ pface->texinfo->vecs[1][3]*t;

	// PGM - changing flow speed for non-warping textures.
	if (pface->texinfo->flags & SURF_FLOWING)
	{
		if(pface->texinfo->flags & SURF_WARP)
			sadjust += 0x10000 * (-128 * ( (r_newrefdef.time * 0.25) - (int)(r_newrefdef.time * 0.25) ));
		else
			sadjust += 0x10000 * (-128 * ( (r_newrefdef.time * 0.77) - (int)(r_newrefdef.time * 0.77) ));
	}
	// PGM

//
// -1 (-epsilon) so we never wander off the edge of the texture
//
	bbextents = ((pface->extents[0] << 16) >> miplevel) - 1;
	bbextentt = ((pface->extents[1] << 16) >> miplevel) - 1;
}


/*
==============
D_BackgroundSurf

The grey background filler seen when there is a hole in the map
==============
*/
void D_BackgroundSurf (surf_t *s)
{
// set up a gradient for the background surface that places it
// effectively at infinity distance from the viewpoint
	d_zistepu = 0;
	d_zistepv = 0;
	d_ziorigin = -0.9;

	D_FlatFillSurface (s, (int)sw_clearcolor->value & 0xFF);
	D_DrawZSpans (s->spans);
}

/*
=================
D_TurbulentSurf
=================
*/
void D_TurbulentSurf (surf_t *s)
{
	d_zistepu = s->d_zistepu;
	d_zistepv = s->d_zistepv;
	d_ziorigin = s->d_ziorigin;

	pface = s->msurf;
	miplevel = 0;
	cacheblock = pface->texinfo->image->pixels[0];
	cachewidth = 64;

	if (s->insubmodel)
	{
	// FIXME: we don't want to do all this for every polygon!
	// TODO: store once at start of frame
		currententity = s->entity;	//FIXME: make this passed in to
									// R_RotateBmodel ()
		VectorSubtract (r_origin, currententity->origin,
				local_modelorg);
		TransformVector (local_modelorg, transformed_modelorg);

		R_RotateBmodel ();	// FIXME: don't mess with the frustum,
							// make entity passed in
	}

	D_CalcGradients (pface);

//============
//PGM
	// textures that aren't warping are just flowing. Use NonTurbulent8 instead
	if(!(pface->texinfo->flags & SURF_WARP))
		NonTurbulent8 (s->spans);
	else
		Turbulent8 (s->spans);
//PGM
//============

	D_DrawZSpans (s->spans);

	if (s->insubmodel)
	{
	//
	// restore the old drawing state
	// FIXME: we don't want to do this every time!
	// TODO: speed up
	//
		currententity = NULL;	// &r_worldentity;
		VectorCopy (world_transformed_modelorg,
					transformed_modelorg);
		VectorCopy (base_vpn, vpn);
		VectorCopy (base_vup, vup);
		VectorCopy (base_vright, vright);
		R_TransformFrustum ();
	}
}

/*
==============
D_SkySurf
==============
*/
void D_SkySurf (surf_t *s)
{
	pface = s->msurf;
	miplevel = 0;
	if (!pface->texinfo->image)
		return;
	cacheblock = pface->texinfo->image->pixels[0];
	cachewidth = 256;

	d_zistepu = s->d_zistepu;
	d_zistepv = s->d_zistepv;
	d_ziorigin = s->d_ziorigin;

	D_CalcGradients (pface);

	D_DrawSpans16 (s->spans);

// set up a gradient for the background surface that places it
// effectively at infinity distance from the viewpoint
	d_zistepu = 0;
	d_zistepv = 0;
	d_ziorigin = -0.9;

	D_DrawZSpans (s->spans);
}

/*
==============
D_SolidSurf

Normal surface cached, texture mapped surface
==============
*/
void D_SolidSurf (surf_t *s)
{
	d_zistepu = s->d_zistepu;
	d_zistepv = s->d_zistepv;
	d_ziorigin = s->d_ziorigin;

	if (s->insubmodel)
	{
	// FIXME: we don't want to do all this for every polygon!
	// TODO: store once at start of frame
		currententity = s->entity;	//FIXME: make this passed in to
									// R_RotateBmodel ()
		VectorSubtract (r_origin, currententity->origin, local_modelorg);
		TransformVector (local_modelorg, transformed_modelorg);

		R_RotateBmodel ();	// FIXME: don't mess with the frustum,
							// make entity passed in
	}
	else
		currententity = &r_worldentity;

	pface = s->msurf;
#if 1
	miplevel = D_MipLevelForScale(s->nearzi * scale_for_mip * pface->texinfo->mipadjust);
#else
	{
		float dot;
		float normal[3];

		if ( s->insubmodel )
		{
			VectorCopy( pface->plane->normal, normal );
//			TransformVector( pface->plane->normal, normal);
			dot = DotProduct( normal, vpn );
		}
		else
		{
			VectorCopy( pface->plane->normal, normal );
			dot = DotProduct( normal, vpn );
		}

		if ( pface->flags & SURF_PLANEBACK )
			dot = -dot;

		if ( dot > 0 )
			printf( "blah" );

		miplevel = D_MipLevelForScale(s->nearzi * scale_for_mip * pface->texinfo->mipadjust);
	}
#endif

// FIXME: make this passed in to D_CacheSurface
	pcurrentcache = D_CacheSurface (pface, miplevel);

	cacheblock = (pixel_t *)pcurrentcache->data;
	cachewidth = pcurrentcache->width;

	D_CalcGradients (pface);

	D_DrawSpans16 (s->spans);

	D_DrawZSpans (s->spans);

	if (s->insubmodel)
	{
	//
	// restore the old drawing state
	// FIXME: we don't want to do this every time!
	// TODO: speed up
	//
		VectorCopy (world_transformed_modelorg,
					transformed_modelorg);
		VectorCopy (base_vpn, vpn);
		VectorCopy (base_vup, vup);
		VectorCopy (base_vright, vright);
		R_TransformFrustum ();
		currententity = NULL;	//&r_worldentity;
	}
}

/*
=============
D_DrawflatSurfaces

To allow developers to see the polygon carving of the world
=============
*/
void D_DrawflatSurfaces (void)
{
	surf_t			*s;

	for (s = &surfaces[1] ; s<surface_p ; s++)
	{
		if (!s->spans)
			continue;

		d_zistepu = s->d_zistepu;
		d_zistepv = s->d_zistepv;
		d_ziorigin = s->d_ziorigin;

		// make a stable color for each surface by taking the low
		// bits of the msurface pointer
		D_FlatFillSurface (s, (int)s->msurf & 0xFF);
		D_DrawZSpans (s->spans);
	}
}

/*
==============
D_DrawSurfaces

Rasterize all the span lists.  Guaranteed zero overdraw.
May be called more than once a frame if the surf list overflows (higher res)
==============
*/
void D_DrawSurfaces (void)
{
	surf_t			*s;

//	currententity = NULL;	//&r_worldentity;
	VectorSubtract (r_origin, vec3_origin, modelorg);
	TransformVector (modelorg, transformed_modelorg);
	VectorCopy (transformed_modelorg, world_transformed_modelorg);

	if (!sw_drawflat->value)
	{
		for (s = &surfaces[1] ; s<surface_p ; s++)
		{
			if (!s->spans)
				continue;

			r_drawnpolycount++;

			if (! (s->flags & (SURF_DRAWSKYBOX|SURF_DRAWBACKGROUND|SURF_DRAWTURB) ) )
				D_SolidSurf (s);
			else if (s->flags & SURF_DRAWSKYBOX)
				D_SkySurf (s);
			else if (s->flags & SURF_DRAWBACKGROUND)
				D_BackgroundSurf (s);
			else if (s->flags & SURF_DRAWTURB)
				D_TurbulentSurf (s);
		}
	}
	else
		D_DrawflatSurfaces ();

	currententity = NULL;	//&r_worldentity;
	VectorSubtract (r_origin, vec3_origin, modelorg);
	R_TransformFrustum ();
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -