Home Manual Reference Source

src/tools/CameraController.js

import InputDetect from "inputdetect";
import S3Vector from "../math/S3Vector.js";
import S3Camera from "../basic/S3Camera.js";

/**
 * カメラ操作用コントローラー
 * タッチ操作やマウス操作を用いて3DCGシーンのカメラの移動・回転・ズームイン/アウトなどを制御するクラスです。
 * InputDetect の入力情報をもとに、カメラの移動・回転・距離変更(ズーム)を自動で計算します。
 */
export default class CameraController {
	/**
	 * CameraControllerのインスタンスを生成します。
	 * マウス/タッチ用の入力管理や、各種移動パラメータも初期化します。
	 */
	constructor() {
		/**
		 * タッチ・マウス入力管理オブジェクト
		 * @type {InputDetect}
		 */
		this.mouse = InputDetect.create();

		/**
		 * ズーム時の移動量の係数
		 * @type {number}
		 */
		this.moveDistance = 4.0;

		/**
		 * カメラ回転時の角度変更係数(度/ピクセル)
		 * @type {number}
		 */
		this.moveRotate = 0.5;

		/**
		 * カメラ移動時の移動量の係数(ピクセル単位から変換)
		 * @type {number}
		 */
		this.moveTranslateRelative = 0.1;

		/**
		 * コントローラが管理・操作するカメラインスタンス
		 * @type {S3Camera}
		 */
		this.camera = null;
	}

	/**
	 * カメラコントローラで操作するcanvas要素を登録し、入力イベントを設定します。
	 * @param {HTMLElement} element 対象となるcanvas要素など
	 */
	setCanvas(element) {
		this.mouse.setListenerOnElement(element);
	}

	/**
	 * 操作対象となるカメラをセットします(cloneで複製して保持)。
	 * @param {S3Camera} camera 操作対象のカメラ
	 */
	setCamera(camera) {
		this.camera = camera.clone();
	}

	/**
	 * 現在のカメラを取得し、入力に基づく移動・回転・ズームなどを反映して返します。
	 *
	 * 毎フレーム呼び出すことで、ユーザー操作を自動で反映したカメラインスタンスが得られます。
	 * @returns {S3Camera} 現在のカメラ状態
	 */
	getCamera() {
		const data = this.mouse.pickInput();

		// 左ドラッグ:平行移動
		this.camera.translateRelative(
			new S3Vector(
				-data.left.dragged.x * this.moveTranslateRelative,
				data.left.dragged.y * this.moveTranslateRelative,
				0
			)
		);

		// 右ドラッグ:カメラ回転(Y軸・X軸)
		this.camera.addRotateY(data.right.dragged.x * this.moveRotate);
		this.camera.addRotateX(-data.right.dragged.y * this.moveRotate);

		// ホイール操作:カメラズームイン・ズームアウト
		let distance = this.camera.getDistance();
		const l = data.wheelrotation;
		distance -= l * this.moveDistance * Math.log(distance);
		this.camera.setDistance(distance);

		return this.camera;
	}
}