반응형

안녕하세요 오랜만에 3DS MAX SCRIPT 포스팅을 합니다.

제가 올리는 글을 누가 보는가 싶은데.. 간혹 스크립트를 잘 봐주시는 방문객들이 계신듯 하여 포스팅을 하게 되었습니다.

오늘은 3DS MAX SCRIPT의 계층 구조에 대한 이야기 입니다. 

왠만한 개발을 해 보신 분들은 사실 약간 상식적으로 알고 계신 내용일 것 같기는 합니만 그래도 역시 누군가에게는 도움이 될 듯 하여 글을 남겨 봅니다.

 

3DS MAX Scritp 에서 어떤 오브젝트는 개발 관점에서 보면 클래스 입니다. 상위 클래스가 있고 또 하위 클래스가 있는데요. 계층 구조라고 말씀 드린것처럼 클래스 안에 또 작은 클래스가 정의 되어 있고 또 그안에 작은 클래스 또는 구조체가 정의 되어 있다고 보시면 됩니다.

 

클래스라고???

개발이 생소하신 분들은 클래스라고 하면 잘 이해가 안되시죠?

우리 인간을 예를 들어 클래스라는 개념을 설명해 보면 다음과 같습니다. (그냥 예 입니다)

각 단계는 상위 클래스의 하위 클래스가 됩니다.

  • 동물 - 호흡을 한다. 심장이 있다. 
    • 포유류 - 4개의 팔 또는 다리를 가지고 있다. 아기를 낳는다. 젖을 먹인다.
      • 영장류 - 지능이 뛰어나다. 두발 또는 네발로 걸을 수 있다. 시각 능력이 좋다
        • 인간 - 특별히 뇌가 발달했다. 다양한 언어를 구사할 수 있다. 손의 움직임이 뛰어나다
    • 조류 ... 
    • 양서류...
    • 파충류...

뭐 이런식으로 어떤 큰 개념을 정의하고 그 하위에 상위의 개념을 포함하지만 조금 세분화된 개념을 담는 그런 방식으로 한단계 한단계 세분화된 그런 개념을 담고 있는 것이 일반적인 클래스의 개념입니다. (위에 설명한 건 그냥 예를 든 것입니다. 시비 노노)

 

예를 들면 익히 잘 알고 있는 Box 는 

요런 순서의 계층 구조를 가지고 있습니다.

우린 레퍼런스 파일을 통해서 Box() 라는 클래스가 가지고 있는 다양한 프라퍼티에 접근을 할 수 있습니다.

2021.03.24 - [DEV/MAX SCRIPT] - 3DS MAX 스크립트 레퍼런스 (헬프파일) 다운 받기

예를 들면 생성된 Box 개체의 width, Height, length 를 다음과 같이 변경할 수 있습니다.

myBox = box()
myBox.width = 25
myBox.Height = 150
myBox.Length = 50

그럼 아래와 같은 모델이 화면에 자동으로 생성되겠죠.

스크립트로 생성한 box

 스크립트에서 설정한 값이 잘 들어가 있는 것을 알 수 있습니다.

 

GeometryClass

그런데 위에 계층 구조를 보면 Box 위에 GeometryClass 라는 상위 클래스가 보이죠? 레퍼런스에서 해당 위치를 클릭해보면 GeometryClass 라는 녀석에 대한 정보가 나오는데요, 

"The mesh operations underlying the Boolean Compound Object in 3ds Max are accessible in MAXScript." 

라는 글이 해당 페이지의 첫줄에 보이고 

  • <node1> + <node2>
  • <node1>-<node2>
  • <node1>*<node2>

요런 수식들이 소개가 되어있습니다. 내용을 읽어 보면 GeometryClass 는 + - * 와 같은 연산자로 boolean 을 수행할 수 있다는 의미가 되겠습니다. Box 는 GeometryClass 이므로 당연히 Box 와 Box 는 위와 같은 boolean 연산이 된다고 볼 수 있겠습니다.

한번 해볼까요? 

myBoxA = box()
myBoxA.width = 50
myBoxA.Height = 50
myBoxA.Length = 50


myBoxB = box()
myBoxB.width = 150
myBoxB.Height = 25
myBoxB.Length = 25

myBoxB.pos.z = 12.5

요렇게 두개의 박스를 만드는 스크립트를 실행하면 

요런 형태의 두개의 박스가 생성이 됩니다.정육면체가 myBoxA, 길다란 육면체가 myBoxB가 되겠습니다.

자 그럼 myBoxA 에서 myBoxB를 빼 보도록 하겠습니다.

myBoxA = box()
myBoxA.width = 50
myBoxA.Height = 50
myBoxA.Length = 50

myBoxB = box()
myBoxB.width = 150
myBoxB.Height = 25
myBoxB.Length = 25
myBoxB.pos.z = 12.5

myBoxA - myBoxB

delete myBoxB

다른부분은 동일하고 마지막에 myBoxA 에서 myBoxB 를 빼는 수식을 추가한 다음 길다란 녀석을 삭제하는 코드를 추가하였습니다.

결과는요?

네. boolean 같은 복잡한 클래스를 사용하지 않아도 이렇게 쉽게 boolean 동작을 수행하는 군요. 

네 그럼 Box 뿐만 아니라 다른 geometryClass 의 모든 대상이 위와 같이 단순한 연산자를 이용하여 boolean 연산을 할 수 있다는 의미로 보시면 됩니다.

GeometryClass 에는 Box 외에도 Sphere 나 Cylinder, Tube 및 친근한 Teapot 같은 개체도 모두 GeometryClass 이므로 모두 동일하게 위와 같은 연산을 사용할 수 있다는 거죠.

GeometryClass 에는 아래와 같은 명령어도 지원합니다.

설명을 보면 

"Returns an array of two integers - the face count and the vertex count of the TriMesh on top of the modifier stack. "

라고 되어 있는데요, Sphere 를 하나 생성한 뒤 위의 코드를 한번 실행해 볼까요?

mySphere = Sphere()
GetTriMeshFaceCount mySphere

요렇게 작성한 뒤 실행해 보면 

$Sphere:Sphere002 @ [0.000000,0.000000,0.000000]
#(224, 114)

요런 결과가 리턴 됩니다. 첫째 줄은 생성된 sphere 에 대한 정보이고요, 두번째가 바로 작성한 코드의 결과물인데요. 위의 설명에 따르면 face 개수와 vertex 개수를 돌려 준다고 합니다. 생성된 sphere 는 224개의 face 와 114개의 vertex 로 이루어져 있다는 것을 알 수 있습니다. 다시 말하자면 우리는 생성한 geometryclass 가 뭐든간에 해당 개체의 폴리곤수를 바로 알 수 있게 되는 겁니다. mesh 나 poly 같은 개체의 geometry 속성 정보를 알기 위하여 class 구분을 하고 getNumfaces 나 polyop.getNumVertexs 를 사용하는 것처럼 개체의 클래스나 구성 방식 등을 검사를 할 필요가 없는거죠.

 

Node

자 그럼 한칸 더 상위로 올라가서 Node 를 볼까요?

Node 는 3DS MAX Script 에서 아주 중요한 개념으로 해당 클래스에서 사용할 수 있는 프라퍼티나 메소드가 아주 많습니다. 스크립팅의 아주 기본적인 부분도 많이 보이네요.

아주 간단한 예를 들면 우리가 scene 에서 보여지는 모든 개체는 node 라는 클래스라고 보면 됩니다. EditableMesh 건 EditablePoly 건 Camera 건 심지어 helper 나 dummy 같은 개체도 모두 node의 하위 클래스 입니다.

즉 Node 라는 개체에 대한 설명이 적혀있는 레퍼런스 페이지에 있는 모든 하위요소를 사용할 수 있습니다.

 제가 아~~주 자주 사용하는 node 의 대표적인 프라퍼티 또는 메소드를 보면 아래와 같습니다.

  • IsValidNode <var>
  • move <node> <point3> -- mapped
  • scale <node> <point3> -- mapped
  • rotate <node> <eulerangles> -- mapped
  • copy <node> -- mapped
  • reference <node> -- mapped
  • instance <node> -- mapped
  • delete <node> -- mapped
  • classOf <node>

딱 봐도 어떤 일을 하는지 아시겠죠? 우리가 알고있는 대부분의 요소는 node 이며 위와 같은 명령어를 이용하여 컨트롤 할 수 있답니다. 복사하고 이동하고, 회전하고 삭제하고, 해당 개체가 어떤 클래스인지 확인하는 그런 것들이죠.

Node Common Methods

 

라는 항목을 보면 Node 에서 사용할 수 있는 더 많은 상세한 레퍼런스들을 확인할 수 있습니다.

Node 클리스의 상세한 레퍼런스 들

이렇게 말이죠.

물론 Node 자신의 subClass 에는 GeometryClass, Shape, Light, Camera, Helper, SpacewarpObject, System 이러한 요소들이 있고 각기 자신에 해당하는 프라펕와 메소드들을 다룰 수 있지만 역시 node 에서 정의하고 있는 모든 프라퍼티와 메소드를 사용할 수 있는 것 입니다.

 

드디어 최상위 클래스 : Value

그럼 최상위 Value 라는 개체로 가 볼까요?

Value 개체는 3DS MAX 에서 정의하고 있는 class 의 최상위 개체입니다. 말하자면 모든 구조체, 클래스 등은 Value 에 속하므로 Value 에서 정의하고 있는 기능을 수행할 수 있는 것이라 할 수 있겠습니다.

최상위인 value 에는 대표적으로 다음과 같은 항목들이 정의되어 있습니다.

  • <value> == <value>
  • <value> != <value>

익히 잘 알고 있는 bool 연산자죠? if 구분 같은 곳에서 대상과 대상이 같은지 다른지 판단할 수 있고요. 

  • print <value>
  • format <format_string>

와 같은 코드를 통해서 해당 정보를 출력해 볼 수 도 있습니다. 

Working with Values

