#109 1 sided triangle polygon doesn't cast raytraced shadows.


Using simple triangle polygon and turning Sides to 1 - raytraced shadow is dissapear!

See example rib attached. If set Sides 2 - shadow is Ok.


  • Okan Arikan
    Okan Arikan

    Hi Sergey,

    I don't this is a bug. When sides = 1, the triangle will only be visible from front. The triangle is facing the camera, so it is visible to the camera. But the light source is hitting the triangle from behind so it is not visible to the light for shadows.

    Does this make sense?


  • Okan Arikan
    Okan Arikan

    • status: open --> open-invalid
  • But - adding 1 point to polygon it's became quad - and shadow appear. By the way - In this small example how to get opposite result when object not visible to camera but do shadow? Changing the order of polygon points as I tried change nothing...
    We use scenes that all consist of triangulated polygons, even cubes and spheres and no shadows when sides 1.

  • Dmitry Yunchik
    Dmitry Yunchik

    Dear Okan,

    I think there is a bug anyway. If you add another reversed triangle in attached *.rib you still do not get any shadows!
    The same example works ok in Aqsis renderer.

    I briefly looked at the source code of CPolygonTriangle::intersect(CShadingContext *context,CRay *cRay) method. Triangle intersection code for one-sided triangle looks very strange when det<=0 and ((attributes->flags & ATTRIBUTES_FLAGS_INSIDE) ^ xform->flip)==false.

    Indeed, lets look at the code with my comments closer:

    } else {

    if ((attributes->flags & ATTRIBUTES_FLAGS_INSIDE) ^ xform->flip) {
    if (det < 0) return;
    } else {
    if (det > 0) return; //dyunchik: if we get det<=0 continue to test

    subvv(tvec, cRay->from, vert0);

    const float u = dotvv(tvec, pvec);
    if (u < 0.0 || u > det) return; //dyunchik: but we will never pass further for det<0 !!! this makes cases with det<0 pointless

    crossvv(qvec, tvec, edge1);

    const float v = dotvv(cRay->dir, qvec);
    if (v < 0.0 || u + v > det) return;

    const float t = dotvv(edge2, qvec);
    const float inv_det = 1.0f / det;
    if ((t > cRay->tmin) && (t < cRay->t)) {
    cRay->object = this;
    cRay->t = t*inv_det;
    cRay->u = (u + v)*inv_det;
    cRay->v = u / (u + v);
    if ((attributes->flags & ATTRIBUTES_FLAGS_INSIDE) ^ xform->flip) crossvv(cRay->N,edge2,edge1);
    else crossvv(cRay->N,edge1,edge2);

    So, I think the code works correctly for ((attributes->flags & ATTRIBUTES_FLAGS_INSIDE) ^ xform->flip)==true case only.

  • Dmitry Yunchik
    Dmitry Yunchik

    also, I think it is better to compare det with some epsilon instead of 0 because of dividing by det in further code.