1 /*
2  * Copyright (C) 1997-2001 Id Software, Inc.
3  *
4  * This program is free software; you can redistribute it and/or modify it under
5  * the terms of the GNU General Public License as published by the Free
6  * Software Foundation; either version 2 of the License, or (at your option)
7  * any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * 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 along with
16  * this program; if not, write to the Free Software Foundation, Inc., 59
17  * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18  *
19  */
20 /* world.c -- world query functions */
21 
22 #include "server.h"
23 
24 /*
25  *
26  * ============================================================================
27  * ===
28  *
29  * ENTITY AREA CHECKING
30  *
31  * FIXME: this use of "area" is different from the bsp file use
32  * ===========================================================================
33  * ====
34  */
35 
36 /* (type *)STRUCT_FROM_LINK(link_t *link, type, member) */
37 /* ent = STRUCT_FROM_LINK(link,entity_t,order) */
38 /* FIXME: remove this mess! */
39 #define	STRUCT_FROM_LINK(l,t,m) ((t *)((byte *)l - (int)&(((t *)0)->m)))
40 
41 #define	EDICT_FROM_AREA(l) STRUCT_FROM_LINK(l,edict_t,area)
42 
43 typedef struct areanode_s {
44 	int		axis;	/* -1 = leaf node */
45 	float		dist;
46 	struct areanode_s *children[2];
47 	link_t		trigger_edicts;
48 	link_t		solid_edicts;
49 } areanode_t;
50 
51 #define	AREA_DEPTH	4
52 #define	AREA_NODES	32
53 
54 areanode_t	sv_areanodes[AREA_NODES];
55 int		sv_numareanodes;
56 
57 float          *area_mins, *area_maxs;
58 edict_t       **area_list;
59 int		area_count, area_maxcount;
60 int		area_type;
61 
62 int		SV_HullForEntity(edict_t * ent);
63 
64 
65 /* ClearLink is used for new headnodes */
66 void
ClearLink(link_t * l)67 ClearLink(link_t * l)
68 {
69 	l->prev = l->next = l;
70 }
71 
72 void
RemoveLink(link_t * l)73 RemoveLink(link_t * l)
74 {
75 	l->next->prev = l->prev;
76 	l->prev->next = l->next;
77 }
78 
79 void
InsertLinkBefore(link_t * l,link_t * before)80 InsertLinkBefore(link_t * l, link_t * before)
81 {
82 	l->next = before;
83 	l->prev = before->prev;
84 	l->prev->next = l;
85 	l->next->prev = l;
86 }
87 
88 /*
89  * =============== SV_CreateAreaNode
90  *
91  * Builds a uniformly subdivided tree for the given world size ===============
92  */
93 areanode_t     *
SV_CreateAreaNode(int depth,vec3_t mins,vec3_t maxs)94 SV_CreateAreaNode(int depth, vec3_t mins, vec3_t maxs)
95 {
96 	areanode_t     *anode;
97 	vec3_t		size;
98 	vec3_t		mins1, maxs1, mins2, maxs2;
99 
100 	anode = &sv_areanodes[sv_numareanodes];
101 	sv_numareanodes++;
102 
103 	ClearLink(&anode->trigger_edicts);
104 	ClearLink(&anode->solid_edicts);
105 
106 	if (depth == AREA_DEPTH) {
107 		anode->axis = -1;
108 		anode->children[0] = anode->children[1] = NULL;
109 		return anode;
110 	}
111 	VectorSubtract(maxs, mins, size);
112 	if (size[0] > size[1])
113 		anode->axis = 0;
114 	else
115 		anode->axis = 1;
116 
117 	anode->dist = 0.5 * (maxs[anode->axis] + mins[anode->axis]);
118 	VectorCopy(mins, mins1);
119 	VectorCopy(mins, mins2);
120 	VectorCopy(maxs, maxs1);
121 	VectorCopy(maxs, maxs2);
122 
123 	maxs1[anode->axis] = mins2[anode->axis] = anode->dist;
124 
125 	anode->children[0] = SV_CreateAreaNode(depth + 1, mins2, maxs2);
126 	anode->children[1] = SV_CreateAreaNode(depth + 1, mins1, maxs1);
127 
128 	return anode;
129 }
130 
131 /*
132  * =============== SV_ClearWorld
133  *
134  * ===============
135  */
136 void
SV_ClearWorld(void)137 SV_ClearWorld(void)
138 {
139 	memset(sv_areanodes, 0, sizeof(sv_areanodes));
140 	sv_numareanodes = 0;
141 	SV_CreateAreaNode(0, sv.models[1]->mins, sv.models[1]->maxs);
142 }
143 
144 
145 /*
146  * =============== SV_UnlinkEdict
147  *
148  * ===============
149  */
150 void
SV_UnlinkEdict(edict_t * ent)151 SV_UnlinkEdict(edict_t * ent)
152 {
153 	if (!ent->area.prev)
154 		return;		/* not linked in anywhere */
155 	RemoveLink(&ent->area);
156 	ent->area.prev = ent->area.next = NULL;
157 }
158 
159 
160 /*
161  * =============== SV_LinkEdict
162  *
163  * ===============
164  */
165 #define MAX_TOTAL_ENT_LEAFS		128
166 void
SV_LinkEdict(edict_t * ent)167 SV_LinkEdict(edict_t * ent)
168 {
169 	areanode_t     *node;
170 	int		leafs[MAX_TOTAL_ENT_LEAFS];
171 	int		clusters[MAX_TOTAL_ENT_LEAFS];
172 	int		num_leafs;
173 	int		i, j, k;
174 	int		area;
175 	int		topnode;
176 
177 	if (ent->area.prev)
178 		SV_UnlinkEdict(ent);	/* unlink from old position */
179 
180 	if (ent == ge->edicts)
181 		return;		/* don't add the world */
182 
183 	if (!ent->inuse)
184 		return;
185 
186 	/* set the size */
187 	VectorSubtract(ent->maxs, ent->mins, ent->size);
188 
189 	/* encode the size into the entity_state for client prediction */
190 	if (ent->solid == SOLID_BBOX && !(ent->svflags & SVF_DEADMONSTER)) {	/* assume that x/y are
191 										 * equal and symetric */
192 		i = ent->maxs[0] / 8;
193 		if (i < 1)
194 			i = 1;
195 		if (i > 31)
196 			i = 31;
197 
198 		/* z is not symetric */
199 		j = (-ent->mins[2]) / 8;
200 		if (j < 1)
201 			j = 1;
202 		if (j > 31)
203 			j = 31;
204 
205 		/* and z maxs can be negative... */
206 		k = (ent->maxs[2] + 32) / 8;
207 		if (k < 1)
208 			k = 1;
209 		if (k > 63)
210 			k = 63;
211 
212 		ent->s.solid = (k << 10) | (j << 5) | i;
213 	} else if (ent->solid == SOLID_BSP) {
214 		ent->s.solid = 31;	/* a solid_bbox will never create
215 					 * this value */
216 	} else
217 		ent->s.solid = 0;
218 
219 	/* set the abs box */
220 	if (ent->solid == SOLID_BSP &&
221 	    (ent->s.angles[0] || ent->s.angles[1] || ent->s.angles[2])) {	/* expand for rotation */
222 		float		max     , v;
223 
224 		max = 0;
225 		for (i = 0; i < 3; i++) {
226 			v = fabs(ent->mins[i]);
227 			if (v > max)
228 				max = v;
229 			v = fabs(ent->maxs[i]);
230 			if (v > max)
231 				max = v;
232 		}
233 		for (i = 0; i < 3; i++) {
234 			ent->absmin[i] = ent->s.origin[i] - max;
235 			ent->absmax[i] = ent->s.origin[i] + max;
236 		}
237 	} else {		/* normal */
238 		VectorAdd(ent->s.origin, ent->mins, ent->absmin);
239 		VectorAdd(ent->s.origin, ent->maxs, ent->absmax);
240 	}
241 
242 	/* because movement is clipped an epsilon away from an actual edge, */
243 	/* we must fully check even when bounding boxes don't quite touch */
244 	ent->absmin[0] -= 1;
245 	ent->absmin[1] -= 1;
246 	ent->absmin[2] -= 1;
247 	ent->absmax[0] += 1;
248 	ent->absmax[1] += 1;
249 	ent->absmax[2] += 1;
250 
251 	/* link to PVS leafs */
252 	ent->num_clusters = 0;
253 	ent->areanum = 0;
254 	ent->areanum2 = 0;
255 
256 	/* get all leafs, including solids */
257 	num_leafs = CM_BoxLeafnums(ent->absmin, ent->absmax,
258 	    leafs, MAX_TOTAL_ENT_LEAFS, &topnode);
259 
260 	/* set areas */
261 	for (i = 0; i < num_leafs; i++) {
262 		clusters[i] = CM_LeafCluster(leafs[i]);
263 		area = CM_LeafArea(leafs[i]);
264 		if (area) {	/* doors may legally straggle two areas, */
265 			/* but nothing should evern need more than that */
266 			if (ent->areanum && ent->areanum != area) {
267 				if (ent->areanum2 && ent->areanum2 != area && sv.state == ss_loading)
268 					Com_DPrintf("Object touching 3 areas at %f %f %f\n",
269 					    ent->absmin[0], ent->absmin[1], ent->absmin[2]);
270 				ent->areanum2 = area;
271 			} else
272 				ent->areanum = area;
273 		}
274 	}
275 
276 	if (num_leafs >= MAX_TOTAL_ENT_LEAFS) {	/* assume we missed some
277 						 * leafs, and mark by
278 						 * headnode */
279 		ent->num_clusters = -1;
280 		ent->headnode = topnode;
281 	} else {
282 		ent->num_clusters = 0;
283 		for (i = 0; i < num_leafs; i++) {
284 			if (clusters[i] == -1)
285 				continue;	/* not a visible leaf */
286 			for (j = 0; j < i; j++)
287 				if (clusters[j] == clusters[i])
288 					break;
289 			if (j == i) {
290 				if (ent->num_clusters == MAX_ENT_CLUSTERS) {	/* assume we missed some
291 										 * leafs, and mark by
292 										 * headnode */
293 					ent->num_clusters = -1;
294 					ent->headnode = topnode;
295 					break;
296 				}
297 				ent->clusternums[ent->num_clusters++] = clusters[i];
298 			}
299 		}
300 	}
301 
302 	/* if first time, make sure old_origin is valid */
303 	if (!ent->linkcount) {
304 		VectorCopy(ent->s.origin, ent->s.old_origin);
305 	}
306 	ent->linkcount++;
307 
308 	if (ent->solid == SOLID_NOT)
309 		return;
310 
311 	/* find the first node that the ent's box crosses */
312 	node = sv_areanodes;
313 	while (1) {
314 		if (node->axis == -1)
315 			break;
316 		if (ent->absmin[node->axis] > node->dist)
317 			node = node->children[0];
318 		else if (ent->absmax[node->axis] < node->dist)
319 			node = node->children[1];
320 		else
321 			break;	/* crosses the node */
322 	}
323 
324 	/* link it in	 */
325 	if (ent->solid == SOLID_TRIGGER)
326 		InsertLinkBefore(&ent->area, &node->trigger_edicts);
327 	else
328 		InsertLinkBefore(&ent->area, &node->solid_edicts);
329 
330 }
331 
332 
333 /*
334  * ==================== SV_AreaEdicts_r
335  *
336  * ====================
337  */
338 void
SV_AreaEdicts_r(areanode_t * node)339 SV_AreaEdicts_r(areanode_t * node)
340 {
341 	link_t         *l, *next, *start;
342 	edict_t        *check;
343 	int		count;
344 
345 	count = 0;
346 
347 	/* touch linked edicts */
348 	if (area_type == AREA_SOLID)
349 		start = &node->solid_edicts;
350 	else
351 		start = &node->trigger_edicts;
352 
353 	for (l = start->next; l != start; l = next) {
354 		next = l->next;
355 		check = EDICT_FROM_AREA(l);
356 
357 		if (check->solid == SOLID_NOT)
358 			continue;	/* deactivated */
359 		if (check->absmin[0] > area_maxs[0]
360 		    || check->absmin[1] > area_maxs[1]
361 		    || check->absmin[2] > area_maxs[2]
362 		    || check->absmax[0] < area_mins[0]
363 		    || check->absmax[1] < area_mins[1]
364 		    || check->absmax[2] < area_mins[2])
365 			continue;	/* not touching */
366 
367 		if (area_count == area_maxcount) {
368 			Com_Printf("SV_AreaEdicts: MAXCOUNT\n");
369 			return;
370 		}
371 		area_list[area_count] = check;
372 		area_count++;
373 	}
374 
375 	if (node->axis == -1)
376 		return;		/* terminal node */
377 
378 	/* recurse down both sides */
379 	if (area_maxs[node->axis] > node->dist)
380 		SV_AreaEdicts_r(node->children[0]);
381 	if (area_mins[node->axis] < node->dist)
382 		SV_AreaEdicts_r(node->children[1]);
383 }
384 
385 /*
386  * ================ SV_AreaEdicts ================
387  */
388 int
SV_AreaEdicts(vec3_t mins,vec3_t maxs,edict_t ** list,int maxcount,int areatype)389 SV_AreaEdicts(vec3_t mins, vec3_t maxs, edict_t ** list,
390     int maxcount, int areatype)
391 {
392 	area_mins = mins;
393 	area_maxs = maxs;
394 	area_list = list;
395 	area_count = 0;
396 	area_maxcount = maxcount;
397 	area_type = areatype;
398 
399 	SV_AreaEdicts_r(sv_areanodes);
400 
401 	return area_count;
402 }
403 
404 
405 /*
406  * ===========================================================================
407  *
408  */
409 
410 /*
411  * ============= SV_PointContents =============
412  */
413 int
SV_PointContents(vec3_t p)414 SV_PointContents(vec3_t p)
415 {
416 	edict_t        *touch[MAX_EDICTS], *hit;
417 	int		i, num;
418 	int		contents, c2;
419 	int		headnode;
420 	float          *angles;
421 
422 	/* get base contents from world */
423 	contents = CM_PointContents(p, sv.models[1]->headnode);
424 
425 	/* or in contents from all the other entities */
426 	num = SV_AreaEdicts(p, p, touch, MAX_EDICTS, AREA_SOLID);
427 
428 	for (i = 0; i < num; i++) {
429 		hit = touch[i];
430 
431 		/* might intersect, so do an exact clip */
432 		headnode = SV_HullForEntity(hit);
433 		angles = hit->s.angles;
434 		if (hit->solid != SOLID_BSP)
435 			angles = vec3_origin;	/* boxes don't rotate */
436 
437 		c2 = CM_TransformedPointContents(p, headnode, hit->s.origin, hit->s.angles);
438 
439 		contents |= c2;
440 	}
441 
442 	return contents;
443 }
444 
445 
446 
447 typedef struct {
448 	vec3_t		boxmins, boxmaxs;	/* enclose the test object along entire move */
449 	float          *mins, *maxs;		/* size of the moving object */
450 	vec3_t		mins2, maxs2;		/* size when clipping against monsters */
451 	float          *start, *end;
452 	trace_t		trace;
453 	edict_t        *passedict;
454 	int		contentmask;
455 } moveclip_t;
456 
457 
458 
459 /*
460  * ================ SV_HullForEntity
461  *
462  * Returns a headnode that can be used for testing or clipping an object of
463  * mins/maxs size. Offset is filled in to contain the adjustment that must be
464  * added to the testing object's origin to get a point to use with the
465  * returned hull. ================
466  */
467 int
SV_HullForEntity(edict_t * ent)468 SV_HullForEntity(edict_t * ent)
469 {
470 	cmodel_t       *model;
471 
472 	/* decide which clipping hull to use, based on the size */
473 	if (ent->solid == SOLID_BSP) {	/* explicit hulls in the BSP model */
474 		model = sv.models[ent->s.modelindex];
475 
476 		if (!model)
477 			Com_Error(ERR_FATAL, "MOVETYPE_PUSH with a non bsp model");
478 
479 		return model->headnode;
480 	}
481 	/* create a temp hull from bounding box sizes */
482 
483 	return CM_HeadnodeForBox(ent->mins, ent->maxs);
484 }
485 
486 
487 /*
488  * ===========================================================================
489  *
490  */
491 
492 /*
493  * ==================== SV_ClipMoveToEntities
494  *
495  * ====================
496  */
497 void
SV_ClipMoveToEntities(moveclip_t * clip)498 SV_ClipMoveToEntities(moveclip_t * clip)
499 {
500 	int		i, num;
501 	edict_t        *touchlist[MAX_EDICTS], *touch;
502 	trace_t		trace;
503 	int		headnode;
504 	float          *angles;
505 
506 	num = SV_AreaEdicts(clip->boxmins, clip->boxmaxs, touchlist
507 	    ,MAX_EDICTS, AREA_SOLID);
508 
509 	/* be careful, it is possible to have an entity in this */
510 	/* list removed before we get to it (killtriggered) */
511 	for (i = 0; i < num; i++) {
512 		touch = touchlist[i];
513 		if (touch->solid == SOLID_NOT)
514 			continue;
515 		if (touch == clip->passedict)
516 			continue;
517 		if (clip->trace.allsolid)
518 			return;
519 		if (clip->passedict) {
520 			if (touch->owner == clip->passedict)
521 				continue;	/* don't clip against own
522 						 * missiles */
523 			if (clip->passedict->owner == touch)
524 				continue;	/* don't clip against owner */
525 		}
526 		if (!(clip->contentmask & CONTENTS_DEADMONSTER)
527 		    && (touch->svflags & SVF_DEADMONSTER))
528 			continue;
529 
530 		/* might intersect, so do an exact clip */
531 		headnode = SV_HullForEntity(touch);
532 		angles = touch->s.angles;
533 		if (touch->solid != SOLID_BSP)
534 			angles = vec3_origin;	/* boxes don't rotate */
535 
536 		if (touch->svflags & SVF_MONSTER)
537 			trace = CM_TransformedBoxTrace(clip->start, clip->end,
538 			    clip->mins2, clip->maxs2, headnode, clip->contentmask,
539 			    touch->s.origin, angles);
540 		else
541 			trace = CM_TransformedBoxTrace(clip->start, clip->end,
542 			    clip->mins, clip->maxs, headnode, clip->contentmask,
543 			    touch->s.origin, angles);
544 
545 		if (trace.allsolid || trace.startsolid ||
546 		    trace.fraction < clip->trace.fraction) {
547 			trace.ent = touch;
548 			if (clip->trace.startsolid) {
549 				clip->trace = trace;
550 				clip->trace.startsolid = true;
551 			} else
552 				clip->trace = trace;
553 		} else if (trace.startsolid)
554 			clip->trace.startsolid = true;
555 	}
556 }
557 
558 
559 /*
560  * ================== SV_TraceBounds ==================
561  */
562 void
SV_TraceBounds(vec3_t start,vec3_t mins,vec3_t maxs,vec3_t end,vec3_t boxmins,vec3_t boxmaxs)563 SV_TraceBounds(vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, vec3_t boxmins, vec3_t boxmaxs)
564 {
565 	int		i;
566 
567 	for (i = 0; i < 3; i++) {
568 		if (end[i] > start[i]) {
569 			boxmins[i] = start[i] + mins[i] - 1;
570 			boxmaxs[i] = end[i] + maxs[i] + 1;
571 		} else {
572 			boxmins[i] = end[i] + mins[i] - 1;
573 			boxmaxs[i] = start[i] + maxs[i] + 1;
574 		}
575 	}
576 }
577 
578 /*
579  * ================== SV_Trace
580  *
581  * Moves the given mins/maxs volume through the world from start to end.
582  *
583  * Passedict and edicts owned by passedict are explicitly not checked.
584  *
585  * ==================
586  */
587 trace_t
SV_Trace(vec3_t start,vec3_t mins,vec3_t maxs,vec3_t end,edict_t * passedict,int contentmask)588 SV_Trace(vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, edict_t * passedict, int contentmask)
589 {
590 	moveclip_t	clip;
591 
592 	if (!mins)
593 		mins = vec3_origin;
594 	if (!maxs)
595 		maxs = vec3_origin;
596 
597 	memset(&clip, 0, sizeof(moveclip_t));
598 
599 	/* clip to world */
600 	clip.trace = CM_BoxTrace(start, end, mins, maxs, 0, contentmask);
601 	clip.trace.ent = ge->edicts;
602 	if (clip.trace.fraction == 0)
603 		return clip.trace;	/* blocked by the world */
604 
605 	clip.contentmask = contentmask;
606 	clip.start = start;
607 	clip.end = end;
608 	clip.mins = mins;
609 	clip.maxs = maxs;
610 	clip.passedict = passedict;
611 
612 	VectorCopy(mins, clip.mins2);
613 	VectorCopy(maxs, clip.maxs2);
614 
615 	/* create the bounding box of the entire move */
616 	SV_TraceBounds(start, clip.mins2, clip.maxs2, end, clip.boxmins, clip.boxmaxs);
617 
618 	/* clip to other solid entities */
619 	SV_ClipMoveToEntities(&clip);
620 
621 	return clip.trace;
622 }
623