public void Viewport_Paint() { if (SurfaceMesh != null) { Vector3[] Bounds = SurfaceMesh.BoundingBoxCorners; Matrix4 ViewMatrix = Viewport.Camera.GetView(); float MinDist = float.MaxValue; float MaxDist = -float.MaxValue; foreach (var corner in Bounds) { float Dist = -Vector3.Transform(corner, ViewMatrix).Z; MinDist = Math.Min(MinDist, Dist); MaxDist = Math.Max(MaxDist, Dist); } MainWindow.Options.Viewport.Camera.ClipNear = Math.Max(1f, MinDist / 2); MainWindow.Options.Viewport.Camera.ClipFar = Math.Max(2f, MaxDist * 2); } MeshProgram.Use(); { MeshProgram.SetUniform("worldViewProjMatrix", MainWindow.Options.Viewport.Camera.GetViewProj()); MeshProgram.SetUniform("surfaceOffset", (float)SurfaceOffset * MainWindow.Options.PixelScale.X); if (TomogramTexture != null) { MeshProgram.SetUniform("useVolume", 1f); MeshProgram.SetUniform("volScale", OpenGLHelper.Reciprocal(TomogramTexture.Scale)); MeshProgram.SetUniform("volOffset", TomogramTexture.Offset); MeshProgram.SetUniform("texSize", OpenGLHelper.Reciprocal(TomogramTexture.Size)); GL.ActiveTexture(TextureUnit.Texture0); GL.BindTexture(TextureTarget.Texture3D, TomogramTexture.Handle); } else { MeshProgram.SetUniform("useVolume", 0f); } GL.ActiveTexture(TextureUnit.Texture1); GL.BindTexture(TextureTarget.Texture2D, SelectionTexture.Handle); float TraceStart = TraceDepthOffset; float TraceLength = TraceDepth; MeshProgram.SetUniform("traceParams", new Vector2(TraceStart, TraceLength)); MeshProgram.SetUniform("traceSharpening", (float)TraceSharpening / 100f); float RangeMin = (float)Math.Min(OutputRangeMin, OutputRangeMax), RangeMax = (float)Math.Max(OutputRangeMin, OutputRangeMax); MeshProgram.SetUniform("normalizeParams", new Vector2(RangeMin, RangeMax - RangeMin)); Vector3 LightDirection = MainWindow.Options.Viewport.Camera.GetDirection(); MeshProgram.SetUniform("lightDirection", LightDirection); MeshProgram.SetUniform("lightIntensity", OutputLight / 100f); if (SurfaceMesh != null) { SurfaceMesh.Draw(); } } // Draw point groups. There are 3 options for depiction: // - Boxes with custom size // - Same mesh for every point in a group, e. g. protein map from EMDB // - Individual mesh for every point in a group, e. g. isosurface within its enclosed volume { List <PointGroup> AllGroups = new List <PointGroup>(PointGroups); AllGroups.Add(PreviewGroup); foreach (PointGroup group in AllGroups.Where(g => g.IsVisible && g.Points.Count > 0)) { if (group.Depiction == PointDepiction.Box) { // Draw orientation gizmos PointGizmoProgram.Use(); PointGizmoProgram.SetUniform("worldViewProjMatrix", MainWindow.Options.Viewport.Camera.GetViewProj()); GL.LineWidth(10f); PointGizmoProgram.SetUniform("cubeSize", (float)group.Size * MainWindow.Options.PixelScale.X); group.PointCloud.Draw(); // Draw boxes PointProgram.Use(); PointProgram.SetUniform("worldViewProjMatrix", MainWindow.Options.Viewport.Camera.GetViewProj()); // Draw back faces first, then front, to ensure correct transparency (locally) GL.Enable(EnableCap.CullFace); GL.CullFace(CullFaceMode.Front); PointProgram.SetUniform("cubeSize", (float)group.Size * MainWindow.Options.PixelScale.X); group.PointCloud.Draw(); GL.CullFace(CullFaceMode.Back); PointProgram.SetUniform("cubeSize", (float)group.Size * MainWindow.Options.PixelScale.X); group.PointCloud.Draw(); GL.Disable(EnableCap.CullFace); } else if (group.Depiction == PointDepiction.Mesh) { PointModelProgram.Use(); PointModelProgram.SetUniform("modelColor", ColorHelper.ColorToVector(group.Color, true)); PointModelProgram.SetUniform("cameraDirection", Viewport.Camera.GetDirection()); foreach (var point in group.Points) { PointModelProgram.SetUniform("isSelected", point.IsSelected ? 1f : 0f); Vector3 Offset = point.TransformedMatrix.Column2 * (float)group.DepictionMeshOffset; PointModelProgram.SetUniform("worldViewProjMatrix", Matrix4.CreateTranslation(point.Position + Offset) * MainWindow.Options.Viewport.Camera.GetViewProj()); PointModelProgram.SetUniform("rotationMatrix", Matrix3.Transpose(point.TransformedMatrix)); group.DepictionMesh?.Draw(); } } else if (group.Depiction == PointDepiction.LocalSurface) { PointModelProgram.Use(); PointModelProgram.SetUniform("modelColor", ColorHelper.ColorToVector(group.Color, true)); PointModelProgram.SetUniform("cameraDirection", Viewport.Camera.GetDirection()); foreach (var point in group.Points) { PointModelProgram.SetUniform("isSelected", point.IsSelected ? 1f : 0f); PointModelProgram.SetUniform("worldViewProjMatrix", Matrix4.CreateTranslation(point.Position) * MainWindow.Options.Viewport.Camera.GetViewProj()); PointModelProgram.SetUniform("rotationMatrix", Matrix3.Identity); point.DepictionMesh?.Draw(); } // Also draw the orientation stick if (KeyboardHelper.CtrlDown()) { PointGizmoProgram.Use(); PointGizmoProgram.SetUniform("worldViewProjMatrix", MainWindow.Options.Viewport.Camera.GetViewProj()); GL.LineWidth(10f); PointGizmoProgram.SetUniform("cubeSize", (float)group.Size * MainWindow.Options.PixelScale.X); group.PointCloud.Draw(); } } } } }
private void Viewport_Paint() { lock (RenderSync) { Viewport.MakeCurrent(); Membrane.MeshProgram.Use(); { Membrane.MeshProgram.SetUniform("worldViewProjMatrix", Viewport.Camera.GetViewProj()); Membrane.MeshProgram.SetUniform("surfaceOffset", (float)SurfaceOffset * MainWindow.Options.PixelScale.X); if (Membrane.TomogramTexture != null) { Membrane.MeshProgram.SetUniform("useVolume", 1f); Membrane.MeshProgram.SetUniform("volScale", OpenGLHelper.Reciprocal(Membrane.TomogramTexture.Scale)); Membrane.MeshProgram.SetUniform("volOffset", Membrane.TomogramTexture.Offset); Membrane.MeshProgram.SetUniform("texSize", OpenGLHelper.Reciprocal(Membrane.TomogramTexture.Size)); GL.ActiveTexture(TextureUnit.Texture0); GL.BindTexture(TextureTarget.Texture3D, Membrane.TomogramTexture.Handle); } else { Membrane.MeshProgram.SetUniform("useVolume", 0f); } GL.ActiveTexture(TextureUnit.Texture1); GL.BindTexture(TextureTarget.Texture2D, Membrane.SelectionTexture.Handle); float TraceStart = TraceDepthOffset; float TraceLength = TraceDepth; Membrane.MeshProgram.SetUniform("traceParams", new Vector2(TraceStart, TraceLength)); Membrane.MeshProgram.SetUniform("traceSharpening", (float)TraceSharpening / 100f); float RangeMin = (float)Math.Min(OutputRangeMin, OutputRangeMax), RangeMax = (float)Math.Max(OutputRangeMin, OutputRangeMax); Membrane.MeshProgram.SetUniform("normalizeParams", new Vector2(RangeMin, RangeMax - RangeMin)); Vector3 LightDirection = Viewport.Camera.GetDirection(); Membrane.MeshProgram.SetUniform("lightDirection", LightDirection); Membrane.MeshProgram.SetUniform("lightIntensity", 0.0f); SurfaceMesh?.Draw(); } Membrane.PointProgram.Use(); { Membrane.PointProgram.SetUniform("worldViewProjMatrix", MainWindow.Options.Viewport.Camera.GetViewProj()); // Draw back faces first, then front, to ensure correct transparency (locally) GL.Enable(EnableCap.CullFace); GL.CullFace(CullFaceMode.Front); foreach (PointGroup group in PointGroups.Where(g => g.IsVisible && g.Points.Count > 0)) { Membrane.PointProgram.SetUniform("cubeSize", (float)group.Size * MainWindow.Options.PixelScale.X); group.PointCloud.Draw(); } GL.CullFace(CullFaceMode.Back); foreach (PointGroup group in PointGroups.Where(g => g.IsVisible && g.Points.Count > 0)) { Membrane.PointProgram.SetUniform("cubeSize", (float)group.Size * MainWindow.Options.PixelScale.X); group.PointCloud.Draw(); } GL.Disable(EnableCap.CullFace); } } }