shadows are lost while Java3D 1.5.2 to 1.7.0 migration

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

shadows are lost while Java3D 1.5.2 to 1.7.0 migration

questioning
Strange behavior was appeared while migrating from Java3D 1.5.2 to 1.7.0.

Looks like shadows are lost in new version of Java3D:

the first picture created with Java3D 1.5.2 (based on j3dcore-ogl.dll)


the second picture created with Java3D 1.7.0 (based on gluegen-rt-2.3.2.jar and jogl-all-2.3.2.jar)


The same code was used for both cases.

Why does it happen?
I can't believe that this hard downgrade is possible, may be some configurations should be change etc.
Reply | Threaded
Open this post in threaded view
|

Re: shadows are lost while Java3D 1.5.2 to 1.7.0 migration

philjord
Hi,
You are right, this shouldn't be the case.

Is it possible to send some example code, I imaine there is just some fairly simple config type issue.

I the second image there looks like not lighting at all, and the base materials are being rendered.

Might be as simple as the lighting enabled flag on the material being default to off for some reason.
Reply | Threaded
Open this post in threaded view
|

Re: shadows are lost while Java3D 1.5.2 to 1.7.0 migration

questioning
Hello @philjord
Code (imports for Java3D 1.7.0):

    import org.jogamp.java3d.*;
    import org.jogamp.java3d.utils.behaviors.keyboard.KeyNavigatorBehavior;
    import org.jogamp.java3d.utils.behaviors.mouse.MouseRotate;
    import org.jogamp.java3d.utils.behaviors.mouse.MouseWheelZoom;
    import org.jogamp.java3d.utils.geometry.GeometryInfo;
    import org.jogamp.java3d.utils.geometry.NormalGenerator;
    import org.jogamp.java3d.utils.universe.PlatformGeometry;
    import org.jogamp.java3d.utils.universe.SimpleUniverse;
    import org.jogamp.vecmath.*;

    import javax.swing.*;
    import java.awt.*;
    import java.util.ArrayList;
   
    public class Plate {

        int jagged;
        private SimpleUniverse universe = null;
        private Canvas3D canvas = null;
        private TransformGroup viewtrans = null;

        private TransformGroup tg = null;
        private Transform3D t3d = null;
        private JPanel canvasPanel;

        public Plate() {
            canvasPanel = new JPanel(new BorderLayout());
            JFrame f = new JFrame();
            f.setLayout(new BorderLayout());
            JPanel p = new JPanel(new BorderLayout());
            p.add(BorderLayout.CENTER, canvasPanel);
            f.add(p, BorderLayout.CENTER);
            f.setSize(500, 500);
            f.setVisible(true);

        }

        public static void main(String[] args) {
            new Plate().paint3D();
        }

        public void paint3D() {
            set3dLoadedStatus();
            Runnable runnable = new Runnable() {
                public void run() {
                    try {
                        GraphicsConfiguration config = SimpleUniverse
                                .getPreferredConfiguration();

                        canvas = new Canvas3D(config);

                        universe = new SimpleUniverse(canvas);


                        universe.getViewingPlatform().setNominalViewingTransform();

                        universe.getViewer().getView().setBackClipDistance(10.0);

                        BranchGroup scene = new BranchGroup();

                        BoundingSphere bounds = new BoundingSphere(new Point3d(), 10000.0);

                        viewtrans = universe.getViewingPlatform().getViewPlatformTransform();

                        KeyNavigatorBehavior keyNavBeh = new KeyNavigatorBehavior(viewtrans);
                        keyNavBeh.setSchedulingBounds(bounds);
                        PlatformGeometry platformGeom = new PlatformGeometry();
                        platformGeom.addChild(keyNavBeh);
                        universe.getViewingPlatform().setPlatformGeometry(platformGeom);

                        BranchGroup objRoot = new BranchGroup();
                        objRoot.setCapability(BranchGroup.ALLOW_DETACH);
                        objRoot.setCapability(BranchGroup.ALLOW_CHILDREN_WRITE);
                        objRoot.setCapability(BranchGroup.ALLOW_CHILDREN_READ);
                        tg = new TransformGroup();
                        t3d = new Transform3D();

                        tg.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);

                        t3d.setTranslation(new Vector3d(-0.15, -0.3, -5.0));
                        t3d.setRotation(new AxisAngle4f(1f, 1f, 1f, 1f));
                        t3d.setScale(getInitialScale());

                        tg.setTransform(t3d);


                        objRoot.addChild(tg);



                        int jagged = getJagged();
                        double[] rectDip = getRectDip();

                        int boxX = 16;

                        createVoxelizedShape(tg, boxX, jagged, rectDip);

                        float directionalPower = 0.55f;

                        final Color3f color3f = new Color3f(directionalPower, directionalPower, directionalPower);

                        DirectionalLight directionalLight = new DirectionalLight(true, color3f, new Vector3f(-0.3f, 0.2f, -1.0f));

                        directionalLight.setInfluencingBounds(new BoundingSphere(new Point3d(), 10000.0));

                        objRoot.addChild(directionalLight);


                        AmbientLight ambientLight = new AmbientLight(true, new Color3f(1f - directionalPower, 1f - directionalPower, 1f - directionalPower));

                        ambientLight.setInfluencingBounds(new BoundingSphere(new Point3d(), 10000.0));

                        objRoot.addChild(ambientLight);


                        MouseRotate myMouseRotate = new MouseRotate();
                        myMouseRotate.setTransformGroup(tg);
                        myMouseRotate.setSchedulingBounds(new BoundingSphere());
                        objRoot.addChild(myMouseRotate);

                        MouseWheelZoom mouseWheelZoom = new MouseWheelZoom();
                        mouseWheelZoom.setTransformGroup(tg);
                        mouseWheelZoom.setSchedulingBounds(tg.getBounds());
                        objRoot.addChild(mouseWheelZoom);
                        objRoot.compile();

                        scene.addChild(objRoot);

                        Background background = new Background();
                        background.setColor(getBackgroundColor());
                        background.setApplicationBounds(bounds);
                        scene.addChild(background);
                        universe.addBranchGraph(scene);

                        SwingUtilities.invokeLater(() -> {
                            try {
                                canvasPanel.removeAll();
                                canvasPanel.add(canvas);
                                canvasPanel.repaint();
                                canvasPanel.revalidate();

                            } catch (Exception e) {
                                set3dLoadedStatus("<html>ERROR: " + e.getMessage() + "</html>");
                            }
                        });
                    } catch (Exception e) {
                        e.printStackTrace();
                        SwingUtilities.invokeLater(() -> {
                            set3dLoadedStatus("something went wrong, try again");
                        });
                    }
                }
            };
            new Thread(runnable).start();
        }

        private double getInitialScale() {
            return 3;
        }

        protected int getJagged() {
            return 1;
        }

        protected double[] getRectDip() {

            return new double[]{1, 1, 1};
        }

        protected void set3dLoadedStatus() {
            set3dLoadedStatus("3D model is loading ...");
        }

        protected void set3dLoadedStatus(String message) {
            canvasPanel.removeAll();
            canvasPanel.add(new JLabel(message));
            canvasPanel.repaint();
            canvasPanel.revalidate();
        }

        public void createVoxelizedShape(TransformGroup tg, int boxX, int jagged, double[] rectDip) {
            this.jagged = jagged;

            double gridspace = 1.0 / boxX;

            double xr, yr, zr;
            double rectScaleX, rectScaleY, rectScaleZ;
            int xj, yj, zj;

            rectScaleX = rectDip[0];
            rectScaleY = rectDip[1];
            rectScaleZ = rectDip[2];

            double gridSpaceX = gridspace * rectScaleX;
            double gridSpaceY = gridspace * rectScaleY;
            double gridSpaceZ = gridspace * rectScaleZ;


            ArrayList<Point3d> point3dArrayList = new ArrayList<Point3d>();

            int boxY = getBoxY(boxX, rectScaleX, rectScaleY, rectScaleZ, jagged);
            int boxZ = getBoxZ(boxX, rectScaleX, rectScaleY, rectScaleZ, jagged);


            for (int k = 0; k < boxZ; k++)
                for (int j = 0; j < boxY; j++)
                    for (int i = 0; i < boxX; i++) {
                        xj = 2 * jagged * (i / jagged) + jagged - boxX;
                        yj = 2 * jagged * (j / jagged) + jagged - boxY;
                        zj = 2 * jagged * (k / jagged) + jagged - boxZ;
                        /* all the following coordinates should be scaled by the same sizeX. So we scale xj,yj,zj by 2boxX with extra
                         * ratio for rectangular dipoles. Thus, yr and zr are not necessarily in fixed ranges (like from -1/2 to 1/2).
                         * This is done to treat adequately cases when particle dimensions are the same (along different axes), but e.g.
                         * boxY!=boxX (so there are some extra void dipoles). All anisotropies in the particle itself are treated in
                         * the specific shape modules below (see e.g. ELLIPSOID).
                         */
                        xr = (0.5 * xj) / boxX;
                        yr = (0.5 * yj) / boxX * (rectScaleY / rectScaleX);
                        zr = (0.5 * zj) / boxX * (rectScaleZ / rectScaleX);

                        if (isPointInsideShapeVolume(xr, yr, zr)) {
                            addVoxel(xr, yr, zr, gridSpaceX, gridSpaceY, gridSpaceZ, point3dArrayList);
                        }
                    }


            if (point3dArrayList.size() < 1) {
                return;
            }

            ArrayList<Double> points = new ArrayList<Double>();
            for (Point3d point3d : point3dArrayList) {
                points.add(point3d.x);
                points.add(point3d.y);
                points.add(point3d.z);
            }

            GeometryInfo gi = new GeometryInfo(GeometryInfo.QUAD_ARRAY);
            gi.setCoordinates(points.stream().mapToDouble(i -> i).toArray());
            NormalGenerator normalGenerator = new NormalGenerator();
            normalGenerator.generateNormals(gi);
            Appearance ap = new Appearance();
            PolygonAttributes polyAttrbutes = new PolygonAttributes();
            polyAttrbutes.setPolygonMode(PolygonAttributes.POLYGON_FILL);
            polyAttrbutes.setCullFace(PolygonAttributes.CULL_NONE);
            ap.setPolygonAttributes(polyAttrbutes);
            Material material = new Material();
            material.setShininess(50f);
            material.setAmbientColor(getVoxelColor());
            material.setDiffuseColor(getVoxelColor());
            ap.setMaterial(material);


            Shape3D shape1 = new Shape3D(gi.getGeometryArray(), ap);
            tg.addChild(shape1);

            ap = new Appearance();
            polyAttrbutes = new PolygonAttributes();
            polyAttrbutes.setPolygonMode(PolygonAttributes.POLYGON_LINE);
            polyAttrbutes.setCullFace(PolygonAttributes.CULL_NONE);
            ap.setPolygonAttributes(polyAttrbutes);
            material = new Material();
            material.setShininess(50f);
            material.setDiffuseColor(getVoxelLineColor());
            material.setAmbientColor(getVoxelLineColor());
            ap.setMaterial(material);
            Shape3D shape2 = new Shape3D(gi.getGeometryArray(), ap);
            tg.addChild(shape2);
        }


        public int getBoxY(int boxX, double rectScaleX, double rectScaleY, double rectScaleZ, int jagged) {
            return fitBox_yz(boxX * (rectScaleX / rectScaleY), jagged);
        }


        public int getBoxZ(int boxX, double rectScaleX, double rectScaleY, double rectScaleZ, int jagged) {
            return fitBox_yz((firstParam + 1) * boxX * (rectScaleX / rectScaleZ), jagged);
        }

        double firstParam = 0.5;

        protected boolean isPointInsideShapeVolume(double xr, double yr, double zr) {
            double ro2 = xr * xr + yr * yr;
            if (ro2 <= 0.25) {
                double tmp1 = Math.abs(zr) - firstParam * 0.5;
                if (tmp1 <= 0 || tmp1 * tmp1 + ro2 <= 0.25) {
                    return true;
                }
            }
            return false;
        }

        protected void addVoxel(double xr, double yr, double zr, double gridSpaceX, double gridSpaceY, double gridSpaceZ, ArrayList<Point3d> point3dArrayList) {
            Point3d point1 = new Point3d(xr + jagged * 0.5 * gridSpaceX, yr - jagged * 0.5 * gridSpaceY, zr - jagged * 0.5 * gridSpaceZ);
            Point3d point2 = new Point3d(xr + jagged * 0.5 * gridSpaceX, yr - jagged * 0.5 * gridSpaceY, zr + jagged * 0.5 * gridSpaceZ);
            Point3d point3 = new Point3d(xr - jagged * 0.5 * gridSpaceX, yr - jagged * 0.5 * gridSpaceY, zr + jagged * 0.5 * gridSpaceZ);
            Point3d point4 = new Point3d(xr - jagged * 0.5 * gridSpaceX, yr - jagged * 0.5 * gridSpaceY, zr - jagged * 0.5 * gridSpaceZ);

            Point3d point5 = new Point3d(xr + jagged * 0.5 * gridSpaceX, yr + jagged * 0.5 * gridSpaceY, zr - jagged * 0.5 * gridSpaceZ);
            Point3d point6 = new Point3d(xr - jagged * 0.5 * gridSpaceX, yr + jagged * 0.5 * gridSpaceY, zr - jagged * 0.5 * gridSpaceZ);
            Point3d point7 = new Point3d(xr - jagged * 0.5 * gridSpaceX, yr + jagged * 0.5 * gridSpaceY, zr + jagged * 0.5 * gridSpaceZ);
            Point3d point8 = new Point3d(xr + jagged * 0.5 * gridSpaceX, yr + jagged * 0.5 * gridSpaceY, zr + jagged * 0.5 * gridSpaceZ);


            point3dArrayList.add(point1);
            point3dArrayList.add(point2);
            point3dArrayList.add(point3);
            point3dArrayList.add(point4);
            point3dArrayList.add(point5);
            point3dArrayList.add(point6);
            point3dArrayList.add(point7);
            point3dArrayList.add(point8);


            Point3d point9 = new Point3d(xr + jagged * 0.5 * gridSpaceX, yr + jagged * 0.5 * gridSpaceY, zr - jagged * 0.5 * gridSpaceZ);
            Point3d point10 = new Point3d(xr + jagged * 0.5 * gridSpaceX, yr + jagged * 0.5 * gridSpaceY, zr + jagged * 0.5 * gridSpaceZ);
            Point3d point11 = new Point3d(xr + jagged * 0.5 * gridSpaceX, yr - jagged * 0.5 * gridSpaceY, zr + jagged * 0.5 * gridSpaceZ);
            Point3d point12 = new Point3d(xr + jagged * 0.5 * gridSpaceX, yr - jagged * 0.5 * gridSpaceY, zr - jagged * 0.5 * gridSpaceZ);

            Point3d point13 = new Point3d(xr - jagged * 0.5 * gridSpaceX, yr + jagged * 0.5 * gridSpaceY, zr - jagged * 0.5 * gridSpaceZ);
            Point3d point14 = new Point3d(xr - jagged * 0.5 * gridSpaceX, yr - jagged * 0.5 * gridSpaceY, zr - jagged * 0.5 * gridSpaceZ);
            Point3d point15 = new Point3d(xr - jagged * 0.5 * gridSpaceX, yr - jagged * 0.5 * gridSpaceY, zr + jagged * 0.5 * gridSpaceZ);
            Point3d point16 = new Point3d(xr - jagged * 0.5 * gridSpaceX, yr + jagged * 0.5 * gridSpaceY, zr + jagged * 0.5 * gridSpaceZ);

            point3dArrayList.add(point9);
            point3dArrayList.add(point10);
            point3dArrayList.add(point11);
            point3dArrayList.add(point12);
            point3dArrayList.add(point13);
            point3dArrayList.add(point14);
            point3dArrayList.add(point15);
            point3dArrayList.add(point16);


            Point3d point17 = new Point3d(xr + jagged * 0.5 * gridSpaceX, yr + jagged * 0.5 * gridSpaceY, zr + jagged * 0.5 * gridSpaceZ);
            Point3d point18 = new Point3d(xr - jagged * 0.5 * gridSpaceX, yr + jagged * 0.5 * gridSpaceY, zr + jagged * 0.5 * gridSpaceZ);
            Point3d point19 = new Point3d(xr - jagged * 0.5 * gridSpaceX, yr - jagged * 0.5 * gridSpaceY, zr + jagged * 0.5 * gridSpaceZ);
            Point3d point20 = new Point3d(xr + jagged * 0.5 * gridSpaceX, yr - jagged * 0.5 * gridSpaceY, zr + jagged * 0.5 * gridSpaceZ);

            Point3d point21 = new Point3d(xr + jagged * 0.5 * gridSpaceX, yr + jagged * 0.5 * gridSpaceY, zr - jagged * 0.5 * gridSpaceZ);
            Point3d point22 = new Point3d(xr + jagged * 0.5 * gridSpaceX, yr - jagged * 0.5 * gridSpaceY, zr - jagged * 0.5 * gridSpaceZ);
            Point3d point23 = new Point3d(xr - jagged * 0.5 * gridSpaceX, yr - jagged * 0.5 * gridSpaceY, zr - jagged * 0.5 * gridSpaceZ);
            Point3d point24 = new Point3d(xr - jagged * 0.5 * gridSpaceX, yr + jagged * 0.5 * gridSpaceY, zr - jagged * 0.5 * gridSpaceZ);

            point3dArrayList.add(point17);
            point3dArrayList.add(point18);
            point3dArrayList.add(point19);
            point3dArrayList.add(point20);
            point3dArrayList.add(point21);
            point3dArrayList.add(point22);
            point3dArrayList.add(point23);
            point3dArrayList.add(point24);
        }

        public static int fitBox(int box, int jagged) {
            return jagged * ((box + jagged - 1) / jagged);
        }

        public static int fitBox_yz(double size, int jagged)
            /* given the size of the particle in y or z direction (in units of dipoles), finds the closest grid size, which would
             * satisfy the FitBox function. The rounding is performed so to minimize the maximum difference between the stack of
             * dipoles and corresponding particle dimension.
             * The distance between the center of the outer super-dipole (J^3 original dipoles) and the particle (enclosing box)
             * boundary is between 0.25 and 0.75 of super-dipole size, corresponding to the discretization along the x-axis, for
             * which the optimum distance of 0.5 (the dipole cube fits tight into the boundary) is automatically satisfied.
             *
             * !!! However, it is still possible that the whole outer layer of dipoles would be void because the estimate does not
             * take into account the details of the shape e.g. its curvature. For instance, 'adda -grid 4 -shape ellipsoid 1 2.13'
             * results in grid 4x4x9, but the layers z=0, z=8 will be void. This is because the dipole centers in this layers always
             * have non-zero x and y coordinates (at least half-dipole in absolute value) and do not fall inside the ellipsoid,
             * although the points {+-4,0,0} do fall into it.
             */ {
            return jagged * (int) Math.round(size / jagged);
        }


        public Color3f getBackgroundColor() {
            return new Color3f(0.75f, 0.69f, 0.680f);
        }

        protected Color3f getVoxelColor() {
            return new Color3f(255, 0, 255);
        }

        protected Color3f getVoxelLineColor() {
            return new Color3f(0, 0, 0);
        }


        protected Color3f getSurfaceColor() {
            return new Color3f(255, 0, 255);
        }

        ;

        protected String error;

        public String getError() {
            return error;
        }
    }
