2016-12-20 61 views
0

如果我有一個帶有單個骨骼的幾何體,我可以使用動畫來渲染它,但是如果它有2個骨骼,頂點不會正確動畫,我會加載從blender導出的JSON格式,據我瞭解子骨骼相對矩陣乘以它的父絕對矩陣,然後乘以相對矩陣的逆矩陣,然後每個骨骼矩陣乘以關鍵幀矩陣以得到最終矩陣,然後將這些矩陣發送到頂點着色器。 我將體重和骨骼指數設置爲VBO的屬性。Android OpenGL ES2骨骼動畫子骨骼矩陣

for (int y = 0; y < g.getBones().size(); y++) { 
    com.thatulborooj.opengl.objects.Bone bone = new com.thatulborooj.opengl.objects.Bone(); 
    Bone gBone = g.getBones().get(y); 
    float[] t = new float[] { gBone.getPosition().get(0), gBone.getPosition().get(0), gBone.getPosition().get(0) }; 
    float[] r = new float[] { gBone.getRotation().get(0), gBone.getRotation().get(1), gBone.getRotation().get(2), gBone.getRotation().get(3) }; 
    float[] s = gBone.getScale() == null ? new float[] { 1, 1, 1 } : new float[] { gBone.getScale().get(0), gBone.getScale().get(1), gBone.getScale().get(2) }; 
    float[] nMatrix = createMat4(t, r, s); 
    float[] inverseMatrix = new float[16]; 
    if (gBone.getParent() == -1) { 
     bone.setBindMatrix(nMatrix); 
     invertM(inverseMatrix, 0, nMatrix, 0); 
     float[] fMatrix = new float[16]; 
     multiplyMM(fMatrix, 0, nMatrix, 0, inverseMatrix, 0); 
     bone.setFinalMatrix(fMatrix); 
    } else { 
     float[] pMatrix = mesh.getBones().get(gBone.getParent()).getBindMatrix(); 
     float[] bMatrix = new float[16]; 
     multiplyMM(bMatrix, 0, pMatrix, 0, nMatrix, 0); 
     bone.setBindMatrix(bMatrix); 
     invertM(inverseMatrix, 0, bMatrix, 0); 
     float[] fMatrix = new float[16]; 
     multiplyMM(fMatrix, 0, bMatrix, 0, inverseMatrix, 0); 
     bone.setFinalMatrix(fMatrix); 
     } 
     bone.setName(gBone.getName()); 
     bone.setParent(gBone.getParent()); 
     mesh.getBones().add(bone); 
    } 
} 

這是渲染代碼

if (animated) { 
     if (playing) { 
      if (curFrame < frames) { 
       for (int i = 0; i < bones.size(); i++) { 
        Key key = animations.get(0).getHierarchy().get(i).getKeys().get(curFrame); 
        setIdentityM(aMatrix, 0); 
        multiplyMM(aMatrix, 0, bones.get(i).getFinalMatrix(), 0, key.getMatrix(), 0); 
        for (int q = 0; q < 16; q++) { 
         bs[i][q] = aMatrix[q]; 
        } 
       } 
       curFrame++; 
      } else 
       curFrame = 0; 
      shaderProgram.setBones(bs); 
     } 
    } 

這是使從位置,四元數和分的基體中的功能:

public static float[] createMat4(float[] t, float[] r, float[] s) { 
    float[] mat4 = new float[16]; 
    float[] T = new float[16]; 
    float[] R = quaternionToMatrix(r); 
    float[] S = new float[16]; 
    setIdentityM(T, 0); 
    setIdentityM(S, 0); 
    translateM(T, 0, t[0], t[1], t[2]); 
    scaleM(S, 0, s[0], s[1], s[2]); 
    float[] temp = new float[16]; 
    multiplyMM(temp, 0, T, 0, R, 0); 
    multiplyMM(mat4, 0, temp, 0, S, 0); 
    return mat4; 
} 

private static float[] quaternionToMatrix(float[] q) { 
    float[] m = new float[16]; 
    final float xx = q[0] * q[0]; 
    final float xy = q[0] * q[1]; 
    final float xz = q[0] * q[2]; 
    final float xw = q[0] * q[3]; 
    final float yy = q[1] * q[1]; 
    final float yz = q[1] * q[2]; 
    final float yw = q[1] * q[3]; 
    final float zz = q[2] * q[2]; 
    final float zw = q[2] * q[3]; 
    // Set matrix from quaternion 
    m[0] = 1 - 2 * (yy + zz); 
    m[1] = 2 * (xy - zw); 
    m[2] = 2 * (xz + yw); 
    m[3] = 0; 
    m[4] = 2 * (xy + zw); 
    m[5] = 1 - 2 * (xx + zz); 
    m[6] = 2 * (yz - xw); 
    m[7] = 0; 
    m[8] = 2 * (xz - yw); 
    m[9] = 2 * (yz + xw); 
    m[10] = 1 - 2 * (xx + yy); 
    m[11] = 0; 
    m[12] = 0; 
    m[13] = 0; 
    m[14] = 0; 
    m[15] = 1; 
    return m; 
} 

我通過此線設置的骨頭陣列均勻:

private void setBonesUniforms() { 
    for (int i = 0; i < bones.length; i++) { 
     int uBonesLocation = glGetUniformLocation(program, "bones[" + i + "]"); 
     glUniformMatrix4fv(uBonesLocation, 1, false, bones[i], 0); 
    } 
} 

終於這是頂點着色器:

vec4 newVertex=vertexPosition; 
vec4 newNormal=vertexNormal; 
if(animated==1){ 
    int index; 
    index=int(skinindex.x); 
    newVertex = (bones[index] * skinweight.x) * vertexPosition; 
    newNormal = (bones[index] * skinweight.x) * vertexNormal; 

    index=int(skinindex.y); 
    newVertex += (bones[index] * skinweight.y) * vertexPosition; 
    newNormal += (bones[index] * skinweight.y) * vertexNormal; 
} 
newVertex=vec4(newVertex.xyz, 1.0); 

我注意到用任何浮點數更改子骨骼矩陣不會改變結果。

回答

0

你可以使用AssimpLib它很容易使用和支持大多數格式,包括與骨骼動畫collada