2008年05月18日

UVマップを使ってメッシュを貼り付ける その2 modo 302

さて、前回のムービーでもちょっと紹介したけど、加工前のデータは下のように貼り付けるメッシュと貼り付けられるメッシュを用意して、それらのUVマップを下の画像の左側ののように重ねる。

fig02

fig01上の画像の右側の下に並べてあるメッシュを左側のUVマップに従って対象となる物体に貼り付けるわけだ。



前回はこのプログラムの大まかなアルゴリズムと、中で使うUVマップ上のポイントがポリゴンの中にあるかどうかの判定プログラムを紹介した。そのファンクションを使って変形して張り付けるメッシュのポイント一つ一つが貼り付けられる側のメッシュのどのポリゴン上にあるかを判定して、見つけたポリゴンを元に、3D上の位置を割り出していくわけだ。

今回は指定したポイントを含む発見されたポリゴンから、3D上の位置を特定する方法についてまとめてみるよ。前提として、前回紹介したファンクションによってポイントを含むポリゴンの三角頂点のインデックス番号と判定に使った媒介変数t0,t1が得られていることにする。

下の図はその三角形の3D上の方を表わしたものだ。

fig04

見つける時はUV上の三角形だったけど、こっちはそれに対応した3D上の方ね。この形はUV上のポリゴンと同じとは限らない。v0〜v2までの頂点のインデックス番号がわかっているので、クエリを使って3つのポイントの3次元座標とその法線ベクトルn0〜n2が求められる。

  • 座標:query layerservice vert.pos ? インデックス番号
  • 法線:query layerservice vert.normal ? インデックス番号

ここから求めたいのはpとnpで、そのためにはまずp’を求める。

点p’は直線v1−v2上にあって、その区間をt1:(1−t1)に内分する点なので、p’とnp’はそれぞれベクトルであわわすと、

  • p’=(1−t1)・v1+t1・v2
  • np’=(1−t1)・n1+t1・n2

になる。t1と(1−t1)を足すと1になるから式は簡単だね。2ベクトルの比例合成の式だ。こんな奴。

fig03

実際にはxyzの成分に分解してそれぞれ掛け算をすることになるよ。その辺はプログラムを見てね。

これで求められたp’とnp’から今度はpとnpを求める。t1はv1とv2の間の点p’を示していたけど、t0はv0−pからp’を示すようになっているので、上図のように、pはv0−p’間を1:(t0−1)で内分する点になる。今度は1とt0−1を足すとt0になるからベクトルの比例合成の式にするためには全体をt0で割って合計を1にしてやらないとダメだな。

  • p=((t0−1)・v0+p’)/t0
  • np=((t0−1)・n0+np’)/t0

これでポイント1つをUVマップ経由で投影するメッシュの表面上の位置までもって来られたわけだ。後は、その貼り付ける面から、実際のポイントがどれだけ浮いているかを指定してやらなくちゃならない。そこで使うのが法線ベクトルnpだ。法線だけに面に対して垂直なので、このベクトルに沿って点pから距離を取って行けば目的のポイントに辿り着く。とりあえずオリジナルのポイントのy座標をそのまま入れるとすると、

  • pos=p+y・np

でOKだ。プログラムはこんな感じ。変数paramにはt0,t1,v0,v1,v2の順にデータが入っている。

#param(t0,t1,v0,v1,v2)
def calcPoint(param,y):
    if param[0]==0:
        pos=lx.eval("query layerservice vert.pos ? %s" % param[2])
        nml=lx.eval("query layerservice vert.normal ? %s" % param[2])
    else:
        pos0=lx.eval("query layerservice vert.pos ? %s" % param[2])
        nml0=lx.eval("query layerservice vert.normal ? %s" % param[2])
        pos1=lx.eval("query layerservice vert.pos ? %s" % param[3])
        nml1=lx.eval("query layerservice vert.normal ? %s" % param[3])
        pos2=lx.eval("query layerservice vert.pos ? %s" % param[4])
        nml2=lx.eval("query layerservice vert.normal ? %s" % param[4])
        t0=param[0]
        t1=param[1]
        pos3=[(1-t1)*pos1[0]+t1*pos2[0],
                   (1-t1)*pos1[1]+t1*pos2[1],
                  (1-t1)*pos1[2]+t1*pos2[2]]
        nml3=[(1-t1)*nml1[0]+t1*nml2[0],
                   (1-t1)*nml1[1]+t1*nml2[1],
                   (1-t1)*nml1[2]+t1*nml2[2]]
        pos=[((t0-1)*pos0[0]+pos3[0])/t0,
                 ((t0-1)*pos0[1]+pos3[1])/t0,
                 ((t0-1)*pos0[2]+pos3[2])/t0]
        nml=[((t0-1)*nml0[0]+nml3[0])/t0,
                 ((t0-1)*nml0[1]+nml3[1])/t0,
                 ((t0-1)*nml0[2]+nml3[2])/t0]
        pos=[pos[0]+nml[0]*y,pos[1]+nml[1]*y,pos[2]+nml[2]*y]
    return pos

やっていることは、あくまで曲面上の点に近い点を比例配分で求めているだけなので、正確に曲面を捕らえる事は出来ない。だから貼り付けられる側のメッシュを複製し、それを細分化することで近似の精度を上げるわけだ。それからベクトルの合成の式を単純に使うと法線ベクトルの長さが短くなっちゃうから長さが1になるように正規化しないとダメだな。ポリゴンが充分に細分化されていれば誤差は大したこと無いと思うけどやっぱり入れておいた方がいいかな?上のプログラムはには入っていない。

それではまた次回。

スクリプトまとめページ( Down Load はこちらから)  

カテゴリー別ページ



take_z_ultima at 12:35│Comments(0)TrackBack(0)modo | CG

トラックバックURL

この記事にコメントする

名前:
URL:
  情報を記憶: 評価: 顔   
 
 
 

Archives