
import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.event.*;

import java.awt.GraphicsConfiguration;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;

public class DoublePrecisionTest extends Applet {
        public static final double DISTANCE = 1000000.0;
        public static final double WIDTH = 0.02;

    private SimpleUniverse u = null;
    
    public BranchGroup createSceneGraph() {
                //
        BranchGroup objRoot = new BranchGroup();
                TransformGroup objTrans = new TransformGroup();
                objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
                objRoot.addChild(objTrans);
                // create appearance	
                Appearance app = new Appearance();
                ColoringAttributes ca = new ColoringAttributes();
                Color3f objColor = new Color3f(1.0f, 0.2f, 0.4f);
                ca.setColor(objColor);
                app.setColoringAttributes(ca);
                // create geometry

                /*
                Point3d lower = new Point3d(-0.02+100000,-0.02,-0.02);
                Point3d upper = new Point3d( 0.02+100000, 0.02, 0.02);
                */

                Point3d lower = new Point3d(DISTANCE - WIDTH,-WIDTH,-WIDTH);
                Point3d upper = new Point3d(DISTANCE + WIDTH, WIDTH, WIDTH);
                GeometryArray geometry = box(lower,upper);
	
                // create shape3f
                Shape3D box = new Shape3D(geometry,app);
                objTrans.addChild(box);

                return objRoot;
    }

    public DoublePrecisionTest() {}

    public void init() {
                setLayout(new BorderLayout());
        GraphicsConfiguration config =
        SimpleUniverse.getPreferredConfiguration();
                Canvas3D c = new Canvas3D(config);
                add("Center", c);
                BranchGroup scene = createSceneGraph();
                u = new SimpleUniverse(c);
        u.getViewingPlatform().setNominalViewingTransform();
        TransformGroup tg = 
                u.getViewingPlatform().getMultiTransformGroup().getTransformGroup(0);
        //Vector3d position = new Vector3d(100000,0,1);
        Vector3d position = new Vector3d(DISTANCE,0.0d,10.0*WIDTH);
        Transform3D t3d = new Transform3D();
        t3d.setTranslation(position);
        tg.setTransform(t3d);
                u.addBranchGraph(scene);
    }

    public void destroy() {
                u.removeAllLocales();
    }

    
    /**
        * 
        */
        public GeometryArray box(Point3d lowerBounds,Point3d upperBounds) { 
        	
                double xMin = lowerBounds.x;
                double yMin = lowerBounds.y;
                double zMin = lowerBounds.z;
                //
                double xMax = upperBounds.x;
                double yMax = upperBounds.y;
                double zMax = upperBounds.z;	
         
                double[] verts = {
                // front face
                        xMax, yMin, zMax,
                        xMax, yMax, zMax,
                        xMin, yMax, zMax,
                        xMin, yMin, zMax,
                // back face
                        xMin, yMin, zMin,
                        xMin, yMax, zMin,
                        xMax, yMax, zMin,
                        xMax, yMin, zMin,
                // right face
                        xMax, yMin, zMin,
                        xMax, yMax, zMin,
                        xMax, yMax, zMax,
                        xMax, yMin, zMax,
                // left face
                        xMin, yMin, zMax,
                        xMin, yMax, zMax,
                        xMin, yMax, zMin,
                        xMin, yMin, zMin,
                // top face
                        xMax, yMax, zMax,
                        xMax, yMax, zMin,
                        xMin, yMax, zMin,
                        xMin, yMax, zMax,
                // bottom face
                        xMin, yMin, zMax,
                        xMin, yMin, zMin,
                        xMax, yMin, zMin,
                        xMax, yMin, zMax,
                };
        	
                float[] normals = {
                // front face
                        0, 0, 1,
                        0, 0, 1,
                        0, 0, 1,
                        0, 0, 1,
                // back face
                        0, 0, -1,
                        0, 0, -1,
                        0, 0, -1,
                        0, 0, -1,
                // right face
                        1, 0, 0,
                        1, 0, 0,
                        1, 0, 0,
                        1, 0, 0,
                // left face
                        -1, 0, 0,
                        -1, 0, 0,
                        -1, 0, 0,
                        -1, 0, 0,
                // top face
                        0, 1, 0,
                        0, 1, 0,
                        0, 1, 0,
                        0, 1, 0,
                // bottom face
                        0, -1, 0,
                        0, -1, 0,
                        0, -1, 0,
                        0, -1, 0,
        };
            	
                QuadArray cube = new QuadArray(24,QuadArray.COORDINATES|QuadArray.NORMALS);
                cube.setCoordinates(0, verts);
                cube.setNormals(0,normals);
        	
                cube.setCapability(Geometry.ALLOW_INTERSECT);
                cube.setCapability(GeometryArray.ALLOW_COORDINATE_READ);
                cube.setCapability(GeometryArray.ALLOW_COORDINATE_WRITE);
                cube.setCapability(GeometryArray.ALLOW_COLOR_WRITE);
	
                /* 
                // To be used for geometry by reference
                QuadArray cube = new QuadArray(24,QuadArray.COORDINATES|QuadArray.NORMALS|QuadArray.BY_REFERENCE);
                cube.setCoordRefDouble(verts);
                cube.setNormalRefFloat(normals);
                cube.setCapability(GeometryArray.BY_REFERENCE);
                double [] quadRef = null;
                quadRef = cube.getCoordRefDouble();
                */
        	
                //print box coordinates
                //System.out.print("cube.getVertexCount() = "+cube.getVertexCount());
        	
                Point3d point = new Point3d();
                for(int i = 0; i < cube.getVertexCount(); i++) {
                        //
                        System.out.print("Original Vertex= ("+verts[i*3]);
                System.out.print(","+verts[i*3+1]);
                        System.out.println(","+verts[i*3+2]+")");
                        //
                        cube.getCoordinate(i,point);
                        System.out.println("Rendered Vertex = "+point);
                	
                        /*
                        // To be used for geometry by reference
                        System.out.print("Reference to Vertex= ("+quadRef[i*3]);
                System.out.print(","+quadRef[i*3+1]);
                        System.out.println(","+quadRef[i*3+2]+")");
                        */
                }
                return cube;
        }

    
    
    //
    // The following allows DoublePrecisionTest to be run as an application
    // as well as an applet
    //
    public static void main(String[] args) {
                new MainFrame(new DoublePrecisionTest(), 512,512);
    }
}
