All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.j3d.utils.behaviors.picking.PickObject Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistribution of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Redistribution in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in
 *   the documentation and/or other materials provided with the
 *   distribution.
 *
 * Neither the name of Sun Microsystems, Inc. or the names of
 * contributors may be used to endorse or promote products derived
 * from this software without specific prior written permission.
 *
 * This software is provided "AS IS," without a warranty of any
 * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
 * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
 * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL
 * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
 * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR
 * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
 * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
 * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
 * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGES.
 *
 * You acknowledge that this software is not designed, licensed or
 * intended for use in the design, construction, operation or
 * maintenance of any nuclear facility.
 *
 */

/*
New Base level methods:

ISSUE :
        How about PickPoint and PickSegment ?

DONE :
	PickShape generatePickRay(int x, int y)

	SceneGraphPath[] pickAll(int x, int y)
	SceneGraphPath[] pickAllSorted(int x, int y)
	SceneGraphPath   pickAny(int x, int y)
	SceneGraphPath   pickClosest(int x, int y)

	Node getPickedNode(SceneGraphPath, flag)
	Node getPickedNode(SceneGraphPath, flag, int count)
	       where flag can be any combo of:
		       Group, Morph, Primitive, Shape3D,
		       TransformGroup, Switch


TODO :
	SceneGraphPath[] pickGeomAll(int x, int y)
        SceneGraphPath[] pickGeomAllSorted(int x, int y)
        SceneGraphPath   pickGeomAny(int x, int y)
	SceneGraphPath   pickGeomClosest(int x, int y)

	bool intersect(SceneGraphPath, PickShape)


        Eventually:
        	getClosestVtx(ScenGraphPath, PickShape)


Misc:
	Mouse should stay on top of object it is dragging

	*/

package com.sun.j3d.utils.behaviors.picking;

import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.Group;
import javax.media.j3d.Link;
import javax.media.j3d.Morph;
import javax.media.j3d.Node;
import javax.media.j3d.PickRay;
import javax.media.j3d.PickShape;
import javax.media.j3d.SceneGraphPath;
import javax.media.j3d.Shape3D;
import javax.media.j3d.Switch;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.media.j3d.View;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3d;

import com.sun.j3d.utils.geometry.Primitive;

/*
 * Contains methods to aid in picking.  A PickObject is created
 * for a given Canvas3D and a BranchGroup.  SceneGraphObjects
 * under the specified BranchGroup can then be checked to determine
 * if they have been picked.
 */

/**
 * @deprecated As of Java 3D version 1.2, replaced by
 * com.sun.j3d.utils.picking.PickCanvas
 *
 * @see com.sun.j3d.utils.picking.PickCanvas
 */

public class PickObject extends Object {

  // Have to rethink what to support. Is this complete.

  /**
   * A flag to indicate to the pickNode method to return a
   * Shape3D node from
   * a given SceneGraphPath.
   *
   * @see PickObject#pickNode
   */
  public static final int SHAPE3D = 0x1;

  /**
   * A flag to indicate to the pickNode method to return a
   * Morph node from
   * a given SceneGraphPath.
   *
   * @see PickObject#pickNode
   */
  public static final int MORPH = 0x2;

  /**
   * A flag to indicate to the pickNode method to return a
   * Primitive node
   * from a given SceneGraphPath.
   *
   * @see PickObject#pickNode
   */
  public static final int PRIMITIVE = 0x4;

  /**
   * A flag to indicate to the pickNode method to return a
   * Link node from
   * a given SceneGraphPath.
   *
   * @see PickObject#pickNode
   */
  public static final int LINK = 0x8;

  /**
   * A flag to indicate to the pickNode method to return a
   * Group node from
   * a given SceneGraphPath.
   *
   * @see PickObject#pickNode
   */
  public static final int GROUP = 0x10;

