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