Exemplo n.º 1
0
void PathInfo::BuildShortcut()
{
    PATH_DEBUG("++ BuildShortcut :: making shortcut\n");

    clear();

    // make two point path, our curr pos is the start, and dest is the end
    m_pathPoints.resize(2);

    // set start and a default next position
    m_pathPoints.set(0, getStartPosition());
    m_pathPoints.set(1, getActualEndPosition());

    setNextPosition(getActualEndPosition());
    m_type = PATHFIND_SHORTCUT;
}
Exemplo n.º 2
0
bool PathInfo::Update(const float destX, const float destY, const float destZ, bool useStraightPath)
{
    PathNode newDest(destX, destY, destZ);
    PathNode oldDest = getEndPosition();
    setEndPosition(newDest);

    float x, y, z;
    m_sourceUnit->GetPosition(x, y, z);
    PathNode newStart(x, y, z);
    PathNode oldStart = getStartPosition();
    setStartPosition(newStart);

    m_useStraightPath = useStraightPath;

    DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ PathInfo::Update() for %u \n", m_sourceUnit->GetGUID());

    // make sure navMesh works - we can run on map w/o mmap
    if (!m_navMesh || !m_navMeshQuery || m_sourceUnit->hasUnitState(UNIT_STAT_IGNORE_PATHFINDING))
    {
        BuildShortcut();
        m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH);
        return true;
    }

    updateFilter();

    // check if destination moved - if not we can optimize something here
    // we are following old, precalculated path?
    float dist = m_sourceUnit->GetObjectBoundingRadius();
    if (inRange(oldDest, newDest, dist, dist) && m_pathPoints.size() > 2)
    {
        // our target is not moving - we just coming closer
        // we are moving on precalculated path - enjoy the ride
        DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ PathInfo::Update:: precalculated path\n");

        m_pathPoints.crop(1, 0);
        setNextPosition(m_pathPoints[1]);

        return false;
    }
    else
    {
        // target moved, so we need to update the poly path
        BuildPolyPath(newStart, newDest);
        return true;
    }
}
Exemplo n.º 3
0
void MosquitoNode::updateCurrent(sf::Time dt)
{
	// ALW - Simulation Mode
	if (mSimulationMode)
	{
		if (!mPause)
		{
			if (mDelaySet)
				delaySpawn(dt);

			if (mActive)
			{
				setNextPosition(dt);
				mAnimation.update(dt);
			}
		}
	}
}
Exemplo n.º 4
0
void PathInfo::BuildShortcut()
{
    //DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ BuildShortcut :: making shortcut\n");

    clear();

    // make two point path, our curr pos is the start, and dest is the end
    m_pathPoints.resize(2);

    // set start and a default next position
    m_pathPoints[0] = getStartPosition();
    m_pathPoints[1] = getActualEndPosition();

    NormalizePath();

    setNextPosition(getActualEndPosition());
    m_type = PATHFIND_SHORTCUT;
}
Exemplo n.º 5
0
void PathInfo::BuildPointPath(float *startPoint, float *endPoint)
{
    float pathPoints[MAX_POINT_PATH_LENGTH*VERTEX_SIZE];
    uint32 pointCount = 0;
    dtStatus dtResult = DT_FAILURE;
    bool usedOffmesh = false;
    if (m_useStraightPath)
    {
        dtResult = m_navMeshQuery->findStraightPath(
                startPoint,         // start position
                endPoint,           // end position
                m_pathPolyRefs,     // current path
                m_polyLength,       // lenth of current path
                pathPoints,         // [out] path corner points
                NULL,               // [out] flags
                NULL,               // [out] shortened path
                (int*)&pointCount,
                MAX_POINT_PATH_LENGTH);   // maximum number of points/polygons to use
    }
    else
    {
        dtResult = findSmoothPath(
                startPoint,         // start position
                endPoint,           // end position
                m_pathPolyRefs,     // current path
                m_polyLength,       // length of current path
                pathPoints,         // [out] path corner points
                (int*)&pointCount,
                usedOffmesh,
                MAX_POINT_PATH_LENGTH);    // maximum number of points
    }

    if (pointCount < 2 || dtResult != DT_SUCCESS)
    {
        // only happens if pass bad data to findStraightPath or navmesh is broken
        // single point paths can be generated here
        // TODO : check the exact cases
        DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ PathInfo::BuildPointPath FAILED! path sized %d returned\n", pointCount);
        BuildShortcut();
        m_type = PATHFIND_NOPATH;
        return;
    }

    // we need to flash our poly path to prevent it being used as subpath next cycle
    // in case of off mesh connection was used
    if(usedOffmesh)
        m_polyLength = 0;

    m_pathPoints.resize(pointCount);
    for (uint32 i = 0; i < pointCount; ++i)
        m_pathPoints.set(i, PathNode(pathPoints[i*VERTEX_SIZE+2], pathPoints[i*VERTEX_SIZE], pathPoints[i*VERTEX_SIZE+1]));

    // first point is always our current location - we need the next one
    setNextPosition(m_pathPoints[1]);
    setActualEndPosition(m_pathPoints[pointCount-1]);

    // force the given destination, if needed
    if(m_forceDestination &&
        (!(m_type & PATHFIND_NORMAL) || !inRange(getEndPosition(), getActualEndPosition(), 1.0f, 1.0f)))
    {
        setActualEndPosition(getEndPosition());
        BuildShortcut();
        m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH);
        return;
    }

    DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ PathInfo::BuildPointPath path type %d size %d poly-size %d\n", m_type, pointCount, m_polyLength);
}
Exemplo n.º 6
0
void PathInfo::BuildPointPath(const float* startPoint, const float* endPoint)
{
    float pathPoints[MAX_POINT_PATH_LENGTH * VERTEX_SIZE];
    uint32 pointCount = 0;
    dtStatus dtResult = DT_FAILURE;
    if (m_useStraightPath)
    {
        dtResult = m_navMeshQuery->findStraightPath(
                       startPoint,         // start position
                       endPoint,           // end position
                       m_pathPolyRefs,     // current path
                       m_polyLength,       // lenth of current path
                       pathPoints,         // [out] path corner points
                       NULL,               // [out] flags
                       NULL,               // [out] shortened path
                       (int*)&pointCount,
                       m_pointPathLimit);   // maximum number of points/polygons to use
    }
    else
    {
        dtResult = findSmoothPath(
                       startPoint,         // start position
                       endPoint,           // end position
                       m_pathPolyRefs,     // current path
                       m_polyLength,       // length of current path
                       pathPoints,         // [out] path corner points
                       (int*)&pointCount,
                       m_pointPathLimit);    // maximum number of points
    }

    if (pointCount < 2 || dtStatusFailed(dtResult))
    {
        // only happens if pass bad data to findStraightPath or navmesh is broken
        // single point paths can be generated here
        // TODO : check the exact cases
        sLog.outMMap("PathInfo::BuildPointPath FAILED! path sized %d returned\n", pointCount);
        BuildShortcut();
        m_type = PATHFIND_NOPATH;
        return;
    }
    else if (pointCount == m_pointPathLimit)
    {
        sLog.outMMap("PathInfo::BuildPointPath pointCount %u == m_pointPathLimit\n", pointCount);
        BuildShortcut();
        m_type = PATHFIND_SHORT;
        return;
    }

    m_pathPoints.resize(pointCount);
    for (uint32 i = 0; i < pointCount; ++i)
        m_pathPoints[i] = Vector3(pathPoints[i * VERTEX_SIZE + 2], pathPoints[i * VERTEX_SIZE], pathPoints[i * VERTEX_SIZE + 1]);

    NormalizePath();

    // first point is always our current location - we need the next one
    setNextPosition(m_pathPoints[1]);
    setActualEndPosition(m_pathPoints[pointCount - 1]);

    // force the given destination, if needed
    if (m_forceDestination &&
        (!(m_type & PATHFIND_NORMAL) || !inRange(getEndPosition(), getActualEndPosition(), 1.0f, 1.0f)))
    {
        // we may want to keep partial subpath
        if (dist3DSqr(getActualEndPosition(), getEndPosition()) <
            0.3f * dist3DSqr(getStartPosition(), getEndPosition()))
        {
            setActualEndPosition(getEndPosition());
            m_pathPoints[m_pathPoints.size() - 1] = getEndPosition();
        }
        else
        {
            setActualEndPosition(getEndPosition());
            BuildShortcut();
        }

        m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH);
    }

    //DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ PathInfo::BuildPointPath path type %d size %d poly-size %d\n", m_type, pointCount, m_polyLength);
}
Exemplo n.º 7
0
void PathInfo::updateNextPosition()
{
    float x, y, z;

    getStartPosition(x, y, z);
    float startPos[3] = {y, z, x};
    getEndPosition(x, y, z);
    float endPos[3] = {y, z, x};

    float* pathPoints = new float[MAX_PATH_LENGTH*3];
    int pointCount = m_navMesh->findStraightPath(
        startPos,           // start position
        endPos,             // end position
        m_pathPolyRefs,     // current path
        m_length,           // lenth of current path
        pathPoints,         // [out] path corner points
        0,                  // [out] flags
        0,                  // [out] shortened path  PATHFIND TODO: see if this is usable (IE, doesn't leave gaps in path)
        MAX_PATH_LENGTH);   // maximum number of points/polygons to use

    // TODO: imitate PATHFIND_ITER code from RecastDemo so that terrain following is smoother

    if(pointCount == 0)
    {
        delete [] pathPoints;

        // only happens if pass bad data to findStraightPath or navmesh is broken
        sLog.outDebug("%u's UpdateNextPosition failed: 0 length path", m_sourceObject->GetGUID());
        shortcut();
        return;
    }

    int ix, iy, iz;
    if(pointCount == 1)
    {
        ix = 2; iy = 0; iz = 1;
    }
    else
    {
        ix = 5; iy = 3; iz = 4;
    }

    setNextPosition(pathPoints[ix], pathPoints[iy], pathPoints[iz]);

    // if startPosition == nextPosition, NPC will never advance to destination
    if(isSamePoint(m_startPosition, m_nextPosition) && !isSamePoint(m_nextPosition, m_endPosition))
        setNextPosition(pathPoints[ix + 3], pathPoints[iy + 3], pathPoints[iz + 3]);

    delete [] m_pathPoints;
    m_pathPoints = pathPoints;

    m_type = PathType(m_type | PATHFIND_NORMAL);

    // if end position from findStraightPath isn't the
    // place we want to go, there is likely no path
    endPos[0] = pathPoints[(pointCount-1)*3+2];
    endPos[1] = pathPoints[(pointCount-1)*3];
    endPos[2] = pathPoints[(pointCount-1)*3+1];
    if(!dtVequal(endPos, m_endPosition))
        m_type = PathType(m_type | PATHFIND_NOPATH);
}
Exemplo n.º 8
0
void PathInfo::Update(const float destX, const float destY, const float destZ)
{
    float x, y, z;

    // update start and end
    m_sourceObject->GetPosition(x, y, z);
    setStartPosition(x, y, z);
    setEndPosition(destX, destY, destZ);

    // make sure navMesh works
    if(!m_navMesh)
    {
        m_sourceObject->GetPosition(x, y, z);
        m_navMesh = m_sourceObject->GetMap()->GetNavMesh();

        if(!m_navMesh)
        {
            // can't pathfind if navmesh doesn't exist
            shortcut();
            return;
        }
    }

    if(!m_pathPolyRefs)
    {
        // path was not built before, most likely because navmesh wasn't working
        // start from scratch, then return
        Build();
        return;
    }

    // should be safe to update path now

    bool startOffPath = false;
    bool endOffPath = false;

    // find start and end poly
    // navMesh.findNearestPoly is expensive, so first we check just the current path
    getStartPosition(x, y, z);
    dtPolyRef startPoly = getPathPolyByPosition(x, y, z);
    getEndPosition(x, y, z);
    dtPolyRef endPoly = getPathPolyByPosition(x, y, z);

    if(startPoly != 0 && endPoly != 0)
        trim(startPoly, endPoly);
    else
    {
        // start or end is off the path, need to find the polygon

        float extents[3] = {2.f, 4.f, 2.f};      // bounds of poly search area
        dtQueryFilter filter = dtQueryFilter();     // filter for poly search

        if(!startPoly)
        {
            getStartPosition(x, y, z);
            float startPos[3] = {y, z, x};
            startOffPath = true;
            startPoly = m_navMesh->findNearestPoly(startPos, extents, &filter, 0);
        }
        if(!endPoly)
        {
            getEndPosition(x, y, z);
            float endPos[3] = {y, z, x};
            endOffPath = true;
            endPoly = m_navMesh->findNearestPoly(endPos, extents, &filter, 0);
        }

        if(startPoly == 0 || endPoly == 0)
        {
            // source or dest not near navmesh polygons:
            // flying, falling, swimming, or navmesh has a hole

            // ignore obstacles/terrain is better than giving up
            // PATHFIND TODO: prevent walking/swimming mobs from flying into the air
            shortcut();
            return;
        }
    }

    if(startPoly == endPoly)
    {
        // start and end are on same polygon
        // just need to move in straight line

        // PATHFIND TODO: prevent walking/swimming mobs from flying into the air

        clear();
        m_pathPolyRefs = new dtPolyRef[1];
        m_pathPolyRefs[0] = startPoly;
        m_length = 1;
        getEndPosition(x, y, z);
        setNextPosition(x, y, z);
        m_type = PathType(m_type | PATHFIND_NORMAL);
        return;
    }

    if(startOffPath)
    {
        bool adjacent = false;
        int i;
        for(i = 0; i < DT_VERTS_PER_POLYGON; ++i)
            if(startPoly == m_navMesh->getPolyByRef(m_pathPolyRefs[0])->neis[i])
            {
                adjacent = true;
                break;
            }

        if(adjacent)
        {
            // startPoly is adjacent to the path, we can add it to the start of the path
            // 50th poly will fall off of path, shouldn't be an issue because most paths aren't that long
            m_length = m_length < MAX_PATH_LENGTH ? m_length + 1 : m_length;
            dtPolyRef* temp = new dtPolyRef[m_length];
            temp[0] = startPoly;

            for(i = 1; i < m_length; ++i)
                temp[i] = m_pathPolyRefs[i - 1];

            delete [] m_pathPolyRefs;
            m_pathPolyRefs = temp;
        }
        else
        {
            // waste of time to optimize, just find brand new path
            Build(startPoly, endPoly);
            return;
        }
    }

    if(endOffPath)
    {
        bool adjacent = false;
        int i;
        for(i = 0; i < DT_VERTS_PER_POLYGON; ++i)
            if(startPoly == m_navMesh->getPolyByRef(m_pathPolyRefs[0])->neis[i])
            {
                adjacent = true;
                break;
            }

        if(adjacent)
        {
            if(m_length < MAX_PATH_LENGTH)
            {
                // endPoly is adjacent to the path, and we have enough room to add it to the end
                dtPolyRef* temp = new dtPolyRef[m_length + 1];
                for(i = 0; i < m_length; ++i)
                    temp[i] = m_pathPolyRefs[i];

                temp[i] = endPoly;

                delete [] m_pathPolyRefs;
                m_pathPolyRefs = temp;
            }
            //else
            //    ;   // endPoly is adjacent to the path, we just don't have room to store it
        }
        else
        {
            // waste of time to optimize, just find brand new path
            Build(startPoly, endPoly);
            return;
        }
    }

    updateNextPosition();
}