Monday, 1 September 2014

Revolve node

One more custom node done in Fabric Splice. This time I tackled a couple of things at once.


First was wheel rotation. This solution is based on the objects world matrix instead of a position value or something similar. The idea was based on one of Rigging Dojo's AIR sessions with Raf Anzovin. The object can have as many controls as you want and it will always calculate the correct roll. I added the possibility to connect a parent inverse matrix so the setup can be a child of some other node. Useful when having world positioning controls on a rig.

The next was a parameter to drive objects along a curve. Similar to the rotation, only the output is different. Instead of outputting an angle value the parameter is a value between 0 and 1.

And the last was instancing. A mesh will be projected on the custom splice curve and it is driven by the parameter value. I extended the BezierXfo class that comes with Splice and added a new function that takes a number of instances and a starting offset as the input. In this case parameter is that offset and it tells the function where the first element should be on the curve. Then the other elements are projected onto the curve with an equal distance between them.

Check out the video bellow to see the node doing its thing:


Revolve Node in Maya from Armin Halac on Vimeo.

Sunday, 24 August 2014

Delta Mush

I've been really busy the last couple of months and things were quiet on my blog. In the meantime I started getting into the Maya API and jumped on the Fabric Splice train. I have a couple of nodes that I want to demo and I will start with the first deformer that I ever wrote. A prototype of the Delta Mush deformer:



The deformer is based on the Delta Mush deformer in Voodoo. You can find more detail about it in this Siggraph paper.
The paper explains it functionality and beside the information they give you all you need is the math to calculate everything.
Maya does not hava a Laplacian smooth deformer so I had to incorporate it in the node. Thanks to Olivier Dionne for sending me a link to this document which contains the necessary calculations for the smoothing.

The node is written in Fabric Splice for Maya. The good thing is that the deformer does not depend on Maya and can be used in any of the Splice implementations (Softimage, 3DS Max among others).
In this thread you can find a lot of useful info on the math behind this and also how to get some of the point data from the mesh. It is great that Roy Nieterau shared it with everyone.

Splice is still under development and even though some things are missing it is already an amazing tool. Especially because of its cross platform compatibility. And how easy it is to do some low level stuff really fast. I am also looking forward to Kraken, an open source cross platform rigging tool.

The model used in the video is downloaded from www.hippydrome.com. A great model and the site is a great resource for everyone.

The video below is showing the deformer in action. I just added some bones and bound the mesh using one influence per vertex, without any weight painting.


Delta Mush Deformer in Maya from Armin Halac on Vimeo.

Wednesday, 22 January 2014

Mirror across sphere rig

In my previous post I explained the math and maya nodes you need to create mirroring of positions in 3D space. Here is a different, more complicated, example where I created a rig that mirrors across any point on a sphere. I used a sphere but it can be any object you want. The only limitation would be a low poly mesh where the mirrored positions would snap since there would not be enough polygons that would provide data on normals that would ensure a smooth transition. In that case I would probably add some nurbs patches that match the poly shape and use their normals.


Mirroring across a sphere from Armin Halac on Vimeo.

Questions and comments are welcome.


Sunday, 19 January 2014

Mirroring across a plane - Tutorial

Mirroring a point across a plane (ex. YZ plane) seems easy but it requires a couple of math tricks to make it work every time. The main tool for achieving this effect is the dot product. It gives us the projections of our point on Y and Z axes and with those values we have almost everything we need for our mirrored position. With a few Maya nodes we can implement this in a scene:

The completed node graph

Same calculations can be done to mirror any object, vertices, curves...
I go into more detail on how this works in the video:

Mirror across a plane - Tutorial from Armin Halac on Vimeo.

Edit:
This technique was more of a demonstration of some math tricks that could be more useful in many other cases. To do the same mirroring the easy way you can just take the world position of the first object and multiply the x value by -1 and you will get the mirrored position. That is what I would do in a real case scenario because it is faster and more efficient then doing all the math stuff.

Thursday, 16 January 2014

Skeleton pose manager - Free script

This script is inspired by some of TD Matt's blog posts where he goes into detail about skinning and rigging meshes in different poses. He was hosting a script that did the similar job as this one (at least I think it did the same job because I never got to use his script) but the download link is broken. So I made my own version of the tool.



A few things to keep in mind while using the tool:
- The pose data for every joint is written to a custom attribute and the data is preserved if the joints are copied. So make sure to delete it from duplicated joints like those for IK/FK switching so they stay in place while you switch poses on your bind joints.
- When mirroring poses from one side to the other make sure to select joints down the chain because the data is stored in the object space.
- The mirroring function uses the "L_" and "R_" prefixes to find the correct joints. Edit the mirrorPrefixs variable in the script to the prefixes you use. I know that it is not good to hard code stuff but I did it here for the sake of simplicity.
- I was playing around with pymel classes for ui elements and tried to write everything in an object oriented way so it might look a bit weird to you who are used to using flags to set up ui elements. When writing this way there are a lot more lines of code but everything is easy to read and a lot easier to edit.

