Verge3Dの最大の特徴は、Puzzlesというビジュアル・プログラミングのツールが備わっていることです。JavaScriptに慣れていなくてもWeb3Dコンテンツが作れます。
いかんせん、Three.jsのいろいろなモジュールをインポートして使いたい時は、Puzzlesの「至れり尽くせり」ぶりが枷になります。
早い話、どうやってモジュールをインポートしていいか分からない😂 完璧過ぎて、Puzzlesがカバーする範囲の外の処理が記述しにくいのですね。
コードベースで作る
前途多難だけどビジュアルツールを使わないで、コードベースで漫画漫文ノート開発を進めることにしました。
まずは、恐る恐るVerge3Dのモジュールを追加してみます。シーンに軸ヘルパーを表示しました。
* * *
実はここ一ヶ月間、JSの基礎あたりをぐるぐる彷徨っていました。
Pythonに慣れているので、JSのソースもざっくりなら読めます。でも一行一行やっていることの意味がわからないと、自分の環境で再現できません。
ブラウザのコンソール画面にエラーが出る度に「これは何?」と検索しまくりの日々でした。
漫画漫文ノートが実用レベルでお目見えするまで、あと少しです🤗
iframeで呼び出すindex.html
<!DOCTYPE html>
<html lang="ja">
<head>
<title>mmNote メイン</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<link rel="stylesheet" type="text/css" href="/css/mystyle.css">
</head>
<body>
<div id="v3d-container">
<div id="fullscreen-button" class="fullscreen-open" title="Toggle fullscreen mode"></div>
<div id="paint-button" class="paint-button"></div>
</div>
<script type="module" src="main.js"></script>
</body>
</html>
index.htmlから呼び込むmain.js
律儀に4文字ずつ字下げしているのは、なるべくソースをPythonの形に似せたいから。Javascriptの標準的な書き方と少し違います。
/* mmNoteツール メインスクリプト */
// https://www.soft8soft.com/docs/api/en/extras/App.html
'use strict';
import * as v3d from "/path-to/v3d.module.js";
import { createPreloader, createCustomPreloader } from "/path-to-sub/preloader.js";
import { prepareFullscreen } from "/path-to-sub/fullscreen.js";
import { camera_fit } from "/path-to-sub/camera_fit.js";
// ページ読込の後、createApp()を実行
window.addEventListener('load', e => {
const params = v3d.AppUtils.getPageParams();
createApp({
containerId: 'v3d-container',
fsButtonId: 'fullscreen-button',
txButtonId: 'paint-button',
sceneURL: 'mmNote.gltf.xz',
objName: 'Morffee'
});
});
// createApp()
// ①initOptionsでctxSettings (WebGL属性。canvas.getContext()に渡される)設定
// ②フルスクリーンとプリローダを組み込む
// ③app実行
async function createApp({ containerId, fsButtonId, txButtonId, sceneURL, objName }) {
// ctxSettings - ドローバッファはFirefoxの印刷で必要
let initOptions = {
useFullscreen: true,
useCompAssets: true,
};
// フルスクリーンとプリローダのコンストラクタ
const disposeFullscreen = prepareFullscreen(containerId, fsButtonId,
initOptions.useFullscreen);
const preloader = createPreloader(containerId, initOptions);
// Appインスタンス作成
const ctxSettings = {};
ctxSettings.preserveDrawingBuffer = true;
const app = new v3d.App(containerId, ctxSettings, preloader);
// フルスクリーンの配置
app.addEventListener('dispose', () => disposeFullscreen?.());
//if (initOptions.preloaderStartCb) initOptions.preloaderStartCb();
// app実行
app.loadScene(sceneURL, () => {
app.enableControls();
// カメラ・フィット
// function camera_fit(app, v3d, objName, cameraName)
camera_fit(app, v3d, 'Morffee', 'Camera');
// 軸ヘルパーを追加
app.scene.add(new v3d.AxesHelper(10));
app.run();
});
return { app };
}