Reply | Threaded
Open this post in threaded view
|

Re: shadows are lost while Java3D 1.5.2 to 1.7.0 migration

questioning
the solution is to use values in range [0.0f; 1.0f] for a color,
for Java3D 1.7.0 Color3f(255, 0 , 0) is not acceptable, the better way is to replace it with Color3f(0.75f, 0 , 0)

PS @philjord thanks for your time
Reply | Threaded
Open this post in threaded view
|

Re: shadows are lost while Java3D 1.5.2 to 1.7.0 migration

gouessej
Administrator
According to the documentation:
"Color components should be in the range of [0.0, 1.0]"
https://jogamp.org/deployment/java3d/1.7.0-final/javadoc/org/jogamp/vecmath/Color3f.html
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: shadows are lost while Java3D 1.5.2 to 1.7.0 migration

questioning
yes, for 1.7.0. it is, but for 1.5.2 a range [0; 255] was acceptable for color (see screenshot from the first post and attached code, it works fine in 1.5.2), so the migration was a little harder that I thought
Reply | Threaded
Open this post in threaded view
|

Re: shadows are lost while Java3D 1.5.2 to 1.7.0 migration

gouessej
Administrator
I was already the case in Java3D 1.6 and in Java3D 1.5.2:
https://jogamp.org/deployment/java3d/1.6.0-final/javadoc/javax/vecmath/Color3f.html

https://download.java.net/media/java3d/javadoc/1.5.2/javax/vecmath/Color3f.html

In my humble opinion, it works with Java3D 1.5.2 if and only if it picks the obsolete native renderer under Windows but this bug is probably reproducible under OS X, GNU Linux and Windows when the use of the JOGL renderer is forced in Java3D 1.5.2. You can try with Java3D 1.5.2 by setting the property "j3d.rend" to "jogl". Note that JogAmp Java3D >= 1.6.0 supports only "jogl" and "noop" as there is no longer native renderer based on Direct3D.
Julien Gouesse | Personal blog | Website