junkerstock
 vrbx2-3 

<!DOCTYPE html>

<!-- ColorfulxMelody YYB 式 初音ミク MUSIC CAFE v1.00 & YYB 2K rin -->

<html xmlns="http://www.w3.org/1999/xhtml">

<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Babylon Template with VR Joystick Movement & UI</title>

<style>
html,
body {
overflow: hidden;
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}

#renderCanvas {
width: 100%;
height: 100%;
touch-action: none;
}
</style>

</head>

<body>
<canvas id="renderCanvas" touch-action="none"></canvas>

<script src="https://cdn.babylonjs.com/babylon.js"></script>
<script src="https://cdn.babylonjs.com/gui/babylon.gui.min.js"></script>
<script src="https://cdn.babylonjs.com/havok/HavokPhysics_umd.js"></script>
<script src="https://www.unpkg.com/babylon-mmd/umd/babylon.mmd.min.js"></script>
<script src="https://code.jquery.com/pep/0.4.3/pep.js"></script>

<script>
const canvas = document.getElementById("renderCanvas"); // Get the canvas element
const engine = new BABYLON.Engine(canvas, true); // Generate the BABYLON 3D engine


const assetsPath = 'assets/'
const pmxPath = assetsPath + 'mmd/musiccafemiku/'
const pmxModel = pmxPath + 'mcmiku.pmx'

const vmdPath = assetsPath + 'ColorfulxMelody/'
const vmdModel = vmdPath + 'mmd_ColorfulxMelody_MIK.vmd'

const wavPath = assetsPath + 'ColorfulxMelody/'
const wavModel = wavPath + 'pv_709.wav'

const camPath = assetsPath + 'ColorfulxMelody/';
const camModel = camPath + 'came2.vmd'

// ▼▼▼ ここから追加 ▼▼▼
// --- 2体目のモデル ---
const pmxPath_2 = assetsPath + 'mmd/2krin/';
const pmxModel_2 = pmxPath_2 + 'YYB2Krin.pmx';

// --- 2体目のモーション ---
const vmdPath_2 = assetsPath + 'ColorfulxMelody/'
const vmdModel_2 = vmdPath_2 + 'mmd_ColorfulxMelody_RIN.vmd'; // 2体目のモーションファイル
// ▲▲▲ ここまで追加 ▲▲▲

// ▼▼▼ ここから追加 ▼▼▼
// --- ステージのモデル ---
const stagePath = assetsPath + 'stage/sea_bench/'; // ステージのフォルダへのパス
const stageModel = stagePath + 'bench.pmx'; // ステージのPMXファイル名
// ▲▲▲ ここまで追加 ▲▲▲

const offsetY = -100


// Add your code here matching the playground format
const createScene = async function (engine) {


const scene = new BABYLON.Scene(engine);
let adt;
let coordinateTextBlock;
let mmdModel;
let latestBonePosition = new BABYLON.Vector3(0, 0, 0); // ボーン座標を格納するグローバル変数
let lastPlayClickTime = 0; // 再生ボタンが最後にクリックされた時刻を記録する変数

const camera = new BABYLONMMD.MmdCamera("mmdCamera", new BABYLON.Vector3(0, 10, 0), scene);

// ▼▼▼ ここからスカイボックスのコードを追加 ▼▼▼
// 1. Skybox用のテクスチャ(空の画像)をURLから読み込む
const skyboxTexture = new BABYLON.CubeTexture("https://assets.babylonjs.com/environments/skybox.dds", scene);

// 2. 読み込んだテクスチャを使って、シーンにスカイボックスを作成する
// createDefaultSkybox(texture, pbr, scale)
const skybox = scene.createDefaultSkybox(skyboxTexture, true, 1000);
// ▲▲▲ ここまで追加 ▲▲▲


// ▼▼▼ このブロックを追加(古いSkyboxのコードは削除) ▼▼▼
// PhotoDomeを生成し、あなたのパノラマ画像を指定します
// const dome = new BABYLON.PhotoDome(
// "skyDome", // オブジェクトの名前(任意)
// "./pic/h154.png", // ← あなたのPNGファイルへのパスに書き換えてください
// {
// resolution: 32, // ドームの滑らかさ(32が一般的)
// size: 1000 // ドームの大きさ(シーン全体が収まるように)
// },
// scene
// );
// ▲▲▲ ここまで ▲▲▲

const ground = BABYLON.MeshBuilder.CreateGround("Ground", { width: 200, height: 200, subdivisions: 2, updatable: false }, scene);
ground.receiveShadows = true;

const hemisphericLight = new BABYLON.HemisphericLight("HemisphericLight", new BABYLON.Vector3(0, 10, -10), scene);
hemisphericLight.intensity = 0.3;
hemisphericLight.specular = new BABYLON.Color3(0, 0, 0);
hemisphericLight.groundColor = new BABYLON.Color3(1.1, 1.1, 1.1);


const shadowLight = new BABYLON.DirectionalLight("shadowLight", new BABYLON.Vector3(-1, -2, 1), scene);
shadowLight.position = new BABYLON.Vector3(20, 100, 100);

const shadowGenerator = new BABYLON.ShadowGenerator(1024, shadowLight, true);
shadowGenerator.useBlurExponentialShadowMap = true;
shadowGenerator.blurKernel = 32;


// ▼▼▼ ここから追加 ▼▼▼
// --- ステージのメッシュを読み込む ---
const stageMesh = await BABYLON.SceneLoader.ImportMeshAsync(undefined, stageModel, undefined, scene).then((result) => result.meshes[0]);

// ▼▼▼ 必要に応じて位置や大きさを調整 ▼▼▼
// 例:ステージ全体を少し下に移動する
// stageMesh.position.y = -1;

// 例:ステージ全体を1.2倍に拡大する
// stageMesh.scaling = new BABYLON.Vector3(1.2, 1.2, 1.2);

stageMesh.rotation.y = Math.PI / 2;
stageMesh.position.x = 40;

// ★ポイント:ステージにはアニメーションを付けないので、mmdRuntimeへの登録は不要です。
// ▲▲▲ ここまで追加 ▲▲▲

// ▼▼▼ 地面と影の調整を追加 ▼▼▼
// 1. ステージの全てのメッシュが影を受け取るように設定
stageMesh.getChildMeshes().forEach(mesh => mesh.receiveShadows = true);

// 2. 元からあった灰色の地面を削除(または非表示)
ground.dispose(); // 完全に削除する場合
// ground.visibility = false; // 非表示にするだけの場合
// ▲▲▲ ここまで追加 ▲▲▲


const mmdMesh = await BABYLON.SceneLoader.ImportMeshAsync(undefined, pmxModel, undefined, scene).then((result) => result.meshes[0]);

shadowGenerator.addShadowCaster(mmdMesh);
mmdMesh.receiveShadows = true;


// ▼▼▼ ここから追加 ▼▼▼
// --- 2体目のメッシュを読み込む ---
const mmdMesh_2 = await BABYLON.SceneLoader.ImportMeshAsync(undefined, pmxModel_2, undefined, scene).then((result) => result.meshes[0]);

// 1体目と重ならないように、X軸方向に2ずらす
mmdMesh_2.position.x = 2;

// 2体目も影を落とすように設定
shadowGenerator.addShadowCaster(mmdMesh_2);
mmdMesh_2.receiveShadows = true;
// ▲▲▲ ここまで追加 ▲▲▲


const vmdLoader = new BABYLONMMD.VmdLoader(scene);
const modelMotion = await vmdLoader.loadAsync("model_motion", vmdModel);


const havokInstance = await HavokPhysics();
const havokPlugin = new BABYLON.HavokPlugin(true, havokInstance);
scene.enablePhysics(new BABYLON.Vector3(0, -9.8 * 8, 0), havokPlugin);

const mmdRuntime = new BABYLONMMD.MmdRuntime(scene, new BABYLONMMD.MmdPhysics(scene));
mmdRuntime.register(scene);
mmdModel = mmdRuntime.createMmdModel(mmdMesh);


// ▼▼▼ このコードを追加してボーン名を調べる ▼▼▼
if (mmdMesh.skeleton) {
console.log("--- 利用可能なボーン名リスト ---");
mmdMesh.skeleton.bones.forEach(bone => {
console.log(bone.name);
});
console.log("---------------------------------");
}
// ▲▲▲ ここまで追加 ▲▲▲


mmdModel.addAnimation(modelMotion);
mmdModel.setAnimation("model_motion");



// ▼▼▼ ここから追加 ▼▼▼
// --- 2体目のモーションを読み込んで適用 ---
const modelMotion_2 = await vmdLoader.loadAsync("model_motion_2", vmdModel_2); // 1つ目と違う名前を付ける

const mmdModel_2 = mmdRuntime.createMmdModel(mmdMesh_2); // 2体目のMMDモデルを作成
mmdModel_2.addAnimation(modelMotion_2);
mmdModel_2.setAnimation("model_motion_2");
// ▲▲▲ ここまで追加 ▲▲▲



mmdRuntime.setCamera(camera);
const cameraMotion = await vmdLoader.loadAsync("camera_motion", camModel);
camera.addAnimation(cameraMotion);
camera.setAnimation("camera_motion");

const audioPlayer = new BABYLONMMD.StreamAudioPlayer(scene);
audioPlayer.preservesPitch = false;
audioPlayer.source = wavModel;

mmdRuntime.setAudioPlayer(audioPlayer);

mmdRuntime.playAnimation();

const mmdPlayerControl = new BABYLONMMD.MmdPlayerControl(scene, mmdRuntime, audioPlayer);
mmdPlayerControl.showPlayerControl();


// ▼▼▼ こちらが正しいコードです ▼▼▼
// sceneオブジェクトの「物理演算完了後」イベントに処理を追加する
scene.onAfterPhysicsObservable.add(() => {
try {
if (mmdModel && mmdModel.skeleton) {
const targetBone = mmdModel.skeleton.bones.find(b => b.name === '上半身');
if (targetBone) {
// グローバル変数に最新の座標をコピー

const finalMatrix = targetBone.getFinalMatrix(); // ボーンの最終的なワールド行列を取得
finalMatrix.decompose(undefined, undefined, latestBonePosition); // 行列から位置情報だけを抽出する


}
}
} catch (e) {
// エラーが発生してもコンソールに表示するだけで、プログラムは止めない
console.error("onAfterPhysicsObservableでエラー:", e);
}
});


// =================================================================
// ▼▼▼ VR機能、UIパネル、ジョイスティック移動処理 ▼▼▼
// =================================================================
const xr = await scene.createDefaultXRExperienceAsync({
uiOptions: {
sessionMode: 'immersive-vr', // 最初に表示される「Enter VR」ボタンはVRモード用
supportedSessionModes: ['immersive-vr', 'immersive-ar'] // VRとARの両方をサポートする
}
});

// ▼▼▼ 追従モードの状態を管理する変数 ▼▼▼
let isFollowing = false;
let followOffset = new BABYLON.Vector3();


// --- 左手コントローラーにUIパネルを追加 ---
xr.input.onControllerAddedObservable.add((controller) => {
if (controller.inputSource.handedness === 'left') {

let uiParent = scene.getTransformNodeByName("leftUIParent");

if (!uiParent) {
// 1. UIの親となるTransformNodeを作成
uiParent = new BABYLON.TransformNode("leftUIParent", scene);
uiParent.position = new BABYLON.Vector3(0, 0.05, 0.08);
uiParent.rotation = new BABYLON.Vector3(Math.PI / 4, 0, 0);

// 2. UIを表示するための平面メッシュを作成(高さを広げる)
const uiPlane = BABYLON.MeshBuilder.CreatePlane("uiPlane", { width: 0.25, height: 0.6 }, scene);
uiPlane.parent = uiParent;
uiPlane.visibility = 0.9;

// 3. 平面メッシュにGUIテクスチャを適用
adt = BABYLON.GUI.AdvancedDynamicTexture.CreateForMesh(uiPlane);

// 4. ボタンを縦に並べるためのStackPanelを作成
const stackPanel = new BABYLON.GUI.StackPanel();
stackPanel.isVertical = true;
stackPanel.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGN_MENT_TOP; // 上揃えに変更
adt.addControl(stackPanel);

const buttonHeight = "60px";


// 5. 「最初から」ボタン
const resetButton = BABYLON.GUI.Button.CreateSimpleButton("resetButton", "最初から");
resetButton.width = "100%";
resetButton.height = buttonHeight;
resetButton.color = "white";
resetButton.background = "#4CAF50"; // 緑色
resetButton.fontSize = 24;
resetButton.onPointerClickObservable.add(() => {
// 常にアニメーションを0秒地点に戻す
mmdRuntime.seekAnimation(0);
});
stackPanel.addControl(resetButton);

// 6. 「再生/停止」トグルボタン
const playPauseButton = BABYLON.GUI.Button.CreateSimpleButton("playPauseButton", "停止"); // 最初は再生されているので「停止」
playPauseButton.width = "100%";
playPauseButton.height = buttonHeight;
playPauseButton.color = "white";
playPauseButton.background = "#f44336"; // 赤色
playPauseButton.fontSize = 24;

playPauseButton.onPointerClickObservable.add(() => {
// もしアニメーションが再生中なら
if (mmdRuntime.isAnimationPlaying) {
// 動きを一時停止する
mmdRuntime.pauseAnimation();
// ボタンの文字を「再生」に変え、色を青系にする
playPauseButton.textBlock.text = "再生";
playPauseButton.background = "#2196F3";
} else { // もしアニメーションが停止中なら
// 動きを再生する
mmdRuntime.playAnimation();
// ボタンの文字を「停止」に変え、色を赤系に戻す
playPauseButton.textBlock.text = "停止";
playPauseButton.background = "#f44336";
}
});
stackPanel.addControl(playPauseButton);

//boneListTextBlock.text = `現在の時刻: ${currentTime} 次回の判定のために記憶: ${lastPlayClickTime} 経過時間: ${timeSinceLastClick}`;


// 7. 「正面」ボタン
const frontButton = BABYLON.GUI.Button.CreateSimpleButton("frontButton", "正面");
frontButton.width = "100%"; frontButton.height = buttonHeight; frontButton.color = "white";
frontButton.background = "#2196F3"; frontButton.fontSize = 24;
frontButton.onPointerClickObservable.add(() => {
isFollowing = false; // 追従モードを解除
xr.baseExperience.camera.position.set(0, 16, -20);
xr.baseExperience.camera.setTarget(new BABYLON.Vector3(0, 10, 0));
});
stackPanel.addControl(frontButton);

// 8. 「背面」ボタン
const backButton = BABYLON.GUI.Button.CreateSimpleButton("backButton", "背面");
backButton.width = "100%"; backButton.height = buttonHeight; backButton.color = "white";
backButton.background = "#FF9800"; backButton.fontSize = 24;
backButton.onPointerClickObservable.add(() => {
isFollowing = false; // 追従モードを解除
xr.baseExperience.camera.position.set(0, 16, 20);
xr.baseExperience.camera.setTarget(new BABYLON.Vector3(0, 10, 0));
});
stackPanel.addControl(backButton);




// 7. 「ARモード」ボタン
const arButton = BABYLON.GUI.Button.CreateSimpleButton("arButton", "ARモード");
arButton.width = "100%";
arButton.height = buttonHeight;
arButton.color = "white";
arButton.background = "#9C27B0"; // 紫色
arButton.fontSize = 24;


arButton.onPointerClickObservable.add(async () => { // ← (1) 関数の前に「async」を追加

// 現在もしVR/ARモードに入っていたら、一度終了する
if (xr.baseExperience.state === BABYLON.WebXRState.IN_XR) {
await xr.baseExperience.exitXRAsync(); // ← (2) 「await」で終了が完了するのを待つ
}

// ARモードで入り直す
await xr.baseExperience.enterXRAsync("immersive-ar", "local-floor");
});

stackPanel.addControl(arButton);




// ▼▼▼ 9. 「追従/解除」ボタンを作成 ▼▼▼
const followButton = BABYLON.GUI.Button.CreateSimpleButton("followButton", "追従");
followButton.width = "100%";
followButton.height = buttonHeight;
followButton.color = "white";
followButton.background = "#607D8B"; // グレー系の色
followButton.fontSize = 24;

followButton.onPointerClickObservable.add(() => {
isFollowing = !isFollowing; // 追従モードをトグル
if (isFollowing) {
// 追従開始:現在のカメラとモデルの「真の中心」との相対位置を計算して保存
const xrCamera = xr.baseExperience.camera;

followOffset = xrCamera.position.subtract(latestBonePosition);

followButton.textBlock.text = "解除";
followButton.background = "#9C27B0"; // 紫色に変更
} else {
// 追従解除
followButton.textBlock.text = "追従";
followButton.background = "#607D8B"; // 元の色に戻す
}
});
stackPanel.addControl(followButton);




// ▼▼▼ 追加するコード ▼▼▼
// 座標表示用のテキストブロック
coordinateTextBlock = new BABYLON.GUI.TextBlock("coordinateTextBlock");
coordinateTextBlock.text = "X: 0.00 Y: 0.00 Z: 0.00";
coordinateTextBlock.color = "white";
coordinateTextBlock.fontSize = 20;
coordinateTextBlock.height = "50px";
stackPanel.addControl(coordinateTextBlock);







// ▼▼▼ ここからが今回の追加機能 ▼▼▼
// 5. ボーン名を表示するためのボタン
const showBonesButton = BABYLON.GUI.Button.CreateSimpleButton("showBonesButton", "ボーン名表示");
showBonesButton.width = "100%";
showBonesButton.height = buttonHeight;
showBonesButton.color = "white";
showBonesButton.background = "#3F51B5"; // 藍色
showBonesButton.fontSize = 24;
stackPanel.addControl(showBonesButton);

// 6. ボーン名リストを表示するためのテキストブロック
const boneListTextBlock = new BABYLON.GUI.TextBlock("boneListTextBlock", "↑ボタンを押してボーン名を表示");
boneListTextBlock.color = "white";
boneListTextBlock.fontSize = 16;
boneListTextBlock.textWrapping = true; // 折り返しを有効にする
boneListTextBlock.resizeToFit = true; // テキスト量に合わせて高さを自動調整
boneListTextBlock.paddingTop = "10px";
stackPanel.addControl(boneListTextBlock);

// ボタンが押された時の処理
showBonesButton.onPointerClickObservable.add(() => {
let debugMessage = ""; // 表示するメッセージを格納する変数

if (mmdModel && mmdModel.skeleton) {
debugMessage += "スケルトンを発見。\n"; // \nは改行

const bones = mmdModel.skeleton.bones;
const boneCount = bones.length;

debugMessage += `ボーンの数: ${boneCount}個\n`;

if (boneCount > 0) {
// bone.nameの配列を作成し、カンマ区切りの文字列に変換
const boneNames = bones.map(bone => bone.name).join(', ');
debugMessage += "名前リスト: " + boneNames;
} else {
debugMessage += "ボーン配列は空です。";
}

} else if (mmdModel) {
debugMessage = "モデルはありますが、スケルトンが見つかりません。";
} else {
debugMessage = "MMDモデル自体が見つかりません。";
}

// 最終的なデバッグメッセージをテキストブロックに表示
boneListTextBlock.text = debugMessage;
});
// ▲▲▲ ここまで追加 ▲▲▲












}

uiParent.parent = controller.grip;
}
});




xr.baseExperience.onStateChangedObservable.add((state) => {
if (state === BABYLON.WebXRState.IN_XR) {
// XRモードに入った時の処理
camera.setAnimation(null);

// もしARモードで入ったなら、地面を非表示にする
if (xr.baseExperience.sessionManager.sessionMode === 'immersive-ar') {
ground.visibility = false;
}

} else if (state === BABYLON.WebXRState.NOT_IN_XR) {
// XRモードを終了した時の処理
camera.setAnimation("camera_motion");
isFollowing = false;

// 地面を再表示する(元の状態に戻す)
ground.visibility = true;
}
});




// 毎フレームごとの処理
scene.onBeforeRenderObservable.add(() => {
if (xr.baseExperience.state !== BABYLON.WebXRState.IN_XR) return;



// ▼▼▼ ここから修正 ▼▼▼
// --- VRカメラ自身の座標をUIに表示する ---
// if (coordinateTextBlock) {const cameraPosition = xr.baseExperience.camera.position;
// coordinateTextBlock.text = `CAMERA X: ${cameraPosition.x.toFixed(2)} Y: ${cameraPosition.y.toFixed(2)} Z: ${cameraPosition.z.toFixed(2)}`;}
// ▲▲▲ ここまで修正 ▲▲▲






// ▼▼▼ ここからが最終修正 ▼▼▼
// mmdMeshと、最も重要なmmdMesh.skeletonが準備完了しているか、最初に確認する
if (mmdModel && mmdModel.skeleton) {

// グローバル変数に格納された最新のボーン座標をUIに表示する
if (coordinateTextBlock) {
coordinateTextBlock.text = `上半身 X: ${latestBonePosition.x.toFixed(2)} Y: ${latestBonePosition.y.toFixed(2)} Z: ${latestBonePosition.z.toFixed(2)}`;
}

// --- 追従モードの処理 ---


// --- 追従モードの処理 ---
if (isFollowing) {
// グローバル変数(上半身の現在位置)をコピーし、それにオフセットを足してカメラの目標位置を決めます
// ※ .clone() は、元の latestBonePosition の値を誤って変更しないための「おまじない」です
const desiredPosition = latestBonePosition.clone().add(followOffset);

// カメラの位置を、計算した目標位置へ更新します
xr.baseExperience.camera.position.copyFrom(desiredPosition);

// カメラの視線を、モデルの現在位置(上半身)に向けます
xr.baseExperience.camera.setTarget(latestBonePosition);
}



}
// ▲▲▲ ここまでが最終修正 ▲▲▲






// --- ジョイスティック操作の処理 ---
// isFollowingがfalseの時だけジョイスティック操作を許可
if (!isFollowing) {
const deltaMillis = engine.getDeltaTime();
const xrCamera = xr.baseExperience.camera;
// 左コントローラー: 平行移動
const leftController = xr.input.controllers.find(c => c.inputSource.handedness === 'left');
if (leftController?.motionController) {
const thumbstick = leftController.motionController.getComponent("xr-standard-thumbstick");
if (thumbstick?.axes) {
const moveSpeed = 6.0 * deltaMillis / 1000;
const forward = xrCamera.getDirection(BABYLON.Vector3.Forward());
forward.y = 0;
xrCamera.position.addInPlace(forward.normalize().scale(-thumbstick.axes.y * moveSpeed));
const right = xrCamera.getDirection(BABYLON.Vector3.Right());
xrCamera.position.addInPlace(right.scale(thumbstick.axes.x * moveSpeed));
}
}

// 右コントローラー: 回転と上下移動
const rightController = xr.input.controllers.find(c => c.inputSource.handedness === 'right');
if (rightController?.motionController) {
const thumbstick = rightController.motionController.getComponent("xr-standard-thumbstick");
if (thumbstick?.axes) {
const rotationThreshold = 0.2;
if (Math.abs(thumbstick.axes.x) > rotationThreshold) {
const rotSpeed = 0.4 * deltaMillis / 1000;
if (xrCamera.parent) {
xrCamera.parent.rotate(BABYLON.Vector3.Up(), thumbstick.axes.x * rotSpeed, BABYLON.Space.WORLD);
}
}
if (Math.abs(thumbstick.axes.y) > rotationThreshold) {
const verticalSpeed = 2.0 * deltaMillis / 1000;
xrCamera.position.y += -thumbstick.axes.y * verticalSpeed;
}
}
}
}
});








return scene;
};

