circe-characterWorks

The character engineer blog of cedric bazillou

  • About
  • Projects
  • resume
  • Demo reel
  • Download

Pose editing: a rig-less approach

Posted by circerigging on November 9, 2018
Posted in: programming, Research. 2 Comments

In today’s article, I will expose some more research related to uberNodes and their associated manipulators.

Pruning rig dependencies :

After taking some years to explore different node design, data-flow and rig architecture , i manage to combine most of the rig evaluation into one unit.

This rig uberNode is now capable of representing most element of a complex character motion and deformation. [this node is covered in the following article ]

The next part I wanted to improve was how to interact with it:

  • No matter how compact the node was its data was relying of a set of complex elements ( local transform attributes, matrix, settings etc).
  • Those element were as well part of a complex hierarchy in order to expose animatable controls which can be manipulated by users.

The answer in this case was to isolate elements relative to manipulation.

Exploring MPxManipContainer :

So from this point my plan was to define my own virtual hierarchy.

structure

This hierarchy was replaced by a set of matrix array attributes.

bipedNode

( above : the dependency node just hold values the manipulator will edit in interactive mode)

Interaction is then delegated to a custom manipulator.

bipedAllManipulators

( click picture to see original size)

Every matrix component have its corresponding manipulator ( most of the time using MFnRotateManip ) and each one of them is part of one ManipContainer using one golden rule:

  • One node is associated to one manipulator

For debugging purposes all manipulators can be drawn on screen.

Viewport and tool exploration :

Along the years we have seen different trend in the animation industry.

  • On screen display with marking menu and their contextual behaviour
  • viewport widget like hudSlider and button
  • Selection handle ( and their high priority selection order)
  • Selection helpers with dedicated picker windows

Pixar and Dreamworks showed their inhouse software featuring proxy shape on screen in order to clean viewport cluttering from the traditional nurbsShape controllers:

premo_demo3_1020

invisible-local-trigger-controls-470x170

 

For my project i wanted interaction to be done with a dedicated picker.

bipedPicker

After some test I was able to edit motion from an alembic and Fbx container without extra dependencies. (I always wanted to add my own pre-roll on the fly and tweak poses while doing shot correctives )

basic_rig2

(above some rigging done by Charles Looker ( Eek on cgtalk ) following the same principle)

The key point here is the hierarchy stay the same structurally ( simple FK for biped) but the manipulator can edit it freely with its own rules.

Similar exploration were done in the past with puppetshop , CAT ( integrated later in 3dsmax) ,motionbuilder’s FBCharacter constraint and tool and even with ( gasp! ) 3dsmax decade old biped.

 

For this project i wrote a bipedNode as an entry point. [any dependecy node can be associated with some accessory and manipulators: usually with MPxManipContainer addToManipConnectTable]

As an added bonus this node can build and draw a shape to evaluate the hierarchy pose and silhouette.

bipedMesh

(Above: cycling through hierarchy component and rootspace can be done through regular toggleManip added to the manipContainer,  it was the debugging method until the picker was functional).

As a regular maya component your manipulator will follow your animation and support undo, it will remove the needs of space-switching ,ik solver blending and any cycle which can appear when beginner tries to implement complex behaviour.

 

Fun features :

a – Picker Manipulator:

e

b – Ik and editing relationship:

e

c – Viewport interaction from picker:

e

d – Pose management:

e

e – Pose management

 

 

Mayanomicon:Toggle state array

Posted by circerigging on July 29, 2018
Posted in: Mayanomicon, scripting. Leave a comment

Today I will show some re-factoring done on my old toggle node .

Pruning rig dependencies :

This node purpose was to simplify a graph network by enabling user to toggle the state of a large number of elements.

Its usually used for common space switching setup :

  • An enum attribute defines which parent is active
  • All other element are then disabled

toggle_UI

As usual on such simple node the core functionality can be written in two lines:

toggleCode

(notice how coding style and pep8 was not my priority nor concern)

def updateToggleStates(self):
    for item in self.currentDataHandleArray:
        item.setBool(False)

    self.currentDataHandleArray[self.currentActiveIndexValue].setBool(True)