라는 레퍼런스 페이지에 보면 스크립팅을 하는 동안 Value 를 어떻게 다룰 수 있는지 잘 소개가 되어있습니다.

스크립트는 다른 개발 언어와 다르게 빠르게 작성하고 빠르게 컴파일, 실행을 할 수 있기 때문에 이런 구조체를 알면 디버깅도 빠르고 작성도 손쉽게 할 수 있겠습니다.

Value 에는 node 와 같은 scene 내의 개체 뿐만 아니라 Float ,Integer ,String ,BitArray ,Point3 ,Ray ,Quat ,AngAxis ,EulerAngles ,Matrix3 ,Point2 ,Color ,Arrays 와 같은 클래스나 구조체들도 포함되어 있습니다. Ray 에 대해서 지난 포스팅에 소개해 드렸었죠?

2022.05.31 - [DEV/MAX SCRIPT] - [3ds max script] ray 에 대하여 알아보기

 

[3ds max script] ray 에 대하여 알아보기

가끔 아니 어쩌면 자주 3D 공간안에서 물체의 위치를 지정할때 이 물체가 저쪽에 닿는 면에 딱 위치하고 싶은데... 할때가 있죠? 예를 들면 나무나 돌덩이 이런걸 랜덤하게 막 생성한 다음 굴곡진

diy-dev-design.tistory.com

사실 Value 는 정말 아~~주 아주 기본적인 속성들을 다루고 있다고 보시면 되고 해당 정보들 없이는 스크립팅이 불가능한 정말 개념이 없어도 늘 사용하는 그런 애들이라고 보시면 됩니다.

 

 

마치며

자 오늘 포스팅은 사실 개념적인 부분이어서 조금 어려울 수도 있을 것 같습니다.

하지만 스크립팅을 하다보면 저처럼 자연스럽게 알게 되기도 하고요. 또 이런 개념을 이해하고 스크립팅을 하면 훨씬 쉽고 유연하게 코딩을 하실 수 있을 거에요. 

저 처럼 무작정 코딩을 하며 배워가는 경우에도 "아~~~ 이게 이런거였어?!?!?" 이런 적이 셀 수 없이 많았거든요. 

 

자 다시 정리하자면 

  • 상위 클래스에서 정의되어 있는 프라퍼티나 메소드는 하위 클래스에서도 접근 할 수 있다.
  • 즉 name, rotate, move, delete, copy 같은 개념은 하위의 어떤 클래스에서도 사용할 수 있다.
  • 지금 보고 있는 개체의 상위 클래스가 무었인지 확인해 보자.

 

자 다들 화이팅하시고 스크립팅을 통해 에이스의 진면모를 보여주시기를 바라며 오늘의 포스팅을 마칩니다.

 

2021.02.26 - [DEV/MAX SCRIPT] - [3ds max script] vector 에 대하여

 

[3ds max script] vector 에 대하여

안녕하세요. 오늘은 디자이너라면 조금 생소할 수 있는 vector 라는 개념에 대하여 소개해 드릴까 합니다. 혹시 작년 쯤인가요? 슈퍼밴드라는 밴드 오디션 프로그램에서 F=ma 라는 곡으로 아주 인

diy-dev-design.tistory.com

2021.02.24 - [DEV/MAX SCRIPT] - 3da max script 점과 점 사이의 거리 구하기

 

3da max script 점과 점 사이의 거리 구하기

간단하게 포스팅을 남기려고 합니다. 제목 그대로 버텍스 간 거리 구하기 입니다. 아니 정확히는 두개의 point3 사이의 거리를 구하는 방법을 소개해 드릴까 합니다. 그리고 용용 편으로 두 점사

diy-dev-design.tistory.com

 

반응형
반응형

가끔 아니 어쩌면 자주 3D 공간안에서 물체의 위치를 지정할때 이 물체가 저쪽에 닿는 면에 딱 위치하고 싶은데... 할때가 있죠? 

예를 들면 나무나 돌덩이 이런걸 랜덤하게 막 생성한 다음 굴곡진 지형에 모두 딱 안착시키고 싶다거나요.

또는 어떤 물체를 기준으로 어떤 방향으로 뻗어 나갈때 무엇인가 닿는 물체가 있는지 검사하고 싶을때도 있지요.

이때 사용되는 개체가 바로 Ray 입니다.

실제로 Ray를 알기 전과 알고난 뒤는 정말 다른 세계라고 할수 있겠습니다.

 

자 오늘은 Ray 에 대하여 알아보도록 하겠습니다.

3D 는 정말 놀라울 정도로 기하학적인 수학의 결정체라 할 수 있겠습니다. 이를 구현하기 위하여 정말 얼마만큼의 수학적 노력이 있었는지 상상이 안될 정도 입니다.

오늘은 그 결정체중의 하나인 Ray에 대하여 알아볼텐데요. 3DS MAX 에서 Ray 는 두가지 명령어를 통해 사용됩니다.

intersectRay 와 intersectRayEx, intersectRayScene 이렇게 세가지 입니다. 사용하는 목적에 따라 구분하여 사용하시면 되는데요. 각각은 아래와 같습니다.

  • intersectRay : Ray 와 대상물체를 지정한 뒤 부딧히는 위치를 알아낸다.
  • intersectRayEx : 위와 동일하며 부딪힌 Face 정보와 부딪힌 면의 normal 정보를 돌려준다
  • intersectRayScene : 대상 개체를 지정하지 않고 Scene 내의 어떤 물체든 부딪힌 정보를 돌려준다. (느림)

사용하는 방법은 간단한데요, 먼저 Ray 를 생성해주고 필요하면 Ray의 출발 위치(pos)와 방향(dir)을 변경할 수 있습니다.

myRay = ray [0,0,0] [0,0,-1]

ray 를 생성하는 구문 인데요, [0,0,0] 위치를 출발점으로 하고 [0,0,-1] 을 방향으로 하는 ray 가 만들어 지게 됩니다. [0,0,-1] 이라 하면 z 축을 기준으로 아래쪽을 바라보는 방향이라고 보면 되겠죠? 

 

이렇게 만들어진 Ray를 위의 명령어와 함께 사용해볼까요?

임시로 테스트용 Scene 을 만들어 봄

먼저 위와 같은 Scene 을 만들어서 테스트 해보려 합니다. 노란색 공이 지면에 부딪히는 위치로 이동 시킬거에요. 중간에 네모 박스가 있지만 네모박스는 무시하고 지면에 위치시켜야 한다면 아래와 같이 intersectray 를 이용하여 위치시킬 수 있습니다.

-- ray 를 생성해 준다
myRay = ray [0,0,0] [0,0,-1]

-- 이동시킬 물체를 지정하자
obj = $Sphere001

-- ray 의 출발 위치를 물체의 중심으로 설정해보자
myRay.pos = obj.pos

-- 위치 검출에 사용될 지형을 지정해보자
tern = $terrain_01

-- intersectray 를 이용하여 지형과 부딪히는 위치를 찾아내자
interResult = intersectray tern myRay

-- 어떤 결과가 나왔는지 print 를 이용해서 살펴보자
print(interResult)

-- 부딪힌 위치에 오브젝트를 위치시키자
obj.pos = interResult.pos

요렇게 하면 어떻게 되냐면요

지면에 정확하게 안착함

요렇게 노란 공이 지면에 달라 붙게 됩니다. 코드에 주석을 달아 놓았으니 따로 설명은 안드려도 될 것 같은데요. 한가지만 설명해 드리자면 intersectray의 결과값을 보면 (ray [-1.62331,11.1008,1.22501] [-0.407511,-0.107746,0.906822]) 요런 식으로 ray 의 형식으로 결과가 나옵니다. ray 는 pos 와 dir 의 속성이 있지 않습니까?? 여기서 결과값의 pos 정보가 바로 부딧힌 면의 위치 정보가 됩니다. 그 뒤에 나오는 [-0.407511,-0.107746,0.906822] 는 부딪힌 면의 normal 값으로 만약 공이 부딪힌 다음 튕겨나간다거나 하는 다음 동작이 필요하다면 반드시 필요한 정보이지요.

어쨌든 intersectray 만 보자면 부딪힌 위치와 각도를 ray 의 형태로 돌려준다는 것을 알 수 있었습니다. 특징이라 하면 , 특정 개체를 대상으로 하기 때문에 속도가 매우 빠릅니다. 사실상 성능을 고려하지 않아도 되는 함수죠.

그런데 만약 부딪힌 면이 어디인지 알아야 하고 부딪힌 개체에도 뭔가 추가적인 액션이 필요할 수 있겠습니다. 사람일은 모르는거자나요? 누군가는 저 지형개체에 어떤 face에 물체가 부딪혔는지를 알아야 할수도 있지 않겠습니까? 이 때 intersectrayex 라는 함수를 이용하게 됩니다.

이번에는 intersectray 대신에 intersectrayex 를 사용해 볼 겁니다. 사용방법은 동일하고요. intersectrayEx [node] [ray] 와 같이 사용해 주면 됩니다.

-- intersectray 를 이용하여 지형과 부딪히는 위치를 찾아내자
interResult = intersectrayex tern myRay

-- 어떤 결과가 나왔는지 print 를 이용해서 살펴보자
print(interResult)

-- 결과는? 
#((ray [-1.62331,11.1008,1.22501] [-0.382998,-0.128105,0.914823]), 240, [0.383149,0.282177,0.334673])

아까와는 결과가 조금 다르죠? #(oo,oo,oo) 형태로 나온걸 보면 배열로 결과가 나온걸 알 수 있습니다. 총 3개의 리턴값이 나왔는데요.

  • (ray [-1.62331,11.1008,1.22501] [-0.382998,-0.128105,0.914823])
  • 240
  • [0.383149,0.282177,0.334673]

intersectray 와 마찬가지로 첫번째 결과에는 부딪힌 면의 위치, 방향을 담는 ray 정보가, 두번째에는 어떤 숫자가 나왔고요, 세번째에는 point3 형식으로 좌표가 나왔는데, 딱보니 위에 ray 에 부딪힌 면의 방향이라는 것을 알 수 있겠습니다. 두번째 숫자는 뭐냐고요?

