Simplify class structure and (WIP) enable screenshots for peeling charts

This commit is contained in:
martin 2021-12-06 19:10:55 +01:00
parent 867041a8c6
commit caa111d121
17 changed files with 95 additions and 273 deletions

View File

@ -1,36 +1,35 @@
package org.jzy3d.factories;
import org.jzy3d.chart.factories.AWTChartFactory;
import org.jzy3d.chart.factories.IChartFactory;
import org.jzy3d.chart.factories.IPainterFactory;
import org.jzy3d.plot3d.rendering.canvas.ICanvas;
import org.jzy3d.plot3d.rendering.canvas.Quality;
import org.jzy3d.plot3d.rendering.ddp.DepthPeelingView;
import org.jzy3d.plot3d.rendering.ddp.algorithms.PeelingMethod;
import org.jzy3d.plot3d.rendering.ordering.AbstractOrderingStrategy;
import org.jzy3d.plot3d.rendering.scene.Graph;
import org.jzy3d.plot3d.rendering.scene.Scene;
import org.jzy3d.plot3d.rendering.view.View;
/**
* The sole purpose of this factory is to disable sorting drawable by scene's {@link Graph} since
* depth peeling make it useless. This is only to improve performances.
*
* Using this factory is not a requirement. It remains possible to enable depth peeling with any native chart factory, e.g. :
*
* <code>
* AWTChartFactory f = new AWTChartFactory(new DepthPeelingPainterFactory());
* Chart chart = f.newChart();
* </code>
*/
public class DepthPeelingChartFactory extends AWTChartFactory {
public DepthPeelingChartFactory() {
this(PeelingMethod.DUAL_PEELING_MODE);
this(new DepthPeelingPainterFactory());
}
public DepthPeelingChartFactory(PeelingMethod method) {
super(new DepthPeelingPainterFactory());
this.method = method;
}
public DepthPeelingChartFactory(IPainterFactory painterFactory, PeelingMethod method) {
public DepthPeelingChartFactory(IPainterFactory painterFactory) {
super(painterFactory);
this.method = method;
}
@Override
public View newView(IChartFactory factory, Scene scene, ICanvas canvas, Quality quality) {
return new DepthPeelingView(factory, scene, canvas, quality);
public Graph newGraph(Scene scene, AbstractOrderingStrategy strategy, boolean sort) {
Graph graph = super.newGraph(scene, strategy, sort);
graph.setSort(false);
return graph;
}
public static boolean CHART_CANVAS_AUTOSWAP = false;
PeelingMethod method;
}

View File

@ -2,13 +2,14 @@ package org.jzy3d.factories;
import org.jzy3d.chart.factories.AWTPainterFactory;
import org.jzy3d.plot3d.rendering.ddp.DepthPeelingRenderer3d;
import org.jzy3d.plot3d.rendering.ddp.DepthPeelingView;
import org.jzy3d.plot3d.rendering.ddp.algorithms.PeelingMethod;
import org.jzy3d.plot3d.rendering.view.Renderer3d;
import org.jzy3d.plot3d.rendering.view.View;
import com.jogamp.opengl.GLCapabilities;
public class DepthPeelingPainterFactory extends AWTPainterFactory {
protected PeelingMethod peelingMethod = PeelingMethod.DUAL_PEELING_MODE;
public DepthPeelingPainterFactory() {
super();
}
@ -20,9 +21,16 @@ public class DepthPeelingPainterFactory extends AWTPainterFactory {
@Override
public Renderer3d newRenderer3D(View view) {
PeelingMethod method = ((DepthPeelingChartFactory) getChartFactory()).method;
DepthPeelingRenderer3d r =
new DepthPeelingRenderer3d(method, (DepthPeelingView) view, traceGL, debugGL);
return r;
return new DepthPeelingRenderer3d(peelingMethod, view, traceGL, debugGL);
}
public PeelingMethod getPeelingMethod() {
return peelingMethod;
}
public void setPeelingMethod(PeelingMethod peelingMethod) {
this.peelingMethod = peelingMethod;
}
}

View File

@ -1,63 +0,0 @@
package org.jzy3d.plot3d.rendering.ddp;
import org.apache.log4j.Logger;
import org.jzy3d.chart.Chart;
import org.jzy3d.chart.factories.IChartFactory;
import org.jzy3d.factories.DepthPeelingChartFactory;
import org.jzy3d.io.glsl.GLSLProgram;
import org.jzy3d.io.glsl.GLSLProgram.Strictness;
import org.jzy3d.plot3d.rendering.canvas.Quality;
import org.jzy3d.plot3d.rendering.ddp.algorithms.PeelingMethod;
import com.jogamp.opengl.GLProfile;
public class DepthPeelingChart extends Chart {
public DepthPeelingChart(IChartFactory factory, Quality quality) {
super(factory, quality);
}
static Logger LOGGER = Logger.getLogger(DepthPeelingChart.class);
public static Chart get(Quality quality, String chartType) {
return get(quality, chartType, PeelingMethod.DUAL_PEELING_MODE);
}
public static Chart get(Quality quality, String chartType, PeelingMethod method) {
return get(quality, chartType, method, Strictness.CONSOLE_NO_WARN_UNIFORM_NOT_FOUND);
}
public static Chart get(Quality quality, String chartType, PeelingMethod method,
Strictness strictness) {
return get(quality, chartType, method, strictness, true);
}
public static Chart get(Quality quality, String chartType, final PeelingMethod method,
Strictness strictness, boolean editFactories) {
GLSLProgram.DEFAULT_STRICTNESS = strictness;
IChartFactory factory = new DepthPeelingChartFactory(method);
LOGGER.info("is available GL2 : " + GLProfile.isAvailable(GLProfile.GL2));
LOGGER.info("is available GL3 : " + GLProfile.isAvailable(GLProfile.GL3));
LOGGER.info("is available GL4 : " + GLProfile.isAvailable(GLProfile.GL4));
GLProfile profile = GLProfile.get(GLProfile.GL4);
// GL2
// GLProfile profile = GLProfile.get(GLProfile.GL2);
// GLSLProgram: ERROR: 0:10: 'DepthTex' : syntax error: syntax error
// GLProfile.get(GLProfile.GL4bc);
LOGGER.info(profile);
// GLCapabilities capabilities = new GLCapabilities(profile);
// capabilities.setHardwareAccelerated(true);
Chart chart = new DepthPeelingChart(factory, quality);
chart.getView().setSquared(false);
chart.getView().setAxisDisplayed(true);
return chart;
}
}

View File

@ -9,6 +9,7 @@ import org.jzy3d.plot3d.rendering.ddp.algorithms.IDepthPeelingAlgorithm;
import org.jzy3d.plot3d.rendering.ddp.algorithms.PeelingMethod;
import org.jzy3d.plot3d.rendering.ddp.algorithms.WeightedAveragePeelingAlgorithm;
import org.jzy3d.plot3d.rendering.ddp.algorithms.WeightedSumPeelingAlgorithm;
import org.jzy3d.plot3d.rendering.view.AWTRenderer3d;
import org.jzy3d.plot3d.rendering.view.Renderer3d;
import org.jzy3d.plot3d.rendering.view.View;
import com.jogamp.opengl.GL2;
@ -37,18 +38,18 @@ import com.jogamp.opengl.glu.GLU;
* @author Louis Bavoil - original paper and C++ code
* @author Martin Pernollet - port to Jzy3d
*/
public class DepthPeelingRenderer3d extends Renderer3d {
public class DepthPeelingRenderer3d extends AWTRenderer3d {
protected Logger LOGGER = Logger.getLogger(DepthPeelingRenderer3d.class);
protected IDepthPeelingAlgorithm dualPeelingAlgorithm;
protected boolean autoSwapBuffer = false;
protected GLU glu = new GLU();
public DepthPeelingRenderer3d(final DepthPeelingView view, boolean traceGL, boolean debugGL) {
public DepthPeelingRenderer3d(final View view, boolean traceGL, boolean debugGL) {
this(PeelingMethod.WEIGHTED_AVERAGE_MODE, view, traceGL, debugGL);
}
public DepthPeelingRenderer3d(PeelingMethod algorithm, final DepthPeelingView view,
public DepthPeelingRenderer3d(PeelingMethod algorithm, final View view,
boolean traceGL, boolean debugGL) {
super(view, traceGL, debugGL);
dualPeelingAlgorithm = getDepthPeelingAlgorithm(algorithm);
@ -75,23 +76,24 @@ public class DepthPeelingRenderer3d extends Renderer3d {
GL2 gl = getGL2(drawable);
preDisplay(gl);
dualPeelingAlgorithm.display(view.getPainter(), gl, glu); // will call taskToRender
postDisplay(gl);
if(view!=null) {
view.clear();
dualPeelingAlgorithm.display(view.getPainter(), gl, glu); // will call taskToRender
view.renderOverlay();
renderScreenshotIfRequired(gl);
if (!autoSwapBuffer)
drawable.swapBuffers();
}
if (!autoSwapBuffer)
drawable.swapBuffers();
}
public void postDisplay(GL2 gl) {
view.renderOverlay();
}
public void preDisplay(GL2 gl) {
((DepthPeelingView) view).clearPeeledView(gl, glu, width, height);
}
public static IGLRenderer getDepthPeelingContentRenderer(final View view) {
return new IGLRenderer() {
@ -116,6 +118,7 @@ public class DepthPeelingRenderer3d extends Renderer3d {
if (this.width != width || this.height != height) {
this.width = width;
this.height = height;
dualPeelingAlgorithm.reshape(view.getPainter(), gl, width, height);
}
}

View File

@ -1,52 +0,0 @@
package org.jzy3d.plot3d.rendering.ddp;
import org.jzy3d.chart.factories.IChartFactory;
import org.jzy3d.plot3d.rendering.canvas.ICanvas;
import org.jzy3d.plot3d.rendering.canvas.Quality;
import org.jzy3d.plot3d.rendering.scene.Scene;
import org.jzy3d.plot3d.rendering.view.AWTView;
import org.jzy3d.plot3d.rendering.view.ViewportConfiguration;
import com.jogamp.opengl.GL;
import com.jogamp.opengl.glu.GLU;
/**
* {@link DepthPeelingRenderer3d} needs to split calls to view clear and view renderer.
* {@link DepthPeelingView} facilitate to perform this with two separate method that replace
* view.renderScene(gl, glu, viewport);
*
* @author Martin
*
*/
public class DepthPeelingView extends AWTView {
public DepthPeelingView(IChartFactory factory, Scene scene, ICanvas canvas, Quality quality) {
super(factory, scene, canvas, quality);
}
public void clearPeeledView(GL gl, GLU glu, int width, int height) {
// decompose super.display, i.e. prevent to render scenegraph now,
// and delegate to peeling algorithm
synchronized (this) {
clear();
// render background
renderBackground(0f, 1f);
// fix quality
updateQuality();
// prepare viewport
this.width = width;
this.height = height;
}
}
protected int width = 0;
protected int height = 0;
public void renderPeeledView() {
updateCamera(new ViewportConfiguration(width, height), computeScaledViewBounds());
renderAxeBox();
renderSceneGraph(false);
}
}

View File

@ -40,7 +40,7 @@ public class DualDepthPeelingAlgorithm extends AbstractDepthPeelingAlgorithm
@Override
public void display(IPainter painter, GL2 gl, GLU glu) {
resetNumPass();
renderDualPeeling(painter, gl);
doRender(painter, gl);
}
@Override
@ -190,7 +190,7 @@ public class DualDepthPeelingAlgorithm extends AbstractDepthPeelingAlgorithm
gl.glDeleteTextures(1, g_dualBackBlenderTexId, 0);
}
protected void renderDualPeeling(IPainter painter, GL2 gl) {
protected void doRender(IPainter painter, GL2 gl) {
gl.glDisable(GL2.GL_DEPTH_TEST);
gl.glEnable(GL2.GL_BLEND);

View File

@ -46,7 +46,7 @@ public class FrontToBackPeelingAlgorithm extends AbstractDepthPeelingAlgorithm
@Override
public void display(IPainter painter, GL2 gl, GLU glu) {
resetNumPass();
renderFrontToBackPeeling(painter, gl);
doRender(painter, gl);
}
@Override
@ -158,7 +158,7 @@ public class FrontToBackPeelingAlgorithm extends AbstractDepthPeelingAlgorithm
gl.glDeleteTextures(1, g_frontColorBlenderTexId, 0);
}
protected void renderFrontToBackPeeling(IPainter painter, GL2 gl) {
protected void doRender(IPainter painter, GL2 gl) {
// ---------------------------------------------------------------------
// 1. Initialize Min Depth Buffer
// ---------------------------------------------------------------------

View File

@ -26,7 +26,7 @@ public class WeightedAveragePeelingAlgorithm extends AbstractAccumulationDepthPe
@Override
public void display(IPainter painter, GL2 gl, GLU glu) {
resetNumPass();
renderAverageColors(painter, gl);
doRender(painter, gl);
}
/* */
@ -58,7 +58,7 @@ public class WeightedAveragePeelingAlgorithm extends AbstractAccumulationDepthPe
glslFinal.destroy(gl);
}
protected void renderAverageColors(IPainter painter, GL2 gl) {
protected void doRender(IPainter painter, GL2 gl) {
gl.glDisable(GL2.GL_DEPTH_TEST);
// ---------------------------------------------------------------------

View File

@ -1,9 +1,8 @@
package org.jzy3d.demos.ddp;
import org.jzy3d.chart.Chart;
import org.jzy3d.chart.factories.NativePainterFactory;
import org.jzy3d.chart.factories.AWTChartFactory;
import org.jzy3d.colors.Color;
import org.jzy3d.factories.DepthPeelingChartFactory;
import org.jzy3d.factories.DepthPeelingPainterFactory;
import org.jzy3d.maths.BoundingBox3d;
import org.jzy3d.maths.Coord3d;
@ -11,11 +10,7 @@ import org.jzy3d.plot3d.primitives.ParallelepipedComposite;
import org.jzy3d.plot3d.primitives.ParallelepipedComposite.PolygonType;
import org.jzy3d.plot3d.primitives.PolygonMode;
import org.jzy3d.plot3d.rendering.canvas.CanvasAWT;
import org.jzy3d.plot3d.rendering.canvas.Quality;
import org.jzy3d.plot3d.rendering.ddp.algorithms.PeelingMethod;
import com.jogamp.opengl.GLCapabilities;
import com.jogamp.opengl.GLContext;
import com.jogamp.opengl.GLProfile;
import com.jogamp.opengl.awt.GLCanvas;
/**
@ -35,7 +30,7 @@ import com.jogamp.opengl.awt.GLCanvas;
public class PeeledCubesDemo {
public static void main(String[] args) throws InterruptedException {
DepthPeelingChartFactory f = new DepthPeelingChartFactory();
AWTChartFactory f = new AWTChartFactory(new DepthPeelingPainterFactory());
Chart chart = f.newChart();

View File

@ -1,82 +0,0 @@
package org.jzy3d.demos.ddp;
import org.jzy3d.chart.Chart;
import org.jzy3d.colors.Color;
import org.jzy3d.maths.BoundingBox3d;
import org.jzy3d.maths.Coord3d;
import org.jzy3d.plot3d.primitives.ParallelepipedComposite;
import org.jzy3d.plot3d.primitives.ParallelepipedComposite.PolygonType;
import org.jzy3d.plot3d.primitives.PolygonMode;
import org.jzy3d.plot3d.rendering.canvas.Quality;
import org.jzy3d.plot3d.rendering.ddp.DepthPeelingChart;
import org.jzy3d.plot3d.rendering.ddp.algorithms.PeelingMethod;
/**
*
*
*
* -------------------------
* no pb avec simple polygon:
* <li>gl.glPolygonMode(GL2.GL_FRONT_AND_BACK, GL2.GL_FILL);
* <li>gl.glEnable(GL2.GL_POLYGON_OFFSET_FILL);
*
* Probleme avec polygon normal > probleme enleve si p1.setWireframeDisplayed(false); > l'ordre dans
* le scene graph n'a pas l'air d'avoir d'impact
*
* Probleme avec simple polygon qd create stack avant ou apres
*
*
* Dans la vue decomposee renderer.display, le rendering devient tres lent si
* view.renderOverlay(gl); n'est pas appele
*/
public class PeeledCubesDemoOld {
public static void main(String[] args) {
Chart chart = DepthPeelingChart.get(Quality.Fastest(), "awt", PeelingMethod.WEIGHTED_SUM_MODE);
chart.getView().setAxisDisplayed(false);
chart.setAnimated(false);
createStack(chart, 0.01f, 0.01f, Coord3d.ORIGIN, Color.BLUE /* no alpha */, Color.BLACK);
createStack(chart, 0.01f, 0.01f, new Coord3d(0.005f, 0.005f, 0.005f),
new Color(1f, 0f, 0f, 0.5f), Color.BLACK);
createStack(chart, 0.01f, 0.01f, new Coord3d(0.01f, 0.01f, 0.01f), new Color(0f, 1f, 0f, 0.5f),
Color.BLACK);
chart.open(800, 600);
chart.getMouse();
String info = chart.getCanvas().getDebugInfo();
if(!info.contains("ARB_texture_rectangle")) {
System.out.println(info);
}
else {
System.out.println("ARB_texture_rectangle is here!!!");
}
if(!info.contains("ARB_draw_buffers")) {
System.out.println(info);
}
else {
System.out.println("ARB_draw_buffers is here!!!");
}
}
public static void createStack(Chart chart, float width, float height, Coord3d position,
Color face, Color wireframe) {
BoundingBox3d bounds =
new BoundingBox3d(position.x - width / 2, position.x + width / 2, position.y - width / 2,
position.y + width / 2, position.z - height / 2, position.z + height / 2);
ParallelepipedComposite p1 = new ParallelepipedComposite(bounds, PolygonType.SIMPLE);
p1.setPolygonMode(PolygonMode.FRONT_AND_BACK);
p1.setPolygonOffsetFill(true);
p1.setColor(face);
p1.setWireframeColor(wireframe);
p1.setWireframeDisplayed(true);
chart.getScene().add(p1);
}
}

View File

@ -6,6 +6,7 @@ import org.jzy3d.chart.factories.AWTChartFactory;
import org.jzy3d.colors.Color;
import org.jzy3d.debugGL.tracers.DebugGLChart3d;
import org.jzy3d.factories.DepthPeelingChartFactory;
import org.jzy3d.factories.DepthPeelingPainterFactory;
import org.jzy3d.io.obj.OBJFileLoader;
import org.jzy3d.maths.Coord3d;
import org.jzy3d.maths.Rectangle;
@ -22,7 +23,8 @@ public class PeeledDragonDemo {
public static void main(String[] args) {
System.err.println("May require vm argument -Xmx1024m");
DepthPeelingChartFactory f = new DepthPeelingChartFactory();
AWTChartFactory f = new AWTChartFactory(new DepthPeelingPainterFactory());
Chart chart = f.newChart();
String objFilePath = "data/models/dragon.obj";

View File

@ -1,8 +1,10 @@
package org.jzy3d.demos.ddp;
import org.jzy3d.chart.Chart;
import org.jzy3d.chart.factories.AWTChartFactory;
import org.jzy3d.colors.Color;
import org.jzy3d.factories.DepthPeelingChartFactory;
import org.jzy3d.factories.DepthPeelingPainterFactory;
import org.jzy3d.maths.BoundingBox3d;
import org.jzy3d.maths.Coord3d;
import org.jzy3d.plot3d.primitives.Cylinder;
@ -20,7 +22,8 @@ public class PeeledStackDemo {
public static void main(String[] args) {
DepthPeelingChartFactory f = new DepthPeelingChartFactory();
AWTChartFactory f = new AWTChartFactory(new DepthPeelingPainterFactory());
Chart chart = f.newChart(Quality.Nicest());

View File

@ -2,6 +2,7 @@ package org.jzy3d.demos.ddp;
import org.jzy3d.chart.Chart;
import org.jzy3d.chart.ChartLauncher;
import org.jzy3d.chart.factories.AWTChartFactory;
import org.jzy3d.chart.factories.NativePainterFactory;
import org.jzy3d.colors.Color;
import org.jzy3d.colors.ColorMapper;
@ -45,10 +46,7 @@ public class PeeledWireSurfaceDemo {
surface.setWireframeColor(Color.BLACK);
// Create a chart and add surface
GLProfile profile = GLProfile.get(GLProfile.GL2); // GL4bcImpl fail to downcast to GL2 on Mac
GLCapabilities caps = NativePainterFactory.getDefaultCapabilities(profile);
DepthPeelingPainterFactory p = new DepthPeelingPainterFactory(caps);
DepthPeelingChartFactory f = new DepthPeelingChartFactory(p, PeelingMethod.DUAL_PEELING_MODE);
AWTChartFactory f = new AWTChartFactory(new DepthPeelingPainterFactory());
Chart chart = f.newChart(Quality.Advanced().setAlphaActivated(false));
chart.getScene().getGraph().add(surface);

View File

@ -2,8 +2,9 @@ package org.jzy3d.plot3d.rendering.ddp.algorithms;
import org.junit.Test;
import org.jzy3d.chart.Chart;
import org.jzy3d.chart.factories.AWTChartFactory;
import org.jzy3d.colors.Color;
import org.jzy3d.factories.DepthPeelingChartFactory;
import org.jzy3d.factories.DepthPeelingPainterFactory;
import org.jzy3d.junit.ChartTester;
import org.jzy3d.junit.NativeChartTester;
import org.jzy3d.maths.BoundingBox3d;
@ -16,7 +17,8 @@ public class TestDualDepthPeelingAlgorithm {
@Test
public void whenTranslucentIntersectingCube_ThenOrderIndependentAlphaIsProcessed() throws InterruptedException {
DepthPeelingChartFactory f = new DepthPeelingChartFactory(PeelingMethod.DUAL_PEELING_MODE);
AWTChartFactory f = new AWTChartFactory(new DepthPeelingPainterFactory());
//f.getPainterFactory().setOffscreen(600, 600);
Chart chart = f.newChart();

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -32,14 +32,19 @@ public class AWTRenderer3d extends Renderer3d {
view.clear();
view.render();
if (doScreenshotAtNextDisplay) {
AWTGLReadBufferUtil screenshot = new AWTGLReadBufferUtil(GLProfile.getGL2GL3(), true);
screenshot.readPixels(gl, true);
image = screenshot.getTextureData();
bufferedImage = screenshot.readPixelsToBufferedImage(gl, true);
renderScreenshotIfRequired(gl);
}
}
doScreenshotAtNextDisplay = false;
}
@Override
protected void renderScreenshotIfRequired(GL gl) {
if (doScreenshotAtNextDisplay) {
AWTGLReadBufferUtil screenshot = new AWTGLReadBufferUtil(GLProfile.getGL2GL3(), true);
screenshot.readPixels(gl, true);
image = screenshot.getTextureData();
bufferedImage = screenshot.readPixelsToBufferedImage(gl, true);
doScreenshotAtNextDisplay = false;
}
}

View File

@ -93,12 +93,7 @@ public class Renderer3d implements GLEventListener {
view.clear();
view.render();
if (doScreenshotAtNextDisplay) {
GLReadBufferUtil screenshot = new GLReadBufferUtil(false, false);
screenshot.readPixels(gl, true);
image = screenshot.getTextureData();
doScreenshotAtNextDisplay = false;
}
renderScreenshotIfRequired(gl);
}
profileDisplayTimer.toc();
@ -106,6 +101,15 @@ public class Renderer3d implements GLEventListener {
}
protected void renderScreenshotIfRequired(GL gl) {
if (doScreenshotAtNextDisplay) {
GLReadBufferUtil screenshot = new GLReadBufferUtil(false, false);
screenshot.readPixels(gl, true);
image = screenshot.getTextureData();
doScreenshotAtNextDisplay = false;
}
}
/** Called when the {@link GLAutoDrawable} is resized. */
@Override
public void reshape(GLAutoDrawable canvas, int x, int y, int width, int height) {