posted by cimple 2016. 4. 18. 17:23


(위 이미지는 참고링크에서 가져온 것)


참고링크

http://forums.autodesk.com/t5/maya-general/joints-display-broken-viewport-2-0/td-p/6053740



엔비디아 그래픽카드 드라이버 업데이트 후, Maya viewport 2.0 에서 조인트가 깨져보이는 현상이 발생하는데,


참고 링크에서 답을 찾을 수 있었다. 


Windows -> Settings/Preferences -> Preferences -> DisplayWindows -> Settings/Preferences -> Preferences -> Display


에 들어가서


Viewport 2.0 의 엔진을 OpenGL 에서 DirectX 로 변경...




posted by cimple 2016. 3. 31. 16:57

Maya 에서 특정 프레임 f 에서 object 의 world position 을 얻는 가장 간단한 방법은 이것이다.


import maya.cmds as mc
mc.currentTime(f)  # f is specific frame
mc.xform(obj, q=True, t=True, ws=True), #obj is specific object

그러나, 이 방식의 경우 'currentTime()' 커맨드로 특정 프레임으로 이동한 다음 계산하므로 씬이 전체적으로 업데이트 되어야 해서 만약 다수의 프레임에 대해 처리를 해야 할 경우 속도가 매우 느리다.


'currentTime()' 커맨드를 쓰지 않고 위치정보를 받아올 수 있는 다른 방법으로는 'getAttr()' 커맨드를 이용하는 방식이 있는데, 이 방식은 말그대로 attribute 의 값을 가져올 뿐이므로, object 의 world position 같은 정보를 직접적으로 얻어올 수는 없다.


이를 위하여, 아래는 Maya Python API 2.0 을 활용하여 특정 ojbect 의 world position 을 내가 원하는 frame 에서 찾는 Python Script 이다.


import maya.cmds as mc
import maya.api.OpenMaya as om

def mayaTimeUnitTypeQuery():
    mayaTimeUnitDic = {'100fps':25, '10fps':18, '1200fps':38, '120fps':26, '125fps':27, '12fps':19, '1500fps':39, '150fps':28, '16fps':20, '2000fps':40, '200fps':29, '20fps':21, '240fps':30, '250fps':31, '2fps':12, '3000fps':41, '300fps':32, '375fps':13, '400fps':34, '40fps':22, '4fps':14, '500fps':35, '5fps':15, '6000fps':42, '600fps':36, '6fps':16, '750fps':37, '75fps':23, '80fps':24, '8fps':17, 'film':6, 'game':15, 'hour':1, 'millisec':4, 'sec':3, 'min':2, 'ntsc':8, 'ntscf':11, 'palf':10, 'pal':7, 'show':9} 
    curTimeUnit = mc.currentUnit(q=True, time=True)
    try:
        mayaTimeUnit = mayaTimeUnitDic[curTimeUnit]
    except:
        raise NameError('Invalid Maya time unit. %s is not in the Maya unit dictionary.'%(curTimeUnit))
    return mayaTimeUnit
    

def getWorldPosAtTime(obj, frame):
    sList = om.MSelectionList()
    sList.add(obj)
    dagPath = sList.getDagPath(0)
    transFn = om.MFnDagNode(dagPath)
    matrixPlugArr = transFn.findPlug('worldMatrix', 0)
    matrixPlugArr.evaluateNumElements()
    matrixPlug = matrixPlugArr.elementByPhysicalIndex(0)
    
    curTimeUnit = mayaTimeUnitTypeQuery()
    mayaTime = om.MTime(frame, unit=curTimeUnit)
    timeContext = om.MDGContext(mayaTime)
    
    plugObj = matrixPlug.asMObject(timeContext)   
    #print plugObj.apiTypeStr  #kMatrixData
    plugObjFn = om.MFnMatrixData(plugObj)
    worldMatrix = plugObjFn.transformation()
    worldPos = worldMatrix.translation(om.MSpace.kWorld)
    return worldPos

mayaTimeUnitTypeQuery() 함수는 현재 Maya 에 설정되어 있는 FPS 값을 미리 상수로 예약되어 있는 MayaTimeUnit 값으로 리턴해준다. Maya 에 예약된 모든 FPS 를 포함하는 함수이므로 유용할 것이다. 이 함수에서 오류가 난다면 버그가 있는 것이므로 제보바람.

getWorldPosAtTime() 함수가 우리가 원하는 일을 해 주는 함수인데, 위치를 알고싶은 obj 와 frame 을 입력하면 해당 frame 에서의 world position 을 반환해준다.
Object DagNode 의 worldMatrix plug 에서 matrix data 형태로 어떻게 가지고 오는지,
그리고 MTime 과 MDGContext timeContext 객체를 만들어 어떻게 특정 frame 에서의 value 를 retrieve 하는지가 주목할 만한 부분이다.



posted by cimple 2014. 12. 31. 03:02

옛날 'Maya2014에서 numpy 사용하기' 라는 글에서 약간 얼렁뚱땅 Maya2014 의 Python library 사용문제를 넘어갔었는데, 결국 언젠가는 굴러굴러 문제로 닥칠수밖에 없는 일. 하루를 모두 소진해서야 문제를 해결할 수 있었다.


