From a4bc6f57b4b1b2e7e73ec3aa1b64d3366bcff97c Mon Sep 17 00:00:00 2001
From: havoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Date: Tue, 9 Dec 2003 13:17:46 +0000
Subject: [PATCH] fixed the wall slide stuttering bug (the one that has been
 annoying me for months), it turned out to be a float precision issue with
 cliphull selection, and this also fixed the movetogoal bug (monsters not
 noticing they hit a wall) and also the scrags-flying-through-wall/ceilings
 bug

git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@3714 d7cf8633-e32d-0410-b094-e92efae38249
---
 model_brush.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++--
 sv_phys.c     | 14 +++++++++++-
 todo          | 17 ++++++++-------
 world.c       |  6 ++++++
 4 files changed, 85 insertions(+), 11 deletions(-)

diff --git a/model_brush.c b/model_brush.c
index 7a5257b6..641c1edd 100644
--- a/model_brush.c
+++ b/model_brush.c
@@ -416,11 +416,17 @@ loc0:
 			// if the first leaf is solid, set startsolid
 			if (t->trace->allsolid)
 				t->trace->startsolid = true;
+#ifdef COLLISIONPARANOID
+			Con_Printf("S");
+#endif
 			return HULLCHECKSTATE_SOLID;
 		}
 		else
 		{
 			t->trace->allsolid = false;
+#ifdef COLLISIONPARANOID
+			Con_Printf("E");
+#endif
 			return HULLCHECKSTATE_EMPTY;
 		}
 	}
