home *** CD-ROM | disk | FTP | other *** search
- /* RAYTRACE.CPP */
-
- #include <stdlib.h>
- #include <graphics.h>
- #include <math.h>
- #include <stdio.h>
- #include <conio.h>
-
- #include "RAYTRACE.HPP"
-
- #define WIDTH 640
- #define HEIGHT 350
-
- inline void plot(int x,int y,int c)
- {
- putpixel( x , (HEIGHT-1)-y , c );
- }
-
- int PlanePattern( unsigned int x, unsigned int y, int light )
- {
- /* Put code for different plane patterns in here */
- return ((x + y) % 8 )+ 8 * light ;
- // return (x % 8 ) ^ ( y % 8 ) + 8 * light ;
- // return (( x * x + y * y ) & 8 ) + 8 * light ;
- }
-
-
- RAY::RAY(double x, double y, double z, double vx, double vy, double vz)
- {
- this->ox = x ;
- this->oy = y ;
- this->oz = z ;
- this->dx = vx ;
- this->dy = vy ;
- this->dz = vz ;
- }
-
- SPHERE::SPHERE( double x, double y, double z, double r)
- {
- this->cx = x ;
- this->cy = y ;
- this->cz = z ;
- this->r2 = r*r ;
- }
-
- double SPHERE::Intersect ( RAY ray )
- {
- double a, b, c, t1, t2, t3, close, farther;
- a = ray.dx * ray.dx + ray.dy * ray.dy + ray.dz * ray.dz ;
- close = farther = -1 ;
- if (a) {
- b = 2.0 * ((ray.ox - this->cx) * ray.dx
- + (ray.oy - this->cy) * ray.dy
- + (ray.oz - this->cz) * ray.dz );
- c = (ray.ox - this->cx) * ( ray.ox - this->cx )
- + (ray.oy - this->cy) * ( ray.oy - this->cy )
- + (ray.oz - this->cz) * ( ray.oz - this->cz ) - this->r2 ;
- t1 = b * b - 4.0 * a * c ;
- if (t1>0){
- t2 = sqrt(t1);
- t3 = 2.0 * a ;
- close = -( b + t2 ) / t3 ;
- farther = -( b - t2 ) / t3 ;
- }
- }
- return (double)((close < farther) ? close : farther);
- }
-
- void SPHERE::Reflect(RAY iray, double time, RAY &rray)
- {
- VECTOR normal; /* Used for readability */
- double ndotn; /* Used for readability */
- double idotn; /* Used for readability */
- double idotn_div_ndotn_x2; /* Used for optimization */
-
- rray.ox = iray.dx * time + iray.ox; /* find the point of */
- rray.oy = iray.dy * time + iray.oy; /* intersection between */
- rray.oz = iray.dz * time + iray.oz; /* iray and sphere. */
-
- normal.dx = rray.ox - this->cx; /* find the ray normal */
- normal.dy = rray.oy - this->cy; /* to the sphere at the */
- normal.dz = rray.oz - this->cz; /* intersection */
-
- ndotn = (normal.dx * normal.dx +
- normal.dy * normal.dy +
- normal.dz * normal.dz );
- idotn = (normal.dx * iray.dx +
- normal.dy * iray.dy +
- normal.dz * iray.dz );
- idotn_div_ndotn_x2 = ( 2.0 * (idotn) / ndotn );
-
- rray.dx = iray.dx - idotn_div_ndotn_x2 * normal.dx ;
- rray.dy = iray.dy - idotn_div_ndotn_x2 * normal.dy ;
- rray.dz = iray.dz - idotn_div_ndotn_x2 * normal.dz ;
- }
-
- PLANE::PLANE(double x, double y, double z, double vx, double vy, double vz)
- {
- this->nx = vx ;
- this->ny = vy ;
- this->nz = vz ;
-
- this->px = x ;
- this->py = y ;
- this->pz = z ;
- }
-
- int PLANE::Pattern(RAY ray, double time, int light)
- {
- return PlanePattern((unsigned)(time * ray.dz + ray.oz),
- (unsigned)(time * ray.dx + ray.ox ),light);
- }
-
- double PLANE::Intersect(RAY ray)
- {
- double p1, p2, p3;
-
- p1 = this->px * this->ny + this->py * this->ny + this->pz * this->nz ;
- p2 = ray.ox * this->nx + ray.oy * this->ny + ray.oz * this->nz ;
- p3 = ray.dx * this->nx + ray.dy * this->ny + ray.dz * this->nz ;
- return (double)((p1-p2)/p3);
- }
-
- int trace(double x, double y)
- {
- static PLANE plane( -8.0 , 0.0 , 0.0 , 0.0 , 1.0 , 0.001 );
- static SPHERE sphere( 0.0 , 0.0 , 5.0 , 1.0 );
- RAY ray(0.0,0.0,0.0,(x-(double)WIDTH / 2.0 ) * .75 ,
- y - (double)HEIGHT / 2.0 , HEIGHT);
- double time1 , time2 ;
-
- time1 = sphere.Intersect(ray);
- time2 = plane.Intersect(ray);
-
- if (time1>0.0 && (time2 <0.0 || time2 > time1)){ /* Circle in fore */
- sphere.Reflect(ray,time1,ray);
- time2 = plane.Intersect(ray);
- if (time2>0.0)
- return plane.Pattern(ray,time2,0);
- else
- return 1 ;
- }
- else
- if (time2 > 0.0)
- return plane.Pattern(ray,time2,1);
-
- return 0;
- }
-
- void draw()
- {
- int x,y ;
- for( x=0 ; x < WIDTH && !kbhit(); x++ )
- for (y = 0 ; y < HEIGHT ; y ++ )
- plot( x , y , trace((double)x,(double)y));
- }
-
- void init_graphics()
- {
- /* request auto detection */
- int gdriver = DETECT, gmode, errorcode;
-
- /* initialize graphics mode */
- initgraph(&gdriver, &gmode, "");
-
- /* read result of initialization */
- errorcode = graphresult();
-
- if (errorcode != grOk) /* an error occurred */
- {
- printf("Graphics error: %s\n", grapherrormsg(errorcode));
- printf("Press any key to halt:");
- getch();
- exit(1); /* return with error code */
- }
-
- setgraphmode(EGAHI);
- }
-
- void exit_graphics(){
- closegraph();
- }
-
- main()
- {
- init_graphics();
- draw();
- getch();
- exit_graphics();
- }
-
-
-