부딪힌 face 의 index 임을 알 수 있다.

바로 부딪힌 mesh 의 face 인덱스 입니다. 240 번이죠? 바로 저부분에 부딪힌 것 입니다. (이번에는 이동은 하지 않았기 때문에..) 만약 동일하게 이동해야 한다면 배열 안의 개체에서 위치 정보를 뽑아내야 하므로 interResult[1].pos 와 같은 방법으로 부딪힌 면의 위치를 가져오면 됩니다.

이런 기능을 이용해서 부딪힌 면의 색상을 바꾸어 준다거나 해당 face를 삭제하는 등의 기능을 넣을 수 있겠지요? 뭐 레이저총에 맞은 face 가 폭파되며 사라지는 등의...  네.. 그럴때 꼭 필요한 훌륭한 명령어 입니다.

참고로 intersectray 나 intersectrayex 는 mesh 오브젝트에서 정확한 정보를 받아 올 수 있습니다. 가끔 기본 primatine 에 modifier 로 edit_poly 같은것을 씌운 경우에는 동작하지 않을 수 있으니 만약 결과값이 undefined 와 같은 값이 나온다면 검출에 사용된 모델링을 mesh 로 변경한 뒤 (convertTomesh obj) 검사를 진행하시면 됩니다.

 

끝으로 intersectRayScene 은 위와는 다르게 Ray 가 어떤 개체에 부딪히는지 알수 없을 때 사용합니다.

모두 동일하고 해당 명령만 intersectRayScene 으로 변경해서 돌려볼까요?

interResult = intersectrayScene myRay

요렇게 말이죠. 이번에는 대상을 특정하지 않기 때문에 함수 뒤에 인자가 ray 개체 하나만 들어갔습니다. 

결과를 볼까요? 

#(#($Editable_Mesh:terrain_01 @ [-4.616531,-2.612816,0.000000], (ray [-1.62331,11.1008,1.22501] [-0.382998,-0.128105,0.914823])), #($Sphere:Sphere001 @ [-1.623309,11.100846,65.260162], (ray [-1.62331,11.1008,61.9389] [0,0,-1])), #($Box:Box001 @ [15.646946,18.567043,19.666662], (ray [-1.62331,11.1008,26.4499] [0,0,1])))

뭔가 무시무시하게 길게 나왔죠?

이녀석도 역시 배열 개체이므로 하나씩 보면 

#($Editable_Mesh:terrain_01 @ [-4.616531,-2.612816,0.000000], (ray [-1.62331,11.1008,1.22501] [-0.382998,-0.128105,0.914823]))
#($Sphere:Sphere001 @ [-1.623309,11.100846,65.260162], (ray [-1.62331,11.1008,61.9389] [0,0,-1]))
#($Box:Box001 @ [15.646946,18.567043,19.666662], (ray [-1.62331,11.1008,26.4499] [0,0,1]))

요렇게 3개의 개체와 부딪혔다는 정보를 돌려준 것을 알 수 있습니다. 심지어는 본인(sphere) 에도 부딪힌 정보를 돌려 받았다는 것을 알 수 있네요 ㄷㄷㄷ. (저걸 원한건 아닌데) 부딪힌 정보를 보면 역시 내부 정보 역시 배열인데요, 첫번째는 부딪힌 대상 개체, 두번째는 부딪힌 위치정보 (ray 속성) 라는걸 알 수 있습니다.

만약 개체에 어떤 특정할만한 속성이 있다면 해당 개체에 물체를 위치 시킬 수 있습니다.

-- ray 를 생성해 준다
myRay = ray [0,0,0] [0,0,-1]

-- 이동시킬 물체를 지정하자
obj = $Sphere001

-- ray 의 출발 위치를 물체의 중심으로 설정해보자
myRay.pos = obj.pos

-- 위치 검출에 사용될 지형을 지정해보자
tern = $terrain_01

-- intersectray 를 이용하여 지형과 부딪히는 위치를 찾아내자
interResult = intersectrayScene myRay

-- 어떤 결과가 나왔는지 print 를 이용해서 살펴보자
print(interResult)

for i = 1 to interResult.count do
(
	testObj = interResult[i][1]
	if (findString testObj.name "Box") != undefined then
	(
		obj.pos = interResult[i][2].pos
	)
)

요렇게요. 

코드에서는 Box 라는 이름을 포함하는 개체를 만나면 해당 개체에 위치하도록 하는 코드 입니다.

이게 사실 한두개일 때는 간단한 이야기 인데 지면에 위치 시켜야 하는 개체가 수십개 ~ 수백개가 되면 일이 커집니다. 그럴때는 스크립트가 필요한 시점인거죠.

예를 들면 이렇게요..

이 많은 공들을 지면에 붙이라고?

 

모두 sphere 라는 이름을 갖고 있기때문에 간단하게 처리할 수 있겠네요. 지면에 닿는 개체는 지면에 닿도록 하고 box 에 닿는 개체는 box 에 위치시키도록 하겠습니다. 

sphere 의 중심을 기준으로 하다보니 약간 파뭍히는 대상이 있었는데요, sphere 의 반지름 만큼 위쪽으로 위치하도록 코드를 짜 보겠습니다.

-- ray 를 생성해 준다
myRay = ray [0,0,0] [0,0,-1]

-- 이름이 sphere 로 시작되는 모든 개체를 변수 objs 에 담자.
objs = execute("$Sphere*")

for obj in objs do
(
	-- 각 sphere 의 중심점으로 ray 의 위치를 지정함
	myRay.pos = obj.pos
	
	-- intersectray 를 이용하여 지형과 부딪히는 위치를 찾아내자
	interResult = intersectrayScene myRay


	for i = 1 to interResult.count do
	(
		testObj = interResult[i][1]
		if (findString testObj.name "Box") != undefined then
		(
			obj.pos = interResult[i][2].pos
			-- 파묻히지 않도록 반지름 만큼 위로 올림
			obj.pos.z += obj.radius
		)
		else if (findString testObj.name "terrain") != undefined then
		(
			--- 부딪힌 정보가 terrain 일때 해당 위치로 이동 시킴 
			obj.pos = interResult[i][2].pos
		-- 파묻히지 않도록 반지름 만큼 위로 올림
			obj.pos.z += obj.radius
		)
	)
)

 

뭐 별거 없죠? 위에서 설명한 것을 반복문만 추가했을 뿐 입니다.

결과는요?

한번에 모두 지면에 안착 성공

요렇게 예쁘게 안착된 것을 확인 할 수 있습니다.

물론 저는 본 기능을 설명 드리기 위해 위와 같은 예제를 들었지만요. 실제 제가 사용하는 함수에는 몇초만에 수천번 이상 위치를 검출하며 ray 가 사용되는 케이스가 허다분 합니다.

저는 주로 자동으로 모델링을 할때 모델링의 위치, 크기, 배치, 부딪힘, 확장 범위 등을 검사할때 사용하는데요, 이런 검사들을 통해 사람이 손을 데지 않고도 아주 정교한 모델링을 할 수 있는 근간이 됩니다.

참고로 intersectRayScene 의 경우 scene 의 모든 개체에 대하여 검사가 이루어지기 때문에 Scene 내에 아주 많은(수만개 이상의) node 들이 자리잡고 있는 경우에는 속도가 매우 느려질 수 있습니다. 그래서 시작 위치를 기준으로 반경내에 들어오는 대상을 먼저 골라낸 다음 속도가 빠른 intersectRay 를 이용하여 각각 부딪힌 위치를 검출하는 방식으로 사용하고 있습니다. 프로그래밍이라는게 그렇자나요. ㅎ 높은 성능과 효율성을 위해 다양하고 창의적인 방법으로 접근해 가는게 바로 프로그래밍의 묘미이지요.

오늘은 이만 마칩니다. 내용이 길어기니 힘드네요 ㅋ

2021.03.24 - [DEV/MAX SCRIPT] - 3DS MAX 스크립트 레퍼런스 (헬프파일) 다운 받기

 

3DS MAX 스크립트 레퍼런스 (헬프파일) 다운 받기

스크립트 초급자든 중급자든 반드시 필요한 것 하나를 꼽으라면 저는 레퍼런스라고 생각합니다. 기존에는 3DS MAX 설치 시에 함께 설치되어 스크립트 작성 창에서 F1 키를 누르면 chm 파일 형식의

diy-dev-design.tistory.com

2021.02.24 - [DEV/MAX SCRIPT] - 3da max script 점과 점 사이의 거리 구하기

 

3da max script 점과 점 사이의 거리 구하기

간단하게 포스팅을 남기려고 합니다. 제목 그대로 버텍스 간 거리 구하기 입니다. 아니 정확히는 두개의 point3 사이의 거리를 구하는 방법을 소개해 드릴까 합니다. 그리고 용용 편으로 두 점사

diy-dev-design.tistory.com

2020.04.29 - [DEV/MAX SCRIPT] - 3DS MAX 스크립트로 개체 선택하기

 

3DS MAX 스크립트로 개체 선택하기

Max Script 를 이용하여 무엇인가를 하려면 필수 요소라고 할 수 있는 것 중의 하나가 개체를 선택하거나 지정하는 방법입니다. 여기서 개체는 3D Scene 안의 오브젝트, 스플라인, 헬퍼 등과 같은 사

diy-dev-design.tistory.com

 

반응형
반응형

스크립트 초급자든 중급자든 반드시 필요한 것 하나를 꼽으라면 저는 레퍼런스라고 생각합니다. 기존에는 3DS MAX 설치 시에 함께 설치되어 스크립트 작성 창에서 F1 키를 누르면 chm 파일 형식의 레퍼런스 파일이 나타나 간편하게 사용을 했는데요. 언제부터인가 온라인 레퍼런스 사이트로 연결이 되기 시작했습니다.

내용상 큰 차이가 없더라도 매번 인터넷 페이지 안에서 검색하고 찾는 것보다 로컬에 저장되어 있는 chm 파일에서 찾고 검색하는 것이 훨씬 빠르고 쉽기 때문에 전느 chm 포멧의 레퍼런스를 선호하는 편입니다.

