Exemple #1
0
/*
* AI_MoveToShortRangeGoalEntity
* A.K.A Item pick magnet
*/
qboolean AI_MoveToShortRangeGoalEntity( edict_t *self, usercmd_t *ucmd )
{
	if( !self->movetarget || !self->r.client )
		return qfalse;

	if( self->ai.goalEnt && ( self->ai.goalEnt->ent == self->movetarget )
		&& ( AI_GetNodeFlags( self->ai.goal_node ) & NODEFLAGS_ENTITYREACH ) )
	{
		// wait
		VectorSubtract( self->movetarget->s.origin, self->s.origin, self->ai.move_vector );
		if( VectorLength( self->ai.move_vector ) < 72 )
			ucmd->buttons |= BUTTON_WALK;

		if( BoundsIntersect( self->movetarget->r.absmin, self->movetarget->r.absmax, self->r.absmin, self->r.absmax ) )
		{
			ucmd->forwardmove = 0;
			ucmd->sidemove = 0;
			ucmd->upmove = 0;
			self->ai.node_timeout = 0;
			return qtrue;
		}
	}

	if( self->movetarget->r.solid == SOLID_NOT || DistanceFast( self->movetarget->s.origin, self->s.origin ) > AI_GOAL_SR_RADIUS + 72 )
	{
		self->movetarget = NULL;
		self->ai.shortRangeGoalTimeout = level.time;
		return qfalse;
	}

	// Force movement direction to reach the goal entity
	VectorSubtract( self->movetarget->s.origin, self->s.origin, self->ai.move_vector );

	return qtrue;
}
Exemple #2
0
/*
* R_SurfaceShadowBits
*/
static unsigned int R_SurfaceShadowBits( const msurface_t *surf, unsigned int checkShadowBits )
{
	unsigned int i, bit;
	shadowGroup_t *grp;
	unsigned int surfShadowBits = 0;

	if( !R_SurfPotentiallyShadowed( surf ) ) {
		return 0;
	}

	for( i = 0; i < rsc.numShadowGroups; i++ ) {
		if( !checkShadowBits ) {
			break;
		}

		grp = rsc.shadowGroups + i;
		bit = grp->bit;

		if( checkShadowBits & bit ) {
			switch( surf->facetype ) {
				case FACETYPE_PLANAR:
					if ( BoundsIntersect( surf->mins, surf->maxs, grp->visMins, grp->visMaxs ) ) {
						float dist = PlaneDiff( grp->visOrigin, surf->plane );
						if ( dist > -grp->visRadius && dist <= grp->visRadius ) {
							// crossed by plane
							surfShadowBits |= bit;
						}
					}
					break;
				case FACETYPE_PATCH:
				case FACETYPE_TRISURF:
				case FACETYPE_FOLIAGE:
					if( BoundsIntersect( surf->mins, surf->maxs, grp->visMins, grp->visMaxs ) ) {
						surfShadowBits |= bit;
					}
					break;
			}
			checkShadowBits &= ~bit;
		}
	}
	
	return surfShadowBits;
}
Exemple #3
0
/*
=====================
RE_AddPolyBufferToScene
=====================
*/
void RE_AddPolyBufferToScene( polyBuffer_t *pPolyBuffer )
{
	srfPolyBuffer_t *pPolySurf;
	int             fogIndex;
	fog_t           *fog;
	vec3_t          bounds[ 2 ];
	int             i;

	if ( !r_drawpolies->integer )
	{
		return;
	}

	if ( r_numPolybuffers >= r_maxPolyVerts->integer )
	{
		return;
	}

	pPolySurf = &backEndData[ tr.smpFrame ]->polybuffers[ r_numPolybuffers ];
	r_numPolybuffers++;

	pPolySurf->surfaceType = surfaceType_t::SF_POLYBUFFER;
	pPolySurf->pPolyBuffer = pPolyBuffer;

	VectorCopy( pPolyBuffer->xyz[ 0 ], bounds[ 0 ] );
	VectorCopy( pPolyBuffer->xyz[ 0 ], bounds[ 1 ] );

	for ( i = 1; i < pPolyBuffer->numVerts; i++ )
	{
		AddPointToBounds( pPolyBuffer->xyz[ i ], bounds[ 0 ], bounds[ 1 ] );
	}

	for ( fogIndex = 1; fogIndex < tr.world->numFogs; fogIndex++ )
	{
		fog = &tr.world->fogs[ fogIndex ];

		if ( BoundsIntersect( bounds[ 0 ], bounds[ 1 ], fog->bounds[ 0 ], fog->bounds[ 1 ] ) )
		{
			break;
		}
	}

	if ( fogIndex == tr.world->numFogs )
	{
		fogIndex = 0;
	}

	pPolySurf->fogIndex = fogIndex;
}
Exemple #4
0
/*
=====================
RE_AddPolyBufferToScene
=====================
*/
void RE_AddPolyBufferToScene(polyBuffer_t *pPolyBuffer)
{
    srfPolyBuffer_t *pPolySurf;
    int             fogIndex;
    fog_t           *fog;
    vec3_t          bounds[2];
    int             i;

    if (!r_drawpolies->integer)
    {
        return;
    }

    if (r_numPolybuffers >= MAX_POLYBUFFERS)
    {
        Ren_Warning("WARNING RE_AddPolyBufferToScene: MAX_POLYBUFFERS (%d) reached\n", MAX_POLYBUFFERS);
        return;
    }

    pPolySurf = &backEndData->polybuffers[r_numPolybuffers];
    r_numPolybuffers++;

    pPolySurf->surfaceType = SF_POLYBUFFER;
    pPolySurf->pPolyBuffer = pPolyBuffer;

    VectorCopy(pPolyBuffer->xyz[0], bounds[0]);
    VectorCopy(pPolyBuffer->xyz[0], bounds[1]);
    for (i = 1; i < pPolyBuffer->numVerts; i++)
    {
        AddPointToBounds(pPolyBuffer->xyz[i], bounds[0], bounds[1]);
    }

    for (fogIndex = 1; fogIndex < tr.world->numFogs; fogIndex++)
    {
        fog = &tr.world->fogs[fogIndex];

        if (BoundsIntersect(bounds[0], bounds[1], fog->bounds[0], fog->bounds[1]))
        {
            break;
        }
    }
    if (fogIndex == tr.world->numFogs)
    {
        fogIndex = 0;
    }

    pPolySurf->fogIndex = fogIndex;
}
Exemple #5
0
/////////////////////////////////////
// Purpose:	find collision with the given
//			model inside the map.
//			NOTE: testT is the starting
//				  't' value (starting minimum)
//				  usu. set as 't = 1'
//				  set mins & maxs to 0 to test
//				  as point
// Output:	pTrace filled
// Return:	true if collided
/////////////////////////////////////
u8 IgfxQBSP::ModelCollision(u32 modelInd, const Vec3D *mins, const Vec3D *maxs,
                            const Vec3D &pt1, const Vec3D &pt2, gfxTrace *pTrace, f32 testT)
{
    memset(pTrace, 0, sizeof(gfxTrace));
    pTrace->t = testT;

    if(TESTFLAGS(m_models[modelInd].status, QBSP_MODEL_FLAG_DISABLE))
        return FALSE;

    Vec3D vec(pt2-pt1);

    //determine if we are colliding with bbox or pt.
    u8 bIsPt = (mins && maxs) ? FALSE : TRUE;

    Vec3D bbMin, bbMax;
    RayModelGetBBoxMin(modelInd, &bbMin);
    RayModelGetBBoxMax(modelInd, &bbMax);

    // build a bounding box of the entire move
    Vec3D trace_absmins, trace_absmaxs;
    Vec3D point;

    BoundsClear(trace_absmins, trace_absmaxs);

    point = mins ? pt1 + (*mins) : pt1;
    BoundsAddPoint(point, trace_absmins, trace_absmaxs);
    point = maxs ? pt1 + (*maxs) : pt1;
    BoundsAddPoint(point, trace_absmins, trace_absmaxs);
    point = mins ? pt2 + (*mins) : pt2;
    BoundsAddPoint(point, trace_absmins, trace_absmaxs);
    point = maxs ? pt2 + (*maxs) : pt2;
    BoundsAddPoint(point, trace_absmins, trace_absmaxs);

    if(BoundsIntersect(bbMin, bbMax, trace_absmins, trace_absmaxs))
    {
        // Loop through and check all of the brushes in this model
        for(s32 i = 0; i < m_models[modelInd].numOfBrushes; i++)
        {
            _mdlCollBrush(&m_models[modelInd].brushes[i], bIsPt, mins, maxs,
                          pt1, vec, pTrace);
        }
    }

    if(pTrace->t < testT)
        return TRUE;

    return FALSE;
}
Exemple #6
0
/*
====================
SV_AddLaddersToPmove
====================
*/
void SV_AddLaddersToPmove( areanode_t *node, const vec3_t pmove_mins, const vec3_t pmove_maxs )
{
    link_t	*l, *next;
    edict_t	*check;
    physent_t	*pe;

    // get water edicts
    for( l = node->water_edicts.next; l != &node->water_edicts; l = next )
    {
        next = l->next;
        check = EDICT_FROM_AREA( l );

        if( check->v.solid != SOLID_NOT ) // disabled ?
            continue;

        // only brushes can have special contents
        if( Mod_GetType( check->v.modelindex ) != mod_brush )
            continue;

        if( !BoundsIntersect( pmove_mins, pmove_maxs, check->v.absmin, check->v.absmax ))
            continue;

        if( svgame.pmove->nummoveent == MAX_MOVEENTS )
            return;

        pe = &svgame.pmove->moveents[svgame.pmove->nummoveent];
        if( SV_CopyEdictToPhysEnt( pe, check ))
            svgame.pmove->nummoveent++;
    }

    // recurse down both sides
    if( node->axis == -1 ) return;

    if( pmove_maxs[node->axis] > node->dist )
        SV_AddLaddersToPmove( node->children[0], pmove_mins, pmove_maxs );
    if( pmove_mins[node->axis] < node->dist )
        SV_AddLaddersToPmove( node->children[1], pmove_mins, pmove_maxs );
}
Exemple #7
0
/*
* GClip_EntityContact
*/
static qboolean GClip_EntityContact( vec3_t mins, vec3_t maxs, edict_t *ent )
{
	trace_t tr;
	struct cmodel_s *model;

	if( !mins )
		mins = vec3_origin;
	if( !maxs )
		maxs = vec3_origin;

	if( ISBRUSHMODEL( ent->s.modelindex ) )
	{
		model = trap_CM_InlineModel( ent->s.modelindex );
		if( !model )
			G_Error( "MOVETYPE_PUSH with a non bsp model" );

		trap_CM_TransformedBoxTrace( &tr, vec3_origin, vec3_origin, mins, maxs, model, MASK_ALL, ent->s.origin, ent->s.angles );

		return tr.startsolid || tr.allsolid;
	}

	return ( BoundsIntersect( mins, maxs, ent->r.absmin, ent->r.absmax ) );
}
Exemple #8
0
/*
* GClip_EntitiesInBox_AreaGrid
*/
static int GClip_EntitiesInBox_AreaGrid( areagrid_t *areagrid, const vec3_t mins, const vec3_t maxs, 
	int *list, int maxcount, int areatype, int timeDelta )
{
	int numlist;
	link_t *grid;
	link_t *l;
	c4clipedict_t *clipEnt;
	vec3_t paddedmins, paddedmaxs;
	int igrid[3], igridmins[3], igridmaxs[3];

	// LordHavoc: discovered this actually causes its own bugs (dm6 teleporters 
	// being too close to info_teleport_destination)
	//VectorSet( paddedmins, mins[0] - 1.0f, mins[1] - 1.0f, mins[2] - 1.0f );
	//VectorSet( paddedmaxs, maxs[0] + 1.0f, maxs[1] + 1.0f, maxs[2] + 1.0f );
	VectorCopy( mins, paddedmins );
	VectorCopy( maxs, paddedmaxs );

	// FIXME: if areagrid_marknumber wraps, all entities need their
	// ent->priv.server->areagridmarknumber reset
	areagrid->marknumber++;

	igridmins[0] = (int) floor( (paddedmins[0] + areagrid->bias[0]) * areagrid->scale[0] );
	igridmins[1] = (int) floor( (paddedmins[1] + areagrid->bias[1]) * areagrid->scale[1] );
	//igridmins[2] = (int) ( (paddedmins[2] + areagrid->bias[2]) * areagrid->scale[2] );
	igridmaxs[0] = (int) floor( (paddedmaxs[0] + areagrid->bias[0]) * areagrid->scale[0] ) + 1;
	igridmaxs[1] = (int) floor( (paddedmaxs[1] + areagrid->bias[1]) * areagrid->scale[1] ) + 1;
	//igridmaxs[2] = (int) ( (paddedmaxs[2] + areagrid->bias[2]) * areagrid->scale[2] ) + 1;
	igridmins[0] = max( 0, igridmins[0] );
	igridmins[1] = max( 0, igridmins[1] );
	//igridmins[2] = max( 0, igridmins[2] );
	igridmaxs[0] = min( AREA_GRID, igridmaxs[0] );
	igridmaxs[1] = min( AREA_GRID, igridmaxs[1] );
	//igridmaxs[2] = min( AREA_GRID, igridmaxs[2] );

	// paranoid debugging
	//VectorSet( igridmins, 0, 0, 0 );VectorSet( igridmaxs, AREA_GRID, AREA_GRID, AREA_GRID );

	numlist = 0;

	// add entities not linked into areagrid because they are too big or
	// outside the grid bounds
	if( areagrid->outside.next )
	{
		grid = &areagrid->outside;
		for( l = grid->next; l != grid; l = l->next ) {
			clipEnt = GClip_GetClipEdictForDeltaTime( l->entNum, timeDelta );

			if( areagrid->entmarknumber[l->entNum] == areagrid->marknumber ) {
				continue;
			}
			areagrid->entmarknumber[l->entNum] = areagrid->marknumber;

			if( !clipEnt->r.inuse ) {
				continue; // deactivated
			}
			if( areatype == AREA_TRIGGERS && clipEnt->r.solid != SOLID_TRIGGER ) {
				continue;
			}
			if( areatype == AREA_SOLID && 
				( clipEnt->r.solid == SOLID_TRIGGER || clipEnt->r.solid == SOLID_NOT ) ) {
				continue;
			}

			if( BoundsIntersect( paddedmins, paddedmaxs, clipEnt->r.absmin, clipEnt->r.absmax )) {
				if( numlist < maxcount ) {
					list[numlist] = l->entNum;
				}
				numlist++;
			}
		}
	}

	// add grid linked entities
	for( igrid[1] = igridmins[1]; igrid[1] < igridmaxs[1]; igrid[1]++ ) {
		grid = areagrid->grid + igrid[1] * AREA_GRID + igridmins[0];

		for( igrid[0] = igridmins[0]; igrid[0] < igridmaxs[0]; igrid[0]++, grid++ ) {
			if( !grid->next ) {
				continue;
			}

			for( l = grid->next; l != grid; l = l->next ) {
				clipEnt = GClip_GetClipEdictForDeltaTime( l->entNum, timeDelta );

				if( areagrid->entmarknumber[l->entNum] == areagrid->marknumber ) {
					continue;
				}
				areagrid->entmarknumber[l->entNum] = areagrid->marknumber;

				if( !clipEnt->r.inuse ) {
					continue; // deactivated
				}
				if( areatype == AREA_TRIGGERS && clipEnt->r.solid != SOLID_TRIGGER ) {
					continue;
				}
				if( areatype == AREA_SOLID && 
					( clipEnt->r.solid == SOLID_TRIGGER || clipEnt->r.solid == SOLID_NOT ) ) {
					continue;
				}

				if( BoundsIntersect( paddedmins, paddedmaxs, clipEnt->r.absmin, clipEnt->r.absmax )) {
					if( numlist < maxcount ) {
						list[numlist] = l->entNum;
					}
					numlist++;
				}
			}
		}
	}

	return numlist;
}
/*
=================
R_AddMD5Interactions
=================
*/
void R_AddMD5Interactions(trRefEntity_t * ent, trRefLight_t * light)
{
	int             i;
	md5Model_t     *model;
	md5Surface_t   *surface;
	shader_t       *shader = 0;
	qboolean        personalModel;
	byte            cubeSideBits = CUBESIDE_CLIPALL;
	interactionType_t iaType = IA_DEFAULT;

	// cull the entire model if merged bounding box of both frames
	// is outside the view frustum and we don't care about proper shadowing
	if(ent->cull == CULL_OUT)
	{
		if(r_shadows->integer <= SHADOWING_BLOB || light->l.noShadows)
			return;
		else
			iaType = IA_SHADOWONLY;
	}

	// avoid drawing of certain objects
#if defined(USE_REFENTITY_NOSHADOWID)
	if(light->l.inverseShadows)
	{
		if(iaType != IA_LIGHTONLY && (light->l.noShadowID && (light->l.noShadowID != ent->e.noShadowID)))
			return;
	}
	else
	{
		if(iaType != IA_LIGHTONLY && (light->l.noShadowID && (light->l.noShadowID == ent->e.noShadowID)))
			return;
	}
#endif

	// don't add third_person objects if not in a portal
	personalModel = (ent->e.renderfx & RF_THIRD_PERSON) && !tr.viewParms.isPortal;

	model = tr.currentModel->md5;

	// do a quick AABB cull
	if(!BoundsIntersect(light->worldBounds[0], light->worldBounds[1], ent->worldBounds[0], ent->worldBounds[1]))
	{
		tr.pc.c_dlightSurfacesCulled += model->numSurfaces;
		return;
	}

	// do a more expensive and precise light frustum cull
	if(!r_noLightFrustums->integer)
	{
		if(R_CullLightWorldBounds(light, ent->worldBounds) == CULL_OUT)
		{
			tr.pc.c_dlightSurfacesCulled += model->numSurfaces;
			return;
		}
	}

	cubeSideBits = R_CalcLightCubeSideBits(light, ent->worldBounds);

	if(!r_vboModels->integer || !model->numVBOSurfaces ||
	   (!glConfig2.vboVertexSkinningAvailable && ent->e.skeleton.type == SK_ABSOLUTE))
	{
		// generate interactions with all surfaces
		for(i = 0, surface = model->surfaces; i < model->numSurfaces; i++, surface++)
		{
			if(ent->e.customShader)
			{
				shader = R_GetShaderByHandle(ent->e.customShader);
			}
			else if(ent->e.customSkin > 0 && ent->e.customSkin < tr.numSkins)
			{
				skin_t         *skin;

				skin = R_GetSkinByHandle(ent->e.customSkin);

				// match the surface name to something in the skin file
				shader = tr.defaultShader;

				// FIXME: replace MD3_MAX_SURFACES for skin_t::surfaces
				if(i >= 0 && i < skin->numSurfaces && skin->surfaces[i])
				{
					shader = skin->surfaces[i]->shader;
				}
				if(shader == tr.defaultShader)
				{
					ri.Printf(PRINT_DEVELOPER, "WARNING: no shader for surface %i in skin %s\n", i, skin->name);
				}
				else if(shader->defaultShader)
				{
					ri.Printf(PRINT_DEVELOPER, "WARNING: shader %s in skin %s not found\n", shader->name, skin->name);
				}
			}
			else
			{
				shader = R_GetShaderByHandle(surface->shaderIndex);
			}

			// skip all surfaces that don't matter for lighting only pass
			if(shader->isSky || (!shader->interactLight && shader->noShadows))
				continue;

			// we will add shadows even if the main object isn't visible in the view

			// don't add third_person objects if not viewing through a portal
			if(!personalModel)
			{
				R_AddLightInteraction(light, (void *)surface, shader, cubeSideBits, iaType);
				tr.pc.c_dlightSurfaces++;
			}
		}
	}
	else
	{
		int             i;
		srfVBOMD5Mesh_t *vboSurface;
		shader_t       *shader;

		for(i = 0; i < model->numVBOSurfaces; i++)
		{
			vboSurface = model->vboSurfaces[i];

			if(ent->e.customShader)
			{
				shader = R_GetShaderByHandle(ent->e.customShader);
			}
			else if(ent->e.customSkin > 0 && ent->e.customSkin < tr.numSkins)
			{
				skin_t         *skin;

				skin = R_GetSkinByHandle(ent->e.customSkin);

				// match the surface name to something in the skin file
				shader = tr.defaultShader;

				// FIXME: replace MD3_MAX_SURFACES for skin_t::surfaces
				if(i >= 0 && i < skin->numSurfaces && skin->surfaces[i])
				{
					shader = skin->surfaces[i]->shader;
				}
				if(shader == tr.defaultShader)
				{
					ri.Printf(PRINT_DEVELOPER, "WARNING: no shader for surface %i in skin %s\n", i, skin->name);
				}
				else if(shader->defaultShader)
				{
					ri.Printf(PRINT_DEVELOPER, "WARNING: shader %s in skin %s not found\n", shader->name, skin->name);
				}
			}
			else
			{
				shader = vboSurface->shader;
			}

			// skip all surfaces that don't matter for lighting only pass
			if(shader->isSky || (!shader->interactLight && shader->noShadows))
				continue;

			// don't add third_person objects if not viewing through a portal
			if(!personalModel)
			{
				R_AddLightInteraction(light, (void *)vboSurface, shader, cubeSideBits, iaType);
				tr.pc.c_dlightSurfaces++;
			}
		}
	}
}
Exemple #10
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;
}
Exemple #11
0
/*
=====================
R_AddPolysToScene
=====================
*/
static void R_AddPolysToScene( qhandle_t hShader, int numVerts, const polyVert_t *verts, int numPolys )
{
	srfPoly_t *poly;
	int       i, j;
	int       fogIndex;
	fog_t     *fog;
	vec3_t    bounds[ 2 ];

	if ( !tr.registered )
	{
		return;
	}

	if ( !r_drawpolies->integer )
	{
		return;
	}

	if ( !hShader )
	{
		Log::Warn("RE_AddPolyToScene: NULL poly shader" );
		return;
	}

	for ( j = 0; j < numPolys; j++ )
	{
		if ( r_numPolyVerts + numVerts >= r_maxPolyVerts->integer || r_numPolys >= r_maxPolys->integer )
		{
			/*
			   NOTE TTimo this was initially Log::Warn
			   but it happens a lot with high fighting scenes and particles
			   since we don't plan on changing the const and making for room for those effects
			   simply cut this message to developer only
			 */
			Log::Debug("RE_AddPolyToScene: r_max_polys or r_max_polyverts reached\n" );
			return;
		}

		poly = &backEndData[ tr.smpFrame ]->polys[ r_numPolys ];
		poly->surfaceType = surfaceType_t::SF_POLY;
		poly->hShader = hShader;
		poly->numVerts = numVerts;
		poly->verts = &backEndData[ tr.smpFrame ]->polyVerts[ r_numPolyVerts ];

		Com_Memcpy( poly->verts, &verts[ numVerts * j ], numVerts * sizeof( *verts ) );

		// done.
		r_numPolys++;
		r_numPolyVerts += numVerts;

		// if no world is loaded
		if ( tr.world == nullptr )
		{
			fogIndex = 0;
		}
		// see if it is in a fog volume
		else if ( tr.world->numFogs == 1 )
		{
			fogIndex = 0;
		}
		else
		{
			// find which fog volume the poly is in
			VectorCopy( poly->verts[ 0 ].xyz, bounds[ 0 ] );
			VectorCopy( poly->verts[ 0 ].xyz, bounds[ 1 ] );

			for ( i = 1; i < poly->numVerts; i++ )
			{
				AddPointToBounds( poly->verts[ i ].xyz, bounds[ 0 ], bounds[ 1 ] );
			}

			for ( fogIndex = 1; fogIndex < tr.world->numFogs; fogIndex++ )
			{
				fog = &tr.world->fogs[ fogIndex ];

				if ( BoundsIntersect( bounds[ 0 ], bounds[ 1 ], fog->bounds[ 0 ], fog->bounds[ 1 ] ) )
				{
					break;
				}
			}

			if ( fogIndex == tr.world->numFogs )
			{
				fogIndex = 0;
			}
		}

		poly->fogIndex = fogIndex;
	}
}
Exemple #12
0
/*
=================
R_TraceLine
=================
*/
msurface_t *R_TransformedTraceLine( trace_t *tr, const vec3_t start, const vec3_t end, ref_entity_t *test, int umask )
{
	ref_model_t	*model;

	r_fragmentframecount++;	// for multi-check avoidance

	// fill in a default trace
	Mem_Set( tr, 0, sizeof( trace_t ));

	trace_surface = NULL;
	trace_umask = umask;
	trace_fraction = 1;
	VectorCopy( end, trace_impact );
	Mem_Set( &trace_plane, 0, sizeof( trace_plane ));

	ClearBounds( trace_absmins, trace_absmaxs );
	AddPointToBounds( start, trace_absmins, trace_absmaxs );
	AddPointToBounds( end, trace_absmins, trace_absmaxs );

	model = test->model;
	if( model )
	{
		if( model->type == mod_world || model->type == mod_brush )
		{
			mbrushmodel_t *bmodel = ( mbrushmodel_t * )model->extradata;
			vec3_t temp, start_l, end_l, axis[3];
			bool rotated = !Matrix3x3_Compare( test->axis, matrix3x3_identity );

			// transform
			VectorSubtract( start, test->origin, start_l );
			VectorSubtract( end, test->origin, end_l );
			if( rotated )
			{
				VectorCopy( start_l, temp );
				Matrix3x3_Transform( test->axis, temp, start_l );
				VectorCopy( end_l, temp );
				Matrix3x3_Transform( test->axis, temp, end_l );
			}

			VectorCopy( start_l, trace_start );
			VectorCopy( end_l, trace_end );

			// world uses a recursive approach using BSP tree, submodels
			// just walk the list of surfaces linearly
			if( test->model->type == mod_world )
				R_RecursiveHullCheck( bmodel->nodes, start_l, end_l );
			else if( BoundsIntersect( model->mins, model->maxs, trace_absmins, trace_absmaxs ) )
				R_TraceAgainstBmodel( bmodel );

			// transform back
			if( rotated && trace_fraction != 1 )
			{
				Matrix3x3_Transpose( axis, test->axis );
				VectorCopy( tr->vecPlaneNormal, temp );
				Matrix3x3_Transform( axis, temp, trace_plane.normal );
			}
		}
	}

	// calculate the impact plane, if any
	if( trace_fraction < 1.0f )
	{
		VectorNormalize( trace_plane.normal );
		trace_plane.dist = DotProduct( trace_plane.normal, trace_impact );
		CategorizePlane( &trace_plane );

		tr->flPlaneDist = trace_plane.dist;
		VectorCopy( trace_plane.normal, tr->vecPlaneNormal );
		tr->iContents = trace_surface->contents;
		tr->pHit = (edict_t *)test;
	}
	
	tr->flFraction = trace_fraction;
	VectorCopy( trace_impact, tr->vecEndPos );

	return trace_surface;
}
/*
=================
R_AddIQMInteractions
=================
*/
void R_AddIQMInteractions( trRefEntity_t *ent, trRefLight_t *light, interactionType_t iaType )
{
	int               i;
	IQModel_t         *model;
	srfIQModel_t      *surface;
	shader_t          *shader = 0;
	bool          personalModel;
	byte              cubeSideBits = CUBESIDE_CLIPALL;

	// cull the entire model if merged bounding box of both frames
	// is outside the view frustum and we don't care about proper shadowing
	if ( ent->cull == cullResult_t::CULL_OUT )
	{
		iaType = (interactionType_t) (iaType & ~IA_LIGHT);

		if( !iaType ) {
			return;
		}
	}

	// avoid drawing of certain objects
#if defined( USE_REFENTITY_NOSHADOWID )

	if ( light->l.inverseShadows )
	{
		if ( (iaType & IA_SHADOW) && ( light->l.noShadowID && ( light->l.noShadowID != ent->e.noShadowID ) ) )
		{
			return;
		}
	}
	else
	{
		if ( (iaType & IA_SHADOW) && ( light->l.noShadowID && ( light->l.noShadowID == ent->e.noShadowID ) ) )
		{
			return;
		}
	}

#endif

	// don't add third_person objects if not in a portal
	personalModel = ( ent->e.renderfx & RF_THIRD_PERSON ) && !tr.viewParms.isPortal;

	model = tr.currentModel->iqm;

	// do a quick AABB cull
	if ( !BoundsIntersect( light->worldBounds[ 0 ], light->worldBounds[ 1 ], ent->worldBounds[ 0 ], ent->worldBounds[ 1 ] ) )
	{
		tr.pc.c_dlightSurfacesCulled += model->num_surfaces;
		return;
	}

	// do a more expensive and precise light frustum cull
	if ( !r_noLightFrustums->integer )
	{
		if ( R_CullLightWorldBounds( light, ent->worldBounds ) == cullResult_t::CULL_OUT )
		{
			tr.pc.c_dlightSurfacesCulled += model->num_surfaces;
			return;
		}
	}

	cubeSideBits = R_CalcLightCubeSideBits( light, ent->worldBounds );

		// generate interactions with all surfaces
		for ( i = 0, surface = model->surfaces; i < model->num_surfaces; i++, surface++ )
		{
			if ( ent->e.customShader )
			{
				shader = R_GetShaderByHandle( ent->e.customShader );
			}
			else if ( ent->e.customSkin > 0 && ent->e.customSkin < tr.numSkins )
			{
				skin_t *skin;

				skin = R_GetSkinByHandle( ent->e.customSkin );

				// match the surface name to something in the skin file
				shader = tr.defaultShader;

				// FIXME: replace MD3_MAX_SURFACES for skin_t::surfaces
				if ( i >= 0 && i < skin->numSurfaces && skin->surfaces[ i ] )
				{
					shader = skin->surfaces[ i ]->shader;
				}

				if ( shader == tr.defaultShader )
				{
					Log::Warn("no shader for surface %i in skin %s", i, skin->name );
				}
				else if ( shader->defaultShader )
				{
					Log::Warn("shader %s in skin %s not found", shader->name, skin->name );
				}
			}
			else
			{
				shader = R_GetShaderByHandle( surface->shader->index );
			}

			// skip all surfaces that don't matter for lighting only pass
			if ( shader->isSky || ( !shader->interactLight && shader->noShadows ) )
			{
				continue;
			}

			// we will add shadows even if the main object isn't visible in the view

			// don't add third_person objects if not viewing through a portal
			if ( !personalModel )
			{
				R_AddLightInteraction( light, ( surfaceType_t * ) surface, shader, cubeSideBits, iaType );
				tr.pc.c_dlightSurfaces++;
			}
		}
}
Exemple #14
0
/*
====================
SV_AddLinksToPmove

collect solid entities
====================
*/
void SV_AddLinksToPmove( areanode_t *node, const vec3_t pmove_mins, const vec3_t pmove_maxs )
{
    link_t	*l, *next;
    edict_t	*check, *pl;
    vec3_t	mins, maxs;
    physent_t	*pe;

    pl = EDICT_NUM( svgame.pmove->player_index + 1 );
    //ASSERT( SV_IsValidEdict( pl ));
    if( !SV_IsValidEdict( pl ) )
    {
        MsgDev( D_ERROR, "SV_AddLinksToPmove: you have broken clients!\n");
        return;
    }

    // touch linked edicts
    for( l = node->solid_edicts.next; l != &node->solid_edicts; l = next )
    {
        next = l->next;
        check = EDICT_FROM_AREA( l );

        if( check->v.groupinfo != 0 )
        {
            if(( !svs.groupop && (check->v.groupinfo & pl->v.groupinfo ) == 0) ||
                    ( svs.groupop == 1 && ( check->v.groupinfo & pl->v.groupinfo ) != 0 ))
                continue;
        }

        if( ( ( check->v.owner > 0) && check->v.owner == pl ) || check->v.solid == SOLID_TRIGGER )
            continue; // player or player's own missile

        if( svgame.pmove->numvisent < MAX_PHYSENTS )
        {
            pe = &svgame.pmove->visents[svgame.pmove->numvisent];
            if( SV_CopyEdictToPhysEnt( pe, check ))
                svgame.pmove->numvisent++;
        }

        if( check->v.solid == SOLID_NOT && ( check->v.skin == CONTENTS_NONE || check->v.modelindex == 0 ))
            continue;

        // ignore monsterclip brushes
        if(( check->v.flags & FL_MONSTERCLIP ) && check->v.solid == SOLID_BSP )
            continue;

        if( check == pl ) continue;	// himself

        if( !sv_corpse_solid->value )
        {
            if((( check->v.flags & FL_CLIENT ) && check->v.health <= 0 ) || check->v.deadflag == DEAD_DEAD )
                continue;	// dead body
        }

        if( VectorIsNull( check->v.size ))
            continue;

        VectorCopy( check->v.absmin, mins );
        VectorCopy( check->v.absmax, maxs );

        if( check->v.flags & FL_CLIENT )
        {
            // trying to get interpolated values
            if( svs.currentPlayer )
                SV_GetTrueMinMax( svs.currentPlayer, ( NUM_FOR_EDICT( check ) - 1), mins, maxs );
        }

        if( !BoundsIntersect( pmove_mins, pmove_maxs, mins, maxs ))
            continue;

        if( svgame.pmove->numphysent < MAX_PHYSENTS )
        {
            pe = &svgame.pmove->physents[svgame.pmove->numphysent];

            if( SV_CopyEdictToPhysEnt( pe, check ))
                svgame.pmove->numphysent++;
        }
    }

    // recurse down both sides
    if( node->axis == -1 ) return;

    if( pmove_maxs[node->axis] > node->dist )
        SV_AddLinksToPmove( node->children[0], pmove_mins, pmove_maxs );
    if( pmove_mins[node->axis] < node->dist )
        SV_AddLinksToPmove( node->children[1], pmove_mins, pmove_maxs );
}
Exemple #15
0
/**
 * @brief R_AddMDVInteractions
 * @param[in] ent
 * @param[in] light
 */
