/// <summary> /// Allows future reuse of spare instance, by putting it into the end of spares store. /// </summary> /// <param name="i_instanceIndex">Instance index, to pu back into spares of instances.</param> /// <param name="i_nodeIntstanceIndex">Node instance index holder, to be reset.</param> static public void _PutBackSpareInstance(ref RootNodeData rootNodeData, int i_instanceIndex, int i_nodeIntstanceIndex, ref DynamicBuffer <NodeInstancesIndexBufferElement> a_nodeInstancesIndexBuffer, ref DynamicBuffer <InstancesSpareIndexBufferElement> a_instancesSpareIndexBuffer) { if (i_instanceIndex < 0) { return; // This instance index has not been used. } rootNodeData.i_instancesSpareLastIndex++; // Put back to spare InstancesSpareIndexBufferElement instancesSpareIndexBuffer = new InstancesSpareIndexBufferElement(); instancesSpareIndexBuffer.i = i_instanceIndex; a_instancesSpareIndexBuffer [rootNodeData.i_instancesSpareLastIndex] = instancesSpareIndexBuffer; // Is assumed, that size of spares store, is appropriate. NodeInstancesIndexBufferElement nodeInstancesIndexBuffer = new NodeInstancesIndexBufferElement(); nodeInstancesIndexBuffer.i = -1; // Reset instance index. a_nodeInstancesIndexBuffer [i_nodeIntstanceIndex] = nodeInstancesIndexBuffer; }
/// <summary> /// Assign instance to node. /// </summary> /// <param name="i_nodeIndex">Internal octree node index.</param> /// <param name="i_instanceID">External instance index, ot unique entity index.</param> /// <param name="i_entityVersion">Optional, used when Id is used as entity index.</param> /// // Optional, used when Id is used as entity index /// <param name="instanceBounds">Boundary of external instance index.</param> static private void _AssingInstance2Node(RootNodeData rootNodeData, int i_nodeIndex, int i_instanceID, int i_entityVersion, Bounds instanceBounds, ref DynamicBuffer <NodeBufferElement> a_nodesBuffer, ref DynamicBuffer <InstanceBufferElement> a_instanceBuffer, ref DynamicBuffer <NodeInstancesIndexBufferElement> a_nodeInstancesIndexBuffer, DynamicBuffer <InstancesSpareIndexBufferElement> a_instancesSpareIndexBuffer) { int i_nodeInstanceIndexOffset = i_nodeIndex * rootNodeData.i_instancesAllowedCount; // Reuse spare store InstancesSpareIndexBufferElement instancesSpareIndexBuffer = a_instancesSpareIndexBuffer [rootNodeData.i_instancesSpareLastIndex]; NodeInstancesIndexBufferElement nodeInstancesIndexBuffer; // Find next spare instance allocation for this node. for (int i = 0; i < rootNodeData.i_instancesAllowedCount; i++) { int i_instanceIndexOffset = i_nodeInstanceIndexOffset + i; nodeInstancesIndexBuffer = a_nodeInstancesIndexBuffer [i_instanceIndexOffset]; // Is spare. if (nodeInstancesIndexBuffer.i == -1) { // Assign instance index. nodeInstancesIndexBuffer.i = instancesSpareIndexBuffer.i; a_nodeInstancesIndexBuffer [i_instanceIndexOffset] = nodeInstancesIndexBuffer; // Set back. break; } } NodeBufferElement nodeBuffer = a_nodesBuffer [i_nodeIndex]; nodeBuffer.i_instancesCount++; a_nodesBuffer [i_nodeIndex] = nodeBuffer; // Set back. InstanceBufferElement instanceBuffer = new InstanceBufferElement() { i_ID = i_instanceID, i_entityVersion = i_entityVersion, // Optional, used when Id is used as entity index. bounds = instanceBounds }; a_instanceBuffer [instancesSpareIndexBuffer.i] = instanceBuffer; }
/// <summary> /// Add required new spare instances. /// </summary> static public void _AddInstanceSpares(ref RootNodeData rootNodeData, ref DynamicBuffer <InstanceBufferElement> a_instanceBuffer, ref DynamicBuffer <InstancesSpareIndexBufferElement> a_instancesSpareIndexBuffer, int i_requiredNumberOfInstances) { rootNodeData.i_instancesSpareLastIndex--; int i_initialSparesCount = a_instanceBuffer.Length; int i_spareInstances2AddCount = i_requiredNumberOfInstances - i_initialSparesCount; InstancesSpareIndexBufferElement instancesSpareIndexBuffer = new InstancesSpareIndexBufferElement(); instancesSpareIndexBuffer.i = -1; InstanceBufferElement instanceBuffer = new InstanceBufferElement(); instanceBuffer.bounds = new Bounds(); instanceBuffer.i_ID = -1; instanceBuffer.i_entityVersion = -1; // Optional, used when Id is used as entity index // Add new spares, from the end of storage. for (int i = 0; i < i_spareInstances2AddCount; i++) { // Need to expand spare store. a_instancesSpareIndexBuffer.Add(instancesSpareIndexBuffer); a_instanceBuffer.Add(instanceBuffer); } // Populate indexes references, with new spares. for (int i = 0; i < i_spareInstances2AddCount; i++) { rootNodeData.i_instancesSpareLastIndex++; // Add new spares. // Add spares in reversed order, from higher index, to lower index. instancesSpareIndexBuffer.i = i_initialSparesCount + i_spareInstances2AddCount - i - 1; a_instancesSpareIndexBuffer [rootNodeData.i_instancesSpareLastIndex] = instancesSpareIndexBuffer; } }
/// <summary> /// Assign instance to node. /// </summary> /// <param name="i_nodeIndex">Internal octree node index.</param> /// <param name="i_instanceID">External instance index, ot unique entity index.</param> /// <param name="i_entityVersion">Optional, used when Id is used as entity index.</param> /// // Optional, used when Id is used as entity index /// <param name="instanceBounds">Boundary of external instance index.</param> static private bool _AssingInstance2Node(ref RootNodeData rootNodeData, int i_nodeIndex, int i_instanceID, int i_entityVersion, Bounds instanceBounds, ref DynamicBuffer <NodeBufferElement> a_nodesBuffer, ref DynamicBuffer <NodeSparesBufferElement> a_nodeSparesBuffer, ref DynamicBuffer <NodeChildrenBufferElement> a_nodeChildrenBuffer, ref DynamicBuffer <InstanceBufferElement> a_instanceBuffer, ref DynamicBuffer <NodeInstancesIndexBufferElement> a_nodeInstancesIndexBuffer, ref DynamicBuffer <InstancesSpareIndexBufferElement> a_instancesSpareIndexBuffer) { int i_nodeInstanceIndexOffset = i_nodeIndex * rootNodeData.i_instancesAllowedCount; // Reuse spare store InstancesSpareIndexBufferElement instancesSpareIndexBuffer = a_instancesSpareIndexBuffer [rootNodeData.i_instancesSpareLastIndex]; NodeInstancesIndexBufferElement nodeInstancesIndexBuffer; bool isInstanceAdded = false; // Find next spare instance allocation for this node. // Find next spare instance allocation for this node. for (int i = 0; i < rootNodeData.i_instancesAllowedCount; i++) { int i_instanceIndexOffset = i_nodeInstanceIndexOffset + i; nodeInstancesIndexBuffer = a_nodeInstancesIndexBuffer [i_instanceIndexOffset]; // Is spare. if (nodeInstancesIndexBuffer.i == -1) { // Assign instance index. nodeInstancesIndexBuffer.i = instancesSpareIndexBuffer.i; a_nodeInstancesIndexBuffer [i_instanceIndexOffset] = nodeInstancesIndexBuffer; // Set back. isInstanceAdded = true; break; } } // for if (!isInstanceAdded) { // Node has 8 children and an more instances, than capacity. // Try to move instance to child, with instance space. // if ( i_instancesCount < rootNodeData.i_instancesAllowedCount && i_childrenCount > 0 ) // Iterate though node's children for (int i_childIndex = 0; i_childIndex < 8; i_childIndex++) { int i_childIndexOffset = i_nodeIndex * 8 + i_childIndex; NodeChildrenBufferElement nodeChildrenBuffer = a_nodeChildrenBuffer [i_childIndexOffset]; // Check if instance bounds fit in child if (CommonMethods._Encapsulates(nodeChildrenBuffer.bounds, instanceBounds)) { //NodeBufferElement childNode = a_nodesBuffer [nodeChildrenBuffer.i_nodesIndex] ; // Debug.LogWarning ( "ChNode: " + childNode.i_instancesCount + "; " + childNode.bounds ) ; int i_requiredNumberOfInstances = a_nodeInstancesIndexBuffer.Length; // l_nodeBounds.Count ; isInstanceAdded = _NodeInstanceSubAdd( ref rootNodeData, nodeChildrenBuffer.i_nodesIndex, i_instanceID, i_entityVersion, instanceBounds, ref a_nodesBuffer, ref a_nodeSparesBuffer, ref a_nodeChildrenBuffer, ref a_nodeInstancesIndexBuffer, ref a_instanceBuffer, ref a_instancesSpareIndexBuffer, i_requiredNumberOfInstances ); if (isInstanceAdded) { return(true); // Added instance } } } // Debug.LogError ( "Found no child node, to fit instance. Try grow octree." ) ; NodeBufferElement nodeBufferElement = a_nodesBuffer [rootNodeData.i_rootNodeIndex]; // Try add node at the root // Debug.LogError ( "Grow again." ) ; _GrowOctree(ref rootNodeData, (float3)instanceBounds.center - nodeBufferElement.f3_center, ref a_nodesBuffer, ref a_nodeSparesBuffer, ref a_nodeChildrenBuffer, ref a_nodeInstancesIndexBuffer, ref a_instanceBuffer, ref a_instancesSpareIndexBuffer ); _AddNodeInstance(ref rootNodeData, i_instanceID, i_entityVersion, instanceBounds, ref a_nodesBuffer, ref a_nodeSparesBuffer, ref a_nodeChildrenBuffer, ref a_nodeInstancesIndexBuffer, ref a_instanceBuffer, ref a_instancesSpareIndexBuffer, out isInstanceAdded ); // Debug.LogWarning ( "Is instant added? " + (isInstanceAdded? "y" : "n") ) ; return(isInstanceAdded); } // if NodeBufferElement nodeBuffer = a_nodesBuffer [i_nodeIndex]; nodeBuffer.i_instancesCount++; a_nodesBuffer [i_nodeIndex] = nodeBuffer; // Set back. InstanceBufferElement instanceBuffer = new InstanceBufferElement() { i_ID = i_instanceID, i_entityVersion = i_entityVersion, // Optional, used when Id is used as entity index. bounds = instanceBounds }; a_instanceBuffer [instancesSpareIndexBuffer.i] = instanceBuffer; return(true); }