示例#1
0
int main()
{
    //srand((int)time(0));
    LKDTreeMatrix dataSet(10, 3, 0.0f);
    LKDTreeMatrix data(1, 3);
    data[0][0] = 3.0f;
    data[0][1] = 2.5f;
    data[0][2] = -5.0f;


    LKDTree tree;

    for (unsigned int i = 0; i < 500; i++)
    {
        printf("Test Index: %u\n", i);

        RandMatrix(dataSet, -10.0f, 10.0f);

        if (i == 739)
        {
            printf("Stop\n");
        }

        tree.BuildTree(dataSet);


        int predictNN = tree.SearchNearestNeighbor(data);

        int actualNN = FindNearestNeighbor(dataSet, data);

        if (actualNN != predictNN)
        {
            printf("Fail\n");
            break;
        }

    }

    system("pause");
    return 0;
}
示例#2
0
HRESULT Update(double deltaTime)
{
	HRESULT hr = S_OK;

	if (g_endgame)
		return EndgameUpdate(deltaTime);

	// TODO: Optimize for cache coherency
	//		 We could attempt to store chains of nodes linearly in memory. That would make the update loop for nodes in those chains
	//		 super fast (since the most chains could probably fit in one cache line). But it would involve a lot of mem moves and 
	//		 could introduce some complexity. Since we're already under 1ms average, I'd say let's not do it.

	// Sort into buckets
	BeginCounter(&binningCounter);
	{
		float pixelsPerVert = float((g_width * g_height) / g_numActiveNodes);
		float binDiameterPixels = sqrt(pixelsPerVert); // conservative
	
		g_binNHeight = binDiameterPixels / g_height;
		g_binNWidth  = binDiameterPixels / g_width;

		g_binCountX  = uint(ceilf(1.0f / g_binNWidth) )+2;  // Add a boundary around the outside
		g_binCountY  = uint(ceilf(1.0f / g_binNHeight))+2;

		uint xiter = g_binUpdateIter % g_numBinSplits;
		uint yiter = g_binUpdateIter / g_numBinSplits;
		g_binRangeX[0] = (g_binCountX * xiter/g_numBinSplits)		  - 1;	// Subtract/Add 1 to each of these ranges for a buffer layer
		g_binRangeX[1] = (g_binCountX * (xiter+1)/g_numBinSplits - 1) + 1;	// This buffer layer will be overlap for each quadrant
		g_binRangeY[0] = (g_binCountY * yiter/g_numBinSplits)		  - 1;	// But without it verts would only target verts in their quadrant
		g_binRangeY[1] = (g_binCountY * (yiter+1)/g_numBinSplits - 1) + 1;
		g_binStride  = g_numSlots / ((g_binRangeX[1] - g_binRangeX[0] + 1) * (g_binRangeY[1] - g_binRangeY[0] + 1));

		int bin;
		memset(g_slots, EMPTY_SLOT, sizeof(g_slots));
		for (uint i = 0; i < g_numNodes; i++)
		{
			if (g_nodes[i].attribs.hasChild == true) continue; // Only bin the chompable tails
			hr = Bin(g_nodes[i].position.getX(), g_nodes[i].position.getY(), &bin);
			if (FAILED(hr)) // If this bin isn't backed by memory, we can't be a target this frame
				continue;

			// Find first empty bin slot
			for (uint slot = 0; slot < g_binStride; slot++) 
			{
				if (g_slots[bin*g_binStride + slot] == EMPTY_SLOT)
				{
					g_slots[bin*g_binStride + slot] = i;
					break;
				}
			}
			// If we overflow the bins, the vertex cannot be targeted. Haven't seen any cases yet...
		}
		g_binUpdateIter = (g_binUpdateIter+1) % (g_numBinSplits*g_numBinSplits);
	}
	EndCounter(&binningCounter);

	// Determine nearest neighbors
	BeginCounter(&nearestNeighborCounter);
	for (uint i = 0; i < g_numNodes; i++)
	{
		IFC( FindNearestNeighbor(i) );
	}
	EndCounter(&nearestNeighborCounter);

	BeginCounter(&positionUpdate);
	for (uint i = 0; i < g_numNodes; i++)
	{
		// Do our memory reads here so we can optimize our access patterns
		Node& current = g_nodes[i];
		Node& target = g_nodes[current.attribs.targetID];

		// Get target vector
		// For optimal precision, pull our shorts into floats and do all math at full precision...
		float2 targetVec;
		targetVec.x = target.position.getX() - current.position.getX(); 
		targetVec.y = target.position.getY() - current.position.getY();

		float dist = targetVec.getLength();
		float2 dir = targetVec;
		if (dist != 0)
			dir = dir / dist;
		
		// Calculate change in position
		float2 offset;
		if (current.attribs.hasParent)
		{
			// This controls wigglyness. Perhaps it should be a function of velocity? (static is more wiggly)
			float parentPaddingRadius = g_tailDist;// + (rand() * 2 - 1)*g_tailDist*0.3f;
			offset = targetVec - dir * parentPaddingRadius;
		}
		else
			offset = min(targetVec, dir * float(g_speed * deltaTime));
		
		// ... then finally, at the verrrry end, stuff our FP floats into 16-bit shorts
		current.position.setX(current.position.getX() + offset.x);
		current.position.setY(current.position.getY() + offset.y);
		
		// Check for chomps
		if (current.attribs.hasParent == false && dist <= g_tailDist)
			Chomp(i);
	}
	EndCounter(&positionUpdate);

Cleanup:
	if (g_numActiveNodes == 1)
		return EndgameInit();

	return hr;
}