예제 #1
0
        /// <summary>
        /// Iterates over the position of every node, translating it to a widget position
        /// Returns the offsets of the furthest nodes of the edges of the widget
        /// To fit the graph in the screen, each offset needs to be as small as possible above 0
        ///
        /// Acquires reader lock
        /// </summary>
        /// <param name="graphWidgetSize">Size of the rendering widget</param>
        /// <param name="graph">Graph being displayed in the widget</param>
        /// <param name="isPreview">True if preview widget, false if main</param>
        /// <param name="xoffsets">Furthest from the left and right sides of the widget</param>
        /// <param name="yoffsets">Furthest from the top and bottom of the widget</param>
        /// <param name="zoffsets">Furthest from in front of/behind the camera lens in the Z direction</param>
        /// <returns>true if a meaningful result was returned</returns>
        public static bool GetWidgetFitOffsets(Vector2 graphWidgetSize, PlottedGraph graph, bool isPreview,
                                               out Vector2 xoffsets, out Vector2 yoffsets, out Vector2 zoffsets)
        {
            if (GlobalConfig.Settings.Logs.BulkLogging)
            {
                Logging.RecordLogEvent($"GetWidgetFitOffsets Start {graph.TID} layout", Logging.LogFilterType.BulkDebugLogFile);
            }
            xoffsets = new Vector2(0, 0);
            yoffsets = new Vector2(0, 0);
            zoffsets = new Vector2(0, 0);
            float zoom = isPreview ? graph.CameraState.PreviewCameraZoom : graph.CameraState.MainCameraZoom;

            float aspectRatio = graphWidgetSize.X / graphWidgetSize.Y;

            Matrix4x4 translation = isPreview ? graph.CameraState.PreviewCameraTranslation : graph.CameraState.MainCameraTranslation;
            Matrix4x4 projection  = Matrix4x4.CreatePerspectiveFieldOfView(1.0f, aspectRatio, 1, 80000);
            Matrix4x4 worldView   = Matrix4x4.CreateFromAxisAngle(Vector3.UnitY, 0) * translation;

            Vector2 xlimits = new Vector2(float.MaxValue, float.MinValue);
            Vector2 ylimits = new Vector2(float.MaxValue, float.MinValue);
            Vector2 zlimits = new Vector2(float.MaxValue, float.MinValue);
            Vector2 ev = new Vector2(0, 0);
            Vector2 xmin = ev, xmax = ev, ymin = ev, ymax = ev;

            float[] positions = graph.LayoutState.DownloadVRAMPositions();

            bool result;

            if (positions.Length < 4)
            {
                result = false;
            }
            else
            {
                result = true;
                for (int idx = 0; idx < positions.Length; idx += 4)
                {
                    float guard = positions[idx + 3];
                    if (guard is not 1)
                    {
                        break;
                    }

                    float x = positions[idx];
                    float y = positions[idx + 1];
                    float z = positions[idx + 2];

                    Vector3 worldpos = new Vector3(x, y, z);

                    Vector2 ndcPos = GraphicsMaths.WorldToNDCPos(worldpos, worldView, projection);
                    if (ndcPos.X < xlimits.X)
                    {
                        xlimits = new Vector2(ndcPos.X, xlimits.Y); xmin = ndcPos;
                    }
                    if (ndcPos.X > xlimits.Y)
                    {
                        xlimits = new Vector2(xlimits.X, ndcPos.X); xmax = ndcPos;
                    }
                    if (ndcPos.Y < ylimits.X)
                    {
                        ylimits = new Vector2(ndcPos.Y, ylimits.Y); ymin = ndcPos;
                    }
                    if (ndcPos.Y > ylimits.Y)
                    {
                        ylimits = new Vector2(ylimits.X, ndcPos.Y); ymax = ndcPos;
                    }
                    if (worldpos.Z < zlimits.X)
                    {
                        zlimits = new Vector2(worldpos.Z, zlimits.Y);
                    }
                    if (worldpos.Z > zlimits.Y)
                    {
                        zlimits = new Vector2(zlimits.X, worldpos.Z);
                    }
                }

                Vector2 minxS = GraphicsMaths.NdcToScreenPos(xmin, graphWidgetSize);
                Vector2 maxxS = GraphicsMaths.NdcToScreenPos(xmax, graphWidgetSize);
                Vector2 minyS = GraphicsMaths.NdcToScreenPos(ymin, graphWidgetSize);
                Vector2 maxyS = GraphicsMaths.NdcToScreenPos(ymax, graphWidgetSize);

                xoffsets = new Vector2(minxS.X, graphWidgetSize.X - maxxS.X);
                yoffsets = new Vector2(minyS.Y, graphWidgetSize.Y - maxyS.Y);
                zoffsets = new Vector2(zlimits.X - zoom, zlimits.Y - zoom);
            }


            //Sometimes the position buffer is full of terrible data.
            //Seems to just be for the preview graph? Only happens at the start so must have gotten hold of uninitialised data
            if (zoffsets.X > 100000000000 || zoffsets.X < -100000000000)
            {
                if (isPreview)
                {
                    graph.CameraState.PreviewCameraZoom = -60000;
                }
                else
                {
                    graph.CameraState.MainCameraZoom = -60000;
                }
                return(false);
            }
            if (GlobalConfig.Settings.Logs.BulkLogging)
            {
                Logging.RecordLogEvent($"GetWidgetFitOffsets exit", Logging.LogFilterType.BulkDebugLogFile);
            }
            return(result);
        }
