Example #1
0
_Use_decl_annotations_
int32_t BspCompiler::ProcessTriangles(Triangle** triangles, uint32_t count)
{
    Triangle* front = nullptr;
    Triangle* back = nullptr;
    const Triangle* splitTriangle = nullptr;
    uint32_t frontCount, backCount;

    if (FindBestSplit(triangles, count, &splitTriangle, &front, &frontCount, &back, &backCount))
    {
        // Able to split the set of triangles. We need a node to desribe this
        Node node;
        node.Plane = splitTriangle->Plane;
        node.Front = ProcessTriangles(&front, frontCount);
        node.Back = ProcessTriangles(&back, backCount);
        _nodes.push_back(node);
        return static_cast<int32_t>(_nodes.size() - 1);
    }
    else
    {
        // Not able to split, already convex. Make it a sector
        Sector sector;
        CreateSectorFromTriangles(triangles, count, &sector);
        _sectors.push_back(sector);
        return static_cast<int32_t>(_sectors.size() - 1) * -1 - 1;
    }
}
Example #2
0
BVHAccelTreeNode *BVHAccel::BuildHierarchy(std::vector<BVHAccelTreeNode *> &list, unsigned int begin, unsigned int end, unsigned int axis) {
	unsigned int splitAxis = axis;
	float splitValue;

	nNodes += 1;
	if (end - begin == 1) // Only a single item in list so return it
		return list[begin];

	BVHAccelTreeNode *parent = new BVHAccelTreeNode();
	parent->primitive = 0xffffffffu;
	parent->leftChild = NULL;
	parent->rightSibling = NULL;

	std::vector<unsigned int> splits;
	splits.reserve(treeType + 1);
	splits.push_back(begin);
	splits.push_back(end);
	for (unsigned int i = 2; i <= treeType; i *= 2) { // Calculate splits, according to tree type and do partition
		for (unsigned int j = 0, offset = 0; j + offset < i && splits.size() > j + 1; j += 2) {
			if (splits[j + 1] - splits[j] < 2) {
				j--;
				offset++;
				continue; // Less than two elements: no need to split
			}

			FindBestSplit(list, splits[j], splits[j + 1], &splitValue, &splitAxis);

			std::vector<BVHAccelTreeNode *>::iterator it =
					partition(list.begin() + splits[j], list.begin() + splits[j + 1], bind2nd(ptr_fun(bvh_ltf[splitAxis]), splitValue));
			unsigned int middle = distance(list.begin(), it);
			middle = Max(splits[j] + 1, Min(splits[j + 1] - 1, middle)); // Make sure coincidental BBs are still split
			splits.insert(splits.begin() + j + 1, middle);
		}
	}

	BVHAccelTreeNode *child, *lastChild;
	// Left Child
	child = BuildHierarchy(list, splits[0], splits[1], splitAxis);
	parent->leftChild = child;
	parent->bbox = child->bbox;
	lastChild = child;

	// Add remaining children
	for (unsigned int i = 1; i < splits.size() - 1; i++) {
		child = BuildHierarchy(list, splits[i], splits[i + 1], splitAxis);
		lastChild->rightSibling = child;
		parent->bbox = Union(parent->bbox, child->bbox);
		lastChild = child;
	}

	return parent;
}
Example #3
0
void RayIntersectorKDTreeNode::MakeInteriorNode(const Vector<UINT> &TriangleIndices, const RayIntersectorKDTree &Root, UINT Depth, Vector<UINT> &LeafTriangles)
{
    UINT BestAxis;
    float SplitValue;
    if(FindBestSplit(TriangleIndices, Root, BestAxis, SplitValue))
    {
        _Flags.Leaf = 0;
        //_Flags.Axis = BestAxis;
        Vector<UINT> LeftTriangleIndices, RightTriangleIndices;

        for(UINT TriangleIndex = 0; TriangleIndex < TriangleIndices.Length(); TriangleIndex++)
        {
            UINT LeftVertices = 0, RightVertices = 0;
            const UINT BaseIndexIndex = TriangleIndices[TriangleIndex] * 3;
            for(UINT VertexIndex = 0; VertexIndex < 3; VertexIndex++)
            {
                const Vec3f &CurVertex = Root._Vertices[Root._Indices[BaseIndexIndex + VertexIndex]];
                if(CurVertex[BestAxis] < SplitValue)
                {
                    LeftVertices++;
                }
                if(CurVertex[BestAxis] >= SplitValue)
                {
                    RightVertices++;
                }
            }
            bool OnLeftSide = (LeftVertices > RightVertices);
            bool OnRightSide = !OnLeftSide;
            if(OnLeftSide)
            {
                LeftTriangleIndices.PushEnd(TriangleIndices[TriangleIndex]);
            }
            if(OnRightSide)
            {
                RightTriangleIndices.PushEnd(TriangleIndices[TriangleIndex]);
            }
        }

        //_Interior.SplitValue = SplitValue;
        _Interior.Left = new RayIntersectorKDTreeNode(LeftTriangleIndices, Root, Depth + 1, LeafTriangles);
        _Interior.Right = new RayIntersectorKDTreeNode(RightTriangleIndices, Root, Depth + 1, LeafTriangles);
    }
    else
    {
        MakeLeafNode(TriangleIndices, LeafTriangles);
    }
}
Example #4
0
_Use_decl_annotations_
void KdTreeCompiler2::Process(uint32_t nodeIndex, uint32_t trianglesRoot, uint32_t numTriangles, const float min[3], const float max[3])
{
    // Find the best split. If this function fails, it means we can't/shouldn't split further,
    // and should just make this node into a leaf.
    uint32_t splitAxis, frontRoot, backRoot, frontCount, backCount;
    float splitValue, frontMin[3], frontMax[3], backMin[3], backMax[3];

    if (FindBestSplit(trianglesRoot, numTriangles, &splitAxis, &splitValue, min, max,
        &frontRoot, &frontCount, frontMin, frontMax, &backRoot, &backCount, backMin, backMax))
    {
        uint32_t frontNode = AllocNode();
        uint32_t backNode = AllocNode();
        KdNode* node = &_nodes[nodeIndex];
        node->Axis = splitAxis;
        node->Value = splitValue;
        node->Front = frontNode;
        memcpy_s(node->Min, sizeof(node->Min), min, sizeof(node->Min));
        memcpy_s(node->Max, sizeof(node->Max), max, sizeof(node->Max));

        Process(frontNode, frontRoot, frontCount, frontMin, frontMax);
        Process(backNode, backRoot, backCount, backMin, backMax);
    }
    else
    {
        KdNode* node = &_nodes[nodeIndex];
        node->Axis = 3;
        node->NumTriangles = numTriangles;
        memcpy_s(node->Min, sizeof(node->Min), min, sizeof(node->Min));
        memcpy_s(node->Max, sizeof(node->Max), max, sizeof(node->Max));
        for (uint32_t i = 0; i < numTriangles; ++i)
        {
            uint32_t tri = AllocTriangle(_compilerTriangles[i]);
            if (i == 0)
            {
                node->FirstTriangle = tri;
            }
        }
    }
}
Example #5
0
//
// Pick a splitter poly then split a pool of polygons into front and back polygons and
// recurse.
//
// iParent = Parent Bsp node, or INDEX_NONE if this is the root node.
// IsFront = 1 if this is the front node of iParent, 0 of back (undefined if iParent==INDEX_NONE)
//
void FBSPOps::SplitPolyList
(
	UModel				*Model,
	int32                 iParent,
	ENodePlace			NodePlace,
	int32                 NumPolys,
	FPoly				**PolyList,
	EBspOptimization	Opt,
	int32					Balance,
	int32					PortalBias,
	int32					RebuildSimplePolys
)
{
	FMemMark Mark(FMemStack::Get());

	// Keeping track of allocated FPoly structures to delete later on.
	TArray<FPoly*> AllocatedFPolys;

	// To account for big EdPolys split up.
	int32 NumPolysToAlloc = NumPolys + 8 + NumPolys/4;
	int32 NumFront=0; FPoly **FrontList = new(FMemStack::Get(),NumPolysToAlloc)FPoly*;
	int32 NumBack =0; FPoly **BackList  = new(FMemStack::Get(),NumPolysToAlloc)FPoly*;

	FPoly *SplitPoly = FindBestSplit( NumPolys, PolyList, Opt, Balance, PortalBias );

	// Add the splitter poly to the Bsp with either a new BspSurf or an existing one.
	if( RebuildSimplePolys )
	{
		SplitPoly->iLink = Model->Surfs.Num();
	}

	int32 iOurNode	= bspAddNode(Model,iParent,NodePlace,0,SplitPoly);
	int32 iPlaneNode	= iOurNode;

	// Now divide all polygons in the pool into (A) polygons that are
	// in front of Poly, and (B) polygons that are in back of Poly.
	// Coplanar polys are inserted immediately, before recursing.

	// If any polygons are split by Poly, we ignrore the original poly,
	// split it into two polys, and add two new polys to the pool.
	FPoly *FrontEdPoly = new FPoly;
	FPoly *BackEdPoly  = new FPoly;
	// Keep track of allocations.
	AllocatedFPolys.Add( FrontEdPoly );
	AllocatedFPolys.Add( BackEdPoly );

	for( int32 i=0; i<NumPolys; i++ )
	{
		FPoly *EdPoly = PolyList[i];
		if( EdPoly == SplitPoly )
		{
			continue;
		}

		switch( EdPoly->SplitWithPlane( SplitPoly->Vertices[0], SplitPoly->Normal, FrontEdPoly, BackEdPoly, 0 ) )
		{
			case SP_Coplanar:
	            if( RebuildSimplePolys )
				{
					EdPoly->iLink = Model->Surfs.Num()-1;
				}
				iPlaneNode = bspAddNode( Model, iPlaneNode, NODE_Plane, 0, EdPoly );
				break;
			
			case SP_Front:
	            FrontList[NumFront++] = PolyList[i];
				break;
			
			case SP_Back:
	            BackList[NumBack++] = PolyList[i];
				break;
			
			case SP_Split:

				// Create front & back nodes.
				FrontList[NumFront++] = FrontEdPoly;
				BackList [NumBack ++] = BackEdPoly;

				FrontEdPoly = new FPoly;
				BackEdPoly  = new FPoly;
				// Keep track of allocations.
				AllocatedFPolys.Add( FrontEdPoly );
				AllocatedFPolys.Add( BackEdPoly );

				break;
		}
	}

	// Recursively split the front and back pools.
	if( NumFront > 0 ) SplitPolyList( Model, iOurNode, NODE_Front, NumFront, FrontList, Opt, Balance, PortalBias, RebuildSimplePolys );
	if( NumBack  > 0 ) SplitPolyList( Model, iOurNode, NODE_Back,  NumBack,  BackList,  Opt, Balance, PortalBias, RebuildSimplePolys );

	// Delete FPolys allocated above. We cannot use FMemStack::Get() for FPoly as the array data FPoly contains will be allocated in regular memory.
	for( int32 i=0; i<AllocatedFPolys.Num(); i++ )
	{
		FPoly* AllocatedFPoly = AllocatedFPolys[i];
		delete AllocatedFPoly;
	}

	Mark.Pop();
}