com.sun.j3d.utils.scenegraph.io.retained.Controller Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of java3d-core Show documentation
Show all versions of java3d-core Show documentation
Java3D Core And Java3D Util Libraries
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