Partial fix for Perspective projection
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
After Width: | Height: | Size: 209 KiB |
After Width: | Height: | Size: 209 KiB |
After Width: | Height: | Size: 120 KiB |
After Width: | Height: | Size: 120 KiB |
After Width: | Height: | Size: 120 KiB |
After Width: | Height: | Size: 120 KiB |
After Width: | Height: | Size: 77 KiB |
After Width: | Height: | Size: 77 KiB |
After Width: | Height: | Size: 60 KiB |
After Width: | Height: | Size: 60 KiB |
After Width: | Height: | Size: 60 KiB |
After Width: | Height: | Size: 60 KiB |
After Width: | Height: | Size: 89 KiB |
After Width: | Height: | Size: 89 KiB |
After Width: | Height: | Size: 66 KiB |
After Width: | Height: | Size: 66 KiB |
After Width: | Height: | Size: 66 KiB |
After Width: | Height: | Size: 66 KiB |