//public const int numOfSpareInstances2Add = 100 ; /// <summary> /// Node Constructor. /// </summary> static public void _CreateNewNode(ref RootNodeData rootNode, int i_nodeIndex, float f_baseLength, float3 f3_center, ref DynamicBuffer <NodeBufferElement> a_nodesBuffer, ref DynamicBuffer <NodeSparesBufferElement> a_nodeSparesBuffer, ref DynamicBuffer <NodeChildrenBufferElement> a_nodeChildrenBuffer, ref DynamicBuffer <NodeInstancesIndexBufferElement> a_nodeInstancesIndexBuffer) { // Expand storage if needed if (rootNode.i_nodeSpareLastIndex <= 9) { int i_baseAddNodeCount = 100; int i_initialSparesCount = a_nodeSparesBuffer.Length + i_baseAddNodeCount - 1; NodeSparesBufferElement nodeSpareBuffer = new NodeSparesBufferElement(); NodeBufferElement nodeBuffer = new NodeBufferElement(); // Populate with default data. for (int i = 0; i < i_baseAddNodeCount; i++) { // Add spares in reversed order, from higher index, to lower index. nodeSpareBuffer.i = -1; a_nodeSparesBuffer.Add(nodeSpareBuffer); rootNode.i_nodeSpareLastIndex++; nodeSpareBuffer.i = i_initialSparesCount - i; a_nodeSparesBuffer [rootNode.i_nodeSpareLastIndex] = nodeSpareBuffer; nodeBuffer.f_baseLength = -1; nodeBuffer.f_adjLength = -1; nodeBuffer.f3_center = float3.zero; nodeBuffer.bounds = new Bounds(); a_nodesBuffer.Add(nodeBuffer); nodeBuffer.i_childrenCount = 0; nodeBuffer.i_instancesCount = 0; for (int j = 0; j < rootNode.i_instancesAllowedCount; j++) { a_nodeInstancesIndexBuffer.Add(new NodeInstancesIndexBufferElement() { i = -1 }); } NodeChildrenBufferElement nodeChildrenBuffer = new NodeChildrenBufferElement(); // Generate 8 new empty children. for (int j = 0; j < 8; j++) { nodeChildrenBuffer.i_group8NodesIndex = -1; nodeChildrenBuffer.bounds = new Bounds(); a_nodeChildrenBuffer.Add(new NodeChildrenBufferElement()); } } } _SetValues(rootNode, i_nodeIndex, f_baseLength, f3_center, ref a_nodesBuffer, ref a_nodeChildrenBuffer); }
/// <summary> /// Splits the octree into eight children. /// </summary> /// <param name="i_nodeIndex">Internal octree node index.</param> static private void _Split(ref RootNodeData rootNode, int i_nodeIndex, ref DynamicBuffer <NodeBufferElement> a_nodesBuffer, ref DynamicBuffer <NodeSparesBufferElement> a_nodeSparesBuffer, ref DynamicBuffer <NodeChildrenBufferElement> a_nodeChildrenBuffer, ref DynamicBuffer <NodeInstancesIndexBufferElement> a_nodeInstancesIndexBuffer) { NodeBufferElement nodeBuffer = a_nodesBuffer [i_nodeIndex]; float f_nodeBaseLength = nodeBuffer.f_baseLength; float f_quarter = f_nodeBaseLength / 4f; float f_newBaseLength = f_nodeBaseLength / 2; float3 f3_center = nodeBuffer.f3_center; nodeBuffer.i_childrenCount = 8; a_nodesBuffer [i_nodeIndex] = nodeBuffer; int i_childrenIndexOffset = i_nodeIndex * 8; // Create for this node, 8 new children nodes NodeChildrenBufferElement nodeChildrenBuffer; // Allocate spare nodes, to children nodes. // Is assumed, there is enough spare nodes for (int i = 0; i < 8; i++) { NodeSparesBufferElement nodeSparesBuffer = a_nodeSparesBuffer [rootNode.i_nodeSpareLastIndex]; nodeChildrenBuffer = a_nodeChildrenBuffer [i_childrenIndexOffset + i]; nodeChildrenBuffer.i_group8NodesIndex = nodeSparesBuffer.i; a_nodeChildrenBuffer [i_childrenIndexOffset + i] = nodeChildrenBuffer; // Set back rootNode.i_nodeSpareLastIndex--; } float3 f3_childCenterQuater; nodeChildrenBuffer = a_nodeChildrenBuffer [i_childrenIndexOffset]; f3_childCenterQuater = f3_center + new float3(-f_quarter, f_quarter, -f_quarter); CommonMethods._CreateNewNode(ref rootNode, nodeChildrenBuffer.i_group8NodesIndex, f_newBaseLength, f3_childCenterQuater, ref a_nodesBuffer, ref a_nodeSparesBuffer, ref a_nodeChildrenBuffer, ref a_nodeInstancesIndexBuffer); nodeChildrenBuffer = a_nodeChildrenBuffer [i_childrenIndexOffset + 1]; f3_childCenterQuater = f3_center + new float3(f_quarter, f_quarter, -f_quarter); CommonMethods._CreateNewNode(ref rootNode, nodeChildrenBuffer.i_group8NodesIndex, f_newBaseLength, f3_childCenterQuater, ref a_nodesBuffer, ref a_nodeSparesBuffer, ref a_nodeChildrenBuffer, ref a_nodeInstancesIndexBuffer); nodeChildrenBuffer = a_nodeChildrenBuffer [i_childrenIndexOffset + 2]; f3_childCenterQuater = f3_center + new float3(-f_quarter, f_quarter, f_quarter); CommonMethods._CreateNewNode(ref rootNode, nodeChildrenBuffer.i_group8NodesIndex, f_newBaseLength, f3_childCenterQuater, ref a_nodesBuffer, ref a_nodeSparesBuffer, ref a_nodeChildrenBuffer, ref a_nodeInstancesIndexBuffer); nodeChildrenBuffer = a_nodeChildrenBuffer [i_childrenIndexOffset + 3]; f3_childCenterQuater = f3_center + new float3(f_quarter, f_quarter, f_quarter); CommonMethods._CreateNewNode(ref rootNode, nodeChildrenBuffer.i_group8NodesIndex, f_newBaseLength, f3_childCenterQuater, ref a_nodesBuffer, ref a_nodeSparesBuffer, ref a_nodeChildrenBuffer, ref a_nodeInstancesIndexBuffer); nodeChildrenBuffer = a_nodeChildrenBuffer [i_childrenIndexOffset + 4]; f3_childCenterQuater = f3_center + new float3(-f_quarter, -f_quarter, -f_quarter); CommonMethods._CreateNewNode(ref rootNode, nodeChildrenBuffer.i_group8NodesIndex, f_newBaseLength, f3_childCenterQuater, ref a_nodesBuffer, ref a_nodeSparesBuffer, ref a_nodeChildrenBuffer, ref a_nodeInstancesIndexBuffer); nodeChildrenBuffer = a_nodeChildrenBuffer [i_childrenIndexOffset + 5]; f3_childCenterQuater = f3_center + new float3(f_quarter, -f_quarter, -f_quarter); CommonMethods._CreateNewNode(ref rootNode, nodeChildrenBuffer.i_group8NodesIndex, f_newBaseLength, f3_childCenterQuater, ref a_nodesBuffer, ref a_nodeSparesBuffer, ref a_nodeChildrenBuffer, ref a_nodeInstancesIndexBuffer); nodeChildrenBuffer = a_nodeChildrenBuffer [i_childrenIndexOffset + 6]; f3_childCenterQuater = f3_center + new float3(-f_quarter, -f_quarter, f_quarter); CommonMethods._CreateNewNode(ref rootNode, nodeChildrenBuffer.i_group8NodesIndex, f_newBaseLength, f3_childCenterQuater, ref a_nodesBuffer, ref a_nodeSparesBuffer, ref a_nodeChildrenBuffer, ref a_nodeInstancesIndexBuffer); nodeChildrenBuffer = a_nodeChildrenBuffer [i_childrenIndexOffset + 7]; f3_childCenterQuater = f3_center + new float3(f_quarter, -f_quarter, f_quarter); CommonMethods._CreateNewNode(ref rootNode, nodeChildrenBuffer.i_group8NodesIndex, f_newBaseLength, f3_childCenterQuater, ref a_nodesBuffer, ref a_nodeSparesBuffer, ref a_nodeChildrenBuffer, ref a_nodeInstancesIndexBuffer); }
/// <summary> /// Grow the octree to fit in all objects. /// </summary> /// <param name="f3_direction">Direction to grow.</param> static private void _GrowOctree(ref RootNodeData rootNode, float3 f3_direction, ref DynamicBuffer <NodeBufferElement> a_nodesBuffer, ref DynamicBuffer <NodeSparesBufferElement> a_nodeSparesBuffer, ref DynamicBuffer <NodeChildrenBufferElement> a_nodeChildrenBuffer, ref DynamicBuffer <NodeInstancesIndexBufferElement> a_nodeInstancesIndexBuffer, ref DynamicBuffer <InstanceBufferElement> a_instanceBuffer, ref DynamicBuffer <InstancesSpareIndexBufferElement> a_instancesSpareIndexBuffer) { int xDirection = f3_direction.x >= 0 ? 1 : -1; int yDirection = f3_direction.y >= 0 ? 1 : -1; int zDirection = f3_direction.z >= 0 ? 1 : -1; int i_oldRootNodeIndex = rootNode.i_rootNodeIndex; NodeBufferElement nodeBufferElement = a_nodesBuffer [i_oldRootNodeIndex]; float f_baseLength = nodeBufferElement.f_baseLength; float f_half = f_baseLength / 2; float f_newBaseLength = f_baseLength * 2; float3 f3_newCenter = nodeBufferElement.f3_center + new float3(xDirection * f_half, yDirection * f_half, zDirection * f_half); // Debug.LogWarning ( "Grow: " + f3_newCenter + "; new base length: " + f_newBaseLength + "; halve: " + f_half + "; pos: " + f3_newCenter ) ; // Create a new, bigger octree root node if (!CommonMethods._HasAnyInstances(i_oldRootNodeIndex, a_nodesBuffer, a_nodeChildrenBuffer)) { CommonMethods._CreateNewNode( ref rootNode, rootNode.i_rootNodeIndex, f_newBaseLength, f3_newCenter, ref a_nodesBuffer, ref a_nodeSparesBuffer, ref a_nodeChildrenBuffer, ref a_nodeInstancesIndexBuffer ); } else { NodeSparesBufferElement nodeSparesBuffer = a_nodeSparesBuffer [rootNode.i_nodeSpareLastIndex]; rootNode.i_rootNodeIndex = nodeSparesBuffer.i; rootNode.i_nodeSpareLastIndex--; CommonMethods._CreateNewNode( ref rootNode, rootNode.i_rootNodeIndex, f_newBaseLength, f3_newCenter, ref a_nodesBuffer, ref a_nodeSparesBuffer, ref a_nodeChildrenBuffer, ref a_nodeInstancesIndexBuffer ); // Create 7 new octree children to go with the old root as children of the new root int i_rootPos = _GetRootPosIndex(xDirection, yDirection, zDirection); NodeBufferElement nodeBuffer = a_nodesBuffer [rootNode.i_rootNodeIndex]; nodeBuffer.i_childrenCount = 8; a_nodesBuffer [rootNode.i_rootNodeIndex] = nodeBuffer; // Set back. int i_newRootNodeChildrenIndexOffset = rootNode.i_rootNodeIndex * 8; for (int i = 0; i < 8; i++) { int i_childIndexOffset = i_newRootNodeChildrenIndexOffset + i; NodeChildrenBufferElement nodeChildrenBuffer = a_nodeChildrenBuffer [i_childIndexOffset]; if (i == i_rootPos) { // Assign old root node as a child. nodeChildrenBuffer.i_group8NodesIndex = i_oldRootNodeIndex; InstanceBufferElement instanceBuffer = a_instanceBuffer [i_oldRootNodeIndex]; nodeChildrenBuffer.bounds = instanceBuffer.bounds; } else { // Assign rest 7 children xDirection = i % 2 == 0 ? -1 : 1; yDirection = i > 3 ? -1 : 1; zDirection = (i < 2 || (i > 3 && i < 6)) ? -1 : 1; nodeSparesBuffer = a_nodeSparesBuffer [rootNode.i_nodeSpareLastIndex]; int i_newNodeIndex = nodeSparesBuffer.i; // Expected output 0 at initialization rootNode.i_nodeSpareLastIndex--; float3 f3_childVector = f3_newCenter + new float3(xDirection * f_half, yDirection * f_half, zDirection * f_half); CommonMethods._CreateNewNode( ref rootNode, i_newNodeIndex, f_newBaseLength, f3_childVector, ref a_nodesBuffer, ref a_nodeSparesBuffer, ref a_nodeChildrenBuffer, ref a_nodeInstancesIndexBuffer ); nodeChildrenBuffer.i_group8NodesIndex = i_newNodeIndex; Bounds bounds = new Bounds( ) { center = f3_childVector, size = Vector3.one * f_newBaseLength }; nodeChildrenBuffer.bounds = bounds; } a_nodeChildrenBuffer [i_childIndexOffset] = nodeChildrenBuffer; // Set back. } // for } }