Category : Files from Magazines
Archive   : DDJ0990.ZIP
Filename : LYKE.ASC
by Daniel Lyke
[LISTING ONE]
/* RAYTRACE.HPP */
class RAY
{
double dx, dy, dz; /* Direction vector */
double ox, oy, oz; /* Origin */
public:
RAY(double x, double y, double z, double vx, double vy, double vz);
friend class PLANE;
friend class SPHERE;
};
class PLANE
{
double nx, ny, nz; /* Vector normal (perpendicular) to plane */
double px, py, pz; /* Point on plane */
public:
PLANE(double x, double y, double z, double vx, double vy, double vz);
double Intersect(RAY ray);
int Pattern(RAY ray, double time, int light);
};
class SPHERE
{
double cx, cy, cz; /* Center of sphere */
double r2; /* Radius squared */
public:
double Intersect(RAY ray);
Reflect(RAY iray,double time, RAY &rray);
SPHERE(double x, double y, double z, double r);
};
class VECTOR
{
public:
double dx, dy, dz; /* Three dimensional vector */
};
[LISTING TWO]
/* RAYTRACE.CPP */
#include
#include
#include
#include
#include "raytrace.hpp"
#define WIDTH 640
#define HEIGHT 350
inline void plot(int x,int y,int c)
{
fg_drawdot(c,FG_MODE_SET,~0,x,y);
}
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;
} /*----- End: PlanePattern() -----*/
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;
} /*----- End: RAY::RAY() -----*/
SPHERE::SPHERE(double x, double y, double z, double r)
{
this->cx = x;
this->cy = y;
this->cz = z;
this->r2 = r * r;
} /*----- End: SPHERE::SPHERE ------*/
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.0;
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);
} /*----- End: SPHERE::Intersect() -----*/
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;
} /*----- End: SPHERE::Reflect() ------*/
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;
} /*----- End: PLANE::PLANE() -----*/
int PLANE::Pattern(RAY ray, double time, int light)
{
PlanePattern((unsigned)(time * ray.dz + ray.oz),
(unsigned)(time * ray.dx + ray.ox),light);
} /*----- End: PLANE::Pattern ------*/
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);
} /*----- End: PLANE::Intersect() -----*/
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;
} /*----- End: trace() -----*/
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));
}
}
} /*----- End: draw() -----*/
main()
{
fg_init_egaecd();
draw();
getch();
fg_term();
}
[LISTING THREE]
#include
#include
#include
#define WIDTH 640
#define HEIGHT 350
#define QUIT_OUT (!kbhit())
plot(x,y,c)
int x,y,c;
{
fg_drawdot(c,FG_MODE_SET,~0,x,HEIGHT - y);
}
typedef struct S_RAY
{
double dx, dy, dz; /* Direction vector */
double ox, oy, oz; /* Origin */
} RAY;
typedef struct S_PLANE
{
double nx, ny, nz; /* Vector normal (perpendicular) to plane */
double px, py, pz; /* Point on plane */
} PLANE;
typedef struct S_SPHERE
{
double cx, cy, cz; /* Center of sphere */
double r2; /* Radius squared */
} SPHERE;
typedef struct S_VECTOR
{
double dx, dy, dz; /* Three dimensional vector */
} VECTOR;
double sphere_intersect(RAY, SPHERE);
double plane_intersect(RAY, PLANE);
void reflect(VECTOR *, VECTOR *, VECTOR *);
double sphere_intersect(RAY ray, SPHERE sphere)
{
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.0;
if(a)
{
b = 2.0 * ((ray.ox - sphere.cx) * ray.dx
+ (ray.oy - sphere.cy) * ray.dy
+ (ray.oz - sphere.cz) * ray.dz);
c = (ray.ox - sphere.cx) * (ray.ox - sphere.cx)
+ (ray.oy - sphere.cy) * (ray.oy - sphere.cy)
+ (ray.oz - sphere.cz) * (ray.oz - sphere.cz) - sphere.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);
} /*----- End: sphere_intersect() -----*/
double plane_intersect(RAY ray, PLANE plane)
{
double p1, p2, p3;
p1 = plane.px * plane.ny + plane.py * plane.ny + plane.pz * plane.nz;
p2 = ray.ox * plane.nx + ray.oy * plane.ny + ray.oz * plane.nz;
p3 = ray.dx * plane.nx + ray.dy * plane.ny + ray.dz * plane.nz;
return (double)((p1-p2)/p3);
} /*----- End: plane_intersect() -----*/
void reflect(VECTOR *normal, VECTOR *incident, VECTOR *r)
{
double ndotn, idotn;
ndotn = (normal->dx * normal->dx +
normal->dy * normal->dy +
normal->dz * normal->dz);
idotn = (normal->dx * incident->dx +
normal->dy * incident->dy +
normal->dz * incident->dz);
r->dx = incident->dx - (2.0 * (idotn) / ndotn) * normal->dx;
r->dy = incident->dy - (2.0 * (idotn) / ndotn) * normal->dy;
r->dz = incident->dz - (2.0 * (idotn) / ndotn) * normal->dz;
} /*----- End: reflect() -----*/
int plane_pattern(int x, int y, int light)
{
return ((x + 16384) % 8) ^ ((y + 16384) % 8) + 8 * light;
} /*----- End: plane_pattern() -----*/
int trace(int x, int y)
{
static PLANE plane = { 0.0, 1.0, 0.001, -8.0, 0.0, 0.0};
static SPHERE sphere = { 0.0, 0.0, 5.0, 9.0 };
VECTOR v1, v2, v3;
RAY ray;
double t1, t2, time;
ray.ox = 0.0; /* Set the ray origin to the eye */
ray.oy = 0.0;
ray.oz = 0.0;
ray.dz = 1.0; /* Set the direction through the pixel */
ray.dy = -((double)y - (double)HEIGHT / 2.0) / 100;
ray.dx = ((double)x - (double)WIDTH / 2.0) / 120;
t1 = sphere_intersect(ray,sphere);
t2 = plane_intersect(ray,plane);
if(t1 > 0.0 && (t2 < 0.0 || t2 > t1)) /* Circle in fore */
{
v1.dx = ray.dx; v1.dy = ray.dy; v1.dz = ray.dz;
v2.dx = ((ray.dx * t1 + ray.ox) - sphere.cx);
v2.dy = ((ray.dy * t1 + ray.oy) - sphere.cy);
v2.dz = ((ray.dz * t1 + ray.oz) - sphere.cz);
reflect(&v2,&v1, &v3);
ray.ox += ray.dx * t1; ray.oy += ray.dy * t1; ray.oz += ray.dz * t1;
ray.dx = v3.dx; ray.dy = v3.dy; ray.dz = v3.dz;
t2 = plane_intersect(ray,plane);
if(t2 > 0.0)
{
return plane_pattern((int)(t2 * ray.dz + ray.oz),(int)(t2 *
ray.dx + ray.ox),0);
}
else
{
return 1;
}
}
else if(t2 > 0.0)
{
return plane_pattern((int)(t2 * ray.dz + ray.oz),(int)(t2 *
ray.dx + ray.ox),1);
}
return 0;
} /*----- End: trace() -----*/
draw()
{
int x,y;
for(x=0;x< WIDTH && QUIT_OUT; x++)
{
for(y = 0; y < HEIGHT; y++)
{
plot(x,y,trace(x,y));
}
}
} /*----- End: draw() -----*/
main()
{
fg_init_all();
draw();
while(QUIT_OUT);
getch();
fg_term();
}
Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!
This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.
But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/