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;
}