2017年09月22日

ビットマップペイントツールのチュートリアルをやってみた その85 3dsmax 2017

引き続きMAXScriptマニュアルに載っている「チュートリアル-ビットマップペイントツールを9つの簡単なステップで作成する」 の続きを考えて見たい。

前回はペイントブラシのサイズが変わらないものとして作ったけど、ブラシサイズもフレーム間で線形補間した場合、単純に距離をブラシの重ね合わせを考慮した移動距離で割るだけでは1フレーム間を線形補間するための分割数を求める事が出来ない。ブラシサイズが大から小へ変わっていく時に大を基準にフレーム間の距離を分割した1ステップの移動距離を決めるとブラシサイズが小さくなるに連れてブラシ間の隙間が大きくなってしまうし、小から大だと逆に詰まってしまう事になる。

前フレーム時のブラシの1ステップの移動距離をd1、現フレーム時のブラシの1ステップの移動距離をd2、分割数をn、前フレームから現フレームの間のブラシの移動距離をLとすると、ブラシの1ステップでの移動量はステップが進むごとに変化して、その量は

(d2−d1)/(n−1)

になる。始点をd1としてkステップ目のブラシの1ステップの移動距離は

stepk=d1+k*(d2−d1)/(n−1)

となり、kは0〜n−1でstepkはd1〜d2まで変化する。そしてこれをnステップ進めると距離Lになるわけだ。よって以下の式が成り立つ。

fig01

これをnについて解くと、

n=2*L/(d1+d2)

になる。

この式に適当な数値を入れて検証してみると、

L=50、d1=5、d2=15

n=2*50/(5+15)=5

1ステップの増分は

(d2−d1)/(n−1)=(15−5)/(5−1)=2.5

この増分でnステップ分の距離を出して足してみると、

5+(5+2.5)+(5+2.5*2)+(5+2.5*3)+(5+2.5*4)
=5+7.5+10+12.5+15
=50

で、計算があうね。上の例では分割数が整数で出たけど実際そんな事はあまり無くて、小数点以下の数が付くけどそれは切り上げてステップ数を決めてやれば少なくとも間があいてスカスカって事にはならないだだろうね。

続きはまた来週。

maxまとめページ



take_z_ultima at 11:30|この記事のURLComments(0)3ds Max | CG

2017年09月21日

自動リトポ ツールを調べてみた その10 modo11.0v3

前回に引き続き「Automatic Retopology(自動リトポ)」ツールと「リトポエッジ固定」と「リトポエッジフロー」について調べてみたい。

「リトポスケッチ」ツールを使っていて謎だったんだけど、「リトポエッジ固定」と「リトポエッジフロー」は何の役割をしてるかって事だ。前回やってみたのはマニュアルに書いてある手順を参考に曲線を描いてから、「リトポエッジ固定」を適用していた。

そこで「リトポスケッチ」ツールで「コンストレイントタイプ」を「位置」にしてから曲線を描いて、

fig01

そのまま「自動リトポ」ツールを適用した場合と「リトポエッジ固定」を適用してから適用した場合を比較してみた。下のGIFアニメがその結果。

fig02

メッシュ構造は微妙に違うけどどっちも同じような結果になっているような感じだ。

ただし、「リトポスケッチ」ツールで曲線を描いただけの場合、頂点マップとして生成されるのは「法線」マップだけだ。

fig03

それに対して選択エッジに「リトポエッジ固定」を適用すると、「エッジピック」マップ(エッジ選択セット)が生成される。

fig04

「法線」マップはガイドになる曲線に適用されるもので、ツールを適用するメッシュの法線にあわせた状態である必要があって、ツールはこれが無いと機能しないらしい。下の画像は曲線に適用された法線ベクトルを表示してみたものだ。この「法線」マップを生成するために「リトポスケッチ」ツールを使ってるわけだね。もし普通の曲線をガイドにしたい場合は手動でこの「法線」マップを生成する必要があるようだ。

fig05

今度は「リトポスケッチ」ツールで「コンストレイントタイプ」を「エッジフロー」にしてから曲線を描いて、そのまま「自動リトポ」ツールを適用してみた。下がその結果。

fig06

拡大してみるとわかるけど、メッシュの流れは曲線に沿ってるけど、頂点の位置は曲線に乗っていない。つまりこの曲線は「エッジフロー」として機能してるって事だ。この場合も頂点マップには「法線」マップしか生成されない。恐らくこの曲線に何らかの情報が付加されてるんだろうね。

fig07

つまりどうも「リトポスケッチ」ツールで指定すれば「リトポエッジ固定」と「リトポエッジフロー」は使わなくても機能しそうな感じだ。

この曲線をエッジ選択してこれに「リトポエッジ固定」を適用すると、下のように「RetopoEdgeLock」エッジピックマップが生成される。

fig09

