Example #1
0
void procTree_c::addDrawCalls()
{
	visCount++;
	if ( nodes.size() == 0 )
	{
		for ( u32 i = 0; i < models.size(); i++ )
		{
			models[i]->addDrawCalls();
		}
		return;
	}
	camArea = pointArea( rf_camera.getPVSOrigin() );
	if ( rf_proc_printCamArea.getInt() )
	{
		g_core->Print( "camera is in area %i of %i\n", camArea, areas.size() );
	}
	// if camera is outside world or if we're debug-drawing all areas
	if ( camArea == -1 || rf_proc_ignorePortals.getInt() )
	{
		addDrawCallsForAllAreas();
		return;
	}
	frustumExt_c baseFrustum( rf_camera.getFrustum() );
	addAreaDrawCalls_r( camArea, baseFrustum, 0 );
}
void rIndexedShadowVolume_c::createDirectionalShadowVolumeForEntity( class rEntityImpl_c* ent, const vec3_c& lightDirection, float lightInfinity )
{
	clear();
	// save the last light position
	//this->lightPos = light;
	
	if ( ent == 0 )
		return;
	if ( ent->getModel() == 0 )
		return;
	if ( ent->isAnimated() && rf_skipAnimatedObjectsShadows.getInt() )
		return;
	const r_model_c* m = ent->getCurrentRModelInstance();
	if ( m )
	{
		fromDirectionalRModel( m, lightDirection, lightInfinity );
	}
	else
	{
		rModelAPI_i* modAPI = ent->getModel();
		if ( modAPI )
		{
			if ( modAPI->isInlineBSPModel() )
			{
				r_model_c tmp;
				modAPI->getModelData( &tmp );
				//tmp.transform(ent->getMatrix());
				fromRModel( &tmp, lightDirection, lightInfinity );
			}
			else if ( modAPI->isStatic() )
			{
				class model_c* m = dynamic_cast<model_c*>( modAPI );
				if ( m )
				{
					fromDirectionalRModel( m->getRModel(), lightDirection, lightInfinity );
				}
				else
				{
					g_core->RedWarning( "rIndexedShadowVolume_c::createDirectionalShadowVolumeForEntity: dynamic_cast to model_c failed for model %s.\n",
										modAPI->getName() );
				}
			}
		}
	}
	if ( rf_printShadowVolumesStats.getInt() )
	{
		g_core->Print( "rIndexedShadowVolume_c::createDirectionalShadowVolumeForEntity: (time %i) %i points, %i tris for model %s (%i edge quads, %i cap pairs)\n",
					   rf_curTimeMsec, points.size(), indices.getNumIndices() / 3, ent->getModelName(), this->c_edgeQuadsAdded, this->c_capTriPairsAdded );
	}
}
bool tsOctTreeHeader_s::logBoxTri( const class aabb& bounds, class boxTrianglesCallback_i* callback, u32 triangleNum )
{
	// see if the triangle was already checked
	if ( cms_tsOctTree_useCheckCounts.getInt() && this->triCheckCounts[triangleNum] == this->checkCount )
	{
		return false;
	}
	// mark as already checked
	this->triCheckCounts[triangleNum] = this->checkCount;
	
	const u32* indices = this->getTriIndexes();
	u32 i0 = indices[triangleNum * 3 + 0];
	u32 i1 = indices[triangleNum * 3 + 1];
	u32 i2 = indices[triangleNum * 3 + 2];
	const vec3_c& p0 = this->getTriPoints()[i0];
	const vec3_c& p1 = this->getTriPoints()[i1];
	const vec3_c& p2 = this->getTriPoints()[i2];
	aabb tmpBB;
	tmpBB.fromThreePoints( p0, p1, p2 );
	if ( tmpBB.intersect( bounds ) == false )
		return false;
		
	callback->onBoxTriangle( p0, p1, p2 );
	return true;
}
void CG_RunTestEmitter()
{
	if ( cg_testEmitter.getStr()[0] == 0 || cg_testEmitter.getStr()[0] == '0' )
	{
		CG_FreeTestEmitter();
		return;
	}
	class particleDeclAPI_i* pDecl = g_declMgr->registerParticleDecl( cg_testEmitter.getStr() );
	if ( pDecl == 0 )
	{
		CG_FreeTestEmitter();
		return;
	}
	if ( cg_testEmitterInstance == 0 )
	{
		cg_testEmitterInstance = new emitterD3_c;
		rf->addCustomRenderObject( cg_testEmitterInstance );
		cg_testEmitterInstance->setOrigin( cg.refdefViewOrigin + cg.refdefViewAxis.getForward()*cg_testEmitter_cameraDistance.getFloat() );
	}
	else
	{
		if ( cg_testEmitter_attachToCamera.getInt() )
		{
			cg_testEmitterInstance->setOrigin( cg.refdefViewOrigin + cg.refdefViewAxis.getForward()*cg_testEmitter_cameraDistance.getFloat() );
		}
	}
	cg_testEmitterInstance->setParticleDecl( pDecl );
	
}
Example #5
0
void rSunLight_c::addSunLightShadowVolumes()
{
	if ( mainVolume == 0 )
	{
		mainVolume = new rIndexedShadowVolume_c;
		const r_model_c* m = RF_GetWorldModel();
		if ( m )
		{
			for ( u32 i = 0; i < m->getNumSurfs(); i++ )
			{
				if ( m->getSurf( i )->findSunMaterial() )
					continue;
				if ( rf_usePointLightForSun.getInt() )
				{
					mainVolume->addRSurface( m->getSurf( i ), getFakePointLightPosition(), 0, getFakePointLightRadius() );
				}
				else
				{
					mainVolume->addDirectionalRSurface( m->getSurf( i ), RF_GetSunDirection(), 5000 );
				}
			}
		}
	}
	for ( u32 i = 0; i < entityInteractions.size(); i++ )
	{
		entityInteractions[i]->updateSunLightInteraction();
	}
	mainVolume->addDrawCall();
}
Example #6
0
		void updateSunLightInteraction()
		{
			if ( ent->hasStageWithoutBlendFunc() == false )
			{
				if ( shadowVolume )
				{
					delete shadowVolume;
					shadowVolume = 0;
				}
				return;
			}
			if ( shadowVolume == 0 )
			{
				shadowVolume = new rIndexedShadowVolume_c;
			}
			else
			{
				if ( ent->isAnimated() == false )
				{
					if ( absSilChangeCount == ent->getSilChangeCount() )
					{
						if ( rf_sunLight_printUnchangedInteractions.getInt() )
						{
							g_core->Print( "sunLightEntityInteraction_c::updateSunLightInteraction: %s didnt change\n",
										   ent->getModelName() );
						}
						addDrawCall();
						return;
					}
				}
			}
			ent->updateAnimatedEntity();
			absSilChangeCount = ent->getSilChangeCount();
			if ( rf_usePointLightForSun.getInt() )
			{
				vec3_c pos = rf_sunLight->getFakePointLightPosition();
				ent->getMatrix().getInversed().transformPoint( pos );
				shadowVolume->createShadowVolumeForEntity( ent, pos, rf_sunLight->getFakePointLightRadius() );
			}
			else
			{
				vec3_c dir = RF_GetSunDirection();
				ent->getMatrix().getInversed().transformNormal( dir );
				shadowVolume->createDirectionalShadowVolumeForEntity( ent, dir, 5000 );
			}
			addDrawCall();
		}
