/**
* Copyright 2012 Jason Sorensen (sorensenj@smert.net)
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package net.smert.frameworkgl.math;
import java.nio.FloatBuffer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author Jason Sorensen <sorensenj@smert.net>
*/
public class Vector4f {
private static Logger log = LoggerFactory.getLogger(Vector4f.class);
float w;
float x;
float y;
float z;
// Constructors
public Vector4f() {
zero();
}
public Vector4f(float x, float y, float z, float w) {
this.x = x;
this.y = y;
this.z = z;
this.w = w;
}
public Vector4f(Vector4f v) {
x = v.x;
y = v.y;
z = v.z;
w = v.w;
}
// Boolean Results
public boolean planeAABBEquation(Vector3f aabbMin, Vector3f aabbMax, float threshold) {
// This will not work correctly for objects bigger than the frustum
float xMinX = x * aabbMin.x;
float yMinY = y * aabbMin.y;
float zMinZ = z * aabbMin.z;
if ((xMinX + yMinY + zMinZ + w) < threshold) {
return false;
}
float zMaxZ = z * aabbMax.z;
if ((xMinX + yMinY + zMaxZ + w) < threshold) {
return false;
}
float yMaxY = y * aabbMax.y;
if ((xMinX + yMaxY + zMinZ + w) < threshold) {
return false;
}
float xMaxX = x * aabbMax.x;
return ((xMinX + yMaxY + zMaxZ + w) < threshold)
|| ((xMaxX + yMinY + zMinZ + w) < threshold)
|| ((xMaxX + yMinY + zMaxZ + w) < threshold)
|| ((xMaxX + yMaxY + zMinZ + w) < threshold)
|| ((xMaxX + yMaxY + zMaxZ + w) < threshold);
}
public boolean planePointEquation(float x, float y, float z, float threshold) {
return ((this.x * x + this.y * y + this.z * z + w) > -threshold);
}
public boolean planePointEquation(Vector3f v, float threshold) {
return planePointEquation(v.x, v.y, v.z, threshold);
}
// Conversion Operations
public void toFloatBuffer(FloatBuffer fbOut) {
fbOut.put(x);
fbOut.put(y);
fbOut.put(z);
fbOut.put(w);
}
// Scalar Results
public float distance(Vector4f vector) {
float d0 = w - vector.w;
float d1 = x - vector.x;
float d2 = y - vector.y;
float d3 = z - vector.z;
return MathHelper.Sqrt(d0 * d0 + d1 * d1 + d2 * d2 + d3 * d3);
}
public float distanceSquared(Vector4f vector) {
float d0 = w - vector.w;
float d1 = x - vector.x;
float d2 = y - vector.y;
float d3 = z - vector.z;
return d0 * d0 + d1 * d1 + d2 * d2 + d3 * d3;
}
public float dot(Vector4f vector) {
return w * vector.w + x * vector.x + y * vector.y + z * vector.z;
}
public float dot3(Vector3f vector) {
return x * vector.x + y * vector.y + z * vector.z;
}
public float dot3(Vector4f vector) {
return x * vector.x + y * vector.y + z * vector.z;
}
public float getW() {
return w;
}
public float getX() {
return x;
}
public float getY() {
return y;
}
public float getZ() {
return z;
}
public float magnitude() {
return MathHelper.Sqrt(w * w + x * x + y * y + z * z);
}
public float magnitudeSquared() {
return w * w + x * x + y * y + z * z;
}
// Vector Results
public Vector4f abs() {
w = Math.abs(w);
x = Math.abs(x);
y = Math.abs(y);
z = Math.abs(z);
return this;
}
public void add(float x, float y, float z, float w) {
this.w += w;
this.x += x;
this.y += y;
this.z += z;
}
public void add(Vector4f vector) {
this.w += vector.w;
this.x += vector.x;
this.y += vector.y;
this.z += vector.z;
}
public void addW(float w) {
this.w += w;
}
public void addX(float x) {
this.x += x;
}
public void addY(float y) {
this.y += y;
}
public void addZ(float z) {
this.z += z;
}
public Vector4f absolute() {
x = Math.abs(x);
y = Math.abs(y);
z = Math.abs(z);
w = Math.abs(w);
return this;
}
public Vector4f multiply(float value) {
w *= value;
x *= value;
y *= value;
z *= value;
return this;
}
public Vector4f normalize() {
float mag = magnitude();
if (mag < MathHelper.ZERO_EPSILON) {
log.warn("Divide By Zero. Magnitude: {} x: {} y: {} z: {} w: {}", mag, x, y, z, w);
w = 0f;
x = 0f;
y = 0f;
z = -1f;
return this;
}
return multiply(1f / mag);
}
public void set(float x, float y, float z, float w) {
this.w = w;
this.x = x;
this.y = y;
this.z = z;
}
public void set(Vector2f vector, float z, float w) {
this.w = w;
x = vector.x;
y = vector.y;
this.z = z;
}
public void set(Vector3f vector, float w) {
this.w = w;
x = vector.x;
y = vector.y;
z = vector.z;
}
public void set(Vector4f vector) {
w = vector.w;
x = vector.x;
y = vector.y;
z = vector.z;
}
public void setW(float w) {
this.w = w;
}
public void setX(float x) {
this.x = x;
}
public void setY(float y) {
this.y = y;
}
public void setZ(float z) {
this.z = z;
}
public final void zero() {
w = 0f;
x = 0f;
y = 0f;
z = 0f;
}
@Override
public int hashCode() {
int hash = 5;
hash = 89 * hash + Float.floatToIntBits(this.w);
hash = 89 * hash + Float.floatToIntBits(this.x);
hash = 89 * hash + Float.floatToIntBits(this.y);
hash = 89 * hash + Float.floatToIntBits(this.z);
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Vector4f other = (Vector4f) obj;
if (Float.floatToIntBits(this.w) != Float.floatToIntBits(other.w)) {
return false;
}
if (Float.floatToIntBits(this.x) != Float.floatToIntBits(other.x)) {
return false;
}
if (Float.floatToIntBits(this.y) != Float.floatToIntBits(other.y)) {
return false;
}
return Float.floatToIntBits(this.z) == Float.floatToIntBits(other.z);
}
@Override
public String toString() {
return "(x: " + x + " y: " + y + " z: " + z + " w: " + w + ")";
}
}