I'm trying to render a dodecahedron triangle mesh and the triangles seem flipped or mirrored somehow. The first picture is what I should be getting, the second picture is what I'm getting and the last picture is if I only render the first triangle face of the mesh from the obj file. I'm attempting to use Barycentric coordinates and Cramer's rule to find the determinant and solve for beta, gamma, and t (the depth of the ray at the point of intersection). I think the mistake is in how I read in the triangle's vertices or how I build the other functions and compute the determinant.

enter image description here enter image description here enter image description here

This function is called during a loop of all the objects in a scene and compares the closest hit point found in the mesh to a global HitRecord (h) that was passed in and has a h.t parameter that has the depth (t) of the ray hit point of any other objects checked before the current mesh.

bool Mesh::hit(Ray r, HitRecord & h){
double closest_sofar = 0.0;
vec3 normal;
size_t size = m_faces.size();
for(int i = 0; i < size; ++i){
    Triangle t = m_faces[i];
    glm::vec3 a = m_vertices[t.v1];
    glm::vec3 b = m_vertices[t.v2];
    glm::vec3 c = m_vertices[t.v3];

    glm::vec3 answer = a - r.r_origin;
    vec3 A = a-b;
    vec3 B = a-c;
    vec3 D = r.r_direction;

    double det = dot(cross(A, B), D);
    if(det == 0.0 || det == -0.0) { continue; }

    double beta = dot(cross(answer, B), D) / det;
    double gamma = dot(cross(A, answer), D) / det;
    double closest = dot(cross(A, B), answer) / det;

    if((1.0 > beta > 0.0) &&
         (1.0 > gamma > 0.0) &&
         (1.0 > 1.0 - beta - gamma > 0.0) &&
         (closest_sofar == 0.0 || closest_sofar > closest > 0.0)){
        closest_sofar = closest;
        normal = normalize(cross(A, B));
    else { continue; }

  if(closest_sofar == 0.0) {
    return false; }
  if(h.t == 0.0 || closest_sofar < h.t){
    h.t = closest_sofar;
    h.normal = normal;
    return true;
  else{ return false; }
  • $\begingroup$ In C++ a<x<b evaluates to (a<x)<b, where the first expression is a true or false, so you get 0<b or 1<b. Instead you want a<x && x<b. It is also enough to check only 0<closest && closest<closest_so_far && 0<beta && 0<gamma && beta+gamma<1. $\endgroup$
    – lightxbulb
    Nov 27, 2021 at 9:42
  • $\begingroup$ thanks it was my a<x<b you were right! but I did need the closest_sofar == 0.0 || ... because closest_sofar gets initialized to 0.0 and will always be < the intersection point t without this check. Thanks again! $\endgroup$
    – Dodeca
    Nov 29, 2021 at 3:58
  • $\begingroup$ You can initialize closest_so_far to infinity, then you wouldn't need such checks. $\endgroup$
    – lightxbulb
    Nov 29, 2021 at 8:50


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Browse other questions tagged or ask your own question.