しゅみぷろ読者になるしゅみぷろプログラミングとかこの広告は、90日以上更新していないブログに表示しています。UnityTexturePaintはじめにesprog.hatenablog.com上記の記事で行っているように、動的にUVを算出してその部分にエフェクトを掛ける場合などではあるワールド座標上の点pがシーン内に配置されたモデルの表面上の点であるかどうか調べるモデル表面上の点である場合は、$p$のUVを計算するといった処理が必要になります。Unityの場合Physics.*cast系メソッドの出力用パラメータにRaycastHit構造体を渡すことでTextureCoordを得ることが出来ます。このTextureCoordの算出はCalculateRaycastTexCoordという関数呼び出しによって実現されているようですが、INTERNAL_CALLとなっていて詳細までは見ることが出来ませんでした。3Dテクスチャペイントを行ったりするのに必要な知識だと思い、後学のために自作してみましたよというのが今回のエントリです。これによってRayを明示的に使わなくても、任意のワールド座標$p$と判定するジオメトリさえわかっていればUVを求めることが出来ます。注意点ですが、今のところ結構負荷の高い実装になってしまっています。この負荷の大部分はメッシュの持つすべての三角形平面について調査しているためで、モデルのサーフェスを構成する三角形平面が多いほど時間がかかることになります。なんとか計算しなくても良いものを弾くことができればもう少し効率的になるかなと思います。マルチスレッドで調査対象を分割してしまうのもアリです。そもそももっと効率のいい方法等ご存知の方がいましたらご教示いただければ幸いです。いうわけで効率化は今後の課題とし、今回は「こんな感じの計算すればUV求められるよ!」っていうのを紹介するのみにとどめます。少々数学知識が必要になります。詳細な説明は省き、知っていることが前提になっている部分もあります。以下の記事も参考になる部分があるかと思いますので紹介しておきます。esprog.hatenablog.comまた、今回のサンプルを含むリポジトリを公開しています。よろしかったら参考までに。github.comアルゴリズム「ある点$p$とメッシュが与えられ、その点$p$がメッシュの表面に含まれるとき、点$p$のUV座標値を求めたい」という問題に対する回答を得るにあたって、以下の手順を踏むことにしました。メッシュを構成する三角形の集合内から、三角形の同一平面上に点$p$が存在するものを調べる1をパスした三角形が点$p$を内部に含んでいるかどうかを調べる2をパスした三角形の面積比から点$p$のUVを求める順にそれぞれの方法について解説していきます。三角形の同一平面上に点$p$が存在するものを調べる与えられるメッシュが三角形ポリゴンの集合で表現されていることを仮定します。$p1,p2,p3$はメッシュのもつサーフェスを構成する三角形です。$p$は任意の点で、これらは共にModelSpaceで表されるものとします。上図のようにベクトル$v1,v2,vp$を定義し、$v1$と$v2$の外積を$nv$とします。ここまで定義すれば話は簡単で、$p1,p2,p3$の構成する平面内に$p$が存在するかどうかを調べるには、$nv$と$vp$の内積が0かどうかを判定するだけです。$nv$は$v1$と$v2$の外積なので、$v1$と$v2$に対して垂直方向のベクトルであるはずです。点$p$が平面内に存在するということは、$vp$も$nv$と垂直である、というわけです。三角形が点$p$を内部に含んでいるかどうかを調べる上図のように点とベクトルを定義します。$a,b,c$はさきほどの$p1,p2,p3$と同じものです。$ab,bc,ca,ap,bp,cp$はそれぞれの点を始点、終点とするベクトルです。cp$が同じ方向を向いているか判定するだけです。点pが三角形外に存在した場合、外積によって求められるベクトルの向きが逆になり、これらのベクトルは違う向きを向くことになります。同じ方向を向いているかどうかの判定には内積が使えます。三角形の面積比から点$p$のUVを求めるここは少々複雑です。いうのも、3次元空間内で単純にUVを線形補完してしまうと、透視投影の影響で歪みが発生します。これを考慮した補完をパースペクティブコレクトと呼ぶらしいのですが、これを行うためにプロジェクション変換を行う行列を用意する必要があります。今回UVの算出に用いているのは面積比による補完です。三角形頂点と$p$の各点をModelSpaceからProjectionSpaceに変換し、同次座標を求め、これを通常座標に変換しZ(深度)を破棄したXY平面上の点として、面積比から補完します。パースペクティブコレクトを実現するために、通常座標に直した($w$で割った)各点を使って線形補完し、最後に$w$の逆数を線形補間したもので割っています。}}マウスクリック位置のUVを求めるサンプルです。最後にUnityのRaycastHitのTextureCoordと照らしあわせて確認するログを表示させています。正しい結果が得られているかと思います。これで、位置さえわかればUVを算出することができます。追記バグ見つけました。)はてなブログをはじめよう!es_programさんは、はてなブログを使っています。ブログを報告する引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。