All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.j3d.utils.scenegraph.io.retained.Controller Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistribution of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Redistribution in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in
 *   the documentation and/or other materials provided with the
 *   distribution.
 *
 * Neither the name of Sun Microsystems, Inc. or the names of
 * contributors may be used to endorse or promote products derived
 * from this software without specific prior written permission.
 *
 * This software is provided "AS IS," without a warranty of any
 * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
 * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
 * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL
 * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
 * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR
 * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
 * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
 * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
 * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGES.
 *
 * You acknowledge that this software is not designed, licensed or
 * intended for use in the design, construction, operation or
 * maintenance of any nuclear facility.
 *
 */

package com.sun.j3d.utils.scenegraph.io.retained;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ListIterator;

import javax.media.j3d.BoundingBox;
import javax.media.j3d.BoundingPolytope;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.Bounds;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.CapabilityNotSetException;
import javax.media.j3d.SceneGraphObject;
import javax.media.j3d.SharedGroup;
import javax.media.j3d.Transform3D;
import javax.vecmath.Color3f;
import javax.vecmath.Color4f;
import javax.vecmath.Matrix4d;
import javax.vecmath.Point3d;
import javax.vecmath.Point3f;
import javax.vecmath.Quat4f;
import javax.vecmath.Tuple3d;
import javax.vecmath.Tuple3f;
import javax.vecmath.Tuple4d;
import javax.vecmath.Tuple4f;
import javax.vecmath.Vector3f;
import javax.vecmath.Vector4d;
import javax.vecmath.Vector4f;

import com.sun.j3d.utils.scenegraph.io.NamedObjectException;
import com.sun.j3d.utils.scenegraph.io.ObjectNotLoadedException;
import com.sun.j3d.utils.scenegraph.io.SceneGraphStateProvider;
import com.sun.j3d.utils.scenegraph.io.UnsupportedUniverseException;
import com.sun.j3d.utils.scenegraph.io.state.com.sun.j3d.utils.universe.SimpleUniverseState;
import com.sun.j3d.utils.scenegraph.io.state.javax.media.j3d.ImageComponentState;
import com.sun.j3d.utils.scenegraph.io.state.javax.media.j3d.NullSceneGraphObjectState;
import com.sun.j3d.utils.scenegraph.io.state.javax.media.j3d.SceneGraphObjectState;
import com.sun.j3d.utils.universe.ConfiguredUniverse;
import com.sun.j3d.utils.universe.SimpleUniverse;

/**
 * Provides code to control the reading and writing of Java3D objects to and
 * from any Java IO mechanism.
 */
public abstract class Controller extends java.lang.Object {


    protected static final long SYMBOL_TABLE_PTR = 30;            // long - 8 bytes
    protected static final long BG_DIR_PTR = 38;                  // long - 8 bytes
    protected static final long NAMES_OBJECTS_TABLE_PTR = 46;     // long - 8 bytes
    protected static final long NODE_TYPES_PTR = 52;              // long - 8 bytes
    protected static final long UNIVERSE_CONFIG_PTR = 60;         // long - 8 bytes
    protected static final long BRANCH_GRAPH_COUNT = 68;          // int - 4 bytes
    protected static final long FILE_DESCRIPTION = 72;            // UTF - n bytes

    protected SymbolTable symbolTable;
    protected NullSceneGraphObjectState nullObject = new NullSceneGraphObjectState( null, this );

    /**
     * The currentFileVersion being read
     */
    protected int currentFileVersion;

    /**
     * The File version which will be written
     *
     * 1 = Java3D 1.3 beta 1
     * 2 = Java3D 1.3 FCS, 1) fix to allow skipping user data written via
			      SceneGraphIO interface
            		   2) Add missing duplicateOnCloneTree flag
			      (bug 4690159)
     * 3 = Java3D 1.5.1    1) Add support for SceneGraphObject Name field
     * 4 = Java3D 1.5.2    issue 532, for saving Background Geometry
     * 5 = Java3D 1.5.2+   issue 654, for saving required SpotLight attributes
     */
    protected int outputFileVersion = 5;

    /**
     * When running the application within webstart this may not be the
     * correct ClassLoader. If Java 3D is not installed in the local vm and
     * is instead installed by webstart then this definitely is NOT the correct
     * classloader, in this case Thread.getCurrent().getClass().getClassLoader()
     * would probably be a good default. The user can also set their preferred
     * classloader by calling setClassLoader in SceneGraph[Stream|File]Reader.
     */
    protected ClassLoader classLoader = ClassLoader.getSystemClassLoader();

