Ray Intersections in OpenGL

I am trying to use ray intersections to perform mouse collection in OpenGL. I found several formulas on the Internet, and the last one I tried was suggested by the user on Stack Exchange:

Intersection beam-sphere

From what I understood from this answer, I check if the quadratic equation has positive roots. I don't care where the intersection occurs, only if the ray crosses the sphere at all. My code is as follows, but does not seem to work.

bool Mesh::useObject(vec3 camera, vec3 direction) {

    // a = (xB-xA)²+(yB-yA)²+(zB-zA)²
    float a = ((direction.v[0] - camera.v[0])*(direction.v[0] - camera.v[0])
        + (direction.v[1] - camera.v[1])*(direction.v[1] - camera.v[1])
        + (direction.v[2] - camera.v[2])*(direction.v[2] - camera.v[2]));

    // b = 2*((xB-xA)(xA-xC)+(yB-yA)(yA-yC)+(zB-zA)(zA-zC))
    float b = 2 * ((direction.v[0] - camera.v[0])*(camera.v[0] - mOrigin.v[0])
        + (direction.v[1] - camera.v[1])*(camera.v[1] - mOrigin.v[1])
        + (direction.v[2] - camera.v[2])*(camera.v[2] - mOrigin.v[2]));

    // c = (xA-xC)²+(yA-yC)²+(zA-zC)²-r²
    float c = ((camera.v[0] - mOrigin.v[0])*(camera.v[0] - mOrigin.v[0])
        + (camera.v[1] - mOrigin.v[1])*(camera.v[1] - mOrigin.v[1])
        + (camera.v[2] - mOrigin.v[2])*(camera.v[2] - mOrigin.v[2])
        - (mRadius)*(mRadius));

    float delta = (b*b) - (4 * a*c);

    if (delta < 0)
        return false;

    else {
        std::cout << "Object " << mMesh << " is at postion (" <<
            mOrigin.v[0] << ", " <<
            mOrigin.v[1] << ", " <<
            mOrigin.v[2] << ")\n" <<
            "Size: " << mRadius << std::endl;
        return true;
    }
}

My C ++ skills are pretty rusty, so I apologize if this is a terrible way to do this. This method takes two vectors of three floats, the position of the camera and the coordinates of the point in my scene, 1 unit in front of the camera (I called this direction).

, , , . , - (, , ), , .: (

, - , - . SO, , , .

EDIT: . .

+4
1

, , , P_ray0 Dir_ray, , P_centerS radius_S. , P_ray0 , Dir_ray .

, , , . , . , . , .


P_ray = dist * Dir_ray + P_ray0
dot( P_plane - P_plane0, NV_plane ) == 0:

P_isect = P_ray0 + Dir_ray * dist;
dist    = dot( P_plane0 - P_ray0, NV_plane ) / dot( Dir_ray, NV_plane )

NV_plane , wt , . , dot( Dir_ray, NV_plane ) == 1:

P_isect = P_ray0 + Dir_ray * dot( P_plane0 - P_ray0, NV_plane );

++ :

#include <math.h>

bool isectRraySphere( 
      const vec3 &P_ray0,
      const vec3 &Dir_ray,
      const vec3 &P_centerS,
      float       radius_S )
{
    // Normalize the Dir_ray of the ray, which is equal the normalvector of the plane.
    // Note, this can be skipped, if `directory` already is a unit vector (a vector with a length of 1.0).
    vec3 NV = normalize( Dir_ray );

    // Calculate the intersection point, using the above formula.
    vec3 P_isect = P_ray0 + NV * dot( P_centerS - P_ray0, NV );

      // Calculate the distance between the center of the sphere and the intersection point
    float isect_dist = length( P_isect - P_centerS );

    // comparet the intersection distance with the radius of the speher.
    bool isect = isect_dist < radius_S;

    return isect;
}

, , . , sqrt:

vec3 dv = P_isect - P_centerS;
bool isect = (dv[0]*dv[0] + dv[1]*dv[1] + dv[2]*dv[2]) < (radius_S * radius_S); 

. : glm.

using vec3 = std::array<float, 3>;
vec3 operator + (vec3 a, vec3 b) { return {a[0]+b[0], a[1]+b[1], a[2]+b[2]}; }
vec3 operator - (vec3 a, vec3 b) { return {a[0]-b[0], a[1]-b[1], a[2]-b[2]}; }
vec3 operator * (vec3 v, float d) { return {v[0]*d, v[1]*d, v[2]*d}; }
vec3 length(vec3 v) { return sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2] ); }
vec3 normalize(vec3 v) { float len = length(v); return {v[0]/len, v[1]/len, v[2]/len}; }
float dot(vec3 a, T_B b) { return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]; }
0

Source: https://habr.com/ru/post/1619713/


All Articles