added in_pitch_min and in_pitch_max cvars to limit pitch (default: -90 to +90)
[divverent/darkplaces.git] / sv_light.c
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
24 int SV_RecursiveLightPoint (vec3_t color, mnode_t *node, float x, float y, float startz, float endz)
25 {
26         int             side, distz = endz - startz;
27         float   front, back;
28         float   mid;
29
30 loc0:
31         if (node->contents < 0)
32                 return false;           // didn't hit anything
33
34         switch (node->plane->type)
35         {
36         case PLANE_X:
37                 node = node->children[x < node->plane->dist];
38                 goto loc0;
39         case PLANE_Y:
40                 node = node->children[y < node->plane->dist];
41                 goto loc0;
42         case PLANE_Z:
43                 side = startz < node->plane->dist;
44                 if ((endz < node->plane->dist) == side)
45                 {
46                         node = node->children[side];
47                         goto loc0;
48                 }
49                 // found an intersection
50 //              mid = startz + (endz - startz) * (startz - node->plane->dist) / (startz - endz);
51 //              mid = startz + distz * (startz - node->plane->dist) / (-distz);
52 //              mid = startz + (-(startz - node->plane->dist));
53 //              mid = startz - (startz - node->plane->dist);
54 //              mid = startz + node->plane->dist - startz;
55                 mid = node->plane->dist;
56                 break;
57         default:
58                 back = front = x * node->plane->normal[0] + y * node->plane->normal[1];
59                 front += startz * node->plane->normal[2];
60                 back += endz * node->plane->normal[2];
61                 side = front < node->plane->dist;
62                 if ((back < node->plane->dist) == side)
63                 {
64                         node = node->children[side];
65                         goto loc0;
66                 }
67                 // found an intersection
68 //              mid = startz + (endz - startz) * ((front - node->plane->dist) / ((front - node->plane->dist) - (back - node->plane->dist)));
69 //              mid = startz + (endz - startz) * ((front - node->plane->dist) / (front - back));
70                 mid = startz + distz * (front - node->plane->dist) / (front - back);
71                 break;
72         }
73         
74         // go down front side
75         if (node->children[side]->contents >= 0 && SV_RecursiveLightPoint (color, node->children[side], x, y, startz, mid))
76                 return true;    // hit something
77         else
78         {
79                 // check for impact on this node
80                 if (node->numsurfaces)
81                 {
82                         int i, ds, dt;
83                         msurface_t *surf;
84
85                         surf = sv.worldmodel->surfaces + node->firstsurface;
86                         for (i = 0;i < node->numsurfaces;i++, surf++)
87                         {
88                                 if (!(surf->flags & SURF_LIGHTMAP))
89                                         continue;
90
91                                 ds = (int) (x * surf->texinfo->vecs[0][0] + y * surf->texinfo->vecs[0][1] + mid * surf->texinfo->vecs[0][2] + surf->texinfo->vecs[0][3]);
92                                 dt = (int) (x * surf->texinfo->vecs[1][0] + y * surf->texinfo->vecs[1][1] + mid * surf->texinfo->vecs[1][2] + surf->texinfo->vecs[1][3]);
93
94                                 if (ds < surf->texturemins[0] || dt < surf->texturemins[1])
95                                         continue;
96                                 
97                                 ds -= surf->texturemins[0];
98                                 dt -= surf->texturemins[1];
99                                 
100                                 if (ds > surf->extents[0] || dt > surf->extents[1])
101                                         continue;
102
103                                 if (surf->samples)
104                                 {
105                                         byte *lightmap;
106                                         int maps, line3, size3, dsfrac = ds & 15, dtfrac = dt & 15, scale = 0, r00 = 0, g00 = 0, b00 = 0, r01 = 0, g01 = 0, b01 = 0, r10 = 0, g10 = 0, b10 = 0, r11 = 0, g11 = 0, b11 = 0;
107                                         line3 = ((surf->extents[0]>>4)+1)*3;
108                                         size3 = ((surf->extents[0]>>4)+1) * ((surf->extents[1]>>4)+1)*3; // LordHavoc: *3 for colored lighting
109
110                                         lightmap = surf->samples + ((dt>>4) * ((surf->extents[0]>>4)+1) + (ds>>4))*3; // LordHavoc: *3 for color
111
112                                         for (maps = 0;maps < MAXLIGHTMAPS && surf->styles[maps] != 255;maps++)
113                                         {
114                                                 scale = 256; // FIXME: server doesn't know what light styles are doing
115                                                 r00 += lightmap[      0] * scale;g00 += lightmap[      1] * scale;b00 += lightmap[      2] * scale;
116                                                 r01 += lightmap[      3] * scale;g01 += lightmap[      4] * scale;b01 += lightmap[      5] * scale;
117                                                 r10 += lightmap[line3+0] * scale;g10 += lightmap[line3+1] * scale;b10 += lightmap[line3+2] * scale;
118                                                 r11 += lightmap[line3+3] * scale;g11 += lightmap[line3+4] * scale;b11 += lightmap[line3+5] * scale;
119                                                 lightmap += size3;
120                                         }
121
122                                         color[0] += (float) ((((((((r11-r10) * dsfrac) >> 4) + r10)-((((r01-r00) * dsfrac) >> 4) + r00)) * dtfrac) >> 4) + ((((r01-r00) * dsfrac) >> 4) + r00)) * (1.0f / 256.0f);
123                                         color[1] += (float) ((((((((g11-g10) * dsfrac) >> 4) + g10)-((((g01-g00) * dsfrac) >> 4) + g00)) * dtfrac) >> 4) + ((((g01-g00) * dsfrac) >> 4) + g00)) * (1.0f / 256.0f);
124                                         color[2] += (float) ((((((((b11-b10) * dsfrac) >> 4) + b10)-((((b01-b00) * dsfrac) >> 4) + b00)) * dtfrac) >> 4) + ((((b01-b00) * dsfrac) >> 4) + b00)) * (1.0f / 256.0f);
125                                 }
126                                 return true; // success
127                         }
128                 }
129
130                 // go down back side
131                 node = node->children[side ^ 1];
132                 startz = mid;
133                 distz = endz - startz;
134                 goto loc0;
135 //              return RecursiveLightPoint (color, node->children[side ^ 1], x, y, mid, endz);
136         }
137 }
138
139 // LordHavoc: added light checking to the server
140 void SV_LightPoint (vec3_t color, vec3_t p)
141 {
142         Mod_CheckLoaded(sv.worldmodel);
143         if (!sv.worldmodel->lightdata)
144         {
145                 color[0] = color[1] = color[2] = 255;
146                 return;
147         }
148
149         color[0] = color[1] = color[2] = 0;
150         SV_RecursiveLightPoint (color, sv.worldmodel->nodes, p[0], p[1], p[2], p[2] - 65536);
151 }