  /**
   * A flag to indicate to the pickNode method to return a
   * TransformGroup
   * node from a given SceneGraphPath.
   *
   * @see PickObject#pickNode
   */
  public static final int TRANSFORM_GROUP = 0x20;

  /**
   * A flag to indicate to the pickNode method to return a
   * BranchGroup
   * node from a given SceneGraphPath.
   *
   * @see PickObject#pickNode
   */
  public static final int BRANCH_GROUP = 0x40;

  /**
   * A flag to indicate to the pickNode method to return a
   * Switch node from
   * a given SceneGraphPath.
   *
   * @see PickObject#pickNode
   */
  public static final int SWITCH = 0x80;


  /**
   * Set this flag if you want to pick by geometry.
   */
  public static final int USE_GEOMETRY = 0x100;


  /**
   * Set this flag if you want to pick by bounds.
   */
  public static final int USE_BOUNDS = 0x200;

  BranchGroup pickRoot;
  Canvas3D canvas;
  Point3d origin = new Point3d();
  Vector3d direction = new Vector3d();
  PickRay pickRay = new PickRay();
  SceneGraphPath sceneGraphPath = null;
  SceneGraphPath sceneGraphPathArr[] = null;
  int pickBy;    // To pick by Bounds or Geometry.

  static final boolean debug = false;

  /**
   * Creates a PickObject.
   * @param c Current J3D canvas.
   * @param root The portion of the scenegraph for which picking is to occur
   * on.  It has to be a BranchGroup.
   *
   * @see BranchGroup
   * @see Canvas3D
   */
  public PickObject(Canvas3D c, BranchGroup root)
    {
      pickRoot = root;
      canvas = c;
    }

  /**
   * Creates a PickRay that starts at the viewer position and points into
   * the scene in the direction of (xpos, ypos) specified in window space.
   *
   * @param xpos The value along the x-axis.
   * @param ypos The value along the y-axis.
   * @return A PickShape object that is the constructed PickRay.
   */
  public PickShape generatePickRay(int xpos, int ypos)
    {

      Transform3D motion=new Transform3D();
      Point3d eyePosn = new Point3d();
      Point3d mousePosn = new Point3d();
      Vector3d mouseVec=new Vector3d();

      canvas.getCenterEyeInImagePlate(eyePosn);
      canvas.getPixelLocationInImagePlate(xpos,ypos,mousePosn);
      if (canvas.getView().getProjectionPolicy() ==
                                View.PARALLEL_PROJECTION) {
          // Correct for the parallel projection: keep the eye's z
          // coordinate, but make x,y be the same as the mouse, this
          // simulates the eye being at "infinity"
	  eyePosn.x = mousePosn.x;
	  eyePosn.y = mousePosn.y;
      }

      canvas.getImagePlateToVworld(motion);

      if (debug) {
	System.out.println("mouse position " + xpos + " " + ypos);
	System.out.println("before, mouse " + mousePosn + " eye " + eyePosn);
      }

      motion.transform(eyePosn);
      motion.transform(mousePosn);
      mouseVec.sub(mousePosn, eyePosn);
      mouseVec.normalize();

      if (debug) {
	System.out.println(motion + "\n");
	System.out.println("after, mouse " + mousePosn + " eye " + eyePosn +
			   " mouseVec " + mouseVec);
      }

      pickRay.set(eyePosn, mouseVec);

      return (PickShape) pickRay;

    }

  /**
   * Returns an array referencing all the items that are pickable below the
   * BranchGroup (specified in the PickObject constructor) that
   * intersect with a ray that starts at the
   * viewer position and points into the scene in the direction of (xpos, ypos)
   * specified in window space. The resultant array is unordered.
   *
   * @param xpos The value along the x-axis.
   * @param ypos The value along the y-axis.
   * @return The array of SceneGraphPath objects that contain Objects that
   *  were picked
   * If no pickable object is found null is returned..
   *
   * @see SceneGraphPath
   */
  public SceneGraphPath[] pickAll(int xpos, int ypos)
    {
      pickRay = (PickRay) generatePickRay(xpos, ypos);
      sceneGraphPathArr = pickRoot.pickAll(pickRay);
      return sceneGraphPathArr;
    }