(async function () {

canvas.focus();
const scene = await createScene(engine); //Call the createScene function


// Register a render loop to repeatedly render the scene
engine.runRenderLoop(async function () {
scene.render();
});

// Watch for browser/canvas resize events
window.addEventListener("resize", function () {
engine.resize();
});
})()

</script>
</body>

</html>


使用変数

-------( Function )
action
adt
arButton
assetsPath
audioPlayer
b
backButton
background
blurKernel
bone
boneCount
boneListTextBlock
boneNames
bones
br> // Register a render loop to repeatedly render the scene engine.runRenderLoop -------( Function )
buttonHeight
c
camera
cameraMotion
cameraPosition
camModel
camPath
canvas
charset
color
content
createScene
debugMessage
deltaMillis
desiredPosition
dome
engine
equiv
finalMatrix
followButton
followOffset
fontSize
forward
frontButton
ground
groundColor
handedness
havokInstance
havokPlugin
height
hemisphericLight
id
intensity
isFollowing
isVertical
lastPlayClickTime
latestBonePosition
leftController
mesh
mmdMesh
mmdMesh_2
mmdModel
mmdModel_2
mmdPlayerControl
mmdRuntime
modelMotion
modelMotion_2
moveSpeed
name
offsetY
oordinateTextBlock
paddingTop
parent
playPauseButton
pmxModel
pmxModel_2
pmxPath
pmxPath_2
ponentialShadowMap
position
preservesPitch
receiveShadows
resetButton
resizeToFit
right
rightController
rotation
rotationThreshold
rotSpeed
scaling
scene
sessionMode
shadowGenerator
shadowLight
showBonesButton
skybox
skyboxTexture
source
specular
src
stackPanel
stageMesh
stageModel
stagePath
state
targetBone
text
textWrapping
thumbstick
uiParent
uiPlane
verticalAlignment
verticalSpeed
visibility
vmdLoader
vmdModel
vmdModel_2
vmdPath
vmdPath_2
wavModel
wavPath
width
x
xmlns
xr
xrCamera
y