Skip to content

Commit

Permalink
Fixed: "jHeretic: P_MoveThingsOutOfWalls VS axis-parallel walls" see …
Browse files Browse the repository at this point in the history
…here (http://sourceforge.net/tracker/?func=detail&aid=2713336&group_id=74815&atid=542099).

The changes I've made do result in a much higher success rate but the algorithm itself is still far from ideal.
  • Loading branch information
danij committed Mar 26, 2009
1 parent 3d19e8b commit bcecb12
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 168 deletions.
6 changes: 5 additions & 1 deletion doomsday/engine/api/doomsday.def
@@ -1,7 +1,7 @@
NAME "DOOMSDAY"

; Highest ordinal is currently
; --> 441 <--
; --> 443 <--
; Other free ordinals:
; 43 formerly P_RegisterPlayerControl
; 44 formerly B_FormEventString
Expand Down Expand Up @@ -466,6 +466,10 @@ EXPORTS
; Vectors.
V2_Rotate @344 NONAME

; Utilities.
M_PointLineDistance @442 NONAME
M_ProjectPointOnLine @443 NONAME

; Miscellaneous: Command line.
ArgAbbreviate @146 NONAME
Argc @147 NONAME
Expand Down
3 changes: 3 additions & 0 deletions doomsday/engine/api/doomsday.h
Expand Up @@ -494,6 +494,9 @@ extern "C" {

// Miscellaneous: Math.
void V2_Rotate(float vec[2], float radians);
float M_PointLineDistance(const float* a, const float* b, const float* c);
float M_ProjectPointOnLine(const float* point, const float* linepoint,
const float* delta, float gap, float* result);
binangle_t bamsAtan2(int y, int x);

// Miscellaneous: Command line.
Expand Down
6 changes: 6 additions & 0 deletions doomsday/plugins/common/include/p_start.h
Expand Up @@ -64,4 +64,10 @@ void P_SpawnPlayers(void);

void P_GetMapLumpName(int episode, int map, char *lumpName);

void P_MoveThingsOutOfWalls();

#if __JHERETIC__
void P_TurnGizmosAwayFromDoors();
#endif

#endif
20 changes: 6 additions & 14 deletions doomsday/plugins/common/src/p_mapsetup.c
Expand Up @@ -70,13 +70,6 @@ typedef struct {

// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------

#if __JHERETIC__
void P_TurnGizmosAwayFromDoors();
void P_MoveThingsOutOfWalls();
#elif __JHEXEN__
void P_TurnTorchesToFaceWalls();
#endif

// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------

// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
Expand Down Expand Up @@ -797,19 +790,18 @@ static void P_FinalizeMap(void)
}
}

#elif __JHERETIC__
// Do some fine tuning with mobj placement and orientation.
P_MoveThingsOutOfWalls();
P_TurnGizmosAwayFromDoors();

#elif __JHEXEN__
P_TurnTorchesToFaceWalls();

// Check if the map should have lightening.
P_InitLightning();

SN_StopAllSequences();
#endif

// Do some fine tuning with mobj placement and orientation.
P_MoveThingsOutOfWalls();
#if __JHERETIC__
P_TurnGizmosAwayFromDoors();
#endif
}

char* P_GetMapNiceName(void)
Expand Down
267 changes: 114 additions & 153 deletions doomsday/plugins/common/src/p_start.c
Expand Up @@ -640,129 +640,150 @@ spawnspot_t *P_GetPlayerStart(int group, int pnum)
#endif
}

#if __JHERETIC__ || __JHEXEN__
float P_PointLineDistance(linedef_t *line, float x, float y, float *offset)
typedef struct {
float pos[2], minDist;
} unstuckmobjinlinedefparams_t;