욕을 하지 않으려고 해도 지랄맞은(...) 마야의 Python 시스템 때문에 정말 수도없는 테스트와 테스트 끝에 해결을 하고 나니 진이 다 빠지는 느낌이지만, 정리를 하지 않으면 누군가가 또 고생할 것이고 인간은 망각의 동물이니 나도 고생할 수 있기 때문에....


단지 Maya2014 에서 python nlopt 를 사용하는 문제뿐만 아니라, python library 를 사용하는데 있어 비슷한 문제가 발생했을 때에 해결하는 단초를 찾았다는 생각이다.





시간없는 사람들을 위해


먼저 일단 차치하고 Maya2014 에서 사용할수 있는 nlopt 라이브러리


nlopt_maya2014.7z


기존처럼 C:\Program Files\Autodesk\Maya2014\Python\Lib\site-packages 에 복사해 넣으면 된다.

(물론 Numpy 도 설치되어 있어야 돌아간다. Numpy 는 위 링크글 참조...)





1. 문제의 유형 및 발생원인


Maya2012 까지는 간편하게 Numpy 와 nlopt 를 설치할 수 있다. 비공식이긴 하지만 64bit python 컴파일된 binary 를 distribute 하기 때문이다. 이걸 설치하고 Maya 의 python 의 site-package 폴더에 복사만 해주면 된다.


numpy 링크

http://www.lfd.uci.edu/~gohlke/pythonlibs/#numpy


nlopt 링크

http://www.lfd.uci.edu/~gohlke/pythonlibs/#nlopt



그런데 이게 Maya2013 부터 numpy 부터 시작해서 라이브러리들이 import 가 잘 안되기 시작했는데, 그 이유가 Maya 의 Python 을 빌드한 컴파일러 문제이다. 이것을 알아보기 위해서 다음 명령어를 

import sys
print sys.version

각각 다른 버전의 Maya Script Editor 에 쳐서 확인해보면 다음과 같은 결과를 얻을 수 있다.


Maya2012


Maya2013


Maya2014


보다시피 Maya2013 부터 Python 컴파일러를 MSC v.1600, 즉 VS2010 compiler 로 컴파일했다는 사실을 알 수 있다. 


이게 아주 쓰레기같은게 뭐냐면 우리가 Python 홈페이지에서 받을 수 있는 파이선 2.x 버전들을 체크 해보면 MSC v.1500 로 컴파일되어 있다. 즉 VS2008 에서 컴파일한 버전을 배포하고 있다. v.1600 은 Python 3.x 버전 이후부터이다.


그런데 이 샹늠의 Maya 는 뭐가 잘났다고 혼자 독특하고 고고하게 VS2010 에서 컴파일한 파이선 2.x 버전을 사용하고 있다. 그것도 Maya2014 부터는 Python 2.7 버전을 사용한다. 아마도 추후에는 Python 3.x 버전으로 업그레이드를 할 목적이긴 하겠지만, 이것이 문제를 발생시키는 가장 큰 원인이었다.


이 문제 때문에 어렵사리 컴파일한 nlopt 를 사용할 수가 없었다. 가장 고생한 에러메시지는 바로 이것일 것이다.


ImportError: DLL load failed: %1은(는) 올바른 Win32 응용 프로그램이 아닙니다.


이걸 해결하기 위해서, 'Python2.7 자체를 VS2010 컴파일러로 다시 컴파일' 해야만 했다. 왜 그래야만 했는지는 아래에 설명...



2. python nlopt 컴파일하기


일단 내 입맛에 맞는 python nlopt 라이브러리의 binary 버전은 없다. 애초에 Window 에서 쓰라고 만든것도 아니고 Python nlopt 는 Wrap 해서 배포할 뿐이지 원래 c++ 라이브러리다. 직접 만들어 써야 한다고 보면 된다. 찾으려고 괜히 애쓰지 말고 컴파일 하는 것이 오히려 이득이다.


다음과 같은 순서를 따르면 된다.


1) 일단 nlopt 소스파일을 다운로드 받아서 압축을 풀어놓는다. 위치는 상관없다. 어차피 필요한건 컴파일한 다음 라이브러리 파일이다.

http://ab-initio.mit.edu/wiki/index.php/NLopt#Download_and_installation


2) 다음은 아래 페이지에서

http://ab-initio.mit.edu/wiki/index.php/NLopt_on_Windows


nlopt-2.4.2-dll64.zip (64-bit) 압축파일을 받아서 압축을 푼다. 미리 컴파일해둔 win64 용 .dll 파일이 있고 어쩌고 하는데 어차피 못쓴다. MinGW 로 컴파일한것이기 때문이다. 어차피 MSVC 로 다시 컴파일해야 한다. 이 압축파일의 용도는, nlopt 의 라이브러리파일 .lib 가 만들어지면, python 으로 컴파일할 수 있는 setup.py 파일이 포함되어 있기 때문이다.


3) 위 2) 의 링크 NLopt on Windows 페이지에서 CMake 관련파일 2개를 받는다. CMakeLists.txt 와 config.cmake.h.in 이다. 이것들을 1) 의 압축 풀어놓은 폴더에 넣는다.


