Advertisement
Guest User

Untitled

a guest
Jan 22nd, 2017
110
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 18.37 KB | None | 0 0
  1. / PropManager.java
  2. // Andrew Davison, January 2003, ad@fivedots.coe.psu.ac.th
  3.  
  4. /* The user supplies the name of a 3D object file to be loaded.
  5.    Its bounding sphere is automatically scaled to have a radius
  6.    of 1 unit, and rotated -90 around x-axis if it is a 3ds model.
  7.  
  8.    A large range of different 3D object formats can be loaded
  9.    since we are using the Portfolio loaders.
  10.  
  11.    Once loaded, the image can be moved and rotated along the
  12.    X, Y, and Z axes, and scaled. The resulting position,
  13.    rotation, and scaling information can be stored in a
  14.    'coords' file (which has the same name as the 3D file
  15.    + "Coords.txt").
  16.  
  17.    The rotation information is stored as a series of rotation
  18.    *numbers* which must be executed in order to get to the curent
  19.    overall rotation:
  20.       1 = positive ROT_INCR around x-axis
  21.       2 = negative ROT_INCR around x-axis
  22.  
  23.       3 = positive ROT_INCR around y-axis
  24.       4 = negative ROT_INCR around y-axis
  25.  
  26.       5 = positive ROT_INCR around z-axis
  27.       6 = negative ROT_INCR around z-axis
  28.  
  29.    This approach is used to try to avoid the problem that a mix of
  30.    rotations about diffrent axes do not produce the same result if
  31.    carried out in different orders.
  32.  
  33.    The coordinates information can be loaded along with the object
  34.    by using:
  35.         java Loader3D -c <3D filename>
  36.  
  37.    The loaded object is hung off several TGs, and the top one can be
  38.    accessed by calling getTG().
  39.  
  40.    Changes:
  41.    - removed use of j3d-fly VRML loader and starfire 3DS loader
  42.  
  43.    March 2010
  44.      - fixed rotInfo generic typing
  45.      - used Java3D's ObjectFile to load wavefront files so material is correct
  46. */
  47.  
  48. import com.sun.j3d.loaders.*;
  49. import com.sun.j3d.loaders.objectfile.ObjectFile;
  50. import java.io.*;
  51. import java.text.DecimalFormat;
  52. import java.util.*;
  53. import javax.media.j3d.*;
  54. import javax.vecmath.*;
  55. import ncsa.j3d.loaders.*;
  56.  
  57.  
  58. public class PropManager
  59. {
  60.   // for specifying moves and rotations
  61.   private static final int X_AXIS = 0;
  62.   private static final int Y_AXIS = 1;
  63.   private static final int Z_AXIS = 2;
  64.   private static final int INCR = 0;
  65.   private static final int DECR = 1;
  66.  
  67.   private static final double MOVE_INCR = 0.1;   // move increment for an object
  68.   private static final double ROT_INCR = 10;     // rotation increment (in degrees)
  69.   private static final double ROT_AMT = Math.toRadians(ROT_INCR);    // in radians
  70.  
  71.  
  72.   // TGs which the loaded object (the prop) hangs off:
  73.   //       moveTG-->rotTG-->scaleTG-->objBoundsTG-->obj
  74.   private TransformGroup moveTG, rotTG, scaleTG;    
  75.   private Transform3D t3d;           // for accessing a TG's transform
  76.   private Transform3D chgT3d;        // holds current change to the posn, rot, or scale
  77.  
  78.   private String filename;           // of loaded object
  79.   private double xRot, yRot, zRot;   // total of rotation angles carried out
  80.   private ArrayList<Integer> rotInfo;         // stores the sequence of rotation numbers
  81.   private double scale;              // current object scaling
  82.  
  83.   private DecimalFormat df;    // for debugging
  84.  
  85.  
  86.   public PropManager(String loadFnm, boolean hasCoordsInfo)
  87.   {
  88.     filename = loadFnm;
  89.     xRot = 0.0; yRot = 0.0; zRot = 0.0;    // initial loaded object settings
  90.     rotInfo = new ArrayList<Integer>();
  91.     scale = 1.0;
  92.  
  93.     t3d = new Transform3D();     // setup reusable Transform3D objects
  94.     chgT3d = new Transform3D();
  95.  
  96.     df = new DecimalFormat("0.###");  // 3 dp
  97.  
  98.     loadFile(loadFnm);
  99.     if (hasCoordsInfo)     // load in coords info also
  100.       getFileCoords(loadFnm);
  101.   }  // end of PropManager()
  102.  
  103.  
  104.  
  105.   private void loadFile(String fnm)
  106.   /* The 3D object file is loaded using a Portfolio loader.
  107.  
  108.      The loaded object has 4 transform groups above it -- objBoundsTG is
  109.      for adjusting the object's bounded sphere so it is centered at
  110.      (0,0,0) and has unit radius.
  111.  
  112.      The other TGs are for doing separate moves, rotations, and scaling
  113.      of the object.
  114.         moveTG-->rotTG-->scaleTG-->objBoundsTG-->object
  115.   */
  116.   { System.out.println("C:/Users/LIRKIS PC/Desktop/pokusNytoolkit/src/models/" + fnm);
  117.  
  118.     String ext = getExtension(fnm);
  119.     Scene s = null;
  120.     try {
  121.       if (ext.equals("obj")) {   // the file is a wavefront model
  122.         // System.out.println("Loading obj file");
  123.         ObjectFile of = new ObjectFile ();
  124.         of.setFlags(ObjectFile.RESIZE | ObjectFile.TRIANGULATE | ObjectFile.STRIPIFY);
  125.         s = of.load("C:/Users/LIRKIS PC/Desktop/pokusNytoolkit/src/models/"+fnm);
  126.       }
  127.       else {  // use Portfolio loader for other models
  128.         ModelLoader modelLoader = new ModelLoader();
  129.         s = modelLoader.load("C:/Users/LIRKIS PC/Desktop/pokusNytoolkit/src/models/"+fnm);   // handles many types of file
  130.       }
  131.     }
  132.     catch (Exception e) {
  133.       System.err.println(e);
  134.       System.exit(1);
  135.     }
  136.  
  137.     // get the branch group for the loaded object
  138.     BranchGroup sceneGroup = s.getSceneGroup();
  139.  
  140.     // create a transform group for the object's bounding sphere
  141.     TransformGroup objBoundsTG = new TransformGroup();
  142.     objBoundsTG.addChild( sceneGroup );
  143.  
  144.     // resize loaded object's bounding sphere (and maybe rotate)
  145.     BoundingSphere objBounds = (BoundingSphere) sceneGroup.getBounds();
  146.     setBSPosn(objBoundsTG, objBounds.getRadius(), ext);
  147.  
  148.     // create a transform group for scaling the object
  149.     scaleTG = new TransformGroup();
  150.     scaleTG.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
  151.     scaleTG.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
  152.     scaleTG.addChild( objBoundsTG );
  153.  
  154.     // create a transform group for rotating the object
  155.     rotTG = new TransformGroup();
  156.     rotTG.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
  157.     rotTG.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
  158.     rotTG.addChild( scaleTG );
  159.  
  160.     // create a transform group for moving the object
  161.     moveTG = new TransformGroup();
  162.     moveTG.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
  163.     moveTG.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
  164.     moveTG.addChild( rotTG );
  165.  
  166.   } // end of loadFile()
  167.  
  168.  
  169.   private String getExtension(String fnm)
  170.   // return the extension of fnm, or "(none)"
  171.   {
  172.     int dotposn = fnm.lastIndexOf(".");
  173.     if (dotposn == -1)  // no extension
  174.       return "(none)";
  175.     else
  176.       return fnm.substring(dotposn+1).toLowerCase();
  177.   }
  178.  
  179.  
  180.   private void setBSPosn(TransformGroup objBoundsTG,
  181.                     double radius, String ext)
  182.   // Scale the object to unit radius, and rotate -90 around x-axis if the
  183.   // file contains a 3ds model
  184.   {
  185.     Transform3D objectTrans = new Transform3D();
  186.     objBoundsTG.getTransform( objectTrans );
  187.  
  188.     // System.out.println("radius: " + df.format(radius));
  189.  
  190.     // scale the object so its bounds are within a 1 unit radius sphere
  191.     Transform3D scaleTrans = new Transform3D();
  192.     double scaleFactor = 1.0/radius;
  193.     // System.out.println("scaleFactor: " + df.format(scaleFactor) );
  194.     scaleTrans.setScale( scaleFactor );
  195.  
  196.     // final transform = [original] * [scale] (and possible *[rotate])
  197.     objectTrans.mul(scaleTrans);
  198.    
  199.     if (ext.equals("3ds")) {   // the file is a 3ds model
  200.       // System.out.println("Rotating -90 around x-axis");
  201.       Transform3D rotTrans = new Transform3D();
  202.       rotTrans.rotX( -Math.PI/2.0 );    // 3ds models are often on their face; fix that
  203.       objectTrans.mul(rotTrans);
  204.     }
  205.  
  206.     objBoundsTG.setTransform(objectTrans);
  207.   } // end of setBSPosn()
  208.  
  209.  
  210.   public TransformGroup getTG()
  211.   // used by WrapLoader3D to add object to 3D world
  212.   {  return moveTG; }
  213.  
  214.  
  215.   // ----------------------------------------------------------------
  216.   // obtain coords file info and apply it to the loaded object
  217.  
  218.  
  219.   private void getFileCoords(String fnm)
  220.   /* Obtain coords info from the coordinates file for fnm.
  221.      The coords file has the format:
  222.          <3D object fnm>
  223.          [-p px py pz]
  224.          [-r sequence of numbers]
  225.          [-s scale]
  226.   */
  227.   {
  228.     String coordFile = "C:/Users/LIRKIS PC/Desktop/pokusNytoolkit/src/models/" + getName(fnm) + "Coords.txt";
  229.     try {
  230.       BufferedReader br = new BufferedReader( new FileReader(coordFile));
  231.       br.readLine();    // skip fnm line (we know this already)
  232.       String line;
  233.       char ch;
  234.       while((line = br.readLine()) != null) {
  235.         ch = line.charAt(1);
  236.         if (ch == 'p')
  237.           setCurrentPosn(line);
  238.         else if (ch == 'r')
  239.           setCurrentRotation(line);
  240.         else if (ch == 's')
  241.           setCurrentScale(line);
  242.         else
  243.           System.out.println(coordFile + ": did not recognise line: " + line);
  244.       }
  245.       br.close();
  246.       System.out.println("Read in coords file: " + coordFile);
  247.     }
  248.     catch (IOException e)
  249.     { System.out.println("Error reading coords file: " + coordFile);
  250.       System.exit(1);
  251.     }
  252.   }  // end of getFileCoords()
  253.  
  254.  
  255.  
  256.   private String getName(String fnm)
  257.   // extract name before the final '.' suffix
  258.   {
  259.     int dotposn = fnm.lastIndexOf(".");
  260.     if (dotposn == -1)  // no extension
  261.       return fnm;
  262.     else
  263.       return fnm.substring(0, dotposn);
  264.   }
  265.  
  266.  
  267.   private void setCurrentPosn(String line)
  268.   // extract the (x,y,z) position info from the coords file,
  269.   // then apply it to the loaded object
  270.   {
  271.     double vals[] = new double[3];            // for the position data
  272.     vals[0] = 0; vals[1] = 0; vals[2] = 0;    // represents (x,y,z)
  273.  
  274.     StringTokenizer tokens = new StringTokenizer(line);
  275.     String token = tokens.nextToken();    // skip command label
  276.     int count = 0;
  277.     while (tokens.hasMoreTokens()) {
  278.       token = tokens.nextToken();
  279.       try {
  280.         vals[count] = Double.parseDouble(token);
  281.         count++;
  282.       }
  283.       catch (NumberFormatException ex){
  284.         System.out.println("Incorrect format for position data in coords file");
  285.         break;
  286.       }
  287.     }
  288.     if (count != 3)
  289.       System.out.println("Insufficient position data in coords file");
  290.  
  291.     // apply the moves to the loaded object
  292.     doMove( new Vector3d( vals[0], vals[1], vals[2]) );
  293.  
  294.   }  // end of setCurrentPosn()
  295.  
  296.  
  297.  
  298.   private void setCurrentRotation(String line)
  299.   // extract the rotation info from the coords file,
  300.   // and apply it to the loaded object
  301.   {
  302.     int rotNum;
  303.     StringTokenizer tokens = new StringTokenizer(line);
  304.     String token = tokens.nextToken();    // skip command label
  305.     if (!tokens.hasMoreTokens())   // there may not be any rotation numbers
  306.       return;
  307.     token = tokens.nextToken();
  308.     for (int i=0; i < token.length(); i++) {
  309.       try {
  310.         rotNum = Character.digit(token.charAt(i),10);
  311.         // rotInfo.add( new Integer(rotNum));
  312.       }
  313.       catch (NumberFormatException ex){
  314.         System.out.println("Incorrect format for rotation data in coords file");
  315.         break;
  316.       }
  317.       if (rotNum == 1)         // positive x-axis rotation
  318.         rotate(X_AXIS, INCR);  
  319.       else if (rotNum == 2)    // negative
  320.         rotate(X_AXIS, DECR);
  321.       else if (rotNum == 3)    // positive y-axis rotation
  322.         rotate(Y_AXIS, INCR);  
  323.       else if (rotNum == 4)    // negative
  324.         rotate(Y_AXIS, DECR);
  325.       else if (rotNum == 5)    // positive z-axis rotation
  326.         rotate(Z_AXIS, INCR);  
  327.       else if (rotNum == 6)    // negative
  328.         rotate(Z_AXIS, DECR);
  329.       else
  330.         System.out.println("Did not recognise the rotation info in the coords file");
  331.     }
  332.   }  // end of setCurrentRotation()
  333.  
  334.  
  335.  
  336.  
  337.   private void setCurrentScale(String line)
  338.   // extract the scale info from the coords file,
  339.   // and apply it to the loaded object
  340.   {
  341.     StringTokenizer tokens = new StringTokenizer(line);
  342.     String token = tokens.nextToken();    // skip command label
  343.     double startScale;
  344.  
  345.     token = tokens.nextToken();    // should be the scale value
  346.     try {
  347.       startScale = Double.parseDouble(token);
  348.     }
  349.     catch (NumberFormatException ex){
  350.       System.out.println("Incorrect format for scale data in coords file");
  351.       startScale = 1.0;
  352.     }
  353.     // System.out.println("Loaded start scale: " + startScale);
  354.     if (startScale != 1.0) {
  355.       scale(startScale);
  356.     }
  357.   }  // end of setCurrentScale()
  358.  
  359.  
  360.  
  361.   //---------------------------------------------------------
  362.   // modify the position/rotation/scale of the loaded object
  363.  
  364.   /* These methods are called when applying the coords file
  365.      information *and* when user commands sent from the GUI
  366.      are being processed.
  367.   */
  368.  
  369.  
  370.   public void move(int axis, int change)
  371.   // move the object along an axis
  372.   {
  373.     double moveStep = (change == INCR) ? MOVE_INCR : -MOVE_INCR ;
  374.     Vector3d moveVec;
  375.     if (axis == X_AXIS)
  376.       moveVec = new Vector3d(moveStep,0,0);
  377.     else if (axis == Y_AXIS)
  378.       moveVec = new Vector3d(0,moveStep,0);
  379.     else   // Z_AXIS
  380.       moveVec = new Vector3d(0,0,moveStep);
  381.     doMove( moveVec );
  382.   }  // end of move()
  383.  
  384.  
  385.   private void doMove(Vector3d theMove)
  386.   // move the object by theMove amount
  387.   {
  388.     moveTG.getTransform(t3d);        // get current position from TG
  389.     chgT3d.setIdentity();            // reset change Trans
  390.     chgT3d.setTranslation(theMove);  // setup move
  391.     t3d.mul(chgT3d);                 // 'add' move to current position
  392.     moveTG.setTransform(t3d);        // update TG
  393.   }  // end of doMove()
  394.  
  395.  
  396.  
  397.   public void rotate(int axis, int change)
  398.   // rotate the object about an axis, and remember the change
  399.   {
  400.     doRotate(axis, change);
  401.     storeRotate(axis, change);
  402.   }  // end of rotate()
  403.  
  404.  
  405.   private void doRotate(int axis, int change)
  406.   // rotate the object about the axis by radians amount
  407.   {
  408.     double radians = (change == INCR) ? ROT_AMT : -ROT_AMT;
  409.     rotTG.getTransform(t3d);     // get current rotation from TG
  410.     chgT3d.setIdentity();        // reset change Trans
  411.     switch (axis) {              // setup new rotation
  412.       case X_AXIS: chgT3d.rotX(radians); break;
  413.       case Y_AXIS: chgT3d.rotY(radians); break;
  414.       case Z_AXIS: chgT3d.rotZ(radians); break;
  415.       default: System.out.println("Unknown axis of rotation"); break;
  416.     }
  417.     t3d.mul(chgT3d);     // 'add' new rotation to current one
  418.     rotTG.setTransform(t3d);     // update the TG
  419.   }  // end of doRotate()
  420.  
  421.  
  422.   private void storeRotate(int axis, int change)
  423.   // store the rotation information
  424.   {
  425.     double degrees = (change == INCR) ? ROT_INCR : -ROT_INCR;
  426.     switch (axis) {
  427.       case X_AXIS: storeRotateX(degrees); break;
  428.       case Y_AXIS: storeRotateY(degrees); break;
  429.       case Z_AXIS: storeRotateZ(degrees); break;
  430.       default: System.out.println("Unknown storage axis of rotation"); break;
  431.     }
  432.   }  // end of storeRotate()
  433.  
  434.  
  435.   private void storeRotateX(double degrees)
  436.   // record the x-axis rotation
  437.   {
  438.     xRot = (xRot+degrees)%360;   // update x-axis total rotation
  439.     if (degrees == ROT_INCR)
  440.       rotInfo.add(new Integer(1));  // rotation number
  441.     else if (degrees == -ROT_INCR)
  442.        rotInfo.add(new Integer(2));
  443.     else
  444.       System.out.println("No X-axis rotation number for " + degrees);
  445.   } // end of storeRotateX()
  446.  
  447.  
  448.   private void storeRotateY(double degrees)
  449.   // record the y-axis rotation
  450.   {
  451.     yRot = (yRot+degrees)%360;   // update y-axis total rotation
  452.     if (degrees == ROT_INCR)
  453.       rotInfo.add(new Integer(3));  // rotation number
  454.     else if (degrees == -ROT_INCR)
  455.        rotInfo.add(new Integer(4));
  456.     else
  457.       System.out.println("No Y-axis rotation number for " + degrees);
  458.   } // end of storeRotateY()
  459.  
  460.  
  461.   private void storeRotateZ(double degrees)
  462.   // record the z-axis rotation
  463.   {
  464.     zRot = (zRot+degrees)%360;   // update z-axis total rotation
  465.     if (degrees == ROT_INCR)
  466.       rotInfo.add(new Integer(5));  // rotation number
  467.     else if (degrees == -ROT_INCR)
  468.        rotInfo.add(new Integer(6));
  469.     else
  470.       System.out.println("No Z-axis rotation number for " + degrees);
  471.   } // end of storeRotateZ()
  472.  
  473.  
  474.   public void scale(double d)
  475.   // Scale the object by d units
  476.   {
  477.     scaleTG.getTransform(t3d);    // get current scale from TG
  478.     chgT3d.setIdentity();         // reset change Trans
  479.     chgT3d.setScale(d);           // set up new scale
  480.     t3d.mul(chgT3d);              // multiply new scale to current one
  481.     scaleTG.setTransform(t3d);    // update the TG
  482.  
  483.     scale *= d;    // update scale variable
  484.   }  // end of scale()
  485.  
  486.  
  487.  
  488.   // ----------------------------------------------------------
  489.   // return current position/rotation/scale information
  490.   // Used by the GUI interface
  491.  
  492.  
  493.   public Vector3d getLoc()
  494.   {
  495.     moveTG.getTransform(t3d);
  496.     Vector3d trans = new Vector3d();
  497.     t3d.get(trans);
  498.     // printTuple(trans, "getLoc");
  499.     return trans;
  500.   } // end of getLoc()
  501.  
  502.  
  503.   public Point3d getRotations()
  504.   {  return new Point3d(xRot, yRot, zRot);  }
  505.  
  506.   public double getScale()
  507.   {  return scale;  }
  508.  
  509.  
  510.   // ------------------------------ storing ---------------------------
  511.  
  512.  
  513.   public void saveCoordFile()
  514.   // create a coords file for this object
  515.   {
  516.     String coordFnm = "C:/Users/LIRKIS PC/Desktop/pokusNytoolkit/src/models/" + getName(filename) + "Coords.txt";
  517.     try {
  518.       PrintWriter out = new PrintWriter( new FileWriter(coordFnm));
  519.  
  520.       out.println(filename);     // object filename
  521.       Vector3d currLoc = getLoc();
  522.       out.println("-p " + df.format(currLoc.x) + " " + df.format(currLoc.y) +
  523.                         " " + df.format(currLoc.z) );
  524.       out.print("-r ");
  525.       for (int i=0; i < rotInfo.size(); i++)
  526.          out.print( ""+((Integer) rotInfo.get(i)).intValue() );
  527.       out.println("");
  528.  
  529.       out.println("-s " + df.format(scale) );
  530.  
  531.       out.close();
  532.       System.out.println("Saved to coord file: " + coordFnm);
  533.     }
  534.     catch(IOException e)
  535.     { System.out.println("Error writing to coord file: " + coordFnm); }
  536.   }  // end of saveCoordFile()
  537.  
  538.  
  539.  
  540.   // --------------------- methods used for debugging --------------------------
  541.  
  542.  
  543.   private void printTG(TransformGroup tg, String id)
  544.   // print the translation stored in tg
  545.   {
  546.     Transform3D currt3d = new Transform3D( );
  547.     tg.getTransform( currt3d );
  548.     Vector3d currTrans = new Vector3d( );
  549.     currt3d.get( currTrans );
  550.     printTuple( currTrans, id);
  551.   }  // end of printTG()
  552.  
  553.  
  554.   private void printTuple(Tuple3d t, String id)
  555.   // used to print Vector3d, Point3d objects
  556.   {
  557.     System.out.println(id + " x: " + df.format(t.x) +
  558.                 ", " + id + " y: " + df.format(t.y) +
  559.                 ", " + id + " z: " + df.format(t.z));
  560.   }  // end of printTuple()
  561.  
  562.  
  563. }  // end of PropManager class
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement