?? propmanager.java
字號:
// PropManager.java
// Andrew Davison, April 2005, ad@fivedots.coe.psu.ac.th
/* The user supplies the name of a 3D object file to be loaded.
Its bounding sphere is automatically scaled to have a radius
of 1 unit, and rotated -90 around x-axis if it is a 3ds model.
A large range of different 3D object formats can be loaded
since we are using the Portfolio loaders.
Once loaded, the image can be moved and rotated along the
X, Y, and Z axes, and scaled. The resulting position,
rotation, and scaling information can be stored in a
'coords' file (which has the same name as the 3D file
+ "Coords.txt").
The rotation information is stored as a series of rotation
*numbers* which must be executed in order to get to the curent
overall rotation:
1 = positive ROT_INCR around x-axis
2 = negative ROT_INCR around x-axis
3 = positive ROT_INCR around y-axis
4 = negative ROT_INCR around y-axis
5 = positive ROT_INCR around z-axis
6 = negative ROT_INCR around z-axis
This approach is used to try to avoid the problem that a mix of
rotations about diffrent axes do not produce the same result if
carried out in different orders.
The coordinates information can be loaded along with the object
by using:
java Loader3D -c <3D filename>
The loaded object is hung off several TGs, and the top one can be
accessed by calling getTG().
Changes:
- removed use of j3d-fly VRML loader and starfire 3DS loader
*/
import java.util.*;
import java.io.*;
import java.text.DecimalFormat;
import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.loaders.*;
// Portfolio loader packages
import ncsa.j3d.*;
import ncsa.j3d.loaders.*;
public class PropManager
{
// for specifying moves and rotations
private static final int X_AXIS = 0;
private static final int Y_AXIS = 1;
private static final int Z_AXIS = 2;
private static final int INCR = 0;
private static final int DECR = 1;
private static final double MOVE_INCR = 0.1; // move increment for an object
private static final double ROT_INCR = 10; // rotation increment (in degrees)
private static final double ROT_AMT = Math.toRadians(ROT_INCR); // in radians
// TGs which the loaded object (the prop) hangs off:
// moveTG-->rotTG-->scaleTG-->objBoundsTG-->obj
private TransformGroup moveTG, rotTG, scaleTG;
private Transform3D t3d; // for accessing a TG's transform
private Transform3D chgT3d; // holds current change to the posn, rot, or scale
private String filename; // of loaded object
private double xRot, yRot, zRot; // total of rotation angles carried out
private ArrayList rotInfo; // stores the sequence of rotation numbers
private double scale; // current object scaling
private DecimalFormat df; // for debugging
public PropManager(String loadFnm, boolean hasCoordsInfo)
{
filename = loadFnm;
xRot = 0.0; yRot = 0.0; zRot = 0.0; // initial loaded object settings
rotInfo = new ArrayList();
scale = 1.0;
t3d = new Transform3D(); // setup reusable Transform3D objects
chgT3d = new Transform3D();
df = new DecimalFormat("0.###"); // 3 dp
loadFile(loadFnm);
if (hasCoordsInfo) // load in coords info also
getFileCoords(loadFnm);
} // end of PropManager()
private void loadFile(String fnm)
/* The 3D object file is loaded using a Portfolio loader.
The loaded object has 4 transform groups above it -- objBoundsTG is
for adjusting the object's bounded sphere so it is centered at
(0,0,0) and has unit radius.
The other TGs are for doing separate moves, rotations, and scaling
of the object.
moveTG-->rotTG-->scaleTG-->objBoundsTG-->object
*/
{ System.out.println("Loading object file: models/" + fnm);
Scene s = null;
ModelLoader modelLoader = new ModelLoader();
try {
s = modelLoader.load("models/"+fnm); // handles many types of file
}
catch (Exception e) {
System.err.println(e);
System.exit(1);
}
// get the branch group for the loaded object
BranchGroup sceneGroup = s.getSceneGroup();
// create a transform group for the object's bounding sphere
TransformGroup objBoundsTG = new TransformGroup();
objBoundsTG.addChild( sceneGroup );
// resize loaded object's bounding sphere (and maybe rotate)
String ext = getExtension(fnm);
BoundingSphere objBounds = (BoundingSphere) sceneGroup.getBounds();
setBSPosn(objBoundsTG, objBounds.getRadius(), ext);
// create a transform group for scaling the object
scaleTG = new TransformGroup();
scaleTG.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
scaleTG.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
scaleTG.addChild( objBoundsTG );
// create a transform group for rotating the object
rotTG = new TransformGroup();
rotTG.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
rotTG.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
rotTG.addChild( scaleTG );
// create a transform group for moving the object
moveTG = new TransformGroup();
moveTG.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
moveTG.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
moveTG.addChild( rotTG );
} // end of loadFile()
private String getExtension(String fnm)
// return the extension of fnm, or "(none)"
{
int dotposn = fnm.lastIndexOf(".");
if (dotposn == -1) // no extension
return "(none)";
else
return fnm.substring(dotposn+1).toLowerCase();
}
private void setBSPosn(TransformGroup objBoundsTG,
double radius, String ext)
// Scale the object to unit radius, and rotate -90 around x-axis if the
// file contains a 3ds model
{
Transform3D objectTrans = new Transform3D();
objBoundsTG.getTransform( objectTrans );
// System.out.println("radius: " + df.format(radius));
// scale the object so its bounds are within a 1 unit radius sphere
Transform3D scaleTrans = new Transform3D();
double scaleFactor = 1.0/radius;
// System.out.println("scaleFactor: " + df.format(scaleFactor) );
scaleTrans.setScale( scaleFactor );
// final transform = [original] * [scale] (and possible *[rotate])
objectTrans.mul(scaleTrans);
if (ext.equals("3ds")) { // the file is a 3ds model
// System.out.println("Rotating -90 around x-axis");
Transform3D rotTrans = new Transform3D();
rotTrans.rotX( -Math.PI/2.0 ); // 3ds models are often on their face; fix that
objectTrans.mul(rotTrans);
}
objBoundsTG.setTransform(objectTrans);
} // end of setBSPosn()
public TransformGroup getTG()
// used by WrapLoader3D to add object to 3D world
{ return moveTG; }
// ----------------------------------------------------------------
// obtain coords file info and apply it to the loaded object
private void getFileCoords(String fnm)
/* Obtain coords info from the coordinates file for fnm.
The coords file has the format:
<3D object fnm>
[-p px py pz]
[-r sequence of numbers]
[-s scale]
*/
{
String coordFile = "models/" + getName(fnm) + "Coords.txt";
try {
BufferedReader br = new BufferedReader( new FileReader(coordFile));
br.readLine(); // skip fnm line (we know this already)
String line;
char ch;
while((line = br.readLine()) != null) {
ch = line.charAt(1);
if (ch == 'p')
setCurrentPosn(line);
else if (ch == 'r')
setCurrentRotation(line);
else if (ch == 's')
setCurrentScale(line);
else
System.out.println(coordFile + ": did not recognise line: " + line);
}
br.close();
System.out.println("Read in coords file: " + coordFile);
}
catch (IOException e)
{ System.out.println("Error reading coords file: " + coordFile);
System.exit(1);
}
} // end of getFileCoords()
private String getName(String fnm)
// extract name before the final '.' suffix
{
int dotposn = fnm.lastIndexOf(".");
if (dotposn == -1) // no extension
return fnm;
else
return fnm.substring(0, dotposn);
}
private void setCurrentPosn(String line)
// extract the (x,y,z) position info from the coords file,
// then apply it to the loaded object
{
double vals[] = new double[3]; // for the position data
vals[0] = 0; vals[1] = 0; vals[2] = 0; // represents (x,y,z)
StringTokenizer tokens = new StringTokenizer(line);
String token = tokens.nextToken(); // skip command label
int count = 0;
while (tokens.hasMoreTokens()) {
token = tokens.nextToken();
try {
vals[count] = Double.parseDouble(token);
count++;
}
catch (NumberFormatException ex){
System.out.println("Incorrect format for position data in coords file");
break;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -