void Actor::setActorPath(ActorData *actor, const Point &fromPoint, const Point &toPoint) { Point nextPoint; int8 direction; _pathList[0] = toPoint; nextPoint = toPoint; _pathListIndex = 0; while (!(nextPoint == fromPoint)) { direction = getPathCell(nextPoint); if ((direction < 0) || (direction >= 8)) { error("Actor::setActorPath error direction 0x%X", direction); } nextPoint.x -= pathDirectionLUT2[direction][0]; nextPoint.y -= pathDirectionLUT2[direction][1]; ++_pathListIndex; if (_pathListIndex >= _pathList.size()) { _pathList.push_back(nextPoint); } else { _pathList[_pathListIndex] = nextPoint; } #ifdef ACTOR_DEBUG addDebugPoint(nextPoint, 0x8a); #endif } pathToNode(); removeNodes(); nodeToPath(); removePathPoints(); for (uint i = 0; i < _pathNodeList.size(); i++) { actor->addWalkStepPoint(_pathNodeList[i].point); } }
void Actor::findActorPath(ActorData *actor, const Point &fromPoint, const Point &toPoint) { Point iteratorPoint; Point bestPoint; int maskType; int i; Rect intersect; #ifdef ACTOR_DEBUG _debugPointsCount = 0; #endif actor->_walkStepsCount = 0; if (fromPoint == toPoint) { actor->addWalkStepPoint(toPoint); return; } for (iteratorPoint.y = 0; iteratorPoint.y < _yCellCount; iteratorPoint.y++) { for (iteratorPoint.x = 0; iteratorPoint.x < _xCellCount; iteratorPoint.x++) { if (_vm->_scene->validBGMaskPoint(iteratorPoint)) { maskType = _vm->_scene->getBGMaskType(iteratorPoint); setPathCell(iteratorPoint, _vm->_scene->getDoorState(maskType) ? kPathCellBarrier : kPathCellEmpty); } else { setPathCell(iteratorPoint, kPathCellBarrier); } } } for (i = 0; i < _barrierCount; i++) { intersect.left = MAX(_pathRect.left, _barrierList[i].left); intersect.top = MAX(_pathRect.top, _barrierList[i].top); intersect.right = MIN(_pathRect.right, _barrierList[i].right); intersect.bottom = MIN(_pathRect.bottom, _barrierList[i].bottom); for (iteratorPoint.y = intersect.top; iteratorPoint.y < intersect.bottom; iteratorPoint.y++) { for (iteratorPoint.x = intersect.left; iteratorPoint.x < intersect.right; iteratorPoint.x++) { setPathCell(iteratorPoint, kPathCellBarrier); } } } #ifdef ACTOR_DEBUG for (iteratorPoint.y = 0; iteratorPoint.y < _yCellCount; iteratorPoint.y++) { for (iteratorPoint.x = 0; iteratorPoint.x < _xCellCount; iteratorPoint.x++) { if (getPathCell(iteratorPoint) == kPathCellBarrier) { addDebugPoint(iteratorPoint, 24); } } } #endif if (scanPathLine(fromPoint, toPoint)) { actor->addWalkStepPoint(fromPoint); actor->addWalkStepPoint(toPoint); return; } i = fillPathArray(fromPoint, toPoint, bestPoint); if (fromPoint == bestPoint) { actor->addWalkStepPoint(bestPoint); return; } if (i == 0) { error("fillPathArray returns zero"); } setActorPath(actor, fromPoint, bestPoint); }
int Actor::fillPathArray(const Point &fromPoint, const Point &toPoint, Point &bestPoint) { int bestRating; int currentRating; Point bestPath; int pointCounter; const PathDirectionData *samplePathDirection; Point nextPoint; int directionCount; int16 compressX = (_vm->getGameId() == GID_ITE) ? 2 : 1; Common::List<PathDirectionData> pathDirectionQueue; pointCounter = 0; bestRating = quickDistance(fromPoint, toPoint, compressX); bestPath = fromPoint; for (int8 startDirection = 0; startDirection < 4; startDirection++) { PathDirectionData tmp = { startDirection, fromPoint.x, fromPoint.y }; pathDirectionQueue.push_back(tmp); } if (validPathCellPoint(fromPoint)) { setPathCell(fromPoint, kDirUp); #ifdef ACTOR_DEBUG addDebugPoint(fromPoint, 24+36); #endif } while (!pathDirectionQueue.empty()) { PathDirectionData curPathDirection = pathDirectionQueue.front(); pathDirectionQueue.pop_front(); for (directionCount = 0; directionCount < 3; directionCount++) { samplePathDirection = &pathDirectionLUT[curPathDirection.direction][directionCount]; nextPoint = Point(curPathDirection.x, curPathDirection.y); nextPoint.x += samplePathDirection->x; nextPoint.y += samplePathDirection->y; if (!validPathCellPoint(nextPoint)) { continue; } if (getPathCell(nextPoint) != kPathCellEmpty) { continue; } setPathCell(nextPoint, samplePathDirection->direction); #ifdef ACTOR_DEBUG addDebugPoint(nextPoint, samplePathDirection->direction + 96); #endif PathDirectionData tmp = { samplePathDirection->direction, nextPoint.x, nextPoint.y }; pathDirectionQueue.push_back(tmp); ++pointCounter; if (nextPoint == toPoint) { bestPoint = toPoint; return pointCounter; } currentRating = quickDistance(nextPoint, toPoint, compressX); if (currentRating < bestRating) { bestRating = currentRating; bestPath = nextPoint; } } } bestPoint = bestPath; return pointCounter; }
bool AABB::intersectsTri( const PrecomputedTriangle& tri, Vector3f &penetration ) const { // the algorith on pg 168 of rtcd is: // do SAT test on: // 1. tri normal // 2. 3 face normals from aabb // 3. 9 axes given by cross products of COMBINATIONS OF EDGES from both the tri and aabb. // - The aabb has 3 unique edge directions (principle axes), and the tri has 3 unique edges. float minOverlap = HUGE ; Vector3f axisOfMinOverlap ; // value b/c the crossed axes are temporary // 1. tri normal float meMin, meMax, oMin, oMax, lowerLim, upperLim ; SATtest( tri.plane.normal, corners, meMin, meMax ) ; SATtest( tri.plane.normal, tri.a, oMin, oMax ) ; //Only need to test 1 pt from tri, since all 3 will collapse to same pt. // Because the tri is going to appear as a POINT in the test, // we have to use `maxOverlaps`. See the comments in `maxOverlaps` // for how it detects overlaps differently than plain `overlaps` if( !maxOverlaps( meMin, meMax, oMin, oMax, lowerLim, upperLim ) ) { addDebugLine( tri.plane.normal*meMin, tri.plane.normal*meMax, Red ) ; addDebugPoint( tri.plane.normal*oMin, Blue ) ; return 0 ; } // These by default are the maxes then minOverlap = upperLim-lowerLim ; axisOfMinOverlap = tri.plane.normal ; // 2. 3 face normals from aabb. for( int axis = 0 ; axis < 3 ; axis++ ) { // because we're projecting points in 3 space TO THE PRINCIPAL AXES, // the span of the projection of all the vertices is just going to be // the min/max in each priniciple axis direction. // Does this look like I ripped this off the convex hull intersection code, cuz i did. meMin=HUGE,meMax=-HUGE ; // init these here for( int j = 0 ; j < corners.size() ; j++ ) { if( corners[j].elts[axis] < meMin ) meMin=corners[j].elts[axis]; if( corners[j].elts[axis] > meMax ) meMax=corners[j].elts[axis]; } // we "cheat" here and just pick out the correct index for the aabb. // its axis aligned! oMin=min.elts[axis] ; oMax=max.elts[axis] ; if( !overlaps( meMin, meMax, oMin, oMax, lowerLim, upperLim ) ) return 0 ; // Overlaps. See if this was the smallest overlap yet float overlap=upperLim-lowerLim ; if( overlap < minOverlap ) { axisOfMinOverlap = axis ; minOverlap = overlap ; } } // See how inaccurate it is w/o cross products //penetration = axisOfMinOverlap*minOverlap ; //return 1 ; // 3 cross products. for( int aabbAxis = 0 ; aabbAxis < 3 ; aabbAxis++ ) { for( int triEdge=0 ; triEdge < 3 ; triEdge++ ) { Vector3f axis = SATAxes[aabbAxis].cross( tri.edges[triEdge] ) ; if( axis.allzero() ) skip ; // this happens often axis.normalize() ; SATtest( axis, corners, meMin, meMax ) ; SATtest( axis, &tri.a, 3, oMin, oMax ) ; // use all 3 tri verts. if( !overlaps( meMin, meMax, oMin, oMax, lowerLim, upperLim ) ) { //addDebugLine( transformedNormals[i]*meMin, transformedNormals[i]*meMax, Red ) ; //addDebugLine( transformedNormals[i]*oMin, transformedNormals[i]*oMax, Blue ) ; return 0 ; } // Overlaps. See if this was the smallest overlap yet float overlap=upperLim-lowerLim ; if( overlap < minOverlap ) { axisOfMinOverlap = axis ; minOverlap = overlap ; } } } penetration = axisOfMinOverlap*minOverlap ; return 1 ; }