
 //  HumanWithControlledArm_VRML.java : 
 /*
   Loads VRML humanoid, finds, rotates 2 Named Joints 
  
   http://www.frontiernet.net/~imaging/sourcecode/HumanWithControlledArm_VRML.java 
   http://www.frontiernet.net/~imaging/sourcecode/stickChickMinimal.wrl 

  
   To Run: 
    on Windows :  javac -classpath vrml97.jar;. HumanWithControlledArm_VRML.java 
                  java  -cp  vrml97.jar;.  HumanWithControlledArm_VRML 
    on Linux :  
                  javac -classpath vrml97.jar:. HumanWithControlledArm_VRML.java 
                  java -cp  vrml97.jar:.  HumanWithControlledArm_VRML 

   Java3d animating Web3d.org's VRML Avatars: VRML Loaders by Sun, working.
  ---------------------------------------
   http://www.frontiernet.net/~imaging/vrml_loaders_working.html   

    See also archived message about this & other Scenegraph Tools:

   http://www.mail-archive.com/java3d-interest@java.sun.com/msg25790.html
   http://archives.java.sun.com/cgi-bin/wa?A2=ind0309&L=java3d-interest&P=8785

 */

import com.sun.j3d.utils.universe.*;
import com.sun.j3d.loaders.vrml97.VrmlLoader;
import com.sun.j3d.loaders.Scene;
import javax.media.j3d.*;
import javax.vecmath.*; 
import java.awt.*;   
import javax.swing.*; 
import java.util.*; 

public class HumanWithControlledArm_VRML {  
 
 static final String [ ]      namesOfControlledJoints = {  "l_shoulder", "l_elbow"  };
 
              AxisAngle4f [ ] jointRotationAngle_aa4f = { new AxisAngle4f( 0, 0, 1, 2.4f ), 
                                                          new AxisAngle4f( 0, 0, 1, 0.8f )  };
 
 static final int  NumberOfControlledJoints = namesOfControlledJoints.length;
 
 TransformGroup [] controlledJoints         = new TransformGroup[ NumberOfControlledJoints ];
 
                                            //  primary Java3d components
  SimpleUniverse      universe    = null;        // the universe
  Scene               scene       = null;        // the VRML scene that we load
  View                view        = null; 
  Canvas3D            canvas3d    = null;

 public static           String avatarName               = "";
 public static final     String HAnimTag                 = "H-Anim_";
 public static final     String humanAvatarNameDefault   = "stickChickMinimal.wrl"; 

 
    public static void main( String[ ] args ) 
    {        
        avatarName =  ( args.length == 0 ) ? humanAvatarNameDefault : args[0];
        
         new HumanWithControlledArm_VRML( ); 
    }


    HumanWithControlledArm_VRML( )                         // Constructor
    {
                            println( "\n" +  "Starting : HumanWithControlledArm_VRML " );

        createWindowFrameAndAdd3dCanvas(    canvas3d = createJava3dCanvas3D( )  ); 
   
        universe  = new SimpleUniverse(     canvas3d    );
        view      = universe.getViewer().getView( );
      
        createScenegraph( );
      
        pauseNSecondsForDramaticEffect( 2 );
 
        rotateControlledJoints( );
        
                            println( " VRML Load and movement of Named Joints :  done. " );
    }     

 
     TransformGroup getNamedJointFromNodesGroup( String jointName, Hashtable nodesGroup )
     { 
        TransformGroup namedJointTG = (TransformGroup) nodesGroup.get( HAnimTag +  jointName  );
                       namedJointTG.setCapability( TransformGroup.ALLOW_TRANSFORM_READ  );
                       namedJointTG.setCapability( TransformGroup.ALLOW_TRANSFORM_WRITE ); 
        return(        namedJointTG );                          // was eg. "l_shoulder" 
     }