    /**
     * If true when loading a scenegraph that contains nodes who's classes
     * are not in the classpath then use then first Java3D core superclass
     * to instantiate the node.
     *
     * If false a SGIORuntimeException will be thrown when classes cannot be
     * located
     */
    private boolean useSuperClass = false;

    private int imageCompression = ImageComponentState.NO_COMPRESSION;

    /** Creates new Controller */
    public Controller() {
        try {
            if ( System.getProperty("j3d.io.UseSuperClassIfNoChildClass")!=null)
                useSuperClass = true;

            String imageC = System.getProperty("j3d.io.ImageCompression");
            if (imageC!=null) {
                if (imageC.equalsIgnoreCase("None"))
                    imageCompression = ImageComponentState.NO_COMPRESSION;
                else if (imageC.equalsIgnoreCase("GZIP"))
                    imageCompression = ImageComponentState.GZIP_COMPRESSION;
                else if (imageC.equalsIgnoreCase("JPEG"))
                    imageCompression = ImageComponentState.JPEG_COMPRESSION;
            }
        } catch( Exception e ) {}

    }

    public final SymbolTable getSymbolTable() {
        return symbolTable;
    }

    /**
     * Get the file version that we should write
     */
    public int getOutputFileVersion() {
        return outputFileVersion;
    }

    /**
     * Get the file version of the file we are reading
     */
    public int getCurrentFileVersion() {
        return currentFileVersion;
    }

    /**
     * Create a new state object and check for a pre-existing symbol table
     * entry
     */
    public SceneGraphObjectState createState( SceneGraphObject obj ) {
        return createState( obj, symbolTable.getSymbol( obj ) );
    }

    /**
      * Given a scene graph object instantiate the correct State class
      * for that object. If the symbol already exists (is not null) then
      * increment the reference count, otherwise create a new symbol.
      */
    public SceneGraphObjectState createState( SceneGraphObject obj, SymbolTableData symbol ) {
        if (obj==null) return nullObject;

        if (symbol!=null) {
            symbol.incrementReferenceCount();
            symbolTable.setBranchGraphID( symbol );
            if (symbol.getNodeState()!=null)
                return symbol.getNodeState();
        } else
            symbol = symbolTable.createSymbol( obj );

        return createState( symbol );
    }

    /**
     * Return the state class for the SceneGraphObject, creating one if it does
     * not already exist
     */
    public SceneGraphObjectState createState( SymbolTableData symbol ) {
        SceneGraphObject obj = symbol.getJ3dNode();
        if (obj==null) return nullObject;

        String name = obj.getClass().getName();
        SceneGraphObjectState ret;

          try {
              Class state;
              if (obj instanceof SceneGraphStateProvider)
                  state = ((SceneGraphStateProvider)obj).getStateClass();
              else
                  state = Class.forName( "com.sun.j3d.utils.scenegraph.io.state."+name+"State" );
              ret = constructStateObj( symbol, state, obj.getClass() );
          } catch(ClassNotFoundException e) {
              ret = checkSuperClasses( symbol );
              if (!(obj instanceof com.sun.j3d.utils.scenegraph.io.SceneGraphIO))
                System.out.println("Could not find "+"com.sun.j3d.utils.scenegraph.io.state."+name+"State, using superclass "+ret.getClass().getName() );
              if (ret==null)
                  throw new SGIORuntimeException( "No State class for "+
                                                  obj.getClass().getName() );
          }

        symbol.nodeState = ret;

        return ret;
    }
    private SceneGraphObjectState constructStateObj( SymbolTableData symbol,
                                                     Class state,
                                                     Class objClass ) {

        SceneGraphObjectState ret = null;

        try {
            Constructor construct = state.getConstructor(
                                new Class[] { com.sun.j3d.utils.scenegraph.io.retained.SymbolTableData.class,
                                              com.sun.j3d.utils.scenegraph.io.retained.Controller.class
                                            } );
            ret = (SceneGraphObjectState)construct.newInstance(
                                                new Object[]{ symbol, this } );

        } catch( NoSuchMethodException ex ) {
            System.out.println("Looking for Constructor ("+symbol.j3dNode.getClass().getName()+", Controller )");
            throw new SGIORuntimeException( "1 Broken State class for "+
                                                state.getName() );
        } catch( InvocationTargetException exc ) {
            exc.printStackTrace();
            throw new SGIORuntimeException( "2 Broken State class for "+
                                                state.getName() );
        } catch( IllegalAccessException exce ) {
            throw new SGIORuntimeException( "3 Broken State class for "+
                                                state.getName() );
        } catch( InstantiationException excep ) {
            throw new SGIORuntimeException( "4 Broken State class for "+
                                                state.getName() );
        }

        return ret;
    }

