Example #1
0
        /// <summary>
        /// Because Octrees are MonoBehaviors, they must be attached to game objects. This static function will deliver an octreeNode, properly attached
        /// to a game object, of a given derivative type.
        /// </summary>
        /// <returns>A game object with an octree node attached.</returns>
        /// <param name="octreeType">A type derived from the class OctreeNodeAlt, specific to the volume for which this OctreeNodeAlt is to be created.</param>
        /// <param name="nodeHandle">The node handle to give the OctreeNodeAlt</param>
        /// <param name="parent">The parent game object of the OctreeNodeAlt</param>
        public static OctreeNodeAlt CreateOctreeNode(Type octreeType, uint nodeHandle, GameObject parent)
        {
            if (octreeType == null)
            {
                Debug.LogWarning("OctreeNodeAlt->CreateOctreeNode was passed a null type. Attempting to fail gracefully by creating a non-functional OctreeNodeAlt.");
                octreeType = typeof(OctreeNodeAlt);
            }
            if (!octreeType.IsSubclassOf(typeof(OctreeNodeAlt)))
            {
                Debug.LogWarning("OctreeNodeAlt->CreateOctreeNode was passed a type (" + octreeType + ") that does not inherit from OctreeNodeAlt. Attempting to fail gracefully by creating a non-functional OctreeNodeAlt.");
                octreeType = typeof(OctreeNodeAlt);
            }

            //new object
            GameObject obj = new GameObject();

            //Add the component of octreeType, DYNAMICALLY MUAHAHAHAHHA
            OctreeNodeAlt node = obj.AddComponent(octreeType) as OctreeNodeAlt;

            //follow the addComponent immediately (I like breaking things into chunks)
            node.InitializeNode(nodeHandle);
            node.InitializeObj(null);
            node.AttachParent(parent);

            return(node);
        }
Example #2
0
        void Start()
        {
            if (material == null)
            {
                // This shader should be appropriate in most scenarios, and makes a good default.
                material = Instantiate(Resources.Load("Materials/ColoredCubes", typeof(Material))) as Material;
            }

            OctreeNodeAlt toSync = gameObject.GetComponentInChildren <OctreeNodeAlt>() as OctreeNodeAlt;

            if (toSync != null)
            {
                toSync.ForceSync();
            }
        }
Example #3
0
        /// <summary>
        /// This function is 'unsafe' in that it does not do any checking to see if i is in bounds (ie: i < 8), or if this.children is null. It WILL avoid creating a node that already exists, and will delete a misplaced node entirely. This function is called as part of SyncNode and typically should not be overwritten.
        /// </summary>
        /// <param name="i">The index of the child node computed using uint i = x + y<<1 + z<<2; or a for loop such as SyncNode's, where we can think of x being the inner loop and z the outer. </param>
        /// <param name="childNodeHandle">Child node handle.</param>
        protected void SetChild(uint i, uint childNodeHandle)
        {
            if (children[i] != null)
            {
                if (children[i].nodeHandle == childNodeHandle)
                {
                    return;
                }
                else
                {
                    //Debug.Log ("Could this be the culprit making the infinite? Trace node Handle|childNodeHandle: " + children[i].nodeHandle + "|" + childNodeHandle);
                    DisposeChild(i);
                }
            }


            children[i] = OctreeNodeAlt.CreateOctreeNode(this.GetType(), childNodeHandle, gameObject);
        }
Example #4
0
        /// <summary>
        /// Performs operations on a new OctreeNodeAlt GameObject, and does not have to be called by the average Editor-User. Typically called in CreateOctreeNode, immediately after InitializeNode.
        /// It may be overwritten with care (particularly in building the localPosition)
        /// </summary>
        /// <param name="parent">The parent game object, typically expected to either be something derived from Cubiquity.Volume OR another Octree Node of an identical type.</param>
        public virtual void AttachParent(GameObject parent)
        {
            //we Should be the child of something, but just in case... (Hey it worries me whether !parent works... null is odd in some languages)
            if (parent == null)
            {
                gameObject.transform.localPosition = lowerCorner;
                return;
            }

            //yay unity-relevant initialization stuff
            gameObject.layer            = parent.layer;
            gameObject.transform.parent = parent.transform;             //this is actually what physically hooks them together. It makes gameObject the child of parent

            //this might seem odd to place here instead of at the top but the order we add transforms matters. If we change localPosition before the parent
            //transform we'll get funny errors where the whole map condenses on itself.
            gameObject.transform.localPosition = lowerCorner;

            //see if we are the child of a volume, or of another node...
            OctreeNodeAlt parentNode = parent.GetComponent <OctreeNodeAlt>();

            //if there is no parent node...
            if (parentNode != null)
            {
                //Debug.Log ("No Parents");
                //Transform the localposition by the parentnode
                gameObject.transform.localPosition -= parentNode.lowerCorner;

                //grab the parent node's volume renderer & collider
                volRend = parentNode.volRend;
                volColl = parentNode.volColl;
            }
            else
            {
                //Debug.Log ("Volume renderer and collider successfully passed to root.");
                //otherwise I really hope this is the child of a Volume!
                volRend = parent.GetComponent <VolumeRenderer>();
                volColl = parent.GetComponent <VolumeCollider>();
            }

            //Debug.Log ("Testing VolRend & VolColl: " + volRend.ToString() + volColl.ToString());
        }
