posted by cimple 2017. 9. 8. 11:12

다음과 같은 상황에 python 의 re(regex) 라이브러리를 활용하였다.


"pPlane1.v[10]"


이라는 string 정보를 Maya 로부터 입력받았을 때, 나는 여기에서 10 이라는 vertex 의 index 만 int 형태로 받고 싶다.

find 같은 명령어를 써서 10을 찾을 수도 있겠지만 re 라이브러리를 사용하면 1줄이면 가능하다.


import re

vtx_index = int(re.findall(r'\b\d+\b', "pPlane1.v[10]")[0])


자세한 사용법은 추후에 더 공부



posted by cimple 2017. 8. 31. 12:07

Maya Node 를 개발할 때, attribute 로 모든 데이터를 저장하기에는 무겁고 처음 한번만 initialize 하면 되는 경우, 별도의 멤버변수를 만들어서 저장해 줄 수 있다.

그러나 이 때, Scene 을 저장했다가 open 할 때 initilize 가 되어 있지 않아서 연산되지 않는 경우가 발생한다. 이를 위해 Scene 이 열릴 때 한 번 더 업데이트를 해주면 된다.

이 때 사용되는 것이 MSceneManager 콜백 함수이다.

나는 다음과 같은 예제에서 활용하였다.


먼저 pluginMain.cpp 에

..

#include <maya/MSceneMessage.h>

MCallbackId openCallback;

..

MStatus initializePlugin(MObject obj){

...

openCallback = MSceneMessage::addCallback(MSceneMessage::kAfterOpen,  lightFollicleNode::sceneOpenSetup)

...

}

MStatus uninitializePlugin(MObject obj){

...

MSceneMessage::removeCallback(openCallback);

...

}


위와 같이 Plugin 에서 Callback 함수를 add 해 주고, Plugin 을 deregister 할 때 반드시 removeCallback 을 해주어야 한다.

이제 Scene 이 열렸을 때 sceneOpenSetup() 이라는 함수를 호출하게 된다.


void lightFollicleNode::sceneOpenSetup(void *data){

  cout << "***lightFollicleNode:scene open***" << endl;

  isSceneOpen = true;

}

위와 같이 단순하게 flag 를 바꾸어주는 함수이다. 이를 통해서 compute function 에서 간단하게 업데이트 컨트롤을 해 줄수 있다.

posted by cimple 2017. 8. 28. 20:21

Centos 의 yum package install 이 안 될 경우에는 repository 주소를 확인하자.

내 경우 /etc/yum.repository.d/ 안에 있는 CentOS-Base.repo 가 사내 주소로 변경되어 있었다.

이러면 제대로 package install 이 될 리가 없지.

기본 Centos repository 나 국내 저장소(다음카카오) 등으로 변경해 주어야 한다.

posted by cimple 2017. 8. 17. 14:17

Maya API 에서 outRotate 값을 array attribute 로 만들어 주려면  compound array attribute 를 활용하면 된다.


initialize(){

...

MFnUnitAttribute uAttrFn;

MFnCompoundAttribute cAttrFn;


aOutRotateX = uAttrFn.create("outRotateX", "orx", MFnUnitattribute::kAngle, 0.0);

addAttribute(aOutRotateX);

aOutRotateY = uAttrFn.create("outRotateY", "ory", MFnUnitattribute::kAngle, 0.0);

addAttribute(aOutRotateY);

aOutRotateZ = uAttrFn.create("outRotateZ", "orz", MFnUnitattribute::kAngle, 0.0);

addAttribute(aOutRotateZ);


aOutRotateArr = cAttrFn.create("outRotateArr", "orarr");

cAttrFn.addChild(aoutRotateX);

cAttrFn.addChild(aoutRotateY);

cAttrFn.addChild(aoutRotateZ);

cAttrFn.setArray(true);

cAttrFn.setUsesArrayDataBuilder(true);

addAttribute(aOutRotateArr);

...

}


compute(){

...

MArrayDataHandle outRotateHndArr = data.outputArrayValue(aOutRotateArr);

MarrayDataBuilder outRotateBldArr = outRotateHndArr.builder();

unsigned int nOutRotate = (int)outRotateHndArr.elementCount();

for (unsigned int i=0 ; i<nOutRotate < i++){

  MDataHandle outHandle = outRotateBldArr.addElement(i);

  outHandle.set3Double(outRotArr[i][0], outRotArr[i][1], outRotArr[i][2]);

}

outRotateHndArr.set(outRotateBldArr);

outRotateHndArr.setAllClean();

...

}


그런데, 여기에서 Rotate 를 set 하는 value 가 angle 임에 주목해야 한다.


현 재 작성한 node 에서 vector 와 vector 사이의 사잇각을 rotateTo() 를 사용해서 MQuaternion 으로 찾고 이를 다시 MEulerRotation 으로 변환, MVector 에 저장한 다음 outRotate Attribute 에 set 해 주었다.

