やること
ARで立方体のオブジェクトを表示して、
その立方体オブジェクトをクリック(orタッチ)すると回転する
Three.js+ARでクリックイベント/タッチイベント使えた。Tween.jsも一応使えた。Win10+Firefox, Android9+Chrome, iOS13+Safariで動いた。ふぅ pic.twitter.com/C6a67RMxvY
— j4amountain (@zsipparu) April 25, 2020
Three.jsのrotationを使った回転と
Tween.jsを使った回転のサンプルスクリプト
ソース
githubに格納 -> ClickToMove
ブラウザがカメラにアクセスするため ↓ などでSSL(https)対応Webサーバを用意
ARマーカ hiro
はネットで別途調達が必要
動作確認結果
以下の条件で動作を確認
- Win10 Chrome (バージョン 81.0.4044.122)
- Win10 FireFox (バージョン 75.0)
- Win10 Microsoft Edge
- iOS13 Safari
- Android9 Chrome
※スマホ(iOS,Android)では、画面タッチしても立方体が動かずに何回も画面タッチした。
スクリプトの説明
mesh01
の立方体を作るスクリプトはここ
//-- ↓ 立方体1つ目 ↓ ---------------------------------//
let geometry01 = new THREE.CubeGeometry(1,1,1);
let material01 = [
new THREE.MeshLambertMaterial({color: 0xE9546B,opacity: 0.3,transparent: true,side: THREE.DoubleSide}), // right
new THREE.MeshLambertMaterial({color: 0xE9546B,opacity: 0.4,transparent: true,side: THREE.DoubleSide}), // left
new THREE.MeshLambertMaterial({color: 0x00A95F,opacity: 0.5,transparent: true,side: THREE.DoubleSide}), // front
new THREE.MeshLambertMaterial({color: 0x00A95F,opacity: 0.6,transparent: true,side: THREE.DoubleSide}), // back
new THREE.MeshLambertMaterial({color: 0x187FC4,opacity: 0.7,transparent: true,side: THREE.DoubleSide}), // top
new THREE.MeshLambertMaterial({color: 0x187FC4,opacity: 0.8,transparent: true,side: THREE.DoubleSide}), // bottom
];
mesh01 = new THREE.Mesh( geometry01, material01 );
mesh01.position.y = 0.5;
mesh01.name = "OBJECT001";
markerRoot01.add( mesh01 );
//-- ↑ 立方体1つ目 ↑ ---------------------------------//
クリック(orタップ)自の処理はここ、これもどこかのソースをコピーさせたもらった(どこだっけ・・)
//===================================================================
// マウスダウン(タップ)によるピッキング処理
//===================================================================
window.addEventListener("mousedown", function(ret) {
let mouseX = ret.clientX; // マウスのx座標
let mouseY = ret.clientY; // マウスのy座標
//console.log(mouseX + " : " + mouseY);
mouseX = (mouseX / window.innerWidth) * 2 - 1; // -1 ~ +1 に正規化されたx座標
mouseY = -(mouseY / window.innerHeight) * 2 + 1; // -1 ~ +1 に正規化されたy座標
let pos = new THREE.Vector3(mouseX, mouseY, 1); // マウスベクトル
pos.unproject(camera); // スクリーン座標系をカメラ座標系に変換
// レイキャスタを作成(始点, 向きのベクトル)
let ray = new THREE.Raycaster(camera.position, pos.sub(camera.position).normalize());
let obj = ray.intersectObjects(scene.children, true); // レイと交差したオブジェクトの取得
if(obj.length > 0) { // 交差したオブジェクトがあれば
picked(obj[0].object.name); // ピックされた対象に応じた処理を実行
console.log("debug 001");
}
console.log("-----");
});
クリック(orタップ)したところにオブジェクトがあれば、各オブジェクトに用意したフラグが変わる
mesh01
, mesh02
の立方体は、フラグ(m01Flg
,m02Flg
)が1以外のときに、Three.jsのrotationで回転する。
function animate()
{
requestAnimationFrame(animate);
deltaTime = clock.getDelta();
update();
render();
}
function update()
{
if( arToolkitSource.ready !== false ) arToolkitContext.update( arToolkitSource.domElement );
if( m01Flg != 1){
mesh01.rotation.x += 0.1
}
if( m02Flg != 1){
mesh02.rotation.y += 0.1
}
}
mesh03
の立方体は、フラグ(m03Flg
)が0以外のときに、Three.jsのrotationで回転する。(ソースは こちらから拝借 )
//===================================================================
// TWEEN
//===================================================================
let cube_size = 1; // cubeのサイズ
let cube_count = 1; // cubeの配置数
let grid_count = 10; // グリッドの分割数
let interval = 1000; // 移動アニメーションの間隔
let duration = 500; // 1回の移動時間
let stop_rate = 0; // 移動しない確率
let cube_half = cube_size / 2;
TWEEN.autoPlay(true);
let next_move = function () {
if(m03Flg != 0){
let origin_pos = mesh03.position.clone();
let origin_quaternion = mesh03.quaternion.clone();
let move_axis = 'x';
let move_offset = cube_size;
let from_param = { x: 0 }; // tween開始時の値
let to_param = { x: 1 }; // tween終了時の値
let duration = 500; // 単位はミリ秒
let tween = new TWEEN.Tween(from_param)
.to(to_param, duration)
.easing(TWEEN.Easing.Linear)
.on('update', function (_a) {
let x = _a.x;
let r = cube_half * Math.sqrt(2); // 中心の回転半径
let center_angle = 45 + (90 * x); // 現在の中心位置の角度(移動開始時は45°)
let center_rad = center_angle * Math.PI / 180; // 角度をラジアンに変換
let current_height = Math.sin(center_rad) * r - cube_half; // 移動中のcube中心の高さ
let current_move = (cube_half - Math.cos(center_rad) * r) * move_offset; // 移動中のcube中心の位置
// 移動前のpositionを基準に計算
mesh03.position[move_axis] = origin_pos[move_axis] + current_move;
mesh03.position.y = origin_pos.y + current_height;
let axis = new THREE.Vector3(0, 0, -1); // 回転軸
let new_q = origin_quaternion.clone();
let target = new THREE.Quaternion();
let rad = (Math.PI / 2) * x;
target.setFromAxisAngle(axis, rad);
new_q.multiply(target);
mesh03.quaternion.copy(new_q);
});
tween.start();
}
};
setInterval(next_move, interval);