2019年05月09日

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

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

とりあえずUVマップの輪郭を膨らませた形状の頂点座標値を「offpoint」配列に格納する「get_offpoints()」ファンクションを「objectPaint」構造体に組み込んでみた。

fn crosspoint2D p1 p2 p3 p4 = (
  a = p2.y - p1.y
  b = p1.x - p2.x
  c = p4.y - p3.y
  d = p3.x - p4.x
  e = p1.x * p2.y - p2.x * p1.y
  f =  p3.x * p4.y - p4.x * p3.y
  g = a*d - b*c
  if g^2 < 0.0000001 then return p2
  x = (d * e - b * f) / g
  y = (-c * e + a * f) / g

  return [x,y,0]
),

fn is_unce v1 v2 obj tch useEdges = (
  faces1 = meshop.getMapFacesUsingMapVert obj tch #{v1}
  faces2 = meshop.getMapFacesUsingMapVert obj tch #{v2}
  if (faces1 * faces2).numberSet == 1 then (
    if useEdges[v1]==undefined  then (useEdges[v1] = #(v2)) else (append useEdges[v1] v2)
    if useEdges[v2]==undefined  then (useEdges[v2] = #(v1)) else (append useEdges[v2] v1)
    return true
  )
  return false
),

fn get_offpoints = (
  useEdges = #()
  theObj = $
  islands = #()

  muw = theObj.modifiers[#unwrap_uvw]
  muw.setTVSubObjectMode 3
  n = muw.numberPolygons()
  allpolys = #{1..n}
  do (
  sseed = (allpolys as array)[1]
  muw.selectFaces #{sseed}
  a = muw.getSelectedFaces()
  do (
    b = a
    muw.expandSelection() 
    a = muw.getSelectedFaces()
  ) while not (a-b).isempty
  append islands (a as array)
  allpolys -= a
  ) while not allpolys.isempty
  muw.selectFaces #{}

  theMesh = snapshotAsMesh theObj
  theChannel = 1
  edges = #{}
  --t2v = #()
  for island in islands do (
    for faceIndex in island do(
      texFace = (meshop.getMapFace theMesh theChannel faceIndex)
      
      --for i = 1 to 3 do t2v[texFace[i]] = (muw.getVertexIndexFromFace faceIndex i)
      
      if is_unce texFace[1] texFace[2] $ theChannel useEdges then (
        edges += #{texFace[1],texFace[2]}
      )
      if is_unce texFace[2] texFace[3] $ theChannel useEdges then (
        edges += #{texFace[2],texFace[3]}
      )
      if is_unce texFace[3] texFace[1] $ theChannel useEdges then (
        edges += #{texFace[3],texFace[1]}
      )
    )
  )
  loopEdges = #()
  edgeVerts = edges as array
  for i = 1 to edgeVerts.count do (
    v1 = edgeVerts[i]
    if edges[v1] then (
      loopEdge = #(v1)
      edges[v1] = false
      nfind = true
      do (
        v2 = useEdges[v1][1]
        if edges[v2] then (
          append loopEdge v2
          edges[v2] = false
        ) else (
          v2 = useEdges[v1][2]
          if edges[v2] then (
            append loopEdge v2
            edges[v2] = false
          ) else (nfind = false)
        )
        v1 = v2
      ) while nfind 
      append loopEdges loopEdge
    )
  )

  for loopEdge in loopEdges do (
    tmp = #(#())
    av = [0,0,0]
    zv = bv = meshop.getMapVert theobj theChannel loopEdge[1] - meshop.getMapVert theobj theChannel loopEdge[loopEdge.count]
    for i=1 to (loopEdge.count-1) do (
      v = meshop.getMapVert theobj theChannel loopEdge[i+1] - meshop.getMapVert theobj theChannel loopEdge[i]
      av += cross v bv
      bv = v
    )
    av += cross zv bv
    if av[3] >= 0 then mR = (rotateYPRMatrix 0 0 90) else mR = (rotateYPRMatrix 0 0 -90)
    for i = 1 to (loopEdge.count-1) do (
      v1 = meshop.getMapVert theobj theChannel loopEdge[i]
      v2 = meshop.getMapVert theobj theChannel loopEdge[i+1]
      nvec = normalize ((v2 - v1) * mR) *overpaint
      append tmp #(v1+nvec , v2+nvec)
    )
    v1 = meshop.getMapVert theobj theChannel loopEdge[loopEdge.count]
    v2 = meshop.getMapVert theobj theChannel loopEdge[1]
    nvec = normalize ((v2 - v1) * mR) *overpaint
    append tmp #(v1+nvec , v2+nvec)
    tmp[1] = #(v1+nvec , v2+nvec)
    for i = 1 to (tmp.count-1) do (
      offpoint[loopEdge[i]] = (crosspoint2D tmp[i][1] tmp[i][2] tmp[i+1][1] tmp[i+1][2])
    )
  )
 ),

UVマップのはみ出し量「overpaint」、「UVWアンラップ」モディファイヤを保管する変数「muw」、オフセットした頂点の座標値の配列「offpoint」を「objectPaint」のメンバに移した。

struct objectPaint (
  public
    maxFaceRadius = 40.0,
    brushsize=10,
    BrushShape = 2,
    BrushColor = black,
    theObj,
    brushtransform,
    bitmapX = 512,
    bitmapY = 512,
    temp_bitmap_filename = (getDir #preview +"/microPaint_temp2.tga"),
    theBitmap,
    checkBitmap,
    overpaint = 0.03,

  private
    sanim = undefined,
    tmpm = undefined,
    maps = undefined,
    muw=undefined,
    cmuw=false,
    offpoint = #(),
  
    flg = false,
    flg2 = false,
    fn chckClip p1 p2 w2b direction =

また、「objectPaint」の初期化「init()」と終了処理「close()」にUVWモディファイヤの追加削除処理などを移した。また、ここで「get_offpoints()」を呼び出して、UVマップの輪郭データを生成した。

public
  fn init = (
    theBitmap = bitmap bitmapX bitmapY color:white filename:temp_bitmap_filename
    if theObj.material == undefined do theObj.material = Standard()
    if theObj.material.diffusemap == undefined do
      theObj.material.diffusemap = bitmapTexture filename:temp_bitmap_filename
    showTextureMap theObj.material true
    
    --select theObj
    if theObj.modifiers[#Vol__Select] == undefined do (
      addModifier theObj (volumeselect())
    )
    if (classof theObj) != Editable_mesh do (
      addModifier theObj  (Turn_to_Mesh ())
    )
    vmod = theObj.modifiers[#Vol__Select]
    vmod.level = 2
    vmod.type = 1
    vmod.volume = 3
    --sanim = vmod.gizmo
    sanim = box()
    vmod.node = sanim
    mt2b=(matrix3 [bitmapX,0,0] [0,-bitmapY,0] [0,bitmapY,1] [0,0,0])
    

    if theObj.modifiers[#Unwrap_UVW] == undefined then (
      addModifier theObj (Unwrap_UVW ())
      muw = theObj.modifiers[#Unwrap_UVW]
      modPanel.setCurrentObject theObj.modifiers[#Unwrap_UVW]
    )
    else  modPanel.setCurrentObject theObj.modifiers[#Vol__Select]
    get_offpoints()
  ),

fn close = (
  if cmuw then (
    deleteModifier theObj muw
  )
  delete sanim
  delmodifier theObj Vol__Select
  delmodifier theObj Turn_to_Mesh
)

これで「offpoint」配列にアクセスすれば、いつでも輪郭を膨らましたUVマップにアクセス出来るはず・・・。

「offpoint」は膨らませて移動させた輪郭頂点のデータが、移動前の頂点と同じ配列の位置に記録されていて、輪郭以外の頂点は記録していないので、その頂点が輪郭かどうかはその頂点番号の「offpoint」を調べて座標値が入っているかどうかで判定できる。

続きはまた次回。

maxまとめページ



take_z_ultima at 11:30│Comments(0)3ds Max | CG

この記事にコメントする

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

Archives