示例#1
0
        private void OnLoad(object sender, EventArgs e)
        {
            Application.Idle += OnApplicationIdle;

            GL.ClearColor(Color.CornflowerBlue);
            GL.Enable(EnableCap.DepthTest);

            SetupViewport();

            Context.VSync = true;

            _window = new Window3D(-50, 50, -50, 50, -50, 50);

            Calculator calc = new Calculator();
            CompiledExpression expr = ExpressionCompiler.CompileInfix("sin(x)+cos(y)", false);

            var mesh = LineCalculator3D.Calculate(calc, expr, _window, 0.5F);

            // Vertices
            GL.GenBuffers(1, out _bufferInfo.VertexId);
            GL.BindBuffer(BufferTarget.ArrayBuffer, _bufferInfo.VertexId);
            GL.BufferData(BufferTarget.ArrayBuffer, mesh.VertexArraySize, mesh.Vertices, BufferUsageHint.StaticDraw);

            // Indices
            GL.GenBuffers(1, out _bufferInfo.IndexId);
            GL.BindBuffer(BufferTarget.ElementArrayBuffer, _bufferInfo.IndexId);
            GL.BufferData(BufferTarget.ElementArrayBuffer, mesh.IndexArraySize, mesh.Indices, BufferUsageHint.StaticDraw);

            // Colors
            GL.GenBuffers(1, out _bufferInfo.ColorId);
            GL.BindBuffer(BufferTarget.ArrayBuffer, _bufferInfo.ColorId);
            GL.BufferData(BufferTarget.ArrayBuffer, mesh.ColorArraySize, mesh.Colors, BufferUsageHint.StaticDraw);

            _bufferInfo.IndexCount = mesh.Indices.Length;
        }
        public static ConstructedMatrix Calculate(Calculator calc, CompiledExpression expr, Window3D window, float step)
        {
            float lowZ = float.MaxValue, highZ = float.MinValue;
            List<Vector3> results = new List<Vector3>();
            List<int> startPoints = new List<int>();

            int i = 0;
            for (float x = window.MinimumX; x < window.MaximumX; x += step)
            {
                startPoints.Add(i);
                calc.SetArgument("x", x);

                bool outsideGraph = true;
                Vector3? last = null;
                for (float y = window.MinimumY; y < window.MaximumY; y += step)
                {
                    calc.SetArgument("y", y);

                    float z = (float)calc.Evaluate(expr);

                    Vector3 result = new Vector3(x, y, z);
                    results.Add(result);

                    bool includeResult = false, includeLast = false;
                    if (z > window.MaximumZ || z < window.MinimumZ)
                    {
                        // Outside the window
                        if (!outsideGraph)
                        {
                            // First point outside the window
                            includeResult = true;
                            outsideGraph = true;
                        }
                    }
                    else
                    {
                        // Inside the window
                        if (outsideGraph)
                        {
                            // First point inside the window, include the last vertex as well
                            includeLast = true;
                        }

                        includeResult = true;
                        outsideGraph = false;
                    }

                    if (includeResult)
                    {
                        if (z < lowZ)
                        {
                            lowZ = includeLast && last.HasValue ? Math.Min(z, last.Value.Z) : z;
                        }

                        if (z > highZ)
                        {
                            highZ = includeLast && last.HasValue ? Math.Max(z, last.Value.Z) : z;
                        }
                    }

                    last = result;
                    i++;
                }
            }

            List<int> indices = new List<int>();
            for (int x = 0; x < startPoints.Count - 1; x++)
            {
                int currentX = startPoints[x];
                int nextX = startPoints[x + 1];

                for (int y = 0; y < startPoints[x + 1] - startPoints[x] - 1; y++)
                {
                    indices.AddRange(new[] { currentX + y, nextX + y, nextX + y + 1, currentX + y, nextX + y + 1, currentX + y + 1 });
                }
            }

            int[] colors = new int[results.Count];

            float absLowZ = Math.Abs(lowZ);
            float mulFactor = 255F / (absLowZ + Math.Abs(highZ));

            for (int j = 0; j < results.Count; j++)
            {
                float z = results[j].Z;

                int normalized = Math.Max(0, Math.Min(255, (int)Math.Round((z + absLowZ) * mulFactor)));
                colors[j] = Color.FromArgb(normalized, normalized, normalized).ToArgb();
            }

            return new ConstructedMatrix(results.ToArray(), indices.ToArray(), colors.ToArray());
        }