@xrift/world-components 0.42.0 → 0.42.1
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/components/Grabbable/__tests__/utils.test.d.ts +2 -0
- package/dist/components/Grabbable/__tests__/utils.test.d.ts.map +1 -0
- package/dist/components/Grabbable/__tests__/utils.test.js +59 -0
- package/dist/components/Grabbable/__tests__/utils.test.js.map +1 -0
- package/dist/components/Grabbable/index.d.ts.map +1 -1
- package/dist/components/Grabbable/index.js +21 -3
- package/dist/components/Grabbable/index.js.map +1 -1
- package/dist/components/Grabbable/utils.d.ts +26 -0
- package/dist/components/Grabbable/utils.d.ts.map +1 -0
- package/dist/components/Grabbable/utils.js +41 -0
- package/dist/components/Grabbable/utils.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.test.d.ts","sourceRoot":"","sources":["../../../../src/components/Grabbable/__tests__/utils.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Euler, Matrix4, Quaternion, Vector3 } from 'three';
|
|
2
|
+
import { describe, expect, it } from 'vitest';
|
|
3
|
+
import { decomposeWorldTransform, worldToLocalTransform } from '../utils';
|
|
4
|
+
describe('decomposeWorldTransform', () => {
|
|
5
|
+
it('単位行列は原点・無回転・スケール1', () => {
|
|
6
|
+
const t = decomposeWorldTransform(new Matrix4());
|
|
7
|
+
expect(t.position).toEqual({ x: 0, y: 0, z: 0 });
|
|
8
|
+
expect(t.scale).toBeCloseTo(1);
|
|
9
|
+
});
|
|
10
|
+
it('平行移動+スケールを分解できる', () => {
|
|
11
|
+
const m = new Matrix4().compose(new Vector3(1, 2, 3), new Quaternion(), new Vector3(2, 2, 2));
|
|
12
|
+
const t = decomposeWorldTransform(m);
|
|
13
|
+
expect(t.position.x).toBeCloseTo(1);
|
|
14
|
+
expect(t.position.y).toBeCloseTo(2);
|
|
15
|
+
expect(t.position.z).toBeCloseTo(3);
|
|
16
|
+
expect(t.scale).toBeCloseTo(2);
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
describe('worldToLocalTransform', () => {
|
|
20
|
+
it('親が単位行列ならワールド=ローカル(そのまま返る)', () => {
|
|
21
|
+
const local = worldToLocalTransform({ x: 1, y: 5, z: -2 }, { x: 0, y: 0, z: 0 }, new Matrix4());
|
|
22
|
+
expect(local.position.x).toBeCloseTo(1);
|
|
23
|
+
expect(local.position.y).toBeCloseTo(5);
|
|
24
|
+
expect(local.position.z).toBeCloseTo(-2);
|
|
25
|
+
});
|
|
26
|
+
it('親が平行移動している場合、その分を差し引く(-4 オフセットの再現)', () => {
|
|
27
|
+
// 親が y=-4 に平行移動 → ワールド y=-3 はローカル y=1
|
|
28
|
+
const parent = new Matrix4().makeTranslation(0, -4, 0);
|
|
29
|
+
const local = worldToLocalTransform({ x: 0, y: -3, z: 1 }, { x: 0, y: 0, z: 0 }, parent);
|
|
30
|
+
expect(local.position.x).toBeCloseTo(0);
|
|
31
|
+
expect(local.position.y).toBeCloseTo(1);
|
|
32
|
+
expect(local.position.z).toBeCloseTo(1);
|
|
33
|
+
});
|
|
34
|
+
it('ローカル→ワールド→ローカルで往復一致する(回転付き親)', () => {
|
|
35
|
+
const parent = new Matrix4().compose(new Vector3(2, -4, 1), new Quaternion().setFromEuler(new Euler(0, Math.PI / 3, 0)), new Vector3(1, 1, 1));
|
|
36
|
+
// 既知のローカル姿勢
|
|
37
|
+
const localPos = new Vector3(0.5, 1.2, -0.3);
|
|
38
|
+
const localEuler = new Euler(0.1, 0.4, -0.2);
|
|
39
|
+
const localQuat = new Quaternion().setFromEuler(localEuler);
|
|
40
|
+
// ローカル→ワールド
|
|
41
|
+
const worldMatrix = new Matrix4()
|
|
42
|
+
.copy(parent)
|
|
43
|
+
.multiply(new Matrix4().compose(localPos, localQuat, new Vector3(1, 1, 1)));
|
|
44
|
+
const wp = new Vector3();
|
|
45
|
+
const wq = new Quaternion();
|
|
46
|
+
const ws = new Vector3();
|
|
47
|
+
worldMatrix.decompose(wp, wq, ws);
|
|
48
|
+
const worldEuler = new Euler().setFromQuaternion(wq);
|
|
49
|
+
// ワールド→ローカルで元に戻る
|
|
50
|
+
const back = worldToLocalTransform({ x: wp.x, y: wp.y, z: wp.z }, { x: worldEuler.x, y: worldEuler.y, z: worldEuler.z }, parent);
|
|
51
|
+
expect(back.position.x).toBeCloseTo(localPos.x);
|
|
52
|
+
expect(back.position.y).toBeCloseTo(localPos.y);
|
|
53
|
+
expect(back.position.z).toBeCloseTo(localPos.z);
|
|
54
|
+
// 回転はクォータニオン一致で確認
|
|
55
|
+
const backQuat = new Quaternion().setFromEuler(new Euler(back.rotation.x, back.rotation.y, back.rotation.z));
|
|
56
|
+
expect(Math.abs(backQuat.dot(localQuat))).toBeCloseTo(1);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
//# sourceMappingURL=utils.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.test.js","sourceRoot":"","sources":["../../../../src/components/Grabbable/__tests__/utils.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Grabbable/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAoD,KAAK,EAAE,EAAE,MAAM,OAAO,CAAA;AAKjF,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Grabbable/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAoD,KAAK,EAAE,EAAE,MAAM,OAAO,CAAA;AAKjF,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAGpC;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,SAAS,EAAE,EAAE,CAAC,KAAK,CAsF/B,CAAA;AAED,YAAY,EAAE,KAAK,IAAI,cAAc,EAAE,MAAM,SAAS,CAAA"}
|
|
@@ -3,6 +3,7 @@ import { useEffect, useMemo, useRef, useSyncExternalStore } from 'react';
|
|
|
3
3
|
import { LAYERS } from '../../constants/layers';
|
|
4
4
|
import { useGrabbableContext } from '../../contexts/GrabbableContext';
|
|
5
5
|
import { GRABBABLE_USER_DATA_KEY } from './constants';
|
|
6
|
+
import { decomposeWorldTransform, worldToLocalTransform } from './utils';
|
|
6
7
|
/**
|
|
7
8
|
* 子オブジェクトを「掴める」と宣言するラッパー(<Interactable> と同じ明示オプトイン)
|
|
8
9
|
*
|
|
@@ -41,10 +42,27 @@ export const Grabbable = ({ id, transform, onMove, renderGhost, enabled = true,
|
|
|
41
42
|
registerGrabbable(id, {
|
|
42
43
|
// ゴースト未指定時は children をそのまま流用する
|
|
43
44
|
renderGhost: () => renderGhostRef.current?.() ?? childrenRef.current,
|
|
44
|
-
|
|
45
|
+
// GrabSystem はワールド座標で確定位置を返すため、ローカル(transform prop と同じ空間)へ
|
|
46
|
+
// 変換してからユーザーの onMove に渡す。変形された親の下に置いてもズレない
|
|
47
|
+
onMove: (world) => {
|
|
48
|
+
const parent = groupRef.current?.parent;
|
|
49
|
+
if (!parent) {
|
|
50
|
+
onMoveRef.current(world);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
parent.updateWorldMatrix(true, false);
|
|
54
|
+
onMoveRef.current(worldToLocalTransform(world.position, world.rotation, parent.matrixWorld));
|
|
55
|
+
},
|
|
56
|
+
// GrabSystem 向けにはワールド姿勢を返す(掴み距離・ゴーストの初期姿勢に使われる)。
|
|
57
|
+
// group 未マウント時のみ transform prop(ローカル)にフォールバック
|
|
45
58
|
getTransform: () => {
|
|
46
|
-
const
|
|
47
|
-
|
|
59
|
+
const group = groupRef.current;
|
|
60
|
+
if (!group) {
|
|
61
|
+
const t = transformRef.current;
|
|
62
|
+
return { position: t.position, rotation: t.rotation, scale: t.scale ?? 1 };
|
|
63
|
+
}
|
|
64
|
+
group.updateWorldMatrix(true, false);
|
|
65
|
+
return decomposeWorldTransform(group.matrixWorld);
|
|
48
66
|
},
|
|
49
67
|
});
|
|
50
68
|
return () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/Grabbable/index.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,oBAAoB,EAAW,MAAM,OAAO,CAAA;AAEjF,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAA;AAC/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAA;AACrE,OAAO,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/Grabbable/index.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Matrix4 } from 'three';
|
|
2
|
+
import type { Position3D, Rotation3D } from '../../types/movement';
|
|
3
|
+
/** GrabSystem が扱う姿勢(位置・Euler回転・均一スケール) */
|
|
4
|
+
export interface WorldTransform {
|
|
5
|
+
position: Position3D;
|
|
6
|
+
rotation: Rotation3D;
|
|
7
|
+
scale: number;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* ワールド行列を GrabSystem 向けの姿勢(位置・Euler回転・均一スケール)に分解する。
|
|
11
|
+
* <Grabbable> のルート group の matrixWorld を渡すと、変形された親の下にあっても
|
|
12
|
+
* 正しいワールド姿勢が得られる(getTransform 用)。
|
|
13
|
+
*/
|
|
14
|
+
export declare function decomposeWorldTransform(matrixWorld: Matrix4): WorldTransform;
|
|
15
|
+
/**
|
|
16
|
+
* ワールド姿勢(位置+Euler回転)を、親のワールド行列に対するローカル姿勢へ変換する。
|
|
17
|
+
* GrabSystem はワールド座標で確定位置を返すため、変形された親を持つ <Grabbable> でも
|
|
18
|
+
* ユーザーの onMove にはローカル座標(transform prop と同じ空間)を渡せる(onMove 用)。
|
|
19
|
+
*
|
|
20
|
+
* 親が無変形(単位行列)ならワールド=ローカルなので、そのまま返るのと同じ結果になる。
|
|
21
|
+
*/
|
|
22
|
+
export declare function worldToLocalTransform(worldPosition: Position3D, worldRotation: Rotation3D, parentMatrixWorld: Matrix4): {
|
|
23
|
+
position: Position3D;
|
|
24
|
+
rotation: Rotation3D;
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/components/Grabbable/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,OAAO,EAAuB,MAAM,OAAO,CAAA;AAC3D,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AAElE,0CAA0C;AAC1C,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,UAAU,CAAA;IACpB,QAAQ,EAAE,UAAU,CAAA;IACpB,KAAK,EAAE,MAAM,CAAA;CACd;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,OAAO,GAAG,cAAc,CAW5E;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,UAAU,EACzB,aAAa,EAAE,UAAU,EACzB,iBAAiB,EAAE,OAAO,GACzB;IAAE,QAAQ,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,UAAU,CAAA;CAAE,CAkBhD"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Euler, Matrix4, Quaternion, Vector3 } from 'three';
|
|
2
|
+
/**
|
|
3
|
+
* ワールド行列を GrabSystem 向けの姿勢(位置・Euler回転・均一スケール)に分解する。
|
|
4
|
+
* <Grabbable> のルート group の matrixWorld を渡すと、変形された親の下にあっても
|
|
5
|
+
* 正しいワールド姿勢が得られる(getTransform 用)。
|
|
6
|
+
*/
|
|
7
|
+
export function decomposeWorldTransform(matrixWorld) {
|
|
8
|
+
const position = new Vector3();
|
|
9
|
+
const quaternion = new Quaternion();
|
|
10
|
+
const scale = new Vector3();
|
|
11
|
+
matrixWorld.decompose(position, quaternion, scale);
|
|
12
|
+
const euler = new Euler().setFromQuaternion(quaternion);
|
|
13
|
+
return {
|
|
14
|
+
position: { x: position.x, y: position.y, z: position.z },
|
|
15
|
+
rotation: { x: euler.x, y: euler.y, z: euler.z },
|
|
16
|
+
scale: scale.x,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* ワールド姿勢(位置+Euler回転)を、親のワールド行列に対するローカル姿勢へ変換する。
|
|
21
|
+
* GrabSystem はワールド座標で確定位置を返すため、変形された親を持つ <Grabbable> でも
|
|
22
|
+
* ユーザーの onMove にはローカル座標(transform prop と同じ空間)を渡せる(onMove 用)。
|
|
23
|
+
*
|
|
24
|
+
* 親が無変形(単位行列)ならワールド=ローカルなので、そのまま返るのと同じ結果になる。
|
|
25
|
+
*/
|
|
26
|
+
export function worldToLocalTransform(worldPosition, worldRotation, parentMatrixWorld) {
|
|
27
|
+
const position = new Vector3(worldPosition.x, worldPosition.y, worldPosition.z);
|
|
28
|
+
const quaternion = new Quaternion().setFromEuler(new Euler(worldRotation.x, worldRotation.y, worldRotation.z));
|
|
29
|
+
const worldMatrix = new Matrix4().compose(position, quaternion, new Vector3(1, 1, 1));
|
|
30
|
+
const localMatrix = new Matrix4().copy(parentMatrixWorld).invert().multiply(worldMatrix);
|
|
31
|
+
const localPosition = new Vector3();
|
|
32
|
+
const localQuaternion = new Quaternion();
|
|
33
|
+
const localScale = new Vector3();
|
|
34
|
+
localMatrix.decompose(localPosition, localQuaternion, localScale);
|
|
35
|
+
const localEuler = new Euler().setFromQuaternion(localQuaternion);
|
|
36
|
+
return {
|
|
37
|
+
position: { x: localPosition.x, y: localPosition.y, z: localPosition.z },
|
|
38
|
+
rotation: { x: localEuler.x, y: localEuler.y, z: localEuler.z },
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/components/Grabbable/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AAU3D;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CAAC,WAAoB;IAC1D,MAAM,QAAQ,GAAG,IAAI,OAAO,EAAE,CAAA;IAC9B,MAAM,UAAU,GAAG,IAAI,UAAU,EAAE,CAAA;IACnC,MAAM,KAAK,GAAG,IAAI,OAAO,EAAE,CAAA;IAC3B,WAAW,CAAC,SAAS,CAAC,QAAQ,EAAE,UAAU,EAAE,KAAK,CAAC,CAAA;IAClD,MAAM,KAAK,GAAG,IAAI,KAAK,EAAE,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAA;IACvD,OAAO;QACL,QAAQ,EAAE,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC,EAAE;QACzD,QAAQ,EAAE,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE;QAChD,KAAK,EAAE,KAAK,CAAC,CAAC;KACf,CAAA;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CACnC,aAAyB,EACzB,aAAyB,EACzB,iBAA0B;IAE1B,MAAM,QAAQ,GAAG,IAAI,OAAO,CAAC,aAAa,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,CAAA;IAC/E,MAAM,UAAU,GAAG,IAAI,UAAU,EAAE,CAAC,YAAY,CAC9C,IAAI,KAAK,CAAC,aAAa,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC,CAC7D,CAAA;IACD,MAAM,WAAW,GAAG,IAAI,OAAO,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,UAAU,EAAE,IAAI,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;IACrF,MAAM,WAAW,GAAG,IAAI,OAAO,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAA;IAExF,MAAM,aAAa,GAAG,IAAI,OAAO,EAAE,CAAA;IACnC,MAAM,eAAe,GAAG,IAAI,UAAU,EAAE,CAAA;IACxC,MAAM,UAAU,GAAG,IAAI,OAAO,EAAE,CAAA;IAChC,WAAW,CAAC,SAAS,CAAC,aAAa,EAAE,eAAe,EAAE,UAAU,CAAC,CAAA;IACjE,MAAM,UAAU,GAAG,IAAI,KAAK,EAAE,CAAC,iBAAiB,CAAC,eAAe,CAAC,CAAA;IAEjE,OAAO;QACL,QAAQ,EAAE,EAAE,CAAC,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,aAAa,CAAC,CAAC,EAAE;QACxE,QAAQ,EAAE,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC,EAAE;KAChE,CAAA;AACH,CAAC"}
|