Skip to content

Instantly share code, notes, and snippets.

@esromneb
Created March 26, 2020 10:41
Show Gist options
  • Save esromneb/9c24703febf151b656234338f04adfd1 to your computer and use it in GitHub Desktop.
Save esromneb/9c24703febf151b656234338f04adfd1 to your computer and use it in GitHub Desktop.
//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 );
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment