Example #1
0
        private void ProcessPendingUpdates()
        {
            // We must be called in edit lock

            var timer = System.Diagnostics.Stopwatch.StartNew();      // Measure time precise in update

            #region Dynamic Loading/Add/Remove native handles ---------------------------------------------------------------

            Performance.Enter("PendNative");

            foreach (NodeLoadInfo nodeLoadInfo in pendingLoaders)
            {
                if (nodeLoadInfo.state == DynamicLoadingState.LOADED)   // We got a callback from dyn loader that we were loaded or unloaded
                {
                    unTransform transform = NodeUtils.FindFirstGameObjectTransform(nodeLoadInfo.loader.GetNativeReference());

                    if (transform == null)              // We have been unloaded or not registered
                    {
                        continue;
                    }

                    if (transform.childCount != 0)       // We have already a child and our sub graph was loaded
                    {
                        continue;
                    }

                    GameObject go = Traverse(nodeLoadInfo.node, null);          // Build sub graph

                    if (go != null)
                    {
                        go.transform.SetParent(transform, false);               // Connect to our parent
                    }
                }
                else if (nodeLoadInfo.state == DynamicLoadingState.UNLOADED)
                {
                    List <GameObject> list;

                    if (NodeUtils.FindGameObjects(nodeLoadInfo.loader.GetNativeReference(), out list))
                    {
                        foreach (GameObject go in list)
                        {
                            foreach (unTransform child in go.transform)         //We need to unload all limked go in hierarchy
                            {
                                RemoveGameObjectHandles(child.gameObject);
                                GameObject.Destroy(child.gameObject);
                            }
                        }
                    }
                }
            }

            pendingLoaders.Clear();

            Performance.Leave();

            #endregion

            #region Activate/Deactivate GameObjects based on scenegraph -----------------------------------------------------

            Performance.Enter("PendActGO");

            foreach (ActivationInfo activationInfo in pendingActivations)
            {
                List <GameObject> list;  // We need to activate the correct nodes

                if (NodeUtils.FindGameObjects(activationInfo.node.GetNativeReference(), out list))
                {
                    foreach (GameObject obj in list)
                    {
                        if (activationInfo.state == NodeActionEvent.IS_TRAVERSABLE)
                        {
                            obj.SetActive(true);
                        }
                        else
                        {
                            obj.SetActive(false);
                        }
                    }
                }
            }

            pendingActivations.Clear();

            Performance.Leave();

            #endregion

            #region Update slow loading assets ------------------------------------------------------------------------------

            Performance.Enter("PendSlow");

            while (pendingBuilds.Count > 0 && timer.Elapsed.TotalSeconds < Settings.MaxBuildTime)
            {
                NodeHandle handle = pendingBuilds.Dequeue();
                handle.BuildGameObject();
            }

            Performance.Leave();

            #endregion

            // Right now we use this as a dirty fix to handle unused shared materials

            _unusedCounter = (_unusedCounter + 1) % Settings.FrameCleanupInterval;
            if (_unusedCounter == 0)
            {
                Performance.Enter("PendCleanup");
                Resources.UnloadUnusedAssets();
                Performance.Leave();
            }
        }
Example #2
0
        // TODO: Make functions...
        public bool Build(NodeHandle nodeHandle, GameObject gameObject, NodeHandle activeStateNode)
        {
            var node = nodeHandle.node;

            var cb = node as Crossboard;

            if (cb == null)
            {
                return(false);
            }

            float[] position_data;
            if (!cb.GetObjectPositions(out position_data))
            {
                return(false);
            }

            float[] object_data;
            if (!cb.GetObjectData(out object_data))
            {
                return(false);
            }

            var objects = position_data.Length / 3; // Number of objects


            // NOTE: CrossboardDatasets are copied to compute buffers when assigning the dataset,
            // thus we can reuse same dataset objects to reduce GC pressure if needed.
            CrossboardDataset dataset = new CrossboardDataset();

            dataset.POSITION    = new Vector3[objects];
            dataset.UV0ListComp = new List <Vector4>(objects);
            dataset.UV1ListComp = new List <Vector4>(objects);
            dataset.COLOR       = new Color[objects];

            var float3_index = 0;
            var float4_index = 0;

            for (var i = 0; i < objects; i++)
            {
                dataset.POSITION[i] = new Vector3(position_data[float3_index], position_data[float3_index + 1], position_data[float3_index + 2]);

                // size, heading, pitch, roll
                dataset.UV0ListComp.Add(new Vector4(object_data[float4_index] * 2f, object_data[float4_index + 1], object_data[float4_index + 2], object_data[float4_index + 3]));

                // postion offset (x - its up normal), planes offset ( xyz - in there normal direction)
                dataset.UV1ListComp.Add(new Vector4(-0.02f, 0, 0, 0));

                float3_index += 3;
                float4_index += 4;
            }

            // Shouldnt this be our settings?
            if (cb.UseColors)
            {
                float[] color_data;

                if (!cb.GetColorData(out color_data))
                {
                    return(false);
                }

                float4_index = 0;

                var colors = new Color[objects];

                for (int i = 0; i < objects; i++)
                {
                    colors[i]     = new Color(color_data[float4_index], color_data[float4_index + 1], color_data[float4_index + 2], color_data[float4_index + 3]);
                    float4_index += 4;
                }

                dataset.COLOR = colors;
            }

            var renderer = gameObject.GetComponent <CrossboardRenderer_ComputeShader>();

            if (renderer == null)
            {
                renderer = gameObject.AddComponent <CrossboardRenderer_ComputeShader>();

                renderer.OpaqueCrossboardCompute = true;
                renderer._computeShader          = GameObject.Instantiate(_computeShader);
            }


            var material = GameObject.Instantiate(_crossboardMaterial);

            // check if the texture is loaded for this state, otherwise load it
            if (activeStateNode != null)
            {
                if ((activeStateNode.stateLoadInfo & StateLoadInfo.Texture) == StateLoadInfo.None)
                {
                    var state = activeStateNode.node.State;

                    if (!StateHelper.Build(state, out StateBuildOutput buildOutput, _textureCache))
                    {
                        return(false);
                    }

                    activeStateNode.stateLoadInfo |= StateLoadInfo.Texture;
                    activeStateNode.texture        = buildOutput.Texture;
                }

                material.mainTexture = activeStateNode.texture;
            }

            renderer.SetCrossboardDataset(dataset, material);

            return(true);
        }
Example #3
0
        //Add GameObjects to dictionary

        // Traverse function iterates the scene graph to build local branches on Unity
        GameObject Traverse(Node n, Material currentMaterial)
        {
            // We must be called in edit lock

            if (n == null || !n.IsValid())
            {
                return(null);
            }

            // --------------------------- Add game object ---------------------------------------

            string name = n.GetName();

            if (String.IsNullOrEmpty(name))
            {
                name = n.GetNativeTypeName();
            }

            GameObject gameObject = new GameObject(name);

            var nodeHandle = gameObject.AddComponent <NodeHandle>();

            //nodeHandle.Renderer = Renderer;
            nodeHandle.node            = n;
            nodeHandle.currentMaterial = currentMaterial;
            nodeHandle.ComputeShader   = Settings.ComputeShader;

            // ---------------------------- Check material state ----------------------------------

            if (n.HasState())
            {
                State state = n.State;

                if (state.HasTexture(0) && state.GetMode(StateMode.TEXTURE) == StateModeActivation.ON)
                {
                    gzTexture texture = state.GetTexture(0);

                    if (!textureMaterialStorage.TryGetValue(texture.GetNativeReference(), out currentMaterial))
                    {
                        if (texture.HasImage())
                        {
                            ImageFormat   image_format;
                            ComponentType comp_type;
                            uint          components;

                            uint depth;
                            uint width;
                            uint height;

                            uint size;

                            bool uncompress = false;

                            Image image = texture.GetImage();

                            image_format = image.GetFormat();

                            image.Dispose();

                            switch (image_format)      // Not yet
                            {
                            case ImageFormat.COMPRESSED_RGBA8_ETC2:
                                if (!SystemInfo.SupportsTextureFormat(TextureFormat.ETC2_RGBA8))
                                {
                                    uncompress = true;
                                }
                                break;

                            case ImageFormat.COMPRESSED_RGB8_ETC2:
                                if (!SystemInfo.SupportsTextureFormat(TextureFormat.ETC2_RGB))
                                {
                                    uncompress = true;
                                }
                                break;

                            case ImageFormat.COMPRESSED_RGBA_S3TC_DXT1:
                            case ImageFormat.COMPRESSED_RGB_S3TC_DXT1:
                                if (!SystemInfo.SupportsTextureFormat(TextureFormat.DXT1))
                                {
                                    uncompress = true;
                                }
                                break;

                            case ImageFormat.COMPRESSED_RGBA_S3TC_DXT5:
                                if (!SystemInfo.SupportsTextureFormat(TextureFormat.DXT5))
                                {
                                    uncompress = true;
                                }
                                break;
                            }


                            if (texture.GetMipMapImageArray(ref _image_texture_data, out size, out image_format, out comp_type, out components, out width, out height, out depth, true, uncompress))
                            {
                                if (depth == 1)
                                {
                                    if (n is Crossboard)
                                    {
                                        currentMaterial = new Material(Settings.CrossboardShader);
                                    }
                                    else
                                    {
                                        currentMaterial = new Material(Settings.DefaultShader);
                                    }

                                    TextureFormat format = TextureFormat.ARGB32;

                                    switch (comp_type)
                                    {
                                    case ComponentType.UNSIGNED_BYTE:
                                    {
                                        switch (image_format)
                                        {
                                        case ImageFormat.RGBA:
                                            format = TextureFormat.RGBA32;
                                            break;

                                        case ImageFormat.RGB:
                                            format = TextureFormat.RGB24;
                                            break;

                                        case ImageFormat.COMPRESSED_RGBA_S3TC_DXT1:
                                        case ImageFormat.COMPRESSED_RGB_S3TC_DXT1:
                                            format = TextureFormat.DXT1;
                                            break;

                                        case ImageFormat.COMPRESSED_RGBA_S3TC_DXT5:
                                            format = TextureFormat.DXT5;
                                            break;

                                        case ImageFormat.COMPRESSED_RGB8_ETC2:
                                            format = TextureFormat.ETC2_RGB;
                                            break;

                                        case ImageFormat.COMPRESSED_RGBA8_ETC2:
                                            format = TextureFormat.ETC2_RGBA8;
                                            break;


                                        default:
                                            // Issue your own error here because we can not use this texture yet
                                            return(null);
                                        }
                                    }
                                    break;

                                    default:
                                        // Issue your own error here because we can not use this texture yet
                                        return(null);
                                    }


                                    Texture2D tex = new Texture2D((int)width, (int)height, format, true);

                                    tex.LoadRawTextureData(_image_texture_data);


                                    switch (texture.MinFilter)
                                    {
                                    default:
                                        tex.filterMode = FilterMode.Point;
                                        break;

                                    case gzTexture.TextureMinFilter.LINEAR:
                                    case gzTexture.TextureMinFilter.LINEAR_MIPMAP_NEAREST:
                                        tex.filterMode = FilterMode.Bilinear;
                                        break;

                                    case gzTexture.TextureMinFilter.LINEAR_MIPMAP_LINEAR:
                                        tex.filterMode = FilterMode.Trilinear;
                                        break;
                                    }

                                    tex.Apply(texture.UseMipMaps, true);

                                    currentMaterial.mainTexture = tex;
                                }
                            }
                        }

                        // Add some kind of check for textures shared by many
                        // Right now only for crossboards

                        if (n is Crossboard)
                        {
                            textureMaterialStorage.Add(texture.GetNativeReference(), currentMaterial);
                        }
                    }

                    nodeHandle.currentMaterial = currentMaterial;
                    texture.Dispose();
                }

                state.Dispose();
            }

            // ---------------------------- Transform check -------------------------------------

            gzTransform tr = n as gzTransform;

            if (tr != null)
            {
                Vec3 translation;

                if (tr.GetTranslation(out translation))
                {
                    Vector3 trans = new Vector3(translation.x, translation.y, translation.z);
                    gameObject.transform.localPosition = trans;
                }

                // Notify subscribers of new Transform
                OnNewTransform?.Invoke(gameObject);
            }

            // ---------------------------- DynamicLoader check -------------------------------------

            DynamicLoader dl = n as DynamicLoader;      // Add dynamic loader as game object in dictionary

            // so other dynamic loaded data can parent them as child to loader
            if (dl != null)
            {
                List <GameObject> list;

                if (!NodeUtils.FindGameObjects(dl.GetNativeReference(), out list))     // We are not registered
                {
                    NodeUtils.AddGameObjectReference(dl.GetNativeReference(), gameObject);

                    nodeHandle.inNodeUtilsRegistry = true;  // Added to registry

                    // We shall continue to iterate as a group to see if we already have loaded children
                }
                else  // We are already in list
                {
                    return(list[0]);     // Lets return first object wich is our main registered node
                }

                // Notify subscribers of new Loader
                OnNewLoader?.Invoke(gameObject);
            }

            // ---------------------------- Lod check -------------------------------------

            Lod ld = n as Lod;

            if (ld != null)
            {
                foreach (Node child in ld)
                {
                    GameObject go_child = Traverse(child, currentMaterial);

                    if (go_child == null)
                    {
                        return(null);
                    }

                    NodeHandle h = go_child.GetComponent <NodeHandle>();

                    if (h != null)
                    {
                        if (!NodeUtils.HasGameObjects(h.node.GetNativeReference()))
                        {
                            NodeUtils.AddGameObjectReference(h.node.GetNativeReference(), go_child);

                            h.inNodeUtilsRegistry = true;
                            h.node.AddActionInterface(_actionReceiver, NodeActionEvent.IS_TRAVERSABLE);
                            h.node.AddActionInterface(_actionReceiver, NodeActionEvent.IS_NOT_TRAVERSABLE);
                        }
                    }

                    go_child.transform.SetParent(gameObject.transform, false);
                }

                // Notify subscribers of new Lod
                OnNewLod?.Invoke(gameObject);

                // Dont process group as group is already processed
                return(gameObject);
            }

            // ---------------------------- Roi check -------------------------------------

            Roi roi = n as Roi;

            if (roi != null)
            {
                nodeHandle.updateTransform  = true;
                nodeHandle.inNodeUpdateList = true;
                updateNodeObjects.AddLast(gameObject);

                foreach (Node child in roi)
                {
                    GameObject go_child = Traverse(child, currentMaterial);

                    if (go_child == null)
                    {
                        return(null);
                    }

                    NodeHandle h = go_child.GetComponent <NodeHandle>();

                    if (h != null)
                    {
                        if (!NodeUtils.HasGameObjects(h.node.GetNativeReference()))
                        {
                            NodeUtils.AddGameObjectReference(h.node.GetNativeReference(), go_child);

                            h.inNodeUtilsRegistry = true;
                            h.node.AddActionInterface(_actionReceiver, NodeActionEvent.IS_TRAVERSABLE);
                            h.node.AddActionInterface(_actionReceiver, NodeActionEvent.IS_NOT_TRAVERSABLE);
                        }
                    }

                    go_child.transform.SetParent(gameObject.transform, false);
                }

                // Dont process group
                return(gameObject);
            }

            // ---------------------------- RoiNode check -------------------------------------

            RoiNode roinode = n as RoiNode;

            if (roinode != null)
            {
                nodeHandle.updateTransform  = true;
                nodeHandle.inNodeUpdateList = true;
                updateNodeObjects.AddLast(gameObject);
            }

            // ---------------------------- Group check -------------------------------------

            Group g = n as Group;

            if (g != null)
            {
                foreach (Node child in g)
                {
                    GameObject go_child = Traverse(child, currentMaterial);

                    if (go_child == null)
                    {
                        return(null);
                    }

                    go_child.transform.SetParent(gameObject.transform, false);
                }

                return(gameObject);
            }

            // ---------------------------ExtRef check -----------------------------------------

            ExtRef ext = n as ExtRef;

            if (ext != null)
            {
                AssetLoadInfo info = new AssetLoadInfo(gameObject, ext.ResourceURL, ext.ObjectID);

                pendingAssetLoads.Push(info);
            }

            // ---------------------------- Crossboard check -----------------------------------

            Crossboard cb = n as Crossboard;

            if (cb != null && GfxCaps.HasCapability(Capability.UseTreeCrossboards))
            {
                // Scheduled for later build
                pendingBuilds.Enqueue(nodeHandle);
            }

            // ---------------------------- Geometry check -------------------------------------

            Geometry geom = n as Geometry;

            if (geom != null)
            {
                nodeHandle.BuildGameObject();

                // Notify subscribers of new Geometry
                OnNewGeometry?.Invoke(gameObject);

                // Later on we will identify types of geoemtry that will be scheduled later if they are extensive and not ground that covers other geometry
                // and build them in a later pass distributed over time
                // pendingBuilds.Enqueue(nodeHandle);
            }

            return(gameObject);
        }
        private GameObject TraverseInternal(Node node, NodeHandle activeStateNode)
        {
            // We must be called in edit lock

            System.Diagnostics.Debug.Assert(node != null && node.IsValid());



            // --------------------------- Add game object ---------------------------------------



            NodeHandle nodeHandle;

            var builder = GetBuilderForNode(node);

            if (builder == null)
            {
                nodeHandle = CreateNodeHandle(node, PoolObjectFeature.None);

                // check for new active state
                if (node.HasState())
                {
                    activeStateNode = nodeHandle;
                }
            }
            else
            {
                nodeHandle = CreateNodeHandle(node, builder.Feature);

                // check for new active state
                if (node.HasState())
                {
                    activeStateNode = nodeHandle;
                }

                // build gameobjects for this node
                BuildNode(builder, nodeHandle, activeStateNode);
            }

            var gameObject = nodeHandle.gameObject;



            // ---------------------------- Transform check -------------------------------------

            if (node is gzTransform tr)
            {
                try
                {
                    Performance.Enter("SM.Traverse.Transform");

                    ProcessTransformNode(tr, gameObject.transform);

                    Performance.Enter("SM.Traverse.OnNewTransform");

                    // Notify subscribers of new Transform
                    OnNewTransform?.Invoke(gameObject);

                    Performance.Leave();
                }
                finally
                {
                    Performance.Leave();
                }
            }

            // ---------------------------- DynamicLoader check -------------------------------------

            // Add dynamic loader as game object in dictionary
            // so other dynamic loaded data can parent them as child to loader
            if (node is DynamicLoader dl)
            {
                try
                {
                    Performance.Enter("SM.Traverse.Loader");

                    var res = ProcessDynamicLoaderNode(dl, nodeHandle);
                    if (res != null)
                    {
                        return(res);
                    }

                    // We shall continue to iterate as a group to see if we already have loaded children


                    Performance.Enter("SM.Traverse.OnNewLoader");

                    // Notify subscribers of new Loader
                    OnNewLoader?.Invoke(gameObject);

                    Performance.Leave();
                }
                finally
                {
                    Performance.Leave();
                }
            }

            // ---------------------------- Lod check -------------------------------------

            if (node is Lod ld)
            {
                ProcessLodNode(ld, nodeHandle, activeStateNode);

                Performance.Enter("SM.Traverse.OnNewLod");

                // Notify subscribers of new Lod
                OnNewLod?.Invoke(gameObject);

                Performance.Leave();

                // Dont process group as group is already processed
                return(gameObject);
            }

            // ---------------------------- Roi check -------------------------------------

            if (node is Roi roi)
            {
                ProcessRoiNode(roi, nodeHandle, activeStateNode);

                // Dont process group as group is already processed
                return(gameObject);
            }

            // ---------------------------- RoiNode check -------------------------------------

            if (node is RoiNode)
            {
                RegisterNodeForUpdate(nodeHandle);
            }

            // ---------------------------- Group check -------------------------------------

            if (node is Group g)
            {
                ProcessGroup(g, nodeHandle, activeStateNode);
                return(gameObject);
            }

            // ---------------------------ExtRef check -----------------------------------------

            if (node is ExtRef extRef)
            {
                var info = new AssetLoadInfo(gameObject, extRef.ResourceURL, extRef.ObjectID);

                pendingAssetLoads.Push(info);
            }

            // ---------------------------- Geometry check -------------------------------------

            if (node is Geometry geom)
            {
                OnNewGeometry?.Invoke(gameObject);
            }

            return(gameObject);
        }
 private void RegisterNodeForUpdate(NodeHandle nodeHandle)
 {
     nodeHandle.updateTransform  = true;
     nodeHandle.inNodeUpdateList = true;
     updateNodeObjects.AddLast(nodeHandle.gameObject);
 }
 private void ProcessRoiNode(Roi node, NodeHandle nodeHandle, NodeHandle activeStateNode)
 {
     RegisterNodeForUpdate(nodeHandle);
     ProcessGroup(node, nodeHandle, activeStateNode, true);
 }
 private void ProcessLodNode(Lod node, NodeHandle nodeHandle, NodeHandle activeStateNode)
 {
     ProcessGroup(node, nodeHandle, activeStateNode, true);
 }