Release Healer Man 0.1.13
This commit is contained in:
1 parent
65e24f644e
commit
67d7a8ebe7
324 files changed
+917
-48
No files matched your search
@@ -8,7 +8,7 @@ import { decodeWotlkM2Mesh } from "./wotlk-m2-mesh.mjs";
|
||||
const projectRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..", "..");
|
||||
|
||||
function syntheticM2AndSkin() {
|
||||
const m2 = Buffer.alloc(640);
|
||||
const m2 = Buffer.alloc(800);
|
||||
const skin = Buffer.alloc(144);
|
||||
const vertexOffset = 304;
|
||||
const materialOffset = 448;
|
||||
@@ -19,6 +19,21 @@ function syntheticM2AndSkin() {
|
||||
const modelNameOffset = 464;
|
||||
const textureOffset = 496;
|
||||
const textureFilenameOffset = 512;
|
||||
const animationOffset = 544;
|
||||
const colorOffset = 608;
|
||||
const textureWeightOffset = 648;
|
||||
const colorTimestampSequencesOffset = 672;
|
||||
const colorValueSequencesOffset = 680;
|
||||
const alphaTimestampSequencesOffset = 688;
|
||||
const alphaValueSequencesOffset = 696;
|
||||
const weightTimestampSequencesOffset = 704;
|
||||
const weightValueSequencesOffset = 712;
|
||||
const colorTimestampsOffset = 728;
|
||||
const colorValuesOffset = 736;
|
||||
const alphaTimestampsOffset = 760;
|
||||
const alphaValuesOffset = 768;
|
||||
const weightTimestampsOffset = 772;
|
||||
const weightValuesOffset = 780;
|
||||
|
||||
m2.write("MD20", 0, "ascii");
|
||||
m2.writeUInt32LE(264, 4);
|
||||
@@ -26,10 +41,16 @@ function syntheticM2AndSkin() {
|
||||
m2.writeUInt32LE(modelName.length, 8);
|
||||
m2.writeUInt32LE(modelNameOffset, 12);
|
||||
modelName.copy(m2, modelNameOffset);
|
||||
m2.writeUInt32LE(1, 28);
|
||||
m2.writeUInt32LE(animationOffset, 32);
|
||||
m2.writeUInt32LE(3, 60);
|
||||
m2.writeUInt32LE(vertexOffset, 64);
|
||||
m2.writeUInt32LE(1, 72);
|
||||
m2.writeUInt32LE(colorOffset, 76);
|
||||
m2.writeUInt32LE(1, 80);
|
||||
m2.writeUInt32LE(textureOffset, 84);
|
||||
m2.writeUInt32LE(1, 88);
|
||||
m2.writeUInt32LE(textureWeightOffset, 92);
|
||||
m2.writeUInt32LE(1, 112);
|
||||
m2.writeUInt32LE(materialOffset, 116);
|
||||
m2.writeUInt32LE(1, 128);
|
||||
@@ -72,6 +93,46 @@ function syntheticM2AndSkin() {
|
||||
m2.writeUInt32LE(textureFilenameOffset, textureOffset + 12);
|
||||
textureFilename.copy(m2, textureFilenameOffset);
|
||||
|
||||
m2.writeUInt16LE(0, animationOffset);
|
||||
m2.writeUInt16LE(0, animationOffset + 2);
|
||||
m2.writeUInt32LE(500, animationOffset + 4);
|
||||
m2.writeFloatLE(0, animationOffset + 8);
|
||||
m2.writeUInt32LE(32, animationOffset + 12);
|
||||
|
||||
const writeTrackHeader = (offset, interpolation, timestampSequencesOffset, valueSequencesOffset) => {
|
||||
m2.writeUInt16LE(interpolation, offset);
|
||||
m2.writeInt16LE(-1, offset + 2);
|
||||
m2.writeUInt32LE(1, offset + 4);
|
||||
m2.writeUInt32LE(timestampSequencesOffset, offset + 8);
|
||||
m2.writeUInt32LE(1, offset + 12);
|
||||
m2.writeUInt32LE(valueSequencesOffset, offset + 16);
|
||||
};
|
||||
const writeSequence = (descriptorOffset, count, valuesOffset) => {
|
||||
m2.writeUInt32LE(count, descriptorOffset);
|
||||
m2.writeUInt32LE(valuesOffset, descriptorOffset + 4);
|
||||
};
|
||||
writeTrackHeader(colorOffset, 1, colorTimestampSequencesOffset, colorValueSequencesOffset);
|
||||
writeTrackHeader(colorOffset + 20, 0, alphaTimestampSequencesOffset, alphaValueSequencesOffset);
|
||||
writeTrackHeader(textureWeightOffset, 1, weightTimestampSequencesOffset, weightValueSequencesOffset);
|
||||
writeSequence(colorTimestampSequencesOffset, 2, colorTimestampsOffset);
|
||||
writeSequence(colorValueSequencesOffset, 2, colorValuesOffset);
|
||||
writeSequence(alphaTimestampSequencesOffset, 2, alphaTimestampsOffset);
|
||||
writeSequence(alphaValueSequencesOffset, 2, alphaValuesOffset);
|
||||
writeSequence(weightTimestampSequencesOffset, 2, weightTimestampsOffset);
|
||||
writeSequence(weightValueSequencesOffset, 2, weightValuesOffset);
|
||||
[0, 500].forEach((value, index) => {
|
||||
m2.writeUInt32LE(value, colorTimestampsOffset + index * 4);
|
||||
m2.writeUInt32LE(value, alphaTimestampsOffset + index * 4);
|
||||
m2.writeUInt32LE(value, weightTimestampsOffset + index * 4);
|
||||
});
|
||||
[1, 0.8, 0.2, 0.5, 0.4, 0.1].forEach((value, index) => (
|
||||
m2.writeFloatLE(value, colorValuesOffset + index * 4)
|
||||
));
|
||||
m2.writeInt16LE(32_767, alphaValuesOffset);
|
||||
m2.writeInt16LE(16_384, alphaValuesOffset + 2);
|
||||
m2.writeInt16LE(0, weightValuesOffset);
|
||||
m2.writeInt16LE(6_553, weightValuesOffset + 2);
|
||||
|
||||
skin.write("SKIN", 0, "ascii");
|
||||
skin.writeUInt32LE(3, 4);
|
||||
skin.writeUInt32LE(48, 8);
|
||||
@@ -109,7 +170,7 @@ function syntheticM2AndSkin() {
|
||||
skin.writeUInt16LE(0, unitOffset + 2);
|
||||
skin.writeUInt16LE(0, unitOffset + 4);
|
||||
skin.writeUInt16LE(0, unitOffset + 6);
|
||||
skin.writeInt16LE(-1, unitOffset + 8);
|
||||
skin.writeInt16LE(0, unitOffset + 8);
|
||||
skin.writeUInt16LE(0, unitOffset + 10);
|
||||
skin.writeUInt16LE(0, unitOffset + 12);
|
||||
skin.writeUInt16LE(1, unitOffset + 14);
|
||||
@@ -135,7 +196,38 @@ test("decodes browser-neutral M2 vertices and resolved SKIN draw data", () => {
|
||||
uv2: [1, 0],
|
||||
});
|
||||
assert.deepEqual(decoded.indices, [0, 1, 2]);
|
||||
assert.deepEqual(decoded.animations, [{
|
||||
index: 0,
|
||||
id: 0,
|
||||
variationIndex: 0,
|
||||
durationMs: 500,
|
||||
moveSpeed: 0,
|
||||
flags: 32,
|
||||
}]);
|
||||
assert.deepEqual(decoded.colors, [{
|
||||
color: {
|
||||
interpolation: 1,
|
||||
globalSequence: -1,
|
||||
sequences: [{
|
||||
timestamps: [0, 500],
|
||||
values: [
|
||||
[1, Math.fround(0.8), Math.fround(0.2)],
|
||||
[0.5, Math.fround(0.4), Math.fround(0.1)],
|
||||
],
|
||||
}],
|
||||
},
|
||||
alpha: {
|
||||
interpolation: 0,
|
||||
globalSequence: -1,
|
||||
sequences: [{ timestamps: [0, 500], values: [32_767, 16_384] }],
|
||||
},
|
||||
}]);
|
||||
assert.deepEqual(decoded.textures, [{ type: 0, flags: 0, filename: "SPELLS\\SYNTHETIC.BLP" }]);
|
||||
assert.deepEqual(decoded.textureWeights, [{
|
||||
interpolation: 1,
|
||||
globalSequence: -1,
|
||||
sequences: [{ timestamps: [0, 500], values: [0, 6_553] }],
|
||||
}]);
|
||||
assert.deepEqual(decoded.materials, [{ flags: 19, blendMode: 4 }]);
|
||||
assert.deepEqual(decoded.skin.submeshes[0].indices, [0, 1, 2]);
|
||||
assert.deepEqual(decoded.skin.textureUnits[0], {
|
||||
@@ -144,7 +236,7 @@ test("decodes browser-neutral M2 vertices and resolved SKIN draw data", () => {
|
||||
shaderId: 0,
|
||||
submeshIndex: 0,
|
||||
geosetIndex: 0,
|
||||
colorIndex: -1,
|
||||
colorIndex: 0,
|
||||
materialIndex: 0,
|
||||
materialLayer: 0,
|
||||
textureCount: 1,
|
||||
@@ -188,6 +280,25 @@ test("decodes the real local Power Word: Shield static mesh", {
|
||||
assert.equal(decoded.indices.length, 18);
|
||||
assert.equal(decoded.skin.submeshes.length, 3);
|
||||
assert.equal(decoded.skin.textureUnits.length, 3);
|
||||
assert.deepEqual(decoded.animations.map(({ id, durationMs }) => ({ id, durationMs })), [
|
||||
{ id: 0, durationMs: 700 },
|
||||
{ id: 158, durationMs: 633 },
|
||||
{ id: 159, durationMs: 1100 },
|
||||
]);
|
||||
assert.equal(decoded.colors.length, 3);
|
||||
assert.equal(decoded.textureWeights.length, 3);
|
||||
assert.deepEqual(decoded.colors[0].color.sequences[0].values[0], [
|
||||
0.9686275124549866,
|
||||
0.9921569228172302,
|
||||
0.3176470696926117,
|
||||
]);
|
||||
assert.deepEqual(decoded.colors.map((color) => color.alpha.sequences[0].values[0]), [
|
||||
32_767, 32_767, 32_767,
|
||||
]);
|
||||
assert.deepEqual(decoded.textureWeights[1].sequences[1], {
|
||||
timestamps: [0, 300, 633],
|
||||
values: [4_915, 1_966, 4_915],
|
||||
});
|
||||
assert.deepEqual(decoded.textures.map((texture) => texture.filename), [
|
||||
"SPELLS\\SHOCKWAVE10D.BLP",
|
||||
"SPELLS\\GENERICGLOW2B1.BLP",
|
||||
|
||||
Reference in new issue
Block a user