CMPS-3480 - Computer Graphics

Lab 9 - Procedural Modeling - Constructive Solid Geometry


In-class coding samples are at bottom of this page.


Get ready...
Do your work in Odin directory: /3480/9/

Copy your lab8.cpp program to 3480/9/lab9.cpp

Follow along with Gordon as we develop CSG elements.

Programming...
We will write code together in lab9.cpp.

Some of what we will do...

1. Define a clip class.
2. Define clipping characteristics.
   • clipping plane
   • clipping sphere
      - inside the sphere
      - outside the sphere
3. Setup an array of clips in the Object class.

Start by rendering a white sphere, then clip the sphere in half.
We will keep going to make it a pokeball.

You will choose one of the following images.
Try to make your scene look the same.




Clipping a cube
Build a cube object using 12 triangles.
Clip the cube with a sphere.
Take a bite out of the cube.

cube


sphere in cube


clipped cube


larger sphere


multiple light sources


soft shadows


anti-aliasing with pixel super-sampling



Below are images demonstrating refraction.

This is the image created during Wednesday's class. The rays hitting the
sphere are tweaked randomly, and thus produce a fuzzy transparent look.



scratchapixel refraction function

The image below on left "refracts" each ray upon hitting the sphere, using
the refract function provided on the Scratch-a-pixel web page.

The image to the right is a photograph of a real glass ball sitting on my desk.
Note: To use the Scratch-a-pixel refract() function will be an exercise in refactoring of source code. Try it yourself, then if you give up I will help you. Indexes of refraction used in the image above: air: 1.000293 glass: 1.52

Here is some code we did in class together.


clipping class class Clip { public: Vec center; Vec normal; double radius; bool inside; Clip() { radius = 0.0; } }; //Clip elements in the Object class. Clip clip[12]; int nclips;
Pokeball bottom sphere definition (yours can differ) o = &g.object[g.nobjects]; o->type = TYPE_SPHERE; vecMake(0.0, 0.0, 0.0, o->center); o->radius = 100.0; vecMake(1.0, 1.0, 1.0, o->color); o->specular = true; vecMake(0.1, 0.1, 0.1, o->spec); //clipping-------------------------- o->nclips = 0; vecMake(0, -6., 0, o->clip[0].center); vecMake(0, 1, 0, o->clip[0].normal); vecNormalize(o->clip[0].normal); ++o->nclips; //clip a hole in the sphere vecMake(0, 0, 100, o->clip[o->nclips].center); o->clip[o->nclips].radius = 20.0; ++o->nclips; //---------------------------------- g.nobjects++;
Triangle definition (yours can differ) o = &.object[g.nobjects]; o->type = TYPE_TRIANGLE; vecMake(-100, 100, 100, o->tri[0]); vecMake(-100, -100, 100, o->tri[1]); vecMake( 100, -100, 100, o->tri[2]); getTriangleNormal(o->tri, o->norm); vecMake(0.1, 1.0, 0.1, o->color); o->surface = SURF_NONE; g.nobjects++;
Ray/Triangle intersection int rayTriangleIntersect(Object *o, Ray *ray, Hit *hit) { //Does the ray intersect the triangle's plane? if (rayPlaneIntersect(o->tri[0], o->norm, ray, hit)) { //Yes. double u, v, w; if (pointInTriangle(o->tri, hit->p, &u, &v)) { w = 1.0 - u - v; (void)w; return 1; } } return 0; }
In trace() case TYPE_TRIANGLE: if (rayTriangleIntersect(o, ray, &hit)) { if (hit.t < closehit.t) { closehit.t = hit.t; vecCopy(hit.p, closehit.p); vecCopy(o->color, closehit.color); vecCopy(o->norm, closehit.norm); h=i; } } break;
In raySphereIntersect() //quadratic solutions... 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; //Is this clipped? for (int i=0; i<o->nclips; i++) { Vec v; vecSub(hit->p, o->clip[i].center, v); if (o->clip[i].radius > 0.0) { //sphere clip double dist = sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]); if (o->clip[i].inside) { if (dist <= o->clip[i].radius) goto back_of_sphere; } else { if (dist > o->clip[i].radius) goto back_of_sphere; } } double dot = vecDotProduct(v, o->clip[i].normal); if (dot > 0.0) goto back_of_sphere; } return 1; } back_of_sphere: 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; //Is this clipped? for (int i=0; i<o->nclips; i++) { Vec v; vecSub(hit->p, o->clip[i].center, v); if (o->clip[i].radius > 0.0) { //sphere clip double dist = sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]); if (o->clip[i].inside) { if (dist <= o->clip[i].radius) return 0; } else { if (dist > o->clip[i].radius) return 0; } } //plane clip double dot = vecDotProduct(v, o->clip[i].normal); if (dot > 0.0) return 0; } return 1; }

What to turn in...
Your instructor will find your work.