Category : Files from Magazines
Archive   : CUJ9208.ZIP
Filename : 1008038A

 
Output of file : 1008038A contained in archive : CUJ9208.ZIP
/* RAY_RAD - A Very Simple Ray-Traced Radiosity Renderer */

#include
#include
#include

#define FLOOR 0 /* X-Y plane, Z = 0.0 */
#define SOUTH_WALL 1 /* X-Z plane, Y = 0.0 */
#define EAST_WALL 2 /* Y-Z plane, X = 8.0 */
#define NORTH_WALL 3 /* X-Z plane, Y = 8.0 */
#define WEST_WALL 4 /* X-Z plane, X = 0.0 */
#define MAX_RAYS 25000 /* Maximum number of rays */
#define MAX_VAL 1.0e+6 /* Maximum floating point value */
#define MIN_VAL 1.0e-6 /* Minimum floating point value */
#define NUM_LOOP 20 /* Number of iterations */
#define NUM_SURF 10 /* Number of surfaces */
#define PI 3.141592654
#define DRAND() ((double) rand() / (double) RAND_MAX)

typedef struct /* 3-D point co-ordinates */
{
double x; /* X-axis co-ordinate */
double y; /* Y-axis co-ordinate */
double z; /* Z-axis co-ordinate */
} PT_3D;

typedef struct /* 3-D ray */
{
PT_3D org; /* Origin */
PT_3D dir; /* Direction */
} RAY;

typedef struct /* Element */
{
double total; /* Total flux */
double unsent; /* Unsent flux */
} ELEM;

typedef struct /* Surface */
{
PT_3D vertex[4]; /* Vertex array */
int num_row; /* Number of element rows */
int num_col; /* Number of element columns */
double col_dim; /* Element column dimension */
double row_dim; /* Element row dimension */
double emittance; /* Emittance */
double reflectance; /* Reflectance */
ELEM *elemp; /* Element array pointer */
} SURF;

static int send_flux(int, int, int);
static void display_surface(void);
static void find_element(RAY *, int *, int *, int *);
static void global_to_local(int, PT_3D *, PT_3D *);
static void local_to_global(int, RAY *, RAY *);
static void select_ray(int, int, int, RAY *);

static double MaxEmittance = 0.0; /* Maximum emittance */
static SURF RoomSurf[NUM_SURF] = { /* Room surfaces */
{ { { 0.0, 0.0, 0.0 }, { 8.0, 0.0, 0.0 }, /* Floor */
{ 8.0, 8.0, 0.0 }, { 0.0, 8.0, 0.0 } }, 8, 8, 1.0, 1.0,
0.0, 0.2, NULL },
{ { { 0.0, 0.0, 0.0 }, { 0.0, 0.0, 8.0 }, /* South wall */
{ 8.0, 0.0, 8.0 }, { 8.0, 0.0, 0.0 } }, 8, 8, 1.0, 1.0,
0.0, 0.5, NULL },
{ { { 8.0, 0.0, 0.0 }, { 8.0, 0.0, 8.0 }, /* East wall */
{ 8.0, 8.0, 8.0 }, { 8.0, 8.0, 0.0 } }, 8, 8, 1.0, 1.0,
0.0, 0.5, NULL },
{ { { 8.0, 8.0, 0.0 }, { 8.0, 8.0, 8.0 }, /* North wall */
{ 0.0, 8.0, 8.0 }, { 0.0, 8.0, 0.0 } }, 8, 8, 1.0, 1.0,
0.0, 0.5, NULL },
{ { { 0.0, 8.0, 0.0 }, { 0.0, 8.0, 8.0 }, /* West wall */
{ 0.0, 0.0, 8.0 }, { 0.0, 0.0, 0.0 } }, 8, 8, 1.0, 1.0,
0.0, 0.5, NULL },
{ { { 0.0, 0.0, 8.0 }, { 0.0, 3.0, 8.0 }, /* South ceil. */
{ 8.0, 3.0, 8.0 }, { 8.0, 0.0, 8.0 } }, 8, 3, 1.0, 1.0,
0.0, 0.8, NULL },
{ { { 5.0, 3.0, 8.0 }, { 5.0, 5.0, 8.0 }, /* East ceiling */
{ 8.0, 5.0, 8.0 }, { 8.0, 3.0, 8.0 } }, 3, 2, 1.0, 1.0,
0.0, 0.8, NULL },
{ { { 0.0, 5.0, 8.0 }, { 0.0, 8.0, 8.0 }, /* North ceil. */
{ 8.0, 8.0, 8.0 }, { 8.0, 5.0, 8.0 } }, 8, 3, 1.0, 1.0,
0.0, 0.8, NULL },
{ { { 0.0, 3.0, 8.0 }, { 0.0, 5.0, 8.0 }, /* West ceiling */
{ 3.0, 5.0, 8.0 }, { 3.0, 3.0, 8.0 } }, 3, 2, 1.0, 1.0,
0.0, 0.8, NULL },
{ { { 3.0, 3.0, 8.0 }, { 3.0, 5.0, 8.0 }, /* Ceil. light */
{ 5.0, 5.0, 8.0 }, { 5.0, 3.0, 8.0 } }, 2, 2, 1.0, 1.0,
5000.0, 0.8, NULL } };

