void CSprite::drawCentered() { draw(_x - getHalfWidth(), _y - getHalfHeight()); }
bool CapsuleShape::findRayIntersection(RayIntersectionInfo& intersection) const { // ray is U, capsule is V glm::vec3 axisV; computeNormalizedAxis(axisV); glm::vec3 centerV = getTranslation(); // first handle parallel case float uDotV = glm::dot(axisV, intersection._rayDirection); glm::vec3 UV = intersection._rayStart - centerV; if (glm::abs(1.0f - glm::abs(uDotV)) < EPSILON) { // line and cylinder are parallel float distanceV = glm::dot(UV, intersection._rayDirection); if (glm::length2(UV - distanceV * intersection._rayDirection) <= _radius * _radius) { // ray is inside cylinder's radius and might intersect caps return findRayIntersectionWithCaps(centerV, intersection); } return false; } // Given a line with point 'U' and normalized direction 'u' and // a cylinder with axial point 'V', radius 'r', and normalized direction 'v' // the intersection of the two is on the line at distance 't' from 'U'. // // Determining the values of t reduces to solving a quadratic equation: At^2 + Bt + C = 0 // // where: // // UV = U-V // w = u-(u.v)v // Q = UV-(UV.v)v // // A = w^2 // B = 2(w.Q) // C = Q^2 - r^2 glm::vec3 w = intersection._rayDirection - uDotV * axisV; glm::vec3 Q = UV - glm::dot(UV, axisV) * axisV; // we save a few multiplies by storing 2*A rather than just A float A2 = 2.0f * glm::dot(w, w); float B = 2.0f * glm::dot(w, Q); // since C is only ever used once (in the determinant) we compute it inline float determinant = B * B - 2.0f * A2 * (glm::dot(Q, Q) - _radius * _radius); if (determinant < 0.0f) { return false; } float hitLow = (-B - sqrtf(determinant)) / A2; float hitHigh = -(hitLow + 2.0f * B / A2); if (hitLow > hitHigh) { // re-arrange so hitLow is always the smaller value float temp = hitHigh; hitHigh = hitLow; hitLow = temp; } if (hitLow < 0.0f) { if (hitHigh < 0.0f) { // capsule is completely behind rayStart return false; } hitLow = hitHigh; } glm::vec3 p = intersection._rayStart + hitLow * intersection._rayDirection; float d = glm::dot(p - centerV, axisV); if (glm::abs(d) <= getHalfHeight()) { // we definitely hit the cylinder wall intersection._hitDistance = hitLow; intersection._hitNormal = glm::normalize(p - centerV - d * axisV); intersection._hitShape = const_cast<CapsuleShape*>(this); return true; } // ray still might hit the caps return findRayIntersectionWithCaps(centerV, intersection); }