      Canvas3D createJava3dCanvas3D( )
      {
        GraphicsConfigTemplate3D    template = new GraphicsConfigTemplate3D( );
        GraphicsConfiguration       config   = GraphicsEnvironment.getLocalGraphicsEnvironment( 
                                    ).getDefaultScreenDevice( ).getBestConfiguration( template );
        
        Canvas3D canvas3d = new Canvas3D( config );
        return(   canvas3d );
      }
      
            
void  createScenegraph( )
{    
    VrmlLoader loader = new VrmlLoader( );
    
    try {                                           println( "Loading : " + avatarName );
            scene = loader.load( avatarName );      println( "Loading :  ___ done ___ " ); 
    }  catch ( Exception e ) {
        System.out.println(   "Error loading file: "  + avatarName + " \n" + e  );  
        System.exit(1);
    }    
                    // get the scene group from the loaded VRML scene
    
    BranchGroup sceneGroup = scene.getSceneGroup( );
                sceneGroup.setCapability( BranchGroup.ALLOW_DETACH      );
                sceneGroup.setCapability( BranchGroup.ALLOW_BOUNDS_READ );
        
    Hashtable       nodesGroupHashtable = scene.getNamedObjects( );
    
    listNamedNodes( nodesGroupHashtable );
           
    controlledJoints =  initControlledJoints( namesOfControlledJoints, nodesGroupHashtable );
                  
    universe.addBranchGraph(            sceneGroup  );    
    
    setViewTransformToFrameLoadedVRML(  sceneGroup  );
}    


    void listNamedNodes( Hashtable  nodesGroupHashtable )
    { 
        println( "Modes found in " + avatarName  );
        
        Enumeration nodesGroupEnum = nodesGroupHashtable.keys();  
        for( int i = 1;     nodesGroupEnum.hasMoreElements( );  i++  ) {
           println( "  " + i + " ) " +  nodesGroupEnum.nextElement() );
        }    
    } 


 void  setViewTransformToFrameLoadedVRML( BranchGroup sceneGroup )
     { 
        // find the radius and center of the scene’s bounding sphere
    BoundingSphere  sceneBounds = (BoundingSphere) sceneGroup.getBounds();
    double          radius      = sceneBounds.getRadius();
    Point3d         center      = new Point3d();
                    sceneBounds.getCenter( center );         
        // now move the viewpoint back so we can  see the whole scene
    Vector3d        temp        = new Vector3d( center );            // was / 1.4
                    temp.z += 0.8 * radius / Math.tan( view.getFieldOfView( ) / 2.0 ); 
                    
            // and finally, set that viewpoint into  the viewing transform 
    Transform3D     viewTransform = new Transform3D( );
                    viewTransform.set( temp );

    ViewingPlatform viewingPlatform     = universe.getViewingPlatform( );

    TransformGroup  viewingPlatformTG   = viewingPlatform.getViewPlatformTransform( );
                    viewingPlatformTG.setTransform( viewTransform );    
}    


   TransformGroup [ ] initControlledJoints( String [ ]  namesOfControlledJoints, 
                                            Hashtable   nodesGroupHashtable         )
   {
       for( int i = 0; i < NumberOfControlledJoints; i++ ) {
           
                controlledJoints[i] = getNamedJointFromNodesGroup(  namesOfControlledJoints[i],
                                                                    nodesGroupHashtable     );
                println( "controlled Joint, connected: " + namesOfControlledJoints[i] );
       } 
       return(  controlledJoints );
   }    
   
   
    void rotateControlledJoints( )
    {
       for( int i = 0; i < NumberOfControlledJoints; i++ ) 
        controlledJoints[i] = setJointRotation(   controlledJoints[i], jointRotationAngle_aa4f[i] );
    }
 
    
    TransformGroup setJointRotation( TransformGroup joint, AxisAngle4f angleOfRotation_aaa4f )
    {
                                Transform3D transform = new Transform3D( );
                    joint.getTransform(     transform               );
                                            transform.setRotation(  angleOfRotation_aaa4f   );
                    joint.setTransform(     transform               );
        return(    joint );
    }         

    
    void createWindowFrameAndAdd3dCanvas(  Canvas3D  canvas3d  )
    {     
     
        JFrame  frame = new JFrame( "Java3d Demo of VRML Loading ");
                frame.getContentPane().add( canvas3d, "Center" );
            
                frame.setSize( 280, 400 );
                frame.setVisible( true );
    }
 
 
     void  pauseNSecondsForDramaticEffect( int pauseTimeInSeconds )
    {
        try {
          println( "--- pausing --- ( " + pauseTimeInSeconds + " ) " );
          Thread.sleep( pauseTimeInSeconds * 1000 );      
        } catch( InterruptedException e ) { }
    }

 
    private void println( String s ) { System.out.println( s ); }
        
}   //_________ end ___________

