ARKitのサンプルに影を追加しよう
ここまでサンプルアプリをよりリアルにする方法として、ライトを追加する方法を紹介しましたが、何か物足りないと感じてはいなかったでしょうか?
現実世界では物体に光を当てると影ができますが、サンプルアプリの飛行機には影がありませんでした。
影を付けることでさらにリアルさを演出することができますので、今回はその方法をご紹介します。
影を付ける方法
影を付ける方法は次の二つがあります。
前者は方法としてはシンプルですが、それぞれの物体に合った影の画像を用意するのは面倒です。
さらに、対象の物体が移動した場合にはそれに合ったファイルを全て用意するのは現実的ではありません。
今回は後者の方法を紹介します。
ship.scnを修正する
1. ShipMeshの位置を修正する
この後にライトと影を写す平面を追加するのですが、shipの子ノードとして追加します。
全ての子ノードがshipと同じ位置にあった方が修正がやり易いので、飛行機本体のshipMeshを親ノードのshipと同じ位置まで移動させます。
ship.scnを開き、左のペインからshipMeshを選択し、Transformsのz positionを0に変更してください。
※このまま進めると、飛行機を回転させた時に翼が地面にめり込むのでy座標も0.2に設定してください
※このまま進めると、飛行機を回転させた時に翼が地面にめり込むのでy座標も0.2に設定してください
2. 影を表示するための平面を追加する
影を表示するための平面を追加します。
影は飛行機本体の下に表示するため、平面は必ずshipMeshと比べて低い位置に配置します。
次に、planeを選択し、角度と位置を調整します。
追加した状態では平面は縦向きです。横にするため、Euerのxを-90にします。
追加した状態では平面は縦向きです。横にするため、Euerのxを-90にします。
位置はPositionのx, y, zをそれぞれ、0, -0.3, 0と入力します。
過去のアニメーションを追加時のコードは次のように書いていましたが、この状態だとライトと影も一緒に回転してしまいます。
次に平面の大きさを調整します。
デフォルト状態では1m × 1mなので、2m × 2mにします。
Sizeのxとyに2を入力します。
最後に、平面に影を写すため、Write To Colorの全てのチェックを外しておきます。
3. Directional Lightを追加する
ライトを追加する方法でも紹介しましたが、ライトのタイプはいくつか存在します。
影を付けるためには投光器のような一方向の光を上から当てる必要があります。
投光器のような光のタイプはDirectionalといい、それを追加します。
先ほどと同じようにオブジェクト選択ボタンからDirectional lightを選択し、編集画面上にドラッグ&ドロップします。
ライトを配置したら角度と位置を調整します。
角度はxを-90に設定し、位置は飛行機の上に来るように1を設定します。
次にshadowの設定を行います。
Casts shadowsにチェックを入れて、ModeをDeferredに設定します。
また、Castersは"Back face only"に設定をします。
この設置をしないと光が当たる上面がちらついてしまいます。
ここまで来れば影が表示されるようになりましたが、影の色が濃すぎるので透過の設定を行います。
先ほどのshadowのColorを選択しカラーパレットを表示させます。
黒を選択し、Opacityを50に変更します。
最後にライトと影をshipの子ノードに設定をしておきます。
このようにすることでshipをロードするとライトと影も一緒にロードされます。
アニメーションのコードをちょっと変更する
過去のアニメーションを追加時のコードは次のように書いていましたが、この状態だとライトと影も一緒に回転してしまいます。
if let ship = sceneView.scene.rootNode.childNode(withName: "ship", recursively: true) { ship.position = targetNode.position let configuration = ARWorldTrackingConfiguration() sceneView.session.pause() sceneView.session.run(configuration) let completion = { let rotationAction = SCNAction.repeatForever(SCNAction.rotateBy(x: 0, y: 0, z: 1, duration: 1)) ship.runAction(rotationAction) } SCNTransaction.begin() SCNTransaction.animationDuration = 1.5 SCNTransaction.completionBlock = completion ship.opacity = 1 SCNTransaction.commit() targetNode.isHidden = true }
そのため、ライトと影の位置は変えずに飛行機だけを回転させるために次のように変更します。
if let ship = sceneView.scene.rootNode.childNode(withName: "ship", recursively: true) { ship.position = targetNode.position let configuration = ARWorldTrackingConfiguration() sceneView.session.pause() sceneView.session.run(configuration) let completion = { let rotationAction = SCNAction.repeatForever(SCNAction.rotateBy(x: 0, y: 0, z: 1, duration: 1)) if let shipMesh = ship.childNode(withName: "shipMesh", recursively: false) { shipMesh.runAction(rotationAction) } } SCNTransaction.begin() SCNTransaction.animationDuration = 1.5 SCNTransaction.completionBlock = completion ship.opacity = 1 SCNTransaction.commit() targetNode.isHidden = true }
0 件のコメント:
コメントを投稿