using System; using System.Collections.Generic; using System.Data.Common; using System.Data.SqlTypes; using System.Drawing; using System.Linq; using OpenTK; using OpenTK.Graphics.OpenGL; using OpenTK.Input; using Platformer.Util; using BeginMode = OpenTK.Graphics.OpenGL4.BeginMode; using BufferRangeTarget = OpenTK.Graphics.OpenGL4.BufferRangeTarget; using BufferTarget = OpenTK.Graphics.OpenGL4.BufferTarget; using ClearBufferMask = OpenTK.Graphics.OpenGL4.ClearBufferMask; using DrawElementsType = OpenTK.Graphics.OpenGL4.DrawElementsType; using EnableCap = OpenTK.Graphics.OpenGL4.EnableCap; using GL = OpenTK.Graphics.OpenGL4.GL; namespace Platformer { public struct ViewMats { public Matrix4 Model; public Matrix4 View; public Matrix4 Proj; public static ViewMats Identity => new ViewMats {Model = Matrix4.Identity, View = Matrix4.Identity}; } public struct PlaneMats { public Matrix4 Tform; public static PlaneMats Identity => new PlaneMats {Tform = Matrix4.Identity}; } public class PlatformWindow : GameWindow { private Buffer _viewBuf; private Buffer _tformBuf; private ViewMats _view; private PlaneMats _tform; private Program _render; private Program _compute; private Buffer _tVerts; private Buffer _tInds; private int _tCount; private VertexArray _tetraVao; private VertexArray _polyVao; private Buffer _pVerts; private Buffer _pEdges; private Buffer _pFaces; private Buffer _tEdges; private Buffer _tFaces; private bool _flat = false; private bool _tetra = true; private bool _pOutline = true; private bool _tOutline = true; private float _time; private void GenSphere(uint res) { var tv = new List(); var ns = new List(); tv.Add(new Vector3(0, 0, 0)); var c = res + 1; for (var p = 0; p <= res; p++) for (var t = 0; t <= res; t++) { var pp = Math.PI * p / res; var tt = Math.PI * 2 * t / res; tv.Add(new Vector3( (float) (Math.Sin(pp) * Math.Cos(tt)), (float) (Math.Sin(pp) * Math.Sin(tt)), (float) (Math.Cos(pp)) )); } for (uint i = 0; i < c - 1; i++) for (uint j = 0; j < c - 1; j++) { var k = 1 + i + j * c; ns.Add(0); ns.Add(k); ns.Add(k + 1); ns.Add(k + c); ns.Add(0); ns.Add(k + c + 1); ns.Add(k + 1); ns.Add(k + c); } if (_tVerts == null) _tVerts = new Buffer(); if (_tInds == null) _tInds = new Buffer(); _tVerts.SetData(tv.Select(v => new Vector4(v, 1)).ToArray()); _tInds.SetData(ns.ToArray()); _tCount = _tInds.Count / 4; } private void GenTorus(uint res, double a, double b) { var tv = new List(); var ns = new List(); for (uint t = 0; t <= res; t++) for (uint p = 0; p <= res; p++) { var tt = Math.PI * 2 * t / res; var pp = Math.PI * 2 * p / res; var v = new Vector3d( (a - b * Math.Cos(pp)) * Math.Cos(tt), (a - b * Math.Cos(pp)) * Math.Sin(tt), b * Math.Sin(pp) ); tv.Add((Vector3) v); } for (uint t = 0; t < res; t++) for (uint p = 1; p < res; p++) { var k = res + 1; ns.Add(t * k); ns.Add(t * k + p); ns.Add(t * k + p + 1); ns.Add(t * k + p + k); ns.Add(t * k); ns.Add(t * k + p + 1); ns.Add(t * k + p + k); ns.Add(t * k + p + k + 1); ns.Add(t * k); ns.Add(t * k + k); ns.Add(t * k + p + k); ns.Add(t * k + p + k + 1); } if (_tVerts == null) _tVerts = new Buffer(); if (_tInds == null) _tInds = new Buffer(); _tVerts.SetData(tv.Select(v => new Vector4(v, 1)).ToArray()); _tInds.SetData(ns.ToArray()); _tCount = _tInds.Count / 4; } protected override void OnLoad(EventArgs e) { base.OnLoad(e); X = (DisplayDevice.Default.Width - Width) / 2; Y = (DisplayDevice.Default.Height - Height) / 2; var vert = Shader.Compile("shaders/simple.vert"); var frag = Shader.Compile("shaders/simple.frag"); _render = Program.Link(vert, frag); var comp = Shader.Compile("shaders/intersect.comp"); _compute = Program.Link(comp); // GenSphere(20); GenTorus(20, 1, .5); _pVerts = new Buffer(_tCount * 4); _pEdges = new Buffer(_tCount * 8); _pFaces = new Buffer(_tCount * 6); _tEdges = new Buffer(_tCount * 12); _tFaces = new Buffer(_tCount * 12); _viewBuf = new Buffer(); _view = ViewMats.Identity; _tformBuf = new Buffer(); _tform = PlaneMats.Identity; GL.BindBufferBase(BufferRangeTarget.UniformBuffer, 0, _viewBuf); GL.UniformBlockBinding(_render, _render.UnifBlockInd("ViewMats"), 0); GL.BindBufferBase(BufferRangeTarget.UniformBuffer, 1, _tformBuf); GL.UniformBlockBinding(_compute, _compute.UnifBlockInd("PlaneMats"), 1); _tetraVao = new VertexArray(); _tetraVao.VertexPointer(_tVerts, index: _render.AttrLoc("pos"), size: 4); _polyVao = new VertexArray(); _polyVao.VertexPointer(_pVerts, index: _render.AttrLoc("pos"), size: 4); } protected override void OnRenderFrame(FrameEventArgs e) { base.OnRenderFrame(e); GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); GL.Viewport(ClientRectangle); GL.UseProgram(_render); if (_tetra) { GL.BindVertexArray(_tetraVao); GL.Disable(EnableCap.DepthTest); GL.BindBuffer(BufferTarget.ElementArrayBuffer, _tFaces); GL.Uniform3(_render.UnifLoc("color"), 1f, 1, 1); GL.DrawElements(BeginMode.Triangles, _tEdges.Count, DrawElementsType.UnsignedInt, 0); } GL.BindVertexArray(_polyVao); GL.Enable(EnableCap.DepthTest); GL.BindBuffer(BufferTarget.ElementArrayBuffer, _pFaces); GL.Uniform3(_render.UnifLoc("color"), .8f, .8f, .9f); GL.DrawElements(BeginMode.Triangles, _pFaces.Count, DrawElementsType.UnsignedInt, 0); if (_pOutline) { GL.BindVertexArray(_polyVao); GL.Disable(EnableCap.DepthTest); GL.BindBuffer(BufferTarget.ElementArrayBuffer, _pEdges); GL.Uniform3(_render.UnifLoc("color"), .1f, .1f, .6f); GL.DrawElements(BeginMode.Lines, _pEdges.Count, DrawElementsType.UnsignedInt, 0); } if (_tetra && _tOutline) { GL.BindVertexArray(_tetraVao); GL.Enable(EnableCap.DepthTest); GL.LineWidth(2f); GL.BindBuffer(BufferTarget.ElementArrayBuffer, _tEdges); GL.Uniform3(_render.UnifLoc("color"), 0f, 0, 0); GL.DrawElements(BeginMode.Lines, _tEdges.Count, DrawElementsType.UnsignedInt, 0); } GL.Flush(); SwapBuffers(); } protected override void OnUpdateFrame(FrameEventArgs e) { base.OnUpdateFrame(e); var dt = (float) e.Time; _time += dt; var dv = Matrix4.Identity; if (Keyboard[Key.LControl]) dt /= 4; if (Keyboard[Key.LShift]) { if (Keyboard[Key.Left]) dv *= Matrix4.CreateRotationZ(dt); if (Keyboard[Key.Right]) dv *= Matrix4.CreateRotationZ(-dt); if (Keyboard[Key.Up]) dv *= Matrix4.CreateRotationY(dt); if (Keyboard[Key.Down]) dv *= Matrix4.CreateRotationY(-dt); } else { if (Keyboard[Key.Left]) dv *= Matrix4.CreateRotationZ(dt); if (Keyboard[Key.Right]) dv *= Matrix4.CreateRotationZ(-dt); if (Keyboard[Key.Up]) dv *= Matrix4.CreateTranslation(-dt, 0, 0); if (Keyboard[Key.Down]) dv *= Matrix4.CreateTranslation(dt, 0, 0); } _tform.Tform *= dv; _view.Proj = Matrix4.CreateOrthographic(5, 5f * Height / Width, -2.5f, 2.5f); if (_flat) { _view.View = Matrix4.LookAt(Vector3.Zero, Vector3.UnitX, Vector3.UnitZ); _view.Model = _tform.Tform; } else { _view.View = Matrix4.LookAt(Vector3.Zero, -Vector3.One, Vector3.UnitZ); _view.Model = Matrix4.Identity; } _viewBuf.SetData(ref _view); _tformBuf.SetData(ref _tform); GL.UseProgram(_compute); GL.BindBufferBase(BufferRangeTarget.ShaderStorageBuffer, 0, _tVerts); GL.BindBufferBase(BufferRangeTarget.ShaderStorageBuffer, 1, _tInds); GL.BindBufferBase(BufferRangeTarget.ShaderStorageBuffer, 2, _pVerts); GL.BindBufferBase(BufferRangeTarget.ShaderStorageBuffer, 3, _pEdges); GL.BindBufferBase(BufferRangeTarget.ShaderStorageBuffer, 4, _pFaces); GL.BindBufferBase(BufferRangeTarget.ShaderStorageBuffer, 5, _tEdges); GL.BindBufferBase(BufferRangeTarget.ShaderStorageBuffer, 6, _tFaces); GL.DispatchCompute(_tCount, 1, 1); } protected override void OnKeyDown(KeyboardKeyEventArgs e) { base.OnKeyDown(e); switch (e.Key) { case Key.A: _flat = !_flat; break; case Key.S: _tetra = !_tetra; break; case Key.D: _pOutline = !_pOutline; break; case Key.F: _tOutline = !_tOutline; break; } } } }