/*
 * Panel3D.java
 *
 * Created on February 17, 2003, 10:19 PM
 */

package com.riverside.util.viewer3d;

import com.mnstarfire.loaders3d.*;
import com.sun.j3d.utils.universe.*;
import com.sun.j3d.utils.geometry.*;
import javax.media.j3d.*;
import javax.vecmath.*;
import java.awt.*;
import javax.swing.*;


/**
 *
 * @author  Eric
 */
public class Panel3D extends javax.swing.JPanel {
    
    private SimpleUniverse simpleU;
    private Canvas3D canvas;
    private BranchGroup scene;
    private BranchGroup modelGroup;
    private Viewer3D viewer;
    private TransformGroup theModel;
    private RotationInterpolator rotate;
    private Alpha spinAlpha;
    
    /** Creates new form Panel3D */
    public Panel3D(Viewer3D view) {
        initComponents();
        
        viewer = view;
        
        // UI Code
        canvas = new Canvas3D(SimpleUniverse.getPreferredConfiguration());
        
        canvasPanel.add("Center", canvas);
        
        xTxt.setText("0");
        yTxt.setText("0");
        zTxt.setText("0");
        degreesTxt.setText("0");
        
        simpleU = new SimpleUniverse(canvas);
        
        modelGroup = new BranchGroup();
        modelGroup.setCapability(BranchGroup.ALLOW_DETACH);
        modelGroup.setCapability(BranchGroup.ALLOW_CHILDREN_READ);
        modelGroup.setCapability(BranchGroup.ALLOW_CHILDREN_WRITE);  
        
        scene = createBranchGroup();
        scene.setCapability(BranchGroup.ALLOW_CHILDREN_READ);
        scene.setCapability(BranchGroup.ALLOW_CHILDREN_WRITE);
        scene.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND);

        scene.compile();

        setView();
        
