aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Horn2009-03-22 23:02:54 +0000
committerMax Horn2009-03-22 23:02:54 +0000
commit00907f32bdc76dbca34ed84933573769952d0756 (patch)
treec1e924b6cfb47592e584271bcfcf82981acc9d18
parent7714b20abff459c52490381c5ef658bce9578d13 (diff)
downloadscummvm-rg350-00907f32bdc76dbca34ed84933573769952d0756.tar.gz
scummvm-rg350-00907f32bdc76dbca34ed84933573769952d0756.tar.bz2
scummvm-rg350-00907f32bdc76dbca34ed84933573769952d0756.zip
TINSEL: More polygon code cleanup
svn-id: r39618
-rw-r--r--engines/tinsel/polygons.cpp127
1 files changed, 66 insertions, 61 deletions
diff --git a/engines/tinsel/polygons.cpp b/engines/tinsel/polygons.cpp
index 34c977ddfd..126b62b632 100644
--- a/engines/tinsel/polygons.cpp
+++ b/engines/tinsel/polygons.cpp
@@ -135,21 +135,38 @@ struct LINEINFO {
#include "common/pack-end.h" // END STRUCT PACKING
-// POLY structure class. This is implemented as a class, because the structure
-// of POLY's changed between TINSEL v1 and v2
+/**
+ * POLY structure class. This is implemented as a class, because the structure
+ * of POLY's changed between TINSEL v1 and v2.
+ *
+ * FIXME: Right now, we always read *all* data in a polygon, even if only a single
+ * field is needed. This is rather inefficient.
+ */
class Poly {
private:
const byte * const _pStart;
const byte *_pData;
int _recordSize;
void nextPoly();
+
public:
Poly(const byte *pSrc);
Poly(const byte *pSrc, int startIndex);
void operator++();
void setIndex(int index);
+
+ POLY_TYPE getType() const { return (POLY_TYPE)FROM_LE_32(type); }
+ int getNodecount() const { return (int)FROM_LE_32(nodecount); }
+ int getNodeX(int i) const { return (int)FROM_LE_32(nlistx[i]); }
+ int getNodeY(int i) const { return (int)FROM_LE_32(nlisty[i]); }
+
+ // get Inter-node line structure
+ LINEINFO *getLineinfo(int i) const { return ((LINEINFO *)(_pStart + (int)FROM_LE_32(plinelist))) + i; }
+
+protected:
POLY_TYPE type; //!< type of polygon
+public:
int32 x[4], y[4]; // Polygon definition
uint32 xoff, yoff; // DW2 - polygon offset
@@ -169,7 +186,7 @@ public:
int32 reel; // } PATH and NPATH
int32 zFactor; // }
- //The arrays now stored externally
+protected:
int32 nodecount; //!<The number of nodes in this polygon
int32 pnodelistx, pnodelisty; //!<offset in chunk to this array if present
int32 plinelist;
@@ -177,6 +194,7 @@ public:
int32 *nlistx;
int32 *nlisty;
+public:
SCNHANDLE hScript; //!< handle of code segment for polygon events
};
@@ -209,9 +227,8 @@ static uint32 nextLong(const byte *&p) {
}
void Poly::nextPoly() {
- // Note: Originally I used a Serialiser, but dropped because for now we want
- // the endian to remain as it is. It may be cleaner to later on switch to using
- // it, and removing all endian conversions from the code that uses POLY's
+ // Note: For now we perform no endian conversion of the data. We could change that
+ // at some point, and remove all endian conversions from the code that uses POLY's
const byte *pRecord = _pData;
int typeVal = nextLong(_pData);
@@ -403,7 +420,6 @@ bool IsInPolygon(int xt, int yt, HPOLYGON hp) {
/**
* Finds a polygon of the specified type containing the supplied point.
*/
-
HPOLYGON InPolygon(int xt, int yt, PTYPE type) {
for (int j = 0; j <= MAX_POLY; j++) {
if (Polys[j] && Polys[j]->polyType == type) {
@@ -558,7 +574,6 @@ void FindBestPoint(HPOLYGON hp, int *x, int *y, int *pline) {
int dropD; // length of perpendicular (i.e. distance of point from line)
int dropX, dropY; // (X, Y) where dropped perpendicular intersects the line
int d1, d2; // distance from perpendicular intersect to line's end nodes
- int32 *nlistx, *nlisty;
int shortestD = 10000; // Shortest distance found
int nearestL = -1; // Nearest line
@@ -566,7 +581,6 @@ void FindBestPoint(HPOLYGON hp, int *x, int *y, int *pline) {
int h = *x; // For readability/conveniance
int k = *y; // - why aren't these #defines?
- LINEINFO *llist; // Inter-node line structure
CHECK_HP(hp, "Out of range polygon handle (3)");
pp = Polys[hp];
@@ -575,15 +589,13 @@ void FindBestPoint(HPOLYGON hp, int *x, int *y, int *pline) {
pps = LockMem(pHandle); // All polygons
Poly ptp(pps, pp->pIndex); // This polygon
- nlistx = ptp.nlistx;
- nlisty = ptp.nlisty;
- llist = (LINEINFO *)(pps + (int)FROM_LE_32(ptp.plinelist));
-
// Look for fit of perpendicular to lines between nodes
- for (int i = 0; i < (int)FROM_LE_32(ptp.nodecount) - 1; i++) {
- const int32 a = (int)FROM_LE_32(llist[i].a);
- const int32 b = (int)FROM_LE_32(llist[i].b);
- const int32 c = (int)FROM_LE_32(llist[i].c);
+ for (int i = 0; i < ptp.getNodecount() - 1; i++) {
+ LINEINFO *line = ptp.getLineinfo(i);
+
+ const int32 a = (int)FROM_LE_32(line->a);
+ const int32 b = (int)FROM_LE_32(line->b);
+ const int32 c = (int)FROM_LE_32(line->c);
#if 1
// TODO: If the comments of the LINEINFO struct are correct, then it contains mostly
@@ -598,7 +610,6 @@ void FindBestPoint(HPOLYGON hp, int *x, int *y, int *pline) {
// One bad thing: We use sqrt to compute a square root. Might not be a good idea,
// speed wise. Maybe we should take Vicent's fp_sqroot. But that's a problem for later.
- LINEINFO *line = &llist[i];
int32 a2 = (int)FROM_LE_32(line->a2); //!< a squared
int32 b2 = (int)FROM_LE_32(line->b2); //!< b squared
int32 a2pb2 = (int)FROM_LE_32(line->a2pb2); //!< a squared + b squared
@@ -626,8 +637,8 @@ void FindBestPoint(HPOLYGON hp, int *x, int *y, int *pline) {
dropX = ((b*b * h) - (a*b * k) - a*c) / (a*a + b*b);
// X distances from intersection to end nodes
- d1 = dropX - (int)FROM_LE_32(nlistx[i]);
- d2 = dropX - (int)FROM_LE_32(nlistx[i+1]);
+ d1 = dropX - ptp.getNodeX(i);
+ d2 = dropX - ptp.getNodeX(i+1);
// if both -ve or both +ve, no fit
if ((d1 < 0 && d2 < 0) || (d1 > 0 && d2 > 0))
@@ -637,8 +648,8 @@ void FindBestPoint(HPOLYGON hp, int *x, int *y, int *pline) {
dropY = ((a*a * k) - (a*b * h) - b*c) / (a*a + b*b);
// Y distances from intersection to end nodes
- d1 = dropY - (int)FROM_LE_32(nlisty[i]);
- d2 = dropY - (int)FROM_LE_32(nlisty[i+1]);
+ d1 = dropY - ptp.getNodeY(i);
+ d2 = dropY - ptp.getNodeY(i+1);
// if both -ve or both +ve, no fit
if ((d1 < 0 && d2 < 0) || (d1 > 0 && d2 > 0))
@@ -654,21 +665,22 @@ void FindBestPoint(HPOLYGON hp, int *x, int *y, int *pline) {
// Distance to nearest node
nearestN = NearestNodeWithin(hp, h, k);
- dropD = ABS(h - (int)FROM_LE_32(nlistx[nearestN])) + ABS(k - (int)FROM_LE_32(nlisty[nearestN]));
+ dropD = ABS(h - ptp.getNodeX(nearestN)) + ABS(k - ptp.getNodeY(nearestN));
// Go to a node or a point on a line
if (dropD < shortestD) {
// A node is nearest
- *x = (int)FROM_LE_32(nlistx[nearestN]);
- *y = (int)FROM_LE_32(nlisty[nearestN]);
+ *x = ptp.getNodeX(nearestN);
+ *y = ptp.getNodeY(nearestN);
*pline = nearestN;
} else {
assert(nearestL != -1);
// A point on a line is nearest
- const int32 a = (int)FROM_LE_32(llist[nearestL].a);
- const int32 b = (int)FROM_LE_32(llist[nearestL].b);
- const int32 c = (int)FROM_LE_32(llist[nearestL].c);
+ LINEINFO *line = ptp.getLineinfo(nearestL);
+ const int32 a = (int)FROM_LE_32(line->a);
+ const int32 b = (int)FROM_LE_32(line->b);
+ const int32 c = (int)FROM_LE_32(line->c);
dropX = ((b*b * h) - (a*b * k) - a*c) / (a*a + b*b);
dropY = ((a*a * k) - (a*b * h) - b*c) / (a*a + b*b);
*x = dropX;
@@ -811,7 +823,6 @@ int NearestEndNode(HPOLYGON hPath, int x, int y) {
int d1, d2;
uint8 *pps; // Compiled polygon data
- int32 *nlistx, *nlisty;
CHECK_HP(hPath, "Out of range polygon handle (8)");
pp = Polys[hPath];
@@ -819,15 +830,12 @@ int NearestEndNode(HPOLYGON hPath, int x, int y) {
pps = LockMem(pHandle); // All polygons
Poly ptp(pps, pp->pIndex); // This polygon
- nlistx = ptp.nlistx;
- nlisty = ptp.nlisty;
-
- const int nodecount = (int)FROM_LE_32(ptp.nodecount);
+ const int nodecount = ptp.getNodecount() - 1;
- d1 = ABS(x - (int)FROM_LE_32(nlistx[0])) + ABS(y - (int)FROM_LE_32(nlisty[0]));
- d2 = ABS(x - (int)FROM_LE_32(nlistx[nodecount - 1])) + ABS(y - (int)FROM_LE_32(nlisty[nodecount - 1]));
+ d1 = ABS(x - ptp.getNodeX(0)) + ABS(y - ptp.getNodeY(0));
+ d2 = ABS(x - ptp.getNodeX(nodecount)) + ABS(y - ptp.getNodeY(nodecount));
- return (d2 > d1) ? 0 : nodecount - 1;
+ return (d2 > d1) ? 0 : nodecount;
}
@@ -839,7 +847,6 @@ int NearestEndNode(HPOLYGON hPath, int x, int y) {
int NearEndNode(HPOLYGON hSpath, HPOLYGON hDpath) {
const POLYGON *pSpath, *pDpath;
- int ns, nd; // 'top' nodes in each path
int dist, NearDist;
int NearNode;
uint8 *pps; // Compiled polygon data
@@ -853,27 +860,28 @@ int NearEndNode(HPOLYGON hSpath, HPOLYGON hDpath) {
Poly ps(pps, pSpath->pIndex); // Start polygon
Poly pd(pps, pDpath->pIndex); // Dest polygon
- ns = (int)FROM_LE_32(ps.nodecount) - 1;
- nd = (int)FROM_LE_32(pd.nodecount) - 1;
+ // 'top' nodes in each path
+ const int ns = ps.getNodecount() - 1;
+ const int nd = pd.getNodecount() - 1;
// start[0] to dest[0]
- NearDist = ABS((int)FROM_LE_32(ps.nlistx[0]) - (int)FROM_LE_32(pd.nlistx[0])) + ABS((int)FROM_LE_32(ps.nlisty[0]) - (int)FROM_LE_32(pd.nlisty[0]));
+ NearDist = ABS(ps.getNodeX(0) - pd.getNodeX(0)) + ABS(ps.getNodeY(0) - pd.getNodeY(0));
NearNode = 0;
// start[0] to dest[top]
- dist = ABS((int)FROM_LE_32(ps.nlistx[0]) - (int)FROM_LE_32(pd.nlistx[nd])) + ABS((int)FROM_LE_32(ps.nlisty[0]) - (int)FROM_LE_32(pd.nlisty[nd]));
+ dist = ABS(ps.getNodeX(0) - pd.getNodeX(nd)) + ABS(ps.getNodeY(0) - pd.getNodeY(nd));
if (dist < NearDist)
NearDist = dist;
// start[top] to dest[0]
- dist = ABS((int)FROM_LE_32(ps.nlistx[ns]) - (int)FROM_LE_32(pd.nlistx[0])) + ABS((int)FROM_LE_32(ps.nlisty[ns]) - (int)FROM_LE_32(pd.nlisty[0]));
+ dist = ABS(ps.getNodeX(ns) - pd.getNodeX(0)) + ABS(ps.getNodeY(ns) - pd.getNodeY(0));
if (dist < NearDist) {
NearDist = dist;
NearNode = ns;
}
// start[top] to dest[top]
- dist = ABS((int)FROM_LE_32(ps.nlistx[ns]) - (int)FROM_LE_32(pd.nlistx[nd])) + ABS((int)FROM_LE_32(ps.nlisty[ns]) - (int)FROM_LE_32(pd.nlisty[nd]));
+ dist = ABS(ps.getNodeX(ns) - pd.getNodeX(nd)) + ABS(ps.getNodeY(ns) - pd.getNodeY(nd));
if (dist < NearDist) {
NearNode = ns;
}
@@ -887,7 +895,6 @@ int NearEndNode(HPOLYGON hSpath, HPOLYGON hDpath) {
*/
int NearestNodeWithin(HPOLYGON hNpath, int x, int y) {
int ThisDistance, SmallestDistance = 1000;
- int NumNodes; // Number of nodes in this follow nodes path
int NearestYet = 0; // Number of nearest node
uint8 *pps; // Compiled polygon data
@@ -896,10 +903,10 @@ int NearestNodeWithin(HPOLYGON hNpath, int x, int y) {
pps = LockMem(pHandle); // All polygons
Poly ptp(pps, Polys[hNpath]->pIndex); // This polygon
- NumNodes = (int)FROM_LE_32(ptp.nodecount);
+ const int numNodes = ptp.getNodecount(); // Number of nodes in this follow nodes path
- for (int i = 0; i < NumNodes; i++) {
- ThisDistance = ABS(x - (int)FROM_LE_32(ptp.nlistx[i])) + ABS(y - (int)FROM_LE_32(ptp.nlisty[i]));
+ for (int i = 0; i < numNodes; i++) {
+ ThisDistance = ABS(x - ptp.getNodeX(i)) + ABS(y - ptp.getNodeY(i));
if (ThisDistance < SmallestDistance) {
NearestYet = i;
@@ -1066,11 +1073,11 @@ void getNpathNode(HPOLYGON hNpath, int node, int *px, int *py) {
Poly ptp(pps, Polys[hNpath]->pIndex); // This polygon
// Might have just walked to the node from above.
- if (node == (int)FROM_LE_32(ptp.nodecount))
+ if (node == ptp.getNodecount())
node -= 1;
- *px = (int)FROM_LE_32(ptp.nlistx[node]);
- *py = (int)FROM_LE_32(ptp.nlisty[node]);
+ *px = ptp.getNodeX(node);
+ *py = ptp.getNodeY(node);
}
/**
@@ -1135,7 +1142,7 @@ int numNodes(HPOLYGON hp) {
Poly pp(LockMem(pHandle), Polys[hp]->pIndex);
- return (int)FROM_LE_32(pp.nodecount);
+ return pp.getNodecount();
}
// *************************************************************************
@@ -1411,17 +1418,15 @@ void CheckNPathIntegrity() {
if (rp && rp->polyType == PATH && rp->subtype == NODE) { //...if it's a node path
// Get compiled polygon structure
cp = (const Poly *)pps + rp->pIndex; // This polygon
- nlistx = cp->nlistx;
- nlisty = cp->nlisty;
- n = (int)FROM_LE_32(cp->nodecount) - 1; // Last node
+ n = cp->getNodecount() - 1; // Last node
assert(n >= 1); // Node paths must have at least 2 nodes
hp = PolygonIndex(rp);
for (j = 0; j <= n; j++) {
- if (!IsInPolygon((int)FROM_LE_32(nlistx[j]), (int)FROM_LE_32(nlisty[j]), hp)) {
+ if (!IsInPolygon(cp->getNodeX(j), cp->getNodeY(j), hp)) {
sprintf(TextBufferAddr(), "Node (%d, %d) is not in its own path (starting (%d, %d))",
- (int)FROM_LE_32(nlistx[j]), (int)FROM_LE_32(nlisty[j]), rp->cx[0], rp->cy[0]);
+ cp->getNodeX(j), cp->getNodeY(j), rp->cx[0], rp->cy[0]);
error(TextBufferAddr());
}
}
@@ -1431,14 +1436,14 @@ void CheckNPathIntegrity() {
if (rp->adjpaths[j] == NULL)
break;
- if (IsInPolygon((int)FROM_LE_32(nlistx[0]), (int)FROM_LE_32(nlisty[0]), PolygonIndex(rp->adjpaths[j]))) {
+ if (IsInPolygon(cp->getNodeX(0), cp->getNodeY(0), PolygonIndex(rp->adjpaths[j]))) {
sprintf(TextBufferAddr(), "Node (%d, %d) is in another path (starting (%d, %d))",
- (int)FROM_LE_32(nlistx[0]), (int)FROM_LE_32(nlisty[0]), rp->adjpaths[j]->cx[0], rp->adjpaths[j]->cy[0]);
+ cp->getNodeX(0), cp->getNodeY(0), rp->adjpaths[j]->cx[0], rp->adjpaths[j]->cy[0]);
error(TextBufferAddr());
}
- if (IsInPolygon((int)FROM_LE_32(nlistx[n]), (int)FROM_LE_32(nlisty[n]), PolygonIndex(rp->adjpaths[j]))) {
+ if (IsInPolygon(cp->getNodeX(n), cp->getNodeY(n), PolygonIndex(rp->adjpaths[j]))) {
sprintf(TextBufferAddr(), "Node (%d, %d) is in another path (starting (%d, %d))",
- (int)FROM_LE_32(nlistx[n]), (int)FROM_LE_32(nlisty[n]), rp->adjpaths[j]->cx[0], rp->adjpaths[j]->cy[0]);
+ cp->getNodeX(n), cp->getNodeY(n), rp->adjpaths[j]->cx[0], rp->adjpaths[j]->cy[0]);
error(TextBufferAddr());
}
}
@@ -1828,7 +1833,7 @@ void InitPolygons(SCNHANDLE ph, int numPoly, bool bRestart) {
Poly pp(LockMem(ph));
for (int i = 0; i < numPoly; ++i, ++pp) {
- switch (FROM_LE_32(pp.type)) {
+ switch (pp.getType()) {
case POLY_PATH:
InitPath(pp, false, i, bRestart);
break;