Loading...
Logo
Processing Forum
I've tried to do this with the Toxiclibs, but I got crazy results.

Has anyone had success finding the elevation of an X,Y point on a 3D triangle?  

Because I'm using landscapes forms it was easy to find the triangle/face that my Ray intersected – by flattening my mesh – but once I have the triangle, I'm not sure how I would actually find the elevation of a point somewhere within the 3D triangle.  

Seems like it could be a pretty easy thing to do if I understood normals better, but I've also seen a bunch of intense solutions on the web.

Any help would be greatly appreciated!

Thanks,

aufsess



Replies(3)

Here is some code testing the ToxicLibs library:

Copy code
  1. import toxi.geom.*; 
  2. import toxi.processing.*;
  3. import processing.opengl.*;
  4. import peasy.*;

  5. ToxiclibsSupport gfx;

  6. Triangle3D tri;
  7. Triangle2D tri2D;
  8. Ray3D rayDown;

  9. void setup() {
  10.   size(680, 382, OPENGL);
  11.   PeasyCam cam;
  12.   PMatrix3D currCameraMatrix;
  13.   cam = new PeasyCam(this, 500);

  14.   smooth();
  15.   textSize(9);
  16.   gfx=new ToxiclibsSupport(this);
  17.   tri = new Triangle3D(new Vec3D(20, 20, 20), new Vec3D(400, 200, 60), new Vec3D(200, 400, 0));
  18.   tri2D = new Triangle2D(toVec2D(tri.a), toVec2D(tri.b), toVec2D(tri.c));
  19.   rayDown = new Ray3D(200, 200, 400, new Vec3D(0, 0, -1));
  20. }

  21. void draw() {
  22.   background(255);

  23.   if (keyPressed) {
  24.     if (keyCode == UP) {
  25.       rayDown.y += 2;
  26.     }
  27.     if (keyCode == DOWN) {
  28.       rayDown.y-=2;
  29.     }
  30.     if (keyCode == RIGHT) {
  31.       rayDown.x+= 2;
  32.     }
  33.     if (keyCode == LEFT) {
  34.       rayDown.x-= 2;
  35.     }
  36.   }

  37.   TriangleIntersector tIntersect = new TriangleIntersector(tri);
  38.   tIntersect.intersectsRay(rayDown);
  39.   IsectData3D isec = tIntersect.getIntersectionData();
  40.   if (isec.isIntersection) {
  41.     stroke(255, 100, 192);
  42.     fill(255, 100, 192);
  43.     pushMatrix();
  44.     translate(isec.pos.x(), isec.pos.y(), isec.pos.z());
  45.     sphere(10);
  46.     popMatrix();
  47.     println("Intersecting");
  48.   }
  49.   else
  50.     fill (0, 255, 0);
  51.     
  52.   gfx.triangle(tri);
  53.   fill(0);
  54.   gfx.triangle(tri2D);
  55.   stroke(0, 150, 0);
  56.   gfx.ray(rayDown, 1000);
  57.   gfx.origin(new Vec3D(), 200);
  58. }

  59. Vec2D toVec2D(Vec3D vector) {
  60.   return new Vec2D(vector.x, vector.y);
  61. }
What is going wrong this example?  Maybe this part isn't fully implemented?

Thanks,

Aufsess
Yes it's implemented. Not sure if the fact that it seems to be checking against the plane instead of literally the triangle itself is intended. But anyway, it can be done using the code below.

Code Example
Copy code
  1. import toxi.geom.*;
  2. import toxi.processing.*;
  3. import processing.opengl.*;
  4. import peasy.*;
  5.  
  6. ToxiclibsSupport gfx;
  7.  
  8. Triangle3D tri;
  9. Triangle2D tri2D;
  10. Ray3D rayDown;
  11. TriangleIntersector tis;
  12.  
  13. void setup() {
  14.   size(800,400,OPENGL);
  15.   PeasyCam cam;
  16.   cam = new PeasyCam(this, 1000);
  17.   gfx = new ToxiclibsSupport(this);
  18.   tri = new Triangle3D(new Vec3D(0,0, 50), new Vec3D(600, 150, 180), new Vec3D(100, 500, 50));
  19.   tri2D = new Triangle2D(toVec2D(tri.a), toVec2D(tri.b), toVec2D(tri.c));
  20.   rayDown = new Ray3D(200,200,-500, new Vec3D(0, 0, 1));
  21.   tis = new TriangleIntersector(tri);
  22. }
  23.  
  24. void draw() {
  25.   background(255);
  26.  
  27.   noStroke();
  28.   fill(0,255,0);
  29.   gfx.triangle(tri);
  30.  
  31.   fill(0,0,255);
  32.   gfx.triangle(tri2D);
  33.  
  34.   stroke(0);
  35.   strokeWeight(3);
  36.   gfx.ray(rayDown, 1000);
  37.  
  38.   strokeWeight(1);
  39.   gfx.origin(500);
  40.  
  41.   // check if the ray is intersecting with the triangle's plane
  42.   if (tis.intersectsRay(rayDown)) {
  43.     // if so, get the intersection data
  44.     IsectData3D info = tis.getIntersectionData();
  45.     // specifically the position of intersection
  46.     Vec3D pos = (Vec3D) info.pos;
  47.     // check if that position is within the triangle (not just the triangle's plane)
  48.     if (tri.containsPoint(pos)) {
  49.       // if so, draw a sphere at that point
  50.       translate(pos.x,pos.y,pos.z);
  51.       noStroke();
  52.       fill(0);
  53.       sphere(25);
  54.     }
  55.   }
  56. }
  57.  
  58. void keyPressed() {
  59.   if (keyCode == UP)    { rayDown.y += 5; }
  60.   if (keyCode == DOWN)  { rayDown.y -= 5; }
  61.   if (keyCode == RIGHT) { rayDown.x += 5; }
  62.   if (keyCode == LEFT)  { rayDown.x -= 5; }
  63. }
  64.  
  65. Vec2D toVec2D(Vec3D vector) {
  66.   return new Vec2D(vector.x, vector.y);
  67. }
By the way, you were pretty close with your code, except you needed to change one line to get it running. Apart from the plane issue I mentioned and accounted for in my code example. Anyway, this was the necessary change for your code:
Copy code
  1.   rayDown = new Ray3D(200, 200, -400, new Vec3D(0, 0, 1));

This fixes it.  It was actually a minor error with Toxiclibs after all.  The updated Toxiclibs code also fixes the issue of having to check whether the ray is intersecting the plane or the actual triangle (Lines 47,49 above are not necessary with the updated code) – which was really stymying me.


Thanks!