Partial fix for Perspective projection

This commit is contained in:
martin 2022-07-12 16:54:51 +02:00
parent 63361f6eed
commit df724fba93
28 changed files with 153 additions and 45 deletions

View File

@ -77,6 +77,12 @@ public class Coord3d implements Serializable {
y = yi;
z = zi;
}
public Coord3d(float xi, float yi) {
x = xi;
y = yi;
z = 0;
}
public Coord3d(Coord2d c, float zi) {
x = c.x;
@ -115,6 +121,12 @@ public class Coord3d implements Serializable {
z = (float) zi;
}
public Coord3d(double xi, double yi) {
x = (float) xi;
y = (float) yi;
z = 0;
}
public Coord3d set(Coord3d c2) {
x = c2.x;
y = c2.y;

View File

@ -1,6 +1,9 @@
package org.jzy3d.plot3d.builder;
import java.util.ArrayList;
import java.util.List;
import org.jzy3d.colors.Color;
import org.jzy3d.maths.Coord3d;
import org.jzy3d.maths.Range;
import org.jzy3d.plot2d.primitives.LineSerie2d;
import org.jzy3d.plot2d.primitives.LineSerie2dSplitted;
@ -55,4 +58,33 @@ public class SerieBuilder {
else
throw new IllegalArgumentException("Unsupported serie type " + type);
}
public List<Coord3d> apply(Func2D func, Range xRange, int steps) {
return apply(func, xRange, steps, true, true);
}
public List<Coord3d> apply(Func2D func, Range xRange, int steps, boolean includeXMin, boolean includeXMax) {
List<Coord3d> out = new ArrayList<>();
double step = xRange.getRange() / steps;
for (double x = xRange.getMin(); x <= xRange.getMax(); x += step) {
// shift lower bound
if(!includeXMin && x==xRange.getMin()) {
out.add(new Coord3d(x+Double.MIN_VALUE, func.f(x+Double.MIN_VALUE)));
}
// shift upper bound
else if(!includeXMax && x==xRange.getMax()) {
out.add(new Coord3d(x-Double.MIN_VALUE, func.f(x-Double.MIN_VALUE)));
}
else {
out.add(new Coord3d(x, func.f(x)));
}
}
return out;
}
}

View File

@ -31,6 +31,16 @@ public class Composite extends Wireframeable implements ISingleColorable, IMulti
components = new ArrayList<Drawable>();
}
public Composite(List<Drawable> drawables) {
this();
add(drawables);
}
public Composite(Drawable... drawables) {
this();
add(drawables);
}
/**
* This indicate to a scene graph if the Composite consider it is worth being decomposed or not.
*
@ -49,6 +59,15 @@ public class Composite extends Wireframeable implements ISingleColorable, IMulti
}
}
public void add(Drawable[] drawables) {
synchronized (components) {
for(Drawable d: drawables) {
components.add(d);
}
}
}
/** Clear the list of Drawables from this composite. */
public void clear() {
synchronized (components) {

View File

@ -76,7 +76,7 @@ public class CoplanarityManager extends Drawable implements IGLBindedResource {
// Set stencil op to set 1 if depth passes, 0 if it fails
painter.glStencilOp(StencilOp.GL_KEEP, StencilOp.GL_ZERO, StencilOp.GL_REPLACE);
// Draw the base polygons
// Draw the base polygons that should be covered by outlines
plane.draw(painter);
// Set stencil function to pass when stencil is 1

View File

@ -640,16 +640,29 @@ public class Camera extends AbstractViewportManager {
* @see {@link #projectionOrtho(IPainter, ViewportConfiguration)}
*/
public void projectionPerspective(IPainter painter, ViewportConfiguration viewport) {
boolean stretchToFill = ViewportMode.STRETCH_TO_FILL.equals(viewport.getMode());
double fov = computeFieldOfView(renderingSphereRadius * 2, eye.distance(target));
float aspect = stretchToFill ? ((float) screenWidth) / ((float) screenHeight) : 1;
float nearCorrected = near <= 0 ? 0.000000000000000000000000000000000000001f : near;
// easier perspective processing
if(perspectiveProjectionUseFrustrum) {
float r = renderingSphereRadius / (painter.getView().getFactorViewPointDistance());
painter.glFrustum(-r, r, -r, r, near, far);
}
// former perspective processing
else {
boolean stretchToFill = ViewportMode.STRETCH_TO_FILL.equals(viewport.getMode());
double fov = computeFieldOfView(renderingSphereRadius * 4, eye.distance(target));
float aspect = stretchToFill ? ((float) screenWidth) / ((float) screenHeight) : 1;
float nearCorrected = near <= 0 ? Float.MIN_VALUE : near;
painter.gluPerspective(fov / 1, aspect * 0.55, nearCorrected, far);
// painter.glFrustum(-radius*3, radius*3, -radius*3, radius*3, near, far);
painter.gluPerspective(fov / 1, aspect * 0.55, nearCorrected, far);
}
}
protected boolean perspectiveProjectionUseFrustrum = true;
public void doLookAt(IPainter painter) {
//System.out.println("Camera.LookAt : " + target + " FROM " + eye);

View File

@ -911,22 +911,16 @@ public class View {
/* CAMERA PROCESSING */
public void updateCamera(ViewportConfiguration viewport, BoundingBox3d boundsScaled) {
float sceneRadius = (float) boundsScaled.getRadius() * factorViewPointDistance;
updateCamera(viewport, boundsScaled, sceneRadius);
updateCamera(viewport, boundsScaled, viewMode, viewpoint, cam, cameraMode, factorViewPointDistance,
center, scaling);
}
public void updateCamera(ViewportConfiguration viewport, BoundingBox3d bounds,
float sceneRadiusScaled) {
updateCamera(viewport, bounds, sceneRadiusScaled, viewMode, viewpoint, cam, cameraMode,
factorViewPointDistance, center, scaling);
}
ViewPositionMode viewmode, Coord3d viewpoint, Camera cam, CameraMode cameraMode,
float factorViewPointDistance, Coord3d center, Coord3d scaling) {
public void updateCamera(ViewportConfiguration viewport, BoundingBox3d bounds,
float sceneRadiusScaled, ViewPositionMode viewmode, Coord3d viewpoint, Camera cam,
CameraMode cameraMode, float factorViewPointDistance, Coord3d center, Coord3d scaling) {
updateCameraWithoutShooting(viewport, bounds, sceneRadiusScaled, viewmode, viewpoint, cam,
factorViewPointDistance, center, scaling);
updateCameraWithoutShooting(viewport, bounds, viewmode, viewpoint, cam, factorViewPointDistance,
center, scaling);
triggerCameraUpEvents(viewpoint);
@ -942,11 +936,12 @@ public class View {
* that are invoked by shoot method.
*/
public void updateCameraWithoutShooting(ViewportConfiguration viewport, BoundingBox3d bounds,
float sceneRadiusScaled, ViewPositionMode viewmode, Coord3d viewpoint, Camera cam,
float factorViewPointDistance, Coord3d center, Coord3d scaling) {
ViewPositionMode viewmode, Coord3d viewpoint, Camera cam, float factorViewPointDistance,
Coord3d center, Coord3d scaling) {
viewpoint.z = computeViewpointDistance(bounds, sceneRadiusScaled, factorViewPointDistance);
viewpoint.z = computeViewpointDistance(bounds, factorViewPointDistance);
Coord3d cameraTarget = computeCameraTarget(center, scaling);
Coord3d cameraUp = computeCameraUp(viewpoint);
Coord3d cameraEye = computeCameraEye(cameraTarget, viewmode, viewpoint);
@ -957,9 +952,16 @@ public class View {
}
public float computeViewpointDistance(BoundingBox3d bounds, float sceneRadiusScaled,
public float computeViewpointDistance(BoundingBox3d bounds,
float factorViewPointDistance) {
return (float) spaceTransformer.compute(bounds).getRadius();
float v;
if (spaceTransformer == null) {
v = (float) bounds.getRadius();
} else {
v = (float) spaceTransformer.compute(bounds).getRadius();
}
return v * factorViewPointDistance;
}
protected Coord3d computeCameraTarget() {
@ -1004,6 +1006,8 @@ public class View {
protected Coord3d computeCameraEyeFree(Coord3d viewpoint, Coord3d target) {
//System.out.println("View : " + viewpoint.z);
return viewpoint.cartesian().add(target);
}
@ -1686,6 +1690,14 @@ public class View {
public boolean isMaintainAllObjectsInView() {
return maintainAllObjectsInView;
}
public float getFactorViewPointDistance() {
return factorViewPointDistance;
}
public void setFactorViewPointDistance(float factorViewPointDistance) {
this.factorViewPointDistance = factorViewPointDistance;
}
public void setMaintainAllObjectsInView(boolean maintainAllObjectsInView) {
this.maintainAllObjectsInView = maintainAllObjectsInView;

View File

@ -10,6 +10,7 @@ import org.jzy3d.mocks.jzy3d.Mocks;
import org.jzy3d.painters.IPainter;
import org.jzy3d.plot3d.rendering.view.modes.CameraMode;
import org.jzy3d.plot3d.rendering.view.modes.ProjectionMode;
import org.mockito.Mockito;
public class TestCamera {
Random r = new Random();
@ -95,6 +96,7 @@ public class TestCamera {
camera.setUp(camera.getEye().add(0, 0, 1));
IPainter painter = Mocks.Painter();
Mockito.when(painter.getView()).thenReturn(Mocks.View());
// --------------------------------------------
// When configuring a rendering sphere

View File

@ -253,34 +253,43 @@ public class TestView {
// When 2D XY, with decreasing X
viewLayout.setHorizontalAxisFlip(true);
viewLayout.setVerticalAxisFlip(false);
view.setViewPositionMode(ViewPositionMode.TOP);
view.shoot();
// Then
Assert.assertEquals(new Coord3d(0,1,0), view.getCamera().getUp());
Assert.assertEquals(View.AZIMUTH_FACING_X_DECREASING, view.getViewPoint().x, 0.001);
Assert.assertEquals(View.ELEVATION_ON_BOTTOM, view.getViewPoint().y, 0.001);
// When 2D XY, with decreasing Y
viewLayout.setHorizontalAxisFlip(false);
viewLayout.setVerticalAxisFlip(true);
viewLayout.setVerticalAxisFlip(true);
view.setViewPositionMode(ViewPositionMode.TOP);
view.shoot();
// Then
Assert.assertEquals(new Coord3d(0,-1,0), view.getCamera().getUp());
Assert.assertEquals(View.AZIMUTH_FACING_X_INCREASING, view.getViewPoint().x, 0.001);
Assert.assertEquals(View.ELEVATION_ON_BOTTOM, view.getViewPoint().y, 0.001);
// -----------------------------------------------------------
// When 2D XZ
viewLayout.setHorizontalAxisFlip(false);
viewLayout.setVerticalAxisFlip(false);
view.setViewPositionMode(ViewPositionMode.XZ);
view.shoot();
// Then
Assert.assertEquals(new Coord3d(0,0,1), view.getCamera().getUp());
// -----------------------------------------------------------
// When 2D YZ
viewLayout.setHorizontalAxisFlip(false);
viewLayout.setVerticalAxisFlip(false);
view.setViewPositionMode(ViewPositionMode.YZ);
view.shoot();

View File

@ -342,15 +342,17 @@ public class ChartTester {
doHighlightPixels(expected, diff, highlight);
}
expected.getSubimage(minX, minY, maxX - minX, maxY - minY);
Graphics2D g2d = (Graphics2D) expected.createGraphics();
g2d.setColor(java.awt.Color.RED);
g2d.setStroke(new BasicStroke(1f));
g2d.drawRect(minX, minY, maxX - minX, maxY - minY);
System.err
.println("Erroneous Area : x[" + minX + ", " + maxX + "] y[" + minY + " " + maxY + "]");
if(minX<=maxX && minY<=maxY) {
//expected.getSubimage(minX, minY, maxX - minX, maxY - minY);
Graphics2D g2d = (Graphics2D) expected.createGraphics();
g2d.setColor(java.awt.Color.RED);
g2d.setStroke(new BasicStroke(1f));
g2d.drawRect(minX, minY, maxX - minX, maxY - minY);
System.err
.println("Erroneous Area : x[" + minX + ", " + maxX + "] y[" + minY + " " + maxY + "]");
}
}
@ -393,10 +395,17 @@ public class ChartTester {
maxY = diff.y;
}
System.err
.println("Erroneous Area : x[" + minX + ", " + maxX + "] y[" + minY + " " + maxY + "]");
return expected.getSubimage(minX, minY, maxX - minX, maxY - minY);
if(minX<=maxX && minY<=maxY) {
System.err
.println("Erroneous Area : x[" + minX + ", " + maxX + "] y[" + minY + " " + maxY + "]");
return expected.getSubimage(minX, minY, maxX - minX, maxY - minY);
}
else {
return expected;
}
}

View File

@ -115,7 +115,7 @@ This is a summary of existing baseline images for tests, which was generated on
<td></td>
<td></td>
<td></td>
<td></td>
<td>Diff chart:<br><img src="target/error-Text_whenDrawableTextRenderer_EmulGL_AWT_HiDPI=ON_DIFF.png"><br>Actual chart:<br><img src="target/error-Text_whenDrawableTextRenderer_EmulGL_AWT_HiDPI=ON_ACTUAL.png"><br>Zoom on error:<br><img src="target/error-Text_whenDrawableTextRenderer_EmulGL_AWT_HiDPI=ON_ZOOM.png"><br>Following tests of the same section have been skipped.</td>
<td></td>
</tr>
</table>
@ -143,7 +143,7 @@ This is a summary of existing baseline images for tests, which was generated on
<td></td>
<td></td>
<td></td>
<td></td>
<td>Diff chart:<br><img src="target/error-AxisLabelRotateLayout_EmulGL_AWT_HiDPI=ON_DIFF.png"><br>Actual chart:<br><img src="target/error-AxisLabelRotateLayout_EmulGL_AWT_HiDPI=ON_ACTUAL.png"><br>Zoom on error:<br><img src="target/error-AxisLabelRotateLayout_EmulGL_AWT_HiDPI=ON_ZOOM.png"><br>Following tests of the same section have been skipped.</td>
<td></td>
</tr>
</table>
@ -632,7 +632,7 @@ This is a summary of existing baseline images for tests, which was generated on
<td><img src="src/test/resources/macosx_11.4_AppleM1/2D_when2DLayoutConfig_ThenApplyMargins_EmulGL_AWT_HiDPI=OFF_BorderMargin=0_TickLabel=10_AxisLabel=10_TextAddMargin=true.png"></td>
</tr>
<tr>
<td></td>
<td>Diff chart:<br><img src="target/error-2D_when2DLayoutConfig_ThenApplyMargins_Native_AWT_HiDPI=ON_BorderMargin=0_TickLabel=10_AxisLabel=10_TextAddMargin=true_DIFF.png"><br>Actual chart:<br><img src="target/error-2D_when2DLayoutConfig_ThenApplyMargins_Native_AWT_HiDPI=ON_BorderMargin=0_TickLabel=10_AxisLabel=10_TextAddMargin=true_ACTUAL.png"><br>Zoom on error:<br><img src="target/error-2D_when2DLayoutConfig_ThenApplyMargins_Native_AWT_HiDPI=ON_BorderMargin=0_TickLabel=10_AxisLabel=10_TextAddMargin=true_ZOOM.png"><br>Following tests of the same section have been skipped.</td>
<td></td>
<td></td>
<td></td>
@ -793,7 +793,7 @@ This is a summary of existing baseline images for tests, which was generated on
<td></td>
<td></td>
<td></td>
<td></td>
<td>Diff chart:<br><img src="target/error-2D_whenAxisRotated_ThenApplyMargins_EmulGL_AWT_HiDPI=ON_yAxisOrientation=VERTICAL_DIFF.png"><br>Actual chart:<br><img src="target/error-2D_whenAxisRotated_ThenApplyMargins_EmulGL_AWT_HiDPI=ON_yAxisOrientation=VERTICAL_ACTUAL.png"><br>Zoom on error:<br><img src="target/error-2D_whenAxisRotated_ThenApplyMargins_EmulGL_AWT_HiDPI=ON_yAxisOrientation=VERTICAL_ZOOM.png"><br>Following tests of the same section have been skipped.</td>
<td></td>
</tr>
</table>

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB