픽셀 필 레이트를 줄여보자.

전에 비트맵 알파정보로 메시정보 만들기를 시도 하였는데 ,  패스파인딩은 패턴이 너무 많고 진행형으로 검사하기때문에  패턴이 꼬이면 스네이크 게임처럼 꼬리를 무는 현상도 일어나고... 결론적으로 좋은 방법이 아니었다. 


첫번째 방법은 가끔 지브러쉬에서 비트맵 알파쉐입을 얻어올 때 쓰던 방식을 응용한 것인데, 아웃라인 크런치에 효과적일것 같아서 시험 해 보았다.

plane 오브젝트를 만든다. 

알파맵을 뽑을 텍스쳐를 매터리얼에 생성한다. 

비트맵 옵션을 alpha as gray 
알파 소스를 image alpha로 셋팅한다. 

plane segs를 넉넉하게 잡는다. (그리드로 쓸 것이므로 여유있게 잡는게 좋을것)

디스플레이스 모디파이어를 적용한다. 
strength는 적당히 높게 잡는다. 
map 항목에 위 매터리얼의 bitmap을 드래그앤드롭한다.

editable_poly등으로 적당히 컨버트 한다. 

이동하지 않은 버텍스를 삭제한다. 

튀어나온 버텍스의 y나 z축을  오브젝트 position의 y나 z축에 맞춘다.


editable_poly의 3번 항목 border로 외곽을 잡는다 . 

create shape 로 spline을 뽑는다. 

spline에 normalize spl 모디파이어를 건다. 

적당히 옵션조정으로 노멀라이즈한다. 

quadify mesh 모디파이어를 건다. 수치를 적당히 낮추면 안쪽에 쿼드 폴리가 생성 되는데
그 정도 옵션에서 pro optimizer 모디파이어를 적용시키고 
calculate 후 적당히 외곽이 알파를 침범하지 않는 선에서 정리한다.

원본 오브젝트에 uvwmap을 건다.

copy후 생성한 오브젝트에 복사한다. (gizmo정보를 복붙하면 그대로 uv를 써먹을 수 있다.)

뭐 대충 이정도..



스크립트로 적어 놓으면 이렇다.

fn crunchFromBitmapAlpha obj density:30 segs:100 =
(
if classof obj != plane then return 0
maxops.clonenodes obj newnodes:&copiedobj
local target = copiedobj[1]
local tm = target.transform
local rm = matrix3 tm.row1 tm.row2 tm.row3 [0,0,0]
target.transform = inverse rm
target.lengthsegs = segs
target.widthsegs = segs
max modify mode
addmodifier target (displace())
target.displace.map = bitmaptexture bitmap:(target.material.diffusemap.bitmap) rgboutput:1
target.displace.strength = 50
converttopoly target
local zerovertlist = #()
for i=1 to target.verts.count do
(
local p = target.verts[i].pos
p-=target.pos
p*= inverse rm
if (integer)p.z == 0 then 
append zerovertlist i
)
select target
subobjectlevel = 1
target.editablepoly.setselection #vertex (zerovertlist as bitarray)
target.EditablePoly.ShrinkSelection ()

target.editablepoly.delete #vertex
subobjectlevel =5
target.editablepoly.setselection #face ((for i = 1 to target.faces.count collect i) as bitarray)
for i = 1 to target.verts.count do
(
local p = target.verts[i].pos *inverse rm
p.z = 0
target.verts[i].pos = p*rm
)
target.transform =tm
subobjectlevel = 2
target.editablepoly.setselection #edge ((polyop.getopenedges target) as bitarray)

local sn = uniquename (target.name+"Shape")
target.EditablePoly.createShape sn on target
local _shape = getnodebyname sn
delete target
local sl = getseglengths _shape 1
addmodifier _shape (Normalize_Spl ())
_shape.normalize_spl.length = (sl[sl.count])/density
local qm = Quadify_Mesh()
qm.quadsize = 1.9
addmodifier _shape (qm)
select _shape
max modify mode
addmodifier _shape (prooptimizer())

completeredraw()
_shape.prooptimizer.vertexpercent = 3
_shape.prooptimizer.calculate = true
addmodifier _shape (uvwmap())
local bb1 = nodegetboundingbox obj (inverse obj.transform)
local bb2 = nodeGetBoundingBox _shape (inverse obj.transform)
local scl = (bb1[1]-bb1[2])/(bb2[1]-bb2[2])
_shape.uvwmap.gizmo.pos = [0,0,0]
_shape.uvwmap.gizmo.scale = scl
return _shape
)

