1/*
2	If the current vertex is affected by bones then the vertex position and
3	normal will be transformed by the bone matrices. Each vertex wil have up
4	to 4 bone indices (inBoneIndex) and bone weights (inBoneWeights).
5
6	The indices are used to index into the array of bone matrices
7	(BoneMatrixArray) to get the required bone matrix for transformation. The
8	amount of influence a particular bone has on a vertex is determined by the
9	weights which should always total 1. So if a vertex is affected by 2 bones
10	the vertex position in world space is given by the following equation:
11
12	position = (BoneMatrixArray[Index0] * inVertex) * Weight0 +
13	           (BoneMatrixArray[Index1] * inVertex) * Weight1
14
15	The same proceedure is applied to the normals but the translation part of
16	the transformation is ignored.
17
18	After this the position is multiplied by the view and projection matrices
19	only as the bone matrices already contain the model transform for this
20	particular mesh. The two-step transformation is required because lighting
21	will not work properly in clip space.
22*/
23
24attribute highp   vec3 inVertex;
25attribute mediump vec3 inNormal;
26attribute mediump vec3 inTangent;
27attribute mediump vec3 inBiNormal;
28attribute mediump vec2 inTexCoord;
29attribute mediump vec4 inBoneIndex;
30attribute mediump vec4 inBoneWeights;
31
32uniform highp   mat4 ViewProjMatrix;
33uniform mediump vec3 LightPos;
34uniform mediump	int	 BoneCount;
35uniform highp   mat4 BoneMatrixArray[8];
36uniform highp   mat3 BoneMatrixArrayIT[8];
37uniform bool	bUseDot3;
38
39varying mediump vec3 Light;
40varying mediump vec2 TexCoord;
41
42void main()
43{
44	if(BoneCount > 0)
45	{
46		// On PowerVR SGX it is possible to index the components of a vector
47		// with the [] operator. However this can cause trouble with PC
48		// emulation on some hardware so we "rotate" the vectors instead.
49		mediump ivec4 boneIndex = ivec4(inBoneIndex);
50		mediump vec4 boneWeights = inBoneWeights;
51
52		highp mat4 boneMatrix = BoneMatrixArray[boneIndex.x];
53		mediump mat3 normalMatrix = BoneMatrixArrayIT[boneIndex.x];
54
55		highp vec4 position = boneMatrix * vec4(inVertex, 1.0) * boneWeights.x;
56		mediump vec3 worldNormal = normalMatrix * inNormal * boneWeights.x;
57
58		mediump vec3 worldTangent;
59		mediump vec3 worldBiNormal;
60
61		if(bUseDot3)
62		{
63			worldTangent = normalMatrix * inTangent * boneWeights.x;
64			worldBiNormal = normalMatrix * inBiNormal * boneWeights.x;
65		}
66
67		for (lowp int i = 1; i < 3; ++i)
68		{
69			if(i < BoneCount)
70			{
71				// "rotate" the vector components
72				boneIndex = boneIndex.yzwx;
73				boneWeights = boneWeights.yzwx;
74
75				boneMatrix = BoneMatrixArray[boneIndex.x];
76				normalMatrix = BoneMatrixArrayIT[boneIndex.x];
77
78				position += boneMatrix * vec4(inVertex, 1.0) * boneWeights.x;
79				worldNormal += normalMatrix * inNormal * boneWeights.x;
80
81				if(bUseDot3)
82				{
83					worldTangent += normalMatrix * inTangent * boneWeights.x;
84					worldBiNormal += normalMatrix * inBiNormal * boneWeights.x;
85				}
86			}
87		}
88		gl_Position = ViewProjMatrix * position;
89
90		// lighting
91		mediump vec3 TmpLightDir = normalize(LightPos - position.xyz);
92
93		if(bUseDot3)
94		{
95			Light.x = dot(normalize(worldTangent), TmpLightDir);
96			Light.y = dot(normalize(worldBiNormal), TmpLightDir);
97			Light.z = dot(normalize(worldNormal), TmpLightDir);
98		}
99		else
100		{
101			Light.x = dot(normalize(worldNormal), TmpLightDir);
102		}
103	}
104
105
106	// Pass through texcoords
107	TexCoord = inTexCoord;
108}
109