Skip to content

Instantly share code, notes, and snippets.

@esromneb
Created March 26, 2020 10:41
Show Gist options
  • Select an option

  • Save esromneb/9c24703febf151b656234338f04adfd1 to your computer and use it in GitHub Desktop.

Select an option

Save esromneb/9c24703febf151b656234338f04adfd1 to your computer and use it in GitHub Desktop.

Revisions

  1. esromneb created this gist Mar 26, 2020.
    283 changes: 283 additions & 0 deletions RayEngineSnip.cpp
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,283 @@
    //Recursive ray tracer

    void RayEngine::trace(
    const Ray& r,
    const int depthIn,
    const double effect,
    Vec3 &color,
    const bool click,
    bool &bSphere, // fixme should be const, needs to be copied below
    Vec3 &objectNum,
    const bool shdFeeling ) {

    if( depthIn > this->depth ) {
    return;
    }

    double b,c,t0,t1;
    Vec3 intersect;
    Vec3 from, fp, refl, lightRefl, tmp, norm;
    color[0] = color[1] = color[2] = 0;
    double srInverse;

    Vec3 pn;
    double vd, vo, t;

    Vec3 d1,d2,d3;
    //double normDotDir;
    numHit = 0;
    double minHit = 999999;
    Vec3 savedColor;
    Vec3 savedRefl;
    Vec3 savedIntersect;
    Ray shadowFeeler;
    Vec3 shadowColor;
    bool tmpBool;
    double savedKr;
    bool hitSphere;
    objectNum[0] = -1;

    for( int iP = 0; iP < this->numPoly; iP++ )
    {
    const Poly &poly = polygons[iP];
    for( int iTri = 0; iTri < poly.trianglePointCount / 3; iTri++ )
    {
    //continue;
    vd = poly.abcnorm[iTri].dot( r.d );
    if( !vd )
    continue; //the ray lies in the plane
    vo = -1* (poly.abcnorm[iTri].dot(r.o) + poly.d[iTri]);
    t = vo / vd;
    if( t < 0 )
    continue; //plane is behind ray's origin

    intersect = r.o + r.d*t;
    //if( vd > 0 )
    // intersection = intersection * -1 ;

    tmp[0] = poly.x[poly.triangles[iTri+0]];
    tmp[1] = poly.y[poly.triangles[iTri+0]];
    tmp[2] = poly.z[poly.triangles[iTri+0]];

    d1 = tmp - intersect;

    tmp[0] = poly.x[poly.triangles[iTri+1]];
    tmp[1] = poly.y[poly.triangles[iTri+1]];
    tmp[2] = poly.z[poly.triangles[iTri+1]];

    d2 = tmp - intersect;

    tmp[0] = poly.x[poly.triangles[iTri+2]];
    tmp[1] = poly.y[poly.triangles[iTri+2]];
    tmp[2] = poly.z[poly.triangles[iTri+2]];

    d3 = tmp - intersect;


    mat->data[0][0] = d1[0];
    mat->data[0][1] = d1[1];
    mat->data[0][2] = d1[2];
    mat->data[1][0] = d2[0];
    mat->data[1][1] = d2[1];
    mat->data[1][2] = d2[2];
    mat->data[2][0] = 1;
    mat->data[2][1] = 1;
    mat->data[2][2] = 1;

    const float det1 = mat->det();

    mat->data[0][0] = d2[0];
    mat->data[0][1] = d2[1];
    mat->data[0][2] = d2[2];
    mat->data[1][0] = d3[0];
    mat->data[1][1] = d3[1];
    mat->data[1][2] = d3[2];

    const float det2 = mat->det();

    mat->data[0][0] = d3[0];
    mat->data[0][1] = d3[1];
    mat->data[0][2] = d3[2];
    mat->data[1][0] = d1[0];
    mat->data[1][1] = d1[1];
    mat->data[1][2] = d1[2];

    const float det3 = mat->det();

    //at this point we know we hit the plane
    //now we have to check if we hit inside the triangle
    if( ( det1 < 0 && det2 < 0 && det3 < 0 )
    || ( det1 > 0 && det2 > 0 && det3 > 0 ) )
    {

    if( shdFeeling )
    {
    color[0] = 1;
    return;
    }

    //if we are the closest intersection so far
    if( min( t, minHit ) == t )
    {
    hitSphere = false;
    objectNum[0] = iP;
    objectNum[1] = iTri;
    minHit = t;

    savedRefl = poly.abcnorm[iTri]*2*( poly.abcnorm[iTri].dot( r.d ) ) - (r.d);
    savedKr = poly.kr;
    savedIntersect = intersect;



    savedColor = this->ia * poly.ka;

    if( !click ) {
    for( int iLight = 0; iLight < lights.size(); iLight++ )
    {
    shadowFeeler.o = intersect;
    shadowFeeler.d = lights[iLight].d * -1;
    shadowColor[0] = shadowColor[1] = shadowColor[2] = 0;
    trace( shadowFeeler, depth, effect, shadowColor, false, bSphere, objectNum, true );
    if( shadowColor[0] != 0 || shadowColor[1] != 0 || shadowColor[2] != 0 )
    continue;
    tmp = poly.abcnorm[iTri] - lights[iLight].d;
    lightRefl = tmp * 2 * poly.abcnorm[iTri].dot(lights[iLight].d);
    lightRefl.normalize();

    savedColor = savedColor + ( lights[iLight].color / ( fp.mag() + this->c ) )*( poly.kd * lights[iLight].d.dot( poly.abcnorm[iTri] ) + poly.ks * pow( lightRefl.dot( r.d ), poly.n) );
    }
    }


    //savedColor = Vec3( 1.0f, 0.0f, 0.0f );

    }
    }
    else
    {
    continue;
    }

    //color = Vec3( 1.0, 0, 0 );
    }

    }


    const int nSphere = spheres.size();
    for( int i = 0; i < nSphere; i++ )
    {
    const Sphere &s = spheres[i];

    b = 2*(r.d[0] * (r.o[0] - s.c[0]) + r.d[1] * (r.o[1] - s.c[1]) + r.d[2] * (r.o[2] - s.c[2]));
    c = pow((r.o[0] - s.c[0]),2) + pow((r.o[1] - s.c[1]),2) + pow((r.o[2] - s.c[2]),2) - s.r*s.r;
    if( b*b - 4*c < 0 )
    continue;

    if( i == 1 )
    i = 1;

    t0 = (-1* b - sqrt(b*b - 4*c)) / 2;
    t1 = (-1* b + sqrt(b*b - 4*c)) / 2;


    if( shdFeeling && t0 < 0 )
    {
    color[0] = 1;
    continue;
    }

    t0 = min( t0, t1 );

    if( shdFeeling )
    {
    //color[0] = 1;
    //return;
    }


    if( min( t0, minHit ) == t0 )
    {
    hitSphere = true;
    objectNum[0] = i;
    minHit = t0;
    intersect = Vec3( r.o[0] + r.d[0]*t0,
    r.o[1] + r.d[1]*t0,
    r.o[2] + r.d[2]*t0 );
    srInverse = 1.0f/s.r;

    norm = Vec3( ( intersect[0] - s.c[0] )*srInverse, ( intersect[1] - s.c[1] )*srInverse, ( intersect[2] - s.c[2] )*srInverse );
    //norm = intersect - s.c;
    norm.normalize();

    //refl = r.d - norm * 2 * (camera.d.dot(norm));
    refl = norm*2* norm.dot( r.d ) - r.d;

    //lighting
    fp = r.o - intersect;


    //we aleways have ambient light
    color = this->ia * s.ka;

    if( !click ) {
    for( int iLight = 0; iLight < lights.size(); iLight++ )
    {
    shadowFeeler.o = intersect;
    shadowFeeler.d = lights[iLight].d * -1;
    shadowFeeler.o = shadowFeeler.o + shadowFeeler.d * 2;
    shadowColor[0] = shadowColor[1] = shadowColor[2] = 0;
    trace( shadowFeeler, depth, effect, shadowColor, false, bSphere, objectNum, true );
    if( shadowColor[0] != 0 || shadowColor[1] != 0 || shadowColor[2] != 0 )
    continue;
    tmp = norm - lights[iLight].d;
    lightRefl = tmp * 2 * norm.dot(lights[iLight].d);
    lightRefl.normalize();

    const Vec3 diffuse = (s.kd * lights[iLight].d.dot( norm ) );

    const Vec3 lightPlusOrigin = r.d + lights[iLight].d;

    const float specular = s.ks * pow( lightRefl.dot( lightPlusOrigin ), s.n);

    const Vec3 lightEffects =
    ( lights[iLight].color / ( fp.mag() + this->c ) )
    * (diffuse + specular);

    color = color + lightEffects;

    }
    }

    savedColor = color;
    savedRefl = refl;
    savedKr = s.kr;
    savedIntersect = intersect;
    }


    }//spheres


    //final actions after main loops--------

    //if this was from a click we don't care about colors etc
    if( click ) {
    bSphere = hitSphere;
    return;
    }


    if( minHit != 999999 ) {
    Ray reflRay;
    reflRay.o = savedIntersect;
    reflRay.d = savedRefl;
    Vec3 newColor(0,0,0);
    trace( reflRay, depthIn+1, effect, newColor, false, bSphere, objectNum, false );
    color = savedColor + newColor * savedKr;
    } else {
    //we hit nothing
    color = Vec3( 0, 0, 0 );
    }
    }