cmake 로 VS 프로젝트를 생성-> 컴파일해서 Shared library (.dll) 생성 -> 이걸 Python 으로 컴파일 하는 것이 전체적인 얼개이다.


4) Cmake 로 해당 폴더를 Configure 하면 설정을 잘 잡아주는데, 주의해야 할 것은 

BUILD_SHARED_LIBS 옵션을 체크해 주어야 한다는 것이다. 여기서 컴파일된 .dll 파일을 가지고 python 에서 다시 컴파일한다.


5) Cmake 에서 Generate 하면 VS2010 프로젝트가 생성된다. 열어서 빌드하면 nlopt-0.dll 이라는 dll 이 생성될 것이다.


6) 이제 이것을 2) 에서 받았던 폴더에 넣는데, 원래 있던 dll 인 libnlopt-0.dll 을 지우고 그 이름으로 넣는다.


7) 이제 dll 을 가지고 lib 를 만들 차례이다. (사실 컴파일 자체는 해당 폴더의 README-WINDOWS 를 읽으면 있는 내용이다.) 명령 프롬프트를 써야 하는데, Visual Studio Win64 명령 프롬프트(x64) 를 실행시킨 다음 해당 폴더로 찾아들어간다. 그리고 아래 명령어 입력.


lib /def:libnlopt-0.def


8) 그럼 libnlopt-0.lib 파일이 만들어진다. 이제 python 으로 컴파일한다.


python setup.py build_ext --inplace


위 명령어로 컴파일하면 되는데, 여기가 지랄맞다!!!! 그 이유는, 여기서 python 으로 컴파일하는 것은 내가 환경변수에 등록된 python 으로 컴파일하는데, 이 python 이 처음에 말했지만 흔히 배포되는 Python2.x 의 MSC v.1500 컴파일된 python 을 사용하면 maya 에서 이 nlopt 를 쓸 수가 없다.


따라서 MSC v.1600 으로 컴파일된 python 으로 이 라이브러리를 빌드해야 한다. 그러기 위해서는 VS2010 에서 컴파일된 python2.x 버전을 사용해야 하는데, 나를 도와준 고마운 링크는 아래...


http://www.p-nand-q.com/python/building-python-27-with-vs2010.html


그냥 여기서 주는 python2.7 다운받아 썼다....지만 근데 site-package 를 뭔 이렇게 쓸데없이 깔아서 배포했는지 너무 무겁다; python 직접 컴파일하셔도 됨. 시간많으시면.


어쨌든 이 MSC v.1600 으로 컴파일된 python 으로 위 명령어를 통해 python 으로 컴파일하면, _nlopt.pyd 파일이 생성된다.


9) _nlopt.pyd, nlopt.py, nlopt-0.dll 3개의 파일을 maya 의 site-package 폴더에 넣으면 Maya 에서 잘 돌아가는 nlopt 를 감상할 수 있다.






써놓고 보니 간단해 보이는데 정말 python/라이브러리/심지어 Maya2014 까지 다시깔고, 컴파일 이런 저런 옵션 찾아가며 또해보고, document 읽고 또 읽고... 


해결은 했지만 이거 정말 Maya 문제 있다는 생각이다....





덧붙임1. NLopt 의 installation guide 에서 python_plugin 파트를 읽어보면


http://ab-initio.mit.edu/wiki/index.php/NLopt_Installation#Python_plugins


'Shared library 로 컴파일을 하면 자동으로 python plugin 을 설치해 줍니다!' (오오??) 라고 하는데 Windows 사용자들은 헛된기대 하지 말자... Linux make 파일에서 제공해주는 설정들이다. 실제로 make 파일과 configure 파일을 뜯어보면 python version 의 site-package 에 설치해주는 부분들이 있어서 한참 들여다봤지만 결국 Windows 에서 CMake 로 만든 VS Project 로 컴파일하는 유저들에게는 그런거 없는거로.....



posted by cimple 2013. 11. 29. 12:45

아래 Python Script 를 다운로드 받으시면 됩니다.


simpleMayaVoxelize.py





Simple Maya Voxelize Tool



Maya 에서 손쉽게 Mesh Voxelization 을 수행할 수 있는 툴입니다.


UI 는 다음과 같습니다.



1. Mesh 를 선택하고 (여러개의 Mesh 를 동시에 Voxelize 할 수도 있으나 속도가 느립니다)


2. Voxel Size 를 선택한 후


3. 원하는 Voxelize 방법으로 만드시면 됩니다.


Make Full Voxel Cubes : 내부까지 Voxel 로 꽉 차있는 Voxelized 된 모델을 만듭니다.


Make Surface Voxel Cubes : 겉표면만 Voxel 로 되어 있는 모델을 만듭니다. 속도가 상대적으로 빠르고 가볍습니다.


Make Shape Carving Voxels : 오브젝트의 겉표면대로 Voxel 을 깎습니다. 내부에도 Voxel 이 차 있습니다.




Shape Carving Voxels 기능을 이용한 데모 동영상입니다.





※ Surface Voxelization 은 다음 링크에 공개된 소스코드를 상당부분 활용하였습니다.

http://zoomy.net/2010/02/25/voxelize-meshes-script-v2/

posted by cimple 2013. 8. 20. 14:41