사실 autodesk 사이트에도 chm 파일을 배포하고 있는데 굳이 온라인 페이지로 연결 시켰는지 잘 이해가 가지 않는 부분입니다.

 

아래 경로에가시면 chm 형식으로 제작된 최신 레퍼런스 파일을 받으실 수 있으니 참고하시기 바랍니다.

www.autodesk.com/developer-network/platform-technologies/me-sdk-docs-2021

 

Media and Entertainment SDK Docs 2021 | Autodesk Developer Network

The Autodesk Media and Entertainment SDK page offers access to the latest documentation for the 2021 releases of the Autodesk Media & Entertainment SDKs. Use the links below to view the documentation in your browser, or to download the documentation to you

www.autodesk.com

위 페이지에 가셔서 아래 표시해 놓은 링크를 클릭하시면 로컬에 저장해 놓고 사용하실 수 있습니다.

빨간 박스 부분을 클릭하면 다운로드가 가능하다.

 

혹 해당 링크가 깨지는 경우를 대비하여 압축파일로도 업로드 해놓도록 하겠으니 아래 압축파일을 풀어 사용하시면 되겠습니다. 파일 4개를 모두 내려받으신 후 001 번을 압축해제 하시면 됩니다.

3dsmax-2021.1-maxscript-help-chm.zip.001
9.00MB
3dsmax-2021.1-maxscript-help-chm.zip.002
9.00MB
3dsmax-2021.1-maxscript-help-chm.zip.003
9.00MB
3dsmax-2021.1-maxscript-help-chm.zip.004
1.37MB

 

chm 파일은 파일 하나로 완전한 레퍼런스 북 입니다. 웹페이지에 비하여 색인도 훨씬 잘 되어 있고 로딩 시간도 필요치 않으며 오프라인 환경에서도 완벽하게 동작하는 훌륭한 녀석이라 할 수 있습니다.

스크립트 개발에 도움이 되시길 바랍니다.

 

감사합니다. 그럼 이만~

 

2021.03.03 - [DEV/MAX SCRIPT] - [3DS MAXscript] 스크립트 에디터 한글이 ??? 로 나오는 문제 해결 방법

 

[3DS MAXscript] 스크립트 에디터 한글이 ??? 로 나오는 문제 해결 방법

3DS MAX script 는 정말 훌륭한 개발 언어이지만 아쉬운점이 없는 것은 아닙니다. 대표적인 예가 바로 한글지원 문제인데요. 개발 코드 상에 한글이 지원되는건 바라지도 않습니다. 적어도 주석이라

diy-dev-design.tistory.com

2019.12.16 - [DEV/MAX SCRIPT] - 3DS MAX SCRIPT 강좌?? 무작정 시작하기 - 디자이너 추천

 

3DS MAX SCRIPT 강좌?? 무작정 시작하기 - 디자이너 추천

개발이라 하면 두드러기가 나는 디자이너 들이 있습니다. 아니 대부분 그렇죠. 이글을 읽고 계신 본인도 그러하다면, 그런데 스크립트로 무언가를 하고 싶다면 어쩌겠습니까.. 배워야지요. 그래

diy-dev-design.tistory.com

2019.06.12 - [DEV/Adobe Script] - 포토샵 스크립트 레퍼런스, 도움말 사용하기

 

포토샵 스크립트 레퍼런스, 도움말 사용하기

포토샵 스크립트 역시 다른 개발언어와 마찬가지로 도움말이 있습니다. 레퍼런스라고 해야할까요. 사실 개발자라고 해도 모든 명령어와 프라퍼티, 메소드를 외우고 있을 수는 없기 때문에 잘

diy-dev-design.tistory.com

 

반응형
반응형

간단하게 포스팅을 남기려고 합니다. 

제목 그대로 버텍스 간 거리 구하기 입니다. 아니 정확히는 두개의 point3 사이의 거리를 구하는 방법을 소개해 드릴까 합니다. 

그리고 용용 편으로 두 점사이의 어떤 특정 위치의 점의 좌표를 구하는 방법도 함께 알려 드리도록 하겠습니다.

어떤 물체가 점 A 로 부터 점 B 까지 움직이거나 A,B 사이의 특정위치를 알기 위한 계산을 하려면 필수적인 연산인데요.

예를들면 점 A 와 점 B 의 한 가운데가 되는 위치, 또는 점 A 로부터 점 B 까지의 0.2 정도 의 위치를 계산 하는 방법을 소개해 드릴까 합니다.

 

 

점과 점사이의 거리 구하기

점과 점 사이의 거리는 max script 에서는 아주 간단하게 구할 수 있답니다. 기본 명령어가 있기 때문인데요.

 

그림과 같이 박스 2개가 있는 경우 정 가운데 새로운 박스를 하나 만들어야 할 경우 사용하면 됩니다.

물론 저는 예를 box 로 들었지만 개체 A 의 어떤 점과 개체 B 의 어떤 점 사이의 위치를 구할때 동일하게 사용할 수 있는 예제 입니다.

boxA = $Box01
boxB = $Box02

ptA = boxA.center
ptB = boxB.center

distAB = distance ptA ptB -- 두점 사이의 거리를 계산한다.

간단하져?

distance 라는 명령을 이용하여 간단하게 두 점 사이의 거리를 구할 수 있습니다.

 

이제 정 가운데의 위치를 알아 볼까요?

공간상에서 위치를 이동시킨 값을 얻는 방법은 아래와 같습니다.

  • 최초 시작위치 + (이동할 방향 * 이동할 거리)

여기서 이동할 방향은 vector 라는 생소한 개념인데요. 나중에 설명을 드리도록 하겠습니다. 일단 vector 라고 하면 방향+거리 라고 간단하게 생각하시면 되겠습니다.

위의 예제를 활용하여 정중앙의 위치를 찾아보겠습니다.

boxA = $Box01
boxB = $Box02

ptA = boxA.center -- boxA 의 중앙 위치 (point3)
ptB = boxB.center -- boxB 의 중앙 위치 (point3)

distAB = distance ptA ptB -- 두점 사이의 거리를 계산한다.

-- 두점 사이의 정 가운데 위치를 찾아보자.
-- ptA --> pt2 방향으로 distAB / 2 한만큼 이동한 위치를 찾아보자

vector = ptB - ptA -- ptA -> ptB 방향 : ptB - ptA

vector = normalize(vector) -- normalize 를 이용하여 벡터(방향+거리) 에서 거리 개념을 제거한다.

ptC = ptA + (vector * (distAB / 2)) -- 시작위치 + (방향 * 이동할 거리)
	
boxC = box()
	
boxC.pos = ptC -- 새로 만들어진 boxC 의 위치를 구해진 정중앙으로 변경

 

요렇게 실행해 보면 아래와 같이 새로운 박스가 생성 됩니다.

가운데 녹색 박스가 두개의 박스 정 중앙에 생성되었다.

 

네 간단하죠? 실제로 제가 아주 많이 사용하는 계산 식으로 사용자 함수로 만들어 놓고 사용한답니다. 물론 정중앙이 아닌 1/3 지점, 아니면 어떤 위치도 설정이 가능합니다.

-- ptA --> pt2 방향으로 ratio 한만큼 이동한 위치를 돌려주는 함수
fn getPointBy2Point ptA ptB ratio =
(
	distAB = distance ptA ptB
	vector = normalize(ptB - ptA) -- 벡터(방향+거리) 에서 거리 개념을 제거한다.
	ptC = ptA + (vector * (distAB / 2)) -- 시작위치 + (방향 * 이동할 거리)		
	return ptC
)

 

이런식으로 만들어서 사용하는데요. 실제 사용할 때는 아래와 같이 사용하게 됩니다.

-- ptA --> pt2 방향으로 ratio 한만큼 이동한 위치를 돌려주는 함수
fn getPointBy2Point p1 p2 ratio =
(
	distAB = distance p1 p2
	vector = normalize(p2 - p1) -- 벡터(방향+거리) 에서 거리 개념을 제거한다.
	p3 = p1 + (vector * (distAB * ratio)) -- 시작위치 + (방향 * 이동할 거리)		
	return p3
)


boxA = $Box01
boxB = $Box02

ptA = boxA.center
ptB = boxB.center

ptC = getPointBy2Point ptA ptB 0.75 -- 위에서 작성된 함수를 이용하여 간단히 위치 계산

boxC = box()
boxC.pos = ptC

실행해 보면 두 박스 사이의 0.75 정도의 위치에 새로운 박스가 생성된 것을 알 수 있습니다.

 

위에서 만들어 놓은 함수를 이용하여 점 A 로부터 점 B 방향으로 1.0 이 넘으로 B 보다 더 멀리에 위치한 점을 얻을 수 있고요. 코드를 조금 수정하면 ratio 대신 직접 거리를 넣는 것도 간단히 구현할 수 있습니다.

 

공간상의 자동화 작업을 할 때 아주 자주 사용되는 기능이므로 저처럼 함수로 만들어 놓고 사용하셔도 좋겠습니다.

 

이만 오늘의 포스팅을 마치도록 하겠습니다.

 

 

반응형
반응형

오늘은 3DS MAX script 를 개발하면서 이해하면 도움이 될 용어 두가지를 설명 드릴까 합니다.

바로 property 와 method 입니다. 프라퍼티와 매소드 정도로 발음하시면 됩니다.

도대체 이게 뭐고 왜 이런걸 설명하는 걸까요? 

사실 몰라도 그만이기는 하지만 본격적으로 스크립트 개발을 하시려면 이해하고 넘어가시면 도움이 될 것 같아 작성하기로 마음 먹었습니다.

 

Property - 속성, 어떤 개체가 가지고 있는 속성을 가져오거나 변경한다.

Method - 명령, 어떤 개체에 대하여 일반적으로 필요한 여러가지 기능을 수행하도록 명령을 보낸다.

