@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
85 lines (66 loc) • 3.03 kB
JavaScript
/**
*
* @param {number[]|Float32Array} destination
* @param {number} destination_offset
* @param {number[]|Float32Array} positions
* @param {number} vertex_count
* @param {number[]|Float32Array} skin_weights_array
* @param {number[]|Uint32Array} skin_indices_array
* @param {number[]|Float32Array} bone_matrices 4x3 transform matrices
* @param {number[]|Float32Array} m4_bind
* @param {number[]|Float32Array} m4_bind_inv
* @param {number} [bones_per_vertex]
*/
export function mesh_apply_skeletal_vertex_skinning(
destination,
destination_offset,
positions,
vertex_count,
skin_weights_array,
skin_indices_array,
bone_matrices,
m4_bind,
m4_bind_inv,
bones_per_vertex = 4
) {
let index, i, x, y, z;
for (index = 0; index < vertex_count; index++) {
const index3 = index * 3;
//read vertex position
const px = positions[index3];
const py = positions[index3 + 1];
const pz = positions[index3 + 2];
//apply bind matrix transform to vertex
const bx = m4_bind[0] * px + m4_bind[4] * py + m4_bind[8] * pz + m4_bind[12];
const by = m4_bind[1] * px + m4_bind[5] * py + m4_bind[9] * pz + m4_bind[13];
const bz = m4_bind[2] * px + m4_bind[6] * py + m4_bind[10] * pz + m4_bind[14];
x = 0;
y = 0;
z = 0;
for (i = 0; i < bones_per_vertex; i++) {
const skin_index = index * bones_per_vertex + i;
const skin_weight = skin_weights_array[skin_index];
if (skin_weight !== 0) {
const boneIndex = skin_indices_array[skin_index];
const bdIndex = boneIndex * 12;
const sx = bone_matrices[bdIndex] * bx + bone_matrices[bdIndex + 1] * by + bone_matrices[bdIndex + 2] * bz + bone_matrices[bdIndex + 3];
const sy = bone_matrices[bdIndex + 4] * bx + bone_matrices[bdIndex + 5] * by + bone_matrices[bdIndex + 6] * bz + bone_matrices[bdIndex + 7];
const sz = bone_matrices[bdIndex + 8] * bx + bone_matrices[bdIndex + 9] * by + bone_matrices[bdIndex + 10] * bz + bone_matrices[bdIndex + 11];
const tx = sx * skin_weight;
const ty = sy * skin_weight;
const tz = sz * skin_weight;
x += tx;
y += ty;
z += tz;
}
}
//apply inverse bind matrix
const wx = m4_bind_inv[0] * x + m4_bind_inv[4] * y + m4_bind_inv[8] * z + m4_bind_inv[12];
const wy = m4_bind_inv[1] * x + m4_bind_inv[5] * y + m4_bind_inv[9] * z + m4_bind_inv[13];
const wz = m4_bind_inv[2] * x + m4_bind_inv[6] * y + m4_bind_inv[10] * z + m4_bind_inv[14];
const destination_address = destination_offset + index3;
destination[destination_address] = wx;
destination[destination_address + 1] = wy;
destination[destination_address + 2] = wz;
}
}