  /**
   * Returns a sorted array of references to all the Pickable items below the
   * BranchGroup (specified in the PickObject constructor) that
   * intersect with the ray that starts at the viewer
   * position and points into the scene in the direction of (xpos, ypos)
   * in the window space.
   * Element [0] references the item closest to viewer.
   *
   * @param xpos The value along the x-axis.
   * @param ypos The value along the y-axis.
   * @return A sorted arrayof SceneGraphPath objects that contain Objects that
   * were picked.  The array is sorted from closest to farthest from the
   * viewer
   * If no pickable object is found null is returned..
   *
   * @see SceneGraphPath
   */
  public SceneGraphPath[] pickAllSorted(int xpos, int ypos)
    {
      pickRay = (PickRay) generatePickRay(xpos, ypos);
      sceneGraphPathArr = pickRoot.pickAllSorted(pickRay);
      return sceneGraphPathArr;
    }

  /**
   * Returns a reference to any item that is Pickable below the specified
   * BranchGroup (specified in the PickObject constructor) which
   *  intersects with the ray that starts at the viewer
   * position and points into the scene in the direction of (xpos, ypos) in
   * window space.
   *
   * @param xpos The value along the x-axis.
   * @param ypos The value along the y-axis.
   * @return A SceneGraphPath of an object that was picked.  This is not
   * guarenteed to return the same result for multiple picks
   * If no pickable object is found null is returned..
   *
   * @see SceneGraphPath
   */
  public SceneGraphPath pickAny(int xpos, int ypos)
    {
      pickRay = (PickRay) generatePickRay(xpos, ypos);
      sceneGraphPath = pickRoot.pickAny(pickRay);
      return sceneGraphPath;
    }

  /**
   * Returns a reference to the item that is closest to the viewer and is
   * Pickable below the BranchGroup (specified in the PickObject
   * constructor) which intersects with the ray that starts at
   * the viewer position and points into the scene in the direction of
   * (xpos, ypos) in the window space.
   *
   * @param xpos The value along the x-axis.
   * @param ypos The value along the y-axis.
   * @return A SceneGraphPath which contains the closest pickable object.
   * If no pickable object is found, null is returned.
   *
   * @see SceneGraphPath
   */
  public SceneGraphPath pickClosest(int xpos, int ypos)
    {
      pickRay = (PickRay) generatePickRay(xpos, ypos);
      sceneGraphPath = pickRoot.pickClosest(pickRay);
      return sceneGraphPath;
    }


  /**
   * Returns an array referencing all the items that are pickable below the
   * BranchGroup (specified in the PickObject constructor) that
   * intersect with a ray that starts at the
   * viewer position and points into the scene in the direction of (xpos, ypos)
   * specified in window space. The resultant array is unordered.
   *
   * @param xpos The value along the x-axis.
   * @param ypos The value along the y-axis.
   * @param flag Specifys picking by Geometry or Bounds.
   * @return The array of SceneGraphPath objects that contain Objects that
   *  were picked
   * If no pickable object is found null is returned..
   *
   * @see SceneGraphPath
   */
  public SceneGraphPath[] pickAll(int xpos, int ypos, int flag)
    {

      if(flag == USE_BOUNDS) {
	return pickAll(xpos, ypos);
      }
      else if(flag == USE_GEOMETRY) {
	return pickGeomAll(xpos, ypos);
      }
      else
	return null;
    }

