package com.jme.math; /* * Copyright (c) 2003-2008 jMonkeyEngine * All rights reserved. * * 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 'jMonkeyEngine' 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) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; import DPJRuntime.*; /** * <code>Vector3f</code> defines a Vector for a three float value tuple. * <code>Vector3f</code> can represent any three dimensional value, such as a * vertex, a normal, etc. Utility methods are also included to aid in * mathematical calculations. * * @author Mark Powell * @author Joshua Slack */ public class Vector3f<region R> implements Externalizable { private static final long serialVersionUID = 1L; /** * An array of Vector3f */ public static arrayclass Array<region R> { Vector3f<R> in R; } /** * the x value of the vector. */ public float x in R; /** * the y value of the vector. */ public float y in R; /** * the z value of the vector. */ public float z in R; /** * Constructor instantiates a new <code>Vector3f</code> with default * values of (0,0,0). * */ public Vector3f() writes R { x = y = z = 0; } public Vector3f(float x, float y, float z) /*writes R*/ { this.x = x; this.y = y; this.z = z; } /** * <code>set</code> sets the x,y,z values of the vector based on passed * parameters. * * @param x * the x value of the vector. * @param y * the y value of the vector. * @param z * the z value of the vector. * @return this vector */ public Vector3f<R> set(float x, float y, float z) writes R { this.x = x; this.y = y; this.z = z; return this; } /** * <code>set</code> sets the x,y,z values of the vector by copying the * supplied vector. * * @param vect * the vector to copy. * @return this vector */ public <region Rvect> Vector3f<R> set(Vector3f<Rvect> vect) reads Rvect writes R { this.x = vect.x; this.y = vect.y; this.z = vect.z; return this; } /** * <code>addLocal</code> adds a provided vector to this vector internally, * and returns a handle to this vector for easy chaining of calls. If the * provided vector is null, null is returned. * * @param vec * the vector to add to this vector. * @return this */ public <region Rvec> Vector3f<R> addLocal(Vector3f<Rvec> vec) reads Rvec writes R { if (null == vec) { return null; } x += vec.x; y += vec.y; z += vec.z; return this; } /** * * <code>dot</code> calculates the dot product of this vector with a * provided vector. If the provided vector is null, 0 is returned. * * @param vec * the vector to dot with this vector. * @return the resultant dot product of this vector and a given vector. */ public <region Rvec> float dot(Vector3f<Rvec> vec) reads R, Rvec { if (null == vec) { return 0; } return x * vec.x + y * vec.y + z * vec.z; } /** * <code>cross</code> calculates the cross product of this vector with a * parameter vector v. The result is stored in <code>result</code> * * @param v * the vector to take the cross product of with this. * @param result * the vector to store the cross product result. * @return result, after recieving the cross product vector. */ public <region Rv, Rresult> Vector3f<Rresult> cross(Vector3f<Rv> v, Vector3f<Rresult> result) reads R, Rv writes Rresult { return cross(v.x, v.y, v.z, result); } /** * <code>cross</code> calculates the cross product of this vector with a * parameter vector v. The result is stored in <code>result</code> * * @param otherX * x component of the vector to take the cross product of with this. * @param otherY * y component of the vector to take the cross product of with this. * @param otherZ * z component of the vector to take the cross product of with this. * @param result * the vector to store the cross product result. * @return result, after recieving the cross product vector. */ public <region Rresult> Vector3f<Rresult> cross(float otherX, float otherY, float otherZ, Vector3f<Rresult> result) reads R writes Rresult { if (result == null) result = new Vector3f<Rresult>(); float resX = ((y * otherZ) - (z * otherY)); float resY = ((z * otherX) - (x * otherZ)); float resZ = ((x * otherY) - (y * otherX)); result.set(resX, resY, resZ); return result; } /** * <code>multLocal</code> multiplies this vector by a scalar internally, * and returns a handle to this vector for easy chaining of calls. * * @param scalar * the value to multiply this vector by. * @return this */ public Vector3f<region R> multLocal(float scalar) writes R { x *= scalar; y *= scalar; z *= scalar; return this; } /** * <code>multLocal</code> multiplies a provided vector to this vector * internally, and returns a handle to this vector for easy chaining of * calls. If the provided vector is null, null is returned. * * @param vec * the vector to mult to this vector. * @return this */ public <region Rvec> Vector3f<R> multLocal(Vector3f<Rvec> vec) reads Rvec writes R { if (null == vec) { return null; } x *= vec.x; y *= vec.y; z *= vec.z; return this; } /** * <code>mult</code> multiplies this vector by a provided vector, * and returns the result in store. * * @param vec * the vector to mult to this vector. * @param store result vector (null to create a new vector) * @return this */ public <region Rvec, Rstore> Vector3f<Rstore> mult(Vector3f<Rvec> vec, Vector3f<Rstore> store) reads R, Rvec writes Rstore { if (null == vec) { return null; } if (store == null) store = new Vector3f<Rstore>(); return store.set(x * vec.x, y * vec.y, z * vec.z); } /** * * <code>subtract</code> * * @param vec * the vector to subtract from this * @param result * the vector to store the result in * @return result */ public <region Rvec, Rresult> Vector3f<Rresult> subtract(Vector3f<Rvec> vec, Vector3f<Rresult> result) reads R, Rvec writes Rresult { if(result == null) { result = new Vector3f<Rresult>(); } result.x = x - vec.x; result.y = y - vec.y; result.z = z - vec.z; return result; } /** * Check a vector... if it is null or its floats are NaN or infinite, * return false. Else return true. * @param vector the vector to check * @return true or false as stated above. */ public static <region Rvector> boolean isValidVector(Vector3f<Rvector> vector) reads Rvector { if (vector == null) return false; if (Float.isNaN(vector.x) || Float.isNaN(vector.y) || Float.isNaN(vector.z)) return false; if (Float.isInfinite(vector.x) || Float.isInfinite(vector.y) || Float.isInfinite(vector.z)) return false; return true; } /** * Saves this Vector3f into the given ArrayFloat object. * * @param floats * The ArrayFloat to take this Vector3f. If null, a new ArrayFloat(3) is * created. * @return The array, with X, Y, Z float values in that order */ public <region Rfloats> ArrayFloat<Rfloats> toArray(ArrayFloat<Rfloats> floats) reads R writes Rfloats:* { if (floats == null) { floats = new ArrayFloat<Rfloats>(3); } floats[0] = x; floats[1] = y; floats[2] = z; return floats; } /** * Used with serialization. Not to be called manually. * @param in input * @throws IOException * @throws ClassNotFoundException * @see java.io.Externalizable */ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { x=in.readFloat(); y=in.readFloat(); z=in.readFloat(); } /** * Used with serialization. Not to be called manually. * @param out output * @throws IOException * @see java.io.Externalizable */ public void writeExternal(ObjectOutput out) throws IOException { out.writeFloat(x); out.writeFloat(y); out.writeFloat(z); } }