diff --git a/jzy3d-core/src/main/java/org/jzy3d/plot3d/primitives/Wireframeable.java b/jzy3d-core/src/main/java/org/jzy3d/plot3d/primitives/Wireframeable.java index e3e1ed57..dc5f4bb2 100644 --- a/jzy3d-core/src/main/java/org/jzy3d/plot3d/primitives/Wireframeable.java +++ b/jzy3d-core/src/main/java/org/jzy3d/plot3d/primitives/Wireframeable.java @@ -170,5 +170,5 @@ public abstract class Wireframeable extends Drawable { * no z-fighting occurs between faces and lines. In case of higher value, line * will be display more often, but also lines that should be behind the polygon */ - protected float NO_OVERLAP_DEPTH_RATIO = 0.1f;//0.1f; + public static float NO_OVERLAP_DEPTH_RATIO = 0.1f;//0.1f; } diff --git a/jzy3d-core/src/main/java/org/jzy3d/plot3d/primitives/axis/AxisBox.java b/jzy3d-core/src/main/java/org/jzy3d/plot3d/primitives/axis/AxisBox.java index 0620077e..1416d5df 100644 --- a/jzy3d-core/src/main/java/org/jzy3d/plot3d/primitives/axis/AxisBox.java +++ b/jzy3d-core/src/main/java/org/jzy3d/plot3d/primitives/axis/AxisBox.java @@ -81,6 +81,15 @@ public class AxisBox implements IAxis { public static final int AXE_X = 0; public static final int AXE_Y = 1; public static final int AXE_Z = 2; + + protected boolean depthRangeTrick = true; + + /** + * The higher the value, the more the line are far from the faces and hence + * no z-fighting occurs between faces and lines. In case of higher value, line + * will be display more often, but also lines that should be behind the polygon + */ + public static float NO_OVERLAP_DEPTH_RATIO = 0.5f; protected List annotations = new ArrayList(); @@ -177,7 +186,8 @@ public class AxisBox implements IAxis { // Push far from camera, to ensure the axis grid // Will remain covered by surface - painter.glDepthRangef(0.5f, 1); + if(depthRangeTrick) + painter.glDepthRangef(NO_OVERLAP_DEPTH_RATIO, 1f); painter.glPolygonMode(PolygonMode.BACK, PolygonFill.LINE); @@ -199,7 +209,9 @@ public class AxisBox implements IAxis { // Reset depth range - painter.glDepthRangef(0f, 1); + + if(depthRangeTrick) + painter.glDepthRangef(0f, 1f); } diff --git a/jzy3d-emul-gl/src/test/java/org/jzy3d/emulgl/opengl/TestDepthRange.java b/jzy3d-emul-gl/src/test/java/org/jzy3d/emulgl/opengl/TestDepthRange.java new file mode 100644 index 00000000..86ccba52 --- /dev/null +++ b/jzy3d-emul-gl/src/test/java/org/jzy3d/emulgl/opengl/TestDepthRange.java @@ -0,0 +1,134 @@ +package org.jzy3d.emulgl.opengl; + +import org.junit.Test; +import org.jzy3d.chart.Chart; +import org.jzy3d.chart.factories.EmulGLChartFactory; +import org.jzy3d.colors.Color; +import org.jzy3d.colors.ColorMapper; +import org.jzy3d.colors.colormaps.ColorMapRainbow; +import org.jzy3d.maths.Range; +import org.jzy3d.painters.IPainter; +import org.jzy3d.plot3d.builder.Mapper; +import org.jzy3d.plot3d.builder.SurfaceBuilder; +import org.jzy3d.plot3d.builder.concrete.OrthonormalGrid; +import org.jzy3d.plot3d.primitives.Shape; +import org.jzy3d.plot3d.primitives.Wireframeable; +import org.jzy3d.plot3d.primitives.axis.AxisBox; +import org.jzy3d.plot3d.rendering.canvas.Quality; +import org.jzy3d.utils.LoggerUtils; +import static org.mockito.Mockito.*; + +/** + * {@AxisBox} and + * @author martin + * + */ +public class TestDepthRange { + @Test + public void whenRenderAxis_DepthRangeModifiedByAxis() { + LoggerUtils.minimal(); + + // When + EmulGLChartFactory factory = new EmulGLChartFactory(); + Chart chart = factory.newChart(Quality.Advanced()); + + Shape surface = surface(); + chart.add(surface); + + IPainter painter = spy(chart.getView().getPainter()); + + // ---------------------------------------------- + // Then surface will NOT update depth range + + surface.setPolygonWireframeDepthTrick(false); + surface.draw(painter); + + verify(painter, never()).glDepthRangef(0, 1); + + // ---------------------------------------------- + // Then axis will update depth range + + chart.getView().getAxis().draw(painter); + + // Called that way to push the depth range farther + verify(painter, atLeast(1)).glDepthRangef(AxisBox.NO_OVERLAP_DEPTH_RATIO, 1); + + // Called that way for reset + verify(painter, atLeast(1)).glDepthRangef(0, 1); + } + + @Test + public void whenRenderSurface_DepthRangeModifiedBySurface() { + LoggerUtils.minimal(); + + // When + EmulGLChartFactory factory = new EmulGLChartFactory(); + Chart chart = factory.newChart(Quality.Advanced()); + + Shape surface = surface(); + chart.add(surface); + + IPainter painter = spy(chart.getView().getPainter()); + + // ---------------------------------------------- + // Then surface will NOT update depth range + + surface.setPolygonWireframeDepthTrick(false); + surface.draw(painter); + + verify(painter, never()).glDepthRangef(0, 1); + + // ---------------------------------------------- + // Then surface WILL update depth range + + surface.setPolygonWireframeDepthTrick(true); + surface.draw(painter); + + // config for face + verify(painter, atLeast(1)).glDepthRangef(0, 1-Wireframeable.NO_OVERLAP_DEPTH_RATIO); + // config for wireframe + verify(painter, atLeast(1)).glDepthRangef(Wireframeable.NO_OVERLAP_DEPTH_RATIO, 1); + // back to default config + verify(painter, atLeast(1)).glDepthRangef(0, 1); + + + // ---------------------------------------------- + // Then axis will update depth range + + chart.getView().getAxis().draw(painter); + + // Called that way to push the depth range farther + verify(painter, atLeast(1)).glDepthRangef(AxisBox.NO_OVERLAP_DEPTH_RATIO, 1); + + // Called that way for reset + verify(painter, atLeast(1)).glDepthRangef(0, 1); + } + + + + private static Shape surface() { + Mapper mapper = new Mapper() { + @Override + public double f(double x, double y) { + return x * Math.sin(x * y); + } + }; + Range range = new Range(-3, 3); + int steps = 50; + + SurfaceBuilder builder = new SurfaceBuilder(); + Shape surface = builder.orthonormal(new OrthonormalGrid(range, steps, range, steps), mapper); + + ColorMapper colorMapper = new ColorMapper(new ColorMapRainbow(), surface.getBounds().getZmin(), + surface.getBounds().getZmax(), new Color(1, 1, 1, ALPHA_FACTOR)); + surface.setColorMapper(colorMapper); + surface.setFaceDisplayed(true); + surface.setWireframeDisplayed(true); + surface.setWireframeColor(Color.BLACK); + return surface; + } + + static final float ALPHA_FACTOR = 0.75f; + + +}