OpenGL ES2 骨骼动画
OpenGL ES2 skeletal animation
"I try to learn skeletal animation so I have many misunderstands"
我有一个从 Blender 导出的非常简单的 JSON 格式文件,它有一个立方体和一个只旋转了 4 帧的骨骼,所以我加载了具有 4 个属性的 VBO,位置 vec4、正常 vec4、权重 vec2 和骨骼索引 vec2渲染正确,骨骼有 pos、rotq 和 scale,所以我使用以下函数创建骨骼的变换矩阵
public static float[] createMat4(float[] t, float[] r, float[] s) {
float[] mat4 = new float[16];
float[] T = new float[16];
float[] R = new float[16];
float[] S = new float[16];
setIdentityM(T, 0);
setIdentityM(R, 0);
setIdentityM(S, 0);
translateM(T, 0, t[0], t[1], t[2]);
rotateM(R, 0, r[3], r[0], r[1], r[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;
}
所以我通过将绑定乘以它的逆来计算骨骼最终矩阵 "as I understand" 对于每一帧,我将该矩阵乘以关键帧矩阵,该矩阵也是我通过先前的方法从 pos、rotq 和scl,最后我通过 mat4[] uniform 将这些矩阵上传到 GPU,这就是顶点着色器
uniform mat4 modelview;
uniform mat4 projection;
uniform mat4 bones[BONES];
uniform int animated;
attribute vec4 vertexPosition;
attribute vec4 vertexNormal;
attribute vec2 textureCoords;
attribute vec2 skinweight;
attribute vec2 skinindex;
varying vec2 vTextureCoords;
varying vec4 viewDir;
varying vec4 modelviewNormal;
varying mat4 mv;
void main() {
mv=modelview;
vec4 newVertex;
vec4 newNormal;
if(animated==1){
int index;
index=int(skinindex.x);
newVertex += (bones[index] * vertexPosition * skinweight.x) ;
newNormal += (bones[index] * vertexPosition * skinweight.x) ;
index=int(skinindex.y);
newVertex += (bones[index] * vertexPosition * skinweight.y);
newNormal += (bones[index] * vertexNormal* skinweight.y);
}
else{
newVertex=vertexPosition;
newNormal=vertexNormal;
}
vec4 modelviewVertex=(modelview * newNormal);
modelviewNormal = normalize(modelviewVertex);
viewDir = normalize(-modelview*newVertex);
vTextureCoords = textureCoords;
gl_Position = (projection * modelview )* vec4(newVertex.xyz, 1.0);
}
当渲染结果出乎意料时,一些面消失了并且顶点随机移动。
问题出在四元数旋转上,我用这个函数把四元数转成旋转矩阵
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];
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;
}
终于搞定骨骼动画了
newVertex += (bones[index] * vertexPosition * skinweight.x) ;
newNormal += (bones[index] * vertexPosition * skinweight.x) ;
我在两个未初始化的值上看到一个 += 赋值运算符。
"I try to learn skeletal animation so I have many misunderstands" 我有一个从 Blender 导出的非常简单的 JSON 格式文件,它有一个立方体和一个只旋转了 4 帧的骨骼,所以我加载了具有 4 个属性的 VBO,位置 vec4、正常 vec4、权重 vec2 和骨骼索引 vec2渲染正确,骨骼有 pos、rotq 和 scale,所以我使用以下函数创建骨骼的变换矩阵
public static float[] createMat4(float[] t, float[] r, float[] s) {
float[] mat4 = new float[16];
float[] T = new float[16];
float[] R = new float[16];
float[] S = new float[16];
setIdentityM(T, 0);
setIdentityM(R, 0);
setIdentityM(S, 0);
translateM(T, 0, t[0], t[1], t[2]);
rotateM(R, 0, r[3], r[0], r[1], r[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;
}
所以我通过将绑定乘以它的逆来计算骨骼最终矩阵 "as I understand" 对于每一帧,我将该矩阵乘以关键帧矩阵,该矩阵也是我通过先前的方法从 pos、rotq 和scl,最后我通过 mat4[] uniform 将这些矩阵上传到 GPU,这就是顶点着色器
uniform mat4 modelview;
uniform mat4 projection;
uniform mat4 bones[BONES];
uniform int animated;
attribute vec4 vertexPosition;
attribute vec4 vertexNormal;
attribute vec2 textureCoords;
attribute vec2 skinweight;
attribute vec2 skinindex;
varying vec2 vTextureCoords;
varying vec4 viewDir;
varying vec4 modelviewNormal;
varying mat4 mv;
void main() {
mv=modelview;
vec4 newVertex;
vec4 newNormal;
if(animated==1){
int index;
index=int(skinindex.x);
newVertex += (bones[index] * vertexPosition * skinweight.x) ;
newNormal += (bones[index] * vertexPosition * skinweight.x) ;
index=int(skinindex.y);
newVertex += (bones[index] * vertexPosition * skinweight.y);
newNormal += (bones[index] * vertexNormal* skinweight.y);
}
else{
newVertex=vertexPosition;
newNormal=vertexNormal;
}
vec4 modelviewVertex=(modelview * newNormal);
modelviewNormal = normalize(modelviewVertex);
viewDir = normalize(-modelview*newVertex);
vTextureCoords = textureCoords;
gl_Position = (projection * modelview )* vec4(newVertex.xyz, 1.0);
}
当渲染结果出乎意料时,一些面消失了并且顶点随机移动。
问题出在四元数旋转上,我用这个函数把四元数转成旋转矩阵
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];
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;
}
终于搞定骨骼动画了
newVertex += (bones[index] * vertexPosition * skinweight.x) ;
newNormal += (bones[index] * vertexPosition * skinweight.x) ;
我在两个未初始化的值上看到一个 += 赋值运算符。