fc2ブログ
ヽ|∵|ゝ(Fantom) の 開発blog? ホーム » Unity »【Unity】【C#】指定ワールド位置がカメラに映っているか調べる

【Unity】【C#】指定ワールド位置がカメラに映っているか調べる  


 最近はチュートリアル・ノウハウ系が多かったので、久しぶりにお役たちコード(?)を書いておこう。

 まぁ、VRM Live Viewer 開発し始めてからどうしても偏ってしまうが、私も最初から知ってたわけじゃないからね。必要に応じて調べてるうちに Unity にも詳しくなったとも言える。何でも勉強するならテーマがあった方が頭に入るね。極端な話、VRM Live Viewer はオープンソースの塊で、再利用可能コードは数年間に渡って公開してるし、アルゴリズムなどもアプリ開発以前から公開してるし、全部無料で手に入るものばかりなので、誰でも作れることになる。つまり、世界中の人と条件は同じなのだ。積み重ねがどれだけ重要かがわかるね(笑)。

 それでは、さっそく今回のテーマのコードを書いてみよう。と言ってもかなり簡単なんだけどね。

●指定のワールド位置がカメラに映っているか調べる
using UnityEngine;

public static partial class Extensions //※クラス名は任意
{
/// <summary>
/// カメラの Viewport 内に表示されているか?
/// 2023/08/01 Fantom
/// http://fantom1x.blog130.fc2.com/blog-entry-430.html
/// </summary>
/// <param name="cam">判定するカメラ</param>
/// <param name="pos">対象ワールド位置(transform.position)</param>
/// <returns></returns>
public static bool InCamera(this Camera cam, Vector3 pos)
{
if (cam == null)
return false;

var vp = cam.WorldToViewportPoint(pos);
return (0f <= vp.x && vp.x <= 1f && 0f <= vp.y && vp.y <= 1f);
}
}

 Camera.WorldToViewportPoint の内容は公式マニュアル見て欲しいが、戻り値の Vector3 は翻訳すると『ビューポート空間は正規化されており、カメラに対して相対的です。カメラの左下は (0,0) です。右上は (1,1) です。Z 位置はカメラからのワールド単位です。』となっているので、要するに値が 0~1 に入ってれば、カメラのビューポートに入ってると考えて良い。

 ただ、指定位置は transform.position 等、あくまで「点」でしかないので、メッシュなどが大きい場合、中心(Pivot)は画面から外れてるが、メッシュの一部が画面に少し見えている、なんてことが起こるかもしれない。そういうときはメッシュのバウンディングボックス(Renderer.bounds)等の8隅を調べるなどすれば良いかもしれない。

 また、Unity では全ての GameObject は Transform 持ってるので、いっそ transform を引数にしたものを作っておくのも良いかもね。

●指定のワールド位置がカメラに映っているか調べる (Transform 指定)
using UnityEngine;