포스트의 제목을 어떻게 지어야 할지 좀 난감하다. 쉐이링-렌더링에 대한 개념이 여전히 생소한 것들이 많아서... 하지만 재미있는 것을 알아내었기에 포스팅을 해야겠다.


포스팅의 결과물을 결론적으로 정리하자면


1. Shading Group 의 attribute 에 surface material / v-ray material 을 각각 등록할 수 있다.


2. 이렇게 함으로써, Maya Viewport 및 Software rendering 에는 원래 Surface material 을, V-ray rendring 시에는 V-ray material 을 사용할 수 있다.


이것이 유용한 이유는 지금 개발하고 있는 Photo-Projection Tool 에서 Viewport 상에서 Real-time 으로 Object 를 관찰할 때 사용하는 쉐이더와, 실제 렌더링에 사용되는 V-ray 쉐이더가 다르기 때문이다.


개념이 생소해서 그렇지 적용하는 방법은 몹시 간단하다.




1. HyperShade 의 Shading Groups 탭에서 지정해주고 싶은 쉐이딩 그룹을 선택한다. 쉐이딩 그룹에 대한 개념은 다른 포스트에서 따로 정리하겠지만, 여기서는 간단하게 기본적인 initialShadingGroup 에 적용시켜보기로 하겠다.



2. Attribute Editor 에서 상단의 Attributes 버튼을 클릭하면, V-ray > V-ray Material override 를 선택할 수 있다. 


3. 그러면 해당 Shading Group 의 Attribute 에 Extra Vray Attributes 탭에 추가된 것을 볼 수 있다.


4. 탭을 열어서, V-ray Material 에 내가 원하는 V-ray material 을 적용시켜 줄 수 있다.


5. 결과는 훌륭하다. Maya Viewport 및 Software Render 에는 기본 Surface material 로 지정해 준 lambert1 이 적용되고, V-ray 로 렌더링할 때에는 내가 새로이 만들어준 VRayMtlWrapper2 가 적용된다. 



Digital Tutors 정말 쓸모있다. GOOOOOD

posted by cimple 2012. 12. 26. 22:11

Maya plug-in 개발 환경을 구축할 때, Plug-in wizard 를 사용하는 방법이 일반적이었지만, Maya version 및 Visual Studio version 에 따라 제대로 만들어지지 않는 등의 많은 문제가 있었다.


CG Circuit 의 Maya API 강좌를 참고해서 Maya Plug-in 개발환경 구축을 설명한다.



1. File > New Project > Win32 Project


2. DLL Project ,Empty project


3. Project properties


4. Configuration 탭다운 메뉴에서 All Configurations 선택


5. Linker > General > Output file 의 확장자를 .mll 로 변경


$(OutDir)\$(ProjectName).mll



6. C++ source code 추가


7. C/C++ > General > Additional include directory 에 Maya Include 디렉토리 추가


8. Preprocessor > Preprocessor Definitions 에


WIN32; NDEBUG;_WINDOWS;NT_PLUGIN;REQUIRE_IOSTREAM 


9. Linker > General > Additional library directory 에 Maya lin 디렉토리 추가


10. Input > Additional Dependencies 에


Foundation.lib OpenMaya.lib OpenMayaUI.lib OpenMayaAnim.lib 

OpenMayaFX.lib OpenMayaRender.lib Image.lib opengl32.lib glu32.lib


11. Command Line > Additional options :


/export:initializePlugin /export:uninitializePlugin


12. 상단의 Configuration 에서 x64로 변경 (64bit 의 경우)


Linker> Advanced 에서 target machine 확인

posted by cimple 2012. 2. 22. 22:41
Maya Plug-in Wizard 는 쉽고 간편하게 Microsoft Visual Studio 환경에서 마야 플러그인을 개발할 수 있도록 설정을 해 주는 기능을 하지만, 마법사라는 놈들이 원래 그렇듯이 뭔가 자동으로 뭘 찾고 연결하고 하다보니 프로그램의 버전이나 환경 등이 조금만 달라져도 잘 동작하지 않는 단점이 있습니다.

때문에 Maya 의 버전에 따라서, 또 Visual Studio 버전에 따라, 운영체제에 따라(32-64bit) Plug-in Wizard 가 잘 동작하지 않는 경우가 많았는데, 이건 지금도 마찬가지입니다; 

지난번에는 Maya2009 - VS2008 조합을 해결하는 포스팅을 했었죠. 이번에도 비슷한 문제에 부딪혀서 이렇게 저렇게 많은 해결 방법을 시도했는데 실패를 거듭했습니다.

결국 구글의 도움을 받아, 아래에 있는 링크의 글을 통해 해결을 할 수 있었는데요, 다른 게 아니라 아예 Issac Peral 이라는 분이 Creative Crash 에 수정한 Plug-in wizard 를 넣어 두었습니다.


솔루션을 발견한 링크 클릭은 여기



파일 크기가 크지 않기 때문에 이 포스팅에 직접 해당 파일을 압축한 파일을 올려둡니다.

 