def compute(self,
            currentPlug,
            dataBlockInput):
    self.collectOutputhandle(dataBlockInput)

    self.prepareBuilder()

    self.resize(dataBlockInput)

    self.updateToggleStates()

    self.writeOutput()

On the updated code the node will resize the output attribute array  with and array data builder and then write the correct value from the selected currentActiveIndexValue.

Tool design :

To help people have the least amount of preparation the primary mode of this tool will be focused on driving a parent constraint .

toggleTool

item can be reorder in the list with dra and drop and the text edited after a double click

toggleResult

Launching the tool can be done with Mayanomicon/run/openToggleParentWeightsTool.py

Final product and parting words:

Source code and tool are now available in my Mayanomicon repository

The download section will be updated accordingly and expose how module installation works.

 

Mayanomicon:MultiLine text display

Posted by circerigging on June 23, 2018
Posted in: Uncategorized. Leave a comment

On this second node introspection I will expand on one common concept one can need when doing scene management / rig diagnostic:

  • On screen value debugging.

NumToStringNode:

Expanding on my previous post “Hacking maya annotationShape Node”  this node was simply formatting text with a simple numeric input attribute.

numToStringNode2

numToStringNode1

Coding wise that was pretty rudimentary project but fulfilled its mission properly.

format01

Drawing on screen paragraph:

Paragraph

While using the factory annotionShape locator, I notice line break and tabulation were not supported. Hence me writing a custom node to fill this needs.

The reportLocator node displays dynamic text , computed by the report node

( technically you can also use a locator’s compute method  but I wanted clear separation of task ). Both viewport type are supported ( which means for this plugin to use python 2.0 API)

The most interesting part of the node will convert the node position into screen coordinates.

This was covered numerous time by the maya community over the years:

  • From rob bredow’s mel script
  • on highend3d’s forum
import maya.OpenMaya as om

def pointWorldToCam(cameraName, point, res):
    sel = om.MSelectionList()
    dag = om.MDagPath()

    sel.add(cameraName)
    sel.getDagPath(0,dag)

    cam = om.MFnCamera(dag)
    floatMat = cam.projectionMatrix()
    projMat = om.MMatrix(floatMat.matrix)
    floatMat = cam.postProjectionMatrix()
    postProjMat = om.MMatrix(floatMat.matrix)
    transMat = dag.inclusiveMatrix()

    #long form ensures compatibility with MPoint and any iterable
    point = om.MPoint(point[0],point[1],point[2]) 

    fullMat =  transMat.inverse() * projMat * postProjMat
    nuPoint = point * fullMat
    return [(nuPoint[0]/nuPoint[3]/2+0.5)*res[0],
            (1-(nuPoint[1]/nuPoint[3]/2+0.5))*res[1]]

#test
print pointWorldToCam('persp', (0,0,0), (640,480))
  • Or  from koichitamura’s blog
import maya.OpenMaya as OpenMaya

def floatMMatrixToMMatrix_(fm):
    mat = OpenMaya.MMatrix()
    OpenMaya.MScriptUtil.createMatrixFromList ([
        fm(0,0),fm(0, 1),fm(0, 2),fm(0, 3),
        fm(1,0),fm(1, 1),fm(1, 2),fm(1, 3),
        fm(2,0),fm(2, 1),fm(2, 2),fm(2, 3),
        fm(3,0),fm(3, 1),fm(3, 2),fm(3, 3)], mat)
    return mat

def WorldPositionToImageCoordinate(cameraName, imageXRes, imageYRes, worldX, worldY, worldZ):
    p = OpenMaya.MPoint(worldX, worldY, worldZ)
    sl = OpenMaya.MSelectionList()
    sl.add(cameraName)
    dpathCameraShape=OpenMaya.MDagPath()
    sl.getDagPath(0, dpathCameraShape)
    dpathCameraShape.extendToShape()
    fnc = OpenMaya.MFnCamera(dpathCameraShape.node())
    mmatProjection = floatMMatrixToMMatrix_(fnc.projectionMatrix())
    mmatInvCamera = dpathCameraShape.inclusiveMatrix().inverse();
    projected = p * mmatInvCamera * mmatProjection
    imageX = (projected.x/projected.w / 2.0 + 0.5) * imageXRes
    imageY = (projected.y/projected.w / 2.0 + 0.5) * imageYRes
    return imageX, imageY

