mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-31 07:53:36 +00:00
GRIM: Implement ShrinkBoxes(), UnShrinkBoxes() and GetShrinkPos().
This commit is contained in:
parent
f5bd174755
commit
554bd2648f
@ -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, §or, &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);
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user