/* ** 2012 March 12 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. */ package info.ata4.bsplib.vector; import info.ata4.io.DataReader; import info.ata4.io.DataWriter; import java.io.IOException; /** * An immutable fluent interface four-dimensional vector class for float values. * * @author Sandern */ public final class Vector4f extends VectorXf { public static Vector4f read(DataReader in) throws IOException { float x = in.readFloat(); float y = in.readFloat(); float z = in.readFloat(); float w = in.readFloat(); return new Vector4f(x, y, z, w); } public static void write(DataWriter out, Vector4f vec) throws IOException { out.writeFloat(vec.x); out.writeFloat(vec.y); out.writeFloat(vec.z); out.writeFloat(vec.w); } // frequently used pre-defined vectors public static final Vector4f NULL = new Vector4f(0, 0, 0, 0); public static final Vector4f MAX_VALUE = new Vector4f(Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE); public static final Vector4f MIN_VALUE = MAX_VALUE.scalar(-1); // don't use Float.MIN_VALUE here // vector values public final float x; public final float y; public final float z; public final float w; /** * Replicating contructor * Constructs new Vector4f by copying an existing Vector4f * * @param v The Vector4f to copy */ public Vector4f(Vector4f v) { this(v.x, v.y, v.z, v.w); } /** * Constructs a new Vector4f using the values out of an array. * The array must have a size of at least 3. * * @param v float array */ public Vector4f(float[] v) { this(v[0], v[1], v[2], v[3]); } /** * Constructs a new Vector4f from x, y and z components * * @param x the vector x component * @param y the vector y component * @param z the vector z component */ public Vector4f(float x, float y, float z, float w) { super(4); this.x = x; this.y = y; this.z = z; this.w = w; } /** * Returns the value of the n'th component. * * @param index component number * @return component value */ @Override public float get(int index) { switch (index) { case 0: return this.x; case 1: return this.y; case 2: return this.z; case 3: return this.w; default: return 0; } } /** * Set the value of the n'th component. * * @param index component number * @param value new component value * @return vector with new value */ @Override public Vector4f set(int index, float value) { switch (index) { case 0: return new Vector4f(value, y, z, w); case 1: return new Vector4f(x, value, z, w); case 2: return new Vector4f(x, y, value, w); case 3: return new Vector4f(x, y, z, value); default: return this; } } /** * Vector dot product: this . that * * @param that the Vector4f to take dot product with * @return the dot product of the two vectors */ public float dot(Vector4f that) { return this.x * that.x + this.y * that.y + this.z * that.z; } /** * Vector normalisation: ^this * * @return the normalised vector */ public Vector4f normalize() { float len = length(); float rx = x / len; float ry = y / len; float rz = z / len; float rw = w / len; return new Vector4f(rx, ry, rz, rw); } /** * Vector addition: this + that * * @param that The vector to add * @return The sum of the two vectors */ public Vector4f add(Vector4f that) { float rx = this.x + that.x; float ry = this.y + that.y; float rz = this.z + that.z; float rw = this.w + that.w; return new Vector4f(rx, ry, rz, rw); } /** * Vector subtraction: this - that * * @param that The vector to subtract * @return The difference of the two vectors */ public Vector4f sub(Vector4f that) { float rx = this.x - that.x; float ry = this.y - that.y; float rz = this.z - that.z; float rw = this.w - that.w; return new Vector4f(rx, ry, rz, rw); } /** * Snap vector to nearest value: round(this / value) * value * * @param value snap value * @return This vector snapped to the nearest values of 'value' */ public Vector4f snap(float value) { float rx = Math.round(x / value) * value; float ry = Math.round(y / value) * value; float rz = Math.round(z / value) * value; float rw = Math.round(w / value) * value; return new Vector4f(rx, ry, rz, rw); } /** * Calculate the length of this vector * * @return length of this vector */ public float length() { return (float) Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2) + Math.pow(this.z, 2) + Math.pow(this.w, 2)); } /** * Performs a scalar multiplication on this vector: this * mul * * @param mul multiplicator * @return scalar multiplied vector */ public Vector4f scalar(float mul) { float rx = this.x * mul; float ry = this.y * mul; float rz = this.z * mul; float rw = this.w * mul; return new Vector4f(rx, ry, rz, rw); } /** * Performs a scalar multiplication on this vector: this * that * * @param that multiplicator vector * @return scalar multiplied vector */ public Vector4f scalar(Vector4f that) { float rx = this.x * that.x; float ry = this.y * that.y; float rz = this.z * that.z; float rw = this.w * that.w; return new Vector4f(rx, ry, rz, rw); } /** * Returns the minima between this vector and another vector. * * @param that other vector to compare * @return minima of this and that vector */ public Vector4f min(Vector4f that) { float rx = Math.min(this.x, that.x); float ry = Math.min(this.y, that.y); float rz = Math.min(this.z, that.z); float rw = Math.min(this.w, that.w); return new Vector4f(rx, ry, rz, rw); } /** * Returns the maxima between this vector and another vector. * * @param that other vector to compare * @return maxima of this and that vector */ public Vector4f max(Vector4f that) { float rx = Math.max(this.x, that.x); float ry = Math.max(this.y, that.y); float rz = Math.max(this.z, that.z); float rw = Math.max(this.w, that.w); return new Vector4f(rx, ry, rz, rw); } }