/**
 *  A point, normal, etc in 3d (possibly homogeneous) coords.
 *  And common ops on it.
 */

public class Vector3D {
    public float x, y, z, w;           // coordinate of vertex

    public Vector3D() {
        w = 1.0f;
    }

    public Vector3D(float xval, float yval, float zval) {
        x = xval;
        y = yval;
        z = zval;
        w = 1.0f;
    }
    
    public void init(float xval, float yval, float zval) {
        x = xval;
        y = yval;
        z = zval;
    }
    
    public void crossProduct(Vector3D u, Vector3D v) {
        x = u.y * v.z - u.z * v.y;
        y = u.z * v.x - u.x * v.z;
        z = u.x * v.y - u.y * v.x;
    }
    
    public float dotProduct(Vector3D u) {
        return x * u.x + y * u.y + z * u.z;
    }
    
    public void normalize() {
    	float mult = 1.0f / (float)Math.sqrt(x * x + y * y + z * z);
    	x *= mult;
    	y *= mult;
    	z *= mult;
    }

    public void add(Vector3D u, Vector3D v) {
        x = u.x + v.x;
        y = u.y + v.y;
        z = u.z + v.z;
    }
    
    public void addScaled(Vector3D u, Vector3D v, float s) {
        x = u.x + v.x * s;
        y = u.y + v.y * s;
        z = u.z + v.z * s;
    }
    
    public void subtract(Vector3D u, Vector3D v) {
        x = u.x - v.x;
        y = u.y - v.y;
        z = u.z - v.z;
    }
    
    // expects planeNormal to be normalized
    public float distancePointPlane(Vector3D planePt, Vector3D planeNormal) {
        return planeNormal.x * (x - planePt.x) + planeNormal.y * (y - planePt.y) + planeNormal.z * (z - planePt.z);
    }
    
    public float length() {
        return (float)Math.sqrt(x * x + y * y + z * z);
    }

    public void zero() {
        x = y = z = 0.0f;
    }

    public void divideByW() {
        float w_1 = 1.0f / w;
        x *= w_1;
        y *= w_1;
        z *= w_1;
        w = 1.0f;
    }

    public String toString() {
        return new String(" ["+(x/w)+", "+(y/w)+", "+(z/w)+"]");
    }
    
    
}

