hism的clusterBuilder
2023-01-12 22:09 kk20161206 阅读(70) 评论(0) 编辑 收藏 举报clusterBuilder的构造函数
FClusterBuilder(TArray<FMatrix> InTransforms, TArray<float> InCustomDataFloats, int32 InNumCustomDataFloats, const FBox& InInstBox, int32 InMaxInstancesPerLeaf, float InDensityScaling, int32 InInstancingRandomSeed, bool InGenerateInstanceScalingRange) : OriginalNum(InTransforms.Num()) , InstBox(InInstBox) , MaxInstancesPerLeaf(InMaxInstancesPerLeaf) , InstancingRandomSeed(InInstancingRandomSeed) , DensityScaling(InDensityScaling) , GenerateInstanceScalingRange(InGenerateInstanceScalingRange) , Transforms(MoveTemp(InTransforms)) , CustomDataFloats(MoveTemp(InCustomDataFloats)) , NumCustomDataFloats(InNumCustomDataFloats) , Result(nullptr) { }
调用是被
void UHierarchicalInstancedStaticMeshComponent::BuildTree()所调用。
FClusterBuilder Builder(InstanceTransforms, PerInstanceSMCustomData, NumCustomDataFloats, GetStaticMesh()->GetBounds().GetBox(), DesiredInstancesPerLeaf(), CurrentDensityScaling, InstancingRandomSeed, PerInstanceSMData.Num() > 0);
Builder.BuildTreeAndBuffer();
ApplyBuildTree(Builder);
BuildTree函数 里面调用了
Init函数
sortIndex是transform数据的数量*密度scale;
sortPoints数量是transform的数量。
sortPoints放transform的origin
sortIndex放符合条件的index。满足随机的,密度scale符合条件。
num是有效数据的数量,乘了密度。
occlusionLayerTarget:每个组件最大遮挡查询
minInstancesPerOcclusionQuery: 每个遮挡查询最小的实例数
if 总数量/每个查询最小实例数(最多的遮挡查询数) < occlusionLayerTarget
则occlusionLayerTarget = 总数量 / 每个查询最小实例数
如果occlusionLayerTarget < minOcclusionQueriesPerComponent
occlusionLayerTarget = 0;
树枝数 internalNodeBranchingFactor = CVarFoliageSplitFactor
if 总数量 / 每个叶子最大实例数 (树枝最小数) < internalNodeBranchingFactor
则每个叶子最大实例数=总数量/树枝因子 internalNodeBranchingFactor
继续看buildTree函数
result是FClusterTree类型
result的instanceReorderTable初始化为总共transform数,>= 实际的(乘了密度)。
如果树枝数 > 2, 遮挡层 >0, 总数量/树枝数 <= 遮挡查询数
则branchingFactor数 大概等于 每个查询最小实例数。
split(Num) //有效的数量
这里我们看看split函数
里面调用了Split(0, num - 1);
是个递归函数
包围盒通过index转换为排序后的index,的originPosition 扩充的。
如果数量 < 遮挡查询数
则clusters里直接加入这个RunPair
否则,拿到最大的轴
这个轴的坐标排序
最终的sortIndex[index]的值是原来的没有排序的索引,sortIndex[index](sortIndex是transform数据的数量*密度scale;)。
递归遍历左半部分和右半部分。
如果当前是遮挡层,则result的outOcclusionLayerNum是clusters的数量
sortedInstances数组填入sortIndex数组
numRoots是clusters数
Result的nodes初始化为clusters的数目
每个是个FClusterNode,它的firstInstance是clusters的start,它的lastInstance是clusters的start+num-1;
对于从fistInstance到lastInstance,通过这个instanceIndex
拿到sortedInstances[instanceIndex],即最开始没有排序的index
transforms这个原来的index,拿到这个矩阵
拿到这个包围盒。
nodesPerLevel数组加入这个numroots
while(numRoot>1)
{
对于每个簇sortIndex是原来簇的index,sortPoint是坐标
如果树枝数目>2 遮挡层 簇数/树枝数 <= 遮挡层目标
树枝数目 = max(2, 簇数目/遮挡层目标) 每个簇看成一个结点,除以遮挡目标数=簇又分为几个父。
Split(numroots);
里面是split(start, end)
< 树枝数目,则直接形成一个FRunPair放到clusters里面
找到这个轴,排序
//得到倒数第二层的簇,它的RunPair放的是倒数第一层的(叶子层)的index;
RemapSortIndex初始化为num(实际数量个)
最终的sortIndex[index]的值是原来的没有排序的索引,
RemapSortIndex[index]对应排序前的instanceIndex
for (int32 Index = 0; Index < Num; Index++)
{
InverseInstanceIndex[RemapSortIndex[Index]] = Index;
}
//排序前的instanceIndex到有序的index的映射:inverseInstanceIndex数组
这一层的每个簇节点的fistInstance,lastinstance都弄成有序的index
for (int32 Index = 0; Index < Result->Nodes.Num(); Index++)
{
FClusterNode& Node = Result->Nodes[Index];
Node.FirstInstance = InverseInstanceIndex[Node.FirstInstance];
Node.LastInstance = InverseInstanceIndex[Node.LastInstance];
}
RemapSortIndex[index]对应排序前的instanceIndex,再sortedInstance拿到最初的transform的那个原始的index。
{
result->nodes是叶子节点的个数,cluster.num是这一层的簇的节点
新的节点数为二者之和
nodesPerLevel已经加入了一个元素:叶子节点的数
levelstarts放入当前层的簇数
对每个叶子节点
levelStarts放入上一层节点数(叶子节点数)+当前层的簇数
对于每个叶子
RemapSortIndex的索引是加上了上一层的index数量
加上孩子的索引
// InverseChildIndex[old index] == new index
InverseChildIndex.AddUninitialized(NewNum);
for (int32 Index = Clusters.Num(); Index < NewNum; Index++)
{
InverseChildIndex[RemapSortIndex[Index]] = Index;
}
for (int32 Index = 0; Index < Result->Nodes.Num(); Index++)
{
FClusterNode& Node = Result->Nodes[Index];
if (Node.FirstChild >= 0)
{
Node.FirstChild = InverseChildIndex[Node.FirstChild];
Node.LastChild = InverseChildIndex[Node.LastChild];
}
}
// Save inverse map
Result->InstanceReorderTable.Init(INDEX_NONE, OriginalNum);
for (int32 Index = 0; Index < Num; Index++)
{
Result->InstanceReorderTable[SortedInstances[Index]] = Index;
}
//
sortedInstance拿到最初的transform的那个原始的index。
InstanceReorderTable是反过来,输入原始,输出新的。
}
}