void CCharacter::FindGroundEntity() { TVector vecVelocity = GetGlobalVelocity(); if (vecVelocity.Dot(GetUpVector()) > JumpStrength()/2.0f) { SetGroundEntity(NULL); SetSimulated(true); return; } TVector vecUp = GetUpVector() * m_flMaxStepSize; size_t iMaxEntities = GameServer()->GetMaxEntities(); for (size_t j = 0; j < iMaxEntities; j++) { CBaseEntity* pEntity = CBaseEntity::GetEntity(j); if (!pEntity) continue; if (pEntity->IsDeleted()) continue; if (!pEntity->ShouldCollide()) continue; if (pEntity == this) continue; TVector vecPoint, vecNormal; if (GetMoveParent() == pEntity) { TMatrix mGlobalToLocal = GetMoveParent()->GetGlobalToLocalTransform(); Vector vecUpLocal = mGlobalToLocal.TransformNoTranslate(GetUpVector()) * m_flMaxStepSize; if (pEntity->CollideLocal(GetLocalOrigin(), GetLocalOrigin() - vecUpLocal, vecPoint, vecNormal)) { SetGroundEntity(pEntity); SetSimulated(false); return; } } else { if (pEntity->Collide(GetGlobalOrigin(), GetGlobalOrigin() - vecUp, vecPoint, vecNormal)) { SetGroundEntity(pEntity); SetSimulated(false); return; } } } SetGroundEntity(NULL); SetSimulated(true); }
void CCharacter::MoveThink() { if (!GetGroundEntity()) return; if (m_vecGoalVelocity.LengthSqr()) m_vecGoalVelocity.Normalize(); m_vecMoveVelocity.x = Approach(m_vecGoalVelocity.x, m_vecMoveVelocity.x, GameServer()->GetFrameTime()*4); m_vecMoveVelocity.y = 0; m_vecMoveVelocity.z = Approach(m_vecGoalVelocity.z, m_vecMoveVelocity.z, GameServer()->GetFrameTime()*4); if (m_vecMoveVelocity.LengthSqr() > 0) { TMatrix m = GetLocalTransform(); Vector vecUp = GetUpVector(); if (HasMoveParent()) { TMatrix mGlobalToLocal = GetMoveParent()->GetGlobalToLocalTransform(); vecUp = mGlobalToLocal.TransformNoTranslate(vecUp); } Vector vecRight = m.GetForwardVector().Cross(vecUp).Normalized(); Vector vecForward = vecUp.Cross(vecRight).Normalized(); m.SetColumn(0, vecForward); m.SetColumn(1, vecUp); m.SetColumn(2, vecRight); TVector vecMove = m_vecMoveVelocity * CharacterSpeed(); TVector vecLocalVelocity = m.TransformNoTranslate(vecMove); SetLocalVelocity(vecLocalVelocity); } else SetLocalVelocity(TVector()); eastl::vector<CEntityHandle<CBaseEntity> > apCollisionList; size_t iMaxEntities = GameServer()->GetMaxEntities(); for (size_t j = 0; j < iMaxEntities; j++) { CBaseEntity* pEntity2 = CBaseEntity::GetEntity(j); if (!pEntity2) continue; if (pEntity2->IsDeleted()) continue; if (pEntity2 == this) continue; if (!pEntity2->ShouldCollide()) continue; apCollisionList.push_back(pEntity2); } TMatrix mGlobalToLocalRotation; if (HasMoveParent()) { mGlobalToLocalRotation = GetMoveParent()->GetGlobalToLocalTransform(); mGlobalToLocalRotation.SetTranslation(TVector()); } float flSimulationFrameTime = 0.01f; // Break simulations up into consistent small steps to preserve accuracy. for (; m_flMoveSimulationTime < GameServer()->GetGameTime(); m_flMoveSimulationTime += flSimulationFrameTime) { TVector vecVelocity = GetLocalVelocity(); TVector vecLocalOrigin = GetLocalOrigin(); TVector vecGlobalOrigin = GetGlobalOrigin(); vecVelocity = vecVelocity * flSimulationFrameTime; TVector vecLocalDestination = vecLocalOrigin + vecVelocity; TVector vecGlobalDestination = vecLocalDestination; if (GetMoveParent()) vecGlobalDestination = GetMoveParent()->GetGlobalTransform() * vecLocalDestination; TVector vecNewLocalOrigin = vecLocalDestination; size_t iTries = 0; while (true) { iTries++; TVector vecPoint, vecNormal; TVector vecLocalCollisionPoint, vecGlobalCollisionPoint; bool bContact = false; for (size_t i = 0; i < apCollisionList.size(); i++) { CBaseEntity* pEntity2 = apCollisionList[i]; if (GetMoveParent() == pEntity2) { if (pEntity2->CollideLocal(vecLocalOrigin, vecLocalDestination, vecPoint, vecNormal)) { bContact = true; Touching(pEntity2); vecLocalCollisionPoint = vecPoint; vecGlobalCollisionPoint = GetMoveParent()->GetGlobalTransform() * vecPoint; } } else { if (pEntity2->Collide(vecGlobalOrigin, vecGlobalDestination, vecPoint, vecNormal)) { bContact = true; Touching(pEntity2); vecGlobalCollisionPoint = vecPoint; if (GetMoveParent()) { vecLocalCollisionPoint = GetMoveParent()->GetGlobalToLocalTransform() * vecPoint; vecNormal = GetMoveParent()->GetGlobalToLocalTransform().TransformNoTranslate(vecNormal); } else vecLocalCollisionPoint = vecGlobalCollisionPoint; } } } if (bContact) { vecNewLocalOrigin = vecLocalCollisionPoint; vecVelocity -= vecLocalCollisionPoint - vecLocalOrigin; } if (!bContact) break; if (iTries > 4) break; vecLocalOrigin = vecLocalCollisionPoint; vecGlobalOrigin = vecGlobalCollisionPoint; // Clip the velocity to the surface normal of whatever we hit. TFloat flDistance = vecVelocity.Dot(vecNormal); vecVelocity = vecVelocity - vecNormal * flDistance; // Do it one more time just to make sure we're not headed towards the plane. TFloat flAdjust = vecVelocity.Dot(vecNormal); if (flAdjust < 0.0f) vecVelocity -= (vecNormal * flAdjust); vecLocalDestination = vecLocalOrigin + vecVelocity; if (GetMoveParent()) vecGlobalDestination = GetMoveParent()->GetGlobalTransform() * vecLocalDestination; else vecGlobalDestination = vecLocalDestination; SetLocalVelocity(vecVelocity.Normalized() * GetLocalVelocity().Length()); } SetLocalOrigin(vecNewLocalOrigin); // Try to keep the player on the ground. // Untested. /*TVector vecStart = GetGlobalOrigin() + GetGlobalTransform().GetUpVector()*m_flMaxStepSize; TVector vecEnd = GetGlobalOrigin() - GetGlobalTransform().GetUpVector()*m_flMaxStepSize; // First go up a bit TVector vecHit, vecNormal; Game()->TraceLine(GetGlobalOrigin(), vecStart, vecHit, vecNormal, NULL); vecStart = vecHit; // Now see if there's ground underneath us. bool bHit = Game()->TraceLine(vecStart, vecEnd, vecHit, vecNormal, NULL); if (bHit && vecNormal.y >= TFloat(0.7f)) SetGlobalOrigin(vecHit);*/ m_flMoveSimulationTime += flSimulationFrameTime; } }
void LCPPolyDist<VectorIn,TVector,TTuple>::VerifyWithTestPoints ( const TVector* akRes, int& riStatusCode) { TVector* akTestPoints1 = new TVector[13]; TVector* akTestPoints2 = new TVector[13]; SetupTestPoints(1,m_iNumFaces1,m_iNumPoints1,akRes[0],m_adB1,m_akA1, m_akP1,akTestPoints1); SetupTestPoints(2,m_iNumFaces2,m_iNumPoints2,akRes[1],m_adB2,m_akA2, m_akP2,akTestPoints2); double fDiffSq; double fMin; TVector kDiff; int iLine = 0; int jLine = 0; // min distance between generated points note that one of these points // is the "solution" int i; for (i = 0; i < 13; i++) { for (int j = 0; j < 13; j++) { kDiff = akTestPoints1[i]-akTestPoints2[j]; fDiffSq = kDiff.Dot(kDiff); if ( i == 0 && j == 0 ) { fMin = fDiffSq; } else { if ( fDiffSq < fMin ) { fMin = fDiffSq; iLine = i; jLine = j; } } } } kDiff = akRes[0]-akRes[1]; float fDistance = (float) kDiff.Dot(kDiff); riStatusCode = SC_FOUND_SOLUTION; if ( fDistance > fDiffSq ) { m_kLog << "Test points closer than solution points by "; m_kLog << fDistance-fDiffSq << " squared units.\n"; if ( (fDistance-fDiffSq > VERIFY_MIN_DIFFERENCE) && (iLine != 12 || jLine != 12) ) { riStatusCode = SC_TEST_POINTS_TEST_FAILED; } } m_kLog << endl << " Solution points are separated by " << Mathf::Sqrt(fDistance); m_kLog << " units." << endl; m_kLog << "The smallest distance between test points is " << Mathf::Sqrt((float)fMin); m_kLog << endl << "and occurs for (" << akTestPoints1[iLine][0]; for (i = 1; i < m_iDimension; i++) { m_kLog << ", " << akTestPoints1[iLine][i]; } m_kLog << ") and (" << akTestPoints2[jLine][0]; for (i = 1; i < m_iDimension; i++) m_kLog << ", " << akTestPoints2[jLine][i]; m_kLog << ")" << endl; delete[] akTestPoints1; delete[] akTestPoints2; }