float HitPlane::HitTest(const Ball * pball, float dtime, CollisionEvent& coll) { if (!m_fEnabled) return -1.0f; //slintf("HitPlane test - %f %f\n", pball->m_pos.z, pball->m_vel.z); const float bnv = normal.Dot(pball->m_vel); // speed in normal direction if (bnv >= (float)C_CONTACTVEL) // return if clearly ball is receding from object return -1.0f; const float bnd = normal.Dot( pball->m_pos ) - pball->m_radius - d; // distance from plane to ball surface if (bnd < pball->m_radius*-2.0f) //!! solely responsible for ball through playfield?? check other places, too (radius*2??) return -1.0f; // excessive penetration of plane ... no collision HACK // slow moving ball? then either contact or no collision at all if (fabsf(bnv) <= (float)C_CONTACTVEL) { if (fabsf(bnd) <= (float)PHYS_TOUCH) { coll.isContact = true; coll.hitnormal = normal; coll.hitvelocity.z = bnv; // remember original normal velocity coll.hitdistance = bnd; //coll.hitRigid = true; return 0.0f; // hittime is ignored for contacts } else return -1.0f; // large distance, small velocity -> no hit } float hittime = bnd / (-bnv); // rate ok for safe divide if (hittime < 0.f) hittime = 0.0f; // already penetrating? then collide immediately if (infNaN(hittime) || hittime > dtime) return -1.0f; // time is outside this frame ... no collision coll.hitnormal = normal; coll.hitdistance = bnd; // actual contact distance //coll.hitRigid = true; // collision type return hittime; }
float Ball::HitTest(const Ball * pball_, float dtime, CollisionEvent& coll) { Ball * pball = const_cast<Ball*>(pball_); // HACK; needed below Vertex3Ds d = pos - pball->pos; // delta position Vertex3Ds dv = vel - pball->vel; // delta velocity float bcddsq = d.LengthSquared(); // square of ball center's delta distance float bcdd = sqrtf(bcddsq); // length of delta if (bcdd < 1.0e-8f) // two balls center-over-center embedded { //return -1; d.z = -1.0f; // patch up pball->pos.z -= d.z; // lift up bcdd = 1.0f; // patch up bcddsq = 1.0f; // patch up dv.z = 0.1f; // small speed difference pball->vel.z -= dv.z; } float b = dv.Dot(d); // inner product const float bnv = b/bcdd; // normal speed of balls toward each other if ( bnv > C_LOWNORMVEL) return -1.0f; // dot of delta velocity and delta displacement, postive if receding no collison const float totalradius = pball->radius + radius; const float bnd = bcdd - totalradius; // distance between ball surfaces float hittime; if (bnd < (float)PHYS_TOUCH) // in contact??? { if (bnd <= (float)(-PHYS_SKIN*2.0)) return -1.0f; // embedded too deep if ((fabsf(bnv) > C_CONTACTVEL) // >fast velocity, return zero time //zero time for rigid fast bodies || (bnd <= (float)(-PHYS_TOUCH))) hittime = 0; // slow moving but embedded else hittime = bnd/(float)(2.0*PHYS_TOUCH) + 0.5f; // don't compete for fast zero time events } else { // find collision time as solution of quadratic equation // at^2 + bt + c = 0 const float a = dv.LengthSquared(); // square of differential velocity if (a < 1.0e-8f) return -1.0f; // ball moving really slow, then wait for contact const float c = bcddsq - totalradius*totalradius; //first contact test: square delta position - square of radii b *= 2.0f; // two inner products float result = b*b - 4.0f*a*c; // squareroot term (discriminant) in quadratic equation if (result < 0.0f) return -1.0f; // no collision path exist result = sqrtf(result); // compute the two solutions to the quadratic equation float time1 = (-b + result)/(2.0f * a); const float time2 = (-b - result)/(2.0f * a); // choose smallest non-negative solution hittime = std::min(time1, time2); if (hittime < 0) hittime = std::max(time1, time2); if (infNaN(hittime) || hittime < 0 || hittime > dtime) return -1.0f; // .. was some time previous || beyond the next physics tick } const Vertex3Ds hitPos = pball->pos + hittime * dv; // new ball position //calc unit normal of collision coll.normal[0] = hitPos - pos; coll.normal[0].Normalize(); coll.distance = bnd; //actual contact distance coll.hitRigid = true; //rigid collision type return hittime; }
float Hit3DPoly::HitTest(const Ball * pball, float dtime, CollisionEvent& coll) { if (!m_fEnabled) return -1.0f; const float bnv = normal.Dot(pball->m_vel); //speed in Normal-vector direction if ((m_ObjType != eTrigger) && (bnv >= 0.f)) // return if clearly ball is receding from object return -1.0f; // Point on the ball that will hit the polygon, if it hits at all Vertex3Ds hitPos = pball->m_pos - pball->m_radius * normal; // nearest point on ball ... projected radius along norm const float bnd = normal.Dot( hitPos - m_rgv[0] ); // distance from plane to ball bool bUnHit = (bnv > C_LOWNORMVEL); const bool inside = (bnd <= 0); // in ball inside object volume const bool rigid = (m_ObjType != eTrigger); float hittime; if (rigid) //rigid polygon { if (bnd < -pball->m_radius/**2.0f*/) return -1.0f; // (ball normal distance) excessive penetration of object skin ... no collision HACK //!! *2 necessary? if (bnd <= (float)PHYS_TOUCH) { if (inside || (fabsf(bnv) > C_CONTACTVEL) // fast velocity, return zero time //zero time for rigid fast bodies || (bnd <= (float)(-PHYS_TOUCH))) // slow moving but embedded hittime = 0; else hittime = bnd*(float)(1.0/(2.0*PHYS_TOUCH)) + 0.5f; // don't compete for fast zero time events } else if (fabsf(bnv) > C_LOWNORMVEL ) // not velocity low ???? hittime = bnd/(-bnv); // rate ok for safe divide else return -1.0f; // wait for touching } else //non-rigid polygon { if (bnv * bnd >= 0) // outside-receding || inside-approaching { if((m_ObjType != eTrigger) || // not a trigger (!pball->m_vpVolObjs) || // temporary ball (fabsf(bnd) >= pball->m_radius*0.5f) || // not too close ... nor too far away (inside != (pball->m_vpVolObjs->IndexOf(m_pObj) < 0)))// ...ball outside and hit set or ball inside and no hit set return -1.0f; hittime = 0; bUnHit = !inside; // ball on outside is UnHit, otherwise it's a Hit } else hittime = bnd/(-bnv); } if (infNaN(hittime) || hittime < 0 || hittime > dtime) return -1.0f; // time is outside this frame ... no collision hitPos += hittime * pball->m_vel; // advance hit point to contact // Do a point in poly test, using the xy plane, to see if the hit point is inside the polygon //this need to be changed to a point in polygon on 3D plane float x2 = m_rgv[0].x; float y2 = m_rgv[0].y; bool hx2 = (hitPos.x >= x2); bool hy2 = (hitPos.y <= y2); int crosscount=0; // count of lines which the hit point is to the left of for (int i=0;i<m_cvertex;i++) { const float x1 = x2; const float y1 = y2; const bool hx1 = hx2; const bool hy1 = hy2; const int j = (i < m_cvertex-1) ? (i+1) : 0; x2 = m_rgv[j].x; y2 = m_rgv[j].y; hx2 = (hitPos.x >= x2); hy2 = (hitPos.y <= y2); if ((y1==y2) || (hy1 && hy2) || (!hy1 && !hy2) || // if out of y range, forget about this segment (hx1 && hx2)) // Hit point is on the right of the line continue; if (!hx1 && !hx2) { crosscount^=1; continue; } if (x2 == x1) { if (!hx2) crosscount^=1; continue; } // Now the hard part - the hit point is in the line bounding box if (x2 - (y2 - hitPos.y)*(x1 - x2)/(y1 - y2) > hitPos.x) crosscount^=1; } if (crosscount & 1) { coll.hitnormal.x = m_rgv[0].z; coll.hitnormal.y = m_rgv[2].z; if (!rigid) // non rigid body collision? return direction coll.hitvelocity.x = bUnHit ? 1.0f : 0.0f; // UnHit signal is receding from outside target coll.hitdistance = bnd; // 3dhit actual contact distance ... //coll.hitRigid = rigid; // collision type return hittime; } return -1.0f; }
float HitTriangle::HitTest(const Ball * pball, float dtime, CollisionEvent& coll) { if (!m_fEnabled) return -1.0f; const float bnv = normal.Dot(pball->m_vel); // speed in Normal-vector direction if (bnv >= C_CONTACTVEL) // return if clearly ball is receding from object return -1.0f; // Point on the ball that will hit the polygon, if it hits at all const float bRadius = pball->m_radius; Vertex3Ds hitPos = pball->m_pos - bRadius * normal; // nearest point on ball ... projected radius along norm const float bnd = normal.Dot( hitPos - m_rgv[0] ); // distance from plane to ball float hittime; if (bnd < -pball->m_radius/**2.0f*/) //!! *2 necessary? return -1.0f; // (ball normal distance) excessive pentratration of object skin ... no collision HACK bool isContact = false; if (bnd <= (float)PHYS_TOUCH) { if (fabsf(bnv) <= C_CONTACTVEL) { hittime = 0; isContact = true; } else if (bnd <= 0) hittime = 0; // zero time for rigid fast bodies else hittime = bnd / -bnv; } else if (fabsf(bnv) > C_LOWNORMVEL ) // not velocity low? hittime = bnd / -bnv; // rate ok for safe divide else return -1.0f; // wait for touching if (infNaN(hittime) || hittime < 0 || hittime > dtime) return -1.0f; // time is outside this frame ... no collision hitPos += hittime * pball->m_vel; // advance hit point to contact // check if hitPos is within the triangle // Compute vectors const Vertex3Ds v0 = m_rgv[2] - m_rgv[0]; const Vertex3Ds v1 = m_rgv[1] - m_rgv[0]; const Vertex3Ds v2 = hitPos - m_rgv[0]; // Compute dot products const float dot00 = v0.Dot(v0); const float dot01 = v0.Dot(v1); const float dot02 = v0.Dot(v2); const float dot11 = v1.Dot(v1); const float dot12 = v1.Dot(v2); // Compute barycentric coordinates const float invDenom = 1.0f / (dot00 * dot11 - dot01 * dot01); const float u = (dot11 * dot02 - dot01 * dot12) * invDenom; const float v = (dot00 * dot12 - dot01 * dot02) * invDenom; // Check if point is in triangle const bool pointInTri = (u >= 0.f) && (v >= 0.f) && (u + v <= 1.f); if (pointInTri) { coll.hitnormal = normal; coll.hitdistance = bnd; // 3dhit actual contact distance ... //coll.hitRigid = true; // collision type if (isContact) { coll.isContact = true; coll.hitvelocity.z = bnv; } return hittime; } else return -1.0f; }
float LineSeg::HitTestBasic(const Ball * pball, const float dtime, CollisionEvent& coll, const bool direction, const bool lateral, const bool rigid) { if (!m_fEnabled || pball->m_frozen) return -1.0f; const float ballvx = pball->m_vel.x; // ball velocity const float ballvy = pball->m_vel.y; const float bnv = ballvx*normal.x + ballvy*normal.y; // ball velocity normal to segment, positive if receding, zero=parallel bool bUnHit = (bnv > C_LOWNORMVEL); if (direction && (bnv > C_CONTACTVEL)) // direction true and clearly receding from normal face return -1.0f; const float ballx = pball->m_pos.x; // ball position const float bally = pball->m_pos.y; // ball normal distance: contact distance normal to segment. lateral contact subtract the ball radius const float rollingRadius = lateral ? pball->m_radius : C_TOL_RADIUS; //lateral or rolling point const float bcpd = (ballx - v1.x)*normal.x + (bally - v1.y)*normal.y; // ball center to plane distance const float bnd = bcpd - rollingRadius; const bool inside = (bnd <= 0.f); // in ball inside object volume float hittime; if (rigid) { if ((bnd < -pball->m_radius/**2.0f*/) || (lateral && bcpd < 0.f)) return -1.0f; // (ball normal distance) excessive pentratration of object skin ... no collision HACK //!! *2 necessary? if (lateral && (bnd <= (float)PHYS_TOUCH)) { if (inside || (fabsf(bnv) > C_CONTACTVEL) // fast velocity, return zero time // zero time for rigid fast bodies || (bnd <= (float)(-PHYS_TOUCH))) hittime = 0; // slow moving but embedded else hittime = bnd*(float)(1.0/(2.0*PHYS_TOUCH)) + 0.5f; // don't compete for fast zero time events } else if (fabsf(bnv) > C_LOWNORMVEL) // not velocity low ???? hittime = bnd/(-bnv); // rate ok for safe divide else return -1.0f; // wait for touching } else //non-rigid ... target hits { if (bnv * bnd >= 0.f) // outside-receding || inside-approaching { if ((m_ObjType != eTrigger) || // no a trigger (!pball->m_vpVolObjs) || (fabsf(bnd) >= pball->m_radius*0.5f) || // not too close ... nor too far away (inside != (pball->m_vpVolObjs->IndexOf(m_pObj) < 0))) // ...ball outside and hit set or ball inside and no hit set return -1.0f; hittime = 0; bUnHit = !inside; // ball on outside is UnHit, otherwise it's a Hit } else hittime = bnd/(-bnv); } if (infNaN(hittime) || hittime < 0.f || hittime > dtime) return -1.0f; // time is outside this frame ... no collision const float btv = ballvx*normal.y - ballvy*normal.x; // ball velocity tangent to segment with respect to direction from V1 to V2 const float btd = (ballx - v1.x)*normal.y - (bally - v1.y)*normal.x // ball tangent distance + btv * hittime; // ball tangent distance (projection) (initial position + velocity * hitime) if (btd < -C_TOL_ENDPNTS || btd > length + C_TOL_ENDPNTS) // is the contact off the line segment??? return -1.0f; if (!rigid) // non rigid body collision? return direction coll.hitvelocity.x = bUnHit ? 1.0f : 0.0f; // UnHit signal is receding from outside target const float ballr = pball->m_radius; const float hitz = pball->m_pos.z - ballr + pball->m_vel.z*hittime; // check too high or low relative to ball rolling point at hittime if (hitz + ballr * 1.5f < m_rcHitRect.zlow // check limits of object's height and depth || hitz + ballr * 0.5f > m_rcHitRect.zhigh) return -1.0f; coll.hitnormal.x = normal.x; // hit normal is same as line segment normal coll.hitnormal.y = normal.y; coll.hitnormal.z = 0.0f; coll.hitdistance = bnd; // actual contact distance ... //coll.hitRigid = rigid; // collision type // check for contact if (fabsf(bnv) <= C_CONTACTVEL && fabsf(bnd) <= (float)PHYS_TOUCH) { coll.isContact = true; coll.hitvelocity.z = bnv; } return hittime; }
float HitPoint::HitTest(const Ball * pball, float dtime, CollisionEvent& coll) { if (!m_fEnabled) return -1.0f; const Vertex3Ds dist = pball->m_pos - m_p; // relative ball position const float bcddsq = dist.LengthSquared(); // ball center to line distance squared const float bcdd = sqrtf(bcddsq); // distance ball to line if (bcdd <= 1.0e-6f) return -1.0f; // no hit on exact center const float b = dist.Dot(pball->m_vel); const float bnv = b/bcdd; // ball normal velocity if (bnv > C_CONTACTVEL) return -1.0f; // clearly receding from radius const float bnd = bcdd - pball->m_radius; // ball distance to line const float a = pball->m_vel.LengthSquared(); float hittime = 0; bool isContact = false; if (bnd < (float)PHYS_TOUCH) // already in collision distance? { if (fabsf(bnv) <= C_CONTACTVEL) { isContact = true; hittime = 0; } else hittime = std::max(0.0f, -bnd / bnv); // estimate based on distance and speed along distance } else { if (a < 1.0e-8f) return -1.0f; // no hit - ball not moving relative to object float time1, time2; if (!SolveQuadraticEq(a, 2.0f*b, bcddsq - pball->m_radius*pball->m_radius, time1, time2)) return -1.0f; hittime = (time1*time2 < 0) ? max(time1,time2) : min(time1,time2); // find smallest nonnegative solution } if (infNaN(hittime) || hittime < 0 || hittime > dtime) return -1.0f; // contact out of physics frame const Vertex3Ds hitPos = pball->m_pos + hittime * pball->m_vel; coll.hitnormal = hitPos - m_p; coll.hitnormal.Normalize(); coll.isContact = isContact; if (isContact) coll.hitvelocity.z = bnv; coll.hitdistance = bnd; // actual contact distance //coll.hitRigid = true; return hittime; }
float HitLineZ::HitTest(const Ball * pball, float dtime, CollisionEvent& coll) { if (!m_fEnabled) return -1.0f; const Vertex2D bp2d(pball->m_pos.x, pball->m_pos.y); const Vertex2D dist = bp2d - m_xy; // relative ball position const Vertex2D dv(pball->m_vel.x, pball->m_vel.y); const float bcddsq = dist.LengthSquared(); // ball center to line distance squared const float bcdd = sqrtf(bcddsq); // distance ball to line if (bcdd <= 1.0e-6f) return -1.0f; // no hit on exact center const float b = dist.Dot(dv); const float bnv = b/bcdd; // ball normal velocity if (bnv > C_CONTACTVEL) return -1.0f; // clearly receding from radius const float bnd = bcdd - pball->m_radius; // ball distance to line const float a = dv.LengthSquared(); float hittime = 0; bool isContact = false; if (bnd < (float)PHYS_TOUCH) // already in collision distance? { if (fabsf(bnv) <= C_CONTACTVEL) { isContact = true; hittime = 0; } else hittime = std::max(0.0f, -bnd / bnv); // estimate based on distance and speed along distance } else { if (a < 1.0e-8f) return -1.0f; // no hit - ball not moving relative to object float time1, time2; if (!SolveQuadraticEq(a, 2.0f*b, bcddsq - pball->m_radius*pball->m_radius, time1, time2)) return -1.0f; hittime = (time1*time2 < 0) ? max(time1,time2) : min(time1,time2); // find smallest nonnegative solution } if (infNaN(hittime) || hittime < 0 || hittime > dtime) return -1.0f; // contact out of physics frame const float hitz = pball->m_pos.z + hittime * pball->m_vel.z; // ball z position at hit time if (hitz < m_zlow || hitz > m_zhigh) // check z coordinate return -1.0f; const float hitx = pball->m_pos.x + hittime * pball->m_vel.x; // ball x position at hit time const float hity = pball->m_pos.y + hittime * pball->m_vel.y; // ball y position at hit time Vertex2D norm(hitx - m_xy.x, hity - m_xy.y); norm.Normalize(); coll.hitnormal.Set(norm.x, norm.y, 0.0f); coll.isContact = isContact; if (isContact) coll.hitvelocity.z = bnv; coll.hitdistance = bnd; // actual contact distance //coll.hitRigid = true; return hittime; }
float HitCircle::HitTestBasicRadius(const Ball * pball, float dtime, CollisionEvent& coll, bool direction, bool lateral, bool rigid) { if (!m_fEnabled || pball->m_frozen) return -1.0f; Vertex3Ds c(center.x, center.y, 0.0f); Vertex3Ds dist = pball->m_pos - c; // relative ball position Vertex3Ds dv = pball->m_vel; float targetRadius; bool capsule3D; if (!lateral && pball->m_pos.z > zhigh) { capsule3D = true; // handle ball over target? //const float hcap = radius*(float)(1.0/5.0); // cap height to hit-circle radius ratio //targetRadius = radius*radius/(hcap*2.0f) + hcap*0.5f; // c = (r^2+h^2)/(2*h) targetRadius = radius*(float)(13.0/5.0); // optimized version of above code //c.z = zhigh - (targetRadius - hcap); // b = c - h c.z = zhigh - radius*(float)(12.0/5.0); // optimized version of above code dist.z = pball->m_pos.z - c.z; // ball rolling point - capsule center height } else { capsule3D = false; targetRadius = radius; if (lateral) targetRadius += pball->m_radius; dist.z = dv.z = 0.0f; } const float bcddsq = dist.LengthSquared(); // ball center to circle center distance ... squared const float bcdd = sqrtf(bcddsq); // distance center to center if (bcdd <= 1.0e-6f) return -1.0f; // no hit on exact center const float b = dist.Dot(dv); const float bnv = b/bcdd; // ball normal velocity if (direction && bnv > C_LOWNORMVEL) return -1.0f; // clearly receding from radius const float bnd = bcdd - targetRadius; // ball normal distance to const float a = dv.LengthSquared(); float hittime = 0; bool fUnhit = false; bool isContact = false; // Kicker is special.. handle ball stalled on kicker, commonly hit while receding, knocking back into kicker pocket if (m_ObjType == eKicker && bnd <= 0 && bnd >= -radius && a < C_CONTACTVEL*C_CONTACTVEL ) { if (pball->m_vpVolObjs) pball->m_vpVolObjs->RemoveElement(m_pObj); // cause capture } if (rigid && bnd < (float)PHYS_TOUCH) // positive: contact possible in future ... Negative: objects in contact now { if (bnd < -pball->m_radius/**2.0f*/) //!! *2 necessary? return -1.0f; else if (fabsf(bnv) <= C_CONTACTVEL) { isContact = true; hittime = 0; } else hittime = std::max(0.0f, -bnd / bnv); // estimate based on distance and speed along distance } else if (m_ObjType >= eTrigger // triggers & kickers && pball->m_vpVolObjs && ((bnd < 0.f) == (pball->m_vpVolObjs->IndexOf(m_pObj) < 0))) { // here if ... ball inside and no hit set .... or ... ball outside and hit set if (fabsf(bnd-radius) < 0.05f) // if ball appears in center of trigger, then assumed it was gen'ed there { if (pball->m_vpVolObjs) pball->m_vpVolObjs->AddElement(m_pObj); //special case for trigger overlaying a kicker } // this will add the ball to the trigger space without a Hit else { hittime = 0; fUnhit = (bnd > 0.f); // ball on outside is UnHit, otherwise it's a Hit } } else { if((!rigid && bnd * bnv > 0.f) || // (outside and receding) or (inside and approaching) (a < 1.0e-8f)) return -1.0f; // no hit ... ball not moving relative to object float time1, time2; if (!SolveQuadraticEq(a, 2.0f*b, bcddsq - targetRadius*targetRadius, time1, time2)) return -1.0f; fUnhit = (time1*time2 < 0.f); hittime = fUnhit ? max(time1,time2) : min(time1,time2); // ball is inside the circle } if (infNaN(hittime) || hittime < 0.f || hittime > dtime) return -1.0f; // contact out of physics frame const float hitz = pball->m_pos.z - pball->m_radius + pball->m_vel.z * hittime; // rolling point if(((hitz + pball->m_radius *1.5f) < zlow) || (!capsule3D && (hitz + pball->m_radius*0.5f) > zhigh) || (capsule3D && (pball->m_pos.z + pball->m_vel.z * hittime) < zhigh)) return -1.0f; const float hitx = pball->m_pos.x + pball->m_vel.x*hittime; const float hity = pball->m_pos.y + pball->m_vel.y*hittime; const float sqrlen = (hitx - c.x)*(hitx - c.x) + (hity - c.y)*(hity - c.y); if (sqrlen > 1.0e-8f) // over center??? { // no const float inv_len = 1.0f/sqrtf(sqrlen); coll.hitnormal.x = (hitx - c.x)*inv_len; coll.hitnormal.y = (hity - c.y)*inv_len; coll.hitnormal.z = 0.0f; } else { // yes, over center coll.hitnormal.x = 0.0f; // make up a value, any direction is ok coll.hitnormal.y = 1.0f; coll.hitnormal.z = 0.0f; } if (!rigid) // non rigid body collision? return direction coll.hitvelocity.x = fUnhit ? 1.0f : 0.0f; // UnHit signal is receding from target coll.isContact = isContact; if (isContact) coll.hitvelocity.z = bnv; coll.hitdistance = bnd; //actual contact distance ... //coll.hitRigid = rigid; // collision type return hittime; }
float HitPlane::HitTest(const Ball * const pball, const float dtime, CollisionEvent& coll) const { if (!m_fEnabled) return -1.0f; //slintf("HitPlane test - %f %f\n", pball->m_pos.z, pball->m_vel.z); const float bnv = m_normal.Dot(pball->m_vel); // speed in normal direction if (bnv > C_CONTACTVEL) // return if clearly ball is receding from object return -1.0f; const float bnd = m_normal.Dot(pball->m_pos) - pball->m_radius - m_d; // distance from plane to ball surface if (bnd < pball->m_radius*-2.0f) //!! solely responsible for ball through playfield?? check other places, too (radius*2??) return -1.0f; // excessive penetration of plane ... no collision HACK float hittime; #ifdef NEW_PHYSICS bool isContact = false; // slow moving ball? then either contact or no collision at all if (bnd <= (float)PHYS_TOUCH) { if (fabsf(bnv) <= C_CONTACTVEL) { hittime = 0; isContact = true; } else if (bnd <= 0.f) hittime = 0; // zero time for rigid fast bodies else hittime = bnd / -bnv; } else if (fabsf(bnv) > C_LOWNORMVEL) // not velocity low? hittime = bnd / -bnv; // rate ok for safe divide else return -1.0f; // wait for touching #else if (fabsf(bnv) <= C_CONTACTVEL) { if (fabsf(bnd) <= (float)PHYS_TOUCH) { coll.m_isContact = true; coll.m_hitnormal = m_normal; coll.m_hit_org_normalvelocity = bnv; // remember original normal velocity coll.m_hitdistance = bnd; //coll.m_hitRigid = true; return 0.0f; // hittime is ignored for contacts } else return -1.0f; // large distance, small velocity -> no hit } hittime = bnd / (-bnv); // rate ok for safe divide if (hittime < 0.f) hittime = 0.0f; // already penetrating? then collide immediately #endif if (infNaN(hittime) || hittime < 0.f || hittime > dtime) return -1.0f; // time is outside this frame ... no collision coll.m_hitnormal = m_normal; coll.m_hitdistance = bnd; // actual contact distance //coll.m_hitRigid = true; // collision type #ifdef NEW_PHYSICS if (isContact) { coll.m_isContact = true; coll.m_hit_org_normalvelocity = bnv; // remember original normal velocity } #endif return hittime; }