Code Monkey home page Code Monkey logo

ragdoll-maya's Introduction

gumtree_cover

Character animation tools for Autodesk Maya 2018-2022 that enable automatic overlapping animation through high-performance rigid-body simulation techniques.


Usage

This repository contains the Python package associated with the commercial compiled plug-in for Maya.

Read more


Open Source

Some of the work in Ragdoll has been separated out into its own smaller projects.


Repository

All Maya integration and user-facing tooling is stored in this repository. It's here to better help you integrate and extend the project to fit your specific pipeline, and similar to my other open-source projects facilitate PRs and the opportunity to take matters into your own hands. You've also got access to the commercial website and learning material to facilitate contributions and fixes.

Path Description
ragdoll The Ragdoll Python package
web Source for https://ragdolldynamics.com
docs Source for https://learn.ragdolldynamics.com

Contributing to Documentation

Alongside the Python package, this repository also contains the documentation for Ragdoll, which you can build and preview locally prior to making a contribution.

From PowerShell on Windows, call each line below.

iwr -useb get.scoop.sh | iex
scoop install python git
python -m pip install mkdocs_git_revision_date_plugin
python -m pip install git+https://github.com/mottosso/mkdocs-material-design.git
git clone https://github.com/mottosso/ragdoll.git
cd ragdoll/docs
.\serve.bat

On Linux, use serve.sh instead of serve.bat

Documentation should now be accessible at http://localhost:8000. Whenever you edit any Markdown document under ragdoll/docs/pages, the website will automatically be rebuilt and your browser refreshed. It might take a few seconds.

ragdoll-maya's People

Contributors

alanjfs avatar costashatz avatar davidlatwe avatar mottosso avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ragdoll-maya's Issues

New Physics in Namespaced Scene

Seems to be a bug whereby if there exists a scene with a namespace, no more physics can be created.

Ragdoll 2021.06.10

# Traceback (most recent call last):
#   File "<maya console>", line 2, in <module>
#   File "C:\gitlab\ragdollai\ragdoll-dynamics\python\ragdoll\internal.py", line 422, in _undo_chunk
#     return func(*args, **kwargs)
#   File "C:\gitlab\ragdollai\ragdoll-dynamics\python\ragdoll\interactive.py", line 1150, in create_active_rigid
#     scene = _find_current_scene()
#   File "C:\gitlab\ragdollai\ragdoll-dynamics\python\ragdoll\interactive.py", line 859, in _find_current_scene
#     current = __.solvers.index(scene.shortestPath())
# ValueError: u'_:rSceneShape' is not in list # 

ragdoll.commands.assign_marker unused group argument

The group argument in ragdoll.commands.assign_marker() is unused.

from ragdoll import commands as ragCmds

cube = ragCmds.cmdx.encode(cmds.polyCube(ch=False)[0])
solver = ragCmds.create_solver("test")
group = ragCmds.create_group(solver, "group")
marker = ragCmds.assign_marker(cube, solver, group=group)

# marker is not connected to group
for con in group.connections(source=True, destination=False):
    print(con)

Exception in ragdoll.commands breaks undo

from ragdoll import commands as ragCmds

# calling with wrong arguments/types to cause exception
group = ragCmds.create_group("test")

Trying to undo in maya results in:
// Error: line 1: Undo is temporarily unavailable. Try exiting the current tool. //

Calling cmds.undoInfo(closeChunk=True) seems to solve the issue.

Is this a bug or is it deliberately left to the TDs to validate their inputs?

Recording Performance Research

Recording is currently a two-step process, each running through the full timeline, e.g. frame 1-100.

  • For each frame:
    1. Evaluate rig, step simulation and record worldspace position of each marker
    2. Evaluate rig, convert world space positions to local space and write into Translate/Rotate channels

Step 1 is fast as the simulation is fast, and as far as Maya is concerned can run in parallel. No Maya data is modified during this step, so the Maya Evaluation Manager won't have to recreate its internal graph.

Step 2 is slow because we must once again evaluate the rig a second time, but this time cannot do it in parallel as we modify the rig each frame. As a result, evaluation happens in a single thread, and the evaluation graph is recreated each frame. It can be infinitely slower, depending on the complexity of such a rebuild. From taking 2x longer than simulating, to 100x longer. From taking 5 seconds, to taking far too long for comfort.

So, is there a way to avoid step 2?

  1. For an entirely kinematic hierarchy, we can internally compute local positions given a worldspace position, by assuming that the dynamic and kinematic parents are the same. If so, we can invert the dynamic parent and multiply it with our world matrix to arrive at a local matrix. An example of entirely kinematic is a mocap joint hierarchy. But anyting beyond that, especially involving IK and constraints and offset groups, break this requirement.
  2. For a character rig whose offsets between markers never change, we can once again use the parent marker alongside a pre-computed offset matrix to arrive at a local matrix. However this is very hard to prove up-front, as even things like rotatePivot can be animated and change over time. Resulting in an unreliable recording unless the animator explicitly guarantees that this relationship holds true.
  3. ...?

