LoginSignup
6
10

More than 5 years have passed since last update.

[Unity]平行投影モデルを透視投影ステージ内に立たせる方法

Posted at

はじめに

 このページはUnityにおいて平行投影モデルを透視投影ステージ内に立たせる方法を示したものである。
 ここでの透視投影はFoV60°、SceneのFoVを弄っていないものとする。
 また、応用としてこのプログラムを利用したFoVの違う透視投影モデルを併用する方法とドリーズームの方法を示す。

この方法を使用すると

 Unity3Dにおいて、平行投影したモデルと透視投影した3Dモデルとを共存することができる。
 3DCGアニメーション作品に使用されている画角の違うモデルを同一画面に表示、合成することができるようになる。
 下画像はUnityちゃんを平行投影した3Dモデル、床と壁を透視投影した3Dモデルとして表示したものである。
 image001.gif

考え方

  • 一点透視図法の上に零点透視図法を合成して表示する方法で実装する。

使う事例

  • 画角を統一した時に起こる3Dモデルの変形を起こしたくない時。
  • 別々のパースでモデルを表示したい時。

実装方法

PerspectiveMove.cs
using UnityEngine;
using System.Collections;

public class PerspectiveMove : MonoBehaviour {
    public Camera orthocamera;
    public Transform p_top;
    public Transform p_center;
    public Transform p_bottom;
    public Transform ScalePoint;
    public Transform PositionPoint;

    void LateUpdate () {//Updateだと表示ずれが起こる。
        int n = 1;

        if(Camera.main.WorldToViewportPoint(ScalePoint.position).z != 0)//0距離以外
        transform.localScale =
            Vector3.one * 2 * Mathf.Tan(60 / 2 * Mathf.Deg2Rad)
            * Vector3.Distance(p_bottom.position, p_top.position)
            / Camera.main.WorldToViewportPoint(ScalePoint.position).z;
        //ピンホールカメラのためzのみでOK。zはカメラからの距離。

        if (transform.localScale.x < 0)    n = -1;
        //(transform.localScale.x < 0)の時カメラの後ろ。
        transform.position = 
            orthocamera.ViewportToWorldPoint(Camera.main.WorldToViewportPoint(PositionPoint.position))
            + Camera.main.transform.forward * 100 * n;//カメラから距離を取ってカメラと被らないようにさせているだけ

        transform.rotation = p_bottom.rotation;
    }
}
  • 下画像同様にScene上で表示されたモデルの3Dモデルの一番上、中央、一番下の位置にTransformオブジェクトを置き、一番上をp_top、中央をp_center、一番下をp_bottomとしてPerspectiveMove.csに適用する。

image006.gifimage007.gif

オプション

モデルのサイズ変更

  • PlayerTopの座標とPlayerBottomの座標の距離を変えることで変更可能。

サイズ変更座標と位置座標の変更

  • サイズ変更座標はScalePoint、位置座標はPositionPointを変えることで変更可能。

応用

FoVの違う透視投影モデルを併用する方法

 PerspectiveMove.csのtransform.localScaleとtransform.positionに下記を代入するよう書き換えることで実装できる。
 また、この時のカメラはどちらもPerspectiveでなければならない。

transform.localScaleの値
Vector3.one * 2 / 3 
/ Mathf.Tan(Camera.main.fieldOfView / 2 * Mathf.Deg2Rad)
* Mathf.Tan(orthocamera.fieldOfView / 2 * Mathf.Deg2Rad)
* Vector3.Distance(p_bottom.position, p_top.position);
transform.positionの値
orthocamera.ViewportToWorldPoint (Camera.main.WorldToViewportPoint (PositionPoint.position));

ドリーズームの方法

 ドリー用カメラをMainCameraの子として作成し、MainCameraと同じ設定にする。
 DepthをMainCamera < ドリー用カメラ < orthocameraにすることで実装できる。

ライセンス

image020.gif
この作品はユニティちゃんライセンス条項の元に提供されています

6
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
10