bool LineConeIntersection(IVRenderInterface *pRenderer, const hkvVec3 &vConePos, const hkvVec3 &vConeAxis, float fConeAngle, const hkvVec3 &vLineStart, const hkvVec3 &vLineDir, hkvVec3 &vIntersection) { // cull back cone float fConeLineAngle = vConeAxis.dot(vLineDir); if (fConeLineAngle < 0) return false; float fCosAngle = hkvMath::cosDeg(fConeAngle); float fCosSquared = fCosAngle*fCosAngle; hkvVec3 vLineToCone = vLineStart - vConePos; float fDotA = vConeAxis.dot(vLineToCone); float fDotB = vLineDir.dot(vLineToCone); float fDotC = vLineToCone.dot(vLineToCone); float a = fConeLineAngle*fConeLineAngle - fCosSquared; float b = fConeLineAngle*fDotA - fCosSquared*fDotB; float c = fDotA*fDotA - fCosSquared*fDotC; float fInnerValue = b*b-4*a*c; float fDenominator = 2*a; if(fInnerValue < 0.0f || fDenominator == 0.0f) return false; float fSqrtInnerValue = sqrt(fInnerValue); float t1 = (-b + fSqrtInnerValue)/fDenominator; float t2 = (-b - fSqrtInnerValue)/fDenominator; // choose front cone float t = (t1 > t2) ? t1 : t2; vIntersection = vLineStart+vLineDir*t; return true; }
hkvVec3 RPG_Explosion::GetHerringBoneImpulse( hkvVec3 const& position ) { hkvVec3 impulse(0.0f, 0.0f, 0.0f); hkvVec3 attackLine = m_direction; attackLine.z = 0.0f; attackLine.normalize(); float const lineProjection = hkvMath::Max(0.0f, position.dot(attackLine) - m_center.dot(attackLine)); hkvVec3 const& closestPointOnAttackLine = m_center + lineProjection * attackLine; impulse = (position - closestPointOnAttackLine); impulse.z = 0.0f; float distanceLineToImpact = impulse.getLengthAndNormalize(); if(hkvMath::isFloatEqual(0.0f, distanceLineToImpact)) { if(Vision::Game.GetFloatRand() > 0.5) { impulse.x = attackLine.y; impulse.y = -attackLine.x; } else { impulse.x = -attackLine.y; impulse.y = -attackLine.x; } } impulse += attackLine; impulse.normalize(); float const strengthScale = hkvMath::Max(0.0f, (m_length - lineProjection) / m_length) * hkvMath::Max(0.0f, (m_radius - distanceLineToImpact) / m_radius); impulse.z = 0.1f; return impulse * strengthScale * m_impulseStrength; }
bool VWallmarkManager::IsTracePointOnPlane(const hkvVec3& vPos, const hkvVec3& vNormal, float fTraceRad, float fEpsilon, hkvVec3& vNewNormal) { hkvVec3 vStart = vPos + vNormal*fTraceRad; hkvVec3 vEnd = vPos - vNormal*fTraceRad; #ifdef WALLMARKS_USE_VISION_TRACELINES VisTraceLineInfo_t result; if (Vision::CollisionToolkit.TraceLine(vStart,vEnd,(ULONG)VIS_TRACE_ALL,(ULONG)VIS_TRACE_NONE,NULL,NULL,&result)) return false; // no hit // only allow wallmarks on static geometry and terrain if (result.hitType != VIS_TRACETYPE_STATICGEOMETRY && result.hitType != VIS_TRACETYPE_TERRAIN) return false; if (hkvMath::Abs (result.distance - fTraceRad)>fEpsilon) return false; // too much deviation from plane normal vNewNormal = result.primitivePlane.m_vNormal; float fDot = vNewNormal.dot(vNormal); if (hkvMath::Abs (fDot-1.f)>fEpsilon) return false; #else IVisPhysicsModule_cl *pPhysMod = Vision::GetApplication()->GetPhysicsModule(); VisPhysicsHit_t result; if (pPhysMod==NULL || !pPhysMod->Raycast(vStart,vEnd,result)) return false; // only allow wallmarks on static geometry and terrain if (result.eHitType != VIS_TRACETYPE_STATICGEOMETRY && result.eHitType != VIS_TRACETYPE_TERRAIN) return false; if (hkvMath::Abs ((result.fHitFraction - 0.5f)*fTraceRad)>fEpsilon) return false; //NOTE: result.vImpactNormal is the interpolated vertex normal and thus not useful here vNewNormal = vNormal; #endif // Vision::Game.DrawSingleLine(vPos,vPos+vNewNormal*20.f); return true; }