ofxRaycaster icon indicating copy to clipboard operation
ofxRaycaster copied to clipboard

Plane, 2D and 3D Ray objects for openFrameworks.It checks for the intersection of a ray with a segment, a sphere, a triangle, a plane, an ofPrimitive, an ofPolyline an with an ofMesh.

ofxRaycaster

Build status Build status

Donation:

If you find this project useful please consider a donation.

paypal

Table of Contents

How to use it

Methods for 2D and 3D rays

2D Intersection Methods

3D Intersection Methods

Mouse Picker

Showcase

img

This addon contains a definition of a ray in 2D and 3D dimension, and it includes methods to check the intersection with segments, spheres, triangles, planes, ofPrimitive, ofPolyline and ofMesh.

How to use it:

Download this addon in your addons folder. Create a new project with the project generator and add as addon ofxRaycaster. In your project, add at the top of your ofApp.h file

#include "ofxRaycaster.h"

To get started using a 2D ray in your project, declare a ray variable in your ofApp.h header file:

ofxraycaster::Ray2D ray;

If you want to use a 3D ray, declare the ray like this.

ofxraycaster::Ray ray;

Generic methods, for both 2D and 3D rays:

setup

void setup(glm::vec2 origin, glm::vec2 direction)

Set the origin and direction of a ray. For example, for a 2D ray:

ray.setup(glm::vec2(10,5), glm::vec2(1,0));

getOrigin

glm::vec2 getOrigin();

Return the origin of the vector. For example, for the 2D ray previously greated:

ray.getOrigin(); // returns glm::vec2(10,5)

getDirection

glm::vec2 getDirection();

Return the direction of the vector. For example, for the 2D ray previously greated:

ray.getDirection(); // returns glm::vec2(1,0)

setOrigin

void setOrigin(glm::vec3 origin);

Set the origin of the ray;

setDirection

void setDirection(glm::vec2 _origin);

Set the direction of the ray;

draw

void draw(float radius = 20.);

Draw a red circle indicating the position and a blue line indicating the direction, useful when debugging. It accepts a parameter to scale the dimension of the line representing the direction.

2D intersection methods:

example-polyline-intersection example-segment-intersection
img img

intersectsPolyline

See example example-polyline-intersection

bool intersectsPolyline(const ofPolyline & poly, float & distance, glm::vec2& surfaceNormal);

Check the intersection between a ray and an ofPolyline. If there is an intersection, it stores in distance and surfaceNormal respectively the distance from the origin to the intersection point, and a 2D normal of the segment of the polyline hit by the ray.

ofxraycaster::Ray2D ray;
ofPolyline poly;

glm::vec2 surfaceNormal; // store the intersection value
float distance; // store the intersection value

if (ray.intersectsPolyline(poly, distance, surfaceNormal)) {
    glm::vec2 intersection = ray.getOrigin() + ray.getDirection() * distance;
    ofDrawLine(ray.getOrigin(), intersection);
}

intersectsSegment

See example example-segment-intersection

bool intersectsSegment(const glm::vec2 & a, const glm::vec2 & b, float & distance)

Check the intersection between a ray and a segment. If there is an intersection, it stores in the variable distance the distance from the origin to the intersection point.

ofxraycaster::Ray2D ray;
auto a = glm::vec2(10, 30);
auto b = glm::vec2(50, 50);
// the segment goes from point a to point b

float distance; // store the intersection value

if (ray.intersectsSegment(a, b, distance)) {
    glm::vec2 intersection = ray.getOrigin() + ray.getDirection() * distance;
    ofDrawLine(ray.getOrigin(), intersection);
}

3D intersection methods:

example-multiple-rays example-mesh-intersection example-3D
img img img

intersectsTriangle

Check the intersection between a ray and a triangle. See example-3D.

bool intersectsTriangle(glm::vec3 const & vert0, glm::vec3 const & vert1, glm::vec3 const & vert2, glm::vec2 & baryPosition, float & distance)

intersectsSphere

Check the intersection between a ray and a sphere. See example-3D.

bool intersectsSphere(const glm::vec3 & _center, const float & _radius, glm::vec3& _position, glm::vec3 & _normal)

intersectsPrimitive

Check the intersection between a ray and an ofPrimitive. See example-3D.

bool intersectsPrimitive(const of3dPrimitive& primitive,  glm::vec2 & baricentricCoords, float & distance, glm::vec3 & intNormal)

intersectsPlane

Check the intersection between a ray and an ofxraycaster::Plane. See example-3D.

bool intersectsPlane(ofxraycaster::Plane plane, float & distance);

intersectsMesh

Check the intersection between a ray and a mesh. See example-mesh-intersection.

bool intersectsMesh(const ofMesh& mesh,  glm::vec2 & baricentricCoords, float & distance, glm::vec3 & intNormal);

Example:

void ofApp::draw(){
    cam.begin();
    mesh.draw();
    ray.draw();

    glm::vec2 baricentricCoordinates; // stores the barycentric coordinate of the triangle hit by the ray.
    float distance;
    glm::vec3 surfaceNormal; // stores the normal of the surface hit by the ray.
    bool intersects = ray.intersectsMesh(mesh, baricentricCoordinates, distance, surfaceNormal);

    // is there an intersection between the mesh and the ray?
    if (intersects) {
        auto intersection =
            ray.getOrigin() + ray.getDirection() * distance;
        // draw the ray hitting the mesh
        ofDrawLine(ray.getOrigin(), intersection);
        // draw the intersection point
        ofDrawSphere(intersection, 5);

        // draw the reflected light
        auto reflLight = glm::reflect(ray.getDirection(), surfaceNormal);
        ofDrawLine(intersection, intersection + 100 * reflLight);
    }
    cam.end();
}

When a glm::mat4 containing the transformation matrix of the mesh is given as second argument, it takes the transformation into account. See example-mesh-intersection.

bool intersectsMesh(const ofMesh& mesh, const glm::mat4& transformationMatrix,  glm::vec2 & baricentricCoords, float & distance, glm::vec3 & intNormal);

Mousepicker:

example-mousepicker
img

setFromCamera

void setFromCamera(const glm::vec2 mouseCoords, const ofCamera camera);

Set the origin and the direction of the ray giving as argument an ofCamera and the mouse coordinates. See example example-mousepicker.

draw

void draw(const float radius = 20);

Draw a sphere under the mouse.

getRay

Ray& getRay();

Return the 3D ray that goes from the camera towards the mouse.

Showcase:

This addon was used in the following projects:

If you want to add your project to this list, please open an issue.