Calculating specular reflection

Intro

This is an pexplanation on how to calculate this type of reflection:

It can be light bouncing off a mirror (or a ball bouncing perfectly off a surface, though it would behave physically unrealistically, on its own)

I did a quick search and I think it is referred to as specular reflection, in the case of light:

(Image by Zátonyi Sándor from Wikipedia — Laws of reflection)

I wanted to write an explanation for these projects:

Context

So I wanted to work out how to calculate bouncing like this from Lumosity:

The ball bounces off those white bumpers at 90 degree angles. But I wanted to make it work for any angle, not just 90°.

Overview

So this is how I was thinking of it:

If you measure from the normal (the line that is perpendicular or at a 90-degree angle to the surface), the size of the angle from the normal to the incoming ray, and from the normal to the outgoing ray would be the same:

(It would be the same size even if you happened to measure the larger angle between the normal and two rays — b, in this case)

(The 90°-turn would occur if the ball hit the bumper/surface at a 45° angle.)

Calculation

So, you can work out the normal by adding 90° to the rotation of the surface.

(It doesn’t matter whether you add or subtract 90, because the line of the perpendicular is the same, and, like I mentioned previously with the picture of a and b, it doesn’t matter which side of the normal that you choose to subtract the angle difference from — as long as you make the outgoing ray the same-sized angle, from the same normal)

So to actually work out the size of the angle a between the incident ray and the reflected ray, the incident ray needs to be turned around by 180° (remembering the original incident ray is going down, and to the right in this case, so subtracting that angle from the perpendicular would not be a):

So here is the size of angle a:


And to work out the outgoing ray’s angle, you just add that difference a, back to the normal, in order to get the outgoing angle on the other side of that normal:

image

Hope that helps to explain a bit. Feel free to add any info or let me know if this could be made clearer and easier to understand ^^

Additional note

If you are familiar with vectors, for this diagram, the angle is the same since the magnitude and direction of the horizontal translation is preserved, and the magnitude of the vertical translation is preserved (but opposite direction):

(But this modelling alone is physically unrealistic for the ball, as it would mean no kinetic energy is lost.)

Here is another explanation by @anisotr0py (using terms that are relative to the surface, and not just the specific case I mentioned where the surface is horizontal):

19 Likes

Cool might use it on one of my games

7 Likes

Cool Topic. I have also made a physics: reflection project a while ago…

7 Likes

Super helpful! Thanks!

5 Likes

Cool, this has a lot of writing.

3 Likes

Super helpful!

4 Likes

This is a cool write-up; thank you for taking the time to make it, and for making the great demo projects. Nice use of arctan btw; I wish HS had a two-argument arctan.

I encountered the same math problem when I was working on a pinball-ish game, and I ended up using 2D vectors (drawn like an arrow, represented as a pair of numbers) to compute bounces off surfaces of different angles.

The surface orientation can be be described (instead of with a single angle) as a “normal vector”- the unit length vector N that points away from the surface, and is perpendicular to the surface. We represent it with two variables as (Nx, Ny) since for now HS doesn’t have vector-valued variables. “Normal” vector is weird terminology but it comes from how “normal” can mean “perpendicular” in some communities. You if you know the angle A off the surface, then Nx = cos(A) and Ny = sin(A). If you have the angle of the surface itself you’ll want Nx = cos(A+90) and Ny = sin(A+90).

The velocity of a ball is another vector V or (Vx, Vy).

The basic idea is to consider the reflection in terms of the decomposition of V into two independent components, a part parallel to the surface (we could call it the tangential component), and other part perpendicular to the surface (the normal component). What it means to bounce is: flip the normal component. The tangential component stays the same (that’s the part not reflecting), the normal component changes sign (that’s the part that is reflecting). That’s all it is.

Happily, you don’t actually have to compute the tangent vector or the tangent component; you can do everything in terms of the normal component, because you can negate a value X by subtracting 2*X : X - 2*X == -X.

So, to bounce velocity (Vx,Vy) off surface with normal (Nx,Ny):

  1. Find the normal component as n == N•V == Nx*Vx + Ny*Vy (this is the “dot” product; when you dot with a unit-length vector you measure a component along that vector)
  2. subtract off 2*n*N from V:
    Vx = Vx - 2*n*Nx
    Vy = Vy - 2*n*Ny

And that’s it. If your game components are all expressed in terms of angles (like in the first demo project with light rays and the mirror you shared here) this may not end up being any easier to code. But if your game components are already expressed and computed in terms of vectors (like the motion of a ball) this might be more convenient.

Here is the incomplete game that uses this idea for all ball bounces.

9 Likes

Amazing tutorial! Lol… I was just studying this a few days ago

3 Likes

Thank you a lot for your in-depth post — I really appreciate the detail that you went into, and I could understand it clearly, even with having only briefly learned about vectors.

This describes the idea that I was trying to get at in the “additional note” section, in a way that I found clear to follow, so I think I would like to quote it in the original post!

This was new to me, about dot product with a unit-length vector (I couldn’t really remember what the dot product is used for ) so thank you for mentioning that part too.

I do think the method with vectors would be easier when coding a game like you did for Pinball (or I was also thinking Peggle) since I think it would also make it easier to include applying forces, like flippers or gravity^^

7 Likes