위 파일의 압축을 푼 뒤, Maya Plug-in Wizard 에 한번이라도 경험이 있으신 분들은 하던 그대로 설치해 주시면 됩니다. 잘 기억이 안나시는 분들도 Maya devkit 의 Plug-in wizard 폴더에 가면 (저 같은 경우는 C:\Program Files\Autodesk\Maya2012\devkit\pluginwizard 폴더 안에) TXT 파일이 있으니, 그것을 읽고 그대로 복사복사 하시면 됩니다.

단, 주의사항은

1.  Maya devkit 안에 들어 있는 TXT 파일에서, 64비트의 경우에는 MayaPluginWizard 폴더를 복사할 때 2중 구조로 복사해야 한다고 별표까지 쳐 놨습니다. 하지만 여기에 올려진 파일은 그냥 MayaPluginWizard 폴더를 Visual Studio 2010 의 VCWizard 폴더에 바로 복사해 주면 됩니다.

2. Visual Studio 2010 에서 Maya Plug-in Wizard 로 프로젝트를 생성하신 이후, 프로젝트 속성에서 구성 속성 > 일반 > 대상 확장명을 .mll 로 바꾸어 주시기 바랍니다. 아마 .dll 로 되어 있을 것입니다. 이건 프로젝트 생성할 때마다 바꾸어 주어야 하는 것 같습니다;


일단 '따라하세요'  수준의 포스팅을 마칩니다. 구글링을 해 보니 이러한 Plug-in Wizard 를 사용하지 않고 안정적으로 Maya Plug-in 개발환경을 구축하는 포스팅들이 있더군요. 나중에는 그 포스팅을 하여서 더이상 이런 폐해가 없도록 막아야 하겠습니다.

감사합니다.

 
posted by cimple 2012. 1. 17. 04:56

C++ 언어로 제작된 Maya Plug-in 이 .mll 파일로 배포되는 것과 같이, Python 으로 제작된 Plug-in 도 .pyc 의 컴파일 된 형태로 제작되어 배포할 수 있습니다.

실제로 마야가 설치되어 있는 폴더 안에 파이썬 라이브러리를 보면 .pyc 형태로 배포되고 있는 것을 볼 수 있습니다.

ex) C:\Program Files\Autodesk\Maya2010\Python\lib\site-packages\maya


이러한 .pyc 파일을 Compiled Bytecode 라 부르며, 소스코드를 숨길 수 있을 뿐만 아니라 파이썬 모듈을 Import 할 때 속도 향상 또한 가져다주는 장점을 가지고 있습니다.

Maya Python 파일은 Python API 뿐만 아니라 Python Script 파일, 심지어 MEL 파일도 Python 으로 wrapping 해서 .pyc 파일로 배포가 가능합니다. 따라서 소스코드 뿐만 아니라 UI 등 어떤 형태의 스크립트 파일도 배포할 수 있습니다.

이번 포스팅에서는 먼저 Python Maya Script 파일을  .pyc 파일로 제작하고, import 하는 과정을 설명하도록 하겠습니다.




1. Python Script 파일을 .pyc 파일로 제작하기

아래 파일은 Mesh 를 선택하고 버튼을 누르면 해당 Mesh 의 이름을 반환하는 간단한 기능을 가지고 있는 UI 를 Maya Python Script 로 구현한 파일입니다.


※주의!
(위 파일을 보통 배포되는 형태처럼, Maya Script Editor 에서 전체 복사이후 실행 (Ctrl+A -> Ctrl+C -> Ctrl+V -> Ctrl+Enter) 시키면, UI 는 뜨지만 버튼들이 제대로 동작하지 않을 것입니다. 이것은 내부 모듈 실행 이름이 다르기 때문인데, 관련한 내용은 잠시 뒤에 설명할 것입니다.)


위 파일을 테스트해보고 싶으면, Maya 에서 Python 모듈을 Import 하는 형태로 사용해야 합니다. Python 모듈을 Import 하고 싶으면 해당 Python 파일을 기존 Python Path 에 넣거나, 해당 파일이 있는 Path 를 Python Path 에 추가해주면 됩니다. 해당 소스코드는 아래를 참조하세요.


#Python Path 확인하기

import sys

for i in sys.path :
    print i 


#Python Path 추가하기

import sys
srcPath = "C:\.... (Custom Path)"
if srcPath not in sys.path :
    sys.path.append(srcPath) 



위와 같이 Module 을 Import 할 Path 를 잡아주고 나면, 해당 Python Script 를 Import 할 수 있습니다. 다음 명령어로 Import 해서 UI 를 실행시켜 봅시다.


#Python Module Import

import testUI



그러면, 아래 그림과 같은 UI 가 뜨는 것을 확인할 수 있습니다. 각 버튼을 눌러서 제대로 작동하는지 확인해 봅니다.

간단한 UI...지만 최대한 Maya 표준에 맞게 제작한 UI



버튼이 제대로 동작하는 지 확인하고 나면, 해당 Python Script (testUI.py) 를 넣어 두었던 폴더에 가 봅니다. 그러면 Python Script 의 Compiled Bytecode Version 인 .pyc 파일이 생성되어 있는 것을 확인할 수 있습니다.

.pyc 가 갑툭튀


이렇게 해당 Python 파일을 Module 로 Import 하면 .pyc 파일이 자동으로 생성됩니다. 이것이 .pyc 파일을 만드는 가장 간단한 방법입니다. 



