🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Three.js

Three.jsはWebGLをサポートしているJavaScriptの3D描画用ライブラリです。

Q&A

3回答

6748閲覧

three.js カメラの角度を変更した後、OrbitControlsに反映させたい

firstbiz

総合スコア60

Three.js

Three.jsはWebGLをサポートしているJavaScriptの3D描画用ライブラリです。

0グッド

0クリップ

投稿2020/12/06 10:26

Three.js(R100)で開発をしています。
OrbitControlsを使用していますが、カメラの角度を変更しても、すぐに角度を元に戻ってしまいます。

ボタンをクリックすると、changeCamera関数のcamera.setRotationFromQuqternionで角度が変更されます。
しかしcontroles.update()を実行するとカメラが元の角度に戻ってしまいます。

camera.position.x で位置を変更した場合にはcontroles.updateで位置が反映されているような動きになり、正しく位置が変更されます。

「OrbitControls以外でカメラの角度を変更した場合、OrbitControlsに反映させたい」場合の方法を教えて下さい。
よろしくお願いいたします。

全コードを添付しました。

<html> <head> <meta charset="utf-8" /> <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/110/three.min.js"></script> <script src="js/controls/OrbitControls.js"></script> <script> // ページの読み込みを待つ window.addEventListener('load', init); let camera; let controls; function changeCamera() { // 角度を変更した場合、OrbitControlsに反映されず、結果的に角度が戻る // 位置を変更した場合、controls.updateで反映されるため正しく動作する。 if(true) { camera.setRotationFromQuaternion(new THREE.Quaternion(-0.2527326204999822, 0.42227344138250583, 0.12385549165623723, 0.8616676740047633)); camera.updateMatrix(); } else { camera.position.x = 100; } controls.update(); console.log('A', camera.quaternion); } function init() { // サイズを指定 const width = 1920; const height = 1080; // シーンを const scene = new THREE.Scene(); // レンダラー const renderer = new THREE.WebGLRenderer({ canvas: document.querySelector('#myCanvas') }); renderer.setSize(width, height); // カメラ camera = new THREE.PerspectiveCamera(45, width / height); camera.position.set(0, 0, 1000); controls = new THREE.OrbitControls(camera); controls.addEventListener( 'change', () => { console.log('B', camera.quaternion); }); // 正方形 const mesh = new THREE.Mesh( new THREE.BoxGeometry(300, 300, 300), new THREE.MeshNormalMaterial() ); scene.add(mesh); tick(); function tick() { renderer.render(scene, camera); requestAnimationFrame(tick); } } </script> </head> <body> <canvas id="myCanvas"></canvas> <button onclick="changeCamera()">カメラの位置変更</button> </body> </html>

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

原因はわかりません。すみません。
OrbitControls.jsのコードを追えばよいのですが、よくわからず力尽きました。

別な方法で申し訳ないのですが、クオタニオン単体よりも視点+見る場所からカメラ行列を作るほうが楽なので、これで解決できるなら試してみてください。

const target = new THREE.Vector3(1, 2, 3); // 見る場所 const eye = new THREE.Vector3(-500, 500, -500); // 視点 const up = new THREE.Vector3(0,1,0) // 行列に変換 const m = new THREE.Matrix4() m.lookAt(target, eye, up) m.setPosition(eye) // position/rotation/scaleに分離。 m.decompose(camera.position,camera.rotation, camera.scale);

投稿2020/12/11 04:34

KphP9

総合スコア78

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

つまり、角度だけ変えても、「見る場所」の影響を受けて角度が変わってしまうということですね。

はい。OrbitControlを利用するとそうなります。

希望する角度にするには、「その角度になるような位置」を計算し、そのセットも必要ということですね

はい。下記のコードのようになるかと思います。

const q = new THREE.Quaternion(-0.2527326204999822, 0.42227344138250583, 0.12385549165623723, 0.8616676740047633) // カメラ向き。元コードからコピー const target = new THREE.Vector3(1,2,3) // 見る場所(適当) // カメラ向きと見る場所から視点(eye)の位置を得る const m = new THREE.Matrix4().makeRotationFromQuaternion(q) const xAxis = new THREE.Vector3(), yAxis = new THREE.Vector3(), zAxis = new THREE.Vector3() m.extractBasis(xAxis, yAxis, zAxis) const DISTANCE = 500 // 見る場所と視点の距離(適当) const eye = zAxis.multiplyScalar(DISTANCE).add(target) camera.setRotationFromQuaternion(q) // カメラ向き camera.position.copy(eye) // 視点 controls.target = target // 見る場所 controls.update()

投稿2020/12/10 12:13

KphP9

総合スコア78

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

firstbiz

2020/12/11 02:04 編集

非常に助かりました。理解できてきました。 いただいたコードのそのまま使い、数字だけ変更してみました。 コントロールを使わなければ対象オブジェクト(平面)から500離れた位置で、対象オブジェクトがまっすぐの状態で表示されました。オブジェクトは平面(長方形)であり、画面上は長方形が表示されています。 これは期待通りです。対象オブジェクト(平面)がピッタリと曲がらずに、歪まずに見える位置を計算して、そこに移動したためです。 なお、カメラのクォータニオンを対象オブジェクトのクォータニオンと一致させることで実現しました。 しかしコントロールを使うと(いただいたコードをコピペ)、歪みはないのですが、カメラのZ軸回転が不足しているような見え方になり、ひし形に近い表示になっています。 つまりもう少しZ軸回転すればピッタリと長方形になってくれる状態です。 ※画像が載せられないので、わかりずらくてすいません。 コントロールを使わないと■なところ、◆になってしまう感じです。 コントロールではオブジェクトの中心を見ています(target.set(x,y,z))。 原因がわかれば非常に助かります。申し訳ございません。
guest

0

js:

1camera.position.set(1286.5012314677283, -436.9550018391255, 644.507715439303) // カメラ位置 2camera.setRotationFromQuaternion(new THREE.Quaternion(0.1329104526203376, 0.41639167154715456, -0.0616769818227606, 0.8973008065100904)) 3camera.updateMatrix(); 4controls.target.set(184.8436704457554, 7.876487115259312e-15, -286.885931422345) // OrbitControlsの見る場所

カメラ位置を設定すればよいです。
またdollyやpanに対応するためにOrbitControls.target(見る場所)の設定も必要です。

投稿2020/12/10 05:01

KphP9

総合スコア78

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

firstbiz

2020/12/10 08:45

ありがとうございます。 つまり、角度だけ変えても、「見る場所」の影響を受けて角度が変わってしまうということですね。 希望する角度にするには、「その角度になるような位置」を計算し、そのセットも必要ということですね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問