reze-engine 0.61.2 → 0.61.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"pmx-loader.d.ts","sourceRoot":"","sources":["../src/pmx-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EAcN,MAAM,SAAS,CAAA;AAGhB,OAAO,EAA0B,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAEzE,qBAAa,SAAS;IACpB,OAAO,CAAC,IAAI,CAAU;IACtB,OAAO,CAAC,MAAM,CAAI;IAClB,OAAO,CAAC,OAAO,CAAc;IAC7B,OAAO,CAAC,QAAQ,CAAI;IACpB,OAAO,CAAC,mBAAmB,CAAI;IAC/B,OAAO,CAAC,eAAe,CAAI;IAC3B,OAAO,CAAC,gBAAgB,CAAI;IAC5B,OAAO,CAAC,iBAAiB,CAAI;IAC7B,OAAO,CAAC,aAAa,CAAI;IACzB,OAAO,CAAC,cAAc,CAAI;IAC1B,OAAO,CAAC,kBAAkB,CAAI;IAC9B,OAAO,CAAC,QAAQ,CAAgB;IAChC,OAAO,CAAC,SAAS,CAAiB;IAClC,OAAO,CAAC,KAAK,CAAa;IAC1B,OAAO,CAAC,mBAAmB,CAA4B;IACvD,OAAO,CAAC,OAAO,CAA2B;IAC1C,OAAO,CAAC,QAAQ,CAA0B;IAC1C,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,WAAW,CAAY;IAC/B,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,QAAQ,CAAe;IAE/B,OAAO;IAQP,OAAO,CAAC,IAAI;WAMC,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;IAI9C,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG,KAAK;WAIpC,cAAc,CAAC,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;IAKxF,OAAO,CAAC,KAAK;IAiBb,OAAO,CAAC,WAAW;IAwDnB,OAAO,CAAC,aAAa;IA+FrB,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,aAAa;IAkBrB,OAAO,CAAC,cAAc;IAsEtB,OAAO,CAAC,UAAU;IAkLlB,OAAO,CAAC,WAAW;IAgMnB,OAAO,CAAC,iBAAiB;IAgDzB,OAAO,CAAC,gBAAgB;IA+FxB,OAAO,CAAC,WAAW;IAmGnB,OAAO,CAAC,kBAAkB;IAmC1B,OAAO,CAAC,OAAO;IAkJf,OAAO,CAAC,QAAQ;IAOhB,OAAO,CAAC,SAAS;IAUjB,OAAO,CAAC,cAAc;IAWtB,OAAO,CAAC,iBAAiB;IAczB,OAAO,CAAC,QAAQ;IAShB,OAAO,CAAC,UAAU;IASlB,OAAO,CAAC,SAAS;IAQjB,OAAO,CAAC,OAAO;IAwBf,OAAO,CAAC,QAAQ;CAIjB"}
1
+ {"version":3,"file":"pmx-loader.d.ts","sourceRoot":"","sources":["../src/pmx-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EAcN,MAAM,SAAS,CAAA;AAGhB,OAAO,EAA0B,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAEzE,qBAAa,SAAS;IACpB,OAAO,CAAC,IAAI,CAAU;IACtB,OAAO,CAAC,MAAM,CAAI;IAClB,OAAO,CAAC,OAAO,CAAc;IAC7B,OAAO,CAAC,QAAQ,CAAI;IACpB,OAAO,CAAC,mBAAmB,CAAI;IAC/B,OAAO,CAAC,eAAe,CAAI;IAC3B,OAAO,CAAC,gBAAgB,CAAI;IAC5B,OAAO,CAAC,iBAAiB,CAAI;IAC7B,OAAO,CAAC,aAAa,CAAI;IACzB,OAAO,CAAC,cAAc,CAAI;IAC1B,OAAO,CAAC,kBAAkB,CAAI;IAC9B,OAAO,CAAC,QAAQ,CAAgB;IAChC,OAAO,CAAC,SAAS,CAAiB;IAClC,OAAO,CAAC,KAAK,CAAa;IAC1B,OAAO,CAAC,mBAAmB,CAA4B;IACvD,OAAO,CAAC,OAAO,CAA2B;IAC1C,OAAO,CAAC,QAAQ,CAA0B;IAC1C,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,WAAW,CAAY;IAC/B,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,QAAQ,CAAe;IAE/B,OAAO;IAQP,OAAO,CAAC,IAAI;WAMC,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;IAI9C,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG,KAAK;WAIpC,cAAc,CAAC,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;IAKxF,OAAO,CAAC,KAAK;IAiBb,OAAO,CAAC,WAAW;IAwDnB,OAAO,CAAC,aAAa;IA0GrB,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,aAAa;IAkBrB,OAAO,CAAC,cAAc;IAsEtB,OAAO,CAAC,UAAU;IAkLlB,OAAO,CAAC,WAAW;IAgMnB,OAAO,CAAC,iBAAiB;IAgDzB,OAAO,CAAC,gBAAgB;IA+FxB,OAAO,CAAC,WAAW;IAmGnB,OAAO,CAAC,kBAAkB;IAmC1B,OAAO,CAAC,OAAO;IAkJf,OAAO,CAAC,QAAQ;IAOhB,OAAO,CAAC,SAAS;IAUjB,OAAO,CAAC,cAAc;IAWtB,OAAO,CAAC,iBAAiB;IAczB,OAAO,CAAC,QAAQ;IAShB,OAAO,CAAC,UAAU;IASlB,OAAO,CAAC,SAAS;IAQjB,OAAO,CAAC,OAAO;IAwBf,OAAO,CAAC,QAAQ;CAIjB"}
@@ -153,8 +153,13 @@ export class PmxLoader {
153
153
  const j0 = this.getNonVertexIndex(this.boneIndexSize);
154
154
  const j1 = this.getNonVertexIndex(this.boneIndexSize);
155
155
  const w0f = this.getFloat32();
156
- const w0 = Math.max(0, Math.min(255, Math.round(w0f * 255)));
157
- const w1 = Math.max(0, Math.min(255, 255 - w0));
156
+ let w0 = Math.max(0, Math.min(255, Math.round(w0f * 255)));
157
+ // A side with no bone (-1) takes nothing: it would land on bone 0.
158
+ if (j1 < 0)
159
+ w0 = 255;
160
+ else if (j0 < 0)
161
+ w0 = 0;
162
+ const w1 = 255 - w0;
158
163
  joints[base] = j0 >= 0 ? j0 : 0;
159
164
  joints[base + 1] = j1 >= 0 ? j1 : 0;
160
165
  weights[base] = w0;
@@ -167,27 +172,36 @@ export class PmxLoader {
167
172
  else if (type === 2 || type === 4) {
168
173
  // BDEF4 or QDEF (treat as LBS4)
169
174
  let sum = 0;
175
+ const valid = [false, false, false, false];
170
176
  for (let k = 0; k < 4; k++) {
171
177
  const j = this.getNonVertexIndex(this.boneIndexSize);
172
178
  joints[base + k] = j >= 0 ? j : 0;
179
+ valid[k] = j >= 0;
173
180
  }
174
181
  const wf = [this.getFloat32(), this.getFloat32(), this.getFloat32(), this.getFloat32()];
175
- const ws = wf.map((x) => Math.max(0, Math.min(1, x)));
176
- const w8 = ws.map((x) => Math.round(x * 255));
177
- sum = w8[0] + w8[1] + w8[2] + w8[3];
178
- if (sum === 0) {
182
+ // A slot with no bone (-1) takes nothing: its index lands on bone 0, the
183
+ // model's root, which a motion never moves with センター.
184
+ const ws = wf.map((x, k) => (valid[k] ? Math.max(0, Math.min(1, x)) : 0));
185
+ sum = ws[0] + ws[1] + ws[2] + ws[3];
186
+ if (sum <= 0) {
179
187
  weights[base] = 255;
180
188
  }
181
189
  else {
182
- // Normalize to 255
183
- const scale = 255 / sum;
190
+ // Normalize to 255, and the rounding's remainder to the HEAVIEST
191
+ // slot. It went to the fourth, which is usually empty — bone 0 — and
192
+ // a vertex one or two 255ths on the root is invisible at the origin
193
+ // but trails a spike back to it from a figure a motion has carried
194
+ // 58 m away.
184
195
  let accum = 0;
185
- for (let k = 0; k < 3; k++) {
186
- const v = Math.max(0, Math.min(255, Math.round(w8[k] * scale)));
196
+ let heaviest = 0;
197
+ for (let k = 0; k < 4; k++) {
198
+ const v = Math.round((ws[k] / sum) * 255);
187
199
  weights[base + k] = v;
188
200
  accum += v;
201
+ if (ws[k] > ws[heaviest])
202
+ heaviest = k;
189
203
  }
190
- weights[base + 3] = Math.max(0, Math.min(255, 255 - accum));
204
+ weights[base + heaviest] = Math.max(0, Math.min(255, weights[base + heaviest] + 255 - accum));
191
205
  }
192
206
  }
193
207
  else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "reze-engine",
3
- "version": "0.61.2",
3
+ "version": "0.61.3",
4
4
  "description": "A lightweight WebGPU engine for real-time 3D MMD/PMX model rendering",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
package/src/pmx-loader.ts CHANGED
@@ -190,8 +190,11 @@ export class PmxLoader {
190
190
  const j0 = this.getNonVertexIndex(this.boneIndexSize)
191
191
  const j1 = this.getNonVertexIndex(this.boneIndexSize)
192
192
  const w0f = this.getFloat32()
193
- const w0 = Math.max(0, Math.min(255, Math.round(w0f * 255)))
194
- const w1 = Math.max(0, Math.min(255, 255 - w0))
193
+ let w0 = Math.max(0, Math.min(255, Math.round(w0f * 255)))
194
+ // A side with no bone (-1) takes nothing: it would land on bone 0.
195
+ if (j1 < 0) w0 = 255
196
+ else if (j0 < 0) w0 = 0
197
+ const w1 = 255 - w0
195
198
  joints[base] = j0 >= 0 ? j0 : 0
196
199
  joints[base + 1] = j1 >= 0 ? j1 : 0
197
200
  weights[base] = w0
@@ -203,26 +206,34 @@ export class PmxLoader {
203
206
  } else if (type === 2 || type === 4) {
204
207
  // BDEF4 or QDEF (treat as LBS4)
205
208
  let sum = 0
209
+ const valid = [false, false, false, false]
206
210
  for (let k = 0; k < 4; k++) {
207
211
  const j = this.getNonVertexIndex(this.boneIndexSize)
208
212
  joints[base + k] = j >= 0 ? j : 0
213
+ valid[k] = j >= 0
209
214
  }
210
215
  const wf = [this.getFloat32(), this.getFloat32(), this.getFloat32(), this.getFloat32()]
211
- const ws = wf.map((x) => Math.max(0, Math.min(1, x)))
212
- const w8 = ws.map((x) => Math.round(x * 255))
213
- sum = w8[0] + w8[1] + w8[2] + w8[3]
214
- if (sum === 0) {
216
+ // A slot with no bone (-1) takes nothing: its index lands on bone 0, the
217
+ // model's root, which a motion never moves with センター.
218
+ const ws = wf.map((x, k) => (valid[k] ? Math.max(0, Math.min(1, x)) : 0))
219
+ sum = ws[0] + ws[1] + ws[2] + ws[3]
220
+ if (sum <= 0) {
215
221
  weights[base] = 255
216
222
  } else {
217
- // Normalize to 255
218
- const scale = 255 / sum
223
+ // Normalize to 255, and the rounding's remainder to the HEAVIEST
224
+ // slot. It went to the fourth, which is usually empty — bone 0 — and
225
+ // a vertex one or two 255ths on the root is invisible at the origin
226
+ // but trails a spike back to it from a figure a motion has carried
227
+ // 58 m away.
219
228
  let accum = 0
220
- for (let k = 0; k < 3; k++) {
221
- const v = Math.max(0, Math.min(255, Math.round(w8[k] * scale)))
229
+ let heaviest = 0
230
+ for (let k = 0; k < 4; k++) {
231
+ const v = Math.round((ws[k] / sum) * 255)
222
232
  weights[base + k] = v
223
233
  accum += v
234
+ if (ws[k] > ws[heaviest]) heaviest = k
224
235
  }
225
- weights[base + 3] = Math.max(0, Math.min(255, 255 - accum))
236
+ weights[base + heaviest] = Math.max(0, Math.min(255, weights[base + heaviest] + 255 - accum))
226
237
  }
227
238
  } else {
228
239
  throw new Error(`Invalid bone weight type: ${type}`)