713 lines · 17.3 KB · C
RawDownload
// r_alias.c: routines for setting up to draw alias models #include "quakedef.h"#include "r_shared.h"#include "r_local.h"#include "d_local.h" // FIXME: shouldn't be needed (is needed for patch						// right now, but that should move) #define LIGHT_MIN 5 // lowest light value we'll allow, to avoid the							// need for inner-loop light clamping mtriangle_t *ptriangles;affinetridesc_t r_affinetridesc; void * acolormap; // FIXME: should go away trivertx_t *r_apverts; // TODO: these probably will go away with optimized rasterizationmdl_t *pmdl;vec3_t r_plightvec;int r_ambientlight;float r_shadelight;aliashdr_t *paliashdr;finalvert_t *pfinalverts;auxvert_t *pauxverts;static float ziscale;static model_t *pmodel; static vec3_t alias_forward, alias_right, alias_up; static maliasskindesc_t *pskindesc; int r_amodels_drawn;int a_skinwidth;int r_anumverts; float aliastransform[3][4]; typedef struct {	int index0;	int index1;} aedge_t; static aedge_t aedges[12] = {{0, 1}, {1, 2}, {2, 3}, {3, 0},{4, 5}, {5, 6}, {6, 7}, {7, 4},{0, 5}, {1, 4}, {2, 7}, {3, 6}}; #define NUMVERTEXNORMALS 162 float r_avertexnormals[NUMVERTEXNORMALS][3] = {#include "anorms.h"}; void R_AliasTransformAndProjectFinalVerts (finalvert_t *fv,	stvert_t *pstverts);void R_AliasSetUpTransform (int trivial_accept);void R_AliasTransformVector (vec3_t in, vec3_t out);void R_AliasTransformFinalVert (finalvert_t *fv, auxvert_t *av,	trivertx_t *pverts, stvert_t *pstverts);void R_AliasProjectFinalVert (finalvert_t *fv, auxvert_t *av); /*================R_AliasCheckBBox================*/bool R_AliasCheckBBox (void){	int i, flags, frame, numv;	aliashdr_t *pahdr;	float zi, basepts[8][3], v0, v1, frac;	finalvert_t *pv0, *pv1, viewpts[16];	auxvert_t *pa0, *pa1, viewaux[16];	maliasframedesc_t *pframedesc;	bool zclipped, zfullyclipped;	unsigned anyclip, allclip;	int minz; // expand, rotate, and translate points into worldspace 	currententity->trivial_accept = 0;	pmodel = currententity->model;	pahdr = Mod_Extradata (pmodel);	pmdl = (mdl_t *)((uint8_t *)pahdr + pahdr->model); 	R_AliasSetUpTransform (0); // construct the base bounding box for this frame	frame = currententity->frame;// TODO: don't repeat this check when drawing?	if ((frame >= pmdl->numframes) || (frame < 0))	{		Con_DPrintf ("No such frame %d %s\n", frame,				pmodel->name);		frame = 0;	} 	pframedesc = &pahdr->frames[frame]; // x worldspace coordinates	basepts[0][0] = basepts[1][0] = basepts[2][0] = basepts[3][0] =			(float)pframedesc->bboxmin.v[0];	basepts[4][0] = basepts[5][0] = basepts[6][0] = basepts[7][0] =			(float)pframedesc->bboxmax.v[0]; // y worldspace coordinates	basepts[0][1] = basepts[3][1] = basepts[5][1] = basepts[6][1] =			(float)pframedesc->bboxmin.v[1];	basepts[1][1] = basepts[2][1] = basepts[4][1] = basepts[7][1] =			(float)pframedesc->bboxmax.v[1]; // z worldspace coordinates	basepts[0][2] = basepts[1][2] = basepts[4][2] = basepts[5][2] =			(float)pframedesc->bboxmin.v[2];	basepts[2][2] = basepts[3][2] = basepts[6][2] = basepts[7][2] =			(float)pframedesc->bboxmax.v[2]; 	zclipped = false;	zfullyclipped = true; 	minz = 9999;	for (i=0; i<8 ; i++)	{		R_AliasTransformVector (&basepts[i][0], &viewaux[i].fv[0]); 		if (viewaux[i].fv[2] < ALIAS_Z_CLIP_PLANE)		{		// we must clip points that are closer than the near clip plane			viewpts[i].flags = ALIAS_Z_CLIP;			zclipped = true;		}		else		{			if (viewaux[i].fv[2] < minz)				minz = viewaux[i].fv[2];			viewpts[i].flags = 0;			zfullyclipped = false;		}	} 	if (zfullyclipped)	{		return false; // everything was near-z-clipped	} 	numv = 8; 	if (zclipped)	{	// organize points by edges, use edges to get new points (possible trivial	// reject)		for (i=0 ; i<12 ; i++)		{		// edge endpoints			pv0 = &viewpts[aedges[i].index0];			pv1 = &viewpts[aedges[i].index1];			pa0 = &viewaux[aedges[i].index0];			pa1 = &viewaux[aedges[i].index1]; 		// if one end is clipped and the other isn't, make a new point			if (pv0->flags ^ pv1->flags)			{				frac = (ALIAS_Z_CLIP_PLANE - pa0->fv[2]) /					   (pa1->fv[2] - pa0->fv[2]);				viewaux[numv].fv[0] = pa0->fv[0] +						(pa1->fv[0] - pa0->fv[0]) * frac;				viewaux[numv].fv[1] = pa0->fv[1] +						(pa1->fv[1] - pa0->fv[1]) * frac;				viewaux[numv].fv[2] = ALIAS_Z_CLIP_PLANE;				viewpts[numv].flags = 0;				numv++;			}		}	} // project the vertices that remain after clipping	anyclip = 0;	allclip = ALIAS_XY_CLIP_MASK; // TODO: probably should do this loop in ASM, especially if we use floats	for (i=0 ; i<numv ; i++)	{	// we don't need to bother with vertices that were z-clipped		if (viewpts[i].flags & ALIAS_Z_CLIP)			continue; 		zi = 1.0 / viewaux[i].fv[2]; 	// FIXME: do with chop mode in ASM, or convert to float		v0 = (viewaux[i].fv[0] * xscale * zi) + xcenter;		v1 = (viewaux[i].fv[1] * yscale * zi) + ycenter; 		flags = 0; 		if (v0 < r_refdef.fvrectx)			flags |= ALIAS_LEFT_CLIP;		if (v1 < r_refdef.fvrecty)			flags |= ALIAS_TOP_CLIP;		if (v0 > r_refdef.fvrectright)			flags |= ALIAS_RIGHT_CLIP;		if (v1 > r_refdef.fvrectbottom)			flags |= ALIAS_BOTTOM_CLIP; 		anyclip |= flags;		allclip &= flags;	} 	if (allclip)		return false; // trivial reject off one side 	currententity->trivial_accept = !anyclip & !zclipped; 	if (currententity->trivial_accept)	{		if (minz > (r_aliastransition + (pmdl->size * r_resfudge)))		{			currententity->trivial_accept |= 2;		}	} 	return true;} /*================R_AliasTransformVector================*/void R_AliasTransformVector (vec3_t in, vec3_t out){	out[0] = DotProduct(in, aliastransform[0]) + aliastransform[0][3];	out[1] = DotProduct(in, aliastransform[1]) + aliastransform[1][3];	out[2] = DotProduct(in, aliastransform[2]) + aliastransform[2][3];} /*================R_AliasPreparePoints General clipped case================*/void R_AliasPreparePoints (void){	int i;	stvert_t *pstverts;	finalvert_t *fv;	auxvert_t *av;	mtriangle_t *ptri;	finalvert_t *pfv[3]; 	pstverts = (stvert_t *)((uint8_t *)paliashdr + paliashdr->stverts);	r_anumverts = pmdl->numverts; 	fv = pfinalverts;	av = pauxverts; 	for (i=0 ; i<r_anumverts ; i++, fv++, av++, r_apverts++, pstverts++)	{		R_AliasTransformFinalVert (fv, av, r_apverts, pstverts);		if (av->fv[2] < ALIAS_Z_CLIP_PLANE)			fv->flags |= ALIAS_Z_CLIP;		else		{			 R_AliasProjectFinalVert (fv, av); 			if (fv->v[0] < r_refdef.aliasvrect.x)				fv->flags |= ALIAS_LEFT_CLIP;			if (fv->v[1] < r_refdef.aliasvrect.y)				fv->flags |= ALIAS_TOP_CLIP;			if (fv->v[0] > r_refdef.aliasvrectright)				fv->flags |= ALIAS_RIGHT_CLIP;			if (fv->v[1] > r_refdef.aliasvrectbottom)				fv->flags |= ALIAS_BOTTOM_CLIP;		}	} //// clip and draw all triangles//	r_affinetridesc.numtriangles = 1; 	ptri = (mtriangle_t *)((uint8_t *)paliashdr + paliashdr->triangles);	for (i=0 ; i<pmdl->numtris ; i++, ptri++)	{		pfv[0] = &pfinalverts[ptri->vertindex[0]];		pfv[1] = &pfinalverts[ptri->vertindex[1]];		pfv[2] = &pfinalverts[ptri->vertindex[2]]; 		if ( pfv[0]->flags & pfv[1]->flags & pfv[2]->flags & (ALIAS_XY_CLIP_MASK | ALIAS_Z_CLIP) )			continue; // completely clipped 		if ( ! ( (pfv[0]->flags | pfv[1]->flags | pfv[2]->flags) &			(ALIAS_XY_CLIP_MASK | ALIAS_Z_CLIP) ) )		{ // totally unclipped			r_affinetridesc.pfinalverts = pfinalverts;			r_affinetridesc.ptriangles = ptri;			D_PolysetDraw ();		}		else		{ // partially clipped			R_AliasClipTriangle (ptri);		}	}} /*================R_AliasSetUpTransform================*/void R_AliasSetUpTransform (int trivial_accept){	int i;	float rotationmatrix[3][4], t2matrix[3][4];	static float tmatrix[3][4];	static float viewmatrix[3][4];	vec3_t angles; // TODO: should really be stored with the entity instead of being reconstructed// TODO: should use a look-up table// TODO: could cache lazily, stored in the entity 	angles[ROLL] = currententity->angles[ROLL];	angles[PITCH] = -currententity->angles[PITCH];	angles[YAW] = currententity->angles[YAW];	AngleVectors (angles, alias_forward, alias_right, alias_up); 	tmatrix[0][0] = pmdl->scale[0];	tmatrix[1][1] = pmdl->scale[1];	tmatrix[2][2] = pmdl->scale[2]; 	tmatrix[0][3] = pmdl->scale_origin[0];	tmatrix[1][3] = pmdl->scale_origin[1];	tmatrix[2][3] = pmdl->scale_origin[2]; // TODO: can do this with simple matrix rearrangement 	for (i=0 ; i<3 ; i++)	{		t2matrix[i][0] = alias_forward[i];		t2matrix[i][1] = -alias_right[i];		t2matrix[i][2] = alias_up[i];	} 	t2matrix[0][3] = -modelorg[0];	t2matrix[1][3] = -modelorg[1];	t2matrix[2][3] = -modelorg[2]; // FIXME: can do more efficiently than full concatenation	R_ConcatTransforms (t2matrix, tmatrix, rotationmatrix); // TODO: should be global, set when vright, etc., set	VectorCopy (vright, viewmatrix[0]);	VectorCopy (vup, viewmatrix[1]);	VectorInverse (viewmatrix[1]);	VectorCopy (vpn, viewmatrix[2]); // viewmatrix[0][3] = 0;// viewmatrix[1][3] = 0;// viewmatrix[2][3] = 0; 	R_ConcatTransforms (viewmatrix, rotationmatrix, aliastransform); // do the scaling up of x and y to screen coordinates as part of the transform// for the unclipped case (it would mess up clipping in the clipped case).// Also scale down z, so 1/z is scaled 31 bits for free, and scale down x and y// correspondingly so the projected x and y come out right// FIXME: make this work for clipped case too?	if (trivial_accept)	{		for (i=0 ; i<4 ; i++)		{			aliastransform[0][i] *= aliasxscale *					(1.0 / ((float)0x8000 * 0x10000));			aliastransform[1][i] *= aliasyscale *					(1.0 / ((float)0x8000 * 0x10000));			aliastransform[2][i] *= 1.0 / ((float)0x8000 * 0x10000); 		}	}} /*================R_AliasTransformFinalVert================*/void R_AliasTransformFinalVert (finalvert_t *fv, auxvert_t *av,	trivertx_t *pverts, stvert_t *pstverts){	int temp;	float lightcos, *plightnormal; 	av->fv[0] = DotProduct(pverts->v, aliastransform[0]) +			aliastransform[0][3];	av->fv[1] = DotProduct(pverts->v, aliastransform[1]) +			aliastransform[1][3];	av->fv[2] = DotProduct(pverts->v, aliastransform[2]) +			aliastransform[2][3]; 	fv->v[2] = pstverts->s;	fv->v[3] = pstverts->t; 	fv->flags = pstverts->onseam; // lighting	plightnormal = r_avertexnormals[pverts->lightnormalindex];	lightcos = DotProduct (plightnormal, r_plightvec);	temp = r_ambientlight; 	if (lightcos < 0)	{		temp += (int)(r_shadelight * lightcos); 	// clamp; because we limited the minimum ambient and shading light, we	// don't have to clamp low light, just bright		if (temp < 0)			temp = 0;	} 	fv->v[4] = temp;} /*================R_AliasTransformAndProjectFinalVerts================*/void R_AliasTransformAndProjectFinalVerts (finalvert_t *fv, stvert_t *pstverts){	int i, temp;	float lightcos, *plightnormal, zi;	trivertx_t *pverts; 	pverts = r_apverts; 	for (i=0 ; i<r_anumverts ; i++, fv++, pverts++, pstverts++)	{	// transform and project		zi = 1.0 / (DotProduct(pverts->v, aliastransform[2]) +				aliastransform[2][3]); 	// x, y, and z are scaled down by 1/2**31 in the transform, so 1/z is	// scaled up by 1/2**31, and the scaling cancels out for x and y in the	// projection		fv->v[5] = zi; 		fv->v[0] = ((DotProduct(pverts->v, aliastransform[0]) +				aliastransform[0][3]) * zi) + aliasxcenter;		fv->v[1] = ((DotProduct(pverts->v, aliastransform[1]) +				aliastransform[1][3]) * zi) + aliasycenter; 		fv->v[2] = pstverts->s;		fv->v[3] = pstverts->t;		fv->flags = pstverts->onseam; 	// lighting		plightnormal = r_avertexnormals[pverts->lightnormalindex];		lightcos = DotProduct (plightnormal, r_plightvec);		temp = r_ambientlight; 		if (lightcos < 0)		{			temp += (int)(r_shadelight * lightcos); 		// clamp; because we limited the minimum ambient and shading light, we		// don't have to clamp low light, just bright			if (temp < 0)				temp = 0;		} 		fv->v[4] = temp;	}} /*================R_AliasProjectFinalVert================*/void R_AliasProjectFinalVert (finalvert_t *fv, auxvert_t *av){	float zi; // project points	zi = 1.0 / av->fv[2]; 	fv->v[5] = zi * ziscale; 	fv->v[0] = (av->fv[0] * aliasxscale * zi) + aliasxcenter;	fv->v[1] = (av->fv[1] * aliasyscale * zi) + aliasycenter;} /*================R_AliasPrepareUnclippedPoints================

Lines 1–500 of 713.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t