그런데 이 때 log 를 찍어보면 MEulerRotation 의 x,y,z 값과, 이를 MVector에 저장한 다음 찍히는 x,y,z 값이 달랐는데, 이 MVector 를 outRotate 에 set 해 보면 Maya 에는 MVector 에 찍히는 값이 아니라 MEulerRotation에 찍히는 값이 나온다.

아마도 라디안 계산을 하는 것으로 보이는데 자세한 사항은 향후 수정바람


posted by cimple 2017. 7. 26. 10:13

Maya 에서 face normal 의 방향은, vertex 의 index 순서에 다라서 오른손 법칙에 따라 결정된다.

다음과 같은 코드로 vertex 의 index 를 확인할 수 있다.


sList = om.MSelectionList()
sList.add('srcShape')
meshDagPath = sList.getDagPath(0)
meshFn = om.MFnMesh(meshDagPath)
vtxIdxList = meshFn.getPolygonVertices(0) # vertex indes list of 0th face
print vtxIdxList


만약 Maya 의 face normal reverse 기능으로 노말 방향을 뒤집으면

이 index list의 순서도 바뀌는 것을 확인할 수 있다.

posted by cimple 2017. 7. 11. 15:45

참고링크 : http://www.marcogiordanotd.com/blog/maya/maya-api-tip-creating-compound-vs-point-attribute


position 과 vector 와 같은 multiple attribute를 Maya API 에서 넘겨주는 방법에는 다음과 같은 방법이 있다.


1) Compound attribute

//Output vector attribute
//Creating 3 single attributes  vectorX,Y,Z
MFnNumericAttribute oVecXAttr;
oVecX= oVecXAttr.create("vectorX","vx",MFnNumericData::kFloat);
addAttribute(oVecX);
 
MFnNumericAttribute oVecYAttr;
oVecY= oVecYAttr.create("vectorY","vy",MFnNumericData::kFloat);
addAttribute(oVecY);
 
MFnNumericAttribute oVecZAttr;
oVecZ= oVecZAttr.create("vectorZ","vZ",MFnNumericData::kFloat);
addAttribute(oVecZ);
 
//Output vector compound attribute
//Group them togheter with a compound attribute
MFnCompoundAttribute FoVec;
oVec= FoVec.create("outputVector","ov");
 
//use addChild method to add our attributes to the compound attribute
FoVec.addChild(oVecX);
FoVec.addChild(oVecY);
FoVec.addChild(oVecZ);
addAttribute(oVec);


2) Point attribute

//Create a numeric attribute function set
 
MFnNumericAttribute originFn;
 
&nbsp;
 
// instead using create() we will use createPoint()
origin=originFn.createPoint("origin","o");
addAttribute(origin);

그런데 이 경우 dataHandle 로 받아서 .asDouble3() 으로 받으면 제대로 값이 들어오지 않는다. .asVector() 도 Double 과 동일하다.

dataHandle.asFloat3() 으로 받아야 제대로 값이 들어온다.

compound attribute 를 사용할 경우 반대로 .asFloat() 을 쓰면 제대로 값이 들어오지 않고 .asDouble3() 을 사용해야 한다.

왜 이런지는 Autodesk 에 직접 문의해보아야 할 듯.


3) Compound attribute with different style

pointXAttrFn = om.MFnNumericAttribute()
lightFollicleLocator.aPositionX = pointXAttrFn.create("positionX", "px", om.MFnNumericData.kDouble, 0.0)
om.MPxNode.addAttribute(lightFollicleLocator.aPositionX)

pointYAttrFn = om.MFnNumericAttribute()
lightFollicleLocator.aPositionY = pointYAttrFn.create("positionY", "py", om.MFnNumericData.kDouble, 0.0)
om.MPxNode.addAttribute(lightFollicleLocator.aPositionY)

pointZAttrFn = om.MFnNumericAttribute()
lightFollicleLocator.aPositionZ = pointZAttrFn.create("positionZ", "pz", om.MFnNumericData.kDouble, 0.0)
om.MPxNode.addAttribute(lightFollicleLocator.aPositionZ)

pointAttrFn = om.MFnNumericAttribute()
lightFollicleLocator.aPosition = pointAttrFn.create("position", "p", lightFollicleLocator.aPositionX, lightFollicleLocator.aPositionY, lightFollicleLocator.aPositionZ)
om.MPxNode.addAttribute(lightFollicleLocator.aPosition)


그리고 이 경우, compute function 에서 plug==attribute 에 해당하는 부분에 attribute 를 그대로 compound attribute 이름을 넣으면 안된다. plug 에서 자동적으로 compound 하위 attribute 들을 plug 로 가져오기 때문이다.

custom 하게 만들어진 attribute들의 경우에는 각각의 경우를 넣으면 되겠지만, createPoint 로 attribute를 만들었을 경우에는 해당 plug 이름에 직접 접근하기가 애매하므로 plug.parent() 가 내가 만든 compound attribute 이름이 맞다면 compute 해라 라고 만들어주면 된다.


posted by cimple 2017. 6. 28. 12:55

