// This function handles the collision between the ray and the ground // Information about the interaction is passed in colEntry void World::ground_collide_handler(const CollisionEntry& colEntry) { // Set the ball to the appropriate Z value for it to be exactly on the ground NodePath renderNp = m_windowFrameworkPtr->get_render(); float newZ = colEntry.get_surface_point(renderNp).get_z(); m_ballRootNp.set_z(newZ + 0.4); // Find the acceleration direction. First the surface normal is crossed with // the up vector to get a vector perpendicular to the slope LVector3f norm = colEntry.get_surface_normal(renderNp); LVector3f accelSide = norm.cross(UP); // Then that vector is crossed with the surface normal to get a vector that // points down the slope. By getting the acceleration in 3D like this rather // than in 2D, we reduce the amount of error per-frame, reducing jitter m_accelV = norm.cross(accelSide); }
// This function handles the collision between the ball and a wall void World::wall_collide_handler(const CollisionEntry& colEntry) { // First we calculate some numbers we need to do a reflection NodePath renderNp = m_windowFrameworkPtr->get_render(); // The normal of the wall LVector3f norm = colEntry.get_surface_normal(renderNp) * -1; // The current speed float curSpeed = m_ballV.length(); // The direction of travel LVector3f inVec = m_ballV / curSpeed; // Angle of incidence float velAngle = norm.dot(inVec); LPoint3f hitDir = colEntry.get_surface_point(renderNp) - m_ballRootNp.get_pos(); hitDir.normalize(); // The angle between the ball and the normal float hitAngle = norm.dot(hitDir); // Ignore the collision if the ball is either moving away from the wall // already (so that we don't accidentally send it back into the wall) // and ignore it if the collision isn't dead-on (to avoid getting caught on // corners) if(velAngle > 0 && hitAngle > .995) { // Standard reflection equation LVector3f reflectVec = (norm * norm.dot(inVec * -1) * 2) + inVec; // This makes the velocity half of what it was if the hit was dead-on // and nearly exactly what it was if this is a glancing blow m_ballV = reflectVec * (curSpeed * (((1-velAngle)*.5)+.5)); // Since we have a collision, the ball is already a little bit buried in // the wall. This calculates a vector needed to move it so that it is // exactly touching the wall LPoint3f disp = (colEntry.get_surface_point(renderNp) - colEntry.get_interior_point(renderNp)); LPoint3f newPos = m_ballRootNp.get_pos() + disp; m_ballRootNp.set_pos(newPos); } }