Non orthogonal collision
These days I been solving the problem of the non orthogonal collision.
I needed to find a system that would let some balls bounce inside an irregular shape, and finally I found it in the book Processing Creative Coding and Computational Art written by Ira Greenberg, where Ira explains how to deal when we want to know the boundaries of a irregular shape (At the same time, Ira explanation and code is based on Keith Peter»s Solution in Foundation Actionscript Animation: Making Things Move!).
The code he explains can be seen here:
http://processing.org/learning/topics/reflection2.html
I modified the code a little bit, because I wanted a ball bouncing inside an irregular surface instead on top of a irregular surface. Moreover, I adapt that code to openframeworks.
Here is a video with both programs running (First processing and then openframeworks):
non orthogonal collision from berio on Vimeo.
This is the processing code, that as I said, it is based on Ira Greenberg one:
There are 4 files:
bounceInsideShape.pde (Main document):
PVector velocity;
float ptsx[] = {172, 209, 290, 380, 418, 409, 366, 303, 238, 190};
float ptsy[] = {162, 96, 58, 83, 154, 218, 274, 296, 279, 228};
Segment segments[] = new Segment[ptsx.length];
float pt1X = 100;
float pt1Y = 200;
float pt2X = 200;
float pt2Y = 100;
float mx = (pt1X + pt2X) / 2;
float my = (pt1Y + pt2Y) / 2;
float rot = atan2((pt2Y-pt1Y), (pt2X-pt1X));
Ball ball;
void setup(){
size(600, 350);
smooth();
ball = new Ball(220, 150, 3);
velocity = new PVector(2, -4);
for(int i=0; iif(i < ptsx.length-1){
segments[i] = new Segment(ptsx[i], ptsy[i], ptsx[i+1], ptsy[i+1]);
}else{
segments[i] = new Segment(ptsx[i], ptsy[i], ptsx[0], ptsy[0]);
}
}
}
void draw(){
noStroke();
fill(0, 15);
rect(0, 0, width, height);
ball.x += velocity.x;
ball.y += velocity.y;
checkWallCollision();
// ************************
// ** Check shape collision
// ************************
for(int i=0; ifloat deltax = ball.x - segments[i].x;
float deltay = ball.y - segments[i].y;
float cosine = cos(segments[i].rot);
float sine = sin(segments[i].rot);
float groundXTemp = cosine * deltax + sine * deltay;
float groundYTemp = cosine * deltay - sine * deltax;
float velocityXTemp = cosine * velocity.x + sine * velocity.y;
float velocityYTemp = cosine * velocity.y - sine * velocity.x;
if(segments[i].isOnTop()){
if(groundYTemp < ball.r &&
ball.x > segments[i].x1 &&
ball.x < segments[i].x2){
groundYTemp = ball.r;
velocityYTemp *= -1.0;
}
}else{
if(groundYTemp < ball.r &&
ball.x < segments[i].x1 &&
ball.x > segments[i].x2){
groundYTemp = ball.r;
velocityYTemp *= -1.0;
}
}
deltax = cosine * groundXTemp - sine * groundYTemp;
deltay = cosine * groundYTemp + sine * groundXTemp;
velocity.x = cosine * velocityXTemp - sine * velocityYTemp;
velocity.y = cosine * velocityYTemp + sine * velocityXTemp;
ball.x = segments[i].x + deltax;
ball.y = segments[i].y + deltay;
}
stroke(255);
for(int i=0; iline(segments[i].x1, segments[i].y1, segments[i].x2, segments[i].y2);
}
ellipse(ball.x, ball.y, ball.r*2, ball.r*2);
}
Ball.pde (Class):
class Ball{
float x, y, r;
Ball() {
}
Ball(float x, float y, float r){
this.x = x;
this.y = y;
this.r = r;
}
}
Segment.pde (Class):
class Segment{
float x, y;
float x1, y1, x2, y2;
float rot;
Segment(float _x1, float _y1, float _x2, float _y2){
x1 = _x1;
y1 = _y1;
x2 = _x2;
y2 = _y2;
x = (x1 + x2) / 2;
y = (y1 + y2) / 2;
rot = atan2((y2 - y1), (x2 - x1));
}
boolean isOnTop(){
if(x2 > x1){
return true;
}else{
return false;
}
}
}
checkWalls.pde (Functions):
void checkWallCollision(){
if (ball.x > width-ball.r){
ball.x = width-ball.r;
velocity.x *= -1;
// velocity.x *= damping;
}
else if (ball.x < ball.r){
ball.x = ball.r;
velocity.x *= -1;
// velocity.x *= damping;
}
else if(ball.y < ball.r){
ball.y = ball.r;
velocity.y *= -1;
}
else if(ball.y > height-ball.r){
ball.y = height-ball.r;
velocity.y *= -1;
}
}
Here you can download the openframeworks version: