CMPS-3480 Computer Graphics
Lab-7
Lab-8 code from Wednesday for dent in sphere------------------------------- structs... ------------------------------- struct Clip { Vec center; Vec normal; Flt radius; int inside; Clip() { radius = 0.0; inside = 1; } }; struct Object { int type; int inside; Vec center; Vec norm; Vec tri[3]; Flt radius, radius2; Vec color; int surface; bool specular; Vec spec; Clip clip; int nclips; Object() { nclips = 0; inside = 0; } }; ------------------------------- function... ------------------------------- void vecNegate(Vec v) { v[0] = -v[0]; v[1] = -v[1]; v[2] = -v[2]; } ------------------------------- from init()... ------------------------------- //big ball o = &g.object[g.nobjects]; o->type = TYPE_SPHERE; vecMake(0.0, 200.0, 0.0, o->center); vecMake(1.0, 0.0, 0.0, o->color); o->radius = 200.0; o->specular = true; o->specular = 0; vecMake(0.3, 0.3, 0.3, o->spec); o->surface = SURF_NONE; //add a clip vecMake(50.0, 380.0, 90.0, o->clip.center); o->clip.radius = 60.0; ++o->nclips; g.nobjects++; // //small ball for dent o = &g.object[g.nobjects]; o->type = TYPE_SPHERE; vecMake(50.0, 380.0, 90.0, o->center); vecMake(1.0, 0.0, 0.0, o->color); o->radius = 60.0; o->specular = true; o->specular = 0; vecMake(0.3, 0.3, 0.3, o->spec); o->surface = SURF_NONE; o->inside = 1; //add a clip vecMake(0.0, 200.0, 0.0, o->clip.center); o->clip.radius = 200.0; o->clip.inside = 0; ++o->nclips; g.nobjects++; ------------------------------- from raySphereIntersect()... ------------------------------- 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); //if (o->inside) // vecNegate(hit->norm); hit->t = t0; if (o->nclips > 0) { if (o->clip.radius != 0.0) { //clipping sphere Vec v; vecSub(o->clip.center, hit->p, v); Flt dist = sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]); if (o->clip.inside) { if (dist <= o->clip.radius) goto t1; } else { if (dist >= o->clip.radius) goto t1; } } } return 1; } t1:; 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); //if (o->inside) // vecNegate(hit->norm); hit->t = t1; if (o->nclips > 0) { if (o->clip.radius != 0.0) { //clipping sphere Vec v; vecSub(o->clip.center, hit->p, v); Flt dist = sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]); if (o->clip.inside) { if (dist <= o->clip.radius) return 0; } else { if (dist >= o->clip.radius) return 0; } } } return 1; } ------------------------------- from trace()... ------------------------------- case TYPE_SPHERE: if (raySphereIntersect(o, ray, &hit)) { if (hit.t < closehit.t) { closehit.t = hit.t; vecCopy(hit.p, closehit.p); vecCopy(o->color, closehit.color); sphereNormal(closehit.p, o->center, closehit.norm); if (o->inside) vecNegate(closehit.norm); h = i; } } break; ------------------------------- spherical texture... -------------------------------
Name your texture image file: lab8a.png //This goes inside the trace() function if (o->surface == SURF_SPHERICAL_TEXTURE) { //Get the spherical texture color based on the hit-point normal. //Must have Image class from lab-1. // const Flt PI = 3.14159265358979; const Flt PIdiv2 = PI / 2.0; const Flt PItimes2 = PI * 2.0; Vec vn; vecCopy(closehit.norm, vn); //Use normal.y to get an angle Flt pct = asin(vn[1]) / PIdiv2; //pct might be positive or negative Flt h2 = (Flt)img.height * 0.5; //Get the row in the image stream Flt row = h2 + (pct * h2); //Get the angle of hitpoint going around the sphere Flt col_angle = atan2(vn[2], vn[0]); //Use angle to get the column in the image stream Flt col = ((col_angle + PI) / PItimes2) * (Flt)img.width; //flip y and x coordinates row = img.height - row - 1; col = img.width - col - 1; //Get row and column to use in pointer arithmetic int y = (int)row; int x = (int)col; //Get the spot within the image stream int spot = y * img.width * 3 + x * 3; //Get pointer to the pixel stream. unsigned char *p = img.data; //Get the red, green, blue colors. closehit.color[0] = (Flt)(*(p + (spot + 0))) / 255.0; closehit.color[1] = (Flt)(*(p + (spot + 1))) / 255.0; closehit.color[2] = (Flt)(*(p + (spot + 2))) / 255.0; }
Log into Odin, using the -YC option. example: ssh -YC myname@odin Do this: $ cd 3480 $ ./lab-start.sh $ cd 7 $ cp /home/fac/gordon/p/3480/code/7/* . $ make $ ./lab7 Press M Step 1: render a scene similar to the one belowThis scene is also possible
Step 2: create a short animation Follow along with Gordon to produce an animation Step 3: make your own ray-traced animation 1. Animation must loop forever. 2. Animation must be seamless. Viewer does not know where it starts or ends. It can go up and down, left and right, or around. You may make the checkerboard floor texture move or change to give the appearance of the camera following an object.. Use the objects given. 3. Create gif animation from program. Create your gif animation at the command-line something like this: convert -delay
-loop 0 *.png mylab7.gif Your program will capture frames and create the gif animation on a key press. Add the key to your menu. 4. Make a web page at public_html/3480/lab7.html Display your animations.
//======================================================================= Screen shot function that produces .png files PNG is about 95% smaller than a PPM file. void takeScreenshot(const char *filename, int reset) { //This function will capture your current X11 window, //and save it to a PPM P6 image file. //File names are generated sequentially. static int picnum = 0; int x,y; int width, height; x11.getWindowAttributes(&width, &height); if (reset) picnum = 0; XImage *image = x11.getImage(width, height); // //If filename argument is empty, generate a sequential filename... char ts[200] = ""; char png[200] = ""; strcpy(ts, filename); strcpy(png, filename); if (ts[0] == '\0') { sprintf(ts,"./lab7%02i.ppm", picnum); sprintf(png,"./lab7%02i.png", picnum); picnum++; } FILE *fpo = fopen(ts, "w"); if (fpo) { fprintf(fpo, "P6\n%i %i\n255\n", width, height); for (y=0; y<height; y++) { for (x=0; x<width; x++) { unsigned long pixel = XGetPixel(image, x, y); fputc(((pixel & 0x00ff0000)>>16), fpo); fputc(((pixel & 0x0000ff00)>> 8), fpo); fputc(((pixel & 0x000000ff) ), fpo); } } fclose(fpo); } XFree(image); char str[450]; sprintf(str, "convert %s %s", ts, png); system(str); unlink(ts); } //=======================================================================
1. vi card.cpp 2. Copy and paste the code below. 3. g++ card.cpp -lm -o card 4. ./card > image.ppm 5. display image.ppm --------------------------------------- #include <stdlib.h> // card > aek.ppm #include <stdio.h> #include <math.h> typedef int i;typedef float f;struct v{ f x,y,z;v operator+(v r){return v(x+r.x ,y+r.y,z+r.z);}v operator*(f r){return v(x*r,y*r,z*r);}f operator%(v r){return x*r.x+y*r.y+z*r.z;}v(){}v operator^(v r ){return v(y*r.z-z*r.y,z*r.x-x*r.z,x*r. y-y*r.x);}v(f a,f b,f c){x=a;y=b;z=c;}v operator!(){return*this*(1/sqrt(*this%* this));}};i G[]={247570,280596,280600, 249748,18578,18577,231184,16,16};f R(){ return(f)rand()/RAND_MAX;}i T(v o,v d,f &t,v&n){t=1e9;i m=0;f p=-o.z/d.z;if(.01 <p)t=p,n=v(0,0,1),m=1;for(i k=19;k--;) for(i j=9;j--;)if(G[j]&1<<k){v p=o+v(-k ,0,-j-4);f b=p%d,c=p%p-1,q=b*b-c;if(q>0 ){f s=-b-sqrt(q);if(s<t&&s>.01)t=s,n=!( p+d*t),m=2;}}return m;}v S(v o,v d){f t ;v n;i m=T(o,d,t,n);if(!m)return v(.7, .6,1)*pow(1-d.z,4);v h=o+d*t,l=!(v(9+R( ),9+R(),16)+h*-1),r=d+n*(n%d*-2);f b=l% n;if(b<0||T(h,l,t,n))b=0;f p=pow(l%r*(b >0),99);if(m&1){h=h*.2;return((i)(ceil( h.x)+ceil(h.y))&1?v(3,1,1):v(3,3,3))*(b *.2+.1);}return v(p,p,p)+S(h,r)*.5;}i main(){printf("P6 512 512 255 ");v g=!v (-6,-16,0),a=!(v(0,0,1)^g)*.002,b=!(g^a )*.002,c=(a+b)*-256+g;for(i y=512;y--;) for(i x=512;x--;){v p(13,13,13);for(i r =64;r--;){v t=a*(R()-.5)*99+b*(R()-.5)* 99;p=S(v(17,16,8)+t,!(t*-1+(a*(R()+x)+b *(y+R())+c)*16))*3.5+p;}printf("%c%c%c" ,(i)p.x,(i)p.y,(i)p.z);}} --------------------------------------- Reference https://fabiensanglard.net/revisiting_the_businesscard_raytracer/