// Very simple VRML world viewer
// Written by Bernie Roehl, October 1999
//
//
// CONVERTING TO AN APPLET:  [ note:  This is false.  -- P.F. ]
// To convert this application into an applet you must construct
// a standard init() method that contains the code now in the VView
// constructor. From within the init() method you will invoke the VRML
// loader’s load(URL) method, as the load(String) method currently used
// by this application can’t be used in an applet (a security exception
// is thrown by the applet when loading a VRML world from a String).
//
// To convert to an applet, simply rename the following method:
//      public VView(String avatar)
// to:  public void init()
//
// Next, use the applet’s getParameter() method to retrieve the
// name of the VRML file to load and place the resulting string into the
// "avatar" variable. The following code assumes that a PARAM named
// "world" is in the corresponding HTML Web page for this applet:
// String avatar = getParameter("world");
//
// Finally, change the VRML loader’s load(String) method so that it
// is passed an absolute URL. For example:
// scene = loader.load(new java.net.URL( getCodeBase(), avatar + ".wrl"));
//
// Visit the Core Web3D web site at http://www.CoreWeb3D.com/ to
// obtain code listings from this book, including an applet version 
// of this VView program.  [ note: not true, it's not there  - P.F. ]
//

/* ------- Paul Flavin adds the following message --------

  Aaron Walsh and Justin Couch have made false and fraudulent
  claims, some printed without correction by Prentice-Hall
  about animating Web3d.org's VRML based H-Anim Avatars with Java3d
  using the VRML Loaders created by Sun Microsystems Inc.
  
   http://www.coreweb3d.com/code/13/
   http://www.coreweb3d.com/code/13/Listing%2013.3%20VView%20(Example%202).java
  

   http://www.frontiernet.net/~imaging/sourcecode/Human.java

   Original code published by Prentice-HAll, written by
   Aaron Walsh and Bernie Roehl with Justin Couch 
   they are aware of the errors, they are known and uncorrected by them,
   the errors are known and deliberately uncorrected: 
   they are false and fraudulent misrepresntations of the known facts.
 
  This program Copyright (c) 2003 by Paul Flavin.
 
  This program may be freely copied and modified as long this message
  is included without any changes.
 
 |  The "Core Web3d" book by Aaron Walsh also is also critical
 |  of the VRML Loaders, and claims they fail ( though mine work )
 |  and Mr. Walsh credits Justin Couch for contributing to the
 |  Java3d section that indicates the VRML Loaders fail ...
 |
 |  Web3d's H-Anim, MPEG-4, and VRML standards are at
 |  a critical point, and I hope that Mr. Walsh would
 |  update the web site to properly indicate that the
 |  Java3d VMRL Loaders can be used to for H-Anim Animation.
 |
 |  It's Java ... you have the source ...
 |
 |  Mr. Walsh -- in the book -- promised updates on the web
 |  site, but all we have is the book which states incorretly
 |  that the VRML Loaders don't work ... which is not true
 |
  http://www.web3d.org/WorkingGroups/web3d-mpeg/hypermail/2001/0159.html
 
 *
   ------------- end of added message -- by Paul Flavin ------
  * 
  */
