Last active
August 29, 2015 14:07
-
-
Save edom18/f366d2f35c39840b138f to your computer and use it in GitHub Desktop.
[WebGL] スキニングメッシュ(ボーン)の仕組みを自前で実装してみる ref: http://qiita.com/edo_m18/items/31ee6cbc3b3ff22013ae
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var newPosition = []; | |
var newNormal = []; | |
for (var i = 0; i < 12; i++) { | |
var idxBase = i * 3; | |
var idx0 = idxBase + 0; | |
var idx1 = idxBase + 1; | |
var idx2 = idxBase + 2; | |
var comb1 = [ | |
mat4(), | |
mat4(), | |
mat4(), | |
mat4() | |
]; | |
var comb2 = mat4.zero; | |
for (var j = 0; j < 3; j++) { | |
var boneIdx = i * 4 + j; | |
var weightIdx = i * 3 + j; | |
mat4.multiplyScalar(combMatArr[plane.boneIndices[boneIdx]], plane.weights[weightIdx], comb1[j]); | |
} | |
var weight = 1.0 - (plane.weights[i * 3 + 0] + | |
plane.weights[i * 3 + 1] + | |
plane.weights[i * 3 + 2]); | |
mat4.multiplyScalar(combMatArr[plane.boneIndices[i * 4 + 3]], weight, comb1[3]); | |
for (var k = 0; k < 4; k++) { | |
mat4.add(comb2, comb1[k], comb2); | |
} | |
var pos = vec3(plane.position[idx0], | |
plane.position[idx1], | |
plane.position[idx2]); | |
vec3.applyMatrix4(pos, comb2, pos); | |
newPosition[idx0] = pos.x; | |
newPosition[idx1] = pos.y; | |
newPosition[idx2] = pos.z; | |
var nor = vec3(plane.normal[idx0], | |
plane.normal[idx1], | |
plane.normal[idx2]); | |
mat4.inverse(comb2, comb2); | |
vec3.applyMatrix4FromRight(nor, comb2, nor); | |
newNormal[idx0] = nor.x; | |
newNormal[idx1] = nor.y; | |
newNormal[idx2] = nor.z; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 各種ボーンを親空間の相対位置に変換 | |
*/ | |
Bone.calcRelativeMat = function (bone, parentOffsetMat) { | |
bone.children.forEach(function (childBone, idx) { | |
Bone.calcRelativeMat(childBone, bone.matrixOffset); | |
}); | |
if (parentOffsetMat) { | |
mat4.multiply(bone.matrixInit, parentOffsteMat, bone.matrixInit); | |
} | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// countはフレームごとに増加していく | |
var s = Math.sin(count) / 5; | |
for (var i = 0; i < bones.length; i++) { | |
// `s`角度だけ全ボーンを回転させる | |
bones[i].rotate(s, axis); | |
} | |
// 合成行列を更新 | |
Bone.updateBone(bones[0], global); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Planeの定義 | |
var plane = { | |
position: [ | |
2.0, 0.0, 0.0, | |
2.0, 1.0, 0.0, | |
3.0, 1.0, 0.0, | |
3.0, 0.0, 0.0, | |
2.0, 2.0, 0.0, | |
3.0, 2.0, 0.0, | |
2.0, 3.0, 0.0, | |
3.0, 3.0, 0.0, | |
2.0, 4.0, 0.0, | |
3.0, 4.0, 0.0, | |
2.0, 5.0, 0.0, | |
3.0, 5.0, 0.0, | |
], | |
color: [ | |
1.0, 0.0, 0.0, 1.0, | |
0.0, 1.0, 0.0, 1.0, | |
0.0, 0.0, 1.0, 1.0, | |
0.0, 0.0, 0.0, 1.0, | |
1.0, 0.0, 0.0, 1.0, | |
0.0, 1.0, 0.0, 1.0, | |
0.0, 0.0, 1.0, 1.0, | |
0.0, 0.0, 0.0, 1.0, | |
1.0, 0.0, 0.0, 1.0, | |
0.0, 1.0, 0.0, 1.0, | |
0.0, 0.0, 1.0, 1.0, | |
0.0, 0.0, 0.0, 1.0, | |
], | |
normal: [ | |
0.0, 0.0, 1.0, | |
0.0, 0.0, 1.0, | |
0.0, 0.0, 1.0, | |
0.0, 0.0, 1.0, | |
0.0, 0.0, 1.0, | |
0.0, 0.0, 1.0, | |
0.0, 0.0, 1.0, | |
0.0, 0.0, 1.0, | |
0.0, 0.0, 1.0, | |
0.0, 0.0, 1.0, | |
0.0, 0.0, 1.0, | |
0.0, 0.0, 1.0, | |
], | |
index: [ | |
0, 1, 2, | |
2, 3, 0, | |
1, 4, 5, | |
5, 2, 1, | |
4, 6, 7, | |
7, 5, 4, | |
6, 8, 9, | |
9, 7, 6, | |
8, 10, 11, | |
11, 9, 8, | |
], | |
boneIndices: [ | |
0, 0, 0, 0, | |
1, 2, 0, 0, | |
0, 1, 0, 0, | |
0, 0, 0, 0, | |
1, 2, 0, 0, | |
1, 2, 0, 0, | |
2, 3, 0, 0, | |
2, 3, 0, 0, | |
3, 4, 0, 0, | |
3, 4, 0, 0, | |
4, 0, 0, 0, | |
4, 0, 0, 0, | |
], | |
weights: [ | |
1.0, 0.0, 0.0, | |
0.5, 0.5, 0.0, | |
0.5, 0.5, 0.0, | |
1.0, 0.0, 0.0, | |
0.5, 0.5, 0.0, | |
0.5, 0.5, 0.0, | |
0.5, 0.5, 0.0, | |
0.5, 0.5, 0.0, | |
0.5, 0.5, 0.0, | |
0.5, 0.5, 0.0, | |
1.0, 0.0, 0.0, | |
1.0, 0.0, 0.0, | |
], | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 中略 | |
init: function (position) { | |
this.matrix = mat4(); | |
this.matrixBone = mat4(); | |
this.matrixComb = mat4(); | |
this.matrixInit = mat4.translate(mat4(), position); | |
this.matrixOffset = mat4.inverse(this.matrixInit); | |
this.children = []; | |
}, | |
// 中略 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var v1 = vec3(0, 1, 0); // 3要素のベクトル | |
var v2 = vec2(0, 1); | |
var v3 = vec3(v2, 0); // vec2成分を流用してvec3を作る | |
var m1 = mat4(); // 引数なしで単位行列を作る | |
var m2 = mat4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); // 引数を与えて初期化 | |
var m3 = mat4(m2); // 同じ値で複製 | |
var result = mat4(); | |
// OpenGLのように結果を得る行列を第3引数に指定する | |
mat4.multiply(m1, m2, result); | |
// 戻り値としても計算できる | |
// result = mat4.multiply(m1, m2); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var nor = vec3(plane.normal[idx0], | |
plane.normal[idx1], | |
plane.normal[idx2]); | |
mat4.inverse(comb2, comb2); | |
vec3.applyMatrix4FromRight(nor, comb2, nor); | |
newNormal[idx0] = nor.x; | |
newNormal[idx1] = nor.y; | |
newNormal[idx2] = nor.z; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var pos = vec3(plane.position[idx0], | |
plane.position[idx1], | |
plane.position[idx2]); | |
vec3.applyMatrix4(pos, comb2, pos); | |
newPosition[idx0] = pos.x; | |
newPosition[idx1] = pos.y; | |
newPosition[idx2] = pos.z; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 中略 | |
rotate: function (angle, axis) { | |
mat4.rotate(this.matrix, angle, axis, this.matrix); | |
this.updateMatrix(); | |
}, | |
// 中略 | |
updateMatrix: function () { | |
mat4.multiply(this.matrixInit, this.matrix, this.matrixBone); | |
}, |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 各種ボーンの合成行列を生成 | |
*/ | |
Bone.updateBone = function (bone, parentWorldMat) { | |
// 親の姿勢行列(ボーン行列)を左から自身の姿勢行列に掛ける | |
mat4.multiply(parentWorldMat, bone.matrixBone, bone.matrixBone); | |
// 自身のオフセット行列を右から掛けて合成行列を生成 | |
mat4.multiply(bone.matrixBone, bone.matrixOffset, bone.matrixComb); | |
bone.children.forEach(function (childBone, idx) { | |
Bone.updateBone(childBone, bone.matrixBone); | |
}); | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
for (var j = 0; j < 3; j++) { | |
var boneIdx = i * 4 + j; | |
var weightIdx = i * 3 + j; | |
mat4.multiplyScalar(combMatArr[plane.boneIndices[boneIdx]], plane.weights[weightIdx], comb1[j]); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment