CMPS-3480 Computer Graphics
Lab-8

Overview:

Step 1:
Change to your 3480/8/ folder.

Copy the lab files now...
cp /home/fac/gordon/p/3480/code/lab8/* .

Compile and run the program:
make
./lab8

Pressing R renders a disk.

If you see this image, your program is working.

We will do some coding together to make an incredible scene.
Get ready to code!

Homework
Homework is...

Choose #1 or #2

1. Create an image using a new object type that you define, such as a ring.
2. Create a gif animation that seamlessly loops forever.


Here are some images created with our lab8.cpp after class.


For the planet Saturn you will need to define a ring object.


This is a gif animation.
You may setup a rendering loop outside of the main function for ray-tracing.
lab8.cpp is not a real-time program.
Setup some global variables to be used inside the init() function.
Modify the variables inside your animation loop.
Render and take a screenshot each frame of your animation loop.

Tuesday in-class code needed

We will code together starting at 7:20am.
Some of our work will require that we copy & paste the code below.


void sphereNormal(Vec hitPoint, Vec center, Vec norm)
{
    //Calculate normal at hit point of sphere
    norm[0] = hitPoint[0] - center[0];
    norm[1] = hitPoint[1] - center[1];
    norm[2] = hitPoint[2] - center[2];
    vecNormalize(norm);
}

int raySphereIntersect(Object *o, Ray *ray, Hit *hit)
{
    //Log("raySphereIntersect()...\n");
    //Determine if and where a ray intersects a sphere.
    //
    // sphere equation:
    // (p - c) * (p - c) = r * r
    //
    // where:
    // p = point on sphere surface
    // c = center of sphere
    //
    // ray equation:
    // o + t*d
    //
    // where:
    //   o = ray origin
    //   d = ray direction
    //   t = distance along ray, or scalar
    //
    // substitute ray equation into sphere equation
    //
    // (o + t*d - c) * (o + t*d - c) - r * r = 0
    //
    // we want it in this form:
    // a*t*t + b*t + c = 0
    //
    // (o + d*t - c)
    // (o + d*t - c)
    // -------------
    // o*o + o*d*t - o*c + o*d*t + d*t*d*t - d*t*c - o*c + c*d*t + c*c
    // d*t*d*t + o*o + o*d*t - o*c + o*d*t - d*t*c - o*c + c*d*t + c*c
    // d*t*d*t + 2(o*d*t) - 2(c*d*t) + o*o - o*c - o*c + c*c
    // d*t*d*t + 2(o-c)*d*t + o*o - o*c - o*c + c*c
    // d*t*d*t + 2(o-c)*d*t + (o-c)*(o-c)
    //
    // t*t*d*d + t*2*(o-c)*d + (o-c)*(o-c) - r*r
    //
    // a = dx*dx + dy*dy + dz*dz
    // b = 2(ox-cx)*dx + 2(oy-cy)*dy + 2(oz-cz)*dz
    // c = (ox-cx)*(ox-cx) + (oy-cy)*(oy-cy) + (oz-cz)*(oz-cz) - r*r
    //
    // now put it in quadratic form:
    // t = (-b +/- sqrt(b*b - 4ac)) / 2a
    //
    //
    //1. a, b, and c are given to you just above.
    //2. Create variables named a,b,c, and assign the values you see above.
    //3. Look how a,b,c are used in the quadratic equation.
    //4. Make your code solve for t.
    //5. Remember, a quadratic can have 0, 1, or 2 solutions.
    //
    //Your code goes here...
    //
    //I'll start you out with a and b
    //You try to do c
    //
    Flt a = ray->d[0]*ray->d[0] + ray->d[1]*ray->d[1] + ray->d[2]*ray->d[2];
    Flt b = 2.0*(ray->o[0]-o->center[0])*ray->d[0] +
            2.0*(ray->o[1]-o->center[1])*ray->d[1] +
            2.0*(ray->o[2]-o->center[2])*ray->d[2];
    Flt c = (ray->o[0]-o->center[0])*(ray->o[0]-o->center[0]) +
            (ray->o[1]-o->center[1])*(ray->o[1]-o->center[1]) +
            (ray->o[2]-o->center[2])*(ray->o[2]-o->center[2]) -
            o->radius*o->radius;
    Flt t0,t1;
    //discriminant
    Flt disc = b * b - 4.0 * a * c;
    if (disc < 0.0) return 0;
    disc = sqrt(disc);
    t0 = (-b - disc) / (2.0*a);
    t1 = (-b + disc) / (2.0*a);
    //
    if (t0 > 0.0) {
        hit->p[0] = ray->o[0] + ray->d[0] * t0;
        hit->p[1] = ray->o[1] + ray->d[1] * t0;
        hit->p[2] = ray->o[2] + ray->d[2] * t0;
        sphereNormal(hit->p, o->center, hit->norm);
        hit->t = t0;
        return 1;
    }
    if (t1 > 0.0) {
        hit->p[0] = ray->o[0] + ray->d[0] * t1;
        hit->p[1] = ray->o[1] + ray->d[1] * t1;
        hit->p[2] = ray->o[2] + ray->d[2] * t1;
        sphereNormal(hit->p, o->center, hit->norm);
        hit->t = t1;
        return 1;
    }
    return 0;
}

//This code segment will be added to trace()
//
if (o->specular) {
    //1. Reflect the ray off the specular surface.
    //Build a reflected ray
    Vec rcol = {0,0,0};
    Ray tray;
    //
    reflect(ray->d, closehit.norm, tray.d);
    vecCopy(closehit.p, tray.o);
    nudge_ray_forward(&tray);
    vecZero(rcol);
    //Recursive call
    trace(&tray, rcol, weight*0.5, level+1);
    //
    rgb[0] += rcol[0] * o->spec[0] * weight;
    rgb[1] += rcol[1] * o->spec[1] * weight;
    rgb[2] += rcol[2] * o->spec[2] * weight;
    //
    //2. Look for a specular highlight...
    //http://en.wikipedia.org/wiki/Specular_highlight
    //Blinn Phong lighting model
    Vec lightDir, halfway;
    lightDir[0] = g.lightPos[0] - closehit.p[0];
    lightDir[1] = g.lightPos[1] - closehit.p[1];
    lightDir[2] = g.lightPos[2] - closehit.p[2];
    halfway[0] = (lightDir[0] - ray->d[0]) * 0.5;
    halfway[1] = (lightDir[1] - ray->d[1]) * 0.5;
    halfway[2] = (lightDir[2] - ray->d[2]) * 0.5;
    vecNormalize(halfway);
    Flt dot = vecDotProduct(halfway, closehit.norm);
    if (dot > 0.0) {
        dot = pow(dot, 512.0);
        rgb[0] += 1.0 * dot;
        rgb[1] += 1.0 * dot;
        rgb[2] += 1.0 * dot;
    }
}


What to turn in...
Your instructor will find your work out on Odin!