bool colliderParticeCirclePeg(Ball &ball, Peg &peg, GLfloat time) { GLfloat sum_radii, sum_radii_sq, n_mag_sq; Point2f normal; normal = ball.position - peg.position; //GLfloat distance = normal.magitude(); sum_radii = ball.radius + peg.radius; sum_radii_sq = sum_radii * sum_radii; //std::cout << "x " << normal._x << std::endl; n_mag_sq = normal.squareMagnitude(); // std::cout << " n_maq_sq:" << sum_radii_sq << std::endl; // std::cout << "sum_radii_sq:" << sum_radii_sq << std::endl; if (n_mag_sq <= sum_radii_sq) { std::cout << "x " << normal._x << std::endl; normal.normalize(); std::cout << "normal x " << normal._x << std::endl; GLfloat velocityDotN = dotProduct(normal, ball.velocity); if(velocityDotN < 0) { ball.velocity._x -= 2.0f * velocityDotN * normal._x; ball.velocity._y -= 2.0f * velocityDotN * normal._y; ball.position._x += 2.0f * (sum_radii - peg.radius + ball.radius) * normal._x * time; ball.position._y += 2.0f * (sum_radii - peg.radius + ball.radius) * normal._y * time; } return true; } else { return false; } }
//Circle to Edge Collision Function aka Poly Collision for predicted_Trajectory bool Peg::polyPegCollision_p(Ball &ball) { GLfloat collisionDist = INFINITY; //bool isClosestEdge; //Variables for edge collision Point2f vecFromVert; Point2f tangent, normal; GLfloat tangentComponent, normalComponent, edgeLenght; //Variables for Corner collision int cornerIndex = -1, prevCornerIndex, nextCornerIndex; Point2f cornerNormal_1, cornerNormal_2; GLfloat cornerDist; //Variable for Rebound Point2f rebound; GLfloat orthogBallVelMag; GLfloat transPolyVelDotReb; //Calculate transformed co-ordinates from ball position Point2f orig(ball.position_p._x - position._x, ball.position_p._y - position._y); Point2f trans(cosf(rotation) * orig._x + sinf(rotation) * orig._y, - sinf(rotation) * orig._x + cosf(rotation) * orig._y); //Calculate transformed co-ordinates from ball velocity Point2f transVel(cosf(rotation) * ball.position_p._x + sinf(rotation) * ball.position_p._y, - sinf(rotation) * ball.position_p._x + cosf(rotation) * ball.position_p._y); //Calculate transformed co-ordinates from peg velocity...errr oh wait...it is zero!! Point2f zeroVeloc(0,0); Point2f transPegPolyVel(cosf(rotation) * zeroVeloc._x + sinf(rotation) * zeroVeloc._y, - sinf(rotation) * zeroVeloc._x + cosf(rotation) * zeroVeloc._y); if(type == circle) { rebound = trans; collisionDist = rebound.magnitude()- ball.radius - vertices[0].magnitude(); rebound.normalize(); } else { //check Edge collision for(int i = 0; i < subs; i++) { //isClosestEdge = false; //Calculate vectFromVert vecFromVert = trans - vertices[i]; //Calculate tangent between two vertices tangent = vertices[i+1] - vertices[i]; edgeLenght = tangent.magnitude(); tangent.normalize(); //calculate normal vector normal._x = tangent._y; normal._y = -tangent._x; //caluclate components tangentComponent = dotProduct(tangent, vecFromVert); normalComponent = dotProduct(normal, vecFromVert); if(normalComponent >= 0.0 && tangentComponent >= 0 && tangentComponent <= edgeLenght) { // isClosestEdge = true; collisionDist = normalComponent - ball.radius; rebound._x = normal._x; rebound._y = normal._y; } } } //if Edge don't collision and check corner collision if(collisionDist == INFINITY) { for(int i = 0; i < subs; i++) { Point2f cornerToBall; cornerToBall = trans - vertices[i]; cornerDist = cornerToBall.magnitude() - ball.radius; if(cornerDist < collisionDist) { cornerIndex = i; nextCornerIndex = i + 1; if(i == 0) prevCornerIndex = subs - 1; else prevCornerIndex = i - 1; collisionDist = cornerDist; cornerToBall.normalize(); rebound._x = cornerToBall._x; rebound._y = cornerToBall._y; //calculate cornerNomral_1 and cornerNomral_2 if(dotProduct(rebound, transVel) > 0.0) { //check a segment line from current corner and previous corner cornerNormal_1 = vertices[cornerIndex] - vertices[prevCornerIndex]; cornerNormal_1.normalize(); //check a segment line from current corner and next corner cornerNormal_2 = vertices[cornerIndex] - vertices[nextCornerIndex]; cornerNormal_2.normalize(); if(dotProduct(cornerNormal_1, transVel) < 0.0) { rebound = cornerNormal_1; } else if(dotProduct(cornerNormal_2, transVel) < 0.0) { rebound = cornerNormal_2; } else { rebound.reset(); collisionDist = INFINITY; } } } } //normalize rebound rebound.normalize(); } if(collisionDist > 0.0f) { return false; } else { //calcuate component that gets mirrored orthogBallVelMag= dotProduct(rebound, transVel); transVel._x -= 2.0f * orthogBallVelMag * rebound._x; transVel._y -= 2.0f * orthogBallVelMag * rebound._y; //calculate transVelocity transPolyVelDotReb = dotProduct(rebound, transPegPolyVel); transVel._x += transPolyVelDotReb * rebound._x; transVel._y += transPolyVelDotReb * rebound._y; //setting ball's velocity with new velocity ball.velocity_p._x = cosf(rotation) * transVel._x - sinf(rotation) * transVel._y; ball.velocity_p._y = sin(rotation) * transVel._x + cosf(rotation) * transVel._y; //relocation ball trans._x -= 2.0 * collisionDist * rebound._x; trans._y -= 2.0 * collisionDist * rebound._y; orig._x = cosf(rotation) * trans._x - sinf(rotation) * trans._y; orig._y = sinf(rotation) * trans._x + cosf(rotation) * trans._y; ball.position_p = orig + position; return true; } }
//Circle to Edge Collision Function aka Poly Collision bool Peg::polyPegCollision(Ball &ball, bool visualDebug) { GLfloat collisionDist = INFINITY; bool isClosestEdge; //Variables for edge collision Point2f vecFromVert; Point2f tangent, normal; GLfloat tangentComponent, normalComponent, edgeLenght; //Variables for Corner collision int cornerIndex = -1, prevCornerIndex, nextCornerIndex; Point2f cornerNormal_1, cornerNormal_2; GLfloat cornerDist; //Variable for Rebound Point2f rebound; GLfloat orthogBallVelMag; GLfloat transPolyVelDotReb; //Calculate transformed co-ordinates from ball position Point2f orig(ball.position._x - position._x, ball.position._y - position._y); Point2f trans(cosf(rotation) * orig._x + sinf(rotation) * orig._y, - sinf(rotation) * orig._x + cosf(rotation) * orig._y); //Calculate transformed co-ordinates from ball velocity Point2f transVel(cosf(rotation) * ball.velocity._x + sinf(rotation) * ball.velocity._y, - sinf(rotation) * ball.velocity._x + cosf(rotation) * ball.velocity._y); //Calculate transformed co-ordinates from peg velocity...errr oh wait...it is zero!! Point2f zeroVeloc(0,0); Point2f transPegPolyVel(cosf(rotation) * zeroVeloc._x + sinf(rotation) * zeroVeloc._y, - sinf(rotation) * zeroVeloc._x + cosf(rotation) * zeroVeloc._y); if(type == circle) { rebound = trans; collisionDist = rebound.magnitude()- (ball.radius * 2) - vertices[0].magnitude(); rebound.normalize(); } else { //check Edge collision for(int i = 0; i < subs; i++) { isClosestEdge = false; //Calculate vectFromVert vecFromVert = trans - vertices[i]; //Calculate tangent between two vertices tangent = vertices[i+1] - vertices[i]; edgeLenght = tangent.magnitude(); tangent.normalize(); //calculate normal vector normal._x = tangent._y; normal._y = -tangent._x; //caluclate components tangentComponent = dotProduct(tangent, vecFromVert); normalComponent = dotProduct(normal, vecFromVert); if(normalComponent >= 0.0 && tangentComponent >= 0 && tangentComponent <= edgeLenght) { isClosestEdge = true; collisionDist = normalComponent - ball.radius; rebound._x = normal._x; rebound._y = normal._y; } //Visual Debug if(visualDebug) { //highlight edge with teal color if closest Edge is choiced glPushMatrix(); if(isClosestEdge) glColor3f(0,1,1); else glColor3f(1,1,1); glTranslatef(position.getX(), position.getY(), 0.0); glRotatef(180.0f * rotation / PI_F, 0.0f, 0.0f, 1.0f); Point2f vertices1 = vertices[i];// + position; Point2f vertices2 = vertices[i+1];// + position; glBegin(GL_LINES); glVertex2f( vertices1._x, vertices1._y ); glVertex2f( vertices2._x, vertices2._y); glEnd(); glPopMatrix(); } } } //if Edge don't collision and check corner collision if(collisionDist == INFINITY) { for(int i = 0; i < subs; i++) { Point2f cornerToBall; cornerToBall = trans - vertices[i]; cornerDist = cornerToBall.magnitude() - ball.radius; if(cornerDist < collisionDist) { cornerIndex = i; nextCornerIndex = i + 1; if(i == 0) prevCornerIndex = subs - 1; else prevCornerIndex = i - 1; collisionDist = cornerDist; cornerToBall.normalize(); rebound._x = cornerToBall._x; rebound._y = cornerToBall._y; //calculate cornerNomral_1 and cornerNomral_2 if(dotProduct(rebound, transVel) > 0.0) { //check a segment line from current corner and previous corner cornerNormal_1 = vertices[cornerIndex] - vertices[prevCornerIndex]; cornerNormal_1.normalize(); //check a segment line from current corner and next corner cornerNormal_2 = vertices[cornerIndex] - vertices[nextCornerIndex]; cornerNormal_2.normalize(); if(dotProduct(cornerNormal_1, transVel) < 0.0) { rebound = cornerNormal_1; } else if(dotProduct(cornerNormal_2, transVel) < 0.0) { rebound = cornerNormal_2; } else { rebound.reset(); collisionDist = INFINITY; } } } } //normalize rebound rebound.normalize(); //visual Debug Mode if(visualDebug) { glPushMatrix(); glTranslatef(position.getX(), position.getY(), 0.0); glRotatef(180.0f * rotation / PI_F, 0.0f, 0.0f, 1.0f); glColor3f(1,0,0); glPointSize(3); glBegin(GL_POINTS); glVertex2f( vertices[cornerIndex]._x, vertices[cornerIndex]._y); glEnd(); glPopMatrix(); } } if(collisionDist > 0.0f) { return false; } else { //calcuate component that gets mirrored orthogBallVelMag= dotProduct(rebound, transVel); transVel._x -= 2.0f * orthogBallVelMag * rebound._x; transVel._y -= 2.0f * orthogBallVelMag * rebound._y; //calculate transVelocity transPolyVelDotReb = dotProduct(rebound, transPegPolyVel); transVel._x += transPolyVelDotReb * rebound._x; transVel._y += transPolyVelDotReb * rebound._y; //setting ball's velocity with new velocity ball.velocity._x = cosf(rotation) * transVel._x - sinf(rotation) * transVel._y; ball.velocity._y = sin(rotation) * transVel._x + cosf(rotation) * transVel._y; //relocation ball trans._x -= 2.0 * collisionDist * rebound._x; trans._y -= 2.0 * collisionDist * rebound._y; orig._x = cosf(rotation) * trans._x - sinf(rotation) * trans._y; orig._y = sinf(rotation) * trans._x + cosf(rotation) * trans._y; ball.position = orig + position; return true; } }