module gedo.math.vector;



private import std.math;
private import gedo.video.ggl;



typedef float[3] Vector;
typedef float[2] Vector2D;



public void invert(Vector a, Vector b)
{
	a[0] = -b[0];
	a[1] = -b[1];
	a[2] = -b[2];
}


public void invert(Vector2D a, Vector2D b)
{
	a[0] = -b[0];
	a[1] = -b[1];
}


public void invert(Vector v)
{
	v[0] = -v[0];
	v[1] = -v[1];
	v[2] = -v[2];
}


public void invert(Vector2D v)
{
	v[0] = -v[0];
	v[1] = -v[1];
}


public void add(Vector a, Vector b, Vector c)
{
	a[0] = b[0] + c[0];
	a[1] = b[1] + c[1];
	a[2] = b[2] + c[2];
}


public void add(Vector2D a, Vector2D b, Vector2D c)
{
	a[0] = b[0] + c[0];
	a[1] = b[1] + c[1];
}


public void add(Vector a, Vector b)
{
	a[0] += b[0];
	a[1] += b[1];
	a[2] += b[2];
}


public void add(Vector2D a, Vector2D b)
{
	a[0] += b[0];
	a[1] += b[1];
}


public void subtract(Vector a, Vector b, Vector c)
{
	a[0] = b[0] - c[0];
	a[1] = b[1] - c[1];
	a[2] = b[2] - c[2];
}


public void subtract(Vector2D a, Vector2D b, Vector2D c)
{
	a[0] = b[0] - c[0];
	a[1] = b[1] - c[1];
}


public void subtract(Vector a, Vector b)
{
	a[0] -= b[0];
	a[1] -= b[1];
	a[2] -= b[2];
}


public void subtract(Vector2D a, Vector2D b)
{
	a[0] -= b[0];
	a[1] -= b[1];
}


public void multiply(Vector a, float b)
{
	a[0] *= b;
	a[1] *= b;
	a[2] *= b;
}


public void multiply(Vector2D a, float b)
{
	a[0] *= b;
	a[1] *= b;
}


public void multiply(Vector c, Vector a, float b)
{
	c[0] = a[0] * b;
	c[1] = a[1] * b;
	c[2] = a[2] * b;
}


public void multiply(Vector2D c, Vector2D a, float b)
{
	c[0] = a[0] * b;
	c[1] = a[1] * b;
}


public void lerp(Vector a, Vector b, float v)
{
	Vector d;
	
	subtract(d, b, a);

	auto l = magnitude(d);

	if(v >= l)
	{
		a[] = b[];
	}
	else
	{
		multiply(d, v/l);

		add(a, d);
	}
}


public void lerp(Vector2D a, Vector2D b, float v)
{
	Vector2D d;

	subtract(d, b, a);

	auto l = magnitude(d);

	if(v >= l)
	{
		a[] = b[];
	}
	else
	{
		multiply(d, v/l);

		add(a, d);
	}
}


public void blend(Vector c, float ka, Vector a, float kb, Vector b)
{
	c[0] = ka*a[0] + kb*b[0];
	c[1] = ka*a[1] + kb*b[1];
	c[2] = ka*a[2] + kb*b[2];
}


public void blend(Vector2D c, float ka, Vector2D a, float kb, Vector2D b)
{
	c[0] = ka*a[0] + kb*b[0];
	c[1] = ka*a[1] + kb*b[1];
}


public float magnitude(Vector v)
{
	return .std.math.sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
}


public float magnitude(Vector2D v)
{
	return .std.math.sqrt(v[0]*v[0] + v[1]*v[1]);
}


public float square(Vector v)
{
	return v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
}


public float square(Vector2D v)
{
	return v[0]*v[0] + v[1]*v[1];
}


public void normalize(Vector v)
{
	auto l = magnitude(v);

	if(l > 0.0)
	{
		multiply(v, 1/l);
	}
	else
	{
		v[0] = 0.0;
		v[1] = 1.0;
		v[2] = 0.0;
	}
}


public void normalize(Vector2D v)
{
	auto l = magnitude(v);

	if(l > 0.0)
	{
		multiply(v, 1/l);
	}
	else
	{
		v[0] = 1.0;
		v[1] = 0.0;
	}
}


public float dot(Vector v0, Vector v1)
{
	return v0[0]*v1[0] + v0[1]*v1[1] + v0[2]*v1[2];
}


public float dot(Vector2D v0, Vector2D v1)
{
	return v0[0]*v1[0] + v0[1]*v1[1];
}


public void cross(Vector c, Vector a, Vector b)
{
	c[0] = a[1]*b[2] - a[2]*b[1];
	c[1] = a[2]*b[0] - a[0]*b[2];
	c[2] = a[0]*b[1] - a[1]*b[0];
}


public void translate(Vector v)
{
	GGL_translate(v[0], v[1], v[2]);
}


public void translate(Vector2D v)
{
	GGL_translate(v[0], v[1], 0.0);
}

