forked from phenom/healer-man
Release Healer Man 0.1.30
This commit is contained in:
1 parent
544c1bee91
commit
7d7fd567f0
845 files changed
+2040
-87
No files matched your search
@@ -7,6 +7,17 @@ const SKIN_SUBMESH_SIZE = 48;
|
||||
const SKIN_TEXTURE_UNIT_SIZE = 24;
|
||||
|
||||
const VALUE_TYPES = {
|
||||
floatQuaternion: {
|
||||
byteLength: 16,
|
||||
read: (buffer, offset) => [0, 4, 8, 12].map((component) => buffer.readFloatLE(offset + component)),
|
||||
},
|
||||
quaternion: {
|
||||
byteLength: 8,
|
||||
read: (buffer, offset) => [0, 2, 4, 6].map((component) => {
|
||||
const value = buffer.readInt16LE(offset + component);
|
||||
return (value < 0 ? value + 32768 : value - 32767) / 32767;
|
||||
}),
|
||||
},
|
||||
uint8x4: {
|
||||
byteLength: 4,
|
||||
read: (buffer, offset) => Array.from(buffer.subarray(offset, offset + 4)),
|
||||
@@ -211,6 +222,39 @@ function decodeTextureWeights(buffer, name) {
|
||||
));
|
||||
}
|
||||
|
||||
/** Source-space bone and UV animation, shared by meshes, particles and ribbons. */
|
||||
export function decodeWotlkM2Animation(buffer, name = "M2") {
|
||||
const bones = readArrayHeader(buffer, 44, `${name} bones`);
|
||||
if (bones.count) assertRange(buffer, bones.offset, bones.count * 88, `${name} bones`);
|
||||
const transforms = readArrayHeader(buffer, 96, `${name} texture transforms`);
|
||||
if (transforms.count) assertRange(buffer, transforms.offset, transforms.count * 60, `${name} texture transforms`);
|
||||
return {
|
||||
globalSequences: decodeArray(buffer, 20, VALUE_TYPES.uint32, `${name} global sequences`).values,
|
||||
bones: Array.from({ length: bones.count }, (_, index) => {
|
||||
const offset = bones.offset + index * 88;
|
||||
const parent = buffer.readInt16LE(offset + 8);
|
||||
if (parent >= index || parent < -1) throw new Error(`${name} bone ${index} has an invalid parent.`);
|
||||
return {
|
||||
parent,
|
||||
flags: buffer.readUInt32LE(offset + 4),
|
||||
pivot: vector3(buffer, offset + 76),
|
||||
translation: decodeTrack(buffer, offset + 16, VALUE_TYPES.vector3, `${name} bone ${index} translation`),
|
||||
rotation: decodeTrack(buffer, offset + 36, VALUE_TYPES.quaternion, `${name} bone ${index} rotation`),
|
||||
scale: decodeTrack(buffer, offset + 56, VALUE_TYPES.vector3, `${name} bone ${index} scale`),
|
||||
};
|
||||
}),
|
||||
textureTransforms: Array.from({ length: transforms.count }, (_, index) => {
|
||||
const offset = transforms.offset + index * 60;
|
||||
return {
|
||||
translation: decodeTrack(buffer, offset, VALUE_TYPES.vector3, `${name} UV ${index} translation`),
|
||||
rotation: decodeTrack(buffer, offset + 20, VALUE_TYPES.floatQuaternion, `${name} UV ${index} rotation`),
|
||||
scale: decodeTrack(buffer, offset + 40, VALUE_TYPES.vector3, `${name} UV ${index} scale`),
|
||||
};
|
||||
}),
|
||||
materials: decodeMaterials(buffer, name),
|
||||
};
|
||||
}
|
||||
|
||||
function decodeSkinSubmeshes(buffer, count, offset, triangleCount, vertexLookupCount, name) {
|
||||
const byteLength = count * SKIN_SUBMESH_SIZE;
|
||||
if (!Number.isSafeInteger(byteLength)) throw new Error(`${name} submeshes are too large to decode.`);
|
||||
@@ -303,7 +347,7 @@ function decodeSkinTextureUnits(buffer, count, offset, context, name) {
|
||||
textureWeightIndices: lookupSlice(
|
||||
context.lookups.textureWeights,
|
||||
textureWeightComboIndex,
|
||||
textureCount,
|
||||
1,
|
||||
`${name} texture unit ${index} texture weights`,
|
||||
),
|
||||
textureTransformIndices: lookupSlice(
|
||||
|
||||
Reference in new issue
Block a user