Example #5
0
        /// <summary>
        /// This function can be used to force the entire mesh to sync on next update, which is useful in situations where a very important top level component has changed dramatically (ie, if volumeRenderer is gone).
        /// </summary>
        public void ForceSync()
        {
            //see if we can get our parent node
            OctreeNodeAlt parentNode = gameObject.GetComponentInParent <OctreeNodeAlt>() as OctreeNodeAlt;

            //if there is no parent node...
            if (parentNode != null)
            {
                //grab the parent node's volume renderer & collider
                volRend = parentNode.volRend;
                volColl = parentNode.volColl;
            }
            else
            {
                //Debug.Log ("Volume renderer and collider successfully passed to root.");
                //otherwise I really hope this is the child of a Volume!
                volRend = gameObject.GetComponentInParent <VolumeRenderer>() as VolumeRenderer;
                volColl = gameObject.GetComponentInParent <VolumeCollider>() as VolumeCollider;
            }

            //doing this will force all meshes to be rebuilt. Which will force the octreenode to ask "Do i have a volume renderer to even display this with?"
            meshLastSyncronised = 0;

            if (children == null)
            {
                return;
            }

            //this loop will iterate through all the children
            for (uint i = 0; i < 8; i++)
            {
                if (children[i] != null)
                {
                    children[i].RelayComponentChanges();
                }
            }
        }
Example #6
0
        /// <summary>
        /// Synchronize this instance.
        /// </summary>
        protected override void Synchronize()
        {
            //super!
            base.Synchronize();


            //Not sure if this needs to be done every synchronization but okay
            CogBlockVolumeRenderer volRend = gameObject.GetComponent <CogBlockVolumeRenderer>();

            //initialize the volume renderer so that it's normals face in the correct direction
            if (volRend != null)            //I miss actionscript with lazy evaluation so I could string these all together in one big if..
            {
                if (volRend.material != null)
                {
                    // We compute surface normals using derivative operations in the fragment shader, but for some reason
                    // these are backwards on Linux. We can correct for this in the shader by setting the multiplier below.
                                        #if UNITY_STANDALONE_LINUX && !UNITY_EDITOR
                    float normalMultiplier = -1.0f;
                                        #else
                    float normalMultiplier = 1.0f;
                                        #endif
                    volRend.material.SetFloat("normalMultiplier", normalMultiplier);
                }
            }

            // Check to make sure we have anything to Synchronize
            if (data == null)
            {
                return;
            }

            //still checking
            if (!data.volumeHandle.HasValue)
            {
                return;
            }

            //update the volume
            CubiquityDLL.UpdateVolume(data.volumeHandle.Value);

            //try to synchronize the octrees
            if (CubiquityDLL.HasRootOctreeNode(data.volumeHandle.Value) == 1)
            {
                if (rootOctreeNode == null || rootOctreeNodeGameObject == null)
                {
                    //Debug.Log("Creating RootOctreeNode from null");
                    uint rootNodeHandle = CubiquityDLL.GetRootOctreeNode(data.volumeHandle.Value);
                    rootOctreeNode           = OctreeNodeAlt.CreateOctreeNode(typeof(CogBlockOctreeNode), rootNodeHandle, gameObject) as CogBlockOctreeNode;
                    rootOctreeNodeGameObject = rootOctreeNode.gameObject;
                }

                //Sync the Node and remember SyncNode will return syncs remaining. If some are remaining, the mesh is syncronized.
                isMeshSyncronized = (rootOctreeNode.SyncNode(maxNodesPerSync) != 0);

                //Where Sync nodes handles re-informed a bunch of nodes based on mesh changes, RelayComponentChanges assumes that something happened
                //which every node of the octree needs to know about. By setting this flag = true, we can relay those changes quickly down through the whole tree.
                //of course since RelayComponentChanges doesn't really 'yield' after a certain number of units are updated, it is important to realize this function is
                //called sparingly, usually only in edit mode, and should not perform incredibly complex per-update operations.
                if (RelayComponentChanges)
                {
                    rootOctreeNode.RelayComponentChanges();
                }
            }
        }