ここで「自動リトポ」ツールを適用すると、下のように曲線状にメッシュの頂点が来るようになる。「リトポエッジ固定」がかかったようだ。

fig08

さらによく調べてみたら、「リトポスケッチ」ツールで曲線を描く時に曲線に付加される情報は「ポリゴン選択セット」の「RetopoFlow」と「RetopoEdgeLock」になっていた。つまり「エッジ選択セット」と「ポリゴン選択セット」のどっちかの「RetopoFlow」と「RetopoEdgeLock」を参照して、「自動リポ」ツールはメッシュの流れや頂点のロックをしてるって事だ。

そして「リトポスケッチ」ツールでは「ポリゴン選択セット」と「法線」マップを生成し、「リトポエッジ固定」と「リトポエッジフロー」は「エッジ選択セット」を生成するという事らしい。

それではまた次回。

続きはまた次回。

modo10-11ブログ目次



take_z_ultima at 11:30|この記事のURLComments(0)modo | CG

2017年09月20日

ビットマップペイントツールのチュートリアルをやってみた その84 3dsmax 2017

引き続きMAXScriptマニュアルに載っている「チュートリアル-ビットマップペイントツールを9つの簡単なステップで作成する」 の続きを考えて見たい。

フレーム間のパーティクルの動きを線形補間できるようになったけど、1フレーム間を5分割固定で分割しているだけだ。これではパーティクルの速度が上がればやがてペイントの跡も跳び跳びの点線になってしまうし、遅い時は過剰にペイントして時間を浪費する事になる。

そうならないためにはパーティクルの1フレームの移動量と1回にペイントするサイズからフレーム間の分割数を決めてやれば良さそうだ。

そこで以下のようにプログラムを変更してみた。1フレーム間の距離を計算して変数「d」に取得して、その距離をブラシサイズに「brushOverlaid」をかけたもので割って分割数を決めている。

fn lerp t1 t2 w = (
  q1 = t1 as quat
  q2 = t2 as quat
  p1 = t1.pos
  p2 = t2.pos
  q = slerp q1 q2 w
  p = ((p2-p1)*w+p1)
  tr = q as matrix3
  tr[4] = p
  return tr
)

