[UE4]Spline MeshのUVを整える

概要

  • Spline Meshを使っているとTextureが伸びちゃったり逆に圧縮されたりする事があるのでどうにか整える話

  • Material側に伸縮処理を用意しておいて、BP側でSplineの長さを見てパラメータを振る形でかいけつ

  • 状況を再現しながら書いてるので途中で脱線する

  • でもそれは楽しいアクシデントなんです(ボブ)

手順

こういう円柱のSpline Meshがあるとする。MeshはEngine ContentのCyliinderを使用。

Materialはこんな感じ。T_GridはEngine Contentに含まれている。

Construction Script内でSplineに沿ってSpline Meshを動的生成する手順を踏んでいるものとする。ここで「どういうこっちゃ」と思った場合は、ヒストリアさんの解説記事を参照されたし。

Add Spline Mesh ComponentノードのDetailsでMeshとMaterialと、ついでにForward Axisを設定している(CylinderがZ方向に伸びているのに合わせている)。

これで自在にSplineに沿ってMeshが作れる。

Viewを左からの平行投影に変更した状態だとこう見える。

まず気になる点として、Splineの点に合わせてMeshが伸縮しているので、全体を通して模様が均一でない。これに取り組んでいこう。

MeshのUVについて、CylinderではV方向がSplineの伸びる向きになっている。Materialで、Vにスケールをかけられるように仕込んでおく。

Spline Meshを生成する際、同時にDynamic Material Instanceを生成する。
動作確認でScaleVに2.0を入れてみる。

2.0倍になったのでUVのV方向が2回繰り返されるようになっている。この繰り返し回数をMeshの長さで調整すれば良さそうだ。

ScaleVは1.0に戻して、基準となる長さを決めよう。

下の円柱を基準にする。これは長さ200cmで、上の円柱もこの密度で模様が続いて欲しい…が…

…と、その前に別の問題に気がつく。下の円柱はSpline Pointが2つなので本当に単純な円柱なのだが、既に模様がやや不均一である(なんか左の方は伸びてて、右の方は詰まっている)。

これはSplineのTangent値をそのままMeshに渡しているのが原因の様だ。そう思ってよく見ると、上の円柱も同じく1つの区間内ですでに不均一だ。

基準が変だと評価が難しくなるので、先に対策しておこう。Tangentに適切な値を与えれば良さそうだ。

まずSpline Mesh生成ループの最初で、Get Distance Along Spline at Spline Pointを使って区間の長さを計算しておく。

Set Start and Endしている箇所で、Spline本来のTangentを無視して、区間長さを使ったTangentを入力する。

↑適用前 ↓適用後

整いました(落語家)。

「1つのSpline Mesh内で不均一」の問題が改善したので、「上の円柱が全体を通して不均一」という問題に戻ろう。

と言っても実はほぼ終わっていて、Tangent用に計算していたSegment Lengthを基準長さで割った値をScaleVに入れればよい。

これで均一化した…が、新たな問題が発覚する。
区間と区間の間で模様が続いてない(太い白線の頻度が不規則)。

あと超いまさら気づいたが、UVの頭と尻が思ってたのと逆だこれ!こっちから解決しよう。
※実際に使用するMeshによってはこの手順は不要です

こういう超単純Materialを作って適用すると…

こういう結果になる。
白い丸がActorの原点で、左側にsplineが伸びている状態なので、UVのV値が1 → 0で変化している。 考えることを減らしたいので、0→1で変化するように修正しよう。

1-xノードを挟めば…

こうなる。

元のMaterialにも反映して…

こうなった。

では、区間と区間の間で模様が続いてない問題に戻ろう。

基準長さが200cmなので、区間長さ100cmだとScaleV=0.5になる。最初の区間なので、Vは0から始まってよい。
その次の長さ300の区間では、ScaleV=1.5になる。ひとつ前の区間はV=0.5で終わっているので、そこからV値が始まれば良さそう。

つまり「Vの初期値」をMaterialに渡せればよい。

Materialに、新たにOffsetVというパラメータを追加する。

Blueprint側では、ScaleVの計算をした後についでにOffsetVを計算する。

まず最初の区間ではOffsetVは0.0でよいから、変数初期値の0.0そのままでよい。
次以降の区間では「前の区間のScaleVの小数部」と「前の区間のOffsetV」の合計がOffsetVになるので合算して小数部だけ記憶しておく。

良い感じになった。
これで伸ばし放題!やったー!

めっちゃ伸ばしたらなんか最初の区間が変になるんですけど!やだー!

なんじゃこりゃ、と思って挙動を調べてみると「Spline Segment間でTangentの値が極端に変化する場合、Get Distance Along Spline at Spline Pointが正確な値を返さなくなる」という仕様(たぶんSpline計算における内部的な誤差)によるものである様だ。

ということで、無視していたSpline側のTangentを適当にケアしてみよう。

既に見た目が整っている場合は以下の工程は不要です!
SplineのTangent値を変更するので形状が変化します。実行前にバックアップしましょう。

Spline Mesh生成処理の前にTangentを強引に揃える。

やったぜ。

Create Meshの中身は最終的にこうなった。
画像を右クリックして「別タブで表示」などすると原寸で見られると思います。

説明は以上になります。
お疲れ様でした。

応用例

Vの起点をSpline先端側にすると蛇腹アームみたいな表現に使える。

これをやったときはTangentを整える作業をやっていなかったので伸縮が出ている。お許し下さいグレイロボ様、次こそは必ず…(敵幹部)