  /**
   * Returns a sorted array of references to all the Pickable items below the
   * BranchGroup (specified in the PickObject constructor) that
   * intersect with the ray that starts at the viewer
   * position and points into the scene in the direction of (xpos, ypos)
   * in the window space.
   * Element [0] references the item closest to viewer.
   *
   * @param xpos The value along the x-axis.
   * @param ypos The value along the y-axis.
   * @param flag Specifys picking by Geometry or Bounds.
   * @return A sorted arrayof SceneGraphPath objects that contain Objects that
   * were picked.  The array is sorted from closest to farthest from the
   * viewer
   * If no pickable object is found null is returned..
   *
   * @see SceneGraphPath
   */
  public SceneGraphPath[] pickAllSorted(int xpos, int ypos, int flag)
    {

      if(flag == USE_BOUNDS) {
	return pickAllSorted(xpos, ypos);
      }
      else if(flag == USE_GEOMETRY) {
	return pickGeomAllSorted(xpos, ypos);
      }
      else
	return null;

    }

  /**
   * Returns a reference to any item that is Pickable below the specified
   * BranchGroup (specified in the PickObject constructor) which
   *  intersects with the ray that starts at the viewer
   * position and points into the scene in the direction of (xpos, ypos) in
   * window space.
   *
   * @param xpos The value along the x-axis.
   * @param ypos The value along the y-axis.
   * @param flag Specifys picking by Geometry or Bounds.
   * @return A SceneGraphPath of an object that was picked.  This is not
   * guarenteed to return the same result for multiple picks
   * If no pickable object is found null is returned..
   *
   * @see SceneGraphPath
   */
  public SceneGraphPath pickAny(int xpos, int ypos, int flag)
    {

      if(flag == USE_BOUNDS) {
	return pickAny(xpos, ypos);
      }
      else if(flag == USE_GEOMETRY) {
	return pickGeomAny(xpos, ypos);
      }
      else
	return null;
    }

  /**
   * Returns a reference to the item that is closest to the viewer and is
   * Pickable below the BranchGroup (specified in the PickObject
   * constructor) which intersects with the ray that starts at
   * the viewer position and points into the scene in the direction of
   * (xpos, ypos) in the window space.
   *
   * @param xpos The value along the x-axis.
   * @param ypos The value along the y-axis.
   * @param flag Specifys picking by Geometry or Bounds.
   * @return A SceneGraphPath which contains the closest pickable object.
   * If no pickable object is found, null is returned.
   *
   * @see SceneGraphPath
   */
  public SceneGraphPath pickClosest(int xpos, int ypos, int flag)
    {

      if(flag == USE_BOUNDS) {
	return pickClosest(xpos, ypos);
      }
      else if(flag == USE_GEOMETRY) {
	return pickGeomClosest(xpos, ypos);
      }
      else
	return null;
    }

