3 minute read

(3D 오브젝트의 길이, 넓이, 부피, 중심좌표 계산)

1. 작업 의도

:blush: 3D 모델링 작업의 편의를 위해 오브젝트의 길이와 넓이, 부피, 중심 좌표를 계산하는 간단한 계산기를 만들었습니다.

1) vertex 길이

사용자가 선택한 두 버텍스 사이의 길이를 측정할 수 있습니다.

2) edge 길이

사용자가 선택한 다수의 선의 길이를 측정할 수 있습니다. 각 선의 길이와 총 길이를 출력합니다.

3) polygon 넓이

사용자가 선택한 다수의 폴리곤 면적의 넓이를 측정할 수 있습니다. 각 면적의 넓이와 총 넓이를 출력합니다.

4) volume

사용자가 선택한 오브젝트의 부피를 출력합니다.

5) 중심 좌표

사용자가 선택한 오브젝트의 중심좌표를 출력합니다.

2. 작업 과정

:runner: 소요 기간: 약 5일

:speech_balloon: maxscript로 작성

1) vertex 길이

fn getDistance EPolyD aVert =
(	
	try
	(
		VertPositionD = for iVert in aVert collect	
		polyop.getVert EPolyD iVert
		return (distance VertPositionD[1] VertPositionD[2])
	)
	catch()
)

사용자로 부터 버텍스 2개를 입력받습니다. 여러 개를 입력 받아도 1,2번째만 리턴합니다. 혹시 오브젝트 바깥의 버텍스를 클릭한 경우 트라이 캐치 예외 처리를 하였습니다.

on disbtn pressed do
	(
		EPolyD= selection[1]
		aVert = polyop.getVertSelection EPolyD
		disVal = getDistance EPolyD aVert		
		
		listBox.items = append listBox.items ("Distance : " + (disVal as string))
	)

버텍스 사이의 거리를 구하는 버튼을 클릭하면 배열에 담아 함수의 매개변수로 넘깁니다. 함수 결과값을 출력합니다.

2) edge 길이

fn getLength EditablePoly iEdge =
(		
	try
	(
	    local aiEdgeVerts = polyop.getEdgeVerts EditablePoly iEdge
        
        local VertPosition = for iVert in aiEdgeVerts collect
		polyop.getVert EditablePoly iVert
        
        return (distance VertPosition[1] VertPosition[2])
	)
	catch()
)

선택한 엣지의 양쪽 끝 버텍스의 좌표를 구하여 거리를 구한 후 반환합니다.

on lenbtn pressed do
	(		
		total = 0
		EPoly = selection[1]         
		aEdge = polyOp.getEdgeSelection EPoly
		                        
		for ed in aEdge do
		(
			LengthValue= getLength EPoly ed 
				
			listBox.items = append listBox.items (($.name as string) +"| Length : #"+(ed as string) +" = " + (LengthValue as string))
				
			if aEdge.count >1 do
			(				
				total += LengthValue				
			)
		)
		listBox.items = append listBox.items (($.name as string) +"| Length Total : "+ (total as string))				
	)

edge의 길이를 array에 담아 반복문을 통해 각 edge의 길이를 출력하도록 하였습니다.

3) polygon 넓이

fn getfaceArea EPolyArea face = 
(	
	try
	(
	local theArea= 0.0
	theArea = polyop.getFaceArea EPolyArea face
	return (theArea)
	)
	catch()
)

반복문을 통해 선택한 폴리곤의 번호를 매개변수로 넘겨서 면적을 구한 후,각 폴리곤의 면적값을 출력했습니다.

on areabtn pressed do
	(		
		areaTotal = 0
		EPolyArea = selection[1]
		aMyselection = EPolyArea.GetSelection #Face 	
				
		for face in aMyselection do
		(
			AreaValue = getfaceArea EPolyArea face
			listBox.items = append listBox.items (($.name as string) +"| Area : #"+(face as string) +" = " + (AreaValue as string))
			
			if aMyselection.count >1 do
			(				
				areaTotal += AreaValue				
			)
		)
		listBox.items = append listBox.items (($.name as string) +"| Area Total : "+ (areaTotal as string))		
	)

4) volume

fn getVolume obj =
(
	local Volume= 0.0
	local theMesh = snapshotasmesh obj
	local numFaces = theMesh.numfaces
	for i = 1 to numFaces do
	(
		local Face= getFace theMesh i
		local vert2 = getVert theMesh Face.z
		local vert1 = getVert theMesh Face.y
		local vert0 = getVert theMesh Face.x
		local dV = Dot (Cross (vert1 - vert0) (vert2 - vert0)) vert0
		Volume+= dV		
	)
delete theMesh
Volume /= 6
print(Volume)
)
on volbtn pressed do
	(
		print "volume"
		vol= getVolume $ 
		listBox.items = append listBox.items (($.name as string) +"| Volume : "+(vol as string) )
	)

maxscript help의 예제를 참고하였습니다. 현재 선택한 오브젝트를 매개변수로 하여 함수를 호출합니다. face의 갯수만큼 반복문을 돌립니다. x,y,z축과 메쉬의 버텍스 값을 이용해 부피를 구합니다. 이 부분은 수학적으로 더 연구가 필요할 것 같습니다.

5) 중심 좌표

fn getCenterOfMass obj =
(
	local Volume= 0.0
	local Center= [0.0, 0.0, 0.0]
	local theMesh = snapshotasmesh obj
	local numFaces = theMesh.numfaces
	for i = 1 to numFaces do
	(
		local Face= getFace theMesh i
		local vert2 = getVert theMesh Face.z
		local vert1 = getVert theMesh Face.y
		local vert0 = getVert theMesh Face.x
		local dV = Dot (Cross (vert1 - vert0) (vert2 - vert0)) vert0
		Volume+= dV
		Center+= (vert0 + vert1 + vert2) * dV
	)
delete theMesh
Volume /= 6
Center /= 24
Center /= Volume
print(Center)
)
on cenbtn pressed do
	(
		print "center"
		cen= getCenterOfMass $
		listBox.items = append listBox.items (($.name as string) +"| Center : "+(cen as string) )
	)	

maxscript help의 예제를 참고하였습니다. vert0부터 2까지 더하고 부피값을 곱해준 후 24를 나눠준 후, 부피값으로 또 나눠줍니다. 이부분 역시 수학적 연구가 더 필요할 것 같습니다.

3. 결과물

*마우스 오른쪽 버튼 > 새 탭에서 열기 (원본 사이즈의 이미지가 열립니다.)

length

length

length

length

:thought_balloon: maxscript를 처음 접하여 help문서를 참고하며 작성하였고, 툴 기획과 아이콘, 알파 아이콘을 직접 제작하였습니다. 혼자 제작한 프로젝트라 어려움도 있었지만 보람있었습니다. 간단한 코드임에도 아직 익숙하지 않아서 제작에 시일이 다소 소요된 것 같습니다.

:books: 깃허브 주소