Python 파일을 .pyc 파일로 만드는 또 다른 방법은 직접 컴파일 하는 방법이 있습니다. 다음 소스코드로 직접 컴파일해 봅시다.

import py_compile
py_compile.compile('C:/..(Custom Path) .../testUI.py')


※ 주의!
직접 컴파일할 때, 경로명은 슬래시 (/) 혹은 백슬래시 2개 (\\) 를 사용해야 합니다. 백슬래시 1개 (\) 는 작동하지 않습니다.

역시 .pyc 파일이 생성되어 있는 것을 확인할 수 있습니다.





2. .pyc 파일을 import 하기

.pyc 파일을 import 하는 방법은 매우 간단합니다. .py 파일을 import 하는 것과 똑같이 그냥 .pyc 파일을 import 하면 됩니다.

.pyc 파일이 잘 import 되는가를 확인하기 위해, 메모리를 청소하기 위해서 Maya 를 한번 껐다 켜고, .pyc 파일만 다른 폴더에 복사해둡니다.

그런 다음 다시 Maya 를 켜서, 먼저 다음 명령어로 testUI 를 Import 할 수 없음을 확인합니다. 당연히 아래 그림과 같은 Import Error 메시지가 떠야 합니다. (만약 testUI.py 파일을 기존 Python Path 에 넣어두었다면 import 가 되어버릴 것입니다. 이러면 .pyc 파일만 확인할 수가 없으므로 testUI.py 파일을 지워주어야겠죠?)

import testUI

 

우리를 겁나게 하는 시뻘건 에러 하지만 이번엔 이게 정상



그리고 testUI.pyc 파일이 담겨 있는 path 를 다음과 같이 등록해준 다음, import 해 봅시다.

srcPath = "C:\...(Custom Path)"

import sys

if srcPath not in sys.path:

    sys.path.append( srcPath )


import testUI

 
아까와 같이 UI 가 제대로 작동하면 .pyc 파일을 제대로 Import 한 것입니다.

.pyc 파일을 열어 보아도, 소스코드 내용을 확인할 수가 없습니다.

확인할수가 업ㅂ어

 

.pyc 파일의 import 를 정리하면 다음과 같습니다.

  • Module 로 Import 됩니다.
    - 기존 Python Module 을 사용하는 것처럼, 모듈명.함수() 형태로 모듈 안의 함수들을 사용할 수 있습니다.
    - 위에 제시된 예제 파일처럼 모듈 안에 들어있는 것이 Class 라면, Class 의 객체를 만들어 사용하거나, 직접 Class 의 멤버함수를 사용할 수 있습니다.
    - ex) import testUI
            myUI = testUI.TestUI()
            myUI.showMyWindow()

            또는

            import testUI
            testUI.testUI().showMyWindow()
            
  • Import 되는 순간 실행됩니다.
    - Import 되는 순간 .pyc 의 내용들이 메모리에 올라가게 됩니다. 
    - 예제 파일에서는 import maya.cmds as mcTestUI().showMyWindow() 가 전역적으로 실행되고, 클래스가 메모리에 올라갑니다. 
     



Maya UI 파일을 .pyc 파일로 배포할 때 주의사항

UI 파일을 .pyc 파일로 배포할 때에 주의사항이 있습니다. 각종 UI 에는 다양한 형태의 '버튼' (이라고 통칭합시다) 이 있는데, 이런 버튼은 마야에서 command 를 실행하게 됩니다. 예를 들면

mc.button(label="Select mesh and press", align="center", command="testUI.TestUI().importMesh()")


예제에 있는 버튼의 한 예입니다. "Select mesh and press" 라는 버튼을 누르면 "testUI.TestUI().importMesh()" 라는 커맨드를 실행하게 되는 버튼입니다.

이와 같이, UI 의 각종 버튼들은 command 인자로 받는 " " 쌍따옴표 안에 들어있는 커맨드를 그대로 실행합니다. 때문에, module 명을 임의로 import 하였을 경우 command 를 실행시키지 못합니다.

예를 들어, 다음과 같이 myUI 라는 임의의 이름으로 module 을 import 한다면

import testUI as myUI


다른 Python module 들은 myUI.함수명() 과 같은 형태로 실행시킬 수 있지만, Maya UI 의 경우 command 를 임의의 모듈명을 받아서 실행시킬 방법이 없습니다. 

따라서 UI 파일이 함수의 나열 형태로 구성되어 있다면 UI 내의 command 부분을

command = "모듈명.함수명()"


으로 정해주어야 하거나, 예제와 같이 클래스 형태로 구성되어 있다면 

command = "모듈명.클래스명().함수명()"


으로 정해 주어야 하고, 모듈을 import 할 때에는

import 모듈명


으로만 import 해야 UI 를 .pyc 파일로 배포하고, 정상적으로 사용할 수 있습니다.





3. Mel 파일을 .pyc 파일로 제작하기


Mel 파일을 .pyc 파일로 제작하는 방법은 간단합니다. Mel Script 를 Python Script 에서 실행시킬 수 있도록 바꾸어 주면, 이후 과정은 당연히 Python Script 를 .pyc 로 만드는 과정과 동일합니다. 예제를 보는 것이 이해가 빠를 것입니다.

