reze-engine 0.27.2 → 0.27.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.
package/dist/camera.d.ts CHANGED
@@ -43,6 +43,20 @@ export declare class Camera {
43
43
  setVmdDriven(enabled: boolean): void;
44
44
  /** Feed the next sampled MMD camera pose (engine calls this each frame while driving). */
45
45
  setVmdPose(pose: CameraPose): void;
46
+ private vmdEye;
47
+ /**
48
+ * Where the shot is actually taken from: the VMD eye while a camera VMD drives, the
49
+ * orbit position otherwise.
50
+ *
51
+ * `getPosition()` deliberately stays orbit-only — pan, zoom and framing reason in the
52
+ * spherical coordinates a camera VMD never touches. Anything asking "where is the
53
+ * viewer" wants THIS. Feeding the orbit position to the shader's `camera.viewPos`
54
+ * while rendering from the VMD camera left every view-dependent term — specular, rim,
55
+ * fresnel, sphere maps, the eye visibility gate — evaluated from a camera that was not
56
+ * the one taking the picture, with the error depending on wherever the orbit happened
57
+ * to be left.
58
+ */
59
+ getEyePosition(): Vec3;
46
60
  getViewMatrix(): Mat4;
47
61
  private getCameraVectors;
48
62
  private panCamera;
@@ -1 +1 @@
1
- {"version":3,"file":"camera.d.ts","sourceRoot":"","sources":["../src/camera.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAQ,IAAI,EAAE,MAAM,QAAQ,CAAA;AACzC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAMpD,qBAAa,MAAM;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,IAAI,CAAA;IACZ,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,MAAM,CAAI;IAClB,IAAI,EAAE,MAAM,CAAO;IACnB,GAAG,EAAE,MAAM,CAAU;IAGrB,OAAO,CAAC,MAAM,CAAiC;IAC/C,OAAO,CAAC,WAAW,CAAiB;IACpC,OAAO,CAAC,UAAU,CAAiB;IACnC,OAAO,CAAC,WAAW,CAAsB;IACzC,OAAO,CAAC,YAAY,CAAiB;IACrC,OAAO,CAAC,YAAY,CAAiB;IACrC,OAAO,CAAC,eAAe,CAAsB;IAC7C,OAAO,CAAC,UAAU,CAAiB;IACnC,OAAO,CAAC,iBAAiB,CAAY;IACrC,OAAO,CAAC,iBAAiB,CAAiB;IAC1C,OAAO,CAAC,oBAAoB,CAAY;IAGxC,kBAAkB,EAAE,MAAM,CAAQ;IAClC,cAAc,EAAE,MAAM,CAAS;IAC/B,cAAc,EAAE,MAAM,CAAO;IAC7B,cAAc,EAAE,MAAM,CAAO;IAC7B,IAAI,EAAE,MAAM,CAAO;IACnB,IAAI,EAAE,MAAM,CAAU;IACtB,cAAc,EAAE,MAAM,CAAQ;IAC9B,cAAc,EAAE,MAAM,CAAkB;IAGxC,OAAO,CAAC,QAAQ,CAAiC;IACjD,OAAO,CAAC,QAAQ,CAAiC;IAKjD,SAAS,EAAE,OAAO,CAAQ;IAC1B,OAAO,CAAC,UAAU,CAAoB;IACtC,OAAO,CAAC,YAAY,CAAoB;IACxC,OAAO,CAAC,YAAY,CAAM;IAC1B,OAAO,CAAC,SAAS,CAAc;IAC/B,OAAO,CAAC,YAAY,CAAuB;gBAE/B,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,GAAE,MAAoB;IAmBhG,WAAW,IAAI,IAAI;IAQnB;wFACoF;IACpF,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAOpC,0FAA0F;IAC1F,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI;IAOlC,aAAa,IAAI,IAAI;IA0BrB,OAAO,CAAC,gBAAgB;IA0CxB,OAAO,CAAC,SAAS;IAiBjB,kFAAkF;IAClF,OAAO,CAAC,mBAAmB;IAK3B,mBAAmB,IAAI,IAAI;IAM3B,aAAa,CAAC,MAAM,EAAE,iBAAiB;IAiBvC,aAAa;IAkBb,cAAc,CAAC,MAAM,EAAE,OAAO;IAS9B,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,WAAW;IAsBnB,OAAO,CAAC,SAAS;IAKjB,OAAO,CAAC,OAAO;IAYf,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,YAAY;IA8BpB,OAAO,CAAC,WAAW;IAuFnB,OAAO,CAAC,UAAU;CA+BnB"}
1
+ {"version":3,"file":"camera.d.ts","sourceRoot":"","sources":["../src/camera.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAQ,IAAI,EAAE,MAAM,QAAQ,CAAA;AACzC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAMpD,qBAAa,MAAM;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,IAAI,CAAA;IACZ,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,MAAM,CAAI;IAClB,IAAI,EAAE,MAAM,CAAO;IACnB,GAAG,EAAE,MAAM,CAAU;IAGrB,OAAO,CAAC,MAAM,CAAiC;IAC/C,OAAO,CAAC,WAAW,CAAiB;IACpC,OAAO,CAAC,UAAU,CAAiB;IACnC,OAAO,CAAC,WAAW,CAAsB;IACzC,OAAO,CAAC,YAAY,CAAiB;IACrC,OAAO,CAAC,YAAY,CAAiB;IACrC,OAAO,CAAC,eAAe,CAAsB;IAC7C,OAAO,CAAC,UAAU,CAAiB;IACnC,OAAO,CAAC,iBAAiB,CAAY;IACrC,OAAO,CAAC,iBAAiB,CAAiB;IAC1C,OAAO,CAAC,oBAAoB,CAAY;IAGxC,kBAAkB,EAAE,MAAM,CAAQ;IAClC,cAAc,EAAE,MAAM,CAAS;IAC/B,cAAc,EAAE,MAAM,CAAO;IAC7B,cAAc,EAAE,MAAM,CAAO;IAC7B,IAAI,EAAE,MAAM,CAAO;IACnB,IAAI,EAAE,MAAM,CAAU;IACtB,cAAc,EAAE,MAAM,CAAQ;IAC9B,cAAc,EAAE,MAAM,CAAkB;IAGxC,OAAO,CAAC,QAAQ,CAAiC;IACjD,OAAO,CAAC,QAAQ,CAAiC;IAKjD,SAAS,EAAE,OAAO,CAAQ;IAC1B,OAAO,CAAC,UAAU,CAAoB;IACtC,OAAO,CAAC,YAAY,CAAoB;IACxC,OAAO,CAAC,YAAY,CAAM;IAC1B,OAAO,CAAC,SAAS,CAAc;IAC/B,OAAO,CAAC,YAAY,CAAuB;gBAE/B,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,GAAE,MAAoB;IAmBhG,WAAW,IAAI,IAAI;IAQnB;wFACoF;IACpF,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAOpC,0FAA0F;IAC1F,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI;IAelC,OAAO,CAAC,MAAM;IAUd;;;;;;;;;;;OAWG;IACH,cAAc,IAAI,IAAI;IAItB,aAAa,IAAI,IAAI;IAgBrB,OAAO,CAAC,gBAAgB;IA0CxB,OAAO,CAAC,SAAS;IAiBjB,kFAAkF;IAClF,OAAO,CAAC,mBAAmB;IAK3B,mBAAmB,IAAI,IAAI;IAM3B,aAAa,CAAC,MAAM,EAAE,iBAAiB;IAiBvC,aAAa;IAkBb,cAAc,CAAC,MAAM,EAAE,OAAO;IAS9B,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,WAAW;IAsBnB,OAAO,CAAC,SAAS;IAKjB,OAAO,CAAC,OAAO;IAYf,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,YAAY;IA8BpB,OAAO,CAAC,WAAW;IAuFnB,OAAO,CAAC,UAAU;CA+BnB"}
package/dist/camera.js CHANGED
@@ -81,22 +81,44 @@ export class Camera {
81
81
  this._vmdDistance = pose.distance;
82
82
  this.fov = pose.fov; // drives the projection
83
83
  }
84
+ // MMD camera: look at `target` from `distance` back, oriented by the euler rotation.
85
+ // forward = q·(0,0,1) (LH), up = q·(0,1,0) — read as columns 2 and 1 of the rot matrix.
86
+ // eye = target + forward·distance (distance is negative in VMD, so eye sits behind).
87
+ // Euler is NEGATED on all three axes: babylon-mmd builds the shot with
88
+ // RotationYawPitchRoll(-ry, -rx, -rz), and our fromEuler(rx,ry,rz) equals
89
+ // RotationYawPitchRoll(ry,rx,rz) — so the MMD-authentic rotation is fromEuler(-r).
90
+ //
91
+ // Leaves the rotation matrix in `_quatScratch`; getViewMatrix reads its up vector.
92
+ vmdEye() {
93
+ const r = this._vmdRotation;
94
+ const q = Quat.fromEuler(-r.x, -r.y, -r.z);
95
+ Mat4.fromQuatInto(q.x, q.y, q.z, q.w, this._quatScratch, 0);
96
+ const s = this._quatScratch;
97
+ const t = this._vmdTarget;
98
+ const d = this._vmdDistance;
99
+ return new Vec3(t.x + s[8] * d, t.y + s[9] * d, t.z + s[10] * d);
100
+ }
101
+ /**
102
+ * Where the shot is actually taken from: the VMD eye while a camera VMD drives, the
103
+ * orbit position otherwise.
104
+ *
105
+ * `getPosition()` deliberately stays orbit-only — pan, zoom and framing reason in the
106
+ * spherical coordinates a camera VMD never touches. Anything asking "where is the
107
+ * viewer" wants THIS. Feeding the orbit position to the shader's `camera.viewPos`
108
+ * while rendering from the VMD camera left every view-dependent term — specular, rim,
109
+ * fresnel, sphere maps, the eye visibility gate — evaluated from a camera that was not
110
+ * the one taking the picture, with the error depending on wherever the orbit happened
111
+ * to be left.
112
+ */
113
+ getEyePosition() {
114
+ return this.vmdDriven ? this.vmdEye() : this.getPosition();
115
+ }
84
116
  getViewMatrix() {
85
117
  if (this.vmdDriven) {
86
- // MMD camera: look at `target` from `distance` back, oriented by the euler rotation.
87
- // forward = q·(0,0,1) (LH), up = q·(0,1,0) — read as columns 2 and 1 of the rot matrix.
88
- // eye = target + forward·distance (distance is negative in VMD, so eye sits behind).
89
- // Euler is NEGATED on all three axes: babylon-mmd builds the shot with
90
- // RotationYawPitchRoll(-ry, -rx, -rz), and our fromEuler(rx,ry,rz) equals
91
- // RotationYawPitchRoll(ry,rx,rz) — so the MMD-authentic rotation is fromEuler(-r).
92
- const r = this._vmdRotation;
93
- const q = Quat.fromEuler(-r.x, -r.y, -r.z);
94
- Mat4.fromQuatInto(q.x, q.y, q.z, q.w, this._quatScratch, 0);
118
+ const eye = this.vmdEye();
95
119
  const s = this._quatScratch;
96
120
  const t = this._vmdTarget;
97
- const d = this._vmdDistance;
98
- const ex = t.x + s[8] * d, ey = t.y + s[9] * d, ez = t.z + s[10] * d;
99
- Mat4.lookAtInto(this._viewMat.values, ex, ey, ez, t.x, t.y, t.z, s[4], s[5], s[6]);
121
+ Mat4.lookAtInto(this._viewMat.values, eye.x, eye.y, eye.z, t.x, t.y, t.z, s[4], s[5], s[6]);
100
122
  return this._viewMat;
101
123
  }
102
124
  const eye = this.getPosition();
package/dist/engine.js CHANGED
@@ -432,7 +432,7 @@ export class Engine {
432
432
  e.stopImmediatePropagation();
433
433
  e.preventDefault();
434
434
  // Pick threshold stays pixel-based — clicking should feel the same at any zoom.
435
- const camPos = this.camera.getPosition();
435
+ const camPos = this.camera.getEyePosition();
436
436
  const dist = Math.max(0.01, bonePos.subtract(camPos).length());
437
437
  const worldPerPixel = (dist * Math.tan(this.camera.fov * 0.5) * 2) / Math.max(1, this.canvas.clientHeight);
438
438
  const worldThreshold = Engine.GIZMO_PICK_THRESHOLD_PX * worldPerPixel;
@@ -4387,7 +4387,7 @@ export class Engine {
4387
4387
  updateCameraUniforms() {
4388
4388
  const viewMatrix = this.camera.getViewMatrix();
4389
4389
  const projectionMatrix = this.camera.getProjectionMatrix();
4390
- const cameraPos = this.camera.getPosition();
4390
+ const cameraPos = this.camera.getEyePosition();
4391
4391
  this.cameraMatrixData.set(viewMatrix.values, 0);
4392
4392
  this.cameraMatrixData.set(projectionMatrix.values, 16);
4393
4393
  this.cameraMatrixData[32] = cameraPos.x;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "reze-engine",
3
- "version": "0.27.2",
3
+ "version": "0.27.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/camera.ts CHANGED
@@ -96,22 +96,46 @@ export class Camera {
96
96
  this.fov = pose.fov // drives the projection
97
97
  }
98
98
 
99
+ // MMD camera: look at `target` from `distance` back, oriented by the euler rotation.
100
+ // forward = q·(0,0,1) (LH), up = q·(0,1,0) — read as columns 2 and 1 of the rot matrix.
101
+ // eye = target + forward·distance (distance is negative in VMD, so eye sits behind).
102
+ // Euler is NEGATED on all three axes: babylon-mmd builds the shot with
103
+ // RotationYawPitchRoll(-ry, -rx, -rz), and our fromEuler(rx,ry,rz) equals
104
+ // RotationYawPitchRoll(ry,rx,rz) — so the MMD-authentic rotation is fromEuler(-r).
105
+ //
106
+ // Leaves the rotation matrix in `_quatScratch`; getViewMatrix reads its up vector.
107
+ private vmdEye(): Vec3 {
108
+ const r = this._vmdRotation
109
+ const q = Quat.fromEuler(-r.x, -r.y, -r.z)
110
+ Mat4.fromQuatInto(q.x, q.y, q.z, q.w, this._quatScratch, 0)
111
+ const s = this._quatScratch
112
+ const t = this._vmdTarget
113
+ const d = this._vmdDistance
114
+ return new Vec3(t.x + s[8] * d, t.y + s[9] * d, t.z + s[10] * d)
115
+ }
116
+
117
+ /**
118
+ * Where the shot is actually taken from: the VMD eye while a camera VMD drives, the
119
+ * orbit position otherwise.
120
+ *
121
+ * `getPosition()` deliberately stays orbit-only — pan, zoom and framing reason in the
122
+ * spherical coordinates a camera VMD never touches. Anything asking "where is the
123
+ * viewer" wants THIS. Feeding the orbit position to the shader's `camera.viewPos`
124
+ * while rendering from the VMD camera left every view-dependent term — specular, rim,
125
+ * fresnel, sphere maps, the eye visibility gate — evaluated from a camera that was not
126
+ * the one taking the picture, with the error depending on wherever the orbit happened
127
+ * to be left.
128
+ */
129
+ getEyePosition(): Vec3 {
130
+ return this.vmdDriven ? this.vmdEye() : this.getPosition()
131
+ }
132
+
99
133
  getViewMatrix(): Mat4 {
100
134
  if (this.vmdDriven) {
101
- // MMD camera: look at `target` from `distance` back, oriented by the euler rotation.
102
- // forward = q·(0,0,1) (LH), up = q·(0,1,0) — read as columns 2 and 1 of the rot matrix.
103
- // eye = target + forward·distance (distance is negative in VMD, so eye sits behind).
104
- // Euler is NEGATED on all three axes: babylon-mmd builds the shot with
105
- // RotationYawPitchRoll(-ry, -rx, -rz), and our fromEuler(rx,ry,rz) equals
106
- // RotationYawPitchRoll(ry,rx,rz) — so the MMD-authentic rotation is fromEuler(-r).
107
- const r = this._vmdRotation
108
- const q = Quat.fromEuler(-r.x, -r.y, -r.z)
109
- Mat4.fromQuatInto(q.x, q.y, q.z, q.w, this._quatScratch, 0)
135
+ const eye = this.vmdEye()
110
136
  const s = this._quatScratch
111
137
  const t = this._vmdTarget
112
- const d = this._vmdDistance
113
- const ex = t.x + s[8] * d, ey = t.y + s[9] * d, ez = t.z + s[10] * d
114
- Mat4.lookAtInto(this._viewMat.values, ex, ey, ez, t.x, t.y, t.z, s[4], s[5], s[6])
138
+ Mat4.lookAtInto(this._viewMat.values, eye.x, eye.y, eye.z, t.x, t.y, t.z, s[4], s[5], s[6])
115
139
  return this._viewMat
116
140
  }
117
141
  const eye = this.getPosition()
package/src/engine.ts CHANGED
@@ -4305,7 +4305,7 @@ export class Engine {
4305
4305
  e.preventDefault()
4306
4306
 
4307
4307
  // Pick threshold stays pixel-based — clicking should feel the same at any zoom.
4308
- const camPos = this.camera.getPosition()
4308
+ const camPos = this.camera.getEyePosition()
4309
4309
  const dist = Math.max(0.01, bonePos.subtract(camPos).length())
4310
4310
  const worldPerPixel = (dist * Math.tan(this.camera.fov * 0.5) * 2) / Math.max(1, this.canvas.clientHeight)
4311
4311
  const worldThreshold = Engine.GIZMO_PICK_THRESHOLD_PX * worldPerPixel
@@ -5237,7 +5237,7 @@ export class Engine {
5237
5237
  private updateCameraUniforms() {
5238
5238
  const viewMatrix = this.camera.getViewMatrix()
5239
5239
  const projectionMatrix = this.camera.getProjectionMatrix()
5240
- const cameraPos = this.camera.getPosition()
5240
+ const cameraPos = this.camera.getEyePosition()
5241
5241
  this.cameraMatrixData.set(viewMatrix.values, 0)
5242
5242
  this.cameraMatrixData.set(projectionMatrix.values, 16)
5243
5243
  this.cameraMatrixData[32] = cameraPos.x