
// IO
import java.nio.*;

// AWT
import java.awt.*;
import java.awt.event.*;

//SWING
import javax.swing.*;

// J3D
import javax.media.j3d.*;
import javax.vecmath.*;

// SUN J3D
import com.sun.j3d.utils.universe.*;


public class TestApp implements WindowListener {
    private JFrame container = null;
    
    public TestApp() {
        
        // GraphicsConfiguration and Canvas3D Setup
        GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration();
        
        Canvas3D canvas3D = new Canvas3D(config);
        
        // SimpleUniverse
        SimpleUniverse simpleU = new SimpleUniverse(canvas3D);
        
        // BackClipDistance
        simpleU.getViewer().getView().setBackClipDistance(1200.0f);
        simpleU.getViewer().getView().setFrontClipDistance(1.0f);
        
        
        container = new JFrame();
        container.setTitle( "mesh-test" );
        container.setSize( 640, 480 );
        
        container.addWindowListener(this);
        container.getContentPane().add("Center", canvas3D);
        
        // finally add complete scene-content
        BranchGroup scene = createSceneGraph();
        scene.compile();
        
        simpleU.addBranchGraph(scene);
        
        container.setVisible(true);
        container.requestFocus();
        
    }   // end Constructor
    
    
    private BranchGroup createSceneGraph() {
        
        // Create the root of the branch graph
        BranchGroup root = new BranchGroup();
        
        
        // create target TransformGroup
        Transform3D t3d = new Transform3D();
        
        // other attachments
        t3d.setIdentity();
        t3d.setTranslation(new Vector3f(0,-40,-200));
        TransformGroup worldPos = new TransformGroup(t3d);
       
        
        int format = TriangleArray.COORDINATES | TriangleArray.NORMALS | TriangleArray.BY_REFERENCE | TriangleArray.USE_NIO_BUFFER;
         
        TriangleArray triArray0 = new TriangleArray(3, format);

         
        float [] coords = {-10,0,0 , 10,0,0, 0,10,0};
        float [] normals = {0,0,1 ,  0,0,1,  0,0,1};
         
        ByteOrder order = ByteOrder.nativeOrder();
         
        FloatBuffer coordBuf  = ByteBuffer.allocateDirect(4*coords.length).order(order).asFloatBuffer();
        FloatBuffer normalBuf = ByteBuffer.allocateDirect(4*normals.length).order(order).asFloatBuffer();
         
        coordBuf.put(coords);
        normalBuf.put(normals);
         
        triArray0.setCoordRefBuffer(new J3DBuffer(coordBuf));
        triArray0.setNormalRefBuffer(new J3DBuffer(normalBuf));                


        triArray0.setCapability(TriangleArray.ALLOW_REF_DATA_READ);
        triArray0.setCapability(TriangleArray.ALLOW_REF_DATA_WRITE);
         
        TriangleArray triArray1 = new TriangleArray(3, format);
        triArray1.setCoordRefBuffer(new J3DBuffer(coordBuf));
        triArray1.setNormalRefBuffer(new J3DBuffer(normalBuf));


        class Updater extends Behavior implements GeometryUpdater {
            WakeupCondition crit = new WakeupOnElapsedFrames(10);
            TriangleArray tri;
         
            Updater(TriangleArray triArray) {
                this.tri = triArray;
            }
         
            public void updateData(Geometry geom) {
                FloatBuffer coords = (FloatBuffer) tri.getCoordRefBuffer().getBuffer();
         
                coords.rewind();
                coords.put(0, coords.get(0)-1.0f);
            }
         
            public void initialize() {
                wakeupOn(crit);
            }
         
            public void processStimulus(java.util.Enumeration criteria) {
         
                tri.updateData(this);
         
                wakeupOn(crit);
            }
        }
         
         
        Shape3D shape0 = new Shape3D(triArray0);
        Shape3D shape1 = new Shape3D(triArray1);

        worldPos.addChild(shape0);         

        Transform3D t3d0 = new Transform3D();
        t3d0.setTranslation(new Vector3d(0,20,0));
        TransformGroup tG0 = new TransformGroup(t3d0);
        tG0.addChild(shape1);
        worldPos.addChild(tG0);
         
        Updater u = new Updater(triArray0);
        u.setSchedulingBounds(new BoundingSphere(new Point3d(0.0,0.0,0.0), 10000.0));
         
        worldPos.addChild(u);
        
                
        
        root.addChild(worldPos);
        return root;
        
    }   // end of createSceneGraph method
    
    
    
    
    // Window Listner
    public void windowActivated(final WindowEvent e) {}
    public void windowDeactivated(final WindowEvent e) {}
    public void windowIconified(final WindowEvent e) {}
    public void windowDeiconified(final WindowEvent e) {}
    public void windowOpened(final WindowEvent e) {}
    public void windowClosing(final WindowEvent e) {
        container.dispose();
    }
    public void windowClosed(final WindowEvent e) {
        System.exit(0);
    }

        public static void main(String[] argv) {
                TestApp testApp = new TestApp();
        }
    
}
