Saturday, May 06, 2006
3dsmax/맥스: 프리핸드(freehand) 곡선 그리기 매크로스크립트(MacroScript)
3dsmax에는 이상하게도 프리핸드 툴이 없다. 프리핸드란 자유곡선이랄까, 연필로 스케치하듯 자유롭게 불규칙한 선을, 또는 운형(雲形)자처럼 곡선을 그리는 것이다.
지금으로선, 개인이 만든 매크로스크립트(MacroScript)를 다운로드받아서 직접 설치해 주어야 프리핸드를 쓸 수 있다.
< scriptspot.com > 에 FreehandSpline 1.5 라는 스크립트가 있었지만
freehandspline15-asmcr-v0_12.zip
그런데 이 파일이 지금은 어디로 갔는지 없어졌다. 그래서 필자가 가지고 있는 파일을 이 블로그에 올려놓았다.
위의 zip 파일 안에 다음과 같은 파일들이 어수선하게 들어 있는데
MAXr3Script-FreehandSpline15.html
fhs-menu15.gif
fhs-profile.gif
readme.txt
ConvertUtilityScript2MacroScript.txt
freehandspline15-ORIGINAL.ms
readme-update.txt
FreehandSpline15-AsMCR-v0_12.mcr
그중에서
FreehandSpline15-AsMCR-v0_12.mcr
이 파일을 사용하면 된다.
다만, 위 mcr 파일을 설치하면 맥스 메뉴에서 fhs 라는 알아보기 힘든 이름으로 나오기에, Freehand Spline 이라는 쉬운 이름으로 나오도록 필자가 약간 수정했다. 파일은 다음과 같다.
원본 파일을 구할 수 없는 분만 이 코드를 복사하여 사용할 것을 권한다. FreehandSpline15.mcr 등의 이름으로 위의 코드를 하드에 저장하면 된다. (이 블로거닷컴에서는 zip 등의 이진파일 Binary File 을 올릴 수 없음)
이것은 위의 프리핸드 스크립트를 맥스의 풀다운메뉴에 넣어주는 방법이다.
(D:\3dsmax 폴더에 맥스가 설치되어 있다고 가정)
FreehandSpline15.mcr 파일을 D:\3dsmax\UI\MacroScripts 폴더에 넣어준다. (기존의 mcr 파일들과 구분해 주기 위해, 윈도우 탐색기에서 Alt+Enter 로 "읽기전용 속성"을 지정해 주면 좋다.)
이미 맥스를 실행했다면, 맥스를 재시작한다. (윈도를 리부팅할 필요는 없다. 맥스만...)
맥스 상단 메뉴에서 Customize/Customize User Interface 를 선택하여 유저 인터페이스 창을 연다.
Menus 탭 을 클릭한다.
왼쪽 Action 창을 스크롤 해보면 Freehand Spline 이라는 항목이 이제 나타난다.
우측에는, File ... Edit ... 등의 풀다운메뉴 편집창이 있다.
우측의 풀다운 메뉴 편집창의 트리에서 MAXScript 메뉴 항목을 클릭해 펼친다. (Create 메뉴 등 아무곳에 넣어도 좋지만, 여기서는 예를 들어...)
좌측의 Freehand Spline을 마우스로 드래그해서, 우측의 MAXScript 메뉴 항목의 맨 밑에다 끌어다 놓는다.
기존의 항목들과 구분해 주기 위해, 메뉴에 수평선을 하나 추가하는 것이 좋다. 좌측 창의 Separator 를 드래그해서, 방금 드래그한 Freehand Spline 위에 끌어다놓으면 된다.
그런 후 창을 끄고 (자동으로 저장됨), 맥스의 화면 상단의 풀다운 메뉴를 펼쳐본다. 이제 MAXScript 메뉴를 펼치면 맨 밑에 FreehandSpline 이라는 것이 생겨 있을 것이다. 그것을 선택하면 프리핸드 스크립트가 실행된다. (아래의 그림을 참조)
FreehandSpline이 실행된 화면. 클릭하면 확대
화면 중앙의, 세로로 긴 작은 창이 프리핸드 스크립트의 실체다. 맥스는 단지 텍스트 스크립트만으로도 이런 툴을 만들 수 있다.
(About 에 gfxcentral.com/bobo/ 라는 주소가 있지만 지금은 연결되지 않는다. 이것은 1999년을 끝으로 개발이 중지된 고전 스크립트다. 이 스크립트에 한해서만은 노스트라다무스의 예언이 적중한 것 같다.)
(1) START DRAWING(그리기 시작) 버튼을 한 번 누름.
(2) 아무 뷰포트에서, 시작점으로 삼을 적당한 곳을 마우스로 1번만 클릭.
(3) 마우스 버튼은 누르지 말고 그냥 자유롭게 마우스를 이리저리 움직임
(4) 끝내고 싶은 지점에서 다시 마우스 버튼을 1번만 클릭
중요한 점은, 일반 그래픽 프로그램과 달리, 마우스 버튼을 누른 채 그리는 것이 아니라, 마우스 버튼을 누르지 않고 그리는 것이다.
Top 뷰포트에서 그리기 시작하여, Front 뷰포트 등으로 마음껏 이동하여 그리기를 계속할 수 있어 아주 강력하다. 이러면 "3차원 프리핸드"가 완성된다.
그리기가 다 끝났으면, 화면 우측 코맨드 패널의 Editable Spline/Vertex 를 클릭하여, 지금 그린 자유곡선의 버텍스의 밀도 등이 적당한지 확인한다.
이 프리핸드 스크립트는, 현재 최신 버전인 맥스8은 물론이고 맥스4 등에서도 잘 작동할 것이다. 비주얼C++로 작성되는 플러그인들과는 달리, 스크립트들은 맥스의 버전에 별로 민감하지 않다. 플러그인보다 스크립트가 좋은 이유도 그것이다.
지금으로선, 개인이 만든 매크로스크립트(MacroScript)를 다운로드받아서 직접 설치해 주어야 프리핸드를 쓸 수 있다.
< scriptspot.com > 에 FreehandSpline 1.5 라는 스크립트가 있었지만
freehandspline15-asmcr-v0_12.zip
그런데 이 파일이 지금은 어디로 갔는지 없어졌다. 그래서 필자가 가지고 있는 파일을 이 블로그에 올려놓았다.
위의 zip 파일 안에 다음과 같은 파일들이 어수선하게 들어 있는데
MAXr3Script-FreehandSpline15.html
fhs-menu15.gif
fhs-profile.gif
readme.txt
ConvertUtilityScript2MacroScript.txt
freehandspline15-ORIGINAL.ms
readme-update.txt
FreehandSpline15-AsMCR-v0_12.mcr
그중에서
FreehandSpline15-AsMCR-v0_12.mcr
이 파일을 사용하면 된다.
다만, 위 mcr 파일을 설치하면 맥스 메뉴에서 fhs 라는 알아보기 힘든 이름으로 나오기에, Freehand Spline 이라는 쉬운 이름으로 나오도록 필자가 약간 수정했다. 파일은 다음과 같다.
-- FreehandSpline15-AsMCR-v0_12.mcr
--
-- 09.01.2k, swami*, a.k.a. "codeWarrior()", swami@cfl.rr.com
-- Written for MAX r3.1
--
-- Original script by Bobo.
-- Modified by swami* to convert from a UtilityScript to a MacroScript.
-- Updated to R4.x, 12.01.01 (search "--s*" for changes).
--
macroScript FreehandSpline
category:"Bobo_s Tools"
buttontext:"FreehandSpline"
toolTip:"Freehand Spline"
(
--s*:Updated to R4.x...
global num_splines
global fh_float, about_roll, main_roll
-- end update.
try (closeRolloutFloater fh_float) catch() -- If fh_float already open, then close.
fh_float = NewRolloutFloater "Freehand Spline" 200 415
old_pos
new_spline = undefined
rollout about_roll "About"
(
group "About..."
(
label ffsa_01 "FreehandSpline"
label ffsa_02 "Version 1.5 - 02/18/99"
label ffsa_03 "by Borislav Petrov"
label ffsa_04 "(c) Bobo's Rendert**ls"
label ffsa_05 "http://gfxcentral.com/bobo/"
label ffsa_06 ""
label ffsa_07 "Converted to MacroScript"
label ffsa_07b "and updated to R4.x"
label ffsa_08 "by swami*"
label ffsa_09 "swami@cfl.rr.com"
label ffsa_10 "09.01.2k"
label ffsa_11 "12.01.01"
label ffsa_12 ""
label ffsa_13 "Notes:" align:#left
label ffsa_14 "- Mouse 'Smart Move' must" align:#left
label ffsa_15 "be DISABLED via ControlPanel." align:#left offset:[0,-3]
label ffsa_16 "- See Listener for important" align:#left
label ffsa_17 "usage info!..." align:#left offset:[0,-3]
)
)
rollout main_roll "Main"
(
group "Spline Drawing:"
(
spinner min_segment "Min.Seg. Length" range:[0,1000,10] type:#float fieldwidth:45
button start_draw "START DRAWING" width:140 height:30
checkbutton user_color "Use Custom Color" checked:true width:94 height:20 across:2 align:#left
colorpicker wire_color "" color:[0,30,100] align:#right
spinner interpolation "Interpolation Steps" range:[0,10,6] type:#integer fieldwidth:32
checkbutton curve_mode "Curve Segs" checked:true width:68 align:#left across:2 highlightcolor:([255,200,200] as color)
checkbutton line_mode "Line Segs" checked:false width:68 align:#right highlightcolor:([200,255,200] as color)
checkbutton bezier_mode "Bezier Verts" checked:true width:68 align:#left across:2 highlightcolor:([255,200,200] as color)
checkbutton smooth_mode "Smooth Verts" checked:false width:68 align:#right highlightcolor:([200,255,200] as color)
)
on curve_mode changed state do
(
line_mode.checked = not state
)
on line_mode changed state do
(
curve_mode.checked = not state
)
on smooth_mode changed state do
(
bezier_mode.checked = not state
)
on bezier_mode changed state do
(
smooth_mode.checked = not state
)
on interpolation changed val do
(
if new_spline != undefined then new_spline.steps = val
)
group "Renderable Spline"
(
checkbutton renderable_yes "Renderable Spline" checked:true width:140 align:#center
spinner spline_thickness "Spline Thickness" range:[0,1000,1] type:#float fieldwidth:45
)
group "Extrude Options"
(
spinner extrude_amount "Extrude Amount" range:[0,1000,10] type:#float fieldwidth:45
)
button reset_properties "Reset To Defaults" width:140 aling:#center
on reset_properties pressed do
(
q = querybox "FREEHAND SPLINE:\nReset All Values\nTo Defaults?"
if q then
(
min_segment.value = 10
user_color.checked = true
wire_color.color = color 0 30 100
curve_mode.checked = true
line_mode.checked = false
smooth_mode.checked = false
bezier_mode.checked = true
interpolation.value = 6
renderable_yes.checked = true
spline_thickness.value = 1
extrude_amount.value = 10
)
)
fn get_mouse_pos pen_pos old_pen_pos =
(
if old_pos == undefined then old_pos = old_pen_pos
delta_dist = sqrt(((pen_pos.x-old_pos.x)^2) + ((pen_pos.y-old_pos.y)^2) + ((pen_pos.z-old_pos.z)^2))
if delta_dist > min_segment.value then
(
if curve_mode.checked then
(
addKnot new_spline num_splines #smooth #curve pen_pos
)
else
(
addKnot new_spline num_splines #smooth #line pen_pos
)
old_pos = pen_pos
updateShape new_spline
)
)--end fn
fn draw_new_line old_pen_pos =
(
draw_pick = pickpoint mouseMoveCallback:#(get_mouse_pos,old_pen_pos) terminators:#("e"," ","d","c","m","p","l","k")
draw_it_again = 0
if draw_pick[2] == "m" then
(
draw_it_again = 0
close new_spline num_splines
deleteknot new_spline num_splines 1
if num_splines > 1 then deleteknot new_spline num_splines 1
updateshape new_spline
dont_mesh = false
for s = 1 to num_splines do
(
if not (isClosed new_spline s) then dont_mesh = true
)
q = true
if dont_mesh then
(
q = querybox "FREEHAND SPLINE:\nThere are OPEN SPLINES\nin the current Shape.\nDo you really want to Mesh?"
)
if q then
(
addmodifier new_spline (normalModifier ())
txt = "FREEHAND SPLINE: Meshed Spline " + new_spline.name
format "\n%\n" txt
)
else
(
txt = "FREEHAND SPLINE: Closed Spline - NOT MESHED " + new_spline.name
format "\n%\n" txt
)
draw_it_again = 0
)
if draw_pick[2] == " " then
(
draw_it_again = 0
close new_spline num_splines
deleteknot new_spline num_splines 1
if num_splines > 1 then deleteknot new_spline num_splines 1
updateshape new_spline
txt = "FREEHAND SPLINE: Closed Spline " + new_spline.name
format "\n%\n" txt
)
if draw_pick[2] == "e" then
(
close new_spline num_splines
deleteknot new_spline num_splines 1
if num_splines > 1 then deleteknot new_spline num_splines 1
updateshape new_spline
draw_it_again = 0
addmodifier new_spline (extrude amount:extrude_amount.value)
txt = "FREEHAND SPLINE: Closed and Extruded Spline " + new_spline.name + " with Extrusion "+extrude_amount.value as string
format "\n%\n" txt
)
if draw_pick[2] == "d" then
(
deleteknot new_spline num_splines 1
if num_splines > 1 then deleteknot new_spline num_splines 1
updateshape new_spline
draw_it_again = 1
txt = "FREEHAND SPLINE: Pen Up... Click again in a viewport to continue drawing..."
format "\n%\n" txt
)
if draw_pick[2] == "c" then
(
draw_it_again = 1
close new_spline num_splines
deleteknot new_spline num_splines 1
if num_splines > 1 then deleteknot new_spline num_splines 1
updateshape new_spline
txt = "FREEHAND SPLINE: Close Spline and Pen Up... Click again in a viewport to continue drawing..."
format "\n%\n" txt
)
if draw_pick[2] == "p" then
(
draw_it_again = 2
updateshape new_spline
txt = "FREEHAND SPLINE: Drawing Paused... Click again in a viewport to continue last spline.."
format "\n%\n" txt
)
if draw_pick[2] == "l" then
(
line_mode.checked = true
curve_mode.checked = false
draw_it_again = 2
updateshape new_spline
txt = "FREEHAND SPLINE: LINEAR Segment Mode ... Click again in a viewport to continue last spline.."
format "\n%\n" txt
)
if draw_pick[2] == "k" then
(
line_mode.checked = false
curve_mode.checked = true
draw_it_again = 2
updateshape new_spline
txt = "FREEHAND SPLINE: CURVE Segment Mode ... Click again in a viewport to continue last spline.."
format "\n%\n" txt
)
max views redraw
draw_it_again
)
on start_draw pressed do
(
undo on
(
txt = "FREEHAND SPLINE: Click in a Viewport to start drawing..."
format "%\n" txt
new_spline = SplineShape ()
new_spline.name = uniquename "FHS_Shape"
if user_color.checked then new_spline.wirecolor = wire_color.color
--s*
--new_spline.renderable = renderable_yes.checked
new_spline.baseObject.renderable = renderable_yes.checked
new_spline.thickness = spline_thickness.value
new_spline.steps = interpolation.value
old_pos = undefined
draw_again = 1
while draw_again != 0 do
(
old_pen_pos = pickpoint ()
if old_pen_pos == #rightclick then
(
delete new_spline
new_spline = undefined
exit
)
if draw_again != 2 then addNewSpline new_spline
num_splines = numSplines new_spline
if num_splines == 1 and draw_again != 2 then new_spline.pos = old_pen_pos
if draw_again != 2 then
(
if curve_mode.checked then
(
addKnot new_spline num_splines #smooth #curve old_pen_pos
addKnot new_spline num_splines #smooth #curve old_pen_pos
)
else
(
addKnot new_spline num_splines #smooth #line old_pen_pos
addKnot new_spline num_splines #smooth #line old_pen_pos
)
)
updateShape new_spline
txt = "FREEHAND SPLINE: Move mouse to draw a spline. Segment Length:"+min_segment.value as string
format "%\n" txt
txt = "COMMANDS: [p]=PenUp-Pause [d]=PenUp-NewSpline [c]=Close&PenUp [l]=Lines [k]=Curves"
format "%\n" txt
txt = " [Space]=Close&End [e]=CloseLast&Extrude [m]=Mesh&End [Right-Click]=End"
format "%\n" txt
draw_again = draw_new_line old_pen_pos
)
txt = "FREEHAND SPLINE: End of Drawing."
format "%\n" txt
if new_spline != undefined then
(
if bezier_mode.checked then
(
for i = 1 to num_splines do
(
for j = 1 to (numknots new_spline i) do
(
setKnotType new_spline i j #bezier
)
)
)
select new_spline
)
)--end undo
)--end on
on freehand_spline open do
(
txt = "Initializing FREEHAND SPLINE..."
format "\n%\n" txt
max_ver2 = true
check_color = color 255 255 255
check_color *=128
if check_color.r > 255 then max_ver2 = false
if max_ver2 then
(
start_draw.enabled = false
start_draw.text = "MAX 2.5 REQUIRED!"
txt = "MAX R2.0 Detected! Utility DISABLED. MAX R2.5 Required!"
format "%\n" txt
)
else
(
txt = "MAX R2.5 Detected..."
format "%\n" txt
)
try
(
ini_file = openfile (scriptspath + "fhspline.ini")
str = readline ini_file
min_segment.value = str as float
str = readline ini_file
if str == "true" then user_color.checked = true else user_color.checked = false
str = readline ini_file
if str == "true" then curve_mode.checked = true else curve_mode.checked = false
str = readline ini_file
if str == "true" then line_mode.checked = true else line_mode.checked = false
str = readline ini_file
interpolation.value = str as float
str = readline ini_file
if str == "true" then renderable_yes.checked = true else renderable_yes.checked = false
str = readline ini_file
spline_thickness.value = str as float
str = readline ini_file
extrude_amount.value = str as float
str = readline ini_file
if str == "true" then smooth_mode.checked = true else smooth_mode.checked = false
str = readline ini_file
if str == "true" then bezier_mode.checked = true else bezier_mode.checked = false
close ini_file
txt = "INI file loaded."
format "%\n" txt
)
catch
(
txt = "INI file corrupted or missing. Using defaults."
format "%\n" txt
)
txt = "Ready."
format "%\n" txt
)
on freehand_spline close do
(
save_file_path = scriptspath + "fhspline.ini"
ini_file = createfile save_file_path
format "%\n" (min_segment.value as string) to:ini_file
format "%\n" (user_color.checked as string) to:ini_file
format "%\n" (curve_mode.checked as string) to:ini_file
format "%\n" (line_mode.checked as string) to:ini_file
format "%\n" (interpolation.value as string) to:ini_file
format "%\n" (renderable_yes.checked as string) to:ini_file
format "%\n" (spline_thickness.value as string) to:ini_file
format "%\n" (extrude_amount.value as string) to:ini_file
format "%\n" (smooth_mode.checked as string) to:ini_file
format "%\n" (bezier_mode.checked as string) to:ini_file
close ini_file
txt = "FREEHAND SPLINE Session Closed."
format "%\n" txt
)
)
addRollout about_roll fh_float rolledUp:true
addRollout main_roll fh_float rolledUp:false
)
--
-- 09.01.2k, swami*, a.k.a. "codeWarrior()", swami@cfl.rr.com
-- Written for MAX r3.1
--
-- Original script by Bobo.
-- Modified by swami* to convert from a UtilityScript to a MacroScript.
-- Updated to R4.x, 12.01.01 (search "--s*" for changes).
--
macroScript FreehandSpline
category:"Bobo_s Tools"
buttontext:"FreehandSpline"
toolTip:"Freehand Spline"
(
--s*:Updated to R4.x...
global num_splines
global fh_float, about_roll, main_roll
-- end update.
try (closeRolloutFloater fh_float) catch() -- If fh_float already open, then close.
fh_float = NewRolloutFloater "Freehand Spline" 200 415
old_pos
new_spline = undefined
rollout about_roll "About"
(
group "About..."
(
label ffsa_01 "FreehandSpline"
label ffsa_02 "Version 1.5 - 02/18/99"
label ffsa_03 "by Borislav Petrov"
label ffsa_04 "(c) Bobo's Rendert**ls"
label ffsa_05 "http://gfxcentral.com/bobo/"
label ffsa_06 ""
label ffsa_07 "Converted to MacroScript"
label ffsa_07b "and updated to R4.x"
label ffsa_08 "by swami*"
label ffsa_09 "swami@cfl.rr.com"
label ffsa_10 "09.01.2k"
label ffsa_11 "12.01.01"
label ffsa_12 ""
label ffsa_13 "Notes:" align:#left
label ffsa_14 "- Mouse 'Smart Move' must" align:#left
label ffsa_15 "be DISABLED via ControlPanel." align:#left offset:[0,-3]
label ffsa_16 "- See Listener for important" align:#left
label ffsa_17 "usage info!..." align:#left offset:[0,-3]
)
)
rollout main_roll "Main"
(
group "Spline Drawing:"
(
spinner min_segment "Min.Seg. Length" range:[0,1000,10] type:#float fieldwidth:45
button start_draw "START DRAWING" width:140 height:30
checkbutton user_color "Use Custom Color" checked:true width:94 height:20 across:2 align:#left
colorpicker wire_color "" color:[0,30,100] align:#right
spinner interpolation "Interpolation Steps" range:[0,10,6] type:#integer fieldwidth:32
checkbutton curve_mode "Curve Segs" checked:true width:68 align:#left across:2 highlightcolor:([255,200,200] as color)
checkbutton line_mode "Line Segs" checked:false width:68 align:#right highlightcolor:([200,255,200] as color)
checkbutton bezier_mode "Bezier Verts" checked:true width:68 align:#left across:2 highlightcolor:([255,200,200] as color)
checkbutton smooth_mode "Smooth Verts" checked:false width:68 align:#right highlightcolor:([200,255,200] as color)
)
on curve_mode changed state do
(
line_mode.checked = not state
)
on line_mode changed state do
(
curve_mode.checked = not state
)
on smooth_mode changed state do
(
bezier_mode.checked = not state
)
on bezier_mode changed state do
(
smooth_mode.checked = not state
)
on interpolation changed val do
(
if new_spline != undefined then new_spline.steps = val
)
group "Renderable Spline"
(
checkbutton renderable_yes "Renderable Spline" checked:true width:140 align:#center
spinner spline_thickness "Spline Thickness" range:[0,1000,1] type:#float fieldwidth:45
)
group "Extrude Options"
(
spinner extrude_amount "Extrude Amount" range:[0,1000,10] type:#float fieldwidth:45
)
button reset_properties "Reset To Defaults" width:140 aling:#center
on reset_properties pressed do
(
q = querybox "FREEHAND SPLINE:\nReset All Values\nTo Defaults?"
if q then
(
min_segment.value = 10
user_color.checked = true
wire_color.color = color 0 30 100
curve_mode.checked = true
line_mode.checked = false
smooth_mode.checked = false
bezier_mode.checked = true
interpolation.value = 6
renderable_yes.checked = true
spline_thickness.value = 1
extrude_amount.value = 10
)
)
fn get_mouse_pos pen_pos old_pen_pos =
(
if old_pos == undefined then old_pos = old_pen_pos
delta_dist = sqrt(((pen_pos.x-old_pos.x)^2) + ((pen_pos.y-old_pos.y)^2) + ((pen_pos.z-old_pos.z)^2))
if delta_dist > min_segment.value then
(
if curve_mode.checked then
(
addKnot new_spline num_splines #smooth #curve pen_pos
)
else
(
addKnot new_spline num_splines #smooth #line pen_pos
)
old_pos = pen_pos
updateShape new_spline
)
)--end fn
fn draw_new_line old_pen_pos =
(
draw_pick = pickpoint mouseMoveCallback:#(get_mouse_pos,old_pen_pos) terminators:#("e"," ","d","c","m","p","l","k")
draw_it_again = 0
if draw_pick[2] == "m" then
(
draw_it_again = 0
close new_spline num_splines
deleteknot new_spline num_splines 1
if num_splines > 1 then deleteknot new_spline num_splines 1
updateshape new_spline
dont_mesh = false
for s = 1 to num_splines do
(
if not (isClosed new_spline s) then dont_mesh = true
)
q = true
if dont_mesh then
(
q = querybox "FREEHAND SPLINE:\nThere are OPEN SPLINES\nin the current Shape.\nDo you really want to Mesh?"
)
if q then
(
addmodifier new_spline (normalModifier ())
txt = "FREEHAND SPLINE: Meshed Spline " + new_spline.name
format "\n%\n" txt
)
else
(
txt = "FREEHAND SPLINE: Closed Spline - NOT MESHED " + new_spline.name
format "\n%\n" txt
)
draw_it_again = 0
)
if draw_pick[2] == " " then
(
draw_it_again = 0
close new_spline num_splines
deleteknot new_spline num_splines 1
if num_splines > 1 then deleteknot new_spline num_splines 1
updateshape new_spline
txt = "FREEHAND SPLINE: Closed Spline " + new_spline.name
format "\n%\n" txt
)
if draw_pick[2] == "e" then
(
close new_spline num_splines
deleteknot new_spline num_splines 1
if num_splines > 1 then deleteknot new_spline num_splines 1
updateshape new_spline
draw_it_again = 0
addmodifier new_spline (extrude amount:extrude_amount.value)
txt = "FREEHAND SPLINE: Closed and Extruded Spline " + new_spline.name + " with Extrusion "+extrude_amount.value as string
format "\n%\n" txt
)
if draw_pick[2] == "d" then
(
deleteknot new_spline num_splines 1
if num_splines > 1 then deleteknot new_spline num_splines 1
updateshape new_spline
draw_it_again = 1
txt = "FREEHAND SPLINE: Pen Up... Click again in a viewport to continue drawing..."
format "\n%\n" txt
)
if draw_pick[2] == "c" then
(
draw_it_again = 1
close new_spline num_splines
deleteknot new_spline num_splines 1
if num_splines > 1 then deleteknot new_spline num_splines 1
updateshape new_spline
txt = "FREEHAND SPLINE: Close Spline and Pen Up... Click again in a viewport to continue drawing..."
format "\n%\n" txt
)
if draw_pick[2] == "p" then
(
draw_it_again = 2
updateshape new_spline
txt = "FREEHAND SPLINE: Drawing Paused... Click again in a viewport to continue last spline.."
format "\n%\n" txt
)
if draw_pick[2] == "l" then
(
line_mode.checked = true
curve_mode.checked = false
draw_it_again = 2
updateshape new_spline
txt = "FREEHAND SPLINE: LINEAR Segment Mode ... Click again in a viewport to continue last spline.."
format "\n%\n" txt
)
if draw_pick[2] == "k" then
(
line_mode.checked = false
curve_mode.checked = true
draw_it_again = 2
updateshape new_spline
txt = "FREEHAND SPLINE: CURVE Segment Mode ... Click again in a viewport to continue last spline.."
format "\n%\n" txt
)
max views redraw
draw_it_again
)
on start_draw pressed do
(
undo on
(
txt = "FREEHAND SPLINE: Click in a Viewport to start drawing..."
format "%\n" txt
new_spline = SplineShape ()
new_spline.name = uniquename "FHS_Shape"
if user_color.checked then new_spline.wirecolor = wire_color.color
--s*
--new_spline.renderable = renderable_yes.checked
new_spline.baseObject.renderable = renderable_yes.checked
new_spline.thickness = spline_thickness.value
new_spline.steps = interpolation.value
old_pos = undefined
draw_again = 1
while draw_again != 0 do
(
old_pen_pos = pickpoint ()
if old_pen_pos == #rightclick then
(
delete new_spline
new_spline = undefined
exit
)
if draw_again != 2 then addNewSpline new_spline
num_splines = numSplines new_spline
if num_splines == 1 and draw_again != 2 then new_spline.pos = old_pen_pos
if draw_again != 2 then
(
if curve_mode.checked then
(
addKnot new_spline num_splines #smooth #curve old_pen_pos
addKnot new_spline num_splines #smooth #curve old_pen_pos
)
else
(
addKnot new_spline num_splines #smooth #line old_pen_pos
addKnot new_spline num_splines #smooth #line old_pen_pos
)
)
updateShape new_spline
txt = "FREEHAND SPLINE: Move mouse to draw a spline. Segment Length:"+min_segment.value as string
format "%\n" txt
txt = "COMMANDS: [p]=PenUp-Pause [d]=PenUp-NewSpline [c]=Close&PenUp [l]=Lines [k]=Curves"
format "%\n" txt
txt = " [Space]=Close&End [e]=CloseLast&Extrude [m]=Mesh&End [Right-Click]=End"
format "%\n" txt
draw_again = draw_new_line old_pen_pos
)
txt = "FREEHAND SPLINE: End of Drawing."
format "%\n" txt
if new_spline != undefined then
(
if bezier_mode.checked then
(
for i = 1 to num_splines do
(
for j = 1 to (numknots new_spline i) do
(
setKnotType new_spline i j #bezier
)
)
)
select new_spline
)
)--end undo
)--end on
on freehand_spline open do
(
txt = "Initializing FREEHAND SPLINE..."
format "\n%\n" txt
max_ver2 = true
check_color = color 255 255 255
check_color *=128
if check_color.r > 255 then max_ver2 = false
if max_ver2 then
(
start_draw.enabled = false
start_draw.text = "MAX 2.5 REQUIRED!"
txt = "MAX R2.0 Detected! Utility DISABLED. MAX R2.5 Required!"
format "%\n" txt
)
else
(
txt = "MAX R2.5 Detected..."
format "%\n" txt
)
try
(
ini_file = openfile (scriptspath + "fhspline.ini")
str = readline ini_file
min_segment.value = str as float
str = readline ini_file
if str == "true" then user_color.checked = true else user_color.checked = false
str = readline ini_file
if str == "true" then curve_mode.checked = true else curve_mode.checked = false
str = readline ini_file
if str == "true" then line_mode.checked = true else line_mode.checked = false
str = readline ini_file
interpolation.value = str as float
str = readline ini_file
if str == "true" then renderable_yes.checked = true else renderable_yes.checked = false
str = readline ini_file
spline_thickness.value = str as float
str = readline ini_file
extrude_amount.value = str as float
str = readline ini_file
if str == "true" then smooth_mode.checked = true else smooth_mode.checked = false
str = readline ini_file
if str == "true" then bezier_mode.checked = true else bezier_mode.checked = false
close ini_file
txt = "INI file loaded."
format "%\n" txt
)
catch
(
txt = "INI file corrupted or missing. Using defaults."
format "%\n" txt
)
txt = "Ready."
format "%\n" txt
)
on freehand_spline close do
(
save_file_path = scriptspath + "fhspline.ini"
ini_file = createfile save_file_path
format "%\n" (min_segment.value as string) to:ini_file
format "%\n" (user_color.checked as string) to:ini_file
format "%\n" (curve_mode.checked as string) to:ini_file
format "%\n" (line_mode.checked as string) to:ini_file
format "%\n" (interpolation.value as string) to:ini_file
format "%\n" (renderable_yes.checked as string) to:ini_file
format "%\n" (spline_thickness.value as string) to:ini_file
format "%\n" (extrude_amount.value as string) to:ini_file
format "%\n" (smooth_mode.checked as string) to:ini_file
format "%\n" (bezier_mode.checked as string) to:ini_file
close ini_file
txt = "FREEHAND SPLINE Session Closed."
format "%\n" txt
)
)
addRollout about_roll fh_float rolledUp:true
addRollout main_roll fh_float rolledUp:false
)
원본 파일을 구할 수 없는 분만 이 코드를 복사하여 사용할 것을 권한다. FreehandSpline15.mcr 등의 이름으로 위의 코드를 하드에 저장하면 된다. (이 블로거닷컴에서는 zip 등의 이진파일 Binary File 을 올릴 수 없음)
설치법
이것은 위의 프리핸드 스크립트를 맥스의 풀다운메뉴에 넣어주는 방법이다.
(D:\3dsmax 폴더에 맥스가 설치되어 있다고 가정)
FreehandSpline15.mcr 파일을 D:\3dsmax\UI\MacroScripts 폴더에 넣어준다. (기존의 mcr 파일들과 구분해 주기 위해, 윈도우 탐색기에서 Alt+Enter 로 "읽기전용 속성"을 지정해 주면 좋다.)
이미 맥스를 실행했다면, 맥스를 재시작한다. (윈도를 리부팅할 필요는 없다. 맥스만...)
맥스 상단 메뉴에서 Customize/Customize User Interface 를 선택하여 유저 인터페이스 창을 연다.
Menus 탭 을 클릭한다.
왼쪽 Action 창을 스크롤 해보면 Freehand Spline 이라는 항목이 이제 나타난다.
우측에는, File ... Edit ... 등의 풀다운메뉴 편집창이 있다.
우측의 풀다운 메뉴 편집창의 트리에서 MAXScript 메뉴 항목을 클릭해 펼친다. (Create 메뉴 등 아무곳에 넣어도 좋지만, 여기서는 예를 들어...)
좌측의 Freehand Spline을 마우스로 드래그해서, 우측의 MAXScript 메뉴 항목의 맨 밑에다 끌어다 놓는다.
기존의 항목들과 구분해 주기 위해, 메뉴에 수평선을 하나 추가하는 것이 좋다. 좌측 창의 Separator 를 드래그해서, 방금 드래그한 Freehand Spline 위에 끌어다놓으면 된다.
그런 후 창을 끄고 (자동으로 저장됨), 맥스의 화면 상단의 풀다운 메뉴를 펼쳐본다. 이제 MAXScript 메뉴를 펼치면 맨 밑에 FreehandSpline 이라는 것이 생겨 있을 것이다. 그것을 선택하면 프리핸드 스크립트가 실행된다. (아래의 그림을 참조)
FreehandSpline이 실행된 화면. 클릭하면 확대
화면 중앙의, 세로로 긴 작은 창이 프리핸드 스크립트의 실체다. 맥스는 단지 텍스트 스크립트만으로도 이런 툴을 만들 수 있다.
(About 에 gfxcentral.com/bobo/ 라는 주소가 있지만 지금은 연결되지 않는다. 이것은 1999년을 끝으로 개발이 중지된 고전 스크립트다. 이 스크립트에 한해서만은 노스트라다무스의 예언이 적중한 것 같다.)
FreehandSpline 사용법
(1) START DRAWING(그리기 시작) 버튼을 한 번 누름.
(2) 아무 뷰포트에서, 시작점으로 삼을 적당한 곳을 마우스로 1번만 클릭.
(3) 마우스 버튼은 누르지 말고 그냥 자유롭게 마우스를 이리저리 움직임
(4) 끝내고 싶은 지점에서 다시 마우스 버튼을 1번만 클릭
중요한 점은, 일반 그래픽 프로그램과 달리, 마우스 버튼을 누른 채 그리는 것이 아니라, 마우스 버튼을 누르지 않고 그리는 것이다.
Top 뷰포트에서 그리기 시작하여, Front 뷰포트 등으로 마음껏 이동하여 그리기를 계속할 수 있어 아주 강력하다. 이러면 "3차원 프리핸드"가 완성된다.
그리기가 다 끝났으면, 화면 우측 코맨드 패널의 Editable Spline/Vertex 를 클릭하여, 지금 그린 자유곡선의 버텍스의 밀도 등이 적당한지 확인한다.
이 프리핸드 스크립트는, 현재 최신 버전인 맥스8은 물론이고 맥스4 등에서도 잘 작동할 것이다. 비주얼C++로 작성되는 플러그인들과는 달리, 스크립트들은 맥스의 버전에 별로 민감하지 않다. 플러그인보다 스크립트가 좋은 이유도 그것이다.
tag: 3dsmax
3ds Max | 맥스 | 멘탈레이 | mental ray | 3D 그래픽
안녕하세요~ 3ds Max Script를 이제 막 시작하게 된 사람입니다.
우연히 알게 된 블로그 인데,
너무 많은 것을 배우고 가네요.
우선 이렇게 Tutorial을 올려 놓으신것에 대해서 감사의 말씀을 올립니다.
앞으로도 많이 찾아뵙겠습니다.
반갑습니다.
*∩_∩*
<< Home