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()); }