1 /*
2 Copyright (C) 2003-2006 Andrey Nazarov
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
21 #include "gl_local.h"
22
23 vec3_t modelViewOrigin; /* viewer origin in model space */
24
25 static vec3_t lightcolor;
26
GL_LightPoint_r(bspNode_t * node,vec3_t start,vec3_t end)27 static qboolean GL_LightPoint_r( bspNode_t *node, vec3_t start, vec3_t end ) {
28 cplane_t *plane;
29 vec_t startFrac, endFrac, midFrac;
30 vec3_t mid;
31 int side;
32 qboolean ret;
33 bspSurface_t *surf;
34 bspTexinfo_t *texinfo;
35 int i, pitch;
36 int s, t;
37 byte *b1, *b2, *b3, *b4;
38 int fracu, fracv;
39 int w1, w2, w3, w4;
40 int color[3];
41
42 if( !( plane = node->plane ) ) {
43 return qfalse;
44 }
45
46 /* calculate distancies */
47 startFrac = DotProduct( plane->normal, start ) - plane->dist;
48 endFrac = DotProduct( plane->normal, end ) - plane->dist;
49 side = ( startFrac < 0 );
50
51 if( ( endFrac < 0 ) == side ) {
52 /* both points are one the same side */
53 return GL_LightPoint_r( node->children[side], start, end );
54 }
55
56 /* find crossing point */
57 midFrac = startFrac / ( startFrac - endFrac );
58 mid[0] = start[0] + ( end[0] - start[0] ) * midFrac;
59 mid[1] = start[1] + ( end[1] - start[1] ) * midFrac;
60 mid[2] = start[2] + ( end[2] - start[2] ) * midFrac;
61
62 /* check near side */
63 ret = GL_LightPoint_r( node->children[side], start, mid );
64 if( ret ) {
65 return ret;
66 }
67
68 surf = node->firstFace;
69 for( i = 0; i < node->numFaces; i++, surf++ ) {
70 texinfo = surf->texinfo;
71 if( texinfo->flags & (SURF_WARP|SURF_SKY) ) {
72 continue;
73 }
74 if( !surf->lightmap ) {
75 continue;
76 }
77 s = DotProduct( texinfo->axis[0], mid ) + texinfo->offset[0];
78 t = DotProduct( texinfo->axis[1], mid ) + texinfo->offset[1];
79
80 s -= surf->texturemins[0];
81 t -= surf->texturemins[1];
82 if( s < 0 || t < 0 ) {
83 continue;
84 }
85 if( s > surf->extents[0] || t > surf->extents[1] ) {
86 continue;
87 }
88
89 fracu = s & 15;
90 fracv = t & 15;
91
92 s >>= 4;
93 t >>= 4;
94
95 pitch = ( surf->extents[0] >> 4 ) + 1;
96 b1 = &surf->lightmap[3 * ( ( t + 0 ) * pitch + ( s + 0 ) )];
97 b2 = &surf->lightmap[3 * ( ( t + 0 ) * pitch + ( s + 1 ) )];
98 b3 = &surf->lightmap[3 * ( ( t + 1 ) * pitch + ( s + 1 ) )];
99 b4 = &surf->lightmap[3 * ( ( t + 1 ) * pitch + ( s + 0 ) )];
100
101 w1 = ( 16 - fracu ) * ( 16 - fracv );
102 w2 = fracu * ( 16 - fracv );
103 w3 = fracu * fracv;
104 w4 = ( 16 - fracu ) * fracv;
105
106 color[0] = ( w1 * b1[0] + w2 * b2[0] + w3 * b3[0] + w4 * b4[0] ) >> 8;
107 color[1] = ( w1 * b1[1] + w2 * b2[1] + w3 * b3[1] + w4 * b4[1] ) >> 8;
108 color[2] = ( w1 * b1[2] + w2 * b2[2] + w3 * b3[2] + w4 * b4[2] ) >> 8;
109
110 VectorMA( lightcolor, 1.0f / 255, color, lightcolor );
111
112 return qtrue;
113 }
114
115 /* check far side */
116 return GL_LightPoint_r( node->children[side^1], mid, end );
117
118 }
119
GL_LightPoint(vec3_t origin,vec3_t dest)120 void GL_LightPoint( vec3_t origin, vec3_t dest ) {
121 extern cvar_t *gl_modulate_hack;
122 vec3_t point;
123 dlight_t *light;
124 vec3_t dir;
125 vec_t dist, f;
126 int i;
127
128 if( !r_world.name[0] || gl_fullbright->integer ) {
129 VectorSet( dest, 1, 1, 1 );
130 return;
131 }
132
133 point[0] = origin[0];
134 point[1] = origin[1];
135 point[2] = origin[2] - 8192;
136
137 VectorClear( lightcolor );
138 if( !r_world.lightmap || !GL_LightPoint_r( r_world.nodes, origin, point ) ) {
139 VectorSet( lightcolor, 1, 1, 1 );
140 }
141
142 if( gl_modulate_hack && gl_modulate_hack->integer ) {
143 VectorScale( lightcolor, gl_modulate->value, lightcolor );
144 }
145
146 for( i = 0, light = glr.fd.dlights; i < glr.fd.num_dlights; i++, light++ ) {
147 VectorSubtract( light->origin, origin, dir );
148 dist = VectorLength( dir );
149 if( dist > light->intensity ) {
150 continue;
151 }
152 f = 1.0f - dist / light->intensity;
153 VectorMA( lightcolor, f, light->color, lightcolor );
154 }
155
156 /* apply modulate twice to mimic original ref_gl behavior */
157 VectorScale( lightcolor, gl_modulate->value, lightcolor );
158
159 for( i = 0; i < 3; i++ ) {
160 if( lightcolor[i] > 1 ) {
161 lightcolor[i] = 1;
162 } else if( lightcolor[i] < 0 ) {
163 lightcolor[i] = 0;
164 }
165 }
166
167 VectorCopy( lightcolor, dest );
168
169 }
170
GL_MarkLights_r(bspNode_t * node,dlight_t * light)171 static void GL_MarkLights_r( bspNode_t *node, dlight_t *light ) {
172 cplane_t *plane;
173 vec_t dot;
174 int lightbit, count;
175 bspSurface_t *face;
176
177 if( !( plane = node->plane ) ) {
178 return;
179 }
180
181 switch( plane->type ) {
182 case PLANE_X:
183 dot = light->transformed[0] - plane->dist;
184 break;
185 case PLANE_Y:
186 dot = light->transformed[1] - plane->dist;
187 break;
188 case PLANE_Z:
189 dot = light->transformed[2] - plane->dist;
190 break;
191 default:
192 dot = DotProduct( light->transformed, plane->normal ) - plane->dist;
193 break;
194 }
195
196 if( dot > light->intensity ) {
197 GL_MarkLights_r( node->children[0], light );
198 return;
199 }
200 if( dot < -light->intensity ) {
201 GL_MarkLights_r( node->children[1], light );
202 return;
203 }
204
205 lightbit = 1 << light->index;
206 face = node->firstFace;
207 count = node->numFaces;
208 while( count-- ) {
209 if( !( face->texinfo->flags & NOLIGHT_MASK ) ) {
210 if( face->dlightframe != glr.drawframe ) {
211 face->dlightframe = glr.drawframe;
212 face->dlightbits = 0;
213 }
214
215 face->dlightbits |= lightbit;
216 }
217 face++;
218 }
219
220 GL_MarkLights_r( node->children[0], light );
221 GL_MarkLights_r( node->children[1], light );
222 }
223
GL_MarkLights(void)224 void GL_MarkLights( void ) {
225 int i;
226 dlight_t *light;
227
228 for( i = 0, light = glr.fd.dlights; i < glr.fd.num_dlights; i++, light++ ) {
229 light->index = i;
230 VectorCopy( light->origin, light->transformed );
231 GL_MarkLights_r( r_world.nodes, light );
232 }
233 }
234
GL_TransformLights(bspSubmodel_t * model)235 static void GL_TransformLights( bspSubmodel_t *model ) {
236 int i;
237 dlight_t *light;
238 vec3_t temp;
239
240 if( !model->headnode ) {
241 // this happens on some maps
242 // could lead to a crash of the original ref_gl
243 //Com_WPrintf( "GL_TransformLights: NULL headnode\n" );
244 return;
245 }
246
247 for( i = 0, light = glr.fd.dlights; i < glr.fd.num_dlights; i++, light++ ) {
248 light->index = i;
249 VectorSubtract( light->origin, glr.ent->origin, temp );
250 light->transformed[0] = DotProduct( temp, glr.entaxis[0] );
251 light->transformed[1] = DotProduct( temp, glr.entaxis[1] );
252 light->transformed[2] = DotProduct( temp, glr.entaxis[2] );
253
254 GL_MarkLights_r( model->headnode, light );
255
256 }
257
258 }
259
GL_MarkLeaves(void)260 void GL_MarkLeaves( void ) {
261 byte fatvis[MAX_MAP_LEAFS/8];
262 bspLeaf_t *leaf, *lastleaf;
263 bspNode_t *node, *lastnode;
264 byte *vis1, *vis2;
265 uint32 *dst, *src1, *src2;
266 int cluster1, cluster2, longs;
267 vec3_t tmp;
268 static int lastNodesVisible;
269
270 leaf = Bsp_FindLeaf( glr.fd.vieworg );
271 cluster1 = cluster2 = leaf->cluster;
272 VectorCopy( glr.fd.vieworg, tmp );
273 if( !leaf->contents ) {
274 tmp[2] -= 16;
275 } else {
276 tmp[2] += 16;
277 }
278 leaf = Bsp_FindLeaf( tmp );
279 if( !( leaf->contents & CONTENTS_SOLID ) ) {
280 cluster2 = leaf->cluster;
281 }
282
283 if( cluster1 == glr.viewcluster1 && cluster2 == glr.viewcluster2 ) {
284 goto finish;
285 }
286
287 if( gl_lockpvs->integer ) {
288 goto finish;
289 }
290
291 vis1 = vis2 = Bsp_ClusterPVS( cluster1 );
292 if( cluster1 != cluster2 ) {
293 vis2 = Bsp_ClusterPVS( cluster2 );
294 if( !vis1 ) {
295 vis1 = vis2;
296 } else if( !vis2 ) {
297 vis2 = vis1;
298 }
299 }
300 glr.visframe++;
301 lastNodesVisible = 0;
302 glr.viewcluster1 = cluster1;
303 glr.viewcluster2 = cluster2;
304
305 if( !vis1 || gl_novis->integer ) {
306 /* mark everything visible */
307 lastleaf = r_world.leafs + r_world.numLeafs;
308 for( leaf = r_world.leafs; leaf != lastleaf; leaf++ ) {
309 leaf->visframe = glr.visframe;
310 }
311 lastnode = r_world.nodes + r_world.numNodes;
312 for( node = r_world.nodes; node != lastnode; node++ ) {
313 node->visframe = glr.visframe;
314 }
315 lastNodesVisible = r_world.numNodes;
316 goto finish;
317 }
318
319 if( vis1 != vis2 ) {
320 longs = ( r_world.numClusters + 31 ) >> 5;
321 src1 = ( uint32 * )vis1;
322 src2 = ( uint32 * )vis2;
323 dst = ( uint32 * )fatvis;
324 while( longs-- ) {
325 *dst++ = *src1++ | *src2++;
326 }
327 vis1 = fatvis;
328 }
329
330 lastleaf = r_world.leafs + r_world.numLeafs;
331 for( leaf = r_world.leafs; leaf != lastleaf; leaf++ ) {
332 cluster1 = leaf->cluster;
333 if( cluster1 == -1 ) {
334 continue;
335 }
336 if( Q_IsBitSet( vis1, cluster1 ) ) {
337 node = ( bspNode_t * )leaf;
338
339 /* mark parent nodes visible */
340 do {
341 if( node->visframe == glr.visframe ) {
342 break;
343 }
344 node->visframe = glr.visframe;
345 node = node->parent;
346 lastNodesVisible++;
347 } while( node );
348 }
349 }
350
351 finish:
352 c.nodesVisible = lastNodesVisible;
353
354 }
355
356 #define NODE_CLIPPED 0
357 #define NODE_UNCLIPPED 15
358
GL_ClipNodeToFrustum(bspNode_t * node,int * clipflags)359 static qboolean GL_ClipNodeToFrustum( bspNode_t *node, int *clipflags ) {
360 int flags = *clipflags;
361 int i, bits;
362
363 for( i = 0; i < 4; i++ ) {
364 if( flags & ( 1 << i ) ) {
365 continue;
366 }
367 bits = BoxOnPlaneSide( node->mins, node->maxs,
368 &glr.frustumPlanes[i] );
369 if( bits == BOX_BEHIND ) {
370 return qfalse;
371 }
372 if( bits == BOX_INFRONT ) {
373 flags |= 1 << i;
374 }
375 }
376
377 *clipflags = flags;
378
379 return qtrue;
380 }
381
382 typedef void (*drawFaceFunc_t)( bspSurface_t *surf );
383
384 static drawFaceFunc_t drawFaceFunc;
385 static drawFaceFunc_t drawFaceFuncTable[] = {
386 GL_AddBspSurface,
387 GL_DrawSurfPoly
388 };
389
390 static bspSurface_t *alphaFaces;
391
392 #define BACKFACE_EPSILON 0.001f
393
394 #define SIDE_FRONT 0
395 #define SIDE_BACK 1
396
GL_DrawBspModel(bspSubmodel_t * model)397 void GL_DrawBspModel( bspSubmodel_t *model ) {
398 bspSurface_t *face;
399 int count;
400 vec3_t bounds[2];
401 vec_t dot;
402 cplane_t *plane;
403 vec3_t temp;
404 entity_t *ent = glr.ent;
405 glCullResult_t cull;
406
407 if( glr.entrotated ) {
408 cull = GL_CullSphere( ent->origin, model->radius );
409 if( cull == CULL_OUT ) {
410 c.spheresCulled++;
411 return;
412 }
413 if( cull == CULL_CLIP ) {
414 VectorCopy( model->mins, bounds[0] );
415 VectorCopy( model->maxs, bounds[1] );
416 cull = GL_CullLocalBox( ent->origin, bounds );
417 if( cull == CULL_OUT ) {
418 c.rotatedBoxesCulled++;
419 return;
420 }
421 }
422 VectorSubtract( glr.fd.vieworg, ent->origin, temp );
423 modelViewOrigin[0] = DotProduct( temp, glr.entaxis[0] );
424 modelViewOrigin[1] = DotProduct( temp, glr.entaxis[1] );
425 modelViewOrigin[2] = DotProduct( temp, glr.entaxis[2] );
426 } else {
427 VectorAdd( model->mins, ent->origin, bounds[0] );
428 VectorAdd( model->maxs, ent->origin, bounds[1] );
429 cull = GL_CullBox( bounds );
430 if( cull == CULL_OUT ) {
431 c.boxesCulled++;
432 return;
433 }
434 VectorSubtract( glr.fd.vieworg, ent->origin, modelViewOrigin );
435 }
436
437 glr.drawframe++;
438
439 if( gl_dynamic->integer ) {
440 GL_TransformLights( model );
441 }
442
443 /* draw visible faces */
444 /* FIXME: go by headnode instead? */
445 face = model->firstFace;
446 count = model->numFaces;
447 while( count-- ) {
448 plane = face->plane;
449 switch( plane->type ) {
450 case PLANE_X:
451 dot = modelViewOrigin[0] - plane->dist;
452 break;
453 case PLANE_Y:
454 dot = modelViewOrigin[1] - plane->dist;
455 break;
456 case PLANE_Z:
457 dot = modelViewOrigin[2] - plane->dist;
458 break;
459 default:
460 dot = DotProduct( modelViewOrigin, plane->normal ) - plane->dist;
461 break;
462 }
463 if( ( dot < -BACKFACE_EPSILON && face->side == SIDE_FRONT ) ||
464 ( dot > BACKFACE_EPSILON && face->side == SIDE_BACK ) )
465 {
466 c.facesCulled++;
467 } else {
468 if( face->texinfo->flags & (SURF_TRANS33|SURF_TRANS66) ) {
469 face->next = alphaFaces;
470 alphaFaces = face;
471 } else {
472 GL_AddBspSurface( face );
473 }
474 c.facesDrawn++;
475 }
476 face++;
477 }
478
479 qglPushMatrix();
480 qglTranslatef( ent->origin[0], ent->origin[1], ent->origin[2] );
481 if( glr.entrotated ) {
482 qglRotatef( ent->angles[YAW], 0, 0, 1 );
483 qglRotatef( ent->angles[PITCH], 0, 1, 0 );
484 qglRotatef( ent->angles[ROLL], 1, 0, 0 );
485 }
486 GL_SortAndDrawSurfs( qtrue );
487 qglPopMatrix();
488
489 }
490
GL_WorldNode_r(bspNode_t * node,int clipflags)491 static void GL_WorldNode_r( bspNode_t *node, int clipflags ) {
492 bspLeaf_t *leaf;
493 bspSurface_t **leafFace, *face;
494 int count, side, area;
495 cplane_t *plane;
496 vec_t dot;
497 uint32 type;
498
499 if( node->visframe != glr.visframe ) {
500 return;
501 }
502
503 if( gl_cull_nodes->integer && clipflags != NODE_UNCLIPPED &&
504 GL_ClipNodeToFrustum( node, &clipflags ) == qfalse )
505 {
506 c.nodesCulled++;
507 return;
508 }
509
510 if( !node->plane ) {
511 /* found a leaf */
512 leaf = ( bspLeaf_t * )node;
513 if( leaf->contents == CONTENTS_SOLID ) {
514 return;
515 }
516 area = leaf->area;
517 if( !glr.fd.areabits || Q_IsBitSet( glr.fd.areabits, area ) ) {
518 leafFace = leaf->firstLeafFace;
519 count = leaf->numLeafFaces;
520 while( count-- ) {
521 face = *leafFace++;
522 face->drawframe = glr.drawframe;
523 }
524 }
525 return;
526 }
527
528 plane = node->plane;
529 type = plane->type;
530 if( type < 3 ) {
531 dot = modelViewOrigin[type] - plane->dist;
532 } else {
533 dot = DotProduct( modelViewOrigin, plane->normal ) - plane->dist;
534 }
535
536 side = dot < 0;
537
538 GL_WorldNode_r( node->children[side], clipflags );
539
540 face = node->firstFace;
541 count = node->numFaces;
542 while( count-- ) {
543 if( face->drawframe == glr.drawframe ) {
544 if( face->side == side ) {
545 if( face->texinfo->flags & (SURF_TRANS33|SURF_TRANS66) ) {
546 face->next = alphaFaces;
547 alphaFaces = face;
548 } else {
549 drawFaceFunc( face );
550 }
551 c.facesDrawn++;
552 } else {
553 c.facesCulled++;
554 }
555 }
556 face++;
557 }
558
559 GL_WorldNode_r( node->children[ side ^ 1 ], clipflags );
560 c.nodesDrawn++;
561 }
562
GL_DrawWorld(void)563 void GL_DrawWorld( void ) {
564 GL_MarkLeaves();
565
566 if( gl_dynamic->integer ) {
567 GL_MarkLights();
568 }
569
570 R_ClearSkyBox();
571
572 drawFaceFunc = drawFaceFuncTable[gl_primitives->integer & 1];
573
574 VectorCopy( glr.fd.vieworg, modelViewOrigin );
575
576 GL_WorldNode_r( r_world.nodes, NODE_CLIPPED );
577 GL_SortAndDrawSurfs( qtrue );
578
579 if( !gl_fastsky->integer ) {
580 R_DrawSkyBox();
581 }
582
583 }
584
GL_DrawAlphaFaces(void)585 void GL_DrawAlphaFaces( void ) {
586 bspSurface_t *face, *next;
587
588 face = alphaFaces;
589 if( !face ) {
590 return;
591 }
592
593 drawFaceFunc = drawFaceFuncTable[gl_primitives->integer & 1];
594
595 do {
596 drawFaceFunc( face );
597 /* Prevent loop condition in case the same face is included twice.
598 * This should never happen normally. */
599 next = face->next;
600 face->next = NULL;
601 face = next;
602 } while( face );
603
604 GL_SortAndDrawSurfs( qfalse );
605
606 alphaFaces = NULL;
607 }
608