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 2016. 3. 29. 17:26

Numpy 에 nonzero 라는 function 이 있다.


http://docs.scipy.org/doc/numpy-1.10.1/reference/generated/numpy.nonzero.html#numpy.nonzero


document 를 봐도 헷갈리는 함수인데, non-zero 인 element 에 대하여 2D array 형태로 리턴하는 함수이다.


예를 들어

import numpy
arr = numpy.array([[1,0],[2,3]])
arr.nonzero()

이런 식으로 사용했을 때, 다음과 같은 결과를 얻게 될 것이다.

--> (array([0, 1, 1]), array([0, 0, 1]))

이 결과물이 낯설게 느껴질 수 있는데, input 으로 주어진 행렬에서 nonzero element 의 'index' 를 행과열을 각각 적은 것이다.


다시 말해서, input 으로 주어진 행렬(numpy array) 는 다음과 같다.


| 1   0 |

| 2   3 |


여기에서 0이 아닌 element 들의 행렬 index 는 다음과 같을 것이다. 행, 열의 성분을 보기 쉽도록 다른 색으로 표현했다.


(0,0), (1,0), (1,1)


numpy.nonzero 함수는 저 index 들에서 행은 행대로, 열은 열대로 따로 묶어서 리턴해주는 것이다. 


(0, 1, 1)

(0, 0, 1)


왜 이런 식으로 리턴하는가 하면, ([0,1,1], [0,0,1]) 형태의 튜플로 원래 array 에서 곧바로 element 를 뽑아올 수 있기 때문이다.


다시 말하면 위의 예제에서

arr[arr.nonzero()]
--> array([1, 2, 3])

이런 식으로 non-zero element 를 직접 접근할 수 있고, 이는

arr[[0,1,1],[0,0,1]]

로 직접 입력해 보면 같은 결과를 얻을 수 있음을 확인할 수 있을 것이다.





Numpy 의 where() 함수도 마찬가지이다.


http://docs.scipy.org/doc/numpy-1.10.1/reference/generated/numpy.where.html


where() 함수는 condition 만 주어지면 condition 을 만족시키는 element 의 index 를 반환하는데, 이 때 반환하는 형식이 nonzero 함수와 동일하다.



posted by cimple 2016. 3. 16. 12:24

Github 사용은 할때마다 조금씩 느는것 같긴 한데 계속 헷갈리는 부분이 있는것 같다.

논문 작성을 다른 멤버들과 같이하기 위해서 논문작성 자체를 Github 를 통해서 진행하려고 한다.


1. 논문 texfile 이 있는곳에 create repository 를 하면 git 저장소가 된다.

2. 일단 master branch 로 initial commit 했다.

3. 내가 수정할 local branch 를 만들고, 거기에서 수정을 한 다음, master 에 merge 할 수 있다. Window 용 github 프로그램에서 손쉽게 할 수 있는데, merge 를 당할(?) branch 에 간다음, 특정 branch 와 compare 하고, 충돌이 없으면 merge 할 수 있다. (ex. master 로 checkout -> songjaewon branch 와 비교 -> 충돌없으면 merge)


4. 협업을 위해서는 github상에서 merge 절차를 하는게 맞아보인다.

5. github 저장소에서 branch 를 만들어 줄 수 있다. 또는, 내 repository 를 fork 한 사람이 나름 local branch 를 만든 다음 push 할 수도 있을 것이다.

6. 내 branch 와 master branch 를 비교해서 pull request 를 보낼수 있다. 문제가 없으면 master 가 merge 시켜주면 해당 버전으로 최신 업데이트 되는 것이다.


7. 내 local 에서는 sync 를 하면 master 의 최신내용으로 업데이트된다. 


(알아야 할 것. 내 master 와 github 의 master 가 서로 다를 경우 sync 를 시키면 어디를 기준으로 최신업데이트가 이루어지는지 궁금하다)


(알아야 할 것. 다른 사람이 올린 branch 를 내 local repository 에 끌고올수는 없는지 궁금하다.)