//
//  MathHelpers.h
//  CRGraphics
//
//  Created by Yaroslav Glushchenko on 7/23/09.
//  Copyright 2009 Corner-A. All rights reserved.
//


//////////////////////////////////////////////////////////////////////
// Math
//////////////////////////////////////////////////////////////////////
struct CRPoint3D
{
	CGFloat x, y, z;
};

struct CRMatrix4x4
{
	CGFloat m11, m12, m13, m14;
	CGFloat m21, m22, m23, m24;
	CGFloat m31, m32, m33, m34;
	CGFloat m41, m42, m43, m44;
};

NS_INLINE CRPoint3D CRPoint3DMake(CGFloat x, CGFloat y, CGFloat z)
{
	CRPoint3D point;
	point.x = x;
	point.y = y;
	point.z = z;
	return point;
}

NS_INLINE CRPoint3D CRTransformPoint(CRPoint3D point, CRMatrix4x4 matrix)
{
	CRPoint3D result;
	result.x = point.x * matrix.m11 + point.y * matrix.m12 + point.z * matrix.m13 + matrix.m14;
	result.y = point.x * matrix.m21 + point.y * matrix.m22 + point.z * matrix.m23 + matrix.m24;
	result.z = point.x * matrix.m31 + point.y * matrix.m32 + point.z * matrix.m33 + matrix.m34;
	return result;
}

NS_INLINE CRPoint3D CRPointFromNSPoint(NSPoint point, CGFloat z)
{
	CRPoint3D result;
	result.x = point.x;
	result.y = point.y;
	result.z = z;
	return result;
}

NS_INLINE CRMatrix4x4 CRPerspectiveTransform(CGFloat fov)
{
	CGFloat N = 1.0f;
	CGFloat F = 1000.0f;
	CGFloat t = N * tanf(fov / 2.0f);
	CGFloat b = -t;
	CGFloat r = t * 1; //aspect
	CGFloat l = -r;
	
	CRMatrix4x4 transform = {
		2 * N / (r - l),	0.0,				(r + l) / (r - l),	0.0,
		0.0,				2 * N / (t - b),	(t + b) / (t - b),	0.0,
		0.0,				0.0,				-(F + N)/ (F - N),	-2 * F * N / (F - N),
		0.0,				0.0,				-1.0,				0.0
	};
	return transform;
}

NS_INLINE CRMatrix4x4 CRRotationTransform(CGFloat angle, CGFloat x, CGFloat y, CGFloat z)
{
	CATransform3D result = CATransform3DRotate(CATransform3DIdentity, angle, x, y, z);
	return *(CRMatrix4x4*)&result;
}

NS_INLINE CRMatrix4x4 CRTransformConcat(CRMatrix4x4 t1, CRMatrix4x4 t2)
{
	CATransform3D result = CATransform3DConcat(*(CATransform3D*)&t1, *(CATransform3D*)&t2);
	return *(CRMatrix4x4*)&result;
}

NS_INLINE CIVector* CIVectorFromPoint(CRPoint3D point)
{
	return [CIVector vectorWithX:point.x Y:point.y Z:point.z];
}