⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 heightfinder.java

📁 java3D game engine design of the source [three-dimensionalvirtualrealitynetworkprogram] - "virtual
💻 JAVA
字号:

// HeightFinder.java
// Andrew Davison, August 2003, dandrew@ratree.psu.ac.th

/* HeightFinder was designed to hide the slowness of picking
   for such a large object (the mesh loaded from the landscape's 
   OBJ file).

   Picking is carried out by getLandHeight(), applied to the 
   landBG BranchGroup. getLandHeight() may take 1-2 seconds to
   complete.

   KeyBehaviour interacts with HeightFinder by calling 
   requestMoveHeight() which stores a (x,y,z) coordinate in theMove. 
   The y-value is a dummy, but the
   (x,z) pair will be used by getLandHeight() to get the y-height at 
   that point.

   requestMoveHeight() returns immediately; KeyBehavior does not wait
   for an answer, or it would be waiting for 1-2 seconds, maybe more.
   Instead, KeyBehavior simply uses the current y-height for its move.

   HeightFinder's run() method constantly loops: it reads the current
   move request from theMove, then calls getLandHeight(). At the end
   of getLandHeight(), the new height is passed back to KeyBehavior by
   calling its adjustHeight() method.

   This approach decouples KeyBehavior from the slow picking operation.
   The downside is that KeyBehavior will use an out-of-date height
   until told a new height by HeightFinder.

   KeyBehavior may send many move requests to HeightFinder while 
   getLandHeight() is slowly churing away, which is fine. When 
   getLandHeight() returns, run() will get the most recent request 
   from theMove and start picking again.

   This approach means that KeyBehavior can deal with very fast user
   keypresses, even though picking is slow. 
*/

import javax.media.j3d.*;
import javax.vecmath.*;
import com.sun.j3d.utils.picking.*;



public class HeightFinder extends Thread
{
  private final static Vector3d DOWN_VEC = new Vector3d(0.0,-1.0,0.0);

  private Landscape land;
  private KeyBehavior keyBeh;

  private PickTool picker;    // used to pick into the landscape
  private double scaleLen;
  private Vector3d theMove;   // holds the current move request from KeyBehavior
  private boolean calcRequested;


  public HeightFinder(Landscape ld, KeyBehavior kb)
  {
    land = ld;
    keyBeh = kb;

    picker = new PickTool(land.getLandBG());   // only check the landscape
    picker.setMode(PickTool.GEOMETRY_INTERSECT_INFO);

    scaleLen = land.getScaleLen();
    theMove = new Vector3d();
    calcRequested = false;
  }  // end of heightFinder()



  synchronized public void requestMoveHeight(Vector3d mv)
  // KeyBehaviour sends a new move request
  { 
    theMove.set(mv.x, mv.y, mv.z);    // this will overwrite any pending request
    calcRequested = true;
  }

  synchronized private Vector3d getMove()
  /* getLandHeight() gets the move request. A synchronized method
     is used so that the get cannot be mixed with a set if
     Keybehavior happens to call requestMoveHeight() at the same time.
  */
  { calcRequested = false;
    return new Vector3d(theMove.x, theMove.y, theMove.z);
  }


  public void run()
  /* Repeatedly get a move request and process it by picking.
     If there is no pending request (calcRequested == false), then
     sleep for a short time.
  */
  { Vector3d vec;
    while(true) {
      if (calcRequested) {
        vec = getMove();      // get the requested move
        getLandHeight(vec.x, vec.z);   // pick with it
      }
      else {   // no pending request
        try {
          Thread.sleep(200);    // sleep a little
        }
        catch(InterruptedException e) {}
      }
    }
  }  // end of run()



  private void getLandHeight(double x, double z)
  /* Picking is a bit flakey, especially near edges and corners,
     so if no PickResult is found, no intersections found, or the
     extraction of intersection coords fails, then keyBeh.adjustHeight()
     is not called.

     pickStart and the pick ray use world coordinates, but the
     intersection info is returned in landscape coords (floor is XY,
     height is Z). This means that the height must be converted to
     world coordinates (i.e. scaled) before being sent to KeyBehavior.
  */
  {
    Point3d pickStart = new Point3d(x, 2000, z);    // high up in world coords
    picker.setShapeRay(pickStart, DOWN_VEC);   // shoot a ray downwards in world coords

    PickResult picked = picker.pickClosest();
    // System.out.println("picked value: " + picked);

    if (picked != null) {    // pick sometimes misses at an edge/corner
      if (picked.numIntersections() != 0) {    // sometimes no intersects are found
        PickIntersection pi = picked.getIntersection(0);
        Point3d nextPt;
        try {   // handles 'Interp point outside quad' error
          nextPt = pi.getPointCoordinates();
          // System.out.println("Picked: " + nextPt);
        }
        catch (Exception e) {
           System.out.println(e);
           return;    // don't talk to KeyBehavior since no height was found
        }

        double nextYHeight = nextPt.z * scaleLen;    // z-axis land --> y-axis world
        // System.out.println("nextYHeight: " + nextYHeight);
        keyBeh.adjustHeight(nextYHeight);    // tell KeyBehavior the new height
      }
    }
  }  // end of getLandHeight()


}  // end of HeightFinder class

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -