diff options
Diffstat (limited to 'apps/plugins/sdl/progs/quake/r_light.c')
-rw-r--r-- | apps/plugins/sdl/progs/quake/r_light.c | 260 |
1 files changed, 260 insertions, 0 deletions
diff --git a/apps/plugins/sdl/progs/quake/r_light.c b/apps/plugins/sdl/progs/quake/r_light.c new file mode 100644 index 0000000000..f735d50d84 --- /dev/null +++ b/apps/plugins/sdl/progs/quake/r_light.c | |||
@@ -0,0 +1,260 @@ | |||
1 | /* | ||
2 | Copyright (C) 1996-1997 Id Software, Inc. | ||
3 | |||
4 | This program is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU General Public License | ||
6 | as published by the Free Software Foundation; either version 2 | ||
7 | of the License, or (at your option) any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
12 | |||
13 | See the GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; if not, write to the Free Software | ||
17 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
18 | |||
19 | */ | ||
20 | // r_light.c | ||
21 | |||
22 | #include "quakedef.h" | ||
23 | #include "r_local.h" | ||
24 | |||
25 | int r_dlightframecount; | ||
26 | |||
27 | |||
28 | /* | ||
29 | ================== | ||
30 | R_AnimateLight | ||
31 | ================== | ||
32 | */ | ||
33 | void R_AnimateLight (void) | ||
34 | { | ||
35 | int i,j,k; | ||
36 | |||
37 | // | ||
38 | // light animations | ||
39 | // 'm' is normal light, 'a' is no light, 'z' is double bright | ||
40 | i = (int)(cl.time*10); | ||
41 | for (j=0 ; j<MAX_LIGHTSTYLES ; j++) | ||
42 | { | ||
43 | if (!cl_lightstyle[j].length) | ||
44 | { | ||
45 | d_lightstylevalue[j] = 256; | ||
46 | continue; | ||
47 | } | ||
48 | k = i % cl_lightstyle[j].length; | ||
49 | k = cl_lightstyle[j].map[k] - 'a'; | ||
50 | k = k*22; | ||
51 | d_lightstylevalue[j] = k; | ||
52 | } | ||
53 | } | ||
54 | |||
55 | |||
56 | /* | ||
57 | ============================================================================= | ||
58 | |||
59 | DYNAMIC LIGHTS | ||
60 | |||
61 | ============================================================================= | ||
62 | */ | ||
63 | |||
64 | /* | ||
65 | ============= | ||
66 | R_MarkLights | ||
67 | ============= | ||
68 | */ | ||
69 | void R_MarkLights (dlight_t *light, int bit, mnode_t *node) | ||
70 | { | ||
71 | mplane_t *splitplane; | ||
72 | float dist; | ||
73 | msurface_t *surf; | ||
74 | int i; | ||
75 | |||
76 | if (node->contents < 0) | ||
77 | return; | ||
78 | |||
79 | splitplane = node->plane; | ||
80 | dist = DotProduct (light->origin, splitplane->normal) - splitplane->dist; | ||
81 | |||
82 | if (dist > light->radius) | ||
83 | { | ||
84 | R_MarkLights (light, bit, node->children[0]); | ||
85 | return; | ||
86 | } | ||
87 | if (dist < -light->radius) | ||
88 | { | ||
89 | R_MarkLights (light, bit, node->children[1]); | ||
90 | return; | ||
91 | } | ||
92 | |||
93 | // mark the polygons | ||
94 | surf = cl.worldmodel->surfaces + node->firstsurface; | ||
95 | for (i=0 ; i<node->numsurfaces ; i++, surf++) | ||
96 | { | ||
97 | if (surf->dlightframe != r_dlightframecount) | ||
98 | { | ||
99 | surf->dlightbits = 0; | ||
100 | surf->dlightframe = r_dlightframecount; | ||
101 | } | ||
102 | surf->dlightbits |= bit; | ||
103 | } | ||
104 | |||
105 | R_MarkLights (light, bit, node->children[0]); | ||
106 | R_MarkLights (light, bit, node->children[1]); | ||
107 | } | ||
108 | |||
109 | |||
110 | /* | ||
111 | ============= | ||
112 | R_PushDlights | ||
113 | ============= | ||
114 | */ | ||
115 | void R_PushDlights (void) | ||
116 | { | ||
117 | int i; | ||
118 | dlight_t *l; | ||
119 | |||
120 | r_dlightframecount = r_framecount + 1; // because the count hasn't | ||
121 | // advanced yet for this frame | ||
122 | l = cl_dlights; | ||
123 | |||
124 | for (i=0 ; i<MAX_DLIGHTS ; i++, l++) | ||
125 | { | ||
126 | if (l->die < cl.time || !l->radius) | ||
127 | continue; | ||
128 | R_MarkLights ( l, 1<<i, cl.worldmodel->nodes ); | ||
129 | } | ||
130 | } | ||
131 | |||
132 | |||
133 | /* | ||
134 | ============================================================================= | ||
135 | |||
136 | LIGHT SAMPLING | ||
137 | |||
138 | ============================================================================= | ||
139 | */ | ||
140 | |||
141 | int RecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end) | ||
142 | { | ||
143 | int r; | ||
144 | float front, back, frac; | ||
145 | int side; | ||
146 | mplane_t *plane; | ||
147 | vec3_t mid; | ||
148 | msurface_t *surf; | ||
149 | int s, t, ds, dt; | ||
150 | int i; | ||
151 | mtexinfo_t *tex; | ||
152 | byte *lightmap; | ||
153 | unsigned scale; | ||
154 | int maps; | ||
155 | |||
156 | if (node->contents < 0) | ||
157 | return -1; // didn't hit anything | ||
158 | |||
159 | // calculate mid point | ||
160 | |||
161 | // FIXME: optimize for axial | ||
162 | plane = node->plane; | ||
163 | front = DotProduct (start, plane->normal) - plane->dist; | ||
164 | back = DotProduct (end, plane->normal) - plane->dist; | ||
165 | side = front < 0; | ||
166 | |||
167 | if ( (back < 0) == side) | ||
168 | return RecursiveLightPoint (node->children[side], start, end); | ||
169 | |||
170 | frac = front / (front-back); | ||
171 | mid[0] = start[0] + (end[0] - start[0])*frac; | ||
172 | mid[1] = start[1] + (end[1] - start[1])*frac; | ||
173 | mid[2] = start[2] + (end[2] - start[2])*frac; | ||
174 | |||
175 | // go down front side | ||
176 | r = RecursiveLightPoint (node->children[side], start, mid); | ||
177 | if (r >= 0) | ||
178 | return r; // hit something | ||
179 | |||
180 | if ( (back < 0) == side ) | ||
181 | return -1; // didn't hit anuthing | ||
182 | |||
183 | // check for impact on this node | ||
184 | |||
185 | surf = cl.worldmodel->surfaces + node->firstsurface; | ||
186 | for (i=0 ; i<node->numsurfaces ; i++, surf++) | ||
187 | { | ||
188 | if (surf->flags & SURF_DRAWTILED) | ||
189 | continue; // no lightmaps | ||
190 | |||
191 | tex = surf->texinfo; | ||
192 | |||
193 | s = DotProduct (mid, tex->vecs[0]) + tex->vecs[0][3]; | ||
194 | t = DotProduct (mid, tex->vecs[1]) + tex->vecs[1][3];; | ||
195 | |||
196 | if (s < surf->texturemins[0] || | ||
197 | t < surf->texturemins[1]) | ||
198 | continue; | ||
199 | |||
200 | ds = s - surf->texturemins[0]; | ||
201 | dt = t - surf->texturemins[1]; | ||
202 | |||
203 | if ( ds > surf->extents[0] || dt > surf->extents[1] ) | ||
204 | continue; | ||
205 | |||
206 | if (!surf->samples) | ||
207 | return 0; | ||
208 | |||
209 | ds >>= 4; | ||
210 | dt >>= 4; | ||
211 | |||
212 | lightmap = surf->samples; | ||
213 | r = 0; | ||
214 | if (lightmap) | ||
215 | { | ||
216 | |||
217 | lightmap += dt * ((surf->extents[0]>>4)+1) + ds; | ||
218 | |||
219 | for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ; | ||
220 | maps++) | ||
221 | { | ||
222 | scale = d_lightstylevalue[surf->styles[maps]]; | ||
223 | r += *lightmap * scale; | ||
224 | lightmap += ((surf->extents[0]>>4)+1) * | ||
225 | ((surf->extents[1]>>4)+1); | ||
226 | } | ||
227 | |||
228 | r >>= 8; | ||
229 | } | ||
230 | |||
231 | return r; | ||
232 | } | ||
233 | |||
234 | // go down back side | ||
235 | return RecursiveLightPoint (node->children[!side], mid, end); | ||
236 | } | ||
237 | |||
238 | int R_LightPoint (vec3_t p) | ||
239 | { | ||
240 | vec3_t end; | ||
241 | int r; | ||
242 | |||
243 | if (!cl.worldmodel->lightdata) | ||
244 | return 255; | ||
245 | |||
246 | end[0] = p[0]; | ||
247 | end[1] = p[1]; | ||
248 | end[2] = p[2] - 2048; | ||
249 | |||
250 | r = RecursiveLightPoint (cl.worldmodel->nodes, p, end); | ||
251 | |||
252 | if (r == -1) | ||
253 | r = 0; | ||
254 | |||
255 | if (r < r_refdef.ambientlight) | ||
256 | r = r_refdef.ambientlight; | ||
257 | |||
258 | return r; | ||
259 | } | ||
260 | |||