boolean unstuckMobjInLinedef(linedef_t* li, void* context)
{
float a[2], b[2], c[2], d[2], len;
unstuckmobjinlinedefparams_t *params =
(unstuckmobjinlinedefparams_t*) context;

P_GetFloatpv(P_GetPtrp(line, DMU_VERTEX0), DMU_XY, a);
P_GetFloatpv(P_GetPtrp(line, DMU_VERTEX1), DMU_XY, b);
if(!P_GetPtrp(li, DMU_BACK_SECTOR))
{
float pos, linePoint[2], lineDelta[2], result[2];

c[VX] = x;
c[VY] = y;
/**
* Project the point (mobj position) onto this linedef. If the
* resultant point lies on the linedef and the current position is
* in range of that point, adjust the position moving it away from
* the projected point.
*/

d[VX] = b[VX] - a[VX];
d[VY] = b[VY] - a[VY];
len = sqrt(d[VX] * d[VX] + d[VY] * d[VY]); // Accurate.
P_GetFloatpv(P_GetPtrp(li, DMU_VERTEX0), DMU_XY, linePoint);
P_GetFloatpv(li, DMU_DXY, lineDelta);

if(offset)
*offset =
((a[VY] - c[VY]) * (a[VY] - b[VY]) -
(a[VX] - c[VX]) * (b[VX] - a[VX])) / len;
return ((a[VY] - c[VY]) * (b[VX] - a[VX]) -
(a[VX] - c[VX]) * (b[VY] - a[VY])) / len;
}
#endif
pos = M_ProjectPointOnLine(params->pos, linePoint, lineDelta, 0, result);

#if __JHERETIC__ || __JHEXEN__
typedef struct findclosestlinedefparams_s {
float pos[2];
float minRad;
float closestDist;
linedef_t* closestLine;
} findclosestlinedefparams_t;
if(pos > 0 && pos < 1)
{
float dist =
P_ApproxDistance(params->pos[VX] - result[VX],
params->pos[VY] - result[VY]);

if(dist >= 0 && dist < params->minDist)
{
float len, unit[2], normal[2];

int findClosestLinedef(void* ptr, void* context)
// Derive the line normal.
len = P_ApproxDistance(lineDelta[0], lineDelta[1]);
if(len)
{
unit[VX] = lineDelta[0] / len;
unit[VY] = lineDelta[1] / len;
}
else
{
unit[VX] = unit[VY] = 0;
}
normal[VX] = unit[VY];
normal[VY] = -unit[VX];

// Adjust the position.
params->pos[VX] += normal[VX] * params->minDist;
params->pos[VY] += normal[VY] * params->minDist;
}
}
}

return true; // Continue iteration.
}

boolean iterateLinedefsNearMobj(thinker_t* th, void* context)
{
linedef_t* li = (linedef_t*) ptr;
findclosestlinedefparams_t *params =
(findclosestlinedefparams_t*) context;
mobj_t* mo = (mobj_t*) th;
mobjtype_t type = *((mobjtype_t*) context);
float aabb[4];
unstuckmobjinlinedefparams_t params;

if(!P_GetPtrp(li, DMU_BACK_SECTOR))
{
float dist, off, lineLen, d1[2];
// \todo Why not type-prune at an earlier point? We could specify a
// custom comparison func for P_IterateThinkers...
if(mo->type != type)
return true; // Continue iteration.

P_GetFloatpv(li, DMU_DXY, d1);
lineLen = P_ApproxDistance(d1[0], d1[1]);
aabb[BOXLEFT] = mo->pos[VX] - mo->radius;
aabb[BOXRIGHT] = mo->pos[VX] + mo->radius;
aabb[BOXBOTTOM] = mo->pos[VY] - mo->radius;
aabb[BOXTOP] = mo->pos[VY] + mo->radius;

dist = P_PointLineDistance(li, params->pos[VX], params->pos[VY],
&off);
if(dist >= 0 &&
off > -params->minRad && off < lineLen + params->minRad &&
(!params->closestLine || dist < params->closestDist))
{
params->closestDist = dist;
params->closestLine = li;
}
params.pos[VX] = mo->pos[VX];
params.pos[VY] = mo->pos[VY];
params.minDist = mo->radius / 2;

VALIDCOUNT++;

P_LinesBoxIterator(aabb, unstuckMobjInLinedef, &params);

if(mo->pos[VX] != params.pos[VX] || mo->pos[VY] != params.pos[VY])
{
mo->angle = R_PointToAngle2(mo->pos[VX], mo->pos[VY],
params.pos[VX], params.pos[VY]);
P_MobjUnsetPosition(mo);
mo->pos[VX] = params.pos[VX];
mo->pos[VY] = params.pos[VY];
P_MobjSetPosition(mo);
}

return true; // Continue iteration.
}
#endif

#if __JHERETIC__
/**
* Only affects torches, which are often placed inside walls in the
* original maps. The DOOM engine allowed these kinds of things but
* a Z-buffer doesn't.
* original maps. The DOOM engine allowed these kinds of things but a
* Z-buffer doesn't.
*/
void P_MoveThingsOutOfWalls(void)
{
#define MAXLIST 200

sector_t *sec;
mobj_t *iter;
static const mobjtype_t types[] = {
#if __JHERETIC__
MT_MISC10,
#elif __JHEXEN__
MT_ZWALLTORCH,
MT_ZWALLTORCH_UNLIT,
#endif
NUMMOBJTYPES // terminate.
};
uint i;
int k, t;
mobj_t *tlist[MAXLIST];
findclosestlinedefparams_t params;

for(i = 0; i < numsectors; ++i)
for(i = 0; types[i] != NUMMOBJTYPES; ++i)
{
sec = P_ToPtr(DMU_SECTOR, i);
memset(tlist, 0, sizeof(tlist));

// First all the things to process.
for(k = 0, iter = P_GetPtrp(sec, DMT_MOBJS);
k < MAXLIST - 1 && iter; iter = iter->sNext)
{
// Wall torches are most often seen inside walls.
if(iter->type == MT_MISC10)
tlist[k++] = iter;
}

// Move the things out of walls.
for(t = 0; (iter = tlist[t]) != NULL; ++t)
{
params.pos[VX] = iter->pos[VX];
params.pos[VY] = iter->pos[VY];
params.minRad = iter->radius / 2;
params.closestDist = DDMAXFLOAT;
params.closestLine = NULL;
mobjtype_t type = types[i];

P_Iteratep(sec, DMU_LINEDEF, &params, findClosestLinedef);
P_IterateThinkers(P_MobjThinker, iterateLinedefsNearMobj, &type);
}
}

if(params.closestLine && params.closestDist < params.minRad)
{
float d1[2], offlen, len;
#if __JHERETIC__
float P_PointLineDistance(linedef_t *line, float x, float y, float *offset)
{
float a[2], b[2], c[2], d[2], len;

offlen = params.minRad - params.closestDist;
P_GetFloatpv(params.closestLine, DMU_DXY, d1);
d1[1] = -d1[1];
P_GetFloatpv(P_GetPtrp(line, DMU_VERTEX0), DMU_XY, a);
P_GetFloatpv(P_GetPtrp(line, DMU_VERTEX1), DMU_XY, b);

len = sqrt(d1[0] * d1[0] + d1[1] * d1[1]);
d1[0] *= offlen / len;
d1[1] *= offlen / len;
c[VX] = x;
c[VY] = y;

P_MobjUnsetPosition(iter);
iter->pos[VX] += d1[0];
iter->pos[VY] += d1[1];
P_MobjSetPosition(iter);
}
}
}
d[VX] = b[VX] - a[VX];
d[VY] = b[VY] - a[VY];
len = sqrt(d[VX] * d[VX] + d[VY] * d[VY]); // Accurate.

#undef MAXLIST
if(offset)
*offset =
((a[VY] - c[VY]) * (a[VY] - b[VY]) -
(a[VX] - c[VX]) * (b[VX] - a[VX])) / len;
return ((a[VY] - c[VY]) * (b[VX] - a[VX]) -
(a[VX] - c[VX]) * (b[VY] - a[VY])) / len;
}

