Vertex shader help pt.2

This code is for skeletal animation

so say i have this code

#define NUM_BONES 50
uniform mat4 bones[NUM_BONES];
uniform vec4 weights[NUM_BONES];
uniform ivec4 attachments[NUM_BONES];
 
in vec4 position;
 
void main() {
    vec4 position4 = vec4(position, 1.0);
    vec4 worldPosition = vec4(0.0);
    for (int i = 0; i < 4; i++)
        worldPosition += weights[attachments[gl_VertexID][i]] * (bones[attachments[gl_VertexID][i]] * position);
    gl_Position = gl_ModelViewProjectionMatrix * worldPosition;
}

1.Why is the weights a vec4? Isn’t a weight only one value, like a float?

2.in the vertex shader, why am i only able to use 1D arrays? I have to make about 8 uniform arrays in order to use all the information i need.

  1. When a parent bone rotates, the matrix of the bone is given a slight change in rotation(Im converting the matrix to quanternion and then multiplying quanternions), how do i correctly rotate the child bones. For example, if i rotate the shoulder, the rest of the arm has to rotate the same amount. Could somebody explain this further? / in more detail.

  2. with the code below, it shows only 4 bones per vertex. What if i want more than just 4? And once again i dont understand the vec4 weight thing.

in vec3 position;
in vec2 textureCoords;
in vec3 normal;
in vec4 BoneIndex;
in vec4 Weights;
uniform mat4 bones[10];

void main()
{
vec4 newvertex;
vev3 newNormal;
new newvertex += bones[int(BoneIndex.x)]*gl_Vertex*Weights.x;
new newNormal+= mat3(bones[int(BoneIndex.x)])*gl_Normal*Weights.x;

new newvertex += bones[int(BoneIndex.y)]*gl_Vertex*Weights.y;
new newNormal+= mat3(bones[int(BoneIndex.y)])*gl_Normal*Weights.y;

new newvertex += bones[int(BoneIndex.z)]*gl_Vertex*Weights.z;
new newNormal+= mat3(bones[int(BoneIndex.z)])*gl_Normal*Weights.z;

new newvertex += bones[int(BoneIndex.w)]*gl_Vertex*Weights.w;
new newNormal+= mat3(bones[int(BoneIndex.w)])*gl_Normal*Weights.w;

gl_Position = Projection*View*Transform*newvertex ;
newNormal = mat4(Transform)*newNormal ;
}

Currently i have this code as my vertex shader:

#version 400 core

in vec3 position;
in vec2 textureCoords;
in vec3 normal;

out vec2 pass_textureCoords;
out vec3 surfaceNormal;
out vec3 toLightVector;
out vec3 toCameraVector;

uniform mat4 transformationMatrix;
uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform vec3 lightPosition;
uniform int boneCount;
uniform mat4 bonesMatrix[21];
uniform float boneWeights[2013];

void main(void){
	float bonepos_x = transformationMatrix[3][0];
	float bonepos_y = transformationMatrix[3][1];
	float bonepos_z = transformationMatrix[3][2];
	vec4 worldPosition = (transformationMatrix* vec4(position,1.0));
	gl_Position = projectionMatrix * viewMatrix * worldPosition; 
	pass_textureCoords = textureCoords;
	surfaceNormal = (transformationMatrix * vec4(normal,0.0)).xyz;
	toLightVector = lightPosition - worldPosition.xyz;
	toCameraVector = (inverse(viewMatrix) * vec4(0.0,0.0,0.0,1.0)).xyz - worldPosition.xyz;
}

as you can see i have an array of boneWeights, but i think it needs to be in vec4 to work? but i dont know.

If you can help me out in any way go ahead! Thanks :D.

This assumes that each vertex may be affected by up to four bones. If you want more, you need to use some other approach. if each vertex is only affected by a single bone, you don’t need weights.

GLSL only supports 1D arrays. You can’t have arrays of arrays.

You can have arrays of vectors or arrays of matrices. You can “unravel” larger arrays yourself. E.g. given

float data[rows][cols];

You can use

float data[rows*cols];

and translate data[r][c] to data[cols*r+c].

Or you can use a texture as an array.

Normally, each transformation is relative to the parent, e.g. the shoulder rotation is the rotation of the upper arm relative to the shoulder blades. A joints absolute transformation is obtained by multiplying the parent’s absolute transformation by the joint’s relative transformation.

So given a hierarchy of joints, you start with either an identity matrix or an absolute transformation for the object as a whole. You then perform a recursive traversal over the hierarchy, generating the absolute transformation for each joint (you always visit the parent before visiting its children, so the parent’s absolute transformation is already available when you need to calculate that of the child).

Having four weights is convenient because it’s enough for many cases while being relatively simple to implement given GLSL’s limitation of 1D arrays. One problem with having many bone attachments per vertex is that performance is dictated by the maximum number rather than the average number (i.e. if most vertices only have one bone but some have 20, you’ll end up performing 20 iterations for every vertex).

That code basically unwraps the loop, and accesses the weights using .x, .y, .z, .w. You can access vector elements using either structure notation (.x, .y etc) or array notation ([0], [1]) etc. Using array notation lets you use a loop.

Thank you once again!