@@ -444,6 +450,9 @@ loc0:
 	{
 		if (t2 < 0)
 		{
+#ifdef COLLISIONPARANOID
+			Con_Printf("<");
+#endif
 			num = node->children[1];
 			goto loc0;
 		}
@@ -453,6 +462,9 @@ loc0:
 	{
 		if (t2 >= 0)
 		{
+#ifdef COLLISIONPARANOID
+			Con_Printf(">");
+#endif
 			num = node->children[0];
 			goto loc0;
 		}
@@ -461,6 +473,9 @@ loc0:
 
 	// the line intersects, find intersection point
 	// LordHavoc: this uses the original trace for maximum accuracy
+#ifdef COLLISIONPARANOID
+	Con_Printf("M");
+#endif
 	if (plane->type < 3)
 	{
 		t1 = t->start[plane->type] - plane->dist;
@@ -506,9 +521,36 @@ loc0:
 	midf = t1 / (t1 - t2);
 	t->trace->fraction = bound(0.0f, midf, 1.0);
 
+#ifdef COLLISIONPARANOID
+	Con_Printf("D");
+#endif
 	return HULLCHECKSTATE_DONE;
 }
 
+#ifndef COLLISIONPARANOID
+static int Mod_Q1BSP_RecursiveHullCheckPoint(RecursiveHullCheckTraceInfo_t *t, int num)
+{
+	while (num >= 0)
+		num = t->hull->clipnodes[num].children[(t->hull->planes[t->hull->clipnodes[num].planenum].type < 3 ? t->start[t->hull->planes[t->hull->clipnodes[num].planenum].type] : DotProduct(t->hull->planes[t->hull->clipnodes[num].planenum].normal, t->start)) < t->hull->planes[t->hull->clipnodes[num].planenum].dist];
+	num = Mod_Q1BSP_SuperContentsFromNativeContents(NULL, num);
+	t->trace->startsupercontents |= num;
+	if (num & SUPERCONTENTS_LIQUIDSMASK)
+		t->trace->inwater = true;
+	if (num == 0)
+		t->trace->inopen = true;
+	if (num & t->trace->hitsupercontentsmask)
+	{
+		t->trace->allsolid = t->trace->startsolid = true;
+		return HULLCHECKSTATE_SOLID;
+	}
+	else
+	{
+		t->trace->allsolid = t->trace->startsolid = false;
+		return HULLCHECKSTATE_EMPTY;
+	}
+}
+#endif
+
 static void Mod_Q1BSP_TraceBox(struct model_s *model, int frame, trace_t *trace, const vec3_t boxstartmins, const vec3_t boxstartmaxs, const vec3_t boxendmins, const vec3_t boxendmaxs, int hitsupercontentsmask)
 {
 	// this function currently only supports same size start and end
@@ -526,7 +568,9 @@ static void Mod_Q1BSP_TraceBox(struct model_s *model, int frame, trace_t *trace,
 		rhc.hull = &model->brushq1.hulls[0]; // 0x0x0
 	else if (model->brush.ishlbsp)
 	{
-		if (boxsize[0] <= 32)
+		// LordHavoc: this has to have a minor tolerance (the .1) because of
+		// minor float precision errors from the box being transformed around
+		if (boxsize[0] < 32.1)
 		{
 			if (boxsize[2] < 54) // pick the nearest of 36 or 72
 				rhc.hull = &model->brushq1.hulls[3]; // 32x32x36
@@ -538,7 +582,9 @@ static void Mod_Q1BSP_TraceBox(struct model_s *model, int frame, trace_t *trace,
 	}
 	else
 	{
-		if (boxsize[0] <= 32)
+		// LordHavoc: this has to have a minor tolerance (the .1) because of
+		// minor float precision errors from the box being transformed around
+		if (boxsize[0] < 32.1)
 			rhc.hull = &model->brushq1.hulls[1]; // 32x32x56
 		else
 			rhc.hull = &model->brushq1.hulls[2]; // 64x64x88
@@ -546,7 +592,16 @@ static void Mod_Q1BSP_TraceBox(struct model_s *model, int frame, trace_t *trace,
 	VectorSubtract(boxstartmins, rhc.hull->clip_mins, rhc.start);
 	VectorSubtract(boxendmins, rhc.hull->clip_mins, rhc.end);
 	VectorSubtract(rhc.end, rhc.start, rhc.dist);
+#ifdef COLLISIONPARANOID
+	Con_Printf("t(%f %f %f,%f %f %f,%i %f %f %f)", rhc.start[0], rhc.start[1], rhc.start[2], rhc.end[0], rhc.end[1], rhc.end[2], rhc.hull - model->brushq1.hulls, rhc.hull->clip_mins[0], rhc.hull->clip_mins[1], rhc.hull->clip_mins[2]);
 	Mod_Q1BSP_RecursiveHullCheck(&rhc, rhc.hull->firstclipnode, 0, 1, rhc.start, rhc.end);
+	Con_Printf("\n");
+#else
+	if (DotProduct(rhc.dist, rhc.dist))
+		Mod_Q1BSP_RecursiveHullCheck(&rhc, rhc.hull->firstclipnode, 0, 1, rhc.start, rhc.end);
+	else
+		Mod_Q1BSP_RecursiveHullCheckPoint(&rhc, rhc.hull->firstclipnode);
+#endif
 }
 
 static int Mod_Q1BSP_LightPoint_RecursiveBSPNode(vec3_t ambientcolor, vec3_t diffusecolor, vec3_t diffusenormal, const mnode_t *node, float x, float y, float startz, float endz)
diff --git a/sv_phys.c b/sv_phys.c
index fd52653a..5b3e2965 100644
--- a/sv_phys.c
+++ b/sv_phys.c
@@ -247,6 +247,18 @@ int SV_FlyMove (edict_t *ent, float time, float *stepnormal)
 			VectorMA(ent->v->origin, time, ent->v->velocity, end);
 			trace = SV_Move (ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL, ent);
 			//Con_Printf("trace %f %f %f : %f : %f %f %f\n", trace.endpos[0], trace.endpos[1], trace.endpos[2], trace.fraction, trace.plane.normal[0], trace.plane.normal[1], trace.plane.normal[2]);
+#ifdef COLLISIONPARANOID
+			{
+				int endstuck;
+				vec3_t temp;
+				VectorCopy(trace.endpos, temp);
+				endstuck = SV_Move(temp, ent->v->mins, ent->v->maxs, temp, MOVE_WORLDONLY, ent).startsolid;
+				Con_Printf("%s{%i:%f %f %f:%f %f %f:%f:%f %f %f%s%s}\n", (trace.startsolid || endstuck) ? "\002" : "", bumpcount, ent->v->origin[0], ent->v->origin[1], ent->v->origin[2], end[0] - ent->v->origin[0], end[1] - ent->v->origin[1], end[2] - ent->v->origin[2], trace.fraction, trace.endpos[0] - ent->v->origin[0], trace.endpos[1] - ent->v->origin[1], trace.endpos[2] - ent->v->origin[2], trace.startsolid ? " startstuck" : "", endstuck ? " endstuck" : "");
+				//Con_Printf("trace %f %f %f : %f : %f %f %f\n", trace.endpos[0], trace.endpos[1], trace.endpos[2], trace.fraction, trace.plane.normal[0], trace.plane.normal[1], trace.plane.normal[2]);
+				if (endstuck)
+					Cbuf_AddText("disconnect\n");
+			}
+#endif
 
 			/*
 			if (trace.startsolid)
@@ -258,7 +270,7 @@ int SV_FlyMove (edict_t *ent, float time, float *stepnormal)
 			}
 			*/
 
-			if (trace.fraction > 0)
+			if (trace.fraction >= 0.001)
 			{
 				// actually covered some distance
 				VectorCopy (trace.endpos, ent->v->origin);
diff --git a/todo b/todo
index 5e44bc89..426a4f7a 100644
--- a/todo
+++ b/todo
@@ -35,6 +35,7 @@
 -n darkplaces: server is starting before the "port" cvar is set by commandline and scripts? (yummyluv)
 -n darkplaces: typing ip in join game menu should show 'trying' and 'no response' after a while, or 'no network' if networking is not initialized (yummyluv)
 -n dpmod: make grapple off-hand (joe hill)
+2 darkplaces: add lan searching to the server browser and related code (Vermeulen)
 4 darkplaces: use larger of model box or collision box for linking into areagrid so that bullet tracing can use the model bounding box instead of the collision one?  (Urre)  
 2 darkplaces: use model box size for SOLID_BSP objects in areagrid linking and such, just for optimal consistency.
 0 darkplaces: GAME_FNIGGIUM: console doesn't show unless you manually pull it down
@@ -108,13 +109,13 @@ d darkplaces: fix key based turning being affected by slowmo - it should not be
 0 darkplaces: make sure r_fullbright works
 0 darkplaces: make sure that sky works without a valid size (just treat it as single layer clouds or non-animated) (tell Vermeulen)
 -n darkplaces: make sure that sound engine does not remove sounds when volume drops to 0 due to going out of range - now spawns sounds even if out of range (SeienAbunae)
-0 darkplaces: make v_cshift affect view even if in a liquid, by adding another cshift slot for it
+d darkplaces: make v_cshift affect view even if in a liquid, by adding another cshift slot for it
 0 darkplaces: mod_q3bsp_optimizedtraceline bug: shooting through brushes? (Vermeulen)
-0 darkplaces: model interpolation off crashes?  (SeienAbunae)
+-f darkplaces: model interpolation off crashes?  (SeienAbunae)
 0 darkplaces: pointcontents crash when building harvester in gvb2? (yummyluv)
-0 darkplaces: q1bsp trace bug: 'wall hugging' stuttering, also stuttering movement when walking over steps or monsters and causes block on moving doors (romi, Static_Fiend)
-0 darkplaces: q1bsp trace bug: bullets don't hit walls at steep angles?
-0 darkplaces: q1bsp trace bug: scrags frequently fly through ceilings - this needs to be fixed
+-n darkplaces: q1bsp trace bug: 'wall hugging' stuttering, also stuttering movement when walking over steps or monsters and causes block on moving doors (Urre, romi, Static_Fiend)
+0 darkplaces: q1bsp trace bug: bullets don't hit walls at extremely steep angles, especially at very high framerates...
+d darkplaces: q1bsp trace bug: scrags frequently fly through ceilings - this needs to be fixed
 0 darkplaces: r_shadow should load .ent when importing light entities
 0 darkplaces: r_skyscroll1 and r_skyscroll2 cvars (SeienAbunae)
 0 darkplaces: rename r_picmip and r_max_size and such to glquake names
@@ -227,7 +228,7 @@ d darkplaces: fix key based turning being affected by slowmo - it should not be
 2 darkplaces: player ip logging by nickname (sublim3)
 2 darkplaces: prevent player name changes faster than twice a second (sublim3)
 2 darkplaces: proquake precise aiming support (sublim3 doesn't care, but tell him anyway)
-2 darkplaces: q1bsp trace bug: movetogoal is broken - monsters are not going around corners, just running into walls (scar3crow)
+-n darkplaces: q1bsp trace bug: movetogoal is broken - monsters are not going around corners, just running into walls (scar3crow)
 2 darkplaces: should support corona-model shaders somehow (equation: pow(normalizationcubemap(transform(eye, vertexmatrix)) dot3 '0 0 1', 8)), which are normally used around unusually shaped lights instead of flat coronas (Mitchell)
 2 darkplaces: upgrade protocol to have shorts for stats (scar3crow)
 2 darkplaces: write a readme (Antti)
@@ -311,8 +312,8 @@ d darkplaces: fix key based turning being affected by slowmo - it should not be
 ? darkplaces: fix colormapping (Demonix)
 ? darkplaces: fix connecting to proquake servers through routers (Demonix)
 ? dpmod: apparently can't fire in start.bsp? (scar3crow)
-bug darkplaces: Zerstorer: riot shotgun rotates even as a view model: need to ignore that model flag when a view model
-bug darkplaces: collision: 'wall stuttering' collision bugs: getting stuck and nudged out constantly when sliding along certain walls
+resolvedbug darkplaces: Zerstorer: riot shotgun rotates even as a view model: need to ignore that model flag when a view model
+resolvedbug darkplaces: collision: 'wall stuttering' collision bugs: getting stuck and nudged out constantly when sliding along certain walls
 bug darkplaces: collision: q3bsp curve problems: comparing nudged impacts causes player to hit edges of triangles in a q3bsp curve closer than the surface
 bug darkplaces: physics: rotating MOVETYPE_PUSH code calls blocked when it's just a touch, it isn't even trying to push (SeienAbunae)
 d darkplaces: (goodvsbad2) increase chase_stevie height to 2048 (yummyluv)
diff --git a/world.c b/world.c
index 338de3dd..b25bd98f 100644
--- a/world.c
+++ b/world.c
@@ -484,6 +484,9 @@ trace_t SV_ClipMoveToEntity(edict_t *ent, const vec3_t start, const vec3_t mins,
 	Matrix4x4_Invert_Simple(&imatrix, &matrix);
 	Matrix4x4_Transform(&imatrix, start, starttransformed);
 	Matrix4x4_Transform(&imatrix, end, endtransformed);
+#ifdef COLLISIONPARANOID
+	Con_Printf("trans(%f %f %f -> %f %f %f, %f %f %f -> %f %f %f)", start[0], start[1], start[2], starttransformed[0], starttransformed[1], starttransformed[2], end[0], end[1], end[2], endtransformed[0], endtransformed[1], endtransformed[2]);
+#endif
 
 	if (model && model->TraceBox)
 	{
@@ -623,6 +626,9 @@ trace_t SV_Move(const vec3_t start, const vec3_t mins, const vec3_t maxs, const
 	VectorCopy(maxs, clip.maxs2);
 	clip.type = type;
 	clip.passedict = passedict;
+#ifdef COLLISIONPARANOID
+	Con_Printf("move(%f %f %f,%f %f %f)", clip.start[0], clip.start[1], clip.start[2], clip.end[0], clip.end[1], clip.end[2]);
+#endif
 
 	// clip to world
 	clip.trace = SV_ClipMoveToEntity(sv.edicts, clip.start, clip.mins, clip.maxs, clip.end, clip.type);
-- 
2.39.5