이라고 쉽게 생각하시면 됩니다. 실제 의미와는 조금 차이가 있긴 하지만 어쨌든 위와 같이 이해하시면 크게 다르지는 않습니다.

 

Property

일반적으로 프라퍼티는 어떤 클래스의 속성을 정의하는 지시어 입니다. 예를 들면

obj = $Box01

obj.Height -- 모델링의 높이, 읽고 쓰기 가능
obj.Width -- 모델링의 가로 폭, 읽고 쓰기 가능
obj.Length -- 모델링의 세로 폭, 읽고 쓰기 가능

obj.pos.x -- 모델링의 x 위치 , 읽고 쓰기 가능
obj.pos.y -- 모델링의 y 위치 , 읽고 쓰기 가능
obj.pos.z -- 모델링의 z 위치 , 읽고 쓰기 가능

obj.max.x -- 모델링의 바운드 박스 (공간 영역)중 가장 큰 x 위치 , 읽기만 가능
obj.max.y -- 모델링의 바운드 박스 (공간 영역)중 가장 큰 y 위치 , 읽기만 가능
obj.max.z -- 모델링의 바운드 박스 (공간 영역)중 가장 큰 z 위치 , 읽기만 가능

obj.min.x -- 모델링의 바운드 박스 (공간 영역)중 가장 작은 x 위치 , 읽기만 가능
obj.min.y -- 모델링의 바운드 박스 (공간 영역)중 가장 작은 y 위치 , 읽기만 가능
obj.min.z -- 모델링의 바운드 박스 (공간 영역)중 가장 작은 z 위치 , 읽기만 가능

와 같이 정의 했을 때 Height 나 Width, Length 는 Box() 라는 클래스(엄연히 말하면 pos, max 는 node 클래스의 프라퍼티 임)의 속성(프라퍼티)이 됩니다. 대부분의 경우 read/wright 가 지원되지만 경우에 따라서는 read 만 지원되는 경우도 있습니다. 무슨 말인가 하면 read 만 지원된다 하면 해당 프라퍼티를 불러올 수 는 있지만 사용자가 변경하지는 못한다는 뜻입니다. Height 나 width, length 는 변경이 가능하죠? 한번 해보세요.

 

 

Methode

method 는 명령이라고 말씀 드렸는데요. 보통 클래스를 만들때 해당 클래스를 제어할 수 있는 여러가지 기능을 한꺼번에 만들게 됩니다. 맥스 스크립트에서는 프라퍼티와 매소드를 굳이 크게 구분하고 있지는 않지만 엄연히 개념적으로 다르므로 이해하시면 좀 더 복잡한 스크립트 코딩에 도움이 됩니다.

대표적으로 editable_poly  같은 클래스를 컨트롤 하기 위한 polyop 라는 오퍼레이션 전용 클래스가 있는데 해당 클래스에 getvert 와 setvert 가 있습니다.
getvert 는 polygon 모델링의 특정 vertex 의 위치를 받아오는 기능이며 setvert 는 특정 버텍스의 위치를 설정(변경) 해주는 기능입니다. getvert 는 사실 프라퍼티에 가까운 기능이지만 setvert 는 분명 매소드처럼 동작 되는 것이죠.
맥스스크립트에서는 get/set 이 대부분 쌍으로 존재합니다.

obj = $ -- editabel poly

pt = polyop.getvert obj 1 -- 1번 버텍스의 위치를 가져온다.
pt.z += 10 -- 가져온 위치의 z 값을 +10 해준다
polyop.setvert obj 1 pt -- +10 된 위치를 다시 원래 버텍스에 세팅한다.

위의 예제는 polyop 라는 폴리곤 전용 오퍼레이션 매소드를 이용하여 버텍스의 좌표를 변경하는 대표적인 간단한 사례 입니다.

for 구분과 연계하여 아래와 같이 할 수도 있죠.

obj = $ -- editabel poly

vNum = polyop.getnumverts obj -- 버텍스의 개수를 가져온다.

for i = 1 to vNum do
(
	pt = polyop.getvert obj i -- i 번쨰 버텍스의 위치를 가져온다.
	pt.z += 10 -- 가져온 위치의 z 값을 +10 해준다
	polyop.setvert obj i pt -- +10 된 위치를 다시 원래 버텍스에 세팅한다.
)

 

물론 editable poly 자체가 가지고 있는 method 와 property 도 있습니다.

obj = $ -- editabel poly

obj.selectByMaterial  1 -- select by material id 1

위의 코드는 머테리얼 ID 1번인 모든 폴리곤을 선택해주는 기능(method) 가 되겠습니다. 뒤의 숫자를 바꿔주면 해당 머테리얼 ID 가 적용된 모든 폴리곤이 선택이 되겠죠.

 

 

맥스 스크립트에서 언급되는 개체는 상위 / 하위 개념을 가지고 있습니다. 이는 일반적으로 계층구조의 프로그래밍을 할때 보여지는 구조인데요. 상위 클래스 > 하위 클래스와 같은 형태인데 하위 클래스는 상위 클래스의 프라퍼티와 매소드를 상속 받아 동일하게 사용할 수 있습니다.

 

맨위의 사례에서 보여드린 .pos 라든가 .max .min 같은 프라퍼티가 대표적인 예인데요, 이는 node 라는 3ds max 의 최상위 클래스를 상속했기 때문입니다.

node 라는 클래스는 우리가 알고 있는 선택가능한 거의 모든 대상이 포함되며 이는 geometry 뿐만 아니라 shape 이나 helper, camera 까지도 모두 node 의 하위 클래스 입니다.

즉 node 클래스에서 정의하고 있는 모든 속성 및 명령을 해당 하위 클래스에서도 사용이 가능한 것입니다.

스크립트 개발하실때 가장 많이 참고하는 것이 바로 help 파일인데요. help 파일 (3ds max script reference)의 특정 개체에 대한 페이지 (예를 들면 editable mesh) 에 나와 있지 않더라도 해당 개체가 node 클래스의 하위 클래스라면 node 클래스에서 정의한 모든 속성과 기능을 사용할 수 있다는 것이죠.

 

How to use

프라퍼티나 매소드는 보통은 아래와 같이 사용됩니다.

클래스.명령어 -- 위에서 보여드렸죠?

명령어 <클래스> -- 실제로는 이런 경우가 많습니다.

위에서 말씀드린 node 클래스의 property/methode 들을 볼까요? 

F1 키를 누르신 뒤 검색 창에 node 를 쳐보시면 node 개체에 대하여 상세하게 설명이 되어 있습니다.

move <node> <point3> -- mapped
scale <node> <point3> -- mapped
rotate <node> <angle> <axis_point3> -- mapped -- angle in degrees
rotate <node> <quat> -- mapped
rotate <node> <eulerangles> -- mapped

이런식으로 사용되는 것이죠. 

앞의 move, scale 등은 node 에 사용할 수 있는 method 라고 할 수 있겠습니다.

말하자면 

명령어 <오브젝트> 옵션

이런 경우가 대부분이고 자주 사용됩니다.

 

 

자 간단하게 설명을 드렸지만 개념에 대한 부분이므로 어려울 수 있습니다.

솔직히 몰라도 스크립트 개발에는 큰 영향은 없습니다. 하지만 개자이너로 거듭나기 위하여 이정도 개념은 가지고 있어야 하지 않겠습니까? ㅋ 개발자들 눈이 동그라미가 될거에요.

끝으로 맥스 스크립트의 node 계층 구조를 간단하게 보여드리겠습니다. reference 에서 Hierarchy를 검색 하시면 max script 의 모든 계층 구조를 보실 수 있답니다.

