CMPS-3480 Computer Graphics
Lab-8
Overview:
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 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.
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;
}
}
Your instructor will find your work out on Odin!