3ds Max에서 추가적인 features나 functionality를 사용하기 위해서는 plug-in이라는 c++ 코드가 필요하다.
이런 Plug-in을 통해, 추가적으로 geometric objects를 처리하거나 texture map, animation 등의 다른 여러 그래픽적인 요소들을 구현할 수 있다. (대표적인 유명한 rendering plug-in에는 Chaos Group에서 개발한 VRay가 있다! )
개발자들은 plug-in을 DLL(Dynamic Link Libraries)을 통해 구현할 수가 있는데, 이 DLL들은 Max SDK 안에 이미 정의되어있는 base class들을 기반으로 확장된 여러 class들을 가지고 있게 된다. (override 등의 member function을 사용하여 원하는 함수를 구현함) 3ds Max를 시작하면 plug-in을 포함한 경로에 있는 모든 DLL 파일들 중에, 아래 조건을 만족하는 DLL function을 export해야지만 load될 것이다. 이 function들은 DLL 파일 안에 몇 개의 plug-in이 있는지를 알려주고, 이 plug-in에 대한 정보들을 return한다.
3ds Max에서 요구하는 plug-in의 조건
DLL function
DLL entry point function(DLLMain()으로 named)이 있어야 함.
3ds Max를 위한 4가지의 function이 있어야 함. ((+2) : initializing, un-initializing)
DLL 안에 class의 개수 return
3ds Max SDK의 버전 return
user에게 plug-in에 대한 정보를 주는 짧은 string return
실제 plug-in이 가지고 있는 mechanism
Class descriptors
모든 plug-in 프로젝트는 'class descriptor'라는 class를 가지고 있음.
class descriptor는 plug-in의정보를 3ds Max에 전달하기 위한 여러 member function을 가지고 있음.
정보 : class ID, category, name
class descriptor는 주로 ClassDesc2(혹은 ClassDesc)를 통해 나온다.
Create() function을 구현하여, 3ds Max에 plug-in object에 대한 pointer를 제공하는 것이 중요하다.
Class ID
3ds Max는 plug-in을 이름이 아니라 ID에 의해 인식함. (2가지의 서로 다른 plug-in이 같은 이름을 가지고 있어도 ID가 다르면 공존 가능)
만약 같은 ID를 가지는 두 plug-in이 존재할 경우, 3ds Max는 그 중 하나만 load한다.
DEF Files
.DEF file을 DLL project에 추가하여, name이나 function의 순서 등에 대해 자세히 설명할 수 있다.
6개의 필수적인 plug-in function을 .DEF 파일 안에 나열함으로써, 3ds Max에게 이 function들이 구현되었고, call될 준비가 되어있다는 것을 알려줄 수 있다!
.DEF 파일이 없어도 plug-in들을 load하는 것이 가능하긴 하지만, howto / samples sub folders 안의 plug-in과 상응가능하게 하기 위해 보통 추가한다.
하나의 독립된 application과는 달리, plug-in은 3ds Max가 호출할 수 있는 여러 member function을 구현하는 것이다.
각 plug-in들은 기존에 정의된 base class를 기반으로 확장된 것이고, 원하는 기능들을 이를 통해 구현할 수 있다!
Plug-in Wizard (AppWizard)
3ds Max Plug-in Wizard(AppWizard)는 3ds Max에서 사용하는 plug-in의 skeleton code를 제공해주는 visual studio 전용 add-in이다. visual studio에서 프로젝트를 새로 생성할 때, 이 wizard를 사용한다면 원하는 plug-in type을 입력하면 필요한 기본 틀을 제공해준다.
3ds Max에 max sdk를 설치하면, Autodesk 폴더 안에 3ds Max 20xx SDK라는 폴더가 생기는데, 이 아래의 maxsdk\howto\3dsmaxPluginWizard 폴더의
3dsmaxPluginWizard.ico
3dsmaxPluginWizard.vsdir
3dsmaxPluginWizard.vsz
를 Visual studio 안의 vcprojects 폴더 안에 붙여넣기 하면 자동으로 add-in이 설치된다. 나의 경우 C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\VC\vcprojects\Extensibility 안에다 붙여넣었더니 제대로 실행이 잘 되었다. 처음에 visual studio 2019를 설치한 후 vcprojects 폴더가 없었는데, visual studio installer에서 확장프로그램을 추가로 설치한 이후 vcprojects 폴더가 생겼다.
그 후, 붙여넣은 파일 중 3dsmaxPluginWizard.vsz을 편집하는데, 검색해본 결과 Visual studio 2019를 사용하기 위해서는, Wizard=VsWizard.VsWizardEngine.16.0 으로 수정해야 한다고 하여 그대로 진행하였다. ABSOLUTE_PATH로 되어있는 부분도 Param="ABSOLUTE_PATH = [Absolute Path Location of 3dsmaxPluginWizard Root Directory]" 로 변경해준다. 변경한 후 visual studio를 실행하면 3ds max plugin으로 프로젝트를 실행할 수 있다.
Sample plug-in 예제
3ds max plugin 프로젝트를 만들면, 여러 템플릿이 있고 이 중에 원하는 것을 고를 수 있다.
진행하다보면, 3가지 path를 입력하는 부분이 있는데 maxsdk의 위치, plugin의 위치, 3ds Max의 위치 등 요구하는 경로를 지정해주면 된다. 전부 입력 후 진행하면 아래의 파일들이 자동으로 생기게 된다. (아래는 간단한 설명)
<yourprojectname>.def
DLL의 various attributes에 대한 설명. (위에서 더 자세히 설명함) 6개의 plug-in 파일들을 나열함.
DllEntry.cpp
DLL functions + DLL entry point function을 가지고 있음. DLL이 loaded될 때 Windows에 의해 call되거나, rendering할 때마다 call될 수도 있음. 이 부분은 항상 똑같아야 한다!
<yourprojectname>.rc
plug-in에 필요한 windows resource들. plug-in name/category/description string. UI panel. 이 부분을 수정할 수 있지만, 3ds max에서 필수로 요구하는 부분이 아니다.
3dsmaxsdk_preinclude.h
compile-time-to-do 메세지를 위한 매크로. plug-in을 수동으로 만들 때는 필요하지 않다.
resource.h
constant value들을 위한 헤더. plug-in을 수동으로 만들 때는 필요하지 않다.
<yourprojectname>.h
내 plug-in class를 위한 헤더. 해당 예제에서는 Utility 종류의 프로젝트로 시작했기 때문에 utilapi.h를 포함함.
- hInstance : OS memory 공간 안에 있는 plug-in DLL module을 위한 Handle - GetString() : name/category/description을 위한 string call.
<yourprojectname>.cpp
이 예제는 utility plug-in이기 때문에, UtilityObj class로부터 확장되었다. 이 안의 기본 뼈대 코드는 전부 제공되고, 내가 필요한 부분을 채워나가야 원하는 plug-in을 완성시킬 수 있다.
이 중 <yourprojectname>.cpp을 수정하면 원하는 plug-in을 대부분 작성할 수 있다.
** 솔루션을 빌드하는 데, .h파일이나 .dlu파일을 열 수 없다는 오류가 나서 이에 대해 써보자면
1. visual studio에서 MFC, SDK 관련 extension들을 설치해야 한다.
위키피디아에 의하면, Voronoi Diagram은 평면을 특정 점까지의 거리가 가장 가까운 점의 집합으로 분할한 것이다.
평면들에 있는 점(seed point)들 중 가장 가까운 점 2개를 모두 연결하고, 그 선들의 수직이등분선을 그어서 분할되는 것들이 보로노이 다각형(서로 다른 색으로 칠해져있는 다각형들)이다. 과정은 아래와 같은데, 여기서 점들을 연결하는 방법을 Delaunay triangulation(들로네 삼각분할)을 사용한다. 이에 대해서는 아래 section에서 설명하도록 하겠다.
보르노이 다이어그램은, proximity information을 담고 있다. 예를 들어, 각 seed point를 도시 하나에 분포하고 있는 가게(shop)라고 하면, 이 다이어그램을 통해 "주어진 point X와 가장 가까운 가게는 어디인가?"와 같은 문제를 풀 수 있다.
What is Delaunay triangulation?
Wiki : Delaunay triangulation
Delaunay triangulation(들로네 삼각분할)은, 다음의 조건을 만족하는 삼각형들의 집합을 만드는 분할이다.
평면위의 점들을 삼각형(simplex. 2D에서 그냥 triangle로 지칭함)으로 연결하여 공간을 분할할 때, 이 삼각형들의 내각의 최소값이 최대가 되도록 하는 분할을 말한다.
(b) O (c) X
즉, (a)와 같이 점들이 있을 때, 이 점들을 연결하여 삼각형을 만드는 방법들이 (b), (c)와 같이 다양한데, (b)와 같이 최대한 정삼각형에 가깝도록 분할하는 기법이다.
삼각형으로 이루어지는 circumsphere(외접원)의 내부에 삼각형을 이루는 세 point 외의 다른 point가 존재하지 않아야 한다.
Voronoi diagram and Delaunay triangulation
보로노이 다이어그램과 들로네 삼각분할은 서로 dual image 관계에 있다. (= 하나를 알면 다른 하나도 바로 알 수 있음)
Voronoi diagram -> Delaunay triangulation
서로 인접한 보로노이 다이어그램의 seed point들을 연결하면 들로네 삼각분할들이 얻어진다.
Delaunay triangulation -> Voronoi diagram
들로네 삼각분할로 구한 삼각형들의 외접원들의 중심을 연결해보면 보로노이 다이어그램이 나온다.
black point : seed points, red point : center of the circumcircle
Convex Hull이란 2차원 평면상에 점이 여러 개가 있을 때, 이 점들 중 일부를 골라서 나머지 점들을 모두 포함하는 볼록 다각형을 만드는 것을 말한다.
(b) is the convex hull of inputs of (a)
Delaunay triangulation을 이용하여 convex hull을 구하기 위해서는, 원래의 input들의 집합에 외부의 점 3개를 추가하여 Delaunay triangulation을 구한 후 어떤 점들이 새로 추가된 외부의 점과 삼각형을 이루었는지를 조사하면 된다. 그 후, 새로 추가한 외부의 점과 삼각형을 형성한 점들을 연결하면 원래 점들에 대한 convex hell을 구할 수 있다.
로봇 내비게이션
로봇이 길을 찾아 목적지까지 이동할 때, 주변 장애물과 부딪히지 않고 안전한 길을 찾아야 한다. 보로노이 다이어그램을 통해 이동경로를 생성하면, 공간의 가장 빈 곳을 따라 이동하기 때문에 안정성을 확보할 수 있다.
위의 그림은 미국 전 대통령 오바마의 사진을 openCV library(Dlib)를 통해 얼굴의 특징점(Facial landmarks)이 되는 점을 찾은 것이다. 순서대로, 가운데 이미지는 이 점들을 seed point로 두고 Delauny triangulation을 구한 것이다. 오른쪽 이미지는 이에 상응하는 보로노이 다이어그램이다. Subdiv2D를 통해 Delauny triangulation이나 보로노이 다이어그램은 쉽게 구할 수 있다.