Ejemplo n.º 1
0
/*
* R_CullBrushModel
*/
qboolean R_CullBrushModel( entity_t *e )
{
	qboolean rotated;
	vec3_t mins, maxs;
	float radius;
	model_t	*model = e->model;
	mbrushmodel_t *bmodel = ( mbrushmodel_t * )model->extradata;

	if( bmodel->nummodelsurfaces == 0 )
		return qtrue;

	radius = R_BrushModelBBox( e, mins, maxs, &rotated );
	if( rotated )
	{
		if( R_CullSphere( e->origin, radius, ri.clipFlags ) )
			return qtrue;
	}
	else
	{
		if( R_CullBox( mins, maxs, ri.clipFlags ) )
			return qtrue;
	}

	if( ri.params & RP_PVSCULL )
	{
		if( rotated )
		{
			if( R_VisCullSphere( e->origin, radius ) )
				return qtrue;
		}
		else
		{
			if( R_VisCullBox( mins, maxs ) )
				return qtrue;
		}
	}

	return qfalse;
}
Ejemplo n.º 2
0
/*
* R_AddBrushModelToDrawList
*/
qboolean R_AddBrushModelToDrawList( const entity_t *e )
{
	unsigned int i;
	vec3_t origin;
	vec3_t bmins, bmaxs;
	qboolean rotated;
	model_t	*model = e->model;
	mbrushmodel_t *bmodel = ( mbrushmodel_t * )model->extradata;
	msurface_t *surf;
	mfog_t *fog;
	float radius, distance;
	unsigned int bit, fullBits;
	unsigned int dlightBits, shadowBits;

	if( bmodel->nummodelsurfaces == 0 ) {
		return qfalse;
	}

	radius = R_BrushModelBBox( e, bmins, bmaxs, &rotated );

	if( R_CullModelEntity( e, bmins, bmaxs, radius, rotated ) ) {
		return qfalse;
	}

	// never render weapon models or non-occluders into shadowmaps
	if( rn.renderFlags & RF_SHADOWMAPVIEW ) {
		if( rsc.entShadowGroups[R_ENT2NUM(e)] != rn.shadowGroup->id ) {
			return qtrue;
		}
	}

	VectorAdd( e->model->mins, e->model->maxs, origin );
	VectorMA( e->origin, 0.5, origin, origin );
	distance = Distance( origin, rn.refdef.vieworg );

	fog = R_FogForBounds( bmins, bmaxs );

	R_TransformPointToModelSpace( e, rotated, rn.refdef.vieworg, modelOrg );

	// check dynamic lights that matter in the instance against the model
	dlightBits = 0;
	for( i = 0, fullBits = rn.dlightBits, bit = 1; fullBits; i++, fullBits &= ~bit, bit <<= 1 ) {
		if( !( fullBits & bit ) ) {
			continue;
		}
		if( !BoundsAndSphereIntersect( bmins, bmaxs, rsc.dlights[i].origin, rsc.dlights[i].intensity ) ) {
			continue;
		}
		dlightBits |= bit;
	}

	// check shadowmaps that matter in the instance against the model
	shadowBits = 0;
	for( i = 0, fullBits = rn.shadowBits; fullBits; i++, fullBits &= ~bit ) {
		shadowGroup_t *grp = rsc.shadowGroups + i;
		bit = grp->bit;
		if( !( fullBits & bit ) ) {
			continue;
		}
		if( !BoundsIntersect( bmins, bmaxs, grp->visMins, grp->visMaxs ) ) {
			continue;
		}
		shadowBits |= bit;
	}

	for( i = 0, surf = bmodel->firstmodelsurface; i < bmodel->nummodelsurfaces; i++, surf++ ) {
		if( !surf->drawSurf ) {
			continue;
		}
		if( surf->visFrame != rf.frameCount ) {
			surf->visFrame = rf.frameCount;
			R_AddSurfaceToDrawList( e, surf, fog, 0, dlightBits, shadowBits, distance );
		}
	}

	return qtrue;
}
Ejemplo n.º 3
0
/*
* R_AddLightOccluder
*/
bool R_AddLightOccluder( const entity_t *ent ) {
	int i;
	float maxSide;
	vec3_t origin;
	unsigned int hash_key;
	shadowGroup_t *group;
	mleaf_t *leaf;
	vec3_t mins, maxs, bbox[8];
	bool bmodelRotated = false;

	if( rn.refdef.rdflags & RDF_NOWORLDMODEL ) {
		return false;
	}
	if( !ent->model || ent->model->type == mod_brush ) {
		return false;
	}

	VectorCopy( ent->lightingOrigin, origin );
	if( ent->model->type == mod_brush ) {
		vec3_t t;
		VectorAdd( ent->model->mins, ent->model->maxs, t );
		VectorMA( ent->origin, 0.5, t, origin );
	}

	if( VectorCompare( origin, vec3_origin ) ) {
		return false;
	}

	// find lighting group containing entities with same lightingOrigin as ours
	hash_key = (unsigned int)( origin[0] * 7 + origin[1] * 5 + origin[2] * 3 );
	hash_key &= ( SHADOWGROUPS_HASH_SIZE - 1 );

	for( group = r_shadowGroups_hash[hash_key]; group; group = group->hashNext ) {
		if( VectorCompare( group->origin, origin ) ) {
			goto add; // found an existing one, add
		}
	}

	if( rsc.numShadowGroups == MAX_SHADOWGROUPS ) {
		return false; // no free groups

	}
	leaf = Mod_PointInLeaf( origin, rsh.worldModel );

	// start a new group
	group = &rsc.shadowGroups[rsc.numShadowGroups];
	memset( group, 0, sizeof( *group ) );
	group->id = group - rsc.shadowGroups + 1;
	group->bit = ( 1 << rsc.numShadowGroups );
	group->vis = Mod_ClusterPVS( leaf->cluster, rsh.worldModel );
	group->useOrtho = true;
	group->alpha = r_shadows_alpha->value;

	// clear group bounds
	VectorCopy( origin, group->origin );
	ClearBounds( group->mins, group->maxs );
	ClearBounds( group->visMins, group->visMaxs );

	// add to hash table
	group->hashNext = r_shadowGroups_hash[hash_key];
	r_shadowGroups_hash[hash_key] = group;

	rsc.numShadowGroups++;
add:
	// get model bounds
	if( ent->model->type == mod_alias ) {
		R_AliasModelBBox( ent, mins, maxs );
	} else if( ent->model->type == mod_skeletal ) {
		R_SkeletalModelBBox( ent, mins, maxs );
	} else if( ent->model->type == mod_brush ) {
		R_BrushModelBBox( ent, mins, maxs, &bmodelRotated );
	} else {
		ClearBounds( mins, maxs );
	}

	maxSide = 0;
	for( i = 0; i < 3; i++ ) {
		if( mins[i] >= maxs[i] ) {
			return false;
		}
		maxSide = max( maxSide, maxs[i] - mins[i] );
	}

	// ignore tiny objects
	if( maxSide < 10 ) {
		return false;
	}

	rsc.entShadowGroups[R_ENT2NUM( ent )] = group->id;
	if( ent->flags & RF_WEAPONMODEL ) {
		return true;
	}

	if( ent->model->type == mod_brush ) {
		VectorCopy( mins, group->mins );
		VectorCopy( maxs, group->maxs );
	} else {
		// rotate local bounding box and compute the full bounding box for this group
		R_TransformBounds( ent->origin, ent->axis, mins, maxs, bbox );
		for( i = 0; i < 8; i++ ) {
			AddPointToBounds( bbox[i], group->mins, group->maxs );
		}
	}

	// increase projection distance if needed
	VectorSubtract( group->mins, origin, mins );
	VectorSubtract( group->maxs, origin, maxs );
	group->radius = RadiusFromBounds( mins, maxs );
	group->projDist = max( group->projDist, group->radius + min( r_shadows_projection_distance->value, 64.0f ) );

	return true;
}