/**
Expand Down Expand Up @@ -847,63 +868,3 @@ void P_TurnGizmosAwayFromDoors(void)
}
}
#endif

#if __JHEXEN__
/**
* Pretty much the same as P_TurnGizmosAwayFromDoors()
* \todo Merge them together
*/
void P_TurnTorchesToFaceWalls(void)
{
#define MAXLIST 200

sector_t *sec;
mobj_t *iter;
uint i;
int k, t;
mobj_t *tlist[MAXLIST];
findclosestlinedefparams_t params;

for(i = 0; i < numsectors; ++i)
{
sec = P_ToPtr(DMU_SECTOR, i);
memset(tlist, 0, sizeof(tlist));

// First all the things to process.
for(k = 0, iter = P_GetPtrp(sec, DMT_MOBJS);
k < MAXLIST - 1 && iter; iter = iter->sNext)
{
if(iter->type == MT_ZWALLTORCH ||
iter->type == MT_ZWALLTORCH_UNLIT)
tlist[k++] = iter;
}

// Turn to face away from the nearest wall.
for(t = 0; (iter = tlist[t]) != NULL; t++)
{
params.pos[VX] = iter->pos[VX];
params.pos[VY] = iter->pos[VY];
params.minRad = iter->radius;
params.closestLine = NULL;
params.closestDist = DDMAXFLOAT;

if(params.closestLine && params.closestDist < params.minRad)
{
vertex_t *v0, *v1;
float v0p[2], v1p[2];

v0 = P_GetPtrp(params.closestLine, DMU_VERTEX0);
v1 = P_GetPtrp(params.closestLine, DMU_VERTEX1);

P_GetFloatpv(v0, DMU_XY, v0p);
P_GetFloatpv(v1, DMU_XY, v1p);

iter->angle = R_PointToAngle2(v0p[VX], v0p[VY],
v1p[VX], v1p[VY]) - ANG90;
}
}
}

#undef MAXLIST
}
#endif

0 comments on commit bcecb12

Please sign in to comment.