/* Vertex.cpp * * Definition of the Vertex class. */ #include "Vertex.h" #include #include Vertex::Vertex(const Tuple& v1, const Tuple& color) : Obstruction(), v1_(v1), color_(color), litNormal_(), sumNormal_(), triCount_(0) { // Nothing (more) to do } Vertex::~Vertex() { // Nothing to do } /* addNormal * * Update the vertex's litNormal_ so that it represents the average of the * normals of the triangles connecting to it. */ void Vertex::addNormal(const Tuple& normal) { sumNormal_ += normal; triCount_++; litNormal_ = sumNormal_ / triCount_; } /* draw * * This is here just in case we ever decide to draw vertices. */ void Vertex::draw(bool light) const { (void)light; // Don't use lighting setting b/c there is nothing to draw } /* pathIntersect * * Determines if this vertex is on the given path and returns the Beta value, * (the percent of path completed before collision). */ const double Vertex::pathIntersect( const Path& path, double radius) const { /* Here we'll use the quadratic equation to determine if and where the ball * collides with the edge. Actually, we're checking whether the center * of the ball intersects a cyllinder about the x-axis with a radius * equal to the ball's radius plus a BUFFER. */ // Standardize input path to match standardized edge vertices Path sPath = path.translate(-v1_); // Define a few helpful variables to clarify the following code double x1 = sPath.endPos().x(); double y1 = sPath.endPos().y(); double z1 = sPath.endPos().z(); double x0 = sPath.begPos().x(); double y0 = sPath.begPos().y(); double z0 = sPath.begPos().z(); // Make sure the ball is moving if (x0 != x1 || y0 != y1 || z0 != z1) { // We'll fill this with the distance along the path where the ball // touches the buffer about the origin double beta; // If the ball starts in the buffer, collide instantly; otherwise // just collide when the ball reaches the buffer double r0 = sqrt(z0 * z0 + y0 * y0 + z0 * z0); if (r0 < radius + BUFFER) { // Define variables for the quadratic equation double a = (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0) + (z1 - z0) * (z1 - z0); double b = 2 * (x0 * (x1 - x0) + y0 * (y1 - y0) + z0 * (z1 - z0)); double c = x0 * x0 + y0 * y0 + z0 * z0 - radius * radius; // Check the determinant; if negative, then no collision double det = b * b - 4 * a * c; if (det >= 0.0) { // Collide no later than now (0.0) beta = min((-b - sqrt(det)) / (2 * a), 0.0); } else { // Add EPSILON to err on the safe side (no collision) beta = 1.0 + EPSILON; } } else { // Define variables for the quadratic equation double a = (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0) + (z1 - z0) * (z1 - z0); double b = 2 * (x0 * (x1 - x0) + y0 * (y1 - y0) + z0 * (z1 - z0)); double c = x0 * x0 + y0 * y0 + z0 * z0 - (radius + BUFFER) * (radius + BUFFER); // Check the determinant; if negative, then no collision double det = b * b - 4 * a * c; if (det >= 0.0) { // We only care about lowest beta, so consider only -sqrt(det) beta = (-b - sqrt(det)) / (2 * a); } else { // Add EPSILON to err on the safe side (no collision) beta = 1.0 + EPSILON; } } // Make sure beta is in range if (beta >= 0.0 && beta < 1.0) return beta; } // Add EPSILON to err on the safe side (no collision) return 1.0 + EPSILON; } /* calcNormal * * Returns the normal of the given vertex relative to a given point, which is * simply the direction of the line from the vertex through the point. */ const Tuple Vertex::calcNormal(const Tuple& point) const { return (point - v1_).norm(); }