#print WorldPositionToImageCoordinate('persp', 720, 486, -0.543, 3.926, 7.532)

 

Multiline text offset:

Inside a locator we can access directly the incoming M3Dview instance provided to us.

    def getPointOffset(self,
                       view,
                       path,
                       pointCount):
        self.nodeMatrix = path.inclusiveMatrix()

        self.worldPoint.x = self.nodeMatrix[12]
        self.worldPoint.y = self.nodeMatrix[13]
        self.worldPoint.z = self.nodeMatrix[14]

        isClipped = False
        self.xPosPointer, self.yPosPointer, isClipped = view.worldToView(self.worldPoint)

        offsetX = int(self.xPosPointer)
        offsetY = int(self.yPosPointer)

        return (self.computeViewOffset(view,
                                       offsetX,
                                       offsetY,
                                       path.inclusiveMatrixInverse(),
                                       index)
                for index in xrange(pointCount))

So the code above will extract the 3d world position and use worldToView method to return screen coordinates. after that a simple list comprehension will consider each text line as a separate draw call and offset by 20 pixels on Y direction.

Viewport 2.0 was interesting as well:

    def getPointInScreenCoordinates(self,
                                    objectMDagPath,
                                    frameContext):
        self.nodeMatrix = objectMDagPath.inclusiveMatrix()

        self.worldPoint.x = self.nodeMatrix[12]
        self.worldPoint.y = self.nodeMatrix[13]
        self.worldPoint.z = self.nodeMatrix[14]

        viewPoint = self.worldPoint*frameContext.getMatrix(frameContext.kViewProjMtx)
        basePointX = 0.0
        basePointY = 0.0
        if viewPoint.z != 0.0:
            basePointX = (viewPoint.x/viewPoint.z)*0.5
            basePointY = (viewPoint.y/viewPoint.z)*0.5
        basePointX += 0.5
        basePointY += 0.5

        originX, originY, width, height = frameContext.getViewportDimensions()
        viewPoint.x = basePointX*width
        viewPoint.y = basePointY*height
        viewPoint.z = 0.0

        return viewPoint

Its the MFrameContext which will provide additional information like matrix data.

Final product and parting words:

Source code will be available shortly in my Mayanomicon repository

and simple tool will follows soon.

For now a sample file can be studied inside Mayanomicon/sample/reportSample01.ma.

Let me know if you have questions and as usual have fun hacking maya.

Posts navigation

← Older Entries
  • Pages

    • About
    • Projects
    • resume
    • Demo reel
    • Download
  • Categories

    • Mayanomicon
    • Motion Capture
    • programming
    • Research
    • Rigging
    • scripting
    • Uncategorized
    • Work
  • Currently:

    Senior Pipeline developer at ScanlineVFX – Vancouver.

  • Meta

    • Register
    • Log in
    • Entries feed
    • Comments feed
    • WordPress.com
  • Food Nodes Disciples

    Raymond Faenza
    Felipe Sanges

  • Rigging Links

    Maulik Kataria
    Charles Looker
    Brad Noble
    Chris Evans
    David Johnson
    Nathan Horne
    Adam Pletcher
    Jonas Avrin
    Tyler Good
    Jeremy Ernst
    Ryan Griffin
    ANOOP A.K

Create a free website or blog at WordPress.com.
Privacy & Cookies: This site uses cookies. By continuing to use this website, you agree to their use.
To find out more, including how to control cookies, see here: Cookie Policy
  • Follow Following
    • circe-characterWorks
    • Already have a WordPress.com account? Log in now.
    • circe-characterWorks
    • Customize
    • Follow Following
    • Sign up
    • Log in
    • Report this content
    • View site in Reader
    • Manage subscriptions
    • Collapse this bar
 

Loading Comments...