Value
--MAXWrapper
----node   
------camera  
--------Freecamera 
--------Missing_Camera 
--------Targetcamera 
------GeometryClass  
--------Apollo_Param_Container 
--------apolloParamContainer 
--------Blizzard 
--------BoneGeometry 
--------BoneObj 
--------Boolean2 
--------Box 
--------C_Ext 
--------Capsule 
--------ChamferBox 
--------ChamferCyl 
--------Cone 
--------Conform 
--------Connect 
--------ControlContainer 
--------CV_Surf 
--------Cylinder 
--------Damper 
--------Editable_mesh 
--------Editable_Patch 
--------Editable_Poly 
--------EditablePolyMesh 
--------Gengon 
--------GeoSphere 
--------Hedra 
--------Hose 
--------L_Ext 
--------Loft 
--------LoftObject 
--------Mesher 
--------meshGrid 
--------Missing_GeomObject 
--------Morph 
--------Nurbs 
--------NURBS_Imported_Objects 
--------NURBSSurf 
--------OilTank 
--------OldBoolean 
--------PArray 
--------particleMesher 
--------PCloud 
--------Plane 
--------Point_Surf 
--------Point_SurfGeometry 
--------PolyMeshObject 
--------Prism 
--------Pyramid 
--------Quadpatch 
--------RingWave 
--------RmModel 
--------RmModelGeometry 
--------Scatter 
--------ShapeMerge 
--------SlidingDoor 
--------SlidingWindow 
--------Snow 
--------Sphere 
--------Spindle 
--------Spray 
--------Spring 
--------SuperSpray 
--------Targetobject 
--------Teapot 
--------Terrain 
--------Torus 
--------Torus_Knot 
--------TriMeshGeometry 
--------Tripatch 
--------Tube 
------helper  
--------Anchor 
--------AudioClip 
--------Background 
--------Billboard 
--------Bone 
--------BoxGizmo 
--------CamPoint 
--------Compass 
--------Cone_Angle 
--------ConeAngleManip 
--------CylGizmo 
--------Dummy 
--------Falloff_Manipulator 
--------FalloffManip 
--------FogHelper 
--------grid 
--------Hotspot_Manip 
--------HotspotManip 
--------IK_Chain_Object 
--------IK_Swivel_Manip 
--------IKSwivelManip 
--------Inline 
--------LOD 
--------Missing_Helper 
--------NavInfo 
--------Plane_Angle 
--------PlaneAngleManip 
--------Point 
--------PointHelperObj 
--------Position_Manip 
--------PositionManip 
--------Protractor 
--------ProxSensor 
--------radiusManip 
--------Reactor_Angle_Manip 
--------Reactor_Vector_Handle_Manip 
--------ReactorAngleManip 
--------ReactorVectorHandleManip 
--------Rotation_--
--------Rotation_Valuehelper 
--------RotationValueManip 
--------Slider_Manip 
--------SliderManip 
--------sliderManipulator 
--------Sound 
--------SphereGizmo 
--------Tape 
--------TimeSensor 
--------TouchSensor 
--------uvwMappingHeightManip 
--------uvwMappingLengthManip 
--------uvwMappingUTileManip 
--------uvwMappingVTileManip 
--------uvwMappingWidthManip 
------light  
--------Directionallight 
--------freeSpot 
--------Missing_Light 
--------Omnilight 
--------TargetDirectionallight 
--------targetSpot 
------NodeObject  
------shape  
--------Arc 
--------Circle 
--------CV_Curve 
--------CV_Curveshape 
--------Donut 
--------Ellipse 
--------Helix 
--------line 
--------LinearShape 
--------Lines 
--------Missing_Shape 
--------Ngon 
--------NURBSCurveShape 
--------Point_Curve 
--------Point_Curveshape 
--------Rectangle 
--------section 
--------Simple_Shape 
--------Simple_Spline 
--------SplineShape 
--------Star 
--------text 
------SpacewarpObject  
--------BendModWSM 
--------Bomb 
--------CameraMapSpaceWarp 
--------ConformSpaceWarp 
--------Deflector 
--------Drag 
--------gravity 
--------MapScalerSpaceWarp 
--------Missing_WSM_Object 
--------Motor 
--------Path_Follow 
--------PathDeformSpaceWarp 
--------PBomb 
--------PDynaFlect 
--------PDynaflector 
--------POmniFlect 
--------PushSpaceWarp 
--------SDeflector 
--------SDynaFlect 
--------SDynaflector 
--------SOmniFlect 
--------SpaceBend 
--------Spacedisplace 
--------SpaceFFDBox 
--------SpaceFFDCyl 
--------SpaceNoise 
--------Spaceripple 
--------SpaceSkew 
--------SpaceStretch 
--------SpaceTaper 
--------SpaceTwist 
--------Spacewave 
--------UDeflector 
--------UDynaDeflector 
--------UDynaFlect 
--------UOmniFlect 
--------Vortex 
--------Wind 
------System  
--------Bones 
--------Missing_System 
--------Ring_Array 
--------Sunlight 
--------XRefObject 

그럼 이만 오늘 포스팅을 마칩니다.

감사합니다.

 

2020/04/29 - [DEV/MAX SCRIPT] - 3DS MAX 스크립트로 개체 선택하기

2019/12/11 - [DEV/MAX SCRIPT] - 3DS MAX 스크립트로 초간단 다이얼로그 창 , UI 버튼 만들기

2019/06/01 - [DEV/MAX SCRIPT] - 3DS MAX Script 에 대하여

반응형
반응형

Max Script 를 이용하여 무엇인가를 하려면 필수 요소라고 할 수 있는 것 중의 하나가 개체를 선택하거나 지정하는 방법입니다. 여기서 개체는 3D Scene 안의 오브젝트, 스플라인, 헬퍼 등과 같은 사용자가 직접 선택할 수 있는 개체를 말합니다. 물론 오늘 강좌에서의 선택은 마우스를 클릭하여 선택하는 select의 개념만을 말하는 것은 아닙니다. 

예를 들어 A 라는 모델링 개체의 스케일을 2배로 변경한다고 했을 때 일반적인 사용자의 입장에서는 마우스로 해당 모델링을 클릭하거나 레이어 리스트에서 선택하거나 개체 리스트에서 해당 모델링을 선택 (select) 한 뒤 속성 등을 변경하게 되는데요. 스크립트에서는 굳이 select 의 상태를 만들 필요는 없습니다. 물론 동일하게 select 상태를 만들 수 있긴 하지만 성능 관점에서는 굳이 select 상태여야 할 필요가 없다면 바로 진행을 하면 됩니다.

참고로 본 강좌 진행을 위해 알아야 할 것은 이제부터는 개체를 노드(Node)라고 부를 것 입니다. 3DS MAX Script 에서 공식적으로 개체를 Node 라고 지정하였기 때문이고요. 레퍼런스 등을 보실때도 그렇게 이해하고 계신 것이 혼선이 없을 것 입니다.

우선 기본적인 방식을 살펴 보겠습니다.

  • selection 상태를 만드는 방법
  • 현재 선택된 개체를 가져오는 방법
  • selection 상태가 아닌 상태에서 개체를 지정하는 방법
    • 지정된 이름을 기준으로 지정하는 방법 (단수 개체)
    • 이름의 일부를 기준으로 지정하는 방법 (복수 개체)
    • 레이어 단위로 지정하는 방법
    • 모델링 클래스 단위로 지정하는 방법 (geometry, spline, ...)

 

이런 것들을 소개해 드릴 까 합니다.

이번 강좌의 내용만 잘 이해하셔도 3D Scene 내의 대부분의 개체를 선택하거나 지정하는 것이 가능합니다.

 

 

Selection 상태를 만드는 방법

먼저 기본형은 Select <Node> 의 형태로 되어 있습니다.

Node 는 $ 표시를 붙인 뒤에 개체의 이름을 적어주면 해당 노드를 지정하게 됩니다.

만약 $Box01 이라 하면 "Box01" 이라는 이름을 갖는 노드(개체)를 지칭하게 됩니다. 이녀석을 선택 (Select) 상태로 만드시려면 아래와 같은 방법을 사용하면됩니다.

Select $Box01

요 코드를 스크립트 에디터 또는 리스너(F11) 창 아래 하얀색 창에 적어주고 실행하면 "Box01" 이라는 이름을 갖는 모델링이 선택된 상태가 됩니다. 물론 Box01 이라는 개체가 존재해야 하지요.

A 라는 오브젝트를 선택한 뒤 B 라는 오브젝트를 추가로 선택하고 싶으신 경우 아래와 같이 코드를 작성하시면 됩니다.

select $Box01
selectmore $Box02

selectmore 라는 명령어를 이용하여 셀렉션을 추가할 수 있습니다.

 

 

 

현재 선택된 개체를 가져오는 방법

코드 작성을 하다보면 모든 기능이 시작부터 끝까지 자동화가 어려운 경우가 있습니다. 그런 경우 사용자에 의해 특정 개체를 선택한 뒤 부터 코드가 실행이 된다거나 하는 경우가 종종 있을 수 있습니다. 이럴때 현재 선택된 개체를 가져오는 스크립트가 필요한데요. 바로 아래와 같이 사용하시면 됩니다.

myObject = getCurrentSelection()

이렇게 하면 현재 선택된 개체들을 myObject 라는 변수로 가져올 수 있는데요. 아래와 같이 실재로 사용할 수 있습니다.

myObject = getCurrentSelection()

for obj in myObject do
(
	-- 선택된 개체에 대하여 수행해야 하는 코드를 작성한다.
    print (obj.name)
)

-- 또는

for i = 1 to myObject.count do
(
	obj = myObject[i]
    print (obj.name)
)

 


selection 상태가 아닌 상태에서 개체를 지정하는 방법

스크립트를 이용하여 자동화 업무를 하다보면 항상 선택이라는 액션이 발생되는 것은 아닙니다. 선택이라는 액션이 이루어 지는동안 속도가 많이 저하되기 때문에 자동화의 대상이 많을 수록 선택 과 같은 액션은 생략하는 것이 좋습니다. 개체가 선택될 때 마다 맥스에서는 UI 를 업데이트 해주어야 하는데요, 이때 성능이 많이 느려지게 됩니다. 아래의 내용에서는 선택 과정 없이 특정 개체에 직접 접근하는 간단한 사례를 설명하겠습니다.

 

지정된 이름을 기준으로 지정하는 방법 (단수 개체)

오브젝트의 이름을 알고 있는 경우 가장 손쉽게 개체를 지정할 수 있습니다. 보통은 코드 작성의 편의를 위하여 변수에 담아서 사용하는것이 일반적인 방법입니다. 위에 select 예제와 유사한 방식으로 지정하게 됩니다.

obj = $Box01
print (obj.name)

Box01 이라는 모델링 개체의 이름을 프린트 창에 출력하는 코드죠. 위와 같이 첫줄을 적어주면 obj 라는 개체가 갖는 다양한 속성들이나 명령들을 적용할 수 있게 됩니다. 예를 들어 해당 개체가 Box 라는 class 인 경우 아래와 같이 속성을 변경할 수 있게 됩니다.

obj = $Box01
print (obj.name)

-- 박스의 크기를 현재의 두배로 만들자
obj.width = obj.width * 2
obj.height = obj.height * 2
obj.length = obj.length * 2

-- 높이를 50 만큼 올려보자
obj.pos.z += 50 

 

요런식으로 사용하는 것이지요.

 

 

 

이름의 일부를 기준으로 지정하는 방법 (복수 개체)

이번에는 이름의 일부분만을 이용하여 개체를 지정하는 방법을 소개해보겠습니다.

예를 들어 "box01" , "box02",... "box99" 이런식으로 동일한 이름 구조를 갖는 복수개의 개체가 있는 경우에 해당됩니다. 

objs = execute ("$box*")

print objs.count

위에 보시면 execute 라는 명령어가 있는데요. 뒤쪽에 나오는 문자열을 실행 가능한 문장처럼 해석하는 것입니다. 문자열에는 "$box*" 이라는 형태로 씌어져 있는데 여기서 * 은 와일드 카드라고 불리는 글자 입니다. 다시말하면 box + 어떤 것이든 해당되는 문자열 이라고 보시면 됩니다. scene 내에 box 로 시작하는 모든 개체가 objs 라는 변수에 담기는 것이죠. objs 는 배열형 변수가 되어 실제 사용하실 때는 아래와 같이 하나씩 꺼내 쓸 수 있게 됩니다.