public static partial class Extensions //※クラス名は任意
{
/// <summary>
/// カメラの Viewport 内に表示されているか?
/// 2023/08/01 Fantom
/// http://fantom1x.blog130.fc2.com/blog-entry-430.html
/// </summary>
/// <param name="cam">判定するカメラ</param>
/// <param name="tr">対象Transform</param>
/// <returns></returns>
public static bool InCamera(this Camera cam, Transform tr)
{
if (cam == null || tr == null)
return false;

var vp = cam.WorldToViewportPoint(tr.position);
return (0f <= vp.x && vp.x <= 1f && 0f <= vp.y && vp.y <= 1f);
}
}


 まぁ、好きに改造して使って欲しい。



 今回も VRM Live Viewer で使ってる再利用可能コードの一部となる。タイトルにもある「特定位置がカメラに映っているか調べる」は、ポストエフェクトの被写界深度の自動フォーカスで「ボーン対象」の選択に使っている。ボーンの選択が無い頃はモデルの「Head」(顔の辺り)1つが対象になっていて、要するに顔が常にフォーカスされていた。しかし、カメラモーションによっては下(足)から上(顔)へ接写など、一時的に顔が画面から外れてしまうことがあったんだよね。そういうとき顔以外にもフォーカスを当てる必要があった。つまり「顔が画面から外れていれば、他の近いボーンをフォーカス対象とする」ようにしたかったんだよね。

 まぁそんなことを VRM Live Viewer リリース以来、約5年近くやってる。最近はたまに「VRM Live Viewer を github で公開しろ」とか言ってくる人もいるが、冒頭に述べたように内容的にはオープンソースの塊だったりする。それをアプリに最適化、一部都合良く手を加えて改造してるので、ほとんど汎用性は無い。汎用的にするためにアプリ依存コードを除外して、一般化すればオープンソースと同じになる(元に戻る)。なので、全然意味が無い。ブログの冒頭でも言ってるように、最初からどうやって作ったかも、使ってるオープンソースも全部書いてあるので、本当に意味を感じない。

 まぁ、言ってくる人は学生さん(?)が多い気がするが、私も学生の頃は何でもできるわけじゃなかったよ。でも四苦八苦して色々考えてたのがいい経験になったのは間違いない。最初から「答えを教えろ」(そしてコピーして作ったものを自分のものにさせろ)というのは、かなり失礼なことだと思う。前述したように「世界中の人と同じ条件で作っている」(恐らく同じVRMアプリ開発者内では最底辺の環境)ので、同じことは誰でもできる。Unity なんてお金を出せば AssetStore でいくらでも優れたアセットを導入できるからね。私は無料で配布してるので、有料アセットなど買えないのだよ。だからオープンソースと自分のこれまでの知識と技術を駆使してるだけで、特別なことはしてない。せいぜい自分なりの工夫を重ねてるだけで、何でもやって貰えるのが当たり前と思われても非常に困る(← 一時期クレクレが年間50件は超えていて頭が痛かった=仮に1件5万~30万取れるとすると250~1500万の仕事をタダ働きすることになる。普通にサラリーマンの給料で換算しても約5年だと1500~2500万を無料で提供してるからね。これ以上仕事してタダでよこせと言われても、自分ならどうかと考えてみて欲しい)。

 経験不足は経験でしか補えないからね。私は学生時代書いたコード(C, C++)を未だに持っているが、物凄く苦労して2週間~1ヶ月くらいかけて作ったコード(システム)も、今では1日くらいで作れる。それくらい人は成長できるのだよ。答えはブログでもオープンソースでもググって大量の資料でも、今では充実してるので(昔はそんなに便利じゃなかった)、ヒントはやるから諦めないで精進しろとしか言えないのが本音なんだよね。今後はビジュアルスクリプティングでコンポーネント組み合わせるだけで作れるし、AI がコード自動生成してくれる時代も来るから、今よりもっと「自分で考える」ことができない人増えるだろうね。与えてくれるのが当たり前って考え方を捨てないと、成長はできないと思うよ。



(関連記事)
【Unity】固定背景画像(2D)を表示する
【Unity】【C#】画面解像度とアクペクト比(整数)を求める
【Unity】【C#】HDR Color を計算(変換)する
【Unity】【C#】ガンマ(Gamma, sRGB) - リニア(Linear) 値の相互変換
【Unity】【C#】3DText(TextMesh) を半透明より手前に表示する


関連記事
スポンサーサイト



category: Unity

thread: ゲーム開発

janre: コンピュータ

tag: Unityライブラリ  Unityリファレンス 
tb: 0   cm: --


トラックバック

トラックバックURL
→http://fantom1x.blog130.fc2.com/tb.php/430-2d873c9c
この記事にトラックバックする(FC2ブログユーザー)

プロフィール

Social

検索フォーム

全記事一覧

カテゴリ

ユーザータグ

最新記事

リンク

PR

▲ Pagetop