2017年06月23日

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

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

今回は前回作ったプログラムの解説から。

以下がプログラムのメインの部分だ。

(
	local theObj =  $GeoSphere001
	
	local bitmapX = bitmapY = 512
	local temp_bitmap_filename = (getDir #preview +"/microPaint_temp2.tga")
	local theCanvasBitmap = 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
	
	local seedface=19
	local theMesh = snapshotAsMesh theObj
	local theChannel = 1
	local brushtransform = $Box001.transform
	local brushsize=10
	maps = #()
	crossFaceMaps &maps theMesh seedface theChannel brushtransform brushsize
	for map in maps do (
		vface = #()
		for p in map do (
			append vface [p.x * bitmapx, bitmapy - p.y * bitmapy]
		)
		paintFace vface theCanvasBitmap
	)
  save theCanvasBitmap
  theObj.material.diffusemap.bitmap = theCanvasBitmap
)

まず冒頭で512X512ピクセルのビットマップを作って変数「theCanvasBitmap」にセットする。

	local theObj =  $GeoSphere001
	
	local bitmapX = bitmapY = 512
	local temp_bitmap_filename = (getDir #preview +"/microPaint_temp2.tga")
	local theCanvasBitmap = bitmap bitmapX bitmapY color:white filename:temp_bitmap_filename

オブジェクトにマテリアルが設定されていなければ、「標準(Standard)」マテリアルを設定する。その「標準」マテリアルの「ディフューズマップ」が未定義なら「ビットマップテクスチャ」を割り当てる。そしてこのマテリアルを表示する。

  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

次にヒットポイントの面番号を19番にして、メッシュをブラシでトリミングして出来た多角形の面をUV座標系に変換したものを変数「maps」に取得する。

	local seedface=19
	local theMesh = snapshotAsMesh theObj
	local theChannel = 1
	local brushtransform = $Box001.transform
	local brushsize=10
	maps = #()
	crossFaceMaps &maps theMesh seedface theChannel brushtransform brushsize

「maps」から面の頂点リストを1つずつ「map」に取り出して、それをビットマップ座標系に変換して、「vface」配列に格納し、「paintFace」に渡して「theCanvasBitmap」に輪郭を描く。

	for map in maps do (
		vface = #()
		for p in map do (
			append vface [p.x * bitmapx, bitmapy - p.y * bitmapy]
		)
		paintFace vface theCanvasBitmap
	)

描き終わったらビットマップをファイルに書き出して、それをマテリアルに再設定する事でビューポートの表示を更新させる。

  save theCanvasBitmap
  theObj.material.diffusemap.bitmap = theCanvasBitmap

輪郭を描く「paintFace()」は面の頂点リストから頂点を順に2つずつ取り出して、その2点間を結ぶ線を「drawStroke」でビットマップに描画している。

fn drawStroke lastPos pos theCanvasBitmap =
(
    currentPos = lastPos
    deltaX = pos.x - lastPos.x
    deltaY = pos.y - lastPos.y
    maxSteps = amax #(abs(deltaX),abs(deltaY))
    deltaStepX = deltaX / maxSteps
    deltaStepY = deltaY / maxSteps
    for i = 0 to maxSteps do
    (
		setPixels theCanvasBitmap  currentPos #(black)
		currentPos += [deltaStepX, deltaStepY]
    )
)

fn paintFace vface theCanvasBitmap = (
	for i= 1 to (vface.count-1) do
		drawStroke vface[i] vface[i+1] theCanvasBitmap
	drawStroke vface[1] vface[vface.count] theCanvasBitmap

)

続きはまた来週。

maxまとめページ



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

2017年06月22日

modo11.0v3のスクリプトについて調べてみた その97

引き続き「TD SDK」の「Vector3」クラスについて調べてみたい。

「normalize()」は「Vector3」の方向はそのままで長さを1にスケーリングする。下がそのプログラムで、生成した値を「self.values」にセットすることで、このメソッドは自分自身の値を書き換えている事がわかる。

 def normalize(self):
     """Normalizes this vector in place"""
     self.values = list(vector.normalize(self.values))

それに対して「normal()」メソッドはノーマライズした「Vector3」値を新たに生成するメソッドだ。

 def normal(self):
     """Returns a normalized copy of this vector"""
     return Vector3(vector.normalize(self.values))

どちらのメソッドも内部で「vector.normalize()」が呼び出されていて、下がそのプログラムだ。ベクトルの長さでベクトルの各要素を割った値をリストにして返している。

 def normalize(v):
     """result = a / length(a)"""
     len = length(v)
     if len:
         return [ x / len for x in v ]
     else:
         return v

ベクトルの方向を変えずに長さを1に出来るなら、ベクトルの方向を変えずに指定の長さにする事も出来るわけで、それをしてくれるのが「setLength()」だ。下がそのプログラム。

    def setLength(self, value):
        """Sets the length of this vector"""
        tmp = Vector3(self.values)
        tmp.normalize()
        tmp *= value
        self.values = tmp.values

同じ値で新たに「Vector3」を生成して、「normalize()」で長さを1に変換してから各要素に「value」をかけて長さを「value」にスケーリングし、その値を「self.values」にセットしている。「tmp.values」は新たに生成された「list」オブジェクトが参照されていて、それを「self.values」に引渡しているから「tmp」が無くなってもリストは残るだろうからこれでいいんだろうけど、複製して渡すなら「[:]」を付ける事になるね。

    def setLength(self, value):
        """Sets the length of this vector"""
        tmp = Vector3(self.values)
        tmp.normalize()
        tmp *= value
        self.values = tmp.values[:]

続きはまた次回。

modo10-11ブログ目次



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

2017年06月21日

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

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

前回のプログラムにプログラムを追加してオブジェクトにブラシの輪郭を描画するようにしてみた。下がそのプログラム。

threshold = 0.00000001

fn chckEdge p1 p2 size trm=
(
	cplist = #()
	tlist = #()
	hsize = size / 2.0
	w2b = inverse(trm)--w2BrushLocalMatrix
	bp1 = p1 * w2b
	bp2 = p2 * w2b
	dx = bp2.x - bp1.x
	dy = bp2.y - bp1.y
	dz = bp2.z - bp1.z
	-- +- X face
	if abs(dx)>threshold then (
		t = (hsize - bp1.x)/dx
		x = dx * t + bp1.x
		y = dy * t + bp1.y
		z = dz * t + bp1.z
		if (abs(y)<=hsize) and (abs(z)<=hsize) then (
			append cplist [x,y,z]
			append tlist t
		)
		t = (-hsize - bp1.x)/dx
		x = dx * t + bp1.x
		y = dy * t + bp1.y
		z = dz * t + bp1.z
		if (abs(y)<=hsize) and (abs(z)<=hsize) and ((findItem tlist t)==0) then (
			append cplist [x,y,z]
			append tlist t
		)
	)
	-- +- Y face
	if abs(dy)>threshold then (
		t = (hsize - bp1.y)/dy
		x = dx * t + bp1.x
		y = dy * t + bp1.y
		z = dz * t + bp1.z
		if (abs(x)<=hsize) and (abs(z)<=hsize) and ((findItem tlist t)==0) then (
			append cplist [x,y,z]
			append tlist t
		)
		t = (-hsize - bp1.y)/dy
		x = dx * t + bp1.x
		y = dy * t + bp1.y
		z = dz * t + bp1.z
		if (abs(x)<=hsize) and (abs(z)<=hsize) and ((findItem tlist t)==0) then (
			append cplist [x,y,z]
			append tlist t
		)
	)
	-- +- Z face
	if abs(dz)>threshold then (
		t = (hsize - bp1.z)/dz
		x = dx * t + bp1.x
		y = dy * t + bp1.y
		z = dz * t + bp1.z
		if (abs(x)<=hsize) and (abs(y)<=hsize) and ((findItem tlist t)==0) then (
			append cplist [x,y,z]
			append tlist t
		)
		t = (-hsize - bp1.z)/dz
		x = dx * t + bp1.x
		y = dy * t + bp1.y
		z = dz * t + bp1.z
		if (abs(x)<=hsize) and (abs(y)<=hsize) and ((findItem tlist t)==0) then (
			append cplist [x,y,z]
			append tlist t
		)
	)
	if tlist.count !=2 then return false
	if tlist[1]>1.0 and tlist[2]>1.0 or tlist[1]<0.0 and tlist[2]<0.0 then return false
	return true
)

fn neighborface verts theMesh = (
	faceSel = #{}
	faces=meshop.getFacesUsingVert theMesh verts
	for faceIndex in faces do (
		vlist =  meshop.getVertsUsingFace theMesh #{faceIndex}
		if (((vlist*verts) as array).count == 2) then append faceSel faceIndex
	)
	return faceSel
)

fn searchFace theMesh seed  brushsize  brushtransform  &doneface cuefaces= (
	sufFace = getFace theMesh seed
	p0 = (getVert theMesh sufFace.x)
	p1 = (getVert theMesh sufFace.y)
	p2 = (getVert theMesh sufFace.z)
	
	if chckEdge p0 p1 brushsize brushtransform then (
		face = neighborface #{sufFace.x,sufFace.y} theMesh - doneface
		if (face as array).count ==1 then (
			doneface += face
			append cuefaces (face as array)[1]
		)
	)
	if chckEdge p1 p2 brushsize brushtransform then (
		face = neighborface #{sufFace.y,sufFace.z} theMesh - doneface
		if (face as array).count ==1 then (
			doneface += face
			append cuefaces (face as array)[1]
		)
	)
	if chckEdge p2 p0 brushsize brushtransform then (
		face = neighborface #{sufFace.z,sufFace.x} theMesh - doneface
		if (face as array).count ==1 then (
			doneface += face
			append cuefaces (face as array)[1]
		)
	)
)

fn queloop theMesh seed  brushsize  brushtransform = (
	local doneface = #{seed}
	local cuefaces = #(seed)
	numfaces = getNumFaces theMesh
	i = 0
	do (
		face = cuefaces[1]
		deleteItem cuefaces 1
		searchFace theMesh face  brushsize  brushtransform &doneface cuefaces
		i=i+1
	) while cuefaces.count != 0 and i <= numfaces 
	return doneface
)

fn chckClip p1 p2 size w2b direction =
(
	cplist = #()
	tlist = #()
	hsize = size / 2.0
	bp1 = p1 * w2b
	bp2 = p2 * w2b

	st = 0
	t = 0.0
	case direction of (
		-- +x
		0:	(
				if bp1.x >= hsize then st = 1
				if bp2.x >= hsize then st = st + 2
				if st == 1 or st ==2 then (
					dx = bp2.x - bp1.x
					t = (hsize - bp1.x)/dx
				)
			)
		-- -x
		1:	(
				if bp1.x <= -hsize then st = 1
				if bp2.x <= -hsize then st = st + 2
				if st == 1 or st ==2 then (
					dx = bp2.x - bp1.x
					t = (-hsize - bp1.x)/dx
				)
			)
		-- +y
		2:	(
				if bp1.y >= hsize then st = 1
				if bp2.y >= hsize then st = st + 2
				if st == 1 or st ==2 then ( 
					dy = bp2.y - bp1.y
					t = (hsize - bp1.y)/dy
				)
			)
		-- -y
		3:	(
				if bp1.y <= -hsize then st = 1
				if bp2.y <= -hsize then st = st + 2
				if st == 1 or st ==2 then (
					dy = bp2.y - bp1.y
					t = (-hsize - bp1.y)/dy
				)
			)
		-- +z
		4:	(
				if bp1.z >= hsize then st = 1
				if bp2.z >= hsize then st = st + 2
				if st == 1 or st ==2 then (
					dz = bp2.z - bp1.z
					t = (hsize - bp1.z)/dz
				)
			)
		-- -z
		5:	(
				if bp1.z <= -hsize then st = 1
				if bp2.z <= -hsize then st = st + 2
				if st == 1 or st ==2 then (
					dz = bp2.z - bp1.z
					t = (-hsize - bp1.z)/dz
				)
			)
	)
	return #(st,t)	
)

fn innerpoint p1 p2 t = (
	dx = p2.x - p1.x
	dy = p2.y - p1.y
	dz = p2.z - p1.z
	x = dx * t + p1.x
	y = dy * t + p1.y
	z = dz * t + p1.z
	return [x,y,z]
)

fn clipface &vlist brushsize  brushtransform = ( 
	for i = 0 to 5 do (
		tmp = #()
		for j = 1 to (vlist.count - 1) do (
			st = chckClip vlist[j] vlist[j+1] brushsize  brushtransform i
			if st[1] == 0 then (
				append tmp vlist[j] 
			) else if st[1] == 2 then (
				append tmp vlist[j] 
				append tmp (innerpoint vlist[j] vlist[j+1] st[2])
			) else if st[1] == 1 then (
				append tmp (innerpoint vlist[j] vlist[j+1] st[2])
			)
		)
		st = chckClip vlist[vlist.count] vlist[1] brushsize  brushtransform i
		if st[1] == 0 then (
				append tmp vlist[vlist.count] 
		) else if st[1] == 2 then (
			append tmp vlist[vlist.count]
			append tmp (innerpoint vlist[vlist.count] vlist[1] st[2])
		) else if st[1] == 1 then (
			append tmp (innerpoint vlist[vlist.count] vlist[1] st[2])
		)
		vlist = tmp
	)
)

fn crossFaceMaps &maps theMesh seedface theChannel brushtransform brushsize =
(
	invBrushTransform = inverse( brushtransform)
	crossfaces = queloop theMesh seedface  brushsize  brushtransform
	for faceIndex in crossfaces do (
		vlist = #()
		sufFace = getFace theMesh  faceIndex
		append vlist (getVert theMesh sufFace.x)
		append vlist (getVert theMesh sufFace.y)
		append vlist (getVert theMesh sufFace.z)
		
		texFace = meshop.getMapFace theMesh theChannel faceIndex
		tv1= meshop.getMapVert theMesh theChannel texFace.x
		tv2= meshop.getMapVert theMesh theChannel texFace.y
		tv3= meshop.getMapVert theMesh theChannel texFace.z
		mg2t=(matrix3 [tv1.x,tv1.y,0] [tv2.x,tv2.y,0] [tv3.x,tv3.y,0] [0,0,0])
		clipface &vlist  brushsize invBrushTransform
		
		maplist =  #()
		for v in vlist do (
			mp = (meshop.getBaryCoords theMesh faceIndex v) * mg2t
			append maplist mp
		)
		append maps maplist
	)
)

fn drawStroke lastPos pos theCanvasBitmap =
(
    currentPos = lastPos
    deltaX = pos.x - lastPos.x
    deltaY = pos.y - lastPos.y
    maxSteps = amax #(abs(deltaX),abs(deltaY))
    deltaStepX = deltaX / maxSteps
    deltaStepY = deltaY / maxSteps
    for i = 0 to maxSteps do
    (
		setPixels theCanvasBitmap  currentPos #(black)
		currentPos += [deltaStepX, deltaStepY]
    )
)

fn paintFace vface theCanvasBitmap = (
	for i= 1 to (vface.count-1) do
		drawStroke vface[i] vface[i+1] theCanvasBitmap
	drawStroke vface[1] vface[vface.count] theCanvasBitmap

)


(
	local theObj =  $GeoSphere001
	
	local bitmapX = bitmapY = 512
	local temp_bitmap_filename = (getDir #preview +"/microPaint_temp2.tga")
	local theCanvasBitmap = 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
	
	local seedface=19
	local theMesh = snapshotAsMesh theObj
	local theChannel = 1
	local brushtransform = $Box001.transform
	local brushsize=10
	maps = #()
	crossFaceMaps &maps theMesh seedface theChannel brushtransform brushsize
	for map in maps do (
		vface = #()
		for p in map do (
			append vface [p.x * bitmapx, bitmapy - p.y * bitmapy]
		)
		paintFace vface theCanvasBitmap
	)
  save theCanvasBitmap
  theObj.material.diffusemap.bitmap = theCanvasBitmap
)

毎回使っているこのシーンで、19番の面に中心点をオブジェクト中央に移動させたBox001がかかるようにしておいてプログラムを実行してみた。

fig01

これがUVマップ。今回ブラシに干渉している面は全て不連続になっている。

fig04

これがその結果。オブジェクトにテクスチャが貼られて、そのテクスチャにブラシの輪郭が描画されている。

fig02

BOXを非表示にしてみたもの。

fig03

続きはまた次回。

maxまとめページ



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

2017年06月20日

modo11.0v3のスクリプトについて調べてみた その96

引き続き「TD SDK」の「Vector3」クラスについて調べてみたい。

「copy()」は「Vector3」の複製を作る。コードは以下の通り。

 def copy(self):  
     return Vector3(self.values[:])

メソッドの中で自分の「values[:]」を引数にして「Vector3」のコンストラクタを呼び出すことで同じ座標値を持つ新規の「Vector3」を作っている。

「Vector3」のコンストラクタは引数に「Vector3」をとる事が出来るので、実際のところ「self.values[:]」を渡さないで「self」を渡せば複製を生成できる。

 def copy(self):  
     return Vector3(self)

ただ、「self」を渡さないで「self.values[:]」を渡すと引数が「list」クラスのインスタンスになるので、「Vector3.__init__()」の中では最終的に下のコードが実行され、「values」の要素数が3より多くても、頭の3つの値だけがコピーされる事になる。

 self.values = [a[0] for i in range(3)]

下のプログラムは「values」に直接リストをセットしてから2つの方法で複製を作ってみたものだ。「copy()」を使った場合は要素数が3になっているのがわかる。

from modo import *

v1 = Vector3()
v1.values = [10,20,30,40]
v2 = Vector3(v1)
v3 = v1.copy()
print "v1 = %s" % v1.values
print "Vector3(v1) = %s" % v2.values
print "v1.copy() = %s" % v3.values

# Result: 
v1 = [10, 20, 30, 40]
Vector3(v1) = [10, 20, 30, 40]
v1.copy() = [10, 20, 30]

また、「self.values[:]」の部分は「self.values」でも構わないような気がする。「[:]」はリストの一部分をスライスする演算子で、

list[開始インデックス:終了インデックス]

という書式でリストの要素の開始インデックスの要素から終了インデックス−1の要素までを切り出してリストを生成する。2つの値を省略すると最初から最後までスライスなしのリストが生成されるから元のリストと中身は一緒だ。違いは複製されたものかどうかだけだ。下のプログラムはリストを1つ作ってそれを他の変数に3回代入した時と「[:]」でスライスしたものを3回代入した時のオブジェクトのIDを表示してみたものだ。単純に代入した場合、リストは複製されず、他の変数からも同じ変数が参照されるだけだからIDも変らないのに対してスライサーを使ったものは新たにリストが生成されているのでそれぞれIDが異なり、別のオブジェクトだとわかる。

a = [10,20,30,40,50]

b = a
print "id(a) = %s" % id(b)
c = a
print "id(a) = %s" % id(c)
d = a
print "id(a) = %s" % id(d)

e = a[:]
print "id(a[:]) = %s" % id(e)
f = a[:]
print "id(a[:]) = %s" % id(f)
g = a[:]
print "id(a[:]) = %s" % id(g)

# Result: 
id(a) = 405851720
id(a) = 405851720
id(a) = 405851720
id(a[:]) = 405851592
id(a[:]) = 405850568
id(a[:]) = 405839688

だから「copy()」メソッドでスライスを使うのは良さそうではあるんだけど、内部で呼び出される「__init__()」で新たにリストを生成しているのでその必要は無いはずだ。

 self.values = [a[0] for i in range(3)]

下のプログラムはそれを確認してみたもの。v1は直接「values」にリストを代入したもの、v2はリストをコンストラクタに渡したもの、v3はスライスしたリストをコンストラクタに渡したものだ。そしてもとのリストの値を変更してみた。リストが複製されていなければ元のリストを変更したら渡した先の「Vector3」でも値が変るはずだ。

結果を見るとスライスをつけてもつけなくても値は変らず結果は一緒だ。

from modo import *
values = [10,20,30]

v1 = Vector3()
v1.values = values
v2 = Vector3(values)
v3 = Vector3(values[:])

values[0] = 1000

print "v1 = %s" % v1
print "v2 = %s" % v2
print "v3 = %s" % v3

# Result: 
v1 = Vector3(1000.000000, 20.000000, 30.000000)
v2 = Vector3(10.000000, 20.000000, 30.000000)
v3 = Vector3(10.000000, 20.000000, 30.000000)

続きはまた次回。

modo10-11ブログ目次



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

2017年06月19日

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

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

今回は前回書いたコードについて中身を見て行きたい。追加したプログラムは「crossFaceMaps()」とそれを呼び出すテストプログラムだ。

「crossFaceMaps()」はブラシに見立てた立方体の変換マトリクス「brushtransform」とブラシのサイズ「brushsize」、それがヒットした面のインデックス「seedface」、ペイントするメッシュオブジェクト「theMesh」、使用するUVマップチャンネル「theChannel」、そして結果を受け取る「maps」配列の参照を渡すと、メッシュとブラシが干渉した部分をUVマップ上の多角形としてその輪郭の頂点の配列を生成して返すものだ。

(
	local seedface=19
	local theMesh = snapshotAsMesh $GeoSphere001
	local theChannel = 1
	local brushtransform = $Box001.transform
	local brushsize=10
	maps = #()
	crossFaceMaps &maps theMesh seedface theChannel brushtransform brushsize
	print maps
)

そしてこれがそのコード。

fn crossFaceMaps &maps theMesh seedface theChannel brushtransform brushsize invBrushTransform=
(
	invBrushTransform = inverse( brushtransform)
	crossfaces = queloop theMesh seedface  brushsize  brushtransform
	for faceIndex in crossfaces do (
		vlist = #()
		sufFace = getFace theMesh  faceIndex
		append vlist (getVert theMesh sufFace.x)
		append vlist (getVert theMesh sufFace.y)
		append vlist (getVert theMesh sufFace.z)
		
		texFace = meshop.getMapFace theMesh theChannel faceIndex
		tv1= meshop.getMapVert theMesh theChannel texFace.x
		tv2= meshop.getMapVert theMesh theChannel texFace.y
		tv3= meshop.getMapVert theMesh theChannel texFace.z
		mg2t=(matrix3 [tv1.x,tv1.y,0] [tv2.x,tv2.y,0] [tv3.x,tv3.y,0] [0,0,0])
		clipface &vlist  brushsize invBrushTransform
		
		maplist =  #()
		for v in vlist do (
			mp = (meshop.getBaryCoords theMesh faceIndex v) * mg2t
			append maplist mp
		)
		append maps maplist
	)
)
  • まず「clipface()」で使うブラシ変換マトリクスの逆行列を生成し、「invBrushTransform」に格納する。
  • 次に「queloop()」でブラシと干渉するメッシュの面のインデックスのリストを生成し、「crossfaces」に格納する。
  • この面のインデックスのリストからfor文で1つずつ「faceIndex」に取り出して、以下のループ処理をする。
    • 面の頂点の座標値リストを「vlist」に格納
    • 面の頂点のUV座標値3つを「tv1」、「tv2」、「tv3」に取り出し、それらを「matrix3」にまとめて「mg2t」に格納する。このマトリクスを重心座標系の座標値に後ろからかけると、UV座標系の座標値が求められる。
    • 面の輪郭の「vlist」を「clipface()」でブラシ立方体でクリッピング処理をして、結果で「vlist」を更新する。これで面1枚ぶんのブラシとの干渉部分の多角形が得られる。
    • 次にUVマップ上の多角形を格納するための配列を生成して「maplist」に格納する。
    • 「vlist」に入っている座標値を「v」に1つずつ取り出して、「meshop.getBaryCoords()」で重心座標系に変換し、さらに「mg2t」をかけてそれをUV座標系に変換する。そしてその値を「maplist」に追加する。
    • これを面の頂点の座標値全てに対して行えば、クリップされた面のUVマップ上の座標値のリストが「maplist」に得られる。
    • 面1枚ぶんのリストが出来たらそれを「maps」配列に追加する。
  • 以上を「crossfaces」にある面全てに対して行えば、「maps」にはUV座標に変換されたクリップ面の頂点座標値リストのリストが得られる。
続きはまた次回。

maxまとめページ



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