int main(void)
{
int col; /* Column counter */
int elem; /* Element counter */
int maximum; /* Maximum number of rays */
int num_elem; /* Number of elements */
int num_rays; /* Number of rays */
int row; /* Row counter */
int surf; /* Surface counter */
ELEM *elemp; /* Element pointer */
SURF *surfp; /* Surface pointer */

for (surf = 0; surf < NUM_SURF; surf++) {
/* Instantiate elements */
surfp = &(RoomSurf[surf]);
num_elem = surfp->num_row * surfp->num_col;
if ((surfp->elemp = (ELEM *) malloc(num_elem * sizeof(ELEM)))
== NULL) {
fputs("Out of memory!\n", stderr);
return (2);
}

elemp = surfp->elemp;
for (elem = 0; elem < num_elem; elem++, elemp++)
elemp->total = elemp->unsent = surfp->emittance;

if (surfp->emittance > MaxEmittance)
MaxEmittance = surfp->emittance;
}

do {
/* Distribute flux between elements */
num_rays = 0;
for (surf = 0; surf < NUM_SURF; surf++) {
surfp = &(RoomSurf[surf]);
for (row = 0; row < surfp->num_row; row++)
for (col = 0; col < surfp->num_col; col++) {
if ((maximum = send_flux(surf, row, col)) > num_rays)
num_rays = maximum;
}
}
display_surface(); /* Display intermediate results */
} while (num_rays > 0); /* Repeat until convergence */

for (surf = 0; surf < NUM_SURF; surf++) /* Free memory */
free(RoomSurf[surf].elemp);

return (0);
}

static int send_flux ( /* Send flux to other elements */
int s_surf, /* Sending surface index */
int s_row, /* Sending element row */
int s_col ) /* Sending element column */
{
int h_col; /* Hit element column */
int h_row; /* Hit element row */
int h_surf; /* Hit surface index */
int num_rays; /* Number of rays */
int ray; /* Ray counter */
double inc_flux; /* Incident (ray) flux */
double ref_flux; /* Reflected flux */
RAY shoot; /* Shooting ray */
ELEM *h_elemp; /* Hit element pointer */
ELEM *s_elemp; /* Sending element pointer */
SURF *h_surfp; /* Hit surface pointer */
SURF *s_surfp; /* Sending surface pointer */

s_surfp = &(RoomSurf[s_surf]);
s_elemp = s_surfp->elemp + s_row * s_surfp->num_col + s_col;

/* Number of rays to shoot proportional to unsent flux */
if ((num_rays = (int) (MAX_RAYS * s_elemp->unsent /
MaxEmittance)) == 0)
return (0);

inc_flux = s_elemp->unsent / num_rays; /* Get ray flux */

for (ray = 0; ray < num_rays; ray++) { /* Distribute flux */
select_ray(s_surf, s_row, s_col, &shoot); /* Select ray */

/* Find hit surface and element */
find_element(&shoot, &h_surf, &h_row, &h_col);

/* Calculate flux reflected from hit element */
h_surfp = &(RoomSurf[h_surf]);
h_elemp = h_surfp->elemp + h_row * h_surfp->num_col + h_col;
ref_flux = h_surfp->reflectance * inc_flux;

h_elemp->total += ref_flux; /* Update total flux */
h_elemp->unsent += ref_flux; /* Update unsent flux */
}

s_elemp->unsent = 0.0; /* Reset sender's unsent flux */

return (num_rays);
}