예제 #2
0
        /// <summary>
        /// Update the node attributes compute VRAM buffer (alpha, node size, mouseover details)
        /// </summary>
        /// <param name="cl">Thread-specific CommandList</param>
        /// <param name="graph">ProtoGraph being drawn</param>
        /// <param name="inputAttributes">Attributes buffer being updated</param>
        /// <param name="resources">Shader resources ResourceSet</param>
        /// <param name="delta">Time-delta from the last update</param>
        /// <param name="mouseoverNodeID">Index of the node the mouse is over</param>
        /// <param name="useAnimAttribs">Flag to specify the graph is in animated-alpha mode</param>
        private unsafe void RenderNodeAttribs(CommandList cl, PlottedGraph graph, DeviceBuffer inputAttributes,
                                              ResourceSet resources, float delta, int mouseoverNodeID, bool useAnimAttribs)
        {
            if (GlobalConfig.Settings.Logs.BulkLogging)
            {
                Logging.RecordLogEvent($"RenderNodeAttribs  {this.EngineID}", Logging.LogFilterType.BulkDebugLogFile);
            }
            AttribShaderParams parms = new AttribShaderParams
            {
                delta         = delta,
                hoveredNodeID = mouseoverNodeID,
                nodeCount     = (uint)Math.Min(graph.RenderedNodeCount(), graph.LayoutState.AttributesVRAM1 !.SizeInBytes / 16),
                MinimumAlpha  = GlobalConfig.AnimatedFadeMinimumAlpha,
                hoverMode     = (mouseoverNodeID != -1) ? 1 : 0,
                isAnimated    = useAnimAttribs ? 1: 0
            };


            graph.GetActiveNodeIndexes(out List <uint> pulseNodes, out List <uint> lingerNodes, out uint[] deactivatedNodes);

            if (GlobalConfig.Settings.Logs.BulkLogging)
            {
                Logging.RecordLogEvent($"RenderNodeAttribs {this.EngineID} updating attribsbuf {inputAttributes.Name}", Logging.LogFilterType.BulkDebugLogFile);
            }

            cl.UpdateBuffer(_attribsParamsBuffer, 0, parms);

            float currentPulseAlpha = Math.Max(GlobalConfig.AnimatedFadeMinimumAlpha, GraphicsMaths.getPulseAlpha());

            //todo - merge contiguous regions to reduce command count
            float[] valArray = new float[3];
            foreach (uint idx in pulseNodes)
            {
                if (idx >= graph.RenderedNodeCount())
                {
                    break;
                }

                if (inputAttributes.SizeInBytes <= idx * 4 * sizeof(float) + (2 * sizeof(float)))
                {
                    break;
                }

                valArray[0] = GlobalConfig.NodeSize; //start big
                valArray[1] = 1.0f;                  //full alpha
                valArray[2] = 1.0f;                  //pulse
                fixed(float *dataPtr = valArray)
                {
                    Debug.Assert((idx * 4 * sizeof(float) + valArray.Length * sizeof(float)) < inputAttributes.SizeInBytes);
                    cl.UpdateBuffer(inputAttributes, idx * 4 * sizeof(float), (IntPtr)dataPtr, (uint)valArray.Length * sizeof(float));
                }
            }

            //make the active node pulse
            if (graph.IsAnimated)
            {
                uint activeNodeIdx = graph.LastAnimatedVert;
                if (!lingerNodes.Contains(activeNodeIdx))
                {
                    valArray[0] = currentPulseAlpha;
                    fixed(float *dataPtr = valArray)
                    {
                        uint nodeAlphaOffset = (activeNodeIdx * 4 * sizeof(float)) + (2 * sizeof(float));

                        if (nodeAlphaOffset + sizeof(float) <= inputAttributes.SizeInBytes)
                        {
                            cl.UpdateBuffer(inputAttributes, nodeAlphaOffset, (IntPtr)dataPtr, sizeof(float));
                        }
                    }
                }
            }

            foreach (uint idx in lingerNodes)
            {
                if (idx >= graph.RenderedNodeCount())
                {
                    break;
                }

                if (inputAttributes.SizeInBytes <= idx * 4 * sizeof(float) + (2 * sizeof(float)))
                {
                    break;
                }

                valArray[0] = 2.0f + currentPulseAlpha;
                fixed(float *dataPtr = valArray)
                {
                    Debug.Assert((idx * 4 * sizeof(float) + (2 * sizeof(float)) + sizeof(float)) < inputAttributes.SizeInBytes);
                    cl.UpdateBuffer(inputAttributes, idx * 4 * sizeof(float) + (2 * sizeof(float)), (IntPtr)dataPtr, sizeof(float));
                }
            }

            foreach (uint idx in deactivatedNodes)
            {
                if (idx >= graph.RenderedNodeCount())
                {
                    break;
                }

                if (inputAttributes.SizeInBytes <= idx * 4 * sizeof(float) + (2 * sizeof(float)))
                {
                    break;
                }

                valArray[0] = 0.8f;
                fixed(float *dataPtr = valArray)
                {
                    Debug.Assert((idx * 4 * sizeof(float) + (2 * sizeof(float)) + sizeof(float)) < inputAttributes.SizeInBytes);
                    cl.UpdateBuffer(inputAttributes, idx * 4 * sizeof(float) + (2 * sizeof(float)), (IntPtr)dataPtr, sizeof(float));
                }
            }

            if (graph.HighlightsChanged)
            {
                ApplyHighlightAttributes(cl, graph, inputAttributes);
            }

            cl.SetPipeline(_nodeAttribComputePipeline);
            cl.SetComputeResourceSet(0, resources);

            cl.Dispatch((uint)Math.Ceiling(inputAttributes.SizeInBytes / (256.0 * sizeof(Vector4))), 1, 1);
        }