1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
#include "config.h"
#include "point.h"
#include "vector.h"
#include "matrix.h"
#include "eval.h"
#include "object.h"
#include "light.h"
#include "intersect.h"
#include "surface.h"
#include "simplify.h"
#include "render.h"
static void render_ray(struct point * amb,
int depth,
int initial,
struct object * obj,
struct light ** lights,
struct point * p,
struct vector * v,
flt multx,
flt multy,
flt multz,
/*out*/ struct point * color)
{
struct object * bobj;
flt t;
struct point inter_w, inter_o;
int face;
flt surf_u, surf_v;
struct surface_characteristics sc;
flt dotprod;
struct vector n, n2, s;
struct point il, is;
if (depth < 0) {
color->x = color->y = color->z = 0.0;
return;
}
bobj = intersect_ray(p, v, obj, initial, &t);
if (bobj == NULL || t == 0.0) {
color->x = color->y = color->z = 0.0;
return;
}
/* Compute surface characteristics */
point_along(p, v, t, &inter_w);
apply_to_point(bobj->world2obj, &inter_w, &inter_o);
surface_coords(bobj, &inter_o, &face, &surf_u, &surf_v);
surface_function(&bobj->surf, face, surf_u, surf_v, &sc);
/* Construct the vectors on figure 4 */
normal_vector(bobj, &inter_w, face, &n);
dotprod = dotproduct(v, &n);
vscale(&n, 2.0 * dotprod, &n2);
vsub(v, &n2, &s);
if (dotprod > 0.0) opposite(&n, &n);
/* Light sources */
color_from_lights(obj, &inter_w, v, &n,
sc.kd, sc.ks, sc.phong,
lights, &il);
/* Recursive call for ray along s */
multx = multx * sc.ks * sc.x;
multy = multy * sc.ks * sc.y;
multz = multz * sc.ks * sc.z;
if (multx < 0.1 && multy < 0.1 && multz < 0.1)
is.x = is.y = is.z = 0.0;
else
render_ray(amb, depth - 1, 0, obj, lights, &inter_w, &s,
multx, multy, multz, &is);
/* Compute final color */
color->x = (sc.kd * amb->x + il.x + sc.ks * is.x) * sc.x;
color->y = (sc.kd * amb->y + il.y + sc.ks * is.y) * sc.y;
color->z = (sc.kd * amb->z + il.z + sc.ks * is.z) * sc.z;
}
static int convert_color(flt c)
{
int n = (int) (c * 255.0);
if (n < 0) n = 0;
if (n > 255) n = 255;
return n;
}
void render(struct point * amb,
int numlights,
struct light ** lights,
struct object * scene,
int depth,
flt fov,
int wid,
int ht,
char * filename)
{
FILE * oc;
flt wid2, ht2, scale, x, y;
int i, j;
struct point p;
struct vector v;
struct point color;
char * command;
compute_bounding_spheres(scene);
wid2 = (flt) wid / 2.0;
ht2 = (flt) ht / 2.0;
scale = tan(fov / 2.0) / wid2;
oc = fopen(filename, "w");
fprintf(oc, "P6\n# Camls 'R Us\n%d %d\n255\n", wid, ht);
arena_init();
for (j = ht - 1; j >= 0; j--) {
y = ((flt) j - ht2 + 0.5) * scale;
for (i = 0; i < wid; i++) {
x = ((flt) i - wid2 + 0.5) * scale;
p.x = p.y = 0.0; p.z = -1.0;
v.dx = x; v.dy = y; v.dz = 1.0;
render_ray(amb, depth, 1, scene, lights, &p, &v, 255.0, 255.0, 255.0,
&color);
fputc(convert_color(color.x), oc);
fputc(convert_color(color.y), oc);
fputc(convert_color(color.z), oc);
arena_clear();
}
}
fclose(oc);
#ifdef XV
command = malloc(strlen(filename) + 20);
sprintf(command, "xv %s &", filename);
system(command);
free(command);
#endif
}
|