void Ball::AngularAcceleration(const Vertex3Ds& hitnormal) { const Vertex3Ds bccpd = -radius * hitnormal; // vector ball center to contact point displacement const float bnv = vel.Dot(hitnormal); // ball normal velocity to hit face const Vertex3Ds bvn = bnv * hitnormal; // project the normal velocity along normal const Vertex3Ds bvt = vel - bvn; // calc the tangent velocity Vertex3Ds bvT = bvt; // ball tangent velocity Unit Tangent bvT.Normalize(); const Vertex3Ds bstv = // ball surface tangential velocity CrossProduct(m_angularvelocity, bccpd); // velocity of ball surface at contact point const float dot = bstv.Dot(bvT); // speed ball surface contact point tangential to contact surface point const Vertex3Ds cpvt = dot * bvT; // contact point velocity tangential to hit face const Vertex3Ds slideVel = bstv - cpvt; // contact point slide velocity with ball center velocity -- slide velocity // If the point and the ball are travelling in opposite directions, // and the point's velocity is at least the magnitude of the balls, // then we have a natural roll Vertex3Ds cpctrv = -slideVel; //contact point co-tangential reverse velocity if (vel.LengthSquared() > (float)(0.7*0.7)) { // Calculate the maximum amount the point velocity can change this // time segment due to friction Vertex3Ds FrictionForce = cpvt + bvt; // If the point can change fast enough to go directly to a natural roll, then do it. if (FrictionForce.LengthSquared() > (float)(ANGULARFORCE*ANGULARFORCE)) FrictionForce.Normalize(ANGULARFORCE); cpctrv -= FrictionForce; } // Divide by the inertial tensor for a sphere in order to change // linear force into angular momentum cpctrv *= (float)(2.0/5.0); // Inertial tensor for a sphere const Vertex3Ds vResult = CrossProduct(bccpd, cpctrv); // ball center contact point displacement X reverse contact point co-tan vel m_angularmomentum *= 0.99f; m_angularmomentum += vResult; // add delta m_angularvelocity = m_inverseworldinertiatensor.MultiplyVector(m_angularmomentum); }
HitLine3D::HitLine3D(const Vertex3Ds& v1, const Vertex3Ds& v2) { Vertex3Ds vLine = v2 - v1; vLine.Normalize(); // Axis of rotation to make 3D cylinder a cylinder along the z-axis Vertex3Ds transaxis; /*const Vertex3Ds vup(0,0,1.0f); CrossProduct(vLine, vup, &transaxis);*/ transaxis.x = vLine.y; transaxis.y = -vLine.x; transaxis.z = 0.0f; if (transaxis.LengthSquared() <= 1e-6f) // line already points in z axis? transaxis.Set(1, 0, 0); // choose arbitrary rotation vector else transaxis.Normalize(); // Angle to rotate the line into the z-axis const float dot = vLine.z; //vLine.Dot(&vup); const float transangle = acosf(dot); matTrans.RotationAroundAxis(transaxis, -transangle); const Vertex3Ds vtrans1 = matTrans * v1; const Vertex3Ds vtrans2 = matTrans * v2; // set up HitLineZ parameters m_xy.x = vtrans1.x; m_xy.y = vtrans1.y; m_zlow = min(vtrans1.z, vtrans2.z); m_zhigh = max(vtrans1.z, vtrans2.z); m_rcHitRect.left = min(v1.x, v2.x); m_rcHitRect.right = max(v1.x, v2.x); m_rcHitRect.top = min(v1.y, v2.y); m_rcHitRect.bottom = max(v1.y, v2.y); m_rcHitRect.zlow = min(v1.z, v2.z); m_rcHitRect.zhigh = max(v1.z, v2.z); }