        simpleU.addBranchGraph(scene);
        
    }
    
    private BranchGroup createBranchGroup() {
        BranchGroup objRoot = new BranchGroup();
      
        objRoot.addChild(modelGroup);
        
        return objRoot;
    }
    
    public void translateView() {
        // Validate our values first
        float x, y, z;
        xTxt.setText("".equals(xTxt.getText())?"0":xTxt.getText());
        yTxt.setText("".equals(yTxt.getText())?"0":yTxt.getText());
        zTxt.setText("".equals(zTxt.getText())?"0":zTxt.getText());
        
        try {
            x = Float.valueOf(xTxt.getText()).floatValue();
            y = Float.valueOf(yTxt.getText()).floatValue();
            z = Float.valueOf(zTxt.getText()).floatValue();
        } catch (NumberFormatException e) {
            JOptionPane.showMessageDialog(viewer,"X, Y, and Z values must be floats!", "Error", JOptionPane.OK_OPTION);
            return;
        }
        
        TransformGroup vpTrans = simpleU.getViewingPlatform().getViewPlatformTransform();
        Vector3f translate = new Vector3f();
        translate.set(x, y, z); // move the view to wherever you want it.
        Transform3D curT3D = new Transform3D();
        vpTrans.getTransform(curT3D); // fill curT3D with current Transform
        Transform3D newT3D = new Transform3D();
        newT3D.setTranslation(translate);
        curT3D.mul(newT3D);
        vpTrans.setTransform(curT3D);
    }
    
    public void rotateView() {
        // Validate our values first
        double x = 0.0;
        double y = 0.0;
        double z = 0.0;
        double angle;
        
        if (xRB.isSelected()) {
            // X was selected
            x = 1.0;
        } else if (yRB.isSelected()) {
            // Y was selected
            y = 1.0;
        } else if (zRB.isSelected()) {
            // Z was selected
            z = 1.0;
        } 
        
        try {
            angle = Double.valueOf(degreesTxt.getText()).doubleValue();
        } catch (NumberFormatException e) {
            JOptionPane.showMessageDialog(viewer,"Angle must be a double!", "Error", JOptionPane.OK_OPTION);
            return;
        }
        
        System.out.println("x: " + x + " y: " + y + " z: " + z);
        System.out.println("angle: " + angle);
        
        TransformGroup vpTrans = simpleU.getViewingPlatform().getViewPlatformTransform();
        Transform3D curT3D = new Transform3D();
        vpTrans.getTransform(curT3D); // fill curT3D with current Transform
        Transform3D newT3D = new Transform3D();
        newT3D.setRotation(new AxisAngle4d(x,y,z,angle * Math.PI / 180));
        curT3D.mul(newT3D);
        vpTrans.setTransform(curT3D);
    }    
    
    public void spinModel() {
        // Validate our values first
        int revs = 0;
        int delay = 0;

        revTxt.setText("".equals(revTxt.getText())?"1":revTxt.getText());
        timeTxt.setText("".equals(timeTxt.getText())?"4000":timeTxt.getText());

        try {
            revs = Integer.valueOf(revTxt.getText()).intValue();
            delay = Integer.valueOf(timeTxt.getText()).intValue();
        } catch (NumberFormatException e) {
            JOptionPane.showMessageDialog(viewer,"Revolutions and Time Delay on Spin must be Integers!", "Error", JOptionPane.OK_OPTION);
            return;
        }

        Transform3D rotT3D = new Transform3D();
        if (xRBSpin.isSelected()) {
            // X was selected
            rotT3D.rotZ(-Math.PI/2);
            System.out.println("rotating on x");
        } else if (yRBSpin.isSelected()) {
            // Y was selected
            System.out.println("rotating on y");
        } else if (zRBSpin.isSelected()) {
            // Z was selected
            rotT3D.rotX(Math.PI/2);
            System.out.println("rotating on z");
        }
        
        System.out.println("revs: " + revs + "  delay: " + delay);

        rotate.setTransformAxis(rotT3D);
        
        spinAlpha.setLoopCount(revs);
        spinAlpha.setIncreasingAlphaDuration(delay);
        spinAlpha.setStartTime(System.currentTimeMillis());
        spinAlpha.resume();
    
    }
    
    public void resetPanel() {
        modelGroup.detach();
        
    }    
    
    public void setView() {
        TransformGroup vpTrans = simpleU.getViewingPlatform().getViewPlatformTransform();
        Vector3f translate = new Vector3f();
        translate.set(0.0f,0.0f,5.0f); // move the view to wherever you want it.
        Transform3D T3D = new Transform3D();
        T3D.setTranslation(translate);
        vpTrans.setTransform(T3D);
        zTxt.setText("5.0");
    }
    
    public void load3DS(String sFilename) {
        
        modelGroup.detach();
        
        modelGroup = new BranchGroup();
        modelGroup.setCapability(BranchGroup.ALLOW_DETACH);
        modelGroup.setCapability(BranchGroup.ALLOW_CHILDREN_READ);
        modelGroup.setCapability(BranchGroup.ALLOW_CHILDREN_WRITE);

        TransformGroup rtg = new TransformGroup();

        Inspector3DS loader = new Inspector3DS(sFilename);
        loader.setLogging(false); // turns on logging to a disk file "log3ds.txt" 
        //loader.setDetail(7); // sets the level of detail to be logged 
        //loader.setTextureLightingOn(); // turns on modulate mode for textures (lighting) 
        // loader.setTexturePath("D:\MyTextures"); // optional alternative path to find texture files 
        loader.parseIt(); 
        theModel = loader.getModel();
        theModel.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
        theModel.setCapability(TransformGroup.ALLOW_CHILDREN_READ);
        theModel.setCapability(TransformGroup.ALLOW_CHILDREN_WRITE);
        theModel.setCapability(TransformGroup.ALLOW_CHILDREN_EXTEND);
        rtg.addChild(theModel);
        modelGroup.addChild(rtg);
        
        spinAlpha = new Alpha();
        spinAlpha.setMode(Alpha.INCREASING_ENABLE);
        spinAlpha.pause();

        rotate = new RotationInterpolator(spinAlpha, rtg);
        BoundingSphere bounds = new BoundingSphere();
        rotate.setSchedulingBounds(bounds);

        rtg.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
        rtg.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
        
        theModel.addChild(rotate);
        
        scene.addChild(modelGroup);
    }        
    
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    private void initComponents() {//GEN-BEGIN:initComponents
        rotateBG = new javax.swing.ButtonGroup();
        canvasPanel = new javax.swing.JPanel();
        controlPanel = new javax.swing.JPanel();
        movePanel = new javax.swing.JPanel();
        xPanel = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        xTxt = new javax.swing.JTextField();
        yPanel = new javax.swing.JPanel();
        jLabel11 = new javax.swing.JLabel();
        yTxt = new javax.swing.JTextField();
        zPanel = new javax.swing.JPanel();
        jLabel12 = new javax.swing.JLabel();
        zTxt = new javax.swing.JTextField();
        jPanel1 = new javax.swing.JPanel();
        moveBut = new javax.swing.JButton();
        setViewBut = new javax.swing.JButton();
        rotatePanel = new javax.swing.JPanel();
        jPanel2 = new javax.swing.JPanel();
        jLabel2 = new javax.swing.JLabel();
        xRB = new javax.swing.JRadioButton();
        yRB = new javax.swing.JRadioButton();
        zRB = new javax.swing.JRadioButton();
        zPanel1 = new javax.swing.JPanel();
        jLabel121 = new javax.swing.JLabel();
        degreesTxt = new javax.swing.JTextField();
        jPanel4 = new javax.swing.JPanel();
        rotateBut = new javax.swing.JButton();
        resetRotBut = new javax.swing.JButton();
        spinPanel = new javax.swing.JPanel();
        jPanel21 = new javax.swing.JPanel();
        jLabel21 = new javax.swing.JLabel();
        xRBSpin = new javax.swing.JRadioButton();
        yRBSpin = new javax.swing.JRadioButton();
        zRBSpin = new javax.swing.JRadioButton();
        zPanel11 = new javax.swing.JPanel();
        zPanel111 = new javax.swing.JPanel();
        jLabel12111 = new javax.swing.JLabel();
        revTxt = new javax.swing.JTextField();
        zPanel1112 = new javax.swing.JPanel();
        jLabel121112 = new javax.swing.JLabel();
        timeTxt = new javax.swing.JTextField();
        jPanel41 = new javax.swing.JPanel();
        spinStartBut = new javax.swing.JButton();
        statusPanel = new javax.swing.JPanel();

        setLayout(new java.awt.BorderLayout());

        canvasPanel.setLayout(new java.awt.BorderLayout());

        canvasPanel.setPreferredSize(new java.awt.Dimension(100, 100));
        canvasPanel.setMinimumSize(new java.awt.Dimension(100, 100));
        add(canvasPanel, java.awt.BorderLayout.CENTER);

        controlPanel.setLayout(new javax.swing.BoxLayout(controlPanel, javax.swing.BoxLayout.Y_AXIS));

        controlPanel.setPreferredSize(new java.awt.Dimension(225, 10));
        controlPanel.setMinimumSize(new java.awt.Dimension(225, 10));
        controlPanel.setMaximumSize(new java.awt.Dimension(225, 32767));
        movePanel.setLayout(new javax.swing.BoxLayout(movePanel, javax.swing.BoxLayout.Y_AXIS));

        movePanel.setBorder(new javax.swing.border.TitledBorder("Move View"));
        xPanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT));

        xPanel.setPreferredSize(new java.awt.Dimension(159, 32));
        xPanel.setMinimumSize(new java.awt.Dimension(159, 32));
        xPanel.setMaximumSize(new java.awt.Dimension(159, 32));
        jLabel1.setText("X:");
        xPanel.add(jLabel1);

        xTxt.setHorizontalAlignment(javax.swing.JTextField.LEFT);
        xTxt.setPreferredSize(new java.awt.Dimension(90, 25));
        xTxt.setMaximumSize(new java.awt.Dimension(90, 25));
        xTxt.setMinimumSize(new java.awt.Dimension(90, 25));
        xPanel.add(xTxt);

        movePanel.add(xPanel);

        yPanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT));

        yPanel.setPreferredSize(new java.awt.Dimension(159, 32));
        yPanel.setMinimumSize(new java.awt.Dimension(159, 32));
        yPanel.setMaximumSize(new java.awt.Dimension(159, 32));
        jLabel11.setText("Y:");
        yPanel.add(jLabel11);

        yTxt.setHorizontalAlignment(javax.swing.JTextField.LEFT);
        yTxt.setPreferredSize(new java.awt.Dimension(90, 25));
        yTxt.setMaximumSize(new java.awt.Dimension(90, 25));
        yTxt.setMinimumSize(new java.awt.Dimension(90, 25));
        yPanel.add(yTxt);

        movePanel.add(yPanel);

        zPanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT));

        zPanel.setPreferredSize(new java.awt.Dimension(159, 32));
        zPanel.setMinimumSize(new java.awt.Dimension(159, 32));
        zPanel.setMaximumSize(new java.awt.Dimension(159, 32));
        jLabel12.setText("Z:");
        zPanel.add(jLabel12);

        zTxt.setHorizontalAlignment(javax.swing.JTextField.LEFT);
        zTxt.setPreferredSize(new java.awt.Dimension(90, 25));
        zTxt.setMaximumSize(new java.awt.Dimension(90, 25));
        zTxt.setMinimumSize(new java.awt.Dimension(90, 25));
        zPanel.add(zTxt);

        movePanel.add(zPanel);

        jPanel1.setMaximumSize(new java.awt.Dimension(32767, 37));
        moveBut.setText("Move");
        moveBut.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                moveButActionPerformed(evt);
            }
        });

        jPanel1.add(moveBut);

        setViewBut.setText("Set Pos");
        jPanel1.add(setViewBut);

        movePanel.add(jPanel1);

        controlPanel.add(movePanel);

        rotatePanel.setLayout(new javax.swing.BoxLayout(rotatePanel, javax.swing.BoxLayout.Y_AXIS));

        rotatePanel.setBorder(new javax.swing.border.TitledBorder("Rotate View"));
        jPanel2.setPreferredSize(new java.awt.Dimension(150, 30));
        jPanel2.setMinimumSize(new java.awt.Dimension(150, 30));
        jPanel2.setMaximumSize(new java.awt.Dimension(200, 30));
        jLabel2.setText("Axis:");
        jLabel2.setMaximumSize(new java.awt.Dimension(31, 17));
        jPanel2.add(jLabel2);

        xRB.setSelected(true);
        xRB.setText("X");
        rotateBG.add(xRB);
        jPanel2.add(xRB);

        yRB.setText("Y");
        rotateBG.add(yRB);
        jPanel2.add(yRB);

        zRB.setText("Z");
        rotateBG.add(zRB);
        jPanel2.add(zRB);

        rotatePanel.add(jPanel2);

        zPanel1.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.RIGHT));

        zPanel1.setPreferredSize(new java.awt.Dimension(159, 32));
        zPanel1.setMinimumSize(new java.awt.Dimension(159, 32));
        zPanel1.setMaximumSize(new java.awt.Dimension(159, 32));
        jLabel121.setText("Degrees:");
        zPanel1.add(jLabel121);

        degreesTxt.setHorizontalAlignment(javax.swing.JTextField.LEFT);
        degreesTxt.setPreferredSize(new java.awt.Dimension(70, 25));
        degreesTxt.setMaximumSize(new java.awt.Dimension(70, 25));
        degreesTxt.setMinimumSize(new java.awt.Dimension(70, 25));
        zPanel1.add(degreesTxt);

        rotatePanel.add(zPanel1);

        jPanel4.setPreferredSize(new java.awt.Dimension(147, 37));
        jPanel4.setMinimumSize(new java.awt.Dimension(147, 37));
        jPanel4.setMaximumSize(new java.awt.Dimension(32000, 37));
        rotateBut.setText("Rotate");
        rotateBut.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                rotateButActionPerformed(evt);
            }
        });

        jPanel4.add(rotateBut);

        resetRotBut.setText("Set Angle");
        jPanel4.add(resetRotBut);

        rotatePanel.add(jPanel4);

        controlPanel.add(rotatePanel);

        spinPanel.setLayout(new javax.swing.BoxLayout(spinPanel, javax.swing.BoxLayout.Y_AXIS));

        spinPanel.setBorder(new javax.swing.border.TitledBorder("Spin"));
        jPanel21.setPreferredSize(new java.awt.Dimension(150, 30));
        jPanel21.setMinimumSize(new java.awt.Dimension(150, 30));
        jPanel21.setMaximumSize(new java.awt.Dimension(200, 30));
        jLabel21.setText("Axis:");
        jLabel21.setMaximumSize(new java.awt.Dimension(31, 17));
        jPanel21.add(jLabel21);

        xRBSpin.setSelected(true);
        xRBSpin.setText("X");
        rotateBG.add(xRBSpin);
        jPanel21.add(xRBSpin);

        yRBSpin.setText("Y");
        rotateBG.add(yRBSpin);
        jPanel21.add(yRBSpin);

        zRBSpin.setText("Z");
        rotateBG.add(zRBSpin);
        jPanel21.add(zRBSpin);

        spinPanel.add(jPanel21);

        zPanel11.setLayout(new javax.swing.BoxLayout(zPanel11, javax.swing.BoxLayout.X_AXIS));

        zPanel11.setPreferredSize(new java.awt.Dimension(159, 32));
        zPanel11.setMinimumSize(new java.awt.Dimension(159, 32));
        zPanel11.setMaximumSize(new java.awt.Dimension(10000, 32));
        zPanel111.setPreferredSize(new java.awt.Dimension(80, 32));
        zPanel111.setMinimumSize(new java.awt.Dimension(80, 32));
        zPanel111.setMaximumSize(new java.awt.Dimension(80, 32));
        jLabel12111.setText("Revs");
        zPanel111.add(jLabel12111);

        revTxt.setHorizontalAlignment(javax.swing.JTextField.LEFT);
        revTxt.setPreferredSize(new java.awt.Dimension(40, 25));
        revTxt.setMaximumSize(new java.awt.Dimension(40, 25));
        revTxt.setMinimumSize(new java.awt.Dimension(40, 25));
        zPanel111.add(revTxt);

        zPanel11.add(zPanel111);

        zPanel1112.setPreferredSize(new java.awt.Dimension(100, 32));
        zPanel1112.setMinimumSize(new java.awt.Dimension(100, 32));
        zPanel1112.setMaximumSize(new java.awt.Dimension(1000, 32));
        jLabel121112.setText("Time (m)");
        zPanel1112.add(jLabel121112);

        timeTxt.setHorizontalAlignment(javax.swing.JTextField.LEFT);
        timeTxt.setPreferredSize(new java.awt.Dimension(50, 25));
        timeTxt.setMaximumSize(new java.awt.Dimension(50, 25));
        timeTxt.setMinimumSize(new java.awt.Dimension(50, 25));
        zPanel1112.add(timeTxt);

        zPanel11.add(zPanel1112);

        spinPanel.add(zPanel11);

        jPanel41.setPreferredSize(new java.awt.Dimension(147, 37));
        jPanel41.setMinimumSize(new java.awt.Dimension(147, 37));
        jPanel41.setMaximumSize(new java.awt.Dimension(32000, 37));
        spinStartBut.setText("Spin");
        spinStartBut.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                spinStartButActionPerformed(evt);
            }
        });

        jPanel41.add(spinStartBut);

        spinPanel.add(jPanel41);

        controlPanel.add(spinPanel);

        add(controlPanel, java.awt.BorderLayout.WEST);

        statusPanel.setPreferredSize(new java.awt.Dimension(10, 30));
        statusPanel.setMinimumSize(new java.awt.Dimension(10, 30));
        statusPanel.setMaximumSize(new java.awt.Dimension(32767, 30));
        add(statusPanel, java.awt.BorderLayout.SOUTH);

    }//GEN-END:initComponents

    private void spinStartButActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_spinStartButActionPerformed
        spinModel();
    }//GEN-LAST:event_spinStartButActionPerformed

    private void rotateButActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_rotateButActionPerformed
        rotateView();
    }//GEN-LAST:event_rotateButActionPerformed

    private void moveButActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_moveButActionPerformed
        translateView();
    }//GEN-LAST:event_moveButActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JRadioButton xRBSpin;
    private javax.swing.JRadioButton zRBSpin;
    private javax.swing.JPanel movePanel;
    private javax.swing.JPanel statusPanel;
    private javax.swing.JPanel jPanel41;
    private javax.swing.JButton rotateBut;
    private javax.swing.JRadioButton yRBSpin;
    private javax.swing.JLabel jLabel12;
    private javax.swing.JLabel jLabel11;
    private javax.swing.JLabel jLabel12111;
    private javax.swing.JRadioButton zRB;
    private javax.swing.JButton spinStartBut;
    private javax.swing.JRadioButton xRB;
    private javax.swing.JPanel zPanel1;
    private javax.swing.JPanel controlPanel;
    private javax.swing.JPanel zPanel11;
    private javax.swing.ButtonGroup rotateBG;
    private javax.swing.JTextField xTxt;
    private javax.swing.JLabel jLabel121;
    private javax.swing.JTextField revTxt;
    private javax.swing.JPanel jPanel4;
    private javax.swing.JTextField yTxt;
    private javax.swing.JPanel canvasPanel;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel zPanel112;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel zPanel111;
    private javax.swing.JTextField zTxt;
    private javax.swing.JButton moveBut;
    private javax.swing.JPanel zPanel1112;
    private javax.swing.JPanel rotatePanel;
    private javax.swing.JPanel zPanel1111;
    private javax.swing.JLabel jLabel121112;
    private javax.swing.JLabel jLabel121111;
    private javax.swing.JTextField degreesTxt;
    private javax.swing.JPanel jPanel21;
    private javax.swing.JButton setViewBut;
    private javax.swing.JTextField revTxt11;
    private javax.swing.JButton resetRotBut;
    private javax.swing.JPanel xPanel;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JPanel spinPanel;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JPanel yPanel;
    private javax.swing.JRadioButton yRB;
    private javax.swing.JPanel zPanel;
    private javax.swing.JTextField timeTxt;
    private javax.swing.JLabel jLabel21;
    // End of variables declaration//GEN-END:variables
    
}
