2018年10月11日

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

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

前回はプログラムを見直して座標値を整数で丸めるのを後回しにするように修正した。そこで今回はそこで得られた実数値の座標を使って「cap」データが示すエッジをエッジと垂直方向にはみ出し塗りをするようにプログラムを修正してみた。

fn paintFace vface mb2w = (
  corner_n = #()
  corner_y = #()
  center = [0,0,0]
  n = vface.count
  dlt1 = delty vface[n] vface[1]
  for i = 1 to n do
  (
    nexti = int(mod i n ) + 1
    dlt2 = delty vface[i] vface[nexti]
    chng = dlt1 * dlt2
    if chng <= 0 and (dlt1 !=0 or dlt2 !=0)then (
      append corner_n i
      append corner_y (int(vface[i].y))
    )
    dlt1 = dlt2
    center += vface[i]
  )
  center /= n
  append corner_n corner_n[1]  
  append corner_y corner_y[1]
      
  side = #()
  cap = #()
  for i = 1 to (corner_n.count-1) do (
    border = #()
    ptr = corner_n[i]
    s = 0
    do (
      append border vface[ptr]
      ptr = int(mod ptr n ) + 1
      s = s + 1
      if s > 100 then exit
    ) while (ptr != corner_n[i + 1])
    append border vface[ptr]
    if (corner_y[i] - corner_y[i+1]) == 0 then (
      append cap border
    ) else (    
      append side border
    )
  )
  if side.count>=2 then (
    if side[1][2][1] > side[2][2][1] then (
      tmps = side[1]
      side[1] = side[2]
      side[2] = tmps
    )
    s1 = s2 = 0  
    if side[1][1][2] > side[1][side[1].count][2] then (
      s1 = 2
      s2 = 1
    ) else (
      s1 = 1
      s2 = 2
    )
    side2ptr = side[s2].count
    for i = 1 to ( side[s1].count - 1) do
    (
      for iy = (int(side[s1][i][2])) to (int(side[s1][i+1][2])) do
      (
        while iy > (int(side[s2][side2ptr - 1][2])) do (
          side2ptr -= 1  
        )
        if side2ptr == 1 then side2ptr = 2
        ix1 = scanx side[s1][i] side[s1][i+1] iy
        ix2 = scanx side[s2][side2ptr] side[s2][side2ptr-1] iy
        drawline ix1 ix2 iy mb2w 
      )
    )

    for ed in cap do (
      for p = 1 to (ed.count - 1) do (
        if ed[p][3] == 1.0 then (
          if ed[p][1] < ed[p+1][1] then (
            x1 = ed[p][1]
            x2 = ed[p+1][1]
            y1 = ed[p][2]
            y2 = ed[p+1][2]
          ) else (
            x2 = ed[p][1]
            x1 = ed[p+1][1]
            y2 = ed[p][2]
            y1 = ed[p+1][2]
          )
          l = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1))
          nx =  - (y2-y1) / l * overpaint
          ny =  (x2-x1) / l * overpaint
          if ny < 0 then (
            nx = -nx
            ny = -ny
          )
          sy = 0
          if ed[1][2] < center[2] then (
            x4 = x1 - nx
            x3 = x2 - nx
            y4 = y1 - ny
            y3 = y2 - ny
          ) else (
            x4 = x1 + nx
            x3 = x2 + nx
            y4 = y1 + ny
            y3 = y2 + ny
          )
          arx = sort #(x1,x2,x3,x4)
          ary = sort #(y1,y2,y3,y4)
          
          det=(x2-x1)*y4+(-x4+x1)*y2+(x4-x2)*y1
          m11 = (y4-y1)/det
          m12 = -(y2-y1)/det
          m21 = -(x4-x1)/det
          m22 = (x2-x1)/det
          m31 = -(x1*y4-x4*y1)/det
          m32 = (x1*y2-x2*y1)/det
          
          for y = int(ary[1]) to int(ary[4]) do (
            for x = int(arx[1]) to int(arx[4]) do (
              tx = m11 * x + m21 * y + m31
              ty = m12 * x + m22 * y + m32
              if tx >=0 and tx <=1 and ty >=0 and ty <= 1 then (
                c = colOnEdge x y x1 y1 x2 y2 mb2w
                setPixels theBitmap  [x,y] #(c)
                --setPixels theBitmap  [x,y] #((color 255 0 0))
              )
            )
          )
          
        )
      )
    )
  )
),

これが実行結果。はみ出し部分がエッジに対して垂直に伸びるようになった。まだ「side」データについては処理していないのではみ出し塗りされているのは長さが短すぎて1ピクセルぶんも傾斜が無いために「cap」データになったエッジに対する塗りだけだ。

fig01

この画像をよく見てみたらまだおかしな塗りがあちこちあるのに気付いた。症状は今までのと同じようだからこれも「side」データに3つエッジグループが出来ちゃったりするパターンかな。なかなか綺麗にならないなぁ。

続きはまた次回。

maxまとめページ



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

この記事にコメントする

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

Archives