protected void ShowCore(FrameEventArgs e) { // workspace viewport GL.Viewport((int)(0.25 * Width), 0, (int)(0.75 * Width), Height); GL.Enable(EnableCap.DepthTest); // TODO: fix depth test so that it doesn't hide objects behind alpha-fragments // clearing viewport GL.Enable(EnableCap.ScissorTest); GL.Scissor((int)(0.25 * Width), 0, (int)(0.75 * Width), Height); GL.ClearColor(0.2f, 0.3f, 0.3f, 1.0f); GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit | ClearBufferMask.StencilBufferBit); GL.Disable(EnableCap.ScissorTest); // attaching shader _shader.Use(); // set view and projection matrices; // these matrices come pre-transposed, so there's no need to transpose them again (see VertexShader file) _shader.SetMatrix4("view", _camera.GetViewMatrix(), false); _shader.SetMatrix4("projection", _camera.GetProjectionMatrix(), false); // set general properties _shader.SetVector3("viewPos", _camera.Position); // set directional light properties _shader.SetVector3("dirLight[0].direction", new Vector3(1.0f, 0.0f, 0.0f)); _shader.SetVector3("dirLight[1].direction", new Vector3(0.0f, -1.0f, 0.0f)); _shader.SetVector3("dirLight[2].direction", new Vector3(0.0f, 0.0f, -1.0f)); for (int i = 0; i < 3; i++) { _shader.SetVector3($"dirLight[{i}].ambient", new Vector3(0.05f, 0.05f, 0.05f)); _shader.SetVector3($"dirLight[{i}].diffuse", new Vector3(0.75f, 0.75f, 0.75f)); _shader.SetVector3($"dirLight[{i}].specular", new Vector3(0.5f, 0.5f, 0.5f)); } // setup line shader lineShader.Use(); lineShader.SetMatrix4("view", _camera.GetViewMatrix(), false); lineShader.SetMatrix4("projection", _camera.GetProjectionMatrix(), false); lineShader.SetVector3("color", Vector3.One); Matrix4 model; if (ManipLoaded) { // obstacles & colliders if (obstacles.Contains(null)) { for (int i = 0; i < obstacles.Length; i++) { obstacles[i] = new Entity(lineShader, GL_Convert(Manager.Obstacles[i].Data, Vector4.One)); switch (Manager.Obstacles[i].Collider.Shape) { case ColliderShape.Box: boundings[i] = new Entity(lineShader, GL_Convert(Manager.Obstacles[i].Collider.Data, new Vector4(Vector3.UnitY, 1.0f)), new uint[] { 0, 1, 2, 3, 0, 4, 5, 1, 5, 6, 2, 6, 7, 3, 7, 4 }); break; case ColliderShape.Sphere: boundings[i] = new Entity(lineShader, GL_Convert(Manager.Obstacles[i].Collider.Data, new Vector4(Vector3.UnitY, 1.0f))); lon[i] = new Entity(lineShader, GL_Convert(Manager.Obstacles[i].Collider.Data, new Vector4(Vector3.UnitY, 1.0f)), ((Sphere)Manager.Obstacles[i].Collider).indicesLongitude); break; } } } else { float dt; if (forward) { dt = (float)e.Time; if (time > 1) { forward = false; } } else { dt = -(float)e.Time; if (time < -1) { forward = true; } } time += dt; model = Matrix4.Identity * Matrix4.CreateTranslation(time, 0, 0); for (int i = 0; i < obstacles.Length; i++) { Manager.Obstacles[i].Move(Vector3.UnitX, dt); obstacles[i].Display(model, () => { GL.DrawArrays(PrimitiveType.Points, 0, Manager.Obstacles[i].Data.Length); }); if (Dispatcher.WorkspaceBuffer.ObstBuffer[i].ShowBounding) { boundings[i].Display(model, Manager.Obstacles[i].Collider.Draw); lon[i].Display(model, ((Sphere)Manager.Obstacles[i].Collider).DrawLongitudes); } } } for (int j = 0; j < Manager.Manipulators.Length; j++) { Manipulator manip = Manager.Manipulators[j]; // goal if (goal[j] == null) { if (manip.States["Goal"]) { List <Vector3> MainAttr = new List <Vector3> { manip.GoodAttractors[0].Center }; MainAttr.AddRange(manip.GoodAttractors[0].Area); goal[j] = new Entity(lineShader, GL_Convert(MainAttr.ToArray(), new Vector4(1.0f, 1.0f, 0.0f, 1.0f))); } } else { model = Matrix4.Identity; goal[j].Display(model, () => { GL.PointSize(5); GL.DrawArrays(PrimitiveType.Points, 0, 1); GL.PointSize(1); GL.DrawArrays(PrimitiveType.Points, 1, manip.GoodAttractors[0].Area.Length); }); } // path if (manip.States["Path"] && manip.Path != null) { int count = manip.Path.Count; path[j] = new Entity(lineShader, GL_Convert(manip.Path.ToArray(), new Vector4(Vector3.UnitX, 1.0f))); model = Matrix4.Identity; path[j].Display(model, () => { GL.DrawArrays(PrimitiveType.LineStrip, 0, count); }); } // random tree if (manip.Tree != null) { // block the manager thread while updating tree Dispatcher.ThreadHandle.Reset(); // add all elements from addition buffer to the hash set var add = new List <Logic.PathPlanning.Tree.Node>(manip.Tree.AddBuffer); tree[j].UnionWith(add); manip.Tree.AddBuffer.Clear(); // delete all elements contained in deletion buffer from the hash set var del = new List <Logic.PathPlanning.Tree.Node>(manip.Tree.DelBuffer); tree[j].ExceptWith(del); manip.Tree.DelBuffer.Clear(); // unblock the manager thread to continue calculations Dispatcher.ThreadHandle.Set(); } if (Dispatcher.WorkspaceBuffer.JointBuffer[j].ShowTree) { model = Matrix4.Identity; foreach (var node in tree[j]) { if (node.Entity == null) { node.Entity = CreateTreeBranch(node.p, node.Parent.p); } node.Entity.Display(model, () => { GL.DrawArrays(PrimitiveType.LineStrip, 0, 2); }); } } // draw manipulator configuration if its model is loaded properly if (ManipLoaded) { manip.Draw(_shader); } } } // workspace grid model = Matrix4.Identity; grid.Display(model, () => { GL.DrawArrays(PrimitiveType.LineStrip, 0, 2); GL.DrawArrays(PrimitiveType.LineStrip, 2, 2); }); for (int i = 1; i < 11; i++) { model = Matrix4.CreateTranslation(Vector3.UnitZ * i); grid.Display(model, () => { GL.DrawArrays(PrimitiveType.LineStrip, 0, 2); }); model = Matrix4.CreateTranslation(Vector3.UnitZ * -i); grid.Display(model, () => { GL.DrawArrays(PrimitiveType.LineStrip, 0, 2); }); model = Matrix4.CreateTranslation(Vector3.UnitX * i); grid.Display(model, () => { GL.DrawArrays(PrimitiveType.LineStrip, 2, 2); }); model = Matrix4.CreateTranslation(Vector3.UnitX * -i); grid.Display(model, () => { GL.DrawArrays(PrimitiveType.LineStrip, 2, 2); }); } model = Matrix4.Identity; gridFloor.Display(model, () => { // the workspace grid rendering is done lastly, because it's common to render all transparent objects at last // // the blending function is determined as follows: // Color = SourceColor * SourceFactor + DestColor * DestFactor, // where // SourceColor - color of the currently rendering fragment, // SourceFactor - its factor, // DestColor - color of the already rendered fragment (the one in the color buffer), // DestFactor - its factor. // // so, to render transparent floor, we take SourceFactor as source's alpha (floor's alpha) and DestFactor as the remainder of the source's alpha // (the visible amount of the opaque object behind the floor) GL.Enable(EnableCap.Blend); GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); GL.DrawElements(BeginMode.Triangles, 7, DrawElementsType.UnsignedInt, 0); GL.Disable(EnableCap.Blend); }); //ImGui.ShowDemoWindow(); base.OnRenderFrame(e); }