package org.geogebra.common.geogebra3D.euclidian3D.draw; import org.geogebra.common.euclidian.EuclidianController; import org.geogebra.common.geogebra3D.euclidian3D.EuclidianView3D; import org.geogebra.common.geogebra3D.euclidian3D.Hitting; import org.geogebra.common.geogebra3D.euclidian3D.openGL.Manager; import org.geogebra.common.geogebra3D.euclidian3D.openGL.PlotterSurface; import org.geogebra.common.geogebra3D.euclidian3D.openGL.Renderer; import org.geogebra.common.geogebra3D.kernel3D.geos.GeoTriangulatedSurface3D; import org.geogebra.common.geogebra3D.kernel3D.geos.GeoTriangulatedSurface3D.SurfaceMover; import org.geogebra.common.geogebra3D.kernel3D.geos.GeoTriangulatedSurface3D.Triangle; import org.geogebra.common.geogebra3D.kernel3D.implicit3D.GeoImplicitSurface; import org.geogebra.common.kernel.geos.GeoElement; import org.geogebra.common.util.MyMath; /** * * @author Shamshad Alam * */ public class DrawImplicitSurface3D extends Drawable3DSurfaces { /** * create a new {@link DrawImplicitSurface3D} object * * @param a_view3d * {@link EuclidianView3D} * @param a_geo * {@link GeoElement} */ public DrawImplicitSurface3D(EuclidianView3D a_view3d, GeoImplicitSurface a_geo) { super(a_view3d, a_geo); } @Override void drawGeometryHiding(Renderer renderer) { drawSurfaceGeometry(renderer); } @Override protected void drawSurfaceGeometry(Renderer renderer) { renderer.getGeometryManager().draw(getSurfaceIndex()); } @Override public void drawGeometry(Renderer renderer) { renderer.getGeometryManager().draw(getGeometryIndex()); } @Override public void drawGeometryHidden(Renderer renderer) { drawSurfaceGeometry(renderer); } @Override public void drawOutline(Renderer renderer) { drawGeometry(renderer); } @Override protected boolean updateForItSelf() { GeoImplicitSurface geo = (GeoImplicitSurface) getGeoElement(); EuclidianView3D v3d = getView3D(); geo.updateSurface(new double[] { v3d.getXmin(), v3d.getXmax(), v3d.getYmin(), v3d.getYmax(), v3d.getZmin(), v3d.getZmax(), v3d.getXscale(), v3d.getYscale(), v3d.getZscale() }); GeoTriangulatedSurface3D surf = geo.getSurface3D(); SurfaceMover surfaceMover = surf.getSurfaceMover(); if (!surfaceMover.hasNext()) { setSurfaceIndex(-1); setGeometryIndex(-1); return true; } Manager m = getView3D().getRenderer().getGeometryManager(); PlotterSurface s = m.getSurface(); s.start(getReusableSurfaceIndex()); s.startTriangles(); while (surfaceMover.hasNext()) { Triangle tri = surfaceMover.next(); s.triangle(tri.v1, tri.v2, tri.v3, tri.n1, tri.n2, tri.n3); } s.endGeometry(); setSurfaceIndex(s.end()); return true; } @Override protected void updateForView() { if (getView3D().viewChangedByTranslate() || getView3D().viewChangedByZoom()) { setWaitForUpdate(); } } // @Override // public void addToDrawable3DLists(Drawable3DLists lists) { // super.addToDrawable3DLists(lists, DRAW_TYPE_CLIPPED_SURFACES); // } // // @Override // public void removeFromDrawable3DLists(Drawable3DLists lists) { // super.removeFromDrawable3DLists(lists, DRAW_TYPE_CLIPPED_SURFACES); // } @Override public int getPickOrder() { return DRAW_PICK_ORDER_SURFACE; } @Override public boolean hit(Hitting hitting) { if (waitForReset) { // prevent NPE return false; } if (getGeoElement() .getAlphaValue() < EuclidianController.MIN_VISIBLE_ALPHA_VALUE) { return false; } GeoImplicitSurface gs = (GeoImplicitSurface) this.getGeoElement(); hitting.calculateClippedValues(); if (Double.isNaN(hitting.x0)) { // hitting doesn't intersect // clipping box return false; } double v0 = gs.evaluateAt(hitting.x0, hitting.y0, hitting.z0); double v1 = gs.evaluateAt(hitting.x1, hitting.y1, hitting.z1); if (MyMath.changedSign(v0, v1)) { return true; } for (int i = 0; i < hitTestParams.length; i++) { double p = hitTestParams[i]; double q = 1 - p; v1 = gs.evaluateAt(hitting.x1 * p + hitting.x0 * q, hitting.y1 * p + hitting.y0 * q, hitting.z1 * p + hitting.z0 * q); if (MyMath.changedSign(v0, v1)) { return true; } } return false; } private final static double[] hitTestParams = new double[] { 0.5, 0.25, 0.75, 0.125, 0.375, 0.625, 0.875 }; }