2004년 01월 22일
Maya API 강좌 3
/*
먼저, API 연재 #2에서 제가 실수한 것을 정정하도록 하겠습니다.
송준택님께서 지적해 주셨듯이, DeclareSimpleCommand는 function이 아니라 Macro입니다.
그 외 많은 분들의 관심과 참여에 감사드립니다.

아, 그리고, 제가 인용하는 Source 코드는 Maya Manual 중에서
Maya Developer's Tool Kit의 Maya API Developer's Manual 에서 가져 온 겁니다.
더 자세한 사항을 보고 싶으신 분들은 이 문서를 직접 참고하시기 바랍니다.
*/

3. API MEL command with MEL UI
_______________________________________________

API 연재 #2를 잘 따라하신 분들이라면, 이제 뭔가 좀 만들어 보고싶다는 생각을 하실 겁니다.
그래서, 이번엔 argument를 가지는 MEL command를 API를 사용해서 만들어보고, 이 MEL command를 이용하기 편하도록 UI를 MEL을 사용하여 만들어 보도록 하겠습니다.

1) Maya Plug-in Wizard
_______________________________________________

API 연재 #2를 기억하시면서 이제 MS Visual C++을 실행시키고, File > New를 선택하시고, Projects 탭에서 Maya Plug-in Wizard를 선택하세요.
그리고, Location부분엔 Project를 만들 위치를, Project name 부분엔 doHelix라고 입력하세요.

그 다음, OK를 누르고, 여기서 해당 Maya 버전을 선택하시고, Plug-in 개발자 이름을 입력한 뒤, Next를 누릅니다.

어떤 종류의 Plug-in을 만들지를 고르는 화면에서는 이번에 만들 doHelix 역시 간단한 MEL Command이므로, MEL Command를 선택하고, Maya type name란에 doHelix라고 입력합니다. 그리고, Next를 누릅니다.

Plug-in에 포함될 Library를 선택하는 화면에서 doHelix는 간단한 Command이므로 가장 기본이 되는, Foundation과 OpenMaya만 선택하면 됩니다. 이제 Finish를 누르세요.

대충 아래와 같은 코드 뼈대가 만들어졌을 겁니다. 이제 이 뼈대에 살을 붙일 차례죠.

//
// Copyright (C) 2001 Gyedo Jeon
//
// File: doHelixCmd.cpp
//
// MEL Command: doHelix
//
// Author: Maya SDK Wizard
//

// Includes everything needed to register a simple MEL command with Maya.
//
#include <maya/MSimple.h>

// Use helper macro to register a command with Maya. It creates and
// registers a command that does not support undo or redo. The
// created class derives off of MPxCommand.
//
DeclareSimpleCommand( doHelix, "Gyedo Jeon", "4.0");

MStatus doHelix::doIt( const MArgList& args )
//
// Description:
// implements the MEL doHelix command.
//
// Arguments:
// args - the argument list that was passes to the command from MEL
//
// Return Value:
// MS::kSuccess - command succeeded
// MS::kFailure - command failed (returning this value will cause the
// MEL script that is being run to terminate unless the
// error is caught using a "catch" statement.
//
{
MStatus stat = MS::kSuccess;

// Since this class is derived off of MPxCommand, you can use the
// inherited methods to return values and set error messages
//
setResult( "doHelix command executed! " );

return stat;
}

2) #include
_______________________________________________

doHelix는 사용자로부터 helix의 radius와 pitch를 입력받아 NURBS Curve로 helix를 그리는 MEL command입니다. 따라서, NURBS Curve를 만들어야 하는데 MFnNurbsCurve를 이용하면 NURBS Curve를 만들 수가 있습니다. 그런데, NURBS Curve를 만드려면, Curve Point들의 좌표와 Knot들의 값이 있어야 합니다. Maya API에는 Maya안에서의 좌표를 저장할 수 있는 MPoint라는 Class가 있고, 이 MPoint들의 array인 MPointArray가 있습니다. 또한 Knot 값들은 MDoubleArray를 이용해서 저장할 수 있습니다.

이러한 Maya API class들을 사용하려면 해당 header file들을 include해야 합니다. 그리고, sin, cos등의 기본 수학 함수를 사용하기 위해 C++ 표준 library인 math.h를 include해야 합니다. 아래의 코드와 같이 #include문을 사용하셔서 include 하세요. (여기서 C/C++ 프로그래밍에 대하여 설명하지는 않을 테니, C/C++을 잘 모르시는 분들은 다른 소스를 참고하시기 바랍니다.)

#include <math.h>
#include <maya/MSimple.h>
#include <maya/MPoint.h>
#include <maya/MPointArray.h>
#include <maya/MDoubleArray.h>
#include <maya/MFnNurbsCurve.h>

3) doHelix::doIt
_______________________________________________

doHelix 명령과 해당 class를 만들어주는 DeclareSimpleCommand 구문은 그냥 놔두시면 됩니다. 그리고 실제 helix를 만드는 doIt function을 만들어야죠.

MStatus stat;

const unsigned deg = 3; // Curve Degree
const unsigned ncvs = 20; // Number of CVs
const unsigned spans = ncvs - deg; // Number of spans
const unsigned nknots = spans+2*deg-1; // Number of knots
double radius = 4.0; // Helix radius
double pitch = 0.5; // Helix pitch
unsigned i;

MPointArray controlVertices;
MDoubleArray knotSequences;


위의 코드 들과 같이 사용하게 될 변수들을 선언합니다. NURBS curve를 만드는 데는 Curve의 degree, CV 개수, Spand의 개수, Knot value등이 필요하죠. 그리고, CV들의 좌표를 저장하기 위해, MPointArray 타입의 controlVertices와 Knot value들을 저장하기 위해 MDoubleArray 타입의 knotSequences를 선언했습니다.

이번엔, 사용자로부터 입력받은 argument들을 parsing하는 부분입니다. MArgList class의 length와 asDouble등의 function을 사용해서 아래의 코드와 같이 argument 값을 읽어들입니다.

// Parse the arguments.
for ( i = 0; i < args.length(); i++ )
if ( MString( "-p" ) == args.asString( i ) )
pitch = args.asDouble( ++i );
else if ( MString( "-r" ) == args.asString( i ) )
radius = args.asDouble( ++i );

이제 필요한 정보가 다 모였으니 실제 helix의 position을 구해 봅시다. helix를 만드는 algorithm은 간단합니다. radius * cos을 X좌표로, radius * sin을 Z좌표로 사용하면 Top View에서의 원을 그릴 수가 있는데, 이렇게 하면서 Y 좌표를 조금씩 키워나가는 방법으로 helix를 만드는 겁니다. helix의 position array는 이렇게 만들었고, knot값들은 0부터 시작해서 순차적으로 증가하게 만들었습니다. (NURBS에서의 knot 값에 대하여도 여기서 설명하지 않겠습니다. ^^;)

// Set up cvs and knots for the helix
//
for (i = 0; i < ncvs; i++)
controlVertices.append( MPoint( radius * cos( (double)i ),
pitch * (double)i, radius * sin( (double)i ) ) );

for (i = 0; i < nknots; i++)
knotSequences.append( (double)i );

이렇게 만들어진 정보로 curve를 만드는 부분입니다. 앞에서도 이야기했듯이, Curve를 만드는데는 MFnNurbsCurve class가 사용됩니다. 먼저 MFnNurbsCurve class의 인스턴스를 하나 만들고, create function을 이용해서 Curve를 만들면 됩니다. MFnNurbsCurve class에 대한 자세한 정보는 Maya Manual 중에서 Maya Developer's Tool Kit의 Class 도큐먼트를 참고하세요. C:AW에 Maya를 설치하셨다면 여기를 누르시면 도큐먼트가 나옵니다.

// Now create the curve
//
MFnNurbsCurve curveFn;

MObject curve = curveFn.create( controlVertices,
knotSequences, deg, MFnNurbsCurve::kOpen, false, false, MObject::kNullObj,
&stat );

if ( MS::kSuccess != stat )
printf("Error creating curve. ");

완성된 코드는 다음과 같습니다. 이제 F7을 눌러서 Compile하시면 debug section에 doHelix.mll 이 만들어질겁니다. 다음 연재에서 이 코드를 사용해서 Debug하는 법을 가르쳐드릴테니까 release로 Compile하지 마세요.

//
// Copyright (C) 2001 Gyedo Jeon
//
// File: doHelixCmd.cpp
//
// MEL Command: doHelix
//
// Author: Maya SDK Wizard
//

// Includes everything needed to register a simple MEL command with Maya.
//
#include <math.h>
#include <maya/MSimple.h>
#include <maya/MPoint.h>
#include <maya/MPointArray.h>
#include <maya/MDoubleArray.h>
#include <maya/MFnNurbsCurve.h>

// Use helper macro to register a command with Maya. It creates and
// registers a command that does not support undo or redo. The
// created class derives off of MPxCommand.
//
DeclareSimpleCommand( doHelix, "Gyedo Jeon", "4.0");

MStatus doHelix::doIt( const MArgList& args )
//
// Description:
// implements the MEL doHelix command.
//
// Arguments:
// args - the argument list that was passes to the command from MEL
//
// Return Value:
// MS::kSuccess - command succeeded
// MS::kFailure - command failed (returning this value will cause the
// MEL script that is being run to terminate unless the
// error is caught using a "catch" statement.
//
{
MStatus stat;

const unsigned deg = 3; // Curve Degree
const unsigned ncvs = 20; // Number of CVs
const unsigned spans = ncvs - deg; // Number of spans
const unsigned nknots = spans+2*deg-1; // Number of knots
double radius = 4.0; // Helix radius
double pitch = 0.5; // Helix pitch
unsigned i;

MPointArray controlVertices;
MDoubleArray knotSequences;

// Parse the arguments.
for ( i = 0; i < args.length(); i++ )
if ( MString( "-p" ) == args.asString( i ) )
pitch = args.asDouble( ++i );
else if ( MString( "-r" ) == args.asString( i ) )
radius = args.asDouble( ++i );

// Set up cvs and knots for the helix
//
for (i = 0; i < ncvs; i++)
controlVertices.append( MPoint( radius * cos( (double)i ),
pitch * (double)i, radius * sin( (double)i ) ) );

for (i = 0; i < nknots; i++)
knotSequences.append( (double)i );

// Now create the curve
//
MFnNurbsCurve curveFn;

MObject curve = curveFn.create( controlVertices,
knotSequences, deg, MFnNurbsCurve::kOpen, false, false, MObject::kNullObj,
&stat );

if ( MS::kSuccess != stat )
printf("Error creating curve. ");

return stat;
}

4) helix.mel
_______________________________________________

이제 Maya를 실행해서 Plug-in Manager에서 doHelix.mll을 load하고, Script Editor에서 doHelix 라고 입력해 보세요. radius와 pitch를 주지 않아도 기본값인 4.0, 0.5를 사용해서 helix가 만들어 질 겁니다. 이번엔, doHelix -r 8.0 -p 1.0 이라고 입력해 보세요. radius가 8.0, pitch가 1.0인 helix가 만들어지죠?

이번엔 간단한 MEL을 만들어서 이 doHelix command의 UI를 만들어 보겠습니다. Maya Script를 이용해서 다음과 같이 입력하세요.

global proc helix()
{
window -t "HelixUI" helixWin;
columnLayout -adjustableColumn true;
floatSliderGrp -l "Radius" -v 4.0 -f true helixRadius;
floatSliderGrp -l "Pitch" -v 0.5 -f true helixPitch;

button -l "Make Helix" -c "makeHelix";

showWindow helixWin;
}

global proc makeHelix()
{
float $radius = `floatSliderGrp -q -v helixRadius`;
float $pitch = `floatSliderGrp -q -v helixPitch`;

doHelix $radius $pitch;
};

이제, Script Editor에서 helix라고 입력하시면 간단한 UI가 생기고 Make Helix 버튼을 누를 때마다 helix가 만들어지게 됩니다.

_______________________________________________
오늘은 여기까지. 질문들 하세요.
by gyedo | 2004/01/22 14:44 | Maya API | 트랙백(1) | 덧글(5)
트랙백 주소 : http://gyedo.egloos.com/tb/232742
☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]
Tracked from at 2014/03/11 00:27

제목 : http://helenmccrory.org/
line3...more

Commented by reflex at 2006/02/13 17:06
마야 공부에 정말 도움이 많이 되고 있습니다. 공부하다가 발견한 건데 마지막 소스 맨 아래에서 2번째 코드에 실수하신 것 같아요. doHelix -r $radius -p $pitch; 로 고쳤더니 슬라이더로 바꿨을때 적용이 되더군요. gyedo님의 가르침 계속 부탁드립니다^^
Commented by reflex at 2006/02/13 17:19
앗 4편에 이미 정정하셨네요 ^^;
Commented by at 2009/03/19 22:11
강좌 완전 친절해요 ㅠ_ㅠb 정말 도움 많이 받고있네요- ㅎㅎㅎㅎ
Commented by 랄프 at 2009/05/26 23:10
잘봤습니다. 친절하게 잘 설명해주셔서 감사해요. 그런데 플러그인을 쓰지않고는 Helix를 만들 수 없나요? 그냥 스크립트 언어로만..
Commented by 超絶頂美少年 at 2010/09/07 19:06
감사합니다. 한참 고민하던 문제를 찾았네요. 나머지도 다 읽어봐야겠습니다. ^^

:         :

:

비공개 덧글



<< 이전 페이지 | 다음 페이지 >>