파이썬의 클래스나 함수에 대해 __doc__ 을 통하여 documentation 을 할 수 있다.

재미있는 것은 쌍따옴표 3개 """ 를 통해서도 가능한 것인데 다음 코드를 보면 알 수 있다.


def foo():
    """
    This is function!
    """
    return 

print function.__doc__
help(function)    


위와 같이 함수 맨 앞에 쌍따옴표 3개를 넣는 것만으로도 해당 함수에 대한 설명을 __doc__ 인자에 넣어줄 수 있다.



posted by cimple 2017. 6. 19. 16:09

PyCharm 에서 Maya API 및 Script 의 Autocompletion 이 가능하게 하는 셋팅이다.

다음 링크를 참조하였다.


https://stackoverflow.com/questions/39072433/how-to-reference-maya-commands-in-pycharm

https://forums.autodesk.com/t5/maya-programming/maya-python-api-2-0-ide-code-complete/td-p/6239681


1) Maya Python Interpreter 연결하기

Pycharm 의 Python 인터프리터를 Maya Python 인터프리터로 연결한다.

물론 Maya 가 하는 기능을 모두 하지는 못하지만, 오류가 발생하는 것을 막을 수 있다.


Setting > Project Interpreter 들어가서

톱니바퀴 > More... > Project Interpreter 를 Maya 의 것으로 선택한다.

현재 내 리눅스 Maya2015 버전의 경우 다음과 같다.


/usr/autodesk/maya2015-x64/bin/mayapy


2) Maya autocompletion 연결하기

이 경우 좀 직관적이지 않은데, 다음과 같이 수행한다.

- 위의 Project Interpreters 메뉴에서 사다리 계층구조 모양 아이콘 클릭

- /usr/autodesk/maya2015-x64/lib/python2.7/site-packages 를 지움

- /..../devkit/other/pymel/extras/completion/py

를 추가한다.

그런데 현재 내 maya2015 devkit 의 경우 추가했을 때 MPxNode 를 인지못하는 버그가 있다. 이유불명.

그래서 인터넷에서 Maya2017 Devkit 을 다운로드 받은 뒤 해당 autocompletion 을 추가하였다.


.../site-packages 를 지우는 과정이 좀 직관적이지 않은데, 지우지 않을 경우 제대로 autocompletion 이 되지 않는다.

그러나 이 경우 numpy 와 같은 external library 들을 설치했을 경우 해당 라이브러리의 autocompletion 이 어떻게 이루어지는가는 지켜 보아야 할 것 같다.


posted by cimple 2017. 6. 16. 17:08

Maya 뿐만 아니라 많은 아이콘들을 마음에 드는 이미지들로 바꿀 수 있다.

일단 아이콘을 선택해서 우클릭 > 속성(p) 에 들어가면 다음과 같은 화면을 볼수 있는데

여기에서 나는 이미 아이콘 이미지를 바꾸어 놓았는데, 왼쪽 위의 마야 아이콘 이미지가 있는 곳을 클릭하면 사용자 아이콘을 선택할 수 있는 창이 뜨게 된다.

인터넷에서 Maya 아이콘을 다운로드 받아서 여기에 연결시켜서 쓰면 된다. 다른 아이콘들도 이쁘게 해서 쓰도록 하자.



posted by cimple 2017. 6. 16. 11:17

참고링크 :

http://discourse.techart.online/t/undo-in-maya-mel-python-execution/2431/7


Maya 의 Undo 는 Queue 에 순차적으로 작업을 쌓는다. 그런데 Undo 를 수행했을 때 Undo 를 여러번 누르는 것이 아니라 Ctrl+Z 한번에 Undo 되기를 원하는 작업이 있을 수 있다. 예를 들어 오브젝트를 한 백개쯤 복사했다던가.... 이럴 때 Undo 를 100번을 눌러야 한다면 그닥 유쾌한 일이 아닐 것이다.


Maya command 의 undoInfo() 가 해당 기능을 가지고 있다.

import maya.cmds as mc
mc.undoinfo(openChunk=True)
#Code Code Code
mc.undoinfo(closeChunk=True)

위 #Code Code Code 에 해당하는 부분을 한방에 Undo 시켜 주는 것이다.

그런데 openChunk 기능은 maya 의 UndoQueue 를 직접 건드리는 상당히 위험한 기능이기 때문에 안전하게 사용할 필요가 있다. 그래서 열고 닫기가 확실하게 진행될 수 있도록


mc.undoInfo(openChunk=True)
try:
    #CODE CODE CODE
finally:
    mc.undoInfo(closeChunk=True)

위와 같은 방식으로 작성하는 것이 안전하다.

또는 다음과 같이 context class 를 만들어서


class UndoContext(object):
    def __enter__(self):
        mc.undoInfo(openChunk=True)
    def __exit__(self, *exc_info):
        mc.undoInfo(closeChunk=True)

with UndoContext():
    ... your code here....

UndoChunk 가 안전하게 열고 닫히도록 할 수도 있다.