스크립트영역과 조작영역에서 약간의 차이가 있으므로 내용 역시 약간 다르다.


스플라인을 추출하는 경우는 스플라인을 다른 용도로 사용 할 일이 있을 경우를 위해 만들어 둔것이다.

순수 메시 정보만 얻기 위한 것이라면 , 스플라인추출과 노멀라이즈 스플라인, 쿼디파이 메시를 생략하고 바로 옵티마이저로 건너 뛰어도 좋다. 

옵티마이저 이후에 쿼디파이 메시를 하면 비교적 고른 분포의  폴리곤을 가진 메시를 얻어 낼 수 있다.



그리고 방금 떠오른 두번째 방법이 있다. 

버텍스의 텍스쳐 쿠디네이트를 활용해서 해당 버텍스가 알파인지 아닌지 판별 하는 것이다. 

fn checkcoords m tex tvindex w h = 
(
local tv  = gettvert m tvindex
local coords = [tv.x,1.0-tv.y]*[w,h]
coords.x =ceil coords.x
coords.y = ceil coords.y
local c = (getpixels tex coords 1)[1]
if c==undefined then return true
if c.alpha  > 0 then return false
return true
)
fn crunchfromBitmapAlpha2 obj = 
(
local m = snapshotasmesh obj
local tex = obj.material.diffusemap.bitmap
local w = tex.width
local h = tex.height
maxops.clonenodes obj newnodes:&copiedobj
local t = copiedobj[1]
converttopoly t
local verts = #()
for i = 1 to m.mesh.faces.count do
(
local fi = gettvface m i
local fi2 = getface m i
if checkcoords m tex fi.x w h then
appendifunique verts fi2.x
if checkcoords m tex fi.y w h then
appendifunique verts fi2.y
if checkcoords m tex fi.z w h then
appendifunique verts fi2.z
)
select t
subobjectlevel = 1
t.editablepoly.setselection #vertex (verts as bitarray)
)

스크립트는 버텍스를 찾아내는것 까지지만 이후, 쿼디파이 + 옵티마이즈는 동일하다.

그리드를 나눌때는 어짜피 화끈하게 나눠야 하므로 동일한 샘플을 만들거라면, 이방법이 더 좋은 답일 수도 있다. 


하지만 getpixels는 느려서 몇십만 버텍스로 나눈 데이터에 쓰긴 안좋다.




다시 디스플레이스를 써보는데 판별 작업을 달리 하였다.

소스 메시 디스플레이스드메시 두개를 비교해서 일정 거리 이상을 걸러내면...


fn crunchfromBitmapAlpha obj expand:0  optimizerate:1.5 =
 (
  
  if superclassof obj  != geometryclass then return 0
  
  max modify mode
  local tex = obj.material.diffusemap.bitmap
  local w = tex.width
  local h = tex.height
  stacks = for i = 1 to h collect #()
  
  maxops.clonenodes obj newnodes:&copiedobj
  local t = copiedobj[1]
  local num = getnumverts obj.mesh

  
  converttopoly t
  
  local s = snapshotasmesh t
  local cm = compositetexturemap()
  cm.maplist[1] = colorcorrection color:white
  cm.maplist[2] = bitmaptexture bitmap:tex rgboutput:1 alphasource:1
  cm.blendmode[2]=3
  
  
  local d = displace()
  
  d.map = cm
  d.strength = 50
  d.usemap = on
  addmodifier t d
  
  local m = snapshotasmesh t
  deletemodifier t d
  local verts = #()
  for i = 1 to m.verts.count do
  (
   local tv = getvert s i
   local sv = getvert m i
   if (distance tv sv) > 49.5 then append verts i
  )
  select t
  subobjectlevel = 1
  
  t.editablepoly.setselection #vertex (verts as bitarray)
  for i = 1 to expand do
  (
   t.EditablePoly.ShrinkSelection ()
  )
  t.editablepoly.delete #vertex
 
  addmodifier t (prooptimizer())

  t.prooptimizer.vertexpercent = optimizerate
  t.prooptimizer.Optimizationmode = 1
  t.prooptimizer.keepuv = true 
  t.prooptimizer.calculate = true
 )

속도 상승이 있었다.



이 방식의 장점은 모디파이드된 오브젝트에 적용 할 수 있다는 점이 되겠다. 예들들면 맵에 배치할 풀이나 나뭇잎등에도 쓸 수 있겠다.


앞으로 해결 해야 할 문제는 grid per inch 등으로 폴리곤 나누기 같은거..



덧글

댓글 입력 영역



메모장

Junhyuck Park
(PN/pakdragon,pakk)
MALE E-mail:pakdragon57@gmail.com