Created
March 26, 2020 10:41
-
-
Save esromneb/9c24703febf151b656234338f04adfd1 to your computer and use it in GitHub Desktop.
Revisions
-
esromneb created this gist
Mar 26, 2020 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal 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 ); } }