I have a ray shot on the inside of an ellipse, it needs to reflect off of the ellipse and continue flying inside the ellipse. I've found that the easiest might be to find a tangent vector to the impact point and from there calculate the reflection angle.
Though I'm not sure how to implement this in code.
Here is what I have so far, I have the following function that draws the ellipse with its semi-major (a) and semi-minor (b) axes. t is incremented in an update function.
void drawEllipse(float t) {
float x = a * cos(t);
float y = b * sin(t);
PVector ellipseDotPosition = new PVector(x, y).add(ellipseCenter);
circle(ellipseDotPosition.x, ellipseDotPosition.y, 2);
}
I determine whether the ray has collided using this function:
boolean hasCollided(PVector pointToCheck) {
return pow((pointToCheck.x - ellipseCenter.x) / a, 2) +
pow((pointToCheck.y - ellipseCenter.y) / b, 2) > 1;
}
Here is how I've tried to calculate the reflection vector.
PVector getReflectionVector(PVector pointOfImpact) {
// Differentiate to get tangent to the collision point.
// PVector tangent = new PVector(-a / b * pointOfImpact.y, b / a * pointOfImpact.x);
// PVector tangent = new PVector(-(a * pointOfImpact.y / b), (b * pointOfImpact.x / a));
// circle(tangent.x, tangent.y, 10);
// Treat the tangent as the surface to be reflected off.
// Determine angle of reflection off the surface.
// Return reflection vector.
return new PVector();
}
Am I bad at math? Yes. Please help :)
Following what wikipedia says:
Analytically, the equation of a standard ellipse centered at the origin with width 2a and height 2b is:
Which, if we do its derivative (that returns its tangent at the point) results in:
The derivative only works for ellipses centered in (0, 0).
Also note that if y = 0, you will get an exception. This is because it would give infinity bacause the tangent is completly vertical.
To treat the tangent as the surface we will do the following steps explained at the code:
// OriginalRay will be the direction of the colliding ray.
// You may also define the origin as the last collision point.
PVector getReflectionVector(PVector pointOfImpact, PVector originalRay){
// Differentiate to get tangent to the collision point.
// atan() to get angle of tangent line from 0X
float tangentAngle;
if(pointOfImpact.y != 0){
float tangent = -1*pointOfImpact.x*sq(b)/(pointOfImpact.y*sq(a));
tangentAngle = atan(tangent);
}else{
tangentAngle = PI/2;
}
// Treat the tangent as the surface to be reflected off.
// Determine angle of reflection off the surface.
float rayAngle = atan2(originalRay.y, originalRay.x);
// We now transform the case as it had collided on an horizontal surfface to simplify.
//float tempRayAngle = rayAngle - tangentAngle;
// Calc the reflectionAngle
//float tempReflectionAngle = PI - tempRayAngle;
// And undo the transformation
//float newRayAngle = rayAngle - tempReflectionAngle;
float newRayAngle = 2*rayAngle - tangentAngle - PI; //End result
// Return reflection vector. (The direction vector with abs() = 1)
PVector reflectedRay = new PVector(cos(newRayAngle), sin(newRayAngle));
return reflectedRay;
}