예제 #1
0
void CE_CBeam::RelinkBeam( void )
{
	// FIXME: Why doesn't this just define the absbox too?
	// It seems that we don't need to recompute the absbox
	// in CBaseEntity::SetObjectCollisionBox, in fact the absbox
	// computed there seems way too big
	Vector startPos = GetAbsStartPos(), endPos = GetAbsEndPos();

	Vector vecAbsExtra1, vecAbsExtra2;
	bool bUseExtraPoints = false;

	// UNDONE: Should we do this to make the boxes smaller?
	//SetAbsOrigin( startPos );

	Vector vecBeamMin, vecBeamMax;
	VectorMin( startPos, endPos, vecBeamMin );
	VectorMax( startPos, endPos, vecBeamMax );

	if ( bUseExtraPoints )
	{
		VectorMin( vecBeamMin, vecAbsExtra1, vecBeamMin );
		VectorMin( vecBeamMin, vecAbsExtra2, vecBeamMin );
		VectorMax( vecBeamMax, vecAbsExtra1, vecBeamMax );
		VectorMax( vecBeamMax, vecAbsExtra2, vecBeamMax );
	}

	SetCollisionBounds( vecBeamMin - GetAbsOrigin(), vecBeamMax - GetAbsOrigin() );
}
예제 #2
0
void CDispInfo::GetIntersectingSurfaces( GetIntersectingSurfaces_Struct *pStruct )
{
    if ( !m_Verts.Count() || !m_nIndices )
        return;

    // Walk through all of our triangles and add them one by one.
    unsigned short *pEnd = m_Indices.Base() + m_nIndices;
    SurfInfo *pOut = &pStruct->m_pInfos[ pStruct->m_nSetInfos ];
    for ( unsigned short *pTri = m_Indices.Base(); pTri < pEnd; pTri += 3 )
    {
        // Is the list going to overflow?
        if ( pStruct->m_nSetInfos >= pStruct->m_nMaxInfos )
            return;

        Vector const &a = m_Verts[pTri[0]].m_vPos;
        Vector const &b = m_Verts[pTri[1]].m_vPos;
        Vector const &c = m_Verts[pTri[2]].m_vPos;

        // Get the boundaries.
        Vector vMin;
        VectorMin( a, b, vMin );
        VectorMin( c, vMin, vMin );

        Vector vMax;
        VectorMax( a, b, vMax );
        VectorMax( c, vMax, vMax );

        // See if it touches the sphere.
        int iDim;
        for ( iDim=0; iDim < 3; iDim++ )
        {
            if ( ((*pStruct->m_pCenter)[iDim]+pStruct->m_Radius) < vMin[iDim] ||
                    ((*pStruct->m_pCenter)[iDim]-pStruct->m_Radius) > vMax[iDim] )
            {
                break;
            }
        }

        if ( iDim == 3 )
        {
            // Couldn't reject the sphere in the loop above, so add this surface.
            pOut->m_nVerts = 3;
            pOut->m_Verts[0] = a;
            pOut->m_Verts[1] = b;
            pOut->m_Verts[2] = c;
            pOut->m_Plane.m_Normal = ( c - a ).Cross( b - a );
            VectorNormalize( pOut->m_Plane.m_Normal );
            pOut->m_Plane.m_Dist = pOut->m_Plane.m_Normal.Dot( a );

            ++pStruct->m_nSetInfos;
            ++pOut;
        }
    }
}
예제 #3
0
//-----------------------------------------------------------------------------
// Compute position	+ bounding box
//-----------------------------------------------------------------------------
void CSpriteTrail::UpdateBoundingBox( void )
{
	Vector vecRenderOrigin = GetRenderOrigin();
	m_vecRenderMins = vecRenderOrigin;
	m_vecRenderMaxs = vecRenderOrigin;

	float flMaxWidth = m_flStartWidth;
	if (( m_flEndWidth >= 0.0f ) && ( m_flEndWidth > m_flStartWidth ))
	{
		flMaxWidth = m_flEndWidth;
	}

	Vector mins, maxs;
	for ( int i = 0; i < m_nStepCount; ++i )
	{
		TrailPoint_t *pPoint = GetTrailPoint(i);

		float flActualWidth = (flMaxWidth + pPoint->m_flWidthVariance) * 0.5f;
		Vector size( flActualWidth, flActualWidth, flActualWidth );
		VectorSubtract( pPoint->m_vecScreenPos, size, mins );
		VectorAdd( pPoint->m_vecScreenPos, size, maxs );
		
		VectorMin( m_vecRenderMins, mins, m_vecRenderMins ); 
		VectorMax( m_vecRenderMaxs, maxs, m_vecRenderMaxs ); 
	}
	
	m_vecRenderMins -= vecRenderOrigin; 
	m_vecRenderMaxs -= vecRenderOrigin;
}
예제 #4
0
void SetupDispBoxes( const CCoreDispInfo *pListBase, int listSize, CUtlVector<CDispBox> &out )
{
	out.SetSize( listSize );
	for ( int i=0; i < listSize; i++ )
	{
		const CCoreDispInfo *pDisp = &pListBase[i];

		// Calculate the bbox for this displacement.
		Vector vMin(  1e24,  1e24,  1e24 );
		Vector vMax( -1e24, -1e24, -1e24 );

		for ( int iVert=0; iVert < 4; iVert++ )
		{
			const Vector &vTest = pDisp->GetSurface()->GetPoint( iVert );
			VectorMin( vTest, vMin, vMin );
			VectorMax( vTest, vMax, vMax );
		}		

		// Puff the box out a little.
		static float flPuff = 0.1f;
		vMin -= Vector( flPuff, flPuff, flPuff );
		vMax += Vector( flPuff, flPuff, flPuff );

		out[i].m_Min = vMin;
		out[i].m_Max = vMax;
	}
}
예제 #5
0
//-----------------------------------------------------------------------------
// Computes the surrounding collision bounds from the current sequence box
//-----------------------------------------------------------------------------
void CCollisionProperty::ComputeRotationExpandedSequenceBounds( Vector *pVecWorldMins, Vector *pVecWorldMaxs )
{
	CBaseAnimating *pAnim = GetOuter()->GetBaseAnimating();
	if ( !pAnim )
	{
		ComputeOBBBounds( pVecWorldMins, pVecWorldMaxs );
		return;
	}

	Vector mins, maxs;
	pAnim->ExtractBbox( pAnim->GetSequence(), mins, maxs );

	float flRadius = MAX( MAX( FloatMakePositive( mins.x ), FloatMakePositive( maxs.x ) ),
					      MAX( FloatMakePositive( mins.y ), FloatMakePositive( maxs.y ) ) );
	mins.x = mins.y = -flRadius;
	maxs.x = maxs.y = flRadius;

	// Add bloat to account for gesture sequences
	Vector vecBloat( 6, 6, 0 );
	mins -= vecBloat;
	maxs += vecBloat;

	// NOTE: This is necessary because the server doesn't know how to blend
	// animations together. Therefore, we have to just pick a box that can
	// surround all of our potential sequences. This should be something we
	// should be able to compute @ tool time instead, however.
	VectorMin( mins, m_vecSurroundingMins, mins );
	VectorMax( maxs, m_vecSurroundingMaxs, maxs );

	VectorAdd( mins, GetCollisionOrigin(), *pVecWorldMins );
	VectorAdd( maxs, GetCollisionOrigin(), *pVecWorldMaxs );
}
예제 #6
0
void CRopeKeyframe::UpdateBBox( bool bForceRelink )
{
	Vector v1, v2;
	Vector vMin, vMax;
	if ( GetEndPointPos( 0, v1 ) )
	{
		if ( GetEndPointPos( 1, v2 ) )
		{
			VectorMin( v1, v2, vMin );
			VectorMax( v1, v2, vMax );

			// Set our bounds to enclose both endpoints and relink.
			vMin -= GetAbsOrigin();
			vMax -= GetAbsOrigin();
		}
		else
		{
			vMin = vMax = v1 - GetAbsOrigin();
		}
	}
	else
	{
		vMin = vMax = Vector( 0, 0, 0 );
	}

	if ( WorldAlignMins() != vMin || WorldAlignMaxs() != vMax )
	{
		UTIL_SetSize( this, vMin, vMax );
	}
}
void C_BaseAnimatingOverlay::GetRenderBounds( Vector& theMins, Vector& theMaxs )
{
	BaseClass::GetRenderBounds( theMins, theMaxs );

	if ( !IsRagdoll() )
	{
		CStudioHdr *pStudioHdr = GetModelPtr();
		if ( !pStudioHdr || !pStudioHdr->SequencesAvailable() )
			return;

		int nSequences = pStudioHdr->GetNumSeq();

		int i;
		for (i = 0; i < m_AnimOverlay.Count(); i++)
		{
			if (m_AnimOverlay[i].m_flWeight > 0.0)
			{
				if ( m_AnimOverlay[i].m_nSequence >= nSequences )
				{
					continue;
				}

				mstudioseqdesc_t &seqdesc = pStudioHdr->pSeqdesc( m_AnimOverlay[i].m_nSequence );
				VectorMin( seqdesc.bbmin, theMins, theMins );
				VectorMax( seqdesc.bbmax, theMaxs, theMaxs );
			}
		}
	}
}
예제 #8
0
void CBeam::RelinkBeam( void )
{
	// FIXME: Why doesn't this just define the absbox too?
	// It seems that we don't need to recompute the absbox
	// in CBaseEntity::SetObjectCollisionBox, in fact the absbox
	// computed there seems way too big
	Vector startPos = GetAbsStartPos(), endPos = GetAbsEndPos();

	Vector vecAbsExtra1, vecAbsExtra2;
	bool bUseExtraPoints = false;

#ifdef PORTAL
	CBaseEntity *pStartEntity = GetStartEntityPtr();
	
	CTraceFilterSkipClassname traceFilter( pStartEntity, "prop_energy_ball", COLLISION_GROUP_NONE );
	
	ITraceFilter *pEntityBeamTraceFilter = NULL;
	if ( pStartEntity )
		pEntityBeamTraceFilter = pStartEntity->GetBeamTraceFilter();

	CTraceFilterChain traceFilterChain( &traceFilter, pEntityBeamTraceFilter );

	bUseExtraPoints = UTIL_Portal_Trace_Beam( this, startPos, endPos, vecAbsExtra1, vecAbsExtra2, &traceFilterChain );
#endif

	// UNDONE: Should we do this to make the boxes smaller?
	//SetAbsOrigin( startPos );

	Vector vecBeamMin, vecBeamMax;
	VectorMin( startPos, endPos, vecBeamMin );
	VectorMax( startPos, endPos, vecBeamMax );

	if ( bUseExtraPoints )
	{
		VectorMin( vecBeamMin, vecAbsExtra1, vecBeamMin );
		VectorMin( vecBeamMin, vecAbsExtra2, vecBeamMin );
		VectorMax( vecBeamMax, vecAbsExtra1, vecBeamMax );
		VectorMax( vecBeamMax, vecAbsExtra2, vecBeamMax );
	}

	SetCollisionBounds( vecBeamMin - GetAbsOrigin(), vecBeamMax - GetAbsOrigin() );
}
예제 #9
0
//-----------------------------------------------------------------------------
// Purpose: Performs the actual partial rebuilds of the mesh, merging multiple
//			updates in one.
//-----------------------------------------------------------------------------
void CRecastMgr::UpdateRebuildPartial()
{
	if( !m_pendingPartialMeshUpdates.Count() )
		return;

	PartialMeshUpdate_t &curUpdate = m_pendingPartialMeshUpdates.Head();

	bool bDidMerge;
	int nTests = 0, nMerges = 0;
	do {
		bDidMerge = false;
		for( int i = m_pendingPartialMeshUpdates.Count() - 1; i >= 1; i-- )
		{
			if( IsBoxIntersectingBox( curUpdate.vMins, curUpdate.vMaxs,
				m_pendingPartialMeshUpdates[i].vMins, m_pendingPartialMeshUpdates[i].vMaxs ) )
			{
				curUpdate.vMins = VectorMin( curUpdate.vMins, m_pendingPartialMeshUpdates[i].vMins );
				curUpdate.vMaxs = VectorMax( curUpdate.vMaxs, m_pendingPartialMeshUpdates[i].vMaxs );
				m_pendingPartialMeshUpdates.Remove( i );
				bDidMerge = true;
				nMerges++;
			}
		}
		nTests++;
	} while( bDidMerge && nTests < 100 );

	if( recast_build_partial_debug.GetBool() && nMerges > 0 )
	{
		DevMsg( "CRecastMgr::UpdateRebuildPartial: Merged multiple updates (%d) into one\n", nMerges+1 );
	}

	// Load map mesh
	if( !LoadMapMesh( recast_build_partial_debug.GetBool(), true, curUpdate.vMins, curUpdate.vMaxs ) )
	{
		Warning( "CRecastMgr::UpdateRebuildPartial: failed to load map data!\n" );
		return;
	}

	// Perform the update
	CUtlVector<CRecastMesh *> meshesToBuild;
	for ( int i = m_Meshes.First(); i != m_Meshes.InvalidIndex(); i = m_Meshes.Next(i ) )
	{
		if( IsMeshBuildDisabled( m_Meshes[i]->GetName() ) )
			continue;
		meshesToBuild.AddToTail( m_Meshes[i] );
	}

	CParallelProcessor<CRecastMesh *, CFuncJobItemProcessor<CRecastMesh *>, 2 > processor;
	processor.m_ItemProcessor.Init( &ThreadedRebuildPartialMesh, &PreThreadedBuildMesh, &PostThreadedBuildMesh );
	processor.Run( meshesToBuild.Base(), meshesToBuild.Count(), 1, recast_build_numthreads.GetInt(), g_pThreadPool );

	m_pendingPartialMeshUpdates.Remove( 0 );
}
예제 #10
0
void CModelInfo::GetModelRenderBounds( const model_t *model, int sequence, Vector& mins, Vector& maxs ) const
{
	if (!model)
	{
		mins.Init(0,0,0);
		maxs.Init(0,0,0);
		return;
	}

	switch( model->type )
	{
	case mod_studio:
		{
			studiohdr_t *pStudioHdr = ( studiohdr_t * )modelloader->GetExtraData( (model_t*)model );
			Assert( pStudioHdr );

			// NOTE: We're not looking at the sequence box here, although we could
			if (!VectorCompare( vec3_origin, pStudioHdr->view_bbmin ))
			{
				// clipping bounding box
				VectorCopy ( pStudioHdr->view_bbmin, mins);
				VectorCopy ( pStudioHdr->view_bbmin, maxs);
			}
			else
			{
				// movement bounding box
				VectorCopy ( pStudioHdr->hull_min, mins);
				VectorCopy ( pStudioHdr->hull_max, maxs);
			}

			// construct the base bounding box for this frame
			if ( sequence >= pStudioHdr->numseq) 
			{
				sequence = 0;
			}

			mstudioseqdesc_t *pseqdesc = pStudioHdr->pSeqdesc( sequence );
			VectorMin( pseqdesc->bbmin, mins, mins );
			VectorMax( pseqdesc->bbmax, maxs, maxs );
		}
		break;

	case mod_brush:
		VectorCopy( model->mins, mins );
		VectorCopy( model->maxs, maxs );
		break;

	default:
		mins.Init( 0, 0, 0 );
		maxs.Init( 0, 0, 0 );
		break;
	}
}
예제 #11
0
파일: TestDSP.cpp 프로젝트: eriser/FxDSP
TEST(DSPSingle, TestVectorMin)
{
    float signal[10] = {0.0, -1.0, -0.5, -0.3, 0.0, 1.0, 0.5, 0.3, 0.2, 0.1};
    float min = VectorMin(signal, 10);
    ASSERT_FLOAT_EQ(-1.0, min);
    
    min = 0.0;
    unsigned index = 0;
    VectorMinVI(&min, &index, signal, 10);
    ASSERT_FLOAT_EQ(-1.0, min);
    ASSERT_EQ(1, index);
}
예제 #12
0
void CSheetSimulator::ComputeBounds( Vector& mins, Vector& maxs )
{
	VectorCopy( m_Particle[0].m_Position, mins );
	VectorCopy( m_Particle[0].m_Position, maxs );

	for (int i = 1; i < NumParticles(); ++i)
	{
		VectorMin( mins, m_Particle[i].m_Position, mins );
		VectorMax( maxs, m_Particle[i].m_Position, maxs );
	}
	mins -= m_Origin;
	maxs -= m_Origin;
}
예제 #13
0
void CMapzoneEdit::Build(Vector *aimpos, int type, int forcestage)
{
    if (mom_zone_grid.GetInt() > 0)
        VectorSnapToGrid(aimpos, (float) mom_zone_grid.GetInt());


    switch ((forcestage != BUILDSTAGE_NONE) ? forcestage : ++m_nBuildStage)
    {
    case BUILDSTAGE_START:
        m_vecBuildStart = *aimpos;
        break;

    case BUILDSTAGE_END:
        m_vecBuildEnd = *aimpos;
        break;

    case BUILDSTAGE_HEIGHT:
    {
        char szClass[64];
        if (ZoneTypeToClass(type, szClass))
        {
            CBaseEntity *pEnt = CreateEntityByName(szClass);
            Vector vecOrigin, vecSize, vecMinsRel;
            int i;

            VectorMin(m_vecBuildStart, m_vecBuildEnd, vecMinsRel);
            VectorMax(m_vecBuildStart, m_vecBuildEnd, vecSize);

            for (i = 0; i < 3; i++)
                vecSize[i] = (vecSize[i] - vecMinsRel[i]) / 2.0f;

            for (i = 0; i < 3; i++)
                vecOrigin[i] = vecMinsRel[i] + vecSize[i];

            pEnt->Spawn();

            pEnt->SetAbsOrigin(vecOrigin);
            pEnt->SetSize(Vector(-vecSize.x, -vecSize.y, -vecSize.z), vecSize);
            pEnt->SetEffects(EF_NODRAW);
            pEnt->SetSolid(SOLID_BBOX);

            pEnt->Activate();

            SetZoneProps(pEnt);
        }
    }
    default:
        m_nBuildStage = BUILDSTAGE_NONE;
    }
}
예제 #14
0
//-----------------------------------------------------------------------------
// bounding box for collision
//-----------------------------------------------------------------------------
void CShieldEffect::ComputeBounds( Vector& mins, Vector& maxs )
{
	VectorCopy( m_pControlPoint[0], mins );
	VectorCopy( m_pControlPoint[0], maxs );

	for (int i = 1; i < SHIELD_NUM_CONTROL_POINTS; ++i)
	{
		VectorMin( mins, m_pControlPoint[i], mins );
		VectorMax( maxs, m_pControlPoint[i], maxs );
	}

	// Bounds are in local coords
	mins -= m_Position;
	maxs -= m_Position;
}
예제 #15
0
        inline bool IntersectWithLine( const Vector3& rayOrigin, Vector3 rayDirection, float &distanceToFrontCollisionOfCube , float &distanceToBackCollisionOfCube ) const
        {
            rayDirection.x = ( rayDirection.x == 0.f ) ? 0.0000001f : rayDirection.x;
            rayDirection.y = ( rayDirection.y == 0.f ) ? 0.0000001f : rayDirection.y;
            rayDirection.z = ( rayDirection.z == 0.f ) ? 0.0000001f : rayDirection.z;
        	Vector3 divisor = 1.f / rayDirection;
        	Vector3 oMin = (m_Min - rayOrigin) * divisor;
        	Vector3 oMax = (m_Max - rayOrigin) * divisor;
        	Vector3 bMax = VectorMax(oMax, oMin);
        	Vector3 bMin = VectorMin(oMax, oMin);
        	distanceToBackCollisionOfCube   = getMinimum(bMax.x, bMax.y, bMax.z);
        	distanceToBackCollisionOfCube   = getMinimum(bMax.x, bMax.y, bMax.z);
        	distanceToFrontCollisionOfCube = getMaximum(bMin.x, 0.0f, bMin.y, bMin.z );

        	return distanceToBackCollisionOfCube > distanceToFrontCollisionOfCube;
        }