Example #7
0
bool procTree_c::cullBoundsByPortals( const aabb& absBB )
{
	if ( rf_proc_ignoreCullBounds.getInt() )
		return false; // didnt cull
	arraySTD_c<u32> areaNums;
	boxAreas( absBB, areaNums );
	return cullBoundsByPortals( absBB, areaNums );
}
Example #8
0
/*
===============
CG_CalcViewValues

Sets cg.refdef view values
===============
*/
static int CG_CalcViewValues( void )
{
    playerState_s*  ps;

    // calculate size of 3D view
    CG_CalcVrect();

    ps = &cg.predictedPlayerState;

    cg.refdefViewOrigin = ps->origin;
    cg.refdefViewAngles = ps->viewangles;

    // add first person / third person view offset
    if ( cg_thirdPerson.integer )
    {
        // back away from character
        CG_OffsetThirdPersonView();
    }
    else
    {
        // offset for local bobbing and kicks
        CG_OffsetFirstPersonView();
    }
    cg.refdefViewAxis.fromAngles( cg.refdefViewAngles );

    if ( cg_printCurCamPos.getInt() )
    {
        CG_Printf( "CG_CalcViewValues: camera eye is at %f %f %f\n", cg.refdefViewOrigin[0], cg.refdefViewOrigin[1], cg.refdefViewOrigin[2] );
    }
    if ( cg_printCurFarPlane.getInt() )
    {
        CG_Printf( "CG_CalcViewValues: cg.farPlane is %f\n", cg.farPlane );
    }

    projDef_s projDef;
    projDef.setDefaults();
    if ( cg.farPlane >= 8.f )
    {
        projDef.zFar = cg.farPlane;
    }
    rf->setupProjection3D( &projDef );
    rf->setup3DView( cg.refdefViewOrigin, cg.refdefViewAngles, cg_thirdPerson.integer );

    return 0;
}
u32 rIndexedShadowVolume_c::registerPoint( const vec3_c& p )
{
	bounds.addPoint( p );
	if ( rf_ssv_hashVertices.getInt() )
	{
		return points.registerVec3( p );
	}
	return points.addPoint( p );
}
Example #10
0
static void CG_DoRailgunEffect()
{
	//  va("doRailgunEffect railCore railDisc railExplosion gfx/damage/plasma_mrk %f %f %f %f %f %f %i",muzzle.x,muzzle.y,muzzle.z,
	vec3_c p, d;
	str coreMaterialName = CG_Argv( 1 );
	str discMaterialName = CG_Argv( 2 );
	str explosionMaterialName = CG_Argv( 3 );
	str decalMaterialName = CG_Argv( 4 );
	p.x = atof( CG_Argv( 5 ) );
	p.y = atof( CG_Argv( 6 ) );
	p.z = atof( CG_Argv( 7 ) );
	d.x = atof( CG_Argv( 8 ) );
	d.y = atof( CG_Argv( 9 ) );
	d.z = atof( CG_Argv( 10 ) );
	int skipEntityNum = atoi( CG_Argv( 11 ) );
	CG_Printf( "CG_DoRailgunEffect: from %f %f %f, dir %f %f %f\n", p.x, p.y, p.z, d.x, d.y, d.z );
	trace_c tr;
	tr.setupRay( p, d * 100000.f );
	if ( CG_RayTrace( tr, skipEntityNum ) == false )
	{
		CG_Printf( "CG_DoRailgunEffect: no hit\n" );
		return; // no hit
	}
	mtrAPI_i* coreMaterial = g_ms->registerMaterial( coreMaterialName );
	mtrAPI_i* diskMaterial = g_ms->registerMaterial( discMaterialName );
	
	CG_AddBulletTracer( tr.getStartPos() - vec3_c( 0, 0, 12 ), tr.getHitPos(), 32.f, coreMaterial, 1000 );
	
	mtrAPI_i* decalMaterial = g_ms->registerMaterial( decalMaterialName );
	float radius = 32.f;
	centity_s* hit = tr.getHitCGEntity();
	if ( hit == 0 || hit == &cg_entities[ENTITYNUM_WORLD] )
	{
		CG_Printf( "CG_DoRailgunEffect: hit Worldspawn\n" );
		if ( cg_debugDrawBulletAttack.getInt() )
		{
			rf->addDebugLine( tr.getHitPos(), tr.getHitPos() + radius * tr.getHitPlaneNormal(), vec3_c( 1, 0, 0 ), 5.f );
		}
		rf->addWorldMapDecal( tr.getHitPos(), tr.getHitPlaneNormal(), radius, decalMaterial );
	}
	else
	{
		CG_Printf( "CG_DoRailgunEffect: hit entity\n" );
		if ( hit->rEnt )
		{
			hit->rEnt->addDecalWorldSpace( tr.getHitPos(), tr.getHitPlaneNormal(), radius, decalMaterial );
		}
		else
		{
			CG_Printf( "CG_DoRailgunEffect: hit centity has NULL rEnt\n" );
		}
	}
}
Example #11
0
static void CG_OnEntityOrientationChange( centity_t* cent )
{
	// NOTE: some centities might have both rEnt and rLight present
	if ( cent->rEnt )
	{
		cent->rEnt->setOrigin( cent->lerpOrigin );
		cent->rEnt->setAngles( cent->lerpAngles );
	}
	if ( cent->rLight )
	{
		if ( cg_printLightFlags.getInt() )
		{
			g_core->Print( "Light entity %i lightFlags %i\n", cent->currentState.number, cent->currentState.lightFlags );
		}
		cent->rLight->setOrigin( cent->lerpOrigin );
		// TODO: lerp light radius?
		cent->rLight->setRadius( cent->currentState.lightRadius );
		cent->rLight->setBNoShadows( cent->currentState.lightFlags & LF_NOSHADOWS );
		if ( cent->currentState.lightFlags & LF_SPOTLIGHT )
		{
			// see if the spotlight can find it's target
			const centity_t* target = &cg_entities[cent->currentState.lightTarget];
			cent->rLight->setSpotRadius( cent->currentState.spotLightRadius );
			cent->rLight->setLightType( LT_SPOTLIGHT );
			if ( target->currentValid == false )
			{
				vec3_c targetPos = cent->lerpOrigin + cent->lerpAngles.getForward() * 64.f;
				cent->rLight->setSpotLightTarget( targetPos );
			}
			else
			{
				cent->rLight->setSpotLightTarget( target->lerpOrigin );
			}
		}
		else
		{
			cent->rLight->setLightType( LT_POINT );
		}
		if ( cent->currentState.lightFlags & LF_COLOURED )
		{
			cent->rLight->setBColoured( true );
			cent->rLight->setColor( cent->currentState.lightColor );
		}
		else
		{
			cent->rLight->setBColoured( false );
		}
	}
}
Example #12
0
void FuncRotating::runFrame()
{
	float rotateSpeed = 10;
	float delta = rotateSpeed * level.frameTime;
	vec3_c a = this->getAngles();
	// rotationAxis == 1 -> rotate around Z axis
	// rotationAxis == 0 -> rotate around Y axis
	a[rotationAxis] += delta;
	this->setAngles( a );
	
	if ( g_funcRotating_printOrientation.getInt() )
	{
		g_core->Print( "FuncRotating::runFrame(): pos %f %f %f rot %f %f %f\n", getOrigin().x, getOrigin().y, getOrigin().z, a.x, a.y, a.z );
	}
}
Example #13
0
static void CG_TestBulletAttack()
{
	vec3_c p, d;
	str decalMaterialName = CG_Argv( 1 );
	p.x = atof( CG_Argv( 2 ) );
	p.y = atof( CG_Argv( 3 ) );
	p.z = atof( CG_Argv( 4 ) );
	d.x = atof( CG_Argv( 5 ) );
	d.y = atof( CG_Argv( 6 ) );
	d.z = atof( CG_Argv( 7 ) );
	int skipEntityNum = atoi( CG_Argv( 8 ) );
	CG_Printf( "CG_TestBulletAttack: from %f %f %f, dir %f %f %f\n", p.x, p.y, p.z, d.x, d.y, d.z );
	trace_c tr;
	tr.setupRay( p, d * 100000.f );
	if ( CG_RayTrace( tr, skipEntityNum ) == false )
	{
		CG_Printf( "CG_TestBulletAttack: no hit\n" );
		return; // no hit
	}
	//mtrAPI_i *decalMaterial = g_ms->registerMaterial("qiotests/testdecalmaterial");
	mtrAPI_i* decalMaterial = g_ms->registerMaterial( decalMaterialName );
	float radius = 8.f;
	centity_s* hit = tr.getHitCGEntity();
	if ( hit == &cg_entities[ENTITYNUM_WORLD] )
	{
		CG_Printf( "CG_TestBulletAttack: hit Worldspawn\n" );
		if ( cg_debugDrawBulletAttack.getInt() )
		{
			rf->addDebugLine( tr.getHitPos(), tr.getHitPos() + radius * tr.getHitPlaneNormal(), vec3_c( 1, 0, 0 ), 5.f );
		}
		rf->addWorldMapDecal( tr.getHitPos(), tr.getHitPlaneNormal(), radius, decalMaterial );
		return;
	}
	else
	{
		CG_Printf( "CG_TestBulletAttack: hit entity\n" );
		if ( hit->rEnt )
		{
			hit->rEnt->addDecalWorldSpace( tr.getHitPos(), tr.getHitPlaneNormal(), radius, decalMaterial );
		}
		else
		{
			CG_Printf( "CG_TestBulletAttack: hit centity has NULL rEnt\n" );
		}
	}
}
Example #14
0
void procTree_c::doDebugDrawing()
{
	if ( rf_proc_showAreaPortals.getInt() )
	{
		for ( u32 i = 0; i < portals.size(); i++ )
		{
			procPortal_c* p = portals[i];
			const cmWinding_c& w = p->points;
			float col[4];
			col[0] = ( i % 39 ) / 39.f;
			col[1] = ( ( i + 10 ) % 47 ) / 47.f;
			col[2] = ( i % 33 ) / 33.f;
			col[3] = 1.f;
			rb->setColor4( col );
			rb->drawWinding( w.getArray(), w.size() );
		}
	}
}
bool tsOctTreeHeader_s::traceRay( class trace_c& tr )
{
	this->checkCount++;
	if ( cms_tsOctTree_checkAllTris.getInt() )
	{
		bool hit = false;
		u32 numTris = this->numIndexes / 3;
		for ( u32 i = 0; i < numTris; i++ )
		{
			if ( traceTriangleRay( i, tr ) )
			{
				hit = true;
			}
		}
		return hit;
	}
	return traceNodeRay_r( 0, tr );
}
Example #16
0
static void CG_CalcEntityLerpPositions( centity_t* cent )
{
	if ( cent->currentState.parentNum != ENTITYNUM_NONE )
	{
		centity_t* parent = &cg_entities[cent->currentState.parentNum];
		if ( parent->rEnt == 0 )
			return;
		if ( cg_printAttachedEntities.getInt() )
		{
			g_core->Print( "Entity %i is attached to %i\n", cent->currentState.number, cent->currentState.parentNum );
		}
		// first we have to update parent orientation (pos + rot),
		// then we can attach current entity to it
		CG_RunCEntity( parent );
		matrix_c mat;
		parent->rEnt->getBoneWorldOrientation( cent->currentState.parentTagNum, mat );
		cent->lerpAngles = mat.getAngles();
		cent->lerpOrigin = mat.getOrigin();
		if ( cent->currentState.parentOffset.isAlmostZero() == false )
		{
			matrix_c matAngles = mat;
			matAngles.setOrigin( vec3_c( 0, 0, 0 ) );
			vec3_c ofs;
			matAngles.transformPoint( cent->currentState.parentOffset, ofs );
			cent->lerpOrigin += ofs;
		}
		if ( cent->currentState.localAttachmentAngles.isAlmostZero() == false )
		{
			cent->lerpAngles += cent->currentState.localAttachmentAngles;
		}
		// NOTE: some centities might have both rEnt and rLight present
		// update render entity and/or render light
		CG_OnEntityOrientationChange( cent );
		return;
	}
	
	if ( cent->interpolate )
	{
		CG_InterpolateEntityPosition( cent );
		return;
	}
}
void rIndexedShadowVolume_c::addRSurface( const class r_surface_c* sf, const vec3_c& light, const struct extraSurfEdgesData_s* edges, float lightRadius )
{
	const rVertexBuffer_c& verts = sf->getVerts();
	const rIndexBuffer_c& indices = sf->getIndices();
	const planeArray_c& triPlanes = sf->getTriPlanes();
	// see if we have plane equations of triangles
	if ( triPlanes.size() )
	{
		// see if we have extra edges data
		if ( edges && ( rf_dontUseExtraEdgeArrays.getInt() == 0 ) )
		{
			addIndexedVertexListWithEdges( indices, verts, light, &triPlanes, edges );
		}
		else
		{
			addIndexedVertexList( indices, verts, light, &triPlanes, lightRadius, &sf->getBB() );
		}
	}
	else
	{
		addIndexedVertexList( indices, verts, light, 0, lightRadius, &sf->getBB() );
	}
}
void rIndexedShadowVolume_c::fromRModel( const class r_model_c* m, const vec3_c& light, float lightRadius )
{
	clear();
	if ( m == 0 )
	{
		g_core->RedWarning( "rIndexedShadowVolume_c::fromRModel: NULL model pointer.\n" );
		return;
	}
	this->points.setEqualVertexEpsilon( 0.f );
#if 0
	( ( r_model_c* )m )->precalculateStencilShadowCaster();
#endif
	if ( m->getStencilShadowCaster() && rf_dontUsePrecomputedSSVCasters.getInt() == 0 )
	{
		this->fromPrecalculatedStencilShadowCaster( m->getStencilShadowCaster(), light );
		return;
	}
	for ( u32 i = 0; i < m->getNumSurfs(); i++ )
	{
		const r_surface_c* sf = m->getSurf( i );
		addRSurface( sf, light, sf->getExtraSurfEdgesData(), lightRadius );
	}
}
// ======================================
//
//  tsOctTreeHeader_s collision detection
//
// ======================================
bool tsOctTreeHeader_s::traceTriangleRay( u32 triangleNum, class trace_c& tr )
{
	// see if the triangle was already checked
	if ( cms_tsOctTree_useCheckCounts.getInt() && this->triCheckCounts[triangleNum] == this->checkCount )
	{
		return false;
	}
	// mark as already checked
	this->triCheckCounts[triangleNum] = this->checkCount;
	
	const u32* indices = this->getTriIndexes();
	u32 i0 = indices[triangleNum * 3 + 0];
	u32 i1 = indices[triangleNum * 3 + 1];
	u32 i2 = indices[triangleNum * 3 + 2];
	const vec3_c& p0 = this->getTriPoints()[i0];
	const vec3_c& p1 = this->getTriPoints()[i1];
	const vec3_c& p2 = this->getTriPoints()[i2];
	if ( tr.clipByTriangle( p0, p1, p2, true ) )
	{
		tr.setHitTriangleIndex( triangleNum );
		return true;
	}
	return false;
}
Example #20
0
/*
=============
SV_EmitPacketEntities

Writes a delta update of an entityState_s list to the message.
=============
*/
static void SV_EmitPacketEntities( clientSnapshot_t* from, clientSnapshot_t* to, msg_s* msg )
{
	entityState_s*  oldent, *newent;
	int     oldindex, newindex;
	int     oldnum, newnum;
	int     from_num_entities;
	
	// generate the delta update
	if ( !from )
	{
		from_num_entities = 0;
	}
	else
	{
		from_num_entities = from->num_entities;
	}
	
	newent = NULL;
	oldent = NULL;
	newindex = 0;
	oldindex = 0;
	while ( newindex < to->num_entities || oldindex < from_num_entities )
	{
		if ( newindex >= to->num_entities )
		{
			newnum = 9999;
		}
		else
		{
			newent = &svs.snapshotEntities[( to->first_entity + newindex ) % svs.numSnapshotEntities];
			newnum = newent->number;
		}
		
		if ( oldindex >= from_num_entities )
		{
			oldnum = 9999;
		}
		else
		{
			oldent = &svs.snapshotEntities[( from->first_entity + oldindex ) % svs.numSnapshotEntities];
			oldnum = oldent->number;
		}
		
		if ( newnum == oldnum )
		{
			if ( sv_debugPlayerSnapshotEntities.getInt() == to->ps.number )
			{
				//Com_Printf("SV_EmitPacketEntities: delting entity %i from player %i view\n",
				//  oldnum,from->ps.number);
			}
			// delta update from old position
			// because the force parm is false, this will not result
			// in any bytes being emited if the entity has not changed at all
			MSG_WriteDeltaEntity( msg, oldent, newent, false );
			oldindex++;
			newindex++;
			continue;
		}
		
		if ( newnum < oldnum )
		{
			if ( sv_debugPlayerSnapshotEntities.getInt() == to->ps.number )
			{
				Com_Printf( "SV_EmitPacketEntities: adding entity %i from player %i view\n",
							newnum, to->ps.number );
			}
			// this is a new entity, send it from the baseline
			MSG_WriteDeltaEntity( msg, &sv.svEntities[newnum].baseline, newent, true );
			newindex++;
			continue;
		}
		
		if ( newnum > oldnum )
		{
			if ( sv_debugPlayerSnapshotEntities.getInt() == to->ps.number )
			{
				Com_Printf( "SV_EmitPacketEntities: removing entity %i from player %i view\n",
							oldnum, to->ps.number );
			}
			// the old entity isn't present in the new message
			MSG_WriteDeltaEntity( msg, oldent, NULL, true );
			oldindex++;
			continue;
		}
	}
	
	MSG_WriteBits( msg, ( MAX_GENTITIES - 1 ), GENTITYNUM_BITS );   // end of packetentities
}
Example #21
0
static void SV_AddEntitiesVisibleFromPoint( vec3_t origin, clientSnapshot_t* frame,
		snapshotEntityNumbers_t* eNums, bool portal, bitSet_c& areaBits )
{
	int     e;//, i;
	edict_s* ent;
	svEntity_t* svEnt;
	//int       l;
	
	// during an error shutdown message we may need to transmit
	// the shutdown message after the server has shutdown, so
	// specfically check for it
	if ( !sv.state )
	{
		return;
	}
	
	bspPointDesc_s eyeDesc; // for .bsp PVS
	pvsHandle_t procVisHandle; // for .proc vis
	if ( sv_bsp )
	{
		sv_bsp->filterPoint( origin, eyeDesc );
		sv_bsp->appendCurrentAreaBits( eyeDesc.area, areaBits );
	}
	else if ( sv_procVis )
	{
		procVisHandle = sv_procVis->SetupCurrentPVS( origin );
	}
	
	
	for ( e = 0 ; e < sv.num_entities ; e++ )
	{
		ent = SV_GentityNum( e );
		
		// never send entities that aren't active
		if ( ent->s == 0 )
		{
			continue;
		}
		
		if ( ent->s->number != e )
		{
			Com_DPrintf( "FIXING ENT->S.NUMBER!!!\n" );
			ent->s->number = e;
		}
		
		// never send entities that aren't visible
		if ( ent->s->isHidden() )
		{
			continue;
		}
		
		// never send ai waypoints (pathnodes)
		if ( ent->s->eType == ET_PATHNODE )
		{
			continue;
		}
		
		edict_s* visEnt = ent;
		while ( visEnt->s->parentNum != ENTITYNUM_NONE )
		{
			visEnt = SV_GentityNum( visEnt->s->parentNum );
		}
		if ( visEnt->bspBoxDesc == 0 )
		{
			continue; // not linked
		}
		
		svEnt = SV_SvEntityForGentity( ent );
		
		// don't double add an entity through portals
		if ( svEnt->snapshotCounter == sv.snapshotCounter )
		{
			continue;
		}
		
		if ( sv_cullEntities.getInt() )
		{
			if ( sv_bsp && sv_bsp->checkVisibility( eyeDesc, *visEnt->bspBoxDesc ) == false )
			{
				continue; // culled by .bsp PVS
			}
			if ( sv_procVis && sv_procVis->InCurrentPVS( procVisHandle, visEnt->bspBoxDesc->areas.getArray(), visEnt->bspBoxDesc->areas.size() ) == false )
			{
				continue; // culled by Doom3 .proc vis
			}
		}
		
		SV_AddEntToSnapshot( svEnt, ent, eNums );
	}
	if ( sv_procVis )
	{
		sv_procVis->FreeCurrentPVS( procVisHandle );
	}
}
void rIndexedShadowVolume_c::addIndexedVertexList( const rIndexBuffer_c& oIndices, const rVertexBuffer_c& oVerts, const vec3_c& light, const class planeArray_c* extraPlanesArray, float lightRadius, const class aabb* bounds )
{
#if 1
	// for a single triangle, in worst case we might need to create:
	// front cap + end cap + 3 edge quads
	// 1 + 1 + 3 * 2 = 2 + 6 = 8 triangles
	indices.ensureAllocated_indices( indices.getNumIndices() + oIndices.getNumTriangles() * 8 * 3 );
	points.ensureAllocated( points.size() + oVerts.size() * 2 );
#endif
#ifdef OPTIMIZE_SLOW_ADDTRIANGLE
	if ( indices.getU16Ptr() == 0 )
		return;
	u16* pFirstIndex = ( ( u16* )indices.getU16Ptr() ) + indices.getNumIndices();
	u16* pNextIndex = pFirstIndex;
#endif
	
	if ( rf_ssv_algorithm.getInt() == 0 )
	{
		for ( u32 i = 0; i < oIndices.getNumIndices(); i += 3 )
		{
			u32 i0 = oIndices[i + 0];
			u32 i1 = oIndices[i + 1];
			u32 i2 = oIndices[i + 2];
			const vec3_c& v0 = oVerts[i0].xyz;
			const vec3_c& v1 = oVerts[i1].xyz;
			const vec3_c& v2 = oVerts[i2].xyz;
			addTriangle( v0, v1, v2, light );
		}
	}
	else
	{
		bool bMeshFullyInsideLight;
		if ( bounds )
		{
			bMeshFullyInsideLight = IsAABBInsideSphere( *bounds, light, lightRadius );
		}
		else
		{
			bMeshFullyInsideLight = false;
		}
		// do the same thing as above, but a little faster way
		static arraySTD_c<byte> bPointTransformed;
		if ( bPointTransformed.size() < oVerts.size() )
		{
			bPointTransformed.resize( oVerts.size() );
		}
		bPointTransformed.nullMemory();
		static arraySTD_c<vec3_c> pointsTransformed;
		if ( pointsTransformed.size() < oVerts.size() )
		{
			pointsTransformed.resize( oVerts.size() );
		}
		
		u32 tri = 0;
		for ( u32 i = 0; i < oIndices.getNumIndices(); i += 3, tri++ )
		{
			u32 vi0 = oIndices[i + 0];
			u32 vi1 = oIndices[i + 1];
			u32 vi2 = oIndices[i + 2];
			const vec3_c& p0 = oVerts[vi0].xyz;
			const vec3_c& p1 = oVerts[vi1].xyz;
			const vec3_c& p2 = oVerts[vi2].xyz;
			
			// cull triangles that are outside light radius
			// This is a good optimisation for very large models intersecting very small lights
			if ( rf_ssv_cullTrianglesOutSideLightSpheres.getInt() )
			{
				// we can't cull that way any triangles if mesh bounds are entirely inside light sphere
				if ( bMeshFullyInsideLight == false )
				{
					if ( CU_IntersectSphereTriangle( light, lightRadius, p0, p1, p2 ) == false )
					{
						continue;
					}
				}
			}
			float d;
			if ( extraPlanesArray == 0 )
			{
				plane_c triPlane;
				triPlane.fromThreePoints( p2, p1, p0 );
				d = triPlane.distance( light );
			}
			else
			{
				d = extraPlanesArray->getArray()[tri].distance( light );
			}
			if ( d > 0 )
			{
				continue;
			}
			vec3_c& p0Projected = pointsTransformed[vi0];
			if ( bPointTransformed[vi0] == 0 )
			{
				bPointTransformed[vi0] = 1;
				p0Projected = p0 - light;
				p0Projected.normalizeFast();
				p0Projected *= getShadowVolumeInf();
				p0Projected += p0;
			}
			vec3_c& p1Projected = pointsTransformed[vi1];
			if ( bPointTransformed[vi1] == 0 )
			{
				bPointTransformed[vi1] = 1;
				p1Projected = p1 - light;
				p1Projected.normalizeFast();
				p1Projected *= getShadowVolumeInf();
				p1Projected += p1;
			}
			vec3_c& p2Projected = pointsTransformed[vi2];
			if ( bPointTransformed[vi2] == 0 )
			{
				bPointTransformed[vi2] = 1;
				p2Projected = p2 - light;
				p2Projected.normalizeFast();
				p2Projected *= getShadowVolumeInf();
				p2Projected += p2;
			}
			u32 i0 = this->registerPoint( p0 );
			u32 i1 = this->registerPoint( p1 );
			u32 i2 = this->registerPoint( p2 );
			u32 pi0 = this->registerPoint( p0Projected );
			u32 pi1 = this->registerPoint( p1Projected );
			u32 pi2 = this->registerPoint( p2Projected );
#ifdef OPTIMIZE_SLOW_ADDTRIANGLE
			ADD_TRIANGLE( pNextIndex, i2, i1, i0 );
			ADD_TRIANGLE( pNextIndex, pi0, pi1, pi2 );
			ADD_QUAD( pNextIndex, i0, i1, pi0, pi1 );
			ADD_QUAD( pNextIndex, i1, i2, pi1, pi2 );
			ADD_QUAD( pNextIndex, i2, i0, pi2, pi0 );
#else
			indices.addTriangle( i2, i1, i0 );
			indices.addTriangle( pi0, pi1, pi2 );
			c_capTriPairsAdded++;
			indices.addQuad( i0, i1, pi0, pi1 );
			c_edgeQuadsAdded++;
			indices.addQuad( i1, i2, pi1, pi2 );
			c_edgeQuadsAdded++;
			indices.addQuad( i2, i0, pi2, pi0 );
			c_edgeQuadsAdded++;
#endif
		}
	}
#ifdef OPTIMIZE_SLOW_ADDTRIANGLE
	u32 numAddedIndices = pNextIndex - pFirstIndex;
	indices.forceSetIndexCount( indices.getNumIndices() + numAddedIndices );
#endif
}
Example #23
0
void procTree_c::cacheLightWorldInteractions( class rLightImpl_c* l )
{
	if ( rf_proc_useProcDataToOptimizeLighting.getInt() == 0 )
	{
		// get all .proc surfaces withing light bounds and cache'em
		arraySTD_c<const r_surface_c*> sfs;
		boxAreaSurfaces( l->getABSBounds(), sfs );
		for ( u32 i = 0; i < sfs.size(); i++ )
		{
			l->addStaticModelSurfaceInteraction( ( r_surface_c* )sfs[i] );
		}
	}
	else
	{
		// get shadow-only interactions
		// It seems we need to render all the surfaces within light bounds,
		// even if they are not visible for light trough portals
		arraySTD_c<u32> list;
		boxAreas( l->getABSBounds(), list );
		for ( u32 i = 0; i < list.size(); i++ )
		{
			int areaNum = list[i];
			procArea_c* a = areas[areaNum];
			r_model_c* m = a->areaModel;
			for ( u32 j = 0; j < m->getNumSurfs(); j++ )
			{
				l->addProcAreaSurfaceInteraction( areaNum, m->getSurf( j ), SIFT_ONLY_SHADOW );
			}
		}
		// flood through portals (for lighting interactions)
		// draw only surfaces that are inside light "view" (affected by portals)
		litCount++;
		int lightArea = this->pointArea( l->getOrigin() );
		if ( lightArea < 0 )
			return;
		const procArea_c* ar = areas[lightArea];
		addSingleAreaSurfacesInteractions( lightArea, l );
		for ( u32 i = 0; i < ar->portals.size(); i++ )
		{
			procPortal_c* portal = ar->portals[i];
			frustumExt_c fr;
			// create light->portal frustum
			fr.fromPointAndWinding( l->getOrigin(), portal->points, portal->plane );
			// add far plane
			//vec3_c center = portal->points.getCenter();
			//vec3_c normal = center - l->getOrigin();
			//normal.normalize();
			//plane_c farPlane;
			//farPlane.fromPointAndNormal(center,normal);
			//fr.addPlane(farPlane);
			
			/*  if(fr.cull(portal->points.getCenter() != CULL_IN) {
			        g_core->RedWarning("bad frustum for portal %i\n",i);
			    }*/
			//g_core->Print("procTree_c::cacheLightWorldInteractions: area %i to portal %i frustum has %i planes\n",lightArea,i,fr.size());
			int otherArea;
			if ( lightArea == portal->areas[0] )
			{
				otherArea = portal->areas[1];
			}
			else
			{
				otherArea = portal->areas[0];
			}
			cacheLightWorldInteractions_r( l, otherArea, fr, portal );
		}
	}
}
Example #24
0
void CG_RunViewModel()
{
	if ( cg_printViewWeaponClipSize.getInt() )
	{
		if ( cg.snap )
		{
			g_core->Print( "ViewWeapon clip %i/%i\n", cg.snap->ps.viewWeaponCurClipSize, cg.snap->ps.viewWeaponMaxClipSize );
		}
	}
	
	int viewModelEntity = cg.snap->ps.curWeaponEntNum;
	if ( cg_thirdPerson.integer )
	{
		CG_FreeViewModelEntity();
		if ( viewModelEntity != ENTITYNUM_NONE && cg_entities[viewModelEntity].rEnt )
		{
			cg_entities[viewModelEntity].rEnt->showModel();
		}
		return;
	}
	if ( viewModelEntity == ENTITYNUM_NONE )
	{
		CG_FreeViewModelEntity();
		return;
	}
	if ( cg_entities[viewModelEntity].rEnt )
	{
		//cg_entities[viewModelEntity].rEnt->hideModel();
		cg_entities[viewModelEntity].rEnt->setThirdPersonOnly( true );
	}
	
	// local weapons offset (affected by cg_gunX/Y/Z cvars)
	vec3_c localOfs( 0, 0, 0 );
	// local weapon rotation (affected by cg_gunRotX/Y/Z cvars)
	vec3_c localRot( 0, 0, 0 );
	
	rModelAPI_i* viewModel;
	if ( cg.snap->ps.customViewRModelIndex )
	{
		viewModel = cgs.gameModels[cg.snap->ps.customViewRModelIndex];
	}
	else
	{
		if ( cg_entities[viewModelEntity].rEnt )
		{
			viewModel = cg_entities[viewModelEntity].rEnt->getModel();
		}
		else
		{
			viewModel = 0;
		}
	}
	if ( viewModel == 0 )
	{
		CG_FreeViewModelEntity();
		return;
	}
	// add hardcoded gun offset
	if ( !stricmp( viewModel->getName(), "models/weapons2/plasma/plasma.md3" )
			|| !stricmp( viewModel->getName(), "models/weapons2/railgun/railgun.md3" )
			|| !stricmp( viewModel->getName(), "models/weapons2/rocketl/rocketl.md3" )
			|| !stricmp( viewModel->getName(), "models/weapons2/shotgun/shotgun.md3" )
			// it could be better for grenade launcher
			|| !stricmp( viewModel->getName(), "models/weapons2/grenadel/grenadel.md3" ) )
	{
		localOfs.set( 5, -5, -10 );
	}
	else if ( !stricmp( viewModel->getName(), "models/weapons/w_physics.mdl" ) )
	{
		// Half Life2 physgun (for weapon_physgun)
		// "w_*" is a worldmodel
		// set 90 yaw rotation (around Z axis)
		localRot.set( 0, 0, 90 );
		localOfs.set( 5, -5, -10 );
	}
	else if ( !stricmp( viewModel->getName(), "models/weapons/v_physcannon.mdl" ) )
	{
		// "v_*" is a viewmodel
#if 0
		localRot.set( 0, 15, 90 );
		localOfs.set( -35, 0, -50 );
#else
		localRot.set( 0, 0, 90 );
		localOfs.set( -15, 0, -65 );
#endif
	}
	else
	{
		localRot = cg.snap->ps.viewModelAngles;
		localOfs = cg.snap->ps.viewModelOffset;
		
		if ( viewModel->isDeclModel() )
		{
			localOfs += viewModel->getDeclModelAPI()->getOffset();
		}
	}
	//g_core->Print("Player velocity: %f %f %f\n",cg.snap->ps.velocity.x,cg.snap->ps.velocity.y,cg.snap->ps.velocity.z);
	
	// calculate viewmodel bobbing offset based on player velocity
	viewModelMovement.setConfig( viewModelMovementConfig );
	viewModelMovement.calcViewModelOffset( cg.snap->ps.isOnGround(), cg.snap->ps.velocity, cg.refdefViewAngles, cg.frametime * 0.001f );
	const vec3_c& currentMovement = viewModelMovement.getCurrentMovement();
	localOfs += currentMovement;
	if ( cg_printViewModelBobbingOffset.getInt() )
	{
		g_core->Print( "Viewmodel bobbing movement: %f %f %f\n", currentMovement.x, currentMovement.y, currentMovement.z );
	}
	
	if ( cg_printCurViewModelName.getInt() )
	{
		g_core->Print( "Current viewmodel name: %s\n", viewModel->getName() );
	}
	if ( cg_printCurViewModelAnimationCount.getInt() )
	{
		g_core->Print( "Current viewmodel animation count: %i\n", viewModel->getNumAnims() );
	}
	if ( cg_printCurViewModelBoneNames.getInt() )
	{
		g_core->Print( "Current viewmodel %s bonenames:\n", viewModel->getName() );
		viewModel->printBoneNames();
	}
	
	CG_AllocViewModelEntity();
	
	vec3_c origin = cg.refdefViewOrigin;
	vec3_c angles = cg.refdefViewAngles;
	
	// apply extra gun offset
	localOfs.x += cg_gunX.getFloat();
	localOfs.y += cg_gunY.getFloat();
	localOfs.z += cg_gunZ.getFloat();
	
	// apply extra gun rotation
	localRot.x += cg_gunRotX.getFloat();
	localRot.y += cg_gunRotY.getFloat();
	localRot.z += cg_gunRotZ.getFloat();
	
	if ( localRot.isNull() == false )
	{
		matrix_c m;
		m.fromAngles( angles );
		m.rotateX( localRot.x );
		m.rotateY( localRot.y );
		m.rotateZ( localRot.z );
		angles = m.getAngles();
	}
	
	// add local offset to hand origin
	origin.vectorMA( origin, cg.refdefViewAxis[0], localOfs.x );
	origin.vectorMA( origin, cg.refdefViewAxis[1], localOfs.y );
	origin.vectorMA( origin, cg.refdefViewAxis[2], localOfs.z );
	
	// always update viewmodel position
	cg_viewModelEntity->setOrigin( origin );
	cg_viewModelEntity->setAngles( angles );
	cg_viewModelEntity->setFirstPersonOnly( true );
	// set viewmodel model
	//rModelAPI_i *viewModel = rf->registerModel("models/testweapons/xrealMachinegun/machinegun_view.md5mesh");
	cg_viewModelEntity->setModel( viewModel );
	int viewModelAnimFlags;
	if ( stricmp( cg_forceViewModelAnimationFlags.getStr(), "none" ) )
	{
		viewModelAnimFlags = cg_forceViewModelAnimationFlags.getInt();
	}
	else
	{
		viewModelAnimFlags = cg.snap->ps.viewModelAnimFlags;
	}
	if ( stricmp( cg_forceViewModelAnimationIndex.getStr(), "none" ) )
	{
		int index = cg_forceViewModelAnimationIndex.getInt();
		cg_viewModelEntity->setDeclModelAnimLocalIndex( index, viewModelAnimFlags );
	}
	else if ( stricmp( cg_forceViewModelAnimationName.getStr(), "none" ) )
	{
		const char* animName = cg_forceViewModelAnimationName.getStr();
		cg_viewModelEntity->setAnim( animName, viewModelAnimFlags );
	}
	else
	{
		const char* animName = CG_ConfigString( CS_ANIMATIONS + cg.snap->ps.viewModelAnim );
		if ( cg_printViewModelAnimName.getInt() )
		{
			g_core->Print( "ViewModelAnim: %s, flags %i\n", animName, viewModelAnimFlags );
		}
		if ( cg_viewModelEntity->hasAnim( animName ) )
		{
			cg_viewModelEntity->setAnim( animName, viewModelAnimFlags );
		}
		else
		{
			g_core->RedWarning( "ViewModel has no animation %s\n", animName );
		}
	}
}
Example #25
0
void procTree_c::addAreaDrawCalls_r( int areaNum, const frustumExt_c& fr, procPortal_c* prevPortal )
{
	if ( areaNum >= areas.size() || areaNum < 0 )
		return;
	procArea_c* ar = areas[areaNum];
	if ( ar == 0 )
		return;
	if ( ar->visCount != this->visCount )
	{
		//drawAreaDrawCalls(ar);
		ar->areaModel->addDrawCalls();
		ar->visCount = this->visCount;
	}
	for ( u32 i = 0; i < ar->portals.size(); i++ )
	{
		procPortal_c* p = ar->portals[i];
		if ( p == prevPortal )
		{
			continue;
		}
		// first check if the portal is in the frustum
		if ( fr.cull( p->bounds ) == CULL_OUT )
			continue;
		// then check if the portal side facing camera
		// belong to current area. If not, portal is occluded
		// by the wall and is not really visible
		float d = p->plane.distance( rf_camera.getOrigin() );
		if ( p->areas[0] == areaNum )
		{
			if ( d > 0 )
				continue;
		}
		else
		{
			if ( d < 0 )
				continue;
		}
		// adjust the frustum, so addAreaDrawCalls_r will never loop and cause a stack overflow...
		frustumExt_c adjusted;
		adjusted.adjustFrustum( fr, rf_camera.getOrigin(), p->points, p->plane );
		if ( adjusted.size() == 0 )
		{
			// it happend very often and doesn't seem to cause any visible errors
			if ( rf_proc_printChoppedFrustums.getInt() )
			{
				g_core->RedWarning( "procTree_c::addAreaDrawCalls_r: frustum chopped away (dist %f)\n", d );
			}
			continue;
		}
		
		if ( p->visCount != this->visCount )
		{
			p->visCount = this->visCount;
			p->visitCount = 0;
		}
		else
		{
			if ( p->visitCount >= MAX_PORTAL_VISIT_COUNT )
			{
				g_core->RedWarning( "MAX_PORTAL_VISIT_COUNT!!!\n" );
				continue;
			}
		}
		p->lastFrustum[p->visitCount] = adjusted;
		p->visitCount++;
		
		if ( p->areas[0] == areaNum )
		{
			addAreaDrawCalls_r( p->areas[1], adjusted, p );
		}
		else
		{
			addAreaDrawCalls_r( p->areas[0], adjusted, p );
		}
	}
}