Permalink
Browse files

baker's rotation turorial from http://forums.inside3d.com/viewtopic.p…

  • Loading branch information...
1 parent a3f63c8 commit 22251acaff33da79d131810ce59a378b3375e95d @ericwa committed Apr 28, 2015
Showing with 235 additions and 0 deletions.
  1. +142 −0 quakespasm/Quake/sv_phys.c
  2. +93 −0 quakespasm/Quake/world.c
View
@@ -569,6 +569,143 @@ void SV_PushMove (edict_t *pusher, float movetime)
}
/*
+ ============
+ SV_PushRotate
+
+ ============
+ */
+void SV_PushRotate (edict_t *pusher, float movetime)
+{
+ int i, e;
+ edict_t *check, *block;
+ vec3_t move, a, amove;
+ vec3_t entorig, pushorig;
+ int num_moved;
+ edict_t *moved_edict[MAX_EDICTS];
+ vec3_t moved_from[MAX_EDICTS];
+ vec3_t org, org2;
+ vec3_t forward, right, up;
+
+ if (!pusher->v.avelocity[0] && !pusher->v.avelocity[1] && !pusher->v.avelocity[2])
+ {
+ pusher->v.ltime += movetime;
+ return;
+ }
+
+ for (i=0 ; i<3 ; i++)
+ amove[i] = pusher->v.avelocity[i] * movetime;
+
+ VectorSubtract (vec3_origin, amove, a);
+ AngleVectors (a, forward, right, up);
+
+ VectorCopy (pusher->v.angles, pushorig);
+
+ // move the pusher to it's final position
+
+ VectorAdd (pusher->v.angles, amove, pusher->v.angles);
+ pusher->v.ltime += movetime;
+ SV_LinkEdict (pusher, false);
+
+
+ // see if any solid entities are inside the final position
+ num_moved = 0;
+ check = NEXT_EDICT(sv.edicts);
+ for (e=1 ; e<sv.num_edicts ; e++, check = NEXT_EDICT(check))
+ {
+ if (check->free)
+ continue;
+ if (check->v.movetype == MOVETYPE_PUSH
+ || check->v.movetype == MOVETYPE_NONE
+ // || check->v.movetype == MOVETYPE_FOLLOW
+ || check->v.movetype == MOVETYPE_NOCLIP)
+ continue;
+
+ // if the entity is standing on the pusher, it will definately be moved
+ if ( ! ( ((int)check->v.flags & FL_ONGROUND)
+ && PROG_TO_EDICT(check->v.groundentity) == pusher) )
+ {
+ if ( check->v.absmin[0] >= pusher->v.absmax[0]
+ || check->v.absmin[1] >= pusher->v.absmax[1]
+ || check->v.absmin[2] >= pusher->v.absmax[2]
+ || check->v.absmax[0] <= pusher->v.absmin[0]
+ || check->v.absmax[1] <= pusher->v.absmin[1]
+ || check->v.absmax[2] <= pusher->v.absmin[2] )
+ continue;
+
+ // see if the ent's bbox is inside the pusher's final position
+ if (!SV_TestEntityPosition (check))
+ continue;
+ }
+
+ // remove the onground flag for non-players
+ if (check->v.movetype != MOVETYPE_WALK)
+ check->v.flags = (int)check->v.flags & ~FL_ONGROUND;
+
+ VectorCopy (check->v.origin, entorig);
+ VectorCopy (check->v.origin, moved_from[num_moved]);
+ moved_edict[num_moved] = check;
+ num_moved++;
+
+ // calculate destination position
+ VectorSubtract (check->v.origin, pusher->v.origin, org);
+ org2[0] = DotProduct (org, forward);
+ org2[1] = -DotProduct (org, right);
+ org2[2] = DotProduct (org, up);
+ VectorSubtract (org2, org, move);
+
+ // try moving the contacted entity
+ pusher->v.solid = SOLID_NOT;
+ SV_PushEntity (check, move);
+ pusher->v.solid = SOLID_BSP;
+
+ // if it is still inside the pusher, block
+ block = SV_TestEntityPosition (check);
+ if (block)
+ { // fail the move
+ if (check->v.mins[0] == check->v.maxs[0])
+ continue;
+ if (check->v.solid == SOLID_NOT || check->v.solid == SOLID_TRIGGER)
+ { // corpse
+ check->v.mins[0] = check->v.mins[1] = 0;
+ VectorCopy (check->v.mins, check->v.maxs);
+ continue;
+ }
+
+ VectorCopy (entorig, check->v.origin);
+ SV_LinkEdict (check, true);
+
+ VectorCopy (pushorig, pusher->v.angles);
+ SV_LinkEdict (pusher, false);
+ pusher->v.ltime -= movetime;
+
+ // if the pusher has a "blocked" function, call it
+ // otherwise, just stay in place until the obstacle is gone
+ if (pusher->v.blocked)
+ {
+ pr_global_struct->self = EDICT_TO_PROG(pusher);
+ pr_global_struct->other = EDICT_TO_PROG(check);
+ PR_ExecuteProgram (pusher->v.blocked);
+ }
+
+ // move back any entities we already moved
+ for (i=0 ; i<num_moved ; i++)
+ {
+ VectorCopy (moved_from[i], moved_edict[i]->v.origin);
+ VectorSubtract (moved_edict[i]->v.angles, amove, moved_edict[i]->v.angles);
+ SV_LinkEdict (moved_edict[i], false);
+ }
+ return;
+ }
+ else
+ {
+ VectorAdd (check->v.angles, amove, check->v.angles);
+ }
+ }
+
+
+}
+
+/*
================
SV_Physics_Pusher
@@ -594,6 +731,11 @@ void SV_Physics_Pusher (edict_t *ent)
if (movetime)
{
+ //ROTATE START
+ if ((ent->v.avelocity[0] || ent->v.avelocity[1] || ent->v.avelocity[2]) && ent->v.solid == SOLID_BSP)
+ SV_PushRotate (ent, host_frametime);
+ else
+ //ROTATE END
SV_PushMove (ent, movetime); // advances ent->v.ltime if not blocked
}
View
@@ -403,8 +403,40 @@ void SV_LinkEdict (edict_t *ent, qboolean touch_triggers)
return;
// set the abs box
+ // ROTATE START
+ if (ent->v.solid == SOLID_BSP &&
+ (ent->v.angles[0] || ent->v.angles[1] || ent->v.angles[2]) && ent != sv.edicts)
+ { // expand for rotation
+ float max, v;
+ int i;
+
+ max = DotProduct(ent->v.mins, ent->v.mins);
+
+ v = DotProduct(ent->v.maxs, ent->v.maxs);
+
+ if (max < v)
+
+ max = v;
+
+ max = sqrt(max);
+
+ for (i=0 ; i<3 ; i++)
+
+ {
+
+ ent->v.absmin[i] = ent->v.origin[i] - max;
+
+ ent->v.absmax[i] = ent->v.origin[i] + max;
+
+ }
+
+ }
+ else
+ {
+ // ROTATE END
VectorAdd (ent->v.origin, ent->v.mins, ent->v.absmin);
VectorAdd (ent->v.origin, ent->v.maxs, ent->v.absmax);
+ }
//
// to make items easier to pick up and allow them to be grabbed off
@@ -723,13 +755,74 @@ trace_t SV_ClipMoveToEntity (edict_t *ent, vec3_t start, vec3_t mins, vec3_t max
VectorSubtract (start, offset, start_l);
VectorSubtract (end, offset, end_l);
+ // ROTATE START
+ // rotate start and end into the models frame of reference
+ if (ent->v.solid == SOLID_BSP &&
+ (ent->v.angles[0] || ent->v.angles[1] || ent->v.angles[2]) && ent != sv.edicts)
+ {
+ vec3_t a;
+ vec3_t forward, right, up;
+ vec3_t temp;
+
+ AngleVectors (ent->v.angles, forward, right, up);
+
+ 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);
+ }
+ // ROTATE END
+
// trace a line through the apropriate clipping hull
SV_RecursiveHullCheck (hull, hull->firstclipnode, 0, 1, start_l, end_l, &trace);
+
+ // ROTATE START
+ // rotate endpos back to world frame of reference
+ if (ent->v.solid == SOLID_BSP &&
+ (ent->v.angles[0] || ent->v.angles[1] || ent->v.angles[2]) && ent != sv.edicts)
+ {
+ vec3_t a;
+ vec3_t forward, right, up;
+ vec3_t temp;
+
+ if (trace.fraction != 1)
+ {
+ VectorSubtract (vec3_origin, ent->v.angles, a);
+ AngleVectors (a, forward, right, up);
+
+ 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);
+ }
+
// fix trace up by the offset
+ VectorAdd (trace.endpos, offset, trace.endpos);
+
+ }
+#if 1 // Baker addition
+ // Cases where not Solid BSP or no avelocity
+ // Otherwise backpacks from dead monsters and such can fall through the floor
+ else {
if (trace.fraction != 1)
VectorAdd (trace.endpos, offset, trace.endpos);
+ }
+#endif
+ // ROTATE END
+
+
// did we clip the move?
if (trace.fraction < 1 || trace.startsolid )
trace.ent = ent;

0 comments on commit 22251ac

Please sign in to comment.