예제 #16
0
void CBeam::RelinkBeam( void )
{
	// FIXME: Why doesn't this just define the absbox too?
	// It seems that we don't need to recompute the absbox
	// in CBaseEntity::SetObjectCollisionBox, in fact the absbox
	// computed there seems way too big
	const Vector &startPos = GetAbsStartPos(), &endPos = GetAbsEndPos();

	// UNDONE: Should we do this to make the boxes smaller?
	//SetAbsOrigin( startPos );

	Vector vecBeamMin, vecBeamMax;
	VectorMin( startPos, endPos, vecBeamMin );
	VectorMax( startPos, endPos, vecBeamMax );

	SetCollisionBounds( vecBeamMin - GetAbsOrigin(), vecBeamMax - GetAbsOrigin() );
}
예제 #17
0
void CDispInfo::ApplyTerrainMod( ITerrainMod *pMod )
{
    // New bbox.
    Vector bbMin(  1e24,  1e24,  1e24 );
    Vector bbMax( -1e24, -1e24, -1e24 );

    int nVerts, nIndices;
    CalcMaxNumVertsAndIndices( m_Power, &nVerts, &nIndices );

    // Ok, it probably touches us. Lock our buffer and change the verts.
    CMeshBuilder mb;
    mb.BeginModify( m_pMesh->m_pMesh, m_iVertOffset, nVerts );

    for( int iVert=0; iVert < nVerts; iVert++ )
    {
        if( m_AllowedVerts.Get( iVert ) )
        {
            Vector &vPos = m_Verts[iVert].m_vPos;
            Vector &vOriginalPos = m_Verts[iVert].m_vOriginalPos;

            if( pMod->ApplyMod( vPos, vOriginalPos ) )
                mb.Position3f( VectorExpand( vPos ) );

            VectorMin( vPos, bbMin, bbMin );
            VectorMax( vPos, bbMax, bbMax );
        }

        mb.AdvanceVertex();
    }

    mb.EndModify();

    // Set our new bounding box.
    m_BBoxMin = bbMin;
    m_BBoxMax = bbMax;
    UpdateCenterAndRadius();

    // Next time this displacement is seen, force it to rebuild and retesselate.
    m_bForceRebuild = true;
}
예제 #18
0
//-----------------------------------------------------------------------------
// compute rest positions of the springs
//-----------------------------------------------------------------------------
void CShieldEffect::ComputeRestPositions()
{
	int i;

	m_vecRenderMins.Init( FLT_MAX, FLT_MAX, FLT_MAX );
	m_vecRenderMaxs.Init( -FLT_MAX, -FLT_MAX, -FLT_MAX );

	// Set the initial directions and distances (in shield space)...
	for	( i = 0; i < SHIELD_NUM_VERTICAL_POINTS; ++i)
	{
		// Choose phi centered at pi/2
		float phi = (M_PI - m_ShieldPhi) * 0.5f + m_ShieldPhi * 
			(float)i / (float)(SHIELD_NUM_VERTICAL_POINTS - 1);

		for (int j = 0; j < SHIELD_NUM_HORIZONTAL_POINTS; ++j)
		{
			// Choose theta centered at pi/2 also (y, or forward axis)
			float theta = (M_PI - m_ShieldTheta) * 0.5f + m_ShieldTheta * 
				(float)j / (float)(SHIELD_NUM_HORIZONTAL_POINTS - 1);

			int idx = i * SHIELD_NUM_HORIZONTAL_POINTS + j;

			m_pFixedDirection[idx].x = cos(theta) * sin(phi);
			m_pFixedDirection[idx].y = sin(theta) * sin(phi);
			m_pFixedDirection[idx].z = cos(phi);

			m_pFixedDirection[idx] *= m_RestLength;

			VectorMin( m_vecRenderMins, m_pFixedDirection[idx], m_vecRenderMins );
			VectorMax( m_vecRenderMaxs, m_pFixedDirection[idx], m_vecRenderMaxs );
		}
	}

	// Compute box for fake volume testing
	Vector dist = m_pFixedDirection[0] - m_pFixedDirection[1];
	float l = dist.Length(); // * m_RestLength;
	SetShieldPanelSize( Vector( -l * 0.25f, -l * 0.25f, -l * 0.25f), 
		Vector( l * 0.25f, l * 0.25f, l * 0.25f) );
}
예제 #19
0
//-----------------------------------------------------------------------------
// Returns the bounding box for the model
//-----------------------------------------------------------------------------
void CDmeMDL::GetBoundingBox( Vector *pMins, Vector *pMaxs ) const
{
	if ( !g_pMaterialSystem || !g_pMDLCache || !g_pStudioRender )
	{
		pMins->Init();
		pMaxs->Init();
		return;
	}

	if ( m_MDLHandle == MDLHANDLE_INVALID )
	{
		pMins->Init();
		pMaxs->Init();
		return;
	}

	pMins->Init( FLT_MAX, FLT_MAX );
	pMaxs->Init( -FLT_MAX, -FLT_MAX );

	studiohdr_t *pStudioHdr = g_pMDLCache->GetStudioHdr( m_MDLHandle );
	if ( !VectorCompare( vec3_origin, pStudioHdr->view_bbmin ) || !VectorCompare( vec3_origin, pStudioHdr->view_bbmax ))
	{
		// look for view clip
		*pMins = pStudioHdr->view_bbmin;
		*pMaxs = pStudioHdr->view_bbmax;
	}
	else if ( !VectorCompare( vec3_origin, pStudioHdr->hull_min ) || !VectorCompare( vec3_origin, pStudioHdr->hull_max ))
	{
		// look for hull
		*pMins = pStudioHdr->hull_min;
		*pMaxs = pStudioHdr->hull_max;
	}

	// Else use the sequence box
	mstudioseqdesc_t &seqdesc = pStudioHdr->pSeqdesc( m_nSequence );
	VectorMin( seqdesc.bbmin, *pMins, *pMins );
	VectorMax( seqdesc.bbmax, *pMaxs, *pMaxs );
}
예제 #20
0
void C_NPC_Surface::GetRenderBounds( Vector& theMins, Vector& theMaxs )
{
	// BaseClass::GetRenderBounds( theMins, theMaxs );
	if(sv_surface_testshape.GetBool())
	{
		theMins.Init(-300.0f, 0.0f, 100.0f);
		theMaxs.Init(0.0f, 100.0f, 200.0f);
	}
	else
	{
		theMins = m_vecSurfacePos[0];
		theMaxs = m_vecSurfacePos[0];
		float surfaceRadius = m_flRadius * 3.0f;
		for (int i = 0; i < m_nActiveParticles; i++)
		{
			VectorMin( m_vecSurfacePos[i] - Vector( surfaceRadius, surfaceRadius, surfaceRadius ), theMins, theMins );
			VectorMax( m_vecSurfacePos[i] + Vector( surfaceRadius, surfaceRadius, surfaceRadius ), theMaxs, theMaxs );
		}
	}
	theMins -= GetRenderOrigin();
	theMaxs -= GetRenderOrigin();

	#if 0
	Vector avg = (theMins + theMaxs) * 0.5f;
	theMins = theMins - ((theMins - avg) * 0.75f);
	theMaxs = theMaxs - ((theMaxs - avg) * 0.75f);
	#endif

	#if 0
	Vector fountainOrigin(-1980, -1792, 1);
	theMins = fountainOrigin + Vector(-10, -10, -20);
	theMaxs = fountainOrigin + Vector(10, 10, 50);
	#endif

	// Msg( "origin  %.2f %.2f %.2f : mins %.2f %.2f %.2f  : maxs %.2f %.2f %.2f\n", GetRenderOrigin().x, GetRenderOrigin().y, GetRenderOrigin().z, theMins.x, theMins.y, theMins.z, theMaxs.x, theMaxs.y, theMaxs.z );

	//debugoverlay->AddBoxOverlay( GetRenderOrigin(), theMins, theMaxs, QAngle( 0, 0, 0 ), 0, 255, 0, 0, 0 );
}
예제 #21
0
//-----------------------------------------------------------------------------
// Expand trigger bounds..
//-----------------------------------------------------------------------------
void CCollisionProperty::ComputeVPhysicsSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs )
{
	bool bSetBounds = false;
	IPhysicsObject *pPhysicsObject = GetOuter()->VPhysicsGetObject();
	if ( pPhysicsObject )
	{
		if ( pPhysicsObject->GetCollide() )
		{
			physcollision->CollideGetAABB( pVecWorldMins, pVecWorldMaxs, 
				pPhysicsObject->GetCollide(), GetCollisionOrigin(), GetCollisionAngles() );
			bSetBounds = true;
		}
		else if ( pPhysicsObject->GetSphereRadius( ) )
		{
			float flRadius = pPhysicsObject->GetSphereRadius( );
			Vector vecExtents( flRadius, flRadius, flRadius );
			VectorSubtract( GetCollisionOrigin(), vecExtents, *pVecWorldMins );
			VectorAdd( GetCollisionOrigin(), vecExtents, *pVecWorldMaxs );
			bSetBounds = true;
		}
	}

	if ( !bSetBounds )
	{
		*pVecWorldMins = GetCollisionOrigin();
		*pVecWorldMaxs = *pVecWorldMins;
	}

	// Also, lets expand for the trigger bounds also
	if ( IsSolidFlagSet( FSOLID_USE_TRIGGER_BOUNDS ) )
	{
		Vector vecWorldTriggerMins, vecWorldTriggerMaxs;
		WorldSpaceTriggerBounds( &vecWorldTriggerMins, &vecWorldTriggerMaxs );
		VectorMin( vecWorldTriggerMins, *pVecWorldMins, *pVecWorldMins );
		VectorMax( vecWorldTriggerMaxs, *pVecWorldMaxs, *pVecWorldMaxs );
	}
}
예제 #22
0
bool CGutModel::LoadMesh_ASCII(void)
{
	char szBuffer[128];
	char sz_Tag[64];

	fgets(szBuffer, 128, m_pFile); // {
	fgets(szBuffer, 128, m_pFile); // meshes n
	sscanf(szBuffer, "%s %d", sz_Tag, &m_iNumMeshes);

	m_iNumFaces = 0;
	m_iNumVertices = 0;

	m_pMeshArray = new sModelMesh[m_iNumMeshes];
	if ( m_pMeshArray==NULL )
		return false;

	m_vMin.Set(FLT_MAX);
	m_vMax.Set(-FLT_MAX);

	for ( int i=0; i<m_iNumMeshes; i++ )
	{
		printf("Loading mesh %d/%d\n", i+1, m_iNumMeshes);

		m_pMeshArray[i].Load_ASCII(m_pFile);

		m_iNumFaces += m_pMeshArray[i].m_iNumFaces;
		m_iNumVertices += m_pMeshArray[i].m_iNumVertices;

		m_vMin = VectorMin(m_vMin, m_pMeshArray[i].m_vMin);
		m_vMax = VectorMax(m_vMax, m_pMeshArray[i].m_vMax);
	}

	fgets(szBuffer, 128, m_pFile); // }

	return true;
}
예제 #23
0
bool CAnimating::ComputeHitboxSurroundingBox( Vector *pVecWorldMins, Vector *pVecWorldMaxs )
{
	// Note that this currently should not be called during Relink because of IK.
	// The code below recomputes bones so as to get at the hitboxes,
	// which causes IK to trigger, which causes raycasts against the other entities to occur,
	// which is illegal to do while in the Relink phase.

	CStudioHdr *pStudioHdr = GetModelPtr();
	if (!pStudioHdr)
		return false;

	mstudiohitboxset_t *set = pStudioHdr->pHitboxSet( m_nHitboxSet );
	if ( !set || !set->numhitboxes )
		return false;

	CBoneCache *pCache = GetBoneCache();

	// Compute a box in world space that surrounds this entity
	pVecWorldMins->Init( FLT_MAX, FLT_MAX, FLT_MAX );
	pVecWorldMaxs->Init( -FLT_MAX, -FLT_MAX, -FLT_MAX );

	Vector vecBoxAbsMins, vecBoxAbsMaxs;
	for ( int i = 0; i < set->numhitboxes; i++ )
	{
		mstudiobbox_t *pbox = set->pHitbox(i);
		matrix3x4_t *pMatrix = pCache->GetCachedBone(pbox->bone);

		if ( pMatrix )
		{
			TransformAABB( *pMatrix, pbox->bbmin, pbox->bbmax, vecBoxAbsMins, vecBoxAbsMaxs );
			VectorMin( *pVecWorldMins, vecBoxAbsMins, *pVecWorldMins );
			VectorMax( *pVecWorldMaxs, vecBoxAbsMaxs, *pVecWorldMaxs );
		}
	}
	return true;
}
예제 #24
0
void C_SteamJet::Update(float fTimeDelta)
{
	if(!m_pParticleMgr)
	{
		assert(false);
		return;
	}

	if( m_bEmit )
	{
		// Add new particles.
		int nToEmit = 0;
		float tempDelta = fTimeDelta;
		while( m_ParticleSpawn.NextEvent(tempDelta) )
			++nToEmit;

		if ( nToEmit > 0 )
		{
			Vector forward, right, up;
			AngleVectors(GetAbsAngles(), &forward, &right, &up);			

			// Legacy env_steamjet entities faced left instead of forward.
			if (m_bFaceLeft)
			{
				Vector temp = forward;
				forward = -right;
				right = temp;
			}

			// EVIL: Ideally, we could tell the renderer our OBB, and let it build a big box that encloses
			// the entity with its parent so it doesn't have to setup its parent's bones here.
			Vector vEndPoint = GetAbsOrigin() + forward * m_Speed;
			Vector vMin, vMax;
			VectorMin( GetAbsOrigin(), vEndPoint, vMin );
			VectorMax( GetAbsOrigin(), vEndPoint, vMax );
			m_ParticleEffect.SetBBox( vMin, vMax );

			if ( m_ParticleEffect.WasDrawnPrevFrame() )
			{
				while ( nToEmit-- )
				{
					// Make a new particle.
					if( SteamJetParticle *pParticle = (SteamJetParticle*) m_ParticleEffect.AddParticle( sizeof(SteamJetParticle), m_MaterialHandle ) )
					{
						pParticle->m_Pos = GetAbsOrigin();
						
						pParticle->m_Velocity = 
							FRand(-m_SpreadSpeed,m_SpreadSpeed) * right +
							FRand(-m_SpreadSpeed,m_SpreadSpeed) * up +
							m_Speed * forward;
						
						pParticle->m_Lifetime	= 0;
						pParticle->m_DieTime	= m_Lifetime;

						pParticle->m_uchStartSize	= m_StartSize;
						pParticle->m_uchEndSize		= m_EndSize;

						pParticle->m_flRoll = random->RandomFloat( 0, 360 );
						pParticle->m_flRollDelta = random->RandomFloat( -m_flRollSpeed, m_flRollSpeed );
					}
				}
			}

			UpdateLightingRamp();
		}	
	}
}
예제 #25
0
//-----------------------------------------------------------------------------
// Emits occluder brushes
//-----------------------------------------------------------------------------
static void EmitOccluderBrushes()
{
	char str[64];

	g_OccluderData.RemoveAll();
	g_OccluderPolyData.RemoveAll();
	g_OccluderVertexIndices.RemoveAll();

	tree_t *pOccluderTree = ClipOccluderBrushes();
	if (!pOccluderTree)
		return;

	CUtlVector<face_t*> faceList( 1024, 1024 );
	CUtlVector<side_t*> sideList( 1024, 1024 );
	GenerateOccluderFaceList( pOccluderTree->headnode, faceList );

#ifdef _DEBUG
	int *pEmitted = (int*)stackalloc( faceList.Count() * sizeof(int) );
	memset( pEmitted, 0, faceList.Count() * sizeof(int) );
#endif

	for ( entity_num=1; entity_num < num_entities; ++entity_num )
	{
		if (!IsFuncOccluder(entity_num))
			continue;

		// Output only those parts of the occluder tree which are a part of the brush
		int nOccluder = g_OccluderData.AddToTail();
		doccluderdata_t &occluderData = g_OccluderData[ nOccluder ];
		occluderData.firstpoly = g_OccluderPolyData.Count();
		occluderData.mins.Init( FLT_MAX, FLT_MAX, FLT_MAX );
		occluderData.maxs.Init( -FLT_MAX, -FLT_MAX, -FLT_MAX );
		occluderData.flags = 0;
		occluderData.area = -1;

		// NOTE: If you change the algorithm by which occluder numbers are allocated,
		// then you must also change FixupOnlyEntsOccluderEntities() below
		sprintf (str, "%i", nOccluder);
		SetKeyValue (&entities[entity_num], "occludernumber", str);

		int nIndex = g_OccluderInfo.AddToTail();
		g_OccluderInfo[nIndex].m_nOccluderEntityIndex = entity_num;
		
		sideList.RemoveAll();
		GenerateOccluderSideList( entity_num, sideList );
		for ( int i = faceList.Count(); --i >= 0; )
		{
			// Skip nodraw surfaces, but not triggers that have been marked as nodraw
			face_t *f = faceList[i];
			if ( ( texinfo[f->texinfo].flags & SURF_NODRAW ) &&
				 (( texinfo[f->texinfo].flags & SURF_TRIGGER ) == 0 ) )
				continue;

			// Only emit faces that appear in the side list of the occluder
			for ( int j = sideList.Count(); --j >= 0; )
			{
				if ( sideList[j] != f->originalface )
					continue;

				if ( f->numpoints < 3 )
					continue;

				// not a final face
				Assert ( !f->merged && !f->split[0] && !f->split[1] );

#ifdef _DEBUG
				Assert( !pEmitted[i] );
				pEmitted[i] = entity_num;
#endif

				int k = g_OccluderPolyData.AddToTail();
				doccluderpolydata_t *pOccluderPoly = &g_OccluderPolyData[k];

				pOccluderPoly->planenum = f->planenum;
				pOccluderPoly->vertexcount = f->numpoints;
				pOccluderPoly->firstvertexindex = g_OccluderVertexIndices.Count();
				for( k = 0; k < f->numpoints; ++k )
				{
					g_OccluderVertexIndices.AddToTail( f->vertexnums[k] );

					const Vector &p = dvertexes[f->vertexnums[k]].point; 
					VectorMin( occluderData.mins, p, occluderData.mins );
					VectorMax( occluderData.maxs, p, occluderData.maxs );
				}

				break;
			}
		}

		occluderData.polycount = g_OccluderPolyData.Count() - occluderData.firstpoly;

		// Mark this brush as not having brush geometry so it won't be re-emitted with a brush model
		entities[entity_num].numbrushes = 0;
	}

	FreeTree( pOccluderTree );
}
예제 #26
0
FBox FBox::TransformBy(const FMatrix& M) const
{
	// if we are not valid, return another invalid box.
	if (!IsValid)
	{
		return FBox(0);
	}

	VectorRegister Vertices[8];

	VectorRegister m0 = VectorLoadAligned(M.M[0]);
	VectorRegister m1 = VectorLoadAligned(M.M[1]);
	VectorRegister m2 = VectorLoadAligned(M.M[2]);
	VectorRegister m3 = VectorLoadAligned(M.M[3]);

	Vertices[0] = VectorLoadFloat3(&Min);
	Vertices[1] = VectorSetFloat3(Min.X, Min.Y, Max.Z);
	Vertices[2] = VectorSetFloat3(Min.X, Max.Y, Min.Z);
	Vertices[3] = VectorSetFloat3(Max.X, Min.Y, Min.Z);
	Vertices[4] = VectorSetFloat3(Max.X, Max.Y, Min.Z);
	Vertices[5] = VectorSetFloat3(Max.X, Min.Y, Max.Z);
	Vertices[6] = VectorSetFloat3(Min.X, Max.Y, Max.Z);
	Vertices[7] = VectorLoadFloat3(&Max);

	VectorRegister r0 = VectorMultiply(VectorReplicate(Vertices[0],0), m0);
	VectorRegister r1 = VectorMultiply(VectorReplicate(Vertices[1],0), m0);
	VectorRegister r2 = VectorMultiply(VectorReplicate(Vertices[2],0), m0);
	VectorRegister r3 = VectorMultiply(VectorReplicate(Vertices[3],0), m0);
	VectorRegister r4 = VectorMultiply(VectorReplicate(Vertices[4],0), m0);
	VectorRegister r5 = VectorMultiply(VectorReplicate(Vertices[5],0), m0);
	VectorRegister r6 = VectorMultiply(VectorReplicate(Vertices[6],0), m0);
	VectorRegister r7 = VectorMultiply(VectorReplicate(Vertices[7],0), m0);

	r0 = VectorMultiplyAdd( VectorReplicate(Vertices[0],1), m1, r0);
	r1 = VectorMultiplyAdd( VectorReplicate(Vertices[1],1), m1, r1);
	r2 = VectorMultiplyAdd( VectorReplicate(Vertices[2],1), m1, r2);
	r3 = VectorMultiplyAdd( VectorReplicate(Vertices[3],1), m1, r3);
	r4 = VectorMultiplyAdd( VectorReplicate(Vertices[4],1), m1, r4);
	r5 = VectorMultiplyAdd( VectorReplicate(Vertices[5],1), m1, r5);
	r6 = VectorMultiplyAdd( VectorReplicate(Vertices[6],1), m1, r6);
	r7 = VectorMultiplyAdd( VectorReplicate(Vertices[7],1), m1, r7);

	r0 = VectorMultiplyAdd( VectorReplicate(Vertices[0],2), m2, r0);
	r1 = VectorMultiplyAdd( VectorReplicate(Vertices[1],2), m2, r1);
	r2 = VectorMultiplyAdd( VectorReplicate(Vertices[2],2), m2, r2);
	r3 = VectorMultiplyAdd( VectorReplicate(Vertices[3],2), m2, r3);
	r4 = VectorMultiplyAdd( VectorReplicate(Vertices[4],2), m2, r4);
	r5 = VectorMultiplyAdd( VectorReplicate(Vertices[5],2), m2, r5);
	r6 = VectorMultiplyAdd( VectorReplicate(Vertices[6],2), m2, r6);
	r7 = VectorMultiplyAdd( VectorReplicate(Vertices[7],2), m2, r7);

	r0 = VectorAdd(r0, m3);
	r1 = VectorAdd(r1, m3);
	r2 = VectorAdd(r2, m3);
	r3 = VectorAdd(r3, m3);
	r4 = VectorAdd(r4, m3);
	r5 = VectorAdd(r5, m3);
	r6 = VectorAdd(r6, m3);
	r7 = VectorAdd(r7, m3);

	FBox NewBox;
	
	VectorRegister min0 = VectorMin(r0, r1);
	VectorRegister min1 = VectorMin(r2, r3);
	VectorRegister min2 = VectorMin(r4, r5);
	VectorRegister min3 = VectorMin(r6, r7);
	VectorRegister max0 = VectorMax(r0, r1);
	VectorRegister max1 = VectorMax(r2, r3);
	VectorRegister max2 = VectorMax(r4, r5);
	VectorRegister max3 = VectorMax(r6, r7);
	
	min0 = VectorMin(min0, min1);
	min1 = VectorMin(min2, min3);
	max0 = VectorMax(max0, max1);
	max1 = VectorMax(max2, max3);
	min0 = VectorMin(min0, min1);
	max0 = VectorMax(max0, max1);

	VectorStoreFloat3(min0, &NewBox.Min);
	VectorStoreFloat3(max0, &NewBox.Max);

	NewBox.IsValid = 1;

	return NewBox;
}
예제 #27
0
void C_EnvProjectedTexture::UpdateLight( void )
{
	VPROF("C_EnvProjectedTexture::UpdateLight");
	bool bVisible = true;

	Vector vLinearFloatLightColor( m_LightColor.r, m_LightColor.g, m_LightColor.b );
	float flLinearFloatLightAlpha = m_LightColor.a;

	if ( m_bAlwaysUpdate )
	{
		m_bForceUpdate = true;
	}

	if ( m_CurrentLinearFloatLightColor != vLinearFloatLightColor || m_flCurrentLinearFloatLightAlpha != flLinearFloatLightAlpha )
	{
		float flColorTransitionSpeed = gpGlobals->frametime * m_flColorTransitionTime * 255.0f;

		m_CurrentLinearFloatLightColor.x = Approach( vLinearFloatLightColor.x, m_CurrentLinearFloatLightColor.x, flColorTransitionSpeed );
		m_CurrentLinearFloatLightColor.y = Approach( vLinearFloatLightColor.y, m_CurrentLinearFloatLightColor.y, flColorTransitionSpeed );
		m_CurrentLinearFloatLightColor.z = Approach( vLinearFloatLightColor.z, m_CurrentLinearFloatLightColor.z, flColorTransitionSpeed );
		m_flCurrentLinearFloatLightAlpha = Approach( flLinearFloatLightAlpha, m_flCurrentLinearFloatLightAlpha, flColorTransitionSpeed );

		m_bForceUpdate = true;
	}
	
	if ( !m_bForceUpdate )
	{
		bVisible = IsBBoxVisible();		
	}

	if ( m_bState == false || !bVisible )
	{
		// Spotlight's extents aren't in view
		ShutDownLightHandle();

		return;
	}

	if ( m_LightHandle == CLIENTSHADOW_INVALID_HANDLE || m_hTargetEntity != NULL || m_bForceUpdate )
	{
		Vector vForward, vRight, vUp, vPos = GetAbsOrigin();
		FlashlightState_t state;

		if ( m_hTargetEntity != NULL )
		{
			if ( m_bCameraSpace )
			{
				const QAngle &angles = GetLocalAngles();

				C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
				if( pPlayer )
				{
					const QAngle playerAngles = pPlayer->GetAbsAngles();

					Vector vPlayerForward, vPlayerRight, vPlayerUp;
					AngleVectors( playerAngles, &vPlayerForward, &vPlayerRight, &vPlayerUp );

					matrix3x4_t	mRotMatrix;
					AngleMatrix( angles, mRotMatrix );

					VectorITransform( vPlayerForward, mRotMatrix, vForward );
					VectorITransform( vPlayerRight, mRotMatrix, vRight );
					VectorITransform( vPlayerUp, mRotMatrix, vUp );

					float dist = (m_hTargetEntity->GetAbsOrigin() - GetAbsOrigin()).Length();
					vPos = m_hTargetEntity->GetAbsOrigin() - vForward*dist;

					VectorNormalize( vForward );
					VectorNormalize( vRight );
					VectorNormalize( vUp );
				}
			}
			else
			{
				vForward = m_hTargetEntity->GetAbsOrigin() - GetAbsOrigin();
				VectorNormalize( vForward );

				// JasonM - unimplemented
				Assert (0);

				//Quaternion q = DirectionToOrientation( dir );


				//
				// JasonM - set up vRight, vUp
				//

				//			VectorNormalize( vRight );
				//			VectorNormalize( vUp );
			}
		}
		else
		{
			AngleVectors( GetAbsAngles(), &vForward, &vRight, &vUp );
		}

		state.m_fHorizontalFOVDegrees = m_flLightFOV;
		state.m_fVerticalFOVDegrees = m_flLightFOV;

		state.m_vecLightOrigin = vPos;
		BasisToQuaternion( vForward, vRight, vUp, state.m_quatOrientation );
		state.m_NearZ = m_flNearZ;
		state.m_FarZ = m_flFarZ;

		// quickly check the proposed light's bbox against the view frustum to determine whether we
		// should bother to create it, if it doesn't exist, or cull it, if it does.
		if ( m_bSimpleProjection == false )
		{
#pragma message("OPTIMIZATION: this should be made SIMD")
			// get the half-widths of the near and far planes, 
			// based on the FOV which is in degrees. Remember that
			// on planet Valve, x is forward, y left, and z up. 
			const float tanHalfAngle = tan( m_flLightFOV * ( M_PI/180.0f ) * 0.5f );
			const float halfWidthNear = tanHalfAngle * m_flNearZ;
			const float halfWidthFar = tanHalfAngle * m_flFarZ;
			// now we can build coordinates in local space: the near rectangle is eg 
			// (0, -halfWidthNear, -halfWidthNear), (0,  halfWidthNear, -halfWidthNear), 
			// (0,  halfWidthNear,  halfWidthNear), (0, -halfWidthNear,  halfWidthNear)

			VectorAligned vNearRect[4] = { 
				VectorAligned( m_flNearZ, -halfWidthNear, -halfWidthNear), VectorAligned( m_flNearZ,  halfWidthNear, -halfWidthNear),
				VectorAligned( m_flNearZ,  halfWidthNear,  halfWidthNear), VectorAligned( m_flNearZ, -halfWidthNear,  halfWidthNear) 
			};

			VectorAligned vFarRect[4] = { 
				VectorAligned( m_flFarZ, -halfWidthFar, -halfWidthFar), VectorAligned( m_flFarZ,  halfWidthFar, -halfWidthFar),
				VectorAligned( m_flFarZ,  halfWidthFar,  halfWidthFar), VectorAligned( m_flFarZ, -halfWidthFar,  halfWidthFar) 
			};

			matrix3x4_t matOrientation( vForward, -vRight, vUp, vPos );

			enum
			{
				kNEAR = 0,
				kFAR = 1,
			};
			VectorAligned vOutRects[2][4];

			for ( int i = 0 ; i < 4 ; ++i )
			{
				VectorTransform( vNearRect[i].Base(), matOrientation, vOutRects[0][i].Base() );
			}
			for ( int i = 0 ; i < 4 ; ++i )
			{
				VectorTransform( vFarRect[i].Base(), matOrientation, vOutRects[1][i].Base() );
			}

			// now take the MIN and MAX extents for the bbox, and see if it is visible.
			Vector mins = **vOutRects; 
			Vector maxs = **vOutRects; 
			for ( int i = 1; i < 8 ; ++i )
			{
				VectorMin( mins, *(*vOutRects+i), mins );
				VectorMax( maxs, *(*vOutRects+i), maxs );
			}

#if 0 //for debugging the visibility frustum we just calculated
			NDebugOverlay::Triangle( vOutRects[0][0], vOutRects[0][1], vOutRects[0][2], 255, 0, 0, 100, true, 0.0f ); //first tri
			NDebugOverlay::Triangle( vOutRects[0][2], vOutRects[0][1], vOutRects[0][0], 255, 0, 0, 100, true, 0.0f ); //make it double sided
			NDebugOverlay::Triangle( vOutRects[0][2], vOutRects[0][3], vOutRects[0][0], 255, 0, 0, 100, true, 0.0f ); //second tri
			NDebugOverlay::Triangle( vOutRects[0][0], vOutRects[0][3], vOutRects[0][2], 255, 0, 0, 100, true, 0.0f ); //make it double sided

			NDebugOverlay::Triangle( vOutRects[1][0], vOutRects[1][1], vOutRects[1][2], 0, 0, 255, 100, true, 0.0f ); //first tri
			NDebugOverlay::Triangle( vOutRects[1][2], vOutRects[1][1], vOutRects[1][0], 0, 0, 255, 100, true, 0.0f ); //make it double sided
			NDebugOverlay::Triangle( vOutRects[1][2], vOutRects[1][3], vOutRects[1][0], 0, 0, 255, 100, true, 0.0f ); //second tri
			NDebugOverlay::Triangle( vOutRects[1][0], vOutRects[1][3], vOutRects[1][2], 0, 0, 255, 100, true, 0.0f ); //make it double sided

			NDebugOverlay::Box( vec3_origin, mins, maxs, 0, 255, 0, 100, 0.0f );
#endif
			
			bool bVisible = IsBBoxVisible( mins, maxs );
			if (!bVisible)
			{
				// Spotlight's extents aren't in view
				if ( m_LightHandle != CLIENTSHADOW_INVALID_HANDLE )
				{
					ShutDownLightHandle();
				}

				return;
			}
		}

		float flAlpha = m_flCurrentLinearFloatLightAlpha * ( 1.0f / 255.0f );

		state.m_fQuadraticAtten = 0.0;
		state.m_fLinearAtten = 100;
		state.m_fConstantAtten = 0.0f;
		state.m_FarZAtten = m_flFarZ;
		state.m_fBrightnessScale = m_flBrightnessScale;
		state.m_Color[0] = m_CurrentLinearFloatLightColor.x * ( 1.0f / 255.0f ) * flAlpha;
		state.m_Color[1] = m_CurrentLinearFloatLightColor.y * ( 1.0f / 255.0f ) * flAlpha;
		state.m_Color[2] = m_CurrentLinearFloatLightColor.z * ( 1.0f / 255.0f ) * flAlpha;
		state.m_Color[3] = 0.0f; // fixme: need to make ambient work m_flAmbient;
		state.m_flShadowSlopeScaleDepthBias = g_pMaterialSystemHardwareConfig->GetShadowSlopeScaleDepthBias();
		state.m_flShadowDepthBias = g_pMaterialSystemHardwareConfig->GetShadowDepthBias();
		state.m_bEnableShadows = m_bEnableShadows;
		state.m_pSpotlightTexture = m_SpotlightTexture;
		state.m_pProjectedMaterial = NULL; // only complain if we're using material projection
		state.m_nSpotlightTextureFrame = m_nSpotlightTextureFrame;
		state.m_flProjectionSize = m_flProjectionSize;
		state.m_flProjectionRotation = m_flRotation;

		state.m_nShadowQuality = m_nShadowQuality; // Allow entity to affect shadow quality

		if ( m_bSimpleProjection == true )
		{
			state.m_bSimpleProjection = true;
			state.m_bOrtho = true;
			state.m_fOrthoLeft = -m_flProjectionSize;
			state.m_fOrthoTop = -m_flProjectionSize;
			state.m_fOrthoRight = m_flProjectionSize;
			state.m_fOrthoBottom = m_flProjectionSize;
		}

		if( m_LightHandle == CLIENTSHADOW_INVALID_HANDLE )
		{
			// Hack: env projected textures don't work like normal flashlights; they're not assigned to a given splitscreen slot,
			// but the flashlight code requires this
			HACK_GETLOCALPLAYER_GUARD( "Env projected texture" );
			if ( m_bSimpleProjection == true )
			{
				m_LightHandle = g_pClientShadowMgr->CreateProjection( state );
			}
			else
			{
				m_LightHandle = g_pClientShadowMgr->CreateFlashlight( state );
			}

			if ( m_LightHandle != CLIENTSHADOW_INVALID_HANDLE )
			{
				m_bForceUpdate = false;
			}
		}
		else
		{
			if ( m_bSimpleProjection == true )
			{
				g_pClientShadowMgr->UpdateProjectionState( m_LightHandle, state );
			}
			else
			{
				g_pClientShadowMgr->UpdateFlashlightState( m_LightHandle, state );
			}
			m_bForceUpdate = false;
		}

		g_pClientShadowMgr->GetFrustumExtents( m_LightHandle, m_vecExtentsMin, m_vecExtentsMax );

		m_vecExtentsMin = m_vecExtentsMin - GetAbsOrigin();
		m_vecExtentsMax = m_vecExtentsMax - GetAbsOrigin();
	}

	if( m_bLightOnlyTarget )
	{
		g_pClientShadowMgr->SetFlashlightTarget( m_LightHandle, m_hTargetEntity );
	}
	else
	{
		g_pClientShadowMgr->SetFlashlightTarget( m_LightHandle, NULL );
	}

	g_pClientShadowMgr->SetFlashlightLightWorld( m_LightHandle, m_bLightWorld );

	if ( !asw_perf_wtf.GetBool() && !m_bForceUpdate )
	{
		g_pClientShadowMgr->UpdateProjectedTexture( m_LightHandle, true );
	}
}
예제 #28
0
// heuristic to find reasonably open space - searches for areas with high node connectivity
CASW_Open_Area* CASW_Spawn_Manager::FindNearbyOpenArea( const Vector &vecSearchOrigin, int nSearchHull )
{
    CBaseEntity *pStartEntity = gEntList.FindEntityByClassname( NULL, "info_player_start" );
    int iNumNodes = g_pBigAINet->NumNodes();
    CAI_Node *pHighestConnectivity = NULL;
    int nHighestLinks = 0;
    for ( int i=0 ; i<iNumNodes; i++ )
    {
        CAI_Node *pNode = g_pBigAINet->GetNode( i );
        if ( !pNode || pNode->GetType() != NODE_GROUND )
            continue;

        Vector vecPos = pNode->GetOrigin();
        float flDist = vecPos.DistTo( vecSearchOrigin );
        if ( flDist > 400.0f )
            continue;

        // discard if node is too near start location
        if ( pStartEntity && vecPos.DistTo( pStartEntity->GetAbsOrigin() ) < 1400.0f )  // NOTE: assumes all start points are clustered near one another
            continue;

        // discard if node is inside an escape area
        bool bInsideEscapeArea = false;
        for ( int d=0; d<m_EscapeTriggers.Count(); d++ )
        {
            if ( m_EscapeTriggers[d]->CollisionProp()->IsPointInBounds( vecPos ) )
            {
                bInsideEscapeArea = true;
                break;
            }
        }
        if ( bInsideEscapeArea )
            continue;

        // count links that drones could follow
        int nLinks = pNode->NumLinks();
        int nValidLinks = 0;
        for ( int k = 0; k < nLinks; k++ )
        {
            CAI_Link *pLink = pNode->GetLinkByIndex( k );
            if ( !pLink )
                continue;

            if ( !( pLink->m_iAcceptedMoveTypes[nSearchHull] & bits_CAP_MOVE_GROUND ) )
                continue;

            nValidLinks++;
        }
        if ( nValidLinks > nHighestLinks )
        {
            nHighestLinks = nValidLinks;
            pHighestConnectivity = pNode;
        }
        if ( asw_director_debug.GetBool() )
        {
            NDebugOverlay::Text( vecPos, UTIL_VarArgs( "%d", nValidLinks ), false, 10.0f );
        }
    }

    if ( !pHighestConnectivity )
        return NULL;

    // now, starting at the new node, find all nearby nodes with a minimum connectivity
    CASW_Open_Area *pArea = new CASW_Open_Area();
    pArea->m_vecOrigin = pHighestConnectivity->GetOrigin();
    pArea->m_pNode = pHighestConnectivity;
    int nMinLinks = nHighestLinks * 0.3f;
    nMinLinks = MAX( nMinLinks, 4 );

    pArea->m_aAreaNodes.AddToTail( pHighestConnectivity );
    if ( asw_director_debug.GetBool() )
    {
        Msg( "minLinks = %d\n", nMinLinks );
    }
    pArea->m_nTotalLinks = 0;
    for ( int i=0 ; i<iNumNodes; i++ )
    {
        CAI_Node *pNode = g_pBigAINet->GetNode( i );
        if ( !pNode || pNode->GetType() != NODE_GROUND )
            continue;

        Vector vecPos = pNode->GetOrigin();
        float flDist = vecPos.DistTo( pArea->m_vecOrigin );
        if ( flDist > 400.0f )
            continue;

        // discard if node is inside an escape area
        bool bInsideEscapeArea = false;
        for ( int d=0; d<m_EscapeTriggers.Count(); d++ )
        {
            if ( m_EscapeTriggers[d]->CollisionProp()->IsPointInBounds( vecPos ) )
            {
                bInsideEscapeArea = true;
                break;
            }
        }
        if ( bInsideEscapeArea )
            continue;

        // count links that drones could follow
        int nLinks = pNode->NumLinks();
        int nValidLinks = 0;
        for ( int k = 0; k < nLinks; k++ )
        {
            CAI_Link *pLink = pNode->GetLinkByIndex( k );
            if ( !pLink )
                continue;

            if ( !( pLink->m_iAcceptedMoveTypes[nSearchHull] & bits_CAP_MOVE_GROUND ) )
                continue;

            nValidLinks++;
        }
        if ( nValidLinks >= nMinLinks )
        {
            pArea->m_aAreaNodes.AddToTail( pNode );
            pArea->m_nTotalLinks += nValidLinks;
        }
    }
    // highlight and measure bounds
    Vector vecAreaMins = Vector( FLT_MAX, FLT_MAX, FLT_MAX );
    Vector vecAreaMaxs = Vector( -FLT_MAX, -FLT_MAX, -FLT_MAX );

    for ( int i = 0; i < pArea->m_aAreaNodes.Count(); i++ )
    {
        vecAreaMins = VectorMin( vecAreaMins, pArea->m_aAreaNodes[i]->GetOrigin() );
        vecAreaMaxs = VectorMax( vecAreaMaxs, pArea->m_aAreaNodes[i]->GetOrigin() );

        if ( asw_director_debug.GetBool() )
        {
            if ( i == 0 )
            {
                NDebugOverlay::Cross3D( pArea->m_aAreaNodes[i]->GetOrigin(), 20.0f, 255, 255, 64, true, 10.0f );
            }
            else
            {
                NDebugOverlay::Cross3D( pArea->m_aAreaNodes[i]->GetOrigin(), 10.0f, 255, 128, 0, true, 10.0f );
            }
        }
    }

    Vector vecArea = ( vecAreaMaxs - vecAreaMins );
    float flArea = vecArea.x * vecArea.y;

    if ( asw_director_debug.GetBool() )
    {
        Msg( "area mins = %f %f %f\n", VectorExpand( vecAreaMins ) );
        Msg( "area maxs = %f %f %f\n", VectorExpand( vecAreaMaxs ) );
        NDebugOverlay::Box( vec3_origin, vecAreaMins, vecAreaMaxs, 255, 128, 128, 10, 10.0f );
        Msg( "Total links = %d Area = %f\n", pArea->m_nTotalLinks, flArea );
    }

    return pArea;
}
예제 #29
0
void sModelMesh::Load_ASCII(FILE *pFile)
{
	const int BufferSize = 256;
	char szBuffer[BufferSize];
	char sz_Tag[BufferSize];
	char sz_Content[BufferSize];
	int i,j;
	fgets(szBuffer, BufferSize, pFile); // {

	fgets(szBuffer, BufferSize, pFile); // matrix
	fgets(szBuffer, BufferSize, pFile); // {
	for ( int r=0; r<4; r++ )
	{
		fgets(szBuffer, BufferSize, pFile); // x,y,z
		sscanf(szBuffer, "%f,%f,%f", &m_Matrix[r][0], &m_Matrix[r][1], &m_Matrix[r][2]);
	}
	fgets(szBuffer, BufferSize, pFile); // }

	fgets(szBuffer, BufferSize, pFile); // buffers n
	sscanf(szBuffer, "%s %d", sz_Tag, &m_iNumVertexChunks);

	m_iNumFaces = 0;
	m_iNumVertices = 0;

	m_vMin.Set(FLT_MAX);
	m_vMax.Set(-FLT_MAX);

	if ( m_iNumVertexChunks )
	{
		m_pVertexChunks = new sModelVertexChunk[m_iNumVertexChunks];
		for ( i=0; i<m_iNumVertexChunks; i++ )
		{
			fgets(szBuffer, BufferSize, pFile); // {

			sModelVertexChunk *pBuffer = m_pVertexChunks + i;
			fgets(szBuffer, BufferSize, pFile); // vertices n
			sscanf(szBuffer, "%s %d", sz_Tag, &pBuffer->m_iNumVertices);
			fgets(szBuffer, BufferSize, pFile); // format
			sscanf(szBuffer, "%s %s", sz_Tag, sz_Content);
			fgets(szBuffer, BufferSize, pFile); // {

			m_iNumVertices += pBuffer->m_iNumVertices;

			bool bVertex = false;
			bool bNormal = false;
			bool bColor = false;
			bool bTangentSpace = false;
			int  iNumUVs = 0;
			int  strLen = strlen(sz_Content);

			for ( int s=0; s<strLen; s++ )
			{
				switch(sz_Content[s])
				{
				case 'v':
					bVertex = true;
					break;
				case 'n':
					bNormal = true;
					break;
				case 'c':
					bColor = true;
					break;
				case 't':
					iNumUVs = sz_Content[++s] - '0';
					break;
				case '_':
					break;
				case 'p':
				case 'q':
					bTangentSpace = true;
					break;
				default:
					break;
				}
			}

			int vsize = 0;
			if ( bVertex )
			{
				pBuffer->m_VertexDecl.m_iPositionOffset = vsize;
				pBuffer->m_VertexDecl.m_iNumPositionElements = 3;
				vsize += 4*3;
			}

			if ( bNormal )
			{
				pBuffer->m_VertexDecl.m_iNormalOffset = vsize;
				pBuffer->m_VertexDecl.m_iNumNormalElements = 3;
				vsize += 4*3;
			}

			if ( bColor )
			{
				pBuffer->m_VertexDecl.m_iColorOffset = vsize;
				pBuffer->m_VertexDecl.m_iNumColorElements = 4;
				vsize += 4;
			}

			for ( j=0; j<iNumUVs; j++ )
			{
				pBuffer->m_VertexDecl.m_iTexcoordOffset[j] = vsize;
				pBuffer->m_VertexDecl.m_iNumTexcoordElements[j] = 2;
				vsize += 4*2;
			}

			if ( bTangentSpace )
			{
				pBuffer->m_VertexDecl.m_iTangentOffset = vsize;
				pBuffer->m_VertexDecl.m_iNumTangentElements = 3;
				vsize += 4 * 3;

				pBuffer->m_VertexDecl.m_iBiNormalOffset = vsize;
				pBuffer->m_VertexDecl.m_iBiNormalElements = 3;
				vsize += 4 * 3;
			}

			if ( vsize==0 )
			{
				int a=0;
			}

			pBuffer->m_VertexDecl.m_iVertexSize = vsize;

			if ( pBuffer->m_iNumVertices )
			{
				pBuffer->m_pVertexArray = new sModelVertex[pBuffer->m_iNumVertices];
			}

			printf(".");

			for ( j=0; j<pBuffer->m_iNumVertices; j++ )
			{
				sModelVertex *pVertex = pBuffer->m_pVertexArray + j;

				Vector4 &position = pVertex->m_Position;
				Vector4 &normal = pVertex->m_Normal;
				Vector4 &color = pVertex->m_Color;
				Vector4 *pUV = pVertex->m_Texcoord;
				Vector4 &tangent = pVertex->m_Tangent;
				Vector4 &binormal = pVertex->m_BiNormal;

				fgets(szBuffer, BufferSize, pFile);
				char *pLoc = szBuffer;

				if ( bVertex )
				{
					pLoc = strstr(pLoc, " ");
					sscanf(pLoc, "%f,%f,%f", &position[0], &position[1], &position[2]);
					position[3] = 1.0f;

					m_vMin = VectorMin(m_vMin, position);
					m_vMax = VectorMax(m_vMax, position);
				}

				if ( bNormal )
				{
					pLoc = strstr(pLoc+1, " ");
					pLoc = strstr(pLoc+1, " ");
					sscanf(pLoc, "%f,%f,%f", &normal[0], &normal[1], &normal[2]);
					normal[3] = 1.0f;
				}

				if ( bColor )
				{
					pLoc = strstr(pLoc+1, " ");
					pLoc = strstr(pLoc+1, " ");
					sscanf(pLoc, "%f,%f,%f,%f", &color[0], &color[1], &color[2], &color[3]);
				}

				for ( int t=0; t<iNumUVs && t<MAX_TEXCOORDS; t++ )
				{
					pLoc = strstr(pLoc+1, " ");
					pLoc = strstr(pLoc+1, " ");
					sscanf(pLoc, "%f,%f", &pUV[t][0], &pUV[t][1]);
				}

				if ( bTangentSpace )
				{
					pLoc = strstr(pLoc+1, " ");
					pLoc = strstr(pLoc+1, " ");
					sscanf(pLoc, "%f,%f,%f", &tangent[0], &tangent[1], &tangent[2]);

					pLoc = strstr(pLoc+1, " ");
					pLoc = strstr(pLoc+1, " ");
					sscanf(pLoc, "%f,%f,%f", &binormal[0], &binormal[1], &binormal[2]);
				}

				if ( (j & 0xff)==0 )
					printf(".");
			}

			fgets(szBuffer, BufferSize, pFile); // }

			fgets(szBuffer, BufferSize, pFile); // triangle_list_indices n
			sscanf(szBuffer, "%s %d", sz_Tag, &pBuffer->m_iNumIndices);
			if ( pBuffer->m_iNumIndices )
				pBuffer->m_pIndexArray = new unsigned short[pBuffer->m_iNumIndices];
			fgets(szBuffer, BufferSize, pFile); // {
			for ( j=0; j<pBuffer->m_iNumIndices/3; j++ )
			{
				int a,b,c;
				fgets(szBuffer, BufferSize, pFile);
				sscanf(szBuffer, "%d %d %d", &a, &b, &c);
				unsigned short *p = pBuffer->m_pIndexArray + j*3;
				p[0] = a; p[1] = b; p[2] = c;
			}
			fgets(szBuffer, BufferSize, pFile); // }

			fgets(szBuffer, BufferSize, pFile); // batches n
			sscanf(szBuffer, "%s %d", sz_Tag, &pBuffer->m_iNumBatches);
			if ( pBuffer->m_iNumBatches )
				pBuffer->m_pBatchArray = new sModelBatch[pBuffer->m_iNumBatches];
			fgets(szBuffer, BufferSize, pFile); // {
			for ( j=0; j<pBuffer->m_iNumBatches; j++ )
			{
				sModelBatch *pBatch = pBuffer->m_pBatchArray + j;

				fgets(szBuffer, BufferSize, pFile); // material n
				sscanf(szBuffer, "%s %d", sz_Tag, &pBatch->m_iMaterialID);
				fgets(szBuffer, BufferSize, pFile); // faces n
				sscanf(szBuffer, "%s %d", sz_Tag, &pBatch->m_iNumPrimitives);
				fgets(szBuffer, BufferSize, pFile); // index_begin n
				sscanf(szBuffer, "%s %d", sz_Tag, &pBatch->m_iIndexArrayBegin);

				pBatch->m_iNumIndices = pBatch->m_iNumPrimitives * 3;
				pBatch->m_iIndexArrayEnd = pBatch->m_iIndexArrayBegin + pBatch->m_iNumIndices;

				m_iNumFaces += pBatch->m_iNumPrimitives;
			}
			fgets(szBuffer, BufferSize, pFile); // }

			fgets(szBuffer, BufferSize, pFile); // }
		}
	}

	printf(".\n");
	fgets(szBuffer, BufferSize, pFile); // }
}
//-----------------------------------------------------------------------------
// Purpose: Recompute my rendering box
//-----------------------------------------------------------------------------
void C_QUA_Strider::ClientThink()
{
	int i;
	Vector vecMins, vecMaxs;
	Vector vecAbsMins, vecAbsMaxs;
	matrix3x4_t worldToStrider, hitboxToStrider;
	Vector vecBoxMins, vecBoxMaxs;
	Vector vecBoxAbsMins, vecBoxAbsMaxs;
	mstudiohitboxset_t *set;
	CBoneCache *pCache = NULL;

	// The reason why this is here, as opposed to in SetObjectCollisionBox,
	// is because of IK. The code below recomputes bones so as to get at the hitboxes,
	// which causes IK to trigger, which causes raycasts against the other entities to occur,
	// which is illegal to do while in the Relink phase.

	studiohdr_t *pStudioHdr = GetModel()?modelinfo->GetStudiomodel( GetModel() ):NULL;
	if (!pStudioHdr)
		goto doneWithComputation;

	set = pStudioHdr->pHitboxSet( m_nHitboxSet );
	if ( !set || !set->numhitboxes )
		goto doneWithComputation;

	CStudioHdr *hdr = GetModelPtr();
	pCache = GetBoneCache( hdr );

	matrix3x4_t *hitboxbones[MAXSTUDIOBONES];
	pCache->ReadCachedBonePointers( hitboxbones, pStudioHdr->numbones );

//	// Compute a box in world space that surrounds this entity
	m_vecRenderMins.Init( FLT_MAX, FLT_MAX, FLT_MAX );
	m_vecRenderMaxs.Init( -FLT_MAX, -FLT_MAX, -FLT_MAX );
//
	MatrixInvert( EntityToWorldTransform(), worldToStrider );
//
	for ( i = 0; i < set->numhitboxes; i++ )
	{
		mstudiobbox_t *pbox = set->pHitbox(i);
		ConcatTransforms( worldToStrider, *hitboxbones[pbox->bone], hitboxToStrider );

		TransformAABB( hitboxToStrider, pbox->bbmin, pbox->bbmax, vecBoxMins, vecBoxMaxs );
		VectorMin( m_vecRenderMins, vecBoxMins, m_vecRenderMins );
		VectorMax( m_vecRenderMaxs, vecBoxMaxs, m_vecRenderMaxs );
	}
//	// Deberiamos poner aqui lo de la vista??
//
//	// UNDONE: Disabled this until we can get closer to a final map and tune
//#if 0
//	// Cut ropes.
//	if ( gpGlobals->curtime >= m_flNextRopeCutTime )
//	{
//		// Blow the bbox out a little.
//		Vector vExtendedMins = vecMins - Vector( 50, 50, 50 );
//		Vector vExtendedMaxs = vecMaxs + Vector( 50, 50, 50 );
//
//		C_RopeKeyframe *ropes[512];
//		int nRopes = C_RopeKeyframe::GetRopesIntersectingAABB( ropes, ARRAYSIZE( ropes ), GetAbsOrigin() + vExtendedMins, GetAbsOrigin() + vExtendedMaxs );
//		for ( int i=0; i < nRopes; i++ )
//		{
//			C_RopeKeyframe *pRope = ropes[i];
//
//			if ( pRope->GetEndEntity() )
//			{
//				Vector vPos;
//				if ( pRope->GetEndPointPos( 1, vPos ) )
//				{
//					// Detach the endpoint.
//					pRope->SetEndEntity( NULL );
//					
//					// Make some spark effect here..
//					g_pEffects->Sparks( vPos );
//				}				
//			}
//		}
//
//		m_flNextRopeCutTime = gpGlobals->curtime + 0.5;
//	}
//#endif

doneWithComputation:	
	// True argument because the origin may have stayed the same, but the size is expected to always change
	g_pClientShadowMgr->AddToDirtyShadowList( this, true );
}