static void select_ray ( /* Randomly select ray */
int surf, /* Surface index */
int row, /* Element row */
int col, /* Element column */
RAY *rayp ) /* Ray pointer */
{
double horz; /* Ray direction local horizontal angle */
double vert; /* Ray direction local vertical angle */
RAY local; /* Ray local co-ordinates */
SURF *surfp; /* Surface pointer */

surfp = &(RoomSurf[surf]);

/* Randomly select local (surface) ray origin co-ordinates */
/* within sending element boundary */
local.org.x = ((double) col + DRAND()) / surfp->col_dim;
local.org.y = ((double) row + DRAND()) / surfp->row_dim;
local.org.z = 0.0;

/* Randomly select local (surface) ray direction co-ordinates */
/* with cosine probability distribution in vertical plane */
horz = 2.0 * PI * DRAND(); /* Horizontal angle */
vert = acos(sqrt(1.0 - DRAND())); /* Vertical angle */

/* Convert from spherical to rectilinear co-ordinates */
local.dir.x = sin(vert) * cos(horz);
local.dir.y = sin(vert) * sin(horz);
local.dir.z = cos(vert);

/* Convert ray co-ordinates from local to global */
local_to_global(surf, &local, rayp);
}

static void find_element ( /* Find intersected element */
RAY *rayp, /* Ray pointer */
int *h_surfp, /* Hit surface index pointer */
int *h_rowp, /* Hit element row pointer */
int *h_colp ) /* Hit element column pointer */
{
int surf; /* Surface counter */
double s = MAX_VAL; /* Smallest parametric value */
double t; /* Current parametric value */
PT_3D hit; /* Hit point co-ordinates */
PT_3D temp; /* Temporary point co-ordinates */
SURF *surfp; /* Surface pointer */

for (surf = 0; surf < NUM_SURF; surf++) {
surfp = &(RoomSurf[surf]);

/* Determine if and where ray intersects surface plane */
switch (surf) {
case EAST_WALL:
case WEST_WALL:
if (fabs(rayp->dir.x) > MIN_VAL) {
t = (surfp->vertex[0].x - rayp->org.x) / rayp->dir.x;
if (t > MIN_VAL && t < s) {
s = t;
*h_surfp = surf;
}
}
break;
case SOUTH_WALL:
case NORTH_WALL:
if (fabs(rayp->dir.y) > MIN_VAL) {
t = (surfp->vertex[0].y - rayp->org.y) / rayp->dir.y;
if (t > MIN_VAL && t < s) {
s = t;
*h_surfp = surf;
}
}
break;
case FLOOR:
if (fabs(rayp->dir.z) > MIN_VAL) {
t = (surfp->vertex[0].z - rayp->org.z) / rayp->dir.z;
if (t > MIN_VAL && t < s) {
s = t;
*h_surfp = surf;
}
}
break;
default:
if (fabs(rayp->dir.z) > MIN_VAL) {
t = (surfp->vertex[0].z - rayp->org.z) / rayp->dir.z;
if (t > MIN_VAL && t < s) {
/* Check for intersection inside surface boundary */
temp.x = rayp->org.x + t * rayp->dir.x;
temp.y = rayp->org.y + t * rayp->dir.y;
if ((temp.x >= surfp->vertex[0].x && temp.x <
surfp->vertex[3].x) && (temp.y >=
surfp->vertex[0].y && temp.y <
surfp->vertex[1].y)) {
s = t;
*h_surfp = surf;
}
}
}
break;
}
}

/* Calculate hit point global co-ordinates */
temp.x = rayp->org.x + s * rayp->dir.x;
temp.y = rayp->org.y + s * rayp->dir.y;
temp.z = rayp->org.z + s * rayp->dir.z;

/* Convert global to local (surface) co-ordinates */
global_to_local(*h_surfp, &temp, &hit);

/* Calculate hit element row and column indices */
*h_rowp = (int) (hit.y / surfp->row_dim);
*h_colp = (int) (hit.x / surfp->col_dim);
}

