MSTRINGIFY(

float length3(float4 a)
{
	a.w = 0;
	return length(a);
}

float4 normalize3(float4 a)
{
	a.w = 0;
	return normalize(a);
}

__kernel void 
ResetNormalsAndAreasKernel(
	const unsigned int numNodes,
	__global float4 * g_vertexNormals,
	__global float * g_vertexArea GUID_ARG)
{
	if( get_global_id(0) < numNodes )
	{
		g_vertexNormals[get_global_id(0)] = (float4)(0.0f, 0.0f, 0.0f, 0.0f);
		g_vertexArea[get_global_id(0)]    = 0.0f;
	}
}


__kernel void 
UpdateSoftBodiesKernel(
	const unsigned int startFace,
	const unsigned int numFaces,
	__global int4 * g_triangleVertexIndexSet,
	__global float4 * g_vertexPositions,
	__global float4 * g_vertexNormals,
	__global float * g_vertexArea,
	__global float4 * g_triangleNormals,
	__global float * g_triangleArea GUID_ARG)
{
	int faceID = get_global_id(0) + startFace;
	if( get_global_id(0) < numFaces )
	{		
		int4 triangleIndexSet = g_triangleVertexIndexSet[ faceID ];
		int nodeIndex0 = triangleIndexSet.x;
		int nodeIndex1 = triangleIndexSet.y;
		int nodeIndex2 = triangleIndexSet.z;

		float4 node0 = g_vertexPositions[nodeIndex0];
		float4 node1 = g_vertexPositions[nodeIndex1];
		float4 node2 = g_vertexPositions[nodeIndex2];
		float4 nodeNormal0 = g_vertexNormals[nodeIndex0];
		float4 nodeNormal1 = g_vertexNormals[nodeIndex1];
		float4 nodeNormal2 = g_vertexNormals[nodeIndex2];
		float vertexArea0 = g_vertexArea[nodeIndex0];
		float vertexArea1 = g_vertexArea[nodeIndex1];
		float vertexArea2 = g_vertexArea[nodeIndex2];
		
		float4 vector0 = node1 - node0;
		float4 vector1 = node2 - node0;
		
		float4 faceNormal = cross(vector0, vector1);
		float triangleArea = length(faceNormal);

		nodeNormal0 = nodeNormal0 + faceNormal;
		nodeNormal1 = nodeNormal1 + faceNormal;
		nodeNormal2 = nodeNormal2 + faceNormal;
		vertexArea0 = vertexArea0 + triangleArea;
		vertexArea1 = vertexArea1 + triangleArea;
		vertexArea2 = vertexArea2 + triangleArea;
		
		g_triangleNormals[faceID] = normalize3(faceNormal);
		g_vertexNormals[nodeIndex0] = nodeNormal0;
		g_vertexNormals[nodeIndex1] = nodeNormal1;
		g_vertexNormals[nodeIndex2] = nodeNormal2;
		g_triangleArea[faceID] = triangleArea;
		g_vertexArea[nodeIndex0] = vertexArea0;
		g_vertexArea[nodeIndex1] = vertexArea1;
		g_vertexArea[nodeIndex2] = vertexArea2;
	}
}

__kernel void 
NormalizeNormalsAndAreasKernel( 
	const unsigned int numNodes,
	__global int * g_vertexTriangleCount,
	__global float4 * g_vertexNormals,
	__global float * g_vertexArea GUID_ARG)
{
	if( get_global_id(0) < numNodes )
	{
		float4 normal = g_vertexNormals[get_global_id(0)];
		float area = g_vertexArea[get_global_id(0)];
		int numTriangles = g_vertexTriangleCount[get_global_id(0)];
		
		float vectorLength = length3(normal);
		
		g_vertexNormals[get_global_id(0)] = normalize3(normal);
		g_vertexArea[get_global_id(0)] = area/(float)(numTriangles);
	}
}

);