    /**
      * Check to see if any of the superclasses of obj are
      * known to the Java3D IO package
      */
    private SceneGraphObjectState checkSuperClasses( SymbolTableData symbol ) {

        Class cl = symbol.j3dNode.getClass().getSuperclass();
        Class state = null;
        boolean finished = false;


        while( cl != null & !finished ) {
            String name = cl.getName();
            //System.out.println("Got superclass "+name);
            try {
                state = Class.forName( "com.sun.j3d.utils.scenegraph.io.state."+name+"State" );
            } catch(ClassNotFoundException e) {
                state = null;
            }

            if (state!=null)
                finished = true;
            else
                cl = cl.getSuperclass();
        }

        if (cl==null)
            throw new SGIORuntimeException( "Unsupported class "+symbol.j3dNode.getClass().getName() );

        return constructStateObj( symbol, state, cl );
    }


    public void writeObject( DataOutput out, SceneGraphObjectState obj ) throws IOException {

        int classID = getStateID( obj );

        out.writeInt( classID );      // Node class id

        if (classID==0) {
            out.writeUTF( obj.getClass().getName() );
        }

        obj.writeObject( out );
    }

    public SceneGraphObjectState readObject( DataInput in ) throws IOException {
        int classID = in.readInt();

        SceneGraphObjectState state = null;

        if (classID==-1)
            return nullObject;
        else if (classID==0) {
            String stateClassName = in.readUTF();

            try {
                Class cl = Class.forName( stateClassName, true, classLoader );
                // System.out.println("Got class "+cl );
                Constructor construct = cl.getConstructor(
                        new Class[] {
                        com.sun.j3d.utils.scenegraph.io.retained.SymbolTableData.class,
                        com.sun.j3d.utils.scenegraph.io.retained.Controller.class} );

                // System.out.println("Got constructor "+construct );
                state = (SceneGraphObjectState)construct.newInstance(
                                                    new Object[]{ null, this } );

                // System.out.println("Got state instance "+state);
            } catch(ClassNotFoundException e) {
                throw new java.io.IOException( "Error Loading State Class "+stateClassName+"  "+e.getMessage() );
            } catch( NoSuchMethodException ex ) {
                 throw new java.io.IOException( "1 Broken State class for "+
                                                    stateClassName+"  "+ex.getMessage() );
            } catch( InvocationTargetException exc ) {
                exc.printStackTrace();
                throw new java.io.IOException( "2 Broken State class for "+
                                                    stateClassName );
            } catch( IllegalAccessException exce ) {
                throw new java.io.IOException( "3 Broken State class for "+
                                                    stateClassName );
            } catch( InstantiationException excep ) {
                throw new java.io.IOException( "4 Broken State class for "+
                                                    stateClassName );
            }
        } else {
            state = createCoreState( classID );
        }

        state.readObject( in );

        return state;
    }

    /**
      * Set the class loader used to load the Scene Graph Objects and
      * the serialized user data. The default is
      * ClassLoader.getSystemClassLoader()
      */
    public void setClassLoader( ClassLoader classLoader ) {
        this.classLoader = classLoader;
    }


    /**
      * Get the class loader used to load the Scene Graph Objects and
      * the serialized user data. The default is
      * ClassLoader.getSystemClassLoader()
      */
    public ClassLoader getClassLoader() {
        return classLoader;
    }

    /**
     * Write all the unsaved NodeComponents and SharedGroups to DataOutput.
     * Mark all the NodeComponents as saved.
     */
    protected void writeNodeComponents( DataOutput out ) throws IOException {
        // This method is overridden by RandomAccessFileControl
        // The RandomAccessFileControl version sets the pointer to
        // the next NodeComponent correclty

        ListIterator list = symbolTable.getUnsavedNodeComponents();
        out.writeInt( symbolTable.getUnsavedNodeComponentsSize() );
        while( list.hasNext() ) {
            SymbolTableData symbol = (SymbolTableData)list.next();

            out.writeInt( symbol.nodeID );
            out.writeLong( 0L );            // Pointer to next NodeComponent

            writeObject( out, symbol.getNodeState() );
        }
    }

    /**
     * Read in all the node components in this block
     */
    protected void readNodeComponents( DataInput in ) throws IOException {
        int count = in.readInt();

        for(int i=0; i




© 2015 - 2024 Weber Informatics LLC | Privacy Policy