Beispiel #1
0
/*
* R_MarkLeaves
* 
* Mark the leaves and nodes that are in the PVS for the current cluster
*/
void R_MarkLeaves( void )
{
	qbyte *pvs;
	unsigned int i;
	int rdflags;
	mleaf_t	*leaf, **pleaf;
	mnode_t *node;
	qbyte *areabits;
	int cluster;
	qbyte fatpvs[MAX_MAP_LEAFS/8];

	rdflags = rn.refdef.rdflags;
	if( rdflags & RDF_NOWORLDMODEL )
		return;
	if( rf.oldviewcluster == rf.viewcluster && ( rdflags & RDF_OLDAREABITS ) 
		&& !(rn.renderFlags & RF_NOVIS) && rf.viewcluster != -1 && rf.oldviewcluster != -1 )
		return;
	if( rn.renderFlags & RF_SHADOWMAPVIEW )
		return;
	if( !rsh.worldModel )
		return;

	// development aid to let you run around and see exactly where
	// the pvs ends
	if( r_lockpvs->integer )
		return;

	rf.pvsframecount++;
	rf.oldviewcluster = rf.viewcluster;

	if( rn.renderFlags & RF_NOVIS || rf.viewcluster == -1 || !rsh.worldBrushModel->pvs )
	{
		// mark everything
		for( pleaf = rsh.worldBrushModel->visleafs, leaf = *pleaf; leaf; leaf = *pleaf++ )
			leaf->pvsframe = rf.pvsframecount;
		for( i = 0, node = rsh.worldBrushModel->nodes; i < rsh.worldBrushModel->numnodes; i++, node++ )
			node->pvsframe = rf.pvsframecount;
		return;
	}

	pvs = Mod_ClusterPVS( rf.viewcluster, rsh.worldModel );
	if( rf.viewarea > -1 && rn.refdef.areabits )
#ifdef AREAPORTALS_MATRIX
		areabits = rn.refdef.areabits + rf.viewarea * ((rsh.worldBrushModel->numareas+7)/8);
#else
		areabits = rn.refdef.areabits;
#endif
	else
Beispiel #2
0
/*
* Mod_CreateSubmodelBufferObjects
*/
static int Mod_CreateSubmodelBufferObjects( model_t *mod, unsigned int modnum, size_t *vbo_total_size )
{
	unsigned int i, j, k;
	uint8_t *visdata = NULL;
	uint8_t *areadata = NULL;
	unsigned int rowbytes, rowlongs;
	int areabytes;
	uint8_t *arearow;
	int *longrow, *longrow2;
	mmodel_t *bm;
	mbrushmodel_t *loadbmodel;
	msurface_t *surf, *surf2, **mark;
	msurface_t **surfmap;
	msurface_t **surfaces;
	unsigned numSurfaces;
	unsigned numUnmappedSurfaces;
	unsigned startDrawSurface;
	drawSurfaceBSP_t *drawSurf;
	int num_vbos;
	vattribmask_t floatVattribs;
	mesh_vbo_t *tempVBOs;
	unsigned numTempVBOs, maxTempVBOs;
	unsigned numUnmergedVBOs;

	assert( mod );

	loadbmodel = (( mbrushmodel_t * )mod->extradata);
	assert( loadbmodel );

	assert( modnum >= 0 && modnum < loadbmodel->numsubmodels );
	bm = loadbmodel->submodels + modnum;

	// ignore empty models
	if( !bm->numfaces )
		return 0;

	surfmap = ( msurface_t ** )Mod_Malloc( mod, bm->numfaces * sizeof( *surfmap ) );
	surfaces = ( msurface_t ** )Mod_Malloc( mod, bm->numfaces * sizeof( *surfaces ) );
	numSurfaces = 0;

	numTempVBOs = 0;
	maxTempVBOs = 1024;
	tempVBOs = ( mesh_vbo_t * )Mod_Malloc( mod, maxTempVBOs * sizeof( *tempVBOs ) );
	startDrawSurface = loadbmodel->numDrawSurfaces;

	if( !modnum && loadbmodel->pvs )
	{
		mleaf_t	*leaf, **pleaf;

		rowbytes = loadbmodel->pvs->rowsize;
		rowlongs = (rowbytes + 3) / 4;
		areabytes = (loadbmodel->numareas + 7) / 8;

		if( !rowbytes )
			return 0;

		// build visibility data for each face, based on what leafs
		// this face belongs to (visible from)
		visdata = ( uint8_t * )Mod_Malloc( mod, rowlongs * 4 * loadbmodel->numsurfaces );
		areadata = ( uint8_t * )Mod_Malloc( mod, areabytes * loadbmodel->numsurfaces );

		for( pleaf = loadbmodel->visleafs, leaf = *pleaf; leaf; leaf = *pleaf++ )
		{
			mark = leaf->firstVisSurface;
			do
			{
				int surfnum;

				surf = *mark++;
				surfnum = surf - loadbmodel->surfaces;

				if( surfmap[surfnum] ) {
					continue;
				}
				surfmap[surfnum] = surf;

				surfaces[numSurfaces] = surf;

				longrow  = ( int * )( visdata + numSurfaces * rowbytes );
				longrow2 = ( int * )( Mod_ClusterPVS( leaf->cluster, mod ) );

				// merge parent leaf cluster visibility into face visibility set
				// we could probably check for duplicates here because face can be
				// shared among multiple leafs
				for( j = 0; j < rowlongs; j++ )
					longrow[j] |= longrow2[j];

				if( leaf->area >= 0 ) {
					arearow = areadata + numSurfaces * areabytes;
					arearow[leaf->area>>3] |= (1<<(leaf->area&7));
				}

				numSurfaces++;
			} while( *mark );
		}
Beispiel #3
0
/*
* Mod_CreateSubmodelBufferObjects
*/
static int Mod_CreateSubmodelBufferObjects( model_t *mod, unsigned int modnum, size_t *vbo_total_size )
{
	unsigned int i, j, k;
	qbyte *visdata = NULL;
	qbyte *areadata = NULL;
	unsigned int rowbytes, rowlongs;
	int areabytes;
	qbyte *arearow;
	int *longrow, *longrow2;
	mmodel_t *bm;
	mbrushmodel_t *loadbmodel;
	msurface_t *surf, *surf2, **mark;
	msurface_t **surfmap;
	drawSurfaceBSP_t *drawSurf;
	int num_vbos;

	assert( mod );

	loadbmodel = (( mbrushmodel_t * )mod->extradata);
	assert( loadbmodel );

	assert( modnum >= 0 && modnum < loadbmodel->numsubmodels );
	bm = loadbmodel->submodels + modnum;

	// ignore empty models
	if( !bm->numfaces )
		return 0;

	// PVS only exists for world submodel
    if( !modnum && loadbmodel->pvs )
    {
	    mleaf_t *leaf, **pleaf;

		rowbytes = loadbmodel->pvs->rowsize;
		rowlongs = (rowbytes + 3) / 4;
		areabytes = (loadbmodel->numareas + 7) / 8;

		if( !rowbytes )
			return 0;

		// build visibility data for each face, based on what leafs
		// this face belongs to (visible from)
		visdata = Mod_Malloc( mod, rowlongs * 4 * loadbmodel->numsurfaces );
		areadata = Mod_Malloc( mod, areabytes * loadbmodel->numsurfaces );
		for( pleaf = loadbmodel->visleafs, leaf = *pleaf; leaf; leaf = *pleaf++ )
		{
			mark = leaf->firstVisSurface;
			do
			{
				int surfnum;

				surf = *mark;

				surfnum = surf - loadbmodel->surfaces;
				longrow  = ( int * )( visdata + surfnum * rowbytes );
				longrow2 = ( int * )( Mod_ClusterPVS( leaf->cluster, mod ) );

				// merge parent leaf cluster visibility into face visibility set
				// we could probably check for duplicates here because face can be
				// shared among multiple leafs
				for( j = 0; j < rowlongs; j++ )
					longrow[j] |= longrow2[j];

				if( leaf->area >= 0 ) {
					arearow = areadata + surfnum * areabytes;
					arearow[leaf->area>>3] |= (1<<(leaf->area&7));
				}
			} while( *++mark );
		}
    }
Beispiel #4
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;
}