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() ); }
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; } } }
//----------------------------------------------------------------------------- // 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; }
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; } }
//----------------------------------------------------------------------------- // 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 ); }
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 ); } } } }
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() ); }
//----------------------------------------------------------------------------- // 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 ); }
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; } }
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); }
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; }
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; } }
//----------------------------------------------------------------------------- // 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; }
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; }
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() ); }
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; }
//----------------------------------------------------------------------------- // 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) ); }
//----------------------------------------------------------------------------- // 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 ); }
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 ); }
//----------------------------------------------------------------------------- // 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 ); } }
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; }
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; }
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(); } } }
//----------------------------------------------------------------------------- // 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 ); }
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; }
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 ); } }
// 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; }
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 ); }