import maya.mel as mel

mel.eval('polySphere -r 3;')

mel.eval('polyCube -w 2 -h 6;')

mel.eval('polyCylinder -h 7 -sx 10;')


위와 같은 python 파일을 만들어서 컴파일하면 MEL 파일도 .pyc 형태로 배포할 수 있습니다.





4. Maya Python Plug-in 파일을 .pyc 파일로 제작하기

아래 소스코드는 'Hello, World' 를 찍는 간단한 Maya Python Plug-in 파일입니다.

import sys

import maya.OpenMaya as OpenMaya

import maya.OpenMayaMPx as OpenMayaMPx


kPluginCmdName = "spHelloWorld"


# command

class scriptedCommand(OpenMayaMPx.MPxCommand):

        def __init__(self):

                OpenMayaMPx.MPxCommand.__init__(self)

        def doIt(self,argList):

                print "Hello World!"


# Creator

def cmdCreator():

        return OpenMayaMPx.asMPxPtr( scriptedCommand() )

        

# Initialize the script plug-in

def initializePlugin(mobject):

        mplugin = OpenMayaMPx.MFnPlugin(mobject)

        try:

                mplugin.registerCommand( kPluginCmdName, cmdCreator )

        except:

                sys.stderr.write( "Failed to register command: %s\n" % kPluginCmdName )

                raise


# Uninitialize the script plug-in

def uninitializePlugin(mobject):

        mplugin = OpenMayaMPx.MFnPlugin(mobject)

        try:

                mplugin.deregisterCommand( kPluginCmdName )

        except:

                sys.stderr.write( "Failed to unregister command: %s\n" % kPluginCmdName )

                raise




이 소스코드를 파이썬 파일로 저장한 다음, Plug-in Manager 에서 불러들여봅니다. 스크립트 에디터에서 spHelloWorld 라는 커맨드를 입력하면 'Hello World!' 라는 텍스트를 출력합니다.




그렇다면 이 Python 파일을 바로 컴파일 해서, .pyc 형태로 만들면 바로 배포 가능하겠네? 라고 생각할 수 있지만 현실은 그렇지 않습니다. 세상일이 그렇게 마음대로 되던가요. 플러그인 파일 전체를 컴파일 해서 .pyc 파일로 만들면, Maya Plug-in Manager 에서 .pyc 파일이 보이긴 합니다(!). 그러나 제대로 플러그인을 읽어 들이지 못하는 것을 볼 수 있습니다.


비록 눈에는 보이지만

세상 일이 맘처럼 쉽지만은 않은 예.pyc





Python Plug-in 파일을 배포하기 위해서는 코어 부분과 이니셜라이징 부분을 분리해서, 코어 부분은 .pyc 파일로 만들고, Plug-in 이니셜라이징 부분은 해당 .pyc 파일을 Import 하는 .py 파일을 만들어 두 파일을 다 배포하면 됩니다.

먼저 위 코드에서 코어 부분을 다음과 같이 떼어 컴파일합니다.

helloWorldCore.py

import sys

import maya.OpenMaya as OpenMaya

import maya.OpenMayaMPx as OpenMayaMPx


kPluginCmdName = "spHelloWorld"


# command

class scriptedCommand(OpenMayaMPx.MPxCommand):

        def __init__(self):

                OpenMayaMPx.MPxCommand.__init__(self)

        def doIt(self,argList):

                print "Hello World!"


# Creator

def cmdCreator():

        return OpenMayaMPx.asMPxPtr( scriptedCommand() )



그렇다면 helloWorldCore.pyc 파일이 제작되겠죠? 그리고 나서 이 .pyc 파일을 import 해서 이니셜라이징 하는 파일을 제작합니다. 원본 파일과 달라진 부분을 진한 글씨로 표시하겠습니다.

helloWorld.py

import sys

import maya.OpenMaya as OpenMaya

import maya.OpenMayaMPx as OpenMayaMPx
import helloWorldCore as hwc


# Initialize the script plug-in

def initializePlugin(mobject):

        mplugin = OpenMayaMPx.MFnPlugin(mobject)

        try:

                mplugin.registerCommand( hwc.kPluginCmdName, hwc.cmdCreator )

        except:

                sys.stderr.write( "Failed to register command: %s\n" % hwc.kPluginCmdName )

                raise


# Uninitialize the script plug-in

def uninitializePlugin(mobject):

        mplugin = OpenMayaMPx.MFnPlugin(mobject)

        try:

                mplugin.deregisterCommand( hwc.kPluginCmdName )

        except:

                sys.stderr.write( "Failed to unregister command: %s\n" % kPluginCmdName )

                raise


그리고 이 helloWorld.py 를 Plug-in Manager 에서 불러들이면 정상적으로 플러그인이 동작하는 것을 확인할 수 있습니다.

정리하면

  • 코어 부분은 .pyc 파일로, 이니셜라이징 하는 부분은 .py 파일로 제작합니다. 
  • 이니셜라이징 하는 .py 파일이 코어 파일인 .pyc 파일을 import 해서 사용하므로, .pyc 파일의 위치는 기존 Python Path 에 넣어주거나, 해당 위치를 Python Path 에 추가해주어야 합니다. 
  • 이니셜라이징 하는 .py 파일 안에, .pyc 파일이 있는 커스텀 경로를 Python Path 로 등록하는 부분을 추가해 주는 것이 하나의 적합한 배포 형태가 될 것 같습니다.