I find this problem difficult to solve, but also difficult to explain. It's complicated. But important. It's the difference between taking 500 ms and 50,000 ms to record a simulation. Given that we can evaluate the entire rig, read-only, over the full timeline, in parallel there must be a way in which we can then turn around and use what we evaluated to generate appropriate local Translate/Rotate channels without re-evaluating the rig.

So I'm leaving this here as a record of where I'm at right now and hope to solve this in the future as my understanding of the problem grows. If this sounds familiar to you reading this, or if you have any further ideas, feel free to comment on this issue.


Example

Here's an example of an IK hierarchy, representing our markers, being animated and recorded in worldspace. And then re-applied to another hierarchy, that assumes a linear, FK relationship between each recorded marker.

record2.mp4
def make_chain(name):
    with cmdx.DagModifier() as mod:
        group = mod.create_node("transform", name=name)
        root = mod.create_node("joint", name="root", parent=group)
        knee = mod.create_node("joint", name="knee", parent=root)
        foot = mod.create_node("joint", name="foot", parent=knee)
        tip = mod.create_node("joint", name="tip", parent=foot)
        
        mod.set_attr(root["translateY"], 10)
        mod.set_attr(knee["translateX"], 5)
        mod.set_attr(foot["translateX"], 5)
        mod.set_attr(tip["translateX"], 2)
        
        mod.set_attr(root["jointOrientZ"], cmdx.radians(-45))
        mod.set_attr(knee["jointOrientX"], cmdx.radians(180))
        mod.set_attr(knee["jointOrientZ"], cmdx.radians(-90))
        mod.set_attr(foot["jointOrientX"], cmdx.radians(180))
        mod.set_attr(foot["jointOrientZ"], cmdx.radians(-135))

    return group, root, knee, foot, tip

outputs = make_chain("outputs")
inputs = make_chain("inputs")

cmds.select(str(outputs[1]), str(outputs[3]))
handle, eff = map(cmdx.encode, cmds.ikHandle())

start_pos = handle["translateY"].read()
anim = {
    1: start_pos,
    20: start_pos + 5,
    40: start_pos
}

with cmdx.DagModifier() as mod:
    mod.set_attr(handle["translateY"], anim)

outputs = tuple(
    (node, {})
    for node in outputs[1:]
)

# Evaluate and Store
before = cmdx.current_time()
for frame in range(1, 45):
    time = cmdx.om.MTime(frame, cmdx.TimeUiUnit())
    cmdx.current_time(time)

    for node, mats in outputs:
        mat = node["worldMatrix"][0].as_matrix()
        mats[frame] = mat

cmdx.current_time(before)


# Restore, no evaluation
with cmdx.DagModifier() as mod:
    # Move others to the side
    mod.set_attr(inputs[0]["tz"], -5)

    for index, (node, mats) in enumerate(outputs):
        parent_node, parent_mats = outputs[index - 1] if index > 0 else (None, None)

        anim = {"rx": {}, "ry": {}, "rz": {}}
        for frame, mat in mats.items():
            parent_inverse = cmdx.Mat4()
            if parent_mats:
                assert parent_node == node.parent(), "%s != %s" % (parent_node, node)
                parent_inverse = parent_mats[frame].inverse()

            tm = cmdx.Tm(mat * parent_inverse)
            r = tm.rotation()
            anim["rx"][frame] = r.x
            anim["ry"][frame] = r.y
            anim["rz"][frame] = r.z
    
        other = cmdx.encode(node.path().replace("outputs", "inputs"))
        mod.set_attr(other["jo"], (0, 0, 0))
        mod.set_attr(other["rx"], anim["rx"])
        mod.set_attr(other["ry"], anim["ry"])
        mod.set_attr(other["rz"], anim["rz"])
        print("Animated %s" % other)

replace_mesh not setting shapeType attribute on marker

I feel like calling replace_mesh() should automatically set the shapeType attribute to Mesh.

This is not a problem with markers that get created on geometry as they get their shape type set to Mesh by default as far as I can tell but replacing the mesh on markers that were created for joints seemingly does nothing.

After running the code in the bottom, visually nothing will happen in scene. The marker will still display as sphere. Only after setting shapeType to Mesh we will see the effect.

(Or is this intended?)

from ragdoll import api as ragApi

jnt = cmds.joint()
torus = cmds.polyTorus(ch=False)[0]

solver = ragApi.create_solver('test_rSolver')
marker = ragApi.assign_marker(jnt, solver)

enum_attr = cmds.attributeQuery('shapeType', n=marker, listEnum=True)
print(f"Shapetype {enum_attr}: {cmds.getAttr(marker + '.shapeType')}")

ragApi.replace_mesh(marker, cmds.listRelatives(torus)[0])

print(f"Shapetype {enum_attr}: {cmds.getAttr(marker + '.shapeType')}")
print("Should switch to 4 -> Mesh")

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.