objs = execute ("$box*")

print objs.count -- 전체 담겨져 있는 개체의 수를 출력한다

for o in objs do
(
	print o.name -- 개체의 이름을 출력한다.
    -- 여기서 개체별로 하고 싶은 액션을 작성하면 됩니다.
)

-- 다른 방법으로는
for i = 1 to objs.count do
(
	print objs[i].name

)

 

위와 같은 형식으로 각각의 개체에 대하여 어떤 작업을 하는 것이 가능합니다.

 

 

레이어 단위로 지정하는 방법

그럼 이번에는 레이어 단위로 개체를 지정하는 방법을 알아보겠습니다. 

3DS MAX 작업을 하다보면 레이어를 기준으로 개체를 생성하고 관리하는 경우가 종종 있습니다. 물론 레이어 창을 열어서 해당 레이어 안의 개체를 선택해 줄 수 있겠지만 레이어가 많은 경우, 또는 특정 레이어에 항상 같은 작업이 반복되는 경우 레이어의 개체를 지정하여 액션을 만들어 주는 것이 유용할 때가 있습니다.

레이어 이름을 아는 경우 아주 간단하게 적용이 가능합니다.

myLayer = LayerManager.getLayerFromName "myObjects"

myLayer.nodes &objs

for  o in objs do
(
	print o.name
)

myObjects 라는 이름을 갖는 레이어의 모든 개체를 objs 라는 변수에 담는 코드 입니다. 

레이어.nodes 라는 명령어가 뒤에 따라오는 참조형 변수에 해당 레이어의 모든 노드를 담아주는 기능을 수행합니다. 

참조형 변수는 반드시 & 기호를 붙여 주어야 하며 미리 정의를 해줄 필요는 없습니다.

 

 

모델링 클래스 단위로 지정하는 방법 (geometry, spline, ...)

scene 내에 위에서 정의한 방식 외에도 여러 레이어에 포함되어 있고 다양한 이름으로 존재하는 개체를 지정해야 하는 경우도 많이 있습니다. 예를 들면 scene 내의 모든 geometry 나 spline, helper 등을 선택해야 할 때도 있기 마련입니다.

이럴 때 사용할 수 있는 간단한 방법이 있습니다.

for  o in objects do
(
	print o.name
)

scene 내의 모든 오브젝트에 대한 처리가 가능하게 하는 간단한 방법입니다.

여기서 사용된  objects 와 같은 개체를 오브젝트 셋이라 부를수 있는데요 다음과 같은 종류가 있습니다.

objects  --all the objects
geometry  --the standard 3ds Max categories... 
lights
cameras
helpers
shapes
systems
spacewarps
selection  --the current selection

어떤 변수에 위에 해당되는 셋을 선언해주면 scene 내의 모든 해당 클래스의 개체가 대상이 됩니다.

아주 간단하지만 강력한 기능이죠.

 

이렇게 다양한 방법으로 화면 내의 개체를 지정하고 지정된 개체에 대하여 필요한 어떤 작업을 수행하는 것이 가능합니다. 어렵지 않죠?

다음번에는 어떤 조건을 붙여서 개체를 지정하거나 피하는 방법을 소개해 드리겠습니다.

 

그럼 이만~

2022.05.31 - [DEV/MAX SCRIPT] - [3ds max script] ray 에 대하여 알아보기

 

[3ds max script] ray 에 대하여 알아보기

가끔 아니 어쩌면 자주 3D 공간안에서 물체의 위치를 지정할때 이 물체가 저쪽에 닿는 면에 딱 위치하고 싶은데... 할때가 있죠? 예를 들면 나무나 돌덩이 이런걸 랜덤하게 막 생성한 다음 굴곡진

diy-dev-design.tistory.com

2019/12/11 - [DEV/MAX SCRIPT] - 3DS MAX 스크립트로 초간단 다이얼로그 창 , UI 버튼 만들기

 

3DS MAX 스크립트로 초간단 다이얼로그 창 , UI 버튼 만들기

3DS MAX 스트립트를 이용하여 스크립팅을 하기 시작하면 MAX 로 할 수 있는 일이 너무나 많고 빠르게 진행된다는 것을 알 수 있게 됩니다. 이 놀라운 기능들을 스크립트를 매번 실행시키는 것이 번�

diy-dev-design.tistory.com

 

2019/12/16 - [DEV/MAX SCRIPT] - 3DS MAX SCRIPT 강좌?? 무작정 시작하기 - 디자이너 추천

 

3DS MAX SCRIPT 강좌?? 무작정 시작하기 - 디자이너 추천

개발이라 하면 두드러기가 나는 디자이너 들이 있습니다. 아니 대부분 그렇죠. 이글을 읽고 계신 본인도 그러하다면, 그런데 스크립트로 무언가를 하고 싶다면 어쩌겠습니까.. 배워야지요. 그래

diy-dev-design.tistory.com

 

반응형
반응형

개발이라 하면 두드러기가 나는 디자이너 들이 있습니다.
아니 대부분 그렇죠.
이글을 읽고 계신 본인도 그러하다면, 그런데 스크립트로 무언가를 하고 싶다면 어쩌겠습니까.. 배워야지요.
 
그래서 책을 사고 공부를 하려면 눈에 영 들어오지를 않습니다.
"hello world !"로 시작한 강좌는 몇 강 따라가다 보면 내가 뭘 하고 있는 것인지 모르겠고 어느 순간 무슨말인지 하나도 모르겠는 상태가 되고 결국 '올해도 포기~' 하는 단계에 이르게 되죠.
 
자 그렇지 않도록 한번 포스팅을 해볼까 합니다.
게임 업계에 계시든 건축쪽에 계시든 다른 어떤 분야에 계시던 간에 MAX script 를 이용하여 무언가를 해보고 싶으신 분들을 위하여 강좌 형태로 포스트를 남겨보겠습니다.
 
참고로 저는 디자이너 이며 수년간 맥스 스크립트를 이용하여 실무를 하고 있는 사람입니다. 물론 포토샵 스크립트도 사용하고 일러스트 스크립트도 사용하고요, VBA 나 VB.NET, C# .NET 도 이용하고 있습니다. 
어떤 언어인가가 중요한 것이 아니라 무엇을 개발 할 것인 가가 중요한거죠.
 

비 개발자도 개발할 수 있는 맥스 스크립트

자 그럼 시작해 볼건데요. 
이 카테고리를 통해서 뭘 다룰 것이냐 하면요. 간단한 맥스 스크립트 구문, 예제, 문법 등을 체계 적이지 않게 포스팅을 할것입니다. 체계적인 순간 갈길이 너무 멀어 힘들어 집니다. 그냥 쓸만한 스크립트들을 설명과 함께 올려보겠습니다.
예를 들면 이런 것 이죠.
<obj 파일 익스포트 예제> - 선택한 개체만

exportPath = "C:\\Users\\mnsoft\\Documents\\exporttest\\"

objs = getCurrentSelection()

for o in objs do
(
	clearselection()
	select o
	
	if (doesFileExist (exportPath + o.name + ".obj" )) then
	(
		exportfile (exportPath + uniqueName(o.name) + ".obj" ) #noprompt selectedOnly:true
	)
	else
	(
		exportfile (exportPath + o.name + ".obj" ) #noprompt selectedOnly:true
	)	
)

이러한 스크립트를 이용하면 아주 많은 시간을 단축할 수 있습니다. 코드를 개발하는 방법에 따라서 혁신 적으로 시간을 단축할 수도 있습니다. 어떤 작업을 자동화 할수 있는가를 정확하게 판단할수 있는 눈과 머리가 만들어 져야 합니다.
<scene 안의 모든 개체의 isolate vertex 제거하기>

objs = getCurrentSelection()

for o in objs do
(
	case (classof o) of
	(
		Editable_mesh:
		(
			meshop.deleteIsoVerts o
			break;
		)		
		Editable_Poly:
		(
			polyop.deleteIsoVerts o
			break;
		)		
		default:
		(
		)
	)	
)

이런 것들 입니다.
처음 시작하는 여러분들께 중요한 것은 코딩 실력이 아니라 무엇을 개발해서 나의 업무 시간을 줄일 것인가 를 빨리 찾아내는 것이죠.
필요한게 있으면 방법은 찾아지게 되어 있습니다.
본 카테고리를 통하여 가능한 손쉽게 해답을 찾는 방법도 설명 드리겠습니다.
빠르지는 않겠지만 천천히 따라오실 수 있도록 지속적으로 포스팅하도록 하겠습니다.
틈틈히 들어오셔서 업데이트 된 내용이 있으시면 차곡차곡 챙겨 가시기 바랍니다.
 
이번 카테고리에서 아래에 해당되는 내용들을 다루어 보겠습니다. (계속 추가 예정)

  • 점과 점 사이의 거리 구하기, 점과 점사이에 있는 특정 위치에 해당 되는 좌표 구하기
  • 특정 개체가 있는 위치로 카메라 move, zoom 시키기
  • 선택한 모든 개체들중 특정 클래스 (shape, mesh 등) 만 걸러내기, 또는 재 선택하기
  • 두 직선의 교점 구하기
  • sin, cos 을 이용하여 동그라미, 부드러운 곡선 그려보기
  • 폴리곤에 두께 주기
  • 여러개의 점을 직선화 하기
  • OBJ 파일 자동 익스포트 시 설정 변경하기
  • 좌표를 정수형으로 모두 이동 시키기
  • ASE 파일 익스포트 옵션 자동으로 설정하기
  • 대량의 파일 Import or merge 하기
  • 특정 max 파일 안의 특정 파일만 현재 scene 으로 merge 하기
  • 여러개의 맥스 스크립트 파일 불러들여서 사용하기
  • 다이얼로그 창 / UI 만들어 사용하기
  • UVW 맵 컨트롤 하기
  •  

필요하신 스크립트가 있으면 뎃글로 문의 남겨 주세요. 시간되면 한번 짜 보겠습니다. 
물론 외주 의뢰를 주셔도 됩니다. 저렴하게 개발해 드릴께요 ㅋ
 
