Rotating bsp model support.

This is based on the code presented on
http://forums.inside3d.com/viewtopic.php?t=2376 (and updates linked from
that thread), but with modifications for hopefully supporting rotating
trains (and not duplicating big fuctions).

For now, only nq. qw will come after some more testing.
This commit is contained in:
Bill Currie 2010-12-15 08:33:20 +09:00
parent 0e677ce0f0
commit 775f8e959b
2 changed files with 100 additions and 17 deletions

View file

@ -397,24 +397,35 @@ SV_PushEntity (edict_t *ent, vec3_t push)
} }
static qboolean static qboolean
SV_Push (edict_t *pusher, vec3_t move) SV_Push (edict_t *pusher, vec3_t tmove, vec3_t amove)
{ {
float solid_save; float solid_save;
int num_moved, i, e; int num_moved, i, e;
edict_t *check, *block; edict_t *check, *block;
edict_t **moved_edict; edict_t **moved_edict;
vec3_t entorig; vec3_t entorig, move, org, org2;
vec3_t mins, maxs, pushorig; vec3_t mins, maxs, pushtorig, pushaorig;
vec3_t *moved_from; vec3_t *moved_from;
vec3_t forward = {1, 0, 0};
vec3_t right = {0, -1, 0};
vec3_t up = {0, 0, 1};
int mark; int mark;
VectorAdd (SVvector (pusher, absmin), move, mins); VectorAdd (SVvector (pusher, absmin), tmove, mins);
VectorAdd (SVvector (pusher, absmax), move, maxs); 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 // 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); SV_LinkEdict (pusher, false);
mark = Hunk_LowMark (); mark = Hunk_LowMark ();
@ -460,6 +471,15 @@ SV_Push (edict_t *pusher, vec3_t move)
moved_edict[num_moved] = check; moved_edict[num_moved] = check;
num_moved++; 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 // try moving the contacted entity
solid_save = SVfloat (pusher, solid); solid_save = SVfloat (pusher, solid);
SVfloat (pusher, solid) = SOLID_NOT; SVfloat (pusher, solid) = SOLID_NOT;
@ -468,6 +488,8 @@ SV_Push (edict_t *pusher, vec3_t move)
block = SV_TestEntityPosition (check); block = SV_TestEntityPosition (check);
if (!block) { if (!block) {
VectorAdd (SVvector (check, angles), amove,
SVvector (check, angles));
continue; continue;
} }
// if it is still inside the pusher, block // if it is still inside the pusher, block
@ -484,7 +506,8 @@ SV_Push (edict_t *pusher, vec3_t move)
VectorCopy (entorig, SVvector (check, origin)); VectorCopy (entorig, SVvector (check, origin));
SV_LinkEdict (check, true); SV_LinkEdict (check, true);
VectorCopy (pushorig, SVvector (pusher, origin)); VectorCopy (pushtorig, SVvector (pusher, origin));
VectorCopy (pushaorig, SVvector (pusher, angles));
SV_LinkEdict (pusher, false); SV_LinkEdict (pusher, false);
// if the pusher has a "blocked" function, call it // if the pusher has a "blocked" function, call it
@ -495,6 +518,8 @@ SV_Push (edict_t *pusher, vec3_t move)
// move back any entities we already moved // move back any entities we already moved
for (i = 0; i < num_moved; i++) { for (i = 0; i < num_moved; i++) {
VectorCopy (moved_from[i], SVvector (moved_edict[i], origin)); 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); SV_LinkEdict (moved_edict[i], false);
} }
Hunk_FreeToLowMark (mark); Hunk_FreeToLowMark (mark);
@ -508,15 +533,18 @@ static void
SV_PushMove (edict_t *pusher, float movetime) SV_PushMove (edict_t *pusher, float movetime)
{ {
vec3_t move; vec3_t move;
vec3_t amove;
if (VectorIsZero (SVvector (pusher, velocity))) { if (VectorIsZero (SVvector (pusher, velocity))
&& VectorIsZero (SVvector (pusher, avelocity))) {
SVfloat (pusher, ltime) += movetime; SVfloat (pusher, ltime) += movetime;
return; return;
} }
VectorScale (SVvector (pusher, velocity), movetime, move); 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; SVfloat (pusher, ltime) += movetime;
} }

View file

@ -455,11 +455,25 @@ SV_LinkEdict (edict_t *ent, qboolean touch_triggers)
if (ent->free) if (ent->free)
return; return;
// set the abs box if (SVfloat (ent, solid) == SOLID_BSP
VectorAdd (SVvector (ent, origin), SVvector (ent, mins), && !VectorIsZero (SVvector (ent, angles)) && ent != sv.edicts) {
SVvector (ent, absmin)); float m, v;
VectorAdd (SVvector (ent, origin), SVvector (ent, maxs), vec3_t r;
SVvector (ent, absmax)); 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 // to make items easier to pick up and allow them to be grabbed off
// of shelves, the abs sizes are expanded // of shelves, the abs sizes are expanded
@ -591,6 +605,9 @@ SV_ClipMoveToEntity (edict_t *touched, const vec3_t start,
hull_t *hull; hull_t *hull;
trace_t trace; trace_t trace;
vec3_t offset, start_l, end_l; vec3_t offset, start_l, end_l;
vec3_t forward, right, up;
int rot = 0;
vec3_t temp;
// fill in a default trace // fill in a default trace
memset (&trace, 0, sizeof (trace_t)); memset (&trace, 0, sizeof (trace_t));
@ -607,12 +624,50 @@ SV_ClipMoveToEntity (edict_t *touched, const vec3_t start,
VectorSubtract (start, offset, start_l); VectorSubtract (start, offset, start_l);
VectorSubtract (end, offset, end_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 // trace a line through the apropriate clipping hull
MOD_TraceLine (hull, hull->firstclipnode, start_l, end_l, &trace); MOD_TraceLine (hull, hull->firstclipnode, start_l, end_l, &trace);
// fix trace up by the offset
if (trace.fraction != 1) // fix trace up 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); VectorAdd (trace.endpos, offset, trace.endpos);
}
// did we clip the move? // did we clip the move?
if (trace.fraction < 1 || trace.startsolid) if (trace.fraction < 1 || trace.startsolid)