Ejemplo n.º 1
0
        /// <summary>
        /// Node Constructor.
        /// </summary>
        static public void _CreateNewNode(ref RootNodeData rootNodeData, 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 (rootNodeData.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);
                    rootNodeData.i_nodeSpareLastIndex++;
                    nodeSpareBuffer.i = i_initialSparesCount - i;
                    a_nodeSparesBuffer [rootNodeData.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 < rootNodeData.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_nodesIndex = -1;
                        nodeChildrenBuffer.bounds       = new Bounds();
                        a_nodeChildrenBuffer.Add(new NodeChildrenBufferElement());
                    }
                }
            }


            _SetValues(rootNodeData, 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 rootNodeData, 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 [rootNodeData.i_nodeSpareLastIndex];
                nodeChildrenBuffer = a_nodeChildrenBuffer [i_childrenIndexOffset + i];
                nodeChildrenBuffer.i_nodesIndex = nodeSparesBuffer.i;
                a_nodeChildrenBuffer [i_childrenIndexOffset + i] = nodeChildrenBuffer;         // Set back
                rootNodeData.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 rootNodeData, nodeChildrenBuffer.i_nodesIndex, 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 rootNodeData, nodeChildrenBuffer.i_nodesIndex, 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 rootNodeData, nodeChildrenBuffer.i_nodesIndex, 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 rootNodeData, nodeChildrenBuffer.i_nodesIndex, 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 rootNodeData, nodeChildrenBuffer.i_nodesIndex, 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 rootNodeData, nodeChildrenBuffer.i_nodesIndex, 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 rootNodeData, nodeChildrenBuffer.i_nodesIndex, 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 rootNodeData, nodeChildrenBuffer.i_nodesIndex, 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 rootNodeData, 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 = rootNodeData.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);

            // Create a new, bigger octree root node

            if (!CommonMethods._HasAnyInstances(i_oldRootNodeIndex, a_nodesBuffer, a_nodeChildrenBuffer))
            {
                CommonMethods._CreateNewNode(
                    ref rootNodeData,
                    rootNodeData.i_rootNodeIndex,
                    f_newBaseLength,
                    f3_newCenter,
                    ref a_nodesBuffer,
                    ref a_nodeSparesBuffer,
                    ref a_nodeChildrenBuffer,
                    ref a_nodeInstancesIndexBuffer
                    );
            }
            else
            {
                NodeSparesBufferElement nodeSparesBuffer = a_nodeSparesBuffer [rootNodeData.i_nodeSpareLastIndex];
                rootNodeData.i_rootNodeIndex = nodeSparesBuffer.i;

                rootNodeData.i_nodeSpareLastIndex--;

                CommonMethods._CreateNewNode(
                    ref rootNodeData,
                    rootNodeData.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 [rootNodeData.i_rootNodeIndex];
                nodeBuffer.i_childrenCount = 8;
                a_nodesBuffer [rootNodeData.i_rootNodeIndex] = nodeBuffer;  // Set back.

                int i_newRootNodeChildrenIndexOffset = rootNodeData.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_nodesIndex = 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;

                        InstancesSpareIndexBufferElement instancesSpareIndexBuffer;
                        instancesSpareIndexBuffer = a_instancesSpareIndexBuffer [rootNodeData.i_nodeSpareLastIndex];
                        int i_newNodeIndex = instancesSpareIndexBuffer.i;                       // Expected output 0 at initialization
                        rootNodeData.i_nodeSpareLastIndex--;

                        float3 f3_childVector = f3_newCenter + new float3(xDirection * f_half, yDirection * f_half, zDirection * f_half);

                        CommonMethods._CreateNewNode(
                            ref rootNodeData,
                            i_newNodeIndex,
                            f_newBaseLength,
                            f3_childVector,
                            ref a_nodesBuffer,
                            ref a_nodeSparesBuffer,
                            ref a_nodeChildrenBuffer,
                            ref a_nodeInstancesIndexBuffer
                            );


                        nodeChildrenBuffer.i_nodesIndex = 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
            }
        }