/// <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 rootNode, 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. } rootNode.i_instancesSpareLastIndex++; // Put back to spare // Is assumed, that size of spares store, is appropriate. InstancesSpareIndexBufferElement instancesSpareIndexBuffer = new InstancesSpareIndexBufferElement(); instancesSpareIndexBuffer.i = i_instanceIndex; a_instancesSpareIndexBuffer [rootNode.i_instancesSpareLastIndex] = instancesSpareIndexBuffer; NodeInstancesIndexBufferElement nodeInstancesIndexBuffer = new NodeInstancesIndexBufferElement(); nodeInstancesIndexBuffer.i = -1; // Reset instance index. a_nodeInstancesIndexBuffer [i_nodeIntstanceIndex] = nodeInstancesIndexBuffer; }
/// <summary> /// Add required new spare instances. /// </summary> static public void _AddInstanceSpares(ref RootNodeData rootNode, ref DynamicBuffer <InstanceBufferElement> a_instanceBuffer, ref DynamicBuffer <InstancesSpareIndexBufferElement> a_instancesSpareIndexBuffer, int i_requiredNumberOfInstances) { rootNode.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++) { rootNode.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 [rootNode.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 rootNode, 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 * rootNode.i_instancesAllowedCount; // Debug.Log ( "Assign instance 2 Node; node offset " + i_nodeInstanceIndexOffset + " Instance ID: " + i_instanceID ) ; // Reuse spare store InstancesSpareIndexBufferElement instancesSpareIndexBuffer = a_instancesSpareIndexBuffer [rootNode.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 < rootNode.i_instancesAllowedCount; i++) { int i_instanceIndexOffset = i_nodeInstanceIndexOffset + i; nodeInstancesIndexBuffer = a_nodeInstancesIndexBuffer [i_instanceIndexOffset]; NodeChildrenBufferElement nodeChildrenBuffer = a_nodeChildrenBuffer [i_nodeIndex]; // Only test. Remove. // Debug.Log ( "#" + i + " offset: " + i_instanceIndexOffset + " node index -1? " + nodeInstancesIndexBuffer.i + " <= " + instancesSpareIndexBuffer.i + "; bounds: " + nodeChildrenBuffer.bounds ) ; // Is spare. if (nodeInstancesIndexBuffer.i == -1) { // Assign instance index. nodeInstancesIndexBuffer.i = instancesSpareIndexBuffer.i; a_nodeInstancesIndexBuffer [i_instanceIndexOffset] = nodeInstancesIndexBuffer; // Set back. isInstanceAdded = true; break; } } // for // Debug.Log ( "Node index: " + i_nodeIndex + " Is instance ID " + i_instanceID + " added: " + isInstanceAdded ) ; 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]; // Debug.Log ( "Is instance child " + i_childIndex + " / " + 8 + "; " + i_instanceID + "; child buffer: " + nodeChildrenBuffer.bounds ) ; // Check if instance bounds fit in child if (CommonMethods._Encapsulates(nodeChildrenBuffer.bounds, instanceBounds)) { // Debug.Log ( "Encapsulates B instance ID: " + i_instanceID + "; bound: " + instanceBounds + " in node " + nodeChildrenBuffer.bounds ) ; //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 rootNode, nodeChildrenBuffer.i_group8NodesIndex, 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 } } } /* * NodeBufferElement rootNodeBufferElement = a_nodesBuffer [rootNode.i_rootNodeIndex] ; * * /Debug.LogError ( "Found no child node, to fit instance. Try grow octree; Instance ID " + i_instanceID + " bounds: " + instanceBounds + "; root node bounds: " + rootNodeBufferElement.bounds ) ; * * // Check if still fits in the root node. * if ( CommonMethods._Encapsulates ( rootNodeBufferElement.bounds, instanceBounds ) ) * { * Debug.Log ( "Still Fits in root." ) ; * } * else * { * * // Try add node at the root * * Debug.LogError ( "Grow again." ) ; * * _GrowOctree ( ref rootNode, * (float3) instanceBounds.center - rootNodeBufferElement.f3_center, * ref a_nodesBuffer, * ref a_nodeSparesBuffer, * ref a_nodeChildrenBuffer, * ref a_nodeInstancesIndexBuffer, * ref a_instanceBuffer, * ref a_instancesSpareIndexBuffer * ) ; * * * } */ // TODO: Requires double check. /* * _AddNodeInstance ( ref rootNode, * 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); }