Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- / PropManager.java
- // Andrew Davison, January 2003, 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
- March 2010
- - fixed rotInfo generic typing
- - used Java3D's ObjectFile to load wavefront files so material is correct
- */
- import com.sun.j3d.loaders.*;
- import com.sun.j3d.loaders.objectfile.ObjectFile;
- import java.io.*;
- import java.text.DecimalFormat;
- import java.util.*;
- import javax.media.j3d.*;
- import javax.vecmath.*;
- 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<Integer> 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<Integer>();
- 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("C:/Users/LIRKIS PC/Desktop/pokusNytoolkit/src/models/" + fnm);
- String ext = getExtension(fnm);
- Scene s = null;
- try {
- if (ext.equals("obj")) { // the file is a wavefront model
- // System.out.println("Loading obj file");
- ObjectFile of = new ObjectFile ();
- of.setFlags(ObjectFile.RESIZE | ObjectFile.TRIANGULATE | ObjectFile.STRIPIFY);
- s = of.load("C:/Users/LIRKIS PC/Desktop/pokusNytoolkit/src/models/"+fnm);
- }
- else { // use Portfolio loader for other models
- ModelLoader modelLoader = new ModelLoader();
- s = modelLoader.load("C:/Users/LIRKIS PC/Desktop/pokusNytoolkit/src/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)
- 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 = "C:/Users/LIRKIS PC/Desktop/pokusNytoolkit/src/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;
- }
- }
- if (count != 3)
- System.out.println("Insufficient position data in coords file");
- // apply the moves to the loaded object
- doMove( new Vector3d( vals[0], vals[1], vals[2]) );
- } // end of setCurrentPosn()
- private void setCurrentRotation(String line)
- // extract the rotation info from the coords file,
- // and apply it to the loaded object
- {
- int rotNum;
- StringTokenizer tokens = new StringTokenizer(line);
- String token = tokens.nextToken(); // skip command label
- if (!tokens.hasMoreTokens()) // there may not be any rotation numbers
- return;
- token = tokens.nextToken();
- for (int i=0; i < token.length(); i++) {
- try {
- rotNum = Character.digit(token.charAt(i),10);
- // rotInfo.add( new Integer(rotNum));
- }
- catch (NumberFormatException ex){
- System.out.println("Incorrect format for rotation data in coords file");
- break;
- }
- if (rotNum == 1) // positive x-axis rotation
- rotate(X_AXIS, INCR);
- else if (rotNum == 2) // negative
- rotate(X_AXIS, DECR);
- else if (rotNum == 3) // positive y-axis rotation
- rotate(Y_AXIS, INCR);
- else if (rotNum == 4) // negative
- rotate(Y_AXIS, DECR);
- else if (rotNum == 5) // positive z-axis rotation
- rotate(Z_AXIS, INCR);
- else if (rotNum == 6) // negative
- rotate(Z_AXIS, DECR);
- else
- System.out.println("Did not recognise the rotation info in the coords file");
- }
- } // end of setCurrentRotation()
- private void setCurrentScale(String line)
- // extract the scale info from the coords file,
- // and apply it to the loaded object
- {
- StringTokenizer tokens = new StringTokenizer(line);
- String token = tokens.nextToken(); // skip command label
- double startScale;
- token = tokens.nextToken(); // should be the scale value
- try {
- startScale = Double.parseDouble(token);
- }
- catch (NumberFormatException ex){
- System.out.println("Incorrect format for scale data in coords file");
- startScale = 1.0;
- }
- // System.out.println("Loaded start scale: " + startScale);
- if (startScale != 1.0) {
- scale(startScale);
- }
- } // end of setCurrentScale()
- //---------------------------------------------------------
- // modify the position/rotation/scale of the loaded object
- /* These methods are called when applying the coords file
- information *and* when user commands sent from the GUI
- are being processed.
- */
- public void move(int axis, int change)
- // move the object along an axis
- {
- double moveStep = (change == INCR) ? MOVE_INCR : -MOVE_INCR ;
- Vector3d moveVec;
- if (axis == X_AXIS)
- moveVec = new Vector3d(moveStep,0,0);
- else if (axis == Y_AXIS)
- moveVec = new Vector3d(0,moveStep,0);
- else // Z_AXIS
- moveVec = new Vector3d(0,0,moveStep);
- doMove( moveVec );
- } // end of move()
- private void doMove(Vector3d theMove)
- // move the object by theMove amount
- {
- moveTG.getTransform(t3d); // get current position from TG
- chgT3d.setIdentity(); // reset change Trans
- chgT3d.setTranslation(theMove); // setup move
- t3d.mul(chgT3d); // 'add' move to current position
- moveTG.setTransform(t3d); // update TG
- } // end of doMove()
- public void rotate(int axis, int change)
- // rotate the object about an axis, and remember the change
- {
- doRotate(axis, change);
- storeRotate(axis, change);
- } // end of rotate()
- private void doRotate(int axis, int change)
- // rotate the object about the axis by radians amount
- {
- double radians = (change == INCR) ? ROT_AMT : -ROT_AMT;
- rotTG.getTransform(t3d); // get current rotation from TG
- chgT3d.setIdentity(); // reset change Trans
- switch (axis) { // setup new rotation
- case X_AXIS: chgT3d.rotX(radians); break;
- case Y_AXIS: chgT3d.rotY(radians); break;
- case Z_AXIS: chgT3d.rotZ(radians); break;
- default: System.out.println("Unknown axis of rotation"); break;
- }
- t3d.mul(chgT3d); // 'add' new rotation to current one
- rotTG.setTransform(t3d); // update the TG
- } // end of doRotate()
- private void storeRotate(int axis, int change)
- // store the rotation information
- {
- double degrees = (change == INCR) ? ROT_INCR : -ROT_INCR;
- switch (axis) {
- case X_AXIS: storeRotateX(degrees); break;
- case Y_AXIS: storeRotateY(degrees); break;
- case Z_AXIS: storeRotateZ(degrees); break;
- default: System.out.println("Unknown storage axis of rotation"); break;
- }
- } // end of storeRotate()
- private void storeRotateX(double degrees)
- // record the x-axis rotation
- {
- xRot = (xRot+degrees)%360; // update x-axis total rotation
- if (degrees == ROT_INCR)
- rotInfo.add(new Integer(1)); // rotation number
- else if (degrees == -ROT_INCR)
- rotInfo.add(new Integer(2));
- else
- System.out.println("No X-axis rotation number for " + degrees);
- } // end of storeRotateX()
- private void storeRotateY(double degrees)
- // record the y-axis rotation
- {
- yRot = (yRot+degrees)%360; // update y-axis total rotation
- if (degrees == ROT_INCR)
- rotInfo.add(new Integer(3)); // rotation number
- else if (degrees == -ROT_INCR)
- rotInfo.add(new Integer(4));
- else
- System.out.println("No Y-axis rotation number for " + degrees);
- } // end of storeRotateY()
- private void storeRotateZ(double degrees)
- // record the z-axis rotation
- {
- zRot = (zRot+degrees)%360; // update z-axis total rotation
- if (degrees == ROT_INCR)
- rotInfo.add(new Integer(5)); // rotation number
- else if (degrees == -ROT_INCR)
- rotInfo.add(new Integer(6));
- else
- System.out.println("No Z-axis rotation number for " + degrees);
- } // end of storeRotateZ()
- public void scale(double d)
- // Scale the object by d units
- {
- scaleTG.getTransform(t3d); // get current scale from TG
- chgT3d.setIdentity(); // reset change Trans
- chgT3d.setScale(d); // set up new scale
- t3d.mul(chgT3d); // multiply new scale to current one
- scaleTG.setTransform(t3d); // update the TG
- scale *= d; // update scale variable
- } // end of scale()
- // ----------------------------------------------------------
- // return current position/rotation/scale information
- // Used by the GUI interface
- public Vector3d getLoc()
- {
- moveTG.getTransform(t3d);
- Vector3d trans = new Vector3d();
- t3d.get(trans);
- // printTuple(trans, "getLoc");
- return trans;
- } // end of getLoc()
- public Point3d getRotations()
- { return new Point3d(xRot, yRot, zRot); }
- public double getScale()
- { return scale; }
- // ------------------------------ storing ---------------------------
- public void saveCoordFile()
- // create a coords file for this object
- {
- String coordFnm = "C:/Users/LIRKIS PC/Desktop/pokusNytoolkit/src/models/" + getName(filename) + "Coords.txt";
- try {
- PrintWriter out = new PrintWriter( new FileWriter(coordFnm));
- out.println(filename); // object filename
- Vector3d currLoc = getLoc();
- out.println("-p " + df.format(currLoc.x) + " " + df.format(currLoc.y) +
- " " + df.format(currLoc.z) );
- out.print("-r ");
- for (int i=0; i < rotInfo.size(); i++)
- out.print( ""+((Integer) rotInfo.get(i)).intValue() );
- out.println("");
- out.println("-s " + df.format(scale) );
- out.close();
- System.out.println("Saved to coord file: " + coordFnm);
- }
- catch(IOException e)
- { System.out.println("Error writing to coord file: " + coordFnm); }
- } // end of saveCoordFile()
- // --------------------- methods used for debugging --------------------------
- private void printTG(TransformGroup tg, String id)
- // print the translation stored in tg
- {
- Transform3D currt3d = new Transform3D( );
- tg.getTransform( currt3d );
- Vector3d currTrans = new Vector3d( );
- currt3d.get( currTrans );
- printTuple( currTrans, id);
- } // end of printTG()
- private void printTuple(Tuple3d t, String id)
- // used to print Vector3d, Point3d objects
- {
- System.out.println(id + " x: " + df.format(t.x) +
- ", " + id + " y: " + df.format(t.y) +
- ", " + id + " z: " + df.format(t.z));
- } // end of printTuple()
- } // end of PropManager class
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement