package pl.vorg.mowa.core.graphics;

/**
 * Wektor w przestrzeni 3d
 * 
 * @author vorg
 */
public class Vec3 {
	private float[] v = {0,0,0};
	
	public Vec3() {
		
	}
	
	public Vec3(float x, float y, float z) {
		v[0] = x;
		v[1] = y;
		v[2] = z;
	}
	
	public Vec3(Vec3 vec) {
		float[] w = vec.getVector();
		v[0] = w[0];
		v[1] = w[1];
		v[2] = w[2];
	}
	
	public Vec3(float[] vec) {
		v[0] = vec[0];
		v[1] = vec[1];
		v[2] = vec[2];
	}
	
	@Override
	public boolean equals(java.lang.Object obj) {
		float[] w = ((Vec3)obj).getVector();
		return (v[0] == w[0]) && (v[1] == w[1]) && (v[2] == w[2]); 
	}
	
	public float getX() {
		return v[0];
	}
	
	public float getY() {
		return v[1];
	}
	
	public float getZ() {
		return v[2];
	}
	
	public void setX(float x) {
		v[0] = x;
	}
	
	public void setY(float y) {
		v[1] = y;
	}
	
	public void setZ(float z) {
		v[2] = z;
	}
	
	
	public float[] getVector() {
		return v;
	}
	
	public void normalize() {
		float length = length();
		if (length > 0) {
			v[0] /= length;
			v[1] /= length;
			v[2] /= length;
		}
	}
	
	public float length() {
		return (float)Math.sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
	}
	
	public void add(Vec3 a) {
		v[0] += a.getX();
		v[1] += a.getY();
		v[2] += a.getZ();
	}
	
	public static Vec3 add(Vec3 a, Vec3 b) {
		return new Vec3(
			a.getX() + b.getX(),
			a.getY() + b.getY(),
			a.getZ() + b.getZ()
		);
	}
	
	public void sub(Vec3 a) {
		v[0] -= a.getX();
		v[1] -= a.getY();
		v[2] -= a.getZ();
	}
	
	public static Vec3 sub(Vec3 a, Vec3 b) {
		return new Vec3(
			a.getX() - b.getX(),
			a.getY() - b.getY(),
			a.getZ() - b.getZ()
		);
	}
	
	public void mul(float f) {
		v[0] *= f;
		v[1] *= f;
		v[2] *= f;
	}
	
	public static Vec3 mul(float f, Vec3 a) {
		return new Vec3(
			a.getX() * f,
			a.getY() * f,
			a.getZ() * f
		);
	}
	
	public static Vec3 cross(Vec3 a, Vec3 b) {
		float[] va = a.getVector();
		float[] vb = b.getVector();
		return new Vec3(
				va[1]*vb[2] - va[2]*vb[1],
				va[2]*vb[0] - va[0]*vb[2],
				va[0]*vb[1] - va[1]*vb[0]
		); 
	}
	
	public float dot(Vec3 a) {
		float[] va = a.getVector();
		return v[0]*va[0] + v[1]*va[1] + v[2]*va[2];
	}
	
	public static float dot(Vec3 a, Vec3 b) {
		float[] va = a.getVector();
		float[] vb = b.getVector();
		return va[0]*vb[0] + va[1]*vb[1] + va[2]*vb[2];
	}
	
	public float angle(Vec3 a) {
		float len = length();
		float alen = a.length();
		if ((len == 0) || (alen == 0)) {
			return 0;
		}
		return (float)Math.acos(this.dot(a)/(len*alen));
	}
	
	public static Vec3 normalized(Vec3 a) {
		Vec3 na = new Vec3(a);
		na.normalize();
		return na;
	}
	
	public static Vec3 neg(Vec3 a) {
		return new Vec3(-a.getX(), -a.getY(), -a.getZ());
	}
}
