/** * Copyright (c) 2003-2009, Xith3D Project Group all rights reserved. * * Portions based on the Java3D interface, Copyright by Sun Microsystems. * Many thanks to the developers of Java3D and Sun Microsystems for their * innovation and design. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions 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 the 'Xith3D Project Group' nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) A * RISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE */ package org.xith3d.picking; import org.jagatoo.input.devices.components.MouseButton; import org.jagatoo.util.errorhandling.UnsupportedFunction; import org.openmali.vecmath2.Point3f; import org.openmali.vecmath2.Ray3f; import org.openmali.vecmath2.Tuple3f; import org.openmali.vecmath2.Vector3f; import org.xith3d.scenegraph.Geometry; import org.xith3d.scenegraph.Leaf; import org.xith3d.scenegraph.Node; import org.xith3d.scenegraph.Shape3D; import org.xith3d.scenegraph.Transform3D; /** * Result of a picking action. * * @author Arne Mueller * @author Amos Wenger (aka BlueSky) * @author Marvin Froehlich (aka Qudus) */ public class PickResult implements Comparable< PickResult > { private Leaf node; // the Leaf that got picked at (with this PickResult) private int faceIndex; // the index of the face that got picked (PickingLibrary only!) protected Tuple3f tmpPos = new Point3f(); private Tuple3f pos; private float minDistance; // minimum distance of the intersection private float maxDistance; // maximum distance of the intersection private float medDistance; // medial distance of the intersection private Transform3D tmpTrans = new Transform3D(); private MouseButton button; /** * Creates a new instance of PickResult. */ public PickResult( Leaf node, float minDist, float maxDist, float medDist ) { this( node, -1, minDist, maxDist, medDist ); } /** * Creates a new instance of PickResult. */ public PickResult( Leaf node, int faceIndex, float minDist, float maxDist, float medDist ) { this.node = node; this.faceIndex = faceIndex; this.pos = null; this.minDistance = minDist; this.maxDistance = maxDist; this.medDistance = medDist; this.button = null; } /** * Creates a new instance of PickResult. */ public PickResult( Leaf node, float dist ) { this( node, dist, dist, dist ); } /** * Creates a new instance of PickResult. */ PickResult() { } /** * Creates a new instance of PickResult. */ void set( Leaf node, float dist, MouseButton button ) { this.node = node; this.faceIndex = -1; this.pos = null; this.minDistance = dist; this.maxDistance = dist; this.medDistance = dist; this.button = button; } /** * @return the picked Node */ public Leaf getNode() { return ( node ); } /** * @return the picked Shape3D's pick-host */ public Node getPickHost() { return ( node.getPickHost() ); } /** * @return the picked Shape3D's pick-host, if not null. The Node itself, otherwise. */ public Node getPickHostOrNode() { if ( node.getPickHost() == null ) return ( node ); return ( node.getPickHost() ); } /** * @return the Geometry of the picked Shape3D * @see #getNode() */ public Geometry getGeometry() { if ( node instanceof Shape3D ) return ( ( (Shape3D)node ).getGeometry() ); return ( null ); } public void setFaceIndex( int faceIndex ) { this.faceIndex = faceIndex; } /** * @return the index of the face which has * been picked in the Shape3D * @see #getNode() * @see #getGeometry() */ public int getFaceIndex() { if ( faceIndex == -1 ) { throw new UnsupportedFunction( "You tried to get the index of the face " + "which has been picked, but you use OpenGL-style picking. If " + "you want to use this functionality, please use org.xith3d." + "picking.PickingLibrary !!" ); } return ( faceIndex ); } /** * Transforms a vector in global-space to local space of this Shape3D. * * @param v the vector to transform */ public void transform( Vector3f v ) { node.getWorldTransform( tmpTrans ); tmpTrans.invert(); tmpTrans.transform( v ); } /** * Transforms a point in global-space to local space of this Shape3D. * * @param p the point to transform */ public void transform( Point3f p ) { node.getWorldTransform( tmpTrans ); tmpTrans.invert(); tmpTrans.transform( p ); } /** * Transforms a Ray3f in global-space to local space of this Shape3D. * * @param ray the ray to transform */ public void transform( Ray3f ray ) { node.getWorldTransform( tmpTrans ); tmpTrans.invert(); tmpTrans.transform( ray.getOrigin() ); tmpTrans.transform( ray.getDirection() ); } public void setPos( Tuple3f pos ) { this.pos = pos; } /** * @return The position of the intersection of the PickRay * with the Shape3D in global-space */ public Tuple3f getPos() { return ( pos ); } /** * Sets the minimum distance to the intersection * * @param dist the distance */ public void setMinimumDistance( float dist ) { minDistance = dist; } /** * @return the minimum distance to the intersection */ public float getMinimumDistance() { return ( minDistance ); } /** * Sets the maximum distance to the intersection * * @param dist the distance */ public void setMaximumDistance( float dist ) { maxDistance = dist; } /** * @return the maximum distance to the intersection */ public float getMaximumDistance() { return ( maxDistance ); } /** * Sets the medial distance to the intersection * * @param dist the distance */ public void setMedialDistance( float dist ) { medDistance = dist; } /** * @return the medial distance to the intersection */ public float getMedialDistance() { return ( medDistance ); } /** * @return the mouse button, that was clicked */ public final MouseButton getButton() { return ( button ); } /** * @return a String-representation of this PickResult object. */ @Override public String toString() { return ( "PickResult: Node: " + node + " Pos: " + pos ); } /** * Compares two PickResults according to their distances. * * @param pr the PickResult to compare to */ public int compareTo( PickResult pr ) { if ( this.minDistance > pr.minDistance ) return ( 1 ); else if ( this.minDistance < pr.minDistance ) return ( -1 ); else return ( 0 ); } @Override public boolean equals( Object o ) { if ( o instanceof PickResult ) { final PickResult r = (PickResult)o; if ( this.node == r.node || ( this.pos.equals( r.pos ) ) ) { return ( true ); } } return ( false ); } }