5. 마치며

1) Python Version

.pyc 파일은 Python version specific 한 파일입니다. 다시 말해서, 다양한 version 의 python 에서 모두 동작하게 만들고 싶으면, 각각의 python 에 맞는 .pyc 파일을 제작해서 배포하여야 합니다.

우리는 Maya Python Script 파일을 배포하므로, Maya 가 사용하는 Python version 이 중요한데, 현재 Maya 2012 의 경우 Python 2.6 을 사용하고 있습니다. (이것이 우리가 Python 2.6 을 설치해야 하는 이유) 그러므로, Python 2.6 버전에서 제작 / 컴파일 하면 되겠습니다.



2) 정말 안전한가?

실컷 설명해 두었지만 안타깝게도 이것이 Python script 를 완벽하게 보호해주는 솔루션이 되지는 못합니다. 구글에서는 손쉽게 Python Script 를 Crack 해서 원본 소스코드를 볼 수 있는 툴을 구할 수 있습니다. 

그렇지만 .pyc 가 완전히 보안에 취약하지는 않습니다. 그렇다면 Maya 도 .pyc 형태로 라이브러리를 배포하지 않았겠죠; .pyc 가 일정 용량이 넘어가면 Crack 으로도 소스코드를 풀 수가 없다고 합니다. 즉 소스 코드의 분량이 어느 정도 이상이 되면 보안성이 향상된다는 이야기인데, 여기에 대해서는 사실 좀더 조사가 필요합니다; 따라서 신중한 접근이 필요할 것 같습니다.



이 포스팅은 다음과 같은 고마운 링크들의 도움을 받았습니다.

http://pyfaq.infogami.com/how-do-i-create-a-pyc-file

http://forums.cgsociety.org/archive/index.php/t-880405.html

http://forums.cgsociety.org/archive/index.php/t-605089.html

http://www.mail-archive.com/python_inside_maya@googlegroups.com/msg01024.html

http://mayastation.typepad.com/maya-station/2010/03/the-lowdown-on-the-python-pyc-files-compiled-bytecode.html


ThEnd. 

posted by cimple 2011. 11. 15. 01:17

Maya 의 기본 World Axis 는 Y-up 이다.

갑자기 무슨 일인지 Z-up 으로 바뀌어서 좀 고생을 했다; 잘 모르면 손이 고생이라고...  물론 Preferences 에 있을 것 같기는 한데 모르니까 잘 보이지도 않는다.

하지만 생각보다 간단하게 있었다.

Window > Setting/Preferences > Preferences 를 켠 다음, Settings 탭에서 World axis 를 바꿀 수 있다.



 고생하는 사람이 나뿐만은 아닌가보다. Youtube 에 올라와 있는 동영상.




ThEnd. 
posted by cimple 2011. 6. 30. 17:11



비둘기 프로젝트를 하는데 다음과 같은 조건을 충족시킬 문제가 떨어졌다.

1. 타임라인이 움직이면 깃털들이 랜덤하게 팔락거렸으면 좋겠다.
2. 추가로 플러그인을 만들지 말고 마야에 있는 기능으로 만들었으면 좋겠다.

이런 문제에서는 Maya Expression 이 적당하다. 각각의 깃털들에 대해서 서로 다른 Expression 이 적용되어야 하므로, Python Script 를 이용해서 Expression 을 만들었다.

코드는 다음과 같이 간단하다.



먼저 날개 mesh 들을 모두 선택한 다음, 날개 메쉬 각각에 expression 을 만들어 주는 것이다.

물론 이러면 항상 일정한 값으로 (0.0~3.0 사이 랜덤하게) rotateX 값이 깃털에 들어가게 되는데

controllable 하게 만들어 줄 수도 있다.

하지만 이 정도면 python script 상에서 어떻게 expression 을 만들면 되는지 hello world 는 찍을 수 있을 것이다.


ThEnd.





p.s.

결국 추가로 최종적으로 만든 expression 은 다음과 같다.

expression 안에 다른 attribute 를 넣고 싶으면 getAttr 같은 것을 쓸 필요 없이 바로 쓰면 되고,

if 문으로 조건문 제어가 가능하다.

Python script 로 2줄 이상의 expression 을 넣고 싶으면 일단은 다음과 같이 죽 붙여 쓰는 형태로 짜야 하는 것 같은데

다른 방법이 있는지 찾아봐야겠다.








p.s.2. 3중 따옴표 (""") 의 사용

재밌는 기능을 발견했다. Maya Python Script 에만 있는 기능은 아니고, Python 자체에 있는 기능인데 3중 따옴표를 쓰면 여러 줄의 문자열을 한 string 에 입력할 수 있다.



여러 줄의 expression 을 입력하고 싶을 때 스크립트로 다른 expression 을 입력해서 기존의 expression 을 수정하는 방법은 없는 것 같다. 그러면 또 다른 expression 이 생겨버린다. expression 을 수정하기 위해서는 expression editor 를 이용하는 방법 뿐인듯.

ThEnd.