1 /*
2 * lightdef.c
3 *
4 * Copyright (C) 1989, 1991, Craig E. Kolb
5 * All rights reserved.
6 *
7 * This software may be freely copied, modified, and redistributed
8 * provided that this copyright notice is preserved on all copies.
9 *
10 * You may not distribute this software, in whole or in part, as part of
11 * any commercial product without the express consent of the authors.
12 *
13 * There is no warranty or other guarantee of fitness of this software
14 * for any purpose. It is provided solely "as is".
15 *
16 * $Id: lightdef.c,v 4.0 91/07/17 14:46:25 kolb Exp Locker: kolb $
17 *
18 * $Log: lightdef.c,v $
19 * Revision 4.0 91/07/17 14:46:25 kolb
20 * Initial version.
21 *
22 */
23 #include "rayshade.h"
24 #include "options.h"
25 #include "liblight/light.h"
26 #include "liblight/infinite.h" /* to create default infinite light */
27 #include "liblight/jittered.h" /* to create jittered light sources */
28
29 Light *Lights = NULL; /* Linked list of defined lights */
30
31 void
LightAddToDefined(light)32 LightAddToDefined(light)
33 Light *light;
34 {
35 if (light) {
36 light->next = Lights;
37 Lights = light;
38 }
39 }
40
41 void
LightSetup()42 LightSetup()
43 {
44 long shadowopts;
45 Light *ltmp;
46
47 /*
48 * Set shadowing options.
49 */
50 shadowopts = 0;
51 if (Options.no_shadows)
52 shadowopts |= SHADOW_NONE;
53 if (Options.shadowtransp)
54 shadowopts |= SHADOW_TRANSP;
55 if (Options.csg)
56 shadowopts |= SHADOW_CSG;
57 if (Options.cache)
58 shadowopts |= SHADOW_CACHE;
59 if (Options.shutterspeed > 0.)
60 shadowopts |= SHADOW_BLUR;
61 ShadowSetOptions(shadowopts);
62
63 /*
64 * If no light sources were defined, add a default.
65 */
66 if (Lights == (Light *)NULL) {
67 Color ctmp;
68 Vector vtmp;
69 vtmp.x = vtmp.z = 1.;
70 vtmp.y = -1;
71 ctmp.r = ctmp.g = ctmp.b = 1.;
72
73 LightAddToDefined(LightInfiniteCreate(&ctmp, &vtmp));
74 }
75 /*
76 * Now that we've parsed the input file, we know what
77 * maxlevel is, and we can allocate the correct amount of
78 * space for each light source's cache.
79 */
80 for (ltmp = Lights; ltmp; ltmp = ltmp->next) {
81 ltmp->cache = (ShadowCache *)Calloc(
82 (unsigned)Options.maxdepth + 1, sizeof(ShadowCache));
83 }
84 }
85
86 void
AreaLightCreate(color,corner,u,usamp,v,vsamp,shadow)87 AreaLightCreate(color, corner, u, usamp, v, vsamp, shadow)
88 Color *color;
89 Vector *corner, *u, *v;
90 int usamp, vsamp, shadow;
91 {
92 Vector vpos, curpos;
93 int i, j, numlight;
94 Float ulen, vlen;
95 Color intens;
96 Light *ltmp;
97
98 if (usamp < 1 || vsamp < 1)
99 RLerror(RL_ABORT, "Invalid area light specification.\n");
100
101 numlight = usamp * vsamp; /* Total number of jittered sources */
102
103 /*
104 * Sum of all intensities is equal to specified intensity.
105 */
106 intens.r = color->r / (Float)numlight;
107 intens.g = color->g / (Float)numlight;
108 intens.b = color->b / (Float)numlight;
109
110 VecSub(*u, *corner, u);
111 VecSub(*v, *corner, v);
112 /*
113 * Make sure that u and v are not degenerate.
114 */
115 ulen = VecNormalize(u);
116 vlen = VecNormalize(v);
117 if (ulen < EPSILON || vlen < EPSILON)
118 RLerror(RL_ABORT, "Degenerate area light source.\n");
119 /*
120 * Scale u and v such that they define the area covered by a
121 * single sample.
122 */
123 VecScale(ulen / (Float)usamp, *u, u);
124 VecScale(vlen / (Float)vsamp, *v, v);
125 /*
126 * For each sample...
127 */
128 vpos = *corner;
129 for (i = 0; i < vsamp; i++) {
130 curpos = vpos;
131 for (j = 0; j < usamp; j++) {
132 /*
133 * current pos is the "corner" of a new light
134 * source. A jittered position based on
135 * the "corner" and the two edge vectors
136 * is used as the position for the
137 * light source in lighting calculations.
138 */
139 ltmp = LightJitteredCreate(&intens, &curpos, u, v);
140 ltmp->shadow = shadow;
141 LightAddToDefined(ltmp);
142 VecAdd(curpos, *u, &curpos);
143 }
144 VecAdd(vpos, *v, &vpos);
145 }
146 }
147