159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/* 259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Copyright (c) 2009-2010 jMonkeyEngine 359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * All rights reserved. 459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Redistribution and use in source and binary forms, with or without 659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * modification, are permitted provided that the following conditions are 759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * met: 859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Redistributions of source code must retain the above copyright 1059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * notice, this list of conditions and the following disclaimer. 1159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 1259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Redistributions in binary form must reproduce the above copyright 1359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * notice, this list of conditions and the following disclaimer in the 1459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * documentation and/or other materials provided with the distribution. 1559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 1659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Neither the name of 'jMonkeyEngine' nor the names of its contributors 1759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * may be used to endorse or promote products derived from this software 1859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * without specific prior written permission. 1959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 2059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 2259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 2359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 2459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 2559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 2659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 2759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 2859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 2959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 3059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 3259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapackage com.jme3.math; 3359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 3459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.bounding.BoundingVolume; 3559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.collision.Collidable; 3659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.collision.CollisionResult; 3759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.collision.CollisionResults; 3859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.collision.UnsupportedCollisionException; 3959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.export.*; 4059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.util.TempVars; 4159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.io.IOException; 4259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 4359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/** 4459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <code>Ray</code> defines a line segment which has an origin and a direction. 4559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * That is, a point and an infinite ray is cast from this point. The ray is 4659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * defined by the following equation: R(t) = origin + t*direction for t >= 0. 4759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 4859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @author Mark Powell 4959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @author Joshua Slack 5059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 5159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapublic final class Ray implements Savable, Cloneable, Collidable, java.io.Serializable { 5259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 5359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta static final long serialVersionUID = 1; 5459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 5559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 5659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * The ray's begining point. 5759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 5859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public Vector3f origin = new Vector3f(); 5959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 6059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 6159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * The direction of the ray. 6259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 6359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public Vector3f direction = new Vector3f(0, 0, 1); 6459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 6559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 6659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public float limit = Float.POSITIVE_INFINITY; 6759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 6859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 6959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Constructor instantiates a new <code>Ray</code> object. As default, the 7059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * origin is (0,0,0) and the direction is (0,0,1). 7159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 7259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 7359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public Ray() { 7459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 7559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 7659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 7759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Constructor instantiates a new <code>Ray</code> object. The origin and 7859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * direction are given. 7959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param origin the origin of the ray. 8059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param direction the direction the ray travels in. 8159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 8259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public Ray(Vector3f origin, Vector3f direction) { 8359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta setOrigin(origin); 8459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta setDirection(direction); 8559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 8659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 8759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 8859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <code>intersect</code> determines if the Ray intersects a triangle. 8959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param t the Triangle to test against. 9059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return true if the ray collides. 9159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 9259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// public boolean intersect(Triangle t) { 9359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// return intersect(t.get(0), t.get(1), t.get(2)); 9459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// } 9559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 9659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <code>intersect</code> determines if the Ray intersects a triangle 9759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * defined by the specified points. 9859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 9959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param v0 10059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * first point of the triangle. 10159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param v1 10259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * second point of the triangle. 10359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param v2 10459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * third point of the triangle. 10559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return true if the ray collides. 10659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 10759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// public boolean intersect(Vector3f v0,Vector3f v1,Vector3f v2){ 10859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// return intersectWhere(v0, v1, v2, null); 10959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// } 11059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 11159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <code>intersectWhere</code> determines if the Ray intersects a triangle. It then 11259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * stores the point of intersection in the given loc vector 11359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param t the Triangle to test against. 11459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param loc 11559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * storage vector to save the collision point in (if the ray 11659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * collides) 11759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return true if the ray collides. 11859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 11959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public boolean intersectWhere(Triangle t, Vector3f loc) { 12059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return intersectWhere(t.get(0), t.get(1), t.get(2), loc); 12159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 12259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 12359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 12459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <code>intersectWhere</code> determines if the Ray intersects a triangle 12559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * defined by the specified points and if so it stores the point of 12659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * intersection in the given loc vector. 12759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 12859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param v0 12959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * first point of the triangle. 13059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param v1 13159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * second point of the triangle. 13259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param v2 13359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * third point of the triangle. 13459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param loc 13559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * storage vector to save the collision point in (if the ray 13659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * collides) if null, only boolean is calculated. 13759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return true if the ray collides. 13859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 13959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public boolean intersectWhere(Vector3f v0, Vector3f v1, Vector3f v2, 14059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f loc) { 14159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return intersects(v0, v1, v2, loc, false, false); 14259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 14359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 14459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 14559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <code>intersectWherePlanar</code> determines if the Ray intersects a 14659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * triangle and if so it stores the point of 14759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * intersection in the given loc vector as t, u, v where t is the distance 14859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * from the origin to the point of intersection and u,v is the intersection 14959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * point in terms of the triangle plane. 15059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 15159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param t the Triangle to test against. 15259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param loc 15359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * storage vector to save the collision point in (if the ray 15459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * collides) as t, u, v 15559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return true if the ray collides. 15659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 15759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public boolean intersectWherePlanar(Triangle t, Vector3f loc) { 15859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return intersectWherePlanar(t.get(0), t.get(1), t.get(2), loc); 15959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 16059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 16159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 16259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <code>intersectWherePlanar</code> determines if the Ray intersects a 16359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * triangle defined by the specified points and if so it stores the point of 16459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * intersection in the given loc vector as t, u, v where t is the distance 16559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * from the origin to the point of intersection and u,v is the intersection 16659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * point in terms of the triangle plane. 16759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 16859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param v0 16959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * first point of the triangle. 17059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param v1 17159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * second point of the triangle. 17259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param v2 17359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * third point of the triangle. 17459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param loc 17559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * storage vector to save the collision point in (if the ray 17659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * collides) as t, u, v 17759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return true if the ray collides. 17859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 17959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public boolean intersectWherePlanar(Vector3f v0, Vector3f v1, Vector3f v2, 18059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f loc) { 18159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return intersects(v0, v1, v2, loc, true, false); 18259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 18359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 18459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 18559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <code>intersects</code> does the actual intersection work. 18659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 18759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param v0 18859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * first point of the triangle. 18959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param v1 19059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * second point of the triangle. 19159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param v2 19259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * third point of the triangle. 19359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param store 19459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * storage vector - if null, no intersection is calc'd 19559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param doPlanar 19659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * true if we are calcing planar results. 19759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param quad 19859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return true if ray intersects triangle 19959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 20059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private boolean intersects(Vector3f v0, Vector3f v1, Vector3f v2, 20159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f store, boolean doPlanar, boolean quad) { 20259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta TempVars vars = TempVars.get(); 20359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 20459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f tempVa = vars.vect1, 20559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta tempVb = vars.vect2, 20659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta tempVc = vars.vect3, 20759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta tempVd = vars.vect4; 20859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 20959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f diff = origin.subtract(v0, tempVa); 21059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f edge1 = v1.subtract(v0, tempVb); 21159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f edge2 = v2.subtract(v0, tempVc); 21259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f norm = edge1.cross(edge2, tempVd); 21359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 21459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float dirDotNorm = direction.dot(norm); 21559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float sign; 21659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (dirDotNorm > FastMath.FLT_EPSILON) { 21759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta sign = 1; 21859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else if (dirDotNorm < -FastMath.FLT_EPSILON) { 21959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta sign = -1f; 22059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta dirDotNorm = -dirDotNorm; 22159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 22259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // ray and triangle/quad are parallel 22359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vars.release(); 22459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return false; 22559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 22659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 22759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float dirDotDiffxEdge2 = sign * direction.dot(diff.cross(edge2, edge2)); 22859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (dirDotDiffxEdge2 >= 0.0f) { 22959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float dirDotEdge1xDiff = sign 23059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * direction.dot(edge1.crossLocal(diff)); 23159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 23259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (dirDotEdge1xDiff >= 0.0f) { 23359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!quad ? dirDotDiffxEdge2 + dirDotEdge1xDiff <= dirDotNorm : dirDotEdge1xDiff <= dirDotNorm) { 23459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float diffDotNorm = -sign * diff.dot(norm); 23559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (diffDotNorm >= 0.0f) { 23659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // this method always returns 23759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vars.release(); 23859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 23959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // ray intersects triangle 24059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // if storage vector is null, just return true, 24159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (store == null) { 24259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return true; 24359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 24459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 24559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // else fill in. 24659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float inv = 1f / dirDotNorm; 24759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float t = diffDotNorm * inv; 24859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!doPlanar) { 24959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta store.set(origin).addLocal(direction.x * t, 25059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta direction.y * t, direction.z * t); 25159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 25259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // these weights can be used to determine 25359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // interpolated values, such as texture coord. 25459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // eg. texcoord s,t at intersection point: 25559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // s = w0*s0 + w1*s1 + w2*s2; 25659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // t = w0*t0 + w1*t1 + w2*t2; 25759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float w1 = dirDotDiffxEdge2 * inv; 25859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float w2 = dirDotEdge1xDiff * inv; 25959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //float w0 = 1.0f - w1 - w2; 26059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta store.set(t, w1, w2); 26159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 26259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return true; 26359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 26459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 26559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 26659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 26759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vars.release(); 26859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return false; 26959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 27059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 27159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public float intersects(Vector3f v0, Vector3f v1, Vector3f v2) { 27259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float edge1X = v1.x - v0.x; 27359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float edge1Y = v1.y - v0.y; 27459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float edge1Z = v1.z - v0.z; 27559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 27659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float edge2X = v2.x - v0.x; 27759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float edge2Y = v2.y - v0.y; 27859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float edge2Z = v2.z - v0.z; 27959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 28059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float normX = ((edge1Y * edge2Z) - (edge1Z * edge2Y)); 28159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float normY = ((edge1Z * edge2X) - (edge1X * edge2Z)); 28259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float normZ = ((edge1X * edge2Y) - (edge1Y * edge2X)); 28359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 28459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float dirDotNorm = direction.x * normX + direction.y * normY + direction.z * normZ; 28559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 28659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float diffX = origin.x - v0.x; 28759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float diffY = origin.y - v0.y; 28859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float diffZ = origin.z - v0.z; 28959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 29059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float sign; 29159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (dirDotNorm > FastMath.FLT_EPSILON) { 29259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta sign = 1; 29359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else if (dirDotNorm < -FastMath.FLT_EPSILON) { 29459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta sign = -1f; 29559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta dirDotNorm = -dirDotNorm; 29659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 29759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // ray and triangle/quad are parallel 29859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return Float.POSITIVE_INFINITY; 29959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 30059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 30159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float diffEdge2X = ((diffY * edge2Z) - (diffZ * edge2Y)); 30259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float diffEdge2Y = ((diffZ * edge2X) - (diffX * edge2Z)); 30359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float diffEdge2Z = ((diffX * edge2Y) - (diffY * edge2X)); 30459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 30559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float dirDotDiffxEdge2 = sign * (direction.x * diffEdge2X 30659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta + direction.y * diffEdge2Y 30759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta + direction.z * diffEdge2Z); 30859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 30959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (dirDotDiffxEdge2 >= 0.0f) { 31059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta diffEdge2X = ((edge1Y * diffZ) - (edge1Z * diffY)); 31159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta diffEdge2Y = ((edge1Z * diffX) - (edge1X * diffZ)); 31259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta diffEdge2Z = ((edge1X * diffY) - (edge1Y * diffX)); 31359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 31459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float dirDotEdge1xDiff = sign * (direction.x * diffEdge2X 31559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta + direction.y * diffEdge2Y 31659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta + direction.z * diffEdge2Z); 31759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 31859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (dirDotEdge1xDiff >= 0.0f) { 31959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (dirDotDiffxEdge2 + dirDotEdge1xDiff <= dirDotNorm) { 32059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float diffDotNorm = -sign * (diffX * normX + diffY * normY + diffZ * normZ); 32159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (diffDotNorm >= 0.0f) { 32259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // ray intersects triangle 32359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // fill in. 32459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float inv = 1f / dirDotNorm; 32559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float t = diffDotNorm * inv; 32659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return t; 32759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 32859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 32959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 33059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 33159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 33259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return Float.POSITIVE_INFINITY; 33359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 33459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 33559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 33659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <code>intersectWherePlanar</code> determines if the Ray intersects a 33759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * quad defined by the specified points and if so it stores the point of 33859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * intersection in the given loc vector as t, u, v where t is the distance 33959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * from the origin to the point of intersection and u,v is the intersection 34059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * point in terms of the quad plane. 34159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * One edge of the quad is [v0,v1], another one [v0,v2]. The behaviour thus is like 34259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * {@link #intersectWherePlanar(Vector3f, Vector3f, Vector3f, Vector3f)} except for 34359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * the extended area, which is equivalent to the union of the triangles [v0,v1,v2] 34459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * and [-v0+v1+v2,v1,v2]. 34559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 34659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param v0 34759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * top left point of the quad. 34859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param v1 34959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * top right point of the quad. 35059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param v2 35159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * bottom left point of the quad. 35259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param loc 35359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * storage vector to save the collision point in (if the ray 35459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * collides) as t, u, v 35559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return true if the ray collides with the quad. 35659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 35759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public boolean intersectWherePlanarQuad(Vector3f v0, Vector3f v1, Vector3f v2, 35859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f loc) { 35959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return intersects(v0, v1, v2, loc, true, true); 36059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 36159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 36259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 36359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 36459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param p 36559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param loc 36659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return true if the ray collides with the given Plane 36759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 36859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public boolean intersectsWherePlane(Plane p, Vector3f loc) { 36959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float denominator = p.getNormal().dot(direction); 37059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 37159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (denominator > -FastMath.FLT_EPSILON && denominator < FastMath.FLT_EPSILON) { 37259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return false; // coplanar 37359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 37459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float numerator = -(p.getNormal().dot(origin) - p.getConstant()); 37559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float ratio = numerator / denominator; 37659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 37759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (ratio < FastMath.FLT_EPSILON) { 37859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return false; // intersects behind origin 37959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 38059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta loc.set(direction).multLocal(ratio).addLocal(origin); 38159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 38259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return true; 38359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 38459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 38559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public int collideWith(Collidable other, CollisionResults results) { 38659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (other instanceof BoundingVolume) { 38759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta BoundingVolume bv = (BoundingVolume) other; 38859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return bv.collideWith(this, results); 38959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else if (other instanceof AbstractTriangle) { 39059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta AbstractTriangle tri = (AbstractTriangle) other; 39159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float d = intersects(tri.get1(), tri.get2(), tri.get3()); 39259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (Float.isInfinite(d) || Float.isNaN(d)) { 39359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return 0; 39459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 39559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 39659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f point = new Vector3f(direction).multLocal(d).addLocal(origin); 39759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta results.addCollision(new CollisionResult(point, d)); 39859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return 1; 39959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 40059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new UnsupportedCollisionException(); 40159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 40259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 40359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 40459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public float distanceSquared(Vector3f point) { 40559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta TempVars vars = TempVars.get(); 40659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 40759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f tempVa = vars.vect1, 40859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta tempVb = vars.vect2; 40959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 41059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta point.subtract(origin, tempVa); 41159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float rayParam = direction.dot(tempVa); 41259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (rayParam > 0) { 41359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta origin.add(direction.mult(rayParam, tempVb), tempVb); 41459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 41559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta tempVb.set(origin); 41659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rayParam = 0.0f; 41759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 41859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 41959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta tempVb.subtract(point, tempVa); 42059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float len = tempVa.lengthSquared(); 42159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vars.release(); 42259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return len; 42359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 42459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 42559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 42659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 42759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <code>getOrigin</code> retrieves the origin point of the ray. 42859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 42959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return the origin of the ray. 43059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 43159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public Vector3f getOrigin() { 43259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return origin; 43359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 43459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 43559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 43659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 43759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <code>setOrigin</code> sets the origin of the ray. 43859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param origin the origin of the ray. 43959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 44059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setOrigin(Vector3f origin) { 44159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.origin.set(origin); 44259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 44359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 44459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 44559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <code>getLimit</code> returns the limit of the ray, aka the length. 44659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * If the limit is not infinity, then this ray is a line with length <code> 44759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * limit</code>. 44859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 44959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return the limit of the ray, aka the length. 45059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 45159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public float getLimit() { 45259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return limit; 45359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 45459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 45559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 45659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <code>setLimit</code> sets the limit of the ray. 45759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param limit the limit of the ray. 45859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @see Ray#getLimit() 45959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 46059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setLimit(float limit) { 46159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.limit = limit; 46259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 46359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 46459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 46559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 46659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <code>getDirection</code> retrieves the direction vector of the ray. 46759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return the direction of the ray. 46859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 46959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public Vector3f getDirection() { 47059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return direction; 47159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 47259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 47359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 47459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 47559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <code>setDirection</code> sets the direction vector of the ray. 47659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param direction the direction of the ray. 47759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 47859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setDirection(Vector3f direction) { 47959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta assert direction.isUnitVector(); 48059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.direction.set(direction); 48159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 48259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 48359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 48459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Copies information from a source ray into this ray. 48559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 48659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param source 48759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * the ray to copy information from 48859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 48959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void set(Ray source) { 49059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta origin.set(source.getOrigin()); 49159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta direction.set(source.getDirection()); 49259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 49359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 49459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public String toString() { 49559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return getClass().getSimpleName() + " [Origin: " + origin + ", Direction: " + direction + "]"; 49659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 49759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 49859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void write(JmeExporter e) throws IOException { 49959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta OutputCapsule capsule = e.getCapsule(this); 50059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta capsule.write(origin, "origin", Vector3f.ZERO); 50159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta capsule.write(direction, "direction", Vector3f.ZERO); 50259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 50359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 50459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void read(JmeImporter e) throws IOException { 50559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta InputCapsule capsule = e.getCapsule(this); 50659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta origin = (Vector3f) capsule.readSavable("origin", Vector3f.ZERO.clone()); 50759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta direction = (Vector3f) capsule.readSavable("direction", Vector3f.ZERO.clone()); 50859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 50959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 51059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 51159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public Ray clone() { 51259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta try { 51359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Ray r = (Ray) super.clone(); 51459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta r.direction = direction.clone(); 51559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta r.origin = origin.clone(); 51659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return r; 51759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } catch (CloneNotSupportedException e) { 51859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new AssertionError(); 51959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 52059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 52159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta} 522