I also needed to get the point in world and local coordinates.  I lifted some code from
various sources to get the desired results.  Here is a snippet from my "pick" behavior
that should generate the correct values.  worldHitPoint and localHitPoint must be
instantiated before they are passed into pickTarget().


 // preconstructed in instance for speed
 transient private Point3d pickEyePos_ = new Point3d();
 transient private Point3d pickMousePos_ = new Point3d();
 transient private Transform3D pickXform_ = new Transform3D();
 transient private Vector3d pickRayDir_ = new Vector3d();
 transient private PickRay pickRay_ = new PickRay();
 transient private double pickDist_[] = {0.0};

/**
 * @param pickCanvas The canvas object that is the source of the mouse event
 * @param mouseX MouseEvent's x coordinate
 * @param mouseY MouseEvent's y coordinate
 * @param worldHitPoint World coordinate for a valid hit
 * @param localHitPoint Local coordinate for a valid hit
 * @return True if the intersection is with a valid object
 */
 public boolean pickTarget(Canvas3D pickCanvas,
                           int mouseX,
                           int mouseY,
                           Point3d worldHitPoint,
                           Point3d localHitPoint)
 {

  // build pick ray
  /// get display positions
  pickCanvas.getCenterEyeInImagePlate(pickEyePos_);
  pickCanvas.getPixelLocationInImagePlate(mouseX, mouseY,
                                          pickMousePos_);

  /// transform to world positions
  pickCanvas.getImagePlateToVworld(pickXform_);
  pickXform_.transform(pickEyePos_);
  pickXform_.transform(pickMousePos_);

  /// build world ray
  pickRayDir_.sub(pickMousePos_, pickEyePos_);
  pickRayDir_.normalize();
  pickRay_.set(pickEyePos_, pickRayDir_);

  // pick test according to flag
  SceneGraphPath hitPath[] = null;

  // geometry picking
  /// throw pick ray at bounds of objects under pick root
  hitPath = pickRoot_.pickAllSorted(pickRay_);

  /// if nothing hit, quit
  if (hitPath != null)
  {
      for (int i=0; i<hitPath.length; i++)
      {
        if (hitPath[i] != null)
        {
         /// check for real hit against geometry
        Node hitNode = hitPath[i].getObject();
        boolean isHit = false;

        if (hitNode instanceof Shape3D)
        {
          try
          {
           isHit = ((Shape3D) hitNode).intersect(hitPath[i], pickRay_, pickDist_);

           if (isHit)
           {
            worldHitPoint.scaleAdd(pickDist_[0], pickRayDir_, pickEyePos_);

            Transform3D t3d = new Transform3D();
            hitNode.getLocalToVworld(t3d);
            t3d.invert();
            t3d.transform(worldHitPoint, localHitPoint);
                return true;
              }
            }
            catch (CapabilityNotSetException e)
            {
              // Catch all CapabilityNotSet exceptions and
              // throw them away, prevents renderer from
              // locking up when encountering "non-selectable"
              // objects.
            }
          }
        }
      }
  }

  // no target hit
   return false;
 }

Hope this is helpful,

Weylin


Guillaume Bilodeau wrote:

> Hi,
>
>         Thank you for your answer.  It is indeed pretty complex and probably very 
>slow
> to do all those calculations.  Like you say, I hope Sun includes such a method
> in a future release, I know other 3D libraries offer it and I have to say, it is
> a must.
>
>         For now, if this could be of interest to anyone, I have resorted to an
> approximation of the 3d point.  I generate a PickRay with the PickObject class,
> get the closest Shape3D, and then get the associated Transform3D from the
> SceneGraphPath.  Then I use the z component of the Transform3D translation as an
> approximation for the z component of the picked point.  I finally use the
> PickRay vector to calculate the x and y components of the picked point.
>
>         This is obviously very approximate, but it still does a good job most of the
> time.
>
> >   After thinking about this some more it isn't so easy.  When I answered I
> > was looking at some code which manually intersects a ray and a single quad
> > from a generated ray, which does give the distance to the picked point.  It
> > is possible to do what you want but it will take quite a bit of code.
> > Maybe the Java3D team at Sun has a better solution???
> >
> > 1) pick the closest geometry using the mouse x,y
> > 2) get the picked Shape3D from the SceneGraphPath object returned by
> > pickClosest
> > 3) generate a ray using generatePickRay with the mouse x,y (the same ray
> > used to pick the Shape3D)
> > 4) intersect that ray with all the quads or tris in the Shap3D's geometry
> > (this is a lot of code for all the different geometry types)
> > 5) when you find an intersection use the distance, ray origin, and ray
> > vector as I described before to get your 3D point
> >
> > I would provide this code but it will take a while and I don't need it
> > right now.  This is vital functionality so maybe Sun will put it in a
> > future release.  It would be MUCH easier to do this inside the pickClosest
> > code where the needed information should already be available.
begin:vcard 
adr;dom:;;;Dallas;TX;75234;
n:Debetaz;Weylin
x-mozilla-html:FALSE
org:i2 Technologies
version:2.1
email;internet:[EMAIL PROTECTED]
title:Software Engineer
tel;fax:(214) 860-6067
tel;work:(214) 515-3789
x-mozilla-cpt:;0
fn:Weylin Debetaz
end:vcard

Reply via email to