GRIM: Implement ShrinkBoxes(), UnShrinkBoxes() and GetShrinkPos().

This commit is contained in:
Joni Vähämäki 2011-06-10 15:09:17 +03:00 committed by Giulio Camuffo
parent f5bd174755
commit 554bd2648f
5 changed files with 150 additions and 11 deletions

View File

@ -744,15 +744,12 @@ void L1_ShrinkBoxes() {
if (lua_isnumber(sizeObj)) {
float size = lua_getnumber(sizeObj);
// g_grim->getCurrScene()->shrinkBoxes(size);
warning("ShrinkBoxes() not implemented");
g_grim->getCurrScene()->shrinkBoxes(size);
}
}
void L1_UnShrinkBoxes() {
warning("UnShrinkBoxes() not implemented");
// g_grim->getCurrScene()->shrinkBoxes(0);
g_grim->getCurrScene()->unshrinkBoxes();
}
/* Given a position and a size this function calculates and pushes
@ -775,12 +772,21 @@ void L1_GetShrinkPos() {
Graphics::Vector3d pos;
pos.set(x, y, z);
Sector* sector;
g_grim->getCurrScene()->shrinkBoxes(r);
g_grim->getCurrScene()->findClosestSector(pos, &sector, &pos);
g_grim->getCurrScene()->unshrinkBoxes();
// TODO
//UnShrinkBoxes();
// lua_pusnumber 1, 2, 3 or lua_pushnil
lua_pushnumber(x);
lua_pushnumber(y);
lua_pushnumber(z);
if (sector) {
lua_pushnumber(pos.x());
lua_pushnumber(pos.y());
lua_pushnumber(pos.z());
} else {
lua_pushnil();
}
warning("Stub function GetShrinkPos(%g,%g,%g,%g) called", x, y, z, r);
}

View File

@ -562,6 +562,20 @@ void Scene::findClosestSector(const Graphics::Vector3d &p, Sector **sect, Graphi
*closestPoint = resultPt;
}
void Scene::shrinkBoxes(float radius) {
for (int i = 0; i < _numSectors; i++) {
Sector *sector = _sectors[i];
sector->shrink(radius);
}
}
void Scene::unshrinkBoxes() {
for (int i = 0; i < _numSectors; i++) {
Sector *sector = _sectors[i];
sector->unshrink();
}
}
ObjectState *Scene::findState(const char *filename) {
// Check the different state objects for the bitmap
for (StateList::iterator i = _states.begin(); i != _states.end(); ++i) {

View File

@ -89,6 +89,8 @@ public:
Sector *findPointSector(const Graphics::Vector3d &p, Sector::SectorType type);
void findClosestSector(const Graphics::Vector3d &p, Sector **sect, Graphics::Vector3d *closestPt);
void shrinkBoxes(float radius);
void unshrinkBoxes();
void addObjectState(ObjectState *s) {
_states.push_back(s);

View File

@ -38,6 +38,8 @@ Sector::Sector(const Sector &other) {
Sector::~Sector() {
if (_vertices)
delete[] _vertices;
if (_origVertices)
delete[] _origVertices;
}
void Sector::saveState(SaveGame *savedState) const {
@ -54,6 +56,15 @@ void Sector::saveState(SaveGame *savedState) const {
}
savedState->writeVector3d(_normal);
// Enable on next save format change.
/*savedState->writeFloat(_shrinkRadius);
savedState->writeLESint32(_invalid);
if (_shrinkRadius != 0.f && !_invalid) {
for (int i = 0; i < _numVertices + 1; ++i) {
savedState->writeVector3d(_origVertices[i]);
}
}*/
}
bool Sector::restoreState(SaveGame *savedState) {
@ -72,6 +83,17 @@ bool Sector::restoreState(SaveGame *savedState) {
_normal = savedState->readVector3d();
// Enable on next save format change.
/*_shrinkRadius = savedState->readFloat();
_invalid = savedState->readLESint32();
if (_shrinkRadius != 0.f && !_invalid) {
_origVertices = new Graphics::Vector3d[_numVertices + 1];
for (int i = 0; i < _numVertices + 1; ++i) {
_origVertices[i] = savedState->readVector3d();
}
} else {
_origVertices = NULL;
}*/
return true;
}
@ -155,13 +177,93 @@ void Sector::loadBinary(Common::MemoryReadStream *ms) {
ms->seek(skip * 4, SEEK_CUR);
ms->read(&_height, 4);
}
void Sector::setVisible(bool vis) {
_visible = vis;
}
void Sector::shrink(float radius) {
if ((getType() & WalkType) == 0 || _shrinkRadius == radius)
return;
_shrinkRadius = radius;
if (!_origVertices) {
_origVertices = _vertices;
_vertices = new Graphics::Vector3d[_numVertices + 1];
}
// Move each vertex inwards by the given amount.
for (int j = 0; j < _numVertices; j++) {
Graphics::Vector3d shrinkDir;
for (int k = 0; k < g_grim->getCurrScene()->getSectorCount(); k++) {
Sector *other = g_grim->getCurrScene()->getSectorBase(k);
if ((other->getType() & WalkType) == 0)
continue;
for (int l = 0; l < other->_numVertices; l++) {
Graphics::Vector3d* otherVerts = other->_vertices;
if (other->_origVertices)
otherVerts = other->_origVertices;
if ((otherVerts[l] - _origVertices[j]).magnitude() < 0.01f) {
Graphics::Vector3d e1 = otherVerts[l + 1] - otherVerts[l];
Graphics::Vector3d e2;
if (l - 1 >= 0)
e2 = otherVerts[l] - otherVerts[l - 1];
else
e2 = otherVerts[l] - otherVerts[other->_numVertices - 1];
e1.normalize();
e2.normalize();
Graphics::Vector3d bisector = (e1 - e2);
bisector.normalize();
shrinkDir += bisector;
}
}
}
if (shrinkDir.magnitude() > 0.1f) {
shrinkDir.normalize();
_vertices[j] = _origVertices[j] + shrinkDir * radius;
} else {
_vertices[j] = _origVertices[j];
}
}
_vertices[_numVertices] = _vertices[0];
// Make sure the sector is still convex.
for (int j = 0; j < _numVertices; j++) {
Graphics::Vector3d e1 = _vertices[j + 1] - _vertices[j];
Graphics::Vector3d e2;
if (j - 1 >= 0)
e2 = _vertices[j] - _vertices[j - 1];
else
e2 = _vertices[j] - _vertices[_numVertices - 1];
if (e1.x() * e2.y() > e1.y() * e2.x()) {
// Not convex, so mark the sector invalid.
_invalid = true;
delete[] _vertices;
_vertices = _origVertices;
_origVertices = NULL;
break;
}
}
}
void Sector::unshrink() {
if (_shrinkRadius != 0.f) {
_shrinkRadius = 0.f;
_invalid = false;
if (_origVertices) {
delete[] _vertices;
_vertices = _origVertices;
_origVertices = NULL;
}
}
}
bool Sector::isPointInSector(const Graphics::Vector3d &point) const {
// The algorithm: for each edge A->B, check whether the z-component
// of (B-A) x (P-A) is >= 0. Then the point is at least in the
@ -375,8 +477,18 @@ Sector &Sector::operator=(const Sector &other) {
for (int i = 0; i < _numVertices + 1; ++i) {
_vertices[i] = other._vertices[i];
}
if (other._origVertices) {
_origVertices = new Graphics::Vector3d[_numVertices + 1];
for (int i = 0; i < _numVertices + 1; ++i) {
_origVertices[i] = other._origVertices[i];
}
} else {
_origVertices = NULL;
}
_height = other._height;
_normal = other._normal;
_shrinkRadius = other._shrinkRadius;
_invalid = other._invalid;
return *this;
}

View File

@ -48,7 +48,7 @@ public:
HotType = 0x8000
};
Sector() : _vertices(NULL) {}
Sector() : _vertices(NULL), _origVertices(NULL), _invalid(false), _shrinkRadius(0.f) {}
Sector(const Sector &other);
virtual ~Sector();
@ -58,11 +58,13 @@ public:
void load(TextSplitter &ts);
void loadBinary(Common::MemoryReadStream *ms);
void setVisible(bool visible);
void shrink(float radius);
void unshrink();
const char *getName() const { return _name.c_str(); }
int getSectorId() const { return _id; }
SectorType getType() const { return _type; } // FIXME: Implement type de-masking
bool isVisible() const { return _visible; }
bool isVisible() const { return _visible && !_invalid; }
bool isPointInSector(const Graphics::Vector3d &point) const;
Common::List<Graphics::Line3d> getBridgesTo(Sector *sector) const;
@ -93,8 +95,11 @@ private:
Common::String _name;
SectorType _type;
bool _visible;
bool _invalid;
Graphics::Vector3d *_vertices;
Graphics::Vector3d *_origVertices;
float _height;
float _shrinkRadius;
Graphics::Vector3d _normal;
};