diff options
author | Max Horn | 2009-03-22 23:02:54 +0000 |
---|---|---|
committer | Max Horn | 2009-03-22 23:02:54 +0000 |
commit | 00907f32bdc76dbca34ed84933573769952d0756 (patch) | |
tree | c1e924b6cfb47592e584271bcfcf82981acc9d18 | |
parent | 7714b20abff459c52490381c5ef658bce9578d13 (diff) | |
download | scummvm-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.cpp | 127 |
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; |