こんにちは、CX事業本部 Delivery部の若槻です。
Matterport の 3D Showcase をWebアプリに埋め込むことができる Matterport SDK for Embeds package では、Observables を介してユーザーが ShowCase を閲覧する際に操作するカメラの状態(カメラポーズ)をサブスクライブすることができます。
Observables をサブスクライブするクラスを「Observer」と言います。Observer がカメラポーズをサブスクライブすることにより、ユーザーが 3D Showcase 上の指定の位置に移動した際に、特定の情報を表示するなどの処理を実装することが可能です。
試してみた
前提
次のエントリの内容を実施済みである前提とします。
サーバーの起動にはWebPackを利用し、コンフィグに環境変数としてMatterportのSDK Keyを記載します。
webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
const webpack = require('webpack');
module.exports = {
entry: './index.js',
output: {
path: path.resolve(__dirname, './dist'),
filename: 'index_bundle.js',
},
plugins: [
new HtmlWebpackPlugin(),
new webpack.EnvironmentPlugin({
SDK_KEY: 'SDK_KEY',
}),
],
};
Functional Observer
カメラの状態(カメラポーズ)は、poseという名前のオブジェクトで表されます。
Functional Observerを利用してposeの状態をサブスクライブするには、次のようにします。
index.js
import { setupSdk } from '@matterport/sdk';
const SDK_KEY = process.env.SDK_KEY || '';
const main = async () => {
const mpSdk = await setupSdk(SDK_KEY);
const poseObserver = (pose) => {
console.log(JSON.stringify(pose));
console.log(pose);
}
mpSdk.Camera.pose.subscribe(poseObserver);
};
main().catch((err) => console.error('Error:', err));
npm run dev
を実行してindes.js
をwebpack-dev-serverで起動します。
localhost:8080
にアクセスすると、デモ用のショーケースを表示できました。また、カメラの操作に応じて、コンソールにposeの情報が出力されています。
poseの情報は次のような形式です。3D Showcase 上でのカメラの位置や方向を取得できています。
pose
{
position: {
x: -4.11534309387207,
y: 1.5915290117263794,
z: -1.7111740112304688,
},
rotation: { x: -2.3478604260139115, y: 177.69234680289787 },
projection: {
0: 0.7333507537841797,
1: 0,
2: 0,
3: 0,
4: 0,
5: 1.3032253980636597,
6: 0,
7: 0,
8: 0,
9: 0,
10: -1.0000666379928589,
11: -0.2000066637992859,
12: 0,
13: 0,
14: -1,
15: 0,
},
sweep: '91800a2940734a2897f806d337440d0d',
mode: 'mode.inside',
};
Object-Oriented Observer
Object-Oriented Observerを利用してカメラポーズをサブスクライブすることもできます。次のようにonChanged
関数を実装します。
index.js
import { setupSdk } from '@matterport/sdk';
const SDK_KEY = process.env.SDK_KEY || '';
const main = async () => {
const mpSdk = await setupSdk(SDK_KEY);
class PoseObserver {
onChanged(pose) {
console.log(JSON.stringify(pose));
console.log(pose);
}
}
mpSdk.Camera.pose.subscribe(new PoseObserver());
};
main().catch((err) => console.error('Error:', err));
カメラポーズが取得できています。
Using Multiple Observers
複数の Observer で同時カメラポーズをサブスクライブすることも可能です。
index.js
import { setupSdk } from '@matterport/sdk';
const SDK_KEY = process.env.SDK_KEY || '';
const main = async () => {
const mpSdk = await setupSdk(SDK_KEY);
mpSdk.Camera.pose.subscribe(function (pose) {
console.log('pose1');
});
mpSdk.Camera.pose.subscribe({
onChanged(pose) {
console.log('pose2');
},
});
};
main().catch((err) => console.error('Error:', err));
同時に2つの Observer で同じカメラの操作から状態を取得できています。
Shutting down an Observer
状態の更新が不要になったら、Observer を Observable から削除する必要があります。Observable をサブスクライブすると、ISubscriptionオブジェクトが返されます。このISubscriptionオブジェクトは、サブスクライブされた Observer を削除し、受信したコールバックを停止するために使用されるオブジェクトです。
index.js
import { setupSdk } from '@matterport/sdk';
const SDK_KEY = process.env.SDK_KEY || '';
const main = async () => {
const mpSdk = await setupSdk(SDK_KEY);
class PoseObserver {
onChanged(pose) {
console.log(pose);
}
}
const poseSubscription = mpSdk.Camera.pose.subscribe(new PoseObserver());
// 10秒後に Observer をシャットダウン
setTimeout(() => {
console.log('poseSubscription.cancel()');
poseSubscription.cancel();
}, 10000);
};
main().catch((err) => console.error('Error:', err));
アプリの実行から10秒後に Observer をシャットダウンされました。
Cloning an Observer’s View of State
カメラポーズが変更されると Observable が変更されるため、必要に応じて pose の状態を保持する実装を行います。
index.js
import { setupSdk } from '@matterport/sdk';
const SDK_KEY = process.env.SDK_KEY || '';
const main = async () => {
const mpSdk = await setupSdk(SDK_KEY);
const poseStack = [];
mpSdk.Camera.pose.subscribe((pose) => {
poseStack.push({
...pose,
position: { ...pose.position },
projection: [...pose.projection],
rotation: { ...pose.rotation },
sweep: pose.sweep.slice(),
});
console.log(poseStack.length);
});
};
main().catch((err) => console.error('Error:', err));
サブスクライブされる毎にposeStack
に状態が保持されています。
参考
以上