Non-orthogonal Reflection
Non-orthogonal Reflection by Ira Greenberg.
Based on the equation (R = 2N(N*L)-L) where R is the reflection vector, N is the normal, and L is the incident vector.
// Position of left hand side of floor
PVector base1;
// Position of right hand side of floor
PVector base2;
// Length of floor
float baseLength;
// An array of subpoints along the floor path
PVector[] coords;
// Variables related to moving ball
PVector position;
PVector velocity;
float r = 6;
float speed = 3.5;
void setup() {
size(640, 360);
fill(128);
base1 = new PVector(0, height-150);
base2 = new PVector(width, height);
createGround();
// start ellipse at middle top of screen
position = new PVector(width/2, 0);
// calculate initial random velocity
velocity = PVector.random2D();
velocity.mult(speed);
}
void draw() {
// draw background
fill(0, 12);
noStroke();
rect(0, 0, width, height);
// draw base
fill(200);
quad(base1.x, base1.y, base2.x, base2.y, base2.x, height, 0, height);
// calculate base top normal
PVector baseDelta = PVector.sub(base2, base1);
baseDelta.normalize();
PVector normal = new PVector(-baseDelta.y, baseDelta.x);
// draw ellipse
noStroke();
fill(255);
ellipse(position.x, position.y, r*2, r*2);
// move elipse
position.add(velocity);
// normalized incidence vector
PVector incidence = PVector.mult(velocity, -1);
incidence.normalize();
// detect and handle collision
for (int i=0; i<coords.length; i++) {
// check distance between ellipse and base top coordinates
if (PVector.dist(position, coords[i]) < r) {
// calculate dot product of incident vector and base top normal
float dot = incidence.dot(normal);
// calculate reflection vector
// assign reflection vector to direction vector
velocity.set(2*normal.x*dot - incidence.x, 2*normal.y*dot - incidence.y, 0);
velocity.mult(speed);
// draw base top normal at collision point
stroke(255, 128, 0);
line(position.x, position.y, position.x-normal.x*100, position.y-normal.y*100);
}
}
// detect boundary collision
// right
if (position.x > width-r) {
position.x = width-r;
velocity.x *= -1;
}
// left
if (position.x < r) {
position.x = r;
velocity.x *= -1;
}
// top
if (position.y < r) {
position.y = r;
velocity.y *= -1;
// randomize base top
base1.y = random(height-100, height);
base2.y = random(height-100, height);
createGround();
}
}
// Calculate variables for the ground
void createGround() {
// calculate length of base top
baseLength = PVector.dist(base1, base2);
// fill base top coordinate array
coords = new PVector[ceil(baseLength)];
for (int i=0; i<coords.length; i++) {
coords[i] = new PVector();
coords[i].x = base1.x + ((base2.x-base1.x)/baseLength)*i;
coords[i].y = base1.y + ((base2.y-base1.y)/baseLength)*i;
}
}
Functions Used
draw()
Called directly after setup(), the draw() function continuously executes the lines of code contained inside its block until the program is stopped or noLoop() is called
Learn More
ceil()
Calculates the closest int value that is greater than or equal to the value of the parameter
Learn More
PVector
A class to describe a two or three dimensional vector, specifically a Euclidean (also known as geometric) vector
Learn More
Learn to Program