static void global_to_local ( /* Convert global to local */
int surf, /* Surface index */
PT_3D *globalp, /* Global co-ordinates pointer */
PT_3D *localp ) /* Local co-ordinates pointer */
{
PT_3D *vp; /* Vertex pointer */

vp = &(RoomSurf[surf].vertex[0]);
switch (surf) {
case FLOOR:
localp->x = globalp->x - vp->x;
localp->y = globalp->y - vp->y;
break;
case SOUTH_WALL:
localp->x = globalp->z - vp->z;
localp->y = globalp->x - vp->x;
break;
case EAST_WALL:
localp->x = globalp->z - vp->z;
localp->y = globalp->y - vp->y;
break;
case NORTH_WALL:
localp->x = globalp->z - vp->z;
localp->y = vp->x - globalp->x;
break;
case WEST_WALL:
localp->x = globalp->z - vp->z;
localp->y = vp->y - globalp->y;
break;
default:
localp->x = globalp->y - vp->y;
localp->y = globalp->x - vp->x;
break;
}
}

static void local_to_global ( /* Convert ray co-ordinates */
int surf, /* Surface index */
RAY *localp, /* Local co-ordinates pointer */
RAY *globalp ) /* Global co-ordinates pointer */
{
PT_3D *vp; /* Vertex pointer */

vp = &(RoomSurf[surf].vertex[0]);
switch (surf) {
case FLOOR:
globalp->org.x = vp->x + localp->org.x;
globalp->org.y = vp->y + localp->org.y;
globalp->org.z = vp->z + localp->org.z;
globalp->dir.x = localp->dir.x;
globalp->dir.y = localp->dir.y;
globalp->dir.z = localp->dir.z;
break;
case SOUTH_WALL:
globalp->org.x = vp->x + localp->org.y;
globalp->org.y = vp->y + localp->org.z;
globalp->org.z = vp->z + localp->org.x;
globalp->dir.x = localp->dir.y;
globalp->dir.y = localp->dir.z;
globalp->dir.z = localp->dir.x;
break;
case EAST_WALL:
globalp->org.x = vp->x - localp->org.z;
globalp->org.y = vp->y + localp->org.y;
globalp->org.z = vp->z + localp->org.x;
globalp->dir.x = -localp->dir.z;
globalp->dir.y = localp->dir.y;
globalp->dir.z = localp->dir.x;
break;
case NORTH_WALL:
globalp->org.x = vp->x - localp->org.y;
globalp->org.y = vp->y - localp->org.z;
globalp->org.z = vp->z + localp->org.x;
globalp->dir.x = -localp->dir.y;
globalp->dir.y = -localp->dir.z;
globalp->dir.z = localp->dir.x;
break;
case WEST_WALL:
globalp->org.x = vp->x + localp->org.z;
globalp->org.y = vp->y - localp->org.y;
globalp->org.z = vp->z + localp->org.x;
globalp->dir.x = localp->dir.z;
globalp->dir.y = -localp->dir.y;
globalp->dir.z = localp->dir.x;
break;
default:
globalp->org.x = vp->x + localp->org.y;
globalp->org.y = vp->y + localp->org.x;
globalp->org.z = vp->z - localp->org.z;
globalp->dir.x = localp->dir.y;
globalp->dir.y = localp->dir.x;
globalp->dir.z = -localp->dir.z;
break;
}
}

static void display_surface(void) /* Display surfaces */
{
int col; /* Element column index */
int row; /* Element row index */
int surf; /* Surface counter */
ELEM *elemp; /* Element pointer */
SURF *surfp; /* Surface pointer */
static int loop = 0; /* Iteration counter */

printf("Loop %d\n", loop++);
for (surf = 0; surf < NUM_SURF; surf++) {
printf("Surface %d\n", surf);
surfp = &(RoomSurf[surf]);
for (row = 0; row < surfp->num_row; row++) {
for (col = 0; col < surfp->num_col; col++) {
elemp = surfp->elemp + row * surfp->num_col + col;
printf("% 8.2f ", elemp->total / (PI * surfp->row_dim *
surfp->col_dim));
}
putchar('\n');
}
}
}



  3 Responses to “Category : Files from Magazines
Archive   : CUJ9208.ZIP
Filename : 1008038A

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. 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/