void IterateDynamicsFunctional3D::processGenericBlocks (
        Box3D domain, std::vector<AtomicBlock3D*> blocks )
{
    PLB_PRECONDITION( blocks.size()==1 );
    AtomicContainerBlock3D& container = *dynamic_cast<AtomicContainerBlock3D*>(blocks[0]);
    StoreDynamicsID* storeId = dynamic_cast<StoreDynamicsID*>(container.getData());
    std::vector<int> nextIDs(previousMaximum.size());
    for (pluint i=0; i<nextIDs.size(); ++i) {
        nextIDs[i] = -1;
    }
    if (!storeId->empty()) {
        nextIDs = storeId->getCurrent();
        util::extendVectorSize(nextIDs, previousMaximum.size());
        if (vectorEquals(nextIDs,previousMaximum)) {
            nextIDs = storeId->iterate();
            util::extendVectorSize(nextIDs, previousMaximum.size());
        }
    }
    for (pluint i=0; i<nextIDs.size(); ++i) {
        this->getStatistics().gatherMax(maxIds[i], (double)nextIDs[i]);
    }
}
Exemple #2
0
void pathfinder( const BNavmesh *navmesh, const BVector *start, const BVector *end, BPath *outPath )
{
	assert( outPath->numVertices == 0 );
	
	const BTriangle *const startTriangle = findTriangleContainingPoint( navmesh, start );
	const BTriangle *const endTriangle = findTriangleContainingPoint( navmesh, end );
	const BTriangle *adjustedStartTriangle, *adjustedEndTriangle;
	BVector adjustedStart, adjustedEnd;

	if ( startTriangle == NULL )
	{
		projectPointOntoNavmesh( navmesh, start, &adjustedStartTriangle, &adjustedStart );
	}
	else
	{
		adjustedStart = *start;
		adjustedStartTriangle = startTriangle;
	}
	assert( adjustedStartTriangle );

	const int isDestinationReachable = endTriangle != NULL && endTriangle->connectedComponent == adjustedStartTriangle->connectedComponent;
	if ( !isDestinationReachable )
	{
		projectPointOntoConnectedComponent( navmesh, end, adjustedStartTriangle->connectedComponent, &adjustedEndTriangle, &adjustedEnd );
	}
	else
	{
		adjustedEnd = *end;
		adjustedEndTriangle = endTriangle;
	}
	assert( adjustedEndTriangle );

	assert( isPointInsideNavmeshTriangle( navmesh, &adjustedStart, adjustedStartTriangle ) );
	assert( isPointInsideNavmeshTriangle( navmesh, &adjustedEnd, adjustedEndTriangle ) );

	BAStarOutput aStarOutput;
	aStar( navmesh, adjustedStartTriangle, adjustedEndTriangle, &adjustedEnd, &aStarOutput );
	
	funnelPath( navmesh, &adjustedStart, &adjustedEnd, &aStarOutput, outPath );
	
	freeAStarOutput( &aStarOutput );
	
	assert( outPath->numVertices > 0 );
	assert( outPath->vertices != NULL );

	if ( !vectorEquals( start, &adjustedStart ) )
	{
		BVector *newVertices = malloc( ( 1 + outPath->numVertices ) * sizeof( BVector ) );
		newVertices[0] = *start;
		memcpy( &newVertices[1], outPath->vertices, ( outPath->numVertices ) * sizeof( BVector ) );
		free( outPath->vertices );
		outPath->vertices = newVertices;
		outPath->numVertices++;
	}

	if ( isDestinationReachable && !vectorEquals( end, &adjustedEnd ) )
	{
		BVector *newVertices = malloc( ( 1 + outPath->numVertices ) * sizeof( BVector ) );
		newVertices[outPath->numVertices] = *end;
		memcpy( newVertices, outPath->vertices, ( outPath->numVertices ) * sizeof( BVector ) );
		free( outPath->vertices );
		outPath->vertices = newVertices;
		outPath->numVertices++;
	}
	
}
Exemple #3
0
// Based on: http://digestingduck.blogspot.com/2010/03/simple-stupid-funnel-algorithm.html
static void funnelPath( const BNavmesh *navmesh, const BVector *start, const BVector *end, const BAStarOutput *aStarOutput, BPath *outPath )
{
	const int numTriangles = aStarOutput->numTriangles;
	const BTriangle **triangles = aStarOutput->triangles;

	if ( numTriangles < 1 )
	{
		outPath->numVertices = 0;
		outPath->vertices = NULL;
		return;
	}

	if ( numTriangles == 1 )
	{
		outPath->numVertices = 2;
		outPath->vertices = malloc( 2 * sizeof( BVector ) );
		outPath->vertices[0] = *start;
		outPath->vertices[1] = *end;
		return;
	}

	assert( isPointInsideNavmeshTriangle( navmesh, start, triangles[0] ) );
	assert( isPointInsideNavmeshTriangle( navmesh, end, triangles[numTriangles - 1] ) );

	const int numPortals = numTriangles;
	BEdge *portals = malloc( numPortals * sizeof( BEdge ) );

	const int maxVertices = numTriangles + 1;
	outPath->vertices = malloc( sizeof( BVector ) * maxVertices );
	outPath->vertices[0] = *start;
	outPath->numVertices = 1;

	for ( int triangleIndex = 0; triangleIndex < numTriangles - 1; triangleIndex++ )
	{
		assert( triangleIndex < numTriangles );
		assert( triangleIndex < numPortals - 1 );
		assert( triangleIndex + 1 < numTriangles );
		getPortal( navmesh, triangles[triangleIndex], triangles[triangleIndex + 1], &portals[triangleIndex] );
	}
	portals[numPortals - 1].start = *end;
	portals[numPortals - 1].end = *end;

	BVector portalApex, portalLeft, portalRight;
	portalApex = *start;
	portalLeft = *start;
	portalRight = *start;

	int apexIndex, leftIndex, rightIndex;
	apexIndex = 0;
	leftIndex = 0;
	rightIndex = 0;

	for ( int portalIndex = 0; portalIndex < numPortals; portalIndex++ )
	{
		const BVector *right = &portals[portalIndex].start;
		const BVector *left = &portals[portalIndex].end;

		if ( triangleArea2( &portalApex, &portalRight, right ) <= 0 )
		{
			if ( vectorEquals( &portalApex, &portalRight ) || triangleArea2( &portalApex, &portalLeft, right ) > 0 )
			{
				// Tighten
				portalRight = *right;
				rightIndex = portalIndex;
			}
			else
			{
				// Right over left, insert left to path and restart scan from portal left point
				assert( outPath->numVertices < maxVertices );
				if ( !vectorEquals( &portalLeft, &outPath->vertices[outPath->numVertices - 1] ) )
				{
					outPath->vertices[outPath->numVertices] = portalLeft;
					outPath->numVertices++;
				}
				// Make current left the new apex
				portalApex = portalLeft;
				apexIndex = leftIndex;
				// Reset portal
				portalLeft = portalApex;
				portalRight = portalApex;
				leftIndex = apexIndex;
				rightIndex = apexIndex;
				// Restart scan
				portalIndex = apexIndex;
				continue;
			}
		}

		if ( triangleArea2( &portalApex, &portalLeft, left ) >= 0 )
		{
			if ( vectorEquals( &portalApex, &portalLeft ) || triangleArea2( &portalApex, &portalRight, left ) < 0 )
			{
				// Tighten
				portalLeft = *left;
				leftIndex = portalIndex;
			}
			else
			{
				// Left over right, insert right to path and restart scan from portal right point
				assert( outPath->numVertices < maxVertices );
				if ( !vectorEquals( &portalRight, &outPath->vertices[outPath->numVertices - 1] ) )
				{
					outPath->vertices[outPath->numVertices] = portalRight;
					outPath->numVertices++;
				}
				// Make current right the new apex
				portalApex = portalRight;
				apexIndex = rightIndex;
				// Reset portal
				portalLeft = portalApex;
				portalRight = portalApex;
				leftIndex = apexIndex;
				rightIndex = apexIndex;
				// Restart scan
				portalIndex = apexIndex;
				continue;
			}
		}
	}

	assert( vectorEquals( &outPath->vertices[0], start ) );
	if ( !vectorEquals( &outPath->vertices[outPath->numVertices - 1], end ) )
	{
		assert( outPath->numVertices < maxVertices );
		outPath->vertices[outPath->numVertices - 1] = *end;
		outPath->numVertices++;
	}

	free( portals );
}