Hope you find the script useful and let me know if you find any bugs. I will fix them as soon as I can.

DOWNLOAD

Sunday, 29 December 2013

Align joint to edge script

I was reading through posts on tech-artists.org and a fellow artist was looking for an automated solution for aligning of joints to edges and to orient them to the edges average normal. So I decided to write this as a little exercise. It is a pretty straightforward solution.



Since I haven't found a method that gives me the average normal on an edge I grabbed all the surrounding faces and calculated the average normals using the normals of those faces.
Then I use the connected edges to find a usable up vector for the further calculation. The up vector and the average normal were used to calculate all axes using the same principle the aim constraint uses. Just a couple of cross products and you're done. The only thing left is to construct a matrix from the data I calculated and to apply this matrix to a joint.

Here is a link to the forum post

And the DOWNLOAD link for the script.


#########################################################################################################################
#########################################################################################################################
###
### ah_jointToEdge.py
### 
### V. 1.10
###
### Made by: Armin Halac
### Email: arminhlc@gmail.com
### Phone: +387 61 908 301
### 
### Client: none
### 
### Setup:
### 1.copy ah_jointToEdge.py to /MyDocuments/Maya/2014x64/scripts (replace "2014x64" with the version that you are using)
### 2.open maya and launch the script editor
### 3.switch to a python tab and enter:
###
### import ah_jointToEdge
### reload(ah_jointToEdge)
### ah_jointToEdge.create()
###
### 4.middle mouse drag this to a shelf
###
### Usage:
### 
### Select any number of edges and run the script. A joint will be created on every selected edge and it will be oriented
### to match the average edge normal.
###
### Please report any bugs or other issues and I will look into them ASAP.
###
#########################################################################################################################
#########################################################################################################################


import pymel.core as pm

def create():
    # Variables to store selected edges, verts and faces those edges are connected to
    verts = []
    edges = []
    faces = []

    # Get the selection and flatten it. Otherwise Maya might return lists and not individual elements
    sel = pm.selected(flatten = True)

    # Get the selected edges
    for s in sel:
        # Get the selections type
        objType = s.__class__.__name__
            
        # If the type is MeshEdge then append the edge to our list
        if objType == "MeshEdge":
            edges.append(s)

    # Continue only if we have edges selected
    if edges:

        # Do this for every edge
        for edge in edges:
            # Get the vertices the edge is connected to
            edgeVerts = edge.connectedVertices()

            # Cluster the verts. We will use this to get the position for our joint
            clusDef, clusTfm = pm.cluster(edgeVerts)

            # Clear the selection. If a joint is selected Maya might make the new joint a child of the selected one
            pm.select(clear = True)
            # Create our joint
            jnt = pm.joint()

            # getPosition doesn't give us the correct result. This does
            pos = clusTfm.rotatePivot.get()
            # We don't need the cluster any more
            pm.delete(clusTfm)

            # Now we calculate the average normal
            normals = []
            for face in edge.connectedFaces():
                # Collect the normal of every face
                normals.append(face.getNormal(space = "world"))

            # Variable that will store the sum of all normals
            normalsSum = pm.datatypes.Vector()
            for normal in normals:
                normalsSum += normal

            # This will be our vector for the x axis
            xVec = (normalsSum / len(normals))  # Average normal. We divide the normal by the total number of vectors

            # The vertex that has the highest position will be the vertex that our Y axis will point to
            for i, vert in enumerate(edgeVerts):
                # We take the first vert as our up vector
                if i == 0:
                    upVec = edgeVerts[0].getPosition(space = "world")

                # And compare the other to it
                vertPos = edgeVerts[i].getPosition(space = "world")
                if vertPos[1] >= upVec[1]:
                    upVec = vertPos

            # This gives us a vector that points from the center of the selection to the highest vertex
            upVec = upVec - pos

            # We get the z vector from the cross product of our x vector and the up vector
            zVec = xVec.cross(upVec)
            # Calculate the y vec the same way. We could use the upVec but this way we make sure they are all correct
            yVec = zVec.cross(xVec)

            # Normalize all vectors so scaling doesn't get messed up
            xVec.normalize()
            yVec.normalize()
            zVec.normalize()

            # Construct the matrix from the vectors we calculated
            jntMtx = pm.dt.Matrix(xVec, yVec, zVec, pos)
            # And set the joints matrix to our new matrix
            jnt.setMatrix(jntMtx)

            # This transfers the rotation values to the joint orientation values.
            pm.makeIdentity(jnt, r = True, apply = True)

Tuesday, 24 December 2013

Elephant Rig

As promised here is a video showing the rig. I have also included a small demonstration of the script that I wrote to automate the trunk creation. The technique for the variable FK rig was demonstrated by Jeff Brodsky in this video.
I was only responsible for the elephant rig and deformation. Everything else is done by the guys at Irie studios.



Elephant Ride rig demo from Armin Halac on Vimeo.

The video, music and registered trademarks or trademarks are property of their respective owners.