示例#1
0
void RE_ProjectDecal( qhandle_t hShader, int numPoints, vec3_t *points, vec4_t projection, vec4_t color, int lifeTime,
                      int fadeTime )
{
	int              i;
	float            radius, iDist;
	vec3_t           xyz;
	vec4_t           omniProjection;
	decalVert_t      dv[ 4 ];
	decalProjector_t *dp, temp;

	/* first frame rendered does not have a valid decals list */
	if ( tr.refdef.decalProjectors == NULL )
	{
		return;
	}

	/* dummy check */
	if ( numPoints != 1 && numPoints != 3 && numPoints != 4 )
	{
		ri.Printf( PRINT_WARNING, "WARNING: Invalid number of decal points (%d)\n", numPoints );
		return;
	}

	/* early outs */
	if ( lifeTime == 0 )
	{
		return;
	}

	if ( projection[ 3 ] <= 0.0f )
	{
		return;
	}

	/* set times properly */
	if ( lifeTime < 0 || fadeTime < 0 )
	{
		lifeTime = 0;
		fadeTime = 0;
	}

	/* basic setup */
	temp.shader = R_GetShaderByHandle( hShader );  /* debug code */
	temp.numPlanes = temp.shader->entityMergable;
	temp.color[ 0 ] = color[ 0 ] * 255;
	temp.color[ 1 ] = color[ 1 ] * 255;
	temp.color[ 2 ] = color[ 2 ] * 255;
	temp.color[ 3 ] = color[ 3 ] * 255;
	temp.numPlanes = numPoints + 2;
	temp.fadeStartTime = tr.refdef.time + lifeTime - fadeTime;
	temp.fadeEndTime = temp.fadeStartTime + fadeTime;

	/* set up decal texcoords (fixme: support arbitrary projector st coordinates in trapcall) */
	dv[ 0 ].st[ 0 ] = 0.0f;
	dv[ 0 ].st[ 1 ] = 0.0f;
	dv[ 1 ].st[ 0 ] = 0.0f;
	dv[ 1 ].st[ 1 ] = 1.0f;
	dv[ 2 ].st[ 0 ] = 1.0f;
	dv[ 2 ].st[ 1 ] = 1.0f;
	dv[ 3 ].st[ 0 ] = 1.0f;
	dv[ 3 ].st[ 1 ] = 0.0f;

	/* omnidirectional? */
	if ( numPoints == 1 )
	{
		/* set up omnidirectional */
		numPoints = 4;
		temp.numPlanes = 6;
		temp.omnidirectional = qtrue;
		radius = projection[ 3 ];
		Vector4Set( omniProjection, 0.0f, 0.0f, -1.0f, radius * 2.0f );
		projection = omniProjection;
		iDist = 1.0f / ( radius * 2.0f );

		/* set corner */
		VectorSet( xyz, points[ 0 ][ 0 ] - radius, points[ 0 ][ 1 ] - radius, points[ 0 ][ 2 ] + radius );

		/* make x axis texture matrix (yz) */
		VectorSet( temp.texMat[ 0 ][ 0 ], 0.0f, iDist, 0.0f );
		temp.texMat[ 0 ][ 0 ][ 3 ] = -DotProduct( temp.texMat[ 0 ][ 0 ], xyz );
		VectorSet( temp.texMat[ 0 ][ 1 ], 0.0f, 0.0f, iDist );
		temp.texMat[ 0 ][ 1 ][ 3 ] = -DotProduct( temp.texMat[ 0 ][ 1 ], xyz );

		/* make y axis texture matrix (xz) */
		VectorSet( temp.texMat[ 1 ][ 0 ], iDist, 0.0f, 0.0f );
		temp.texMat[ 1 ][ 0 ][ 3 ] = -DotProduct( temp.texMat[ 1 ][ 0 ], xyz );
		VectorSet( temp.texMat[ 1 ][ 1 ], 0.0f, 0.0f, iDist );
		temp.texMat[ 1 ][ 1 ][ 3 ] = -DotProduct( temp.texMat[ 1 ][ 1 ], xyz );

		/* make z axis texture matrix (xy) */
		VectorSet( temp.texMat[ 2 ][ 0 ], iDist, 0.0f, 0.0f );
		temp.texMat[ 2 ][ 0 ][ 3 ] = -DotProduct( temp.texMat[ 2 ][ 0 ], xyz );
		VectorSet( temp.texMat[ 2 ][ 1 ], 0.0f, iDist, 0.0f );
		temp.texMat[ 2 ][ 1 ][ 3 ] = -DotProduct( temp.texMat[ 2 ][ 1 ], xyz );

		/* setup decal points */
		VectorSet( dv[ 0 ].xyz, points[ 0 ][ 0 ] - radius, points[ 0 ][ 1 ] - radius, points[ 0 ][ 2 ] + radius );
		VectorSet( dv[ 1 ].xyz, points[ 0 ][ 0 ] - radius, points[ 0 ][ 1 ] + radius, points[ 0 ][ 2 ] + radius );
		VectorSet( dv[ 2 ].xyz, points[ 0 ][ 0 ] + radius, points[ 0 ][ 1 ] + radius, points[ 0 ][ 2 ] + radius );
		VectorSet( dv[ 3 ].xyz, points[ 0 ][ 0 ] + radius, points[ 0 ][ 1 ] - radius, points[ 0 ][ 2 ] + radius );
	}
	else
	{
		/* set up unidirectional */
		temp.omnidirectional = qfalse;

		/* set up decal points */
		VectorCopy( points[ 0 ], dv[ 0 ].xyz );
		VectorCopy( points[ 1 ], dv[ 1 ].xyz );
		VectorCopy( points[ 2 ], dv[ 2 ].xyz );
		VectorCopy( points[ 3 ], dv[ 3 ].xyz );

		/* make texture matrix */
		if ( !MakeTextureMatrix( temp.texMat[ 0 ], projection, &dv[ 0 ], &dv[ 1 ], &dv[ 2 ] ) )
		{
			return;
		}
	}

	/* bound the projector */
	ClearBounds( temp.mins, temp.maxs );

	for ( i = 0; i < numPoints; i++ )
	{
		AddPointToBounds( dv[ i ].xyz, temp.mins, temp.maxs );
		VectorMA( dv[ i ].xyz, projection[ 3 ], projection, xyz );
		AddPointToBounds( xyz, temp.mins, temp.maxs );
	}

	/* make bounding sphere */
	VectorAdd( temp.mins, temp.maxs, temp.center );
	VectorScale( temp.center, 0.5f, temp.center );
	VectorSubtract( temp.maxs, temp.center, xyz );
	temp.radius = VectorLength( xyz );
	temp.radius2 = temp.radius * temp.radius;

	/* frustum cull the projector (fixme: this uses a stale frustum!) */
	if ( R_CullPointAndRadius( temp.center, temp.radius ) == CULL_OUT )
	{
		return;
	}

	/* make the front plane */
	if ( !PlaneFromPoints( temp.planes[ 0 ], dv[ 0 ].xyz, dv[ 1 ].xyz, dv[ 2 ].xyz ) )
	{
		return;
	}

	/* make the back plane */
	VectorSubtract( vec3_origin, temp.planes[ 0 ], temp.planes[ 1 ] );
	VectorMA( dv[ 0 ].xyz, projection[ 3 ], projection, xyz );
	temp.planes[ 1 ][ 3 ] = DotProduct( xyz, temp.planes[ 1 ] );

	/* make the side planes */
	for ( i = 0; i < numPoints; i++ )
	{
		VectorMA( dv[ i ].xyz, projection[ 3 ], projection, xyz );

		if ( !PlaneFromPoints( temp.planes[ i + 2 ], dv[( i + 1 ) % numPoints ].xyz, dv[ i ].xyz, xyz ) )
		{
			return;
		}
	}

	/* create a new projector */
	dp = &tr.refdef.decalProjectors[ r_numDecalProjectors & DECAL_PROJECTOR_MASK ];
	Com_Memcpy( dp, &temp, sizeof( *dp ) );

	/* we have a winner */
	r_numDecalProjectors++;
}
示例#2
0
static int MakeDecalProjector( shaderInfo_t *si, vec4_t projection, float distance, int numVerts, bspDrawVert_t **dv )
{
	int					i, j;
	decalProjector_t	*dp;
	vec3_t				xyz;
	
	
	/* dummy check */
	if( numVerts != 3 && numVerts != 4 )
		return -1;
	
	/* limit check */
	if( numProjectors >= MAX_PROJECTORS )
	{
		MsgDev( D_WARN, "MAX_PROJECTORS (%d) exceeded, no more decal projectors available.\n", MAX_PROJECTORS );
		return -2;
	}
	
	/* create a new projector */
	dp = &projectors[ numProjectors ];
	Mem_Set( dp, 0, sizeof( *dp ));
	
	/* basic setup */
	dp->si = si;
	dp->numPlanes = numVerts + 2;
	
	/* make texture matrix */
	if( !MakeTextureMatrix( dp, projection, dv[ 0 ], dv[ 1 ], dv[ 2 ] ) )
		return -1;
	
	/* bound the projector */
	ClearBounds( dp->mins, dp->maxs );
	for( i = 0; i < numVerts; i++ )
	{
		AddPointToBounds( dv[ i ]->xyz, dp->mins, dp->maxs );
		VectorMA( dv[ i ]->xyz, distance, projection, xyz );
		AddPointToBounds( xyz, dp->mins, dp->maxs );
	}
	
	/* make bouding sphere */
	VectorAdd( dp->mins, dp->maxs, dp->center );
	VectorScale( dp->center, 0.5f, dp->center );
	VectorSubtract( dp->maxs, dp->center, xyz );
	dp->radius = VectorLength( xyz );
	dp->radius2 = dp->radius * dp->radius;
	
	/* make the front plane */
	if( !PlaneFromPoints( dp->planes[ 0 ], dv[ 0 ]->xyz, dv[ 1 ]->xyz, dv[ 2 ]->xyz ) )
		return -1;
	
	/* make the back plane */
	VectorSubtract( vec3_origin, dp->planes[ 0 ], dp->planes[ 1 ] );
	VectorMA( dv[ 0 ]->xyz, distance, projection, xyz );
	dp->planes[ 1 ][ 3 ] = DotProduct( xyz, dp->planes[ 1 ] );
	
	/* make the side planes */
	for( i = 0; i < numVerts; i++ )
	{
		j = (i + 1) % numVerts;
		VectorMA( dv[ i ]->xyz, distance, projection, xyz );
		if( !PlaneFromPoints( dp->planes[ i + 2 ], dv[ j ]->xyz, dv[ i ]->xyz, xyz ) )
			return -1;
	}
	
	/* return ok */
	numProjectors++;
	return numProjectors - 1;
}
示例#3
0
/**
 * @brief Creates a new decal projector from a triangle.
 *
 * Projected polygons should be 3 or 4 points.
 *
 * If a single point is passed in (numPoints == 1) then the decal will be omnidirectional
 * omnidirectional decals use points[ 0 ] as center and projection[ 3 ] as radius
 * pass in lifeTime < 0 for a temporary mark.
 *
 * @param[in] hShader
 * @param[in] numPoints
 * @param[in] points
 * @param[in] projection
 * @param[in] color
 * @param[in] lifeTime
 * @param[in] fadeTime
 */