  private SceneGraphPath[] pickGeomAll(int xpos, int ypos)
    {
      Node obj;
      int i, cnt=0;

      pickRay = (PickRay) generatePickRay(xpos, ypos);
      sceneGraphPathArr = pickRoot.pickAll(pickRay);

      if(sceneGraphPathArr == null)
	return null;

      boolean found[] = new boolean[sceneGraphPathArr.length];

      for(i=0; inull is returned.
   */
  public Node pickNode(SceneGraphPath sgPath, int flags)
    {

      if (sgPath != null) {
	Node pickedNode = sgPath.getObject();

	if ((pickedNode instanceof Shape3D) && ((flags & SHAPE3D) != 0)){
	  if (debug) System.out.println("Shape3D found");
	  return pickedNode;
	}
	else if ((pickedNode instanceof Morph) && ((flags & MORPH) != 0)){
	  if (debug) System.out.println("Morph found");
	  return pickedNode;
	}
	else {
	  for (int j=sgPath.nodeCount()-1; j>=0; j--){
	    pickedNode = sgPath.getNode(j);
	    if (debug) System.out.println("looking at node " + pickedNode);

	    if ((pickedNode instanceof Primitive) &&
		((flags & PRIMITIVE) != 0)){
	      if (debug) System.out.println("Primitive found");
	      return pickedNode;
	    }
	    else if ((pickedNode instanceof Link) && ((flags & LINK) != 0)){
	      if (debug) System.out.println("Link found");
	      return pickedNode;
	    }
	    else if ((pickedNode instanceof Switch) && ((flags & SWITCH) != 0)){
	      if (debug) System.out.println("Switch found");
	      return pickedNode;
	    }
	    else if ((pickedNode instanceof TransformGroup) &&
		     ((flags & TRANSFORM_GROUP) != 0)){
	      if (debug) System.out.println("xform group found");
	      return pickedNode;
	    }
	    else if ((pickedNode instanceof BranchGroup) &&
                     ((flags & BRANCH_GROUP) != 0)){
	      if (debug) System.out.println("Branch group found");
	      return pickedNode;
	    }
	    else if ((pickedNode instanceof Group) && ((flags & GROUP) != 0)){
	      if (debug) System.out.println("Group found");
	      return pickedNode;
	    }
	  }

	  if (pickedNode == null)
	    if (debug) System.out.println("ERROR: null SceneGraphPath");
	}

      }

      return null;

    }


  /**
   * Returns a reference to a Pickable Node that
   * is of the specified type
   * that is contained in the specified SceneGraphPath.
   * The Node returned is the nth occurrence
   * of a Node that is of the specified type.
   *
   * @param sgPath the SceneGraphPath to be traversed.
   * @param flags the Node types interested.
   * @param occurrence the occurrence of a Node that
   * matches the specified type to return.  An occurrence of
   * 1 means to return the first occurrence of that object type (the object
   * closest to the Locale).
   * @return the nth occurrence of a Node
   * of type flags, starting from the Locale. If no pickable object is
   * found, null is returned.
   */
  public Node pickNode(SceneGraphPath sgPath, int flags, int occurrence)
    {
      int curCnt=0;

      if (sgPath != null) {
	Node pickedNode = sgPath.getObject();

	// Shape3D and Morph are leaf nodes and have no children. It doesn't
        // make sense to do occurrence check here. We'll just return it for now.
	if ((pickedNode instanceof Shape3D) && ((flags & SHAPE3D) != 0)){
	  if (debug) System.out.println("Shape3D found");
	  return pickedNode;
	} else if ((pickedNode instanceof Morph) && ((flags & MORPH) != 0)){
	  if (debug) System.out.println("Morph found");
	  return pickedNode;
	}
	else {
	  for (int j = 0; j < sgPath.nodeCount(); j++){
	    pickedNode = sgPath.getNode(j);
	    if (debug) System.out.println("looking at node " + pickedNode);

	    if ((pickedNode instanceof Group) && ((flags & GROUP) != 0)){
	      if (debug) System.out.println("Group found");
	      curCnt++;
	      if(curCnt == occurrence)
		return pickedNode;
	    }
	    else if ((pickedNode instanceof BranchGroup) &&
                    ((flags & BRANCH_GROUP) != 0)){
	      if (debug) System.out.println("Branch group found");
	      curCnt++;
	      if(curCnt == occurrence)
		return pickedNode;
	    }
	    else if ((pickedNode instanceof TransformGroup) &&
                    ((flags & TRANSFORM_GROUP) != 0)){
	      if (debug) System.out.println("xform group found");
	      curCnt++;
	      if(curCnt == occurrence)
		return pickedNode;
	    }
	    else if ((pickedNode instanceof Primitive) &&
                    ((flags & PRIMITIVE) != 0)){
	      if (debug) System.out.println("Primitive found");
	      curCnt++;
	      if(curCnt == occurrence)
		return pickedNode;
	    }
	    else if ((pickedNode instanceof Link) && ((flags & LINK) != 0)){
	      if (debug) System.out.println("Link found");
	      curCnt++;
	      if(curCnt == occurrence)
		return pickedNode;
	    }
	  }

	  if (pickedNode == null)
	    if (debug) System.out.println("ERROR: null SceneGraphPath");
	}

      }

      return null;

    }

}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy