Android OpenGL ES2骨骼动画儿童骨骼矩阵

时间:2016-12-20 11:33:22

标签: java android opengl-es opengl-es-2.0

如果我有一个带有单个骨骼的几何体我可以用动画渲染它但是如果它有2个骨骼顶点没有正确动画,我加载从混合器导出的JSON格式,因为我理解子骨骼相对矩阵乘以它父绝对矩阵然后乘以它相对矩阵逆,然后每个骨矩阵乘以关键帧矩阵得到最终矩阵然后将这些矩阵发送到顶点着色器。 我使用VBO将重量和骨骼索引设置为属性。

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);

我注意到用任何浮点数更改子骨骼矩阵都不会改变结果。

1 个答案:

答案 0 :(得分:0)

您可以使用AssimpLib,它易于使用并支持大多数格式,包括带有骨骼动画的collada