mariine98@gmail.com
여기로 메일주시면 됩니다.

즐거운 코딩생활 되시길 바랍니다.
 
그럼 이만~
 
2020/04/29 - [분류 전체보기] - 3DS MAX 스크립트로 개체 선택하기

3DS MAX 스크립트로 개체 선택하기

Max Script 를 이용하여 무엇인가를 하려면 필수 요소라고 할 수 있는 것 중의 하나가 개체를 선택하거나 지정하는 방법입니다. 여기서 개체는 3D Scene 안의 오브젝트, 스플라인, 헬퍼 등과 같은 사��

diy-dev-design.tistory.com

 

반응형
반응형

3DS MAX 스트립트를 이용하여 스크립팅을 하기 시작하면 MAX 로 할 수 있는 일이 너무나 많고 빠르게 진행된다는 것을 알 수 있게 됩니다. 이 놀라운 기능들을 스크립트를 매번 실행시키는 것이 번거롭고 여러가지 기능을 한번에 수행하거나 관리할 수 있게끔 만들고 싶은 욕심이 생길 때가 있습니다. 그럴때 그런 기능들을 한곳에 모아 실행하기 위하여는 마치 어떤 툴이나 프로그램 처럼 UI 가 있는 것이 실행하기도 편하고 보기에도 좋을 것입니다.

그래서 오늘은 3DS MAX Script 를 이용하여 다이얼로드 창을 만드는 방법, 그리고 간단한 UI 를 적용하는 방법을 알아 보겠습니다.

  • 다이얼로그 창 만들기 / 버튼 만들어 기능 연결하기
  • 롤아웃 플로터 만들기

먼저 3DS MAX 에서 다이얼로그 창을 만들어 보겠습니다.

다이얼로그 는 윈도우에서 예/아니오 경고창과 같이 간단한 타이틀바와 닫기 버튼, 내부에 간단한 UI 들을 담을 수 있는데요. 기본적으로는 rollout 을 만들어 rollout 내부에 UI 를 담고 만들어진 rollout 을 다이얼로그창의 형식으로 보여주는 형태로 되어 있습니다.

 

다이얼로그 창 만들기 / 버튼 만들어 기능 연결하기

가장 기본형은 아래와 같습니다.

rollout myFirstRollout "my menu 01"
(
	button bt_myButton "press me!"
	
	on bt_myButton pressed do
	(
		messageBox "You got it!"
	)
	
)

createDialog myFirstRollout

먼저 롤아웃을 선언해 준 뒤 그안에 버튼을 하나 만들고 버튼을 눌렀을때 특정한 메시지를 팝업으로 보여주는 다이얼로그입니다.

바로 요렇게 만들어 지게 됩니다.

심플한 다이얼로그

가운데 있는 버튼을 눌러주면 아래와 같이 팝업으로 메시지가 출력이 됩니다.

messagebox 가 뜬 모습

 

자 이게 기본은 했고요. 다이얼로그의 크기, 위치, 버튼의 크기나 위치등을 지정하지 않았기 때문에 위와 같이 작게 표시가 되었는데요. 여기서 그 크기위 위치를 지정하는 방법을 알아보도록 하겠습니다.

제일 마지막 줄에 createDialog 라는 명령으로 만들어준 롤아웃을 다이얼로그라는 형태로 보여주었는데요. 이부분에서 다이얼로그릐 크기, 위치를 지정할 수 있습니다. 마지막 줄의 내용을 아래와 같이 수정해 보겠습니다.

createDialog myFirstRollout 300 200 100 100

요런 식으로 정의 할 수 있는데요. 4개의 숫자를 뒤에 연속해서 써주게 되는데

[가로길이] [세로길이] [윈도우상의 가로위치] [윈도우상의 세로위치]

의 순서로 적어주면 되며 뒤의 두가지 숫자를 생략하게 되면 화면의 중앙에 다이얼로그가 생성이 됩니다.

위의 코드로 수정한 뒤 실행하게 되면 아래와 같이 윈도우 좌측 상단에 가로 300 세로 200 픽셀의 다이얼로그 창이 만들어 지게 됩니다.

화면의 좌상단에서 열린 다이얼로그 창

버튼을 하나 추가해 볼까요?

rollout myFirstRollout "my menu 01"
(
	button bt_myButton1 "press me!"
	button bt_myButton2 "don't press me!"
	
	on bt_myButton1 pressed do
	(
		messageBox "You got it!"
	)
	
	on bt_myButton2 pressed do
	(
		destroyDialog myFirstRollout
	)
	
)

createDialog myFirstRollout 300 200 100 100

자 이제 버튼이 두개가 되었습니다. 두번째 버튼을 누르게 되면 다이얼 로그 창이 닫히는 그런 코드가 실행이 됩니다.

스크립트를 실행해 보면 아래와 같이 버튼이 두개가 표시됩니다.

다이얼로그에 버튼이 두개가 되었다.

그런데 저는 저 두개의 버튼을 가로로 배치하고 싶어서 코드를 약간 더 손을 보았습니다. 레이아웃을 조정하는 것이죠.

rollout myFirstRollout "my menu 01"
(
	button bt_myButton1 "press me!" pos:[10,10] width:130 height:30
	button bt_myButton2 "don't press me!" pos:[150,10] width:130 height:30
	
	on bt_myButton1 pressed do
	(
		messageBox "You got it!"
	)
	
	on bt_myButton2 pressed do
	(
		destroyDialog myFirstRollout
	)
	
)

createDialog myFirstRollout 300 200 100 100

맨위에 버튼을 만들어주는 부분에 pos 와 width, height 를 설정해 줌으로써 사용자가 원하는 위치와 크기로 버튼을 배치할 수 있습니다.

실행해보면 아래와 같이 변경이 됩니다.

두개의 버튼이 가로로 배치되었다

 

네.. 그럴싸 해 졌습니다.

롤아웃 플로터 (rollout floater) 만들기

이번에는 좀더 고급 UI 를 이용해 보겠습니다. 3DS MAX 의 우측에 보면 여러가지 옵션이나 설정을 입력하고 기능을 선택하는 메뉴바가 나오는데요. command pannel 이라고 합니다. 해당 패널에 보면 기능이 많은 경우 기능을 접었다 폈다 할 수 있는 형태로 메뉴가 만들어져 있습니다. 

유사한 기능끼리 그룹을 만들어 묶어주고 사용하지 않는 기능 그룹은 묶어 둘 수 있어 상당히 편리한 UI 라고 할 수 있겠습니다. 스크립트  UI 로도 거의 동일한 기능을 아주 쉽게 구현할 수 있습니다.

그런 기능들의 묶음이 위에서 보여주었던 하나의 롤아웃이 되며 롤아웃들을 하나의 창에 보여줄 수 있는 개체가 롤아웃 플로터 입니다.

간단한 예를 보여드리겠습니다.

rollout myRollout_ani "my Animation"
(
	button bt_myButton1 "run" pos:[10,10] width:130 height:30
	button bt_myButton2 "stop" pos:[150,10] width:130 height:30
	
	on bt_myButton1 pressed do
	(
		messageBox "No function now"
	)
	
	on bt_myButton2 pressed do
	(
		messageBox "No function now"
	)	
)

rollout myRollout_geom "my Geometry"
(
	button bt_myButton1 "convertTo mesh" pos:[10,10] width:130 height:30
	button bt_myButton2 "remove Iso Vertex" pos:[150,10] width:130 height:30
	
	on bt_myButton1 pressed do
	(
		messageBox "No function now"
	)
	
	on bt_myButton2 pressed do
	(
		messageBox "No function now"
	)	
)

myTool = newrolloutFloater "my custon tool" 300 300 100 100

addRollout myRollout_ani myTool 
addRollout myRollout_geom myTool 

myTool.open

두개의 롤아웃을 먼저 만들고 myTool 이라는 변수를 새로운 롤아웃 플로터로 설정한뒤 myTool 에 두개의 롤아웃을 추가합니다. 끝으로 만들어진 롤아웃 플로터를 보여주는 것이죠.

간단하지 않습니까?

실행하면 아래와 같이 됩니다.

두개의 롤아웃이 있는 메뉴가 만들어 졌다.

 

이렇게 만들어진 롤아웃 플로터내의 롤아웃 들은 아래와 같이 접는것도 가능합니다.

롤아웃은 말그대로 접어 올릴수 있는 메뉴다.

이제 제법 툴같이 만들어 졌습니다.

 

자 3DS MAX 에서 롤아웃을 만드는 것을 알아보았습니다.

이제 다음 강좌에서는 롤아웃 내의 버튼에 기능을 할당해 보도록 하겠습니다. 인터넷에서 긁어 모은 각종 스크립트 들을 저렇게 만든 롤아웃 플로터 하나에 모아두면 필요할때 빠르게 기능 동작이 가능할 것 입니다.

 

그럼 이만~

 

2020/04/29 - [분류 전체보기] - 3DS MAX 스크립트로 개체 선택하기

 

3DS MAX 스크립트로 개체 선택하기

Max Script 를 이용하여 무엇인가를 하려면 필수 요소라고 할 수 있는 것 중의 하나가 개체를 선택하거나 지정하는 방법입니다. 여기서 개체는 3D Scene 안의 오브젝트, 스플라인, 헬퍼 등과 같은 사��

diy-dev-design.tistory.com

 

2019/12/16 - [DEV/MAX SCRIPT] - 3DS MAX SCRIPT 강좌?? 무작정 시작하기 - 디자이너 추천

 

3DS MAX SCRIPT 강좌?? 무작정 시작하기 - 디자이너 추천

개발이라 하면 두드러기가 나는 디자이너 들이 있습니다. 아니 대부분 그렇죠. 이글을 읽고 계신 본인도 그러하다면, 그런데 스크립트로 무언가를 하고 싶다면 어쩌겠습니까.. 배워야지요. 그래

diy-dev-design.tistory.com

 

반응형

+ Recent posts