From e6e1b10c58ba37e218fd89579ca888aa7a2ac023 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 5 Sep 2011 21:05:09 +0900 Subject: [PATCH] Add support for rotating entities to QW. Same as the rotating entities in NQ. Unfortunately, I have some problems with certain entities doing really weird things during collisions. I'll sort that out later. --- include/qw/pmove.h | 1 + qw/source/cl_entparse.c | 3 ++ qw/source/pmovetst.c | 40 +++++++++++++++++++++++- qw/source/sv_phys.c | 47 ++++++++++++++++++++++------ qw/source/sv_user.c | 1 + qw/source/world.c | 68 ++++++++++++++++++++++++++++++++++++----- 6 files changed, 142 insertions(+), 18 deletions(-) diff --git a/include/qw/pmove.h b/include/qw/pmove.h index 606e7d176..ac5adb413 100644 --- a/include/qw/pmove.h +++ b/include/qw/pmove.h @@ -40,6 +40,7 @@ #define MAX_PHYSENTS (MAX_CLIENTS + MAX_PACKET_ENTITIES) typedef struct { vec3_t origin; + vec3_t angles; model_t *model; // only for bsp models vec3_t mins, maxs; // only for non-bsp models hull_t *hull; // hey, magic :) diff --git a/qw/source/cl_entparse.c b/qw/source/cl_entparse.c index 29e4ccecc..477af00f2 100644 --- a/qw/source/cl_entparse.c +++ b/qw/source/cl_entparse.c @@ -519,6 +519,7 @@ CL_SetSolidEntities (void) pmove.physents[0].model = cl.worldmodel; VectorZero (pmove.physents[0].origin); + VectorZero (pmove.physents[0].angles); pmove.physents[0].info = 0; pmove.numphysent = 1; @@ -543,6 +544,8 @@ CL_SetSolidEntities (void) cl.model_precache[state->modelindex]; VectorCopy (state->origin, pmove.physents[pmove.numphysent].origin); + VectorCopy (state->angles, + pmove.physents[pmove.numphysent].angles); pmove.numphysent++; } } diff --git a/qw/source/pmovetst.c b/qw/source/pmovetst.c index c368a3290..bca6f1bc5 100644 --- a/qw/source/pmovetst.c +++ b/qw/source/pmovetst.c @@ -214,6 +214,9 @@ PM_PlayerMove (const vec3_t start, const vec3_t end) trace_t trace, total; vec3_t maxs, mins, offset, start_l, end_l; vec3_t move[2]; + vec3_t forward, right, up; + int rot = 0; + vec3_t temp; // fill in a default trace memset (&total, 0, sizeof (trace_t)); @@ -249,6 +252,23 @@ PM_PlayerMove (const vec3_t start, const vec3_t end) VectorSubtract (start, offset, start_l); VectorSubtract (end, offset, end_l); + if (1 && pe->model && pe->model->type == mod_brush + && !VectorIsZero (pe->angles)) { + rot = 1; + AngleVectors (pe->angles, forward, right, up); + VectorNegate (right, right); // convert lhs to rhs + + VectorCopy (start_l, temp); + start_l[0] = DotProduct (temp, forward); + start_l[1] = DotProduct (temp, right); + start_l[2] = DotProduct (temp, up); + + VectorCopy (end_l, temp); + end_l[0] = DotProduct (temp, forward); + end_l[1] = DotProduct (temp, right); + end_l[2] = DotProduct (temp, up); + } + // fill in a default trace memset (&trace, 0, sizeof (trace_t)); @@ -289,7 +309,25 @@ PM_PlayerMove (const vec3_t start, const vec3_t end) // did we clip the move? if (trace.fraction < total.fraction) { - // fix trace up by the offset + // fix up trace by the offset + if (rot) { + vec_t t; + + // transpose the rotation matrix to get its inverse + t = forward[1]; forward[1] = right[0]; right[0] = t; + t = forward[2]; forward[2] = up[0]; up[0] = t; + t = right[2]; right[2] = up[1]; up[1] = t; + + VectorCopy (trace.endpos, temp); + trace.endpos[0] = DotProduct (temp, forward); + trace.endpos[1] = DotProduct (temp, right); + trace.endpos[2] = DotProduct (temp, up); + + VectorCopy (trace.plane.normal, temp); + trace.plane.normal[0] = DotProduct (temp, forward); + trace.plane.normal[1] = DotProduct (temp, right); + trace.plane.normal[2] = DotProduct (temp, up); + } VectorAdd (trace.endpos, offset, trace.endpos); total = trace; total.ent = (struct edict_s *) &pmove.physents[i]; diff --git a/qw/source/sv_phys.c b/qw/source/sv_phys.c index 48b39b3ae..7bed3f488 100644 --- a/qw/source/sv_phys.c +++ b/qw/source/sv_phys.c @@ -398,23 +398,35 @@ SV_PushEntity (edict_t *ent, vec3_t push) } static qboolean -SV_Push (edict_t *pusher, vec3_t move) +SV_Push (edict_t *pusher, const vec3_t tmove, const vec3_t amove) { float solid_save; int num_moved, i, e; edict_t *check, *block; edict_t **moved_edict; - vec3_t mins, maxs, pushorig; + vec3_t move, org, org2; + vec3_t mins, maxs, pushtorig, pushaorig; vec3_t *moved_from; + vec3_t forward = {1, 0, 0}; + vec3_t right = {0, -1, 0}; + vec3_t up = {0, 0, 1}; int mark; - VectorAdd (SVvector (pusher, absmin), move, mins); - VectorAdd (SVvector (pusher, absmax), move, maxs); + VectorAdd (SVvector (pusher, absmin), tmove, mins); + VectorAdd (SVvector (pusher, absmax), tmove, maxs); - VectorCopy (SVvector (pusher, origin), pushorig); + if (!VectorIsZero (amove)) { + vec3_t a; + VectorSubtract (vec3_origin, amove, a); + AngleVectors (a, forward, right, up); + } + + VectorCopy (SVvector (pusher, origin), pushtorig); + VectorCopy (SVvector (pusher, angles), pushaorig); // move the pusher to it's final position - VectorAdd (SVvector (pusher, origin), move, SVvector (pusher, origin)); + VectorAdd (SVvector (pusher, origin), tmove, SVvector (pusher, origin)); + VectorAdd (SVvector (pusher, angles), amove, SVvector (pusher, angles)); SV_LinkEdict (pusher, false); mark = Hunk_LowMark (); @@ -462,6 +474,15 @@ SV_Push (edict_t *pusher, vec3_t move) moved_edict[num_moved] = check; num_moved++; + // calculate destination position + VectorSubtract (SVvector (check, origin), + SVvector (pusher, origin), org); + org2[0] = DotProduct (org, forward); + org2[1] = -DotProduct (org, right); + org2[2] = DotProduct (org, up); + VectorSubtract (org2, org, move); + VectorAdd (move, tmove, move); + // try moving the contacted entity VectorAdd (SVvector (check, origin), move, SVvector (check, origin)); block = SV_TestEntityPosition (check); @@ -490,7 +511,8 @@ SV_Push (edict_t *pusher, vec3_t move) continue; } - VectorCopy (pushorig, SVvector (pusher, origin)); + VectorCopy (pushtorig, SVvector (pusher, origin)); + VectorCopy (pushaorig, SVvector (pusher, angles)); SV_LinkEdict (pusher, false); // if the pusher has a "blocked" function, call it @@ -501,6 +523,8 @@ SV_Push (edict_t *pusher, vec3_t move) // move back any entities we already moved for (i = 0; i < num_moved; i++) { VectorCopy (moved_from[i], SVvector (moved_edict[i], origin)); + VectorSubtract (SVvector (moved_edict[i], angles), amove, + SVvector (moved_edict[i], angles)); SV_LinkEdict (moved_edict[i], false); } Hunk_FreeToLowMark (mark); @@ -514,15 +538,18 @@ static void SV_PushMove (edict_t *pusher, float movetime) { vec3_t move; + vec3_t amove; - if (VectorIsZero (SVvector (pusher, velocity))) { + if (VectorIsZero (SVvector (pusher, velocity)) + && VectorIsZero (SVvector (pusher, avelocity))) { SVfloat (pusher, ltime) += movetime; return; } VectorScale (SVvector (pusher, velocity), movetime, move); + VectorScale (SVvector (pusher, avelocity), movetime, amove); - if (SV_Push (pusher, move)) + if (SV_Push (pusher, move, amove)) SVfloat (pusher, ltime) += movetime; } @@ -560,7 +587,7 @@ SV_Physics_Pusher (edict_t *ent) l = VectorLength (move); if (l > (1.0 / 64.0)) { VectorCopy (oldorg, SVvector (ent, origin)); - SV_Push (ent, move); + SV_Push (ent, move, vec3_origin); //FIXME angle } } } diff --git a/qw/source/sv_user.c b/qw/source/sv_user.c index bb32c293e..192ea77ac 100644 --- a/qw/source/sv_user.c +++ b/qw/source/sv_user.c @@ -1540,6 +1540,7 @@ AddLinksToPmove (areanode_t *node) pmove.numphysent++; VectorCopy (SVvector (check, origin), pe->origin); + VectorCopy (SVvector (check, angles), pe->angles); pe->info = NUM_FOR_EDICT (&sv_pr_state, check); if (sv_fields.rotated_bbox != -1 diff --git a/qw/source/world.c b/qw/source/world.c index f07d4ee6a..2ae9aa700 100644 --- a/qw/source/world.c +++ b/qw/source/world.c @@ -455,11 +455,25 @@ SV_LinkEdict (edict_t *ent, qboolean touch_triggers) if (ent->free) return; - // set the abs box - VectorAdd (SVvector (ent, origin), SVvector (ent, mins), - SVvector (ent, absmin)); - VectorAdd (SVvector (ent, origin), SVvector (ent, maxs), - SVvector (ent, absmax)); + if (SVfloat (ent, solid) == SOLID_BSP + && !VectorIsZero (SVvector (ent, angles)) && ent != sv.edicts) { + float m, v; + vec3_t r; + m = DotProduct (SVvector (ent, mins), SVvector (ent, mins)); + v = DotProduct (SVvector (ent, maxs), SVvector (ent, maxs)); + if (m < v) + m = v; + m = sqrt (m); + VectorSet (m, m, m, r); + VectorSubtract (SVvector (ent, origin), r, SVvector (ent, absmin)); + VectorAdd (SVvector (ent, origin), r, SVvector (ent, absmax)); + } else { + // set the abs box + VectorAdd (SVvector (ent, origin), SVvector (ent, mins), + SVvector (ent, absmin)); + VectorAdd (SVvector (ent, origin), SVvector (ent, maxs), + SVvector (ent, absmax)); + } // to make items easier to pick up and allow them to be grabbed off // of shelves, the abs sizes are expanded @@ -591,6 +605,9 @@ SV_ClipMoveToEntity (edict_t *touched, const vec3_t start, hull_t *hull; trace_t trace; vec3_t offset, start_l, end_l; + vec3_t forward, right, up; + int rot = 0; + vec3_t temp; // fill in a default trace memset (&trace, 0, sizeof (trace_t)); @@ -607,12 +624,49 @@ SV_ClipMoveToEntity (edict_t *touched, const vec3_t start, VectorSubtract (start, offset, start_l); VectorSubtract (end, offset, end_l); + if (SVfloat (touched, solid) == SOLID_BSP + && !VectorIsZero (SVvector (touched, angles)) + && touched != sv.edicts) { + rot = 1; + AngleVectors (SVvector (touched, angles), forward, right, up); + VectorNegate (right, right); // convert lhs to rhs + + VectorCopy (start_l, temp); + start_l[0] = DotProduct (temp, forward); + start_l[1] = DotProduct (temp, right); + start_l[2] = DotProduct (temp, up); + + VectorCopy (end_l, temp); + end_l[0] = DotProduct (temp, forward); + end_l[1] = DotProduct (temp, right); + end_l[2] = DotProduct (temp, up); + } + // trace a line through the apropriate clipping hull MOD_TraceLine (hull, hull->firstclipnode, start_l, end_l, &trace); - // fix trace up by the offset - if (trace.fraction != 1) + // fix up trace by the rotation and offset + if (trace.fraction != 1) { + if (rot) { + vec_t t; + + // transpose the rotation matrix to get its inverse + t = forward[1]; forward[1] = right[0]; right[0] = t; + t = forward[2]; forward[2] = up[0]; up[0] = t; + t = right[2]; right[2] = up[1]; up[1] = t; + + VectorCopy (trace.endpos, temp); + trace.endpos[0] = DotProduct (temp, forward); + trace.endpos[1] = DotProduct (temp, right); + trace.endpos[2] = DotProduct (temp, up); + + VectorCopy (trace.plane.normal, temp); + trace.plane.normal[0] = DotProduct (temp, forward); + trace.plane.normal[1] = DotProduct (temp, right); + trace.plane.normal[2] = DotProduct (temp, up); + } VectorAdd (trace.endpos, offset, trace.endpos); + } // did we clip the move? if (trace.fraction < 1 || trace.startsolid)