Preliminary version of wall handling. Manny still gets stuck at walls,

but he now turns until he can move forward again.
This commit is contained in:
Daniel Schepler 2005-03-28 01:56:40 +00:00
parent 9abc55fcfd
commit 932ccec21b
6 changed files with 116 additions and 9 deletions

View file

@ -34,6 +34,7 @@
Actor::Actor(const char *name) :
_name(name), _talkColor(255, 255, 255), _pos(0, 0, 0),
_pitch(0), _yaw(0), _roll(0), _walkRate(0), _turnRate(0),
_reflectionAngle(80),
_visible(true), _lipSynch(NULL), _turning(false), _walking(false),
_restCostume(NULL), _restChore(-1),
_walkCostume(NULL), _walkChore(-1), _walkedLast(false), _walkedCur(false),
@ -98,16 +99,65 @@ void Actor::walkForward() {
std::sin(pitch_rad));
Vector3d destPos = _pos + forwardVec * dist;
if (!_constrain) {
_pos = destPos;
if (! _constrain) {
_pos += forwardVec * dist;
_walkedCur = true;
} else {
Sector *sector = g_engine->currScene()->findPointSector(destPos, 0x1000);
if (sector != NULL) {
_pos = sector->projectToPlane(destPos);
return;
}
if (dist < 0) {
dist = -dist;
forwardVec = -forwardVec;
}
Sector *currSector = NULL, *prevSector = NULL;
Sector::ExitInfo ei;
g_engine->currScene()->findClosestSector(_pos, &currSector, &_pos);
if (currSector == NULL) { // Shouldn't happen...
_pos += forwardVec * dist;
_walkedCur = true;
return;
}
while (currSector != NULL) {
prevSector = currSector;
Vector3d puckVector = currSector->projectToPuckVector(forwardVec);
puckVector /= puckVector.magnitude();
currSector->getExitInfo(_pos, puckVector, &ei);
float exitDist = (ei.exitPoint - _pos).magnitude();
if (dist < exitDist) {
_pos += puckVector * dist;
_walkedCur = true;
return;
}
_pos = ei.exitPoint;
dist -= exitDist;
if (exitDist > 0.0001)
_walkedCur = true;
// Check for an adjacent sector which can continue
// the path
currSector = g_engine->currScene()->findPointSector(ei.exitPoint + 0.0001 * puckVector, 0x1000);
if (currSector == prevSector)
break;
}
ei.angleWithEdge *= (180.0 / M_PI);
int turnDir = 1;
if (ei.angleWithEdge > 90) {
ei.angleWithEdge = 180 - ei.angleWithEdge;
ei.edgeDir = -ei.edgeDir;
turnDir = -1;
}
if (ei.angleWithEdge > _reflectionAngle)
return;
ei.angleWithEdge += 0.1;
float turnAmt = g_engine->perSecond(_turnRate);
if (turnAmt > ei.angleWithEdge)
turnAmt = ei.angleWithEdge;
_yaw += turnAmt * turnDir;
}
Vector3d Actor::puckVector() const {

View file

@ -66,6 +66,7 @@ public:
return _setName == name;
}
void walkForward();
void setReflection(float angle) { _reflectionAngle = angle; }
Vector3d puckVector() const;
void turn(int dir);
@ -125,6 +126,7 @@ private:
float _walkRate, _turnRate;
bool _constrain; // Constrain to walkboxes
float _reflectionAngle; // Maximum angle to turn by at walls
bool _visible;
bool _lookingMode;
std::string _talkSoundName;

View file

@ -457,6 +457,12 @@ static void WalkActorForward() {
act->walkForward();
}
static void SetActorReflection() {
Actor *act = check_actor(1);
float angle = luaL_check_number(2);
act->setReflection(angle);
}
static void GetActorPuckVector() {
Actor *act = check_actor(1);
Vector3d result = act->puckVector();
@ -1584,7 +1590,6 @@ STUB_FUNC(SetActorWalkDominate)
STUB_FUNC(GetCameraActor)
STUB_FUNC(DriveActorTo)
STUB_FUNC(WalkActorVector)
STUB_FUNC(SetActorReflection)
STUB_FUNC(GetActorRect)
STUB_FUNC(GetActorNodeLocation)
STUB_FUNC(SetActorTimeScale)
@ -1924,6 +1929,8 @@ struct luaL_reg mainOpcodes[] = {
{ "PutActorInSet", PutActorInSet },
{ "WalkActorVector", WalkActorVector },
{ "WalkActorForward", WalkActorForward },
{ "SetActorReflection", SetActorReflection },
{ "GetActorPuckVector", GetActorPuckVector },
{ "DriveActorTo", DriveActorTo },
{ "WalkActorTo", WalkActorTo },
{ "WalkActorToAvoiding", WalkActorToAvoiding },

View file

@ -125,6 +125,10 @@ inline Vector3d operator *(float s, const Vector3d& v) {
return result;
}
inline Vector3d operator -(const Vector3d& v) {
return (-1.0f) * v;
}
inline Vector3d operator *(const Vector3d& v, float s) {
return s * v;
}

View file

@ -160,3 +160,38 @@ Vector3d Sector::closestPoint(Vector3d point) const {
}
return _vertices[index];
}
void Sector::getExitInfo(Vector3d start, Vector3d dir,
struct ExitInfo *result) {
start = projectToPlane(start);
dir = projectToPuckVector(dir);
// First find the edge the ray exits through: this is where
// the z-component of (v_i - start) x dir changes sign from
// positive to negative.
// First find a vertex such that the cross product has
// positive z-component.
int i;
for (i = 0; i < _numVertices; i++) {
Vector3d delta = _vertices[i] - start;
if (delta.x() * dir.y() > delta.y() * dir.x())
break;
}
// Now continue until the cross product has negative
// z-component.
while (i < _numVertices) {
i++;
Vector3d delta = _vertices[i] - start;
if (delta.x() * dir.y() <= delta.y() * dir.x())
break;
}
result->edgeDir = _vertices[i] - _vertices[i - 1];
result->angleWithEdge = angle(dir, result->edgeDir);
Vector3d edgeNormal(result->edgeDir.y(), -result->edgeDir.x(), 0);
result->exitPoint = start + (dot(_vertices[i] - start, edgeNormal) /
dot(dir, edgeNormal)) * dir;
}

View file

@ -46,6 +46,15 @@ public:
Vector3d closestPoint(Vector3d point) const;
// Interface to trace a ray to its exit from the polygon
struct ExitInfo {
Vector3d exitPoint;
float angleWithEdge;
Vector3d edgeDir;
};
void getExitInfo(Vector3d start, Vector3d dir,
struct ExitInfo *result);
private:
int _numVertices, _id;