pt = objectPaint()
pf = $PFソース002
pt.theObj =  $Sphere002
pt.maxFaceRadius = 4.0
pt.BrushShape = 1
pt.brushsize = 4
pt.BrushColor = red
pt.init()
pstart = 0
pstop = 32
particleTMs = #()
for i = pstart to pstop do (
  sliderTime = i
  count = pf.NumParticles()
  for j = 1 to count do (
    pf.particleIndex = j
    id = pf.particleID
    if particleTMs[id] == undefined then (
      particleTMs[id] = pf.particleTM
    ) else (
      --div = 5.0
      brushOverlaid = 0.2
      t1 = particleTMs[id]
      t2 = pf.particleTM
      d = distance t1.pos t2.pos
      div = d/(pt.brushsize * brushOverlaid)
      dcount = (div as integer) - 1
      if dcount < 0 then dcount = 0
      for j = 0 to dcount do (
        if div == 0.0 then w = 0.0 else w = j / div
        pt.brushtransform = lerp t1 t2 w
        pt.doPaint()
      )
      particleTMs[id] = pf.particleTM
    )
  )
  sf = "00" + (i as string)
  temp_bitmap_filename = (getDir #preview +"/test"+ substring sf (sf.count - 2) (sf.count)  +".tga")
  pt.theBitmap.filename = temp_bitmap_filename
  print pt.theBitmap.filename
  pt.saveimage()
)
pt.close()

ブラシをどのくらい重ねるかは「brushOverlaid」の値をどうとるかで決まるようにしていて、これによってブラシサイズの何割の距離ずらして重ねていくかが決まる。数値が小さいほどステップが細かくなる。

続きはまた次回。

maxまとめページ



take_z_ultima at 11:30|この記事のURLComments(0)3ds Max | CG

2017年09月19日

自動リトポ ツールを調べてみた その9 modo11.0v3

前回に引き続き「Automatic Retopology(自動リトポ)」ツールについて調べてみたい。

今回は「リトポエッジ固定」と「リトポエッジフロー」について調べてみたい。これらは曲線と法線マップを使ってメッシュのエッジラインの位置や流れを制御するための仕組みだ。

fig13

これらの機能を使う一番手っ取り早い方法は、「Model」パネルの「カーブ」サブタブの「リトポスケッチ」を使ってメッシュ表面にカーブを描く事だ。

fig01

その際ツールプロパティの「コンストレイントタイプ」で「位置」と「エッジフロー」が選択出来る。「位置」にすれば曲線は「リトポエッジ固定」として使われ、「エッジフロー」にすれば「リトポエッジフロー」に使われるようだ。

fig02

fig03

「精度」はラインセグメント長で数値を小さくするほどストロークに対して細かくポイントが打たれるようになる。

例えば下のような球体メッシュを用意して、

fig04

「リトポスケッチ」ツールをONにして「コンストレイントタイプ」を「位置」にして、この球体表面に下のような曲線を描く。

fig10

次にエッジ選択モードに切り替えてこのカーブを選択して、「メッシュ編集」サブタブの「リトポエッジ固定」ボタンを押す。

fig11

次に「自動リトポ」ツールを起動して、以下のパラメータで適用する。

fig05

これがその結果。わかりやすいように描いた曲線を強調してある。見ての通り曲線上にポイントが来るようにメッシュが生成されているのがわかる。

fig12

比較として曲線を描かないで処理した時のメッシュは以下のようになった。

fig06

同様に「リトポエッジフロー」も「リトポスケッチ」で「コンストレイントタイプ」を「エッジフロー」にして曲線を描いて、それをエッジ選択して「リトポエッジフロー」を押す。

fig14

次に「自動リトポ」ツールを起動して処理をすると下のようにエッジに沿った流れのポリゴンメッシュが生成される。

fig15

続きはまた次回。

modo10-11ブログ目次



take_z_ultima at 11:30|この記事のURLComments(0)modo | CG

2017年09月14日

ビットマップペイントツールのチュートリアルをやってみた その83 3dsmax 2017

引き続きMAXScriptマニュアルに載っている「チュートリアル-ビットマップペイントツールを9つの簡単なステップで作成する」 の続きを考えて見たい。

今回は前回作ったプログラムについてだ。下の太字になってるところが核になる部分だ。

fn lerp t1 t2 w = (
  q1 = t1 as quat
  q2 = t2 as quat
  p1 = t1.pos
  p2 = t2.pos
  q = slerp q1 q2 w
  p = ((p2-p1)*w+p1)
  tr = q as matrix3
  tr[4] = p
  return tr
)

pt = objectPaint()
pf = $PFソース002
pt.theObj =  $Sphere002
pt.maxFaceRadius = 4.0
pt.BrushShape = 1
pt.brushsize = 4
pt.BrushColor = red
pt.init()
pstart = 0
pstop = 32
particleTMs = #()
for i = pstart to pstop do (
  sliderTime = i
  count = pf.NumParticles()
  for j = 1 to count do (
    pf.particleIndex = j
    id = pf.particleID
    if particleTMs[id] == undefined then (
      particleTMs[id] = pf.particleTM
    ) else (
      div = 5.0
      t1 = particleTMs[id]
      t2 = pf.particleTM
      for j = 0 to 4 do (
        w = j / div
        pt.brushtransform = lerp t1 t2 w
        pt.doPaint()
      )
      particleTMs[id] = pf.particleTM
    )
  )
  sf = "00" + (i as string)
  temp_bitmap_filename = (getDir #preview +"/test"+ substring sf (sf.count - 2) (sf.count)  +".tga")
  pt.theBitmap.filename = temp_bitmap_filename
  pt.saveimage()
)
pt.close()

「particleTMs」の配列が1フレーム前のパーティクルの変換マトリクスを記録するためのものだ。

最初の「for」文と次の「sliderTime = i」で「pstart」フレームから「pstop」フレームまで1フレームずつタイムスライダを移動させて、その時のシーン中のパーティクルの数を「pf.NumParticles()」で取得して、次の「for」文とその次の行の「pf.particleIndex = j」で処理対象のパーティクルを切り替えて全てのパーティクルを巡回して処理をするようになっている。

現在処理対象のパーティクルの「particleIndex」プロパティはフレームごとに振られる単なる通し番号なので、同じパーティクルに同じ番号が振られるとは限らない。それに対して「particleID」は変わらないので、現在処理しようとしているパーティクルのIDを「id = pf.particleID」で取得して、そのIDをインデックスとして「particleTMs」の配列にアクセスして、直前のフレームで記録したそのパーティクルの変換マトリクスがあるか調べる。無ければ「undefined」なのでその時は現在のパーティクルの変換マトリクスをその配列に記録して次のパーティクルに処理を移す。配列に前フレームの変換マトリクスがあれば、それを変数「t1」に取得し、現在の変換マトリクスを「t2」に取得して、次の「for」文で「lerp」関数を使って「t1」から「t2」を1/5フレーム刻みで線形補間した変換マトリクスを生成して「brushtransform」プロパティにセットして「doPaint()」でペイントする。これで「t1」から「t2」の1/5フレーム前までの間をブラシストロークするペイントが出来る。最後に現在のパーティクルの変換マトリクスを「particleTMs」配列に記録して次のパーティクルに処理を送る。

この処理を全てのパーティクルについて行って、最後にファイル名を生成してビットマップをファイルに書き出して1フレームぶんの処理が終了する。

続きはまた次回。明日はお休みします。

maxまとめページ



take_z_ultima at 11:30|この記事のURLComments(0)3ds Max | CG
Archives