com.sun.j3d.loaders.lw3d.SequenceLine 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.loaders.lw3d;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.StreamTokenizer;
import java.util.Enumeration;
import java.util.Hashtable;
import javax.media.j3d.Alpha;
import javax.media.j3d.Behavior;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.Group;
import javax.media.j3d.Link;
import javax.media.j3d.Shape3D;
import javax.media.j3d.SharedGroup;
import javax.media.j3d.Switch;
import javax.media.j3d.SwitchValueInterpolator;
import javax.media.j3d.TransformGroup;
import javax.vecmath.Point3d;
import com.sun.j3d.loaders.IncorrectFormatException;
import com.sun.j3d.loaders.ParsingErrorException;
/**
* This class was created to handle "sequence files", which allow
* holosketch-type Tloop sequences to be loaded through the lw3d loader.
* The class reads a sequence file line by line and uses SequenceLine to
* load the file specified in each line.
* Idea behind the Tloop process:
* Artist creates "tloops" (animations with each keyframe's
* geometry saved out explicitly) where the geometries are spaced
* one frame apart. Then I can automatically create a SwitchValueInterpolator
* based on this spacing. If the number of frames in the sequence is
* greater than the number of frames in the tloop, then it will automatically
* loop until the end of the sequence.
* Process:
* 1) Artist creates an animation of a null group that has a child with some
* special name, such as "bucket_sequence_bucketsequence.txt.lwo", which tells
* the lw3d loader that it should look for a sequence file by the name of
* bucketsequence.txt. What happens to this object is irrelevant (as far as
* the loader is concerned); all animation information is taken from its
* parent instead.
* 2) Artist saves out the geometry of the bucket at whatever frames she wants
* to. If she's saving a tloop (a sequence of frames), she should save them
* under the names xxx.lwo, where xxx is the 3-digit sequence number
* (000, 001, 002, etc.).
* 3) Artist creates the sequence file, which lists all saved geometry files
* (except sequences - these can be referred to simply by the first file
* (...000.lwo)), along with their associated start/end frames. She also lists
* the number of files in the sequence, although this parameter is implied
* anyway, through the existence of the sequence files and their naming
* convention. Maybe we should trash this guy.
* 4) In the lw3d loader, when LwsObject encounters an object with the
* filename "..._sequence_.lwo", it searches for filename. If
* found, it parses the file (using the SequenceReader class) to retrieve
* all parameters.
* 5) Each SequenceLine creates a Java3D group containing its objects. This
* is either a plain-old-Group (if there is only one object) or a Switch group
* with a SwitchValueInterpolator.
* 6) SequenceReader constructs a Switch group and adds all SequenceLine groups
* to this new group. It also creates a SwitchPathInterpolator (child of
* PathInterolator) that contsructs an Alpha based on the startFrame values of
* each SequenceLine. It creates a group and adds the SwitchPathInterpolator
* plus any SequenceLine SwitchValueInterpolators to this group.
* 7) LwsObject adds the SequenceReader Switch group to its objectTransform.
* It does a getBehaviors() from SequenceReader and adds the result (the
* SwitchPathInterpolator group) to its objectBehaviors group.
* 8) Done.
*/
class SequenceLine {
int startFrame;
int endFrame;
String fileName;
Group geometryGroup = null;
Behavior behaviors;
int numFrames;
float totalTime;
int totalFrames;
// storedRefList keeps references to already loaded objects
static Hashtable storedRefList = new Hashtable();
SequenceLine(StreamTokenizer st, float time, int frames)
throws ParsingErrorException {
try {
totalTime = time;
totalFrames = frames;
startFrame = (int)st.nval;
st.nextToken();
endFrame = (int)st.nval;
st.nextToken();
fileName = st.sval;
numFrames = endFrame - startFrame + 1;
}
catch (IOException e) {
throw new ParsingErrorException(e.getMessage());
}
}
/**
* Creates a SwitchValueInterpolator which is used to switch between
* the objects specified for the sequence. This is done for files
* that end in "000", meaning that there are a sequence of files
* with that same base name that should specify every frame of a
* sequence for an object. The Switch node is used to hold all of the
* files and the Switch Behavior node is used to activate switching
* at the right time and to the right object.
*/
private void createSwitchBehavior(Switch target) {
int loopCount = -1;
float animTime = 1000.0f * totalTime *
(float)(target.numChildren())/(float)totalFrames;
float startTime = 1000f * totalTime *
(float)startFrame/(float)totalFrames;
Alpha theAlpha =
new Alpha(-1, (long)startTime, 0, (long)animTime, 0, 0);
SwitchValueInterpolator b=new SwitchValueInterpolator(theAlpha,target);
behaviors = b;
BoundingSphere bounds =
new BoundingSphere(new Point3d(0.0,0.0,0.0), 1000000.0);
b.setSchedulingBounds(bounds);
target.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
target.addChild(behaviors);
}
/**
* Create Java3d objects from the data in the sequence line. This
* means that for a tloop file (ends in "000"), we're going to create
* the appropriate geometry for each file, put them all in a Switch
* node, then create a SwitchValueInterpolator to swap between the
* frames of the tloop. If it's not a tloop, then we're just going to
* create the geometry for that file.
*/
void createJava3dObjects(int debugVals, int loadBehaviors)
throws IncorrectFormatException, FileNotFoundException {
if (fileName.indexOf("000") != -1) { // Tloop
int index = fileName.indexOf("000");
String fileNameBase = fileName.substring(0, index);
Switch s = new Switch();
s.setCapability(Switch.ALLOW_SWITCH_READ);
s.setCapability(Switch.ALLOW_SWITCH_WRITE);
String tempFileName = fileName;
int fileNum = 0;
while ((new File(tempFileName)).exists()) {
if (storedRefList.get(tempFileName) != null) {
// System.out.println("retrieve stored version of " +
// tempFileName);
SharedGroup storedGroup =
(SharedGroup)storedRefList.get(tempFileName);
Link newLink = new Link(storedGroup);
s.addChild(newLink);
}
else {
// System.out.println("reading " + tempFileName);
J3dLwoParser objParser = new J3dLwoParser(tempFileName,
debugVals);
objParser.createJava3dGeometry();
TransformGroup t = new TransformGroup();
SharedGroup newSharedGroup = new SharedGroup();
storedRefList.put(tempFileName, newSharedGroup);
newSharedGroup.addChild(t);
Link newLink = new Link(newSharedGroup);
s.addChild(newLink);
if (objParser.getJava3dShapeList() != null) {
for (Enumeration e =
objParser.getJava3dShapeList().elements() ;
e.hasMoreElements() ;) {
t.addChild((Shape3D)e.nextElement());
}
}
}
++fileNum;
String fileNumString = String.valueOf(fileNum);
if (fileNum < 10)
fileNumString = "00" + fileNumString;
else if (fileNum < 100)
fileNumString = "0" + fileNumString;
tempFileName = fileNameBase + fileNumString + ".lwo";
}
behaviors = null;
if (loadBehaviors != 0) {
createSwitchBehavior(s);
}
geometryGroup = (Group)s;
}
else {// Not a tloop, just a file
geometryGroup = new Group();
if (storedRefList.get(fileName) != null) {
// System.out.println("getting old ref to " + fileName);
SharedGroup storedGroup =
(SharedGroup)storedRefList.get(fileName);
Link newLink = new Link(storedGroup);
geometryGroup.addChild(newLink);
}
else {
// System.out.println("reading " + fileName);
J3dLwoParser objParser = new J3dLwoParser(fileName,
debugVals);
objParser.createJava3dGeometry();
TransformGroup t = new TransformGroup();
if (objParser.getJava3dShapeList() != null) {
for (Enumeration e = objParser.getJava3dShapeList().elements() ;
e.hasMoreElements() ;) {
t.addChild((Shape3D)e.nextElement());
}
}
SharedGroup newSharedGroup = new SharedGroup();
newSharedGroup.addChild(t);
Link newLink = new Link(newSharedGroup);
geometryGroup.addChild(newLink);
storedRefList.put(fileName, newSharedGroup);
}
}
}
Group getGeometry() {
return geometryGroup;
}
Behavior getBehavior() {
return behaviors;
}
}