상세 컨텐츠

본문 제목

ripple plugin 강좌

Maya API/Maya_PythonAPI 구문들

by hwano 2013. 12. 16. 06:02

본문

 

 

물론 플러그인의 계산 퍼포먼스를 올리기위한 방법이 좀더 있을거라고 생각은 되지만

아래의 기본적인 deformer를 불러와 마야에서 sphere subdivision  200/200에

적용한 결과는 암담하다.

 

 

무려 5fps의 속도로 거의 쓰레기같은 계산 퍼포먼스를 보여준다.

( 마야에서 제공하는 기본 디포머들은 저정도 subdivision엔 거의 퍼포먼스 저하가 없다.

물론 sphere 딱 하나로만 계산했을 경우지만,,  어쨌든 거기에 비하면 전혀 쓸모없는 deformer라고 볼 수있다. )

 

 

아무리 python이라지만 나름 API이름을 달고 있는데

마치 기본 python 스크립트로 script단에서 class로 버텍스를 움직이는 것과 별반 달라보이지 않는

퍼포먼스를 보여주니 매우 실망스럽다.

 

 

이 정도 테스트 해봤으면 파이썬으로 속도와 연관되는 플러그인을 개발하는건

거의 시간을 버리는 거라 결론되어 진다.

 

 

 

maya python        - 아주 단순 반복작업과 UI정도에 사용

maya python API  - 버전을 타지않고 다소 쉬운코딩때문에 가벼운 계산의 노드에서만 사용

                            ex) 가이드용 노드 등

maya API            - 속도와 관계된 모든 플러그인에 사용

 

해야할거 같다..

 

 

즉, 

 

아,,  공부하기 싫어 시방

 

 

 

////////////////////////////////////////////////////

 

 

 

c++로 넘어가면 좀 다를 순 있겠지만

pythonAPI로 노드를 구성하는 코딩이 생각보다

복잡하지 않은건 다행이다.

 

각 플러그인들 마다 반복되는 구문들을 제외하면

개발시간이 오래걸리지는 않는듯.

 

script에서 dag에서 겹치는 이름들과 namesapce문제, freeze문제

world, local시에 달라지는 좌표들, 간단한 계산 구문을 짤려고 해도 expression이 아니면

수천개의 muliply, plus노드들을 만들고 관리해야하는 문제들

때문에 어느 상황에서나 완벽하게

구동하는 script를 짜려면 말도 못하게 쓸데없는 노력이 들어가는걸 생각한다면 이정도야,,

 

 

 

 

#-*- coding: utf-8 -*-
import sys
import maya.OpenMaya as om
import maya.OpenMayaMPx as omMPx
import math

nodeName = 'RippleDeformer'
nodeId = om.MTypeId(0x102fff)

class Ripple( omMPx.MPxDeformerNode ):
    '''
    Commands ----> MPxCommand
    Custom   ----> MPxNode
    Deformer ----> MPxDeformerNode
    '''
    mObj_Amplitude = om.MObject()
    mObj_Displace = om.MObject()

    def __init__( self ):
        omMPx.MPxDeformerNode.__init__( self )

    def deform( self, dataBlock,geoIterator, matrix, geometryIndex ):
       
        input = omMPx.cvar.MPxDeformerNode_input
        #____ 1. input Array Attribute에 handle을 붙인다
        dataHandleInputArray = dataBlock.inputArrayValue( input )
        #____ 2. 각각의 element로 넘어간다
        dataHandleInputArray.jumpToElement( geometryIndex )
        #____ 3. Attach a handle to specific data block
        dataHandleInputElement = dataHandleInputArray.inputValue()
        #____ 4. Reach to the child - inputGeom
        inputGeom = omMPx.cvar.MPxDeformerNode_inputGeom
        dataHandleInputGeom = dataHandleInputElement.child( inputGeom )
        inMesh = dataHandleInputGeom.asMesh()
       
        #____ Envelope
        envelope = omMPx.cvar.MPxDeformerNode_envelope
        dataHandleEnvelope = dataBlock.inputValue( envelope )
        envelopeValue = dataHandleEnvelope.asFloat()
       
        #____ Amplitude
        dataHandleAmplitude = dataBlock.inputValue( Ripple.mObj_Amplitude )
        amplitudeValue = dataHandleAmplitude.asFloat()
       
        #____ Displace
        dataHandleDisplace = dataBlock.inputValue( Ripple.mObj_Displace )
        displaceValue = dataHandleDisplace.asFloat()
       
        mFloatVectorArray_normal = om.MFloatVectorArray()
        mFnMesh = om.MFnMesh( inMesh )
        mFnMesh.getVertexNormals( False, mFloatVectorArray_normal, om.MSpace.kObject )
       
        while( not geoIterator.isDone() ):
            pointPosition = geoIterator.position()
           
            pointPosition.x = pointPosition.x + math.sin( geoIterator.index() + displaceValue ) * amplitudeValue * mFloatVectorArray_normal[ geoIterator.index()].x * envelopeValue
            pointPosition.y = pointPosition.y + math.sin( geoIterator.index() + displaceValue ) * amplitudeValue * mFloatVectorArray_normal[ geoIterator.index()].y * envelopeValue
            pointPosition.z = pointPosition.z + math.sin( geoIterator.index() + displaceValue ) * amplitudeValue * mFloatVectorArray_normal[ geoIterator.index()].z * envelopeValue
            geoIterator.setPosition( pointPosition )
            geoIterator.next()
                   

def deformerCreator():
    nodePtr = omMPx.asMPxPtr( Ripple() )
    return nodePtr
   
def nodeInitializer():
    '''
    구성순서
    Create Attributes
    Attach Attributes
    Design Circuitry
    '''
   
    #____Create Attributes
    mFnAttr = om.MFnNumericAttribute()
    Ripple.mObj_Amplitude = mFnAttr.create( 'AmplitudeValue', 'AmplitudeVal',
                                             om.MFnNumericData.kFloat, 0.0 )
    mFnAttr.setKeyable( 1 )
    mFnAttr.setMin( 0.0 )
    mFnAttr.setMax( 1.0 )

    Ripple.mObj_Displace = mFnAttr.create( 'DisplaceValue', 'DispVal',
                                           om.MFnNumericData.kFloat, 0.0 )
    mFnAttr.setKeyable( 1 )
    mFnAttr.setMin( 0.0 )
    mFnAttr.setMax( 10.0 )
   
   
    #____Attach Attributes
    Ripple.addAttribute( Ripple.mObj_Amplitude )
    Ripple.addAttribute( Ripple.mObj_Displace )
   
   
    '''
    SWIG - simplified Wrapper Interface Generator
    '''
    #____Design Circuitry
    outputGeom = omMPx.cvar.MPxDeformerNode_outputGeom
    Ripple.attributeAffects( Ripple.mObj_Amplitude, outputGeom )
    Ripple.attributeAffects( Ripple.mObj_Displace, outputGeom )
   
   
   
   
   
def initializePlugin( mobject ):
    mplugin = omMPx.MFnPlugin( mobject )
    try:
        mplugin.registerNode( nodeName, nodeId, deformerCreator, nodeInitializer, omMPx.MPxNode.kDeformerNode )
    except:
        sys.stderr.write( 'Failed to register command: %s\n' %nodeName )
        raise

관련글 더보기