3
\$\begingroup\$

I'm trying to reflect a ray of a triangle using Processing and not sure I got the code right. I'm using two bits of pseudo code from two locations:

  1. Intersection of a Line with a Plane from Paul Bourke's site.
  2. Reflecting a vector from 3DKingdoms site.

Here's my code so far:

PVector[] face = new PVector[3];
float ai = TWO_PI/3;//angle increment
float r  = 300;//overall radius
float ro = 150;//random offset

PVector n;//normal
Ray r1;

void setup(){
  size(500,500,P3D);
  for(int i = 0 ; i < 3; i++) face[i] = new PVector(cos(ai * i) * r + random(ro),random(-50,50),sin(ai * i) * r + random(ro));
  r1 = new Ray(new PVector(-100,-200,-300),new PVector(100,200,300));
}
void draw(){
  background(255);
  lights();
  translate(width/2, height/2,-500);
  rotateX(map(mouseY,0,height,-PI,PI));
  rotateY(map(mouseX,0,width,-PI,PI));
  //draw plane
  beginShape(TRIANGLES);
  for(PVector p : face) vertex(p.x,p.y,p.z);
  endShape();
  //normals
  PVector c = new PVector();//centroid
  for(PVector p : face) c.add(p);
  c.div(3.0);
  PVector cb = PVector.sub(face[2],face[1]);
  PVector ab = PVector.sub(face[0],face[1]);
  n = cb.cross(ab);//compute normal
  line(c.x,c.y,c.z,n.x,n.y,n.z);//draw normal

  pushStyle();
  //http://paulbourke.net/geometry/planeline/
  //line to plane intersection u = N dot ( P3 - P1 ) / N dot (P2 - P1), P = P1 + u (P2-P1), where P1,P2 are on the line and P3 is a point on the plane
  PVector P2SubP1 = PVector.sub(r1.end,r1.start);
  PVector P3SubP1 = PVector.sub(face[0],r1.start);
  float u = n.dot(P3SubP1) / n.dot(P2SubP1);
  PVector P = PVector.add(r1.start,PVector.mult(P2SubP1,u));
  strokeWeight(5);
  point(P.x,P.y,P.z);//point of ray-plane intersection

  //vector reflecting http://www.3dkingdoms.com/weekly/weekly.php?a=2
  //R = 2*(V dot N)*N - V
  //Vnew = -2*(V dot N)*N + V
  //PVector V = PVector.sub(r1.start,r1.end);
  PVector V = PVector.sub(r1.start,P);
  PVector R = PVector.sub(PVector.mult(n,3 * (V.dot(n))),V);
  strokeWeight(1);
  stroke(0,192,0);
  line(P.x,P.y,P.z,R.x,R.y,R.z);
  stroke(192,0,0);
  line(r1.start.x,r1.start.y,r1.start.z,P.x,P.y,P.z);
  stroke(0,0,192);
  line(P.x,P.y,P.z,r1.end.x,r1.end.y,r1.end.z);
  popStyle();

}
void keyPressed(){   setup();  }//reset
class Ray{
  PVector start = new PVector(),end = new PVector();
  Ray(PVector s,PVector e){   start = s ; end = e;  }
}

I've tried to keep it simple and comment it. Still, the reflected vector (drawn in green) doesn't seem to be quite right:

reflect 1 reflect 2

I'm not sure if the reflected vector should meet the normal. Should I normalize/scale some vectors at some point?

\$\endgroup\$
  • \$\begingroup\$ It definitely looks wrong, but it could be due to 3D perspective. The reflected vector only meets a normal (I guess you mean the one raising from the centre of the shape) by coincidence. 3dkingdoms having picked an example so close to 45° is an unfortunate decision, makes it hard to see what is supposed to happen. \$\endgroup\$ – ANeves wants peace for Monica Mar 15 '12 at 9:53
  • \$\begingroup\$ Are you confident about the mathematical formulas being right? I tried looking at it, but it's been a while since I thought about vectors and don't want to get it wrong... so I'll pass. In 2D, a ray with incidence angle of N° reflects with a (180-N)° angle: it is mirrored through a perpendicular to the reflector line, this perpendicular raising from the point of incidence. I think the 3D version can be reduced to a 2D problem if you constrain it to the plane including the ray and the normal raising from the incidence point. \$\endgroup\$ – ANeves wants peace for Monica Mar 15 '12 at 9:57
4
\$\begingroup\$

Turns out I needed to normalize the normal first:

n.normalize();

full code for reference:

PVector[] face = new PVector[3];
float ai = TWO_PI/3;//angle increment
float r  = 300;//overall radius
float ro = 150;//random offset

PVector n;//normal
Ray r1;

void setup() {
  size(500, 500, P3D);
  for (int i = 0 ; i < 3; i++) face[i] = new PVector(cos(ai * i) * r + random(ro), random(-50, 50), sin(ai * i) * r + random(ro));
  r1 = new Ray(new PVector(-100, -200, -300), new PVector(100, 200, 300));
}
void draw() {
  background(255);
  lights();
  translate(width/2, height/2, -500);
  rotateX(map(mouseY, 0, height, -PI, PI));
  rotateY(map(mouseX, 0, width, -PI, PI));
  //draw plane
  beginShape(TRIANGLES);
  for (PVector p : face) vertex(p.x, p.y, p.z);
  endShape();
  //normals
  PVector c = new PVector();//centroid
  for (PVector p : face) c.add(p);
  c.div(3.0);
  PVector cb = PVector.sub(face[2], face[1]);
  PVector ab = PVector.sub(face[0], face[1]);
  n = cb.cross(ab);//compute normal
  n.normalize();
  line(c.x, c.y, c.z, n.x, n.y, n.z);//draw normal

  pushStyle();
  //http://paulbourke.net/geometry/planeline/
  //line to plane intersection u = N dot ( P3 - P1 ) / N dot (P2 - P1), P = P1 + u (P2-P1), where P1,P2 are on the line and P3 is a point on the plane
  PVector P2SubP1 = PVector.sub(r1.end, r1.start);
  PVector P3SubP1 = PVector.sub(face[0], r1.start);
  float u = n.dot(P3SubP1) / n.dot(P2SubP1);
  PVector P = PVector.add(r1.start, PVector.mult(P2SubP1, u));
  strokeWeight(5);
  point(P.x, P.y, P.z);//point of ray-plane intersection

  //vector reflecting http://www.3dkingdoms.com/weekly/weekly.php?a=2
  //R = 2*(V dot N)*N - V
  //Vnew = -2*(V dot N)*N + V
  //PVector V = PVector.sub(r1.start,r1.end);
  PVector V = PVector.sub(r1.start, P);
  PVector R = PVector.sub(PVector.mult(n, 2 * (V.dot(n))), V);
  strokeWeight(1);
  stroke(0, 192, 0);
  line(P.x, P.y, P.z, R.x, R.y, R.z);
  stroke(192, 0, 0);
  line(r1.start.x, r1.start.y, r1.start.z, P.x, P.y, P.z);
  stroke(0, 0, 192);
  line(P.x, P.y, P.z, r1.end.x, r1.end.y, r1.end.z);
  popStyle();
}
void keyPressed() {   
  setup();
}//reset
class Ray {
  PVector start = new PVector(), end = new PVector();
  Ray(PVector s, PVector e) {   
    start = s ; 
    end = e;
  }
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.