void RE_ProjectDecal(qhandle_t hShader, int numPoints, vec3_t *points, vec4_t projection, vec4_t color, int lifeTime,
                     int fadeTime)
{
	static int       totalProjectors = 0;
	vec3_t           xyz;
	decalVert_t      dv[4];
	int              i;
	decalProjector_t *dp, temp;

	if (r_numDecalProjectors >= MAX_DECAL_PROJECTORS)
	{
		Ren_Print("WARNING: RE_ProjectDecal() Max decal projectors reached (%d)\n", MAX_DECAL_PROJECTORS);
		return;
	}

	// dummy check
	if (numPoints != 1 && numPoints != 3 && numPoints != 4)
	{
		Ren_Print("WARNING: RE_ProjectDecal() Invalid number of decal points (%d)\n", numPoints);
		return;
	}

	// early outs
	if (lifeTime == 0)
	{
		Ren_Developer("WARNING: RE_ProjectDecal() lifeTime == 0\n"); // modders should have a look at this - vanilla does these calls
		return;
	}
	if (projection[3] <= 0.0f)
	{
		Ren_Print("WARNING: RE_ProjectDecal() projection[3] <= 0.0f\n");
		return;
	}

	// set times properly
	if (lifeTime < 0 || fadeTime < 0)
	{
		lifeTime = 0;
		fadeTime = 0;
	}

	// basic setup
	temp.shader        = R_GetShaderByHandle(hShader);
	temp.color[0]      = (byte)(color[0] * 255);
	temp.color[1]      = (byte)(color[1] * 255);
	temp.color[2]      = (byte)(color[2] * 255);
	temp.color[3]      = (byte)(color[3] * 255);
	temp.numPlanes     = numPoints + 2;
	temp.fadeStartTime = tr.refdef.time + lifeTime - fadeTime; // FIXME: stale refdef time
	temp.fadeEndTime   = temp.fadeStartTime + fadeTime;
	temp.projectorNum  = 0;

	// set up decal texcoords (FIXME: support arbitrary projector st coordinates in trapcall)
	dv[0].st[0] = 0.0f;
	dv[0].st[1] = 0.0f;
	dv[1].st[0] = 0.0f;
	dv[1].st[1] = 1.0f;
	dv[2].st[0] = 1.0f;
	dv[2].st[1] = 1.0f;
	dv[3].st[0] = 1.0f;
	dv[3].st[1] = 0.0f;

	// omnidirectional?
	if (numPoints == 1)
	{
		float radius;
		float iDist;

		// set up omnidirectional
		numPoints            = 4;
		temp.numPlanes       = 6;
		temp.omnidirectional = qtrue;
		radius               = projection[3];

		Vector4Set(projection, 0.0f, 0.0f, -1.0f, radius * 2.0f);
		iDist = 1.0f / (radius * 2.0f);

		// set corner
		VectorSet(xyz, points[0][0] - radius, points[0][1] - radius, points[0][2] + radius);

		// make x axis texture matrix (yz)
		VectorSet(temp.texMat[0][0], 0.0f, iDist, 0.0f);
		temp.texMat[0][0][3] = -DotProduct(temp.texMat[0][0], xyz);
		VectorSet(temp.texMat[0][1], 0.0f, 0.0f, iDist);
		temp.texMat[0][1][3] = -DotProduct(temp.texMat[0][1], xyz);

		// make y axis texture matrix (xz)
		VectorSet(temp.texMat[1][0], iDist, 0.0f, 0.0f);
		temp.texMat[1][0][3] = -DotProduct(temp.texMat[1][0], xyz);
		VectorSet(temp.texMat[1][1], 0.0f, 0.0f, iDist);
		temp.texMat[1][1][3] = -DotProduct(temp.texMat[1][1], xyz);

		// make z axis texture matrix (xy)
		VectorSet(temp.texMat[2][0], iDist, 0.0f, 0.0f);
		temp.texMat[2][0][3] = -DotProduct(temp.texMat[2][0], xyz);
		VectorSet(temp.texMat[2][1], 0.0f, iDist, 0.0f);
		temp.texMat[2][1][3] = -DotProduct(temp.texMat[2][1], xyz);

		// setup decal points
		VectorSet(dv[0].xyz, points[0][0] - radius, points[0][1] - radius, points[0][2] + radius);
		VectorSet(dv[1].xyz, points[0][0] - radius, points[0][1] + radius, points[0][2] + radius);
		VectorSet(dv[2].xyz, points[0][0] + radius, points[0][1] + radius, points[0][2] + radius);
		VectorSet(dv[3].xyz, points[0][0] + radius, points[0][1] - radius, points[0][2] + radius);
	}
	else
	{
		// set up unidirectional
		temp.omnidirectional = qfalse;

		// set up decal points
		VectorCopy(points[0], dv[0].xyz);
		VectorCopy(points[1], dv[1].xyz);
		VectorCopy(points[2], dv[2].xyz);
		VectorCopy(points[3], dv[3].xyz);

		// make texture matrix
		if (!MakeTextureMatrix(temp.texMat[0], projection, &dv[0], &dv[1], &dv[2]))
		{
			Ren_Print("WARNING: RE_ProjectDecal() MakeTextureMatrix returns NULL\n");
			return;
		}
	}

	// bound the projector
	ClearBounds(temp.mins, temp.maxs);
	for (i = 0; i < numPoints; i++)
	{
		AddPointToBounds(dv[i].xyz, temp.mins, temp.maxs);
		VectorMA(dv[i].xyz, projection[3], projection, xyz);
		AddPointToBounds(xyz, temp.mins, temp.maxs);
	}

	// make bounding sphere
	VectorAdd(temp.mins, temp.maxs, temp.center);
	VectorScale(temp.center, 0.5f, temp.center);
	VectorSubtract(temp.maxs, temp.center, xyz);
	temp.radius  = VectorLength(xyz);
	temp.radius2 = temp.radius * temp.radius;

	// make the front plane
	if (!PlaneFromPoints(temp.planes[0], dv[0].xyz, dv[1].xyz, dv[2].xyz))
	{
		Ren_Developer("WARNING: RE_ProjectDecal() PlaneFromPoints is NULL\n"); // occurs on UJE_fueldump
		return;
	}

	// make the back plane
	VectorSubtract(vec3_origin, temp.planes[0], temp.planes[1]);
	VectorMA(dv[0].xyz, projection[3], projection, xyz);
	temp.planes[1][3] = DotProduct(xyz, temp.planes[1]);

	// make the side planes
	for (i = 0; i < numPoints; i++)
	{
		VectorMA(dv[i].xyz, projection[3], projection, xyz);
		if (!PlaneFromPoints(temp.planes[i + 2], dv[(i + 1) % numPoints].xyz, dv[i].xyz, xyz))
		{
			Ren_Developer("WARNING: RE_ProjectDecal() a side plane is NULL\n"); // occurs on map venice
			return;
		}
	}

	// create a new projector
	dp = &backEndData->decalProjectors[r_numDecalProjectors];
	Com_Memcpy(dp, &temp, sizeof(*dp));
	dp->projectorNum = totalProjectors++;

	// we have a winner
	r_numDecalProjectors++;
}
示例#4
0
static int MakeDecalProjector( int mapEntityNum, shaderInfo_t *si, vec4_t projection, float distance, int numVerts, bspDrawVert_t **dv, float backfacecull, float lightmapScale, vec3_t lightmapAxis, vec3_t minlight, vec3_t minvertexlight, vec3_t ambient, vec3_t colormod, int smoothNormals )
{
	int					i, j;
	decalProjector_t	*dp;
	vec3_t				xyz;

	/* dummy check */
	if( numVerts != 3 && numVerts != 4 )
		return -1;
	
	/* limit check */
	if( numProjectors >= MAX_PROJECTORS )
	{
		Sys_Warning( mapEntityNum, "MAX_PROJECTORS (%d) exceeded, no more decal projectors available.", MAX_PROJECTORS );
		return -2;
	}
	
	/* create a new projector */
	dp = &projectors[ numProjectors ];
	memset( dp, 0, sizeof( decalProjector_t ) );
	
	/* basic setup */
	dp->si = si;
	dp->numPlanes = numVerts + 2;
	dp->backfacecull = backfacecull;
	dp->lightmapScale = lightmapScale;
	VectorCopy( lightmapAxis, dp->lightmapAxis );
	VectorCopy( minlight, dp->minlight );
	VectorCopy( minvertexlight, dp->minvertexlight );
	VectorCopy( ambient, dp->ambient );
	VectorCopy( colormod, dp->colormod );
	dp->smoothNormals = smoothNormals;
	dp->mapEntityNum = mapEntityNum;
	
	/* make texture matrix */
	if( !MakeTextureMatrix( dp, projection, dv[ 0 ], dv[ 1 ], dv[ 2 ] ) )
		return -1;
	
	/* bound the projector */
	ClearBounds( dp->mins, dp->maxs );
	for( i = 0; i < numVerts; i++ )
	{
		AddPointToBounds( dv[ i ]->xyz, dp->mins, dp->maxs );
		VectorMA( dv[ i ]->xyz, distance, projection, xyz );
		AddPointToBounds( xyz, dp->mins, dp->maxs );
	}
	
	/* make bouding sphere */
	VectorAdd( dp->mins, dp->maxs, dp->center );
	VectorScale( dp->center, 0.5f, dp->center );
	VectorSubtract( dp->maxs, dp->center, xyz );
	dp->radius = VectorLength( xyz );
	dp->radius2 = dp->radius * dp->radius;
	
	/* make the front plane */
	if( !PlaneFromPoints( dp->planes[ 0 ], dv[ 0 ]->xyz, dv[ 1 ]->xyz, dv[ 2 ]->xyz ) )
		return -1;
	
	/* make the back plane */
	VectorSubtract( vec3_origin, dp->planes[ 0 ], dp->planes[ 1 ] );
	VectorMA( dv[ 0 ]->xyz, distance, projection, xyz );
	dp->planes[ 1 ][ 3 ] = DotProduct( xyz, dp->planes[ 1 ] );
	
	/* make the side planes */
	for( i = 0; i < numVerts; i++ )
	{
		j = (i + 1) % numVerts;
		VectorMA( dv[ i ]->xyz, distance, projection, xyz );
		if( !PlaneFromPoints( dp->planes[ i + 2 ], dv[ j ]->xyz, dv[ i ]->xyz, xyz ) )
			return -1;
	}
	
	/* return ok */
	numProjectors++;
	return numProjectors - 1;
}