//The purpose of availableNodeSyncs is because: This function is recursive. availableNodeSyncs tells it how deep to plumb /// <summary> /// A recursive function responsible for synchronizing Unity data with the CubiquityDLL data. /// </summary> /// <returns>The amount of synchronization steps left unexpended.</returns> /// <param name="availableNodeSyncs">a parameter to track how much synchronization can and will be done from recrusive layer to recursive layer.</param> public int SyncNode(int availableNodeSyncs) { //terminator of the all-powerful recursion if (availableNodeSyncs <= 0) { return(0); } //------------------------------------------- // PHASE ONE: Building Meshes! //------------------------------------------- //is a synchronization even called for? uint meshLastUpdated = CubiquityDLL.GetMeshLastUpdated(nodeHandle); //we don't have to synchronize this node if it wasn't updated. if (meshLastSyncronised < meshLastUpdated) { //I like major control branches that are concise to read! if (CubiquityDLL.NodeHasMesh(nodeHandle) == 1) { NodeMeshUp(); } else { NodeMeshDown(); } //absolutely do not decrement availableNodesyncs if no meshSyncing occured, or we'll never //explore the whole tree @.@ meshLastSyncronised = CubiquityDLL.GetCurrentTime(); availableNodeSyncs--; } //------------------------------------------- // PHASE TWO: RECURSE! //------------------------------------------- //we needs to know if any children were ever used in the making of this node. (that way we can children == null) at the end if necessary. bool usedChildren = false; //normally we would have to iterate across the two x children, the two y children, and the two z children using 3 nested //for-loops. Typically speaking, nesting for loops in a recursive function causes nausea, dry mouth, dizzinss and vomiting. //Let's flatten the array! for (uint x = 0, y = 0, z = 0, i = 0;; x++, i++) { //iteration code! if (x > 1) { y++; x = 0; } if (y > 1) { z++; y = 0; } if (z > 1) { break; } //At this point we know i is an element of [0,8) //And we know children exists. So we can directly getChild by using children[i]; //Steps: // 1) Ascertain whether we SHOULD have a unity node // 2) Ascertain whether we have a children array to store the unity node in. // 3) Ascertain whether we DO have a unity node // 4) See if the unity node is right, and then Synchronize it. //Test whether we have a child node and, if not, clean up leaves and bare branches if (CubiquityDLL.HasChildNode(nodeHandle, x, y, z) != 1) { //check to make sure we aren't about to dispose and a nonexistant child/array. //Use continue to check the next child if (children == null) { continue; } if (children[i] == null) { continue; } //Testing will need to be done, but TECHNICALLY this should destroy not only the octree node, but all octree nodes that come afterward (because it is //done on the game object, and the game object is the parent of the other octreenodes game objects) Destroy(children[i].gameObject); children[i] = null; continue; } //if we need a child Node and haven't even a child array, we need to init the array. else if (children == null) { children = new OctreeNodeAlt[8] { null, null, null, null, null, null, null, null }; } //nab the child Node Handle uint childNodeHandle = CubiquityDLL.GetChildNode(nodeHandle, x, y, z); //and create the Unity-side child, if necessary SetChild(i, childNodeHandle); //and synchronize the child if syncs are available. availableNodeSyncs = children[i].SyncNode(availableNodeSyncs); //if even one spot in the childArray is used, we set this to true usedChildren = true; } //delete children array to save space. if (usedChildren == false) { children = null; } //return any Syncs we have left! return(availableNodeSyncs); }
public int syncNode(int availableNodeSyncs, GameObject voxelTerrainGameObject) { int nodeSyncsPerformed = 0; if (availableNodeSyncs <= 0) { return(nodeSyncsPerformed); } uint meshLastUpdated = CubiquityDLL.GetMeshLastUpdated(nodeHandle); if (meshLastSyncronised < meshLastUpdated) { if (CubiquityDLL.NodeHasMesh(nodeHandle) == 1) { // Set up the rendering mesh VolumeRenderer volumeRenderer = voxelTerrainGameObject.GetComponent <VolumeRenderer>(); if (volumeRenderer != null) { //Mesh renderingMesh = volumeRenderer.BuildMeshFromNodeHandle(nodeHandle); Mesh renderingMesh = null; if (voxelTerrainGameObject.GetComponent <Volume>().GetType() == typeof(TerrainVolume)) { renderingMesh = BuildMeshFromNodeHandleForTerrainVolume(nodeHandle); } else if (voxelTerrainGameObject.GetComponent <Volume>().GetType() == typeof(ColoredCubesVolume)) { renderingMesh = BuildMeshFromNodeHandleForColoredCubesVolume(nodeHandle); } MeshFilter meshFilter = gameObject.GetOrAddComponent <MeshFilter>() as MeshFilter; MeshRenderer meshRenderer = gameObject.GetOrAddComponent <MeshRenderer>() as MeshRenderer; if (meshFilter.sharedMesh != null) { DestroyImmediate(meshFilter.sharedMesh); } meshFilter.sharedMesh = renderingMesh; meshRenderer.sharedMaterial = volumeRenderer.material; #if UNITY_EDITOR EditorUtility.SetSelectedWireframeHidden(meshRenderer, true); #endif } // Set up the collision mesh VolumeCollider volumeCollider = voxelTerrainGameObject.GetComponent <VolumeCollider>(); if ((volumeCollider != null) && (Application.isPlaying)) { Mesh collisionMesh = volumeCollider.BuildMeshFromNodeHandle(nodeHandle); MeshCollider meshCollider = gameObject.GetOrAddComponent <MeshCollider>() as MeshCollider; meshCollider.sharedMesh = collisionMesh; } } // If there is no mesh in Cubiquity then we make sure there isn't on in Unity. else { MeshCollider meshCollider = gameObject.GetComponent <MeshCollider>() as MeshCollider; if (meshCollider) { DestroyImmediate(meshCollider); } MeshRenderer meshRenderer = gameObject.GetComponent <MeshRenderer>() as MeshRenderer; if (meshRenderer) { DestroyImmediate(meshRenderer); } MeshFilter meshFilter = gameObject.GetComponent <MeshFilter>() as MeshFilter; if (meshFilter) { DestroyImmediate(meshFilter); } } meshLastSyncronised = CubiquityDLL.GetCurrentTime(); availableNodeSyncs--; nodeSyncsPerformed++; } VolumeRenderer vr = voxelTerrainGameObject.GetComponent <VolumeRenderer>(); MeshRenderer mr = gameObject.GetComponent <MeshRenderer>(); if (vr != null && mr != null) { if (mr.enabled != vr.enabled) // Not sure we really need this check? { mr.enabled = vr.enabled; } if (lastSyncronisedWithVolumeRenderer < vr.lastModified) { mr.receiveShadows = vr.receiveShadows; mr.castShadows = vr.castShadows; lastSyncronisedWithVolumeRenderer = Clock.timestamp; } } VolumeCollider vc = voxelTerrainGameObject.GetComponent <VolumeCollider>(); MeshCollider mc = gameObject.GetComponent <MeshCollider>(); if (vc != null && mc != null) { if (mc.enabled != vc.enabled) // Not sure we really need this check? { mc.enabled = vc.enabled; } if (lastSyncronisedWithVolumeCollider < vc.lastModified) { // Actual syncronization to be filled in in the future when we have something to syncronize. lastSyncronisedWithVolumeCollider = Clock.timestamp; } } //Now syncronise any children for (uint z = 0; z < 2; z++) { for (uint y = 0; y < 2; y++) { for (uint x = 0; x < 2; x++) { if (CubiquityDLL.HasChildNode(nodeHandle, x, y, z) == 1) { uint childNodeHandle = CubiquityDLL.GetChildNode(nodeHandle, x, y, z); GameObject childGameObject = GetChild(x, y, z); if (childGameObject == null) { childGameObject = OctreeNode.CreateOctreeNode(childNodeHandle, gameObject); SetChild(x, y, z, childGameObject); } //syncNode(childNodeHandle, childGameObject); OctreeNode childOctreeNode = childGameObject.GetComponent <OctreeNode>(); int syncs = childOctreeNode.syncNode(availableNodeSyncs, voxelTerrainGameObject); availableNodeSyncs -= syncs; nodeSyncsPerformed += syncs; } } } } return(nodeSyncsPerformed); }