Babylon.js メモ

細かいBabylon.jsのメモを個別記事化はちょっと手間だったので、この記事にまとめていく。

モデルの読み込み

モデルを読み込みだけして、後で実体化

パターン1

fetchでデータを取得して、そのデータをbase64に変換して、そのデータを使ってモデルを読み込む。

1
2
3
4
5
6
7
8
9
10
11
12
const res = await fetch("./box3.glb")
const arr = await res.arrayBuffer()
const bytes = new Uint8Array(arr);
const dataUri = "data:base64," + btoa(String.fromCharCode(...bytes));

const load = await BABYLON.SceneLoader.ImportMeshAsync("","",dataUri)
const mesh = load.meshes[0]
mesh.position = new BABYLON.Vector3(2,0,0)

const load2 = await BABYLON.SceneLoader.ImportMeshAsync("",dataUri)
const mesh2 = load2.meshes[0]
mesh2.position = new BABYLON.Vector3(-2,0,0)

パターン2

LoadAssetContainerで読み込んで、後でクローンして使う。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const meshes: BABYLON.AbstractMesh[] = []
BABYLON.SceneLoader.LoadAssetContainer("./", "box1.glb", scene, function (container) {
meshes.push(container.meshes[0])
});

setTimeout(() => {
const mesh = meshes[0].clone("model1", null)!
mesh.position = new BABYLON.Vector3(2, 0, 0)
}, 500);

setTimeout(() => {
const mesh = meshes[0].clone("model2", null)!
mesh.position = new BABYLON.Vector3(-2, 0, 0)
}, 1000);

パターン3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
let keepContainer: {[key:string]: BABYLON.AssetContainer} = {}
BABYLON.SceneLoader.LoadAssetContainer("./", "box1.glb", scene, function (container) {
keepContainer["box"] = container
});

setTimeout(() => {
const entries = keepContainer["box"].instantiateModelsToScene(undefined, true);
console.log(entries)
entries.rootNodes[0].position = new BABYLON.Vector3(2, 0, 0)
}, 500);

setTimeout(() => {
const entries = keepContainer["box"].instantiateModelsToScene(undefined, true);
entries.rootNodes[0].position = new BABYLON.Vector3(-2, 0, 0)
}, 1000);

メタセコイアで作成したデータを読み込む時の注意点

  • Babylon.js の座標系で1は、メタセコイアの座標系で1000になる。

関節角度の取得

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
function getAegleFromQuaternions(
q1: BABYLON.Quaternion,
q2: BABYLON.Quaternion,
axis: BABYLON.Vector3,
) {
const rotationQuaternion1 = q1.clone();
const rotationQuaternion2 = q2.clone();
const diffRotation = rotationQuaternion1.invert().multiply(
rotationQuaternion2,
);

if (diffRotation.length() == 1) {
return 0;
}

const halfThetas = [
(axis.x) ? Math.atan2(diffRotation.x / axis.x, diffRotation.w) : null,
(axis.y) ? Math.atan2(diffRotation.y / axis.y, diffRotation.w) : null,
(axis.z) ? Math.atan2(diffRotation.z / axis.z, diffRotation.w) : null,
];

const halfTheta = halfThetas.find(function (halfTheta) {
return halfTheta;
}) as number;

if (Math.abs(halfTheta * 2) > Math.PI) {
const theta = 2 * Math.PI - Math.abs(halfTheta * 2);
return halfTheta > 0 ? -theta : theta;
}
return halfTheta * 2;
}

const box1To2Angle = getAegleFromQuaternions(
boxMesh1.rotationQuaternion!,
boxMesh2.rotationQuaternion!,
new BABYLON.Vector3(0, 0, 1),
);

const box1to2AngleDeg = Math.round(box1To2Angle / Math.PI * 180 * 100) / 100;