void R_AddMDVInteractions(trRefEntity_t *ent, trRefLight_t *light)
{
	int               i;
	mdvModel_t        *model      = 0;
	mdvSurface_t      *mdvSurface = 0;
	shader_t          *shader     = 0;
	int               lod;
	qboolean          personalModel;
	byte              cubeSideBits;
	interactionType_t iaType = IA_DEFAULT;

	// cull the entire model if merged bounding box of both frames
	// is outside the view frustum and we don't care about proper shadowing
	if (ent->cull == CULL_OUT)
	{
		if (r_shadows->integer <= SHADOWING_BLOB || light->l.noShadows)
		{
			return;
		}
		else
		{
			iaType = IA_SHADOWONLY;
		}
	}

	// avoid drawing of certain objects
#if defined(USE_REFENTITY_NOSHADOWID)
	if (light->l.inverseShadows)
	{
		if (iaType != IA_LIGHTONLY && (light->l.noShadowID && (light->l.noShadowID != ent->e.noShadowID)))
		{
			return;
		}
	}
	else
	{
		if (iaType != IA_LIGHTONLY && (light->l.noShadowID && (light->l.noShadowID == ent->e.noShadowID)))
		{
			return;
		}
	}
#endif

	// don't add third_person objects if not in a portal
	personalModel = (ent->e.renderfx & RF_THIRD_PERSON) && !tr.viewParms.isPortal;

	// compute LOD
	lod = R_ComputeLOD(ent);

	model = tr.currentModel->mdv[lod];

	// do a quick AABB cull
	if (!BoundsIntersect(light->worldBounds[0], light->worldBounds[1], ent->worldBounds[0], ent->worldBounds[1]))
	{
		tr.pc.c_dlightSurfacesCulled += model->numSurfaces;
		return;
	}

	// do a more expensive and precise light frustum cull
	if (!r_noLightFrustums->integer)
	{
		if (R_CullLightWorldBounds(light, ent->worldBounds) == CULL_OUT)
		{
			tr.pc.c_dlightSurfacesCulled += model->numSurfaces;
			return;
		}
	}

	cubeSideBits = R_CalcLightCubeSideBits(light, ent->worldBounds);

	// generate interactions with all surfaces
	if (r_vboModels->integer && model->numVBOSurfaces)
	{
		// new brute force method: just render everthing with static VBOs
		int             i;
		srfVBOMDVMesh_t *vboSurface;
		shader_t        *shader;


		// static VBOs are fine for lighting and shadow mapping
		for (i = 0; i < model->numVBOSurfaces; i++)
		{
			vboSurface = model->vboSurfaces[i];
			mdvSurface = vboSurface->mdvSurface;

			shader = GetMDVSurfaceShader(ent, mdvSurface);

			// skip all surfaces that don't matter for lighting only pass
			if (shader->isSky || (!shader->interactLight && shader->noShadows))
			{
				continue;
			}

			// we will add shadows even if the main object isn't visible in the view

			// don't add third_person objects if not viewing through a portal
			if (!personalModel)
			{
				R_AddLightInteraction(light, (surfaceType_t *)vboSurface, shader, cubeSideBits, iaType);
				tr.pc.c_dlightSurfaces++;
			}
		}
	}
	else
	{
		for (i = 0, mdvSurface = model->surfaces; i < model->numSurfaces; i++, mdvSurface++)
		{
			shader = GetMDVSurfaceShader(ent, mdvSurface);

			// skip all surfaces that don't matter for lighting only pass
			if (shader->isSky || (!shader->interactLight && shader->noShadows))
			{
				continue;
			}

			// we will add shadows even if the main object isn't visible in the view

			// don't add third_person objects if not viewing through a portal
			if (!personalModel)
			{
				R_AddLightInteraction(light, (surfaceType_t *)mdvSurface, shader, cubeSideBits, iaType);
				tr.pc.c_dlightSurfaces++;
			}
		}
	}
}
Exemple #16
0
/*
* GClip_AreaEdicts
* fills in a table of edict ids with edicts that have bounding boxes
* that intersect the given area.  It is possible for a non-axial bmodel
* to be returned that doesn't actually intersect the area on an exact
* test.
* returns the number of pointers filled in
* ??? does this always return the world?
*/
static int GClip_AreaEdicts( vec3_t mins, vec3_t maxs, int *list, int maxcount, int areatype, int timeDelta )
{
	link_t *l, *start;
	c4clipedict_t *clipEnt;
	int stackdepth = 0, count = 0;
	areanode_t *localstack[AREA_NODES], *node = sv_areanodes;

	while( 1 )
	{
		// touch linked edicts
		if( areatype == AREA_SOLID )
			start = &node->solid_edicts;
		else
			start = &node->trigger_edicts;

		for( l = start->next; l != start; l = l->next )
		{
			clipEnt = GClip_GetClipEdictForDeltaTime( l->entNum, timeDelta );

			if( clipEnt->r.solid == SOLID_NOT )
				continue; // deactivated

			if( !BoundsIntersect( clipEnt->r.absmin, clipEnt->r.absmax, mins, maxs ) )
				continue; // not touching

			if( count == maxcount )
			{
				G_Printf( "G_AreaEdicts: MAXCOUNT\n" );
				return count;
			}
			list[count++] = l->entNum;
		}

		if( node->axis == -1 )
			goto checkstack; // terminal node

		// recurse down both sides
		if( maxs[node->axis] > node->dist )
		{
			if( mins[node->axis] < node->dist )
			{
				localstack[stackdepth++] = node->children[0];
				node = node->children[1];
				continue;
			}
			node = node->children[0];
			continue;
		}
		if( mins[node->axis] < node->dist )
		{
			node = node->children[1];
			continue;
		}

checkstack:
		if( !stackdepth )
			return count;
		node = localstack[--stackdepth];
	}

	return count;
}
Exemple #17
0
/*
* R_TraceLine
*/
static msurface_t *R_TransformedTraceLine( rtrace_t *tr, const vec3_t start, const vec3_t end,
										   entity_t *test, int surfumask ) {
	model_t *model;

	r_traceframecount++;    // for multi-check avoidance

	// fill in a default trace
	memset( tr, 0, sizeof( *tr ) );

	trace_surface = NULL;
	trace_umask = surfumask;
	trace_fraction = 1;
	VectorCopy( end, trace_impact );
	memset( &trace_plane, 0, sizeof( trace_plane ) );

	ClearBounds( trace_absmins, trace_absmaxs );
	AddPointToBounds( start, trace_absmins, trace_absmaxs );
	AddPointToBounds( end, trace_absmins, trace_absmaxs );

	model = test->model;
	if( model ) {
		if( model->type == mod_brush ) {
			mbrushmodel_t *bmodel = ( mbrushmodel_t * )model->extradata;
			vec3_t temp, start_l, end_l;
			mat3_t axis;
			bool rotated = !Matrix3_Compare( test->axis, axis_identity );

			// transform
			VectorSubtract( start, test->origin, start_l );
			VectorSubtract( end, test->origin, end_l );
			if( rotated ) {
				VectorCopy( start_l, temp );
				Matrix3_TransformVector( test->axis, temp, start_l );
				VectorCopy( end_l, temp );
				Matrix3_TransformVector( test->axis, temp, end_l );
			}

			VectorCopy( start_l, trace_start );
			VectorCopy( end_l, trace_end );

			// world uses a recursive approach using BSP tree, submodels
			// just walk the list of surfaces linearly
			if( test->model == rsh.worldModel ) {
				R_RecursiveHullCheck( bmodel->nodes, start_l, end_l );
			} else if( BoundsIntersect( model->mins, model->maxs, trace_absmins, trace_absmaxs ) ) {
				R_TraceAgainstBmodel( bmodel );
			}

			// transform back
			if( rotated && trace_fraction != 1 ) {
				Matrix3_Transpose( test->axis, axis );
				VectorCopy( tr->plane.normal, temp );
				Matrix3_TransformVector( axis, temp, trace_plane.normal );
			}
		}
	}

	// calculate the impact plane, if any
	if( trace_fraction < 1 && trace_surface != NULL ) {
		VectorNormalize( trace_plane.normal );
		trace_plane.dist = DotProduct( trace_plane.normal, trace_impact );
		CategorizePlane( &trace_plane );

		tr->shader = trace_surface->shader;
		tr->plane = trace_plane;
		tr->surfFlags = trace_surface->flags;
		tr->ent = R_ENT2NUM( test );
	}

	tr->fraction = trace_fraction;
	VectorCopy( trace_impact, tr->endpos );

	return trace_surface;
}
Exemple #18
0
/////////////////////////////////////
// Name:	LightGetAllNearest
// Purpose:	add lights that are near
//			given world AABB to given list
// Output:	lights added to given list
// Return:	none
/////////////////////////////////////
void LightGetAllNearest(const Vec3D & mins, const Vec3D &maxs, hLIGHT *pLights)
{
	//the point is at the center of both mins/maxs
	Vec3D pt((mins+maxs)*0.5f);

	//clear out given list first...
	memset(pLights, 0, sizeof(hLIGHT)*MAXLIGHT);

	//don't bother doing anything for no lights
	if(!TESTFLAGS(g_FLAGS, GFX_LIGHTENABLE))
		return;

	Vec3D v;

	if(g_lights && g_lightInds && g_numLight > 0)
	{
		u32 i, ind;
		for(i = 0; i < g_numAvail; i++)
		{
			ind = g_lightInds[i];

			if(g_lights[ind]->lDat.Type == GFXLIGHT_POINT || g_lights[ind]->lDat.Type == GFXLIGHT_SPOT)
			{
				v = pt - g_lights[ind]->lDat.Position;

				g_lights[ind]->dist = Vec3DDot(&v, &v);

				//make sure it is in range
				/*if(g_lights[ind]->dist <= g_lights[ind]->lDat.Range*g_lights[ind]->lDat.Range)
				{
				}*/
			}
			else //we prioritize directional lights, so they are always added
			{
				g_lights[ind]->dist = -((f32)i);
			}
		}

		//sort
		qsort(g_lightInds, g_numAvail, sizeof(u32), _LightCompare);

		//get the first 3 or less lights
		f32 r;

		ind = 0;

		Vec3D lMin, lMax;

		u32 max = MAXLIGHT < g_numAvail ? MAXLIGHT : g_numAvail;
		for(i = 0; i < max; i++)
		{
			lMin.x = g_lights[g_lightInds[i]]->lDat.Position.x - g_lights[g_lightInds[i]]->lDat.Range;
			lMin.y = g_lights[g_lightInds[i]]->lDat.Position.y - g_lights[g_lightInds[i]]->lDat.Range;
			lMin.z = g_lights[g_lightInds[i]]->lDat.Position.z - g_lights[g_lightInds[i]]->lDat.Range;

			lMax.x = g_lights[g_lightInds[i]]->lDat.Position.x + g_lights[g_lightInds[i]]->lDat.Range;
			lMax.y = g_lights[g_lightInds[i]]->lDat.Position.y + g_lights[g_lightInds[i]]->lDat.Range;
			lMax.z = g_lights[g_lightInds[i]]->lDat.Position.z + g_lights[g_lightInds[i]]->lDat.Range;

			//r = g_lights[g_lightInds[i]]->lDat.Range; r *= r;
			//if(g_lights[g_lightInds[i]]->dist <= r)
			if(g_lights[g_lightInds[i]]->lDat.Type == GFXLIGHT_DIRECTIONAL
				|| BoundsIntersect(mins, maxs, lMin, lMax))
			{ pLights[ind] = g_lights[g_lightInds[i]]; ind++; }
		}
	}
}