//Qiuli Sun, July 2000
package edu.ou.eml.fea3d;


//standard import
import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.utils.behaviors.mouse.*;
import com.sun.j3d.utils.picking.*;
import javax.swing.*;

public final class SceneGraph
{
    Shape3D shape3D;
    IndexedGeometryArray myGeometry;
    boolean wireFrame;
    Appearance materialAppear;
    TransformGroup geometryTG;

    Canvas3D canvas;

    //Constructor
    SceneGraph(boolean wireFrame,Shape3D shape3D,
    IndexedGeometryArray myGeometry,
    Appearance materialAppear,
    TransformGroup geometryTG,
    Canvas3D canvas)
    {
        this.shape3D = shape3D;
        this.myGeometry = myGeometry;
        this.wireFrame = wireFrame;
        this.materialAppear = materialAppear;
        this.geometryTG = geometryTG;
        this.canvas = canvas;
    }

    /////////////////////////////////////////////////
    //
    // create scene graph branch group
    //
    final public BranchGroup createSceneGraph()
    {
        if(wireFrame==true)
        {
            shape3D.setAppearance(createWireFrameAppearance());
        }
        else
        {
            shape3D.setAppearance(createMaterialAppearance());
        }
        //shape3D.setGeometry(processGeometryData().getIndexedGeometryArray(true));
        shape3D.setGeometry(myGeometry);
        PickTool.setCapabilities(shape3D, PickTool.INTERSECT_FULL);

        BranchGroup contentRoot = new BranchGroup();
        //In order to add child after compilation
        //Appropriate capability must be set.
        contentRoot.setCapability(Group.ALLOW_CHILDREN_EXTEND);
         contentRoot.setCapability(Group.ALLOW_CHILDREN_READ);
         contentRoot.setCapability(Group.ALLOW_CHILDREN_WRITE);
  
        // Create the transform group node and initialize it to the
        // identity. Add it to the root of the subgraph.

        Transform3D myFirstRotate = new Transform3D();
        myFirstRotate.rotY(Math.PI/4.0);
        Transform3D mySecondRotate = new Transform3D();
        mySecondRotate.rotZ(Math.PI/6.0);
        mySecondRotate.mul(myFirstRotate);
       Transform3D myThirdRotate = new Transform3D();
        myThirdRotate.rotX(Math.PI/6.0);
        myThirdRotate.mul(mySecondRotate);
        Transform3D myScale = new Transform3D();

        myScale.mul(myThirdRotate);
        //TransformGroup geometryTG = new TransformGroup(myScale);
        //geometryTG.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
        //geometryTG.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
        geometryTG.setTransform(myScale);

        contentRoot.addChild(geometryTG);
        geometryTG.addChild(shape3D);

        BoundingSphere bounds = new BoundingSphere();
        //1000.0 is a reasonable value since if it is too small, the view volume cannot
        //intersect with BoundingSphere, and no object is active
        bounds.setRadius(1000.0);
        //record this for use somewhere else
        DataContainer.bounds = bounds;
        
        BoundingLeaf boundingLeaf = new BoundingLeaf(bounds);
        geometryTG.addChild(boundingLeaf);

        MouseRotate myMouseRot = new MouseRotate();
        myMouseRot.setTransformGroup(geometryTG);
        myMouseRot.setSchedulingBoundingLeaf(boundingLeaf);
        geometryTG.addChild(myMouseRot);

        MouseZoom myMouseZoom = new MouseZoom();
        myMouseZoom.setFactor(0.5);
        myMouseZoom.setTransformGroup(geometryTG);
        myMouseZoom.setSchedulingBoundingLeaf(boundingLeaf);
        geometryTG.addChild(myMouseZoom);

        MouseTranslate myMouseTrans = new MouseTranslate();
        myMouseTrans.setFactor(0.2);
        myMouseTrans.setTransformGroup(geometryTG);
        myMouseTrans.setSchedulingBoundingLeaf(boundingLeaf);
        geometryTG.addChild(myMouseTrans);

        DirectionalLight lightD1 = new DirectionalLight();
        lightD1.setDirection(new Vector3f(4.0f,-7.0f,-12.0f));
        lightD1.setColor(new Color3f(1.0f, 1.0f, 0.9f));
        lightD1.setInfluencingBoundingLeaf(boundingLeaf);
        contentRoot.addChild(lightD1);

        DirectionalLight lightD2 = new DirectionalLight();
        lightD2.setDirection(new Vector3f(-6.0f,-2.0f,-1.0f));
        lightD2.setColor(new Color3f(0.3f, 0.3f, 0.4f));
        lightD2.setInfluencingBoundingLeaf(boundingLeaf);
        contentRoot.addChild(lightD2);

        AmbientLight lightA = new AmbientLight(true,new Color3f(0.3f,0.3f,0.3f));
        lightA.setInfluencingBoundingLeaf(boundingLeaf);
        contentRoot.addChild(lightA);

        Background background = new Background();
        background.setColor(DataContainer.backGroundColor);
        background.setApplicationBoundingLeaf(boundingLeaf);
        geometryTG.addChild(background);

        // Let Java 3D perform optimizations on this scene graph.
        //contentRoot.compile();
        return contentRoot;
    } // end of CreateSceneGraph method of MobiusApp

    ////*******************************************************
    private Appearance createMaterialAppearance(){
        PolygonAttributes polyAttrib = new PolygonAttributes();
        polyAttrib.setCullFace(PolygonAttributes.CULL_NONE);
        polyAttrib.setCapability(PolygonAttributes.ALLOW_NORMAL_FLIP_WRITE);
        polyAttrib.setBackFaceNormalFlip(true);

        materialAppear.setPolygonAttributes(polyAttrib);
        return materialAppear;
    }
    //********************************************
    public static Appearance createWireFrameAppearance(){
        Appearance materialAppearWire = new Appearance();
        PolygonAttributes polyAttrib = new PolygonAttributes();
        polyAttrib.setPolygonMode(PolygonAttributes.POLYGON_LINE);
      
        polyAttrib.setCullFace(PolygonAttributes.CULL_NONE);
        
        materialAppearWire.setPolygonAttributes(polyAttrib);
        ColoringAttributes redColoring = new ColoringAttributes();
        redColoring.setColor(1.0f, 1.0f, 0.0f);
        materialAppearWire.setColoringAttributes(redColoring);
             
        return materialAppearWire;
    }
}
