2016-12-20 1 views
0

Wenn ich eine Geometrie mit einzelnen Knochen habe, kann ich es mit Animation rendern, aber wenn es 2 Knochen hat, werden die Scheitelpunkte nicht korrekt animiert, ich lade ein JSON-Format exportiert aus Blender, wie ich verstehe die Kindknochenrelativmatrix multipliziert mit ihrer Elternabsolutmatrix, dann multipliziert mit dieser relativen Matrix, die invers ist, dann multipliziert jede Knochenmatrix mit der Schlüsselrahmenmatrix, um die Endmatrix zu erhalten, und sendet diese Matrizen dann an den Vertexshader. Ich stelle den Gewichts- und Knochenindex als Attribute mit dem VBO ein.Android OpenGL ES2 Skelettanimation Kind Knochenmatrix

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

Dies ist der Code

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

Dies ist die Funktion, welche die Matrix von der Position, Quaternion und Maßstab machen machen:

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

I durch diese Linie der Knochen Array uniform set :

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

schließlich ist dies der Vertex-Shader:

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

Ich bemerkte, dass das Kind Knochenmatrix mit irgendwelchen Schwimmer ändert das Ergebnis nicht ändern.

Antwort

0

Sie können AssimpLib verwenden, es ist einfach zu bedienen und unterstützt die meisten Formate einschließlich Collada mit Skelettanimationen