Esempio n. 1
0
static void ProjectDecalOntoWinding( decalProjector_t *dp, int numPoints, vec3_t points[ 2 ][ MAX_DECAL_VERTS ], bspSurface_t *surf,
                                     bspModel_t *bmodel )
{
	int        i, pingPong, count, axis;
	float      pd, d, d2, alpha = 1.f;
	vec4_t     plane;
	vec3_t     absNormal;
	decal_t    *decal, *oldest;
	polyVert_t *vert;

	/* make a plane from the winding */
	if ( !PlaneFromPoints( plane, points[ 0 ][ 0 ], points[ 0 ][ 1 ], points[ 0 ][ 2 ] ) )
	{
		return;
	}

	/* omnidirectional projectors need plane type */
	if ( dp->omnidirectional )
	{
		/* compiler warnings be gone */
		pd = 1.0f;

		/* fade by distance from plane */
		d = DotProduct( dp->center, plane ) - plane[ 3 ];
		alpha = 1.0f - ( fabs( d ) / dp->radius );

		if ( alpha < 0.0f )
		{
			return;
		}

		if ( alpha > 1.0f )
		{
			alpha = 1.0f;
		}

		/* set projection axis */
		absNormal[ 0 ] = fabs( plane[ 0 ] );
		absNormal[ 1 ] = fabs( plane[ 1 ] );
		absNormal[ 2 ] = fabs( plane[ 2 ] );

		if ( absNormal[ 2 ] >= absNormal[ 0 ] && absNormal[ 2 ] >= absNormal[ 1 ] )
		{
			axis = 2;
		}
		else if ( absNormal[ 0 ] >= absNormal[ 1 ] && absNormal[ 0 ] >= absNormal[ 2 ] )
		{
			axis = 0;
		}
		else
		{
			axis = 1;
		}
	}
	else
	{
		/* backface check */
		pd = DotProduct( dp->planes[ 0 ], plane );

		if ( pd < -0.0001f )
		{
			return;
		}

		/* directional decals use first texture matrix */
		axis = 0;
	}

	/* chop the winding by all the projector planes */
	pingPong = 0;

	for ( i = 0; i < dp->numPlanes; i++ ) //%    dp->numPlanes
	{
		ChopWindingBehindPlane( numPoints, points[ pingPong ], &numPoints, points[ !pingPong ], dp->planes[ i ], 0.0f );
		pingPong ^= 1;

		if ( numPoints < 3 )
		{
			return;
		}

		if ( numPoints == MAX_DECAL_VERTS )
		{
			break;
		}
	}

	/* find first free decal (fixme: optimize this) */
	count = ( bmodel == tr.world->models ? MAX_WORLD_DECALS : MAX_ENTITY_DECALS );
	oldest = &bmodel->decals[ 0 ];
	decal = bmodel->decals;

	for ( i = 0; i < count; i++, decal++ )
	{
		/* try to find an empty decal slot */
		if ( decal->shader == NULL )
		{
			break;
		}

		/* find oldest decal */
		if ( decal->fadeEndTime < oldest->fadeEndTime )
		{
			oldest = decal;
		}
	}

	/* guess we have to use the oldest decal */
	if ( i >= count )
	{
		decal = oldest;
	}

	/* r_speeds useful info */
	tr.pc.c_decalSurfacesCreated++;

	/* set it up (fixme: get the shader before this happens) */
	decal->parent = surf;
	decal->shader = dp->shader;
	decal->fadeStartTime = dp->fadeStartTime;
	decal->fadeEndTime = dp->fadeEndTime;
	decal->fogIndex = surf->fogIndex;

	/* add points */
	decal->numVerts = numPoints;
	vert = decal->verts;

	for ( i = 0; i < numPoints; i++, vert++ )
	{
		/* set xyz */
		VectorCopy( points[ pingPong ][ i ], vert->xyz );

		/* set st */
		vert->st[ 0 ] = DotProduct( vert->xyz, dp->texMat[ axis ][ 0 ] ) + dp->texMat[ axis ][ 0 ][ 3 ];
		vert->st[ 1 ] = DotProduct( vert->xyz, dp->texMat[ axis ][ 1 ] ) + dp->texMat[ axis ][ 1 ][ 3 ];

		/* unidirectional decals fade by half distance from front->back planes */
		if ( !dp->omnidirectional )
		{
			/* set alpha */
			d = DotProduct( vert->xyz, dp->planes[ 0 ] ) - dp->planes[ 0 ][ 3 ];
			d2 = DotProduct( vert->xyz, dp->planes[ 1 ] ) - dp->planes[ 1 ][ 3 ];
			alpha = 2.0f * d2 / ( d + d2 );

			if ( alpha > 1.0f )
			{
				alpha = 1.0f;
			}
			else if ( alpha < 0.0f )
			{
				alpha = 0.0f;
			}
		}

		/* set color */
		vert->modulate[ 0 ] = Q_ftol( pd * alpha * dp->color[ 0 ] );
		vert->modulate[ 1 ] = Q_ftol( pd * alpha * dp->color[ 1 ] );
		vert->modulate[ 2 ] = Q_ftol( pd * alpha * dp->color[ 2 ] );
		vert->modulate[ 3 ] = Q_ftol( alpha * dp->color[ 3 ] );
	}
}
Esempio n. 2
0
//	projects decal onto a polygon
void ProjectDecalOntoWinding( decalProjector_t* dp, int numPoints, vec3_t points[ 2 ][ MAX_DECAL_VERTS ],
	const idWorldSurface* surf, mbrush46_model_t* bmodel ) {
	//	make a plane from the winding
	vec4_t plane;
	if ( !PlaneFromPoints( plane, points[ 0 ][ 0 ], points[ 0 ][ 1 ], points[ 0 ][ 2 ] ) ) {
		return;
	}

	//	omnidirectional projectors need plane type
	float pd;
	int axis;
	float alpha = 1.f;
	if ( dp->omnidirectional ) {
		pd = 1.0f;

		//	fade by distance from plane
		float d = DotProduct( dp->center, plane ) - plane[ 3 ];
		alpha = 1.0f - ( fabs( d ) / dp->radius );
		if ( alpha < 0.0f ) {
			return;
		}
		if ( alpha > 1.0f ) {
			alpha = 1.0f;
		}

		//	set projection axis
		vec3_t absNormal;
		absNormal[ 0 ] = fabs( plane[ 0 ] );
		absNormal[ 1 ] = fabs( plane[ 1 ] );
		absNormal[ 2 ] = fabs( plane[ 2 ] );
		if ( absNormal[ 2 ] >= absNormal[ 0 ] && absNormal[ 2 ] >= absNormal[ 1 ] ) {
			axis = 2;
		} else if ( absNormal[ 0 ] >= absNormal[ 1 ] && absNormal[ 0 ] >= absNormal[ 2 ] ) {
			axis = 0;
		} else {
			axis = 1;
		}
	} else {
		//	backface check
		pd = DotProduct( dp->planes[ 0 ], plane );
		if ( pd < -0.0001f ) {
			return;
		}

		//	directional decals use first texture matrix
		axis = 0;
	}

	//	chop the winding by all the projector planes
	int pingPong = 0;
	for ( int i = 0; i < dp->numPlanes; i++ ) {
		ChopWindingBehindPlane( numPoints, points[ pingPong ], &numPoints, points[ !pingPong ], dp->planes[ i ], 0.0f );
		pingPong ^= 1;
		if ( numPoints < 3 ) {
			return;
		}
		if ( numPoints == MAX_DECAL_VERTS ) {
			break;
		}
	}

	//	find first free decal (fixme: optimize this)
	int count = ( bmodel == tr.world->bmodels ? MAX_WORLD_DECALS : MAX_ENTITY_DECALS );
	mbrush46_decal_t* oldest = &bmodel->decals[ 0 ];
	mbrush46_decal_t* decal = bmodel->decals;
	int i;
	for ( i = 0; i < count; i++, decal++ ) {
		//	try to find an empty decal slot
		if ( decal->shader == NULL ) {
			break;
		}

		//	find oldest decal
		if ( decal->fadeEndTime < oldest->fadeEndTime ) {
			oldest = decal;
		}
	}

	//	guess we have to use the oldest decal
	if ( i >= count ) {
		decal = oldest;
	}

	//	r_speeds useful info
	tr.pc.c_decalSurfacesCreated++;

	//	set it up (fixme: get the shader before this happens)
	decal->parent = surf;
	decal->shader = dp->shader;
	decal->fadeStartTime = dp->fadeStartTime;
	decal->fadeEndTime = dp->fadeEndTime;
	decal->fogIndex = surf->fogIndex;

	//	add points
	decal->numVerts = numPoints;
	polyVert_t* vert = decal->verts;
	for ( i = 0; i < numPoints; i++, vert++ ) {
		//	set xyz
		VectorCopy( points[ pingPong ][ i ], vert->xyz );

		//	set st
		vert->st[ 0 ] = DotProduct( vert->xyz, dp->texMat[ axis ][ 0 ] ) + dp->texMat[ axis ][ 0 ][ 3 ];
		vert->st[ 1 ] = DotProduct( vert->xyz, dp->texMat[ axis ][ 1 ] ) + dp->texMat[ axis ][ 1 ][ 3 ];

		//	unidirectional decals fade by half distance from front->back planes
		if ( !dp->omnidirectional ) {
			//	set alpha
			float d = DotProduct( vert->xyz, dp->planes[ 0 ] ) - dp->planes[ 0 ][ 3 ];
			float d2 = DotProduct( vert->xyz, dp->planes[ 1 ] ) - dp->planes[ 1 ][ 3 ];
			alpha = 2.0f * d2 / ( d + d2 );
			if ( alpha > 1.0f ) {
				alpha = 1.0f;
			} else if ( alpha < 0.0f ) {
				alpha = 0.0f;
			}
		}

		//	set color
		vert->modulate[ 0 ] = idMath::FtoiFast( pd * alpha * dp->color[ 0 ] );
		vert->modulate[ 1 ] = idMath::FtoiFast( pd * alpha * dp->color[ 1 ] );
		vert->modulate[ 2 ] = idMath::FtoiFast( pd * alpha * dp->color[ 2 ] );
		vert->modulate[ 3 ] = idMath::FtoiFast( alpha * dp->color[ 3 ] );
	}
}