From 25d0b1da90a4f0935d415055b5afe64cce509cbd Mon Sep 17 00:00:00 2001
From: Alan Jefferson This addon is licenced under the MIT licence Ragdoll 2024.04.14 awaits. Ragdoll 2024.04.15 awaits. If you agree with the Ragdoll Dynamics EULA, you may select a platform below. Ragdoll 2024.04.14 awaits. Ragdoll 2024.04.15 awaits. Learn RAGDOLL Real-time physics for Autodesk\u00ae Maya 2018-2022 Ragdoll provides animators with real-time physics for fast, automatic overlapping motion. Here's a brief overview of how Ragdoll came to be. In 2008 Marcus Ottosson graduated from BTH in Blekinge, Sweden and ventured into the world as character animator at Meindbender; to work on The Duplicators and The Pirate amongst others. In 2012 He joined Framestore and familiarised himself with the world of physics simulation, developing the technology behind the tethers for Alfonso Cuaron's feature film Gravity, and later completed work on the Cloak of Leviation in Doctor Strange. In 2015 He started a company called Abstract Factory developing tools in Python for use in production pipelines, including Avalon, Pyblish, Qt.py, cmdx and Allzpark; later recieving the \"Best Tool\" award for Pyblish at the 2020 DigiPro/The Pipeline Conference. In 2017 He started a company called WeightShift with co-founders Danny Chapman and Tim Daust. They had just wrapped up the Endorphin and Euphoria projects at Natural Motion. Like Euphoria, WeightShift developed a physically based animation tool, except this one was tailored to Autodesk Maya and got adopted by major feature film studios including Framestore (Harry Potter, Gravity et. al.) and Weta Digital (Avatar, Lord of the Rings et. al.) In 2020 WeightShift is purchased by Epic Games In 2020 Ragdoll carries on where WeightShift left off, but turns things on its head. Rather than targeting riggers and technical animators, Ragdoll adopts a \"no-rigging required\" approach. July 28th 2021 Ragdoll is launched. In 2012, Marcus travelled to London after 5 years of character animation experience in Sweden and \u00a315,000 of life savings in order to secure a job at Framestore, the studio he'd been looking up to since before venturing out into the real-world. He booked a crummy hotel around Hyde Park for 2 weeks during which time he expected to find a permanent residence somewhere in town, but it wasn't so easy! After days of viewing flats and hours after finally checking out - in desperation - he transferred a majority of his life savings for 6 months of rent up-front to a listing he found on Craigslist. That luckily wasn't a scam. With his foot firmly on the ground, Marcus applied to work for Framestore; only to find that they weren't looking for animators! Instead, they needed \"Creature FX\" artists, to begin work right away on a project taking place in space. Creatures? In space? Done deal! That's when he learned that \"creature\" actually meant \"tether\" and FX means \"simulation\" and that the project was Gravity. It was during that time when the character animator was introduced to physics simulation and with it an idea to bring this marvel of technology to the otherwise non-physically simulated world of character animation. With Maya and nCloth under his belt, he had all the tools necessary to begin working on an adaptation for animators. Or so he thought! First Prototype Utilising the nCloth to IK This time using follicles on the simulated geometry to derive positions for a skeleton to be attached and used to skin the final character geometry. Don't let the fps counter fool you, this version was point-cached. The interactive performance was less than 5 fps. Alternative Setup Same idea, now interacting with another nCloth object in the scene. A few prototypes later, he realised this wasn't going to fly. To tackle this, one would need a firm grasp on software development, but that would take time. As they say; two steps forward, one step back. Inspired by the manner and amount of automation taking place at Framestore, he set out to bring automation to the masses, using skills less reliant on maths and algorithms and more reliant on workflow. 3 years later, Pyblish is a technically and practically successful product, another 3 years it would go on to win the DigiPro 2020 award for Best Pipeline Tool, even though it would yield very little money; lessons learnt in running a business on open-source software. (Namely don't) He was now somewhat technically savvy with a greater understanding of the challenge that lies ahead, what he needed now was a team. Building on his prior connections in Sweden, he reached out to the founders of a former workplace for aid. They were interested in branching out into software development and was a suitable customer to the technology I had in mind; they offered to invest. By happenstance, he found a character rigger with multiple feature film projects behind her, interested in trying something new. Finally, the technology was to be based heavily on machine learning for which he found a lecturer at Oxford University interested in dedicating time and resources to our cause. Months of pitching at events in search for a team (Startup Weekend ftw!), everything was now in place. But there was a hitch; in order to offer investment, they wanted something in return. A pipeline. Marcus spent the next 3 months developing Avalon, which was later open sourced and is now a moderately successful pipeline framework powering dozens of studios around the globe, including Colorbleed, Moonshine and Kredenc. Ready, set, go; the team was set, a customer waiting and investment ready to go. But there was a problem. After signing for a shared office space and days before moving in to start working, the investor couldn't live up to his end of the bargain and the deal blew up. Two steps forward, one step back. After having to let everyone go, Marcus remembered one of the prospects he interviewed for this team; a senior figure at Natural Motion - developers of physics simulation software Endorphin and Euphoria - which was just about to be absorbed by the mobile-games goliath Zynga, scrapping their work on character animation technology. They spent two weeks putting together a prototype of their aspirations and went on to form a company to develop WeightShift Dynamics 2 years later and WeightShift had been adopted by Weta Digital in New Zealand and Framestore in London. But there was a hitch; visions no longer aligned, conflict arose and the team disbanded. The silver lining was that Epic Games was interested purchasing the technology, providing enough of a runway to restart development and try again. Two steps forward, one step back. After a brief stint developing Allzpark for the Japanese Studio Anima and then animating for Redfall and Horizon Zero Dawn II at Goodbye Kansas it was now 2020. With funding and experience spanning animation, programming, business and now physics all the pieces were in place. What he could not do in 2012 was now made possible. Ragdoll consists of custom nodes written in C++, but everything involved in connecting these up and generating the dependency network happens in Python. This API is exposed to you for integration with auto-rigging, tools development and to generally just extend the capabilities of the system. The full source code of everything Python is also available on GitHub, where you may also submit issues and pull-requests to improve the tooling for everyone. See Also There are 3 supported methods of integrating Ragdoll into your pipeline. Each with its own flare. The publicly facing programming interface to Ragdoll. Use this for tools integrated with other tools that rely on heavy compatibility between versions and few surprises on what goes in and out. Member Reference The All of Finally, this module is used for UI elements like the main Ragdoll menu. Every function takes selection into account, along with any preferences set via the Option Dialogs. It's useful for when you want to replicate what the menu does, including taking selection into account and outputting warning messages in the Script Editor. It won't raise exceptions like Pro Tip Whenever you click a menu item, this Python command is printed in the Script Editor! Currently available members of Gain more control over the integration of Ragdoll into your pipeline with these optional environment variables. For example, to avoid the startup dialog on first launch, set The complete Ragdoll API. A more in-depth view on each function. Create a new rdSolver node Download
Download for Blender 3.4 to 4.0
+
Read about it -
Previous versions
Download
Download Ragdoll Core
+
Read about it -
Previous versions
Ragdoll enters chat
Bend Resistance
and Attract to Matching Mesh
features of nCloth. The challenge was tailoring the edges such that they carried the weight of the character and the motion he was to perform. More rigidity meant less performance, thus he always ended up too squishy.
"},{"location":"api/#overview","title":"Overview","text":"
"},{"location":"api/#apipy","title":"api.py","text":"api.py
- Public interfacecommands.py
- Low-level commandsinteractive.py
- User-facing commands
maya.cmds
, including camelCase
from maya import cmds\nfrom ragdoll import api as rd\n\ncube, _ = cmds.polyCube()\ncmds.move(0, 10, 0)\ncmds.rotate(35, 50, 30)\n\nsolver = rd.createSolver()\nmarker = rd.assignMarker(cube, solver)\n\nrd.record()\n\ncmds.evalDeferred(cmds.play)\n
"},{"location":"api/#commandspy","title":"commands.py","text":"api.py
module builds on commands.py
, but wraps it in a string-based interface so as to make it compatible with your everyday calls to maya.cmds
.api.py
is present in commands.py
, along with a few extras that may or may not change over time. It is best suited for tight integration and control but is primarily used internally for implementing interactive.py
and tools.py
.
api.py
for identical memberscmdx
typescommands.py
uses the highly performant cmdx
library to communicate with Maya and all return values are instances of cmdx
.
"},{"location":"api/#interactivepy","title":"interactive.py","text":"from maya import cmds\nfrom ragdoll import commands as rc\nfrom ragdoll.vendor import cmdx\n\ncmds.file(new=True, force=True)\n\ncube, _ = map(cmdx.encode, cmds.polyCube())\ncube[\"translateY\"] = 10\ncube[\"rotate\", cmdx.Degrees] = (35, 50, 30)\n\n# Every simulation needs a solver\nsolver = rc.create_solver(\"mySolver\")\nassert isinstance(solver, cmdx.DagNode)\nassert solver.isA(\"rdSolver\")\n\n# Every solver needs one or more marker bodies\nmarker = rc.assign_marker(cube, solver)\nassert isinstance(marker, cmdx.DagNode)\nassert marker.isA(\"rdMarker\")\n\n# Allow start frame to evaluate before progressing\ncmds.evalDeferred(cmds.play)\n
api
and commands
, instead each function return either True
for success or nothing for failure. Failures typically follow one or more warning messages.
from maya import cmds\nfrom ragdoll import interactive as ri\n\ncube, _ = cmds.polyCube()\ncmds.move(0, 10, 0)\ncmds.rotate(35, 50, 30)\n\ncmds.select(cube)\nri.assign_marker()\n\ncmds.evalDeferred(cmds.play)\n
ragdoll.api
.
help()
for usage instructions
"},{"location":"api/#environment-variables","title":"Environment Variables","text":"# Fundamentals\napi.createSolver(name=\"mySolver\")\napi.assignMarker(transform, solver)\napi.assignMarkers([transform1, transform2], solver)\n\n# Constraints\napi.createFixedConstraint(marker1, marker2)\napi.createDistanceConstraint(marker2, marker2)\napi.createPinConstraint(marker1)\n\n# Edit\napi.reconnect(child_marker, parent_marker)\napi.retarget(marker, new_transform)\napi.replaceMesh(marker, new_mesh)\n\n# IO\napi.recordPhysics()\napi.exportPhysics()\napi.reinterpretPhysics() # A.k.a. Import Physics\napi.extractPhysics()\n
RAGDOLL_NO_STARTUP_DIALOG=1
before loading the plug-in.MAYA_PLUG_IN_PATH
\"ragdoll\"
RAGDOLL_NO_STARTUP_DIALOG Do not display the startup-dialog on first launch. False
RAGDOLL_AUTO_SERIAL Automatically activate Ragdoll on install using this serial number. Unset RAGDOLL_TELEMETRY Help development by uploading usage data. Enabled for non-commercial licences, optional for commercial licences."},{"location":"api_reference/","title":"Api reference","text":""},{"location":"api_reference/#api-member-reference","title":"API Member Reference","text":"
Function Description createSolver Create a new rdSolver node createGroup Create a new group under from maya import cmds\nimport ragdoll.api as rd\n\nbox = cmds.polyCube()\n\nsolver = rd.createSolver()\nmarker = rd.assignMarker(box[0], solver)\n\nrd.recordPhysics()\n
solver
with name
and opts
assignMarkers Assign markers to transforms
belonging to solver
assignMarker Convenience function for passing and recieving a single transform
createDistanceConstraint Create a new distance constraint between parent
and child
createPinConstraint Create a new constraint for parent
and optionally parent
createFixedConstraint Create a new fixed constraint between parent
and child
linkSolver Link solver a
with b
unlinkSolver Unlink solver
retargetMarker Retarget marker
to transform
untargetMarker Remove parent from child
reparentMarker Make new_parent
the new parent of child
unparentMarker Remove parent from child
replaceMesh Replace the 'Mesh' shape type in marker
with mesh
. assignCollisionGroup Assign markers
to a new collision group
addToCollisionGroup Assign markers
to a new collision group
removeFromCollisionGroup Assign markers
to a new collision group
exportPhysics Export everything Ragdoll-related into fname
importPhysics Recreate Maya scene from exported Ragdoll file updatePhysics Update existing physics from an exported Ragdoll file recordPhysics Transfer simulation from solver
to animation land reinterpretPhysics Recreate Maya scene from exported Ragdoll file loadPhysics Create a Maya scene from an exported Ragdoll file extractPhysics Generate an animated joint hierarchy from solver
deletePhysics Delete Ragdoll from anything related to nodes
deleteAllPhysics Nuke it from orbit "},{"location":"api_reference/#argument-signatures","title":"Argument Signatures","text":"def createSolver(name, opts):\n \"\"\"Create a new rdSolver node\n ____\n / \\\n / | |\n ---/----\\____/\n / /\n ---/-------/---\n / /\n\n The solver is where the magic happens. Markers are connected to it\n and solved within; populating its .outputMatrix attribute with the\n final result.\n\n Arguments:\n name (str, optional): Override the default name of this solver\n opts (dict, optional): Configure the solver with these options\n\n Options:\n frameskipMethod (int): Method to use whenever a frame is skipped,\n can be either api.FrameskipPause or api.FrameskipIgnore\n\n \"\"\"\n
Create a new group under solver
with name
and opts
def createGroup(solver, opts):\n \"\"\"Create a new group under `solver` with `name` and `opts`\n\n Arguments:\n solver (rdSolver): Owning solver of this group\n name (str, optional): A custom name for this group\n opts (dict, optional): Default attributes of this group\n\n Options:\n selfCollide (bool): Whether or not members of this\n group should collide with each other.\n\n \"\"\"\n
"},{"location":"api_reference/#assignmarkers","title":"assignMarkers","text":"Assign markers to transforms
belonging to solver
def assignMarkers(transforms, solver, opts):\n \"\"\"Assign markers to `transforms` belonging to `solver`\n\n Each marker transfers the translation and rotation of each transform\n and generates its physical equivalent, ready for recording.\n\n Arguments:\n transforms (list): One or more transforms to assign markers onto\n solver (rdSolver or rdGroup): Add newly created markers to this solver\n opts (dict, optional): Options, see below\n\n Options:\n autoLimit (bool): Transfer locked channels into physics limits\n preventIdenticalMarker (bool): Skip transforms with identical position\n and orientation, typically sub-controls.\n defaults (dict): Key/value pairs of default attribute values\n\n \"\"\"\n
"},{"location":"api_reference/#assignmarker","title":"assignMarker","text":"Convenience function for passing and recieving a single transform
def assignMarker(transform, solver, opts):\n \"\"\"Convenience function for passing and recieving a single `transform`\n\n \"\"\"\n
"},{"location":"api_reference/#createdistanceconstraint","title":"createDistanceConstraint","text":"Create a new distance constraint between parent
and child
def createDistanceConstraint(parent, child, opts):\n \"\"\"Create a new distance constraint between `parent` and `child`\n\n \"\"\"\n
"},{"location":"api_reference/#createpinconstraint","title":"createPinConstraint","text":"Create a new constraint for parent
and optionally parent
def createPinConstraint(child, parent, opts):\n \"\"\"Create a new constraint for `parent` and optionally `parent`\n\n Arguments:\n child (rdMarker): Affected Marker\n parent (rdMarker, optional): Attach child to parent, otherwise to world\n transform (dagNode, optional): Parent the constraint shape node here\n opts (dict, optional): User options\n\n \"\"\"\n
"},{"location":"api_reference/#createfixedconstraint","title":"createFixedConstraint","text":"Create a new fixed constraint between parent
and child
def createFixedConstraint(parent, child, opts):\n \"\"\"Create a new fixed constraint between `parent` and `child`\n\n \"\"\"\n
"},{"location":"api_reference/#linksolver","title":"linkSolver","text":"Link solver a
with b
def linkSolver(a, b, opts):\n \"\"\"Link solver `a` with `b`\n\n This will make `a` part of `b`, allowing markers to interact.\n\n Arguments:\n a (rdSolver): The \"child\" solver\n b (rdSolver): The \"parent\" solver\n\n Returns:\n Nothing\n\n \"\"\"\n
"},{"location":"api_reference/#unlinksolver","title":"unlinkSolver","text":"Unlink solver
def unlinkSolver(solver, opts):\n \"\"\"Unlink `solver`\n\n From any other solver it may be connected to.\n\n Arguments:\n a (rdSolver): The solver to unlink from any other solver\n\n Returns:\n Nothing\n\n \"\"\"\n
"},{"location":"api_reference/#retargetmarker","title":"retargetMarker","text":"Retarget marker
to transform
def retargetMarker(marker, transform, opts):\n \"\"\"Retarget `marker` to `transform`\n\n When recording, write simulation from `marker` onto `transform`,\n regardless of where it is assigned.\n\n \"\"\"\n
"},{"location":"api_reference/#untargetmarker","title":"untargetMarker","text":"Remove parent from child
def untargetMarker(marker, opts):\n \"\"\"Remove parent from `child`\n\n Meaning `child` will be a free marker, without a parent.\n\n \"\"\"\n
"},{"location":"api_reference/#reparentmarker","title":"reparentMarker","text":"Make new_parent
the new parent of child
def reparentMarker(child, parent, opts):\n \"\"\"Make `new_parent` the new parent of `child`\n\n Arguments:\n child (rdMarker): The marker whose about to have its parent changed\n new_parent (rdMarker): The new parent of `child`\n\n \"\"\"\n
"},{"location":"api_reference/#unparentmarker","title":"unparentMarker","text":"Remove parent from child
def unparentMarker(child, opts):\n \"\"\"Remove parent from `child`\n\n Meaning `child` will be a free marker, without a parent.\n\n \"\"\"\n
"},{"location":"api_reference/#replacemesh","title":"replaceMesh","text":"Replace the 'Mesh' shape type in marker
with mesh
.
def replaceMesh(marker, mesh, opts):\n \"\"\"Replace the 'Mesh' shape type in `marker` with `mesh`.\n\n Arguments:\n marker (cmdx.Node): Rigid whose mesh to replace\n mesh (cmdx.Node): Mesh to replace with\n clean (bool, optional): Remove other inputs, such as curve\n or surface node. Multiple inputs are supported, so this\n is optional. Defaults to True.\n\n Returns:\n Nothing\n\n \"\"\"\n
"},{"location":"api_reference/#assigncollisiongroup","title":"assignCollisionGroup","text":"Assign markers
to a new collision group
def assignCollisionGroup(markers, group, delete_orphans):\n \"\"\"Assign `markers` to a new collision `group`\n\n Arguments:\n markers (list): Markers to assign\n group (rdCollisionGroup, optional): The group to add Markers to,\n if none is given a new one is created.\n delete_orphans (bool, optional): Delete any orphaned groups\n\n \"\"\"\n
"},{"location":"api_reference/#addtocollisiongroup","title":"addToCollisionGroup","text":"Assign markers
to a new collision group
def addToCollisionGroup(markers, group, delete_orphans):\n \"\"\"Assign `markers` to a new collision `group`\n\n Arguments:\n markers (list): Markers to assign\n group (rdCollisionGroup, optional): The group to add Markers to,\n if none is given a new one is created.\n delete_orphans (bool, optional): Delete any orphaned groups\n\n \"\"\"\n
"},{"location":"api_reference/#removefromcollisiongroup","title":"removeFromCollisionGroup","text":"Assign markers
to a new collision group
def removeFromCollisionGroup(markers, group, delete_orphans):\n \"\"\"Assign `markers` to a new collision `group`\n\n Arguments:\n markers (list): Markers to assign\n group (rdCollisionGroup, optional): The group to add Markers to,\n if none is given a new one is created.\n delete_orphans (bool, optional): Delete any orphaned groups\n\n \"\"\"\n
"},{"location":"api_reference/#exportphysics","title":"exportPhysics","text":"Export everything Ragdoll-related into fname
def exportPhysics(fname, opts):\n \"\"\"Export everything Ragdoll-related into `fname`\n\n Arguments:\n fname (str, optional): Write to this file,\n or console if no file is provided\n data (dict, optional): Export this dictionary instead\n\n Returns:\n data (dict): Exported data as a dictionary\n\n \"\"\"\n
"},{"location":"api_reference/#importphysics","title":"importPhysics","text":"Recreate Maya scene from exported Ragdoll file
def importPhysics(fname, opts):\n \"\"\"Recreate Maya scene from exported Ragdoll file\n\n User-interface attributes like `density` and display settings\n are restored from a file otherwise mostly contains the raw\n simulation data.\n\n \"\"\"\n
"},{"location":"api_reference/#updatephysics","title":"updatePhysics","text":"Update existing physics from an exported Ragdoll file
def updatePhysics(fname, opts):\n \"\"\"Update existing physics from an exported Ragdoll file\n\n \"\"\"\n
"},{"location":"api_reference/#recordphysics","title":"recordPhysics","text":"Transfer simulation from solver
to animation land
def recordPhysics(solver, opts):\n \"\"\"Transfer simulation from `solver` to animation land\n\n Options:\n start_time (int, optional): Record from this time\n end_time (int, optional): Record to this time\n include (list, optional): Record these transforms only\n exclude (list, optional): Do not record these transforms\n kinematic (bool, optional): Record kinematic frames too\n maintain_offset (bool, optional): Maintain whatever offset is\n between the source and destination transforms, default\n value is True\n\n \"\"\"\n
"},{"location":"api_reference/#reinterpretphysics","title":"reinterpretPhysics","text":"Recreate Maya scene from exported Ragdoll file
def reinterpretPhysics(fname, opts):\n \"\"\"Recreate Maya scene from exported Ragdoll file\n\n User-interface attributes like `density` and display settings\n are restored from a file otherwise mostly contains the raw\n simulation data.\n\n \"\"\"\n
"},{"location":"api_reference/#loadphysics","title":"loadPhysics","text":"Create a Maya scene from an exported Ragdoll file
def loadPhysics(fname, opts):\n \"\"\"Create a Maya scene from an exported Ragdoll file\n\n New transforms are generated and then assigned Markers.\n\n \"\"\"\n
"},{"location":"api_reference/#extractphysics","title":"extractPhysics","text":"Generate an animated joint hierarchy from solver
def extractPhysics(solver, opts):\n \"\"\"Generate an animated joint hierarchy from `solver`\n\n This will generate a new joint hierarchy and apply the full\n simulation as keyframes onto it, for a complete replica of\n the simulation in a Ragdoll-independent way.\n\n \"\"\"\n
"},{"location":"api_reference/#deletephysics","title":"deletePhysics","text":"Delete Ragdoll from anything related to nodes
def deletePhysics(nodes):\n \"\"\"Delete Ragdoll from anything related to `nodes`\n\n This will delete anything related to Ragdoll from your scenes, including\n any attributes added (polluted) onto your animation controls.\n\n Arguments:\n nodes (list): Delete physics from these nodes\n dry_run (bool, optional): Do not actually delete anything,\n but still run through the process and throw exceptions\n if any, and still return the results of what *would*\n have been deleted if it wasn't dry.\n\n \"\"\"\n
"},{"location":"api_reference/#deleteallphysics","title":"deleteAllPhysics","text":"Nuke it from orbit
def deleteAllPhysics():\n \"\"\"Nuke it from orbit\n\n Return to simpler days, days before physics, with this one command.\n\n \"\"\"\n
"},{"location":"api_reference/#constants","title":"Constants","text":"Some functions take constants for arguments.
from ragdoll import api\napi.assign_marker(a, b, opts={\"density\": api.DensityFlesh})\n
Constant Value FrameskipPause 0 FrameskipIgnore 1 DisplayDefault 0 DisplayWire 1 DisplayConstant 2 DisplayShaded 3 DisplayMass 4 DisplayFriction 5 DisplayRestitution 6 DisplayVelocity 7 DisplayContacts 8 InputInherit 0 InputKinematic 2 InputDynamic 3 PGSSolverType 0 TGSSolverType 1 BoxShape 0 SphereShape 1 CapsuleShape 2 MeshShape 4 ConvexHullShape 4 DensityOff 0 DensityCotton 1 DensityWood 2 DensityFlesh 3 DensityUranium 4 DensityBlackHole 5 DensityCustom 6 StartTimeRangeStart 0 StartTimeAnimationStart 1 StartTimeCustom 2 Lod0 0 Lod1 1 Lod2 2 LodCustom 3 MatchByName 0 MatchByHierarchy 1 RecordConstraintMethod 0 RecordMatchMethod 1 InputOff 3 InputGuide 3"},{"location":"blender-beta/","title":"Blender Beta","text":"Thanks to Blender Studio for the Dragonfly rig \u2764\ufe0f
"},{"location":"blender-beta/#beta-testing-ragdoll-in-blender","title":"Beta Testing Ragdoll in Blender \ud83e\udd73","text":""},{"location":"blender-beta/#welcome","title":"Welcome","text":"Ragdoll is a real-time physics solver for Maya, and now it's coming to Blender. At this moment, we are working hard to port features from the Maya version of Ragdoll into the Blender one. In the meantime, we invite you to join us in shaping its final form for Blender animators!
"},{"location":"blender-beta/#addon-status","title":"AddOn Status","text":"Blender Version Windows macOS (Intel) macOS (Apple Silicon) Linux 3.4 \u2705 \u2705 \u2705 \u274c 3.5 \u2705 \u274c \u274c \u274c"},{"location":"blender-beta/#a-quick-warm-up","title":"A Quick Warm Up","text":"From left to right:
And that's basically what Ragdoll is for \u2014 adding the fun of physics to your animation workflow!
To learn more about this Ragdoll Dragonfly, read below!
"},{"location":"blender-beta/#interface","title":"Interface","text":"Since we are playing with physics, you can find Ragdoll in the Physics Properties
tab, if the current active object is compatible with Ragdoll.
What types of things can work with Ragdoll (assign marker to)?
At this moment, only Mesh-type objects and Pose-Bones can. NURBS or Empty may be supported in the future.
Mesh
When the current active object is already in Ragdoll, the Physics Properties
tab will display associated properties.
Pose Bone
To work with Pose-Bones, enter Pose Mode
and select the bone you want to use with Ragdoll.
You can, and mostly would, select multiple bones and click on the Assign and Connect
button. It will give you a chain of markers.
Note that the Ragdoll solver (and all its friends) can be found in a collection called RagdollCol
. The solver node is responsible for simulating physical interactions between all its associated markers and more.
Currently, when clicking the Assign and Connect
button with multiple objects/pose-bones, a Group is created with them.
A group allows you to batch tweak some common properties like Stiffness
and Damping
for convenience.
Please visit the Learn Ragdoll website for more details about them. Especially this page which discusses the cornerstone of Ragdoll \u2014 Marker.
"},{"location":"blender-beta/#manipulator-tool","title":"Manipulator Tool","text":"The Ragdoll manipulator tool provides a direct way to tweak some common marker properties. It will become more feature-rich in the future, and you can expect to spend more time using it when working with Ragdoll.
The tool can be activated through here:
And the solver node needs to be selected to bring up the GUI.
"},{"location":"blender-beta/#tips-to-make-dragonfly-fly","title":"Tips to Make Dragonfly Fly","text":"Full walkthrough video: https://www.youtube.com/watch?v=vAAiqxYW9Us
Here's a short list of tips that could help:
"},{"location":"blender-beta/#connecting-marker","title":"Connecting Marker","text":"When assigning multiple markers, those markers will be chained together, and the first one will be set to Kinematic. And if a marker's behavior is set to Kinematic, it will 100% follow the input animation.
Since we will only apply an up-down movement to the rig base, just pick the torax (chest) of the Dragonfly for the first marker to follow that animation.
Then, when assigning the next chain of markers, remember to also start from that torax bone.
"},{"location":"blender-beta/#offset-solver","title":"Offset Solver","text":"Other than changing the Display Type
property to Wire
in the Solver for a cleaner view, sometimes you may want a side-by-side view when editing markers. If that's the case, simply move the Solver node and all the marker shapes will step aside.
You may want to uncheck Lock Object Modes
for faster object and bone selection.
Once done, move back and then activate the Manipulator tool for matching marker shapes to geometry.
"},{"location":"blender-beta/#ik-legs","title":"IK Legs","text":"You may also reference this page.
Simply put, we don't want to assign markers directly to IK controllers since physics is more like an FK thing. So instead, we would assign them to the bones that are driven by IK controls.
With this Dragonfly rig, although we can find them, they are basically locked. To work around that, the idea is to add an extra bone (the gray one in the middle) and make our own FK to drive IK.
"},{"location":"blender-beta/#scene-scale","title":"Scene Scale","text":"This Dragonfly is quite a big one. To get a much real-world result, we have to tune down the scene scale.
That's it!
We hope you have fun, and please don't hesitate to ask questions on the forum!
"},{"location":"crack-torrent/","title":"Ragdoll Crack Torrent","text":"Looking for a crack for Ragdoll, to use it for free without reprocussions? Look no further! Here's a torrent you can use to download it for free.
The Record Simulation
command consists of 4 steps.
Extract
Extract Simulation onto a new joint hierarchy 2 Attach
Constrain rig controls to joint hierarchy 3 Bake
Call cmds.bakeResults
4 Cleanup
Delete joint hierarchy and constraints The final result is keyframes on the rig controls, in a new Animation Layer.
Version 2.0 - Up to date
Written for Ragdoll 2022.05.04
and above.
Here's what it looks like to do manually, for 1 control.
Repeat the Attach
step for each control, and take locked channels into account, and you've entirely replicated what Record Simulation
does.
The Attach
step can be overridden to accommodate for custom constraints, for when your studio rigs cannot use the native cmds.parentConstraint
and cmds.orientConstraint
nodes that ship with Maya.
Here's how it works.
# 1 - Import the Record Simulation command\nfrom ragdoll import recording\n\n# 2 - Write your own command to attach\ndef custom_attach(...):\n ...\n\n# 3 - Replace the default attach\nrecording._Recorder._attach = custom_attach\n
Here's an example of the default implementation, pay special attention to the calls to cmds.parentConstraint
and cmds.orientConstraint
; these are the ones you want to replace with your own commands.
from ragdoll.vendor import cmdx\nfrom ragdoll import recording\n\n\ndef custom_attach(self, marker_to_dagnode):\n \"\"\"Constrain rig controls to simulation\n\n Arguments:\n marker_to_dagnode (dict): Dictionary with marker: dagnode, the dagnode\n is the animation control, e.g. L_hand_ctl\n\n Returns:\n new_constraints (list): Newly created constraints as cmdx.Node instances\n\n \"\"\"\n\n # Constraints created by this function\n # This list is used to delete the constraints after recording is complete\n new_constraints = []\n\n # Attach animation controls at the start time,\n # that's where the simulation and animation overlap\n initial_time = cmdx.current_time()\n cmdx.current_time(self._solver_start_frame)\n\n for dst, marker in self._dst_to_marker.items():\n src = marker_to_dagnode.get(marker, None)\n\n if not src:\n continue\n\n # dst == your rig control\n # src == the extracted transform\n\n skip_rotate = set()\n skip_translate = set()\n\n for chan, plug in zip(\"xyz\", dst[\"rotate\"]):\n if plug.locked:\n skip_rotate.add(chan)\n\n for chan, plug in zip(\"xyz\", dst[\"translate\"]):\n if plug.locked:\n skip_translate.add(chan)\n\n if skip_translate != {\"x\", \"y\", \"z\"}:\n\n #\n # REPLACE ME\n #\n pcon = cmds.parentConstraint(\n src.shortest_path(),\n dst.shortest_path(),\n maintainOffset=True,\n skipTranslate=list(skip_translate) or \"none\",\n skipRotate=list(\"xyz\"),\n )\n\n # Store reference to this node\n pcon = cmdx.encode(pcon[0])\n new_constraints.append(pcon)\n\n if skip_rotate != {\"x\", \"y\", \"z\"}:\n\n #\n # REPLACE ME\n #\n ocon = cmds.orientConstraint(\n src.shortest_path(),\n dst.shortest_path(),\n maintainOffset=True,\n skip=list(skip_rotate) or \"none\",\n )\n\n ocon = cmdx.encode(ocon[0])\n new_constraints.append(ocon)\n\n cmdx.current_time(initial_time)\n\n return new_constraints\n\n\n# Store original attach, just in case\ntry:\n old_attach\nexcept NameError:\n old_attach = recording._Recorder._attach\n\n# Replace with custom implementation\nrecording._Recorder._attach = custom_attach\n
"},{"location":"custom-attach/#usage","title":"Usage","text":"Copy/paste the above snippet into your Script Editor and call Record Simulation
. Nothing should have changed, because the above is a near-exact copy of the original.
From here, start editing the snippet. Keep executing the script in your Script Editor as you make changes, and call Record Simulation
from the Ragdoll
menu to try it out.
To restore the original implementation, either use old_attach
or reload the plug-in.
The src
variable is the extracted simulation, the joint. The dst
variable is your rig control, what you want to constrain to src
. The skip_translate
and skip_rotate
variables are two sets
containing the channels on your rig controls were locked (if any). Use these if your constraint commands needs them (like cmds.parentConstraint
does).
The default implementation uses cmds.parentConstraint
for the Translate
channels, and cmds.orientConstraint
for the Rotate
channels to accommodate for when one or more Rotate
channels are locked. As it happens, the cmds.parentConstraint
produces gimbal locks in situations like that.
You may use a single constraint command for all channels, if available, to try and see whether those also run into gimbal issues - such as randomly flipping 180 degrees. If they do, consider using a different constraint for the rotate channel.
"},{"location":"custom-attach/#return-value","title":"Return Value","text":"The command MUST return new_constraint
which MUST be of list
type and contain any and all nodes created by this function. In the default implementation, we call on maya.cmds
to create the constraint, but convert the resulting string
types to cmdx.Node
via cmdx.encode()
. You MUST do the same.
See the original command, along with available members of self
on GitHub.
mottosso/ragdoll/ragdoll/tools/markers_tool.py
Read all about each feature of Ragdoll in detail here.
Here I'll collect any third-party tutorials written or recorded for Ragdoll.
Resource Description Review by Amedeo Beretta General overview, covering the basics of the tool just as it's coming out of private early access"},{"location":"download/","title":"Download","text":"DownloadPick an integration
Autodesk Maya 2019-2024
DownloadBlender 3.4-4.0
DownloadRagdoll Core Installer
DownloadRagdoll Core Python SDK
Read MoreRagdoll Core C++ SDK
Coming SoonJoin the community of ragdollers on Discord and/or Discourse.
Chat Forums"},{"location":"examples/","title":"Examples","text":""},{"location":"examples/#examples","title":"Examples","text":"Download and have a go!
6.78 mb
Example 1 | Just a Girl An example of hair simulation with Ragdoll.
Download2.93 mb
Example 2 | mGirl An example of cloth simulation with Ragdoll.
Download2.77 mb
Example 3 | Muscle An example of muscle simulation with Ragdoll.
Download1.18 mb
Example 4 | Overview Some basic object types to fool around with.
Download0.16 mb
Example 5 | Parkour An animated Ragdoll \"parkour\" character.
Download4.15 mb
Example 6 | mHair Basic character setup with basic hair controls.
Download0.44 mb
Example 7 | Mechanical An accurate mechanical contraption.
Download0.40 mb
Example 8 | Driving A late night drive on a busy country road.
Download0.05 mb
Example 9 | Dynamic Control A regular animation control. With dynamics!
Download2.91 mb
Example 10 | Dance, Baby Fool around with guide strength to affect this dance performance!
Download0.24 mb
Example 11 | Slowmo Manipulate time with the timeMultiplier
attribute.
Congratulations on your purchase of a floating licence for Ragdoll Dynamics!
"},{"location":"floating-licence/#overview","title":"Overview","text":"This page will help you get set-up with a licence server, on-premise, and instruct Ragdoll to \"lease\" a licence from it. The server itself can run on any machine and any platform, including Windows, Linux and MacOS, so long as it is accessible from the machine running Ragdoll.
Windows, Linux and MacOS
The server can run on a different operating system than your workstations. For example, a common scenario is having the server running on Linux and workstations run on a combination of Windows, MacOS and Linux.
On each platform, the procedure is the same.
Product Key
The server will need to remain running in order for Ragdoll to lease licences.
"},{"location":"floating-licence/#linux","title":"Linux","text":"Here's a typical series of commands for an x64 system, look inside the .zip for alternative Linux-based platforms.
Requirements
Make sure you have unzip
and wget
at the ready, or use alternatives like curl
and tar
at your own leisure.
mkdir turbofloat\ncd turbofloat\nwget https://files.ragdolldynamics.com/api/public/dl/hAlavAOP/TurboFloat-Server-Linux.zip\nwget https://files.ragdolldynamics.com/api/public/dl/6lMDDMdn/TurboActivate.dat\nunzip TurboFloat-Server-Linux.zip\nmv bin-linux/x64/turbofloatserver ./\nchmod +x turbofloatserver\n./turbofloatserver -a=\"YOUR-SERIAL-NUMBER\"\n./turbofloatserver -x\n# Floating license server for Ragdoll Dynamics (TFS v4.4.4.0)\n
You can optionally pass -silent
after -x
for less verbosity.
The licence server can be activated offline.
From here, you'll likely want turbofloatserver -x
called automatically on reboot, such that Ragdoll and Maya can lease licences from it. The exact procedure varies between Linux distributions and company preferences, see the systemd section for tips on the most common approach.
More Details
Here's what you need to do in order to run the licence server on the Windows platform.
"},{"location":"floating-licence/#download","title":"Download","text":"TurboFloat-Server-Windows.zip
Inside of this file you will find this.
Edit the .xml
file with a port
you would like to use.
Port number
Make note of this port number as you will need it later when connecting to it from Maya.
64-bit Server
If you need a 32-bit version of the server, find the appropriate TurboFloat
binaries here.
Next we'll need to activate the server. Open a cmd.exe
or PowerShell prompt and type in the following.
TurboFloatServer.exe -a=\"YOUR-SERIAL-NUMBER\"\n
There should be no output from the command, unless there's a problem.
No internet?The licence server can be activated offline.
Now you're ready to launch the server!
"},{"location":"floating-licence/#start","title":"Start","text":"This next command will launch the server.
TurboFloatServer.exe -x\n# Floating license server for Ragdoll Dynamics (TFS v4.4.3.0)\n
Test
This is a good place to test Ragdoll from within Maya, so scroll to the Maya section, test it out and then come back here to finish things up.
All good? Great.
Optional
At this point, you can optionally have the server restart itself and run in the background by installing it as a \"service\".
TurboFloatServer.exe -i\n# 2021-05-12, 07:47:26 <error>: OpenSCManager failed (5)\n
To do that, you'll need to launch PowerShell/cmd as Administrator.
# As Administrator\nTurboFloatServer.exe -i\n# 2021-05-12, 07:48:40 <notification>: Service installed successfully.\n
From here you can try launching Ragdoll Dynamics in Maya to see whether it manages to successfully lease a licence.
More Details
With a licence server running, your next step is having Ragdoll connect to it.
On each platform, the procedure is the same.
RAGDOLL_FLOATING
Example
# From Python\nos.environ[\"RAGDOLL_FLOATING\"] = \"127.0.0.1:13\"\ncmds.loadPlugin(\"ragdoll\")\n
# From an environment like bash\nexport RAGDOLL_FLOATING=127.0.0.1:13\nmaya\n
The format of RAGDOLL_FLOATING
is <ip-address>:<port-number>
.
Everything ok?
Failed to initialise floating licenceIf this message appears in your Script Editor upon loading the plug-in, take a closer look at your Output Window on Windows or terminal on Unix.
# Error: ragdoll._install_floating() - Failed to initialise floating licence, error code '1' #\n
Could not load ragdollfloat.dll Windows users may experience this issue, which indicates a broken install. In your distribution, you should have seen both a ragdoll.mll
and ragdollfloat.dll
. Make sure this file exists, else contact us and we'll help you sort it.
Just like with a node-locked licence, you can control the leasing of licences via Python.
from ragdoll import licence\n\n# Activate this machine\nlicence.request_lease()\n\n# Deactivate this machine\nlicence.drop_lease()\n
"},{"location":"floating-licence/#troubleshooting","title":"Troubleshooting","text":"Let's have a look at a few common errors and how to solve them.
"},{"location":"floating-licence/#failed-to-save-activation-request","title":"Failed to Save Activation Request","text":"This can happen when attempting to generate an activation request for offline activation.
./turbofloatserver -a=\"KWVT-U5RS-...\" -areq=\"/bad/path/request.xml\"\n# <error>: Failed to save the activation request file.\n# <error>: Error code 0x1. Contact support or your system administrator.\n
The path given, in this case /bad/path/request.xml
might not be writable. Try a different path.
This can happen when attempting to activate a floating licence
./turbofloatserver -a=\"KWVT-U5RS-...\"\n# <error>: Failed to load the product details file.\n# <error>: Failed to load the settings.\n
The turbofloatserver
executable wasn't able to find the TurboActivate.dat
file. This file should reside in the same folder as turbofloatserver
and can be downloaded from here.
Let's cover some common scenarios.
"},{"location":"floating-licence/#how-can-i-test-connectivity-between-my-machines","title":"How can I test connectivity between my machines?","text":"To test whether machine A is accessible from machine B, try ping
.
ping 10.0.0.13\n# Reply from 10.0.0.13: bytes=32 time=1ms TTL=117\n
"},{"location":"floating-licence/#can-i-limit-the-internet-access-of-my-licence-server","title":"Can I limit the internet access of my licence server?","text":"If you're in a secure network, you may want to limit the licence server to the least amount of external access. You can do so by \"whitelisting\" it in your firewall, using this URL and port number.
https://wyday.com
443
More details here: https://wyday.com/limelm/help/turbofloat-server/
"},{"location":"floating-licence/#can-i-activate-my-server-offline","title":"Can I activate my server offline?","text":"Lifetime licences, yes. Monthly licences, no.
Like node-locked licences, the floating licence server can be activated without an internet connection to the machine running the server.
The procedure is the same on each platform.
Here's how to generate the request.
./turbofloatserver -areq=\"/path/to/ActivationRequest.xml\" -a=\"YOUR-SERIAL-NUMBER\"\n
And here's how to apply the response.
./turbofloatserver -aresp=\"/path/to/ActivationResponse.xml\" -a\n
Absolute Path
Take care to replace the path in the above commands, and use an absolute path rather than anything relative or special such as ~/
. The turbofloatserver
command can get a little cranky about those things.
If you are offline and changes has been made to your licence on our end, such as the number of seats changing or a new expiry date has been set, here is what you need to do.
1. Deactivate locally and remotely
Run the following command, replacing the path with one that can be written to.
./turbofloatserver -deact=\"/path/to/DeactivationRequest.xml\"\n
This should generate the file DeactivationRequest.xml
that should look something like this.
<DeactivationRequest>blablabla</DeactivationRequest>\n
Now paste the contents of this file into to https://ragdolldynamics.com/offline along with your serial and press Deactivate.
Your licence is now deactivated both on locally and remotely.
Warning
If you forget to pass the DeactivationRequest.xml
into the offline deactivation page, Ragdoll will not know about your deactivation. It will continue to believe that your licence remains activated, and may prevent you from activating it twice.
If this happens, contact us such that we can manually deactivate your licence on our end.
2. Activate
Next, follow the steps in Can I activate my server offline as usual.
"},{"location":"floating-licence/#how-do-i-reactivate-my-licence-online","title":"How do I reactivate my licence online?","text":"If your licence has been activated online and has been updated on our end, you may need to reactivate your licence.
./turbofloatserver -deact\n./turbofloatserver -a=\"KWVT-U5RS-...\"\n
This will refresh your local licence with whatever changes occured on our end.
"},{"location":"floating-licence/#failed-to-deactivate-old-product-key","title":"Failed to Deactivate Old Product Key","text":"Can happen during offline activation if your local machine is activated twice.
./turbofloatserver -areq=\"/path/to/ActivationRequest.xml\" -a=\"XXXX-XXXX-XXXX-XXXX-XXXX-XXXX-XXXX\"\n./turbofloatserver -areq=\"/path/to/ActivationRequest.xml\" -a=\"XXXX-XXXX-XXXX-XXXX-XXXX-XXXX-XXXX\"\n# Failed to deactivate old product key.\n
If this happens, locally deactivate your machine and try again.
./turbofloatserver -deact\n./turbofloatserver -areq=\"/path/to/ActivationRequest.xml\" -a=\"XXXX-XXXX-XXXX-XXXX-XXXX-XXXX-XXXX\"\n
"},{"location":"floating-licence/#failed-to-parse-the-configuration-xml-file","title":"Failed to Parse the Configuration XML File","text":"Can happen if the activation request is passed in as a response.
turbofloatserver
and is uploaded to https://ragdolldynamics.com/offlineturbofloatserver
./turbofloatserver -areq=\"/path/to/ActivationRequest.xml\" -a=\"XXXX-XXXX-XXXX-XXXX-XXXX-XXXX-XXXX\"\n
Should instead be:
./turbofloatserver -areq=\"/path/to/ActivationResponse.xml\" -a=\"XXXX-XXXX-XXXX-XXXX-XXXX-XXXX-XXXX\"\n
Note the \"Response\" and not \"Request\"
"},{"location":"floating-licence/#what-happens-when-my-server-is-offline","title":"What happens when my server is offline?","text":"Leasing will attempt to connect for about 2 seconds until giving up. During that time, Maya may appear frozen.
"},{"location":"floating-licence/#what-happens-when-my-server-goes-offline","title":"What happens when my server goes offline?","text":"Leasing is re-done once every 30 minutes.
30 minutes is the default value (see below), which means that if the server goes down whilst an artist is using it, the solver will be disabled within 30 minutes.
The duration can be adjusted, however it is a balance since the time is also how long it takes for the server to free a lease as a result of a Maya crash.
Yes.
The default port is 13
and can be edited via the TurboFloatServer-config.xml
file residing in the same directory as the server executable.
<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<config>\n ...\n <bind port=\"13\"/>\n ...\n</config>\n
Yes.
To move a licence, you can deactivate it and then activate it again someplace else.
TurboFloatServer -deact\n
This will deactivate the server. The same can be done if your licence server is offline, by passing a filename to the command.
TurboFloatServer -deact=\"deactivation_request.xml\"\n
Open this file and paste the contents of it into the offline deactivation wizard here.
Complete, Unlimited and Batch have their own serial numbers and each serial number needs its own server.
From there, provide each of your clients with the full server address to the pool it should lease licences from.
For example.
# Render farm\nRAGDOLL_FLOATING=10.0.0.4:601\n\n# Artist workstations\nRAGDOLL_FLOATING=10.0.0.5:601\n
"},{"location":"floating-licence/#can-i-disable-the-splash-screen","title":"Can I disable the splash screen?","text":"Yes.
Consumers of floating licences generally won't need to manage licenses themselves, and so the startup dialog can be avoided altogether for a smoother experience when inside of Maya.
export RAGDOLL_NO_STARTUP_DIALOG=1\nmaya\n
Yes.
Cloud workstations can pick up licences from your locally hosted licence server. It is not recommended nor supported to run your licence server on a virtual machine.
# Cloud workstation example\nexport RAGDOLL_FLOATING=local.server:8001\nmaya\n
In this example, the cloud workstation is referencing your locally hosted licence server via an IP on your VPN.
"},{"location":"floating-licence/#what-happens-to-a-lease-when-maya-crashes","title":"What happens to a lease when Maya crashes?","text":"A lease is automatically dropped upon unloading the plug-in or shutting down Maya. In the event of a Maya crash, a lease will automatically drop after 30 minutes per default.
The time can be edited via the configuration file; a lower time means more compute and file resources are consumed on the server, the lowest value is 30 seconds.
<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<config>\n ...\n <lease length=\"30\"/><!-- seconds -->\n ...\n</config>\n
"},{"location":"floating-licence/#can-i-fall-back-to-a-node-locked-licence","title":"Can I fall back to a node-locked licence?","text":"Yes.
Remove the RAGDOLL_FLOATING
environment variable and reload the plug-in or restart Maya to attempt activation of a node-locked licence.
No.
The server cannot distinguish between two virtual machines which would make it possible to activate an endless amount of them with their own duplicate pools of licences.
Although the server cannot run on a VM, clients can. E.g. running Docker for testing in a continous-integration environment or automation for simulation baking or rendering etc.
"},{"location":"floating-licence/#can-i-monitor-my-licence-server","title":"Can I monitor my licence server?","text":"Yes.
With a logging level set to \"notification\", you'll get real-time output from the server whenever a lease is requested and dropped, including..
The expiry is when the lease will be renewed. Normally not something you need to worry about, unless Maya crashes. This is then the time it'll take the server to realise the lease has been freed.
<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<config>\n ...\n <log file=\"tfs-log.txt\" level=\"notification\"/>\n ...\n</config>\n
2021-05-12, 11:58:47 <notification>: New connection from IP: ::ffff:127.0.0.1\n2021-05-12, 11:58:47 <notification>: New lease assigned (marcus, 1, IP=::ffff:127.0.0.1, PID=14328). Expires: 2021-05-12 11:28:47 (in UTC). Used / Total leases: 1 / 1\n2021-05-12, 11:58:51 <notification>: New connection from IP: ::ffff:127.0.0.1\n2021-05-12, 11:58:51 <notification>: Lease was released by client (marcus, 1, IP=::ffff:127.0.0.1, PID=14328). Used / Total leases: 0 / 1\n
The tfs-log.txt
file is dynamically updated as users lease and drop licences, and includes mention of how many licences are in use and remaining. You can monitor the tail of this file for real-time updates, and use any tooling to parse these notifications into your own infrastructure.
See Also
With level=\"notification\"
it'll say this.
2021-05-16, 14:52:50 <notification>: License lease request rejected because no more free slots, numTotalLics=9, pkey=YOUR-SERIAL-NUMBER\n
"},{"location":"floating-licence/#how-do-i-run-my-server-in-the-background-using-systemd","title":"How do I run my server in the background using systemd?","text":"systemd is a common option for running background processes on Linux. Here's a quick run-down how to get turbofloatserver
running with it.
Prerequisities
turbofloatserver -x
alreadyturbofloatserver
, here we will assume /turbofloat
Ok, with that out of the way, create a new file called /etc/systemd/system/turbofloat.service
with the content below.
turbofloat.service
[Unit]\nDescription=TurboFloat server for CI\nAfter=network.target\n\n[Service]\nType=simple\nUser=root\nWorkingDirectory=/root\nExecStart=/turbofloat/turbofloatserver -x -s\nRestart=on-failure\n\n[Install]\nWantedBy=multi-user.target\n
Replace with your Path
Here we use /turbofloat/turbofloatserver -x -s
but your path will likely be different!
Now let's start it.
systemctl start turbofloat\n
You may need sudo
Unless you are logged in as a root/administrator user, you may need to use sudo
with this command. E.g. sudo systemctl
If there are no complaints, we're set to have this automatically run in the background whenever the computer restarts.
systemctl enable turbofloat\n
And that's it. You should now have access to this server in the exact same way as you did when calling turbofloatserver -x
manually.
To check the status of your server, try this.
~/turbofloat$ systemctl status turbofloat\n\u25cf turbofloat.service - TurboFloat server for CI\n Loaded: loaded (/etc/systemd/system/turbofloat.service; enabled; vendor preset: enabled)\n Active: active (running) since Wed 2023-10-18 13:31:21 BST; 37s ago\n Main PID: 81594 (turbofloatserve)\n Tasks: 17 (limit: 35692)\n Memory: 1.1M\n CPU: 18ms\n CGroup: /system.slice/turbofloat.service\n \u2514\u250081594 /home/marcus/turbofloat/turbofloatserver -x -s\n\nOct 18 13:31:21 minilinux systemd[1]: Started TurboFloat server for CI.\nOct 18 13:31:21 minilinux turbofloatserver[81594]: 2023-10-18, 13:31:21 <notification>: Auto-detected 16 CPU cores; creating a thread pool that large.\nOct 18 13:31:21 minilinux turbofloatserver[81594]: Floating license server for Ragdoll Dynamics (TFS v4.4.4.0)\n
You can also use journalctl
to follow the log interactively, as though it was running in the local terminal.
~/turbofloat$ journalctl --follow --unit turbofloat\nOct 18 13:31:21 minilinux systemd[1]: Started TurboFloat server for CI.\nOct 18 13:31:21 minilinux turbofloatserver[81594]: 2023-10-18, 13:31:21 <notification>: Auto-detected 16 CPU cores; creating a thread pool that large.\nOct 18 13:31:21 minilinux turbofloatserver[81594]: Floating license server for Ragdoll Dynamics (TFS v4.4.4.0)\n
"},{"location":"licencing/","title":"Licencing","text":""},{"location":"licencing/#overview","title":"Overview","text":"Let's cover the basics..
About activation..
Product Key
Product Key
by purchasing a licenceSee also
Once activated without a Product Key
, Ragdoll enters \"Apprentice Mode\", and is limited to the following.
See the Ragdoll EULA for details.
"},{"location":"licencing/#faq","title":"FAQ","text":"Let's dive into specifics.
"},{"location":"licencing/#how-does-it-work","title":"How does it work?","text":"On first launch, Ragdoll will try and connect to the Ragdoll Licence Server and register your trial version. This version is node-locked to the particular machine you are on.
Once you've acquired a product key, you can either:
Ragdoll
menu item (bottom)Activate
Or if you prefer:
from ragdoll import licence\nlicence.activate(key)\n
"},{"location":"licencing/#what-happens-when-my-trial-expires","title":"What happens when my trial expires?","text":"Any rdScene.enabled
attribute will be set to False
.
Scenes will still load just fine and nothing else in your scene is affected. Once activated, the .enabled
attribute will return to normal.
Possibly. Reach out to us if this is relevant to you.
"},{"location":"licencing/#can-i-open-scenes-made-with-the-trial-version-in-the-commercial-version","title":"Can I open scenes made with the trial version in the commercial version?","text":"No.
Files made with Ragdoll Apprentice will appear scrambled with a commercial version. Ragdoll Apprentice is however able to read files saved with a commercial version.
"},{"location":"licencing/#can-i-use-my-licence-on-more-than-one-machine","title":"Can I use my licence on more than one machine?","text":"One licence, one machine.
Ragdoll is licenced per simultaneous use, so for use on two or more machines in parallel you will need 2 licences - a.k.a. \"seats\".
When purchasing multiple seats, you may receive a single serial number containing all seats. For floating licences, you'd host a single licence server using this serial to accommodate each machine. For node-locked licences, you'd activate each individual machine using the same serial.
"},{"location":"licencing/#can-i-move-a-licence-between-two-machines","title":"Can I move a licence between two machines?","text":"Yes.
For node-locked licences, you can hit the Deactivate
button (which is same as the Activate
button once you've activated) and the serial may be used to activate another machine.
Floating licences are dynamically activated on any machine requesting a licence from your centralised licence server.
"},{"location":"licencing/#do-i-need-an-internet-connection-to-use-ragdoll","title":"Do I need an internet connection to use Ragdoll?","text":"No.
Activation can happen either offline or online, online happening from within Maya at the click of a button and offline being a 4-step process, see below.
"},{"location":"licencing/#how-do-i-use-my-floating-licence","title":"How do I use my floating licence?","text":"Floating licences have two parts.
Whenever Ragdoll is loaded from Maya, it connects to your licence server in order to \"lease\" a licence. If you own 10 licences, then one of them will remain leased until the plug-in is unloaded from Maya.
See also
Yes.
See Offline Activation below.
"},{"location":"licencing/#when-exactly-is-internet-required","title":"When exactly is internet required?","text":"A connection is made in one of two separate occasions.
ragdoll.licence.install()
from Pythoninstall()
is typically called when the plug-in is loaded and menu is installed.
That is, Maya can open a scene with Ragdoll in it without making a connection to the internet if neither of these things happen. This means you can simulate on one machine, bake or otherwise disable the solver and send it off to a farm (e.g. local or cloud) without worrying about licences.
The alternative would be having to erase any trace of Ragdoll from a scene which would be such a pain.
"},{"location":"licencing/#disabled-network-devices","title":"\"Disabled Network Devices\"","text":"The licence software used by Ragdoll (WyDay TurboActivate) uses your network devices to associate your serial number with a unique fingerprint of your machine. In order for it to do that, it needs access to each of them.
Try running your DCC as admin while activating Ragdoll, and then run Maya as normal.
Alternatively, have a look at your network connections and make sure they are all enabled while activating Ragdoll, then they can be disabled again.
"},{"location":"licencing/#can-i-manage-my-licence-via-python","title":"Can I manage my licence via Python?","text":"Sure can, see below.
"},{"location":"licencing/#licence-api","title":"Licence API","text":"As a user, you'll generally use the UI. But the UI is ultimately making calls to Python (which is making calls to C++) and you can bypass the UI using these same calls.
from ragdoll import licence\n\n# Called once before calling any other licencing function\n# This is automatically called on Ragdoll Python initialisation\n# and simulation start, but needs calling manually if simulation\n# hasn't yet started.\nlicence.install()\n\n# Retrieve the currently activated product key\nlicence.current_key()\n\n# Activate using your product ket\nlicence.activate(key)\n\n# Activation for those without access to Internet\nlicence.activation_request_to_file(key, fname)\nlicence.activate_from_file(fname)\n\n# Deactivate whatever key is currently activated\nlicence.deactivate()\n\n# Deactivate offline, to e.g. move a licence from one machine to another\nlicence.deactivation_request_to_file(fname)\n\n# Dictionary of useful information\ndata = licence.data()\n\n{\n # Same as current_key\n \"key\": \"Your-Key\",\n\n # Is the current licence activated?\n \"isActivated\": True,\n\n # Is the current licence a trial licence?\n \"isTrial\": False,\n\n # Has the licence not been tampered with?\n \"isGenuine\": True,\n\n # Has the licence been verified with the server\n # (requires a connection to the internet)?\n \"isVerified\": True,\n\n # How many days until this trial expires?\n \"trialDays\": 23\n}\n
"},{"location":"licencing/#offline-activation","title":"Offline Activation","text":"Lifetime licences may be activated offline.
What about monthly licences?These require an internet connection. Floating licences require internet only for the licence server itself, meaning your workstations can remain disconnected and protected. Node-locked licences require internet on the machine being activated.
Similar to Activation, Deactivation happens via the Offline Deactivation Wizard.
Caution
Once you press Deactivate
, then from Maya's perspective your licence will be deactivated. However, the licence server will not know of your deactivation until you paste the request into online deactivation page.
This means that it is possible to deactivate a licence but forget to tell the licence server about it, which means you will not be able to reactivate it elsewhere.
If this happens, reach out to support@ragdolldynamics.com and we may manually deactivate it for you.
"},{"location":"menu/","title":"Menu Reference","text":"All items found in the Ragdoll
menu at the top of Maya's main window.
Add menu items to your shelf with Ctrl + Shift + Click
Stay up to date with the latest improvements and fixes to Ragdoll.
You've just been redirected from a JavaScript-heavy landing page because your browser won't permit JavaScript.
Continue Try again"},{"location":"nodes/","title":"Nodes","text":"
Detailed information about all of Ragdoll's custom nodes along with the most commonly used attributes. For full attribute reference, see the link at the bottom of each node type, such as rdRigid.
Each Ragdoll node starts with rd
, e.g. rdRigid
Container of all rigids, constraints and forces that interact.
The scene represents the knowledge each simulation has, including rigids and their properties, constraints, forces. The works. There can be more than one Ragdoll scene in your Maya scene, but much like Maya scenes they cannot interact. The order in which scenes are simulated is also undefined, so you cannot expect e.g. fingers in one solver to run after the body in another solver.
Parallelism
Ragdoll scenes support both scene-level parallelism and node-level parallelism.
Scene-level parallelism happens when there are more than one Ragdoll scene present, each scene is then run in parallel for improved performance. For that reason, prefer using as many scenes as possible, especially if they are unlikely to interact.
Node-level Parallelism happens internally, whereby a single simulation is distributed over multiple threads. The behavior can be tuned via the rdScene.threadCount
attribute. Keep this at 0 when your scenes are small, i.e. < 100 rigids. The overhead of splitting up a simulation outweighs the benefit unless there is a lot to split. You should notice a performance difference in either direction as you manipulate this attribute.
.airDensity
Global multiplier to the linearDamping
and angularDamping
of every rigid part of this scene. This is a convenience attribute to the same attribute found in the rdRigid
node for global effects, like the whole scene turning into honey. float
.currentTime
Ragdoll's knowledge of time. This is typically connected automatically and needn't be touched, but it is technically possible to animate this and achieve complex slow-motion or time-related effects. time
.enabled
State of the solver. An enabled solver will update whenever time changes. bool
.gravity
Default gravity, in Maya's current distance unit (typically centimeters). Because native Maya shapes are generally quite small - e.g. 1 centimeter for a polyCube - the default gravity is less than the realistic 986.0 cm/s2. If your characters are real-world scaled - e.g. 2 meters tall - then gravity should be closer to 986.0 instead. distance3
.groundFriction
Friction of the ground. float
.groundRestitution
Bounciness of the ground plane. float
.substeps
Divide changes in time by this many. Ragdoll simulates once per frame (or generally once per change in time, including sub-frame changes), but multiples the number of steps taken by this amount for greater accuracy at a (possible) cost to performance. int
.useGround
Automatically add a static ground shape to this scene. This has a very similar effect to making your own plane and turning that into a Passive Rigid. The ground responds to changes in translation of the scene, but cannot be animated. bool
Full Reference "},{"location":"nodes/#rigid","title":"Rigid","text":"A single transform in or out of Ragdoll.
The rigid is the physical equivalent of native Maya geometry. It can either feed into the simulation (passive) or come out of the simulation (active).
Active Rigid
pass data from Ragdoll to MayaPassive Rigid
pass data from Maya to Ragdoll.airDensity
Multiplier of both linearDamping
and angularDamping
. The two damping attributes are typically used together, but can also be used separately in which case this attribute could be left at 1.0 and forgotten. float
.angularDamping
Resistance along the opposite direction of rotation for a rigid. Like linearDamping
but along the rotation axes. float
.collide
Whether this rigid should collide with other rigids. This can be useful in areas of many overlapping rigids that aren't necessarily constrained, such as a shoulder or hip. bool
.friction
The resistance at which two rigids rub against each other. A value of 0 creates an appearance of ice, whereas a value of 1.0 represents 100% friction, no sliding allowed. The value may exceed 1.0, but it is unclear what happens. Use at your own risk. float
.inputMatrix
Passive position and orientation, this may be animated. matrix
.inputParentInverseMatrix
Used to cancel out any Maya parent prior to outputting the outputMatrix. matrix
.kinematic
Whether this rigid should be affected by contacts, constraints and forces. bool
.linearDamping
Resistance in the opposite direction of travel for a rigid. This creates an underwater look, or at high-enough values resembles honey or eventually cement. float
.mass
The 'weight' of a rigid. Except 'weight' is technically the result of mass and gravity, and a rigid still has mass even when there isn't any gravity. This attribute is mostly relevant when two active rigids interact, think of a pool table where one of the balls is heavier than another. On the other hand, dropping a feather from high on up onto a static ground yields an identical result to dropping much heavier bowling ball. The ground being static will not move regardless and the speed at which your rigid falls to the ground is independent of its mass given there is no actual air in the simulation to apply counterforce like in the real world. float
.restitution
The 'bounciness' of a rigid body. Bounce is an opposite force applied whenever two rigids come into contact. The bounce is however also dependent on the rdScene.bounceThresholdVelocity
which determines how strong a contact must be in order for an opposing force to be added. Without a threshold, a rigid would bounce at increasingly small intervals into infinity. However, for high-frequency bounces, like a billiard ball bouncing on a marble floor, don't forget to increase your substeps so as to capture the very small and fast motion happening towards the end of its bounce lifetime. float
.shapeExtents
The dimensions of the 'Box' shapeType
. float3
.shapeLength
Length of the 'Capsule' and 'Cylinder' shapeType
. float
.shapeOffset
Position of a shape relative the rigid. Think of the shape as being a child of the rigid, and this is its child position. It'll be in the orientation of the parent, as you would expect. double3
.shapeRadius
Radius of the 'Sphere', 'Capsule' and 'Cylinder' shapeType
. float
.shapeType
Shape used for collision detection and automatic computation of centerOfMass
and angularMass
. The 'Mesh' option converts any input to inputMesh
or inputCurve
to a suitable physical representation called 'Convex Hull'. As the name implies, the hull cannot be concave. To model concave shapes, like a torus, use multiple rigids and parent them together to form a compound shape. enum
.thickness
Additional offset from the surface of a shape. Think of this as the shape being extruded by this amount along the surface normals. It's meant to create some padding between two rigids that collide and can help stabilise complex or strong contacts. float
Full Reference "},{"location":"nodes/#constraint","title":"Constraint","text":"A relationship between two rigids.
Typically this relationship is something to limit one or more axes - e.g. translateXYZ
and rotateZ
- of one rigid relative another rigid, like a door \"constrained\" to a wall. In that case, the wall would be considered a \"parent\" and the door a \"child\".
However it is important to keep in mind that in the real world, there is no such thing. The door is as constrained to the wall as the wall is constrained to the door. This is especially apparent when the two constrained rigids are both active and have a similar mass, such as your upper and lower leg. As you bend your knee, both the thigh and lower leg are affected equally.
Attribute Description Type.angularDriveDamping
Angular damping of the drive. float
.angularDriveStiffness
Angular stiffness of the drive. float
.angularLimitDamping
Damping of contacts with the limit. It is an opposing force to whatever direction a contact is applied. A low value produces a springy appearance, whereas a high value resists any and all motion. float
.angularLimitStiffness
Stiffness of contacts with the angular limit. A low value makes limits appear soft. Values are relative the mass of your rigid and the amount of force being applied by contacts and other constraints. But with a mass of 1.0 and under normal gravity, the default value should produce a somewhat hard response. float
.driveEnabled
Whether or not to try and follow the driveMatrix
attribute. Drives (a.k.a. Guides) are used to follow an input animation by applying forces relative the delta between your animation and the simulation. The further your animation is from the current state of the simulation, the stronger the force. It's a spring-like force. bool
.driveMatrix
A target position and orientation for the childRigid
, relative the parentFrame
. The constraint can apply a spring-like force to both parent and child to try and match this matrix as though the childRigid
was an actual child of the parentRigid
. matrix
.driveStrength
Multipler to linearDriveStiffness
, linearDriveDamping
, angularDriveStiffness
and angularDriveDamping
. This is a convenience attribute to simplify manipulation (and animation) of the overall drive behaviour. The same result can be achieved by manually multiplying these values. The equation is strength * strength * stiffness
and the same for damping. float
.limitEnabled
Whether any of the specified limits are enabled or not. Think of this as a convenience override for linear (position) and angular (rotation) limits. You can achieve the same effect by setting each limit to a value of 0. bool
.limitStrength
Multiplier for the linearLimitStiffness
, linearLimitDamping
, angularLimitStiffness
and angularLimitDamping
attributes. float
.linearDriveDamping
Linear damping of the drive. A high value produces a slimy, slow-moving motion. float
.linearDriveStiffness
Linear stiffness of the drive. If you think of the drive as a spring, then the stiffness determines the thickness of the coil of that spring. A thick coil yields a fast, springy motion. float
.linearLimitDamping
Damping factor for contacts with the limit. float
.linearLimitStiffness
Stiffness of contacts with linear limit. Whenever the linear limit is hit, this attribute determines how soft/hard to response should be. A low value (e.g. 10) yields a soft appearance, whereas a high (e.g. 1'000'000) yields a metal-versus-marble contact. float
Full Reference "},{"location":"nodes/#control","title":"Control","text":"A placeholder for drawing a rigid under a different transform.
This node is cosmetic only. It helps you spot the rigid and rigid orientation in the viewport for a standalone controller, like a Guide
. It also draws the node with a special icon in the outliner. But that's about it!
Multiply one or more attributes of one or more constraints.
This node enables you to animate one attribute that affect many attributes, like Translate Guide Stiffness
across an entire character or limb.
.angularDriveDamping
Multiplier for rdConstraint.angularDriveDamping
float
.angularDriveStiffness
Multiplier for rdConstraint.angularDriveStiffness
float
.angularLimitDamping
Multiplier for rdConstraint.angularLimitDamping
float
.angularLimitStiffness
Multiplier for rdConstraint.angularLimitStiffness
float
.driveStrength
Multiplier for rdConstraint.driveStrength
float
.limitStrength
Multiplier for rdConstraint.limitStrength
float
.linearDriveDamping
Multiplier for rdConstraint.linearDriveDamping
float
.linearDriveStiffness
Multiplier for rdConstraint.linearDriveStiffness
float
.linearLimitDamping
Multiplier for rdConstraint.linearLimitDamping
float
.linearLimitStiffness
Multiplier for rdConstraint.linearLimitStiffness
float
Full Reference "},{"location":"nodes/#rigid-multiplier","title":"Rigid Multiplier","text":"Multiply one or more attributes of one or more rigids.
This node enables you to animate one attribute that affect many attributes, like Air Density
across an entire character or limb.
.airDensity
Multiplier for rdRigid.airDensity
float
.angularDamping
Multiplier for rdRigid.angularDamping
float
.linearDamping
Multiplier for rdRigid.linearDamping
float
Full Reference "},{"location":"nodes/#other","title":"Other","text":"Notes on general concepts used in Ragdoll.
"},{"location":"nodes/#backwards-compatibility","title":"Backwards Compatibility","text":"This means previously authored scenes will always behave the same, whilst still enabling new default values for future versions and future authored physics.
"},{"location":"nodes/#exclusive-nodes","title":"Exclusive Nodes","text":"Ragdoll consists of a few new native types, like rdRigid
and rdConstraint
. During creation, Ragdoll may generate Maya-native types too, like multMatrix
and composeMatrix
. Those nodes are exclusive to Ragdoll and should be removed alongside them. This is managed via the so-called .exclusiveNodes
attribute on each Ragdoll node type.
Whenever Ragdoll attributes appear on your original animation controls, they are referred to as \"user attributes\" by Ragdoll and tracked via the .userAttributes
attribute on each Ragdoll node. These attributes are exclusive to Ragdoll and are removed alongside the Ragdoll node types they interact with.
MIT License
Copyright \u00a9 2013-2020 Ryo Suzuki reputeless@gmail.com
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
https://github.com/skypjack/entt The MIT License (MIT)
Copyright \u00a9 2017-2020 Michele Caini
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copy of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copy or substantial portions of the Software.
THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
https://github.com/bulletphysics/bullet3 The files in this repository are licensed under the zlib license, except for the files under 'Extras' and examples/ThirdPartyLibs.
Bullet Continuous Collision Detection and Physics Library http://bulletphysics.org
This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
NVIDIA PhysX SDK Copyright \u00a9 2019 NVIDIA Corporation. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of NVIDIA CORPORATION nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Open Dynamics Engine Copyright \u00a9 2001-2004, Russell L. Smith. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
Neither the names of ODE's copyright owner nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
https://github.com/stack-of-tasks/pinocchio BSD 2-Clause License
Copyright \u00a9 2014-2020, CNRS Copyright \u00a9 2018-2020, INRIA All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of the Pinocchio project.
https://github.com/mosra/magnum Copyright \u00a9 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Vladim\u00edr Vondru\u0161 mosra@centrum.cz
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"},{"location":"overview/","title":"Overview","text":"Ragdoll is a real-time physics solver for Maya and Blender, similar the native nCloth and nHair solvers except it works on transforms rather than points. That makes it better equipt to integrate with your existing animation controls and doesn't require translating from points like people did in the 90's.
This domain contains Ragdoll learning resources, for a more general overview see the Product Page.
"},{"location":"overview/#where-to-find-help","title":"Where to Find Help?","text":"Depending on where you are and what you are looking for, one of these should fit the bill.
# Source Description Chat Come join the party on Discord! Release Notes Every new release has examples of every new feature and squashed bug. Search Top of every page, you know what to do \u261d\ufe0f YouTube Videos Long-form walkthroughs and examples. Community Inspire and be inspired via the Ragdoll forums Support Get us involved and let's make some waves "},{"location":"overview/#whats-next","title":"What's Next?","text":"Here are some options for getting into Ragdoll.
Route Description Install & Explore Tried and true, who reads documentation anyway? Watch & Learn We've made a number of videos demonstrating how to use Ragdoll. Read All About It Keep clicking that next button at the bottom of every page. "},{"location":"overview/#press","title":"Press","text":"Mentions of Ragdoll in the press.
Date Source Title 2022-11-29 gfxspeak Manipulate Maya character rigs with real-time physics in seconds 2022-11-29 digitalmediaworld Ragdoll Dynamics 3.0 Develops Real-Time Character Physics for Animators 2022-11-29 cgsociety.org Ragdoll Dynamics 3.0 Adds Real-Time Character Physics Animators Can Steer Like a Puppeteer 2022-11-29 80.lv Ragdoll Dynamics 3.0 for Maya Released 2022-11-29 redsharknews Ragdoll Dynamics 3.0: steer like a puppeteer 2022-11-29 postperspective Ragdoll 3.0: Fast Automation of Character Physics in Maya 2022-11-29 postperspective Ragdoll Dynamics 3.0 \u0434\u043b\u044f Maya 2022-11-29 blog.superrendersfarm Ragdoll Dynamics 3.0 released 2022-11-29 render.ru Ragdoll Dynamics sort en version 3.0! 2022-11-29 swiss.dayfr Ragdoll Dynamics is released in version 3.0! 2022-11-29 germany.detailzero From 'Gravity' tethers to, literally, Ragdoll Dynamics 2022-11-29 beforesandafters Ragdoll Dynamics 3.0 released 2022-11-29 cgchannel Imbalance releases Ragdoll Dynamics 3.0 for Maya 2022-11-29 cgbucket Ragdoll Dynamics 3.0 released 2022-11-29 cgpress.org Ragdoll Dynamics erscheint in der Version 3.0! 2022-11-29 digitalproduction Imbalance Releases Ragdoll Dynamics 3.0 2022-11-29 boxreview Imbalance Releases Ragdoll Dynamics 3.0 2022-11-29 afnews Imbalance Releases Ragdoll Dynamics 3.0 2022-11-29 animationmagazine Ragdoll Dynamics 3.0 Adds Real-Time Character Physics Animators Can Steer Like a Puppeteer 2022-11-29 awn Imbalance Releases Ragdoll Dynamics 3.0 2022-11-29 facebook 80 Level - Imbalance has released Ragdoll Dynamics 3.0 2022-11-29 facebook Imbalance Releases Ragdoll... - Animation World Network 2022-11-29 facebook Are you a Befores & Afters PLUS Patron 2022-11-29 facebook Check out Ragdoll Dynamics 3.0 for Maya. The ace real-time physics tool now lets you pose charact... 2022-11-29 facebook CGPress - Imbalance has announced the release of Ragdoll... 2022-11-29 facebook Ragdoll Dynamics 3.0 Develops Real-Time Character Physics for Animators 2022-11-29 facebook Ragdoll Dynamics erscheint in der... - Digital Production 2022-11-29 80level Tweet by @80Level 2022-11-29 afnewsinfo Tweet by @afnewsinfo 2022-11-29 afnewsinfo Tweet by @animag 2022-11-29 animag Tweet by @ANIMATIONWorld 2022-11-29 animationworld Tweet by @beforesmag 2022-11-29 beforesmag Tweet by @BoxReview_ 2022-11-29 boxreview_ Tweet by @theCGchannel 2022-11-29 dig_prod Tweet by @dig_prod 2022-11-29 thecgchannel Tweet by @RedSharkNews 2022-11-29 redsharknews 2022-11-29 linkedin 80.lv on LinkedIn 2022-11-29 youtube From 'Gravity' tethers to Ragdoll Dynamics 2022-11-29 postperspective 2022-12-18 Escape Studios Ragdoll Dynamics for Maya 2022-09-21 80lv Development and Capabilities of Ragdoll Dynamics 2021-08-03 CGChannel Ragdoll Dynamics adds real-time physics to your Maya rigs 2021-07-30 CGPress Ragdoll Dynamics plugin for Maya 2021-07-28 80lv New Tool Lets You Animate With Physics in Real-TimeShare your sources
Know of anywhere else Ragdoll got mentioned? Let us know and we'll add it to the list!
Contact Us
"},{"location":"parallel/","title":"Parallel","text":""},{"location":"parallel/#overview","title":"Overview","text":"This guide describes the Maya features for accelerating playback and manipulation of animated scenes. It covers key concepts, shares best practices/usage tips, and lists known limitations that we aim to address in subsequent versions of Maya.
This guide will be of interest to riggers, TDs, and plug-in authors wishing to take advantage of speed enhancements in Maya.
If you would like an overview of related topics prior to reading this document, check out Supercharged Animation Performance in Maya 2016.
"},{"location":"parallel/#key-concepts","title":"Key Concepts","text":"Starting from Maya 2016, Maya accelerates existing scenes by taking better advantage of your hardware. Unlike previous versions of Maya, which were limited to node-level parallelism, Maya now includes a mechanism for scene-level analysis and parallelization. For example, if your scene contains different characters that are unconstrained to one another, Maya can evaluate each character at the same time.
Similarly, if your scene has a single complex character, it may be possible to evaluate rig sub-sections simultaneously. As you can imagine, the amount of parallelism depends on how your scene has been constructed. We will get back to this later. For now, let\u2019s focus on understanding key Maya evaluation concepts.
At the heart of Maya\u2019s new evaluation architecture is an Evaluation Manager (EM), responsible for handling the parallel-friendly representation of your scene. It maintains (and updates while the scene is edited) a few data structures (described below) used for efficient evaluation.
The basic description of the scene is the Dependency Graph (DG), consisting of DG nodes and connections. Nodes can have multiple attributes, and instances of these attributes on a specific node are called plugs. The DG connections are at the plug level, that is, two nodes can be connected to one another multiple ways through different plugs. Generally speaking, these connections represent data flow through the nodes as they evaluate. The following image shows an example DG:
The dotted arrows inside the nodes represent an implicit computation dependency between an output attribute (on the right of the node) and the input attributes (on the left) being read to compute the result stored in the output.
Before Parallel Maya, the DG was used to evaluate the scene using a Pull Model or Pull Evaluation. In this model, the data consumer (for instance the renderer) queries data from a given node. If the data is already evaluated, the consumer receives it directly. However, if the data is dirty, the node must first recompute it. It does so by pulling on the inputs required to compute the requested data. These inputs can also be dirty, in which case the evaluation request will then be forwarded to those dirty sources until it reaches the point where the data can be evaluated. The result then propagates back up in the graph, as the data is being \u201cpulled\u201d.
This evaluation model relies on the ability to mark node data as invalid and therefore requiring new evaluation. This mechanism is known as the Dirty Propagation in which the invalid data status propagates to all downstream dependencies. The two main cases where dirty propagation happened in the Pull Evaluation model were when:
The Pull Evaluation model is not well suited for efficient parallel evaluation because of potential races that can arise from concurrent pull evaluations.
To have tighter control over evaluation, Maya now uses a Forward Evaluation model to enable concurrent evaluation of multiple nodes. The general idea is simple: if all a node\u2019s dependencies have been evaluated before we evaluate the given node, pull evaluation will not be triggered when accessing evaluated node data, so evaluation remains contained in the node and is easier to run concurrently.
All data dependencies between the nodes must be known to apply this evaluation model, and this information is captured in the Evaluation Graph (EG), containing Evaluation Nodes. The EM uses dirty propagation to capture dependency information between the nodes, as well as which attributes are animated. EG connections represent node-level dependencies; destination nodes employ data from source nodes to correctly evaluate the scene. One important distinction between the DG and the EG is that the former uses plug-level connections, while the latter uses node-level connections. For example, the previous DG would create the following EG:
A valid EG may not exist or become invalid for various reasons. For example, you have loaded a new scene and no EG has been built yet, or you have changed your scene, invalidating a prior EG. However, once the EG is built, unlike previous versions of Maya that propagated dirty on every frame, Maya now disables dirty propagation, reusing the EG until it becomes invalid.
Tip
If your scene contains expression nodes that use getAttr
, the DG graph will be missing explicit dependencies. This results in an incorrect EG. Expression nodes also reduce the amount of parallelism in your scenes (see Scheduling Types for details). Consider removing getAttr
from expressions and/or using utility nodes.
While the EG holds the dependency information, it is not ready to be evaluated concurrently as-is. The EM must first create units of work that can be scheduled, that is, tasks. The main types of task created are:
This step, called partitioning, is where the EM creates the individual pieces of work that will have to be executed. Each of these tasks will map to a Scheduling Node in the Scheduling Graph (SG), where connections represent dependencies between the tasks:
The SG is an acyclic graph, otherwise it would be impossible to schedule nodes in a cycle since there would be no starting point for which all dependencies could be evaluated. In addition to the dependencies that come directly from the EG, the SG can have additional scheduling constraints to prevent concurrent evaluation of subsets of nodes (see Scheduling Types for details).
"},{"location":"parallel/#supported-evaluation-modes","title":"Supported Evaluation Modes","text":"Starting in Maya 2016, 3 evaluation modes are supported:
Mode What does it do? DG Uses the legacy Dependency Graph-based evaluation of your scene. This was the default evaluation mode prior to Maya 2016 Serial Evaluation Manager Serial mode. Uses the EG but limits scheduling to a single core. Serial mode is a troubleshooting mode to pinpoint the source of evaluation errors. Parallel Evaluation Manager Parallel mode. Uses the EG and schedules evaluation across all available cores. This mode is the new Maya default since 2016.When using either Serial or Parallel EM modes, you can also activate GPU Override to accelerate deformations on your GPU. You must be in Viewport 2.0 to use this feature (see GPU Override).
To switch between different modes, go to the Preferences window (Windows > Settings/Preferences > Preferences > Animation). You can also use the evaluationManager MEL/Python command; see documentation for supported options.
To see the evaluation options that apply to your scene, turn on the Heads Up Display Evaluation options (Display > Heads Up Display > Evaluation).
"},{"location":"parallel/#first-make-it-right-then-make-it-fast","title":"First Make it Right Then Make it Fast","text":"Before discussing how to make your Maya scene faster using Parallel evaluation, it is important to ensure that evaluation in DG and EM modes generates the same results. If you see different results in the viewport during animation (as compared to previous versions of Maya), or tests reveal numerical errors, it is critical to understand the cause of these errors. Errors may be due to an incorrect EG, threading related problems, or other issues.
Below, we review Evaluation Graph Correctness and Thread Safety, two important concepts to understand errors.
"},{"location":"parallel/#evaluation-graph-correctness","title":"Evaluation Graph Correctness","text":"If you see evaluation errors, first test your scene in Serial evaluation mode (see Supported Evaluation Modes). Serial evaluation mode uses the EM to build an EG of your scene, but limits evaluation to a single core to eliminate threading as the possible source of differences. Note that since Serial evaluation mode is provided for debugging, it has not been optimized for speed and scenes may run slower in Serial than in DG evaluation mode. This is expected.
If transitioning to Serial evaluation eliminates errors, this suggests that differences are most likely due to threading-related issues. However, if errors persist (even after transitioning to Serial evaluation) this suggests that the EG is incorrect for your scene. There are a few possible reasons for this:
Custom Plugins. If your scene uses custom plug-ins that rely on the mechanism provided by the MPxNode::setDependentsDirty
function to manage attribute dirtying, this may be the source of problems. Plug-in authors sometimes use MPxNode::setDependentsDirty
to avoid expensive calculations in MPxNode::compute
by monitoring and/or altering dependencies and storing computed results for later re-use.
Since the EM relies on dirty propagation to create the EG, any custom plug-in logic that alters dependencies may interfere with the construction of a correct EG. Furthermore, since the EM evaluation does not propagate dirty messages, any custom caching or computation in MPxNode::setDependentsDirty
is not called while the EM is evaluating.
If you suspect that your evaluation errors are related to custom plug-ins, temporarily remove the associated nodes from your scene and validate that both DG and Serial evaluation modes generate the same result. Once you have made sure this is the case, revisit the plug-in logic. The API Extensions section covers Maya SDK changes that will help you adapt plug-ins to Parallel evaluation.
Another debugging option is to use \u201cscheduling type\u201d overrides to force custom nodes to be scheduled more conservatively. This approach enables the use of Parallel evaluation even if only some of the nodes are thread-safe. Scheduling types are described in more detail in the Thread Safety section.
Errors in Autodesk Nodes. Although we have done our best to ensure that all out-of-the-box Autodesk Maya nodes correctly express dependencies, sometimes a scene uses nodes in an unexpected manner. If this is the case, we ask you make us aware of scenes where you encounter problems. We will do our best to address problems as quickly as possible.
"},{"location":"parallel/#thread-safety","title":"Thread Safety","text":"Prior to Maya 2016, evaluation was single-threaded and developers did not need to worry about making their code thread-safe. At each frame, evaluation was guaranteed to proceed serially and computation would finish for one node prior to moving onto another. This approach allowed for the caching of intermediate results in global memory and using external libraries without considering their ability to work correctly when called simultaneously from multiple threads.
These guarantees no longer apply. Developers working in recent versions of Maya must update plug-ins to ensure correct behavior during concurrent evaluation.
Two things to consider when updating plug-ins:
Different instances of a node type should not share resources. Unmanaged shared resources can lead to evaluation errors since different nodes, of the same type, can have their compute()
methods called at the same time.
Avoid non thread-safe lazy evaluation. In the EM, evaluation is scheduled from predecessors to successors on a per-node basis. Once computation has been performed for predecessors, results are cached, and made available to successors via connections. Any attempt to perform non-thread safe lazy evaluation could return different answers to different successors or, depending on the nature of the bug, instabilities.
Here\u2019s a concrete example for a simple node network consisting of 4 nodes:
In this graph, evaluation first calculates outputs for Node1 (that is, Node1.A, Node1.B, Node1.C), followed by parallel evaluation of Nodes 2, 3, and 4 (that is, Read Node1.A to use in Node2, Read Node1.B to use in Node3, and so on).
Knowing that making legacy code thread-safe requires time, we have added new scheduling types to provide control over how the EM schedule nodes. Scheduling types provide a straightforward migration path, so you do not need to hold off on performance improvements, just because a few nodes still need work.
There are 4 scheduling types:
Scheduling Type What are you telling the scheduler? Parallel Asserts that the node and all third-party libraries used by the node are thread-safe. The scheduler may evaluate any instances of this node at the same time as instances of other nodes without restriction. Serial Asserts it is safe to run this node with instances of other nodes. However, all nodes with this scheduling type should be executed sequentially within the same evaluation chain. Globally Serial Asserts it is safe to run this node with instances of other node types but only a single instance of this node type should be run at a time. Use this type if the node relies on static state, which could lead to unpredictable results if multiple node instances are simultaneously evaluated. The same restriction may apply if third-party libraries store state. Untrusted Asserts this node is not thread-safe and that no other nodes should be evaluated while an instance of this node is evaluated. Untrusted nodes are deferred as much as possible (that is, until there is nothing left to evaluate that does not depend on them), which can introduce costly synchronization.By default, nodes scheduled as Serial provide a middle ground between performance and stability/safety. In some cases, this is too permissive and nodes must be downgraded to GloballySerial or Untrusted. In other cases, some nodes can be promoted to Parallel. As you can imagine, the more parallelism supported by nodes in your graph, the higher level of concurrency you are likely to obtain.
Tip
When testing your plug-ins with Parallel Maya, a simple strategy is to schedule nodes with the most restrictive scheduling type (that is, Untrusted), and then validate that evaluation produces correct results. Raise individual nodes to the next scheduling level, and repeat the experiment.
There are three ways to alter the scheduling level of your nodes:
Evaluation Toolkit. Use this tool to query or change the scheduling type of different node types.
C++/Python API methods. Use the OpenMaya API to specify the desired node scheduling by overriding the MPxNode::schedulingType
method. This function should return one of the enumerated values specified by MPxNode::schedulingType
. See the Maya MPxNode class reference for more details.
MEL/Python Commands. Use the evaluationManager command to change the scheduling type of nodes at runtime. Below, we illustrate how you can change the scheduling of scene transform nodes:
Scheduling Type Command ParallelevaluationManager -nodeTypeParallel on \"transform\"
Serial evaluationManager -nodeTypeSerialize on \"transform\"
GloballySerial evaluationManager -nodeTypeGloballySerialize on \"transform\"
Untrusted evaluationManager -nodeTypeUntrusted on \"transform\"
The Evaluation Toolkit and MEL/Python Commands method to alter node scheduling level works using node type overrides. They add an override that applies to all nodes of a given type. Using C++/Python API methods and overriding the MPxNode::schedulingType
function gives the flexibility to change the scheduling type for each node instance. For example, expression nodes are marked as globally serial if the expression outputs are a purely mathematical function of its inputs.
The expression engine is not thread-safe so only one expression can run at a time, but it can run in parallel with any other nodes. However, if the expression uses unsafe commands (expressions could use any command to access any part of the scene), the node is marked as untrusted because nothing can run while the expression is evaluated.
This changes the way scheduling types should be queried. Using the evaluationManager
command with the above flags in query mode will return whether an override has been set on the node type, using either the Evaluation Toolkit or the MEL/Python commands.
The Evaluation Toolkit window lets you query both the override type on the node type (which cannot vary from one node of the same type to the other), or the actual scheduling type used for a node when building the scheduling graph (which can change from one node instance to the other).
"},{"location":"parallel/#safe-mode","title":"Safe Mode","text":"On rare occasions you may notice that Maya switches from Parallel to Serial evaluation during manipulation or playback. This is due to Safe Mode, which attempts to trap errors that possibly lead to instabilities. If Maya detects that multiple threads are attempting to simultaneously access a single node instance, evaluation will be forced to Serial execution to prevent problems.
Tip
If Safe Mode forces your scene into Serial mode, the EM may not produce the expected incorrect results when manipulating. In such cases you can either disable the EM:
cmds.evaluationManager(mode=\"off\")
or disable EM-accelerated manipulation:
cmds.evaluationManager(man=0)
While Safe Mode exposes many problems, it cannot catch them all. Therefore, we have also developed a special Analysis Mode that performs a more thorough (and costly) check of your scene. Analysis mode is designed for riggers/TDs wishing to troubleshoot evaluation problems during rig creation. Avoid using Analysis Mode during animation since it will slow down your scene.
"},{"location":"parallel/#evaluation-graph-invalidation","title":"Evaluation Graph Invalidation","text":"As previously described, the EG adds necessary node-level scheduling information to the DG. To make sure evaluation is correct, it\u2019s critical the EG always be up-to-date, reflecting the state of the scene. The process of detecting things that have changed and rebuilding the EG is referred to as graph invalidation.
Different actions may invalidate the EG, including:
Other, less obvious, actions include:
Frequent graph invalidations may limit parallel evaluation performance gains or even slow it down (see Idle Actions), since Maya requires DG dirty propagation and evaluation to rebuild the EG. To avoid unwanted graph rebuilds, consider adding 2 keys, each with slightly different values, on rig attributes that you expect to use frequently. You can also lock static channels to prevent creation of static animation curves during keying. We expect to continue tuning this area of Maya, with the goal of making the general case as interactive as possible.
Tip
You can use the controller command to identify objects that are used as animation sources in your scene. If the Include controllers in evaluation graph option is set (see Windows > Settings/Preferences > Preferences, then Settings > Animation), the objects marked as controllers will automatically be added to the evaluation graph even if they are not animated yet. This allows Parallel evaluation for manipulation even if they have not yet been keyed.
"},{"location":"parallel/#idle-actions","title":"Idle Actions","text":"In this section, we discuss the different idle actions available in Maya that helps rebuild the EG without any intervention from the user. Prior to Maya 2019, only one idle action, the EG rebuild, was available, but it was not enabled by default. Since Maya 2019, we have added another idle action, the EG preparation for manipulation, and both of these are enabled by default.
Here is a description of the idle actions:
Idle Action Description EG Rebuild Builds the graph topology. This idle action is executed after a file load operation, or after a graph topology invalidation. EG Preparation for manipulation Partitions and schedules the graph. This idle action is executed after a graph rebuild (either manually or through the idle action), or after a partitioning invalidation.Tip
You can use the evaluationManager command to change which idle actions are enabled. You can enable and disable both idle actions individually.
"},{"location":"parallel/#benefits","title":"Benefits","text":"To make use of the Parallel Evaluation and GPU deformation during manipulation, the EG needs to be properly built, partitioned and scheduled, otherwise it will revert to DG. These idle actions allow the EG to automatically build and be ready to use when needed, since they are triggered at file load and after graph invalidation.
If you use Cached Playback, your cache automatically refills, too. This way, you can start playing from cache as soon as the scene is loaded or after you modify to the scene.
"},{"location":"parallel/#caveats","title":"Caveats","text":"In a typical frame evaluation, temporary values that are set on keyed attributes are restored to their original values, that is, the values on their associated curves. With the idle actions, this is an unwanted behavior, otherwise you would not be able to do any modifications to keyed attributes. To circumvent that issue, we had to add some special behaviougs One of these is the dirty propagation from stale plugs after an idle preparation for manipulation. When not in idle preparation for manipulation, this operation is done during the partitioning and scheduling phase. With idle preparation for manipulation, this operation is done at the next complete evaluation. Therefore, if you have many static curves, you might experience a slowdown on the first frame of playback.
If you do frequent operations that invalidate the graph or partitioning, you may experience some slowdowns due to the graph always being rebuilt. In such cases, it is advised that you disable the offending idle action until you are done.
"},{"location":"parallel/#custom-evaluators","title":"Custom Evaluators","text":"In this section, we describe mechanisms to perform targeted evaluation of node sub-graphs. This approach is used by Maya to accelerate deformations on the GPU and to catch evaluation errors for scenes with specific nodes. Maya 2017 also introduced new Open API extensions, allowing user-defined custom evaluators.
Tip
Use the evaluator command to query the available/active evaluators or modify currently active evaluators. Some evaluators support using the nodeType flag to filter out or include nodes of certain types. Query the info flag on the evaluator for more information on what it supports.
# Returns a list of all currently available evaluators.\nimport maya.cmds as cmds\ncmds.evaluator( query=True )\n# Result: [u'invisibility',\nu'frozen',\n...\nu'transformFlattening',\nu'pruneRoots'] #\n\n# Returns a list of all currently enabled evaluators.\ncmds.evaluator( query=True, enable=True )\n# Result: [u'invisibility',\nu'timeEditorCurveEvaluator',\n...\nu'transformFlattening',\nu'pruneRoots'] #\n
Note: Enabling or disabling custom evaluators only applies to the current Maya session: the state is not saved in the scene nor in the user preferences. The same applies to configuration done using the evaluator
command and the configuration flag.
Maya contains a custom deformer evaluator that accelerates deformations in Viewport 2.0 by targeting deformation to the GPU. GPUs are ideally suited to tackle problems such as mesh deformations that require the same operations on streams of vertex and normal data. We have included GPU implementations for several of the most commonly-used deformers in animated scenes: skinCluster, blendShape, cluster, tweak, groupParts, softMod, deltaMush, lattice, nonLinear and tension.
Unlike Maya\u2019s previous deformer stack that performed deformations on the CPU and subsequently sent deformed geometry to the graphics card for rendering, the GPU override sends undeformed geometry to the graphics card, performs deformations in OpenCL and then hands off the data to Viewport 2.0 for rendering without read-back overhead. We have observed substantial speed improvements from this approach in scenes with dense geometry.
Even if your scene uses only supported deformers, GPU override may not be enabled due to the use of unsupported node features in your scene. For example, with the exception of softMod, there is no support for incomplete group components. Additional deformer-specific limitations are listed below:
Deformer
Limitation(s)
skinCluster
The following attribute values are ignored:
- bindMethod
- bindPose
- bindVolume
- dropOff
- heatmapFalloff
- influenceColor
- lockWeights
- maintainMaxInfluences
- maxInfluences
- nurbsSamples
- paintTrans
- smoothness
- weightDistribution
blendShape
The following attribute values are ignored:
- baseOrigin
- icon
- normalizationId
- origin
- parallelBlender
- supportNegativeWeights
- targetOrigin
- topologyCheck
cluster
n/a
tweak
Only relative mode is supported. relativeTweak must be set to 1.
groupParts
n/a
softMod
Only volume falloff is supported when distance cache is disabled
Falloff must occur on all axes
Partial resolution must be disabled
deltaMush
n/a
lattice
n/a
nonLinear
n/a
tension
n/a
A few other reasons that can prevent GPU override from accelerating your scene:
Meshes not sufficiently dense. Unless meshes have a large number of vertices, it is still faster to perform deformations on the CPU. This is due to the driver-specific overhead incurred when sending data to the GPU for processing. For deformations to happen on the GPU, your mesh needs over 500/2000 vertices, on AMD/NVIDIA hardware respectively. Use the MAYA_OPENCL_DEFORMER_MIN_VERTS
environment variable to change the threshold. Setting the value to 0 sends all meshes connected to supported deformation chains to the GPU.
Downstream graph nodes required deformed mesh results. Since GPU read-back is a known bottleneck in GPGPU, no node, script, or Viewport can read the mesh data computed by the GPU override. This means that GPU override is unable to accelerate portions of the EG upstream of deformation nodes, such as follicle or pointOnPolyConstraint, that require information about the deformed mesh. We will re-examine this limitation as software/hardware capabilities mature. When diagnosing GPU Override problems, this situation may appear as an unsupported fan-out pattern. See deformerEvaluator command, below, for details.
Animated Topology. If your scene animates the number of mesh edges, vertices, and/or faces during playback, corresponding deformation chains are removed from the GPU deformation path.
Maya Catmull-Clark Smooth Mesh Preview is used. We have included acceleration for OpenSubDiv (OSD)-based smooth mesh preview, however there is no support for Maya\u2019s legacy Catmull-Clark. To take advantage of OSD OpenCL acceleration, select OpenSubDiv Catmull-Clark as the subdivision method and make sure that OpenCL Acceleration is selected in the OpenSubDiv controls.
Unsupported streams are found. Depending on which drawing mode you select for your geometry (for example, shrunken faces, hedge-hog normals, and so on) and the material assigned, Maya must allocate and send different streams of data to the graphics card. Since we have focused our efforts on common settings used in production, GPU override does not currently handle all stream combinations. If meshes fail to accelerate due to unsupported streams, change display modes and/or update the geometry material.
Back face culling is enabled.
Driver-related issues. We are aware of various hardware issues related to driver support/stability for OpenCL. To maximize Maya\u2019s stability, we have disabled GPU Override in the cases that will lead to problems. We expect to continue to eliminate restrictions in the future and are actively working with hardware vendors to address detected driver problems.
You can also increase support for new custom/proprietary deformers by using new API extensions (refer to Custom GPU Deformers for details).
If you enable GPU Override and the HUD reports Enabled (0 k), this indicates that no deformations are happening on the GPU. There could be several reasons for this, such as those mentioned above.
To troubleshoot factors that limit the use of GPU override for your particular scene, use the deformerEvaluator command. Supported options include:
Command
What does it do?
deformerEvaluator
Prints the chain or each selected node is not supported.
deformerEvaluator -chains
Prints all active deformation chains.
deformerEvaluator -meshes
Prints a chain for each mesh or a reason if it is not supported.
"},{"location":"parallel/#dynamics-evaluator","title":"Dynamics Evaluator","text":"Starting in Maya 2017, the dynamics evaluator fully supports parallel evaluation of scenes with Nucleus (nCloth, nHair, nParticles), Bullet, and Bifrost dynamics. Legacy dynamics nodes (for example, particles, fluids) remain unsupported. If the dynamics evaluator finds unsupported node types in the EG, Maya will revert to DG-based evaluation. The dynamics evaluator also manages the tricky computation necessary for correct scene evaluation. This is one of the ways custom evaluators can be used to change Maya\u2019s default evaluation behavior.
The dynamics evaluator supports several configuration flags to control its behavior.
Flag
What does it do?
disablingNodes
specifies the set of nodes that will force the dynamics evaluator to disable the EM. Valid values are: legacy2016
, unsupported
, and none
.
handledNodes
specifies the set of nodes that are going to be captured by the dynamics evaluator and scheduled in clusters that it will manage. Valid values are: dynamics
and none
.
action
specifies how the dynamics evaluator will handle its nodes. Valid values are: none
, evaluate
, and freeze
.
In Maya 2017, the default configuration corresponds to:
cmds.evaluator(name=\"dynamics\", c=\"disablingNodes=unsupported\")\ncmds.evaluator(name=\"dynamics\", c=\"handledNodes=dynamics\")\ncmds.evaluator(name=\"dynamics\", c=\"action=evaluate\")\n
where unsupported (that is, blacklisted) nodes are:
This configuration disables evaluation if any unsupported nodes are encountered, and performs evaluation for the other handled nodes in the scene.
To revert to Maya 2016 / 2016 Extension 2 behavior, use the configuration:
cmds.evaluator(name=\"dynamics\", c=\"disablingNodes=legacy2016\")\ncmds.evaluator(name=\"dynamics\", c=\"handledNodes=none\")\ncmds.evaluator(name=\"dynamics\", c=\"action=none\")\n
where unsupported (that is, blacklisted) nodes are:
Tip
To get a list of nodes that cause the dynamics evaluator to disable the EM in its present configuration, use the following command:
cmds.evaluator(name=\"dynamics\", valueName=\"disabledNodes\", query=True)\n
You can configure the dynamics evaluator to ignore unsupported nodes. If you want to try Parallel evaluation on a scene where it is disabled because of unsupported node types, use the following commands:
cmds.evaluator(name=\"dynamics\", c=\"disablingNodes=none\")\ncmds.evaluator(name=\"dynamics\", c=\"handledNodes=dynamics\")\ncmds.evaluator(name=\"dynamics\", c=\"action=evaluate\")\n
Note: Using the dynamics evaluator on unsupported nodes may cause evaluation problems and/or application crashes; this is unsupported behavior. Proceed with caution.
Tip
If you want the dynamics evaluator to skip evaluation of all dynamics nodes in the scene, use the following commands:
cmds.evaluator(name=\"dynamics\", c=\"disablingNodes=unsupported\")\ncmds.evaluator(name=\"dynamics\", c=\"handledNodes=dynamics\")\ncmds.evaluator(name=\"dynamics\", c=\"action=freeze\")\n
This can be useful to quickly disable dynamics when the simulation impacts animation performance.
Dynamics simulation results are very sensitive to evaluation order, which may differ between DG and EM-based evaluation. Even for DG-based evaluation, evaluation order may depend on multiple factors. For example, in DG-mode when rendering simulation results to the Viewport, the evaluation order may be different than when simulation is performed in \u2018headless mode\u2019. Though EM-based evaluation results are not guaranteed to be identical to DG-based, evaluation order is consistent; once the evaluation order is scheduled by the EM, it will remain consistent regardless of whether results are rendered or Maya is used in batch. This same principle applies to non-dynamics nodes that are order-dependent.
"},{"location":"parallel/#reference-evaluator","title":"Reference Evaluator","text":"When a reference is unloaded it leaves several nodes in the scene representing reference edits to preserve. Though these nodes may inherit animation from upstream nodes, they do not contribute to what is rendered and can be safely ignored during evaluation. The reference evaluator ensures all such nodes are skipped during evaluation.
"},{"location":"parallel/#invisibility-evaluator","title":"Invisibility Evaluator","text":"Toggling scene object visibility is a critical artist workflow used to reduce visual clutter and accelerate performance. To bring this workflow to parallel evaluation, Maya 2017 and above includes the invisibility evaluator, whose goal is to skip evaluation of any node that does not contribute to a visible object.
The invisibility evaluator will skip evaluation of DAG nodes meeting any of the below criteria:
visibility
attribute is false.intermediateObject
attribute is true.overrideEnabled
attribute is true and overrideVisibility
attribute is false.enabled
attribute is true and visibility
attribute is false.As of Maya 2018, the invisibility evaluator supports the isolate select
method of hiding objects. If there is only a single Viewport, and it has one or more objects isolated, then all of the other, unrelated objects are considered invisible by the evaluator.
There is also support in Maya (2018 and up) for the animated
attribute on expression nodes. When this attribute is set to 1, the expression node is not skipped by the invisibility evaluator, even if only invisible objects are connected to it.
Note: The default value of the animated
attribute is 1, so in an expression-heavy scene you may see a slowdown from Maya 2017 to Maya 2018. To restore performance, run the script below to disable this attribute on all expression nodes. (It is only required when the expression has some sort of side-effect external to the connections, such as printing a message or checking a cache file size.)
for node in cmds.ls( type='expression' ):\n cmds.setAttr( '{}.animated'.format(node), 0 )\n
Tip: The invisibility evaluator is off by default in Maya 2017. Use the Evaluation Toolkit or this:
cmds.evaluator(enable=True, name='invisibility')\n
to enable the evaluator.
The invisibility evaluator only considers static visibility; nodes with animated visibility are still evaluated, even if nodes meet the above criteria. If nodes are in a cycle, all cycle nodes must be considered invisible for evaluation to be skipped. Lastly, if a node is instanced and has at least one visible path upward, then all upward paths will be evaluated.
Tip: The invisibility evaluator determines visibility solely from the node\u2019s visibility state; if your UI or plug-in code requires invisible nodes to evaluate, do not use the invisibility evaluator.
"},{"location":"parallel/#frozen-evaluator","title":"Frozen Evaluator","text":"The frozen evaluator allows users to tag EG subsections as not needing evaluation. It enhances the frozen
attribute by propagating the frozen state automatically to related nodes, according to the rules defined by the evaluator\u2019s configuration. It should only be used by those comfortable with the concepts of connection and propagation in the DAG and Evaluation Graph. Many users may prefer the invisibility evaluator; it is a simpler interface/workflow for most cases.
The frozen attribute has existed on nodes since Maya 2016. It can be used to control whether node is evaluated in Serial or Parallel EM evaluation modes. In principle, when the frozen attribute is set, the EM skips evaluation of that node. However, there are additional nuances that impact whether or not this is the case:
Warning: All the frozen attribute does is skip evaluation, nothing is done to preserve the current node data during file store; if you load a file with frozen attributes set, the nodes may not have the same data as when you stored them.
"},{"location":"parallel/#operation","title":"Operation","text":"The evaluation manager does not evaluate any node that has its frozen
attribute set to True, referred to here as explicitly frozen nodes. An implicitly frozen node is one that is disabled because of the operation of the frozen evaluator, but whose frozen
attribute is not set to True. When the frozen evaluator is enabled it will also prevent evaluation of related nodes according to the rules corresponding to the enabled options, in any combination.
The frozen evaluator operates in three phases. In phase one, it gathers together all of the nodes flagged by the invisible and displayLayers options as being marked for freezing. In phase two, it propagates the freezing state outwards through the evaluation graph according to the values of the downstream and upstream options.
"},{"location":"parallel/#phase-1-gathering-the-nodes","title":"Phase 1: Gathering The Nodes","text":"The list of nodes for propagation is gathered as follows:
frozen
attribute set to True are found. (Note: This does not include those whose frozen attribute is animated. They are handled via Phase 3.)The list gathered by Phase 1 will all be implicitly frozen. In addition, the downstream and upstream options may implicitly freeze nodes related to them. For each of the nodes gathered so far, the evaluation graph will be traversed in both directions, implicitly freezing nodes encountered according to the following options:
If a node has its frozen or visibility states animated, the evaluator still has to schedule it. The runtime freezing can still assist at this point in preventing unnecessary evaluation. Normally any explicitly frozen node will have its evaluation skipped, with all other nodes evaluating normally. When the runtime option is enabled, after skipping the evaluation of an explicitly frozen node no further scheduling of downstream nodes will occur. As a result, if the downstream nodes have no other unfrozen inputs they will also be skipped.
Note: The runtime option does not really modify the evaluator operation, it modifies the scheduling of nodes for evaluation. You will not see nodes affected by this option in the evaluator information (for example, the output from cmds.evaluator( query=True, clusters=True, name='frozen' )
)
Options can be set for the frozen evaluator in one of two ways:
Accessing them through the Evaluation Toolkit
Using the evaluator command\u2019s configuration option:
cmds.evaluator( name='frozen', configuration='KEY=VALUE' )\n
Legal KEY and VALUE values are below, and correspond to the options as described above:
KEY
VALUES
DEFAULT
runtime
True/False
False
invisible
True/False
False
displayLayers
True/False
False
downstream
\u2018off\u2019/\u2018safe\u2019/\u2018force\u2019
\u2018off\u2019
upstream
\u2018off\u2019/\u2018safe\u2019/\u2018force\u2019
\u2018off\u2019
Unlike most evaluators the frozen evaluator options are stored in user preferences and persists between sessions.
"},{"location":"parallel/#limitations","title":"Limitations","text":"frozen
attribute to True to instruct the frozen evaluator to shut off evaluation on affected nodes. The most practical use of this would be on a display layer so that nodes can be implicitly frozen as a group.frozen
attribute, or any of the attributes used to define related implicit nodes for freezing (for example, visibility
) are animated then the evaluator will not remove them from evaluation. They will still be scheduled and only the runtime option will help in avoiding unnecessary evaluation.The curve manager evaluator can be used to include additional nodes in the Evaluation Graph, which can have two main benefits:
To achieve those benefits efficiently, the curve manager evaluator performs two main tasks:
To illustrate this result, let\u2019s compare the three following situations.
The third situation is where we are trying to take advantage of the curve manager evaluator to have an Evaluation Graph that is already set up to allow parallel evaluation when the controllers will be manipulated.
The following table summarizes the differences between the situations and the compromises provided by the curve manager evaluator.
Situation
# of nodes in EG
Playback
EM Manip
Rebuild when keying
Static curves + curve manager off
Lowest
Fastest
No
Yes
Animated curves
Highest
Slowest
Yes
No
Static curves + curve manager on
Highest
Middle
Yes
No
In summary, the curve manager evaluator benefits from having the Evaluation Graph already populated with nodes so it is ready to evaluate interactive manipulation, while paying as little of a cost as possible for those constant nodes during playback.
It can be activated using:
cmds.evaluator(\n name=\"curveManager\",\n enable=True\n )\ncmds.evaluator(\n name=\"curveManager\",\n configuration=\"forceAnimatedCurves=keyed\"\n )\n
The available values for forceAnimatedCurves
are:
Another option, forceAnimatedNodes
, can be used:
This allows tagging nodes to be added with a boolean dynamic attribute. By default, the name of this attribute is forcedAnimated
. If it is present on a node and set to true, the node is added to the graph. The name of the attribute can be controlled by using the \u201cforcedAnimatedAttributeName\u201d option.
By default, the curve manager evaluator tries to skip the evaluation of the static parts of the graph. For debugging or performance measurement purposes, this optimization can be disabled:
cmds.evaluator(\n name=\"curveManager\",\n configuration=\"skipStaticEvaluation=disable\"\n )\n
"},{"location":"parallel/#other-evaluators","title":"Other Evaluators","text":"In addition to evaluators described above, additional evaluators exist for specialized tasks:
Evaluator
What does it do?
cache
Constitutes the foundation of Cached Playback. See the Maya Cached Playback whitepaper for more information.
timeEditorCurveEvaluator
Finds all paramCurves connected to time editor nodes and puts them into a cluster that will prevent them from evaluating at the current time, since the time editor will manage their evaluation.
ikSystem
Automatically disables the EM when a multi-chain solver is present in the EG. For regular IK chains it will perform any lazy update prior to parallel execution.
disabling
Automatically disables the EM if user-specified nodes are present in the EG. This evaluator is used for troubleshooting purposes. It allows Maya to keep working stably until issues with problem nodes can be addressed.
hik
Handles the evaluation of HumanIK characters in an efficient way by recognizing HumanIK common connection patterns.
cycle
Unrolls cycle clusters to augment the opportunity for parallelism and improve performance. Likely gives the best performance improvements when large cycle clusters are present in the scene. Prototype, work in progress.
transformFlattening
Consolidates deep transform hierarchies containing animated parents and static children, leading to faster evaluation. Consolidation takes a snapshot of the relative parent/child transformations, allowing concurrent evaluation of downstream nodes.
pruneRoots
We found that scenes with several thousand paramCurves become bogged down because of scheduling overhead from resulting EG nodes and lose any potential gain from increased parallelism. To handle this situation, special clusters are created to group paramCurves into a small number of evaluation tasks, thus reducing overhead.
Custom evaluator names are subject to change as we introduce new evaluators and expand these functionalities.
"},{"location":"parallel/#evaluator-conflicts","title":"Evaluator Conflicts","text":"Sometimes, multiple evaluators will want to \u201cclaim responsibility\u201d for the same node(s). This can result in conflict, and negatively impact performance. To avoid these conflicts, upon registration each evaluator is associated with a priority; nodes are assigned to the evaluator with the highest priority. Internal evaluators have been ordered to prioritize correctness and stability over speed.
"},{"location":"parallel/#api-extensions","title":"API Extensions","text":"Several API extensions and tools have been added to help you make the most of the EM in your pipeline. This section reviews API extensions for Parallel Evaluation, Custom GPU Deformers, Custom Evaluator API, VP2 Integration and Profiling Plug-ins.
"},{"location":"parallel/#parallel-evaluation","title":"Parallel Evaluation","text":"If your plug-in plays by the DG rules, you will not need many changes to make the plug-in work in Parallel mode. Porting your plug-in so that it works in Parallel may be as simple as recompiling it against the latest version of OpenMaya!
If the EM generates different results than DG-based evaluation, make sure that your plug-in:
Overrides MPxNode::compute()
. This is especially true of classes extending MPxTransform
which previously relied on asMatrix()
. See the rockingTransform SDK sample. For classes deriving from MPxDeformerNode
and MPxGeometryFilter
, override the deform()
method.
Handles requests for evaluation at all levels of the plug tree. While the DG can request plug values at any level, the EM always requests the root plug. For example, for plug N.gp[0].p[1] your compute() method must handle requests for evaluation of N.gp, N.gp[0], N.gp[0].p, and N.gp[0].p[1].
If your plug-in relies on custom dependency management, you need to use new API extensions to ensure correct results. As described earlier, the EG is built using the legacy dirty-propagation mechanism. Therefore, optimizations used to limit dirty propagation during DG evaluation, such as those found in MPxNode::setDependentsDirty
, may introduce errors in the EG. Use MEvaluationManager::graphConstructionActive() to detect if this is occurring.
There are new virtual methods you will want to consider implementing:
MPxNode::preEvaluation
. To avoid performing expensive calculations each time the evaluation method MPxNode::compute()
is called, one strategy plug-in authors use is to store results from previous evaluations and then rely on MPxNode::setDependentsDirty
to trigger re-computation. As discussed previously, once the EG has been built, dirty propagation is disabled and the EG is re-used. Threrefore, any custom logic in your plug-in that depends on setDependentsDirty no longer applies.
MPxNode::preEvaluation
allows your plug-in to determine which plugs/attributes are dirty and if any action is needed. Use the new MEvaluationNode class to determine what has been dirtied.
Refer to the simpleEvaluationNode devkit example for an illustration of how to use MPxNode::preEvaluation
.
MPxNode::postEvaluation
. Until now, it was difficult to determine at which point all processing for a node instance was complete. Users sometimes resorted to complex bookkeeping/callback schemes to detect this situation and perform additional work, such as custom rendering. This mechanism was cumbersome and error-prone.
Once all computations have been performed on a specific node instance, a new method, MPxNode::postEvaluation
, is called. Since this method is called from a worker thread, it performs calculations for downstream graph operations without blocking other Maya processing tasks of non-dependent nodes.
See the simpleEvaluationDraw devkit example to understand how to use this method. If you run this example in regular evaluation, Maya slows down, since evaluation is blocked whenever expensive calculations are performed. When you run in Parallel Evaluation Mode, a worker thread calls the postEvaluation method and prepares data for subsequent drawing operations. When testing, you will see higher frame rates in Parallel evaluation versus regular or Serial evaluation. Please note that code in postEvaluation should be thread-safe.
Other recommended best practices include:
Avoid storing state in static variables. Store node state/settings in attributes. This has the additional benefit of automatically saving/restoring the plug-in state when Maya files are written/read.
Node computation should not have any dependencies beyond input values. Maya nodes should be like functions. Output values should be computed from input state and node-specific internal logic. Your node should never walk the graph or try to circumvent the DG.
To make GPU Override work on scenes containing custom deformers, Maya provides new API classes that allow the creation of fast OpenCL deformer back-ends.
Though you still need to have a CPU implementation for the times when it is not possible to target deformations on the GPU (see GPU Override), you can augment this with an alternate deformer implementation inheriting from MPxGPUDeformer. This applies to your own nodes as well as to standard Maya nodes.
The GPU implementation will need to:
When you have done this, do not forget to load your plug-in at startup. Two working devkit examples (offsetNode and identityNode) have been provided to get you started.
Tip
To get a sense for the maximum speed increase you can expect by providing a GPU backend for a specific deformer, tell Maya to treat specific nodes as passthrough. Here\u2019s an example applied to polySoftEdge:
cmds.GPUBuiltInDeformerControl(\n name=\"polySoftEdge\",\n inputAttribute=\"inputPolymesh\",\n outputAttribute=\"output\",\n passthrough=True\n )\n
Although results will be incorrect, this test will confirm if it is worth investing time implementing an OpenCL version of your node.
"},{"location":"parallel/#custom-evaluator-api","title":"Custom Evaluator API","text":"API classes and methods introduced in Maya 2017 let you define custom evaluators that allow control over how the Maya scene is computed.
To create a custom evaluator, you must define a plug-in that extends the MPxCustomEvaluator
class. The key class methods to override are described below.
Before you can use the new evaluators, they must be registered:
MStatus registerEvaluator(\n // name of the evaluator\n const char * evaluatorName,\n\n // evaluator priority. Higher priority evaluators get 'first-dibs'\n unsigned int uniquePriority,\n\n // function pointer to method returning a new evaluator instance\n MCreatorFunction creatorFunction\n)\n
and deregistered:
MStatus deregisterEvaluator(\n // name of the evaluator\n const char* evaluatorName\n)\n
using MFnPlugin
methods. These functions should be used during plug-in initialization:
MStatus initializePlugin( MObject obj )\n{\n MFnPlugin plugin( obj, PLUGIN_COMPANY, \"3.0\", \"Any\");\n MStatus status = plugin.registerEvaluator(\n \"SimpleEvaluator\",\n 40,\n simpleEvaluator::creator);\n if (!status)\n status.perror(\"registerEvaluator\");\n return status;\n}\n
and uninitialization:
MStatus uninitializePlugin( MObject obj )\n{\n MFnPlugin plugin( obj );\n MStatus status = plugin.deregisterEvaluator( \"SimpleEvaluator\" );\n if (!status)\n status.perror(\"deregisterEvaluator\");\n return status;\n}\n
as illustrated above.
Once the plug-in has been loaded, use Python or MEL commands to enable:
import maya.cmds as cmds\ncmds.evaluator(enable=True, name='SimpleEvaluator')\n\n# Result: False #\n
disable:
cmds.evaluator(enable=False, name='SimpleEvaluator')\n\n# Result: True #\n
and query information about evaluators:
print cmds.evaluator(query=True)\n\n[u'invisibility', ... u'SimpleEvaluator']\n
NOTE: The evaluator command returns the previous state of the evaluator (as described in the documentation). This command fails if the evaluator cannot be enabled.
To view the priorities of all loaded evaluators, use the priority flag on the evaluator command:
for evaluatorName in cmds.evaluator():\n print \"%-25s : %d\" % (\n evaluatorName,\n cmds.evaluator(name=evaluatorName, query=True, priority=True))\n\ninvisibility : 1003000\nfrozen : 1002000\ncurveManager : 1001000\ncache : 1000000\ntimeEditorCurveEvaluator : 104000\ndynamics : 103000\nikSystem : 102000\ndisabling : 100000\nhik : 7000\nreference : 6000\ndeformer : 5000\ncycle : 4000\ntransformFlattening : 3000\npruneRoots : 1000\nSimpleEvaluator : 40\n
"},{"location":"parallel/#api-reference","title":"API Reference","text":"This section provides more detail on different MPxCustomEvaluator
API methods.
During EG partitioning, each evaluator gets to claim evaluation nodes, using the:
bool MPxCustomEvaluator::markIfSupported(const MEvaluationNode* node)\n
method. You can safely cause evaluation in this call but doing so increases partitioning and evaluation time. The developer can decide whether evaluation is required (call .inputValue
/ .inputArrayValue
), or the previously-evaluated datablock values can be re-used (call .outputValue
/ .outputArrayValue
). If multiple evaluators mark a specific node, which evaluator is assigned a node at run-time is determined by priority. For example, if you have two evaluators, A and B, mark node C of interest, if evaluator A has priority 100, and evaluator B has priority 10, during graph partitioning, evaluator A will get the opportunity to grab node C before evaluator B. Evaluators should not try to grab a node already grabbed by a higher-priority evaluator.
To determine if an evaluator can evaluate clusters in Parallel, use:
MCustomEvaluatorClusterNode::SchedulingType schedulingType(\n // a disjoint set of nodes on a custom evaluator layer\n const MCustomEvaluatorClusterNode * cluster\n)\n
where:
SchedulingType
Details
kParallel
any number of nodes of the same type can run in parallel
kSerial
all nodes of this type should be chained and executed sequentially
kGloballySerial
only one node of this type can be run at a time
kUntrusted
nothing else can execute with this node since we cannot predict what will happen
During EG scheduling:
bool MPxCustomEvaluator::clusterInitialize(\n // evaluation cluster node\n const MCustomEvaluatorClusterNode* cluster\n)\n
can be used to perform the required cluster preparation. The pointer to the cluster remains valid until graph invalidation, such as when the scene topology changes.
Before the cluster is deleted,
void MPxCustomEvaluator::clusterTerminate(\n // the cluster to terminate\n const MCustomEvaluatorClusterNode* cluster\n)\n
is called to allow needed cleanup, for example, releasing evaluator-specific resources. It is up to the custom evaluator to decide if it wants to clear its internal representation.
"},{"location":"parallel/#execution","title":"Execution","text":"There are 3 main methods used during execution.
Prior to graph execution, the EM calls:
void MPxCustomEvaluator::preEvaluate(\n // the graph about to be evaluated\n const MEvaluationGraph* graph\n)\n
during execution, the EM calls:
void MPxCustomEvaluator::clusterEvaluate(\n // the cluster to be evaluated\n const MCustomEvaluatorClusterNode* cluster\n)\n
You will only receive clusters that belong to this evaluator. This call always happens after clusterInitialize
and never after clusterTerminate
. Finally,
void MPxCustomEvaluator::postEvaluate(\n // the graph that was evaluated\n const MEvaluationGraph* graph\n)\n
is called just after a graph evaluation is finished.
"},{"location":"parallel/#simpleevaluator-api-example","title":"SimpleEvaluator API Example","text":"Now that we have reviewed relevant API methods, the following example limits evaluation by caching previous results. simpleEvaluator
assumes the existence of scene nodes that tag controller nodes with animation and works as follows:
In clusterInitialize
, we-2\">ld a list of translation and rotation attribute plugs.
// Build a list of plugs by scanning the scene for controller nodes.\n// This gets called during scheduling.\nbool simpleEvaluator::clusterInitialize(\n const MCustomEvaluatorClusterNode* cluster\n )\n{\n if (fControllerPlugs.length() == 0)\n buildPlugListWithControllerTag();\n return true;\n}\n\n// Scan the scene for any controller nodes, populating the plug list.\n// Called during the scheduling phase\nvoid simpleEvaluator::buildPlugListWithControllerTag()\n{\n MStatus stat;\n MItDependencyNodes dgIter(MFn::kControllerTag, &stat);\n if (stat != MS::kSuccess)\n return;\n\n const char* values[] = {\n \"translateX\",\n \"translateY\",\n \"translateZ\",\n \"rotateX\",\n \"rotateY\",\n \"rotateZ\"\n };\n\n for (; !dgIter.isDone(); dgIter.next())\n {\n MFnDependencyNode controllerTagNode(dgIter.thisNode(), &stat);\n if (stat != MS::kSuccess)\n continue;\n\n MPlug currControllerTagPlug =\n controllerTagNode.findPlug(\"controllerObject\", &stat);\n if (stat != MS::kSuccess)\n continue;\n\n // found controller tag node, now get its source controller\n MPlugArray source;\n bool retval = currControllerTagPlug.connectedTo(\n source,\n true /* asDst */,\n false /* asSrc */,\n &stat)\n if ((retval == false) || (stat != MS::kSuccess))\n continue;\n\n // there should only be one source with the controller tag node\n // as destination\n MObject controllerNode = source[0].node(&stat);\n if (stat != MS::kSuccess)\n continue;\n\n MFnDependencyNode currControllerNode(controllerNode, &stat);\n if (stat != MS::kSuccess)\n continue;\n\n for (unsigned int j = 0; j < 6; j++)\n {\n MPlug currPlug = currControllerNode.findPlug(values[j], &stat);\n if (stat == MS::kSuccess)\n fControllerPlugs.append(currPlug);\n else\n std::cerr\n << \"NO PLUG: \"\n << currControllerNode.name().asChar()\n << \".\"\n << values[j]\n << std::endl;\n }\n }\n}\n
Later, during preEvaluate
, which is called per-frame, a hash value is calculated based on the plug values of the current frame.
void simpleEvaluator::preEvaluate(const MEvaluationGraph* graph)\n{\n buildHashValue();\n}\n\nvoid simpleEvaluator::buildHashValue()\n{\n unsigned int length = fControllerPlugs.length();\n MStatus stat = MS::kSuccess;\n\n for (unsigned int i = 0; i < length; i++)\n {\n float value = 0;\n stat = fControllerPlugs[i].getValue(value);\n\n if (stat == MS::kSuccess)\n {\n boost::hash_combine(fCurrentHashValue, value);\n }\n else\n {\n std::cerr\n << \"NO VALUE: \"\n << fControllerPlugs[i].name().asChar()\n << std::endl;\n }\n }\n}\n
This value is compared with the previous frame\u2019s hash in clusterEvaluate
. If the hash is different, the evaluation proceeds, otherwise we do nothing.
void simpleEvaluator::clusterEvaluate(\n const MCustomEvaluatorClusterNode* cluster\n )\n{\n if (fOldHashValue != fCurrentHashValue)\n cluster->evaluate();\n}\n
To make sure the hash value is up-to-date, the hash value is stored in postEvaluate
.
void simpleEvaluator::postEvaluate(const MEvaluationGraph* graph)\n{\n fOldHashValue = fCurrentHashValue;\n fCurrentHashValue = 0;\n}\n
Finally, when the graph topology becomes invalid, we call clusterTerminate
to clear the cached list of plugs.
void simpleEvaluator::clusterTerminate(\n const MCustomEvaluatorClusterNode* cluster\n )\n{\n if (fControllerPlugs.length() > 0)\n fControllerPlugs.clear();\n}\n
Since simpleEvaluator
claims control over the entire graph, markIfSupported
returns true for all nodes. Additionally, nothing special is done to alter the cluster\u2019s scheduling behavior.
bool simpleEvaluator::markIfSupported(const MEvaluationNode* node)\n{\n return true;\n}\n\nMCustomEvaluatorClusterNode::SchedulingType\nsimpleEvaluator::schedulingType(const MCustomEvaluatorClusterNode* cluster)\n{\n return cluster->schedulingType();\n}\n
See the provided simpleEvaluator devkit example for more details and complete source code.
"},{"location":"parallel/#vp2-integration","title":"VP2 Integration","text":"Evaluation Manager Parallel Evaluation executes the Dependency Graph in parallel. Internally, Maya nodes begin preparing render data for VP2 immediately after a node is evaluated, and before the rest of the graph has finished evaluation. This is exposed to users as Evaluation Manager Parallel Update in the MPxGeometryOverride API (this feature may also be referred to as \u201cDirect Update\u201d). Supporting Evaluation Manager Parallel Update can significantly reduce time spent in Vp2BuildRenderLists and improve overall scene performance.
The following profiler images were created from the same scene (100 footPrintNode_GeometryOverride nodes with animated \u201csize\u201d attributes). In the first image Evaluation Manager Parallel Update is not enabled, and a large amount of time is spent serially preparing draw data for each footPrint node in Vp2BuildRenderLists.
In the second image the footPrintNode_GeometryOverride has been modified to support Evaluation Manager Parallel Update. You can see that the long serial execution time in Vp2BuildRenderLists has been eliminated. All the data marshalling for VP2 is occurring in parallel while the Evaluation Manager is evaluating the Dependency Graph.
The footPrintNode_GeometryOverride example plug-in provides a detailed example for you to create an efficient MPxGeometryOverride plugin which supports Evaluation Manager Parallel Update and gives excellent performance in VP2.
Supporting Evaluation Manager Direct Update adds some restrictions to which operations can safely be performed from MPxGeometryOverride function calls. All MPxGeometryOverride functions (except cleanUp() and the destructor) may be called from a worker thread in parallel with other Maya execution. These methods must all be thread safe. An MPxGeometryOverride object is guaranteed to have at most one of its member functions called at a time. If two different MPxGeometryOverride objects \u201cA\u201d and \u201cB\u201d both require updating, then any member function on \u201cA\u201d could be called at the same time as any member function on \u201cB\u201d.
Furthermore, because these methods may be called from a worker thread, direct access to the rendering context is prohibited. MVertexBuffer and MIndexBuffer can still be used, but some of their features are prohibited from use when in Evaluation Manager Parallel Update. Details about which features are safe to use are provided in the documentation for MVertexBuffer and MIndexBuffer.
"},{"location":"parallel/#tracking-topology","title":"Tracking Topology","text":"Evaluation Manager Parallel Update currently has the limitation that it can only be used on geometries that do not have animated topology. The status of whether topology is animated or not needs to be tracked from the geometry\u2019s origin to its display shape.
If the nodes in the graph are built-in nodes, Maya can know if an animated input will affect the output geometry topology. Similarly, deformers (even custom ones derived from MPxDeformerNode), are assumed to simply deform their input in their output, keeping the same topology.
However, more generic nodes can also generate geometries. When a custom node is a MPxNode, Maya cannot know whether an output geometry has animated topology. It therefore assumes the worst and treats the topology as animated. While this approach is the safest, it can prevent optimizations such as Evaluation Manager Parallel Update.
As of Maya 2019, a new API has been added to inform Maya about attributes that might not affect the topology of an output geometry.
Using this new API helps Maya to know that it is safe to use Evaluation Manager Parallel Update and benefit from its performance boost in more situations.
"},{"location":"parallel/#profiling-plug-ins","title":"Profiling Plug-ins","text":"To visualize how long custom plug-ins take in the new profiling tools (see Profiling Your Scene) you will need to instrument your code. Maya provides C++, Python, and MEL interfaces for you to do this. Refer to the Profiling using MEL or Python or the API technical docs for more details.
"},{"location":"parallel/#profiling-your-scene","title":"Profiling Your Scene","text":"In the past, it could be challenging to understand where Maya was spending time. To remove the guess-work out of performance diagnosis, Maya includes a new integrated profiler that lets you see exactly how long different tasks are taking.
Open the Profiler by selecting:
Once the Profiler window is visible:
Tip
By default, the Profiler allocates a 20MB buffer to store results. The record buffer can be expanded in the UI or by using the profiler -b value;
command, where value is the desired size in MB. You may need this for more complex scenes.
The Profiler includes information for all instrumented code, including playback, manipulation, authoring tasks, and UI/Qt events. When profiling your scene, make sure to capture several frames of data to ensure gathered results are representative of scene bottlenecks.
The Profiler supports several views depending on the task you wish to perform. The default Category View, shown below, classifies events by type (e.g., dirty, VP1, VP2, Evaluation, etc). The Thread and CPU views show how function chains are subdivided amongst available compute resources. Currently the Profiler does not support visualization of GPU-based activity.
![][image1.jpg]
"},{"location":"parallel/#understanding-your-profile","title":"Understanding Your Profile","text":"Now that you have a general sense of what the Profiler tool does, let\u2019s discuss key phases involved in computing results for your scene and how these are displayed. By understanding why scenes are slow, you can target scene optimizations.
Every time Maya updates a frame, it must compute and draw the elements in your scene. Hence, computation can be split into one of two main categories:
When the main bottleneck in your scene is evaluation, we say the scene is evaluation-bound. When the main bottleneck in your scene is rendering, we say the scene is render-bound.
"},{"location":"parallel/#profiler-colors","title":"Profiler Colors","text":"Each event recorded by the profiler has an associated color. Each color represents a different type of event. By understanding event colors you can quickly interpret profiler results. Some colors are re-used and so have different meanings in different categories.
We can\u2019t see every different type of event in a single profile, because some events like Dirty Propagation only occur with Evaluation Manager off, and other events like GPU Override CPU usage only occur with Evaluation Manager on. In the following example profiles we will show DG Evaluation, Evaluation Manager Parallel Evaluation, GPU Override Evaluation, Evaluation Cached Evaluation and VP2 Cached Evaluation. Through these examples we\u2019ll see how to interpret a profile based on graph colors and categories, and we\u2019ll learn how each performance optimization in Maya can impact a scene\u2019s performance. The following example profiles are all generated from the same simple FK character playing back.
"},{"location":"parallel/#dg-evaluation","title":"DG Evaluation","text":"In this profile of DG Evaluation we can see several types of event.
A significant fraction of each frame is spent on Dirty Propagation, a problem which is alleviated by Evaluation Manager.
"},{"location":"parallel/#em-parallel-evaluation","title":"EM Parallel Evaluation","text":"In this profile of EM Parallel Evaluation we can see all the purple and pink dirty propagation is gone.
In this profile we see much less time spent on Vp2SceneRender (4). This occurs because time spent reading data from dependency nodes has been moved from rendering to EM Parallel Evaluation (1). DG evaluation uses a data pull model, while EM Evaluation uses a data push model. Additionally, some geometry translation (2), is also moved from rendering to evaluation. We call geometry translation during evaluation \u201cVP2 Direct Update\u201d. A significant portion of each frame is spent deforming and translating the geometry data, a problem which is alleviated by GPU Override.
"},{"location":"parallel/#em-parallel-evaluation-with-gpu-override","title":"EM Parallel Evaluation with GPU Override","text":"In this profile of EM Parallel Evaluation we can see one major new difference from the previous profile of EM Parallel Evaluation.
In this profile of EM Evaluation Cached Playback we can see several new types of event.
When the main bottleneck in your scene is evaluation, we say the scene is evaluation-bound. There are several different problems that may lead to evaluation-bound performance.
Lock Contention. When many threads try to access a shared resource you may experience Lock Contention, due to lock management overhead. One clue that this may be happening is that evaluation takes roughly the same duration regardless of which evaluation mode you use. This occurs since threads cannot proceed until other threads are finished using the shared resource.
Here the Profiler shows many separate identical tasks that start at nearly the same time on different threads, each finishing at different times. This type of profile offers a clue that there might be some shared resource that many threads need to access simultaneously.
Below is another image showing a similar problem.
In this case, since several threads were executing Python code, they all had to wait for the Global Interpreter Lock (GIL) to become available. Bottlenecks and performance loses caused by contention issues may be more noticeable when there is a high concurrency level, such as when your computer has many cores.
If you encounter contention issues, try to fix the code in question. For the above example, changing node scheduling converted the above profile to the following one, providing a nice performance gain. For this reason, Python plug-ins are scheduled as Globally Serial by default. As a result, they will be scheduled one after the other and will not block multiple threads waiting for the GIL to become available.
Clusters. As mentioned earlier, if the EG contains node-level circular dependencies, those nodes will be grouped into a cluster which represents a single unit of work to be scheduled serially. Although multiple clusters may be evaluated at the same time, large clusters limit the amount of work that can be performed simultaneously. Clusters can be identified in the Profiler as bars wiip.opaqueTaskEvaluation label, shown below.
If your scene contains clusters, analyze your rig\u2019s structure to understand why circularities exist. Ideally, you should strive to remove coupling between parts of your rig, so rig sections (e.g., head, body, etc.) can be evaluated independently.
Tip
When troubleshooting scene performance issues, you can temporarily disable costly nodes using the per-node frozen
attribute. This removes specific nodes from the EG. Although the result you see will change, it is a simple way to check that you have found the bottleneck for your scene.
When the main bottleneck in your scene is rendering, we say the scene is render-bound. The following is an illustration of a sample result from the Maya Profiler, zoomed to a single frame measured from a large scene with many animated meshes. Because of the number of objects, different materials, and the amount of geometry, this scene is very costly to render.
![][image6.jpeg]
The attached profile has four main areas:
In this scene, a substantial number of meshes are being evaluated with GPU Override and some profiler blocks appear differently from what they would otherwise.
Evaluation. Area A depicts the time spent computing the state of the Maya scene. In this case, the scene is moderately well-parallelized. The blocks in shades of orange and green represent the software evaluation of DG nodes. The blocks in yellow are the tasks that initiate mesh evaluation via GPU Override. Mesh evaluation on the GPU starts with these yellow blocks and continues concurrently with the other work on the CPU.
An example of a parallel bottleneck in the scene evaluation appears in the gap in the center of the evaluation section. The large group of GPU Override blocks on the right depend on a single portion of the scene and must wait until that is complete.
Area A2 (above area A), depicts blue task blocks that show the work that VP2 does in parallel to the scene evaluation. In this scene, most of the mesh work is handled by GPU Override so it is mostly empty. When evaluating software meshes, this section shows the preparation of geometry buffers for rendering.
GPUOverridePostEval. Area B is where GPU Override finalizes some of its work. The amount of time spent in this block varies with different GPU and driver combinations. At some point there will be a wait for the GPU to complete its evaluation if it is heavily loaded. This time may appear here or it may show as additional time spent in the Vp2BuildRenderLists section.
Vp2BuildRenderLists. Area C. Once the scene has been evaluated, VP2 builds the list of objects to render. Time in this section is typically proportional to the number of objects in the scene.
Vp2PrepareToUpdate. Area C2, very small in this profile. VP2 maintains an internal copy of the world and uses it to determine what to draw in the viewport. When it is time to render the scene, we must ensure that the objects in the VP2 database have been modified to reflect changes in the Maya scene. For example, objects may have become visible or hidden, their position or their topology may have changed, and so on. This is done by VP2 Vp2PrepareToUpdate.
Vp2PrepareToUpdate is slow when there are shape topology, material, or object visibility changes. In this example, Vp2PrepareToUpdate is almost invisible since the scene objects require little extra processing.
Vp2ParallelEvaluationTask is another profiler block that can appear in this area. If time is spent here, then some object evaluation has been deferred from the main evaluation section of the Evaluation Manager (area A) to be evaluated later. Evaluation in this section uses traditional DG evaluation.
Common cases for which Vp2BuildRenderLists or Vp2PrepareToUpdate can be slow during Parallel Evaluation are:
Vp2Draw3dBeautyPass. Area D. Once all data has been prepared, it is time to render the scene. This is where the actual OpenGL or DirectX rendering occurs. This area is broken into subsections depending on viewport effects such as depth peeling, transparency mode, and screen space anti-aliasing.
Vp2Draw3dBeautyPass can be slow if your scene:
Other Considerations. Although the key phases described above apply to all scenes, your scene may have different performance characteristics.
For static scenes with limited animation, or for non-deforming animated objects, consolidation is used to improve performance. Consolidation groups objects that share the same material. This reduces time spent in both Vp2BuildRenderLists and Vp2Draw3dBeatyPass, since there are fewer objects to render.
"},{"location":"parallel/#saving-and-restoring-profiles","title":"Saving and Restoring Profiles","text":"Profile data can be saved at any time for later analysis using the Edit -> Save Recording...
or Edit -> Save Recording of Selected Events...
menu items in the Profiler window. Everything is saved as plain string data (see the appendix describing the profiler file format for a description of how it is stored) so that you can load profile data from any scene using the Edit -> Load Recording...
menu item without loading the scene that was profiled.
The purpose of Analysis Mode is to perform more rigorous inspection of your scene to catch evaluation errors. Since Analysis Mode introduces overhead to your scene, only use this during debugging activities; animators should not enable Analysis Mode during their day-to-day work. Note that Analysis Mode is not thread-safe, so it is limited to Serial; you cannot use analysis mode while in Parallel evaluation.
The key function of Analysis Mode is to:
Tip
To activate Analysis Mode, use the dbtrace -k evalMgrGraphValid;
MEL command.
Once active, error detection occurs after each evaluation. Missing dependencies are saved to a file in your machine\u2019s temporary folder (e.g., %TEMP%\\_MayaEvaluationGraphValidation.txt
on Windows). The temporary directory on your platform can be determined using the internalVar -utd;
MEL command.
To disable Analysis Mode, type: dbtrace -k evalMgrGraphValid -off;
Let\u2019s assume that your scene contains the following three nodes. Because of the dependencies, the evaluation manager must compute the state of nodes B and C prior to calculating the state of A.
Now let\u2019s assume Analysis Mode returns the following report:
Detected missing dependencies on frame 56\n{\n A.output <-x- B\n A.output <-x- C [cluster]\n}\nDetected missing dependencies on frame 57\n{\n A.output <-x- B\n A.output <-x- C [cluster]\n}\n
The <-x-
symbol indicates the direction of the missing dependency. The [cluster]
term indicates that the node is inside of a cycle cluster, which means that any nodes from the cycles could be responsible for attribute access outside of evaluation order
In the above example, B accesses the output
attribute of A, which is incorrect. These types of dependency do not appear in the Evaluation Graph and could cause a crash when running an evaluation in Parallel mode.
There are multiple reasons that missing dependencies occur, and how you handle them depends on the cause of the problem. If Analysis Mode discovers errors in your scene from bad dependencies due to:
There are two primary methods of displaying the graph execution order.
The simplest is to use the \u2018compute\u2019 trace object to acquire a recording of the computation order. This can only be used in Serial mode, as explained earlier. The goal of compute trace is to compare DG and EM evaluation results and discover any evaluation differences related to a different ordering or missing execution between these two modes.
Keep in mind that there will be many differences between runs since the EM executes the graph from the roots forward, whereas the DG uses values from the leaves. For example in the simple graph shown earlier, the EM guarantees that B and C will be evaluated before A, but provides no information about the relative ordering of B and C. However in the DG, A pulls on the inputs from B and C in a consistent order dictated by the implementation of node A. The EM could show either \"B, C, A\" or \"C, B, A\" as their evaluation order and although both might be valid, the user must decide if they are equivalent or not. This ordering of information can be even more useful when debugging issues in cycle computation since in both modes a pull evaluation occurs, which will make the ordering more consistent.
"},{"location":"parallel/#the-evaluation-toolkit","title":"The Evaluation Toolkit","text":"A set of debugging tools used to be shipped as a special shelf in Maya Bonus Tools, but they are now built-in within Maya. The Evaluation Toolkit provides features to query and analyze your scene and to activate / deactivate various modes. See the accompanying Evaluation Toolkit documentation for a complete list of all helper features.
"},{"location":"parallel/#known-limitations","title":"Known Limitations","text":"This section lists known limitations for the new evaluation system.
The profiler stores its recording data in human-readable strings. The format is versioned so that older format files can still be read into newer versions of Maya (though not necessarily vice-versa).
This is a description of the version 1 format.
First, a content example:
1 #File Version, # of events, # of CPUs\n2 2\\t12345\\t8\n3 Main\\tDirty\n4 #Comment mapping---------\n5* @27 = MainMayaEvaluation\n6 #End comment mapping---------\n7 #Event time, Comment, Extra comment, Category id, Duration, \\\n Thread Duration, Thread id, Cpu id, Color id\n8* 1234567\\t@12\\t@0\\t2\\t12345\\t11123\\t36\\t1\\t14\n9 #Begin Event Tag Mapping---------\n10 #Event ID, Event Tag\n11* 123\\tTaggy McTagface\n12 #End Event Tag Mapping---------\n13 #Begin Event Tag Color Mapping---------\n14 #Tag Label, Tag Color\n15* Taggy\\tMcTagface\\t200\\t200\\t13\n16 #End Event Tag Color Mapping---------\nEOF\n
The following table describes the file format structure by referring to the previous content:
Line(s)
Description
1
A header line with general file information names
2
A tab-separated line containing the header information
3
A tab-separated line containing the list of categories used by the events (category ID is the index of the category in the list)
4
A header indicating the start of comment mapping (a mapping from an ID to the string it represents)
5*
Zero or more lines lines mapping a number onto a string in the form @LINE = STRING
. The IDs do not correspond to anything outside of the file.
6
A footer indicating the end of comment mapping
7
A header indicating the start of event information. The names are the titles of the event columns.
8*
Zero or more tab-separated lines mapping to all of the events that were stored in the file
9
A header indicating the start of the event tag maps
10
A title line showing what values are in the event tag map columns
11*
Zero or more tab-separated lines attaching an event tag, defined through the profiler tool, to a specific event ID. The event ID will correspond to the ID given to it in the comment mapping section.
12
A footer indicating the end of the event tag maps
13
A header indicating the start of the event tag color maps
14
A title line showing what values are in the event tag color map columns
15*
Zero or more tab-separated lines mapping a tag label defined above to an R,G,B color
16
A header indicating the end of the event tag color maps
EOF
Sample version 2 file on 4 CPUs containing a single event of type \u201cETName\u201d, description \u201cETDescription\u201d, in category \u201cETCategory\u201d with description \u201cCategory description\u201d, using color 7, of duration 100 ticks, starting at tick 999, on a single thread with ID 22, tagged with \u201cTagMe\u201d which has color red (255 0 0)
#File Version, # of events, # of CPUs\n2 1 4\nETCategory\nCategory description\n#Comment mapping---------\n@0 = ETName\n#End comment mapping---------\n999 @0 @0 1 100 100 22 1 7\n#Begin comment description mapping---------\n@1 = ETDescription\n#End comment description mapping---------\n#Begin Event Tag Mapping---------\n#Event ID, Event Tag\n1 TagMe\n#End Event Tag Mapping---------\n#Begin Event Tag Color Mapping---------\n#Tag Label, Tag Color\nTagMe 255 0 0\n#End Event Tag Color Mapping---------\n
"},{"location":"parallel/#debugging-commands","title":"Debugging Commands","text":"Several commands can be used to help display information about your scene to help in debugging or optimizations. This is a summary of some of the more common ones, and represents only the available runtime information. Consult the command documentation in Maya\u2019s online technical documentation for more information about each command.
"},{"location":"parallel/#dbcount","title":"dbcount","text":"Maintains embedded code location counters for higher-level debugging of scene operation. Generally, this uses specialized code that is only available in custom builds.
Synopsis: dbcount [flags]\nFlags:\n -e -enabled on|off\n -f -file String\n -k -keyword String\n -l -list \n -md -maxdepth UnsignedInt\n -q -quick \n -r -reset \n -s -spreadsheet\n\nCommand Type: Command\n
"},{"location":"parallel/#dbmessage","title":"dbmessage","text":"Monitors messaging that adds and removes DAG and DG nodes.
Synopsis: dbmessage [flags]\nFlags:\n -f -file String\n -l -list \n -m -monitor on|off\n -t -type String\n\nCommand Type: Command\n
"},{"location":"parallel/#dbtrace","title":"dbtrace","text":"Turns on conditional code, typically to print out status information or to take different code paths when enabled.
To find available trace objects use dbtrace \u2013q to list currently-enabled traces, and dbtrace \u2013q \u2013off to list currently-disabled traces.
To find the current trace output target, use dbtrace -q -k keyword -o.
See below for information on specific keywords.
Note: Work is currently in progress to make these trace objects more flexible. It is a current design constraint that sometimes they are visible in a release, even though they only function internally, and some cannot be used when using Parallel evaluation.
Synopsis: dbtrace [flags]\nFlags:\n -q -query\n -f -filter String\n -i \u2013info\n -k -keyword String (multi-use)\n (Query Arg Optional)\n -m -mark \n -o -output String\n -off - \n -t -title String\n -tm -timed on|off\n -v -verbose\n\nCommand Type: Command\n
Keyword
Description
Contents (Default Output File)
OGSPolyGhosts
Shows progress of data extraction from the evaluation of poly ghosts through OGS
(stdout)
cacheConfig
Shows cache configuration rules evaluation
Result of cache configuration rules for each evaluation node (_Trace_CacheConfig.txt)
cipEM
Shows what Customer Improvement Program data is being collected.
Generic usage information. No longer being used (stdout)
cmdTracking
Enables the tracking of counts of commands. Use the dbpeek \u2018cmdTracking\u2019 operation to view the results.
No output, but enables tracking of the counts for all commands being executed. (For example, you can turn it on during file load to get a count of the number of createNode calls, including those in referenced files, a task that is difficult to do manually) (stdout)
compute
High level trace of the compute path
Nested output showing compute methods being called. Typically in EM mode you should see nesting only in cycles. DG mode will show the full set of nodes triggered by a single evaluation request (_Trace_Compute.txt)
dbCache
Data block manipulation
Details of the creation and manipulation of datablock information (_Trace_DataBlockCache.txt)
deformerEvaluator
Statistics for the deformer evaluator setup
Shows statistics on what the deformer evaluator was able to ingest, once enabled (stderr)
evalMgr
Evaluation manager interactions
(_Trace_EvalManager.txt)
evalMgrGraphInvalid
Evaluation manager graph invalidation
(stdout)
evalMgrGraphValid
Evaluation manager execution graph validation errors and warnings
Nodes that were evaluated while in EMS mode using the pull (DG) model. This indicates missing dependencies in the evaluation graph, possibly caused by custom dirty propagation (_MayaEvaluationGraphValidation.txt)
evalMgrSched
Internal use only
(_MayaScheduling.txt)
idleBuild
Operation of the idle build mechanism for the evaluation graph
When the idle build is active, this appears when the idle build is triggered and executed (_Trace_EGBuild.txt)
nodeTracking
Enables tracking of counts of created nodes. Use the dbpeek \u2018nodeTracking\u2019 operation to view results.
(stdout)
peekCache
Shows progress of the dbpeek -op cache operation
Dumps data collected by the dbpeek operation, and how (_Trace_DbPeekCache.txt)
peekContext
Shows progress of the dbpeek -op context operation
Dumps data collected by the dbpeek operation, and how (stdout)
peekData
Shows progress of the dbpeek -op data operation
Dumps data collected by the dbpeek operation, and how (_Trace_DbPeekData.txt)
peekMesh
Shows progress of the dbpeek -op mesh operation
Dumps data collected by the dbpeek operation, and with what flags (_Trace_DbPeekMesh.txt)
"},{"location":"parallel/#dgdebug","title":"dgdebug","text":"Historical debugging command; not robust or documented. Deprecated: Use the newer dbpeek command.
No help is provided for this command.\n
"},{"location":"parallel/#dgdirty","title":"dgdirty","text":"Forces dirty/clean states onto specified plugs and everything downstream from them. Meant to be a safety net for restoring proper states to your scene when something has gone wrong.
You should not need to use this command, but it will continue to exist as a \u201creset button\u201d, just in case.
Synopsis: dgdirty [flags] [String...]\nFlags:\n -q -query\n -a -allPlugs \n -c -clean \n -i -implicit \n -l -list String\n -p -propagation\n -st -showTiming \n -v -verbose\n\nCommand Type: Command\n
"},{"location":"parallel/#dgeval","title":"dgeval","text":"Forces the node to compute certain plugs. Like dgdirty, this command is meant to be a safety net if computation has not occurred in the proper order. Similar in function to the getAttr command, but since it returns no results, it can handle all attribute types, not only those supported by getAttr.
Synopsis: dgeval [flags] String...\nFlags:\n -src - \n -v -verbose\n\nCommand Type: Command\n
"},{"location":"parallel/#dginfo","title":"dgInfo","text":"Dumps information about the current state of the graph. Be aware that when plug dirty states are reported, they represent the connection associated with the plug. In fan-out or in-out connections there will be more than one dirty state associated with the connection attached to the plug. This means it is legal to see A->B as dirty but B->A as clean if A has multiple connections. Being Deprecated: Use the newer dbpeek command.
Synopsis: dgInfo [flags] [String...]\nFlags:\n -all -allNodes \n -c -connections \n -d -dirty on|off\n -n -nodes \n -nd -nonDeletable\n -nt -type String\n -of -outputFile String\n -p -propagation on|off\n -s -short \n -sub -subgraph \n -sz -size\n\nCommand Type: Command\n
"},{"location":"parallel/#dgmodified","title":"dgmodified","text":"Checks on the reason a file requests saving when no changes have been made.
Synopsis: dgmodified\n\nNo Flags.\n
"},{"location":"parallel/#dbpeek","title":"dbpeek","text":"This command is called out intentionally, as it combines multiple operations into a single command by use of various operations.
It runs one of several operations that provide a view into the data internals in the scene. This is the most useful and flexible of the debugging commands, and new variations of it are often being introduced. Use dbpeek -q -op to show a list of currently available operations and dbpeek -op X -q to show detailed help for operation X.
See below for information on specific keywords.
Note: The syntax of the argument flag allows for both keyword argument=\u2019key\u2019 and keyword/value argument=\u2019key=value\u2019 forms.
Synopsis: dbpeek [flags] [String...]\nFlags:\n -q -query\n -a -argument String (multi-use) (Query Arg Mandatory)\n -all -allObjects \n -c -count UnsignedInt\n -eg -evaluationGraph\n -of -outputFile String\n -op -operation String (Query Arg Optional)\n\nCommand Type: Command\n
"},{"location":"parallel/#dbpeek-op-attributes","title":"dbpeek -op attributes","text":"Analyzes node or node-type attributes and dumps information about them based on what the selected operation type.
Various arguments to the operation change the content of the output. The essence remains the same; the attributes belong to the node or node type.
Argument
Meaning
detail
Adds all internal details from attributes being dumped, otherwise dumps only the names and structure. The details are output as object members of the attribute, including the children.
nodeType
Dumps all attributes belonging to the selected node(s) types. If nothing is selected, it dumps the attributes for all available node types. This includes all node types up the hierarchy to the base node class.
noDynamic
Skips dynamic attributes in all output.
noExtension
Skips extension attributes in all output.
noStatic
Skips static attributes in all output.
onlyPlugins
Restricts any output to nodes and node types that originate from a plug-in.
type=affects
Dumps attribute structure and affects relationships in the graphical .dot format.
type=detail
Dumps attribute information in .json format. This is the default if no type is specified.
type=validate
Validates flags and structure for consistency and validity.
If no nodes are selected, then this command prints the list of all attributes on all nodes. For example, if you had a node type called reversePoint with a vector input and a vector output.
type=detail would output this JSON data:
{\n \"nodes\" :\n {\n \"reversePoint\" :\n {\n \"staticAttributes\" : [\n { \"pointInput\" : [\n \"pointInputX\",\n \"pointInputY\",\n \"pointInputZ\",\n ]\n },\n { \"pointOutput\" :\n [\n15\"> \"pointOutputX\",\n \"pointOutputY\",\n \"pointOutputZ\",\n ]\n }\n ],\n \"extensionAttributes\" : []\n }\n }\n }\n
type=affects would output this DOT data:
digraph G\n{\n compound=true;\n subgraph cluster_NODENAME\n {\n label=\"Node NODENAME, Type NODETYPE\";\n color=\".7 .0 .0\";\n ia [label=\"ia/inputAttribute\",style=\"rounded\",shape=ellipse];\n oa [label=\"oa/outputAttribute\",style=\"rounded\",shape=rectangle];\n ia -> oa;\n }\n}\n
and type=validate would output this JSON validation summary:
{\n \"Attribute Validation\" :\n {\n \"NODENAME\" :\n {\n \"staticAttributes\" :\n [\n {\n \"Both input and output attributes in compound\" :\n [\n { \"root\" : \"rootAttribute\",\n \"inputs\" : [\"inputChild\"],\n \"outputs\" : [\"outputChild\"],\n }\n ]\n }\n ]\n }\n }\n}\n
"},{"location":"parallel/#dbpeek-op-cache","title":"dbpeek -op cache","text":"This operation is explained in detail in the Debugging section of the Maya Cached Playback whitepaper.
"},{"location":"parallel/#dbpeek-op-cmdtracking","title":"dbpeek -op cmdTracking","text":"By default, when no detail argument is present it shows a list of all commands run since the last reset as well as a count of how many of each type were executed.
Outputs in command/count pair form, one per line, with a tab character separating them.
Argument
Meaning
reset
Set all of the command tracking statistics to zero
"},{"location":"parallel/#dbpeek-op-connections","title":"dbpeek -op connections","text":"By default, when no type argument is present, shows a list of all connections in the DG.
Argument
Meaning
summary
Reduces the output to show only the connection counts on the nodes. It separates by single and multi but no further information is added. Useful for getting basic usage information.
verbose
Shows extra information about every connection, including dirty/propagation states, plug ownership, and type connectivity of the connection. Connections can be single or multi, and be connected either to each other or to plugs.
"},{"location":"parallel/#dbpeek-op-data","title":"dbpeek -op data","text":"Dumps the current contents of a node\u2019s plug data in a standard format. By default the output is in CSV format consisting of 5 columns: NODE PLUG DATA_TYPE CLEAN_STATE DATA_AS_TEXT
Example for a simple integer attribute with a dirty value of 5: MyNode MyPlug Int32 0 5
Argument
Meaning
eval
Evaluates plugs first to guarantee that they are clean. Note: Some plugs are always dirty so there may still be plugs that show a dirty value.
full
Includes plugs with default values in the output.
json
Uses JSON format for the output. The general form is { \"NODE\" : { \"PLUG\" : { \"TYPE\", \"CLEAN\", \"VALUE\" } } }
. For example, a simple numeric attribute with a dirty value of 5 { \"MyNode\" : { \"MyPlug\", \"0\", \"5\" } }
matrix
Includes all plugs with a \u201cmatrix\u201d data type in the output. This does not include generic data that may have a matrix value at runtime, only attributes that are exclusively matrix types.
number
Includes all plugs with any numerical data type in the output. This does not include any generic data that may have numerical value at runtime, only attributes that are exclusively numeric types. It includes all types of numeric values, including linear, angular, time, and unitless values.
state
Includes the current dirty state of the data in the output.
time=TIME
Rather than evaluating at the normal context, evaluates at a context using the given time. This is somewhat equivalent to getAttr -t TIME.
vector
Includes all plugs with a \u201cvector\u201d data type in the output. Does not include generic data that may have a vector value at runtime, only attributes that are exclusively double[3] types.
"},{"location":"parallel/#dbpeek-op-context","title":"dbpeek -op context","text":"Analyzes context evaluation to detect various errors violating the design.
Argument
Meaning
isolationType=animatedAttributes
Filters errors, reporting only those involving animated attributes
isolationType=animatedNodes
Filters errors, reporting only those involving animated nodes
isolationType=staticAndAnimated
Reports all errors
test=isolation
During evaluation, detects when evaluation context is violated causing data to be read or written into a state that belongs to some other evaluation context
test=correctness
Evaluates the scene in the background, comparing evaluation data stored for background and main context; compares traversing evaluation graph visiting nodes only if all upstream nodes generate equivalent data in both the background and the main context
time=TIME
Takes a string value indicating the frame time at which evaluation should be performed.
verbose
Adds extra information to output report. Each test will have its own verbose data. Isolation: Adds callstack information to the report for each detected error. Correctness: Adds attributes which compare failed to compare (due to missing logic)
Sample output for isolation tests:
{\n \"context isolation\": {\n \"frame\": 5.0,\n \"type\": \"animatedNodes\",\n \"verbose\": true,\n \"errors\": [\n {\n \"node\": \"ikHandle1\",\n \"type\": \"ikHandle\",\n \"attribute\": \"ikFkManipulation\",\n \"call stack\": [\n \"METHOD Line NUMBER\",\n \"METHOD Line NUMBER\",\n \"METHOD Line NUMBER\"\n ]\n },\n {\n \"node\": \"shape\",\n \"type\": \"mesh\",\n \"attribute\": \"displaySmoothMesh\",\n \"call stack\": [\n \"METHOD Line NUMBER\",\n \"METHOD Line NUMBER\",\n \"METHOD Line NUMBER\"\n ]\n }\n ],\n \"time out\": true\n }\n}\n
Sample output for correctness tests:
{\n \"context correctness\": {\n \"frame\": 14.0,\n \"verbose\": true,\n \"errors\": [\n {\n \"node\": \"IKSpineCurveShape\",\n \"type\": \"nurbsCurve\",\n \"attributes\": [\n \"worldSpace\"\n ]\n }\n ],\n \"failed to compare\": [\n \"input\",\n \"clusterXforms\",\n \"clusterTransforms\",\n \"target\",\n \"mySpecialAttribute\"\n ],\n \"time out\": true\n }\n}\n
"},{"location":"parallel/#dbpeek-op-edits","title":"dbpeek -op edits","text":"Shows a list of all nodes for which tracking is currently enabled. The \u201ctrack\u201d flag is mandatory.
Argument
Meaning
track
Shows a list of all nodes for which tracking is currently enabled.
"},{"location":"parallel/#dbpeek-op-evalmgr","title":"dbpeek -op evalMgr","text":"Outputs the current state of all of the custom evaluators used by the Evaluation Manager.
Argument
Meaning
custom
Outputs the custom evaluators registered with the evaluation manager.
global
Adds output that is independent of scene contents, for example, node types enabled for the custom evaluators.
local
Adds output that is specific to the scene contents, for example, nodes supported by a custom evaluator.
"},{"location":"parallel/#dbpeek-op-graph","title":"dbpeek -op graph","text":"Gets a list of nodes or connections from either the dependency graph or the underlying evaluation graph.
Argument
Meaning
connections
Dumps the list of all connections in the chosen graph. The sorting order is alphabetical by destination plug name.
dot
Dumps the graph information in .dot format for parsing and display by an external application such as graphViz.
evaluationGraph
Gets the structure information from the evaluation graph, otherwise uses the raw dependency graph. The dbpeek command flag \u201cevaluationGraph\u201d does the same thing.
graph
Dumps the graph state and contents, not including what is dumped by any of the other flags.
nodes
Dumps the list of all nodes in the chosen type of graph, in alphabetical order by full node name.
plugs
For the evaluation graph option, dumps the list of all plugs in its dirty plug list in the evaluation nodes. For the DG option, dumps the list of plugs currently in the plug trees.
scheduling
Dumps the scheduling type used for all nodes in the type of graph in the form NODE = SCHEDULING_TYPE. If a node type is specified, the default scheduling type for nodes of that specific node type is returned in the same format.
verbose
When dumping the scheduling graph in .dot format, adds all of the names of the nodes to the clusters. Otherwise, it is only a count of nodes in each cluster
"},{"location":"parallel/#dbpeek-op-mesh","title":"dbpeek -op mesh","text":"Dumps the current contents of the mesh to a standard format. There are two types of formatting and two levels of detail to present.
Argument
Meaning
eval
Evaluates mesh plugs first to guarantee they are clean. Otherwise the values currently present in the mesh shape are used as-is.
json
Dumps data in JSON format instead of CSV.
verbose
Puts full values for all of the data in the output. Otherwise, only a number count of each type is returned. See the flag descriptions for more information on which data can be requested and what is returned for each type.
vertex
Includes vertex position or vertex count in the output. The short return is a count of vertices in the mesh. The verbose values are a list of vertex number and the {X,Y,Z} positions of the vertex, with W factored in, if appropriate.
For the default level of detail, the default CSV format output will look like this:
NODE_NAME,DATA_TYPE,DATA_COUNT\n
For example, a cube containing 32 vertices would have these lines:
Node,DataType,Count\npCubeShape1,outMesh,32\n
The JSON equivalent format would look like this:
{\n \"pCubeShape1\" : {\n \"outMesh\" : \"32\"\n }\n}\n
If the full detail is requested, then the (abbreviated) output for CSV format will look like this:
Node,Plug,Clean,Value\npCubeShape1,outMesh[0],1,0.0 0.0 0.0\npCubeShape1,outMesh[1],1,0.0 0.5 0.0\n...\npCubeShape1,outMesh[32],1,1.0 1.0 1.0\n
and like this for JSON format:
{\n \"pCubeShape1\" : {\n \"outMesh\" : {\n \"clean\" : 1,\n \"0\" : [0.0, 0.0, 0.0],\n \"1\" : [0.0, 0.5, 0.0],\n \"...\" : \"...\",\n \"32\": [1.0, 1.0, 1.0]\n }\n }\n}\n
"},{"location":"parallel/#dbpeek-op-metadata","title":"dbpeek -op metadata","text":"Shows node metadata. The default operation shows a list of all nodes containing metadata.
Argument
Meaning
summary
Shows a single line per node, with metadata indicating how many channels, streams, and values are present in the metadata.
verbose
Shows a detailed list of all metadata on nodes, including a dump in the debug serialization format for each of the metadata streams.
"},{"location":"parallel/#dbpeek-op-node","title":"dbpeek -op node","text":"Show select debugging information on DG nodes. See also the \u201cplug\u201d and \u201cconnection\u201d operations for display of information specific to those facets of a node. If no arguments are used then the ones marked as [default] will all be enabled, for convenience.
Argument
Meaning
datablock
[default] Shows the values in the datablock(s)
datablockMemory
Shows raw datablock memory. This is independent of the other other datablock flags.
dynamicAttr
Shows dynamic attributes.
evaluationGraph
[default] Includes evaluation graph information on the node
extensionAttr
Shows the extension attributes
node
[default] Shows information specific to individual node types, such internal caches, flags, or special relationships it maintains. All other data shown is common to all node types
plug
[default] Shows the nodes plug information
skipClean
Does not include datablock values that are clean
skipDirty
[default] Does not include the datablock values that are dirty
skipMulti
Does not include the datablock values that are multi (array) attributes
staticAttr
Shows the static attributes
verbose
Shows much more detail where available. This will include things such as flags set on objects, full detail on heavy data, and any extra detail specific to a node type, such as caches.
"},{"location":"parallel/#dbpeek-op-nodes","title":"dbpeek -op nodes","text":"By default, when no detail argument is present, shows a list of all currently registered node types.
Argument
Meaning
binary
Also includes the IFF tag used to identify each node type in the \u201c.mb\u201d file format
"},{"location":"parallel/#dbpeek-op-nodetracking","title":"dbpeek -op nodeTracking","text":"By default, when no argument is present, shows a list of all nodes created since the last reset along with a count of how many of each type were created. Output is in the form of nodeType/count pairs, one per line, with a tab character separating them.
Argument
Meaning
reset
Erases all of the node tracking statistics.
"},{"location":"parallel/#dbpeek-op-plugs","title":"dbpeek -op plugs","text":"Shows information about all of the plugs in a scene. By default, when no argument is present, shows static plug footprint. A lot of this is only displayed in specially-instrumented builds, and generally only of use internally.
Argument
Meaning
details
Includes the full plug/node name information in the output. Otherwise only the total and summary counts are dumped.
group=stat
Groups all output by statistic name
group=node
Groups all output by node name
mode=footprint
Reports size information for currently-existing networked plugs.
mode=usage
Reports dynamic code path statistics, if they have been enabled in the current build
mode=reset
When used in conjunction with \u201cusage\u201d, resets the statistics back to zero.
mode=state
Gets unevaluated state information for boolean plugs. Only available on specially-built cuts.
nodeType=TYPE
Restricts the operation to the node types specified in the argument. This includes inherited types, for example if the value is \u201ctransform\u201d, then the operation also applies to \u201cjoint\u201d nodes, as the node type \u201cjoint\u201d inherits from the node type \u201ctransform\u201d. See the node type documentation or the nodeType command for complete information on which node types inherit from each other.
stat=STAT
If this argument has no STAT, then sorts by the name of the statistic. If this argument does have a STAT, for example, \u201cstat=addToNet\u201d, then only reports that statistic. Only available on specially-built cuts.
"},{"location":"parallel/#revisions","title":"Revisions","text":""},{"location":"parallel/#2020","title":"2020","text":"Every object in the real world can move along 6 different axes, or 6 \"degrees of freedom\".
A constraint limits one or more of these axes.
In Maya, the most typical form of constraint is locking a channel. This prevents this axis from changing.
LOCKED
, meaning it may not move along this axisFREE
, meaning it may freely move along this axisLIMITED
, meaning it may move within the limited range of this axisLimits above 0 are referred to as \"soft\", because their amount of influence can be tuned using the Stiffness
and Damping
attributes. These can safely flex and can approach that of a hard constraint given enough stiffness and damping, but would struggle to reach a given target 100%.
Limits below 0, typically -1, are referred to as \"hard\", because their influence is infinite. These should never flex, as even the slightest amount of flex means the constraint has broken. Leaving the solver in a poor state, struggling to keep up.
"},{"location":"quick-tail-setup/","title":"Quick tail setup","text":"In this tutorial you'll learn how to setup a tail with physics and how to steer the look and feel of the simulation using normal keyframing techniques. We'll use one of the excellent rigs by Truong CG Artist.
Optional example files
Let's start with a walkcycle, and move towards interacting with the environment.
"},{"location":"quick-tail-setup/#apply-simulation","title":"Apply Simulation","text":"Select the hip followed by each tail control along the tail in order, and click Create Dynamic Control.
"},{"location":"quick-tail-setup/#reduce-gravity","title":"Reduce Gravity","text":"This particular rig is very small, about 1.6 cm tall, so we need to reduce the default Gravity to reflect this.
"},{"location":"quick-tail-setup/#global-strength","title":"Global Strength","text":"The first selected Dynamic Control contains a Guide Multiplier to influence the strength on all of the tail controls at the same time.
"},{"location":"quick-tail-setup/#local-strength","title":"Local Strength","text":"You can also adjust the strength values individually for each joints, to taper their stiffness along the length of the tail.
"},{"location":"quick-tail-setup/#strength-falloff","title":"Strength Falloff","text":"Let's taper the strength along the length of the tail.
"},{"location":"quick-tail-setup/#result","title":"Result","text":"Let's see how it looks.
"},{"location":"quick-tail-setup/#sitting-down","title":"Sitting Down","text":"Now let's see how to steer our simulation with regular keyframes.
"},{"location":"quick-tail-setup/#switch-to-animation","title":"Switch to Animation","text":"The simulation will try to follow your keyframe animation. Just switch off the Simulated
attribute on the root control while you're animating, then switch it back on to see how it looks.
You can see the animation input on the left and the resulting simulation on the right. With just 3 keyframed poses we end up with this result. Note that I had to overcompensate my animation poses to fight gravity when the tail swings around.
"},{"location":"quick-tail-setup/#advanced-control","title":"Advanced Control","text":"Gain even more fine-grained control with these advanced topics.
"},{"location":"quick-tail-setup/#flex-and-relax-muscles","title":"Flex and Relax Muscles","text":"By keyframing the root strength multiplier you can flex or relax the muscles in the tail. The higher the value the stiffer it gets and the lower the value the more relaxed it becomes, allowing gravity to drop it to the ground.
"},{"location":"quick-tail-setup/#damping","title":"Damping","text":"Damping controls how fleshy and sluggish your simulation behaves.
Low or zero damping preserves more energy in the system, making a simulation more elastic or rubbery. Creatures and humans tend to look best with moderate to high damping values.
"},{"location":"sdk/","title":"SDK","text":"The Ragdoll SDK is not Object Oriented, it is Data-Oriented in the form of an Entity Component System (ECS).
Concept Is A Description Entityunsigned int
Represents a \"thing\", like a marker, group and solver Component struct
Represents some data, like a name, position and color System for-loop
Represents some operation on said data Stay Tuned
This is where you'll find documentation for Ragdoll Core.
"},{"location":"tutorials/","title":"Tutorials","text":"Learn about Ragdoll from the ground up with these short videos.
This addon is licenced under the MIT licence
Windows & LinuxRagdoll 2024.04.14 awaits. Read about it - Previous versions
Join the community of ragdollers on Discord and/or Discourse.
GitHub Chat Forums "},{"location":"blender/download/#install","title":"Install","text":"Ragdoll for Blender is a bridge between Ragdoll Core and Blender, and ships as a platform independent Addon.
To install the addon, you do what you'd normally do for addons, via the \"Install\" button in Blender's preferences.
Edit > Preferences...
Add-ons
pageInstall..
and select RagdollBlender.zip
you downloaded aboveRagdoll
Next, you'll need Ragdoll Core. Which is the engine that performs the actual physics computations.
When a new version of Ragdoll hits the shelves, here's what you do.
Upon loading the addon, Ragdoll will automatically start the clock on a 1-month trial.
To carry on from your trial, you can purchase a new licence via our website.
You'll receive a serial which you can enter via the bottom item of the Ragdoll menu.
Enter your serial in the bottom text field and press Activate.
Issues?
Let us know if you run into any issues at licencing@ragdolldynamics.com
"},{"location":"blender/download/#using-ragdoll","title":"Using Ragdoll","text":"Once the addon has been enabled, you'll find a few new elements in your Blender UI.
We're working on material explicitly for Blender, until then feel free to enjoy the tutorials for Maya, as the workflow is near identical:
Let us know on our forums, we'll keep updating this page with new releases.
"},{"location":"blender/home/","title":"Blender","text":""},{"location":"blender/home/#ragdoll-in-blender","title":"Ragdoll in Blender","text":"Welcome to Ragdoll in Blender, first released in February of 2024 and with support for versions 3.4 up to 4.0.
"},{"location":"blender/reference/","title":"Reference","text":""},{"location":"blender/reference/#manipulator","title":"Manipulator","text":"With Industry Standard keymapping, the Manipulator has a default interaction model.
With native Blender keymapping, the Middle-mouse button is occupied so instead:
Action Key Translate Ctrl + LMB Scale Ctrl + Shift + LMB Rotate Ctrl + Alt + LMB "},{"location":"blender/reference/#properties","title":"Properties","text":"Ragdoll exposes several properties you can use to tune your simulation, divided into several \"archetypes\". One of which is the physics solver itself, responsible for overall settings like start and end frames and quality parameters such as Substeps
.
Responsible for overall simulation settings and keep track of what to include in the physics world.
Property Description Enabled Whether to simulate or not Export Include this solver when exporting the Ragdoll file to disk Cache Keep simulated frames for the next time you playback your scene Start Time When to start simulating Simulate Every X Frames Enable stop-motion like simulation Substeps Divide every Blender frame into this many \"sub steps\", improves quality at the expense of performance Iterations Try this many times to solve each internal physics constraint Air Density The effect of air, 0 means space and 10 means water Gravity Force applied to all Markers in the solver, to emulate gravity Time Scale Slow motion, or not Scene Scale When your character is not at a realistic e.g. 1.8m height, use this to compensate "},{"location":"blender/reference/#rmarker","title":"rMarker","text":"Tracker for your animation controls, like the red pill in The Matrix. This transmits information about each control to Ragdolll, such that it knows where to go and at which strength.
Property Description Enabled Whether to include this rMarker in the rSolver Export Include this Marker when exporting Behaviour Whether to simulate the control, or treat it as pure animation. The default is to inherit the value from the rGroup Translate Motion Should the control be allowed to translate? Rotate Stiffness The \"strength\" at which to follow the animation control Rotate Damping The \"resistance\" at which to follow the animation control "},{"location":"blender/reference/#rgroup","title":"rGroup","text":"Control the stiffness of multiple markers at once.
Property Description Enabled Whether to include this rMarker in the rSolver Export Include this Group when exporting Self Collide Allow contained Markers to collide with each other Translate Motion Should the controls in this group be allowed to translate? Rotate Stiffness Multiply this value with every Markers contained in the group Rotate Damping Likewise, multiply this value with every Markers contained in the group "},{"location":"blender/reference/#workspace-tool","title":"Workspace Tool","text":"On the left-hand side you'll find the Ragdoll Manipulator
. This is where you can manipulate shapes and limits, along with entering into Live Mode to interactively pose your character and verify thet contacts and limits behave to your liking.
Any new Ragdoll object is automatically added to a Ragdoll
collection.
An advanced course in how to setup a character in Blender with Ragdoll.
Comments
\"Make your own motion reference\"
In this tutorial, we will setup a human-like character for use as reference or constraint target to your rig. You will be able to pose and position this Manikin like you would a real Manikin, and drop it from various heights and onto various obstacles to produce realistic poses as it falls.
Something the animator can import and throw around for reference on how it would look like.
Version 1.0 - Up to date
Written for Ragdoll 2024.02.25
and above.
Estimated Time
You will learn
Where to find help
If you find or run into any issues with this tutorials, here's what you can do.
Follow this tutorial either using our provided Manikin rig, or your own character. It can have any number of limbs.
Download Manikin Download Final Scene "},{"location":"blender/tutorials/manikin/#motivation","title":"Motivation","text":"Why should we even bother simulating a character?
Finding motion reference is one of the most important activities for any animator. And yet I can safely challenge you to find reference for perhaps the most common motion in all blockbuster movies today, something that is either impossible or dangerous for actors or animators alike.
Or how about reference of someone simply falling over, perhaps from heat stroke or staring into the sun.
This is, after all, one of the major reasons for pursuing computer graphics in storytelling rather than real people.
Animators bring life to characters, but of equal challenge is that of lifelessness. Of natural and realistic motion without someone behind the wheel. Be it getting hit or shot, blasted or thrown, animating lifelessness is enough to challenge even the most senior of animators.
As you will find, there is a lot more we can do once our motion reference is in 3D, on our actual character rig within Maya and infinitely customisable. As opposed to some video on the internet.
"},{"location":"blender/tutorials/manikin/#setup","title":"Setup","text":"Open your chosen character rig or download the above Manikin rig to get started.
Play around with the controls to get a feel for what we're working with.
FK or IK
Use FK for this tutorial
This Manikin rig has FK and IK (legs) controls, but we will focus on FK controls for this tutorial to keep things simple.
"},{"location":"blender/tutorials/manikin/#simulation","title":"Simulation","text":"The stage is set, now let's apply physics!
"},{"location":"blender/tutorials/manikin/#torso","title":"Torso","text":"Let's start with the Torso.
hip_ctl
torso_ctl
head_ctl
Assign and Connect
This will produce our first Group
, which is a collection of connected Markers
.
New Concept
Group
The rdGroup
node contains attributes that affect all contained markers. It's where you'd edit the overall look and feel of your character, like how stiff it should be and whether or not body parts should collide with each other.
Each Marker can either inherit or otherwise override these values.
Assignable Objects
These objects can have Markers assigned to them in Blender.
Next we will continue from the torso_ctl
and out into the arms.
torso_ctl
L_clavicle_ctl
L_upperArm_ctl
L_lowerArm_ctl
L_hand_ctl
Assign and Connect
Yes, the order in which you select will determine how the markers are connected.
Your first selection is extra important, as it determines whether to start a new group, like for the hip_ctl
, or to add to an existing group, like the torso_ctl
.
In this case, we would very much like our arm to be connected to the torso.
Can I skip the clavicles?Yes, if you have extra controls - such as twist
or bend
- you can skip these if you don't care to simulate them.
Simply skip over them as you select, from torso_ctl
directly to L_upperarm_ctl
.
Now repeat the above process for the other arm.
"},{"location":"blender/tutorials/manikin/#legs","title":"Legs","text":"Now let's continue down the hips and into the legs.
hip_ctl
L_thigh_ctl
L_knee_ctl
L_foot_ctl
Assign and Connect
That's enough setup, let's drop him!
New Concept
Behaviour
Each Marker has a \"behaviour\", which tells Ragdoll it should interpret the control it has been assigned. Should it fall with gravity? Should it try and match the pose? Should it remain fully animated, even in simulation?
rMarker_Armature_hip_ctl
Behaviour = Simulated
of the MarkerThe default behaviour for Assign and Connect
is to give the first selection - the \"root\" - a Animated
behaviour.
What does Animated mean?
Animated means \"copy the animation into simulation and make no changes to it\"
By instead setting this to Simulated
, then Ragdoll will only use the animation for the starting position and orientation of the simulation.
Inherit
Alternatively, you can set it to Inherit
to have it inherit the value of the rGroup
node that was created for the whole character.
Next let's address the elephant in the room; the shapes. They look awful.
"},{"location":"blender/tutorials/manikin/#volumes","title":"Volumes","text":"The shape of each collider affects your simulation in 2 ways.
The contact point can be important if your character interacts with an environment or another character. Like in this case where the feet are incorrectly colliding with the ground because of a bad shape.
That's not always the case though, sometimes you just want overlapping motion without contacts in which case the shapes won't matter.
They do however also affect their resistance to rotation. Consider this.
Here, we rotate the exact same shapes, the exact same amount in the exact same amount of time. And yet they respond differently.
This shape has vastly different dimensions in the X, Y and Z directions, resulting in a different rotation mass for each one. As a result, the effort required to rotate it in each axis differs too.
In practice, you'll find this for just about any limb on a character, which is typically longer in one axis. For our Manikin, this is especially true for the default clavicle shapes.
Override Rotate Mass
In some cases, you have a shape but want it to act like a different shape. Rotate Mass
is very similar to normal Mass
, except in 3 dimensions. Where the position of an object is affected equal in X, Y and Z directions, rotations have 3 separate masses.
With this in mind, let's tune some shapes.
This brings up the Manipulator interface, where you can manipulate shapes interactively.
Great, now let's turn those hands and feet into boxes.
Translate, Rotate and Scale
Notice I'm using the..
Translate
Rotate
Scale
The help text screen-right will help you remember these.
Greater Value Step
While dragging the value on Manipulator UI panel, you may hold Shift
to increase value changing step.
Symmetry
Also notice the edits are symmetrical; even when they don't start out that way like the feet!
"},{"location":"blender/tutorials/manikin/#recording","title":"Recording","text":"That's all there is for setting up your character rig for simulation! Let's now transfer the simulation back onto the rig.
Record Simulation
Visit our forums and YouTube channel for latest up to date material!
An example of how to setup a character, append it twice to one scene, and merge their solvers for character-to-character interactions.
A few weeks ago, Kojima Productions dropped a first trailer for Death Stranding 2, where they leveraged Ragdoll for a puppet being tossed around.
While we await a breakdown from Kojima, we threw together our own breakdown and tutorial of how it could be made with Blender.
Enjoy :)
Comments
For Blender users but also applicable to Maya. This one is about tweaking existing animation, such as motion capture, with physical parameters to create variations and generally just have fun.
It uses a motion capture clip from Mixamo and applies physics to just one arm at first, followed by the second arm for some different kind of dance moves.
Any questions, feel free to ask here or on YouTube, we'll be on the lookout!
Comments
A continuation of Slap'n'Sass 1 from the other day, this time simulating the entire character rather than just the arms, covering:
Comments
Talk about cmdx and why it's necessary.
"},{"location":"blog/20201215_cmdx/#overview","title":"Overview","text":"Some idea of what cmdx even is.
"},{"location":"blog/20201215_cmdx/#end","title":"End","text":""},{"location":"blog/20201216_high_dpi_and_px/","title":"20201216 high dpi and px","text":""},{"location":"blog/20201216_high_dpi_and_px/#ui-and-resolution-scaling","title":"UI and Resolution Scaling","text":"Read about how Ragdoll implements resolution scaling, to support scalable UIs on modern high-resolution displays.
"},{"location":"blog/20201216_high_dpi_and_px/#tldr","title":"TL;DR","text":"Here's a standalone version of the function I'll be walking you through, requires Maya 2017 (Qt 5) and above (due to QScreen
).
def px(value):\n if not hasattr(px, \"dpi\"):\n any_widget = QtWidgets.QWidget()\n any_widget.setWindowFlags(QtCore.Qt.ToolTip)\n any_widget.show()\n window = any_widget.windowHandle()\n scale = window.screen().logicalDotsPerInch() / 96.0\n px.dpi = scale\n\n return value * px.dpi\n
"},{"location":"blog/20201216_high_dpi_and_px/#what-is-resolution-scaling","title":"What is Resolution Scaling?","text":"Most displays have resolutions beyond the traditional 1080p, which makes text and graphics overly small. To account for this, operating systems have implemented \"resolution scaling\"; which is some factor to scale text and graphics by when drawing it on screen.
Maya added (early and crude) support for resolution scaling in Maya 2016 with a usable and mostly transparent version landing in 2018 and beyond.
Building UIs with Maya's native MEL-based UI tools account for scaling automatically, so you generally don't have to think about it. Unfortunately, for any non-trivial Qt project however you'll need to actively implement and maintain support for it.
Ragdoll does this, and here's how.
"},{"location":"blog/20201216_high_dpi_and_px/#implementation","title":"Implementation","text":"In short, any mention pixels run through a conversion function like this.
# setFixedWidth(50) # Before\nsetFixedWidth(px(50)) # After\n
Where px()
looks something like this.
def px(value):\n return value * 1.5\n
That goes for stylesheets as well.
style = \"\"\"\n QPushButton {\n width: 50px;\n }\n\"\"\"\nstyle = convert_px(style)\nsetStyleSheet(style)\n
Where convert_px()
looks something like..
def convert_px(style):\n lines = []\n for line in style.splitlines();\n if \"px\" in line:\n # Find them and destroy them\n return \"\\n\".join(lines)\n
But where does this magical 1.5
value come from? The value depends on your display scale factor, or more precisely whichever scale factor Maya is currently working with.
On Windows, the scale factor is set under your Display settings and Linux's various display managers have something like it.
You can read this straight from the operating system, but the more cross-platform method would be to lean on Qt. Unfortunately, the Qt documentation for resolution scaling is a good representation of how confusing resolution scaling is amongst UI developers at large.
Because you have (1) an application scale, (2) an operating system scale and (3) a physical monitor scale; each of which combine in non-obvious ways to produce the final pixel coordinate on screen.
What is the difference between \"Physical DPI\" and \"Logical DPI\"? Where does \"Device Pixel Ratio\" come into the picture?
Here's what you need to know.
scale = logicalDpi / 96.0\n
The value you'll end up with is 1.0
for a non-scaled display, such as your everyday 1080p monitor, and 1.5
or 2.0
for greater resolutions. If your OS allows, you could get values inbetween or greater, and although text scales somewhat well to any value, graphics shipped with Ragdoll is scaled at 2.0
which means it'll look best at 1.0
, 1.5
and 2.0
. Anything else will likely introduce blur.
But wait, where does logicalDpi
come from, and what's this magical 96.0
?
Qt can provide that for you, but not without a fight.
window.\n
"},{"location":"blog/20201217_option_dialogs/","title":"20201217 option dialogs","text":"Talk about qargparse and why it's necessary.
"},{"location":"blog/20201218_optionvar/","title":"20201218 optionvar","text":"Maya's native persistent preferences, with support for access from C++.
"},{"location":"blog/20201219_pythonreload/","title":"20201219 pythonreload","text":"Talk about how you iterate in Maya, reloading all modules by namespace and what to look out for. Especially undo. And always having an uninstall.
"},{"location":"blog/20210325_view_to_pixmap/","title":"20210325 view to pixmap","text":"Write about this.
def view_to_pixmap(size=None):\n \"\"\"Render currently active 3D viewport as a QPixmap\"\"\"\n\n # Python 2 backwards compatibility\n try:\n long\n except NameError:\n long = int\n\n image = om.MImage()\n view = omui.M3dView.active3dView()\n view.readColorBuffer(image, True)\n\n # Translate from Maya -> Qt jargon\n image.verticalFlip()\n\n osize = size or QtCore.QSize(512, 256)\n isize = image.getSize()\n buf = ctypes.c_ubyte * isize[0] * isize[1]\n buf = buf.from_address(long(image.pixels()))\n\n qimage = QtGui.QImage(\n buf, isize[0], isize[1], QtGui.QImage.Format_RGB32\n ).rgbSwapped()\n\n return QtGui.QPixmap.fromImage(qimage).scaled(\n osize.width(), osize.height(),\n QtCore.Qt.KeepAspectRatio,\n QtCore.Qt.SmoothTransformation\n )\n\n\ndef pixmap_to_base64(pixmap):\n array = QtCore.QByteArray()\n buffer = QtCore.QBuffer(array)\n\n buffer.open(QtCore.QIODevice.WriteOnly)\n pixmap.save(buffer, \"png\")\n\n return bytes(array.toBase64())\n\n\ndef base64_to_pixmap(base64):\n data = QtCore.QByteArray.fromBase64(base64)\n pixmap = QtGui.QPixmap()\n pixmap.loadFromData(data)\n return pixmap\n
"},{"location":"blog/20210409_littlebits_locatorshotkey/","title":"20210409 littlebits locatorshotkey","text":"Write about the script for toggling locators in the viewport, alongside curves and meshes. A workflow tip. A short one. A \"Little Bits\". :D
"},{"location":"blog/20210420_bugfree/","title":"20210420 bugfree","text":"The bug-free software guarantee.
Requirements:
Always give users a way to circumvent protections and to workaround issues without waiting for a new update (which could be days or weeks).
"},{"location":"blog/20210531_backend/","title":"20210531 backend","text":"The month of May 2021 was spent authoring the frontend and backend of the ragdolldynamics.com website. Let's have a look at what makes it tick.
"},{"location":"blog/20210531_backend/#overview","title":"Overview","text":"Here's life of the website in a nutshell.
That is, we want a user to put the versions and amount of seats for Ragdoll into a \"cart\" and for that \"cart\" to be passed on to Stripe for the transaction to take place. Once Stripe is done, we'll want to generate a serial to go with it.
With a serial in hand, we'd then like to generate a web page specifically for this one purchase. Ideally something the user can revisit later if they forget their key(s).
Because many things can go wrong in these few steps, we need to record each step of the way, including log messages, such that we can debug any such issue.
And that's it. Let's have a look at practicalities.
"},{"location":"blog/20210531_backend/#static-website","title":"Static Website","text":"Because most of the site - namely the landing page and contact page - is static I opted to use the same static site generator I use for https://learn.ragdolldynamics.com. Namely mkdocs.
Unlike the learn domain, this one wouldn't require a theme as we're laying everything out ourselves.
One of the pages need purchase-specific information - namely your serial numbers - so that needs a \"dynamic site generator\", and for that I'll use flask because of my brief excursion many years ago for Pyblish Events.
"},{"location":"blog/20210708_limitations/","title":"20210708 limitations","text":"Document and offer alternatives to these.
On July 28th 2021, animators around the world will finally get something new. Something that isn't just your average incremental workflow improvement, but an entirely new way to animate.
"},{"location":"blog/20210713_july28/#the-past","title":"The Past","text":"30 years ago there was innovation in character animation, much like the innovation we see today - modelers went from box modeling to sculpting, lighting artists nowadays reflect light and simulate the material properties in textures made with simulated wear-and-tear based on natural weather conditions and concept artists generate imagery through machine learning.
But what are animators doing?
That's right! The dopesheet, the graph editor, inverse kinematics, rigs that run at 5 fps. We're still animating like it's 1995!
As a result, every part of the filmmaking process has seen a massively reduced cost, except animation. Animation of today is often the most expensive and time consuming part of the pipeline; and when it isn't it really ought to be because despite accurate models, realistic lighting and pixel perfect textures, motion is what makes a character truly come alive.
"},{"location":"blog/20210713_july28/#the-present","title":"The Present","text":"Ragdoll was made to address this need. The need for more believable characters with less effort. The need for animators to spend time where it matters - on telling story. Here is where and how I expect animators spend their time today in 2021.
Story (10%) Performance (10%) Physics (80%) Message Body language Balance Delivery Timing Contacts Continuity Interactions Force Continuity Momentum PropagationSee that 80%? Let's get rid of that.
"},{"location":"blog/20210713_july28/#the-future","title":"The Future","text":"Mark your calendars, spread the word. Roughly 2 weeks from now we will embark on a journey together to resume innovating. To ensure that 30 years from now we'll look back at today and not recognise a thing.
Best, Marcus Ottosson CEO and Founder Ragdoll Dynamics
"},{"location":"blog/20210727_debugging/","title":"20210727 debugging","text":"Quick sanity check for overlapping shapes and an initial state residing within limits.
Welcome to Ragdoll Dynamics, the real-time physics solver for Maya.
Website Download "},{"location":"blog/20210728_announce_1_0/#july-28th-2021","title":"July 28th 2021","text":"Today marks the launch of Ragdoll Dynamics and you are reading the announcement post for this moment. With Ragdoll, you'll be able to achieve faster and more realistic character animation with less work.
Read on to find out what it's all about.
"},{"location":"blog/20210728_announce_1_0/#background","title":"Background","text":"In 2012 I had an idea for a physics system suitable for animators.
The idea sprung from the mind of a Character Animator landing a job in Creature FX and being exposed to nCloth in Maya. The goal was simple; animate a piece of string in space. But, traditional tools failed us. The desired motion was too subtle and the level of control we had was too fine. Like laying bricks with a tweezer.
So we turned to physics simulation as a means of automating subtlety and focusing on how we wanted the animation to feel and what we wanted it to do, rather than spending time making it look like it belonged in the real world. But now we had the opposite problem; although the results were subtle, they were hard to control. Like playing Jenga with a tractor.
The process was highly technical, very few animators would endure that kind of process. If this was to become accessible to animators, something drastic needed to happen. Something to transform highly technical concepts into creative choices, something that could leverage the computational power of our workstations without overburdening the artist with nonsense.
It is now July 28th 2021 - the birthday of Ragdoll - and we may (finally) begin our journey towards exactly that.
More "},{"location":"blog/20210728_announce_1_0/#what-is-early-access","title":"What is Early Access?","text":"Ragdoll is now in \"Early Access\" for the next 1-3 months.
During this time, we'll round off corners and improve the overall experience - including more tutorials, more documentation and generally being here for you as we both take our first steps into this together. Unlike most new technology, there has never been a physics solver for animators before; everything we do from here on out will be unexplored pastures, ripe with new discoveries.
So, if you're happy to dive into the unknown and learn the old-fashioned-way of trial-and-error, Ragdoll is yours. Alternatively, sit back, relax and watch other people suffer through the growing pains of an early-stage startup for the next 1-3 months.
We'll post updates both here and on LinkedIn during this time.
"},{"location":"blog/20210728_announce_1_0/#early-bird","title":"Early Bird","text":"During these first 1-3 months, there's carrot.
Ragdoll Unlimited is the unrestricted, full version of Ragdoll. The full price of which is \u00a31950 for a floating licence. But because it's early, the price is lowered to the price of Ragdoll Complete - \u00a3499 for a node-locked licence. This will be reflected in the total price during checkout.
Once early access is over - about 1 to 3 months from now - the price will return to normal.
Buy it Try it "},{"location":"blog/20210728_announce_1_0/#immediate-roadmap","title":"Immediate Roadmap","text":"The next 1-3 months will have a singular focus.
That means tutorials, documenation, interface tweaks, bug fixing, performance improvements and everything in between. If you find yourself struggling with something, it's not you, it's Ragdoll. Let us know via chat or forum here and we'll aim for same-day or same-week fixes. That's what Early Access is all about.
Chat Forums "},{"location":"blog/20210728_announce_1_0/#product-tiers","title":"Product Tiers","text":"Ragdoll comes in 5 flavours.
Each flavour is priced differently to enable access to everyone. For non-commercial users - namely anyone wanting to fool around with physics for their personal or student projects at home - there's a special version of Ragdoll. This version is identical to a node-locked version of Ragdoll Unlimited plus having free upgrades forever.
Trial Personal Complete Unlimited Batch Commercial Use \u274c \u274c \u2714\ufe0f \u2714\ufe0f \u2714\ufe0f Interactive Tools \u2714\ufe0f \u2714\ufe0f \u2714\ufe0f \u2714\ufe0f \u274c Python API \u2714\ufe0f \u2714\ufe0f \u274c \u2714\ufe0f \u274c Multi-Threading \u2714\ufe0f \u2714\ufe0f \u274c \u2714\ufe0f \u274c JSON Import/Export \u2714\ufe0f \u2714\ufe0f \u274c \u2714\ufe0f \u274c Per-process Licence \u274c \u274c \u274c \u274c \u2714\ufe0f Perpetual Pricing \u274c \u00a399 \u00a3499 \u00a31299 \u00a3199 Floating Licence \u274c \u274c \u00a3750 \u00a31950 \u00a3250 Monthly Pricing \u274c \u274c \u00a355 \u00a380 \u00a320 Annual Upgrade Plan \u274c \u00a30 \u00a3250 \u00a3650 \u00a399 "},{"location":"blog/20210728_announce_1_0/#next-steps","title":"Next Steps","text":"Ready?
Click here to download and install Ragdoll for Windows and Linux, Maya versions 2018-2022. You'll have a whole month to experiment before having to make up your mind, so go nuts!
Try it Buy it"},{"location":"blog/20210730/","title":"Documentation Writers, Ahoy!","text":"Hey you!
We launched our animation software Ragdoll Dynamics the other day and are on now the lookout for someone to author learning material on either a full-time or part-time basis.
It would involve:
To qualify, you don't need experience with Autodesk Maya although it wouldn't hurt. What you would need however is:
We could compensate you in various ways.
Is this you? Do you know someone?
"},{"location":"blog/20210821/","title":"Maya Developers, ahoy!","text":"Hello!
We've recently launched our animation software Ragdoll Dynamics and are on now the lookout for a motivated Maya Developer, on either a full-time or part-time basis.
"},{"location":"blog/20210821/#about-us","title":"About Us","text":"At the time of this writing, Ragdoll is me - Marcus - doing all things Maya along with handling just about every other aspect of running the business - like marketing, licencing, web development, design, animation, documentation.. too many things! And recently Kostas, doing secret things related to robotics in Maya.
What I'd like to do is hand over my Maya-development role to you. It would involve all manner of challenges, from UI and UX to physics and low-level optimisations to workflow enhancements and tools development. The more you fancy the better.
You will be given a great deal of agency and resonsibility that shape the future of Ragdoll in these early days. How should animators interact with physics? What parts of their workflow can be enhanced or even replaced with physics? These are questions you and I will explore, and the earlier you get involved the greater your influence.
"},{"location":"blog/20210821/#about-you","title":"About You","text":"What I'd like to see from you is examples of your work along with some motivation for wanting to come on this journey. Startup-life is unlike corporate-life in a few key ways, primarily in being able to create and execute your own set of tasks, of not only implement a solution but also understanding the problem and finding a optimal solution to an otherwise muddy and unexplored problem. It also heavily relies on our pace and progress; if you and I don't make it, it's all over! Hah! On the upside it also means that our success is ours alone, and let me tell you that is incredibly rewarding!
To cope with this, you should have some of these.
Bonus Points
If you have experience or interest in one or more of these, you're in.
The Offer
Like the position, the offer is flexible.
\u00a350,000-80,000/year
is fair game.\u00a3300-600/day
is fair game.And that's it! If this tickles your curiosity, feel free to get in touch. We can setup a call and talk things through. Maybe all you do is low-level optimisations in x86 assembly, and none of that fancy-pants UX and Python stuff? Or maybe you've got the fanciest pants in town? As an early part of the Ragdoll Dynamics team there's plenty of space in all manner of pants.
Email Contact FormBest, Marcus
"},{"location":"blog/20220809/","title":"SIGGRAPH 2022 Schedule","text":""},{"location":"blog/20220809/#schedule","title":"Schedule","text":"Here's what we'll be doing at SIGGRAPH 2022!
"},{"location":"blog/20220809/#tuesday-9th-august","title":"Tuesday - 9th August","text":"First day, we'll be ready and waiting at booth 442.
Time # Demo 11:00 Intro with Manikin - I'll walk through the basics of Ragdoll Dynamics, the physics solver for animators working in Autodesk Maya. We'll take a hand-animated Manikin character rig through to completion with physics for secondary motion. 13:00 Dragon Rig Setup - We'll take things to the next level, and turn a production-level Dragon rig into a complete ragdoll, something we can play around with interactively and have almost completely automated via turbulence and wind 14:00 RAGDOLL FOR FIRST TIMERS by Vanessa Rossi - I recently tried out Ragdoll as an animator at DNEG, and wanted to share my experience on the basics of it from an user perspective.1. Ragdoll set up using manikin2. Throwing a ball at Manikin with a walk or run cycle mocap - I'll play around with values of the ball in the channel box, in order to show some of the many different results we can get (and say how you can quickly get a few blocking pass options in minutes)3. Falling from a ladder - I'll do a simple constraint set up, and watch Manikin fall from the ladder with variations depending on when the constraint is released. 15:00 Requests - During each demo, we welcome any requests or questions at which point this is where we'll demonstrate their answer. Come join and make requests in real-time! 16:00 Live Mode - Next generation of rigging and animation, come visit us at 16:00 for the reveal! 18:30 End - The conference is done for the day, see you tomorrow! "},{"location":"blog/20220809/#wednesday-10th-august","title":"Wednesday - 10th August","text":"It's been a whirlwind of a day, and here's the next whirlwind!
Time # Demo 10:00 Hands and Fingers - We'll setup hands and fingers to see how much we can get out of contacts with itself and the environment. 11:00 Self-Walking Manikin - Wouldn't it be nice if your character could walk on its own? Or balance on its own, as the environment moves around? That's what we'll attempt in this demo! 14:00 DNEG - Rafael Cardenas Rivera and Vanessa Rossi is joining us at this time to take you through a fun demo! 15:00 Requests - We'll demo any requests having come in from you, the audience, during this block of time. Feel free to drop by and make requests \"on-air\"! 16:00 Technology Preview - Have a look at what life will be like in Unreal Engine from now on. 18:00 End - The conference is done for the day, one day left, see you tomorrow!! "},{"location":"blog/20220809/#thursday-11th-august","title":"Thursday - 11th August","text":"Final day! Come join and make requests in real-time.
Time # Demo 10:00 Locomotion - We'll share some technical details behind how Locomotion - the automatic walk, run and jump solver - works under the hood, and demonstrate how to use it on a Boston Dynamics-like character. 11:00 DNEG - Rafael Cardenas Rivera and Vanessa Rossi is joining us at this time to take you through a fun demo! 13:00 Requests - An improvised session, showcasing some of the best of what we've seen so far and taking requests from you in the audience in real-time. Any last requests? Come join at this time! 16:00 End - SIGGRAPH is done and dusted, hope you had fun! "},{"location":"blog/20220809/#overview","title":"Overview","text":"We're heading to SIGGRAPH this year!
To everyone who visits, there will be:
We'll be there from 9th to 11th August at:
Vancouver Convention Centre 1055 Canada Place Vancouver, BC, Canada.
Booth 442, here's us!
"},{"location":"blog/20220809/#meet","title":"Meet","text":"Reach out to us if you'd like to arrange a meet and greet, we'd love to meet you.
See you there!
"},{"location":"blog/20231018_building_a_business/","title":"On Building a Business in VFX and Games","text":""},{"location":"blog/20231018_building_a_business/#prelude","title":"Prelude","text":"I want more artists making tools for other artists, so I'll share the answers to what is normally sensitive information with everyone here and on the web in the interest of encouraging that. Let's go!
From a legal standpoint, what [do] the original software vendor (Autodesk / Foundry / SideFX) think about someone selling a plugin that uses their API. Are there any legal issues connected with it?
In short, anything you write is yours and can be distributed freely in any way you choose.
The part about \"using their API\" is interesting; the thing to keep in mind here is that law and licencing mostly applies to distributing other people's code. And by \"using\" their API, you are not distributing their API.
For example:
my_software.py
print(\"Hello World\")\n
Here, I'm \"using\" the Python API to emit messages to the console of anyone running my software. You may argue that I do not own the right to Python's source code and thus cannot distribute this file, but the Python source code is not included in what I distribute. Only my own characters, written on my own keyboard. It is the user, running my_software.py
, who has Python on their machine and who is the one who agreed to whatever licence was involved when installing Python such that they can run my software.
Let's take a look at another example.
my_other_software.py
import maya\nprint(maya)\n
Now I'm \"using\" the Maya Python API. But again, this file contains only characters written on my own keyboard which means I can distribute this freely with absolutely no restrictions. In fact, what does \"maya\" refer to in this case? Is it the Python API of Autodesk Maya, or is it this Python package?
Or maybe this file is part of a Python package you've written, in which there is a maya.py
that my_other_software.py
is calling on. At the end of the day, it cannot be known and doesn't matter. These written characters are mine, I wrote them.
If you only ever distribute code you write, you can stop reading here and live a merry life.
Where licencing does become relevant however, is when you do distribute other people's code. For example, in Ragdoll, we use several open source libraries, like this one.
When it comes to distributing other people's code, there are usually two categories.
Most projects are specific about what you can do with both of these. For example, you are able to freely download and use an LGPL licenced project, but if you distribute it you must also distribute the source code; Qt is a good example, Autodesk has made modifications to it for Maya which is why Autodesk then also distributes it alongside every other project is uses for its software projects.
The prevalent reason for GPL-style licencing is for making additions to a library; the author wants those additions to be free like the original, so as to benefit the project and everyone using it. Other common licence types are MIT and BSD which you may distribute, both in source and compiled form, so long as you include their licence. As a form of credit.
The RapidJSON licence is here, which includes mention of this obligation.
For Ragdoll, we include this with each release of Ragdoll, and looks something like this.
How are you handling taxes as part of your sale? This question may sound silly, but does it require you to open some legal business to handle the tax of selling plugins from your website?
This would depend on country and state but in general whenever you have income, you need to declare it to the government. In the UK, you can have income as an individual, that's called a sole trader - for example:
Whenever you declare income to the government, they will want a slice of that income in the form of taxes, and there comes a point when opening a separate business will yield more money for you and less for them. If you operate a \u00a3100/year business, you are likely better off as a sole trader. The tax you pay will become part of your personal tax declaration (i.e. self assessment). Depending on how much that is, you're looking at roughly 30% of your income to taxes. 30% of \u00a3100 is nothing to lose sleep over, it's the cost of doing business. If you operate a \u00a31mil/year business however, it won't be 30% but 60% and above, and suddenly taxes are no joke. Somewhere between \u00a3100/year and \u00a31mil/year will it become sensible for you to open a separate business - probably around the \u00a310,000 and \u00a3100,000 mark. In the UK that would/should be a \"limited\" company.
A company is like a person. It will earn income just like a person, except taxes are slightly different. A company can earn income and spend it before paying any taxes; in fact most companies spend all of their income for the sole purpose of not having to pay any tax. Any percentage of tax on \u00a30 is still \u00a30. And that's good for the economy as well, it means more money in circulation. For example, if you charge customers \u00a310/licence and you sell 100 licences over the course of a year, your company will have \u00a31,000 in the bank. By the end of the year, the tax man will stop by and ask for 30% in what's called \"corporation tax\". 30% of \u00a31,000 is \u00a3300. The rest you get to keep, the tax man is now done and will return next year to take another 30% of whatever you make that year. If instead you sell 100 licences, get \u00a31,000 and then spend that \u00a31,000 on e.g. a new computer, then the tax man will stop by and find you have \u00a30 in the bank, and promptly leave without asking for any payment. So now you (or your company, rather) have a brand new computer worth \u00a31,000 in your belongings.
And I say \"your company\" because that's important to remember. Again, a company is like a person, and all that you are to your company is a director. A director is like an employee, and like any employee you would have responsibilities towards this company, primarily in doing what is essentially a self-assessment but for the company, called a corporation tax return.
For developers in our field, there are other ways in which to lower that 30% number, such as government grants and paying for your home office through the company and things such as:
Which is one of the many ways in which a limited company is different from being a sole trader, and your main consideration for whether to start one comes down to that yearly revenue figure.
"},{"location":"blog/20231018_building_a_business/#payment-processor","title":"Payment Processor","text":"You can take cash, and you can have people transfer money to you via bank transfer. But for online businesses (and offline, for that matter) card payments are more common and you can't do these yourself. For that, you need some service capable of facilitating the transfer of money from customer to yourself.
For that, we use Stripe.
There's a bunch of options here too, like PayPal and Square. What it comes down to is cost; they all want a slice of your sale. Stripe is rather expensive, but makes up for it in convenience and features. For example, handling subscriptions is no small task.
There are even services that combine the payment processor and licence management; we initially used https://www.sendowl.com but found that (1) their method of bundling licencing and downloads were limiting and (2) their UI for payments is lacking and (3) they are basically a wrapper on-top of Stripe and Stripe has a really nice API so we opted to simply use that directly.
"},{"location":"blog/20231018_building_a_business/#software-licencing-vs-pirates","title":"Software Licencing vs Pirates","text":"How are you handling the licensing of your tools? I mean the piracy part. It is an issue, and running some RLM servers is not an option when discussing some relatively small plugins for Maya.
It's great question with many answers; some subjective others strategical.
For Ragdoll, we use LimeLM by WyDay.
It's based on a DLL file (SO file on Linux) that ships alongside Ragdoll, and this DLL file has already been cracked. Meaning if you get hold of this cracked DLL and replace the file shipped with Ragdoll, Ragdoll will believe you are a legit commercial user.
We're able to spot the when, where and who of this happening on our end and do keep an eye on it in case we need to take action, but so far it's under control.
At the end of the day, we don't use LimeLM to keep pirates out, we do it to keep honest people honest. Not everyone agrees with this approach, and that's okay. I personally believe that if someone wants to use your software illegally, they will. If there isn't a way to do it, they will find a way to do it. I also believe that if someone wants to use your software legally, they will. What they won't do is jump through too many hoops to get there. If using it legally becomes more difficult than using it illegally, you'll turn honest users dishonest because what matters in the end is getting their job done. So, Ragdoll was cracked weeks after the release of 1.0 and we are aware of it (flattered, you might say!). Are we losing sales because of it, probably. Are we gaining sales from keeping licencing simple? Most definitely. So given that you cannot completely eliminate piracy, it becomes a matter of figuring out the balance which I today believe we've found. But again, this is subjective and will vary based on person and product.
"},{"location":"blog/20231018_building_a_business/#was-it-worth-it","title":"Was it Worth it?","text":"Was it beneficial for you? I mean developing and selling those plugins from your website commercially. I mean, understand me correctly, I'm not interested in any numbers - that's out of the question and not my business, I mean overall.
Without numbers, no answer I could give would mean anything to anyone, because whether it is beneficial will depend on your personal goals. Some want wealth, others want freedom.
I've now spent 10 years down this path; from prototyping with nCloth in Maya with my limited skills as an animator to realising it wasn't enough and having taught myself programming and how to run a business and manage a team of developers; if we look at the total figure in 10 years of earning income working for someone else, then I only recently reached the point where I have earned as much via Ragdoll as I would have as an employee.
Which, as you can see from my fancy graph, involves a large up-front cost. In my case, I never had to dip below 0, which many do in the form of taking on investment or loan.
As an aside, let's have a look at some other ways in which this graph can and often do go:
Bad idea, bad execution, or both
You use up all of your savings/investment but never manage to sell any copies.
Not worth it
You manage to sell product, but would have made more money as an employee. This may still be a win, if all you want is freedom and don't care about money.
No savings, no investment
This was me 4 times in a row for 7 years; restarting can be easy (like it was for me) but heavily depends on life circumstances (e.g. kids).
In my case and the first graph, what happens after today is obviously highly optimistic, but you'll need a lot of optimism if you are to run a business.
Moving on, I was earning \u00a340-70k/year as an animator in 2006-2013, which I expect would have increased with those 10 years of experience and perhaps change of role into something more technical, so let's be generous and say on average I would have made \u00a3100k/year and that I worked full-time for 10 years, that's \u00a31,000,000. On average, companies take 5 years to become profitable. As in, 5 years until you've covered the cost of developing the first version and reached plus/minus 0 and can start saving again, so add another couple of years to reach the point you would have been at if you had just taken those initial 5 years and saved money along the way.
I heard this exact thing 10 years ago but never believed it could take this long, and here I am 10 years later repeating it to you.
In my case, I never made \u00a370k in a year, but rather spent 2-4 months each year on freelance earning roughly \u00a320k followed by 8-9 months of living off of that (in London, i.e. very frugally) to try and develop what is today known as Ragdoll. Once cash ran out, rinse and repeat and 7 years later I had developed the first version of Ragdoll.
Early Website
It was a bug-ridden mess with very few features. But, it solved a real problem, for real customers. There is a lot more to say on the topic of how to develop and launch, so feel free to ask if that's interesting. I publicly launched Ragdoll in 2021 and generated \u00a3200k in the first 3 months of trading, far exceeding my expectation and more than covering the cost of development up until that point. Since then revenue has ebbed and flowed; there are a few key players out there more willing to take risks on startups (the early adopters) and once you've crossed that threshold you are left with the realists; the bulk of the market with higher demands and less patience. This is where the real work begins.
Overall I feel the timing was just right; for me personally, given that I get to utilise every skill and experience I've had as an artist and programmer, from modeling to animating for showcase material, to pipeline development and Python tooling, to web design and development for our landing page, to writing documentation via my work in open source (e.g. Pyblish and Allzpark), to managing people as a lead and co-founder in previous companies, to devops and setting up build servers, to making music for announcement trailers, to having enough of a network that I could rather easily find my first set of customers. The timing was right commercially and technically as well; hardware is more than capable of doing what Ragdoll requires in real-time and realism in film and animation is in dire need of tooling; it is simply too expensive and challenging to match the expectations of our audience and to follow the leads of rendering and modeling and texturing, which have gotten so far ahead of where character animation is today. There is a lot more to say on that too, so feel free to ask.
With this in mind, was developing and selling software beneficial to me? I enjoy working with others and not having to think about what to do next; being given a task and executing it to the best of my abilities. I know studios enjoy hiring me, I do a good job. But oh man, it does not compare to having built your own thing and seeing it help others. Putting all of my experience, and lately the experience of my staff, together into single .zip file to be distributed to peers in the industry I know and love; there is nothing more rewarding.
I take it you didn't expect a reply like this, but believe you me; founders are happy to share. I speak to some of them myself on a regular basis (shoutout to JangaFX, Polygonflow and Inbibo!) and reached out to many more before starting Ragdoll, including Ziva and Pixologic (shoutout to James and Ofer!), they love talking about their experiences too. Running a company can be a lonely endeavour; there are far more employees than employers, so you'll naturally find more conversations about being an employee but at the end of the day we're all human.
One of the reasons I chose to get into detail here is because one of the things that bothers me about starting a business is how black box it is. In your case, the legal aspect alone can understandably drive you away from even trying. In others, the financial aspect such as \"do I need investment?\" - which seems really common but does not have to be! - can drive someone away. I also had these questions. For the first year or two of Ragdoll, I stood prepared for the UK government to come crashing through my door due to having forgotten some obligation for running a business - some missed tax payment or missing bit on our website. Or for Autodesk to require I only sell software on their their own app store and demand compensation for not having done so already. And there are still threats out there, things that can cripple any business in an instant for things not already done in the past - especially for things related to law which is why your questions are so important.
It is necessary to read licence agreements, like the MIT and GPL walls of text, and the Autodesk EULA when developing for Autodesk software. Some of those texts are trivial and clearly a non-issue, others will be challenging to understand which is when you do need an accountant and/or lawyer. But these people are out there for you, so when that time comes it really is as simple as reaching out to ask. It is unlikely you will need any of that before you generate any revenue, and by the time you do you also have money to spend which turns it not into a question of \"can I afford it\" but rather \"how much more will I earn by having an accountant? By hiring this lawyer for a couple of hours?\". When everything you spend can and often does make you more money, that's when you know you've got a successful business. At the end of they day, nobody is expected to know everything; mistakes can and will be made. Even law is built around this, because law is built around us being human. What matters is not that you know everything up-front, but how you deal with mistakes. If a payment is due, you will be reminded. If some law is broken, you will be notified. At no point will you be punished before being given a chance to remedy the mistake.
Bottom line is, you can do it. Aside from an idea, all you need is perseverance. Where there's a will there's a way, true in life as it is in business.
"},{"location":"blog/20231018_building_a_business/#podcast","title":"Podcast","text":"Finally, in the interest of completeness, there's a podcast between me and Miguel Campos from a few months back talking about many of these things and more at depth.
https://www.youtube.com/watch?v=PMWvM9-vbgA&list=PL9LaIDCCDjfhZa-a_rT74cFDAk2R0Sf4S&index=3
Hope it helps, and feel free to continue asking questions here!
"},{"location":"blog/20240101_omx_vs_cmdx/","title":"cmdx v omx","text":""},{"location":"blog/20240101_omx_vs_cmdx/#omx-by-animal-logic","title":"omx by Animal Logic","text":"The appearance of omx
gave me an excellent opportunity to shed some light on the Maya API and how undo is implemented, along with finding some inspiration for things to improve in cmdx
.
omx and cmdx provide an alternative to maya.cmds
and pymel
that is both faster and - in the case of cmds
- more convenient.
One of the big failings of cmds
is nodes being referenced by name; such that when a name changes, the variable containing your node is no longer valid.
from maya import cmds\nnode = cmds.createNode(\"transform\", name=\"name\")\ncmds.rename(node, \"newName\")\ncmds.setAttr(node + \".translateX\", 5)\n# \"name\" does not exist!\n
PyMEL solved this, and added a boatload of additional features like exposing Maya's native math classes for e.g. easy vector addition.
from pymel import core as pm\nvec1 = pm.dt.Vector(1, 2, 3)\nvec2 = pm.dt.Vector(4, 5, 6)\nresult = vec1 + vec2\n
But it also added a performance overhead - importing the library can take seconds and generally using the library made code take several times longer than it would have via cmds
.
Performance Comparison
See below for a brief comparison, along with the README for cmdx
and documentation for omx
for more.
For Ragdoll, we needed both performance and maths.
For example, the Load Physics
command can read a JSON and generate a complete Maya scene with Maya nodes, Ragdoll nodes, connections between them and attributes restored from disk in a handful of milliseconds. On par with how long it takes Maya to load a .ma
or .mb
file off disk.
We built cmdx
to provide the terse readability of PyMEL with the performance of cmds
. Actually even better than cmds
, as you'll find below, due to leveraging the Maya Python API 2.0.
About two weeks ago, Animal Logic announced another open source contender called omx
and this page is a comparison between the two. To compare them, we'll need a better understanding of Maya, undo and the \"modifiers\", so you'll also learn about how these work!
More alternatives
The complete list of all other alternatives I know of, let me know if you know any more!
Let's start with a quick side-by-side.
omx
import omx\nfrom maya.api import OpenMaya as om2\n\nmod = omx.currentModifier()\njoint = mod.createNode(\"joint\", name=\"joint\")\n\nfn = om2.MFnNumericAttribute()\nattr = fn.create(\"flash\", \"flash\",\n om2.MFnNumericData.kInt)\nfn.setMin(0)\nfn.setMax(10)\n\nmod.addAttribute(joint.object(), attr)\n\njoint.radius.setFloat(1.5)\njoint.translate.setCompoundDouble((1, 2, 3))\n\nmod.commandToExecute(\n f\"setKeyframe -at tx -t 1 -v 10 {joint}\"\n)\nmod.commandToExecute(\n f\"setKeyframe -at tx -t 5 -v 15 {joint}\"\n)\nmod.commandToExecute(\n f\"setKeyframe -at tx -t 10 -v 10 {joint}\"\n)\n\nmod.doIt()\n
cmdx
import cmdx\n\nwith cmdx.DagModifier() as mod:\n joint = mod.createNode(\"joint\", name=\"joint\")\n attr = cmdx.Integer(\"flash\", min=0, max=10)\n mod.addAttr(joint, attr)\n mod.setAttr(joint[\"radius\"], 1.5)\n mod.setAttr(joint[\"translate\"], (1, 2, 3))\n mod.setAttr(joint[\"tx\"], {\n 1: 10,\n 5: 15,\n 10: 10\n })\n
Highlights
Feature omx cmdx Maya Support 2022-2024 2016-2024 Attribute Access Dot-access,.attr
Dict-access, [\"attr\"]
Attribute Setter node.attr.setInt(5)
node[\"attr\"] = 5
Attribute Getter if node.attr
if node[\"attr\"]
Animation mod.commandToExecute
mod.setAttr
Undo MPxCommand
+ MDGModifier
Same "},{"location":"blog/20240101_omx_vs_cmdx/#performance","title":"Performance","text":"Both omx and cmdx performs better than cmds, PyMEL and MEL. They also all scale linearly with the number of nodes, so let's see how they compare on the heaviest of cases.
10,000 nodes
Units are in seconds.
Test cmds cmdx cmdx noundo omx omx immediate Create 5.66 3.89 2.68 3.17 4.38 Edit 4.8 4.44 3.13 3.19 7.03 Rename 1.29 0.66 0.65 0.47 0.77 Query 0.73 0.52 0.52 0.68 0.66 Remove 0.89 0.61 0.62 0.41 0.70 Overall 13.5 10.1 7.67 7.94 13.6Both omx and cmdx thinly wrap the Maya API, so both of their bottlenecks is Maya itself.
Source
Tested on Maya 2024, Windows, source here
Bad performance
The AL performance comparison of cmds
ability to create is off by 3x, clocking in at 15 seconds.
Let's take a closer look, starting with syntax.
"},{"location":"blog/20240101_omx_vs_cmdx/#syntax","title":"Syntax","text":"# omx\nnode.t.x = 5;\n\n# cmdx\nnode[\"tx\"] = 5\n
Somewhat subjective, and we've learnt from PyMEL that accessing attributes via the dot-syntax does work. But not without cost.
Consider this.
# Attribute, function or property?\nnode.visible = True\nnode.flash.keyable = True\nnode.translate(1, 2, 3)\n
..did these even exist, or did we just add new variables to the Python object?
Wouldn't my IDE warn about it?
Consider readers on GitHub, GitLab or BitBucket; including the source code on this page.
Whenever you call .something
on a node, the __getattribute__
method of the object is called. In the case of omx, here's what this looks like.
AL/omx/_xnode.py#L75
class XNode:\n def __getattribute__(self, name):\n # (1)\n if hasattr(XNode, name):\n return object.__getattribute__(self, name)\n\n mob = object.__getattribute__(self, \"object\")()\n\n # (2)\n if name == \"apiTypeStr\":\n # ...\n\n if mob == om2.MObject.kNullObj:\n # ...\n\n nodeClass = XNode._NODE_CLASS_CACHE[mayaType]\n attrs = XNode._ATTRIBUTE_CACHE[mayaType]\n attr = attrs.get(name, None)\n\n # (3)\n if attr is None:\n if not nodeClass.hasAttribute(name):\n plug = _plugs.findPlug(name, mob)\n if plug:\n return _xplug.XPlug(plug)\n\n raise AttributeError(f\"Node {mayaType} has no attribute called {name}\")\n\n attr = nodeClass.attribute(name)\n attrs[name] = attr\n\n # (4)\n return _xplug.XPlug(mob, attr)\n
Some highlights
node.apiTypeStr
in which case we return a special caseXPlug
if soXPlug
Here, attributes are shadowed by native functions and properties, and as the count of both native functions and user attributes increases name clashes are inevitable.
It's also not clear when you assign whether you are assigning to a Python property or Maya attribute.
node.name = \"My Name\"\n
Conversely, cmdx uses __getitem__
instead. Here's what happens when you call node[\"attr\"]
cmdx.py#L570
class Node:\n def __getitem__(self, key):\n unit = None\n cached = False\n\n # (1)\n if isinstance(key, (list, tuple)):\n # ...\n\n # (2)\n if cached:\n # ...\n\n assert isinstance(key, str), (\n \"%s was not the name of an attribute\" % key\n )\n\n try:\n plug = self.findPlug(key)\n except RuntimeError:\n raise ExistError(\"%s.%s\" % (self.path(), key))\n\n # (3)\n return Plug(self, plug, unit=unit, key=key)\n
Some highlights.
node[\"tx\", Meters]
or node[\"rx\", Degrees\"]
cmdx.Plug
The first surprise when working with maya.api.OpenMaya
is the lack of undo.
from maya import cmds\nfrom maya.api import OpenMaya as om\nom.MFnDependencyNode().create(\"transform\")\ncmds.undo() # Nope!\n
We take it for granted with cmds
and pymel
but with naked access to OpenMaya
we are on our own. And it just so happens that undo/redo is (or, can be) really hard.
To understand why, we need to look closer at undo in general, and how Maya implements this with MPxCommand
and MDGModifier
.
The basic premise of undo in any application is that for every action there is an equal and opposite reaction. Wait, that's Newtons Third Law. But it does apply!
def do():\n createNode()\n\ndef undo():\n deleteNode()\n
Maya implements undo via the \"Command Pattern\".
Alternatives
There are other ways to implement undo, such as the \"Memento Pattern\" utilised by Blender.
Here are some excellent resources on it for deeper diving!
In a nutshell, it looks like this.
class Command:\n def __init__(self, name):\n self._name = name\n self._node = None\n\n def do(self):\n self._node = createNode(self._name)\n\n def undo(self):\n deleteNode(self._node)\n
And that's about all there is to it! What makes this pattern work, is that we can keep a list of previous commands..
previous_commands = list()\n\ndef execute(cmd):\n cmd.do()\n previous_commands.append(cmd)\n\nexecute(Command(\"hello\"))\nexecute(Command(\"world\"))\nexecute(Command(\"bye\"))\n
..and call their undo
in the reverse order!
def undo():\n last_command = previous_commands.pop() # Get and remove last item\n last_command.undo()\n\nundo()\nundo()\nundo()\n
There's one additional list for redo()
but the premise is the same. Append and pop.
Here's a real example of how this is implemented in the Maya Python API 2.0.
# my_command.py\nfrom maya.api import OpenMaya as om\n\nclass MyCommand(om.MPxCommand):\n kPluginCmdName = \"myCommand\"\n\n def __init__(self):\n super(MyCommand, self).__init__()\n self._node = None\n self._name = None\n\n def doIt(self, args):\n self.redoIt()\n print(\"Created '%s'\" % self._name)\n\n def undoIt(self):\n om.MGlobal.deleteNode(self._node)\n print(\"Deleted '%s'\" % self._name)\n\n def redoIt(self):\n fn = om.MFnDagNode()\n self._node = fn.create(\"transform\")\n self._name = fn.name()\n print(\"Re-created '%s'\" % self._name)\n\n def isUndoable(self):\n return True\n\n @staticmethod\n def cmdCreator():\n return MyCommand()\n\n\ndef initializePlugin2(plugin):\n pluginFn = om.MFnPlugin(plugin)\n pluginFn.registerCommand(MyCommand.kPluginCmdName, MyCommand.cmdCreator)\n\n\ndef uninitializePlugin2(plugin):\n pluginFn = om.MFnPlugin(plugin)\n pluginFn.deregisterCommand(MyCommand.kPluginCmdName)\n
Apart from a few syntactical differences, this is pretty vanilla Command Pattern.
You can call it like this.
from maya import cmds\ncmds.loadPlugin(\"my_command.py\")\ncmds.myCommand() # doIt is called\ncmds.undo()\ncmds.redo()\n# Created transform1\n# Deleted transform1\n# Re-created transform1\n
There are however two problems with this approach that make it unsuitable for use in scripting with Python. For starters, we must register each command as a plug-in, and the name of each plug-in must be unique as it will be present in Maya's own maya.cmds
module. Secondly, you have to implement the opposite command for every command you do!
Consider the case of an auto rigger.
class CreateRig(om.MPxCommand):\n kPluginCmdName = \"createRig\"\n\n def doIt(self, args):\n spine = self.create_limb()\n left_arm = self.create_limb(parent=spine)\n right_arm = self.create_limb(parent=spine)\n left_leg = self.create_limb(parent=spine)\n right_leg = self.create_limb(parent=spine)\n head = self.create_head(parent=spine)\n\n def undoIt(self):\n # Undo everything we just did!\n pass\n
Imagine the amount of state you would need to keep track of in order to undo such a thing. No longer just a self._node
but many dependent nodes and attributes, that need to be deleted and reset in the proper order (children first) and attributes potentially created on nodes outside of those created by this one command.
You'd have to be pretty dedicated to go this route, even Autodesk (Alias, rather) thought so too, which is why they gave us the modifier.
"},{"location":"blog/20240101_omx_vs_cmdx/#modifier-primer","title":"Modifier Primer","text":"Maya provides a means of wrapping one or more commands into an undoable chunk called a \"modifier\".
There are 2 flavours.
MDGModifier
for DG related modificationsMDagModifier
for DAG related modificationsThe DG handles things like creating DG nodes, connecting things, renaming things. Whereas the DAG version handles parenting and creating DAG nodes.
mod = maya.api.OpenMaya.MDagModifier()\nnode1 = mod.createNode(\"transform\", name=\"hello1\")\nnode2 = mod.createNode(\"transform\", name=\"hello2\")\nmod.doIt()\n
Points of interest:
doIt
is calledMDagModifier
But this still doesn't grant you the ability to undo. Instead, you have:
mod.undoIt()\n
Which has nothing to do with undo you know - i.e. Ctrl + Z - it's merely a command you can call yourself do undo whatever was done up until doIt
. The modifier has been keeping a log of every command you've done, so as to perform the opposite in the same order as you did. So to incorporate this with what you know as undo you need one more ingredient, the command.
Here's one way to couple the modifier and command.
class MyUndoCommand(maya.api.OpenMaya.MPxCommand):\n def __init__(self):\n self._modifier = None\n\n def doIt(self, args):\n self._modifier = _GLOBAL_MODIFIER\n _GLOBAL_MODIFIER = None\n\n def undoIt(self, args):\n self._modifier.undoIt()\n\n def redoIt(self, args):\n self._modifier.redoIt()\n
Maya will create an instance of this command and store it, so by storing the last modifier inside of it, Maya will ensure the right modifier is called at the right time.
Aside from some minutia, this is how both cmdx and omx solves this problem.
from AL import omx\nmod = omx.XModifier(immediate=False)\nmod.createDagNode(\"transform\")\ncmds.AL_OMXCommand() # Fetch and store this latest modifier\n\nimport cmdx\nmod = cmdx.DagModifier()\nmod.createNode(\"transform\")\ncmds.cmdx_0_6_3_command()\n
And in both cases, this command is hidden from view and is automatically called.
from AL import omx\nmod = omx.XModifier(immediate=False)\nmod.createDagNode(\"transform\")\n\nimport cmdx\nwith cmdx.DagModifier() as mod:\n mod.createNode(\"transform\")\n
"},{"location":"blog/20240101_omx_vs_cmdx/#modifiers","title":"Modifiers","text":"Given what we now know, you might be thinking \"modifiers, where have you been all my life!?\". And it's true they provide something rather unique, but they can be both a blessing and a curse.
"},{"location":"blog/20240101_omx_vs_cmdx/#blessing","title":"Blessing","text":"Since nothing happens until you call doIt()
that also means that if anything goes wrong up until that point, your Maya scene will be unaffected by anything that preceeded it.
mod.createNode(\"transform\")\ncond = mod.createNode(\"condition\")\nmod.addAttr(cond, attr)\nmod.createNode(\"BAD\") # <---\nmod.doIt()\n
With MEL, cmds and Pymel, the above would produce an error and leave your scene is a dirty state. As a user, you never know what has been created and what has not; was it enough to carry on? Do you need to undo and try again? Can you even undo, or has the undo queue been disrupted already?
With a modifier, an error is produced..
Traceback (most recent call last):\n File \"C:\\github\\test.py\", line 8, in <module>\n a = mod.createNode(\"BAD\")\nTypeError: invalid node type\n
..and since doIt()
was never called nothing will have happened! This is very nice.
Consider the case of an auto-rigger, where multiple functions and multiple modules call on each other to produce the final result. If anything breaks, an error is produced and nothing will have changed.
"},{"location":"blog/20240101_omx_vs_cmdx/#curse","title":"Curse","text":"There are however 2 main drawbacks to this approach.
(2) means that there are things you cannot do with a modifier, and thus cannot capture their undo. For example, you cannot cmds.play()
and you cannot manipulate the Maya UI in any way and you cannot change the min and max of attributes.
(1) however is the most damning.
Consider the case of a real-world production project, 15 modules, 150 functions, thousands of calls to generate a character rig. Creating nodes, adding and connecting attributes, setting values; the works.
from maya.api import OpenMaya as om\n\nmod = om.MDagModifier()\na = mod.createNode(\"transform\")\n\nfn1 = om.MFnDependencyNode(a)\n\nplug1 = fn1.findPlug(\"tx\", False)\nplug2 = fn1.findPlug(\"rx\", False)\nplug3 = fn1.findPlug(\"sx\", False)\n\n# Locked attributes cannot be connected\nplug2.isLocked = True\n\nmod.connect(plug1, plug2)\nmod.connect(plug2, plug3)\n\nmod.doIt()\n
And then, an error is thrown. Here's what you'll see.
Error: Connection not made: 'unitConversion1.output' -> 'transform2.rotateX'. Destination is locked.\nTraceback (most recent call last):\n File \"example.py\", line 18, in <module>\n mod.doIt()\nRuntimeError: (kFailure): Unexpected Internal Failure\n
And here's the kicker; the error occurs at line 18. At mod.doIt()
.
In this example - with only 1 call to connect
- the source is obvious. But you can already see how unitConversion1.output
is not what you wrote. It's automatically created by the modifier, and is part of the error message. In this hypotethical production example, these errors can start to get near impossible to debug.
Other times, you won't get an error at all until it's too late.
"},{"location":"blog/20240101_omx_vs_cmdx/#silently-adding-duplicate-attributes","title":"Silently adding duplicate attributes","text":"mod = om.MDGModifier()\nnode1 = mod.createNode(\"multMatrix\")\n\nfn = om.MFnNumericAttribute()\nattr1 = fn.create(\"myAttr\", \"at\", om.MFnNumericData.kFloat)\nattr2 = fn.create(\"myAttr\", \"at\", om.MFnNumericData.kDouble)\n\nmod.addAttribute(node1, attr1)\nmod.addAttribute(node1, attr2)\n\nmod.doIt()\n# No error\n
Now you're left with 2 duplicate attributes. This is not allowed by the Maya API and will likely segfault if you try and operate on either of these once they are done.
Under normal, non-modifier circumstances, an error would occur when attempting to add an attribute that already exists.
from maya import cmds\ncmds.addAttr(\"persp\", ln=\"myAttr\", at=\"float\")\ncmds.addAttr(\"persp\", ln=\"myAttr\", at=\"double\")\n# Warning: Name 'myAttr' of new attribute clashes with an existing attribute of node 'persp'.\n# Traceback (most recent call last):\n# File \"<stdin>\", line 1, in <module>\n# RuntimeError: Found no valid items to add the attribute to.\n
"},{"location":"blog/20240101_omx_vs_cmdx/#interoperability-with-non-modifiers","title":"Interoperability with non-modifiers","text":"Modifiers know about the surrounding API, but the surrounding API does not know about modifiers.
from maya.api import OpenMaya as om\n\nmod = om.MDagModifier()\nnode = mod.createNode(\"transform\")\n\n# (1)\nfn = om.MFnNumericAttribute()\nlength = fn.create(\"length\", \"le\", om.MFnNumericData.kFloat)\nmod.addAttribute(node, length)\n\n# (2)\nfn = om.MFnDependencyNode(node)\nplug = fn.findPlug(\"at\", False)\nmod.newPlugValueFloat(plug, 5.3)\n\nprint(plug.asFloat())\n
In this case, (1) is a modifier given data created outside of the modifier, this is fine.
But at (2), a non-modifier is operating on modifier data; this won't work because the data has not yet been created. We haven't yet called doIt()
. Neither the attribute nor node exists yet. The MObject
passed to MFnDependencyNode
is essentially invalid.
We can work around this by calling doIt()
multiple times.
from maya.api import OpenMaya as om\n\nmod = om.MDagModifier()\nnode = mod.createNode(\"transform\")\n\n# (1)\nfn = om.MFnNumericAttribute()\nlength = fn.create(\"length\", \"le\", om.MFnNumericData.kFloat)\nmod.addAttribute(node, length)\nmod.doIt() # Prepare attribute for the below call\n\n# (2)\nfn = om.MFnDependencyNode(node)\nplug = fn.findPlug(\"at\", False)\nmod.newPlugValueFloat(plug, 5.3)\nmod.doIt() # Again prepare the the *next* call\n\nprint(plug.asFloat())\n
Each time doIt()
is called, it will only perform the newly created operations since the last doIt()
. The undoIt()
on the other hand will undo all operations. Just as one would expect.
Both omx
and cmdx
had the same brilliant idea of recording commands made with the modifier, such that they can be printed out on error. Something Maya really should be doing already.
node[\"rx\"].lock()\n\nwith cmdx.DagModifier() as mod:\n mod.connect(node[\"tx\"], node[\"rx\"])\n\n# cmdx.ModifierError: An unexpected internal failure occurred, these tasks were attempted:\n# - connect('|transform1.translateX', '|transform1.rotateX')\n# - connect('|transform1.rotateX', '|transform1.scaleX')\n
cmdx
incorporates common sources of error into the modifier, so the above for example would error immediately.
# cmdx.LockedError: Channel locked, cannot connect 'rotateX'\n
"},{"location":"blog/20240101_omx_vs_cmdx/#comparison","title":"Comparison","text":"Let's compare the use of modifiers and commands between cmdx and omx.
"},{"location":"blog/20240101_omx_vs_cmdx/#mdgmodifier","title":"MDGModifier","text":"Let's look at how users interface with modifiers through cmdx and omx.
omx
import omx\nfrom maya.api import OpenMaya as om2\n\nmod = omx.currentModifier()\nmod.createNode(...)\nmod.addAttribute(...)\n\n# Current modifier implicitly called\njoint.radius.setFloat(...)\n\nmod.commandToExecute(...)\nmod.doIt()\n
cmdx
import cmdx\n\nwith cmdx.DagModifier() as mod:\n joint = mod.createNode(...)\n mod.addAttr(...)\n mod.setAttr(...)\n
When I first started writing cmdx
I desperately wanted to avoid exposing the modifier directly, as it added another layer of complexity compared to cmds
and PyMEL
. By having a \"current\" modifier somewhere globally accessible, you can make naked calls like joint.radius.setFloat
take advantage of it without the user explicitly calling on it.
# omx/_xplug.py:119\ndef setFloat(self, value):\n _currentModifier().newPlugValueFloat(self, value)\n
The problem is that it was never clear which call made use of this global modifier and which did not.
# We know this does\njoint.radius.setFloat(3.5)\n\n# But how about this?\njoint.myArray.append(5)\n\n# ..and this?\njoint.tx.locked = True\n\n# hmm..\njoint.visibility.setDoNotWrite(True)\n
With cmdx
, all undoable things are encapsulated in the modifier. Things outside of it are not immediately undoable.
with cmdx.DagModifier() as mod:\n mod.createNode(...) # Undoable\n mod.addAttr(...) # Undoable\n mod.setAttr(...) # Undoable\n\nnode[\"myArray\"].append(5) # Not undoable\nnode[\"attr\"].storable = False # Not undoable\n
For hand-rolled undoable operations, there is cmdx.commit
.
import cmdx\n\nhistory = []\nhistory.append(cmdx.createNode(\"transform\"))\nhistory.append(cmdx.createNode(\"condition\"))\nhistory.append(cmdx.createNode(\"multMatrix\"))\n\ndef undo():\n cmdx.delete(history)\n\ncmdx.commit(undo)\n
Which is what cmdx.DagModifier
uses too.
class Modifier:\n # ...\n\n def __exit__(...):\n cmdx.commit(self.undoIt, self.redoIt)\n
Although in practice I have never had to use this in Ragdoll.
"},{"location":"blog/20240101_omx_vs_cmdx/#mpxcommand","title":"MPxCommand","text":"Another subtle difference between omx and cmdx is how they store their modifiers.
omx
_xcommand.py#L40
Highlight Comment Implicit list of modifiers There exists this notion of a \"current\" modifier, and apparently there can be many. They are stored together in the same command. Instances Modifier instances themselves are stored alongside the command. Potentially problematic given that one cannot inspect what commands are in Maya's undo buffer at any given time and thus cannot confirm they do what you expect.def getAndClearModifierStack():\n global _CURRENT_MODIFIER_LIST\n existingMods = []\n for xmod in _CURRENT_MODIFIER_LIST:\n if isinstance(xmod, XModifier):\n if xmod.isClean():\n continue\n mmod = xmod._modifier # NOQA\n else:\n mmod = None\n logger.debug(\"Retrieving mod %r from list for execution\", mmod)\n existingMods.append(DoItModifierWrapper(xmod, mmod))\n _CURRENT_MODIFIER_LIST = []\n return existingMods\n\nclass XCommand(om2.MPxCommand):\n def __init__(self):\n # ...\n self._modifiers = _xmodifier.getAndClearModifierStack()\n\ncmds.AL_OMXCommand()\n
cmdx
The undo
and redo
commands are stored in a shared location, accessible to both the cmdx
module and plug-ins made with cmdx
.
cmdx.py#L8407
Highlight Commentunique_command
cmdx supports vendoring, whereby there may be multiple instances of cmdx
on the sys.path
any given time, of different versions. Therefore, they each use a unique name for their command. Addresses Undo and redo addresses are stored in a shared memory location, accessible from outside of Maya's undo queue for inspection, along with inside of new Maya commands made with cmdx
. class _apiUndo(om.MPxCommand):\n def doIt(self, args):\n self.undoId = shared.undoId\n self.redoId = shared.redoId\n\ndef commit(undo, redo=lambda: None):\n shared.undoId = \"%x\" % id(undo)\n shared.redoId = \"%x\" % id(redo)\n shared.undos[shared.undoId] = undo\n shared.redos[shared.redoId] = redo\n\n getattr(cmds, unique_command)()\n
To the end user, the behavious is identical. There really only is 1 way to undo and redo, anything else is a bug.
"},{"location":"blog/20240101_omx_vs_cmdx/#omx-and-the-current-modifier","title":"omx and the \"Current Modifier\"","text":"Given what we know know about undo inside of Maya, with modifiers and commands, it was interesting to see the notion of a \"current\" modifier in omx
.
Consider this.
# module1.py\ndef function1():\n mod = omx.currentModifier()\n mod.createNode(...)\n\n# module2.py\ndef function2():\n mod = omx.currentModifier()\n mod.setAttr(...)\n
To the naked eye, both of these functions, in these two separate Python modules, call on the same \"current\" modifier. In which case, by the end of your multi-file, multi-function call you must be incredibly lucky to not have encountered a single error - user or otherwise - for the function to have executed perfectly and without error. Only then will you get undo and only then will your scene state be safe. Because yes - as opposed to errors occurring prior to calling doIt()
- modifiers will still have executed all commands prior to the one that failed, leaving you with a mess and no undo.
But having looked closer at the omx source code, this is not the case. Instead, doIt
is frequently called automatically - such as when both creating and deleting new nodes - leaving me wondering what the purpose of a \"current\" modifier is, given that there is also a omx.newModifier()
?
cmdx deals with this by encouraging small batches of modifiers.
def function1():\n with cmdx.DagModifier() as mod:\n mod.createNode(...)\n\ndef function2():\n with cmdx.DagModifier() as mod:\n mod.setAttr(...)\n
"},{"location":"blog/20240101_omx_vs_cmdx/#xmodifier-implementation","title":"XModifier Implementation","text":"omx provides:
omx.newModifier()
omx.currentModifier()
Whereby currentModifier
will create a new modifier if there is no modifier. I was expecting this to keep returning the same modifier until I call newModifier
, but this wasn't the case.
mod = omx.currentModifier()\nassert mod is omx.currentModifier()\nmod.createDagNode(\"joint\")\nassert mod is omx.currentModifier() # AssertionError\n
Furthermore, the documentation states:
If AL.omx.XModifier._immediate
is True, whenever you call its method to edit Maya\u2019s scene data, it will call doIt()
to apply the edit to the scene immediately. On the other hand, if AL.omx.XModifier._immediate
is False, then you\u2019ll have to manually call AL.omx.doIt()
or XModifier.doIt()
to apply the edit.
However this does not appear true.
mod = omx.XModifier(immediate=False)\nassert not mod._immediate\nmod.createDagNode(\"joint\") # Still creates the joint\n# mod.doIt()\n
There is a comment in the source explaining why.
\"To get a valid MObjectHandle in XNode the creation needs to happen right away\" - Source
"},{"location":"blog/20240101_omx_vs_cmdx/#extras","title":"Extras","text":"Let's highlight some other points of interest.
"},{"location":"blog/20240101_omx_vs_cmdx/#commandtoexecute","title":"commandToExecute","text":"One of the things I struggled with was incorporating non-modifier commands in a modifier context, like locking attributes.
omx
handles this by utilising MDGModifier.commandToExecute
which queues a (MEL) command to execute at the right time, which I thought was very nice.
omx
Elegant method of handling this scenario.
class Modifier:\n def setLocked(self, locked):\n cmd = f\"setAttr -locked {locked} {self}\"\n _currentModifier().commandToExecute(cmd)\n
There is also pythonCommandToExecute
which does the same but with a Python command instead.
cmdx
Manual way, which will likely be converted to pythonCommandToExecute
instead.
class Modifier:\n def setLocked(self, plug, value=True):\n self._lockAttrs.append((plug, value))\n\n def _doLockAttrs(self):\n while self._lockAttrs:\n plug, value = self._lockAttrs.pop(0)\n elements = plug if plug.isArray or plug.isCompound else [plug]\n\n for el in elements:\n cmds.setAttr(el.path(), lock=value)\n\n def __exit__(self):\n self.redoIt()\n self._doLockAttrs()\n
"},{"location":"blog/20240101_omx_vs_cmdx/#animation","title":"Animation","text":"Shorthand for animating values.
node = cmdx.createNode(\"transform\")\nnode[\"tx\"] = {\n 1: 0.0,\n 5: 1.0,\n 10: 0.0\n}\n
This sets keyframes on frames 1, 5 and 10, with values 0, 1 and 0 respectively.
It might surprise you to know that cmds
returns units relative the units your UI is configured to.
# cm, meters or feet?\nheight = cmds.getAttr(\"persp.ty\")\n
Which is convenient sometimes, but not often!
cmdx
on the other hand always returns cm
and radians
, unless you specify otherwide.
height = persp[\"ty\", cmdx.Centimeters]\nheight = persp[\"ty\", cmdx.Meters]\n
All of the Maya math classes are available via cmdx
and may be directly passed (and gotten) as attribute values.
node = cmdx.createNode(\"transform\")\nnode[\"ty\"] = 5\nmtx = node[\"worldMatrix\"][0].as_matrix()\n\n# Store Y-transform as offset\nnode[\"offsetParentMatrix\"] = mtx\nnode[\"ty\"] = 0\n\n# Do some math\nmtx_inverse = node[\"worldMatrix\"][0].as_matrix_inverse()\nnode[\"newAttr\"] = cmdx.MatrixType()\nnode[\"newAttr\"] = mtx * mtx_inverse\n
All of cmdx
is available both as Maya-standard camelCase but also as camel_case
.
cmdx.createNode(\"transform\")\ncmdx.create_node(\"transform\")\n
As such, it'll fit into any codebase, no matter the convention!
Under the hood, the members are simply aliases of each other, so the functionality remains the same.
def createNode(...):\n pass\n\n# Alias\ncreate_node = createNode\n
Generate curves with a lot less code than the Maya API!
import cmdx\n\nparent = cmdx.createNode(\"transform\")\nshape = cmdx.curve(parent, [\n (0, 0, 0), # first CV point\n (0, 1, 0), # second CV point\n (0, 2, 0), # ...\n])\n
Have a look at the little brother of cmdx called cmdc
, a complete re-implementation of Maya's API, a.k.a. \"Maya Python API 3.0\"
Read more about cmdx and the tons of quality-of-life features incorporated over the years here.
Let me know what you think of the above summary! You can reach me at marcus@ragdolldynamics.com or via the Ragdoll forums. The post is intended for Maya developers at large, but also the developers of omx and anyone using omx or cmdx with a desire to better understand the things it does for you, under that hood.
"},{"location":"blog/20240101_omx_vs_cmdx/#try-it","title":"Try it","text":"That's all I got! Take both cmdx and omx for a spin via pip.
mayapy -m pip install AL_omx\nmayapy -m pip install cmdx\n
There's a topic created in the omx repository with some more discussion.
How to make yourself known without unethical practices.
Saying you are somewhere, but are actually somewhere else. For example, advertising that you are in London when you are really in Italy. Why? Because London is known, familiar and ripe with the tools of your industry. Because money. Manipulation for money. That's unethical.
Or how about advertising that you are in Cyprus when you are really in Russia. Why? Because Russa isn't too hot right now, so it may impact your brand. I.e. money. Manipulation for money. That's unethical.
"},{"location":"blog/20240319_ethical_branding/#features","title":"Features","text":"Advertising that something is done in X amount of time, when really it's X+n amount of time (e.g. Adonis and the \"2 clicks\" which was 10+ clicks). Why? Faster is better. Therefore, money. Manipulation for money. That's unethical.
"},{"location":"documentation/cache/","title":"Cache","text":"The fundamental building block to Ragdoll, for \"reverse motion capture\" or Animation Capture.
"},{"location":"documentation/cache/#caching","title":"Caching","text":"Ragdoll runs alongside your character animation, but sometimes it can be useful to keep the results from a previous run and stop being so interactive.
Meet Cache
and Uncache
.
Caching is entirely non-destructive, and in fact leverages the very same cache you've been enjoying all this time whenever rewinding.
The menu commands toggle an attribute on your solver node, called .cache
and automatically plays the entire timeline for you. But the same result can be achieved by setting the attribute and playing it yourself.
The minimal HUD will show you what's been cached, and like before once you resume playback from a cached to an uncached frame, Ragdoll will continue filling up the cache as one would expect.
Look forward to a future release where caching happens in the background, as you work. Something that can also be handy from time to time (pun!).
"},{"location":"documentation/constraints/","title":"Constraints","text":"Establish a relationship between two markers.
"},{"location":"documentation/constraints/#constraints","title":"Constraints","text":"You can constrain one marker to another!
Constraint Type Description Weld Constraint Simplest of constraints, welds two markers together; no change to their distance or relative orientation is allowed. This is akin to the MayaParent Constraint
Distance Constraint Maintain a minimum, maximum or total distance between two markers. Pin Constraint Match a position and orientation in worldspace, similar to Drive Space = World
. "},{"location":"documentation/constraints/#weld","title":"Weld","text":"Maintain the position and orientation of one marker relative another from the first frame onwards.
"},{"location":"documentation/constraints/#distance","title":"Distance","text":"A simple but versatile constraint with animatable distance.
Maintain Start Distance
Whatever the distance between two markers, it will be maintained throughout a simulation.
Minimum Distance
Alternatively, only respond to when two controls get too close.
Maximum Distance
Conversely, keep markers from getting too far away from each other.
Custom Distance
Or go all-in, with both a minimum and maximum distance, for the most complex behavior.
Offsets
Control at which point on a control to measure the distance.
Animated Distance
Both min and max distance, along with stiffness and damping, can be animated for some pretty rad effects.
Hard Distance
A Stiffness = -1
means the constraint is \"hard\". It will not accept any slack or \"springiness\".
In this example, the distance is animated whilst soft, and transitioned into a hard constraint. Notice how it snaps into place once hard.
Limitation
A limitation of a hard constraint is that the distance cannot be animated whilst hard. You can however animate it between values of -1 and above, to transition to and from hard to soft.
"},{"location":"documentation/constraints/#pin","title":"Pin","text":"Pin the translation and/or rotation of a Marker in worldspace.
"},{"location":"documentation/environment/","title":"Environment","text":"Collide against complex but immovable geometry.
"},{"location":"documentation/environment/#environment","title":"Environment","text":"Ragdoll supports static environments; meaning environments that cannot move or deform, but allow for normal polygonal geometry without the need for a simplified \"convex hull\".
As you might expect, this works well for environments like terrain and other complex geometry that is otherwise hard to turn into a rounded mesh.
"},{"location":"documentation/environment/#performance","title":"Performance","text":"It's fast.
Normal shapes are limited in how complex they can get, and as such you never really run into a situation where the shape noticeably affects performance.
Triangle meshes are different; they can be of any complexity. Up to millions of polygons and beyond. So it falls upon you to decide where to make the performance/quality tradeoff!
Vertex Count Cooking Time Run-time performance 400 0.39 ms 685 fps 8'000 3.51 ms 599 fps 16'000 14.3 ms 594 fps 64'000 61.5 ms 327 fps 256'000 287.7 ms 40 fps 1'000'000 1490 ms 2 fpsWhat is cooking time?
The time it takes for Ragdoll to convert your polygonal geometry into the internal representation needed for collision detection. It involves splitting up the mesh into areas or \"zones\" for faster lookup.
This only happens when the mesh actively changes and when first opening the Maya scene, and won't affect playback speed.
"},{"location":"documentation/export_physics/","title":"Export Physics","text":"Export physics from one scene, for import into another scene.
Coming Soon
Scheduled for release in January 2022
"},{"location":"documentation/fields/","title":"Fields","text":"Environmental effects like Wind and Turbulence for your Markers.
"},{"location":"documentation/fields/#fields","title":"Fields","text":"Ragdoll supports all of Maya's native \"fields\"
What are fields?
A field represents a set of forces applied to each Marker. Ranging from Gravity
to Turbulence
, each field carries unique properties you can use to emulate some environment or environmental effect, like wind and gravity fields along a curve.
What is the difference from regular Maya fields?
They are the very same!
If you're already familiar with them, from e.g. nParticles of nCloth, then you can leverage your experience with Ragdoll, and vice versa if you ever venture into nCloth and friends.
"},{"location":"documentation/fields/#overview","title":"Overview","text":"Let's walk through these fields one-by-one.
"},{"location":"documentation/fields/#turbulence","title":"Turbulence","text":"The perhaps most interesting field. Apply forces in \"random\" directions, based on the worldspace positions of your Markers.
The way to think of turbulence is as Perlin Noise you may have seen in images such as this.
Where the amount of white determines the amount of force being applied. As a Marker travels across this field, both the magnitude and direction changes in interesting ways.
"},{"location":"documentation/fields/#drag","title":"Drag","text":"Apply an opposite force to any motion.
The faster things move, the greater the force.
Pro tip
This field is similar to Ragdoll's Air Density
. Not technically, but practically.
Apply a uniform force, at a given speed, in a given direction. Like wind, including a kitchen fan with some Spread
.
A familiar force, except this one can be also be animated!
"},{"location":"documentation/fields/#newton","title":"Newton","text":"Force Markers towards or away from a point in space.
"},{"location":"documentation/fields/#radial","title":"Radial","text":"A more curious field; with a force which increases as it gets farther from the source.
"},{"location":"documentation/fields/#uniform","title":"Uniform","text":"Apply a constant force. That's all.
"},{"location":"documentation/fields/#vortex","title":"Vortex","text":"Apply forces in a circular pattern.
"},{"location":"documentation/fields/#volume-axis-field","title":"Volume Axis Field","text":"A field for when you don't know what field you want.
A true Swiss Army Knife of fields, can do everything from Vortex, to Newton to Turbulence in one convenient node.
"},{"location":"documentation/fields/#volume-curve","title":"Volume Curve","text":"Have some fun with this curve-based field. Perhaps to emulate an underwater current?
In this example, I'm also using a Drag
field to keep things from flying off into space.
Pro tip
The curve is a normal Maya NURBS curve. If you need more points, right click and add points as you normally would.
"},{"location":"documentation/fields/#combined-fields","title":"Combined Fields","text":"Make two or more fields to combine their effect and create complex forces or series of forces!
"},{"location":"documentation/fields/#centroids","title":"Centroids","text":"Where within each Marker should a field apply forces?
At the center, forces will be nice and predictable; except they won't be able to introduce rotations to your Marker, which may or may not be what you want. For the most realistic fields, use volumetric centroids.
Here's another example using the Turbulence Field.
Which is better?
Up to you! There is a tiny performance penalty for volumetric origins, as the number of forces increase. But you shouldn't notice much if any impact on performance.
"},{"location":"documentation/fields/#centroid-seed","title":"Centroid Seed","text":"For complex meshes, centroids can end up in unwanted locations or gather in an area with dense vertices. That's when you can give the algorithm a little jolt to try and see whether there is a better alternative out there.
"},{"location":"documentation/fields/#use-selected-as-source","title":"Use Selected as Source","text":"Some forces act according to their position in the world. Attach a field to a Marker to create an interesting relationship between the two.
Non-commercial Ragdoll
This feature is limited to 100 frames in non-commercial versions of Ragdoll.
Distance constrain two markers, and attach a field to the outer-most Marker for a doubly-interesting effect. That also wrecks your brain. \ud83d\ude43
"},{"location":"documentation/fields/#field-scale","title":"Field Scale","text":"If forces start becoming large, you may find yourself in a situation where the visualisation needs to tone down just a bit.
In the solver settings, you will find options to scale those lines (i.e. Field Scale
), as well as control how many steps into the future (i.e. Field Iterations
) it should draw for you.
Fine-tune the effect of fields by having one or more Markers ignore the effect of fields.
"},{"location":"documentation/fields/#more","title":"More","text":"Being native to Maya, Autodesk has some documentation of its own here.
You may also search for fields on YouTube or ask your colleagues about them; any trick they've learnt may very well apply to Ragdoll as well!
"},{"location":"documentation/group/","title":"Group","text":"Ragdolls are combined into what's called a \"group\", with attributes to control the overall behavior of all contained Markers.
"},{"location":"documentation/group/#self-collision","title":"Self Collision","text":"Previously, it was very important that your shapes did not overlap any shape other than it's immediate neighbour. If they did, chaos ensued.
Before
Clavicles intersect their parent spine, but also each other!
After
With the new Self Collision = Off
, this is no longer a problem.
This can be taken into the extreme!
And here's another example to fill out a large volume in the center of a character.
Attention
Notice how the spine is made up of many shapes, some of which cover the width of the body, others the depth. An overlapping mess that would never have simply not have been possible without self-collision support!
Original asset created by Mehmet Tayfur T\u00fcrkmeno\u011fluwe and Dr. Reel, licensed by The Rookies.
"},{"location":"documentation/import_physics/","title":"Import Physics","text":"Import physics onto existing controllers from disk.
"},{"location":"documentation/import_physics/#import","title":"Import","text":"You can import a Ragdoll setup exported from Maya, back into Maya. It'll re-create everything just the way it was.
What is included in the export?Just about everything.
Very little.
Yes, anything else is a bug.
More precisely, determinism depends on (1) the type and number of items in the solver along with (2) the order in which these are created. Both of these are part of the exported file format and is taken into account during import. Meaning you should get identical results so long as the content is the same.
"},{"location":"documentation/import_physics/#example","title":"Example","text":"Here's an exported Ragdoll setup for the free CG Spectrum Tiger rig.
2.8 mb
)To use it, download the rig and import the Ragdoll file.
It contains 2 levels of detail.
Level Content Level 0 Body and feet Level 1 Everything on Level 0, plus toes "},{"location":"documentation/import_physics/#workflow","title":"Workflow","text":"Here's the rundown.
On import, Ragdoll will try and find the names of what you exported in your currently opened scene.
Namespace
dropdown menu.Search and Replace
fields to modify the names searched for by Ragdoll.Export
Once you're happy with your character, it's time to export. Towards the bottom of the UI, you'll get a preview of what is about to be exported. This can help clarify that what ends up on disk is what you expect.
Import
In a new scene, with the same character, same names and everything, import as you'd expect. At the bottom of this UI, you'll get a preview of what's in the file on disk, along with how it will associate the node names found in the file with what you have on disk.
"},{"location":"documentation/import_physics/#namespace-from-file","title":"Namespace from File","text":"Odds are, the character you're importing either has no namespace, or has a different namespace to what you've currently got in your scene. As in this example here, with 3 copies of the same character, each with its own namespace.
Use the Namespace
dropdown to select one of the current namespaces in your scene, or Custom
to type one in yourself.
Per default, Ragdoll will import the file into the current solver in your scene, if any. Or, you can import the original solver from the source file.
"},{"location":"documentation/import_physics/#known-limitations","title":"Known Limitations","text":"Here are a few things that will be addressed over time. Let us know if you encounter anything else!
Light-weight or heavy-duty? How about both!
"},{"location":"documentation/level_of_detail/#level-of-detail","title":"Level of Detail","text":"Setup your character once with all bells-and-whistles, and interactively pick which level of detail to use for your simulation in a given situation.
Usecases
Level 0
, fingers at Level 1
Level 1
, muscles at Level 2
Level 0
, extremities at Level 1
and Level 2
For example, here's a Wasp character with 3 levels of increasing detail.
As you'd expect, it'll record only the currently active markers.
"},{"location":"documentation/level_of_detail/#workflow","title":"Workflow","text":"Here's how it works.
1
1
And that's it! Any marker with a matching level is simulated and recorded.
"},{"location":"documentation/level_of_detail/#operators","title":"Operators","text":"What does each level mean? The answer lies in the \"operator\".
Operator DescriptionLess Than
If the Marker Level
is less than (or equal) to the Solver Level
, simulate it. Greater Than
If the Marker Level
is greater than (or equal) to the Solver Level
, simulate it. Equal
If the Marker Level
is equal to the Solver Level
, simulate it. NotEqual
If the Marker Level
is not equal to the Solver Level
, simulate it. With these, you can use each level for..
With Equal
and NotEqual
operators, you can have some markers appear or disappear on particular levels, enabling endless combinations.
Roadmap
This should cover a majority of cases, but there are things you cannot yet do, but will be able to in the future.
Capsule
on one level, Mesh
on another. For higher-resolution contacts.For the geeks out there, here's what the underlying algorithm looks like in Python.
# Membership types\nMinimum = 1 # Present at this level and higher\nMaximum = 3 # Present at this level and lower\nOnly = 4 # Only present at this level\nNot = 5 # Present at all levels *except* this one\n\nmarkers = [\n {\"name\": \"hip\", \"level\": 0, \"membership\": Minimum},\n {\"name\": \"spine\", \"level\": 0, \"membership\": Minimum},\n {\"name\": \"neck\", \"level\": 0, \"membership\": Minimum},\n {\"name\": \"head\", \"level\": 0, \"membership\": Minimum},\n {\"name\": \"L_upper_leg\", \"level\": 0, \"membership\": Minimum},\n {\"name\": \"L_lower_leg\", \"level\": 0, \"membership\": Minimum},\n {\"name\": \"R_hand\", \"level\": 1, \"membership\": Minimum},\n {\"name\": \"L_foot_box\", \"level\": 1, \"membership\": Maximum},\n {\"name\": \"L_foot_convex\", \"level\": 2, \"membership\": Minimum},\n {\"name\": \"R_toe_capsule\", \"level\": 2, \"membership\": Not},\n {\"name\": \"R_toe_convex\", \"level\": 2, \"membership\": Only},\n]\n\ndef resolve(level):\n print(\"Level %d\" % level)\n for marker in markers:\n if marker[\"membership\"] == Minimum and marker[\"level\"] <= level:\n print(\" - {name} ({level})\".format(**marker))\n\n if marker[\"membership\"] == Maximum and marker[\"level\"] >= level:\n print(\" - {name} ({level})\".format(**marker))\n\n if marker[\"membership\"] == Only and marker[\"level\"] == level:\n print(\" - {name} ({level})\".format(**marker))\n\n if marker[\"membership\"] == Not and marker[\"level\"] != level:\n print(\" - {name} ({level})\".format(**marker))\n\nresolve(0)\nresolve(1)\nresolve(2)\n
Run this, and this is what you'll find.
Level 0\n - hip (0)\n - spine (0)\n - neck (0)\n - head (0)\n - L_upper_leg (0)\n - L_lower_leg (0)\n - L_foot_box (1)\n - R_toe_capsule (2)\nLevel 1\n - hip (0)\n - spine (0)\n - neck (0)\n - head (0)\n - L_upper_leg (0)\n - L_lower_leg (0)\n - R_hand (1)\n - L_foot_box (1)\n - R_toe_capsule (2)\nLevel 2\n - hip (0)\n - spine (0)\n - neck (0)\n - head (0)\n - L_upper_leg (0)\n - L_lower_leg (0)\n - R_hand (1)\n - L_foot_convex (2)\n - R_toe_convex (2)\n
"},{"location":"documentation/link/","title":"Link","text":"Combine, or \"merge\" multiple solvers together, to simulate them as one.
"},{"location":"documentation/link/#linking","title":"Linking","text":"Reference two characters, link their solvers.
Until now, you've been able to author physics using Active Chain
and combine scenes using the Combine Scene
menu item. That would transfer all connected rigids from one scene to another.
But, that feature is destructive. There's no way to \"uncombine\" and even if you could, there's no record of what was originally combined.
Let me introduce Solver Linking
, a lightweight and non-destructive alternative.
Linking
This fellow is referenced twice, and get their solvers linked together.
Unlinking
Unlinking restores their previous behavior exactly.
That's neat, but can you..
I know exactly what you're thinking, I was thinking the same thing.
Can you link a solver to another solver that is also linked? So that I can build a network of simple solvers that all work together to form one complex solver?
Yes. Yes, you can. \ud83e\udd2d See below.
"},{"location":"documentation/link/#example","title":"Example","text":"Here are 2 assets, a manikin and a backpack.
Manikin BackbackThe backback and manikin has been combined into one, which is then referenced twice into the final scene for a total of 4 unique solvers.
Non-destructively link solvers
Notice the hierarchy of solvers formed here, enabling you to build complex solvers out of many small solvers.
Non-destructively unlinking too
Likewise, safely deconstruct a network of solvers by just removing the connection.
Technically, a solver is added to another solver in the same manner a marker, group and constraint is added. One big happy family.
"},{"location":"documentation/live_mode/","title":"Live Mode","text":"Interact with your simulation in real-time.
"},{"location":"documentation/live_mode/#live-mode","title":"Live Mode","text":"Here's \"Live Mode\" in a nutshell.
Traditional Rig
And here's the equivalent task with the traditional rig.
If you don't make it through all of the 95 seconds that the traditional method takes, I don't blame you. Not only is posing with Live Mode already 3x faster, it also has the following benefits.
But perhaps most importantly.
This same workflow applies to plain joint hierarchies, meaning an animator could:
For example, here's 30 seconds of \"rigging\" a character from scratch.
And that's where things are going.
Let's have a closer look at what this thing can do today.
"},{"location":"documentation/live_mode/#general-posing","title":"General Posing","text":"Clicking and dragging on any marker will affect it the way you'd expect.
"},{"location":"documentation/live_mode/#reset","title":"Reset","text":"Exiting out of the mode or changing from the Manipulator to e.g. the Maya Translate tool (W hotkey) will reset the simulation to where it originally started.
"},{"location":"documentation/live_mode/#drop-press-hold","title":"Drop Press & Hold","text":"Towards the bottom, you'll find a number buttons, one of which is called Drop
. This \"drops\" the character. In other words, it temporarily enables gravity. This can help ease a character onto the ground or generally relax things that are hovering. It's also fun to play with.
Hold Shift to toggle gravity on, such that you can throw things around! Also fun to play with
"},{"location":"documentation/live_mode/#tense-press-hold","title":"Tense Press & Hold","text":"Next up is Tense
. This tenses the character.
What's really happening is that it tries to reach whatever pose your rig is in at that time.
"},{"location":"documentation/live_mode/#tense-toggle","title":"Tense Toggle","text":"Like Drop
, the Tense
button can be toggled, which would leave the character tense.
Hold Ctrl whilst clicking to \"mask\" a Marker. This prevents it from moving at all, it's technically turning the Marker into a Kinematic object temporarily.
Pro tip
You can also press Ctrl whilst dragging and release to leave the Marker you are currently dragging in place, for some cool posing mechanic!
"},{"location":"documentation/live_mode/#unmask-all","title":"Unmask All","text":"Next up is \"unmask\" which involves \"masking\" via Ctrl + Clicking on a Marker. It's how you prevent a Marker from moving.
How does it work?
It temporarily turns any marker Kinematic
, identical to the Behaviour = Kinematic
attribute.
Hold Shift whilst dragging to isolate the effect to a marker and it's children.
"},{"location":"documentation/live_mode/#transfer-pose","title":"Transfer Pose","text":"The final button is the Transfer
button. It's what transfers the simulation back onto your animation controls.
Like Drop and Tense, this button can also be toggled, meaning the pose is transferred as soon as you let go of the mouse cursor.
"},{"location":"documentation/live_mode/#animation","title":"Animation","text":"And these are the tools you use to animate.
"},{"location":"documentation/live_mode/#visual-undo","title":"Visual Undo","text":"The timeline helps you understand where undo will take you.
You can also interact with the timeline, for fine control over where in history you want to go.
"},{"location":"documentation/live_mode/#recording-live-mode","title":"Recording Live Mode","text":"Use Live Mode with Cache = Static
to enable recording of your interactions!
Toggle the Lock button far-right to keep simulating outside of the Manipulator.
This enables you to use Ragdoll as a normal Maya deformer, and see real-time updates on contacts and limb limits.
Here are some more examples!
"},{"location":"documentation/live_mode/#rigging-for-live-mode","title":"Rigging for Live Mode","text":"In order for your characters to work with Live Mode, you'll need to take a few things into consideration. Primarily that your character has FK controls with the ability to disable space switches and other mechanics that differ from a straightforward parent/child relationship.
A quick tutorial on how to setup a character using Maya's multi-cut, and then export and load this character to assemble it alongside our favourite Manikin!
Here's an example of how you can \"trick\" Live Mode into working for you with any traditional Maya rig.
At the bottom-left hand corner of Live Mode, you'll find a set of experimental controls.
"},{"location":"documentation/live_mode/#magnet-tuning","title":"Magnet Tuning","text":"Whenever you click and drag, you are dynamically creating and destroying a Pin Constraint. The settings for this Pin Constraint can be customised here.
These can also affect the Modifier keys on the right-hand center of the Live Mode UI, such as how strong gravity should be or how tense the character should get when pressing the Tense
button.
In Live Mode, all constraints are disabled. This way, they will not interfere with the primary purpose of Live Mode, which is to pose your character. However, outside of Live Mode, such as in Interactive Mode, it may be useful to keep these active.
See example here
Like Pin Constraints, Fields are disabled in Live Mode per default, but can be re-enabled using this button.
"},{"location":"documentation/live_mode/#workflows","title":"Workflows","text":"These are having a hard time finding a good default or place in the UI. They affect the overall workflow of Live Mode, so play with them but don't put too much faith into them.
Button Description Synchronise Keep the Live Timeline in sync with the Maya timeline Reset on Time Changed Keep the simulation in sync with the Maya scene whenever time changes Force Viewport Update Improved interaction when in Interactive Mode "},{"location":"documentation/locomotion/","title":"Locomotion","text":"Automatic walking, running, jumping and more with Locomotion.
"},{"location":"documentation/locomotion/#usage","title":"Usage","text":"Here's what you do.
Assign Plan
What is a \"Plan\"?
The generated locomotion is the result of a \"plan\", meaning each of the inputs you give it. Including this initial selection.
"},{"location":"documentation/locomotion/#examples","title":"Examples","text":"Let's start with a quick look at what you can get out of this new toy.
Locobot
Modeling by Christophe Desse.
Spot and Friends
Happy Box
Yes, you can give it a terrain.
Two Happy Boxes
Locoboy
A 2-legged quadruped, look at 'em go!
Locomotion & Physics
Playing well together.
Humanoid Locomotion
As you can tell, quadrupeds fair much better!
Human Dynamics
But with some physics, it's starting to look nice. :)
"},{"location":"documentation/locomotion/#abilities","title":"Abilities","text":"Here's what we're aiming for with this feature.
To achieve this, you've got control over:
Step Sequence
Terrain
upon which to walkThere can be any number of feet and it can travel any amount of distance. The Step Sequence
is how you're able to achieve different kind of walks.
And the Terrain
is how it can do this across geometry of any complexity.
Let's talk about what cannot be solved with Ragdoll Locomotion
.
Currently, it only understands 2 things.
And for feet, it only understand the position of the foot, not its orientation.
Most importantly, it does not understand arms! Arms are critical to human locomotion, they swing in tandem with each step. This version of Ragdoll does not understand arms. Yet. Meaning it's good for locomotion involving any creature that does not have arms.
But Marcus, that doesn't leave much room for many creatures. They all have arms!
Think again!
With that out of the way, let's look at what it can do!
"},{"location":"documentation/locomotion/#press-t","title":"Press T","text":"Locomotion also has a manipulator, accessible by selecting the rPlan
node and pressing T
on your keyboard.
Locomotion is computed in the background.
Normally, it'll take a second or two to compute 4-12 seconds worth of locomotion, and you can safely interact with Maya whilst it's running. It has zero impact on your overall Maya or character rig performance.
"},{"location":"documentation/locomotion/#rig-compatibility","title":"Rig Compatibility","text":"Anything from a box with a sphere for feet to the most complex digi-double will do.
The rig in the above example is nothing special, as you've seen from the examples above this works on \"rigs\" as complex as a box and 2 spheres.
"},{"location":"documentation/locomotion/#multiple-characters","title":"Multiple Characters","text":"You can have as many characters in the scene as you like.
"},{"location":"documentation/locomotion/#parallel-processing","title":"Parallel Processing","text":"That's right! If 1 character takes 2 seconds to compute, 5 characters also take 2 seconds to compute. Or 10 characters, or 100 characters. 2 seconds in total, that's all you'd have to wait, up to the number of cores on your system.
As core-count continues to increase in our machines, you can expect the number of characters being run in parallel to increase as well, up to the level of full crowds; each individual character a unique and precise sequence of steps that conform to their environment.
Juice Left
There is still a little bit of juice left to squeeze.
At the moment, if Ragdoll detects any relation between one plan and another, it will run these one-by-one.
Normally, this is not the case, but if you for example connect the output of one plan to the input of another, there isn't much that can be done other than wait for one to finish. However this can also happen when unrelated things are connected, such as your character being connected to two plans, such that you can blend between them. This is too much, and will be addressed in a future release. Subtle balance!
"},{"location":"documentation/locomotion/#physics","title":"Physics","text":"Locomotion is an entirely separate \"brain\" that you may, or may not, want to combine with regular Markers.
Body and/or feet can be Kinematic
or driven by a Pin Constraint
, or anything inbetween.
Unlike a simulation, Locomotion
is entirely time independent. So it isn't strictly necessary to record; it will run directly on your character rig.
You can edit the locomotion as keyframes via Maya's native Bake Results
command.
This will become your new best friend. With an easily recognisable pattern for when to move your feet.
Sequencer Mode
Shift
to paintCtrl
to eraseIt can be used to produce a wide variety of locomotion, such as this frog sequence.
"},{"location":"documentation/locomotion/#targets","title":"Targets","text":"Once you've figured how to get somewhere, next up is figuring out where to go.
Target Mode
Start
or End
of the body or footTranslate
gizmo to control the position of either body
or foot
Rotate
gizmo to control the start and end orientation of the body
Use the Rotate
gizmo to control the orientation of the body at the start or end positions.
Is your character jumping or limping? Maybe dancing? Limits control the area in which each foot is allowed to move.
Limit Mode
body
to adjust the size of your characterfoot
to adjust the amount of motion a foot is allowed to haveHere's an example of how a short limit on one foot, and long steps with the other foot, can generate a wounded or limping locomotion.
"},{"location":"documentation/locomotion/#terrain","title":"Terrain","text":"Things can easily get more interesting by swapping out that flat ground with some geometry.
"},{"location":"documentation/locomotion/#shift-to-toggle","title":"Shift to Toggle","text":"You can choose whether to use the Shift and Control keys to add and remove steps in the Locomotion Step Sequencer, or whether to use Shift for both. Dragging over a filled step will erase it, whereas dragging over an unfilled step will fill it. A toggle!
"},{"location":"documentation/manipulator/","title":"Manipulator","text":"Interactively manipulate shapes and limits using the Manipulator.
"},{"location":"documentation/manipulator/#manipulator","title":"Manipulator","text":"One of the most challenging aspects of Ragdoll to date is editing shapes and limits. These have now been greatly simplified via the use of \"manipulators\", similar to your standard Translate/Rotate/Scale manipulators. Except on steroids.
Here's a 21 second overview.
"},{"location":"documentation/manipulator/#activate","title":"Activate","text":"You have a few options for activating the manipulator.
Ragdoll -> Manipulator
T
on your keyboardShow Manipulator Tool
in the ToolbarAny of the Ragdoll nodes can be selected in order to enable the manipulator via the T
keyboard shortcut.
rdSolver
rdGroup
rdMarker
rdDistanceConstraint
rdPinConstraint
rdFixedConstraint
Manipulator UI Scale
If the Manipulator's UI is too big or too small, you can change that via Ragdoll > System > Ragdoll Preferences > Resolution Scale
. Make sure to restart Maya or reload Ragdoll after changing the Resolution Scale.
Solver Shape
At the time of this writing, the solver needs its shape selected, not the parent transform. This will be addressed in a future release.
A comfortable workflow is..
T
The selected Marker will be pre-selected in the manipulator.
Alternatively, press the Show Manipulator Tool
button in the Toolbar.
This release introduces a manipulator with two \"modes\".
Mode Description Shape Mode Edit shape properties, likeLength
, Radius
, Position
and Orientation
Limit Mode Edit limit properties, like Twist
and Swing
along with their pivots. In Shape Mode, you currently have 5 manipulators.
Manipulator DescriptionTranslate
Affects the Shape Offset
attribute Rotate
Affects the Shape Rotation
attribute Scale
Affects the Shape Radius
and Shape Extents
attributes Length
Affects the Shape Length
attribute, for the Capsule
shape HUD
Individual control over primary attributes, like Shape Extents
axes Translate
Hold the middle-mouse button to translate.
Rotate
Hold Ctrl + middle-mouse button to rotate.
Scale
Hold Ctrl + left-mouse button to scale.
Length
The Capsule
shape have additional in-view manipulators you can drag to affect each side independently.
HUD
Finally, attributes without a visual handle can be edited via the viewport HUD.
"},{"location":"documentation/manipulator/#limit-mode","title":"Limit Mode","text":"In Limit Mode, you currently have 2 manipulators.
Manipulator DescriptionLimit
Affects the Limit Range XYZ
attributes HUD
For locking and enabling of limits Enable and Disable
Click the Axis
button to limit the rotation about a particular axis.
Lock and Unlock
Click the Lock
button to prevent all rotation about the axis.
Asymmetrical Edits
Hold Ctrl
to make asymmetrical edits
Some limbs start out at the center of their limit. Like your hip and neck. They are typically modeled to enable equal movement in each axis.
Other limbs, like the elbow and knee, are typically modeled in the extreme of their limit. Able to only rotate in one direction. For these cases, they need an asymmetrical limit.
With limits in multiple axes, keep an eye out for how asymmetrical edits to one axis affect the others.
Why are they moving?
Under the hood, each axis must still be symmetrical; edits only appear to be asymmetrical for your convenience. What's really happening is the entire limit is both changing shape and also rotating and the rotation is causing all axes to move.
This is an inherent limitation (pun!) of limits in Ragdoll and is unlikely to be addressed in the future, so we'll have to work with it.
If you mess up and want to start from scratch, hit the Reset
button, also found under..
Ragdoll -> Utilities -> Reset Constraint Frames
Enabled per default, symmetry will mirror your edits across an axis.
There are 2 types of symmetry at the time of this writing.
Type DescriptionWorld
Look for a marker across the current axis in worldspace Pose
Based on the pose at the time of assigning markers, which is typically symmetrical. Each of which can be made symmetrical in either the X, Y or Z axes. The Pose
axis means you can make changes even if a character has been posed after having been assigned. A feature particularly useful when assigning to the A- or T-pose of a character rig.
Pose Based Symmetry
Because these controls were assigned in the T-pose of the rig, you can use Pose-based symmetry to make changes even when the character is currently asymmetrical.
Multiple Rigs
If two or more characters are present in the scene, and they were all rigged in the same pose, at the center of the world, then Ragdoll will only look at markers in the same rdGroup
as the selected Marker.
Search Distance
On the right-hand side of the Enable Symmetry
button, there is a Search Distance
gizmo.
Drag to edit this value
When you select a marker on one side, it will search for a marker at the opposite side of the axis you've chosen. Because positions are all approximate, it uses a maximum search distance to look for it.
Matches
Ideally, there should only be one match. But in a crowded hierarchy there may be several. Tune the Search Distance
to control the number of matches, to ensure it doesn't pick the wrong one.
Disable Symmetry
to enable multi-select
Hold Shift
to select and manipulate multiple markers at once.
Drag Select?
Not yet! But will be added in a future release.
"},{"location":"documentation/manipulator/#undo-redo","title":"Undo & Redo","text":"No surprises here.
Changes made using the manipulator are undoable as you would expect, with the exception that it currently does not let you undo the selection itself like normal Maya selection does; this will be addressed in a future release.
"},{"location":"documentation/manipulator/#fit-to-view","title":"Fit-to-view","text":"Tap the F
key to fit any selected Marker(s) to the view, like you would expect from selected Maya nodes.
Caveat
This currently only applies if you've activated the manipulator using the Ragdoll -> Manipulator
menu item, or have the rdSolver
shape node selected.
Click the Select Node
button to select this node in Maya
Per default, Ragdoll and Maya selection are separate. You can have Maya select the node(s) currently seleted in Ragdoll by pressing the Select Node
button.
You can automate this using the Synchronise
button at the far-left of the HUD.
Why is this not on per default?
The solver is what is actually being fitted. If the selection is changed to a marker (which is not a DAG node, and therefore lacks a visual representation) then fit-to-view no longer works.
This will be addressed in a future release and made into the default.
With Multi-select or symmetry enabled, all selected markers will be selected in Maya, to make bulk edits via the Channel Box easier.
"},{"location":"documentation/manipulator/#manipulator-help","title":"Manipulator Help","text":"On the right-hand side is an overview of the hotkeys and mouse button combinations you can use, and what they do.
It can be hidden via the HUD button on the upper right-hand side.
"},{"location":"documentation/marker/","title":"Marker","text":"Markers form the fundamental building block of Ragdoll, to achieve Animation Capture a.k.a. \"reverse motion capture\".
"},{"location":"documentation/marker/#animation-capture","title":"Animation Capture","text":"Capture your character rig, as though it was a live action actor.
Inspired by Motion Capture - Animation Capture is a new way to think about and work with physics in Maya. To learn about it, let's first understand how Motion Capture generally works.
Here is a typical data pipeline for motion capture, from real-life actor to final character animation.
# Description 1 Markers are attached to an actor 2 Markers are \"captured\" 3 A pointcloud is generated 4 A hierarchy of joints is generated 5 Joints drive a typical character rig 6 Rig drives final geometry for renderEach \"Marker\" is a dud. Nothing of any complexity. Something for the camera(s) to recognise and track as it moves through space. Once tracked, it's able to translate this Marker from a 2D image into a 3D position, and continues to do so for each Marker. The real processing to take place inside software.
Once the capture is complete, the human actor can remove the markers and go enjoy the rest of their day. The rest is up to the computer.
With 3D positions generated, software takes over to translate these points into a hierarchy; the FK joint hierarchy you may be familiar with if you've ever worked with mocap. The joint hierarchy can then be used to either drive the final geometry, or to drive a more complex character rig which in turn drives the final geometry.
Animation Capture is just like that, but in reverse. Instead of capturing a person, it captures your character rig.
# Description 1 Markers are attached to a character rig 2 Markers are \"captured\" 3 A rigid body is generated for each Marker 4 A hierarchy of constraints is generated to connect them 5 Simulation is recorded back onto the original character rigUnlike motion capture, we'd like the result mapped back onto our character rig again, which is how animators iterate with physics.
"},{"location":"documentation/marker/#example-1-basics","title":"Example 1 - Basics","text":"Here's how to simulate a box.
Assign
Once you're happy with what you see..
Record Simulation
Here's how to setup a full Ragdoll.
1. Setup hierarchy
Select controls in the order you'd like them attached.
2. Edit shapes
Fit the shapes to your character model.
3. Record
Once your happy with the way the simulation looks, record it back onto your rig.
"},{"location":"documentation/marker/#behaviour","title":"Behaviour","text":"The Behaviour
is how Ragdoll should interpret the controls you assign. Did you mean for them to remain animated, i.e. Animated
? Or should they follow the control around, i.e. Simulated
?
The Behaviour
can be set either for a whole group of markers, or each Marker individually.
Simulated
if there is no group Animated Follow the input exactly, physics need not apply Simulated Follow the input approximately, with some Stiffness
and Damping
"},{"location":"documentation/marker/#animated","title":"Animated","text":"Follow the input exactly, no exceptions. Not even collisions.
"},{"location":"documentation/marker/#simulated","title":"Simulated","text":"Follow the local pose of your animation.
"},{"location":"documentation/marker/#pose-space","title":"Pose Space","text":"Pose matching happens in either Local
or World
space.
Look, it's Ragdoll Blaine!
This is an example of Worldspace Pose Stiffness. Ragdoll will try and reach the worldspace position and orientation of your rig, rather than only looking at the relative angles between each limb.
Here's another example of the difference between Local
and World
space.
Notice how in Local
space, the controls arms remain relative the torso. And with World
space they instead follow the worldspace orientation of the controls.
This attribute is also animatable, and is how you can transition from animation into simulation and back again.
Here's a more complete example:
Frame Transition 100 Starts as a regular animated character 125 Transitions into physics as he jumps, for a physically-correct trajectory 155 Transitions back to animation once he rolls over on that cabinet 160 Transitions back to physics until he stands up 170 Transitions back into animation to match an exact pose 200 Partially transitions into physics, for secondary motion in the upper body as his arm is raised. "},{"location":"documentation/marker/#overlap-group","title":"Overlap Group","text":"Specify which markers may overlap rather than collide. This can be useful to enable dense areas of a character, like the clavicles, where there is natural overlap amongst large shapes like with the neck and spine.
Value Meaning-1
No overlap allowed 0
Default, respects self-collision on the group (if any) 1-255
Overlap everything with the same number An rdMarker
part of a rdGroup
can get an overlap group assigned procedurally, based on other members of that group. For example, in a complete ragdoll, all markers are part of the same group. So a Self Collide = On
means these will all be given the same overlap group.
If it isn't in a group, then 0
is the same as -1
, in that it will collide with everything.
Let's have a look at a few scenarios.
"},{"location":"documentation/marker/#collide-with-everything","title":"Collide with Everything","text":"In this example, every Marker is part of the same group. The group has Self Collide = Off
, which is fine for just about every Marker except the fingers. In that case, we do want self-collision, so they are given the group -1
.
In this case, we're happy with a default group of 0
since we don't need anything to self collide. Especially these clavicles that overlap significantly!
Finally, for the very specific cases of wanting two or more markers to overlap. Notice how we give both the ground and 3 of the boxes an Overlap Group = 5
.
Each Marker has a \"material\" to control how it interacts with other markers.
"},{"location":"documentation/marker/#mass","title":"Mass","text":"How much influence one Marker should have over another during contact.
Pro tip 1 - Misconception about Mass
A common misconception in physics is that Mass
affects how quickly something falls to the ground. But in Ragdoll - like in real-life - mass is only relevant during interaction with another Marker and when forces are applied, like Guide Strength
.
Have a look at this video of a bowling ball falling in a vacuum alongside a feather.
Pro tip 2 - Making something fall fasterSo how do you make something fall faster?
Scene Scale
under the solver nodeGravity
, also under the solver nodeTo make something \"bend\" faster, like an arm flexing, that would be controlled via the Guide Strength
and typically what causes it to reach a given speed and then stay there is governed by the Rotate Damping
. That's how much of any motion should be cancelled out, to stabilise the motion. A very fast motion would have very little damping, but then also run the risk of \"overshooting\". That is, of passing the point at which you wanted it to reach.
Ragdoll can automatically compute a suitable mass for each Marker, based on the volume of your shape and a density of your choosing.
In other words, big objects become heavy, small objects become light.
Before
After
"},{"location":"documentation/marker/#presets","title":"Presets","text":"Enter any value, or pick one from these pre-defined ones.
Density Value DescriptionCotton
0.05 Very sparse, 0.05 grams per cubic centimeter Wood
0.2 Sparse, 0.2 grams per cubic centimeter Flesh
1.0 Default, 1.0g/cm3 Uranium
19.0 Dense, 19.0g/cm3 Black Hole
1000.0 Very, very dense Mass is computed based on the volume of your shape, along with a density of your choosing.
"},{"location":"documentation/marker/#options","title":"Options","text":"Choose between various densities either at creation-time or after creation.
"},{"location":"documentation/marker/#visualise","title":"Visualise","text":"The computed mass updates interactively as you change the size and type of your shape, including convex hulls!
In the Manipulator, you'll be able to not only edit the density, but preview the computed mass given the current shape volume and density you provide.
"},{"location":"documentation/marker/#friction","title":"Friction","text":"Control how much resistance should be added between two rigids rubbing against each other.
"},{"location":"documentation/marker/#bounciness","title":"Bounciness","text":"Control how much rigids should repel each other when coming into contact.
Values beyond 1.0
Here's a tip!
Bounciness can be greater than 1.0, which means they will gain energy during contact.
In practice, energy will always dissipate in some way. The most-bouncy character in the GIF above has a bounciness of 2.0
, which in theory means that for every contact it should fly 200%
faster away than it did coming in, and keep doing this forever.
If you try and balance something on your finger, but the \"center of mass\" is off center, it would fall over.
It is the point at which the weight of an object is equal in all directions.
Ragdoll automatically computes this point based on what the shape looks like. For meshes, it will voxelise your geometry to figure out the physically accurate volumetric center of mass, assuming the density of the object is uniform throughout (rather than hollow or variadic, like swiss cheese).
You now override this point using the attribute Center of Mass
found under the Advanced tab.
Guidelines
0
to compute the point automatically based on the shapeIn real life, if you spin a broom 180 degrees along its length; that's easy. But if you spin it 180 degrees along any other axis, like a ninja, it's considerably heavier.
The reason is something called \"angular mass\", also known as \"moment of inertia\". It's like mass, but in terms of rotation rather than position. The broom has a low angular mass along its length axis. It takes more force to affect a \"heavier\" axis than a lighter one which is why a broom spins more easily along its length.
This effect happens in Ragdoll too and is typically automatically computed for you based on the shape you use. If it looks like the broom, it will act like a broom.
With this release, you can now customise this for greater control of your rotations.
When would you want to do that?
Or any combination in between. :) Generally, a broom or any thin shape is more easily spun along its length, so you may find stability in setting your angular mass to (1.0, 1.0, 1.0)
, at the expense of realism.
Guidelines
-1
to automatically compute the angular massConvert a simulation into keyframes using Record Simulation
.
Markers can be recorded all together, or independently. For example, say you wanted animation from frame 1-100, simulate 101-150 and return to animation from 151-200. You can do that.
Furthermore, say you liked what the simulation was doing, but only on one half of the body. Or only on the hip, driving the main trajectory in a physically-plausible way. Keeping the rest of your animation intact.
Record All
With nothing selected, Ragdoll will record all marked controls to the current Maya playback range.
Record Selected Markers
Select a few controls to control what gets recorded.
Record Range
Limit the Maya playback range for control over when recording takes place.
Record Selected Range
Or, select an explicit range interactively.
Record to Animation Layer
Ragdoll will record to a layer per default.
Mode
Update the viewport whilst recording, or not. That's Nice and Steady
and Fast and Loose
respectively. There's a performance benefit to not updating the viewport, however some character rigs depend on viewport updates to evaluate properly, so it may not always work.
Here's an example with an almost 2x performance difference!
"},{"location":"documentation/record_simulation/#transitions","title":"Transitions","text":"Let's have a look at how you would use markers to transition between simulation and animation.
Notice how we're animated up until the jump, and then Ragdoll takes over.
Pose Space
from Local
to World
and have him reach the target pose in worldspace.Behaviour
to Kinematic
and kinematically move him.Guide
, this time with Pose Space = Local
.Sometimes, rotation isn't coming from Rotate X
but rather a custom Ball Roll
attribute on a different IK control.
As Ragdoll only understands Translate
and Rotate
, how would you go about recording onto this attribute!? Here's what you can do.
Locator.rotateX -> R_foot_CTL.ballRoll
Now Ragdoll will record onto a familiar channel, and Maya will handle the conversion back onto the rig.
"},{"location":"documentation/record_simulation/#extract-simulation","title":"Extract Simulation","text":"Get data out of the solver and into a baked joint hierarchy.
You can use this to build a library of animations, or to handle the retargeting from simulation to animation manually by just constraining to the resulting joint hierarchy.
Performance
Notice how fast this is!
A Debugging Companion
It can also be used for situations where Record Simulation
doesn't do what you need it to. The extracted skeleton will be a plain joint hierarchy, with no scale, and guaranteed to match the simulation exactly. So you can extract it, and constrain your rig to it.
Assign to joints, record to controls.
"},{"location":"documentation/retargeting/#retarget","title":"Retarget","text":"You can visually see where keyframes go upon running Record Simulation
.
Let's take a look at what this UI is, what it can do for you and when to use it.
The UI can help you spot problems with recording, before recording happens.
In this case, some of our markers are retargeted onto joints that are driven by some other object. If we were to attempt to record these, it's unclear what the result should be.
Neither of these are a great pick, since we don't want to break the rig, but we also want our simulation to go somewhere.
"},{"location":"documentation/retargeting/#workflow","title":"Workflow","text":"Once you've assigned your markers, grab a clean slate and gain complete control over where animation is to be recorded.
And finally, here's a longer-form example of a full setup of the Truong Dragon that we did a livestream on a while back.
The opposite of Retarget.
Rather than assigning to joints and retargeting to IK controls, we assign to IK controls and reassign to joints. Same coin, different side; which one do you prefer?
"},{"location":"documentation/retargeting/#reparent","title":"Reparent","text":"Use Reparent
when you selected things in the wrong order and want a do-over.
Success!
"},{"location":"documentation/retargeting/#untarget","title":"Untarget","text":"For when you don't want anything recorded for this Marker. Useful for utility Markers, like twist joints or extra spine controls or just Markers without a corresponding control.
"},{"location":"documentation/snap_to_simulation/","title":"Snap to Simulation","text":"Snap a character to wherever the simulation is currently at.
"},{"location":"documentation/snap_to_simulation/#snap-to-simulation","title":"Snap to Simulation","text":"Yet another way to work with physics, by transferring individual poses from the solver into your animation. You can use it to pose or layout a scene.
Coming Up
An upcoming release will enable you to advance time in the simulation, without affecting time in Maya. Such that you can \"relax\" a pose, for example. \ud83d\ude01
"},{"location":"documentation/solver/","title":"Solver","text":"Markers connect to a solver, and anything connected to one solver is able to interact.
"},{"location":"documentation/solver/#solver","title":"Solver","text":"Where the magic happens.
The rdSolver
node is akin to the motion capture camera(s). It'll monitor any markers in your Maya scene and show you what their physical equivalent version looks like.
Ragdoll needs a consistent progression of time to provide reliable results. So per default, if it notices a frame being skipped, it kindly pauses and waits until you revisit the last simulated frame.
Alternatively, you can let it look the other way and pretend time has progressed linearly, like nCloth and countless other solvers do.
"},{"location":"documentation/solver/#pause","title":"Pause","text":"The default. It's safe, predictable, but requires Play Every Frame
to work.
The nCloth and nHair default, of trying its best to simulate even though it wasn't given the frames inbetween. Unpredictable, unreliable but may handle playing along with sound.
Aside from not giving you the same result each time you play, if too many frames are skipped your simulation can completely explode. You can semi-work around this by increasing the number of substeps, forcing more simulation frames to fill for the missing frames.
Non-deterministic
Bear in mind that the Ignore
method cannot give you the same results each playthrough. The Pause
method is guaranteed to give you the same results, and are identical to what you get when you use the Record Simulation
or Cache
commands.
Rather than having to specify which frame to start simulating at, Ragdoll can keep track of your animation start frame. Either the start of the range, or the full timeline. Or, you can still set a Custom
start time for when you do care about specifics.
solverType
Differences","text":"Type Description Strong Better for characters, it makes the Rotate Stiffness
stronger; more capable of matching the animated pose. It can become unstable if there are too many loose objects in the scene. Stable Better for many independent objects, like a destruction scene. You can find solverType
under the Channel Box and the Attribute Editor.
The fundamental building block to Ragdoll, for \"reverse motion capture\" or Animation Capture.
"},{"location":"documentation/utilities/#replace-mesh","title":"Replace Mesh","text":"You can now replace the original geometry assigned to your marker, just like you could with Rigids.
"},{"location":"documentation/utilities/#auto-limits","title":"Auto Limits","text":"Markers are now able to infer which axes to lock in the simulation, based on the locked channels of your control or joint.
Notice in this example how some of the channels are locked. With the Auto Limit
option checked, the corresponding limit axes will be locked too, such as to prevent the simulation from rotating around those axes.
If you forget or want to detect locked axes on an existing marker, you can use the Utility option too.
"},{"location":"maya/download/","title":"Download","text":"Download for Autodesk Maya 2019 to 2024If you agree with the Ragdoll Dynamics EULA, you may select a platform below.
Windows Linux MacOSRagdoll 2024.02.10 awaits. Read about it - Previous versions
Join the community of ragdollers on Discord and/or Discourse.
Chat Forums "},{"location":"maya/download/#install","title":"Install","text":"Ragdoll ships as a Maya Module for Windows, Linux and MacOS.
Installation for Windows
On the Windows platform, there's an executable you can run.
.msi
installerAlternatively, download the Linux distribution above and unzip it into your ~/maya
directory. You should end up with something like this.
c:\\Users\\marcus\\Documents\\maya\\modules\\Ragdoll.mod\n
Installation for Linux On Linux, installation and upgrades are done in the same fashion.
.zip
into your ~/maya
directoryYou should end up with something like this.
/home/marcus/maya/modules/Ragdoll.mod\n
Installation for MacOS On MacOS, installation and upgrades are done in the same fashion.
/modules
into /Users/Shared/Autodesk/modules/maya
You should end up with something like this.
/Users/Shared/Autodesk/modules/maya/Ragdoll-2021_11_15.mod\n
Gatekeeper
Ragdoll is still in the process of being verified by Apple, until then you may need to tell Gatekeeper \"everything is OK\" for both the ragdoll.dylib
which is the physics solver, and loco3d
which is the Locomotion module. It may also ask about TurboFloat
and TurboActivate
which is the licencing system.
The plug-in is now available via the Plug-in Manager.
Everything ok?
No menuYou've booted up Maya, loaded the plug-in via the Plug-in Manager, but there is no menu, what gives?
Maya Modules work in mysterious ways. Try installing it the old fashioned way.
from ragdoll import interactive\ninteractive.install()\n
No module named 'ragdoll' A clue! Let's go deeper.
import os\nmodules_path = r\"c:\\Users\\marcus\\Documents\\maya\\modules\"\nragdoll_path = os.path.join(modules_path, \"Ragdoll-Maya-2021_11_06\\scripts\")\n\nimport sys\nsys.path.insert(0, ragdoll_path)\n\nfrom ragdoll import interactive\ninteractive.install()\n
Make sure you replace the version number (date) with the version you are using. At this point, I expect you've uncovered why your module wasn't working in the first place and should probably revisit that as this process would require you to manually update the version number in that path each time you upgrade. No fun.
Something else happenedOh no! I'd like to know about what happened, please let me know here.
"},{"location":"maya/download/#faq","title":"FAQ","text":"What are my workstation requirements?Anything capable of running Maya can run Ragdoll.
See Pricing.
What happens when my licence runs out?Your scenes will still open, but the solver will be disabled. Contact licence@ragdolldynamics.com for renewal of your licence.
What happens when I skip frames?The simulation gracefully pauses until you revisit the last simulated frame. See the Frameskip Method
attribute on the rdSolver
node for another option, Ignore
. This will continue simulating, and ignore any skipped frames. Good for real-time playback with audio.
Yes, the only environment variable needed for Rez is MAYA_MODULE_PATH
, such as:
env[\"MAYA_MODULE_PATH\"].append(\"{root}\")\n
Where the Ragdoll-2021_07_28
folder and Ragdoll-2021_07_28.mod
file resides at {root}
.
Ragdoll simulates your translate and rotate channels, whereas nHair simulates point geometry. You can convert those points into translation and rotation, but given the choice why would you? Besides, Ragdoll has far more robust collisions, control and constraints than nHair or nCloth could ever hope to achieve, at much greater performance.
"},{"location":"maya/download/#limitations","title":"Limitations","text":"As of Ragdoll 2024.02.29
these are the current known limitations of Ragdoll.
Welcome to Ragdoll in Maya, first released in July of 2021 and with support for versions 2019 up to 2024.
"},{"location":"maya/home/#where-to-find-help","title":"Where to Find Help?","text":"Depending on where you are and what you are looking for, one of these should fit the bill.
# Source Description Chat Come join the party on Discord! Documentation Read about each command available to you in Maya Release Notes Every new release has examples of every new feature and squashed bug. Search Top of every page, you know what to do \u261d\ufe0f UI Help Find help without leaving Maya YouTube Videos Long-form walkthroughs and examples. Tutorials Long-form, written tutorials for learning Ragdoll from the ground up. Reference The Reference page lists all menu items, item options and node attributes of Ragdoll along with descriptions and examples. Community Inspire and be inspired via the Ragdoll forums Support Get us involved and let's make some waves"},{"location":"releases/2020.11.10/","title":"Multi-threading","text":"Performance!
Ragdoll is now multi-threaded!
There are two mechanisms for managing performance.
With 2 or more Ragdoll solvers in the same Maya scene, Maya will run these in parallel. Which means they will both run independently, on separate hardware cores on your CPU. Currently, you can expect a 2-3x performance increase through use of multiple solvers, with more optimisation to come.
A single Ragdoll solver can be automatically broken up into simulation \"islands\" that run in parallel. Islands are created when two or more groups of rigid bodies are unlikely or unable to interact. For example, two characters in the same solver far away from each other. To leverage solver-level parallelism, adjust the rdScene.threadCount
attribute (under Advanced in the Attribute Editor). A value of 0
(default) means it will run on a single thread, on the same thread as the rest of Ragdoll and Maya.
For small scenes, with less than 100 rigid bodies, you should expect improved performance from a single thread. Each thread comes with some amount of overhead.
"},{"location":"releases/2020.11.10/#option-dialogs","title":"Option Dialogs","text":"
Some menu items now have option dialog boxes for further customisation. Settings are stored with Maya's preferences and persists across scenes and between application launches.
"},{"location":"releases/2020.11.10/#animation-influence","title":"Animation Influence","text":"
The \"Dynamic Control\" feature now enables control of the simulation using the animation used for blending.
The highlight for this release is Cached Playback!
jointOrient
being proper for joints, gone are the days.Box
shape does now draw correctly with a custom rdRigid.shapeRotation
"},{"location":"releases/2020.11.16/#cached-playback","title":"Cached Playback","text":"
Maya 2019 introduced support for Cached Playback, and Maya 2020 added support for Cached Simulation, which is now supported by Ragdoll!
Create new rigids
Edit existing rigids
Trajectories can be enabled with the rdScene.drawTrajectories
attribute, under Visualisation
of the Attribute Editor
There is still work to be done. Currently, animated visualisations aren't updating in cached mode. However the simulation still runs correctly and your driven character animation will behave identically to non-cached mode.
The animation of the slice visualisation doesn't represent the current, animated state
The connection visualisation is not up-to-date, you can disable the drawing with rdConstraint.drawConnection
The guide delta drawn to represent the difference between simulation and your animation only draws the latest result, rather than the result on the current frame.
Note that these are only visual and does not affect the simulation. These will all be addressed in a future release!
rdRigid.ouputGeometry
Remove any geometries when working with cached playback, these cause instant death to Maya and it's still unclear why.
"},{"location":"releases/2020.11.16/#help-videos","title":"Help Videos","text":"
Find out more about a command, by seeing an example of how to use it. There's only one video at the moment, with more to come. Including videos for different ways of using the same command.
The goal is to never have to leave Maya to learn about Ragdoll.
"},{"location":"releases/2020.11.16/#shape-orientation","title":"Shape Orientation","text":"
Shapes typically align with the Maya node, but in the case of joints that isn't always what you want. Maya separates between joint orientation and drawing; it'll always draw joints facing its child. When the orientation and visual orientation of a joint differs, you would end up with correct but unexpected results.
This release fixes that by properly updating..
rdRigid.shapeOffset
rdRigid.shapeRotation
..to mimic how joints appear in the Maya viewport.
"},{"location":"releases/2020.11.17/","title":"Splash Screen","text":"Minor release.
Ragdoll | Character
menu item has been fixed and is operating at 100%"},{"location":"releases/2020.11.17/#install-confirmation","title":"Install Confirmation","text":"
It isn't obvious to new users that Ragdoll installed successfully, so here's what the splash screen looks like that you'll see on first launch.
"},{"location":"releases/2020.11.22/","title":"Bugfixes","text":"Minor release, no breaking changes.
Auto
option to Convert Rigid
, to toggle a rigid between dynamic and kinematicrdRigid.kinematic
attribute is now up-top, better indicating its importanceRagdoll | Convert
menu item is now split into Convert Rigid
and Convert Constraint
Convex Hull
-> Mesh
, should make more sense now"},{"location":"releases/2020.11.22/#capsule-orientation","title":"Capsule Orientation","text":"
Fixed a bug where the capsule of a joint would face the wrong way.
"},{"location":"releases/2020.11.22/#what-is-rigid-body-dynamics","title":"What is Rigid Body Dynamics?","text":"
Loose thoughts that will eventually transform into a quick 10 second video.
Rigid Body Dynamics is a branch of computer science which \"studies the movement of systems of interconnected bodies under the action of external forces\". It differs from your typical simulation - such as nHair and nCloth - in that it simulates the translate
and rotate
channels of a given transform node rather than points of the geometry.
The main advantage is that it is well suited for animation and rigging, since animation and rigging is all about translate and rotate.
Ragdoll Jargon
Dynamic Rigid Body
is a transform affected by forces. Forces like Wind, but also contacts and constraints which are both considered forces, in that they happen instantaneously rather than continuously.Kinematic Rigid Body
is a transform affected by animation. It does not respect forces, but enables you to animate Box
, Sphere
, Capsule
or Mesh
. Shape attributes are prefixed Shape *
e.g. Shape Length
affects the length of the Capsule
, whereas Shape Extents
affects the dimensions of the Box
translate
or rotate
or both channels to each other.Wind
or Push
you can use to affect a Dynamic Rigid Body
"},{"location":"releases/2020.11.22/#performance-tips","title":"Performance Tips","text":"
Many things are currently unoptimised and these are the lowest hanging fruit you can reap for greater performance.
rdRigid
shape once you're done tweakingOther things come down to scene-by-scene basis.
rdRigid.positionIterations
is how many iterations are given to each related constraint. Greater numbers means you can use higher values for Guide Strength
and Limit Strength
, at the expense of performanceThe headline of this release is Dynamic Control 2.0
"},{"location":"releases/2020.11.23/#dynamic-control-20","title":"Dynamic Control 2.0","text":"
Ragdoll is currently very technical.
It is exposing features of an underlying mathematical framework for solving \"Rigid-Body Dynamics\" (wiki) and tries to be as friendly about it as possible, but there is always a tradeoff in usability and flexibility.
Dynamic Control was made to bridge that gap.
It combines a user-selection with a series of commands to automatically try and figure out your intentions when those intentions are \"add some dynamics to my animation control\".
Dynamic Control has been with Ragdoll for a few weeks now, and have undergone a series of changes to try and increase its intuitiveness whilst reducing complexity. It's hard! But in this release I'd like to present what I'm dubbing the \"2.0\" of Dynamic Control.
The main differences are:
stiffness
is the \"springiness\" whereas damping
is the \"plasticity\". A control can have 0 damping and be very springy and active. It can also have 0 stiffness, but that would basically disable it.
On a technical note, the attributes exposed on your animation control are \"proxy\" attributes. Which means they can be animated either from your control, or from the source node, such as the rSocketConstraint
shape node under your control.
Here are some more videos to get you familiar with the tool.
Some limitations in this current version, yell if these affect you.
The same goes for all things Ragdoll at the moment.
"},{"location":"releases/2020.11.23/#center-of-mass","title":"Center of Mass","text":"If you try and balance something on your finger, but the \"center of mass\" is off center, it would fall over.
It is the point at which the weight of an object is equal in all directions.
Ragdoll automatically computes this point based on what the shape looks like. For meshes, it will voxelise your geometry to figure out the physically accurate volumetric center of mass, assuming the density of the object is uniform throughout (rather than hollow or variadic, like swiss cheese).
You can now override this point using rdRigid.centerOfMass
.
Guidelines
0
to compute the point automatically based on the shapeIn real life, if you spin a broom 180 degrees along its length; that's easy. But if you spin it 180 degrees along any other axis, like a ninja, it's considerably heavier.
The reason is something called \"angular mass\", also known as \"moment of inertia\". It's like mass, but in terms of rotation rather than position. The broom has a low angular mass along its length axis. It takes more force to affect a \"heavier\" axis than a lighter one which is why a broom spins more easily along its length.
This effect happens in Ragdoll too and is typically automatically computed for you based on the shape you use. If it looks like the broom, it will act like a broom.
With this release, you can now customise this for greater control of your rotations.
When would you want to do that?
Or any combination in between. :) Generally, a broom or any thin shape is more easily spun along its length, so you may find stability in setting your angular mass to (1.0, 1.0, 1.0)
, at the expense of realism.
Guidelines
-1
to automatically compute the angular massThe \"Auto Connect\" option now enables you to specify whether to connect joints, or any selected object.
"},{"location":"releases/2020.11.24/","title":"Hotfix","text":"Hotfix, the last release broke a few things.
That's all, have mercy.
"},{"location":"releases/2020.12.01/","title":"Character 2.0","text":"Lots of good stuff!
Delete all Physics
now also deletes Ragdoll's attributes on your animation controls, for that squeaky clean feelingrdRigid
The rigids should now clean up after themselves betterThe terminology for \"Rigid\" and \"Collider\" wasn't clear. Surely, a \"Rigid\" collides too?
With this release, I've updated the jargon to make a little more sense.
Active Rigid
A rigid that moves is activePassive Rigid
A rigid that doesn't move is passiveThis also goes for the kinematic
attribute which has been renamed passive
, highlighting that an active rigid can made passive by flicking this switch. Backwards compatibility is preserved by keeping the underlying attribute name, and only changing it in the Channel Box and Attribute Editor (i.e. the \"nice name\").
This release expands on the \"Character\" tool with some nifty new features. But since I haven't mentioned what 1.0 was capable of, here's an overall round down of what it is and when to use it.
Character
is a one-click character creation tool - and auto-rigger (or auto-ragger, if you will). It's designed to give you the essential tools for turning any native Maya skeleton into an animatable rigid body hierarchy.
Read more about it on this new dedicated page I've made for it.
Now Dynamic Control can be configured to generate capsules between selected controls, instead of assuming that the NURBS CVs neatly wrap around the model.
Current and Default behaviour
The tool uses the Mesh
shape per default like before.
Alternative Capsules
But if your controls do not have volume, or do not nicely wrap the underlying model, you can now use Capsules instead.
The caveat with capsules is that the tool cannot know how long to make your capsules. Therefore, there is an option to use the last-selected node as a hint for how long to make it.
In this example, 5 nodes selected, 1 passive and 3 active rigids comes out. If you don't use a last selection for length, the last selected capsule will have a length of 0 (it'll be a sphere). That can work in some cases, but is generally discouraged. The center of mass would be wrong and you should expect unrealistic results until you tweak it to fit your model.
Gathering information about Dynamic Control on the..
An early version of the \"Normalise Sizes\" tool, meant to more evenly distribute sizes of shapes across a hierarchy. Per default, shapes are sized based on the geometry of the Maya node. If it's a box, it'll get the dimensions of the box. If it's a joint, it'll get the length and radius of that joint.
But because this mechanism can't see past the one node it's looking at, it's an uphill battle making shapes evenly distributed in a greater network.
The \"Normalise Sizes\" tool is meant to address that.
It's still early, and a few things are missing.
Now you can speed up or slow down your simulation with a multiplier attribute found on the rdScene
node!
Substeps
.Continuous Collision Detection
to prevent it from flying through stuff without noticing.For anything slower than real-time, remember contacts and constraints are solved each frame, so more frames means more accurate simulation. If you don't like that, you can either (1) half the substeps alongside halving time or (2) bake out the simulation and scale the bake instead.
Example Scene
Now rigids play well with non-standard rotation orders, very common your everyday character animation rigs to ensure axes don't go gimbal.
Thanks to Peter Jemstedt for help on this one!
"},{"location":"releases/2020.12.01/#auto-orient","title":"Auto Orient","text":"Shapes and constraints can now be automatically oriented based on the parent and child of each joint (soon coming to controls). This should help sort out those pesky joint orientations any manner of skeletons.
"},{"location":"releases/2020.12.01/#undo-bug","title":"Undo Bug","text":"There was this nasty bug that caused rdRigid
nodes to remain behind after creating and then undoing. But what got left behind wasn't your normal nodes. They only appeared in the Node Editor and could not be selected or even deleted. They would show themselves out when re-opening the Maya scene which is great.
This visibility isn't a problem in itself, if it wasn't for them also being visible from Python. If any command needed to know \"hey, animation control, are you connected to a rigid?\" then it would happily reply \"yes! for sure!\".
And that's bad. But not anymore, because it's fixed!
"},{"location":"releases/2020.12.01/#stick-figures","title":"Stick Figures","text":"In a previous release I touched on \"angular mass\" and what it meant for your simulations.
Let's look at this in practice.
Here's one character with identical settings, the only difference is the radius of her capsules, and yet the move differently. Why is that?
Remember that angular mass is 3-dimensional. Just like normal mass, when mass is high, more force is required to introduce motion. In the case of angular mass, the force required is divided into three axes.
In this illustration, the angular mass along the X axis is much larger than Y and Z, so in to rotate around this axis you need much more force than the other two axes.
There is however only 1 value for \"guide strength\". You can think of this force as being distributed across each axis, relative its mass.
For example, if your Guide Strength
is 10.0, then the distribution might look something like this.
X Strength = 10\nY Strength = 2\nZ Strength = 1\n
Whereas if angularMassX
was equal like a square cube..
X Strength = 10\nY Strength = 10\nZ Strength = 10\n
In light of this, what are your options?
angularMass
The least intrusive but perhaps most complex option is to manually specify a preferred angular mass.Here's the scene and one more gif to keep you warm at night.
Some things to experiment with:
Guide Strength
was halved?Guide Strength
on her hip?Guide
to her head?Stumbled upon this (thanks Jarl!) which I think is a great example of what I think we're ready to move away from as an industry. :)
Here's a prediction for you - about a year from now, you won't be keyframing anymore. You'll be recording.
"},{"location":"releases/2020.12.07/","title":"Dynamic Control Improvements","text":"Small release with important changes if you use Dynamic Controls on complex rigs with pre-existing animation.
Non-destructive guidance from your original animation when making active rigid bodies. This works much like Dynamic Control, except the guidance is in worldspace. :)
Look at this example of driving an IK handle with physics.
You can blend between simulation and animation using the blendSimulation
node in the Channel Box.
Change shape type, after creation. No matter the starting type.
In the previous release, I added an option for generating dynamic controls as capsules instead of using the actual NURBS geometry. The usecase is for controls that don't have enough geometry to sufficiently wrap around the underlying geometry.
This release enables the user to switch between capsules and mesh after having made the dynamic control. Previously, it was only possible to switch from Capsule to Mesh, not the other way around.
"},{"location":"releases/2020.12.07/#dynamic-control-and-undo","title":"Dynamic Control and Undo","text":"You couldn't undo, now you can.
I found and patched a nasty bug that affected any Dynamic Control - and in fact any Rigid - created with anyhting that had pre-existing animation or connections of any kind, breaking undo.
"},{"location":"releases/2020.12.07/#dynamic-control-and-orient","title":"Dynamic Control and Orient","text":"Orientations were whack, now they're back.
Previously, the orientation of dynamic controls were determined by the physical hierarchy of the control. If the immediate parent was the expected parent control, all was well. But in real-world rigs, there are typically several intermediate groups - some empty, some constrained, some offsets. In such cases, the immediate parent can't be assumed to be the visible parent control the animator sees on screen.
This releases solves this by treating the user-selection as the hierarchy, regardless of what the actual hierarchy looks like. This means you the animator get to control how things are oriented, just like you control what is to be simulated.
"},{"location":"releases/2020.12.18/","title":"Documentation","text":"Documentation documentation documentation!
maya.cmds
Ctrl + Shift + Click
This version expires January 10 2021
"},{"location":"releases/2020.12.18/#documentation","title":"Documentation","text":"Since the last release I've added a boatload of documentation to Ragdoll, including the very website you are visiting now!
This is where I'll aggregate anything there is to know about Ragdoll, including links to the upcoming forums and chat rooms, YouTube series and more. More more more!
Documentation is generated dynamically from the same source used to generate the in-Maya menu and graphical dialogs, so whenever you want quick help from within Maya without breaking your flow, you can! And when you're on the train without access to Maya wanting to know more about a particular button or feature, you can!
Overview "},{"location":"releases/2020.12.18/#help-page","title":"Help Page","text":"Every menu item now comes with the Help
sub-menu active.
The page can also be accessed by clicking on the top description.
I also added hints to the labels of attributes, rather than just the widgets themselves.
All of the information is generated from the same source as the website, so they'll tell you the same thing except closer to where you are.
For example, the Active Rigid
menu item:
Multiple videos are now visible in the UI, to shed more light onto how things work.
Hints
Hovering over the currently playing video displays a description of what it is about.
Real-time scrubbing
I've added real-time scrubbing too!
The caveat however is that it consumes a lot of RAM, this dialog of about 1,000 frames takes 1.5 GB of RAM, and a hefty delay to showing the option dialog.
"},{"location":"releases/2020.12.18/#api-and-cmds","title":"API and cmds","text":"The API used to take and return instances of cmdx
, the high-performance alternative to PyMEL. The API now integrates seamlessly with maya.cmds
, both taking and returning node paths (i.e. strings) rather than instances, which means you can now do this!
from maya import cmds\nfrom ragdoll import api as rd\n\ncube, _ = cmds.polyCube()\ncmds.move(0, 10, 0)\ncmds.rotate(35, 50, 30)\n\nscene = rd.createScene()\nrigid = rd.createRigid(cube, scene)\n\ncmds.evalDeferred(cmds.play)\n
The performance advantage of cmdx
is still intact, and can be accessed via commands.py
which contains identical members and argument signatures, except returning instanced of cmdx
instead. This is what's used internally for both performance and readability.
In addition, there is now support for interactive.py
for quick-and-dirty one-off scripts. This module contains all of what is provided by the Ragdoll menu and work similarly to api.py
except they take (1) user selection and (2) user preferences into account.
Menu items can now be added to the shelf by holding Ctrl + Shift + Click. Menu items also reveal the equivalent Python command to use for your scripts!
"},{"location":"releases/2020.12.18/#helper-warnings","title":"Helper Warnings","text":"If nodes have custom pivots or if your Maya scene is set to DG evaluation mode, Ragdoll will tell you about why that's a bad idea.
"},{"location":"releases/2021.01.04/","title":"Licencing","text":"This release introduces proper licencing to Ragdoll.
Happy New Year, the year of Ragdoll. :)
I've launched the next generation of Ragdoll's website. Something a little more flashy and intended to wet people's appetite for what lies ahead. Feel free to tell people about it, I've added a note about when it'll become a reality.
Also see this news coverage happening in Japan! :D
The old website can still be accessed, although it is a little crippled.
If any link fails, just make sure it's prefixed with ragdoll-web/
as the landing page, e.g. https://alanjfs.github.io/ragdoll-web/howto
Ragdoll is growing up and now understands the \"product key\" which means users can now purchase a copy and register it to themselves.
Here's the short version, with a longer version below.
Now let's cover the nitty gritty details, at the time of this writing.
You won't notice a change, other than a new UI.
Rather than Ragdoll expiring on a fixed date, it'll now expire 30 days after first launch, unless you activate.
Activation requires a product key
which you get by either purchasing a licence or being really awesome.
On first launch, Ragdoll will try and connect to the Ragdoll Licence Server (internet connection required, offline activation coming soon) and register your trial version. This version is node-locked to the particular machine you are on. It'll stick with the machine even across re-installs of your operating system.
Once you've acquired a product key, you can either:
Ragdoll
menu item (bottom)Activate
Or if you prefer:
from ragdoll import licence\nlicence.activate(key)\n
"},{"location":"releases/2021.01.04/#can-i-use-it-on-more-than-one-machine","title":"Can I use it on more than one machine?","text":"Yes. You can activate and use Ragdoll on up to 3 machines. You just can't run a simulation on more than 1 at a time, that could lead to suspension of the licence.
"},{"location":"releases/2021.01.04/#can-i-move-a-licence-between-two-machines","title":"Can I move a licence between two machines?","text":"Yes. If you've activated 3 licences, you can hit the Deactivate
button (which is same as the Activate
button once you've actiavted) and the activation will be released.
Yes and no.
That key is all that is required to run Ragdoll on any machine. If someone takes your key and activates 3 of their own machines, you won't be able to activate it yourself. If this happens, email us with proof of ownership (e.g. via the email used when purchasing) and you'll get a new one.
"},{"location":"releases/2021.01.04/#can-i-have-a-floating-licence","title":"Can I have a floating licence?","text":"Yep, get in touch with licencing@ragdolldynamics.com. Later on, these will be as trivial as node-locked licences. All I need is you.
"},{"location":"releases/2021.01.04/#can-i-activate-offline","title":"Can I activate offline?","text":"Yes. As soon as someone needs it, I'll add it. Get in touch with licencing@ragdolldynamics.com
Offline will be a 4-step process.
activation_request_to_file()
from you local machineactivate_from_file(fname)
on the same local machine.Floating offline is also be possible, again get in touch.
"},{"location":"releases/2021.01.04/#when-exactly-is-internet-required","title":"When exactly is internet required?","text":"A connection is made in one of two separate occasions.
ragdoll.licence.install()
install()
is typically called on Maya startup when the plug-in is loaded and menu is installed. You can disable this.
That is, Maya can open a scene with Ragdoll in it without making a connection to the internet if neither of these things happen. This means you can simulate on one machine, bake or otherwise disable the solver and send it off to a farm (e.g. local or cloud) without worrying about licences.
The alternative would be having to erase any trace of Ragdoll from a scene which would be such a pain.
"},{"location":"releases/2021.01.04/#can-i-manage-my-licence-via-python","title":"Can I manage my licence via Python?","text":"Sure can, see below.
"},{"location":"releases/2021.01.04/#licence-api","title":"Licence API","text":"As a user, you'll generally use the UI. But the UI is ultimately making calls to Python (which is making calls to C++) and you can bypass the UI using these same calls.
from ragdoll import licence\n\n# Called once before calling any other licencing function\n# This is automatically called on Ragdoll Python initialisation\n# and simulation start, but needs calling manually if simulation\n# hasn't yet started.\nlicence.install()\n\n# Retrieve the currently activated product key\nlicence.current_key()\n\n# Activate using your product ket\nlicence.activate(key)\n\n# Deactivate whatever key is currently activated\nlicence.deactivate()\n\n# Dictionary of useful information\ndata = licence.data()\n\n{\n # Same as current_key\n \"key\"\n\n # Is the current licence activated?\n \"isActivated\"\n\n # Is the current licence a trial licence?\n \"isTrial\"\n\n # Has the licence not been tampered with?\n \"isGenuine\"\n\n # Has the licence been verified with the server\n # (requires a connection to the internet)?\n \"isVerified\"\n\n # How many days until this trial expires?\n \"trialDays\"\n}\n
"},{"location":"releases/2021.01.04/#locked-rotate-pivot","title":"Locked Rotate Pivot","text":"Ragdoll doesn't support a custom rotatePivot
attribute and would zero this out whenever a transform is turned dynamic. It'll provide a warning to the end user that this would happen.
But, it wasn't taking into account the rotatePivot
being connected or locked. If that happened, Ragdoll would flat out refuse and print something cryptic in the Script Editor.
This has now been fixed.
Ragdoll still doesn't actually support a custom rotate pivot. So this fixes only the situation where..
rotatePivot
is zero (default), and..rotatePivot
is lockedHighlight for this release are the new Multiplier Nodes!
Rotate Limit
of Dynamic Controls? No longer!Work procedurally, with this centralised place to edit any number of rigids or constraints simultaneously. The idea is to facilitate a top-level node which govern the overall look of your simulation; withouth having to find and select each control individually.
Workflow
Multiply Selected Constraints
(or Rigids
)The order in which you select matters, the first selection gets the node. The recommended workflow is to start with the root and work your way out. But your selection can span multiple hierarchies or even the whole character. A quick \"Select Hierarchy\" across an entire character is possible also.
A constraint and rigid can only have 1 multiplier connected at any one time.
Demo
The most common attributes are made available currently, let me know if you find something missing!
YouTube
Added these suckers for you to play around with.
Variable Description Default RAGDOLL_PLUGIN Absolute path to binary plugin, .mll on Windows .so on Linux. This overrides whatever is onMAYA_PLUG_IN_PATH
\"ragdoll\"
RAGDOLL_NO_AUTOLOAD Do not automatically load the plug-in and add the menu on startup of Maya. False
RAGDOLL_NO_STARTUP_DIALOG Do not display the startup-dialog on first launch. False
RAGDOLL_AUTO_SERIAL Automatically activate Ragdoll on install using this serial number. Unset For up to date information, see here.
Getting some more recognition on the interwebs from EnTT, the library used to keep Ragdoll fast and clean!
Now only relevant attributes are visible in the Channel Box, dynamically based on the current type.
I've added an option to disable this in the Global Preferences.
"},{"location":"releases/2021.01.14/#bounding-box","title":"Bounding Box","text":"Maya uses bounding box information to avoid drawing things that aren't visible in camera. The previous version of Ragdoll didn't provide Maya with any bounding box, which left Maya with no choice but to draw these always; even when behind the camera.
Now this isn't so. You shouldn't notice much for smaller scenes, but drawing typically consumes 20-30% of the total CPU impact Ragdoll has on your character rigs. So for larger scenes this should reap a significant performance boost.
Pro tip: You can also disable drawing of all Ragdoll primitives by disabling Locators
in your viewport; that's how Maya classifies any and all Ragdoll nodes.
TLDR; you should now experience fewer cycle warnings.
Whenever you create a rigid from any Maya node, like an animation control, Ragdoll makes a note of the position and orientation of that control. It takes into account that you may not be on the start frame when you create the control, which is what you most likely intended to do. When that happens, Maya will silently roll back time in the background to query an attribute at the start frame.
This silent roll-back has a tendency to trigger evaluation of unrelated nodes, like IK handles, which in turn trigger other nodes, ultimately leading back to where it came from, and thus cause a cycle. These were somewhat harmless, but could mask a real cycle from happening.
In this release, this silent roll back only happens when you actually aren't on the start frame. So you should see less of it. There's still room for improvement however, so if you still find warnings or any odd behaviors being due to cycles, do reach out!
"},{"location":"releases/2021.01.14/#nan","title":"NaN","text":"If you've ever gotten these, you can now rest easy. They are gone. They could happen on occasion, especially after repeated undo. It had to do with memory access violation by Maya being naughty, something it really shouldn't be able to do in the first place. We now guard against this, so all is well.
"},{"location":"releases/2021.01.15/","title":"Dynamic Control 3.0","text":"The gift that keeps on giving, the highlight for this release is Dynamic Control 3.0!
Another step forward for Dynamic Controls.
"},{"location":"releases/2021.01.15/#default-capsule","title":"Default Capsule","text":"Ragdoll now defaults to the newer Capsule
shape type for dynamic controls. It's faster and applies more generally to most rigs; even those that do have NURBS curves wrapping around the underlying character geometry.
Before
After
"},{"location":"releases/2021.01.15/#automatic-multiplier","title":"Automatic Multiplier","text":"The previous release introduced Multiplier Nodes. This release add a multiplier to each new dynamic control chain per default, on the root control, which means you can now do stuff like this!
"},{"location":"releases/2021.01.15/#centralised-blend-simulation","title":"Centralised Blend Simulation","text":"
Previously, to blend between animation and simulation you needed to select the controls to blend and edit each individually. But it's rather uncommon (and probably not very useful) to want independent control over each blend.
In this release, there is 1 central Blend Simulation
attribute on the root dynamic control. This can be changed in the Options, but will probably disappear unless someone says they like it and wants to keep it!
Previously, Ragdoll wasn't able to figure out how long to make the last control. Now it borrows length, radius and orientation from the parent capsule, which should be what you expect for the majority of cases.
Meaning you can now expect this.
Before
After
You can change the shape type after creation, and modify the default value in the options dialog.
"},{"location":"releases/2021.01.15/#transparent-root","title":"Transparent Root","text":"The first selection of a dynamic control chain is passive, and it used to also collide with the first child. But, most of the time, that root isn't useful as a collider. It would be a global hip control or some particular shoulder/clavicle gizmo.
So the root is now set to Collide = False
, meaning this is now ok.
You can still enable it afterwards if you'd like.
"},{"location":"releases/2021.01.15/#convert-and-restore","title":"Convert and Restore","text":"I've merge the Convert Rigid
and Convert Constraint
buttons into the rigid and constraint creation buttons.
Turn a passive into an active rigid, or vice versa.
Passive
to convert it into a passive rigidIf it's already passive, nothing happens. If you wanted to make a passive rigid active, you know what to do.
"},{"location":"releases/2021.01.15/#convert-constraint","title":"Convert Constraint","text":"Turn a Socket Constraint into a Hinge Constraint, or any other type, on-the-fly.
Socket
to turn it into a socket constraint, regardless of what it wasSometimes you just want to start from scratch. And using the same convert feature you can also restore a constraint to its original settings.
Spot passive rigids by their colors, now all passive rigids are gray.
That means..
Sometimes you want to make bulk changes to all rigids or all constraints at once. You could select each of them, or you could turn to Python and say..
cmds.select(cmds.ls(type=\"rdRigid\"))\n
Now there's a menu item for it too!
That means you can either find everything all at once and make great big changes, or you can zone in on a particular hierarchy or character and affect all rigids or constraints in just that hierarchy!
Fire Wolf rig courtesy of Truong CG Artist
"},{"location":"releases/2021.01.17/","title":"Hotfix","text":"Minor maintenance release.
The startup code for Ragdoll since 2021.01.14 didn't play well with other userSetup.py
files, like the ones you might have in a major production pipeline.
If you were having any issues with the os
module, then this is the fix for you.
The previous release made it possible for the last selected Dynamic Control to inherit its size and orientation from the previously selected control.
This only worked if you have 3 controls selected. This release makes it work on just 2 controls!
"},{"location":"releases/2021.01.27/","title":"Message Board","text":"Focus of this release is Solver Iterations, and some UI additions too!
Ever opened the Script Editor to find Ragdoll screaming for help? I've added a new Message Board to help Ragdoll stand out from the overall messy or hidden messages from rigs and Maya and all else.
Your goal then is to never have any messages appear in the Message Board.
A silent Message Board means a happy simulation. :)
"},{"location":"releases/2021.01.27/#solver-iterations","title":"Solver Iterations","text":"Anything called strength
in Ragdoll is a multipler for stiffness
and damping
. And currently there's a ceiling to how high stiffness
and damping
values can go, after which point they just stop having an effect.
The values are limited by how many \"iterations\" you let the solver perform. Per default, they are set to 8
and can be found at rdRigid.positionIterations
. This release sheds some more light on this somewhat obscure attribute by exposing it directly on the solver, right next to Substeps
.
This value multiplies each rdRigid.positionIterations
attribute, meaning a value of 2
yields a total iteration count for every rigid in the solver of 16
(i.e. 2 * 8
).
Which means you can now do this!
You can further customise iteration counts per rigid, under the Advanced tab.
There's no limit to how many iterations you can allow; more iterations means greater accuracy. However, I have found that values beyond 128 tend to get funky.
Iteration Count Strength Range Description8
(default) 0-5 Default, sensible for most uses 16
0-10 High 32
0-500 Really, really high 64
0-1000 Ultra Nightmare For completeness, here's how Iterations
differ from Substeps
.
They both provide accuracy in slightly different ways. With a greater amount of substeps, the solver is effectively working in slow-motion. Everything is easier in slow-motion. Resolving constraints is independent of time and a little more technical to describe, so you can instead kind of think of it a little bit like rubbing dirt of a silver platter. The first rub, you'll get most of it off. But the more you rub, the shinier it gets. There's no limit to how much you can rub, but eventually rubbing will stop having a visible effect.
"},{"location":"releases/2021.01.27/#help-line","title":"Help Line","text":"Hovering over any menu item now reveals a short description of what it does in the native Maya Help Line (typically at the bottom of the Maya window).
This is the same information as can be found in the Menu Reference.
"},{"location":"releases/2021.01.27/#delete-from-selection","title":"Delete From Selection","text":"The Delete All Physics
menu-item has gotten an option box, now it can be used to limit deletion to currently selected nodes!
The previous release would bark at you whenever trying to turn any transform dynamic if it had any of its translate
or rotate
channels locked. This was a problem when you didn't necessarily care for some of them. For example, with a dynamic control, you really only cared for the rotate
channels but would be prevented from simulating them if the sibling translate
channels were locked. No longer!
That said, the simulation does still produce both translate and rotate values. There's no way around it. And locked channels cannot be connected or edited. Even though you might want to. If the transform is referenced, then there's nothing you can do.
Warnings will be emitted (and made visible in the new Message Board!) if this happens, so it's still true that if your Message Board is silent, all is well.
"},{"location":"releases/2021.01.27/#multiple-cmdx","title":"Multiple cmdx","text":"This should only really affect users of WeightShift, which also uses cmdx
. The previous release was adamant on being the one and only physics solver for Maya. But it has now become more lenient and accepting of other lifestyle choices. :D
Heads up! This got removed. Stay tuned for a re-appearance in a later release
In the previous release, you could animate your dynamic controls, but you couldn't change the initial pose unless you explicitly called Set Initial Pose
from the Ragdoll | Rigging
menu. With this release, you can!
Limitations
This currently only works reliably with strict FK control hierarchies.
The animation is translated into an initial state, but in doing so we are effectively recreating the parent/child relationship between controls. And sometimes - perhaps a lot of times - this isn't a direct FK hierarchy.
Here you can see how the physics and animation controls disagree on what the pose should be. The animation controls aren't in a hierarchy, they are constrained in a complex manner. It isn't accurately reproduced in the initial state.
So if you notice your the simulated initial state to differ from the first pose of your animation, it's the best you can get at the moment.
"},{"location":"releases/2021.01.27/#worldspace-dynamic-control","title":"Worldspace Dynamic Control","text":"Heads up! This got removed. Stay tuned for a re-appearance in a later release
Guide forces in dynamic controls are all local. Which means it'll maintain a pose, even if that pose is upside down or sideways.
And since many versions ago, you've been able to append these \"Guide\" controls, that are in worldspace (per default). These look at the worldspace position and rotation of the control, and use that to line up the simulation. Much like IK!
Now these are built-in to each Dynamic Control (toggle in the option dialog).
These can help keep a character closer to an animated pose. But they are \"cheats\". Forces that appear out of nowhere, as opposed to the local forces which behave like muscles. Muscles can tense and relax whilst still appearing natural, but these are not natural. You can however use them to fake natural.
One more thing; world spaces have strength in either translation or rotation, or both. A worldspace rotation could for example keep a head facing a certain direction, not unlike how IK works. Except physical!
Limitations
This feature uses the same \"virtual hierarchy\" as the animated initial state and suffers from the same limitations.
"},{"location":"releases/2021.02.07/","title":"Scale","text":"Highlight of this release is Support for Scale!
This has been an epic challenge, but it finally happened!
Up till now, any scale other than (1, 1, 1) at any level of a hierarchy would have either broken a simulation or refused to work outright. Not anymore! Now you can simulate scaled transforms, including scaled rigs and all of what it entails.
Here's a brief on what works and what doesn't.
Feature Example \u2714\ufe0f Uniform Scale1.5, 1.5, 1.5
\u2714\ufe0f Non-uniform Scale 0.5, 0.6, 0.12
\u2714\ufe0f Scaled parent(s) Scaled root control \u2714\ufe0f Mixed Scale & Constraints Scaled box to differently-scaled capsule \u2796 Zero Scale 0.0, 0.0, 0.0
\u2796 Mixed Zero Scale 1.0, 0.0, 1.0
\u2796 Negative Scale -1.5, -1.5, -1.5
\u2796 Mixed Positive/Negative Scale 0.9, -1.5, -1.1
\u2796 Non-uniform Negative Scale -1.0, 1.0, -2.0
\u274c Non Object-Space Scale Scale in World
mode There are a few caveats.
Commonly found in parent hierarchies that attempt to mirror the behavior of a control or hierarchy of controls. I'd like to better support this, but it is currently limited by math. More specifically, in that a transformation matrix simply cannot distinguish between negative and positive scale.
So this one is semi-supported. The problem is for Ragdoll to distinguish between scale and rotation. It's a bit mathy, but you know how you can achieve the same pose by either scaling something negatively or rotate it 180 degrees along one or more axes? Ragdoll currently cannot know which of the possible outcomes you wanted.
Here's a visual to help illustrate this point. (Reference)
Here's what can happen in practice.
Notice how both the scale and rotation values changed, even though the object in the viewport remains in the same orientation. That's because these values are both correct scale and orientation for this particular transform.
You might think..
Well, whatever. So long as it's oriented right, why should I care?
Well, what if you had animated a realistically looking horse locomotion, rotating around the X-axis?
Did you spot it? Both X and Z got their scale neutralised and X got 180 degrees steeper, compensating for the neutralised scale values. Also Z got flipped too! You can work around it, by accepting the new Z and offsetting your animation by 180 degrees.
There's also the issue with it flying off for the first few frames. It's unclear why this happens, this may be a bug in the solver itself, trying to reconcile an orientation that is 180 degrees wrong.
So, negative scale works, but it's painful. Avoid if possible.
"},{"location":"releases/2021.02.07/#zero-scale","title":"Zero Scale","text":"This is \"supported\" in that it doesn't fatal crash your Maya session. Ragdoll is a 3D solver, it cannot operate on anything without volume and mass.
Here's an example of what to expect should you find the need for zero scale.
"},{"location":"releases/2021.02.07/#scaled-rotation","title":"Scaled Rotation","text":"TLDR; if you animate something from 0-45 degrees, it will rotate 45 degrees, regardless of scale.
This should be what you expect and won't need remembering, but for completeness here's what happening under the hood.
Ragdoll strips scale from most internal computations. It's kept mostly so that it can be outputted again, as well as for rendering. See, custom Maya nodes render in the space of the transform. So rendering a point at coordinate (0, 0, 0) ends up in the middle of the transform node. Even as you move that transform around with the translate tool. That's problematic if you need to draw something uniformly, like the limits and drive visualisations. Even more so when you attempt to draw a line from one transform to another.. at different scales!
But stripping it early is beneficial for both readability of code, but also usability for you. Uniform scale normally doesn't affect rotation, but non-uniform scale could.
Consider this.
Here, we've got a single angle of 45 degrees. If you were to scale this horizontally, you can see how the angle now changes! At a scale of 0, the angle has gone from 45 degrees to 90 degrees.
This complicates things a lot, and Ragdoll saves you from that by not taking non-uniform scale into consideration for its rotations. A 45 degree angle will remain 45 degree regardless of scale; with the exception of negative scales which still flip the angle as you'd expect.
"},{"location":"releases/2021.02.07/#non-object-space-scale","title":"Non Object-Space Scale","text":"You probably don't do this, but for completeness here's what doesn't work.
"},{"location":"releases/2021.02.07/#nurbs-surfaces","title":"NURBS Surfaces","text":"
Ragdoll could translate polygon meshes and NURBS curves into collision meshes, and today I'm happy to announce that it now also supports the latest trend in computer graphics, heavily used in the 90s at Dreamworks for critically acclaimed feature animation films Antz and Shark Tale.
Join the future!
"},{"location":"releases/2021.02.07/#output-attributes","title":"Output Attributes","text":"The Attribute Editor now displays the output translate, rotate and scale attributes from each rigid body. In both local and world space coordinates.
These are the values that feed into your animation control, or any transform you're simulating.
"},{"location":"releases/2021.02.07/#zombie-attributes","title":"Zombie Attributes","text":"Minor bug fix.
The Delete All Physics
menu item didn't catch the last remaining Local Strength
attribute created by Create Dynamic Control
. This is all patched up!
It's been an epic month of problem-solving, but it finally happened. :D Highlight for this release is.. drumroll.. Automatic Initial State!
Tiger Rig courtesy of www.cgspectrum.com
"},{"location":"releases/2021.03.01/#auto-initial-state","title":"Auto Initial State","text":"Have you ever used the Set Initial State
button? It's useful, isn't it? It's what enables you to turn something dynamic but then change your mind about where it should start simulating.
With this release, that process is automatic! It's more or less what you expected would happen anyway. I mean, obviously the box should drop from where you left it, rather than where it was originally turned dynamic?
"},{"location":"releases/2021.03.01/#disable-feature","title":"Disable Feature","text":"If you would rather have none of it, or if it gives you trouble, you can switch it off like this.
NOTE: Changes take effect on next scene open and newly created rigids.
"},{"location":"releases/2021.03.01/#parallel-only","title":"Parallel Only","text":"That's right, automatic initial state will only work in Maya's Parallel Evaluation mode.
It may end up getting support for DG later on, the trouble lies in the callback we use to read an edited initial state is not reliable in DG. It's possible we'll find another means of achieving the same goal in the future, although DG really is part of the past. Ragdoll works best under Parallel for other reasons too; primarily performance but also stability and robustness.
"},{"location":"releases/2021.03.01/#constraints-stay-behind","title":"Constraints Stay Behind","text":"Constraints currently show you the true position of rigid bodies.
They stay behind because hierarchy preservation is \"artificial\". It's just for you and Maya. In a later release, I'll make rigids also stay behind, and only have your controls move with hierarchy, so that you get to visualise where rigid bodies really are (even when your controls have locked channels, like translate) whilst at the same time letting you move and see your controls and how they reflect that true position.
"},{"location":"releases/2021.03.01/#caveat","title":"Caveat","text":"There's one known \"gotcha\" with the automated initial state.
Namely, the initial state is \"recorded\" whenever you transition from the start time to the next frame. Evaluation on the next frame will automatically read whatever was evaluated previously, and store that as the initial state.
However! It is possible to trigger evaluation without actually changing time. Maya loves doing that. You can do it by either scrubbing the timeline, or holding K
and dragging (effectively scrubbing) the viewport. As you scrub, even if time isn't actually changing, Maya will go ahead and re-evaluated the time.
When that happens, it won't actually record a new initial state, but instead restore the original value. Something to be aware of.
"},{"location":"releases/2021.03.01/#journey","title":"Journey","text":"For the technically inclined, here you can witness last month's struggle first hand and all the kinks uncovered in Maya's API and evaluation graph.
"},{"location":"releases/2021.03.01/#hierarchy-preservation","title":"Hierarchy Preservation","text":"Like in the real world, physics happens in worldspace. There are no \"children\" and no \"parents\". As a result, as soon as you turn any of your controls dynamic, they start acting that way. But we don't want that.
With this release, you'll now get realism along with that familiar feeling of having children and being a parent!
Before
After
"},{"location":"releases/2021.03.01/#caveat_1","title":"Caveat","text":"There is one known case to be aware of when it comes to children.
Passive Rigids
Hierarchy is currently preserved only if a rigid is active. The reason being.. well, I'll just show you.
In this case, the passive rigid bodies are driven by an external transform, those blue \"controls\". Hierarchy is coming from the blue rigids, so we wouldn't want the passive rigids to mess with that.
But now when we move the rigids themselves (gray, in this example) we aren't getting our hierarchy preservation.. :(
At the other extreme, if we do account for hierarchy then the problem pops up at the other end instead.
I trust experience and feedback will light the way here for a more intuitive experience working with external controls.
"},{"location":"releases/2021.03.01/#worldspace-constraints","title":"Worldspace Constraints","text":"If you thought automatic initial state was enough, think again! If your controls have animation already applied, Ragdoll will now translate it into physics in world- and local-space.
"},{"location":"releases/2021.03.01/#default-behavior","title":"Default Behavior","text":"Local animation, like a rotated arm, are imbued with a \"local constraint\" to preserve the relative angle between it and its parent. World animation, like in this case where there is no parent, get imbued with a \"world constraint\".
"},{"location":"releases/2021.03.01/#world-only","title":"World Only","text":"Here's what you get when constraining the child to its worldspace pose. Notice how it assumes the angle you give it regardless of whatever the parent is doing.
"},{"location":"releases/2021.03.01/#local-only","title":"Local Only","text":"Conversely, with just the local constraint, it'll assume the relative angle and respects its parent.
"},{"location":"releases/2021.03.01/#world-local","title":"World + Local","text":"Things get interesting when you combine the two!
"},{"location":"releases/2021.03.01/#world-world-local","title":"World + World + Local","text":"..or combine the three! Here's the lower arm trying to adhere to both its worldspace and local orientation. Notice the constraint coming out of alignment at the root; the constraints are of equal strength per default so it'll end up averaging the desired poses.
There's one more thing happening here that I'll touch on in an upcoming release, which is the concept of world space forces. Notice how the joint chain follows animation
"},{"location":"releases/2021.03.01/#dg-viewport-bug","title":"DG Viewport Bug","text":"If you've ever had the viewport \"remember\" old frames as you scrub the timeline, this fix is for you.
"},{"location":"releases/2021.03.01/#unload-plug-in","title":"Unload Plug-in","text":"In the previous release, licencing was implemented as a Python binding. The trouble with compiled Python bindings in Maya is that they cannot be unloaded. As a result, Ragdoll could not be unloaded.
Licencing is now implemented as a native Maya command, accessible as ragdollLicence
from MEL and cmds.ragdollLicence()
from Python.
Three new commands was added in this release, they are primarily intended for TDs and technically minded folk.
cmds.ragdollLicence()
cmds.ragdollPeek()
cmds.ragdollDump()
Synopsis: ragdollLicence [flags]\nFlags:\n -q -query\n -a -activate String\n -d -deactivate \n -h -help \n -i -init \n -ia -isActivated \n -ig -isGenuine \n -it -isTrial \n -iv -isVerified \n -md -magicDays \n -r -reverify \n -s -serial \n -td -trialDays \n
You still typically interact with ragdoll.licence
, as documented here. But under the hood, this is now the native Maya command being called.
from maya import cmds\ncmds.ragdollLicence(serial=True, query=True)\n# Your-Serial-Number-Here\n
"},{"location":"releases/2021.03.01/#cmdsragdollpeek","title":"cmds.ragdollPeek","text":"Synopsis: ragdollPeek [flags]\nFlags:\n -e -entity UnsignedInt\n -h -help \n -ps -physicsStatistics \n -ss -sceneStatistics\n
Gain insight into what Maya sees in Ragdoll.
cmds.ragdollPeek(sceneStatistics=True)\n\n# Ragdoll Peek Scene\n ____________ ___________________________ _______________\n| Id | Scene | Name |\n|------------|---------------------------|---------------|\n| 71 | rSceneShape | rSceneShape |\n| 70 | rSceneShape | rRigid18 |\n| 69 | rSceneShape | rRigid17 |\n| 67 | rSceneShape | rRigid |\n| 65 | rSceneShape | rRigid7 |\n| 63 | rSceneShape | rRigid8 |\n| 61 | rSceneShape | rRigid14 |\n| 59 | rSceneShape | rRigid15 |\n| 57 | rSceneShape | rRigid16 |\n| 55 | rSceneShape | rRigid11 |\n| 53 | rSceneShape | rRigid12 |\n| 51 | rSceneShape | rRigid13 |\n| 49 | rSceneShape | rRigid9 |\n| 46 | rSceneShape | rRigid10 |\n| 44 | rSceneShape | rRigid4 |\n| 42 | rSceneShape | rRigid5 |\n| 40 | rSceneShape | rRigid6 |\n| 38 | rSceneShape | rRigid1 |\n| 36 | rSceneShape | rRigid2 |\n| 34 | rSceneShape | rRigid3 |\n| 15 | rSceneShape | rRigid27 |\n| 14 | rSceneShape | rRigid28 |\n| 13 | rSceneShape | rRigid29 |\n| 12 | rSceneShape | rRigid30 |\n| 11 | rSceneShape | rRigid31 |\n| 10 | rSceneShape | rRigid32 |\n| 9 | rSceneShape | rRigid33 |\n| 8 | rSceneShape | rRigid34 |\n| 7 | rSceneShape | rRigid19 |\n| 6 | rSceneShape | rRigid20 |\n| 5 | rSceneShape | rRigid21 |\n| 4 | rSceneShape | rRigid22 |\n| 3 | rSceneShape | rRigid23 |\n| 1048576 | rSceneShape | rRigid24 |\n| 1048578 | rSceneShape | rRigid25 |\n| 1048577 | rSceneShape | rRigid26 |\n|____________|___________________________|_______________|\n
cmds.ragdollPeek(physicsStatistics=True)\n\n# Ragdoll Peek Solver\n- Number of scenes: 1\n- Number of shapes: 36\n- Number of materials: 36\n- Number of convex meshes: 0\n- scene[71]\n - Number of dynamic actors: 35\n - Number of static actors: 1\n - Number of constraints: 18 # \n
"},{"location":"releases/2021.03.01/#cmdsragdolldump","title":"cmds.ragdollDump","text":"Synopsis: ragdollDump\n -h -help \n
This is more of a teaser of what's to come, but let me tell you about it for completeness of these release notes.
ragdollDumps
is the start of an integration effort of Ragdoll into any and all external software, like Unreal and Blender. Anything able to parse JSON. Including web-applications.
What if you could rig and/or animate in Maya, but then export the physics setup into e.g. Unreal? I'm not talking about baking your animation and playing it back somewhere else. But of exporting the internal physics objects from Ragdoll, translating them to whatever the third-party software uses for physics, and re-using it there!
With that, you could bypass all of the horrible authoring tools of those applications and transfer a physics scene or setup across applications.
Later, you'll be able to load these into a standalone Ragdoll desktop and web-based application. Useful for sharing your creations and animations with others, and for debugging too!
import json\nfrom maya import cmds\n\ncmds.ragdollDump()\n# {\n# \"scenes\": {\n# \"0\": {\n# \"id\": 0,\n# \"name\": \"rSceneShape\",\n# \"entities\": {\n# \"0\": {\n# \"id\": 0,\n# \"components\": {\n# \"NameComponent\": {\n# \"type\": \"NameComponent\",\n# \"members\": {\n# \"value\": \"rSceneShape\"\n# }\n# }\n# }\n# },\n# \"1\": {\n# \"id\": 1,\n# \"components\": {\n# \"NameComponent\": {\n# \"type\": \"NameComponent\",\n# \"members\": {\n# \"value\": \"rRigid\"\n# }\n# }\n# }\n# },\n# \"2\": {\n# \"id\": 2,\n# \"components\": {\n# \"NameComponent\": {\n# \"type\": \"NameComponent\",\n# \"members\": {\n# \"value\": \"rGuideConstraint\"\n# }\n# }\n# }\n# }\n# }\n# }\n# }\n# }\n
Turn this string into json, with the native Python json
module.
import json\nfrom maya import cmds\n\ndump = cmds.ragdollDump()\ndump = json.loads(dump) # From string to dictionary\n\n# The format is internal and yet to be documented, stay tuned\nscene = dump[\"scenes\"][\"0\"]\nrigid = scene[\"entities\"][\"1\"]\nname = rigid[\"components\"][\"NameComponent\"][\"members\"][\"value\"]\nprint(name)\n# rRigid\n
Expect the output to grow throughout later releases as more internals get serialised to JSON.
"},{"location":"releases/2021.03.04/","title":"Passive to Active Transitions","text":"Small fixes and tweaks, with one pretty cool new feature - the ability to animate the transition between active and passive mode for any rigid!
Active rigid bodies can now be made passive interactively, and continue to be animated as passive, and then - here's the cool part! - once they transition from passive to active, they inherit the animated velocity you gave it!
Pay special attention to the fact that we can key the simulated values, such that we can continue animating from exactly where they left off. Making for a clean transition both to and from physics!
"},{"location":"releases/2021.03.04/#more-scene-visualisation","title":"More Scene Visualisation","text":"The rdScene
node has been able to draw velocities, trajectories and constraints to help you track down problems or gain better insight into the inner workings of the solver. Now it can also draw the current position and orientation of rigids, regardless of where your animation controls are.
This can be especially helpful if your controls have locked channels, such as translate, as they would be unable to show you the translation of the physical version of the control.
Here's how it works.
See how the box as-seen from the scene falls down, whereas the original box doesn't? Because the translate channels were locked, they weren't able to fully represent the simulation.
Here's a more practical example of a tail.
Notice that because the translate channels of the tail are locked, they remain positioned according to the rig. And the rig has some clever mechanics going on to keep the tail attached to the body even when the hip control moves away.
Here's a close-up of that mechanic.
The solver shows you what is actually going on physically and can help track down controls that misbehave.
"},{"location":"releases/2021.03.04/#better-scaled-shape-rendering","title":"Better Scaled Shape Rendering","text":"Small, but important. When you scale things, rendering needs to keep up and descale the normals of the geometry.
"},{"location":"releases/2021.03.11/","title":"Localspace Simulation","text":"Highlight for this release is Local Space Simulation!
Sunny Side Up
Just a wolf, for breakfast.
Waterproof Fire Fox
If you squint, it almost looks like he's underwater!
Collision Volumes
The automatically-generated colliders you get when turning animation NURBS controls dynamic.
"},{"location":"releases/2021.03.11/#ragdog-tutorial","title":"Ragdog Tutorial","text":"That's no typo, this is a Ragdoll-dog! :D Learn about how to achieve the above simulation in this 2-part series on using Dynamic Control.
Spotted an animation on LinkedIn the other day by Radovan Zivkovic, and wanted to see whether it would work with Ragdoll. Here's about 15 minutes of work from launch of Maya to final playblast.
TLDR; This will keep simulation of children intact whilst manipulating parents.
Up until this release, simulation has taken place in worldspace. The last few releases has tried translating worldspace into localspace to try and mimic that familiar feeling of moving the parent and having children follow.
This release moves simulation altogether into local space which means a seamless integration with he parent/child hierarchy that your animation controls are normally in!
"},{"location":"releases/2021.03.11/#before","title":"Before","text":"Pay special attention to how you can edit the master control mid-way through a simulation, but then have that change completely ignored as you return to frame 1.
"},{"location":"releases/2021.03.11/#after","title":"After","text":"Now, with simulation resting in the local space, it behaves as you would expect.
"},{"location":"releases/2021.03.11/#rotate-order-warning","title":"Rotate Order Warning","text":"A while back, support was implemented for a custom rotateOrder
, such as ZYX
or YXZ
. As it turns out, this support was rather incomplete. Solving for a custom rotate order is much more involved than I'd hoped it would be, so for the time being you are advised not to use them.
If you do, you may run into issues such as this.
"},{"location":"releases/2021.03.11/#animated-rigid-attributes","title":"Animated Rigid Attributes","text":"The previous release broke your ability to animate anything on a rigid, e.g. rdRigid.linearDamping
. That's been all patched up!
A bug in a prior version caused frames ahead of the start frame to not reset correctly, unless you explicitly visited the start frame. E.g. skipping from frame 100 directly to 1 rather than from 2 to 1 wouldn't look right. Coupled with the next auto-initial-state feature, this could break a pose. This has now been patched up!
"},{"location":"releases/2021.03.11/#explosion-on-initial-state","title":"Explosion on Initial State","text":"Ragdoll could mistakenly treat a broken simulated first frame as the new and correct initial state. Detecting that stuff is hard! Now it's doing a better job, but keep an eye out for when your start pose breaks, that should never happen.
Also don't forget that this fancy new shiny feature can be disabled under Ragdoll -> System -> Ragdoll Preferences.
"},{"location":"releases/2021.03.11/#shear","title":"Shear","text":"The enemy of any animation, shear is scale's ugly brother. Ragdoll now accounts for shear, even though you are strongly advised never to introduce it willingly.
"},{"location":"releases/2021.03.23/","title":"JSON Export","text":"Highlight for this release is JSON Export, this one's for you game developers out there!
Important!
This version won't self-install like the past releases, see Dynamic Install on how you need to load the plug-in via Maya's Plug-in Manager from now on.
Ragcar
It's a ragcar allright. You can tell by how bouncy it is!
Knocking things around
No obstacle is too tall for ragcar.
A look underneath
The parts are all there, it's how it would work in real life if you put an engine in it. :D
Vehicle model from Mecabricks.
"},{"location":"releases/2021.03.23/#json-export","title":"JSON Export","text":"In 2021.03.01 we introduced cmds.ragdollDump
to get a copy of all rigids in the form of a JSON dictionary.
This release includes all initial state for the simulation, such that you can reproduce the results you see in Maya in a game engine, like Unreal, Unity, CryEngine or your own custom game engine. Or why not Houdini, Blender or 3dsMax?
This enables you to use Maya as an authoring platform for physics anywhere.
from maya import cmds\ndump = cmds.ragdollDump()\n\n# Convert big string to structured dictionary\nimport json\ndump = json.loads(dump)\n\nfor entity, data in dump.items():\n components = data[\"components\"]\n name = components[\"NameComponents\"][\"members\"][\"path\"]\n print(name)\n\n# |root|pelvis|rRigid1\n# |root|pelvis|spine|rRigid2\n# |root|pelvis|spine2|rRigid3\n# ...\n
Here's an example of what to expect from the output.
output_example.json
{\n \"entities\": {\n \"10\": {\n \"components\": {\n \"NameComponent\": \"upperArm\",\n \"ColorComponent\": [1.0, 0.0, 0.0],\n \"GeometryDescriptionComponent\": \"Capsule\",\n ...\n }\n },\n \"15\": {\n \"components\": {\n \"NameComponent\": \"lowerArm\",\n \"ColorComponent\": [0.0, 1.0, 0.0],\n \"GeometryDescriptionComponent\": \"Box\",\n ...\n }\n }\n}\n
See the new Serialisation documentation for an overview, examples and data reference.
Previous releases shipped with a userSetup.py
that triggered on launch of Maya. This made it easy to get setup, but made it challenging to uninstall without physically removing files off of the file system (hint: ~/Documents/maya/modules/Ragdoll.mod
).
This release associates install with plug-in load.
Install
Uninstall
"},{"location":"releases/2021.03.23/#active-chain","title":"Active Chain","text":"Dynamic Control has been renamed Active Chain
.
Turns out, what Dynamic Control was really all about was a generic chain that can also be turned into hierarchies of chains - or \"branches\" - to form a tree. Even a literal one!
"},{"location":"releases/2021.03.23/#dynamic-constraint-attributes","title":"Dynamic Constraint Attributes","text":"
Now whatever attributes are relevant show up in the Channel Box, and stay relevant as you make changes. Similar to how the rdRigid.shapeType
attribute updates the shapeExtents
and shapeOffset
attributes!
Ragdoll now understands when the up-axis is Z rather than the default Y.
"},{"location":"releases/2021.03.23/#simplified-menu","title":"Simplified Menu","text":"Items have been re-arranged and grouped together to be easier to find and less cluttered.
"},{"location":"releases/2021.03.23/#greater-guide-strength","title":"Greater Guide Strength","text":"The solver Iterations
determines how high your Guide Strength
attribute can go. Per default, Iterations
was set to 1
which enabled strengths between 0-5
or so until their effect dimished.
This release increases this default value to 4
for ranges between 0-100
, which means \"incredibly high!\". The change comes at a minor performance impact - estimated between 1-5% - so if you find the need to optimise, lower this value back to 2 or 1.
Hint
Bear in mind that the number of iterations are spread across all rigid in your scene. Meaning twice the number of rigids would half the amount of iterations dedicated to each one.
"},{"location":"releases/2021.03.23/#before","title":"Before","text":""},{"location":"releases/2021.03.23/#after","title":"After","text":""},{"location":"releases/2021.03.23/#crash-on-cleanup","title":"Crash on Cleanup","text":"In rare cases, Ragdoll could crash Maya due to accessing memory it had no business accessing. Those have now been patched up and refactored for a more stable, crash-free experience!
"},{"location":"releases/2021.03.23/#bad-initial-state-on-load","title":"Bad Initial State on Load","text":"In rare cases, opening a scene could lead to some controls being badly positioned. This could happen if the control you made dynamic was parented to a group with no values. That made the parent and local matrices cancel out, producing an identity matrix. Maya doesn't normally save attributes that are equal to their default values, and this includes matrices whose defaults are the identity matrix.
This has now been fixed.
"},{"location":"releases/2021.03.23/#rotate-order-improvement","title":"Rotate Order Improvement","text":"In previous releases, any rotation order other than XYZ (the default) would make your rotations all whack. Ragdoll didn't know how to translate physics into any order other than XYZ, so it would put them in the wrong place.
In the last release, I added a warning for that and in this release I've lifted that warning somewhat. Most rotation orders works well, but I have spotted rare instances of one axis flipping.
Here's the problem.
See how arms and torso flips? It tends to happen around the 90 and 180 degree values, values below that normally look fine. This will be fixed in a future release, one way or another!
"},{"location":"releases/2021.03.25/","title":"Maya 2022","text":"Highlight for this release is support for Maya 2022!
cmds.ragdollDump()
Ready when you are, Python 3 and all!
"},{"location":"releases/2021.03.25/#ragdoll-on-github","title":"Ragdoll on GitHub","text":"Ragdoll is a high-performance C++ plug-in with a flexible Python API.
The API is what powers all user interfaces and all menu items, including the tools themselves. It's what generates Ragdoll nodes and hooks them up to other nodes, translating your selection into physics.
This API is now available on GitHub and will soon open for contributions too!
What does breaking backwards compatibility of a dynamics solver look like?
Original
Last Release
He's the same person! Only the circumstances have changed. :D This has now been fixed, and all previous examples now open and run as expected!
Still pretty cool though I thought, that even though it's broken it still gives you an interesting result. Look at how he initially falls over, it looks like he's attempting to hold onto the seat for balance, and also takes a step back before landing on his butt. :D
"},{"location":"releases/2021.03.25/#accurate-gravity","title":"Accurate Gravity","text":"The indicator used to face in the Y-axis of wherever the node was facing. That wasn't true. It's now accurate no matter how you spin it around, including a potential Z-up axis!
Before
After
"},{"location":"releases/2021.03.25/#ragdoll-explorer","title":"Ragdoll Explorer","text":"Added an early version of a visual interface for the cmds.ragdollDump()
command, something to inspect the internals of the solver. Mostly intended for game developers but also advanced users and techincal directors. Expect an Outliner-like appearance and use for this explorer, more to come!
Highlight for this release is import of physics from one character to another!
Head's up Game Developers
NameComponent
was changed, and entity
values are now a fully-fledged type.
See Backwards Incompatibility for details.
Import onto Selected Character
Import onto the Ragcar
Import limbs of Tiger
"},{"location":"releases/2021.04.11/#import","title":"Import","text":"Animators can now setup physics one character, export it, and then import onto another.
The usecase is having spent time setting up a perfect ragdoll and then wanting to reuse this setup across multiple scenes, on multiple instances of the same referenced character, or on characters with similar naming scheme and anatomy. It can also be used to import parts of a character or individual objects.
Demo
Here's an 18 second run-down of the complete workflow, from authoring to import.
"},{"location":"releases/2021.04.11/#features","title":"Features","text":"Anything you can apply physics to can be exported.
The nodes onto which physics is imported..
It will remember..
Guide Strength
It will not remember..
Convex hulls, those triangulated versions of your Maya shapes - the Mesh
shape type - are re-generated onto whatever character you import onto. This is probably what you want, and enables you to apply physics onto characters with different geometry from when you originally authored the physics. Although sometimes it's not, which is why this we be augmented in a future release.
The root in any chain is the first in your selection when creating the chain. If you build a network of chains - a \"tree\" - which is common for any character of more than 1 limb, the exported file will not remember which the original root was. It will figure out new roots procedurally based on their parent/child relationship which may or may not be the same as your original. For importing a full character, this makes no difference. Only for the advanced case of exporting a full character but then wanting to apply only the arm or leg of that character onto another character makes this problematic. This will be addressed in a future release.
And that's about it! It doesn't even have to be a \"character\", any combination of Maya nodes you can apply physics to can have their physics exported. Like a (rag)car, or just a (rag)box.
"},{"location":"releases/2021.04.11/#user-interface","title":"User Interface","text":"In addition to import everything found in an exported file, there's a UI for more control.
The UI resembles native Maya and Ragdoll option dialogs, with two interesting bits.
"},{"location":"releases/2021.04.11/#1-file-browser","title":"1. File Browser","text":"The top part displays other Ragdoll scene (.rag
) files in the same directory as the selected file, along with the thumbnail stored during the time of export. The thumbnail currently isn't visible during export, it is captured from the currently active viewport. An Export UI with thumbnail preview (and more!) will be added in a future release.
This sections shows you the contents of the physics scene, ahead of actually importing it.
It will visualise a number of things.
nurbsCurve
or mesh
?Shape Type
of the exported rigid, e.g Capsule
?Did you see Snyder's Justice League? In it, they introduce and explain the \"mother box\" and how it is capable of turning the dust of a burnt house back into a house.
This Import
feature is the Mother Box of Ragdoll.
The export format is identical to what game developers use to author physics in Maya and import it into their game engine. It contains all data managed by Ragdoll in full detail. Enough detail to reverse-engineer it back into a Maya scene, which is exactly what's going on here.
Example Files
mytiger.rag
mycharacter.rag
ragcar.rag
Each export captures the currently active 3d viewport for use as a thumbnail. So, whenever you export, remember to smile and wave! :D
"},{"location":"releases/2021.04.11/#context-sensitive","title":"Context Sensitive","text":"The visualisations will update as you select different nodes and edit the various options in the UI.
To illustrate this, let's import onto the same scene we exported.
Export
Only one character is physicalised and exported.
Import
Notice that importing is not possible, since the character is already physicalised. Unless we replace the namespace, by selecting another character.
"},{"location":"releases/2021.04.11/#use-selection","title":"Use Selection","text":"Import onto selected nodes with Use Selection
toggled (it's the default).
Every node is stored along with its full path, such as..
|root_grp|spine_grp|spine_ctrl\n
And in most cases can get quite long, with one or more namespaces and tens to hundreds of levels deep in hierarchy.
|_:Group|_:Main|_:DeformationSystem|_:Root_M|_:RootPart1_M|_:RootPart2_M|_:Spine1_M|_:Spine1Part1_M|_:Spine1Part2_M|_:Chest_M|_:Scapula_L|_:Shoulder_L|_:ShoulderPart1_L|_:ShoulderPart2_L|_:Elbow_L|_:ElbowPart1_L|_:ElbowPart2_L|_:Wrist_L|_:IndexFinger1_L\n
Here, the namespace is simply _:
The Search and Replace
boxes of the UI can be used to replace parts of each path, to try and map the original path to whatever path is currently available in the scene.
One challenge with export/import it remapping names from the original scene onto your new scene. Ragdoll solves the typical case of only the namespace being different with \"Auto Namespace\".
\"Auto Namespace\" will replace any namespace in the original file with whatever namespace is currently selected. Neat! If there are multiple namespaces, it'll use the last namespace. Let me know how you find that, there's room left to explore here. Most often, you only ever have a single namespace, but Maya does allow you to tie yourself into a knot if you really wanted to.
"},{"location":"releases/2021.04.11/#auto-scene","title":"Auto Scene","text":"Locate and use the original physics scene from the original file, so as to preserve your multi-scene setups.
For example, if your one character has 3 physics scenes - one for the right arm, one for the left and a single one for both legs - then \"Auto Scene\" will preserve these scenes for you.
Performance Tip
Using more than one scene can improve performance significantly, as Ragdoll will parallelise each invidual scene. The caveat is that rigids in different scenes cannot interact with each other.
"},{"location":"releases/2021.04.11/#ragdoll-clean","title":"Ragdoll Clean","text":"Here's a quick way you can use this feature to \"clean\" a physics scene.
The resulting scene will be \"clean\" in that it will have been broken down into its componens and reassembled again, not taking into account anything Ragdoll doesn't know about.
(I may just add a menu item for this, called Clean
to do this in one go :)
A few things became apparent as I rounded off this feature
Anything the UI can do can be done via Python, using the new dump.Loader
object.
from ragdoll import dump\nloader = dump.Loader()\nloader.read(r\"c:\\path\\to\\myRagdoll.rag\")\n\n# Search and replace these terms from the full node path\n# E.g. |root_grp|arm_left -> |root_grp|arm_right\nloader.set_replace((\n (\"_left\", \"_right\"),\n (\"_ik\", \"_fk\"),\n))\n\n# An automatic method of search-and-replace, that replaces\n# any namespaces found in the file with this.\n# E.g. |char1:root_grp -> |char2:root_grp\nloader.set_namespace(\"char2:\")\n\n# Limit imported nodes to those with an absolute path \n# starting with *any* of these\nloader.set_roots((\n \"|char1:root_grp\",\n \"|char2:root_grp\"\n))\n\n# Deconstruct the provided `.rag` file\n# (This is what is visualised in the UI)\n# (The exact layout of this data may change)\nanalysis = loader.analyse()\nassert isinstance(analysis, dict)\n\n# Print a brief human-readable summary of the current analysis\nloader.report()\n
Heads up
Consider this a version 0.1 of the API, it will likely change in the future.
"},{"location":"releases/2021.04.11/#ragdoll-stability","title":"Ragdoll Stability","text":"Implementing import put a lot of strain on Ragdoll.
Whereas before, authoring physics was a matter of calling one command at a time, playing around with the result, calling another. Maybe undoing every so often.
Import on the other hand calls tens to hundreds of commands at once, undoing them en masse, redoing them en masse. It exposed a ton of flaws in the system that had gone unnoticed in all but the rarest of occasions. Crashes, a ton of them. The worst kind, the kind that doesn't tell you anyhing about why it crashes.
The above an example of:
I'm happy to say these have all been resolved, and the automated test-suite has grown 10x since the last release. Every command is tested, and tested again with undo, and again with redoing an undone redo. It is rock solid, and fast.
You can now undo any command as-one, any number of times, redo it any number of times, undo your redo any number of times. Ragdoll will not be the cause of any crashes.
"},{"location":"releases/2021.04.11/#maya-2022-stability","title":"Maya 2022 Stability","text":"Maya 2022 in its current state has proven incapable of reliably supporting Ragdoll.
Maya 2022 may crash with Ragdoll
That's right. Maya 2022 isn't quite baked yet, and needs a Service Pack. Until then, Ragdoll will run reliably so long as you don't delete anything, or try and open a new scene.
In addition to that, the multiplier nodes didn't quite work with Maya 2022, or more specifically with Python 3.
from ragdoll import interactive as ri\nri.multiply_rigids()\n# Error: 'filter' object is not subscriptable\n# Traceback (most recent call last):\n# File \"<maya console>\", line 2, in <module>\n# File \"C:\\Users\\marcus\\Documents\\maya\\modules\\Ragdoll\\python\\ragdoll\\interactive.py\", line 2112, in multiply_rigids\n# root = rigids[0].parent()\n# TypeError: 'filter' object is not subscriptable #\n
There were also crashes happening on deleting rigid bodies from your scene, these got swept away alongside a number of other fixes to the handling of nodes.
So one step forward, one step back. :)
"},{"location":"releases/2021.04.11/#edit-shape","title":"Edit Shape","text":"A new menu item got added for manipulating shapes with a native Maya transform, as an alternative to fiddling with numbers in the Channel Box.
"},{"location":"releases/2021.04.11/#proxy-attributes","title":"Proxy Attributes","text":"In Maya 2018 and 2020, the attributes added to your original animation controls that mirror those of Ragdoll were \"proxy attributes\". That is, they could be edited from either their original attribute, or the one connected to by your control.
That's really convenient.
Turns out, it is also really unstable. Most of the crashes happening so far, especially on deleting physics or starting a new scene, has come from proxy attributes messing everything up. It should't be surprising, even Maya struggles with them.
node = cmds.createNode(\"transform\")\nshape = cmds.createNode(\"nurbsCurve\", parent=node)\ncmds.addAttr(node, ln=\"proxyVisibility\", proxy=shape + \".visibility\")\nassert cmds.objExists(node + \".proxyVisibility\")\nassert cmds.getAttr(node + \".proxyVisibility\") == 1\n\n# What should happen to the proxy attribute? :O\ncmds.delete(shape)\n\ncmds.getAttr(node + \".proxyVisibility\")\n# RuntimeError: The value for the attribute could not be retrieved. # \n
The same thing applies with access from the API. It just doesn't know what's going on. If we're lucky - which we have been so far - it'll just fail and tell you about it. Other times it'll fail and take Maya down with it. That's just bad.
In Maya 2019, the problem was so severe that proxy attributes were simply not used. With this release, no proxy attributes are used.
I hope to reintroduce them at a later date, once I discover is a safe method (read: workaround) to using them.
"},{"location":"releases/2021.04.11/#python-api-consistency","title":"Python API Consistency","text":"The good news is, the Python API is maturing. The bad news is, this release introduces backwards incompatible changes.
from maya import cmds\nfrom ragdoll import api\n\ncube, _ = cmds.polyCube()\ncmds.move(0, 5, 0)\ncmds.rotate(0, 45, 45)\nscene = api.createScene()\nrigid = api.createRigid(cube)\n
So far so good.
# Before\napi.socketConstraint(parent, child, maintain_offset=False)\n\n# After\napi.socketConstraint(parent, child, opts={\"maintainOffset\": False})\n
Here's the change. These behavior-like arguments have been moved into an opts={}
argument, and is now consistent across any commands that take \"options\". It's to faciliate a large number of options, both from the UI and scripting and enhance compatibility over time; with a dictionary, you can test for availability of arguments at run-time, as opposed to suffer the consequences of not being able to call an update function.
I'm still exploring ways of getting more options into commands, without polluting the argument signature, without changing their order when an argument is deprecated, or changing an argument name when jargon inevitably changes. Using a dictionary for options-like arguments enables us to pass arbitrary sized options to functions, they can also be passed to functions that don't necessarily need all contained options, meaning you can establish a single options dictionary up-front and pass that to all relevant functions.
It's too soon to tell whether the cons of this approach outweighs the pros. This is one reason for the API still going through changes.
The non-optional arguments are those that are never intended to change, like the createRigid(node)
argument. Every rigid needs something to make rigid. (Or so you'd think, as you can now also create a rigid from a new empty transform).
So, the API has changed and will continue changing for a while longer.
Node/Attribute format
The Ragdoll scene format is stable and has been for months. It will remain compatible with future versions of Ragdoll, which means anything you build today (or months ago) will continue to work identically.
The Python API on the other hand is not yet refined and is still changing. So when you build tools ontop of Ragdoll, keep in mind that nodes, their attributes and their connections are stable, but the means of creating those connections are not. So if you need stability today, look at what nodes and connections are made by the API, and do it yourself.
"},{"location":"releases/2021.04.11/#ragdoll-explorer","title":"Ragdoll Explorer","text":"For developers
Explorer has gotten an update, inching its way towards Outliner-like behavior and feel. Eventually maybe even an integration with the Outliner, similar to how USD slots into Maya 2022. That's quite neat!
"},{"location":"releases/2021.04.11/#logging-level","title":"Logging Level","text":"You can now tune the way Ragdoll communicates with you.
Off
means it won't tell you anything, not even warningsDefault
is what you've gotten used to so farLess
only shows you important messages that require you to take actionMore
is the full monty, performance metrics, detailed messages, you name itThese are animator-friendly jargon for the native logging.INFO
and logging.WARNING
levels. \"Off\" means logging.CRITICAL
since Ragdoll does not emit any critical messages.
A few things has been improved for those using Ragdoll as an authoring platform for other software like Unreal and general game engines.
"},{"location":"releases/2021.04.11/#new-components","title":"New Components","text":"The export format has been graced with new components to accommodate for the import feature. As the name suggests, these are stricly related to UI and aren't required for reproducing the physics in another application or engine.
They are meant to cover user elements in Maya such that they can be accurately reproduced on re-import back into Maya.
New Components
RigidUIComponent
ConstraintUIComponent
LimitUIComponent
DriveUIComponent
RigidMultiplierUIComponent
ConstraintMultiplierUIComponent
Here's what the new components may look like in your exported file.
{\n \"type\": \"RigidUIComponent\",\n \"members\": {\n \"shaded\": false,\n \"airDensity\": 1.0,\n \"shapeIcon\": \"transform\",\n \"multiplierEntity\": {\n \"type\": \"Entity\",\n \"value\": 0\n }\n }\n},\n{\n \"type\": \"ConstraintUIComponent\",\n \"members\": {\n \"multiplierEntity\": {\n \"type\": \"Entity\",\n \"value\": 0\n },\n \"childIndex\": 2\n }\n},\n \"type\": \"LimitUIComponent\",\n \"members\": {\n \"strength\": 1.0,\n \"angularStiffness\": 1000000.0,\n \"angularDamping\": 10000.0,\n \"linearStiffness\": 1000000.0,\n \"linearDamping\": 10000.0\n }\n},\n \"type\": \"DriveUIComponent\",\n \"members\": {\n \"strength\": 0.5,\n \"angularStiffness\": 10000.0,\n \"angularDamping\": 1000.0,\n \"linearStiffness\": 0.0,\n \"linearDamping\": 0.0\n }\n}\n
There's also an added section for \"ui\" related data, most interestingly a base64-encoded QPixmap of a thumbnail
.
\"ui\": {\n \"description\": \"\",\n \"filename\": \"C:/scenes/demo/advancedskeleton5.rag\",\n \"thumbnail\": \"iVBORw0KGgoAAAAN ... lots more characters ...\"\n }\n
That can be converted like this.
from ragdoll import ui\nqpixmap = ui.base64_to_pixmap(data[\"ui\"][\"thumbnail\"])\n
"},{"location":"releases/2021.04.11/#backwards-incompatibility","title":"Backwards Incompatibility","text":"The export format has changed slightly, here's what you need to know.
NameComponent.path
was changed from the full path + Ragdoll node to just full path.Example
# Before\n|root_grp|spine1_ctrl|upperArm_ctrl|rRigid3\n\n# After\n|root_grp|spine1_ctrl|upperArm_ctrl\n
Some values were entities themselves, but there wasn't any way of knowing unless you explicitly new that JointComponent.parent
is in fact an entity. This has now been addressed, and all entities now carry a [\"type\"]
signature.
# Before\n{\n \"type\": \"JointComponent\",\n \"members\": {\n \"disableCollision\": true,\n \"parent\": 16\n \"child\": 15\n }\n}\n\n# After\n{\n \"type\": \"JointComponent\",\n \"members\": {\n \"disableCollision\": True,\n \"parent\": {\n \"type\": \"Entity\",\n \"value\": 16\n },\n \"child\": {\n \"type\": \"Entity\",\n \"value\": 15\n }\n }\n}\n
"},{"location":"releases/2021.04.23/","title":"No Limits and Improved Performance","text":"Highlight for this release is No Limits and Greater Performance!
10 Second Ragdoll
Here's the absolute quickest way to turn a fresh mesh into a full ragdoll.
And here's a more practical example of using this feature to clean up a bad mocap clip.
It'll endure changes to the environment too, with little to no modification of the physics settings or the original animation.
"},{"location":"releases/2021.04.23/#no-more-limits","title":"No More Limits!","text":"That's right!
It used to be the case that if your character had a non-default Rotate Order
, or a tweaked Rotate Pivot
or maybe made use of the handy Rotate Axis
or the joints you were using had a non-zero Joint Orient
, then you were out of luck! Ragdoll just couldn't handle those. It would aggressively reset those to their defaults, or flat-out refuse to work.
This release adds support for these missing members, which just so happens to be the very last major limitations of Ragdoll when used with your everyday character rigs!
From now on, if it doesn't work with your rig, that's a bug (let me know!).
"},{"location":"releases/2021.04.23/#rotate-pivot","title":"Rotate Pivot","text":"This release introduces support for both the .rotatePivot
and rotatePivotTranslate
attributes, letting you do things like..
I've also added an option to actually use the rotate pivot (for greater good?) such that you can do this.
"},{"location":"releases/2021.04.23/#rotate-axis","title":"Rotate Axis","text":"The advanced rigger will know of his lesser-known feature of Maya transform nodes, with the ability to modify the axis around which the Rotate XYZ
channels operate.
Finally cracked this one, it has been far too long and is a far-too used feature of Maya transform nodes to not support. But it's done! You should now be able to pick any rotate order and experience no flipping or issue of any kind. Don't even bother getting in touch if you do, because I will not believe you. xD
This tiger (courtesy of www.cgspectrum.com) has a different rotate order on nearly every control.
Before
After
Hold on a second!
That final flip of the spine is coming from the rig itself, the joints driven by the controllers we're simulating. Ragdoll isn't the only one having issues with flipping. :)
"},{"location":"releases/2021.04.23/#joint-orient","title":"Joint Orient","text":"When simulating joints, it can be important to retain the original jointOrient
values. Especially if those joints are later used for IK or if you want or need to zero out those rotate values. But it is perhaps most important for an already-animated skeleton, like what you get out of motion capture.
Some motion capture libraries, like Rokoku, do a good job not having any jointOrient
in which case they would already work well with Ragdoll. But for animated skeletons with a non-default jointOrient
you would have been out of luck..
Until now!
"},{"location":"releases/2021.04.23/#30-greater-performance","title":"30% Greater Performance","text":"Ragdoll used to be really really fast, and is now really really really fast!
Rendering is one of two areas where Ragdoll spends time computing (the other being simulating), and rendering performance has been improved by 400%, making Ragdoll 30% faster overall!
Here you can see the improvement up-close, notice how much time was spent simulating versus rendering each frame in the previous version; almost half the time was spent just rendering!
And if you're wondering...
Ok, but what features did you remove?
On the contrary! Rendering now includes..
Even More Performance?
You'll notice that the rendering square isn't entirely gone.
If 4 ms just to render is too much to ask, you'll get even more of a performance jolt by simply hiding anything Ragdoll related, in particular the rdRigid
and rdConstraint
nodes. The simulated result is independent of whether or not it is visible in the viewport.
If you are a rigger, this can be handy for your animators once you've finished setting things up, as they may not benefit from seeing these things anyway and could use all of the performance you can give.
"},{"location":"releases/2021.04.23/#simulated-attribute","title":"Simulated Attribute","text":"Whenever you make a new chain, an attribute is created on the root of that chain to control whether or not the chain should be Simulated
or animated.
With this release, Simulated = Off
means:
Additions to the physics solver can only happen on the start frame, and if you in previous version created anything on any other frame Ragdoll would yell at you.
This release aids in this process, in that rather then telling you you are wrong, it helps you make it right by automatically returning to the start frame when necessary.
"},{"location":"releases/2021.04.23/#cycle-protection","title":"Cycle Protection","text":"Cycle warnings are generally bad but especially bad for Ragdoll. Understanding when they happen and where they come from can be difficult, especially in complex setups.
Ragdoll now includes Cycle Protection to help you spot potential cycles before they happen!
Notice how making a passive rigid here would have resulted in it becoming a child of an otherwise active hierarchy. That would have been bad!
"},{"location":"releases/2021.04.23/#protected-commands","title":"Protected Commands","text":"These commands will try and protect your from cycles.
All other commands is already safe to use and shouldn't cause any cycles.
"},{"location":"releases/2021.04.23/#faq","title":"FAQ","text":"These are some of the things you might want to learn more about.
How does it work?Whenever a new Passive Rigid or Active Chain (with passive root) is being created, Ragdoll is asked to evaluate the world transformation of the node you are attempting to make dynamic. The solver should not be bothered to simulate anything during this encounter, because if it did then that would mean a cycle is about to happen.
Why?
Because passive rigids pass data into the solver. Namely, the position and orientation of the node you are attempting to turn into a passive rigid. It cannot both pass and receive data. If it is to receive translate/rotate from the solver, then that's an active rigid.
Is it accurate?Very.
Character rigs can get very complex; how can Ragdoll distinguish between an actual parent being active, and a node acting like a parent via something like Maya's Parent Constraints (i.e. a \"broken rig\")?
The answer is that the feature builds on Maya's own evaluation mechanism to figure out whether a node is dependent on the solver or not. The mechanism is surprisingly simple.
def is_dynamic(transform, scene):\n \"\"\"Does `transform` in any way affect `scene`?\"\"\"\n scene[\"clean\"] = True\n\n # Pull, but do not bother actually serialising it\n transform[\"worldMatrix\"].pull()\n\n return not scene[\"clean\"].read()\n
By pulling on worldMatrix
we ensure all hierarchy and constraints is taken into account, and by not actually retrieving value we limit the computational cost to dirty propagation only - as opposed to actually reading and serialising the 16 values that make up the matrix.
Yes.
The protection is only happening when interacting with Ragdoll via the UI menu items. The API remains unaffected and there is an option in the Preferences to disable it in the UI as well.
"},{"location":"releases/2021.04.23/#new-constraints","title":"New Constraints","text":"Have more fun with more control. \ud83d\ude18
These were previously available under a different names and less intuitive usage
"},{"location":"releases/2021.04.23/#hard-pin","title":"Hard Pin","text":"When you want a rigid to be at an exact place at an exact time, use Hard Pin.
Limitations
Previously called Passive Control
.
When you want a rigid to be at an approximate place at an approximate time, whilst still respecting the laws of physics including contacts and gravity, use Soft Pin.
Soft pins are nothing more than a constraint with a guide position towards the newly created transform.
Limitations
Previously called Guide Control
.
In the the previous releases I've been experimenting with the idea of turning the Maya translate/rotate channels directly into a guide constraint.
There are three possible scenarios with subtle differences.
In the above, the parent of the newly created rigid with an animation constraint is non-dynamic, it's got nothing to do with Ragdoll. Just your everyday (boring) Maya transform. In this case, the channel is successfully converted to a worldspace position and orientation from your translate/rotate channels.
Here on the other hand, the immediate parent is a Passive Rigid
which is a little more flexible, and gives you an option to actually collide with the parent.
Finally, the parent is active. This is also OK and quite fun. Now the new rigid will affect the parent, since it adds weight onto it. Like a backback.
Dynamic Grandparent
Here's where things get less predictable. If the parent of the control you want physics to follow along with your translate/rotate channels is non-dynamic, but one or more of its parent are active rigids, then the channel box values no longer align.
This will be addressed in a future release.
"},{"location":"releases/2021.04.23/#character-multiplier","title":"Character Multiplier","text":"Making a new character now includes a default multiplier for all constraints (just like chains do!), meaning you can more easily create effects like this!
"},{"location":"releases/2021.04.23/#import-bugs","title":"Import Bugs","text":"Two issues were found with the importer introduced in the last version.
Passive versus Rigid
When importing a passive rigid, odds are it got imported as a active rigid instead. This could get very messy, as it could end up creating passive rigids as children of active ones, which could reak all kinds of havoc, including cycle warnings.
2-link chains
Any \"chain\" with more than one child (head) is a special case of each chain only having 1 rigid each, as opposed to longer chains like arms and legs. Now these can be imported too!
Export is Unchanged
This and the above import fix were only related to importing of physics, both your existing Maya scenes and exported .rag
files are unchanged and were already in good condition. Yay!
Whenever you make a rigid or chain, some attributes are forwarded onto your animation controls. These attributes are called \"User Attributes\" and the previous release changed these from Maya proxy-attributes to plain-attributes.
In doing so, they lost their nice names and default values. :( This has now been fixed!
"},{"location":"releases/2021.04.23/#looped-playback-bug","title":"Looped Playback Bug","text":"If you've ever had both passive and active rigids and let playback run on a loop, you might have encountered something like this.
Whereas if you rewound and playback without looping, everything would be allright. This bug got squashed in this release, letting you loop things to your hearts content!
"},{"location":"releases/2021.04.23/#auto-cleanup","title":"Auto-cleanup","text":"Whenever you Delete All Physics
anything created by Ragdoll disappears, including User Attributes. What wasn't included however was the handles that appears when you Edit Constraint Pivot
and Edit Shape
.
These now also vanish with delete-all, making your life just a little bit better!
Thanks to Remi Comtois for pointing this out!
"},{"location":"releases/2021.04.23/#offline-activation","title":"Offline Activation","text":"Activation is streamlined by happening inside of Maya at the paste of a serial and press of a button. Unless you are one of those without access to the internet, in which case we'll need to do a little dance. :)
Step 1 - Generate Request
from ragdoll import licence\nkey = \"YOUR-VERY-LONG-KEY-HERE\"\nfname = r\"c:\\ragdoll_activation_request.xml\"\nlicence.activation_request_to_file(key, fname)\n
Step 2 - Email Request
Send this file to licencing@ragdolldynamics.com. We'll abrakadabra this file before you can say Taumatawhakatangi\u00adhangakoauauotamatea\u00adturipukakapikimaunga\u00adhoronukupokaiwhen\u00aduakitanatahu.
Step 3 - Activate
Once you've got a response, activate your licence like this.
from ragdoll import licence\nfname = r\"c:\\ragdoll_activation_response.xml\"\nlicence.activate_from_file(fname)\n
Linux users, you'll know what to do about that Windows-like path.
Full documentation
The last release included a callback for synchronising the Import Options UI with the Maya selection. As a result, a bug slipped in which could - in rare cases - produce the following error messages in your Script Editor whenever you changed selection.
../ragdoll/vendor/qargparse.py line 654: Internal C++ object (WidgetHoverFactory) already deleted. //\n
This has now been patched up, but do shout out if this or anything like it happens to you!
Thanks to Rafael Villar for finding this bug!
"},{"location":"releases/2021.04.23/#low-dpi-cosmetics","title":"Low-DPI Cosmetics","text":"The Import Options UI didn't quite live up to the hype at 720p and 1080p, now it does!
Whenever you make a Guide control (now called Soft Pin
) you are technically creating a constraint between a rigid and the world. That's what makes it worldspace.
Until now, constraints assumed the world didn't move. But you z-up folks out there know that, sometimes, it does! Ragdoll is now OK with that.
Before
After
Thanks to Jason Snyman for finding this bug!
"},{"location":"releases/2021.04.23/#tree-multipliers","title":"Tree Multipliers","text":"There was a minor bug with multipliers for any chain branching off of another chain (e.g. an arm from a spine) which caused the default multiplier to not correctly affect every link in those chains.
This has now been fixed!
"},{"location":"releases/2021.04.23/#known-issues","title":"Known Issues","text":"At the time of this release, these are the known issues that will be addressed in a future release.
"},{"location":"releases/2021.04.23/#evaluation-graph-controllers","title":"Evaluation Graph Controllers","text":"If you use \"controllers\" in your rig, there is a possibility Ragdoll will be drawing things incorrectly.
This can be addressed by either not (1) using controllers, (2) disabling controllers in the evaluation or (3) awaiting a future update. The problem appears visual-only and should have no effect on the simulation itself.
"},{"location":"releases/2021.04.23/#scale-pivot","title":"Scale Pivot","text":"When you hold the D
key and move the pivot, there are 4 attributes being edited.
If scalePivot
and scalePivotTranslate
result in zero change to a nodes position (the default) then all is well. But, if you edit these independently then that will in turn affect the final position of the node, in which case Ragdoll will struggle to simulate it.
I've narrowed down a particularly annoying behavior (likely a bug) in Maya that can affect users of auto-key and Ragdoll.
This will be fixed in a future release, and if anyone knows of any workaround please let me know!
"},{"location":"releases/2021.04.23/#joint-orient-non-linear-hierarchy","title":"Joint Orient & Non-linear Hierarchy","text":"When joints do not immediately follow each other, the rotate channel isn't entirely accurate.
Notice how there is a joint inbetween the two rigids? Avoid this edge case for now, or zero out the jointOrient
.
Solved
Solved in 2021.04.28
Guiding the translation
of an Active Rigid
with a Passive Rigid
is currently problematic and creates an unrealistic increase of acceleration.
The current workaround is to swap solvers under the Advanced tab of the scene.
"},{"location":"releases/2021.04.28/","title":"Solver Upgrade","text":"This release introduces more robustness, in exchange for changes to the default values for any Stiffness
and Damping
parameters.
The solver has been upgraded for more accuracy and stability. Unfortunately, this changes the default values Stiffness
and Damping
attributes, which may require changes in your scene.
ATTENTION: Backwards Incompatibility
Ragdoll takes backwards compatibility very seriously. At no point should a scene you have created break because of an update. This however is an exception to that rule, one that I expect never to happen again.
"},{"location":"releases/2021.04.28/#what-has-changed","title":"What has changed?","text":"Stiffness
and Damping
need higher values.
So far, we've used the Iterations
value on the solver to control how strong our constraints could be. As it happens, this isn't right. Iterations shouldn't control strength, it should only control how close the solution is to the true analytical solution.
Iterations
optionally bringing it closer to the true solution.In practice, not much has changed. You should still increase stiffness/damping when relevant, and still increase Iterations
if you find the values aren't being respected.
Stiffness
by 3-10xDamping
by 3-10xThat is, if Stiffness
was previously 1'000, make it 10'000.
Exceptions
Projected Gauss-Seidel
(Advanced) remains unchanged.It's not an exact science, in some cases you only need 3x, like in this case here.
Where the Yellow
line is from the previous version at 1'000 stiffness and 100 damping, the Blue
line has 3'000 stiffnes and 300 damping.
The previous version was subtly faulty, so this was inevitable. In practice however, under a very particular - but useful - circumstance the solver would struggle to obey.
Circumstance
Active Rigid
Passive Rigid
On
Use Cases
Here was the result.
Notice how the active rigid does what the active rigid does, but is a little too excited? One workaround was to use \"Projected Gauss-Seidel\" in place of the default \"Temporal Gauss-Seidel\", however that solver isn't as accurate or fast.
You might be thinking..
Well that's an awefully specific case, when would I even hit that?
Which is when you realise..
This was previously only possible with Projected Gauss-Seidel which is less performant and less able to handle large networks of constraints like a full ragdoll.
Result
This behavior was due to a subtle bug in how constraints were solved, a deeply rooted bug that once sorted out was what caused this change to the overall behavior of Stiffness
and Damping
values.
In this release, the bug has been squashed and muscles and props now follow their passive counterpart much more accurately and without surprises.
"},{"location":"releases/2021.04.28/#frameskip-protection","title":"Frameskip Protection","text":"The simulation is like a train running on a train track. It absolute must not miss a stop, else it can't realistically figure how how to get to the subsequent stop.
Allow me to demonstrate.
Notice how everything falls apart when skipping just a handful of frames? It's trying to catch up, but the time difference is just too great to produce accurate values.
This release adds support for pausing the solver whenever a frame is skipped, meaning you either get a (A) good solve or (B) a patient solver, awaiting your return.
The behavior can be disabled in the Preferences.
"},{"location":"releases/2021.04.28/#why-should-i-care","title":"Why should I care?","text":"Consider your everyday situation of adding dynamics to a tail.
Whenever a frame is skipped, the result is garbage. This can get even more extreme during more extreme movements. But, what's worse, this garbage is expensive! It's still simulating, and trying to solve these skipped frames is more expensive than non-skipped frames. That's a bad deal.
Here what happens with frameskip protection.
See how it just stays put? It'll remember the last simulated frame, awaiting your return.
"},{"location":"releases/2021.04.28/#clear-initial-state","title":"Clear Initial State","text":"Setting the initial state can be used to relax a physics character or scene.
But once relaxed, you had no way to returning to its original creation state, until now!
Thanks to Jason Snyman for this suggestion!
"},{"location":"releases/2021.04.28/#passive-visualisation","title":"Passive Visualisation","text":"Rigids will now turn gray when made passive, making it easier to understand what's going on visually.
"},{"location":"releases/2021.04.28/#start-frame-explosion","title":"Start Frame Explosion","text":"In a specific and rare circumstance, a passive rigid body could appear to have velocity on the start frame.
Notice here how animation starts immediately from the start frame, giving it an upwards velocity? The active rigids connected to the root on the other hand gets an even stronger velocity, for some reason.
If we move the animation to just one frame after the start frame, all is well.
A subtle bug, having to do with the rigid body being created on the second frame of the simulation, which in this case had a position the was different from the start frame. However! The animation started at the start frame, so the velocity got inherited from there instead. Yes, it's complicated. :)
And is now fixed!
"},{"location":"releases/2021.04.28/#negative-scale","title":"Negative Scale","text":"Ragdoll has supported scale, but negative scale has been unreliable. This release extends this support to negative scale used to mirror controls and behavior across a rig.
Before
This whole arm has a negative scale in the X-axis, from when it was mirrored across from the other side. Notice here how it look like the arm is about to move forwards, and instead move backwards.
After
This has now been fixed.
It also means you can flip entire performances with a little more ease. :)
"},{"location":"releases/2021.04.28/#caveat","title":"Caveat","text":"Avoid negative scale on the control you are animating.
You are still better off not having any negative scales in your rig, as there is still at least one special case I found that might jump up and bite you.
And that is if the animated control itself has negative local scale.
Typically, one or more of the parents have negative scale, so as to mirror a whole hierarchy of controls. And that is \u2714\ufe0f. But if the control you are animating also have negative scale, you might experience this.
Notice how on rewind, it twitches at the start of playback every other time? That's because it cannot tell the whether the control has negative scale or whether it is rotated 180 degrees.
This will be addressed in a future release.
"},{"location":"releases/2021.04.28/#rotate-order","title":"Rotate Order","text":"The animation constraint is what translates your keyframes into physics and with the introduction of support for Rotate Order in the previous few releases it has been possible for Ragdoll to output rotations onto any control with a custom rotate order.
This release now includes support for input of custom rotate order into the simulation.
Before
Notice how changing the rotate order should have changed the axis around which the Y-animation was happening, but didn't?
After
Now it does!
"},{"location":"releases/2021.04.28/#draw-shaded","title":"Draw Shaded","text":"The previous release revamped the rendering system in Ragdoll, but left out a the convenience attribute to disable shading when rigid bodies were used alongside animation controls.
Before AfterManual Override
The behavior can be manually adjusted to taste via the Attribute Editor.
"},{"location":"releases/2021.05.10/","title":"Mimic","text":"Highlight for this release is Mimic!
Some awesome simulations, courtesy of Jason Snyman, a.k.a. The Wizard. xD
Facial Rigging
Move lips, pull muscles. Collides with the teeth too!
Ragdolls have feelings too
Zilla is nothing with Kong, Kong is nothing without Zilla.
Wreck-it Zilla
Old recovered footage from the 60s!
Wreck-it Warm-up
Ever wondered how Zilla prepares for world domination?
"},{"location":"releases/2021.05.10/#mimic","title":"Mimic","text":"Transition in and out of physics, in both pose-space and world-space, with the newly added Mimic.
Options In-Depth
A step-by-step guide on what each option mean, there's quite a few of them!
Production Rig Example
A closer look at the Fire Wolf.
Courtesy of Truong CG Artist
"},{"location":"releases/2021.05.10/#multiple-mimic","title":"Multiple Mimic","text":"Mimic is a replica of your control hierarchy, and there's no limit to the number of replicas you can make. The final force applied to your rigid bodies is the sum of constraints applied.
"},{"location":"releases/2021.05.10/#order-independent","title":"Order Independent","text":"The controls in character rigs typically don't form a linear hierarchy. They're in some offset group, or in a different part altogether hanging together with constraints. That are animated, for space switching and what not.
Mimics don't mind.
"},{"location":"releases/2021.05.10/#partial-chain","title":"Partial Chain","text":"Sometimes you only want a little bit of control.
"},{"location":"releases/2021.05.10/#bake-simulation","title":"Bake Simulation","text":"You can now convert physics into keyframes with Bake Simulation
.
I did not edit this GIF, it really was that fast! :D
Tutorial
Bake Duration
It'll tell you how much time was spent baking too.
Bake Options
There are a few more options to choose from, with more to come.
"},{"location":"releases/2021.05.10/#import-additions","title":"Import Additions","text":"The import mechanic got an upgrade, you're now able to choose whether or not to re-apply changes to attributes and more finely import onto part of a larger chain hierarchy.
"},{"location":"releases/2021.05.10/#preserve-attributes","title":"Preserve Attributes","text":"You now have the option to preserve attributes when importing, for when you'd rather stick with the default values.
"},{"location":"releases/2021.05.10/#preserve-roots","title":"Preserve Roots","text":"Exported files now remember what their original roots were.
The original root of chains aren't important to Ragdoll. Whether the spine was a chain followed by the left and right arm, or whether the spine and left arm were part of one chain followed by the neck and right arm makes no difference.
Consider these two characters.
Notice how in the front character, one chain starts at the hip and goes out into the arm, whereas in the back character the spine is a single chain as you may expect?
Regardless of how you authored it, to Ragdoll these characters are identical. Ragdoll doesn't bother with hierarchies, everything happens in worldspace. The hierarchy is between you and Maya.
However
What if you wanted to import just one of the roots? You can import only onto the selected controls, but you can't import part of a network of chains like a full ragdoll. It's either a complete character, or no character at all.
In the case of the foreground character, you could import the screen-left arm, but not the screen-right. Not without importing the whole spine.
This release preserves the original root, such that you can isolate an import onto the same chain you originally authored.
"},{"location":"releases/2021.05.10/#sleep","title":"Sleep","text":"It is now possible to reap additional performance benefits in situations where one or more rigids remain immobile for a given number of frames.
The behavior can be tuned via two attributes on each rdRigid
node.
Wake Counter
How many frames of inactivity before I fall asleep? Sleep Threshold
How low of a force should be applied before I start counting? In practice, you'll likely only want to tweak the Wake Counter to some reasonable value like 5 or 20 frames of immobility. The default value of 0 means they'll never fall asleep. Like a proper insomniac or new parent.
Caveat
Currently, the wake counter is not reset when you rewind, so it's possible to have them fall asleep on frame 20, rewind to frame 19 and have the counter reset and keep them awake past frame 20. It's unlikely to affect you, and will be addressed in a later release.
"},{"location":"releases/2021.05.10/#textures","title":"Textures","text":"As you author your ragdolls, the distribution of mass can play a big role. But it can be tricky to balance something you cannot see, smell or touch.
With this release, you're able to see (but not smell, I promise) the masses in each rigid using the handy new Texture
attribute and when your viewport is set to Textured mode (the 6
key on your keyboard).
Thanks to Jason Snyman for the idea!
Normalised Distribution
Notice how the colors even out to always give you pure white for the maximum weight in any of the rigids in the scene they are part of, and approaching black for anything less. No need to manually specify min/max values!
Friction and Restitution
These can be visualised too.
Maya 2018 Caveat
In Maya 2018, consolidation is disabled to facilitate this shader. It shouldn't affect anything of value, you probably don't even know what it is. But if you'd rather it didn't do that, untick the \"Maya 2018 Consolidate World Fix\" in the Ragdoll Preferences and reload the plug-in or restart Maya.
"},{"location":"releases/2021.05.10/#vertex-limit","title":"Vertex Limit","text":"Meshes are the slowest to compute and have an upper-limit of 256 vertices. You can now lower this limit for meshes that would normally result in 256 for greater performance.
"},{"location":"releases/2021.05.10/#collide-off","title":"Collide Off","text":"Rigids have always been able to ignore contacts with Collide: Off
The problem here is subtle, but has been present since the beginning of Ragdoll. It mostly makes itself known once there is a constraint between a rigid with Collide: On
and a rigid with Collide: Off
.
Notice how with Collide: Off
the upper part of the \"creature\" is more wobbly? As if the effect of the constraint has somehow dimished? That's not right. Unless there are contacts involved, disabling them shouldn't have an effect on the simulation.
With this release, it behaves as you would expect.
"},{"location":"releases/2021.05.10/#quality-of-life","title":"Quality of Life","text":"A number of improvements were made to make working with Ragdoll more pleasant!
"},{"location":"releases/2021.05.10/#translate-limit-rendering","title":"Translate Limit Rendering","text":"The translate limit is making an appearance!
This should make it just a tiny bit easier to work with, now that it's clear which axes are actually free. Letting you see whether they are constrained in 3D, 2D or 1D. All the D's!
Edit Limit
Using the same method as editing rotate limits, they can be rotated (and moved!).
Soft Limit
Like rotate limits, these can also be made soft!
"},{"location":"releases/2021.05.10/#constraint-rendering","title":"Constraint Rendering","text":"Have you ever noticed constraints looking real nervous?
You now needn't lose any more sleep over it, as they now render flicker-free. :D
Before
After
"},{"location":"releases/2021.05.10/#constraint-interactivity","title":"Constraint Interactivity","text":"You may also have noticed how when you edit one of two constrained rigids, how things get all whack?
Before
Best case you'd at least get constraints to stick together as you make changes.
After
And oh golly how ugly it was. No more! Yay! \ud83e\udd29
"},{"location":"releases/2021.05.10/#constraint-colors","title":"Constraint Colors","text":"When rigids have multiple constraints, it can be hard to tell them apart visually given they all share the same red/green colors. And if you're amongst the colorblinds things are even more challenging.
This release enables you to give some extra flare to your constriants, by editing the Twist
(X-axis) and Swing
(YZ-axes).
"},{"location":"releases/2021.05.10/#trajectory-on-selected","title":"Trajectory on Selected","text":"
There's now an option to isolate trajectories to selected rigids only.
"},{"location":"releases/2021.05.10/#less-explosive","title":"Less Explosive","text":"Overlaps are resolved by moving one or both rigids away from each other. The force with which that resolution happens could be infinite, resulting in what looks like explosions.
This release addresses this, by compromising between realism and aesthetics.
Before
After
Editable
The behavior can be restored or tweaked further by adjusting the Max Depenetration Velocity
attribute of the rigid.
There are 3 ways to load Ragdoll.
cmds.loadPlugin(\"ragdoll\")
When Ragdoll is loaded, it appends to a special environment variable Maya uses to look for icons in the Outliner called XBMLANGPATH
. Because of course that's what it is called, why do you have that look on your face?
Anyway, as it happens, if the Outliner was given a chance to draw icons before Ragdoll added this variable then it'd go ahead and draw a generic, non-pleasant-looking icon like this.
This release fixes that. \ud83e\udd70
Before After "},{"location":"releases/2021.05.10/#upgrade-on-file-open","title":"Upgrade on File Open","text":"Like above, there was another issue when loading the plug-in alonside opening of scenes, which had to do with upgrades.
Normally, what happens is this.
But since the plug-in is loaded during scene open, Ragdoll wasn't given a chance to check it first.
This has now been fixed.
Install on Idle
This changes the initialisation mechanism somewhat, if this causes any issues for you, set the RAGDOLL_INSTALL_ON_IDLE
environment variable to revert to the old behavior. It won't be able to upgrade on scene open unless you load the plug-in first, but that's the only thing you're missing out on.
Our precious icons now appear in the node editor too!
Before After "},{"location":"releases/2021.05.10/#passive-initial-state","title":"Passive Initial State","text":"Here's a subtle one.
In previous releases, the initial state is automatically updated on the 2nd frame of the simulation to wherever a rigid was on the 1st frame. Even if you modified the position interactively with manipulators, or via curves in the Graph Editor, or the channel box, and so on.
It even updated when a rigid was affected by passive input, like a Hard Pin, which meant you lost track of the original initial state whenever you disabled the hard pin.
This release addresses that by only automatically updating the initial state if a rigid is active on the start frame.
Notice how I can disable Hard Pin and have the rigids return to where they were before they got pinnned? It's what you would expect.
"},{"location":"releases/2021.05.10/#passive-to-active-and-back-again","title":"Passive to Active and Back Again","text":"Ragdoll tries to clean up after itself by removing constraints no longer in use. When a rigid is passive, it can no longer be affected by constraints, so those constraints are deleted.
However, active rigids can still be influenced by a passive rigid, and Ragdoll was a little too aggressive in removing those constraints too.
This release fixes that.
"},{"location":"releases/2021.05.10/#undo-and-attribute-order","title":"Undo and Attribute Order","text":"Whenever you delete physics and undo, the order in which proxy attributes would appear on your controllers would go all whack.
This is basic-Maya, it loves doing this. But now love goes both ways, and we are much happier. \ud83e\udd70
Before
After
"},{"location":"releases/2021.05.10/#control-rendering","title":"Control Rendering","text":"Controls give you a preview of what the rigid they control look like.
These are special in that Maya doesn't actually need them. Ragdoll doesn't actually need them either. They are exclusively for-your-eyes-only.
And due to Maya only updating things it absolutely needs to whenever rendering anything, these won't get updated unless Ragdoll explicitly tells them to. So far, they've been told to update whenever the selection changed, which can end up looking bad.
This has now been improved!
Before
After
"},{"location":"releases/2021.05.10/#fixed-startup-crash","title":"Fixed Startup Crash","text":"On plug-in load, Ragdoll would check your licence. Under rare circumstances (2 out of 100 users reported it happening) this would be enough to put Maya under, instantly and without warning.
This has now been fixed.
"},{"location":"releases/2021.05.10/#fixed-initial-state","title":"Fixed Initial State","text":"An error was introduced between 2021.04.23 and 2021.04.28 leading to an issue with updating the initial pose via the Channel Box or Graph Editor.
This got addressed on the same day and released unofficially as 2021.04.30, and is now officially part of the latest version.
Thanks to Niels Dervieux for reporting this bug!
Before
After
"},{"location":"releases/2021.05.10/#fixed-qt","title":"Fixed Qt","text":"Whenever you clicked Import Physics
in the Import Physics Option Window, it would needlessly shout at you.
# RuntimeError: Internal C++ object (WidgetHoverFactory) already deleted.\n
No more!
"},{"location":"releases/2021.05.10/#scene-drawing-in-2019","title":"Scene Drawing in 2019","text":"Maya was misbehaving in 2018-2019, refused to draw the scene visualisation correctly. No longer!
Before
After
"},{"location":"releases/2021.05.17/","title":"Floating Licence Support","text":"Highlight for this release is support for Floating Licences!
So far, Ragdoll has been activated on a per-machine basis. It's been node-locked.
But in many cases, you are a studio with a team of artists using Ragdoll. That's when it becomes impractical for each artist to manage their own licences, or for licences to become associated with a single machine.
Floating licences solve this problem. With it, you register a fixed amount of licences with a server somewhere on your network, and then have Maya \"lease\" licences off of it. For example, with 10 floating licences, 10 artists can use Ragdoll in parallel. On Maya shutdown or plug-in unload, the lease is \"dropped\" meaning it can be picked up by another artist, on some other machine.
Heads-up SysAdmins
On Windows, the floating licence mechanism is currently a dedicated DLL.
This will be merged into the plug-in like on Linux in a future release.
See also
The Mimic introduced in the last release generated a clean hierarchy of transforms.
This release introduced \"mimik\", which is a joint hierarchy suitable for skinning and IK. It's got a proper Joint Orient too, irregardless of what the original animation controls looked like.
They're great if IK is what you want, but they do make the overall hierarchy more complex and introduce an additional jointOrient
offset onto the joints themselves. For that reason, Transform
is the default node type and is currently the most simple mimic to work with.
Room for Improvement
There's still room for improvement, the user attributes remain on the blue control nodes rather than the joints themselves for now. This will be addressed in a future release.
"},{"location":"releases/2021.05.17/#quality-of-life","title":"Quality of Life","text":"More quality, less problems. Hacuna matata!
"},{"location":"releases/2021.05.17/#constraint-outliner-style","title":"Constraint Outliner Style","text":"You can now choose how constraints appear in the outliner.
Style ResultnConstraint
At the root of the outliner, as its own transform Maya Constraint
As a child transform Ragdoll
As a shape The rRigid
node appears as a shape of any node you apply physics to, and normally constraints appear alongside them. But normal Maya constraints do not, and neither does the constraints you get with nCloth and nHair. So which do you prefer?
Ragdoll Style
As a shape, alongside the rRigid
node.
Maya Constraint Style
As a child, similar to native Maya constraints.
nConstraint Style
As a new transform at the root of the scene, similar to nCloth and nHair constraints. Group them, hide them; if you can imagine it, you can achieve it!
Subjective
Whichever you prefer, it has no effect on the simulation and is strictly related to the Outliner only. They can also be re-parented after being created, it really doesn't matter where they are. So organise away!
"},{"location":"releases/2021.05.17/#constraint-scale-rendering","title":"Constraint Scale Rendering","text":"The last release made constraints render poorly if the node they were parented to was scaled. The simulation was still fine, but you couldn't see what you were doing.
Before
After
"},{"location":"releases/2021.05.17/#constraint-maintain-offset","title":"Constraint Maintain Offset","text":"Constraints typically maintain their offset on creation, such that rigids do not abruptly snap together on simulation start.
But it's optional, and if you don't maintain offset then they would snap together. With this release, the default behavior is now soft as opposed to infinitely strong.
"},{"location":"releases/2021.05.17/#installer-improvements","title":"Installer Improvements","text":"On Windows, the MSI installer can now be used to install multiple versions of Ragdoll simultaneously, with a dedicated uninstall option each.
This should also help clear out issues with upgrading using the MSI, which has been problematic in the past since the installer really didn't like overwriting files.
On all platforms, multiple Maya module files now co-exist, which means that if you want to disable or switch versions you can do that by removing the offending version - rather than editing the text file itself like in previous versions of Ragdoll.
"},{"location":"releases/2021.05.17/#rigid-scale-rendering","title":"Rigid Scale Rendering","text":"Rendering of non-uniformly scaled rigid bodies has been improved and now respond interactively to scale changes. Notice in particular how scale is translated into sphere radius only along the X-axis. For non-uniform scale of a sphere, switch to Shape Type = Mesh
.
Before
After
"},{"location":"releases/2021.05.17/#scene-scale","title":"Scene Scale","text":"The default distance unit in Maya is centimeters. Meaning Translate X=5.0
means \"5 centimeters along the X axis\". And in some cases, characters get modeled by this unit too, to an average height of 160-190cm.
But often this unit is ignored and now Ragdoll can too.
Default Value
Ragdoll has assumed a scene scale of 0.1 so far, meaning 10 centimeters meant 1 meter. That's the typical scale of most rigs, some having smaller - like the Fire Wolf at 0.01 - and some larger - like a real-world scale of 1.0.
This value used to be reflected in Gravity Y
as 98.2
meaning 98.2 cm/s2
. Which means that an object falling for 1 second would reach a velocity of 98.2 cm/s and keep increasing by the amount each second until reaching terminal velocity.
It is now reflected in Scene Scale instead as 0.1. For a real-world scale, simply set this value to 1.0 and leave gravity unchanged.
"},{"location":"releases/2021.05.17/#quick-select","title":"Quick Select","text":"The quick-select commands now feature an option to ignore whatever is currently selected.
rdRigid
rdRigid
Filtering grows more useful as your scenes grow large. When you have e.g. 2 characters and want to edit all constraints in one of them, then filtering is what you're looking for.
"},{"location":"releases/2021.05.17/#bulk-edits","title":"Bulk Edits","text":"The Maya Channel Box is great for editing multiple nodes at once.
Select two or more nodes, change an attribute in the Channel Box, and the change is applied to each of the selected nodes at once. Win!
But what about attributes that aren't in the Channel Box?
Here are 3 ways in which you can bulk-edit a class of Ragdoll nodes in one-go. In each case, I'm using the Ragdoll -> Select
menu item to bulk-select all rigid bodies in the scene.
Also known as \"the slow way\". Simply edit each attribute, one at a time. Like watching paint dry. It's slow.
"},{"location":"releases/2021.05.17/#2-channel-editor","title":"2. Channel Editor","text":"All attributes found in the Attribute Editor are also available in the Channel Editor. The most-commonly used ones are already exposed, but you can expose more.
"},{"location":"releases/2021.05.17/#3-attribute-spreadsheet","title":"3. Attribute Spreadsheet","text":"For total control, irregardless of the Channel Box and with searchability amongst attributes, you can also try the lesser-known Attribute Spreadsheet.
"},{"location":"releases/2021.06.07/","title":"Minor Bugfixes","text":"Highlight for this release is minor bugfixes, in preparation for launch.
It's been almost a month, and this is all you have to show for it?
Yes! The past few weeks has been \"Less C++, more HTML\". The website is getting an overhaul, along with documentation and tutorials. Stay tuned, and for early access users: keep on reporting any issues you encounter!
"},{"location":"releases/2021.06.07/#broken-scale","title":"Broken Scale","text":"Sometimes, when animation controls has been scaled the default values and drawing of rigids and constraints did not look right. This has now been fixed.
Before
As you can see, the rigids are far away from their control, and the constraint visualisation is all whack. These are exactly 10x wrong, which is how scaled the top-level group is.
After
Thanks to @mariia for reporting this issue!
"},{"location":"releases/2021.06.07/#zero-length-spheres","title":"Zero Length Spheres","text":"When making a chain for a tail, there was a specific circumstance that could trip-up Ragdoll when trying to figure out how large to make the tip of that tail, resulting in a rigid body of zero length and width.
These don't simulate well and didn't communicate that it had happened. This has now been fixed!
Thanks to Amedeo Beretta for reporting this issue!
"},{"location":"releases/2021.06.07/#crash-on-playback","title":"Crash on Playback","text":"The previous release intoduced interactive re-generation of rigid body meshes when scaling. It was really neat! Unfortunately, the Maya feature used to support this feature had a critical fault in Maya 2020.
Leaving mention of the culprit here should anyone surf the interwebs and arrive to at similar fate.
MDagMessage::addWorldMatrixModifiedCallback()
As such, in order to scale a rigid body of Shape Type = Mesh
you must trigger a rebuild. The simplest way of doing that at the time of this writing is to jiggle the vertex limit.
Other options include:
rdRigid
nodeWhen referencing another file, the nodes are \"locked\". Meaning they have some restrictions on what you can do with them, like not being able to delete them.
Ragdoll would happily attempt to delete these but not tell you that it had failed. It simply isn't allowed to do it.
This release communicates this to you.
It also applies to deletion happening indirectly, such that when you want physics removed after baking.
"},{"location":"releases/2021.06.10/","title":"Telemetry","text":"Highlight for this release is telemetry.
Ragdoll is now able to gather usage statistics so that I can strip menu items that aren't used, pay more attention to the ones that are and get an overall understanding of how Ragdoll performs out in the wild.
"},{"location":"releases/2021.06.10/#faq","title":"FAQ","text":"What is telemetry?
It's the term coined for gathering anonymous usage statistics and send it to a product vendor for a greater understanding of how their product is used.
Do I need it?
No, this won't help you. Not directly. But it will help you and others indirectly, in that it allows me to spend more time on features you use, and less time on those you don't.
What does it collect?
Mostly performance numbers, nothing personal. See Data below.
How is it collected?
Mostly through C++, but some of it through Python. You can read about exactly what it does in telemetry.py
What if I'm offline?
Then the file will still be written to your home directory, and you'd be welcome to email it at your own leisure to telemetry@ragdolldynamics.com
"},{"location":"releases/2021.06.10/#opt-in","title":"Opt-in","text":"It is currently opt-in while I work out the kinks, so if you're interested in helping out put this in your maya.env
or type it into your script editor before loading the plug-in.
Maya.env
RAGDOLL_TELEMETRY = Yes\n
Script Editor
os.environ[\"RAGDOLL_TELEMETRY\"] = \"Yes\"\n
"},{"location":"releases/2021.06.10/#data","title":"Data","text":"Data is gathered and stored in 2 places.
~/.ragdoll/telemetry_10-06-2021-100402.json
It is gathered and stored when Maya closes. Or more precisely, when the plug-in is unloaded.
Here's what the complete data currently looks like.
~/.ragdoll/telemetry_10-06-2021-100402
{\n \"maya\": {\n \"crashed\": false,\n \"version\": 20200200,\n \"errors\": 0,\n \"warnings\": 0\n },\n \"system\": {\n \"time\": \"10-06-2021, 10:04:39\",\n \"memory_cpu\": \"31010.8 MB\",\n \"machine\": \"AMD64\",\n \"memory_gpu\": \"24576 MB\",\n \"gpu\": \"GeForce RTX 3090/PCIe/SSE2\",\n \"os\": \"win32\",\n \"processor\": \"AMD64 Family 23 Model 49 Stepping 0, AuthenticAMD\",\n \"render_api\": \"OpenGL V.4.6\"\n },\n \"ragdoll\": {\n \"simulationTimeMax\": 1.2327,\n \"computeTimeMax\": 1.6763,\n \"setupTimeMin\": 0.301,\n \"computeTimeMin\": 0.7595,\n \"setupTimeMax\": 0.4756,\n \"simulationTimeMin\": 0.4697,\n \"rigidCountMax\": 15,\n \"constraintCountMax\": 16,\n \"version\": 20210606,\n \"computeTimeAvg\": 0.949111823737213,\n \"simulationTimeAvg\": 0.597494786145304,\n \"setupTimeAvg\": 0.25006875,\n \"rigidCountMin\": 15,\n \"constraintCountMin\": 16\n }\n}\n
This was generated from that throbbing heart simulation above.
There are currently 3 categories of data gathered.
\"maya\"
As you can see, it'll capture how many errors and warnings were emitted from the plug-in whilst the plug-in was loaded. It'll also include whether Maya crashed the last time Ragdoll was loaded. Ragdoll's goal is to keep crashes at 0.
\"system\"
It'll also include system information such that I know how restrained to keep Ragdoll, both in terms of memory and CPU power. If everyone's running on an integrated Intel chip, then Ragdoll simply wouldn't try to benefit from the GPU that much. These numbers also help put the next category into perspective.
\"ragdoll\"
The ragdoll
category is perhaps the most interesting, as it sheds light on how much you are willing to suffer haha! Ragdoll is a real-time solver and is designed to be operated without waiting. So if I see these numbers climb too high, I'll crank up the number of optimisations to bring them back down again. Simple!
There will be a publicly available website for this information - with graphs and charts - such that we can all witness just how fast Ragdoll is and get some perspective on the kind of workload it typically deals with. From this overview, development can then focus on exactly those.
"},{"location":"releases/2021.06.10/#fractional-start-time","title":"Fractional Start Time","text":"You wouldn't normally set your start time to 0.8
or 16.351
, but it can happen whether you like it or not if e.g. physics was made in one scene and later referenced into another with differing frame rates. Such as 24 fps in one, and 30 fps in another.
If that happened, then best case your simulation flickers on the first frame, worst case you're looking at a fatal crash.
Why?
In this illustration, you can see how the simulation (blue) progresses alongside time (red). As we reach just beyond a whole frame, such as 1.1, you'll notice how the simulation immediately fills in that whole frame; even though we haven't actually reached the end yet!
The result is a simulation that operates on incomplete information. Your animation at frame 1.1
is not where it is at frame 2
.
In this release, here's what happens instead.
Now we're only simulating once we've actually reached a whole frame step. Your animation has reached the full pose at that frame and that's what will be used to compute the simulation. As you would expect.
Does this mean I can playback in fractional frames?
Not yet, simulation happens on whole frames and won't output anything until the next whole frame. At a later date, fractional frames will be automatically interpolated, similar to when you bake a simulation and set keys to linear
.
This isn't typically useful for animation, but can help with motion blur during the rendering of fast-moving objects; especially spinning objects like propellers and wheels.
That said, you can achieve some pretty surreal effects with this. :D
Stay tuned for real-time interpolation, and do let me know if this is something you're interested in.
Thanks to Amedeo Beretta for spotting this issue!
"},{"location":"releases/2021.06.10/#suspend-on-bake","title":"Suspend on Bake","text":"Baking is fast and light with the default option for disabling the viewport as it runs, but should you also opt to delete physics once baking is complete you would find suspension to have no effect. :(
This was due to deletion of physics also suspending the viewport as it deletes things and - wanting to be helpful - went ahead and resumed rendering of the viewport before baking got a chance to get started.
This has now been fixed.
Speed!
0.51 seconds versus 0.13 seconds, a 4x speedup!
"},{"location":"releases/2021.06.10/#more-resilient-constraint-rendering","title":"More Resilient Constraint Rendering","text":"You are unlikely to end up with zero scaled things, but if you do you could also run into visual flicker like this.
Before
After
Not only is this gone, it's fast too. It is as fast as though the constraints were never visible to begin with, giving you another option for hiding them. Scaling them down. Hah!
"},{"location":"releases/2021.07.02/","title":"Quality of Life","text":"Highlight for this release is quality of life.
In preparation for the upcoming website, there are 4 new animations in progress. Here's just a taste. :)
"},{"location":"releases/2021.07.02/#replace-mesh","title":"Replace Mesh","text":"When you turn a mesh dynamic, the vertices are plugged into the rigid node.
mesh
nodes plug into rdRigid.inputMesh
nurbsCurve
nodes plug into rdRigid.inputCurve
nurbsSurface
nodes plug into rdRigid.inputSurface
But what if you wanted a different mesh? What if there was no mesh, such as for a joint or empty transform?
I give you, Replace Mesh
. \ud83d\udc4f
Here's a more practical example, of a dynamic joint being replaced with the mesh of a car wheel.
"},{"location":"releases/2021.07.02/#freeze-evaluation","title":"Freeze Evaluation","text":"Rigid bodies have an Enabled
state to exclude it from a simulation, but it will still partake in most evaluation and still cost precious CPU cycles.
In Maya 2016, an attribute was introduced for exclude nodes from Parallel Evaluation called .frozen
. Ragdoll now supports this attribute to a limited extent.
This operation is completely non-destructive and affects nothing but the nodes you select.
Important
The more you freeze, the more performance you gain, and that includes Maya's native nodes. So go ahead and freeze the controls as well.
Caveat
The optimisations are coming from deep within Maya and is mostly outside of our control. And it isn't perfect. How Maya chooses to evaluate nodes is sometimes a mystery, and sometimes even frozen nodes get included in evaluation. For the technically minded, you can read more about the attribute and behavior here.
Sometimes, you find yourself with rigid bodies that could run separately, in parallel. Either for performance, or because they could benefit from independent solver settings like iterations and substeps, or time scale and more.
Now you can extract rigid bodies from one scene into a new scene, akin to extracting polygons from one mesh into another.
Extract
Move one or more rigids out of one scene, and into another.
Move
Move one rigid between two scenes.
Merge
Collapse two or more scenes into the first-selected scene.
Constraints
For constraints to work, both rigids must be in the same scene and currently extracting only one rigid from a constrained pair would break the constraint. In a later version, the rigid will automatically become a Passive rigid in the extracted scene, such that it can still be constrained albeit indirectly.
This will enable you to extract parts of a simulation, like muscle and cloth, from an overall dynamic character without breaking anything.
"},{"location":"releases/2021.07.02/#ignore-contact-constraint","title":"Ignore Contact Constraint","text":"You can now select two rigids and say \"Hey, ignore each other, ok?\"
Technically, this is just a constraint but with both the Limit
and Guide
disabled, and Allow Overlap
kept enabled.
The Bake Simulation tool now allows you to bake either all or selected scenes.
"},{"location":"releases/2021.07.02/#multi-mesh-shapes","title":"Multi-mesh Shapes","text":"The rdRigid
node has an attribute called .inputMesh
which takes a normal Maya mesh, like a polyCube, and turns it into a volume suitable for simulation. It's also got a .inputCurve
and .inputSurface
attribute, to treat NURBS curves and surfaces in the same way.
Until now, only one of these could be connected at a time. Connecting to one when another was already connected would lead to undefined behavior. In this release, the behavior is defined! If you want two meshes, you can have'm!
"},{"location":"releases/2021.07.02/#edit-constraint-and-chain","title":"Edit Constraint and Chain","text":"When you make a chain, attributes from rigids and constraints are mapped to the original animation control as attributes. When you then want to edit the constraint pivot of any of those constraints, it would overwrite that connection so as to make it easier/possible to edit values directly from the locators that appear representing the pivots.
This no longer breaks your connections, at the expense of having to edit values on the original constraints instead. This will be addressed in a future release, once we get a proper manipulator in place instead of the makeshift Maya transform.
"},{"location":"releases/2021.07.02/#constraints-and-focus","title":"Constraints and Focus","text":"The F-key zooms and centers and object in the viewport. But trying that on constraints would have you flying through the cosmos until NaN
appears in your channel box.
Before
After
"},{"location":"releases/2021.07.02/#skinweight-painting","title":"Skinweight Painting","text":"Any joint with a shape causes the right-click menu to stop working. It's typical Maya, and has been the case for years.
Ragdoll nodes are mostly shapes of the control they drive, including joints. As a result, you weren't able to right-click on a dynamic joint to select its skinweights..
Before
After
"},{"location":"releases/2021.07.02/#referenced-physics","title":"Referenced Physics","text":"The previous releases tried adding any new physics added to a referenced physics scene, but was unable to! This release fixes that.
"},{"location":"releases/2021.07.02/#two-users-one-machine","title":"Two Users, One Machine","text":"When Ragdoll starts for the first time, a file is written into your temp-directory. The undo plug-in for cmdx
. The file is written using the permissions of the currently logged on user and cannot be touched by anyone else.
When another user logs in to the same machine, Ragdoll will attempt to overwrite this file but cannot! It doesn't have permission! The result is a limit of 1 user able to leverage Ragdoll per machine. And that's no good.
This release fixes that!
"},{"location":"releases/2021.07.02/#export-initialisation","title":"Export Initialisation","text":"If you author physics and immediately export, without playing back, the results could be incomplete. \ud83e\udd14 The reason is that Maya only evaluates what it has to, and until you actually run the simulation a lot of things are left unevaluated. To Ragdoll, it's as if they never existed in the first place.
This has now been fixed.
"},{"location":"releases/2021.07.02/#center-of-mass-visualisation","title":"Center Of Mass Visualisation","text":"With the recent upgrade and performance improvements to rendering, a small but necessary visualisation feature of the rigid bodies was the COM or center of mass.
This has now been restored!
"},{"location":"releases/2021.07.02/#something-went-wrong","title":"Something Went Wrong","text":"The order in which Maya evaluates Ragdoll nodes is important, and whenever it tries doing that in some unexpected way it'll tell you.
# Warning: ragdoll._on_cycle() - Something is not right!\n
The reason it happens is difficult to say. The evaluation order is something Maya dynamically generates on the first frame of your animation, and it's based on the way nodes are connected. Cycles are the most common culprit. Ragdoll cannot stand cycles.
But another reason was discovered in this release which was that when you constrain A to B but then delete B, A is left constrained to a broken constraint. This could throw off evaluation, and break the scene.
This particular situation has now been fixed!
"},{"location":"releases/2021.07.02/#more-accurate-auto-mass","title":"More Accurate Auto Mass","text":"Rigid bodies have an option to have their masses automatically computed from their initial shape. This value was 10,000x wrong, and is now roughly 1-2x wrong. It is 100% accurate for boxes, but diverges from there as it does not take into account the negative volume within its bounding box.
Choose Density
Be like water, my friend.
Responds to Scale
The computed mass will respect the size of the object, and the overall scene scale.
Important
Remember that large mass differences between two rigids that interact can result in instabilities.
In the real world, an object with the density of air under a much heavier object with the density of water would crumble. However, it cannot do that here. Instead, it will bounce around and act unnaturally.
The recommended max difference is 10x. E.g. one rigid can weigh 10 kg, whereas the other can weigh 100 kg. That's at the edge of what the solver (and the real-world) considers manageable.
"},{"location":"releases/2021.07.15/","title":"Launch Tweaks","text":"Highlight for this release is improved Rotate Pivot support.
In a previous release support for the .rotatePivot
attribute was added. But it was only partial. It only applied to solo rigid bodies, like the one in that example.
Once rigids form a hierarchy, things get more complex, but also more realistic. A lot of character rigs make use of it, some even going as far as to leave NURBS controls at the origin, moving the CVs to where the character is and compensating with the .rotatePivot
to make it appear in the right place.
This didn't gel with Ragdoll, who uses the center of a control to determine how to draw chains.
What is this \"rotate pivot\"?
Just so we're all on the same page, here's me creating a control by moving the rotate pivot and CVs rather than translating/rotating the node.
Notice how I'm not actually moving it to the hip, but rather hold the D
-key and move the rotate pivot. Then I'm moving the CVs to where the rotate pivot is to make it both act and appear at the hip.
Why would anyone do this?
Hah! Yes that was my thought too!
As you can see, to make this work you really have to work at it. My guess is this isn't something riggers do by hand but rather via scripting. Done that way, you don't really notice how odd it is.
Either way, there are rigs out there that works like this and it shouldn't limit your use of Ragdoll.
Next, I'll repeat this process for each of my controls.
Pay special attention to how all of my controls are still technically at the origin. Their rotate/translate channels are all zero.
Let's have a look at what the current version of Ragdoll does in this situation.
Before
Notice how nothing appears! That's because Ragdoll tried figuring out where to generate capsules and how large to make them based on the center of each control. But! The controls are all at the origin. They lie there, right on top of each other, with zero distance from each other.
So Ragdoll does what it thinks you want. It generates a series of rigid bodies at the origin with 0 size. When what you really meant was for it to use the center plus this \"rotate pivot\".
After
This release recognises this, here's what it looks like now.
Win!
"},{"location":"releases/2021.07.15/#re-scale","title":"Re-scale","text":"Sometimes you're experimenting and aren't quite sure that the scale of an object is what you'd like it to be until you see it in action.
Currently, whenever you make something dynamic it'll use the current scale of the NURBS curve or mesh as part of the collision geometry. But! If you change the size after making it dynamic, Ragdoll won't know about that.
This was especially damning for geometry that needed to be tesselated, namely the Mesh
shape type. The most convenient way of refreshing that was to edit the .shapeVertexLimit
attribute, forcing a re-tesselation.
That's because Ragdoll cannot know when you resize something. You have to explicitly say you did. That is, until now.
Caveat
It still isn't perfect.
Ragdoll still cannot know when you scale the object. Instead, it queries the current scale on the 1st frame of the simulation, which means it won't actually recognise a new scale until the 2nd playthrough.
That's because once the simulation starts, the initial state is automatically set. Only then can it know that scale has changed, but by then it is too late! Simulation has already begun. So instead, the change is picked up on the next playthrough.
Of course manually setting the initial state (via the Rigging sub-menu) or re-opening the scene will have the same effect so you really shouldn't have to struggle with this in practice.
"},{"location":"releases/2021.07.15/#scene-tolerance","title":"Scene Tolerance","text":"Ragdoll assumes you're working with human characters in centimeters, meaning a value of 170 means 170 cm and 0.1 cm is a small distance. If that's true, then you typically won't have to worry about \"tolerances\".
But if you're characters are 17,000 units tall or 0.017 units short odd things start to happen.
Notice how it initially slides around for no apparent reason? In this case, the cube is much smaller than Ragdoll expects and we can address this by decreasing the global scene scale.
Likewise, for very large cubes you will notice similar artifacts. For that, you'd increase the scale.
Currently, there exists a Scene Scale
on the solver node, which is saved in your scene, and a Scene Scale
in the global preferences which is not. The intention is for global scene scale to rarely change, to change alongside a studio's or project's convention, whereas the solver scene scale is more flexible.
The default value is 10.0
but it's possible smaller values such as 0.1
is better suited. It's also possible they both belong under global preferences. Give this a try and let me know what you think.
There are two kinds of limits; twist and swing.
Twist is great for hinge-like limits, like knees and elbows, whereas swing is great for more complex 2D limits like shoulders and hips. The current position of a rigid body in terms of swing and twist have always been drawn as a green/red line, but it could sometimes be hard to know which was which. If the red line starts out in the twist limit, then Ragdoll will promptly snap it back into the swing limit.
This release colors the twist and swing shapes using the same colors as the current twist and swing axes, making it just a tad easier to see which belongs where.
Before
After
Also notice how the twist axis is now confined into the twist shape itself, making it just a bit more clear how close it is to colliding with that limit.
Here's a more complete example of a full set of constraints.
"},{"location":"releases/2021.07.15/#unique-names","title":"Unique Names","text":"Prior to a recent release, all new nodes generated by Ragdoll was given a unique name. That really shouldn't matter to Maya, as nodes are distinguished by their parent. For the most part. But sometimes not!
For example, cycle warnings produce a message only containing the name of the node itself, not its hierarchy. So you wouldn't be able to tell which of the many rigid nodes were at the root of any cycle by merely looking at this message. And don't get me started on the connection editor. It's perfectly capable of making and breaking connections, but refuses to auto-fill the currently selected nodes if they happen to have the same name as any other node in the scene!
In any case, this has now been fixed and all nodes are once again unique. Automated tests have also been put in place to prevent this slip-up from happening again; but do let me know if you find any duplicates as Ragdoll generates a lot of nodes, and it's possible one may have yet slipped through!
"},{"location":"releases/2021.07.15/#passive-constraints","title":"Passive Constraints","text":"Select two rigid to create a constraint.
But if one of those rigids was passive, or even animated between passive and active, and had a different passive animation than the initial state, and your constraint could end up like this.
Before
Especially notice how the passive pose differs from the initial active pose. The active pose was used to compute how to draw the constraint, whereas the passive pose was used during the simulation.
After
This has now been fixed!
"},{"location":"releases/2021.07.15/#single-joint-shapes","title":"Single Joint Shapes","text":"In the rare case of turning solo-joints dynamic, you could end up with results like this.
Before
After
This has now been fixed!
"},{"location":"releases/2021.07.15/#bake-static-rigids","title":"Bake Static Rigids","text":"There was a bug when baking simulation for any rigid what started out passive, e.g. it was hard pinned, but animated active. The Bake Simulation command would mistake these later-simulated rigids as passive, and simply not bake them.
This has now been fixed!
"},{"location":"releases/2021.07.27/","title":"Launch","text":"Highlight for this release is the Launch of 1.0!
Out with the old, in with the new. As they say! Ragdoll is finally here!
Read Announcement Try it "},{"location":"releases/2021.07.27/#evolution","title":"Evolution","text":"For the fun of it, here's a look at how the website has evolved since day 0.
"},{"location":"releases/2021.07.27/#september-2020","title":"September 2020","text":"Soil was fresh, seeds planted.
"},{"location":"releases/2021.07.27/#january-2021","title":"January 2021","text":"Flowers were blossoming, sun was shining.
"},{"location":"releases/2021.07.27/#july-2021","title":"July 2021","text":"Fruits were ripe, table is set.
"},{"location":"releases/2021.08.06/","title":"New Documentation","text":"Highlight for this release is new documentation!
Put together this example of animating a Pinocchio-like character recently, which is trending on LinkedIn. :D
"},{"location":"releases/2021.08.06/#linkedin","title":"LinkedIn","text":"The Ragdoll page on LinkedIn is getting some more attention since launch - keep refreshing that page if you'd like to stay up to date with the latest and greatest, including new version releases and cool simulations to inspire and delight.
3,000% haha, let's see if we can keep that up!
"},{"location":"releases/2021.08.06/#menu-documentation","title":"Menu Documentation","text":"Items from the Ragdoll menu are getting some spotlight in the new Documentation
section in the learning material!
In it, you'll find basic tutorials, basic information and tips and tricks on how to use each item, such as the Active Rigid. Along with supplementary information such as Debugging Tips and details about the Cycle Protection.
\ud83d\udc48 See new navigation to the left
"},{"location":"releases/2021.08.06/#non-commercial-telemetry","title":"Non-Commercial Telemetry","text":"Opt-in telemetry was added to Ragdoll a few releases ago via the environment variable RAGDOLL_TELEMETRY
. This behavior is now default for Trial and Personal licences of Ragdoll, and remains opt-in for Complete and Unlimited licences.
The following bugs were harmed in the making of this release.
"},{"location":"releases/2021.08.06/#add-to-referenced-scene","title":"Add to Referenced Scene","text":"A minor but critical bug was discovered whereby you couldn't add a new rigid body to a referenced Ragdoll scene. It had to do with Ragdoll needing to know which scenes are present whenever a new rigid is made, something it keeps track of by listening to an event for \"Maya Open Scene\". But this wasn't triggered for \"Reference Scene\" which led to some confusion.
This has now been fixed!
"},{"location":"releases/2021.08.06/#maya-20221","title":"Maya 2022.1","text":"Finally that service pack was released for Maya, addressing a critical but which led many users to experience fatal crashes when attempting to delete rigids from their scene.
This has now been fixed (by Autodesk!).
"},{"location":"releases/2021.08.06/#import-physics-in-maya-2022","title":"Import Physics in Maya 2022","text":"A Python 3-related error was discovered in Maya 2022, meaning you couldn't use the UI to browse for Ragdoll files. :(
This has now been fixed!
"},{"location":"releases/2021.08.28/","title":"New Tutorials","text":"Highlight for this release is new tutorials!
Sphere
shape typeThree new tutorials from basics to intermediate, with more to come!
"},{"location":"releases/2021.08.28/#bouncing-ball","title":"Bouncing Ball","text":"Learn the fundamentals of Ragdoll in this classic animation tutorial.
View Tutorial "},{"location":"releases/2021.08.28/#rally-car","title":"Rally Car","text":"Build upon the skills learnt with a bouncing ball to combine several rigids into a car (with an engine!)
View Tutorial "},{"location":"releases/2021.08.28/#manikin","title":"Manikin","text":"Construct a full ragdoll from any rig, even your own custom one!
View Tutorial "},{"location":"releases/2021.08.28/#personal-ui","title":"Personal UI","text":"The Licence Window at the bottom of the Ragdoll menu now accurately displays your current licence, including Personal, Complete, Unlimited and Batch, along with the licence type - Floating
or Node Locked
.
Can you believe it. A clear sign of success, not everyone is on Twitter! If you're one of the lucky few, you can now follow along with updates to the project, documentation and general company news from there!
The only question is, who's going to be the first to follow? \ud83d\ude31
"},{"location":"releases/2021.08.28/#pivot-editor","title":"Pivot Editor","text":"In making he tutorials, the main bottleneck in terms of time taken was editing constraints. They are both complex and difficult to manage.
This release addresses this problem with the Pivot Editor GUI.
"},{"location":"releases/2021.08.28/#basics","title":"Basics","text":"Here's how to use it to tune a broken knee.
"},{"location":"releases/2021.08.28/#spin-swap","title":"Spin & Swap","text":"One of the main reasons to want to edit constraint pivots is to align the Twist axis with the main rotation of a knee or elbow.
"},{"location":"releases/2021.08.28/#mirror","title":"Mirror","text":"If the pivots face in opposite directions, orientations can be un-mirrored with the Mirror
option.
Tuning limits alongside pivots works well too, middle-click drag attributes from the Channel Box like you normally would, whilst dragging in the UI to compensate.
"},{"location":"releases/2021.08.28/#snap","title":"Snap","text":"Use the snap option to make precise adjustment to specific angles.
"},{"location":"releases/2021.08.28/#worldspace-trajectories","title":"Worldspace Trajectories","text":"Trajectories used to follow the scene wherever it went. Now they'll stay put, where they belong.
Before
After
"},{"location":"releases/2021.08.28/#sphere-rendering","title":"Sphere Rendering","text":"This fixes a minor annoyance you may have noticed, of the outline of spheres visible in shaded mode.
Before
After
"},{"location":"releases/2021.08.28/#floating-server-details","title":"Floating Server Details","text":"When you first lease a licence from your licence server, the IP and port details are stored on the local machine for quicker access the next time.
However, if you then later needed to change those details, then any local machine previously leasing a licence would not be able to update their details.
This has now been fixed!
"},{"location":"releases/2021.09.27/","title":"Animation Capture pt. 1/4","text":"Highlight for this release is Animation Capture.
Let's start with some eye-candy, thanks to Jason Snyman for the gorilla rig! :)
"},{"location":"releases/2021.09.27/#introduction","title":"Introduction","text":"Lighter, faster, stronger. This release introduces a new way of thinking about physics, and is part \u00bc.
Something amazing has happened.
Since release only a few weeks ago, Ragdoll is now used in production across the globe in over a dozen countries at the most major of studios, several dozens of mid-sized studios wanting to gain an advantage and hundreds of independent animators and riggers alike.
And that is amazing, it is. But something even more amazing has happened; Ragdoll has leaped forward. And that will be what the next 4-part release is about.
See, since launch I've had conversations with animators using Ragdoll for the very first time. One of those animators made a request that at first glance didn't look like much.
Quote
\"I don't like working with green channels, as it is not ideal for animating. Is there a way to I can overcome this?\" - Christopher Page
Here's what he was referring to.
Notice how the nodes with physics applied got green channels? The reason they are green is because Ragdoll is driving them. They are green rather than yellow because you can still edit them, at the same time as Ragdoll is editing them. Your changes will be reflected in the simulation, this is how you control the simulation as it is running.
Can we get rid of that connection? Well.. No? This is Ragdoll's connection to your controls. Without those.. there is no physics.
I quickly dismissed the idea and carried on with my day.. But then something clicked.. What if..?
In the next section, I'll dive into how this works and why this change goes far beyond just getting rid of green channels.
Benefits at a glance
From here, this list has no end, because anything capable of affecting the worldspace position and orientation of your controls is natively supported with this workflow. Anything.
I'm a techy, gimme the deetsThe reason this works is because Ragdoll will consider the .worldMatrix
attribute of any control and this is the same attribute Maya itself uses for just about anything.
Inspired by Motion Capture - Animation Capture is a new way to think about and work with physics in Maya. To learn about it, let's first understand how Motion Capture generally works.
Here is a typical data pipeline for motion capture, from real-life actor to final character animation.
# Description 1 Markers are attached to an actor 2 Markers are \"captured\" 3 A pointcloud is generated 4 A hierarchy of joints is generated 5 Joints drive a typical character rig 6 Rig drives final geometry for renderEach \"marker\" is a dud. Nothing of any complexity. Something for the camera(s) to recognise and track as it moves through space. Once tracked, it's able to translate this marker from a 2D image into a 3D position, and continues to do so for each marker, for the real processing to take place inside software.
Once the capture is complete, the human actor can remove the markers and go enjoy the rest of their day. The rest is up to the computer.
With 3D positions generated, software takes over to translate these points into a hierarchy; the FK joint hierarchy you may be familiar with if you've ever worked with mocap. The joint hierarchy can then be used to either drive the final geometry, or to drive a more complex character rig which in turn drives the final geometry.
Animation Capture is just like that, but in reverse. Instead of capturing a person, it captures your character rig.
# Description 1 Markers are attached to a character rig 2 Markers are \"captured\" 3 A rigid is generated for each marker 4 A hierarchy of constraints is generated 5 Simulation is recorded back onto the original character rigUnlike motion capture, we'd like the result mapped back onto our character rig again, which is how animators iterate with physics.
"},{"location":"releases/2021.09.27/#demo-1-basics","title":"Demo 1 - Basics","text":"Ok, enough prelude, let's dive in.
Before
Here's what life was like before, with Active Rigid
.
After
And here's life with Markers
.
Notice how the channels are left alone?
This is the key difference between Marker
and Rigid
. Although you still provide Ragdoll with controls, Ragdoll no longer drives your controls directly. Instead, it shows you what they would look like if they were driven with physics.
Once you're happy with what you see, you Record
.
Let's have a look at how Markers
work with a full ragdoll.
1. Setup hierarchy
The first step is nothing new, you've seen it before.
2. Edit shapes
This too, it's second nature by now.
Except!
Notice how the shapes overlap? That's ok! No longer will you have to worry about self-intersecting shapes. Unless you want it to, with the new Self Collide
attribute. :D I'll touch on this a bit more below, under #self-collide
Double Except!
Release 4/4 in this series will deal with the channel box, and make editing these values interactive in the viewport for a superior experience and a lot less clicks and fiddling with numbers.
3. Animate
Now things are getting interesting. To keep our viewport clean, we can offset the simulation slightly. The offset is purely visual and won't affect the simulation or subsequent recording.
4. Record
Finally, and this is what separates Markers
from Rigids
, we record our simulation back onto our controls.
That last example was contrived. No rig is without IK, so how does Markers
work here?
1. No IK
Since we put markers on the FK controls, Ragdoll doesn't know about what the IK controls are doing.
2. Reassign
So let's put markers on the joints driven by both IK and FK, such that when you switch between the two, Ragdoll knows how to follow along. So let's Reassign
.
3. Retarget
But recording still targets our original FK controls, and what we want is to record our IK controls. So we can Retarget
.
4. Record Translation
Unlike FK, IK isn't just rotation, but translation too. So let's tell Ragdoll to record the translation from these markers too.
And there you have it! This works with IK, SpineIK, Follicles, Geometry Constraints; anything you can throw at it.
"},{"location":"releases/2021.09.27/#demo-4-real-world-example","title":"Demo 4 - Real World Example","text":"Here's a work-in-progress animation from Christopher Page (thanks for lending it to me!) Let's see how we can use Ragdoll to help improve upon it.
1. The Problem
Notice how the elbow intersects the table as he moves his torso around? A difficult problem and moving target as you need to keep tweaking both the torso and hand IK handle to tune your animation.
2. Isolate Timeline
Since this animation is over 600 frames, we'll isolate our work to a small portion of it. For both performance and cleanliness; Ragdoll will only record onto the current timeline (or selected portion of it).
3. Assign Markers
Like before, we'll assign markers to the underlying skeleton to respect what the IK solver does. We'll also make the hand Kinematic
to respect the original animation exactly. The clavicle is also Kinematic
per default, as it was the first assigned control - and is thus the \"root\" of our dynamic hierarchy.
4. Include Table
Since we're interacting with the table, we'll include this too. Also Kinematic
, no dynamics will be affecting it, and also as a Box
shape to speed up and improve the stability of the simulation.
5. Tune Shapes
Next we'll isolate contacts with just the elbow area, to respect the hand and lower arm animation.
6. Tune Material
In this case, we'd like for the elbow to slide across the table, no friction.
More Realism?In the real world, there would be friction and it could come in handy here too. But what should we expect from the elbow rubbing against the table? We should include the torso for this as well, which you absolutely can (and maybe should!). But to keep things simple, we'll let the clavicle preserve it's original animation exactly.
7. Retargeting
Ragdoll will record onto the nodes you originally assign, but like before we want recording to go elsewhere; from joints to IK controls.
8. Record Translation
Likewise, we'd also like translation included. And we don't care for the shoulder and clavicle animation; all we want is the IK handle and Pole Vector.
9. Record Simulation
We're all set! Let's hit Record
!
10. Before And After
And there we go! 2 minutes or less, and you've got a reusable setup for correcting the elbow whenever the animation changes. IK is intact and you can keep working with keyframes. Keeping Ragdoll attached to your rig has zero impact on performance (as you can see by looking at the fps counter near the bottom of the two comparisons), and once hidden it has no impact on your Outliner either. All clean!
Here's one more I couldn't find room for, an earlier version of the animation with stepped keys and finger simulation. Look at all that juicy finger interaction with the table. \ud83d\ude0a
Rig and Model courtesy of Ramon Arango - Apollo Rig
"},{"location":"releases/2021.09.27/#new-menu","title":"New Menu","text":"Let's take a moment to reflect on what we've just seen. There are 3 new nodes in Ragdoll.
# Node DescriptionrdSolver
The \"camera\" that monitors \"Markers\" and performs all heavy-lifting. rdMarker
A tracking marker, something to monitor an individual control. rdGroup
A collection of markers, with high-level control over many markers. Here's the new menu. If all goes well, it will completely replace the Active Rigid
and Active Chain
menu items, along with Controls
including Mimic
. All of those things are made possible in a much easier and performant way using Markers.
The most important elements are at the top.
# Item DescriptionAssign Single
Monitor a single object in the Maya scene. Use this for props, environment and other free-falling things. Assign Group
Monitor a series of connected objects, like a limb. Record
Transfer simulation to marked objects Like Active Chain
, the order of selection determines the order in which markers assume your objects are connected. And adding more markers to a group is done by starting your selection from any point in an existing group and working your way outwards. Just like Active Chain
.
Limitations
You currently cannot create multiple rdSolver
nodes, but can work around it by importing one from another Maya scene file.
The Guide Space
is somewhat complicated. The group has one too that affects all markers, and per default it's set to -1
for Localspace
. The benefit is that you can quickly change the space for all markers by changing this one attribute. The downside is that if you want to change it for just one marker, you first need to reset this attribute to 0
.
These will be addressed in the upcoming few releases.
"},{"location":"releases/2021.09.27/#recording","title":"Recording","text":"Markers can be recorded all together, or independently. For example, say you wanted animation from frame 1-100, simulate 101-150 and return to animation from 151-200. You can do that.
Furthermore, say you liked what the simulation was doing, but only on one half of the body. Or only on the hip, driving the main trajectory in a physically-plausible way. Keeping the rest of your animation intact.
Record All
With nothing selected, Ragdoll will record all marked controls to the current Maya playback range.
Record Selected Markers
Select a few controls to control what gets recorded.
Record Range
Limit the Maya playback range for control over when recording takes place.
Record Selected Range
Or, select an explicit range interactively.
Intelligent Range
A Kinematic
marker is entirely animated, so there's no need to actually record those. Ragdoll will ensure only non-kinematic frames are recorded, so you can do things like this.
Record to Animation Layer
Ragdoll will record to whichever layer is currently active.
"},{"location":"releases/2021.09.27/#input-type","title":"Input Type","text":"In the above examples, I mentioned Kinematic
and you probably spotted a few other options too, like Inherit
and Guide
. What are those?
The Input Type
is how Ragdoll should interpret the controls you assign. Did you mean for them remain animated, i.e. Kinematic
? Or should they follow the control around, i.e. Guide
? Or should they just fall with gravity, ignoring the original control altogether, i.e. Off
?
The Input Type
can be set either for a whole group of markers, or each marker individually.
Kinematic
if there is no group Off Do nothing, just fall under gravity Kinematic Follow the input exactly, physics need not apply Guide Follow the input approximately, with some Stiffness
and Damping
Off
Treat the input as a starting position, but nothing else.
Kinematic
Follow the input exactly, no exceptions. Not even collisions.
Guide Space -1
Follow the local angles of the input.
Guide Space +1
Follow the world position and orientation of the input.
"},{"location":"releases/2021.09.27/#retarget","title":"Retarget","text":"We've talked a lot about \"retargeting\". But what is that?
Per default, markers are recorded onto the controls you assigned, this is called Rig to Rig
.
But often times, rigs are more complicated and what you want is for the simulation to look at one set of nodes, but record onto another. This is called Joint to Rig
, but can be from any source. Even other controls (like FK to IK).
The Old Days
Think about how you would accomplish this using the Active Rigid
or Active Chain
commands. That would be a huge pain, but not with markers!
Over in Demo 2 - Ragdoll we \"reassigned\" already marked controls. What does that mean?
In that example, we've assigned our FK controls directly, which means Ragdoll would grab the translation and rotation from those controls during simulation. But what we really wanted was the IK controls.
But! We couldn't just assign to the IK controls directly, since they are indirectly rotating a characters limbs. So instead, we Reassign
the markers previously made onto the underlying joints that follow IK around.
We then also Retarget
them, since they would have otherwise been recorded onto the original FK controls.
Sometimes, you change your mind.
Success!
"},{"location":"releases/2021.09.27/#guide-space","title":"Guide Space","text":"Now let's talk about a few things you haven't seen yet.
Look, it's Ragdoll Blaine!
So what's happening here? Well, it looks like a Soft Pin to his head, along with a slight Guide Strength
on the rest of his body. But unlike the Rigid
, another significant advantage to Markers
is their ability to capture both local and worldspace position and orientation of your controls. And because of this, you are able to interactively choose whether a marker should look at the Worldspace or Localspace position of your controls.
Notice how with a Guide Space = -1
the controls arms remain relative the torso. And with Guide Space = 1
they instead follow the worldspace orientation of the controls. Just like a Soft Pin.
This attribute is also animatable, and is how you can transition from animation into simulation and back again.
Here's a more complete example:
Frame Transition 100 Starts as a regular animated character 125 Transitions into physics as he jumps, for a physically-correct trajectory 155 Transitions back to animation once he rolls over on that cabinet 160 Transitions back to physics until he stands up 170 Transitions back into animation to match an exact pose 200 Partially transitions into physics, for secondary motion in the upper body as his arm is raised. "},{"location":"releases/2021.09.27/#transitions","title":"Transitions","text":"Let's have a look at how you would use markers to transition between simulation and animation.
Notice how we're animated up until the jump, and then Ragdoll takes over. Once he approaches that box, we turn our Guide Space
from -1
to 1
and have him reach the target pose in worldspace. Once he's close, we switch Input Type
to Kinematic
and kinematically move him until we once again transition to Guide
, this time with a Guide Space
or -1
for pose space.
Previously, it was very important that your shapes did not overlap any shape other than it's immediate neighbour. If they did, chaos ensued.
Before
Clavicles intersect their parent spine, but also each other!
After
With the new Self Collision = Off
, this is no longer a problem.
This can be taken into the extreme!
And here's a another example to fill out a large volume in the center of a character.
Attention
Notice how the spine is made up of many shapes, some of which cover the width of the body, others the depth. An overlapping mess that would never have simply not have been possible without self-collision support!
Original asset created by Mehmet Tayfur T\u00fcrkmeno\u011fluwe and Dr. Reel, licensed by The Rookies.
"},{"location":"releases/2021.09.27/#no-graph-editor-mess","title":"No Graph Editor Mess","text":"Because Rigids
were children of your controls, Maya had a funny way of including them in the Graph Editor that rightly drove animators, myself included, absolutely mad.
Before
Just look at this; why-oh-why would I want channels from a completely unrelated node when working with the hip?
After
Contrast that to this, whereby only the nodes you actually select are made visible. You can even select Markers
via the Channel Box and deselect your controls to get up real close.
A significant effort was made to make the simulation start where you expected it to.
Under the hood, simulation and animation were at odds with one another. Ragdoll needed to know where to start, but it was also telling your controls where to start. It's an inherent cycle, which was finally broken.
Read More
You can read all about the month-long journey in the release notes from March
Nowadays, you barely have to think about it, but it does occasionally rear its ugly head. It is a hack.
With Markers
there isn't any cycle to begin with. Ragdoll only reads from your controls, it doesn't write to anything. Under the hood, recording is a 2-step process; first it simulates, and then it writes animation back onto the controls. That's how this cycle is broken, without having any effect on the overall workflow.
With the previous version, because Rigids
both read and wrote to each control, you could sometimes run into a situation where the parent depends on a child.
Before
Here, I'll try and make a second chain in the opposite direction of how the controls are laid out hierarchically. This cannot work; because in order for Ragdoll to figure out where the Passive hand should be, it would first need to consult the upper arm, which is both dynamic and a child of the spine, which is also dynamic. It's a lovely cycle. \u2764\ufe0f
After
With Markers
, this isn't a problem because to Ragdoll every limb can now be independently evaluated, in parallel.
Sometimes, markers are added to an already busy control with tons of Channel Box entries. Lollipop controls can help organise things a little better.
These can be moved around and scaled to suit your needs, and will provide access to the same marker node in the channel box, so you can select and edit the marker from either the originally marked control or this lollipop control.
"},{"location":"releases/2021.09.27/#rotate-pivot","title":"Rotate Pivot","text":"Use the default Maya rotate pivot to control where to pin a simulation, both in worldspace and localspace.
Attention
Take care about scale, especially the scale pivot. Ragdoll can sometimes struggle when the scale pivot differs from the rotate pivot. This will be addressed in a future release.
"},{"location":"releases/2021.09.27/#quality-of-life","title":"Quality of Life","text":"Some minor things to brighten your day.
"},{"location":"releases/2021.09.27/#real-ground","title":"Real Ground","text":"With Rigids
, the ground was embedded into the scene. With Markers
, an actual ground is created to for more stability and more control over its physical parameters. Something that can also be animated, and that dynamically appears right underneath your markers.
The Attribute Editor doesn't show you Rigids
related to Maya joints because of a Maya UI quirk.
With Markers
, this is no longer a problem!
Hiding the solver completely removes all overhead of having Ragdoll in your scene. Previously, with rdScene
and rdRigid
, because they were directly connected to your controls, hiding things made little difference. But now, because we no longer have this direct connection, all computations come from explicitly seeing the rdSolver
node.
No visible rdSolver
node, no computations. Period.
TLDR
Sometimes, re-opening the scene could lead to different results. This has now been fixed.
Each time you play a simulation starting from the beginning, the results are the same. This is an important characteristic of any simulation and is called \"determinism\". It used to be the case however that when you re-opened the scene, there was a small chance the results would differ from when you last saved it.
This has now been fixed. The determinism is now dependent on the order in which rigid bodies connect to the rdSolver
node. It's an array attribute, whose order is saved with the Maya scene.
Whenever a machine connected to your floating licence server, the host and IP were stored on the machine in an effort to speed up subsequent connections made. However, this also meant that you weren't able to update those details.
Despite providing new details, Ragdoll would favour the already-stored details. Worse yet, the Ragdoll UI would lie to you, by repeating the connection details provided in the RAGDOLL_FLOATING
environment variable, despite those not actually being used.
This release addresses this by always using the details you provide, and not bother reusing any previously provided details. In addition, you now have the option to explicitly query and set server details directly.
# Will query the *actual* server used by Ragdoll, rather\n# than return the environment variable you provided\ncmds.ragdollLicence(getServer=True)\n\n# Will manipulate the currently-in-use key, meaning it will\n# try and drop a licence from this address as well\ncmds.ragdollLicence(setServer=(\"localhost\", 1313))\n
"},{"location":"releases/2021.09.27/#next-release","title":"Next Release","text":"This release is part \u00bc, for next 2/4 release you can expect Performance Improvements.
In this release, simulation and overall Maya scenegraph performance has seen a 200x performance boost, the performance is already there. You'll notice it as you try them on your rigs.
However, rendering performance has dropped significantly, cancelling out most of that performance gain. Here's what performance looks like now.
Rendering mostly Maya default shading, rendeing its own things. Unrelated to Ragdoll. The Rig Evaluation on the other hand is almost entirely Ragdoll. It's connected to every control in this rig, forcing each control to be evaluated in serial; one after the other.
Here's what it looks like with Markers
.
Notice the huge pile of lines to the left? Those are all running parallel and almost entirely default Maya evaluations; things your rig would do without Ragdoll. Rendering on the other hand is almost entirely Ragdoll, it is very slow.
To properly compare performance between Rigids
and Markers
, here's what you should be looking at.
This is the only thing Ragdoll does to your rig. This is the entire overhead, the added load onto your rig. 16 microseconds. That's 0.016 ms
. For a rig to run at 30 fps, it'll need 1,000/30 = 33 ms
per frame. This overhead, 0.016 ms/frame
is all Ragdoll needs to solve an entire character, contacts and constraints and forces, all of it. In this particular profiling, that's 430x faster than Rigids
, which not only took longer to solve but made everything else slower by just being connected to your controls.
So how about we get this rendering performance sorted, shall we?
"},{"location":"releases/2021.09.27/#limitations","title":"Limitations","text":"These are some of the things lacking from Markers
in this release that we'll be working on for subsequent releases.
Highlight for this release is Performance, and is part 2/4 of the new Markers.
You know the drill, we'll start with some eye candy. \ud83c\udf6c
New Shading
Now more like actual candy. Nom nom nom!
Raining Ragdolls
Quick! Get inside!
Do the Robot
Model and Rig courtesy of Amedeo Beratta
Vehicular Render
Made by @tris
Guide Space Mania
Oh the trickery you can get up to. \ud83e\udd73
"},{"location":"releases/2021.10.07/#anniversary","title":"Anniversary","text":"That's right! Ragdoll turned 1 this week! \ud83e\udd73
In my original business plan, I had written..
\"Revenue, year 1: \u00a320,000\"
..which was blissfully optimistic. However! I'm happy to say that Ragdoll blew past this in the first 6 days into launch, on the 28th of July this year. Very few startups achieve this amount of revenue in year 1; the vast majority achieve \u00a30 for the first number of years (I watch a lot of Dragon's Den \ud83d\ude05), the expectation being that they will regain their investment once enough value has been created. But given we're past this point already, this to me is validation that you want this.
So, let's keep it going, shall we? :)
"},{"location":"releases/2021.10.07/#manikin-rig","title":"Manikin Rig","text":"Throughout these notes, I'll be using this guy here. Feel free to download and play around with it.
Download Manikin "},{"location":"releases/2021.10.07/#performance","title":"Performance","text":"This release was all about performance, so how did we do?
In short, very well! We're now a lot closer to the capabilities of your hardware with a lot less waste. Because you see, software development is a lot like Jenga. You start off with a tower full of bricks, but every brick adds to the overall weight of the tower. And not every brick is necessary to keep it standing. The Eiffel Tower is an example of what a structure can look like with the absolute minimal amount of material. It is an optimal shape; anything added is wasted weight, anything removed would sacrifice stability. That is the structure we've been working towards with this release.
In terms of time spent, Ragdoll has three stages.
# Stage Description 1Evaluation
This is primarily your character rig - the transform hierarchy, constraints, any deformers, and so forth. It is how data is passed from Maya into Ragdoll. 2 Simulation
Once data has been aquired, Ragdoll considers all of it and applies forces, solves constraints, contacts, that kind of thing. 3 Rendering
Finally, we need pixels. In the case of Ragdoll, this means generating and uploading geometry to the GPU; including capsules but also your meshes which are converted into \"convex hulls\". Simulation has always been fast and in the previous release, we focused entirely on workflow which had an indirect impact on Evaluation
and Rendering
. One got faster, but the other got slower.
Changes in Part \u00bc
Let's recap what happened in the previous release.
We tackled Evaluation which boosted performance by 2-10x by unlocking parallelism. Before, the better your character rig benefited from multithreading the worse it would perform with Ragdoll. Ragdoll would force any control you simulated into serial evaluation - to compute one after another - because the solver was fundamentally single-threaded.
With Markers, Ragdoll separated from the overall rig evaluation, which meant (1) your rig can continue running in parallel and (2) Ragdoll could also run in parallel.
Consider this example.
Rigids MarkersThis is how Maya scheduled evaluation for this scene with Rigid
versus Marker
. To the left, everything runs one after the other. It's terrible. To the right, every box is evaluated in parallel. Which means the more boxes and cores you have, the better utilisation you get.
The scene itself is very simple, it's this one here.
So evaluation got faster, but rendering got slower. All-in-all we gained about 100% performance.
With this release, we'll tackle that rendering block. Let's have a look at what's changed, in order of most-to-least significance.
Topic Savings Description Less CPU to GPU communication 1550x More buffers, less uniforms Connection Monitoring 40x Less dependence on time, more on physical connections being made and unmade Change Monitoring 40x Ignore anything that hasn't actually changed Less Dirty Propagation 3x Less of a shotgun blast, more like a sniper "},{"location":"releases/2021.10.07/#cpu-to-gpu-communication","title":"CPU to GPU Communication","text":"The previous release, and each one before it, had 1 shader per rigid. In the case of 600 rigid bodies, that meant 600 shaders. 600 shaders means 600 parameter updates of primarily color and 600 unique draw calls.
On top of this, all geometry was regenerated and re-uploaded to the GPU on every frame. Robust, but not very fast.
This release consolidates all shaders into one, colors are uploaded only once alongside their geometry and rendered using a custom GLSL shader (i.e. OpenGL 3.3).
What about DirectX?If you are on Windows and can't use OpenGL for whichever reason, there is backwards compatibility built-in.
from ragdoll import options\noptions.write(\"useShaders\", False)\n
Or via the Ragdoll Preferences.
Bearing in mind this will cost you 50% of the rendering performance and won't benefit from future shading related features and improvements. The option will remain until it's clear whether and how much it is actually used. (Let us know in the chat!)
Let's have a look at how this change affects your overall experience.
Before (7fps)
After (130 fps)
A closer look reveals exactly where this improvement comes from.
Before
This block is what we control, it's the Ragdoll rendering pipeline taking a whopping 93 ms per refresh.
After
With this release, this number dropped to 0.06ms (58 microseconds) that's an improvement of 1550x (!).
What about the other blocks?
The bottleneck has now moved to that green one and all of those blue, and those are Maya's internal rendering pipeline.
There isn't much we can do to directly impact it; it's mostly out of our hands. However, by massaging our data more and making life easier for Maya it should be possible to reduce these as well.
See Future Work for details on next steps, and if this is something you, fellow reader, is familiar with do get in touch!
Finally, as a result of having complete control over the shader running on the GPU, we're now able to more intimately design it to look the way we want. Expect more refinements here over time.
Before After "},{"location":"releases/2021.10.07/#connection-change-monitoring","title":"Connection & Change Monitoring","text":"In the previous release, and all versions of Ragdoll so far, we've tasked Maya with evaluating every plug on every frame, including the heavy-duty plugs between Rigid Body
-> Solver
.
Here's what this felt like in a scenario of 600 unique objects.
Before (5 fps)
Painful! The reason is because even though we're only moving a single box, Ragdoll checks-in with all other boxes too.
After (90 fps)
Blissful. In this case, only one of the boxes is actually updated, as one would expect.
Let's have a closer look at where performance is going here.
Before
Oh that's ghastly. Not only does it spend time evaluating all of those boxes, but it's making the solver take much longer consolidating the results taking a whopping 56 ms.
After
Whereas now, as one would expect, we're only evaluating this one box in a total of 0.7ms, resulting in a performance improvement 80x.
That looks like 3?
And that's true, it still makes three separate calls to this one box. Which means there's more room to optimise here, and we'll get there.
Needless to say, this happened before as well but was obscured by how many calls there actually are. Luckily, at least two of these calls happen in parallel.
600 capsules
The current framerate on 600 unique objects, something for future Ragdoll to try and compete with. For reference, an average ragdoll consists of about 20-30 objects.
"},{"location":"releases/2021.10.07/#future-work","title":"Future Work","text":"There is at least 4-16x performance left on the table for specialised cases.
Work Savings Benefit Optimised Render Items 4x Native Maya still renders 4x faster than us, which means there's more things we can do. Instancing for Rendering 2-4x Every render item is currently unique which means neither Maya nor your GPU is able to reuse geometry. Instancing is how games is able to render millions of objects on-screen at 60 fps, and best we can hope for is thousands. Instancing for Simulation 2-4x Likewise, every physics object is unique and, again, instancing in simulation is how games is able to run destruction and have thousands of objects interact in real-time.The challenge in both of these is deduplication; of identifying which of the many shapes you use can reuse their geometry.
"},{"location":"releases/2021.10.07/#overlap-group","title":"Overlap Group","text":"Specify which markers may overlap rather than collide. This can be useful to enable dense areas of a character, like the clavicles, where there is natural overlap amongst large shapes like with the neck and spine.
Value Meaning-1
No overlap allowed 0
Default, respects self-collision on the group (if any) 1-255
Overlap everything with the same number An rdMarker
part of a rdGroup
can get an overlap group assigned procedurally, based on other members of that group. For example, in a complete ragdoll, all markers are part of the same group. So a Self Collide = On
means these will all be given the same overlap group.
If it isn't in a group, then 0
is the same as -1
, in that it will collide with everything.
Let's have a look at a few scenarios.
"},{"location":"releases/2021.10.07/#collide-with-everything","title":"Collide with Everything","text":"In this example, every marker is part of the same group. The group has Self Collide = Off
, which is fine for just about every marker except the fingers. In that case, we do want self-collision, so they are given the group -1
.
In this case, we're happy with a default group of 0
since we don't need anything to self collide. Especially these clavicles that overlap significantly!
Finally, for the very specific cases of wanting two or more markers to overlap. Notice how we give both the ground and 3 of the boxes an Overlap Group = 5
.
Sometimes, you want things to stay put until something comes into contact with it. That's when you can tell a marker to start asleep, and \"wake up\" when necessary.
"},{"location":"releases/2021.10.07/#ignore-gravity","title":"Ignore Gravity","text":"It surrounds us. It penetrates us. It binds the galaxy together. But sometimes, you just don't care.
"},{"location":"releases/2021.10.07/#quality-of-life","title":"Quality of Life","text":"A few things to make your day that much more bright. \ud83c\udf1e
"},{"location":"releases/2021.10.07/#guide-space-20","title":"Guide Space 2.0","text":"In the previous release, we introduced Guide Space
. Which was a quick way of controlling whether a simulation should follow your animation in..
But it was challenging to control, not very obvious. Especially with how it was also taking into account its \"group\" guide space. This release addresses this by enabling you to specify a guide space for all markers and selectively override only the ones you're interested in. Just like how the Input Space
works.
Group Guide Space
Override all guide spaces, by editing the group.
Marker Guide Space
Or gain surgical control over guide space per-marker.
Have Fun
\ud83e\udd2d
"},{"location":"releases/2021.10.07/#auto-delete","title":"Auto Delete","text":"The Delete All Physics
menu command does what it says on the tin; it deletes all Ragdoll nodes from your Maya scene. But deleting a node, such as the new rSolver
left behind anything associated with it, like rGroup
and any rMarker
nodes.
This releases addresses this by automatically removing anything that depends on the node you delete. For example..
rMarker
node also deletes any associated lollipop controlsrGroup
also deletes the associated rMarker
nodesrSolver
deletes all rGroup
and rMarker
nodesTherefore, deleting a solver is now equivalent to Delete All Physics
, making it much more intuitive to delete things on a whim.
Minor cosmetic improvement, the Reset to Default
button now has an icon so you can actually tell it's a reset button (and not a bug, as many have pointed out \ud83d\ude05).
The default plane and solver offset was a off in the previous release, this fixes that. You can also manually re-adjust the plane and remove and orientation from the solver node to fix it locally, the solver itself is A-OK.
"},{"location":"releases/2021.10.07/#auto-time","title":"Auto Time","text":"Rather than having to specify which frame to start simulating at, Ragdoll can now keep track of your animation start frame. Either the start of the range, or the full timeline. Or, you can still set a Custom
start time for when you do care about specifics.
Monitoring for and responding to changes is a hard problem.
Odds are some things aren't updating the way you expect, which could affect viewport rendering, or worse, the actual simulation. If you encounter any such issues, please let us know in the chat or ping me directly at marcus@ragdolldynamics.com
Here are the currently known issues that we'll be fixing once a solution presents itself.
"},{"location":"releases/2021.10.07/#motion-blur","title":"Motion Blur","text":"As an unintended consequence of the optimisation and shader work, we're currently compliant with Maya's requirement for motion blur. Since all of our simulation is transform-based, it means all of what you simulate can be motion blurred, as opposed to deformer and particle-based motion.
It won't work with any animated attributes, which makes it rather limited in what you can use it for. \ud83e\udd14
"},{"location":"releases/2021.10.07/#maintain-offset-ikfk","title":"Maintain Offset IK/FK","text":"If you retarget a marker, the difference between the original and target is stored.
When you record, you have the option to Maintain Offset
. That's important if the assigned control has a different position and/or orientation than the destination control. For example, you can assign to a joint, but record onto a NURBS control.
For example, IK joints are assigned markers but are retargeted onto FK controls, it's important that you retarget when they are both in a similar pose. Otherwise, the difference between them will remain after recording.
To combat this, you have two options.
Retarget
(1) may not always be an option. If the position and/or orientation of an assigned control is simply different, then there isn't much you can do. :(
(2) is your best option. If you make a mistake, you can always re-retarget to the same control again, and the offset will be updated.
"},{"location":"releases/2021.10.07/#recording-kinematic-markers","title":"Recording Kinematic Markers","text":"When a marker treats the input as Kinematic
, it means it won't simulate it. It'll be 100% locked to animation. If that's the case, then there's really no point in recording those keys, right? Because they'd be 100% identical to the animation?
Except! If there's a parent, then we'll still need those keys to compensate for the parent not being kinematic.
Problem
Let's record without kinematic keys. Notice how the hand isn't given any keys, even though it needed them?
Solution
Record all keys, and the hand - even though kinematic - will still get recorded.
"},{"location":"releases/2021.10.07/#record-to-custom-attributes","title":"Record to Custom Attributes","text":"Sometimes, rotation isn't coming from Rotate X
but rather a custom Ball Roll
attribute on a different IK control.
As Ragdoll only understands Translate
and Rotate
, how would you go about recording onto this attribute!? Here's what you can do.
Locator.rotateX -> R_foot_CTL.ballRoll
Now Ragdoll will record onto a familiar channel, and Maya will handle the conversion back onto the rig.
"},{"location":"releases/2021.10.07/#slow-constraints","title":"Slow Constraints","text":"Like in earlier versions, drawing constraints are the slowest part. If you don't need them, disable them. You can do that either on the rSolver
node, or individually per rMarker
node.
Some well-hidden but essential resources for any of the above. If you are into anything related to Maya plug-in development and performance, you'll treasure these as I have.
Highlight for this release is Linking and Caching, and is part 3 out of 4 of the new Markers.
Let's start these notes with some examples of what you can do with all of the new features added. \ud83e\udd70
Best Friends, No Matter What
Two referenced characters, their solvers linked.
Hang On!
The new Distance Constraint
at work.
Dance Baby!
The new Pin Constraint
working alongside a Distance Constraint
and regular old pose matching.
Updated with limits from this release.
As before, this guy can either be opened or referenced into your scene. See Solver Linking for how you can reference multiple characters into the same simulation.
Download Manikin "},{"location":"releases/2021.10.25/#new-tutorials","title":"New Tutorials","text":"Markers have one part left before being considered complete, at which point they can completely succeed Active Rigid
and Active Chain
.
Until then, here's how you can get started with Markers today.
Tutorial Duration Description Markers 101 01:23 What are markers? Markers 101 - Key Concepts 03:23 Overview of Input Type and Pose Space Markers 101 - Local and World 03:00 Overview of the two Pose Spaces, local and world Overlapping Motion I 02:27 The very basics or Capture and Record Overlapping Motion II 02:21 Animation layers Full Ragdoll I 04:08 Hierarchy and volume Full Ragdoll II 04:05 Kinematic and animation Full Ragdoll III 04:30 Self collisions and recording IK I 03:00 Capturing the skeleton IK II 01:59 Retargeting to IK controls IK III 01:59 Record both Translation and Rotation Practical Example I 06:53 Fix table and elbow intersection in this dialog performance "},{"location":"releases/2021.10.25/#solver-linking","title":"Solver Linking","text":"Reference two characters, link their solvers.
Until now, you've been able to author physics using Active Chain
and combine scenes using the Combine Scene
menu item. That would transfer all connected rigids from one scene to another.
But, that feature is destructive. There's no way to \"uncombine\" and even if you could, there's no record of what was originally combined.
Let me introduce Solver Linking
, a lightweight and non-destructive alternative.
Linking
This fellow is referenced twice, and get their solvers linked together.
Unlinking
Unlinking restores their previous behavior exactly.
That's neat, but can you..
I know exactly what you're thinking, I was thinking the same thing.
Can you link a solver to another solver that is also linked? So that I can build a network of simple solvers that all work together to form one complex solver?
Yes. Yes, you can. \ud83e\udd2d See below.
"},{"location":"releases/2021.10.25/#example","title":"Example","text":"Here are 2 assets, a manikin and a backpack.
Manikin BackbackThe backback and manikin has been combined into one, which is then referenced twice into the final scene for a total of 4 unique solvers.
Non-destructively link solvers
Notice the hierarchy of solvers formed here, enabling you to build complex solvers out of many small solvers.
Non-destructively unlinking too
Likewise, safely deconstruct a network of solvers by just removing the connection.
Technically, a solver is added to another solver in the same manner a marker, group and constraint is added. One big happy family.
"},{"location":"releases/2021.10.25/#solver-caching","title":"Solver Caching","text":"Ragdoll runs alongside your character animation, but sometimes it can be useful to keep the results from a previous run and stop being so interactive.
Meet Cache
and Uncache
.
Caching is entirely non-destructive, and in fact leverages the very same cache you've been enjoying all this time whenever rewinding.
The menu commands toggle an attribute on your solver node, called .cache
and automatically plays the entire timeline for you. But the same result can be achieved by setting the attribute and playing it yourself.
The minimal HUD will show you what's been cached, and like before once you resume playback from a cached to an uncached frame, Ragdoll will continue filling up the cache as one would expect.
Look forward to a future release where caching happens in the background, as you work. Something that can also be handy from time to time (pun!).
"},{"location":"releases/2021.10.25/#limitations","title":"Limitations","text":"The viewport HUD currently draws relative the solver node in your Outliner. Moving this node also moves the HUD, which isn't right. Moving it along the Z-axis can actually cause the HUD to vanish due to being outside of the camera frustrum.
Other than that, if you encounter odd behavior let me know. This should work just fine in all cases where Ragdoll works, since the underlying mechanics are the same.
"},{"location":"releases/2021.10.25/#marker-limits","title":"Marker Limits","text":"Markers now support the limits you've grown accustomed to from chains and constraints. They are much easier to work with, now that they are built-in to each marker and have an understanding for what a \"parent\" is.
You should find a lot less need to use Edit Pivots
from here on, and in the next release you'll also get some interactive manipulators to avoid the Channel Box even more.
Limit Type
"},{"location":"releases/2021.10.25/#hinge-limit","title":"Hinge Limit","text":"The simplest of limits, allow a limb to rotate along a single axis. Like hinges on a door.
Use this for knees and elbows.
"},{"location":"releases/2021.10.25/#ragdoll-limit","title":"Ragdoll Limit","text":"For more complex anatomical limits, such as shoulders and hips, use the \"ragdoll\" limit for control over each of the 3 rotate axes.
Defaults
A good place to start is to just play with default settings and get an idea of what it looks like.
Customise
In this case, we'll keep the leg from crossing over too far, and from bending too far backwards. Like a real human leg.
"},{"location":"releases/2021.10.25/#custom-limit","title":"Custom Limit","text":"The Hinge and Ragdoll limits should cover the vast majority of limit needs, but sometimes you need more control. The Custom
limit lets you control the parent and child frames independently, similar to the \"traditional\" Rigid constraints let you do.
Here's an example of replicating the Ragdoll
constraint with a custom limit.
Specify the \"main\" axis for your limit.
Different rigs follow different conventions, and this attribute enables you to keep Ragdoll in the loop. It should typically align with whatever axis your joint or control points in the direction of the child joint or control.
"},{"location":"releases/2021.10.25/#rotation-vs-offset","title":"Rotation vs Offset","text":"You can either rotate or offset the limit.
Rotation
rotates both parent and child framesOffset
rotates only the parent frameRemember
The Parent Frame
is the space in which a Child Frame
is allowed to move.
You can now constrain one marker to anothe!
Constraint Type Description Weld Constraint Simplest of constraints, welds two markers together; no change to their distance or relative orientation is allowed. This is akin to the MayaParent Constraint
Distance Constraint Maintain a minimum, maximum or total distance between two markers. Pin Constraint Match a position and orientation in worldspace, similar to Drive Space = World
. "},{"location":"releases/2021.10.25/#weld","title":"Weld","text":"Maintain the position and orientation of one marker relative another from the first frame onwards.
"},{"location":"releases/2021.10.25/#distance","title":"Distance","text":"A simple but versatile constraint with animatable distance.
Maintain Start Distance
Whatever the distance between two markers, it will be maintained throughout a simulation.
Minimum Distance
Alternatively, only respond to when two controls get too close.
Maximum Distance
Conversely, keep markers from getting too far away from each other.
Custom Distance
Or go all-in, with both a minimum and maximum distance, for the most complex behavior.
Offsets
Control at which point on a control to measure the distance.
Animated Distance
Both min and max distance, along with stiffness and damping, can be animated for some pretty rad effects.
Hard Distance
A Stiffness = -1
means the constraint is \"hard\". It will not accept any slack or \"springiness\".
In this example, the distance is animated whilst soft, and transitioned into a hard constraint. Notice how it snaps into place once hard.
Limitation
A limitation of a hard constraint is that the distance cannot be animated whilst hard. You can however animate it between values of -1 and above, to transition to and from hard to soft.
"},{"location":"releases/2021.10.25/#pin","title":"Pin","text":"Similar to the Soft Pin
used with Rigids, this creates a new position and orientation a marker will try and reach. It's exactly what you get using Guide Space = World
on the markers themselves, but with the convenience of a new transform you can animate. They will both try and pull on the marker, greatest stiffness wins!
Sometimes, you want to tweak the overall look of an entire simulation at once, rather than tweaking or modifying individual nodes. Now you can.
All guides, limits and constraints now have their values combined with equivalent values on the solver node.
Edit One
Here's how you edit just a single marker or constraint.
Edit Many
And here's how you can edit them all.
Animation
Guides and Constraints can be animated, however Limits cannot.
This behavior is consistent with the rdGroup
node too, here's the complete attribute hierarchy.
A mere 15% boost to Recording performance.
Before
After
More was expected, and odds are there's room to optimise this further. But, the bottleneck is writing keyframes which cannot happen across multiple threads. It also needs to happen alongside evaluating your rig, which is dirtied with setting of each key, else it cannot take into account the various constraints, offset groups and IK solvers happening in there.
On the upside, the more complex your rig, the more benefit you should see from this optimisation. What happens in the above examples are extremely lightweight rigs with no animation, hence the difference is minor.
"},{"location":"releases/2021.10.25/#remainder","title":"Remainder","text":"Markers are almost feature complete. Most if not all things you could do with Rigids are now possible with markers.
Except for:
These will be addressed in an upcoming release. The next release will focus on getting those darn shape and limit attributes out of the Channel Box and into the viewport for interactive control.
"},{"location":"releases/2021.11.15/","title":"Animation Capture pt. 4/4","text":"Highlight for this release is Markers part 4 of 4!
Previous Parts
PATH
and Windows If you don't know what this is, you don't have to worry about itIn with the new, out with the old
The next few releases will slowly but surely replace Rigids with Markers. So if there is anything you find yourself unable to do with Markers, let us know and we'll get that in there as soon as possible.
Let's start off with some eye candy. \ud83d\ude07
Spiderman
Courtesy of Jason Snyman, a.k.a. the wizard.
Piggyback Ride
Thought it was fun to see how the simulation would look with the previous simulation as input!
Motion Graphics
Courtesy of Peter Crowther, for their client
Design company. Art direction Matt Walpole.
Halloween
And another from Jason!
"},{"location":"releases/2021.11.15/#recap","title":"Recap","text":"We did it! We're at part 4 out of 4 of the new Markers. Just about. \ud83e\udd70
This release here was intended to round off the interactive manipulators - so that you didn't have to fiddle around the channel box to edit shapes, constraints and limits - but we ran into a wall with our drawing API (see Robust Rendering below) which led us to throw everything out and start from scratch. \ud83d\ude14
On the upside, we've now got a significantly stronger foundation upon which to build manipulators, you will see these in action in the next release. Part 5 out of 4! \ud83e\udd70
These are the things scheduled for the next releases.
Next Release Description Interactive Manipulators Editing shapes is hard, constraints too. And limits. Export & Import Rigids could be exported and later imported, Markers does not have this ability yet Forces Next up, native Maya fields for Ragdoll Mechanical Constraints Like vehicle suspension are nowhere to be seen just yet."},{"location":"releases/2021.11.15/#new-terminology","title":"New Terminology","text":"A few things found a more representative name in this release.
Before After Guide-->
Pose, e.g. Pose Space
Input Type -->
Behaviour, e.g. Kinematic
and Pose Match
Assign Single -->
Assign Individual Assign Group -->
Assign Hierarchy What does it mean?
Still fuzzy on what \"assign\" means? Refer back to the introductory tutorials from the last release here. (hint: it's motion capture terminology)
"},{"location":"releases/2021.11.15/#future-of-rigids","title":"Future of Rigids","text":"
When Markers was first discovered, it wasn't clear whether they would live alongside Rigids, or replace them. But at this point it's safe to say Markers is applicable to everything rigids can do with far greater performance and usability.
Which is why from this release onwards Rigids
are now to be considered deprecated.
Long live Markers!
The following few releases will be about transitioning from Rigids to Markers. Tutorials will be updated, the documentation too and you're encouraged to start using Markers for your everyday animation tasks.
Rigids will live on for the next few releases and eventually end up in a Legacy
sub-menu until being completely removed in February 2022.
February 2022 Deadline
If you didn't read the above, remember this date for when Active Rigid
and Active Chain
goes bye-bye.
There is now an option to download Ragdoll for MacOS! \ud83c\udf4e
Download for MacHeads Up
If you are a Mac user, please let us know how you get along. The builds were made on Big Sur and should work well with Big Sur, but Autodesk recommends El Capitan.
"},{"location":"releases/2021.11.15/#robust-rendering","title":"Robust Rendering","text":"This release has taken quite a while, and not because of MacOS support but because of rendering.
In short, we've had to throw out and rebuild a significant chunk of Ragdoll for this release. Everything related to lines, everything!
The reason is that an unlucky few of you have had the following experience with Ragdoll.
Those lines don't look quite right.. \ud83e\udd14
In short, the reason for this is that the Maya API for drawing lines ends up looking different across various graphics cards and versions of Maya. Maya 2019 was especially egregious.
But let's dig deeper.
"},{"location":"releases/2021.11.15/#digging-deeper","title":"Digging Deeper","text":"Animator?
This next part is mostly for techies, feel free to skip ahead.
Whenever Ragdoll drew shapes, like capsules and convex hulls, it used part of Maya's drawing API called MRenderItem
. Lines on the other hand - like those for limits and guides - were drawn using a simplified API called MUIDrawManager
.
drawManager->circle(point, radius);\ndrawManager->line(pointA, pointB, thickness);\n// And so on..\n
Which is a fantastic, well-designed API that has worked great for the past year. Until it didn't. As it happens, this API is broken.. Reports were coming in from all across the globe about lines looking like.. Well, like this.
Some if it I could replicate, this here is Maya 2019 in which the behavior is erratic. But the same could be said for some hardware and driver combinations; most of which I have never been able to replicate here.
This version throws all of that out the window, and reimplements it from scratch. It's a pity, because the API was very easy to work with and a great way to get started rendering in Maya.
That said, our new API is not only much faster but also much more powerful. You can expect to see a lot of new 2D rendering, including fully interactive UI elements in 3D space.
Until then, if you've been having issues with Ragdoll and lines, you can now breathe easy.
Caveat
This is great and all, but it no longer supports DirectX.
In the previous release, we already started moving away from DirectX, and if you've been using it you would have gotten some warnings about it. If not, then you've got nothing to worry about for this release.
OpenGL is where the action is at, and is supported equally on each platform; including MacOS!
"},{"location":"releases/2021.11.15/#robust-recording","title":"Robust Recording","text":"Recording now automatically ends up on an Animation Layer per default, with only the simulated controls associated with it. It is also at least 2x faster and less sensitive to quirks in a rig or skeletal hierarchy.
Here are the things it didn't take into account before, but does now.
And that should cover it!
Important
Recording is the most important aspect of Markers; if you can't get the simulation out then it's all for nothing. So do reach out via the..
..if you have any issues with this, and a fix will be crafted in a hot minute.
"},{"location":"releases/2021.11.15/#performance","title":"Performance","text":"I mentioned a 200% increase in performance, didn't I? Let's have a quick look (pun!).
Before
A solid 49 fps.
After
135 fps. The numbers speak for themselves.
At the end of the day, the main bottlenecks are out of Ragdoll's hands:
Sometimes, the simulation is really fast; it will usually be the fastest of the four. Other times, evaluating the rig is fast; such as if there are no keyframes and no fancy processing like follicles or spline IK. But the overhead from recording should approach zero as time goes on.
About (3), Ragdoll must evaluate your rig twice. Once to provide the simulation with your animation, and a second time to bake the resulting simulation back onto your controls.
Why so slow?
Interestingly, this is what made Active Rigid and Active Chain so slow. It was doing recording every frame, whether you wanted to or not. It was how the simulation was made visible to you; by continuously recording it.
With Markers, we delay the recording until you hit Record Simulation
, which is the primary way in which they enable us to reap this crazy amount of performance out of Maya.
Several improvements were made to Caching, introduced in the last version.
Caching whilst standing on the start frame could cause hiccups on occasion, this release fixes that.
Before
There was also a minor issue whereby if you cached half-way, revisited the start frame and then went back to resume caching, it would resume from the wrong spot and thus break the cache.
In either of these cases, one could disable and re-enable the cache to \"fix\" it, but now you don't have to!
Notice how it doesn't update the cache when standing on the start frame?
After
And, like before, you can enable caching via the solver. The only difference is that the menu item automatically plays through the entire timeline for you.
"},{"location":"releases/2021.11.15/#snap-to-simulation","title":"Snap to Simulation","text":"Yet another way to work with physics, by transferring individual poses from the solver into your animation. You can use it to pose or layout a scene.
Coming Up
An upcoming release will enable you to advance time in the simulation, without affecting time in Maya. Such that you can \"relax\" a pose, for example. \ud83d\ude01
"},{"location":"releases/2021.11.15/#frameskip-method","title":"Frameskip Method","text":"Ragdoll needs a consistent progression of time to provide reliable results. So per default, if it notices a frame being skipped, it kindly pauses and waits until you revisit the last simulated frame.
Alternatively, you can let it look the other way and pretend time has progressed linearly, like nCloth and countless other solvers do.
"},{"location":"releases/2021.11.15/#pause","title":"Pause","text":"The default. It's safe, predictable, but requires Play Every Frame
to work.
The nCloth and nHair default, of trying its best to simulate even though it wasn't given the frames inbetween. Unpredictable, unreliable but may handle playing along with sound.
Aside from not giving you the same result each time you play, if too many frames are skipped your simulation can completely explode. You can semi-work around this by increasing the number of substeps, forcing more simulation frames to fill for the missing frames.
Non-deterministic
Bear in mind that the Ignore
method cannot give you the same results each playthrough. The Pause
method is guaranteed to give you the same results, and are identical to what you get when you Record Simulation
too.
Get data out of the solver and into a baked joint hierarchy.
You can use this to build a library of animations, or to handle the retargeting from simulation to animation manually by just constraining to the resulting joint hierarchy.
Performance
Notice how fast this is!
"},{"location":"releases/2021.11.15/#a-debugging-companion","title":"A Debugging Companion","text":"It can also be used for situations where Record Simulation
doesn't do what you need it to. The extracted skeleton will be a plain joint hierarchy, with no scale, and guaranteed to match the simulation exactly. So you can extract it, and constrain your rig to it.
You've already given Ragdoll a go many moons ago, but really like where things have gone since? Well you're in luck. You can now request a re-trial!
You can now replace the original geometry assigned to your marker, just like you could with Rigids.
"},{"location":"releases/2021.11.15/#auto-limits","title":"Auto Limits","text":"Markers are now able to infer which axes to lock in the simulation, based on the locked channels of your control or joint.
Notice in this example how some of the channels are locked. With the Auto Limit
option checked, the corresponding limit axes will be locked too, such as to prevent the simulation from rotating around those axes.
If you forget or want to detect locked axes on an existing marker, you can use the Utility option too.
"},{"location":"releases/2021.11.15/#scale-mastery","title":"Scale Mastery","text":"Simplified and more robust, scale now handles well for all manner of shapes.
"},{"location":"releases/2021.11.15/#unloading-on-linux","title":"Unloading on Linux","text":"Linux users were not able to unload and later reload Ragdoll, without experiencing a fatal crash. This was a problem related to the dynamic licensing library not letting go of its TCP handle and forcing the plug-in to remain loaded, even though you kindly asked it to unload.
This has now been fixed, and the plug-in can safely be unloaded and reloaded and unloaded and reloaded over and over and over again. Enjoy!
"},{"location":"releases/2021.11.15/#path-and-windows","title":"PATH and Windows","text":"For TDs
The following is meant for administrators and TDs
With the introduction of Mac support a change was made to the way LimeLM - the licencing software used by Ragdoll - is distributed. Rather than being statically linked on Linux and dynamically linked but programatically located on Windows, it is now dynamically linked and automatically located on all platforms.
Windows Only
This only applies to Windows. Linux and Mac references the libraries relative the plug-in location. In short, you don't have to worry about it.
You don't have to care about this, unless you are on Windows and care about what's on your PATH
to which this happens.
# Windows\nos.environ[\"PATH\"] += \";\\\\Ragdoll\\\\shared\\\\windows\"\n
The change is coming from the Ragdoll.mod
file.
Why am I telling you this?
In the wildly unlikely chance that there is another plug-in using a different version of LimeLM in your arsenal, there may be a conflict whereby:
PATH
PATH
v0.5beta
v0.5beta
This will be resolved in a later version of Ragdoll, but until then, in the unlikely event there is a conflict, here's what you can do.
import os\nbefore = os.environ[\"PATH\"]\nos.environ[\"PATH\"] = \"/path/to/Ragdoll/shared:%s\" % before\ncmds.loadPlugin(\"ragdoll\")\nos.environ[\"PATH\"] = before\n
Namely, rather than loading Ragdoll from your plug-in manager, load it using this wrapper script. It will ensure Ragdoll's path is picked up ahead of any third-party plug-in, without negatively affecting anything around it.
"},{"location":"releases/2021.12.12/","title":"Interactive Manipulators","text":"Highlight for this release is The Manipulator!
This release marks the end of Active Rigid
and Active Chain
.
Important
If you read only one paragraph in this document, read this.
Tutorials have been updated, documentation as well and you are encouraged to use Markers
which are far superior in both performance and usability.
Legacy
submenu in the Ragdoll menuLet's kick things off with some eye candy!
Flying Lizard
A work-in-progress clip from Jason Snyman.
Ragdoll in 30 Seconds
A brief overview of what Ragdoll is.
Mocap Chap
Footage from one of the the new tutorials.
Now watch what happens when we increase the mass of the box by 50x. \ud83d\ude01
"},{"location":"releases/2021.12.12/#new-tutorials","title":"New Tutorials","text":"Have a look!
"},{"location":"releases/2021.12.12/#manipulators","title":"Manipulators","text":"
One of the most challenging aspect of Ragdoll to date is editing shapes and limits. These have now been greatly simplified via the use of \"manipulators\", similar to your standard Translate/Rotate/Scale manipulators. Except on steroids.
Here's a 21 second overview.
Before
Here's the equivalent process in the last version. Sped up by 4x.
It's is about as boring to watch as it was to make. \ud83d\ude04 Notice how shapes and limits need manual adjustment on both sides, because there was no symmetry. And notice how many clicks it takes to make one change, keep expanding that item in the Channel Box over and over and over.
"},{"location":"releases/2021.12.12/#activate","title":"Activate","text":"You have a few options for activating the manipulator.
Ragdoll -> Manipulator
T
on your keyboardShow Manipulator Tool
in the ToolbarAny of the Ragdoll nodes can be selected in order to enable the manipulator via the T
keyboard shortcut.
Solver Shape
At the time of this writing, the solver needs its shape selected, not the parent transform. This will be addressed in a future release.
A comfortable workflow is..
T
The selected Marker will be pre-selected in the manipulator.
Alternatively, press the Show Manipulator Tool
button in the Toolbar.
This release introduces a manipulator with two \"modes\".
Mode Description Shape Mode Edit shape properties, likeLength
, Radius
, Position
and Orientation
Limit Mode Edit limit properties, like Twist
and Swing
along with their pivots. In Shape Mode, you currently have 5 manipulators.
Manipulator DescriptionTranslate
Affects the Shape Offset
attribute Rotate
Affects the Shape Rotation
attribute Scale
Affects the Shape Radius
and Shape Extents
attributes Length
Affects the Shape Length
attribute, for the Capsule
shape HUD
Individual control over primary attributes, like Shape Extents
axes Translate
Hold the middle-mouse button to translate.
Rotate
Hold Ctrl + middle-mouse button to rotate.
Scale
Hold Ctrl + left-mouse button to scale.
Length
The Capsule
shape have additional in-view manipulators you can drag to affect each side independently.
HUD
Finally, attributes without a visual handle can be edited via the viewport HUD.
"},{"location":"releases/2021.12.12/#limit-mode","title":"Limit Mode","text":"In Limit Mode, you currently have 2 manipulators.
Manipulator DescriptionLimit
Affects the Limit Range XYZ
attributes HUD
For locking and enabling of limits Enable and Disable
Click the Axis
button to limit the rotation about a particular axis.
Lock and Unlock
Click the Lock
button to prevent all rotation about the axis.
Asymmetrical Edits
Hold Ctrl
to make asymmetrical edits
Some limbs start out at the center of their limit. Like your hip and neck. They are typically modeled to enable equal movement in each axis.
Other limbs, like the elbow and knee, are typically modeled in the extreme of their limit. Able to only rotate in one direction. For these cases, they need an asymmetrical limit.
With limits in multiple axes, keep an eye out for how asymmetrical edits to one axis affect the others.
Why are they moving?
Under the hood, each axis must be still be symmetrical; edits only appear to be asymmetrical for your convenience. What's really happening is the entire limit is both changing shape and also rotating and the rotation is causing all axes to move.
This is an inherent limitation of limits (pun!) in Ragdoll and is unlikely to be addressed in the future, so we'll have to work with it.
If you mess up and want to start from scratch, hit the Reset
button, also found under Ragdoll -> Utilities -> Reset Constraint Frames
Enabled per default, symmetry will mirror your edits across an axis.
There are 2 types of symmetry at the time of this writing.
Type DescriptionWorld
Look for a marker across the current axis in worldspace Pose
Based on the pose at the time of assigning markers, which is typically symmetrical. Each of which can be made symmetrical in either the X, Y or Z axes. The Pose
axis means you can make changes even if a character has been posed after having been assigned. A feature particularly useful when assigning to the A- or T-pose of a character rig.
Pose Based Symmetry
Because these controls were assigned in the T-pose of the rig, you can use Pose-based symmetry to make changes even when the character is currently asymmetrical.
Multiple Rigs
If two or more characters are present in the scene, and they were all rigged in the same pose, at the center of the world, then Ragdoll will only look at markers in the same rdGroup
as the selected Marker.
Search Distance
On the right-hand side of the Enable Symmetry
button, there is a Search Distance
gizmo.
Drag to edit this value
When you select a marker on one side, it will search for a marker at the opposite side of the axis you've chosen. Because positions are all approximate, it uses a maximum search distance to look for it.
Matches
Ideally, there should only be one match. But in a crowded hierarchy there may be several. Tune the Search Distance
to control the number of matches, to ensure it doesn't pick the wrong one.
Disable Symmetry
to enable multi-select
Hold Shift
to select and manipulate multiple markers at once.
Drag-select
Will be added in a future release.
"},{"location":"releases/2021.12.12/#undo-redo","title":"Undo & Redo","text":"No surprises here.
Changes made using the manipulator is undoable as you would expect, with the exception that it currently does not let you undo the selection itself like normal Maya selection does; this will be addressed in a future release.
"},{"location":"releases/2021.12.12/#fit-to-view","title":"Fit-to-view","text":"Tap the F
key to fit any selected Marker(s) to the view, like you would expect from selected Maya nodes.
Caveat
This currently only applies if you've activated the manipulator using the Ragdoll -> Manipulator
menu item, or have the rdSolver
shape node selected.
Click the Select Node
button to select this node in Maya
Per default, Ragdoll and Maya selection are separate. You can have Maya select the node(s) currently seleted in Ragdoll by pressing the Select Node
button.
You can automate this using the Synchronise
button at the far-left of the HUD.
Why is this not on per default?
The solver is what is actually being fitted. If the selection is changed to a marker (which is not a DAG node, and therefore lacks a visual representation) then fit-to-view no longer works.
This will be addressed in a future release and made into the default.
With Multi-select or symmetry enabled, all selected markers will be selected in Maya, to make bulk edits via the Channel Box easier.
"},{"location":"releases/2021.12.12/#manipulator-help","title":"Manipulator Help","text":"On the right-hand side is an overview of the hotkeys and mouse button combinations you can use, and what they do.
It can be hidden via the HUD button on the upper right-hand side.
"},{"location":"releases/2021.12.12/#quality-of-life","title":"Quality of Life","text":"More of this!
"},{"location":"releases/2021.12.12/#1d-2d-and-3d-limits","title":"1D, 2D and 3D Limits","text":"Ragdoll used to have a preference as to which axes you use for limits.
X
is great for 1D limits, like a hinge, elbow or kneeYZ
is great for 2D limits, like a shoulder or hipBut XY
is no good. XZ
is also bad. And god forbid you should attempt use Y
or Z
as a hinge limit. Ragdoll would try, but try in vain.
Knowing which combination to use is not easy, and now you no longer have to. Pick an axis, any axis or combination of axes and Ragdoll will figure things out on its end. You don't have to worry about it.
As an added bonus, the limit axis now aligns with your Maya axis! (with one caveat, see below)
Here's a table to make this absolutely clear. \ud83e\udd70
Maya Rotate Axis Ragdoll Limit AxisX
= X
Y
= Y
Z
= Z
Caveat
With one exception, see Asymmetrical Limits under Limit Mode above. As soon as they rotate, they will no longer align with Maya; which isn't a problem most of the time, but can be.
"},{"location":"releases/2021.12.12/#cache-on-record","title":"Cache On Record","text":"Previously, when you recorded your simulation back onto your character rig, a new simulation would kick in the next time you played. And because your character rig has now changed - to follow the original simulation - the new simulation will be different.
This makes logical sense but can be unexpected. So now, the Cache
attribute on the solver is automatically enabled to let you compare and contrast your character rig with the simulation; and avoid needless re-simulating when what you really wanted was to record-and-forget.
Once you're ready to re-simulate, run the Uncache
command or set the Cache
attribute back to Off
.
Pose Deltas are now cleaner and more performant (up to 10x).
Deltas are the triangular-looking shapes drawn to visualise the difference between your animation and the current simulation. They are now only drawn when there is at least some difference, which means the vast majority of them in a complex scene are now not drawn, speeding up your viewport significantly.
Before
After
Notice how they only appear if there is actually a difference between the animation and simulation.
"},{"location":"releases/2021.12.12/#ground-fits-grid","title":"Ground Fits Grid","text":"Previous releases would put a ground underneath the first assigned controls, with a size relative the size of your selection.
Turns out, this wasn't great in practice and usually ended up being too small. In this release, the ground inherits whatever size your viewport grid is.
"},{"location":"releases/2021.12.12/#auto-limits-ii","title":"Auto Limits II","text":"The previous release introduced Auto Limits whereby Ragdoll would look at the locked-state of your Rotate
channels and try to figure out how to replicate this effect physically.
This sometimes worked, sometimes not. This release fixes that, covering all combinations of locked channels, with any manner of joint or rotate axis.
Here's what locking the Rotate channels will result in.
Unlocking them, we can see how much of an effect it has.
Thanks to the more robust and predictable limits in this release, the Maya axis will now always align with the Ragdoll limit axes!
"},{"location":"releases/2021.12.12/#lollipop-hierarchy","title":"Lollipop Hierarchy","text":"The Create Lollipop
option of Markers generates an extra control shape in the viewport that you can use to manipulate a Marker. The goal being to make it easier to spot a Marker in a potentially busy channel box.
But the last release didn't let you use Assign Hierarchy
with Create Lollipop
without ending up with a broken hierarchy.
Before
After
"},{"location":"releases/2021.12.12/#disappearing-limits","title":"Disappearing Limits","text":"The limit indicator is drawn using a 2D drawing API which is initialised whenever a Solver is created. It was however uninitialized whenever any Solver was deleted, so if you had 2 solvers you were out of luck. A re-open of the scene would fix it, but it was annoying and incorrect.
This has now been fixed.
"},{"location":"releases/2021.12.12/#replace-intermediate-mesh","title":"Replace Intermediate Mesh","text":"In the previous release, if a mesh had a second \"intermediate\" mesh it would be more difficult to use it with the Replace Mesh
command.
Before
After
Here's it working with intermediate shapes, and the new Maintain History
option which was always true in the previous release.
Without it, modifications to the original mesh are ignored; such as a skinned mesh.
"},{"location":"releases/2021.12.12/#transform-limits","title":"Transform Limits","text":"Recording onto transforms with Maya's native limits on them could result in this.
This has now been fixed.
How?Since you asked, they are simply disabled. I've never seen or heard of anyone actually using these and was surprised to find they were in active use by the native motion capture library that ships with Maya.
If you or anyone you know do use them, let me know and they will be given support.
"},{"location":"releases/2021.12.12/#separate-translate-xyz-amount","title":"Separate Translate XYZ Amount","text":"The Pose Stiffness
in World
space affected each axis equally.
You can now control each axis independently, to for example follow an input animation closely along the ground plane, the X and Z-axes, but allow for it to deviate along the Y-axis,
"},{"location":"releases/2021.12.12/#separate-twist-and-swing-amount","title":"Separate Twist and Swing Amount","text":"The Pose Stiffness
and Pose Damping
parameters of Markers apply to both Swing and Twist - that is, rotations around the X and YZ axes.
You can now control these independently, for an even finer control over the resulting simulation.
"},{"location":"releases/2021.12.12/#maya-exit","title":"Maya Exit","text":"There was a memory leak, whereby Maya would sometimes freeze on exit, with an anomymous-looking dialog box appearing on Windows.
This has been fixed.
"},{"location":"releases/2021.12.12/#customised-recording","title":"Customised Recording","text":"Some rigs don't work with Maya's default Parent and Orient constraint. As a result, neither does Record Simulation
or Snap to Simulation
because those commands use these default constraints.
If this is you, then I have good news. You can now override the command responsible for creating these constraints with one that uses your custom in-house constraints instead.
Minor maintenance release.
As is tradition, we must start with candy. Now, it's only been 3 days so all I have for you today is this amazing piece of animation here. \ud83d\ude05
Wyvern 2
Follow-up to the WIP from last release from The Wizard, a.k.a. Jason Snyman.
Wasp
Here's a response to a question on LinkedIn about whether or not you can use Ragdoll to make animation cycles. So here are 3 parts.
Total time spent 1h, including rigging and skinning. The model is a default Maya model from the Content Browser.
"},{"location":"releases/2021.12.15/#clean-channel-box","title":"Clean Channel Box","text":"With the manipulator in the last release, the Channel Box saw a huge spring cleaning.
Before AfterIt was, however, a little too aggressive. Some of the attributes were still useful, especially for making sweeping changes across lots of markers at once. So in this release, you know have the option of:
Assign
via the Option DialogRagdoll -> Utilities -> Toggle Marker Attributes
More specifically, the environment variable MAYA_ENABLE_VP2_PLUGIN_LOCATOR_LEGACY_DRAW
, is still in use in some studios. This variable would cause the Manipulator UI to be unselectable.
This has now been fixed.
"},{"location":"releases/2021.12.15/#collision-group","title":"Collision Group","text":"Lone markers, like boxes and other environment assets and props have an Overlap Group
like any other. But unless they are also part of a group, they would sometimes not respect the Overlap Group
, requiring a scene re-open in order to take effect.
This has now been fixed.
"},{"location":"releases/2021.12.15/#z-up","title":"Z-up","text":"The default ground now correctly fits the grid even in a Z-up Maya scene.
"},{"location":"releases/2021.12.15/#double-hud","title":"Double HUD","text":"The Manipulator HUD could sometimes fight with Maya's default HUD. Now it'll step aside temporarily until the manipulator is done.
Room to improve
It will temporarily toggle the Maya HUD on/off in the currently active viewport, based on the viewport your mouse is currently hovering. This can get finnicky sometimes. If it does, the option toggled is the one under Display -> HUD
in the Maya viewport.
This will be improved in a future release.
"},{"location":"releases/2021.12.15/#robust-viewport-icons","title":"Robust Viewport Icons","text":"The viewport icons would sometimes be unselectable.
This was due to Maya being unable to provide Ragdoll with the correct \"Active View\", which Ragdoll uses to map your mouse to 3D. This has now been fixed, by no longer relying on the Active View.
"},{"location":"releases/2021.12.15/#edit-constraint-frames","title":"Edit Constraint Frames","text":"The previous release simplified limits by a lot, but there are still cases where the default orientation of some rig controls ends up in a funny situation.
Note
This does not matter to the simulation. It is only a rendering artefact.
To make this a little easier to work with, you can rotate the entire limit like this.
Note
You don't need the locators once you are done editing them, you should definitely delete them.
This will be made redundant in a future version as it gets much too technical and too easy to shoot yourself in the foot. If you make a mistake, delete the locators and call Reset Constraint Frames
in the same menu to start again.
Highlight for this release is Ragdoll 2.0!
Let's start with the good stuff.
Medusa Breakdown
Excellent Animation and breakdown by Andras Ormos.
Batman Learning Cursive
Animation by Jason Snyman, with a very interesting approach to getting ink out of a pen digitally. \ud83d\ude04
DMV Lady
Courtesy of Dragana Mandic.
Scalable Rig, Scalable Ragdoll
No special setup required, if your rig is scalable then so is Ragdoll.
Circus Import
Toying with the ability to import characters into the same solver.
The Ocean
Give a man a fish, and you'll feed him for 2 ragdolls.
Noodles
Something from the Linux world.
"},{"location":"releases/2022.01.17/#ragdoll-20","title":"Ragdoll 2.0","text":"Since 28th July 2021, Ragdoll has been publicly available under the \"early bird\" umbrella. It started out with a reduced price point for those brave enough to venture into new territory and expect a few left turns every now and then as kinks are worked out in the software.
Now the time has come to step into the world as an adult piece of software with the guarantees of any commercially available software and a pricing to reflect that.
And as Ragdoll has grown significantly since those days - given the new Markers - it's only reasonable to consider this Ragdoll 2.0.
"},{"location":"releases/2022.01.17/#january-voucher","title":"January Voucher","text":"Pricing has now reached its intended price point, leaving Early Bird behind. For the next two weeks however, you can use this voucher code to get the Early Bird discount before the deadline.
Ragdoll Unlimited
uX1bFhjZ
The Ragdoll of today is very different from the Ragdoll of July 2021.
Back then, I had no idea that this amount of performance and usability was possible and was prepared to cram tutorials and documentation until everyone was accustomed to the complexity of physics simulation. \ud83d\ude04
But then something happened - Markers. Like lightning from a clear sky, it unexpectedly changed everything. Performance is now far beyond what Maya is expected to handle, with physics much much faster than simply skinning of a character, and close to the performance of native IK handles. This opens up a lot of possibilities.
The problems faced back then..
None of those problems are a problem with Markers. Because Markers look at the world from a different perspective, they just work. It made Ragdoll not only more user friendly and significantly faster but also simpler to develop and smaller in size. The code for Markers is about \u2153 of the equivalent for Rigids. Just think about that!
And most of all, it opened up for all the things you are about to see happen for Ragdoll in the coming months. \ud83d\ude43
"},{"location":"releases/2022.01.17/#ragdoll-flavours","title":"Ragdoll Flavours","text":"Let's take a quick look at the different versions of Ragdoll and how they differ.
Flavour Description Ragdoll Unlimited The fully-featured, unrestricted version of Ragdoll. When people talk about Ragdoll, this is the version they mean. Ragdoll Complete The cost-effective flavour of Ragdoll, suitable for freelancers and indie studios. It lacks studio-conveniences such as a Python API for pipeline integration, export to JSON for sharing of physics configurations and is less performant than \"Ragdoll Unlimited\", being unable to operate in parallel across multiple cores. Ragdoll Batch A non-interactive version without ability to render into the viewport. Suitable for automation and pipeline integration. Ragdoll Personal A non-commercial version, suitable for students and anyone wanting to fool around with Ragdoll at home. It is identical to Unlimited, except that it has limits on how much can be recorded and exported. Ragdoll Educational A non-commercial version of Ragdoll Unlimited whose saved scenes cannot be opened with a commercial licence. Ragdoll Trial A non-commercial first experience with Ragdoll; this is what you get when downloading Ragdoll onto a new machine and use it without activating it first. Similar limitations to Personal, except it also expires about a month after first use. "},{"location":"releases/2022.01.17/#ragdoll-unlimited","title":"Ragdoll Unlimited","text":"This is the version you want.
It contains everything mentioned on any website, is capable of doing everything you've seen Ragdoll do and is the unrestricted, unlimited and gold standard of Ragdoll.
"},{"location":"releases/2022.01.17/#ragdoll-complete","title":"Ragdoll Complete","text":"This is the version for freelancers.
It is Ragdoll Unlimited, with a few limitations.
Performance is limited in how quickly Ragdoll is able to read from your character. Ragdoll is natively parallel, but Complete turns any character you assign markers to into a Serial affair. Limiting performance by the number of cores you have in your machine.
The advantage of export is that your rigs don't need physics built-in. They can remain simple and without physics, until the animator actually needs it. This feature is limited to 10 markers; for the time being. Generally, export is reserved for Unlimited and users in need of pipeline integration. But Complete let's you get at least a taste of the comfort and flexibility of exporting your physics contraptions from one scene and importing onto an unsuspecting character in another.
Like Export, the ability to interact with Ragdoll through Python is an important part of any production pipeline; not so much for the individual animator of small indie studio.
Info
At the time of this writing, this limitation is not yet in place, and users of Complete is currently able to utilise the Python API just like users of Unlimited. This will be addressed in an upcoming release.
"},{"location":"releases/2022.01.17/#ragdoll-batch","title":"Ragdoll Batch","text":"This is the version for your render farm.
It's a low-cost alternative to Ragdoll Unlimited, without the ability to render into the viewport. Making it effectively useful only via Python. It is also unable to export and lacks the parallelism of Unlimited.
Unlike all other flavours, a Batch licence is reserved per-process; meaning that if you spin up 2 mayapy
instances on the same machine, it will occupy 2 licences. This obviously only works if your licences are floating, as otherwise a machine can only carry a single node-locked licence, limiting it to a single process running Ragdoll Batch.
Leaving Early Access, Ragdoll is stepping into the world as a 1.0. Here's an overview of what you can expect from now on.
Feature Trial Personal Complete Unlimited Batch Commercial Use \u274c \u274c \u2714\ufe0f \u2714\ufe0f \u2714\ufe0f Interactive Tools \u2714\ufe0f \u2714\ufe0f \u2714\ufe0f \u2714\ufe0f \u274c Python API \u2714\ufe0f \u2714\ufe0f \u274c \u2714\ufe0f \u2714\ufe0f Multi-Threading \u2714\ufe0f \u2714\ufe0f \u274c \u2714\ufe0f \u274c JSON Import/Export \u2714\ufe0f \u2714\ufe0f \u274c \u2714\ufe0f \u274c Per-machine Licence \u2714\ufe0f \u2714\ufe0f \u2714\ufe0f \u2714\ufe0f \u274cBatch
has a per-process licence, meaning it will occupy one seat per individually running process.
Trial and Personal licences are non-commercial, meaning they can't be used for commercial purposes. Such as in a studio, or for anything where money is involved.
When a file saved with a non-commercial licence of Ragdoll is opened in a commercial licence, it'll temporarily turn your licence into a non-commercial licence.
Feature Unlimited Complete Non-commercial Export Unlimited markers Up to 10 markers Up to 10 markers Record Unlimited frames Unlimited frames Up to 100 framesEarly Birds
Did you purchase a Ragdoll Personal licence before this release?
Then as thanks for believing in us and joining early, these limits do not apply to you. Your version is still unrestricted for non-commercial use.
Enjoy! \ud83e\udd70
"},{"location":"releases/2022.01.17/#import","title":"Import","text":"You can now import a Ragdoll setup exported from Maya, back into Maya. It'll re-create everything just the way it was.
Can I export scenes I made with an earlier version?Yes, anything made with Markers can be exported regardless of when it was made.
What is included in the export?Just about everything.
Very little.
Yes, anything else is a bug.
More precisely, determinism depends on (1) the type and number of items in the solver along with (2) the order in which these are created. Both of these are part of the exported file format and is taken into account during import. Meaning you should get identical results so long as the content is the same.
"},{"location":"releases/2022.01.17/#example","title":"Example","text":"Here's an exported Ragdoll setup for the free CG Spectrum Tiger rig.
2.8 mb
)To use it, download the rig and import the Ragdoll file.
It contains 2 levels of detail.
Level Content Level 0 Body and feet Level 1 Everything on Level 0, plus toes "},{"location":"releases/2022.01.17/#workflow","title":"Workflow","text":"Here's the rundown.
On import, Ragdoll will try and find the names of what you exported in your currently opened scene.
Namespace
dropdown menu.Search and Replace
fields to modify the names searched for by Ragdoll.Export
Once you're happy with your character, it's time to export. Towards the bottom of the UI, you'll get a preview of what is about to be exported. This can help clarify that what ends up on disk is what you expect.
Import
In a new scene, with the same character, same names and everything, import as you'd expect. At the bottom of this UI, you'll get a preview of what's in the file on disk, along with how it will associate the node names found in the file with what you have on disk.
"},{"location":"releases/2022.01.17/#namespace-from-file","title":"Namespace from File","text":"Odds are, the character you're importing either has no namespace, or has a different namespace to what you've currently got in your scene. As in this example here, with 3 copies of the same character, each with its own namespace.
Use the Namespace
dropdown to select one of the current namespaces in your scene, or Custom
to type one in yourself.
Per default, Ragdoll will import the file into the current solver in your scene, if any. Or, you can import the original solver from the source file.
"},{"location":"releases/2022.01.17/#known-limitations","title":"Known Limitations","text":"Here are a few things that will be addressed over time. Let us know if you encounter anything else!
Ragdoll can now automatically compute a suitable mass for each Marker, based on the volume of your shape and a density of your choosing.
In other words, big objects become heavy, small objects become light.
Before
After
"},{"location":"releases/2022.01.17/#presets","title":"Presets","text":"Provide a custom density, or choose from one of the provided ones.
Density ValueOff
Do not compute, use the Mass
attribute Cotton
Very sparse, 0.05 grams per cubic centimeter Wood
Sparse, 0.2 grams per cubic centimeter Flesh
Default, 1.0g/cm3 Uranium
Dense, 19.0g/cm3 Black Hole
Very, very dense Custom
You pick Mass is computed based on the volume of your shape, along with a density of your choosing.
"},{"location":"releases/2022.01.17/#options","title":"Options","text":"Choose between various densities either at creation-time or after creation.
"},{"location":"releases/2022.01.17/#visualise","title":"Visualise","text":"The computed mass updates interactively as you change the size and type of your shape, including convex hulls!
In the Manipulator, you'll be able to not only only edit the density, but preview the computed mass given the current shape volume and density you provide.
"},{"location":"releases/2022.01.17/#level-of-detail","title":"Level of Detail","text":"Setup your character once with all bells-and-whistles, and interactively pick which level of detail to use for your simulation in a given situation.
Usecases
Level 0
, fingers at Level 1
Level 1
, muscles at Level 2
Level 0
, extremities at Level 1
and Level 2
For example, here's a Wasp character with 3 levels of increasing detail.
As you'd expect, it'll record only the currently active markers.
"},{"location":"releases/2022.01.17/#workflow_1","title":"Workflow","text":"Here's how it works.
1
1
And that's it! Any marker with a matching level is simulated and recorded.
"},{"location":"releases/2022.01.17/#operators","title":"Operators","text":"What does each level mean? The answer lies in the \"operator\".
Operator DescriptionLess Than
If the Marker Level
is less than (or equal) to the Solver Level
, simulate it. Greater Than
If the Marker Level
is greater than (or equal) to the Solver Level
, simulate it. Equal
If the Marker Level
is equal to the Solver Level
, simulate it. NotEqual
If the Marker Level
is not equal to the Solver Level
, simulate it. With these, you can use each level for..
With Equal
and NotEqual
operators, you can have some markers appear or disappear on particular levels, enabling endless combinations.
Roadmap
This should cover a majority of cases, but there are things you cannot yet do, but will be able to in the future.
Capsule
on one level, Mesh
on another. For higher-resolution contacts.For the geeks out there, here's what the underlying algorithm looks like in Python.
# Membership types\nMinimum = 1 # Present at this level and higher\nMaximum = 3 # Present at this level and lower\nOnly = 4 # Only present at this level\nNot = 5 # Present at all levels *except* this one\n\nmarkers = [\n {\"name\": \"hip\", \"level\": 0, \"membership\": Minimum},\n {\"name\": \"spine\", \"level\": 0, \"membership\": Minimum},\n {\"name\": \"neck\", \"level\": 0, \"membership\": Minimum},\n {\"name\": \"head\", \"level\": 0, \"membership\": Minimum},\n {\"name\": \"L_upper_leg\", \"level\": 0, \"membership\": Minimum},\n {\"name\": \"L_lower_leg\", \"level\": 0, \"membership\": Minimum},\n {\"name\": \"R_hand\", \"level\": 1, \"membership\": Minimum},\n {\"name\": \"L_foot_box\", \"level\": 1, \"membership\": Maximum},\n {\"name\": \"L_foot_convex\", \"level\": 2, \"membership\": Minimum},\n {\"name\": \"R_toe_capsule\", \"level\": 2, \"membership\": Not},\n {\"name\": \"R_toe_convex\", \"level\": 2, \"membership\": Only},\n]\n\ndef resolve(level):\n print(\"Level %d\" % level)\n for marker in markers:\n if marker[\"membership\"] == Minimum and marker[\"level\"] <= level:\n print(\" - {name} ({level})\".format(**marker))\n\n if marker[\"membership\"] == Maximum and marker[\"level\"] >= level:\n print(\" - {name} ({level})\".format(**marker))\n\n if marker[\"membership\"] == Only and marker[\"level\"] == level:\n print(\" - {name} ({level})\".format(**marker))\n\n if marker[\"membership\"] == Not and marker[\"level\"] != level:\n print(\" - {name} ({level})\".format(**marker))\n\nresolve(0)\nresolve(1)\nresolve(2)\n
Run this, and this is what you'll find.
Level 0\n - hip (0)\n - spine (0)\n - neck (0)\n - head (0)\n - L_upper_leg (0)\n - L_lower_leg (0)\n - L_foot_box (1)\n - R_toe_capsule (2)\nLevel 1\n - hip (0)\n - spine (0)\n - neck (0)\n - head (0)\n - L_upper_leg (0)\n - L_lower_leg (0)\n - R_hand (1)\n - L_foot_box (1)\n - R_toe_capsule (2)\nLevel 2\n - hip (0)\n - spine (0)\n - neck (0)\n - head (0)\n - L_upper_leg (0)\n - L_lower_leg (0)\n - R_hand (1)\n - L_foot_convex (2)\n - R_toe_convex (2)\n
"},{"location":"releases/2022.01.17/#markers-api","title":"Markers API","text":"With the retirement of the legacy Python API, a new Markers API is now available.
from maya import cmds\nimport ragdoll.api as rd\n\nbox = cmds.polyCube()\n\nsolver = rd.createSolver()\nmarker = rd.assignMarker(box[0], solver)\n\nrd.recordPhysics()\n
The new export and import mechanic can be accessed from here too.
import ragdoll.api as rd\nfname = r\"c:\\path\\to\\my_ragdoll.rag\"\n\n# Get everything out\nrd.exportPhysics(fname)\n\n# Remove everything\nrd.deleteAllPhysics()\n\n# Bring everything back\nrd.reinterpretPhysics(fname)\n
"},{"location":"releases/2022.01.17/#legacy-api","title":"Legacy API","text":"The old Rigid API is still accessible under a new home.
from ragdoll.legacy import commands\ncommands.create_active_rigid()\ncommands.create_point_constraint()\n# ...\n
But will be removed entirely soon, so do transition away from it ASAP.
"},{"location":"releases/2022.01.17/#quality-of-life","title":"Quality of Life","text":"Make it more difficult to make mistakes with these new additions. \ud83d\ude0a
"},{"location":"releases/2022.01.17/#max-mass-ratio","title":"Max Mass Ratio","text":"With Density
, there's a chance Markers get Ragdoll into a situation it does not like; namely that the difference between masses are too great.
As you wish. \ud83e\udd13
Ragdoll doesn't like differences any greater than 10x, sometimes 100x, else it can fail or become unstable. For example, if the torso of your character has a mass of 100kg, and the foot Marker has a mass of 0.5kg, that's a ratio of 100/0.5 = 200x which is far greater than Ragdoll would like. As a result, the body would crush the foot which would be unable to properly hold the entire body up.
Up until now, the masses on all Markers have had a default value of 1kg. Meaning that regardless of the size of a Marker - be it the torso, the head or tip of a finger - it would always have a mass of 1.0. As a result, hands would typically end up far heavier than the rest of the body.
Before
Here's an example of the solver failing. There are three identical chains, the tip of the last one having a mass of 10,000. That's 10,000x greater then each link in the chain. As a result, Markers separate; that is incorrect.
After
If we limit the maximum ratio to just 1000x, we get the correct behavior. You can also see how it affected the other two chains. They now behave more similarly, because in order to ensure a mass ratio across the whole system, the mass of their tips need to be reduced as well.
The new Max Mass Ratio
attribute protects against these situations, letting you give objects a suitable mass and only have to worry about which should weigh more, and which should weigh less. Ragdoll will balance everything out before passing it along to be simulated.
What are the consequences?
Sometimes, large mass ratios are what you want. For example, a heavy weight on a string tends to do quite well with ratios up to 1000x. But markers being crushed by another marker 1000x its weight tends to not do as well.
So the result is less of an effect at the extreme ratios.
In the Manipulator, you can preview the final mass used given the density and the ratio you specified.
"},{"location":"releases/2022.01.17/#directx","title":"DirectX","text":"Look. Closely. Look. Closlier.
That's right! You've now got the option to use Ragdoll with Maya in DirectX viewport mode.
"},{"location":"releases/2022.01.17/#truly-non-keyable","title":"Truly Non-keyable","text":"Some Ragdoll attributes are keyable, others are not. Which is which? Impossible to say. Until now!
On attempting to keyframe a non-keyable attribute, you'll now see an error message along with a visual cue things might not work out the way you expect. As opposed to happily setting that keyframe but then ignoring it once the simulation starts, like it used to.
A little quality of life for ya'!
Pro-tip for Riggers
There are at least 2 ways to prevent non-keyable attributes from being keyframed.
MFnAttribute::setConnectable(false);
MPxNode::legalConnection()
The former means you are also unable to make a control and connect it to multiple non-keyable attributes. Like if you wanted to control Mass
of a series of markers from a single source, or the Overlap Group
.
The latter on the other hand is more flexible. It allows Ragdoll to prevent connections to specific attributes or types of nodes, like animCurve
nodes, which means animators won't be able to keyframe it but you'll still be able to build controls for it.
And that's exactly how it works.
"},{"location":"releases/2022.01.17/#delta-drawing-bug","title":"Delta Drawing Bug","text":"The worldspace deltas were drawn separate from the marker they affected, which could produce a jarring effect especially when the solver position had been offset.
Before
After
This has now been fixed.
More Performance
As an added bonus, we're now also doing 2 matrix multiplications less per frame, per marker. That kind of thing adds up quickly.
"},{"location":"releases/2022.01.17/#shape-sync","title":"Shape Sync","text":"If you play, pause and then change the Shape
from Box
to Capsule
nothing happens. Because the shape, like many other attributes, can only be changed on the start frame.
But, when you later returned to the start frame, the shape would still not update. This has now been fixed.
"},{"location":"releases/2022.01.17/#profiler-view","title":"Profiler View","text":"Mostly meant to keep the development of Ragdoll fast and interactive, you can now spot where most time is spent via the built-in Maya Profiler.
Here's what one frame of this looks like; 5 ms to both simulate and render Ragdoll in the viewport.
"},{"location":"releases/2022.01.17/#removed-attributes","title":"Removed Attributes","text":"These attributes were no longer relevant in the last release, but were still present in the Channel Editor. These have now been hidden and will no longer be saved with your file. A few weeks from now, they will be removed.
limitAutoOrient
limitType
limitAxis
limitOffsetX
limitOffsetY
limitOffsetZ
limitOffset
limitRotationX
limitRotationY
limitRotationZ
limitRotation
It has come to my attention that the first thing every new user of Ragdoll sees is this dialog, with this message for a serial number.
And yet..
Nobody has said a thing! \ud83e\udd23
Correction shout-out to @Rosaline for pointing this out just a few days ago!
According to my Mandarin-speaking friends, this is jibberish (or at least should be!) and is a result of badly translated Unicode to ASCII characters.
This has now been fixed!
"},{"location":"releases/2022.01.21/","title":"Maintenance Release","text":"Minor release with some fixed for you, especially Floating Licence users.
In addition to recording your simulation, you can also snap your rig to wherever the simulation is currently at.
However this only applied to things that aren't yet keyframed. Useful to layout and setting of an initial pose for your character.
With this release, it will also keyframe your rig, such that you can use it to interactively animate a character on specific frames, as you simulate. You know what, it's easier to just show you. \ud83d\ude04
"},{"location":"releases/2022.01.21/#commercial-floating-licence","title":"Commercial Floating Licence","text":"A glitch was found that turned Floating Licences into non-commercial licences, imposing the recording and exporting limits of 100 frames and 10 markers.
This has now been fixed.
"},{"location":"releases/2022.01.21/#limits-and-export","title":"Limits and Export","text":"The new Import functionality introduced in the last version neglected to include limits, this has now been fixed!
"},{"location":"releases/2022.01.21/#z-up-is-inconsistent","title":"Z-up is Inconsistent","text":"One user experienced having their gravity turned sideways, thinking Maya was configured with Z-up when really it was Y-up. It still unclear exactly why this happened, but the one potential edgecase has now been strengthened. If you experience gravity facing the wrong way, or the ground plane being orthogonal to your viewport grid, let us know!
"},{"location":"releases/2022.01.21/#scaled-limits","title":"Scaled Limits","text":"When your rig or controls are scaled, the Manipulator wasn't able to accurately provide you with the limit handles. This has now been fixed.
"},{"location":"releases/2022.01.21/#manipulator-and-viewport-shadows","title":"Manipulator and Viewport Shadows","text":"It used to be the case that the manipulator became invisible whenever viewport shadows was enabled. This has now been fixed!
"},{"location":"releases/2022.02.01/","title":"Quality of Life","text":"Highlight for this release is Quality of Life!
Let's start with the good stuff.
Pounce
Our Manikin is stuck!
Batman Writes
A behind-the-scenes from Jason's cool constraint setup.
"},{"location":"releases/2022.02.01/#kinematic-dynamic","title":"Kinematic & Dynamic","text":"Also known as \"Animated\" and \"Simulated\"
Marker behaviour has been simplified.
Groups are now either Kinematic
- for fully animated, no physics involved - or Dynamic
for having things affected by gravity and contacts with other Markers.
In the above example, I'm alternating between Kinematic
and Dynamic
for the entire character.
Changed
As part of this simplification, two things have changed.
Initial State
was removedPose Match
was renamed to Dynamic
Initial State can be achieved with Dynamic
and a Pose Stiffness
of 0
.
And like before, individual markers can be overridden to be either Kinematic
or Dynamic
. When set to Inherit
it continues to use whatever value was found in the group.
..speaking of which!
"},{"location":"releases/2022.02.01/#group","title":"Group","text":"In the previous version, a group was automatically created whenever you assign to a connected series of controls.
This release enables you to group standalone markers too, and to retroactively group markers in any way you please.
"},{"location":"releases/2022.02.01/#new-group","title":"New Group","text":"Select some markers, put them in a group.
"},{"location":"releases/2022.02.01/#move-to-group","title":"Move To Group","text":"Select one or more markers, along with a destination group, and move them.
"},{"location":"releases/2022.02.01/#group-on-assign","title":"Group on Assign","text":"When assigning markers, you are now also able to pick which group to put it into, or whether to make a new group. Or no group!
"},{"location":"releases/2022.02.01/#lollipop-20","title":"Lollipop 2.0","text":"Lollipops now feature Marker and Group attributes in the Channel Box; less clicks!
"},{"location":"releases/2022.02.01/#customisable","title":"Customisable","text":"Rotate and scale the resulting lollipops to fit your rig and workflow.
"},{"location":"releases/2022.02.01/#retroactive-lollipops","title":"Retroactive Lollipops","text":"Should you have markers without a lollipop, assign them afterwards using the Lollipop menu item. This is also where you can customise which attributes should appear on them.
Pro tip
The Use Proxy Attributes
option makes attributes editable both on the Lollipop and on the original Marker. The downside however is that they make life in the Graph Editor less pleasant. \ud83e\udd14
Some improvements and reshufflings to make your life more complete. \ud83e\udd70
"},{"location":"releases/2022.02.01/#robust-recording","title":"Robust Recording","text":"There hasn't yet been any rig not supported by Ragdoll, until last week when @mandala got in touch with a new challenge. A rig made with an rigging system plug-in called Contour.
Recording this rig results in cycle warnings, presumably because part of how it operates depends on viewport updates.
In this update, there is a (default) Nice and Steady
option for recording which ensures the viewport stays up-to-date with the dependency graph, and that did the trick!
Importing markers onto a character in a different group, or a different character altogether, could be tricky since their hierarchies would differ.
There is now an option to find a matching control by name rather than its full path.
In this example, the character has a different parent group than when it was exported, changing all of the full paths to each control.
"},{"location":"releases/2022.02.01/#scale-replace","title":"Scale Replace","text":"In the case of scaled markers with a replaced mesh, this happened.
Before
But no longer!
After
"},{"location":"releases/2022.02.01/#offline-activation-wizard","title":"Offline Activation Wizard","text":"The offline activation process has now been streamlined; no longer requiring an email conversation back and forth. It should take some of our load off, whilst at the same time enabling you to offline activate when we are sleeping. \ud83d\ude05
Activation
Deactivation
"},{"location":"releases/2022.02.01/#offline-trial-notification","title":"Offline Trial Notification","text":"Whenever someone attempts to trial Ragdoll, but their machine is not connected to the internet, they would receive a message about how their Trial has expired.. Even though it was never activated in the first place!
This has now been fixed.
"},{"location":"releases/2022.02.01/#world-translate-visualisation","title":"World Translate Visualisation","text":"The translation component of the World Pose Space wasn't very visible before, now it is! It's also drawn using the color of the Marker it's associated with, to aid in figuring out what it's actually affecting. And also make things a little nicer to look at.
Before
After
"},{"location":"releases/2022.02.01/#record-leaving-joints-behind","title":"Record Leaving Joints Behind","text":"Sometimes, Ragdoll could leave some remains after recording your simulation. This has now been fixed.
"},{"location":"releases/2022.02.01/#existing-constraints-deleted-on-record","title":"Existing Constraints Deleted on Record","text":"Under rare circumstances, it's possible to assign a marker onto a control that's been constrained. It wouldn't make sense to record onto this control; because what should you expect to have happen? The control is either animated or it is constrained.
At the moment, this constraint is also recorded and once complete your original constraint is deleted. If possible! If the constraint is from a referenced file, then you'll instead see an error. \ud83e\udd14
"},{"location":"releases/2022.02.01/#record-range-options","title":"Record Range Options","text":"The Record UI has seen some updates. It used to always record your current playback range, but can now be customised.
Record To Selected Range
You can now drag-select on the timeline to record only that specific region.
Record Full Range
The minimum and maximum range on your timeline, beyond what is played back.
Record Playback Range
Record only the range currently played back, this is the default and current behaviour.
Customise Range
And finally, provide your own values. These values, along with the option of which range to pick from, is remembered alongside your Maya preferences just like all other Ragdoll options.
"},{"location":"releases/2022.02.01/#existing-constraints","title":"Existing Constraints","text":"In the rare circumstance of:
Record
You would find yourself with a missing constraint. As it happens, when Maya encounters an existing constraint it won't actually create a new constraint when you try and constrain again. Instead, it will append to this constraint.
As a result, since Recording constrains your character to the simulation and then bakes the keyframes, once it was complete and went on to clean up any new constraints it had made, it also deleted yours.
This has now been fixed.
"},{"location":"releases/2022.02.01/#manipulator-multiple-viewports","title":"Manipulator & Multiple Viewports","text":"The Ragdoll Manipulator didn't like multiple viewports being present at the same time, resulting in a similar situation as 2021.12.15.
Ragdoll now draws and responds to the manipulator in the currently active viewport.
"},{"location":"releases/2022.02.01/#plug-in-unload-and-new-scene","title":"Plug-in Unload and New Scene","text":"Sometimes, especially on a floating licence, you'd like to release your licence such that another artist can pick it up.
To do that, you can either go to the Ragdoll UI and Drop Lease
for a floating licence of Deactivate
for a node-locked licence. Or, you can simply unload the plug-in.
As it happens, if you did then Ragdoll would clear your scene. Without confirmation. \ud83d\ude35
This has now been fixed. You'll still need to ensure no Ragdoll nodes are present in your scene though, like any normal plug-in.
"},{"location":"releases/2022.02.01/#delete-from-selection","title":"Delete from Selection","text":"A new menu item has been added to delete physics only from the current selection.
Pro tip I
This was possible using the Use Selection
option within the Delete Physics
option dialog.
Pro tip II
Markers can also be manually deleted in the Outliner, they are DG nodes.
Pro tip III
Another way of deleting an individual marker is:
Delete
or Backspace
on your keyboardPro tip IV
Yet another way of deleting an individual marker is:
Delete Node
Drive Space Custom
appears under in the channel box when Drive Space = Custom
Include Kinematic
option for record has been fixedopts
argument of api.reinterpret
is repairedHighlight for this release is Fields!
Today I'm happy to announce that Jason Snyman joins Ragdoll Dynamics! \ud83c\udf89
Jason is a wizard of an animator with 20 years of experience in the industry - from King Kong and Avatar to Game of Thrones - and will be helping you become the best animator you can be, with Ragdoll at your side. That means tutorials, live streams and more of these awesome demos you may already have seen on LinkedIn!
Batman and Shark Dragon and Kong Dragon on Branch "},{"location":"releases/2022.02.14/#showcase","title":"Showcase","text":"You know the drill. Let's get into it.
Live Stream
We hosted a live stream last Friday! If you couldn't make it, it's been recorded and is made available here. :)
Dragon
Jason's latest animation, using the newly added Fields! Model by Antoine Verney-Carron
Dragon \u2764\ufe0f Kong
I just can't stop watching this.
Manikin Marine
He's packing!
Tentacle Field
"},{"location":"releases/2022.02.14/#manikin-30","title":"Manikin 3.0","text":"The Manikin has been updated to leverage the new goodies from this release, go ahead and grab it here!
Features
Ragdoll now supports all of Maya's native fields.
What are fields?
A field represents a set of forces applied to each Marker. Ranging from Gravity
to Turbulence
, each field carries unique properties you can use to emulate some environment or environmental effect, like wind and gravity fields along a curve.
What is the difference from regular Maya fields?
They are the very same!
If you're already familiar with them, from e.g. nParticles of nCloth, then you can leverage your experience with Ragdoll, and vice versa if you ever venture into nCloth and friends.
Let's walk through these fields one-by-one!
"},{"location":"releases/2022.02.14/#turbulence","title":"Turbulence","text":"The perhaps most interesting field. Apply forces in \"random\" directions, based on the worldspace positions of your Markers.
The way to think of turbulence is as Perlin Noise you may have seen in images such as this.
Where the amount of white determines the amount of force being applied. As a Marker travels across this field, both the magnitude and direction changes in interesting ways.
"},{"location":"releases/2022.02.14/#drag","title":"Drag","text":"Apply an opposite force to any motion.
The faster things move, the greater the force.
Pro tip
This field is similar to Ragdoll's Air Density
. Not technically, but practically.
Apply a uniform force, at a given speed, in a given direction. Like wind, including a kitchen fan with some Spread
.
A familiar force, except this one can be also be animated!
"},{"location":"releases/2022.02.14/#newton","title":"Newton","text":"Force Markers towards or away from a point in space.
"},{"location":"releases/2022.02.14/#radial","title":"Radial","text":"A more curious field; with a force which increases as it gets farther from the source.
"},{"location":"releases/2022.02.14/#uniform","title":"Uniform","text":"Apply a constant force. That's all.
"},{"location":"releases/2022.02.14/#vortex","title":"Vortex","text":"Apply forces in a circular pattern.
"},{"location":"releases/2022.02.14/#volume-axis-field","title":"Volume Axis Field","text":"A field for when you don't know what field you want.
A true Swiss Army Knife of fields, can do everything from Vortex, to Newton to Turbulence in one convenient node.
"},{"location":"releases/2022.02.14/#volume-curve","title":"Volume Curve","text":"Have some fun with this curve-based field. Perhaps to emulate an underwater current?
In this example, I'm also using a Drag
field to keep things from flying off into space.
Pro tip
The curve is a normal Maya NURBS curve. If you need more points, right click and add points as you normally would.
"},{"location":"releases/2022.02.14/#combined-fields","title":"Combined Fields","text":"Make two or more fields to combine their effect and create complex forces or series of forces!
"},{"location":"releases/2022.02.14/#centroids","title":"Centroids","text":"Where within each Marker should a field apply forces?
At the center, forces will be nice and predictable; except they won't be able to introduce rotations to your Marker, which may or may not be what you want. For the most realistic fields, use volumetric centroids.
Here's another example using the Turbulence Field.
Which is better?
Up to you! There is a tiny performance penalty for volumetric origins, as the number of forces increase. But you shouldn't notice much if any impact on performance.
"},{"location":"releases/2022.02.14/#centroid-seed","title":"Centroid Seed","text":"For complex meshes, centroids can end up in unwanted locations or gather in an area with dense vertices. That's when you can give the algorithm a little jolt to try and see whether there is a better alternative out there.
"},{"location":"releases/2022.02.14/#use-selected-as-source","title":"Use Selected as Source","text":"Some forces act according to their position in the world. Attach a field to a Marker to create an interesting relationship between the two.
Non-commercial Ragdoll
This feature is limited to 100 frames in non-commercial versions of Ragdoll.
Distance constrain two markers, and attach a field to the outer-most Marker for a doubly-interesting effect. That also wrecks your brain. \ud83d\ude43
"},{"location":"releases/2022.02.14/#field-scale","title":"Field Scale","text":"If forces start becoming large, you may find yourself in a situation where the visualisation needs to tone down just a bit.
In the solver settings, you will find options to scale those lines (i.e. Field Scale
), as well as control how many steps into the future (i.e. Field Iterations
) it should draw for you.
Fine-tune the effect of fields by having one or more Markers ignore the effect of fields.
"},{"location":"releases/2022.02.14/#force-modes","title":"Force Modes","text":"Fields can apply to your markers in 2 different ways.
Mode Description Math Force Traditional forcemass * distance / time^2
Impulse Typically used for contacts mass * distance / time
Which should I use?
The default is Force
, whereas Impulse
is what is typically used for collision handling. Experiment, and let us know which you prefer!
Combine multiple meshes for a complex \"compound shape\".
Vertices connected by edges are considered an \"island\", each island is then turned into an independent convex hull. Like this complex endevour.
434 islands in 147 ms
That's how long it took Ragdoll to generate the simulation volumes for the above meshes.
You can slice an dice any mesh to introduce new islands at will, for complete control.
Performance?
If you're wondering what effect this many meshes has on your simulation, the answer is we haven't noticed any. Go crazy, and if you do notice anything, let us know!
"},{"location":"releases/2022.02.14/#mesh-decomposition","title":"Mesh Decomposition","text":"Collision shapes are generated from each individual \"island\"; that is, groups of vertices that are connected by at least one edge. When you combine two or more meshes together, they will naturally form individal islands.
Sometimes, you'd rather treat the entire mesh as one big shape and for that you can use the Mesh Decomposition = Mesh Islands
.
Shape Vertex Limit
Also notice how the vertex limit is applied to each island. Meaning that you can achieve much higher resolution for your collision shapes by cutting things up into pieces!
"},{"location":"releases/2022.02.14/#quality-of-life","title":"Quality of Life","text":"Let's brighten up your day, shall we? \ud83e\udd70
"},{"location":"releases/2022.02.14/#robust-frame-skips","title":"Robust Frame Skips","text":"Anyone playing back their simulation to audio may prefer Ragdoll with a Frameskip Method = Ignore
. Such that it'll keep simulating, even though the result won't be 100% reproducible.
But! If you did, you may have ran into this.
Notice how it sometimes fails to keep up with fast time changes? Well, no longer!
Caveat
Like before however, the simulated result you get when frames are skipped will still differ from the result when frames are not skipped, or when different frames get skipped.
The final recorded result will not skip any frames, so you should use this while working but ensure there aren't any frames skipped when you tune and tweak the final values.
"},{"location":"releases/2022.02.14/#manipulator-and-hud","title":"Manipulator and HUD","text":"The View Cube and other viewport ornaments are automatically and temporarily hidden whenever you use the Manipulator. But sometimes, Ragdoll could get confused and leave you having to manually re-enable the viewport HUD.
This has now been fixed, and Ragdoll will more predictably re-enable any HUD it hides.
"},{"location":"releases/2022.02.14/#kinematic-stiffness","title":"Kinematic Stiffness","text":"Markers set to Kinematic
would also lose their stiffness with their parent.
Before
After
This has now been fixed.
Pro tip
To achieve the effect from the previous version, set Pose Stiffness
to 0
Users of Maya 2022 would experience this dialog when getting started with Ragdoll.
This has now been fixed.
"},{"location":"releases/2022.02.14/#negative-scale-edgecase","title":"Negative Scale Edgecase","text":"A rare case was discovered by @BigRoy whereby negatively scaled controllers would yield an incorrect shape drawing. The simulation was fine, but it wasn't looking quite right in the viewport.
Before
After
This has now been fixed!
"},{"location":"releases/2022.02.14/#import-additions","title":"Import Additions","text":"These attributes were added to the export and import mechanism.
Nice Name Long Name World Pose Translate XdriveAbsoluteLinearX
World Pose Translate Y driveAbsoluteLinearY
World Pose Translate Z driveAbsoluteLinearZ
Pose Twist Amount driveAngularAmountTwist
Pose Swing Amount driveAngularAmountSwing
"},{"location":"releases/2022.02.14/#capsule-length","title":"Capsule Length","text":"All this time, capsules had been scaled in an axis that didn't align with your scale manipulator.
No longer!
Before
After
"},{"location":"releases/2022.02.28/","title":"Environment","text":"Highlight for this release is Complex Geometry!
Before we get into the new features of this release, let's have a look back at some highlights of the week.
For the Love of Ragdoll
Animation by Kevin Taylor, model by Shaun Keenan.
Dragon Setup Livestream
The dragon from the latest livestream last Friday!
Chewsday
A little experiment with worldspace rotation stiffness.
Rhino Workout
Soft joints for some belly-jiggle.
Rhino Walk
Nice self-walking rhino.
Self Walking Manikin
Same trick, different character. :)
Soft Joints
Jason experimenting with the new Soft Joints feature.
Facial Animation
Getting some nice secondary motion out of moving the head and jaw around!
"},{"location":"releases/2022.02.28/#environment","title":"Environment","text":"Ragdoll now supports static environments; meaning environments that cannot move or deform, but allow for normal polygonal geometry without the need for a simplified \"convex hull\".
As you might expect, this works well for environments like terrain and other complex geometry that is otherwise hard to turn into a rounded mesh.
"},{"location":"releases/2022.02.28/#performance","title":"Performance","text":"It's fast.
Normal shapes are limited in how complex they can get, and as such you never really run into a situation where the shape noticeably affects performance.
Triangle meshes are different; they can be of any complexity. Up to millions of polygons and beyond. So it falls upon you to decide where to make the performance/quality tradeoff!
Vertex Count Cooking Time Run-time performance 400 0.39 ms 685 fps 8'000 3.51 ms 599 fps 16'000 14.3 ms 594 fps 64'000 61.5 ms 327 fps 256'000 287.7 ms 40 fps 1'000'000 1490 ms 2 fpsWhat is cooking time?
The time it takes for Ragdoll to convert your polygonal geometry into the internal representation needed for collision detection. It involves splitting up the mesh into areas or \"zones\" for faster lookup.
This only happens when the mesh actively changes and when first opening the Maya scene, and won't affect playback speed.
"},{"location":"releases/2022.02.28/#automatic-mesh-islands","title":"Automatic Mesh Islands","text":"Ragdoll needs \"convex\" meshes for anything that moves.
What is a convex mesh?Think of it like a shrink-wrapped version of your mesh.
In 2D, it might look something like this.
Notice how the points in the middle are excluded? This is an optimal shape for collision detection, as you can draw a straight line from anywhere in the world and know that if it ever hits this shape, it hits it in only 1 spot.
In the previous release, \"Mesh Islands\" were introduced to turn each separate polygonal island into its own convex hull and glued together as one complex shape.
With that, you have a great deal of control over the final collision shape
Multi-cut settingsTick the Extract Faces
box, and zero out those values to get Maya to perform an actual split in the geometry as you cut. Otherwise, it will only insert new edge-loops and not actually create two separate meshes.
It did, however, mean that you had to take the time to manually slice up the mesh, which may not always be feasible. This release introduces an automatic method of slicing up a given mesh, into a close approximation of the original mesh.
"},{"location":"releases/2022.02.28/#attributes","title":"Attributes","text":"There are a number of parameters to tune when generating your convex hulls, here's what they mean.
Attribute DescriptionResolution
The number of \"voxels\" to generate from a given volume; the greater the number the more accurate the resulting representation. At the expense of time. Values between 100-1000 are normally sufficient. Concavity
The maximum allowed different in angle across the surface of the resulting meshes. It might be thought of as \"roundness\". Symmetry Bias
Slices are made either horizontally and vertically, or radially. This value controls how much to favour the former. Revolute Bias
And this value controls how much to favour the latter Min Volume
Ignore computed volumes that are smaller than this. It can help reduce the number of very tiny meshes. Max Convex Hulls
How many separate meshes to make. This will depend on the complexity of your mesh, but generally the lower the better. Plane Downsampling
Performance related, lower values take longer Hull Downsampling
Also perforamnce related, lower values take longer Fill Mode
Various ways to deal with geometry that isn't a closed volume. A sphere for example is a closed volume, whereas a plane is not. Approximate Hull
Performance related, faster when ticked. Project Hull Vertices
See what the generated meshes look like before they are \"shrink-wrapped\" back onto your model. These give you a good sense of how large the voxel resolution is. Complexity
Over time, as we learn more about which parameters work best in the most general case, I'd like to reduce the number of attributes here. Ideally we would only have a Quality
attribute with Low
, Medium
and High
settings.
It's slow.
The process of automatically slicing your geometry is not real-time, it can take up to a few seconds or more. On the upside, it only ever happens when the mesh changes and does not affect playback performance.
Here are some timings for the meshes in the below simulation.
Object Pieces TimerMarker_Barrels
30 1.9 s rMarker_Ceratopsia
16 0.7 s rMarker_FingerPlates
64 6.1 s rMarker_LeaflessTree
183 6.3 s rMarker_bull
16 0.8 s rMarker_fish
16 0.7 s rMarker_hand_basemesh
16 0.3 s rMarker_horse
16 0.9 s rMarker_humanBody
32 2.9 s rMarker_jetFighter
16 0.5 s rMarker_polySurface9
16 1.6 s rMarker_shirt
16 0.9 s Faster performance is on the map
This method is new to us, and we expect to find faster - ideally real-time - alternatives to this in the future.
"},{"location":"releases/2022.02.28/#soft-joints","title":"Soft Joints","text":"To balance out the talk of complex but hard geometry, let's talk about \"soft joints\".
Once I set Translate Motion = Soft
and the feet hits the ground, notice how:
Here's a more extreme example.
"},{"location":"releases/2022.02.28/#general-purpose","title":"General Purpose","text":"We're calling it \"soft joints\" when in reality this is Pose Stiffness
but for translation rather than rotation. Which means you could use it for tentacles and other appendages that depend on not just rotating limbs but squishy and compressed limbs. Potentially stretchy limbs and spines too?
We haven't yet explored this fully, so take it for a spin and let us know what you come up with. \ud83d\ude0a
"},{"location":"releases/2022.02.28/#caveat","title":"Caveat","text":"When stiffness goes too low, limbs detach.
This is unintended behaviour and will be addressed in a future release. Proper breakable constraints are on the map, but this isn't it. So use with caution, and limit it to create softness between your limbs.
"},{"location":"releases/2022.02.28/#forum","title":"Forum","text":"The forum has gotten a face-lift! This will henceforth be where tutorials and showcases appear, along with notifications for new releases!
So sign up, subscribe to the News
category to receive notifications when things happen in Ragdoll-land!
Out of beta and available to all.
If you need a more low-cost but commercial introduction to Ragdoll in your studio, then this is for you.
You can now make groups via the API.
from maya import cmds\nfrom ragdoll import api\n\nsolver = api.createSolver()\nground = api.createGround(solver)\ngroup = api.createGroup(solver)\nsphere, _ = cmds.polySphere()\ncmds.move(0, 10, 0)\nmarker = api.assignMarker(sphere, group)\n\ncmds.evalDeferred(cmds.play)\n
The assignMarker
command has also been simplified and does not longer implicitly create a group.
A few more things to make your day that much more bright.
"},{"location":"releases/2022.02.28/#merge-solvers","title":"Merge Solvers","text":"You can now merge two solvers together, move markers from one solver to another and extract markers into a new solver.
"},{"location":"releases/2022.02.28/#extract-markers","title":"Extract Markers","text":"Sometimes, you want some of your markers to be part of a separate solvers.
"},{"location":"releases/2022.02.28/#move-to-solver","title":"Move to Solver","text":"Rather than merge two solvers in its entirety, move specific markers from one solver to another.
"},{"location":"releases/2022.02.28/#manipulator-with-multiple-solvers","title":"Manipulator with Multiple Solvers","text":"The Manipulator can now be used in scenes with two or more solvers in them!
"},{"location":"releases/2022.02.28/#manipulator-selection","title":"Manipulator Selection","text":"You can now use the Manipulator to select both the Marker and Maya node, such that attributes can be edited in the Channel Box.
"},{"location":"releases/2022.02.28/#manipulator-fit-to-view","title":"Manipulator Fit-to-view","text":"Using the manipulator via the Ragdoll menu enabled you to also benefit from the F
key, to fit your selection to the current camera.
But if a Marker or Group was selected and editable in the Channel Box, that no longer worked. Because under the hood, what you were really fitting in view was the solver shape node.
This has now been fixed such that you can fit any selected Marker, regardless of whether the solver shape node is selected or not!
"},{"location":"releases/2022.02.28/#select-during-playback","title":"Select During Playback","text":"The Manipulator can now be used to select Markers during playback.
Caveat
Selection is based on the current simulated state and doesn't understand rewind. To fix this, step at least 1 frame forward whenever you attempt to select, to ensure the selection and simulation is staying in sync.
This will be addressed in a future release.
"},{"location":"releases/2022.02.28/#reset-shape","title":"Reset Shape","text":"Whenever you assign a Marker, a default shape is computed based on your selection and available geometry or NURBS curves.
"},{"location":"releases/2022.02.28/#refit-assignment","title":"Refit Assignment","text":"Likewise, when you branched off into a tree-like structure for your markers, you could easily end up with something like this.
This has now been addressed, whereby the marker which forms a fork now being reset automatically.
"},{"location":"releases/2022.02.28/#licence-conservation","title":"Licence Conservation","text":"Applies to
This feature only applies to Floating Licence customers.
In the previous release, a licence was leased on plug-in load.
The problem was that, sometimes, an artist merely opens a scene with Ragdoll in it. Maya will determine that this file requires the Ragdoll plug-in to be loaded, and loads it. Upon load, Ragdoll would go ahead and check out a licence. But this artist doesn't necessarily want to interact with Ragdoll, it could have been a texture artist opening up an animator's scene, or someone rendering it.
This release introduces \"licence conservation\" which only tries to lease a licence upon a simulation taking place. That means a lease is not made on plug-in load, nor on scene open. If a solver is hidden from view, nor does it take place on playback start.
Only once simulation visibly begins is a lease requested, helping you save those precious seats for the artists that need it most.
Markers are still rendered in the viewport on the start frame for everyone, without a lease. The Solver is automatically hidden upon failure to lease a licence, pausing any further requests until it is made visible again.
"},{"location":"releases/2022.02.28/#minor-releases","title":"Minor Releases","text":"Inbetween this release and the previous release there were a few minor releases made.
rdGroup
nodeRequest Lease
button in the Ragdoll UI now actually worksThe menu items for the old Legacy interface to Ragdoll Dynamics has now been removed. Scenes created with this interface will still open, so this is your last chance to save your work and transition to the current Marker-based workflow.
"},{"location":"releases/2022.03.14/","title":"Quality of Life","text":"Highlight for this release is Quality of Life!
Let's catch up on a few highlights over the past 2 weeks.
Instict
Andrei got Ragdoll introduced to this beautiful thing.
Some nice stills.
Rhinos
Jason's working on a new tutorial for how to make self-walking quadrupeds.
Let's have some more, shall we? \ud83e\udd73
"},{"location":"releases/2022.03.14/#manipulator-and-multiple-solvers","title":"Manipulator and Multiple Solvers","text":"The Manipulator operates on 1 solver at a time.
When there are two or more manipulator in the scene, Ragdoll will now be more kind and smart about which one you mean.
Select any..
..and the manipulator will figure out which solver you mean.
When unsure, it will ask you to clarify.
"},{"location":"releases/2022.03.14/#selection-highlight","title":"Selection Highlight","text":"Each marker have 3 possible nodes you can select.
Selecting the marker and source transforms gave you a handy selection highlighting in the viewport, confirming what you had selected. But so far, selecting a destination transform did no such thing. Until now!
Notice how this also helps you detect whether something has a target at all, like the upper legs here. These remain unrecorded, as they are connected to the hip and driven by IK.
"},{"location":"releases/2022.03.14/#contact-visualisation","title":"Contact Visualisation","text":"You can now visualise when and where contacts occur.
This can help spot self-collisions too!
"},{"location":"releases/2022.03.14/#import-symmetry","title":"Import Symmetry","text":"Symmetry is now preserved on import.
For any character authored in a symmetrical pose, the Ragdoll Manipulator would let you operate on this character on both sides at once.
But until now, this symmetry was lost if at any point an import was made on a character was not symmetrical, such as an animated character.
This changes today!
"},{"location":"releases/2022.03.14/#manipulator-deselect","title":"Manipulator Deselect","text":"With nothing selected, you now have access to the Solver in the Channel Box.
"},{"location":"releases/2022.03.14/#clean-abort-on-record","title":"Clean Abort on Record","text":"Almost rhymes. If recording takes too long and you hit the ESC key to cancel, Ragdoll no longer leaves a mess behind. It's clean!
"},{"location":"releases/2022.03.14/#coloured-limits","title":"Coloured Limits","text":"The manipulator now colors limits by their axis. Where X is red, Y is green and Z is blue; just as you'd expect.
"},{"location":"releases/2022.03.14/#auto-cache","title":"Auto Cache","text":"There is now an option to disable auto cache upon completed record.
This will let the simulation continue running after recording, using your newly recorded controls as input.
"},{"location":"releases/2022.03.14/#on-location-pin","title":"On-Location Pin","text":"Whenever you make a new Pin Constraint, it would appear at the location of your animation. But now, it will appear wherever the simulated version of your animation is.
"},{"location":"releases/2022.03.14/#limit-on-select","title":"Limit on Select","text":"Limits are now only visible when selected, making things a little less messy in the viewport.
"},{"location":"releases/2022.03.14/#fixes","title":"Fixes","text":"Some house cleaning of minor things that could sometimes trip you up.
"},{"location":"releases/2022.03.14/#nested-namespaces-and-import","title":"Nested Namespaces and Import","text":"Ragdoll is now happy to import physics onto any number of namespaces.
"},{"location":"releases/2022.03.14/#animated-pose-space","title":"Animated Pose Space","text":"The previous release broke any transition between Local
and World
, this has now been fixed.
When you want a marker to follow your animation in worldspace in all but one or two axes, you can use World Pose Translation
. However, in the previous release, the axes were aligned with the control rather than the world. This has now been fixed.
Linking two solvers is a non-destructive method of getting multiple characters to interact in the same scene. As it happens, you haven't been able to unlink until now.
"},{"location":"releases/2022.03.14/#export-without-rag","title":"Export without .rag","text":"As it happens, the Import Options will only show you files that have a .rag
extension. But! The Export Options would permit export of files without this extension.
As a result, it could appear as though nothing was exported. :(
This has now been fixed.
"},{"location":"releases/2022.03.14/#euler-filter","title":"Euler Filter","text":"To keep gimbal locks from happening in your recorded simulation, an \"Euler Filter\" could be automatically applied. This hasn't been the case so far, but has now been fixed.
"},{"location":"releases/2022.03.14/#0-density","title":"0 Density","text":"Giving markers a density of 0 would make it infinitely light, or infinitely heavy depending on your perspective. Such things does not exist in the real world and cannot be simulated.
Ragdoll will now protect you against this.
"},{"location":"releases/2022.05.04/","title":"Retargeting 2.0 and Maya 2023","text":"Highlight for this release is a new Retargeting UI and support for Maya 2023
We've got a lot of new content since last release, so let's break it down.
Pirate
New livestream from last Friday!
And a new start-to-finish asset and breakdown on the forums for this guy!
Woody
Another gem from @Andrei on the forums!
Ice Dragon
This one from Jack Preston on the forums!
Gundam
And one more, also from Jack The Magnificent!
VR Rabbit
Jason took a spin in virtual reality to come up with this nightmare of a rabbit.
Rhino Companion
The Manikin got a friend.
"},{"location":"releases/2022.05.04/#retargeting-ui","title":"Retargeting UI","text":"You can now visually see where keyframes go upon running Record Simulation
.
Let's take a look at what this UI is, what it can do for you and when to use it.
The UI can help you spot problems with recording, before recording happens.
In this case, some of our markers are retargeted onto joints that are driven by some other object. If we were to attempt to record these, it's unclear what the result should be.
Neither of these are a great pick, since we don't want to break the rig, but we also want our simulation to go somewhere.
"},{"location":"releases/2022.05.04/#workflow","title":"Workflow","text":"Once you've assigned your markers, grab a clean slate and gain complete control over where animation is to be recorded.
And finally, here's a longer-form example of a full setup of the Truong Dragon that we did a livestream on a while back.
Ragdoll now ships with plug-ins for Maya 2023, enjoy!
Heads up
Maya 2018 is still included in this release, but should be considered deprecated and will be removed entirely by July 2022.
"},{"location":"releases/2022.05.04/#moar-performance","title":"Moar Performance","text":"Ragdoll now renders up to 20% faster.
Before
It used to be the case that each frame uploaded vertices and colors to the GPU.
After
But now, there is zero memory allocations. The programmers amongst you will appreciate the benefit and difficulty of such an improvement. This lays the foundation for future performance advances, in particular related to instancing and crowd simulation. \ud83e\udd2b
For the techies amongst you, here's what the improvement looks like in the Profiler.
Before
After
The top two layers is Ragdoll, notice the slight reduction in length. Win!
"},{"location":"releases/2022.05.04/#quality-of-life","title":"Quality of Life","text":"Here's a summary of changes designed to make your day just a little more bright.
"},{"location":"releases/2022.05.04/#following-pin-constraint","title":"Following Pin Constraint","text":"You now have the option of automatically constraining the Pin Constraint to your animation, giving you a similar look to Pose Space = World
except with a new dedicated transform node.
Multiple Pins
There can be many of these for the same marker!
Pin to Current Animation Pose
The default, put a pin wherever the animation currently is.
Pin to Current Simulation Pose
Alternatively, put it wherever the simulation is.
Ragdoll Non-Commercial
This option can only find the simulated pose for the first 100 frames unless you've got a commercial licence, like Ragdoll Complete or Ragdoll Unlimited.
Constrain Pin to Animation
Follow your animation interactively, by putting a Parent Constraint between pin and control.
"},{"location":"releases/2022.05.04/#select-group-members","title":"Select Group Members","text":"You can now select the members of a group, to aid in organising your scene.
"},{"location":"releases/2022.05.04/#visualise-environment","title":"Visualise Environment","text":"You can now see where the environment is when the solver is offset.
Before
After
"},{"location":"releases/2022.05.04/#manipulator-ordered-selection","title":"Manipulator & Ordered Selection","text":"The Manipulator now remembers the order in which you select, meaning you can use it for ordinary tasks like reparenting and constraining markers!
For example, consider this character here. He's symmetrical, and yet seem heavier on one side..
Let's take a closer look at the updated Hierarchy visualisation to see whether there is something wrong with the hierarchy we have created.
Aha! Let's fix this, by..
Reparent
All from the comfort of the Manipulator.
Here are some more funky hierarchies to solidify the point.
"},{"location":"releases/2022.05.04/#manipulator-symmetry-on-enter","title":"Manipulator & Symmetry on Enter","text":"Ragdoll will now look for symmetry right after entering the Manipulator. Especially helpful if you enter with some marker already selected, and especially if you use the T-hotkey to enter into the Manipulator!
"},{"location":"releases/2022.05.04/#manipulator-symmetry-toggle","title":"Manipulator & Symmetry Toggle","text":"Ragdoll will now look for a symmetrical partner when toggling the Enabled checkbox. Win!
"},{"location":"releases/2022.05.04/#manipulator-delete","title":"Manipulator & Delete","text":"You can now delete markers from within the Manipulator!
"},{"location":"releases/2022.05.04/#environment-node-crash","title":"Environment Node & Crash","text":"In the case of having more than 1 environment, you may have experienced a crash!
Before
After
This has now been patched up!
"},{"location":"releases/2022.05.04/#mesh-protection","title":"Mesh Protection","text":"Ragdoll can take meshes of any complexity.
Sometimes meshes have no volume. And that's fine; Ragdoll will generate a flat surface with some volume to it, to try and interpret what you want. However, under rare circumstances, those volume-less meshes could cause trouble for Ragdoll.
New attributes have been added to try and protect you from these. These will jiggle the vertices to try and discard anything suspicious. You normally won't have to interact with these, the defaults should keep you safe. But if you find vertices missing from your colliders, try editing these.
"},{"location":"releases/2022.05.04/#recording-start-frame","title":"Recording & Start Frame","text":"In some situations, you could find yourself with recorded keyframes all over the place.
Before
Notice how all of the destination controls - the joints, in this case - are all mangled! This would happen when the current time and the start frame of the simulation did not align. Not always, but in this particular case, and likely others too!
After
Now working as you'd expect. Phew!
"},{"location":"releases/2022.05.04/#recording-initial-pose","title":"Recording & Initial Pose","text":"When deleting a recorded layer, Maya would sometimes forget where your character was prior to recording.
Before
Notice how our character remains on the ground when deleting the layer, even though that's clearly one of the simulated poses.
After
This is instead what we expect, for it to return to where it was prior to recording.
"},{"location":"releases/2022.05.04/#linked-solver-stability","title":"Linked Solver Stability","text":"Solver linking is when the contents of two or more solvers participate in the same physical world; for example, reference two characters and link their solvers. Viola, you've got a single simulation with the two characters interacting with each other. Great!
However, under some circumstances this didn't always work. Especially with referenced files. It had to do with the order in which the solvers were created, and which solver was created when. It could happen that the link was ignored. Sometimes it behaved differently on scene re-open.
No longer! Now solver linking is robust, as you would expect.
"},{"location":"releases/2022.05.04/#inches","title":"Inches","text":"Using the manipulator in a Maya configured for inches, or any other unit than millimeters..
..could result in funky behaviour. This has now been fixed!
"},{"location":"releases/2022.06.09/","title":"Locomotion","text":"The highlight for this release is Locomotion!
The above animation is automatically generated, given just a handful of parameters to ragdoll.
Start
and End Position
Step Sequence
Limits
I'll walk through what each of these mean in the rest of this documentation.
"},{"location":"releases/2022.06.09/#examples","title":"Examples","text":"Let's start with a quick look at what you can get out of this new toy.
Locobot
Modeling by Christophe Desse.
Spot and Friends
Happy Box
Yes, you can give it a terrain.
Two Happy Boxes
Locoboy
A 2-legged quadruped, look at'em go!
Locomotion & Physics
Playing well together.
Humanoid Locomotion
As you can tell, quadrupeds fair much better!
Human Dynamics
But with some physics, it's starting to look nice. :)
"},{"location":"releases/2022.06.09/#abilities","title":"Abilities","text":"Here's what we're aiming for with this release.
To achieve this, you've got control over:
Step Sequence
Terrain
upon which to walkThere can be any number of feet and it can travel any amount of distance. The Step Sequence
is how you're able to achieve different kind of walks.
And the Terrain
is how it can do this across geometry of any complexity.
Let's talk about what cannot be solved with Ragdoll Locomotion
.
As of this release, it only understands 2 things.
And for feet, it only understand the position of the foot, not its orientation.
Most importantly, it does not understand arms! Arms are critical to human locomotion, they swing in tandem with each step. This version of Ragdoll does not understand arms. Yet. Meaning it's good for locomotion involving any creature that does not have arms.
But Marcus, that doesn't leave much room for many creatures. They all have arms!
Think again!
With that out the way, let's look at what it can do!
"},{"location":"releases/2022.06.09/#workflow","title":"Workflow","text":"Here's what you do.
Assign Plan
Plan?
The generated locomotion is the result of a \"plan\", meaning each of the inputs you give it. Including this initial selection.
"},{"location":"releases/2022.06.09/#press-t","title":"Press T","text":"Locomotion also has a manipulator, accessible by selecting the rPlan
node and pressing T
on your keyboard.
Locomotion is computed in the background.
Normally, it'll take a second or two to compute 4-12 seconds worth of locomotion, and you can safely interact with Maya whilst it's running. It has zero impact on your overall Maya or character rig performance.
"},{"location":"releases/2022.06.09/#rig-compatibility","title":"Rig Compatibility","text":"Anything from a box with a sphere for feet to the most complex digi-double will do.
The rig in the above example is nothing special, as you've seen from the examples above this works on \"rigs\" as complex as a box and 2 spheres.
"},{"location":"releases/2022.06.09/#multiple-characters","title":"Multiple Characters","text":"You can have as many characters in the scene as you like.
Parallelism
These currently run 1 at a time, but the next release will unlock this to 1-per-core. Meaning you can have 128 characters computed in parallel on a 64-core AMD CPU. Now for what purpose could you ever need that many?
"},{"location":"releases/2022.06.09/#physics","title":"Physics","text":"Locomotion is an entirely separate \"brain\" that you may, or may not, want to combine with regular Markers.
Body and/or feet can be Kinematic
or driven by a Pin Constraint
, or anything inbetween.
Unlike a simulation, Locomotion
is entirely time independent. So it isn't strictly necessary to record; it will run directly on your character rig.
You can edit the locomotion as keyframes via Maya's native Bake Results
command.
This will become your new best friend. With an easily recognisable pattern for when to move your feet.
Sequencer Mode
Shift
to paintCtrl
to eraseIt can be used to produce a wide variety of locomotion, such as this frog sequence.
"},{"location":"releases/2022.06.09/#targets","title":"Targets","text":"Once you've figured how to get somewhere, next up is figuring out where to go.
Target Mode
Start
or End
of the body or footTranslate
gizmo to control the position of either body
or foot
Rotate
gizmo to control the start and end orientation of the body
Use the Rotate
gizmo to control the orientation of the body at the start or end positions.
Is your character jumping or limping? Maybe dancing? Limits control the area in which each foot is allowed to move.
Limit Mode
body
to adjust the size of your characterfoot
to adjust the amount of motion a foot is allowed to haveHere's an example of how a short limit on one foot, and long steps with the other foot, can generate a wounded or limping locomotion.
"},{"location":"releases/2022.06.09/#terrain","title":"Terrain","text":"Things can easily get more interesting by swapping out that flat ground with some geometry.
"},{"location":"releases/2022.06.09/#known-issues","title":"Known Issues","text":"Sometimes, Locomotion can get stuck Thinking...
. Let us know if this happens, along how you got to that point. We're working on narrowing this down.
In addition to locomotion, a few minor things were improved in this release.
"},{"location":"releases/2022.06.09/#manipulator-constraints","title":"Manipulator & Constraints","text":"With the previous release keeping track of the order in which you select things using the manipulator, this release carries on the trend by enabling constraints to be made from within the comfort of the Manipulator. \ud83e\udd17
"},{"location":"releases/2022.06.09/#manipulator-namespaces","title":"Manipulator & Namespaces","text":"If you had 2 controls of the same name but in different namespaces, the Manipulator could get confused about which one you were actually editing.
This has now been fixed.
"},{"location":"releases/2022.06.09/#new-defaults","title":"New Defaults","text":"In response to feedback on the default values, 3 of them has seen an upgrade.
Air Density = 1.0 -> 0.1
Substeps = 4 -> 8
Iterations = 4 -> 8
These can all be found on the rSolver
node. And will result in more accurate simulation and less explosions. Bearing in mind that many simulations do not require this amount of substeps and iterations, and they come at the expense of performance. So if you find yourself in need of more juice, lower these back down to 4 or lower. If it looks right, it is right.
As it happens, MacOS users were getting a much too small Manipulator HUD!
This has now been addressed.
If you encounter any issues like this, please let us know in the forums!
"},{"location":"releases/2022.06.15/","title":"Parallel Locomotion","text":"The highlight for this release is Parallel Locomotion!
You know the drill, let's start with the good stuff! \ud83e\udd70
Model by Christophe Desse
"},{"location":"releases/2022.06.15/#parallel-locomotion","title":"Parallel Locomotion","text":"That's right! If 1 character takes 2 seconds to compute, 5 characters now also takes 2 seconds to compute. Or 10 characters, or 100 characters. 2 seconds in total, that's all you'd have to wait, up to the number of cores on your system.
As core-count continues to increase in our machines, you can expect the number of characters being run in parallel to increase as well, up to the level of full crowds; each individual character a unique and precise sequence of steps that conform to their environment.
Juice Left
There is still a little bit of juice left to squeeze.
At the moment, if Ragdoll detects any relation between one plan and another, it will run these one-by-one.
Normally, this is not the case, but if you for example connect the output of one plan to the input of another, there isn't much that can be done other than wait for one to finish. However this can also happen when unrelated things are connected, such as your character being connected to two plans, such that you can blend between them. This is too much, and will be addressed in a future release. Subtle balance!
"},{"location":"releases/2022.06.15/#locomotion-for-macos","title":"Locomotion for MacOS","text":"Go nuts!
"},{"location":"releases/2022.06.15/#determinism-restored","title":"Determinism Restored","text":"A bug was introduced in the last release, which could have resulted in your simulation returning different results when:
This has now been fixed.
"},{"location":"releases/2022.06.15/#endless-thinking","title":"Endless Thinking","text":"Sometimes Locomotion could simply never stop thinking, and you know how too much thinking is bad for you? The same applies to Locomotion.
This has now been fixed!
"},{"location":"releases/2022.06.15/#shift-to-toggle","title":"Shift to Toggle","text":"You can now choose whether to use the Shift and Control keys to add and remove steps in the Locomotion Step Sequencer, or whether to use Shift for both. Dragging over a filled step will erase it, whereas dragging over an unfilled step will fill it. A toggle!
"},{"location":"releases/2022.06.15/#updating-the-duration","title":"Updating the Duration","text":"You used to have Locomotion a kick in the butt whenever changing the Duration
attribute, to give your locomotion more time to reach the goal position.
This has now been fixed. :)
"},{"location":"releases/2022.06.15/#scale-factor","title":"Scale Factor","text":"The last release attempted to scale the viewport HUD automatically for your Mac users out there, but as it happens the built-in Mac display and an external display give different values to the mechanism we use to detect that scale. So, I leave it to you to tweak to your hearts content.
All things are scaled interactively, except the font which needs a plug-in reload to remain crisp.
"},{"location":"releases/2022.06.15/#optimised-rendering","title":"Optimised Rendering","text":"Hiding the rSolver
node automatically halts simulation, freeing up resources for your character rigs. The same applies to..
With this release, simulation now also takes a backseat with the viewport Plugin Shapes
unticked.
You'll no longer see warnings from Firefox or Chrome when downloading our plug-in, nor when using our .msi
installer to install it, nor will anti-virus ever thing our software is anything but authentic.
Hurray!
For Mac users with \"Gatekeeper\" enabled, a solution is headed your way soon!
DigiCertUtil
This is for search engines, and developers working with DigiCertUtil.exe
Animators, look away
As it happens, you can use DigiCertUtil.exe
from the command-line. As is mentioned here, https://www.digicert.com/kb/util/utility-code-signing-command-line.htm
But what's this? It just causes the GUI to appear? No message? What did you do wrong? Well, as it happens..
# Before\ndigicertutil /noInput sign loco3d.exe\n\n# After\ndigicertutil sign /noInput loco3d.exe\n
This matters. The order in which you pass the sign
argument. I must come first. And that's it, really. Pass it first, and then it will tell you what's wrong and what to do about it. You've also got.
digicertutil /?\n
Which does not need the sign
argument, apparently, but will provide you with a separate window with details about each argument to sign
possible.
There, search engines, index this and save the hour or more I lost investigating and scratching my head about this.
"},{"location":"releases/2022.07.20/","title":"Meshes Meshes Meshes","text":"Highlight for this release is Meshes meshes meshes!
Leave any comments and report any issues here.
We've launched a Ragdoll Challenge since the last release, here are some highlights!
Crabomotion
From the ongoing competition by Kaehwai.
Hands
By V4NDL0 on the forums.
Jason
Some clips from Jason's LinkedIn feed over the past 2 weeks.
"},{"location":"releases/2022.07.20/#raggraph","title":"Raggraph","text":"In August, we're heading to Siggraph 2022 in Vancouver!
We'll be over here, at booth 442.
Running a handful of demos of how Locomotion works under the hood (hint: robotics tech!) along with the basics of Ragdoll.
Our booth will look something like this.
We'll be wearing t-shirts that look like this.
And have some nice banners that look like this.
Preliminary schedule looks like this.
The most important and complex aspect of Ragdoll are the Pose parameters.
Pose Stiffness
Pose Damping
Pose Space
In an effort to simplify these attributes, you'll now find an alternative - experimental - set of attributes.
Translate Stiffness
Translate Damping
Rotate Stiffness
Rotate Damping
A Translate Stiffness = -1
means \"infinite\" or \"locked\". It's the equivalent of Translate Motion = Locked
.
Use the new option in the Assign
option box to enable these.
Any replaced mesh is now included in the exported .rag
file, enabling you to import meshes onto characters that are missing the originally replaced mesh.
This should help keep both scene files and rag files clean and self-contained!
To the programmers out there, the .rag
file now features this section.
\"ConvexMeshComponents\": {\n \"members\": {\n \"indices\": {\n \"type\": \"UintArray\",\n \"values\": [\n 0,\n 1,\n 2,\n ]\n },\n \"vertices\": {\n \"type\": \"PointArray\",\n \"values\": [\n 1.8463890552520752,\n -0.5881761908531189,\n -0.28559789061546326,\n ]\n }\n },\n \"type\": \"ConvexMeshComponents\"\n},\n
These are unique vertex positions of one or more meshes. Ragdoll separates them into individual convex hulls by looking towards their connectivity, as per the indices
array.
As a side-effect, you are now also able to delete the mesh you used with Replace Mesh
. Keeping your scene a little more clean.
The automated convex hull mechanic has been updated and is now both faster and easier to work with.
Before
After
Furthermore, you now have the option of baking the automatically computed convex hull so as to avoid recomputing it each time you open the Maya scene file.
For example, here we've got a decomposited human mesh.
And here you can see how we get to keep the collider, but lose both the connection and the automatic decomposition. File-open times are now optimised, as well as file size. As we only store the bare essential vertices for the convex hulls!
"},{"location":"releases/2022.07.20/#convert-to-mesh","title":"Convert to Mesh","text":"You can now convert any Marker geometry - including convex hulls - into Maya geometry!
"},{"location":"releases/2022.07.20/#attach-constraint","title":"Attach Constraint","text":"The Pin Constraint has been expanded and can now pin one marker to another.
Under the hood
This is exactly the same as calling Reparent
to parent one marker to another. Except a marker can be attached to many other markers, and their relationship can be animated!
Here's how it works.
Let's take a closer look.
Here we've got two independent markers. No parent and child relationship. Now let's attach the box to the torus.
As you'd expect, the box is now a child of the torus. You can use the handle to reposition exactly where this box is attached onto the torus.
The position and orientation can be animated too. It's a rather complex little constraint, but very powerful!
"},{"location":"releases/2022.07.20/#quality-of-life","title":"Quality of Life","text":"Next up, let's have a look at some of the minor improvements made to put a smile on your face.
"},{"location":"releases/2022.07.20/#closed-loop-recording","title":"Closed Loop Recording","text":"If you parent the tip to the root, you'll get a closed loop. Something Maya natively cannot do, but Ragdoll can. And for good reason, since you can do things like this!
However, it wasn't able to record it. Until now. :)
Why make this an option?
Yes, if it's able to do more than why not just leave this as default and remove the option?
Well, as it happens, there are times when closed loop recording performs worse than regular recording. Keep an eye out for what happens between frames, your rotation channels might be under stress, and let us know in the forums how it got that way. It's something I'd like to sort out.
You can now control individual axes of a pin constraint, just like you can with Pose Space = World
on normal markers.
For example, here's what happens if we pin it along X and Z, but ignore the Y axis.
Likewise, here we only pin the Z axis. Notice how it's only allowed to move along the Z plane, staying at wherever the pin is in Z.
And similarly for X.
The rotation works the same, except Twist represents the X axis and Swing is both Y and Z.
"},{"location":"releases/2022.07.20/#predictable-enabled-state","title":"Predictable Enabled State","text":"Every Ragdoll node has an Enabled
attribute for you to temporarily and non-destructively enable and disable the node without physically removing it from the scene. It acts indentically to physically deleting that node, but is safe to do even on a referenced node.
However, in the previous release you could find yourself..
Enabled = Off
Enabled = On
Only to then not actually having it enabled. What's up with that? When you..
Enabled = On
a second timeIt works. That isn't particularly intuitive, and has now been fixed!
"},{"location":"releases/2022.07.20/#infinite-terrain","title":"Infinite Terrain","text":"If you provide Locomotion with a terrain, it will generate a heightmap from it. Where there wasn't geometry, such as outside the borders of the geometry or inside of holes, it would struggle to figure out what to do.
This release now extends your terrain in every direction, such that you get more what you'd expect.
Notice how he's able to start outside of the terrain, and step on missing parts of the terrain!
"},{"location":"releases/2022.07.20/#simplified-density","title":"Simplified Density","text":"Fewer options for working with density, now it's just a single number.
As it turns out, the presets were really limiting and was rarely a good fit for anything. And they didn't make intuitive sense either. \"Uranium\"? I don't know how heavy that is, when should I use it?
So instead, a single Density
value with a default value of 1
remains. This is the previous Density Custom
attribute with a shorter name, so if you were already using this attribute then you already know what to expect.
With a special density of 0
you'll be greeted by the Mass
attribute to disable automatically computing mass from the size and volume of your shape.
You can now choose to work with Stiffness
values without worrying about the weight of markers.
This can help get a better understanding of what a value of 1 means, as it would no longer depend on the mass of a marker, which is automatically computed per default. The marker would retain its mass, such that if a heavy marker fell on a light marker it would still act accordingly. But the stiffness values would act as though they weighed the same.
Should this be enabled per default? What are the consequences of this option? Let's find out!
"},{"location":"releases/2022.07.20/#frameskip-default","title":"Frameskip Default","text":"When a frame is skipped, Ragdoll would normally pause simulation and wait for you to return to the last successfully simulated frame. This ensures that the simulation always produces the same result each time you play. But also means it is unable to solve if Maya skips a frame, as can happen when a rig is especially heavy or when playing back with Audio.
This mode is called Pause
and the alternative is a mode called Ignore
which will continue solving even though it isn't given each and every frame.
Ignore
is now the new default, to avoid surprises especially for beginners who might not know why simulation suddenly stops for no apparent reason. You are still advised to stick with Pause
especially towards the end of fine-tuning your work. That's the only mode in which Ragdoll can guarantee that each and every playthrough is identical unless you have actually changed something in your animation.
The two lines towards the bottom tell you two things.
Ideally, for the most accurate and consistent results, these two should be identical. And when they are, they are hidden. They can be explicitly enabled via the Solver Display settings, called Draw Buffer
.
In addition to the Convert to Mesh
menu option, advanced users can now also experiment with the new rMarker.outputGeometry
attribute which provides access to the computed convex hull!
This is a live attribute, regenerating the mesh whenever anything affects the convex hull generated for collisions.
"},{"location":"releases/2022.07.20/#cache-hud","title":"Cache HUD","text":"You'll now find buttons in the viewport for manipulating the solver cache.
"},{"location":"releases/2022.07.20/#record-stuck-at-0","title":"Record Stuck at 0%","text":"Some users experienced recording getting stuck before it even began.
This should solve that!
Behind the scenes
For you programmers and riggers out there; as it turns out, calling OpenMayaAnim.MAnimControl.setCurrentTime
is not safe. When Maya wants to compute one or more things in parallel, this call could cause a deadlock. The simple solution, and the one employed here, was to instead use cmds.currentTime
. It was the strangest thing.
The alternative solution was to use Serial or DG evaluation modes.
"},{"location":"releases/2022.07.20/#import-solver-attributes","title":"Import Solver Attributes","text":"A bug was found whereby the attributes from your solver would get exported properly, but not imported! This has now been fixed.
"},{"location":"releases/2022.07.20/#use-selection-for-record","title":"Use Selection for Record","text":"The previous release broke the Use Selection
option for Record Simulation
and Snap to Simulation
commands. This has now been fixed!
A bug was found (thanks Andrei!) whereby having fields on your scene could cause a crash. This was related to the field trying to also affect the \"world\" rather than just the markers. This has now been fixed.
"},{"location":"releases/2022.07.20/#solver-bounding-box","title":"Solver Bounding Box","text":"Minor nitpick, if you had 2 or more solvers, unselected, and tried to \"Fit all\" (the F or A-key), it may not have actually fit all of the solvers. This has now been fixed.
The problem was that each solver was taking every marker into account, even those that did not belong to it.
"},{"location":"releases/2022.07.20/#locomotion-on-linux","title":"Locomotion On Linux","text":"We spent a lot of effort getting Locomotion running on Linux, only to trip over our own feet for release and include a spelling error in the Maya .mod
file causing Ragdoll to not find the Locomotion executable!
This has now been fixed, Linux users unite!
"},{"location":"releases/2022.07.20/#viewport-refresh","title":"Viewport Refresh","text":"Disabling and enabling a marker could sometimes leave it behind in the viewport, until the solver was hidden and unhidden, or the scene reloaded.
This has now been fixed.
"},{"location":"releases/2022.07.20/#locomotion-crash","title":"Locomotion Crash","text":"Ragdoll could sometimes bring Maya down when opening a scene containing a plan, for locomotion. This happened due to some really intricate memory and threading issues that you would not be interested in knowing more about. Rest assured, this has now been fixed!
"},{"location":"releases/2022.11.29/","title":"Live Mode","text":"Highlight for this release is Live Mode!
As is tradition, let's have a look at some of the things people have been up to with Ragdoll since the last release.
Ragdoll 3 Trailer
A 2 minute summary of what you'll find in this document!
Pavel Orsher
Some excellent mechanical work by Pavel on the forums.
Live Wyvern
Made with the beta version of Live Mode by @emi on the forums.
Live Dance
Animated with Live Mode, and re-simulated for balance!
Catfish
Made with a beta version of Live Mode by @riccardo_p on the forums.
Halloween
This happened.
Ho Ho Ho
A little early, or is it?
Live Mode Workflow
One example of how to use the new Live Mode from this release.
Interactive Wyvern
Animated in Interactive Mode, with caching enabled.
"},{"location":"releases/2022.11.29/#ragdoll-30","title":"Ragdoll 3.0","text":"That's right, this is a big one!
Last major release was the introduction of Markers back in January of this year. A major overhaul to both performance and usability of Ragdoll. This release is no different, with the introduction of Live Mode.
This is the direction we have in mind for Ragdoll and, dare I say, for character animation at large. We believe now is the perfect time to leverage much of the untapped technology from the past few decades and throw out much of what we know about animation - starting with how characters are posed.
"},{"location":"releases/2022.11.29/#ragdoll-freelancer","title":"Ragdoll Freelancer","text":"A new limited edition pricing tier for the individual out there wanting to take Ragdoll to work.
Details
Who is this for?
It's exclusively for individuals who work on a project-basis and wants to take their Ragdoll licence with them as they move between studios. It
Is this you? Click here to get yours today!
Buy "},{"location":"releases/2022.11.29/#live-mode","title":"Live Mode","text":"Here's \"Live Mode\" in a nutshell.
Traditional Rig
And here's the equivalent task with the traditional rig.
If you don't make it through all of the 95 seconds that the traditional method takes, I don't blame you. Not only is posing with Live Mode already 3x faster, it also has the following benefits.
But perhaps most importantly.
This same workflow applies to plain joint hierarchies, meaning an animator could:
For example, here's 30 seconds of \"rigging\" a character from scratch.
And that's where things are going.
Let's have a closer look at what this thing can do today.
"},{"location":"releases/2022.11.29/#general-posing","title":"General Posing","text":"Clicking and dragging on any marker will affect it the way you'd expect.
"},{"location":"releases/2022.11.29/#reset","title":"Reset","text":"Exiting out of the mode or changing from the Manipulator to e.g. the Maya Translate tool (W hotkey) will reset the simulation to where it originally started.
"},{"location":"releases/2022.11.29/#drop-press-hold","title":"Drop Press & Hold","text":"Towards the bottom, you'll find a number buttons, one of which is called Drop
. This \"drops\" the character. In other words, it temporarily enables gravity. This can help ease a character onto the ground or generally relax things that are hovering. It's also fun to play with.
Hold Shift to toggle gravity on, such that you can throw things around! Also fun to play with
"},{"location":"releases/2022.11.29/#tense-press-hold","title":"Tense Press & Hold","text":"Next up is Tense
. This tenses the character.
What's really happening is that it tries to reach whatever pose your rig is in at that time.
"},{"location":"releases/2022.11.29/#tense-toggle","title":"Tense Toggle","text":"Like Drop
, the Tense
button can be toggled, which would leave the character tense.
Hold Ctrl whilst clicking to \"mask\" a Marker. This prevents it from moving at all, it's technically turning the Marker into a Kinematic object temporarily.
Pro tip
You can also press Ctrl whilst dragging and release to leave the Marker you are currently dragging in place, for some cool posing mechanic!
"},{"location":"releases/2022.11.29/#unmask-all","title":"Unmask All","text":"Next up is \"unmask\" which involves \"masking\" via Ctrl + Clicking on a Marker. It's how you prevent a Marker from moving.
How does it work?
It temporarily turns any marker Kinematic
, identical to the Behaviour = Kinematic
attribute.
Hold Shift whilst dragging to isolate the effect to a marker and it's children.
"},{"location":"releases/2022.11.29/#transfer-pose","title":"Transfer Pose","text":"The final button is the Transfer
button. It's what transfers the simulation back onto your animation controls.
Like Drop and Tense, this button can also be toggled, meaning the pose is transferred as soon as you let go of the mouse cursor.
"},{"location":"releases/2022.11.29/#animation","title":"Animation","text":"And these are the tools you use to animate.
"},{"location":"releases/2022.11.29/#visual-undo","title":"Visual Undo","text":"The timeline helps you understand where undo will take you.
You can also interact with the timeline, for fine control over where in history you want to go.
"},{"location":"releases/2022.11.29/#recording-live-mode","title":"Recording Live Mode","text":"Use Live Mode with Cache = Static
to enable recording of your interactions!
Toggle the Lock button far-right to keep simulating outside of the Manipulator.
This enables you to use Ragdoll as a normal Maya deformer, and see real-time updates on contacts and limb limits.
Here are some more examples!
"},{"location":"releases/2022.11.29/#rigging-for-live-mode","title":"Rigging for Live Mode","text":"In order for your characters to work with Live Mode, you'll need to take a few things into consideration. Primarily that your character has FK controls with the ability to disable space switches and other mechanics that differ from a straightforward parent/child relationship.
A quick tutorial on how to setup a character using Maya's multi-cut, and then export and load this character to assemble it alongside our favourite Manikin!
Here's an example of how you can \"trick\" Live Mode into working for you with any traditional Maya rig.
The viewport rendering pipeline has seen an overhaul - replacing much of Maya's own API for our own based on OpenGL 4 and DirectX 11.
The result is a much nicer presentation of Markers, especially those with a Mesh.
But that's not all.
It also resulted in a 4x performance improvement to rendering, which means that playback performance is now 2x faster!
"},{"location":"releases/2022.11.29/#selection-outline","title":"Selection Outline","text":"Selection and anything \"wireframe\" in general has been significantly improved.
Before
After
"},{"location":"releases/2022.11.29/#group-selection","title":"Group Selection","text":"This has also seen a major face lift since the last release, resulting in a much more clear idea of what's included in a given group. Rather than the lasso from the prior release, which was great! But, it wasn't able to clearly visualise markers inbetween many other markers, since the lasso would encapsulate those too!
Before
After
Old Rendering
If you prefer, you can still enable the old group drawing. It's merely disabled in the Solver Display section of the Attribute Editor.
"},{"location":"releases/2022.11.29/#2x-performance","title":"2x Performance","text":"Here's a simple performance test to give you some idea!
Before
After
Here's one with only rendering and no simulation, meaning that navigating the viewport is even faster than the overall performance improvements.
Before
After
OpenGL vs DirectX
OpenGL is the quickest, use it if you can. DirectX clocks in at 120 fps, versus 200 fps for OpenGL. That's almost half the speed if you desperately need DirectX! But, still faster than the previous version.
"},{"location":"releases/2022.11.29/#parallelism","title":"Parallelism","text":"Here's what you can expect from parallelism with multiple solvers in this release.
1 Solver
25 solvers
We'd expect a 25x speedup here, but are only getting on the order of 3-4x. Useful, but room to grow!
"},{"location":"releases/2022.11.29/#load-physics","title":"Load Physics","text":"You can now open a .rag
file without anything already existing in your scene.
Before, you could export the layer of physics wrapping around your character rig, and later re-apply this layer via the Import Physics
menu item. With this release, you can throw away your character rigs and import and use the physics layer independently!
Asset Library Backend
This is the functionality the new Asset Library builds upon!
"},{"location":"releases/2022.11.29/#asset-library","title":"Asset Library","text":"You've now got a number of assets at your fingertips, ready for import.
"},{"location":"releases/2022.11.29/#version-history","title":"Version History","text":"Spot which version you are on, and read more about past versions to see how Ragdoll has evolved over time.
Clicking on a version will take you to the web page for it, assuming you've got internet access. Otherwise, you can copy the resulting address into somewhere you do.
"},{"location":"releases/2022.11.29/#licence-information","title":"Licence Information","text":"The Asset Library is where you'll now also find information about your licence.
"},{"location":"releases/2022.11.29/#multiple-loads","title":"Multiple Loads","text":"Load one or load many, they'll all interact with each other and can be manipulated with Live Mode too!
"},{"location":"releases/2022.11.29/#assets","title":"Assets","text":"Along with the new library, and your ability to add your own assets, we've got some default ones for you to play with!
"},{"location":"releases/2022.11.29/#alien","title":"Alien","text":"Let's have a look at what assets you've got to play with in this release, first up is the \"Alien\".
"},{"location":"releases/2022.11.29/#dog","title":"Dog","text":"A friendly dog, ready for posing.
"},{"location":"releases/2022.11.29/#manikin","title":"Manikin","text":"The classic Ragdoll Manikin character as a ragfile.
"},{"location":"releases/2022.11.29/#spaceman","title":"Spaceman","text":"A zero-gravity astronaut, waiting to be tossed around in space!
"},{"location":"releases/2022.11.29/#pirate","title":"Pirate","text":"Argghhhhh! This one's got fingers and a face.
"},{"location":"releases/2022.11.29/#rhino","title":"Rhino","text":"A quadruped as well, with fatty bits for some nice secondary motion.
"},{"location":"releases/2022.11.29/#wasp","title":"Wasp","text":"The wasp from the tutorial section!
"},{"location":"releases/2022.11.29/#cowboy","title":"Cowboy","text":"A plastic doll with gun and hat!
"},{"location":"releases/2022.11.29/#dragon","title":"Dragon","text":"A deconstructed version of Antoine Verney-Carron's wyvern, used in one of our early Live Streams.
"},{"location":"releases/2022.11.29/#batty","title":"Batty","text":"What do you get if you combine a bat with a frog?
"},{"location":"releases/2022.11.29/#shark","title":"Shark","text":"It's the Rag Shark!
"},{"location":"releases/2022.11.29/#dude","title":"Dude","text":"If Rag Shark had a friend, it'd be the Dude!
"},{"location":"releases/2022.11.29/#lion","title":"Lion","text":"A generic lion, in bad need of limits. Can you help him?
"},{"location":"releases/2022.11.29/#beta-videos","title":"Beta Videos","text":"A series of videos made during the beta, some of which are out of date but still potentially useful!
We've making a change to how you animate with the \"stiffness\" attributes.
Primarily, we're removing the Pose Space
attribute. If you hadn't yet used it, good on you. It was far too complicated of an attribute to make sense of.
If you have been using it, you'll be pleased to know that the behaviour is now entirely consolidated into the Pin Constraint which performs exactly the same behaviour except without the mental overhead of figuring out what a \"Custom\" space actually is.
Before
After
"},{"location":"releases/2022.11.29/#backwards-compatibility","title":"Backwards Compatibility","text":"The previous Pose Stiffness
attributes are still available for the time being.
To use it, untick the Use Translate/Rotate Stiffness
in the Assign
menu options.
Like removing a pebble from your shoe, the api.replaceMesh()
command now automatically changes your rMarker.shapeType
attribute to Mesh
. A small but helpful change!
Prior to this release, whenever you Export Physics
you'd get absolutely everything that Ragdoll knows about. Every Marker, every group and every solver too.
With this release, you can cherry-pick the things you want included in your export, via the new Export
attribute, found on all Ragdoll nodes. On
by default, if Off
then it will be invisible to the export process.
You'd use it when you have things in your scene you know aren't interesting to export. The Ground Plane for example is Off
per default, since it's unlikely you'd want that included in a new scene.
Two components has seen an update with new members and deprecated members.
These won't affect external use of .rag
files in e.g. game engines, and shouldn't have effect anywhere really. They are used as a means of passing Maya-specific values in and out of the .rag
file for import and export.
\"MarkerUIComponent\": {\n \"driveStiffness\": \"is now -> angularStiffness\",\n \"driveDampingRatio\": \"is now -> angularDampingRatio\",\n}\n\n\"GroupUIComponent\": {\n \"driveStiffness\": \"is now -> angularStiffness\",\n \"driveDampingRatio\": \"is now -> angularDampingRatio\",\n}\n
The prior members remain, but should not be used.
"},{"location":"releases/2022.11.29/#import-attach-constraint","title":"Import Attach Constraint","text":"You can now export and import the Attach Constraint!
"},{"location":"releases/2022.11.29/#scale-attach-constraint","title":"Scale Attach Constraint","text":"You can now scale characters that use the Attach Constraint.
"},{"location":"releases/2022.11.29/#scale-distance-constraints","title":"Scale Distance Constraints","text":"The minimum and maximum values of the Distance Constraint is now scaled alongside your character, just as you'd expect!
Pro tip
Notice how as the character grows in size, the effect of the Distance Constraint diminishes. That's because with greater size comes greater mass. You can control this via Density = 0
which allows you to give a character a fixed mass regardless of size, which you may or may not want!
A tiny little typo slipped in with the prior release, 2022.07.20, which led to you being unable to import anything with replaced meshes. \ud83d\ude2d This has now been fixed! \ud83e\udd73
ri.import_physics()\n// ragdoll._create_solvers() - Creating solver(s)..\n// ragdoll._create_groups() - Creating group(s)..\n// ragdoll._create_markers() - Creating marker(s)..\n// Warning: ragdoll._import_physics_wrapper() - Traceback (most recent call last):\n// File \"C:\\Users\\marcus\\Documents\\maya\\modules\\Ragdoll-2022_07_20\\scripts\\ragdoll\\interactive.py\", line 3604, in _import_physics_wrapper\n// _singleton_import_loader.reinterpret()\n// File \"C:\\Users\\marcus\\Documents\\maya\\modules\\Ragdoll-2022_07_20\\scripts\\ragdoll\\internal.py\", line 441, in _undo_chunk\n// return func(*args, **kwargs)\n// File \"C:\\Users\\marcus\\Documents\\maya\\modules\\Ragdoll-2022_07_20\\scripts\\ragdoll\\dump.py\", line 450, in reinterpret\n// rdmarkers = self._create_markers(rdgroups, rdsolvers)\n// File \"C:\\Users\\marcus\\Documents\\maya\\modules\\Ragdoll-2022_07_20\\scripts\\ragdoll\\dump.py\", line 665, in _create_markers\n// self._apply_marker(mod, entity, rdmarker)\n// File \"C:\\Users\\marcus\\Documents\\maya\\modules\\Ragdoll-2022_07_20\\scripts\\ragdoll\\dump.py\", line 1272, in _apply_marker\n// mobj = meshes_to_mobj(Meshes)\n// File \"C:\\Users\\marcus\\Documents\\maya\\modules\\Ragdoll-2022_07_20\\scripts\\ragdoll\\dump.py\", line 1299, in meshes_to_mobj\n// for index in range(len(polygon_connects) / 3):\n// TypeError: 'float' object cannot be interpreted as an integer\n// Warning: ragdoll._import_physics_wrapper() - An unexpected error occurred, see Script Editor\n
"},{"location":"releases/2022.11.29/#known-issue-render-gliches-from-the-inside","title":"Known Issue - Render Gliches from the Inside","text":"Moving the camera inside of a marker with an outline can look a little freaky!
"},{"location":"releases/2022.11.29/#minor-releases","title":"Minor Releases","text":"Following this release, here are some minor changes made.
2022.12.01
Revert incomplete Locomotion 2.0, coming up in the next larger release.
2022.12.05
Repair broken Educational licences, they were acting like trial/non-commercial licences.
2022.12.13
Keep fields with 0 magnitude from affecting anything.
"},{"location":"releases/2023.04.01/","title":"Locomotion 2.0","text":"Highlight for this release is Locomotion 2.0
As is tradition, let's start off with some of the cool Ragdoll material surfacing across the interwebs since the last release.
Mechanical Spider
\"Mechanical Spider\" by vertexmonster
60s Marionettes
Some excellent use of Ragdoll here by Ernst-Jan on the forums
Human Ball
Zombies + Radial field = This, by Jason
Oh Deer
Another one by Jason from last Christmas.
Fast Food
Jason has been on fire lately, here's another knockout!
A Whale of a Time
Jason jason jason.
"},{"location":"releases/2023.04.01/#locomotion-20","title":"Locomotion 2.0","text":"First released in June 2022, this automated method of generating complete character locomotion has seen a major update!
With a new and much more intuitive workflow, ability to locomote along a path, with feet snapping to terrain and interactive updates as the solver works, you'll be able to achieve much greater results with far less headaches.
"},{"location":"releases/2023.04.01/#new-workflow","title":"New Workflow","text":"Locomotion Markers.
Borrowing from Markers, Locomotion no longer occupies your animation channels directly. Instead, a preview is shown for you to evaluate and later record.
"},{"location":"releases/2023.04.01/#iterative-updates","title":"Iterative Updates","text":"More insight into while you wait.
Locomotion will now show you each result it comes up with, as it searches for one that both looks great and fulfils each of your requirement; targets, limits, mass and gravity.
"},{"location":"releases/2023.04.01/#new-manipulators","title":"New Manipulators","text":"Editing targets and limits was a huge chore with Locomotion 1.0. This new release makes authoring plans much less error prone and more fun.
"},{"location":"releases/2023.04.01/#translate","title":"Translate","text":"Drag the gizmo to translate a target. Notice how it is no longer possible to author invalid targets that hover above the ground, a significant burden to anyone trying to achieve nice results has been lifted!
"},{"location":"releases/2023.04.01/#rotate","title":"Rotate","text":"Hold Ctrl (on Windows and Linux, Cmd on Mac) to rotate a target.
"},{"location":"releases/2023.04.01/#height","title":"Height","text":"Hold Shift to adjust the height of the body. Feet must always touch the ground.
"},{"location":"releases/2023.04.01/#terrain-snapping","title":"Terrain Snapping","text":"Aligning feet to the ground in the case of having a terrain was even more daunting; but no longer! Now feet automatically snap to any terrain.
"},{"location":"releases/2023.04.01/#multi-target","title":"Multi-target","text":"Go there, then here. Do a twirl, and then go over there!
In Locomotion 1.0, you were able to specify a start and end position for your character. But now, you can specify any number of points inbetween, effectively a path!
"},{"location":"releases/2023.04.01/#timing","title":"Timing","text":"Start fast, then walk slowly. Then finish fast!
With more than 1 target, you also need to decide at when you intend on a target being reached. Click and drag on the targets in the UI to adjust.
Shading
You'll notice that each target has two shades, a top and bottom.
Shade Meaning Top Distance, dark is less Bottom Timing, dark is less "},{"location":"releases/2023.04.01/#pin","title":"Pin","text":"Targets are guidelines to Locomotion. It'll try to follow them, but if some are physically impossible or there are conflicting goals then it will try and find a compromise. Sometimes, you need the target to be more respected, and that's when you can \"pin\" a target.
"},{"location":"releases/2023.04.01/#multi-plan","title":"Multi-plan","text":"Create complex locomotion by stringing together two or more plans.
Complete the illusion by blending them all together with traditional Marker physics.
Here's how it works.
The command will start the second plan where the first plan ends, creating one continuous motion.
"},{"location":"releases/2023.04.01/#animation-to-plan","title":"Animation to Plan","text":"A \"make good\" button?
We've talked about generating an animation from a plan, but what about the reverse? What if we could use your animation as input to the plan, and output a refined version of it?
The Animation to Plan
menu item evaluates your animation and converts it into (1) targets and (2) stepsequence; the ingredients to a fully defined plan.
Plans now more accurately follows your terrain and enables you to visualise what Locomotion sees.
"},{"location":"releases/2023.04.01/#reset-starting-position","title":"Reset Starting Position","text":"If you change the starting position of your plan, or move the character after having assigned a plan, you can re-align the two with the Reset Starting Position command.
"},{"location":"releases/2023.04.01/#terrain-debugging","title":"Terrain Debugging","text":"If your terrain has two sides, Locomotion can struggle to snap its feet to the one you intend.
Here's a problematic result.
If we look at the feet snapping, we can see how they tend to snap towards the lower side of this terrain.
We can resolve this by removing the lower side altogether.
And presto, all good!
"},{"location":"releases/2023.04.01/#new-tutorials","title":"New Tutorials","text":"Mohamed Elbebawy has produced a new series of tutorials for Ragdoll, available here.
Released just a few days ago, Ragdoll is fully onboard.
On the other hand, Maya 2018 has left the chat and is no longer supported by Ragdoll (or Autodesk, for that matter!)
"},{"location":"releases/2023.04.01/#account-management","title":"Account Management","text":"You can now monitor and manage your account with us, starting with performing remote deactivation of your node-locked licences.
Features
Checked items are ready for you, unchecked are coming soon!
For the time being, please contact us for login details.
"},{"location":"releases/2023.04.01/#blend-simulation","title":"Blend Simulation","text":"There are now 2 ways in which to blend between simulation and animation; before or after.
"},{"location":"releases/2023.04.01/#before","title":"Before","text":"There is now an option to blend between animation and simulation before recording!
Here are some more examples.
This will also work alongside Translate Motion = Soft
.
Ragdoll typically records your simulation onto a layer, and this layer has a Weight
attribute that you can animate to blend between simulation and animation.
But, most of the time, it isn't doing what you'd expect.
A new option has been added to the Record Simulation option dialog to solve this.
Here you can see the effect in action.
"},{"location":"releases/2023.04.01/#stepped-simulation","title":"Stepped Simulation","text":"Japanese anime, and 2D animation in general, is normally animated on 2's, 3's and sometimes 4's and sometimes at arbitrary times altogether.
Previously, Ragdoll was only ever able to produce 1 frame per Maya frame, meaning the animator would retroactively need to reduce the keys to only happen when animation happens. No longer!
"},{"location":"releases/2023.04.01/#smooth-input-stepped-output","title":"Smooth input, Stepped output","text":"In the simplest case, Ragdoll can be instructed to output simulation ever other or every third frame, or every fourth. Creating a 2D or stopmotion kind of look.
"},{"location":"releases/2023.04.01/#stepped-input-stepped-output","title":"Stepped input, Stepped output","text":"In the more complex case, consider this animation.
Notice how there are pauses between frames, and that keyframes are not distributed evenly. Some have a 2 frame pause, some a 5 frame pause. Here's what would happen if you were to try and simulate this.
Notice how the torso and especially the tail gets jerked around. Because during each pause, Ragdoll goes ahead and simulates it as though the character came to a complete halt. And then kicks off again when it moves, at a very high velocity.
You can now match simulation to when animation occurs, via the new Warp Time
menu item.
Now simulation only happens when the character actually moves. You can control the frequency and time delta of each frame by tuning the resulting animation curve.
Restore Time
Use Restore Time
to get back to a non-stepped simulation.
Time is controlled via a normal animation curve, and there's no reason it cannot also go backwards.
Let your creativity out!
"},{"location":"releases/2023.04.01/#time-method","title":"Time Method","text":"Normally, during playback Maya will transition from one frame to the next. For example, from frame 1 to 2. But sometimes, when a rig is too heavy, Maya may skip a frame or two. For example from 1 to 3, without first visiting frame 2.
To Maya, the different in time between frame 1 and 2 is about 1/24 seconds, with a playback rate of 24 fps; that is, about 41 milliseconds. The difference between frames 1 and 3 is 83 milliseconds.
To Ragdoll, the difference is always 41 milliseconds. No matter the difference in Maya. Why does that matter? Well, consider this.
At frame 17, the character hits the ground. But what if we go to frame 17 immediately, and skip a few more frames?
Now the character hits the ground at frame 78! To Maya, 78 frames has passed; about 3 seconds. But to Ragdoll, barely a second has passed.
With the new Time Method
attribute, you can now choose to handle this in a realistic way instead.
You can now more easily manage which Markers collide, and which does not!
Create New Collision Group
Assign to two or more Markers to create a new collision group.
Add to Existing Collision Group
Select a collision group along with one or more Markers to add.
Remove from Existing Collision Group
Similarly remove Markers.
Multiple Collision Groups
Select multiple groups to visualise them together. They will each occupy a (customisable) color.
Merge Collision Groups
Assign to two or more groups to combine them.
"},{"location":"releases/2023.04.01/#trajectories","title":"Trajectories","text":"You can now visualise the trajectories of your Markers via the Solver Display attribute.
"},{"location":"releases/2023.04.01/#mass-independent-fields","title":"Mass Independent Fields","text":"Fields were introduced in Ragdoll 2022.02.14 to help apply environment effects such as wind and turbulence to your animations.
Forces are applied as they would in real life... which isn't always practical!
Consider this.
Here, as the character grows in size, so does its mass. As the mass increases, the effect of the turbulence force diminishes. Since the same force is applied to a now much-heavier object. Like if you pushed on a woodden door and then tried pushing a car; your muscles remain as strong, but the object is now much heavier.
With this release, forces are instead applied evenly regardless of mass, which should result is more control and predictability of your simulation.
You can revert to the old (realistic) behaviour by changing Force Mode
from Velocity Change
to Force
in the rSolver
node.
Ragdoll supports 4 geometry types for collisions.
Assign to a control, and then use Replace Mesh
alongside any geometry to use this geometry for collision detection.
However!
Sometimes collisions are more complex and require multiple meshes to make up 1 physical collision shape. You can now achieve this with ease.
You can now select any number of meshes and use the combination of them as a collision shape.
"},{"location":"releases/2023.04.01/#pin-constraint-pivot","title":"Pin Constraint Pivot","text":"You can now control where on a Marker to Pin Constrain it.
Hold D
to edit the position of the rotate pivot
Like the Pin Constraint, Attach Constraints can have their pivots edited too. Especially useful if you are looking to attach two Markers at a specific location.
"},{"location":"releases/2023.04.01/#quality-of-life","title":"Quality of Life","text":"Last but not least, a few minor things to make your life easier.
"},{"location":"releases/2023.04.01/#new-behaviour-names","title":"New Behaviour Names","text":"The options for a Marker's Behaviour
attribute has been updated for more clarity.
Inherit
-> Use Group
Kinematic
-> Animated
Dynamic
-> Simulated
The name \"kinematic\" is the technical term for when something is animated, so we figured we may as well call it what it is! A Marker set to Animated
is entirely animated, with no simulation applied. It may affect other Simulated
Markers, but cannot be affected by them.
Some things in Ragdoll can be animated, others cannot. Those that cannot can also not be changed on any frame other than the start frame.
This used to be a chore, and is no longer! Ragdoll will now automatically return to the start frame when it needs to, leaving you with less to worry about.
"},{"location":"releases/2023.04.01/#symmetry-and-undo","title":"Symmetry and Undo","text":"You can now undo both sides at once, as you'd expect!
"},{"location":"releases/2023.04.01/#z-up-assets","title":"Z-up Assets","text":"You can now export assets from a Y-up Maya scene, and load it into a Z-up Maya scene! This means our default assets, which were made in a Y-up environment, will now load perfectly fine in your Z-up scenes.
Before
After
"},{"location":"releases/2023.04.01/#linked-solver-crash","title":"Linked Solver Crash","text":"Many linked solvers could potentially crash Maya, no longer!
"},{"location":"releases/2023.04.01/#deprecating-max-mass-ratio","title":"Deprecating Max Mass Ratio","text":"Ragdoll likes when the masses of objects that interact are somewhat similar. A 60kg character sitting on a 100kg horse is \ud83d\udc4c. But a million ton planet falling onto a 60g ant is less than OK.
To combat this, an attribute was introduced a while back called Max Mass Ratio
whose job it was to even out the differences (\"ratio\") between masses. But it didn't work that great, the simulation was no happier because of it.
So in this release, we are deprecating this attribute. It will still exist in your scene, and can be found at the very bottom of the Solver node in the Attribute Editor. If you find yourself needing it, let us know. If not, you have one less thing to worry about.
"},{"location":"releases/2023.04.01/#restore-t-key","title":"Restore T Key","text":"There's an option to restore the functionality of the T key, and to change it to something else.
"},{"location":"releases/2023.04.01/#one-off-bug","title":"One-off bug","text":"Ragdoll was reading values from Maya that were 1 frame too old.
Before
I'm stepping through the simulation, notice how the pelvis is set to Animated
(Kinematic) but how it doesn't actually have an effect until the next frame?
After
This has now been fixed.
"},{"location":"releases/2023.04.01/#solver-update","title":"Solver Update","text":"The underlying maths behind your physics has been modernised to resolve subtle issues but primarily lay the foundation for new things to come. You shouldn't notice much of any difference, apart from subtle things like this.
For the Python folk out there, these members were added to the Python API.
from ragdoll import api\n\n# Create a new group\ngroup = api.assign_collision_group(markers)\n\n# Add some more markers\napi.add_to_collision_group(other_markers, group)\n\n# Remove some markers\napi.remove_from_collision_group(markers, group)\n
"},{"location":"releases/2023.10.03/","title":"Beyond Ragdoll","text":"Highlight for this release is.. lots of releases!
And we're back! This release is going to be a little different. Over the past few months, we've expanded upon Ragdoll's reach. It used to be written as a Maya-only plug-in, but is now written as a software development toolkit, an SDK, and re-integrated into Maya. This means that we can reuse the Ragdoll \"core\" in other software, such as Blender. It also means we can use it without Maya, and without Blender. As its own independent application! It also means developers out there can incorporate Ragdoll into their own software, as a dedicated ragdoll-simulation solution.
To summarise, \"Ragdoll\" is now:
Product Description Ragdoll Maya Autodesk Maya integration, the one you know! Ragdoll Blender New integration for Blender Ragdoll Standalone Ragdoll without strings Ragdoll Web Ragdoll in your browser and on your phone Ragdoll SDK Software Development Kit (SDK)So, lots of new potential!
"},{"location":"releases/2023.10.03/#releases","title":"Releases","text":"We'll be releasing each new product separately, so to kick things off starting with the new Maya release which boasts a lot of new fixes and improvements.
Read more
The next release will be Ragdoll for Blender, follow us on LinkedIn for live updates.
Highlight for this release is.. Blender!
After months of labour, we're pleased to announce Ragdoll for Blender is now generally available.
"},{"location":"releases/2024.02.29/#blender","title":"Blender","text":"Find a full breakdown of this new release here.
It's a little different from previous releases, in that it does not assume prior knowledge of Ragdoll since Blender is an entirely new audience for us.
"},{"location":"releases/2024.02.29/#open-source","title":"Open Source","text":"You'll now find much of the source code for Blender's Ragdoll on GitHub, to serve as a reference implementation for the forthcoming Ragdoll SDK that you/developers can use to incorporate Ragdoll into new DCCs and games.
Developers out there may recognise bpx
as the Blender equivalent to cmdx
we developed for Maya, to cope with the performance and maintainence burden of Ragdoll.
Contacts now include the direction and magnitude of the force being applied, helping you understand how strong (or weak) forces are at specific locations.
"},{"location":"releases/blender/2024.02.29/","title":"Ragdoll x Blender","text":"Today we are pleased to announce Ragdoll for Blender!
Ragdoll is a real-time physics solver for animators originally built for Autodesk Maya and now available to Blender!
Started development in 2021 by animator/programmer Marcus Ottosson, Ragdoll has since been adopted by just about every large visual effects company in the world and several AAA and indie games studios too.
If you've been to the theatres at any point in the past few years, it is highly likely you've witnessed Ragdoll-powered animations!
Now we're extending the reach of Ragdoll to those outside of the Maya domain, to you lovely bunch in the Blender camp. Our hope is that more animators will be able to benefit from Ragdoll, whilst also encouraging new animators to join the field with access to more tools to help simplify the animation process.
"},{"location":"releases/blender/2024.02.29/#showcase","title":"Showcase","text":"Here are some examples of Ragdoll in the wild.
Character animation is hard.
You've got the techincal barrier of understanding your computer and software, which on its own is hard, but then you've got the artistic choices involved in communicating your story. There are poses and there is timing - critical to any performance. But then you have momentum, contacts and a sense of weight.
Equally critical but boring.
Your audience has a keen eye for things like momentum and contacts, often without realising it. It feels either right or wrong. And it is incredibly hard - as an animator - to get it right.
This is where Ragdoll can help.
Animation is all about breathing life into inanimate objects, but also lifelessness. It's a spectrum, and Ragdoll can almost entirely handle a large part of this spectrum on its own.
0% Life 100% Life\n|--------------------------------------------------------------------|\n^ ^\n| |\n|=======================================|\n Ragdoll\n
In its most simple form, Ragdoll can entirely generate lifeless animation.
With keyframes for input, it can generate semi-lifeless animation.
"},{"location":"releases/blender/2024.02.29/#how-does-it-work","title":"How does it work?","text":"Ragdoll monitors your animation and provides you with a preview of what it would look like if you let physics take the wheel.
In this example, the blue character is your animation. It's the \"guide\" for the simulated version of your animation.
Here's what that might look like in practice.
Here's a more elaborate example, animation versus simulation towards the end.
Points of interest.
Ok, with that out of the way, let's get you going with Ragdoll!
We aim to get Ragdoll to users on all platforms, the one lagging behind is MacOS due to its recent transition to Metal for rendering into the viewport.
Blender Windows Linux macOS 3.4 \u2714\ufe0f \u2714\ufe0f \u274c 3.5 \u2714\ufe0f \u2714\ufe0f \u274c 3.6 \u2714\ufe0f \u2714\ufe0f \u274c 4.0 \u2714\ufe0f \u2714\ufe0f \u274cMacOS
Tim Apple made it difficult with their transition to Metal, and Blender followed suit with version 3.5. Ragdoll was originally built with OpenGL and DirectX support and it'll take a moment to re-do all of this work (again!) for Metal.
"},{"location":"releases/blender/2024.02.29/#quickstart","title":"Quickstart","text":"In the Ragdoll menu, load some asset and fool around.
You can also enter into the \"Manipulator\" to fool around even more.
Tense
Hold Shift to toggle the \"Tense\" icon, having the character try to reach its current Blender pose.
"},{"location":"releases/blender/2024.02.29/#first-steps","title":"First steps","text":"With our beak wet, let's have a look at how this actually works.
Step 1
Make a cube.
Step 2
Assign a \"Marker\"
Step 3
Record Simulation.
And that's it! You'll now find keyframes on your cube.
"},{"location":"releases/blender/2024.02.29/#second-steps","title":"Second Steps","text":"With your first steps out of the way, let's have a look at how this applies to a real-world scenario, to achieve this:
We'll use one of the Animation Fundamental rigs.
Step 1
Once you've loaded your character, you can start assigning to the controls you normally use to animate with.
Step 2
Next, we tune our shapes to better fit our character. This helps distribute mass and make things move more realistically, as though your character was an actual physical being.
In this case, we'll also use some of the meshes of the character directly, as opposed to simple capsules.
Step 3
If your character didn't already have animation, let's add some!
Step 4
Finally, we can record the simulation onto keyframes to witness the result.
"},{"location":"releases/blender/2024.02.29/#third-steps","title":"Third Steps","text":"Many new concepts in the above few steps, here's a full walkthrough of all steps.
If you are already familiar with Ragdoll from Maya, here's what's carried over versus missing so far.
Feature Status Notes Solver \u2714\ufe0f Marker \u2714\ufe0f Group \u2714\ufe0f Manipulator \u2714\ufe0f Live Mode \u2714\ufe0f Constraints \u2714\ufe0f Export Physics \u2714\ufe0f Load Physics \u2714\ufe0f Record Simulation \u2714\ufe0f Retargeting \u2714\ufe0f Licencing \u2714\ufe0f Collision Group \u274c But you can use Marker'sOverlap Group
instead Force Fields \u274c Coming Soon \u2122 Snap to Simulation \u2714\ufe0f Import Physics \u274c Export Physics \u2714\ufe0f Update Physics \u274c "},{"location":"releases/blender/2024.02.29/#performance","title":"Performance","text":"Ragdoll in Blender runs at 0.6x performance compared to Maya, which is far greater than we'd hoped considering that much of the addon is written in Python whereas the Maya plug-in is entirely written in a compiled language.
Compared to Blender's native physics, the comparison is more difficult because Ragdoll does more than Blender, primarily steering the simulation with your animation. What we do share however is a general simulation of loose objects with a high amount of substeps. In this regard, Ragdoll is both more stable (less explosions) and more accurate (automatically computed mass and center of mass).
In this scenario, ragdoll runs about 30% faster than native Blender physics.
That said, this scene features heavy interpenetrations of objects which require Split Impulse
to be enabled (Ragdoll does something similar). Without it, Blender struggles with intersections but runs much faster, on the order of 10x quicker than Ragdoll.
With this in mind, native physics is better suited for large scenes of loose objects, like building destruction and the like.
"},{"location":"releases/blender/2024.02.29/#open-source","title":"Open Source","text":"The Blender Addon is licenced under MIT, and so is bpx
; the library we developed specifically for Ragdoll. They can both be found on GitHub, here.
You're all set. We'll work towards more tutorials, including how to achieve this effect from Kojima's Death Stranding 2.
See also
Enjoy, and speak soon! :party:
"},{"location":"releases/blender/2024.03.07/","title":"Patch 1","text":"Minor patch release for Blender with common issues patched up and ready to go! :party:
Check out this awesome thread on the forums from user @Manikandan_Rajendran!
We've got a new tutorial, live and available on YouTube!
Ragdoll will now tell you when exceeding the 100 frame limit during trial, it'll also tell you when it expires which for those of you who started the trial on the 1st of March should happen around the 1st of April. Minor things that solve a lot confusion.
The binaries we shipped are now also \"code signed\", meaning Windows will be familiar with them and not warn about potential threats. This should have happened before but we've had a bit of an office move in the past week so things have been up in the air!
You'll also find instructions on how to activate your licence on the Download page for Blender.
Download links are in the usual places, right here:
Stay tuned for more, and please report any issues or feature requests on our forums, here:
Enjoy, and see you soon!
"},{"location":"releases/blender/2024.04.09/","title":"Patch 2","text":"Minor patch release for Blender with common issues patched up and ready to go! \ud83e\udd73
Let's start with some goodies!
"},{"location":"releases/blender/2024.04.09/#new-tutorials","title":"New Tutorials","text":"The above goodies are part of the new tutorials since last release!
You'll now find a more pleasant looking geometry for convex meshes.
"},{"location":"releases/blender/2024.04.09/#merge-solvers","title":"Merge Solvers","text":"You can now append one character into scene with an existing solver, and either continue to simulate each independently or merge their solvers to have them interact.
See Maya release notes for the same feature for more details.
You can now export your Ragdoll character and load it back in.
This can be helpful to debug complex characters, but it can also be used for inter-application export and load, like this one to Maya.
The file format will be compatible with the Standalone and Web versions of Ragdoll too, anything you export will work everywhere!
"},{"location":"releases/blender/2024.04.09/#record-quaternions","title":"Record Quaternions","text":"Ragdoll will now respect the choice of rotation interpolation, rather than setting them to Euler/XYZ upon recording.
"},{"location":"releases/blender/2024.04.09/#download","title":"Download","text":"As always, you can find the latest download on the Downloads page.
Note
This update involves both Ragdoll for Blender and Ragdoll Core, so be sure to get both up to 2024.04.09 for this to work.
"},{"location":"releases/core/2023.07.xx/","title":"Ragdoll Core","text":"No longer just a Maya plug-in. Today we are announcing Ragdoll Core, a Ragdoll software development kit (SDK) to enable third-parties to integrate Ragdoll into their own projects, from Games to DCCs.
We extracted all of what was unique about Ragdoll from Maya and turned it into its own project. Ragdoll Core is the enginer that powers Ragdoll, and now you can benefit from this engine too. If you develop your own software or game and are interested in utilising Ragdoll for your character animation needs, contact us!
Highlight for this release is Universal Transfer!
These release notes are the Maya-specific notes from the overall notes here.
For minor patch notes, e.g. 2023.10.06 see the announcement thread.
Let's start with the good stuff!
Jasons Spider
Jason's Monkey
Skeletons
Excellent work by Hirokazu-san!
Davy Jones
Enother excellent piece by Nithin_Piano on our forums.
Retro
Finished work by Erns-Jan on our forums.
Ragdoll will now happily simulate without requiring a licence.
This has 2 main implications.
Licences now only become relevant when getting simulation out of Ragdoll, primarily to record your simulation. This way, you can learn and experiment with simulation to your hearts content and only pay for a licence and seat when you are happy with the result. How great is that?
"},{"location":"releases/maya/2023.10.03/#universal-transfer","title":"Universal Transfer","text":"Live Mode now works with native Maya rigs!
Rig from https://agora.community/content/stormtrooper-may
Rig from https://www.cgspectrum.com/resources/tiger-animation-rig
IK too
Notice how all controllers, including IK, is transferred. This was not possible before!
"},{"location":"releases/maya/2023.10.03/#distraction-free-posing","title":"Distraction Free Posing","text":"Use Live Mode as a substitute for your normal animation controls, by SHIFT clicking on the transfer button. This overlays Ragdoll over your character and automatically transfers upon releasing the mouse cursor.
At this point, we can go distraction-free and hide all NURBS control to work entirely with Live Mode.
"},{"location":"releases/maya/2023.10.03/#background","title":"Background","text":"So, wasn't this the case already?
Live Mode was released with Ragdoll 2022.11.29 as a means of experimenting and gaining intuition of limits and contacts. With it came the ability to transfer the live poses back onto the Maya character. However, it only supported characters loaded natively with Ragdoll, or at best very simplistic native Maya rigs. Those that consisted of a plain FK hierarchy, such as a joint hierarchy.
At the time, it seemed this mechanic would not be possible with native Maya rigs, since Ragdoll relies on this hierarchy to figure out the final position and orientation of each body part. For example, to know where the hand is, Ragdoll first needs to know where the arm is, which needs to know where the torso is and where the hip is and so on. The hand depend on those positions.
Native Maya rigs don't work like that; they rarely form a linear hierarchy like this, with IK and space switching constraints and stretchy limbs all complicating the transformation path from hip to hand.
"},{"location":"releases/maya/2023.10.03/#tuning","title":"Tuning","text":"The universal transfer is an \"iterative\" solver. Here's how it works:
The challenge is that some control cause other controls to move. For example, after Ragdoll has matched the foot, matching the upper leg would move the foot again. And so the process needs to be repeated until each cyclic dependency is resolved.
Per default, Ragdoll will iterate up to 4 times, and stop as soon as controls get \"close enough\". The distance Ragdoll considers \"close enough\" is called \"tolerance\" and the number of times it attempts to reach that position is called \"iterations\".
Here's the normal circumstances.
And here's what happens when you tune iterations.
Notice how that with just 1 iteration, it isn't enough to transfer once. You'll have to keep pressing the transfer button until your character is close enough. That's that's exactly what iterations do; they keep pressing the button until it's close enough.
"},{"location":"releases/maya/2023.10.03/#iterations","title":"Iterations","text":"Here's one more visual to help you understand the effect of iterations.
Here, iterations are set to 1, meaning that each time we click we run exactly 1 iteration.
Pro Tip
You can manually type in an iteration count, such as 8 or 16, in case 4 is not enough. Generally, it depends on the number of cycles in your rig that contradicts the hierarchy. For example, if the upper leg is affected by the foot, then that's a cycle. This is also the most common cycle for IK-based rigs, where the upper leg is affected by the pole vector which is typically affected by the foot.
"},{"location":"releases/maya/2023.10.03/#minimum-iterations","title":"Minimum Iterations","text":"Sometimes, Ragdoll thinks it finds a close match, but you as a human know better. That's when you can force Ragdoll to keep trying to find a match for X number of times. This number is the minimum number of iterations.
"},{"location":"releases/maya/2023.10.03/#limitations","title":"Limitations","text":"Some rigs are still out of bounds for Ragdoll, no matter how many iterations. Here are a few things you can potentially expect depending on the complexity of your rigs.
Notice how the arm sometimes doesn't match, until you hit the transfer button a few more times.
Help
If you find a pattern, something small that consistently fails, let us know. We'd like to solve this!
"},{"location":"releases/maya/2023.10.03/#update-physics","title":"Update Physics","text":"Work faster and in parallel with your peers using this new feature.
Rag files can now be used presets and save-states for your characters, enabling updates to your character as you animate.
"},{"location":"releases/maya/2023.10.03/#options","title":"Options","text":"Everything is updated per default, minus any attribute that is already keyframed or otherwise locked. For more control, see the options provided in the UI.
Option Description Include Materials Friction, restitution and collide attributes Include Shapes Extents, radius and shape type Include Limits On/off state, angles, frames Include Springs Stiffness and damping Include Solvers Whether to include solver attributes at all Include Markers Whether to include any Marker attributes at all Include Constraints Whether to include pin constraints et. al. Include Groups Whether to include groups Include Targets If Markers have been retargeted, include the new target "},{"location":"releases/maya/2023.10.03/#update-api","title":"Update API","text":"Since this is suitable for pipeline automation, here's what you tech gurus can do.
from ragdoll import api\napi.update_physics(fname, opts)\n
Where fname
is the full path to a .rag
file, such as c:\\assets\\storm1.rag
and opts
is an optional dictionary with the same options as for import_physics
.
Options
You'll generally want to match these with whatever options you used to originally import your .rag
file.
opts = {\n \"roots\": [],\n \"matchBy\": constants.MatchByHierarchy,\n \"searchAndReplace\": [\"\", \"\"],\n \"namespace\": None,\n \"preserveAttributes\": True,\n \"retarget\": True,\n\n \"overrideSolver\": \"\",\n \"createMissingTransforms\": False,\n\n \"includeSprings\": True,\n \"includeLimits\": True,\n \"includeShapes\": True,\n \"includeMarkers\": True,\n \"includeGroups\": True,\n \"includeSolvers\": True,\n \"includeConstraints\": True,\n \"includeMaterials\": True,\n \"includeTargets\": True,\n}\n
"},{"location":"releases/maya/2023.10.03/#snap-to-simulation","title":"Snap to Simulation","text":"This button has seen an upgrade too, and now works like the Live Mode transfer!
"},{"location":"releases/maya/2023.10.03/#ghosting","title":"Ghosting","text":"Gain greater control over your animation by visualising past and present.
"},{"location":"releases/maya/2023.10.03/#caching","title":"Caching","text":"Cache your simulation to see the future too, this can be helpful when making tweaks without changing time to see the effects of your tweaks with very high precision.
"},{"location":"releases/maya/2023.10.03/#past-future","title":"Past & Future","text":"Tune the number of frames to look ahead or into the past.
"},{"location":"releases/maya/2023.10.03/#increment","title":"Increment","text":"Choose how many frames in between each frame to skip.
"},{"location":"releases/maya/2023.10.03/#colors","title":"Colors","text":"Finally, tune the colors of your ghosts to fit your preference.
"},{"location":"releases/maya/2023.10.03/#live-mode-precision","title":"Live Mode Precision","text":"You'll now find greater precision when posing your character in Live Mode, along with an improved IK behaviour.
IK will now lock the grandparent of anything you drag, just like traditional IK, in addition to keeping the Marker you drag from rotating.
Pro Tip
Hold the SHIFT key for a \"full-body IK\" type behaviour.
"},{"location":"releases/maya/2023.10.03/#additive-recording","title":"Additive Recording","text":"You can now record physics onto an additive layer, meaning layers can be combine, blended and kept active even when changing the underlying animation.
"},{"location":"releases/maya/2023.10.03/#scene-scale","title":"Scene Scale","text":"There is now an interactive widget to configure Ragdoll to fit your character.
When creating your first scene, Ragdoll will automatically try and detect your scene scale based on your first assignments.
See this option in the UI for how to control this.
"},{"location":"releases/maya/2023.10.03/#mass-units","title":"Mass Units","text":"Units now make physical sense.
Kilograms all around
Notice how values are in kg
This not only enables you to get a clear sense of what scale simulation happens at, but also provides accurate values of mass, in kilograms. A typical human weighs 60-100 kg and Ragdoll's forces depend on this being an accurate measure. Previously, mass was rather fixed at 6-10 kg as Ragdoll assumed your characters were roughly 18 cm tall, as is the norm in visual effects and animation (strangely enough!).
You'll also see the effect of making your character a giant, via the new Scene Scale manipulator.
With this release, characters of any scale will produce identical results.
Pro Tip
Because a giant weighs more, it also has an effect on any forces that act upon it. Like trying to push a car versus pushing a planet; the same amount of push will affect the object differently.
"},{"location":"releases/maya/2023.10.03/#rotation-mass","title":"Rotation Mass","text":"You'll also notice a new member to the property panel; Rotate Mass
. This can help you understand how easily an object starts to spin and how strongly it is affected by Rotate Stiffness
in which axis.
An axis with little mass will move more quickly and with less force; it will also affect other objects less. Just like Mass
, except for rotations!
Pro Tip
This is also called Moment of Inertia and Angular Momentum, if you would like to Google it.
"},{"location":"releases/maya/2023.10.03/#influence","title":"Influence","text":"The Attach Constraint has a new attribute called Influence
that lets you control the amount of influence the child has over its parent.
You can use it when you want one Marker to reach another, without the other being influenced by it. Notice here for example how the monkey limbs reach for the limb, without the limb being affected (until eventually reaching, at which point the influence is animated back to 0.5).
And yes, you can animate this attribute!
"},{"location":"releases/maya/2023.10.03/#resizable-uis","title":"Resizable UIs","text":"Sometimes names of things gets too long, and the UI is unable to fully show it to you. Until now, when you can (finally) resize the UI horizontally!
"},{"location":"releases/maya/2023.10.03/#root-stiffness","title":"Root Stiffness","text":"The first controller in your character hierarchy can now make use of Rotate and Translate Stiffness, just like any of its children. The difference is, the parent of the root is the world; so it will behave just like it was Pin Constrained.
"},{"location":"releases/maya/2023.10.03/#quality-of-life","title":"Quality of Life","text":"A number of smaller things have been addressed, take a look!
"},{"location":"releases/maya/2023.10.03/#multi-select-replace-mesh","title":"Multi-select Replace Mesh","text":"Sometimes, you need more than just a single mesh for your Marker. That's when you can combine your meshes and use the resulting combined mesh to replace with. We've saved you the extra clicks in this release, making it possible to do this!
Each mesh will be combined into a single Marker mesh.
"},{"location":"releases/maya/2023.10.03/#prevent-duplicate-markers","title":"Prevent Duplicate Markers","text":"Sometimes, you accidentally assign
"},{"location":"releases/maya/2023.10.03/#attach-constraint-parent","title":"Attach Constraint Parent","text":"You can now unparent an attach constraint, leaving it at the root of your Outliner. There's also a new option called \"Parent\" in the UI you can use to set the default.
"},{"location":"releases/maya/2023.10.03/#record-translation-rotation","title":"Record Translation & Rotation","text":"When Markers were first added to Ragdoll, they came with two attributes called:
Record Translation
Record Rotation
The idea being that you can choose whether controls should receive translation keyframes, rotation keyframes or both. It didn't work; because the way we recorded was somewhat limited.
This changes today, and you are now able to use these attribute to selectively skip or include channels that would otherwise receive keyframes.
"},{"location":"releases/maya/2023.10.03/#api-changes","title":"API Changes","text":"There is now an alias for reinterpret_physics
, which has already had a bit of a difficult name. The word \"import\" has special meaning in Python, hence it was mostly avoided. But alongside _physics
it is now available as:
from ragdoll import api\napi.import_physics(fname, opts)\n
"},{"location":"releases/maya/2023.10.03/#deprecated","title":"Deprecated","text":"Less attributes to worry about in this release; if you use them you are adviced to transition away from these.
Mass Ratio
on the rdSolver
node has been deprecatedDrive Per Substep
attribute on the Solver node turned out to be a success and is now always-on!Frameskip Method
attribute on the Solver node has been removed, turns out Pausing the simulation is never really that useful!Highlight for this release is ...!
The rendering pipeline has been upgraded with some new bells and whistles!
There's a new window to control the overall render settings under Ragdoll
-> System
-> Ragdoll Rendering
that look like this.
Contacts now include the direction and magnitude of the force being applied, helping you understand how strong (or weak) forces are at specific locations.
"},{"location":"releases/maya/2023.11.xx/#translate-and-rotate-drag","title":"Translate and Rotate Drag","text":"Previously called \"Translate Damping\" and \"Rotate Damping\", these attribute lets you block motion of an individual Marker, similar to the Air Density
attribute on the Solver except applied to an individual Marker.
You can override the scale of your UI in Maya's global preferences.
Ragdoll wasn't aware of this, and used your display scaling directly. Now it is away, and scales with Maya as you would expect!
Programmers
For the programmers out there, the trick is to query maya.MQtUtil.dpiScale
, instead of going through native Qt, e.g. QWindow.QScreen().logicalDotsPerInch() / 96.0
since Maya overrides this value.
Typically, Markers are assigned to a hierarchy of controls in a character rig, and thus translation is only relevant to the root control. But when assigning to a series of objects part of, say, a brick wall then you would expect all objects to have translation recorded as well.
That is now the case!
"},{"location":"sdk/download/","title":"Download","text":"Download Ragdoll CoreIf you agree with the Ragdoll Dynamics EULA, you may select a platform below.
Windows LinuxRagdoll 2024.04.14 awaits. Read about it - Previous versions
Join the community of ragdollers on Discord and/or Discourse.
Chat Forums "},{"location":"sdk/download/#install-on-windows","title":"Install on Windows","text":"To install Ragdoll Core, double-click the RagdollCore.msi
you downloaded from above, and click through the dialogs.
Ragdoll core installation on Linux is basically two steps:
RagdollCore*.zip
above/home/user-name
, replacing user-name
with your usernameFor example, to install current latest core:
cd ~/\nwget https://content.ragdolldynamics.com/6fb6a202-bd24-4db0-8d03-40e8c306c20c/RagdollCore-linux-2024.03.07.zip\nunzip RagdollCore-linux-2024.03.07.zip\n
If you prefer to place core libraries in elsewhere, environment variable RAGDOLL_CORE_PATH
can be used.
For example:
export RAGDOLL_CORE_PATH=/home/user-name/ragdolldynamics/core/2024.03.07/lib\n
"},{"location":"sdk/home/","title":"SDK","text":"The Ragdoll SDK is not Object Oriented, it is Data-Oriented in the form of an Entity Component System (ECS).
Concept Is A Description Entityunsigned int
Represents a \"thing\", like a marker, group and solver Component struct
Represents some data, like a name, position and color System for-loop
Represents some operation on said data Stay Tuned
This is where you'll find documentation for Ragdoll Core.
"},{"location":"sdk/serialisation/","title":"Serialisation","text":"Serialise all rigid bodies to JSON, for import into external software such as Unreal, Unity, Godot, CryEngine or any other engine able to read and parse JSON, including your own custom game engine.
Units
centimeters
radians
XYZW
On playback, Ragdoll generates a physical representation of your Maya scene, suitable for simulation. You can gain access to that representation, independent of Maya, for use in your own software and for your own purposes.
This enables you to use Maya as an authoring environment for general-purpose physics scenes, including full or partial ragdolls, for characters or props and even full environments.
"},{"location":"sdk/serialisation/#target-audience","title":"Target Audience","text":"Once a ragdoll has been authored in Maya, it can be exported for later import into external software for a variety of purposes.
Ragdoll internally stores data as \"entities\" and \"components\".
The exported format reflects this relationship and looks something like this.
{\n \"entities\": {\n \"10\": {\n \"components\": {\n \"NameComponent\": \"upperArm\",\n \"ColorComponent\": [1.0, 0.0, 0.0],\n \"GeometryDescriptionComponent\": \"Capsule\",\n ...\n }\n },\n \"15\": {\n \"components\": {\n \"NameComponent\": \"lowerArm\",\n \"ColorComponent\": [0.0, 1.0, 0.0],\n \"GeometryDescriptionComponent\": \"Box\",\n ...\n }\n }\n}\n
"},{"location":"sdk/serialisation/#rigid-body","title":"Rigid Body","text":"A single translation/rotation pair.
Components
Component DescriptionNameComponent
Name and path in Maya ColorComponent
Used in Maya viewport SceneComponent
Reference to the scene entity this rigid belongs to RestComponent
Initial transformation RigidComponent
Physics attributes GeometryDescriptionComponent
Shape attributes \"RigidComponent\": {\n \"type\": \"RigidComponent\",\n \"members\": {\n \"enabled\": true,\n \"mass\": 1.0,\n \"friction\": 0.80,\n \"restitution\": 0.10,\n \"thickness\": 0.0,\n \"disableGravity\": false,\n \"collide\": true,\n \"kinematic\": false,\n \"dynamic\": true,\n \"sleeping\": false,\n \"linearDamping\": 0.5,\n \"angularDamping\": 1.0,\n \"positionIterations\": 8,\n \"velocityIterations\": 1,\n \"maxContactImpulse\": -1.0,\n \"maxDepenetrationVelocity\": -1.0,\n \"sleepThreshold\": 0.00,\n \"enableCCD\": false,\n\n # A value of -1 means \"automatically computed\"\n \"angularMass\": {\n \"type\": \"Vector3\",\n \"values\": [-1.0, -1.0, -1.0]\n },\n\n # A value of 0 means \"automatically computed\"\n \"centerOfMass\": {\n \"type\": \"Vector3\",\n \"values\": [0.0, 0.0, 0.0]\n }\n }\n}\n
"},{"location":"sdk/serialisation/#shape","title":"Shape","text":"Every rigid has exactly one collision shape. The transformation of this shape can be optionally offset, and that offset happens in the frame of the rigid.
________\n ^ |\\ \\\n | | \\_______\\\n | | | |\n o--\\-|-> |\n \\ \\|______|\n \\\n v\n
In this example, the center of the box is offset from the center of the rigid along the X axis. Notice how the geometry is relative the axis of the rigid, so rotating the rigid along the Z axis would naturally take the geometry with it.
\"GeometryDescriptionComponent\": {\n \"type\": \"GeometryDescriptionComponent\",\n \"members\": {\n \"type\": \"Capsule\",\n\n # Used by Capsule\n \"length\": 0.123,\n\n # Used by Sphere\n \"radius\": 0.012,\n\n # Used by Box\n \"extents\": {\n \"type\": \"Vector3\",\n \"values\": [0.123, 0.024, 0.0247]\n },\n\n # Translation relative the associated rigid\n \"offset\": {\n \"type\": \"Vector3\",\n \"values\": [0.033, -0.05, 0.00]\n },\n\n # Rotation relative the associated rigid\n # Ordered as XYZW\n \"rotation\": {\n \"type\": \"Quaternion\",\n \"values\": [0.87, -0.47, 0.00, 0.00]\n }\n }\n}\n
"},{"location":"sdk/serialisation/#constraint","title":"Constraint","text":"A relationship between two rigid bodies is referred to as a \"constraint\". A constraint constrains the way two rigid bodies move relative each other.
For example, the position of the lower arm is typically associated with the tip of the upper arm. Wherever the upper arm goes, the lower arm must follow. It may also be further limited in how it is oriented, to e.g. prevent a lower arm from bending past the natural elbow limit; i.e. to rotate between 20-180 degrees along the Z axis, and 0-10 degrees around the X and Y axis (as that rotation would normally come from twisting the upper arm).
parentFrame
childFrame
Despite the name, there is no notion of hierarchy or \"parent\" in Ragdoll; the naming reflects the hierarchy as represented in Maya, where constraints are parented to the rigid representing the childFrame
.
Components
Component DescriptionJointComponent
References to associated rigids and frame matrices LimitComponent
Optional limits on translation and/or rotation DriveComponent
Optional target transformation, i.e. the animation \"JointComponent\": {\n \"type\": \"JointComponent\",\n \"members\": {\n\n # Reference to the associated rigid body entities\n \"parent\": 1048586,\n \"child\": 1048584,\n\n # The translate/rotate of the parent\n # rigid in the frame of child rigid\n \"parentFrame\": {\n \"type\": \"Matrix44\",\n \"values\": [\n 0.760, -0.594, -0.259, 0.0,\n -0.648, -0.680, -0.340, 0.0,\n 0.0262, 0.4274, -0.903, 0.0,\n 10.51, -0.646, 0.0, 1.0\n ]\n },\n\n # The translate/rotate of the child\n # rigid in the frame of parent rigid\n \"childFrame\": {\n \"type\": \"Matrix44\",\n \"values\": [\n 0.606, -0.751, -0.259, 0.0,\n -0.785, -0.515, -0.340, 0.0,\n 0.122, 0.4103, -0.903, 0.0,\n 0.0, 0.0, 0.0, 1.0\n ]\n },\n\n # Allow intersections between connected rigids\n \"disableCollision\": true\n }\n}\n
"},{"location":"sdk/serialisation/#limit","title":"Limit","text":"Constraints may optionally have a \"limit\", which means it can keep a rigid within a given angle (\"angular limit\") or position (\"linear limit\").
Min & Max
Values represent a upper end of a range. With x=5
the minimum value of the linear X axis is -5
.
\"LimitComponent\": {\n \"type\": \"LimitComponent\",\n \"members\": {\n \"enabled\": true,\n \"x\": -1.0, # Linear limit along the X-axis\n \"y\": -1.0,\n \"z\": -1.0,\n \"twist\": 0.78, # Angular limit along the X-axis\n \"swing1\": 0.78, # ..Y\n \"swing2\": 0.78, # ..Z\n \"angularStiffness\": 1000000.0,\n \"angularDamping\": 10000.0,\n \"linearStiffness\": 1000000.0,\n \"linearDamping\": 10000.0\n }\n}\n
Locked, Free or Limited
A value of -1
means the axis is \"Locked\", i.e. the value along this axis cannot change. A Point Constraint is typically locked on all linear axes, but free on the angular axes. A value of 0
means the axis if \"Free\", meaning it has no effect. It is \"limitless\". A value above 0
indicates the range of a given limit.
<0
means Locked=0
means Free>0
means LimitedA constraint may optionally have a \"drive\", which means having one rigid reach a target
position and/or angle relative another rigid. The typical use case is having simulation match your input animation, where the animation provides the positions and angles.
\"DriveComponent\": {\n \"type\": \"DriveComponent\",\n \"members\": {\n \"enabled\": true,\n \"linearStiffness\": 0.0,\n \"linearDamping\": 0.0,\n \"angularStiffness\": 10000.0,\n \"angularDamping\": 1000.0,\n \"acceleration\": true,\n \"target\": {\n \"type\": \"Matrix44\",\n \"values\": [\n 0.973, 0.2267, 0.0, 0.0,\n -0.226, 0.973, 0.0, 0.0,\n 0.0, 0.0, 0.999, 0.0,\n 0.1051, -0.006, 0.0, 1.0\n ]\n }\n }\n}\n
"},{"location":"sdk/serialisation/#data-types","title":"Data Types","text":"In addition to the plain-old-data types int
, double
and bool
, these are all possible data types found in the exported JSON.
{\n \"type\": \"Color4\",\n \"values\": [\n 0.4429999887943268, # red\n 0.7049999833106995, # green\n 0.9520000219345093 # blue\n 1.0 # alpha\n ]\n}\n\n{\n \"type\": \"Vector3\",\n \"values\": [\n 100.00001788139201, # x\n 100.00001788139201, # y\n 100.00000000000003 # z\n ]\n}\n\n{\n \"type\": \"Quaternion\",\n \"values\": [\n 0.8791841887437938, # x\n -0.47648206919348187, # y\n -2.7953360940182678e-8, # z\n 1.191501461145112e-7 # w\n ]\n}\n\n{\n # Unscaled, unsheared matrix\n \"type\": \"Matrix44\",\n \"values\": [\n 1.0, # rotation matrix\n 0.0, # rotation matrix\n 0.0, # rotation matrix\n 0.0,\n 0.0, # rotation matrix\n 1.0, # rotation matrix\n 0.0, # rotation matrix\n 0.0,\n 0.0, # rotation matrix\n 0.0, # rotation matrix\n 1.0, # rotation matrix\n 0.0,\n 0.0, # translateX\n 0.0, # translateY\n 0.0, # translateZ\n 1.0\n ]\n}\n
"},{"location":"sdk/serialisation/#reference","title":"Reference","text":""},{"location":"sdk/serialisation/#components","title":"Components","text":"These are all possible types of components found in the exported JSON.
SolverComponent
SceneComponent
NameComponent
ColorComponent
RestComponent
ScaleComponent
RigidComponent
GeometryDescriptionComponent
JointComponent
DriveComponent
LimitComponent
ConstraintUIComponent
RigidUIComponent
DriveUIComponent
LimitUIComponent
Here's an example of what a complete dump looks like.
Test your dump, by re-building the scene in Maya.
from maya import cmds\nfrom ragdoll.vendor import cmdx\n\n\nclass Component(dict):\n \"\"\"Simplified access to component members\"\"\"\n def __getattr__(self, key):\n value = self[\"members\"][key]\n\n if not isinstance(value, dict):\n return value\n\n if value[\"type\"] == \"Vector3\":\n return cmdx.Vector(value[\"values\"])\n\n elif value[\"type\"] == \"Color4\":\n return cmdx.Color(value[\"values\"])\n\n elif value[\"type\"] == \"Matrix44\":\n return cmdx.Matrix4(value[\"values\"])\n\n elif value[\"type\"] == \"Quaternion\":\n return cmdx.Quaternion(*value[\"values\"])\n\n else:\n raise TypeError(\"Unsupported type: %s\" % value)\n\n\ndef dedump(dump):\n with cmdx.DagModifier() as mod:\n root = mod.createNode(\"transform\", name=\"dump\")\n\n for entity, data in dump[\"entities\"].items():\n comps = data[\"components\"]\n\n if \"RigidComponent\" not in comps:\n continue\n\n name = Component(comps[\"NameComponent\"])\n\n if not name.path:\n # Bad export\n continue\n\n joint = name.path.rsplit(\"|\", 3)[-2]\n\n scale = Component(comps[\"ScaleComponent\"])\n rest = Component(comps[\"RestComponent\"])\n desc = Component(comps[\"GeometryDescriptionComponent\"])\n\n # Establish rigid transformation\n tm = cmdx.TransformationMatrix(rest.matrix)\n\n # Establish shape\n if desc.type in (\"Cylinder\", \"Capsule\"):\n radius = desc.radius * scale.absolute.x\n length = desc.length * scale.absolute.y\n geo, _ = cmds.polyCylinder(axis=(1, 0, 0),\n radius=radius,\n height=length,\n roundCap=True,\n subdivisionsCaps=5)\n\n elif desc.type == \"Box\":\n extents = desc.extents\n extents.x *= scale.absolute.x\n extents.y *= scale.absolute.y\n extents.z *= scale.absolute.z\n geo, _ = cmds.polyCube(width=extents.x,\n height=extents.y,\n depth=extents.z)\n\n elif desc.type == \"Sphere\":\n radius = desc.radius * scale.absolute.x\n geo, _ = cmds.polySphere(radius=radius)\n\n else:\n print(\"Unsupported shape type: %s.type=%s\" % (name.path, desc.type))\n continue\n\n with cmdx.DagModifier() as mod:\n transform = mod.createNode(\"transform\", name=joint, parent=root)\n transform[\"translate\"] = tm.translation()\n transform[\"rotate\"] = tm.rotation()\n\n # Establish shape transformation\n offset = desc.offset\n offset.x *= scale.absolute.x\n offset.y *= scale.absolute.y\n offset.z *= scale.absolute.z\n\n geo = cmdx.encode(geo)\n geo[\"translate\"] = offset\n geo[\"rotate\"] = desc.rotation\n\n transform.addChild(geo)\n\n\n# Usage Example\nimport json\ndump = cmds.ragdollDump()\ndump = json.loads(dump)\ndedump(dump)\n
"},{"location":"sdk/serialisation/#more-examples","title":"More Examples","text":""},{"location":"sdk/serialisation/#tiger","title":"Tiger","text":"Courtesy of www.cgspectrum.com
mytiger.rag
Model from https://mecabricks.com
ragcar.rag
A generic human character, rigged with AS.
mycharacter.rag
Jason worked on this shot of bombs falling from an airplane.
https://youtu.be/98Ys1aI9a_Y?t=56
"},{"location":"tutorials/20240308_rebelmoon/","title":"20240308 rebelmoon","text":"One or more shots in Rebel Moon used Ragdoll. Ask Jason.
"},{"location":"tutorials/20240309_houseofdragon/","title":"20240309 houseofdragon","text":"Something about a dragon eating bits. Ask Jason.
"},{"location":"tutorials/20240310_avatarii/","title":"20240310 avatarii","text":"It was used on Avatar II, but where? Ask Jason.
"},{"location":"tutorials/20240311_buffalokids/","title":"20240311 buffalokids","text":"Was used here:
It 's scheduled to be released in August the 30th. We used Ragdoll in the movie to create secondaries animations, specially for movement of Dress, hairs, etc. This way this kind of secondary animations don't depend on every animator as we give the same style with Ragdoll.
"},{"location":"tutorials/bouncing_ball/","title":"Bouncing Ball","text":""},{"location":"tutorials/bouncing_ball/#bouncing-ball","title":"Bouncing Ball","text":"The fundamentals of animation
In this tutorial, we will reproduce a classic animation tutorial, the Bouncing Ball. With it, we will explore various material properties of a ball whilst learning about the inner workings of Ragdoll.
Version 1.0 - Up to date
Written for Ragdoll 2022.05.04
and above.
Estimated Time
You will learn
polySphere
Where to find help
If you find or run into any issues with these tutorials, here's what you can do.
Why should an animator simulate a ball bouncing, rather than just keyframe it?
If you are new to animation or in a neighbouring field such as modeling or lighting, it might seem silly to consider such a trivial task for simulation. But as the more seasoned animator knows, getting the trajectory of any free-flying object right is incredibly hard. It can mean the difference between a believable character, and a character that looks like Earths gravity varies for the duration of a single jump, or one that appears to be on a different planet altogether.
With that in mind, although a single ball bouncing on a flat plane may seem trivial, it can be enough to challenge even the most senior of animators.
"},{"location":"tutorials/bouncing_ball/#setup","title":"Setup","text":"For this tutorial, all you need is an empty Maya scene. So go ahead and clear out all of those references and meshes with hours of history on it and let's get crackin'!
"},{"location":"tutorials/bouncing_ball/#poly-sphere","title":"Poly Sphere","text":"Let's make our ball out of a regular Maya polySphere
.
Sphere
from the Polygon Primitives
submenu of the Create
main menuTranslate Y = 5.0
Yes, if you prefer, you can also use a NURBS sphere.
"},{"location":"tutorials/bouncing_ball/#dynamics","title":"Dynamics","text":"With our sphere in place, let's give it some physical properties by turning it into a Active Rigid
.
pSphere1
Assign Marker
from the Ragdoll
MenuThat's great! Except hm.. It's not really a bouncing ball just yet.
"},{"location":"tutorials/bouncing_ball/#bounciness","title":"Bounciness","text":"Default settings make the ball rather dull, so let's try introducing some bounciness via its material properties.
pSphere1
rMarker_pSphere1
in the Channel BoxBounciness = 1.0
It means 100%! Technically, it means any force produced by the ball hitting the ground is reversed in its entirety with no loss of energy what-so-ever.
"},{"location":"tutorials/bouncing_ball/#infinite-bounciness","title":"Infinite Bounciness","text":"The reason the ball stops bouncing is that even though our ball is 100% bouncy, the ground is not. Like dropping a bowling ball on grass or a wooden floor. For perfect bounce, they both need to be 100% bouncy.
rGround
rMarker_rGround
in the Channel BoxBounciness = 1.0
Ragdoll creates this ground automatically for you whenever the first marker is assigned. It can be disabled by setting Create Ground = Off
in the Assign Marker
option dialog.
Now that we have complete control over our ball, let's put it to good use.
You have learnt
polySphere
Give the ball a little push.
pSphere1
Behaviour
from Animated
to Simulated
Translate X
0.0
0.5
Behaviour
Animated
Simulated
"},{"location":"tutorials/bouncing_ball/#trajectory","title":"Trajectory","text":"With our bouncing ball underway, let's gain a deeper understanding of what it looks like over time.
Record Simulation
from the Ragdoll menupSphere1
Create Editable Motion Trail
from Maya's Visualize menuNow, as every animator knows, this is not the trajectory of a bouncing ball. It looks as if the ball isn't actually touching the floor half the time, what's up with that? \ud83e\udd14
Expected Result\u2714\ufe0f Actual Result\u274cThis is a problem of resolution. Cameras have this problem too.
See how despite this most definitely not being a simulation (or is it?) we are still getting bounces that don't actually touch the ground! The reason is simply that a camera can only capture moments of reality. It can only sample it.
In this case, the ball did touch the floor, but the camera caught at a slightly different time. Shortly before and after contact. This is how you can think of Ragdoll too; a camera for physics.
Can you overeducate me?With pleasure. \ud83d\ude01 Let's look at audio.
Notice how sound itself, represented by the curved line, is continuous - of infinite resolution - and that what we capture in our computers are samples of it, at some fixed resolution - typically at 44,000 fps or as it is more commonly known 44khz
.
Ragdoll works like this too. Physics is continuous, but Ragdoll can only provide you with snapshots of physics at a fixed resolution; the resolution of your framerate.
Is every bouncing ball tutorial on YouTube wrong?A typical bouncing ball tutorial has the ball come into contact on whole frames. But because the time between each bounce is decreasing, it is impossible for every bounce to land on a whole frame.
So in a way, yes, they are wrong! Science says so!
Should I change the way I animate?Well, it depends. Take motion blur for example.
Because you see, the final position from a video recorded tennis ball is only half the story. Motion blur isn't the result of only these samples, but of the actual continuous motion. As light hits the lens inbetween the shutter opening and closing, the ball is still moving.
To accurately reproduce this effect in your animation or with Ragdoll, you still need those inbetween positions of the ball. Just so that your renderer can throw those away once it's done computing motion blur.
Even without motion blur, your eyes and brain still interprets the ball not hitting the ground as though it floats or hits an invisible obstacle. So for the greatest sense of realism when everything has been said and done and the images actually reach your eyes (brain), you may still want to defy physics and realism.
Because at the end of the day, the animation curves isn't what you are making. They are mere tools for you to achieve realism in the final output picture.
"},{"location":"tutorials/bouncing_ball/#tennis-ball","title":"Tennis Ball","text":"Now that we've got some reference for a tennis ball, let's tune our settings to match.
pSphere1
rMarker_pSphere1
in the Channel BoxBounciness = 0.4
Let's also take it out of orbit and into Earths atmosphere by restoring the Air Density
rSolver
Air Density = 1.0
Now that we've got a ball, what could we possibly do with it?
"},{"location":"tutorials/bouncing_ball/#soft-bounce","title":"Soft Bounce","text":"Notice our trajectory now has a smooth transition from being in contact to lifting off the ground.
By playing around with the density, we can get different effects.
Or playing around with this invisible collision sphere we've created.
So what's going on here?
pSphere2
pSphere2
under pSphere1
Next, let's assign to pSphere2
with pSphere1
as its parent.
pSphere1
and pSphere2
Assign and Connect
Not much happens, they both move together. Let's change that.
pSphere2
Translate Motion = Soft
pSphere1
Collide = Off
I found values of Translate Stiffness = 0.1
and Translate Damping = 0.1
to look decent.
And that does it! This same technique can be used on full ragdolls too to achieve all manner of soft contacts, have fun.
"},{"location":"tutorials/bouncing_ball/#troubleshooting","title":"Troubleshooting","text":"Let's have a look at some common issues.
"},{"location":"tutorials/bouncing_ball/#vibrating-at-rest","title":"Vibrating at Rest","text":"There is no right value for Bounce Threshold
, it's an art. And it depends on the size of your scene and rigids, their shape, how fast they move and the look you are after.
When the threshold is too low, Ragdoll can get into an infinite bounce like this.
To address this, increase the threshold until it stops.
"},{"location":"tutorials/cloth_emulation/","title":"Cloth Emulation","text":""},{"location":"tutorials/cloth_emulation/#cloth-emulation","title":"Cloth Emulation","text":"In this tutorial, we'll use many interconnected Markers to emulate cloth.
Version 1.0 - Up to date
Written for Ragdoll 2022.03.14
and above.
Estimated Time
You will need
You will learn
Where to find help
If you find or run into any issues with these tutorials, here's what you can do.
See here for part 1 of 1 this tutorial.
This has been a tutorial on how to emulate - not simulate - cloth. Because Ragdoll currently does not understand deformations. It only understands hard objects.
So, how else can you make hard objects appear like cloth? Share your experiences with the community!
\"Make your own motion reference\"
In this tutorial, we will setup a human-like character for use as reference or constraint target to your rig. You will be able to pose and position this Manikin like you would a real Manikin, and drop it from various heights and onto various obstacles to produce realistic poses as it falls.
Something the animator can import and throw around for reference on how it would look like.
Version 1.2 - Up to date
Written for Ragdoll 2023.08.01
and above.
Estimated Time
You will learn
Where to find help
If you find or run into any issues with this tutorials, here's what you can do.
There are two ways to spell \"Manikin\", this tutorial is based on this term here.
Follow this tutorial either using our provided Manikin rig, or your own character. It can have any number of limbs.
Download Manikin Download Final Scene "},{"location":"tutorials/manikin/#motivation","title":"Motivation","text":"Why should we even bother simulating a character?
Finding motion reference is one of the most important activities for any animator. And yet I can safely challenge you to find reference for perhaps the most common motion in all blockbuster movies today, something that is either impossible or dangerous for actors or animators alike.
Or how about reference of someone simply falling over, perhaps from heat stroke or staring into the sun.
This is, after all, one of the major reasons for pursuing computer graphics in storytelling rather than real people.
Animators bring life to characters, but of equal challenge is that of lifelessness. Of natural and realistic motion without someone behind the wheel. Be it getting hit or shot, blasted or thrown, animating lifelessness is enough to challenge even the most senior of animators.
As you will find, there is a lot more we can do once our motion reference is in 3D, on our actual character rig within Maya and infinitely customisable. As opposed to some video on the internet.
"},{"location":"tutorials/manikin/#setup","title":"Setup","text":"Create a new reference of your chosen character rig or download this Manikin rig to get started.
Play around with the controls to get a feel for what we're working with. This character is entirely FK which will make simulating it straightforward.
"},{"location":"tutorials/manikin/#simulation","title":"Simulation","text":"The stage is set, now let's apply physics!
"},{"location":"tutorials/manikin/#torso","title":"Torso","text":"Let's start with the Torso.
hip_ctl
torso_ctl
head_ctl
Assign and Connect
This will produce our first Group
, which is a collection of connected Markers
.
New Concept
Group
The rdGroup
node contains attributes that affect all contained markers. It's where you'd edit the overall look and feel of your character, like how stiff it should be and whether or not body parts should collide with each other.
Each Marker can either inherit or otherwise override these values.
"},{"location":"tutorials/manikin/#left-arm","title":"Left Arm","text":"Next we will continue from the torso_ctl
and out into the arms.
torso_ctl
L_clavicle_ctl
L_upperArm_ctl
L_lowerArm_ctl
L_hand_ctl
Assign and Connect
Yes, the order in which you select will determine how the markers are connected.
Your first selection is extra important, as it determines whether to start a new group, like for the hip_ctl
, or to add to an existing group, like the torso_ctl
.
In this case, we would very much like our arm to be connected to the torso.
Can I skip the clavicles?Yes, if you have extra controls - such as twist
or bend
- you can skip these if you don't care to simulate them.
Simply skip over them as you select, from torso_ctl
directly to L_upperarm_ctl
.
Now repeat the above process for the other arm.
"},{"location":"tutorials/manikin/#legs","title":"Legs","text":"Now let's continue down the hips and into the legs.
hip_ctl
L_thigh_ctl
L_knee_ctl
L_foot_ctl
Assign and Connect
We will address those long feet shortly. \ud83d\udc43
"},{"location":"tutorials/manikin/#drop-test","title":"Drop Test","text":"That's enough setup, let's drop him!
New Concept
Behaviour
Each Marker has a \"behaviour\", which tells Ragdoll it should interpret the control it has been assigned. Should it fall with gravity? Should it try and match the pose? Should it remain fully animated, even in simulation?
hip_ctl
Behaviour = Simulated
The default behaviour for Assign and Connect
is to give the first selection - the \"root\" - a Animated
behaviour.
What does Animated mean?
Animated means \"copy the animation into simulation and make no changes to it\"
By instead setting this to Simulated
, then Ragdoll will only use the animation for the starting position and orientation of the simulation.
Inherit
Alternatively, you can set it to Inherit
to have it inherit the value of the rGroup
node that was created for the whole character.
Next let's address the elephant in the room; the shapes. They look awful.
"},{"location":"tutorials/manikin/#volumes","title":"Volumes","text":"The shape of each collider affects your simulation in 2 ways.
The contact point can be important if your character interacts with an environment or another character. Like in this case where the feet are incorrectly colliding with the ground because of a bad shape.
That's not always the case though, sometimes you just want overlapping motion without contacts in which case the shapes won't matter.
They do however also affect their resistance to rotation. Consider this.
Here, we rotate the exact same shapes, the exact same amount in the exact same amount of time. And yet they respond differently.
This shape has vastly different dimensions in the X, Y and Z directions, resulting in a different rotation mass for each one. As a result, the effort required to rotate it in each axis differs too.
In practice, you'll find this for just about any limb on a character, which is typically longer in one axis. For our Manikin, this is especially true for the default clavicle shapes.
Override Rotate Mass
In some cases, you have a shape but want it to act like a different shape. Rotate Mass
is very similar to normal Mass
, except in 3 dimensions. Where the position of an object is affected equal in X, Y and Z directions, rotations have 3 separate masses.
With this in mind, let's tune some shapes.
Manipulator
from the Ragdoll
menuAlternatively
Select a rMarker
node in the Channel Box, or the rGroup
node in your Outliner, and hit the T
key on your keyboard. You can also select the shape of the rSolver
node.
This brings up the Manipulator interface, where you can manipulate shapes using mouse gestures.
Great, now let's turn those hands and feet into boxes.
Translate, Rotate and Scale
Notice I'm using the..
Translate
Rotate
Scale
The help text screen-right will help you remember these.
Greater Value Step
While dragging the value on Manipulator UI panel, you may hold Shift
to increase value changing step.
Symmetry
Also notice the edits are symmetrical; even when they don't start out that way like the feet!
"},{"location":"tutorials/manikin/#recording","title":"Recording","text":"That's all there is for setting up your character rig for simulation! Let's now transfer the simulation back onto the rig.
Record Simulation
The recorded simulation ends up on an Animation Layer, and is also Cached. To start over, delete this layer and disable the cache.
"},{"location":"tutorials/manikin/#next-steps","title":"Next Steps","text":"In the next tutorial, we'll take this a bit further. As you play around with the Rotate Stiffness
on either the rGroup
or individual rMarker
nodes, you'll find some limbs start to misbehave. Especially the knees and elbows, that normally won't allow rotations past a certain angle in a real human (or Manikin for that matter!).
That isn't the case here, because we've left out a critical part of any ragdoll - \"limits\".
See you there!
"},{"location":"tutorials/manikin_blender/","title":"Blender Manikin I","text":""},{"location":"tutorials/manikin_blender/#manikin","title":"Manikin","text":"\"Make your own motion reference\"
In this tutorial, we will setup a human-like character for use as reference or constraint target to your rig. You will be able to pose and position this Manikin like you would a real Manikin, and drop it from various heights and onto various obstacles to produce realistic poses as it falls.
Something the animator can import and throw around for reference on how it would look like.
Estimated Time
You will learn
Where to find help
If you find or run into any issues with this tutorials, here's what you can do.
There are two ways to spell \"Manikin\", this tutorial is based on this term here.
Follow this tutorial either using our provided Manikin rig, or your own character. It can have any number of limbs.
Download Manikin Download Final Scene "},{"location":"tutorials/manikin_blender/#motivation","title":"Motivation","text":"Why should we even bother simulating a character?
Finding motion reference is one of the most important activities for any animator. And yet I can safely challenge you to find reference for perhaps the most common motion in all blockbuster movies today, something that is either impossible or dangerous for actors or animators alike.
Or how about reference of someone simply falling over, perhaps from heat stroke or staring into the sun.
This is, after all, one of the major reasons for pursuing computer graphics in storytelling rather than real people.
Animators bring life to characters, but of equal challenge is that of lifelessness. Of natural and realistic motion without someone behind the wheel. Be it getting hit or shot, blasted or thrown, animating lifelessness is enough to challenge even the most senior of animators.
As you will find, there is a lot more we can do once our motion reference is in 3D, on our actual character rig within Blender/Maya and infinitely customisable. As opposed to some video on the internet.
"},{"location":"tutorials/manikin_blender/#setup","title":"Setup","text":"Open your chosen character rig or download the above Manikin rig to get started.
Play around with the controls to get a feel for what we're working with.
FK or IK
Use FK for this tutorial
This Manikin rig has FK and IK (legs) controls, but we will focus on FK controls for this tutorial because it makes simulating much straightforward.
"},{"location":"tutorials/manikin_blender/#simulation","title":"Simulation","text":"The stage is set, now let's apply physics.
"},{"location":"tutorials/manikin_blender/#torso","title":"Torso","text":"Let's start with the Torso.
hip_FK
torso_FK
head_FK
Physics Properties
panel, run Assign and Connect
This will produce our first Group
(named as hip_FK_rGroup
, in Ragdoll
collection), which is a set of connected Markers
.
New Concept
Group
The Group
object contains properties that affect all contained markers. It's where you'd edit the overall look and feel of your character, like how stiff it should be and whether or not body parts should collide with each other.
Each Marker can either inherit or otherwise override these values.
Markable Objects
Who can have Marker assigned?
Next we will continue from the torso_FK
and out into the arms.
torso_FK
L_clavicle_FK
L_upperArm_FK
L_lowerArm_FK
L_hand_FK
Assign and Connect
Yes, the order in which you select will determine how the markers are connected.
Your first selection is extra important, as it determines whether to start a new group, like for the hip_FK
, or to add to an existing group, like the torso_FK
.
In this case, we would very much like our arm to be connected to the torso.
Can I skip the clavicles?Yes, if you have extra controls - such as twist
or bend
- you can skip these if you don't care to simulate them.
Simply skip over them as you select, from torso_FK
directly to L_upperArm_FK
.
Now repeat the above process for the other arm.
"},{"location":"tutorials/manikin_blender/#legs","title":"Legs","text":"Now let's continue down the hips and into the legs.
hip_FK
L_thigh_FK
L_knee_FK
L_foot_FK
Assign and Connect
That's enough setup, let's drop him!
hip_FK
Behaviour = Simulated
New Concept
Behaviour
Each Marker has a \"behaviour\", which tells Ragdoll it should interpret the control it has been assigned. Should it fall with gravity? Should it try and match the pose? Should it remain fully animated, even in simulation?
The default behaviour for Assign and Connect
is to give the first selection - the \"root\" - an Animated
behaviour.
What does 'Animated'/'Simulated' mean?
Animated means \"copy the animation into simulation and make no changes to it\"
By instead setting this to Simulated
, then Ragdoll will only use the animation for the starting position and orientation of the simulation.
Use Group
Alternatively, you can set it to Use Group
to have it use the value of the rGroup
node that was created for the whole character.
Next let's address the elephant in the room; the shapes. They look awful.
"},{"location":"tutorials/manikin_blender/#volumes","title":"Volumes","text":"The shape of each collider affects your simulation in 2 ways.
The contact point can be important if your character interacts with an environment or another character. Like in this case where the feet are incorrectly colliding with the ground because of a bad shape.
That's not always the case though, sometimes you just want overlapping motion without contacts in which case the shapes won't matter.
They do however also affect their resistance to rotation. Consider this.
Here, we rotate the exact same shapes, the exact same amount in the exact same amount of time. And yet they respond differently.
This shape has vastly different dimensions in the X, Y and Z directions, resulting in a different rotation mass for each one. As a result, the effort required to rotate it in each axis differs too.
In practice, you'll find this for just about any limb on a character, which is typically longer in one axis. For our Manikin, this is especially true for the default clavicle shapes.
Override Rotate Mass
In some cases, you have a shape but want it to act like a different shape. Rotate Mass
is very similar to normal Mass
, except in 3 dimensions. Where the position of an object is affected equal in X, Y and Z directions, rotations have 3 separate masses.
With this in mind, let's tune some shapes.
rSolver
object, within Ragdoll
collection.Manipulator
tool at the ToolbarThis brings up the Manipulator interface, where you can manipulate shapes using mouse gestures.
Great, now let's turn those hands and feet into boxes.
Translate, Rotate and Scale
Notice I'm using the..
Translate
Rotate
Scale
The help text screen-right will help you remember these.
Greater Value Step
While dragging the value on Manipulator UI panel, you may hold Shift
to increase value changing step.
Symmetry
Also notice the edits are symmetrical; even when they don't start out that way like the feet!
"},{"location":"tutorials/manikin_blender/#recording","title":"Recording","text":"That's all there is for setting up your character rig for simulation! Let's now transfer the simulation back onto the rig.
Record Simulation
Recording options?
By holding Ctrl
while clicking Record Simulation
, a dialog pops up provides you more control over recording process.
The simulation was recorded into the NLA Track of each marker assigned object with Solo enabled for playback. To start over, disable Solo mode for those tracks (or delete them).
Initial Key
By default, Ragdoll adds one keyframe on the simulation starting frame, this is to keep original pose intact after playback recorded animation.
Auto Cache
If you have recording option Auto Cache
enabled while recording, solver will remember simulation result after recorded, which can be helpful if you wish to compare the simulation against baked result. If so, don't forget to turn it off before next simulation.
In the next tutorial, we'll take this a bit further. As you play around with the Rotate Stiffness
on either the rGroup
or individual rMarker
nodes, you'll find some limbs start to misbehave. Especially the knees and elbows, that normally won't allow rotations past a certain angle in a real human (or Manikin for that matter!). That isn't the case here, because we've left out a critical part of any complete ragdoll.
See you there!
"},{"location":"tutorials/manikin_ik/","title":"Manikin and IK","text":""},{"location":"tutorials/manikin_ik/#manikin-and-ik","title":"Manikin and IK","text":"In the previous tutorial we turned a character rig into a ragdoll, driven by your animation.
In this tutorial, we'll have a look at how we apply this to the IK controls of a rig.
Version 1.1 - Up to date
Written for Ragdoll 2021.12.10
and above.
Estimated Time
You will learn
Where to find help
If you find or run into any issues with these tutorials, here's what you can do.
Follow this tutorial either using our provided Manikin rig, or your own character. It can have any number of limbs.
Download Manikin Download Final Scene "},{"location":"tutorials/manikin_ik/#setup","title":"Setup","text":"Let's start fresh, with a non-dynamic character rig. In this case, the IK controls are disabled per default, so let's enable them.
master_ctl
Left Leg Fk Ik = 1
Right Leg Fk Ik = 1
As per usual, let's assign markers onto the FK controls in the upper body.
"},{"location":"tutorials/manikin_ik/#find-ik-joints","title":"Find IK Joints","text":"The legs are different. We don't want to pass the position of the IK controls in the solver, instead what we want are the joints they drive.
Where are the joints in my rig?
The location of these will differ in every rig. What's important is that they are the ones that move when you move your IK controls. Any joints that do that will suffice.
In the case of the Manikin, these will be located under the skeleton_grp
.
Once you've found a suitable set of joints, assign to them as per usual. Starting from the hip.
"},{"location":"tutorials/manikin_ik/#recording","title":"Recording","text":"Per default, Ragdoll will record onto the control you assign.
However, we don't want keyframes on our IK joints. We want keyframes on our IK controls. Therefore, we aren't ready to record just yet.
Notice how our IK controls didn't get any keyframes?
"},{"location":"tutorials/manikin_ik/#retarget","title":"Retarget","text":"Because we did not assign to our IK controls, we'll need to retarget the joints onto the controls.
Now when we record, our retargeted IK controls will be getting keyframes from our simulated IK joints.
Not Just IK
This will work between any controls or joints. Even from one rig to another, or more complex IK like Spline IK. The Record Simulation
command uses a native Maya Parent Constraint
between the assigned and retargeted controls, so anywhere you could manually do this will work with this command.
That's it for this tutorial! Here's some test animation.
"},{"location":"tutorials/manikin_ik/#shapes","title":"Shapes","text":"Grab the manipulator and tweak those shapes to fit your character.
"},{"location":"tutorials/manikin_ik/#test-animation","title":"Test Animation","text":"Then drop some keys on our IK rig to see it in action.
"},{"location":"tutorials/manikin_ragdoll/","title":"Manikin II","text":""},{"location":"tutorials/manikin_ragdoll/#manikin-ragdoll","title":"Manikin Ragdoll","text":"In the previous tutorial we assigned markers onto a rig such that you can achieve overlapping motion.
That's enough for some things, but other times you don't want any animation. You just want to drop a ragdoll someplace dangerous and watch it go.
Version 1.2 - Up to date
Written for Ragdoll 2023.08.01
and above.
Estimated Time
You will learn
Where to find help
If you find or run into any issues with these tutorials, here's what you can do.
Either continue from the last tutorial or start anew with your own rig.
Download Manikin Download Final Scene "},{"location":"tutorials/manikin_ragdoll/#limits","title":"Limits","text":"Next let's see how our character behaves when there isn't any animation around to steer it.
hip_ctl_rGroup
Rotate Stiffness = 0.0
As in our last tutorial when we changed the hip_ctl
from Animated
to Simulated
, now we do the same but for the whole character!
Yikes! That's a mess. No longer is the animation holding a pose together, it's all up to gravity and the anatomy of our character now.
The way we will address this is via \"limits\", which is like locked rotate channels except they also lock a range of values. We can use this to replicate natural limits in our human joints.
"},{"location":"tutorials/manikin_ragdoll/#legs","title":"Legs","text":"Let's start at legs and work our way up. First, let's figure out what axis we want to rotate, and which we want to lock.
Ok, great. The Z axis should rotate but X and Y should be locked.
Ragdoll -> Manipulator
Limit Mode
X
, Y
and Z
X
and Y
Next, tune the minimum and maximum values of the limit.
Tune Minimum and Maximum Separately
By holding the Ctrl key, you can manipulate one bound at a time.
Then we can do the same for the feet.
Something like that should do the trick.
"},{"location":"tutorials/manikin_ragdoll/#clavicles","title":"Clavicles","text":"Let's keep the clavicles simple. We'll allow only 1 axis of rotation by locking the others.
Ragdoll -> Manipulator
We'll lock the X
and Y
axes of the lower arm like we did for the lower leg.
Ragdoll -> Manipulator
Both the hip and spine should be allowed to rotate around all three axes, so we can leave these at their default values for now.
Ragdoll -> Manipulator
And that's it! From here, we can hide the limits to have another look at contacts.
"},{"location":"tutorials/manikin_ragdoll/#contacts","title":"Contacts","text":"If we hide away our limits for a moment, we can see something that's not right. Notice how the arms and legs intersecting each other? That's because, per default, limbs within a single group are allowed to overlap.
Should I enable Self Collision?Normally the answer is \"no\", but when you do, this can be overridden on the rGroup
node.
Let's address this by having these overlap with Nothing
.
You now know enough to construct any character of any anatomy!
You have learnt
As you tune, try dropping the Manikin from different heights and angles. Put an obstacle underneath for more detail and to catch more edge cases. Once you are unable to produce an unnatural pose, you are done!
Download Completed Scene
For your reference, here is the completed scene with the Manikin file referenced.
Download Manikin Download Final Scene "},{"location":"tutorials/manikin_ragdoll/#damped-limits","title":"Damped Limits","text":"You can tune the behaviour of each limit to capture the look you're after, such as making things a little more damped.
Global Damping
This, and other stiffness and damping-related attributes, can be controlled globally - for every limit in your scene - via the rSolver
node.
Sometimes, a limit is hard. Like your elbow. It won't allow you to continue rotating it once it's straightened out. You'll break it!
Other limits are more flexible. Let's reflect this in our simulation by reducing their range and lowering their Stiffness
, accepting that they will exceed it, but get gently pushed back.
Feet contact with the ground is often more important than other contacts. For such cases, a box or capsule shape may not be enough.
So let's use Replace Mesh
to fix that.
L_foot_jnt
Replace Mesh
In most cases, you'll want some control over the resulting simulation. Just a little bit.
Group Markers
You could add/remove groups as you go for better control, each group multiplies stiffnesses and damping on each contained Marker.
"},{"location":"tutorials/manikin_ragdoll_blender/","title":"Blender Manikin II","text":""},{"location":"tutorials/manikin_ragdoll_blender/#manikin-ragdoll","title":"Manikin Ragdoll","text":"In the previous tutorial we assigned markers onto a rig such that you can achieve overlapping motion.
That's enough for some things, but other times you don't want any animation. You just want to drop a ragdoll someplace dangerous and watch it go.
Estimated Time
You will learn
Where to find help
If you find or run into any issues with these tutorials, here's what you can do.
Either continue from the last tutorial or start anew with your own rig.
Download Manikin Download Final Scene "},{"location":"tutorials/manikin_ragdoll_blender/#limits","title":"Limits","text":"Next let's see how our character behaves when there isn't any animation around to steer it.
hip_FK_rGroup
Behaviour = Simulated
Rotate Stiffness = 0.0
As in our last tutorial when we changed the hip_FK
from Animated
to Simulated
, now we do the same but for the whole character!
Yikes! That's a mess. No longer is the animation holding a pose together, it's all up to gravity and the anatomy of our character now.
The way we will address this is via \"limits\", which is like locked rotate channels except they also lock a range of values. We can use this to replicate natural limits in our human joints.
"},{"location":"tutorials/manikin_ragdoll_blender/#legs","title":"Legs","text":"Let's start at legs and work our way up. First, let's figure out what axis we want to rotate, and which we want to lock.
Ok, great. The Z axis should rotate but X and Y should be locked.
Except... no. Because Ragdoll uses different axis system at the moment, so we better head right into Limit Mode
and find out!
Manipulator
Limit Mode
X
, Y
and Z
X
and Z
Next, tune the minimum and maximum values of the limit.
Tune Minimum and Maximum Separately
By holding the Ctrl key, you can manipulate one bound at a time.
Then we can do the same for the feet.
Something like that should do the trick.
"},{"location":"tutorials/manikin_ragdoll_blender/#clavicles","title":"Clavicles","text":"Let's keep the clavicles simple. We'll allow only 1 axis of rotation by locking the others.
Manipulator
We'll lock the X
and Z
axes of the lower arm like we did for the lower leg.
Manipulator
Both the hip and spine should be allowed to rotate around all three axes, so we can leave these at their default values for now.
Manipulator
And that's it! From here, we can hide the limits to have another look at contacts.
"},{"location":"tutorials/manikin_ragdoll_blender/#contacts","title":"Contacts","text":"If we hide away our limits for a moment, we can see something that's not right. Notice how the arms and legs intersecting each other? That's because, per default, the limbs within a single group are allowed to overlap.
Should I enable Self Collision?Normally the answer is \"no\", but when you do, this can be overridden on the rGroup
node.
Let's address this by having these overlap with Nothing
.
You now know enough to construct any character of any anatomy!
You have learnt
As you tune, try dropping the Manikin from different heights and angles. Put an obstacle underneath for more detail and to catch more edge cases. Once you are unable to produce an unnatural pose, you are done!
Download Completed Scene
For your reference, here is the completed scene with the Manikin file referenced.
Download Manikin Download Final Scene "},{"location":"tutorials/manikin_ragdoll_blender/#damped-limits","title":"Damped Limits","text":"You can tune the behaviour of each limit to capture the look you're after, such as making things a little more damped.
Global Damping
This, and other stiffness and damping-related attributes, can be controlled globally - for every limit in your scene - via the rSolver
node.
Sometimes, a limit is hard. Like your elbow. It won't allow you to continue rotating it once it's straightened out. You'll break it!
Other limits are more flexible. Let's reflect this in our simulation by reducing their range and lowering their Stiffness
, accepting that they will exceed it, but get gently pushed back.
Feet contact with the ground is often more important than other contacts. For such cases, a box or capsule shape may not be enough.
So let's use Replace Mesh
to fix that.
L_foot_blend_jnt
Default Shape
and find Custom mesh shape
propertyL_foot_geo
Shape
to Mesh
typeIn most cases, you'll want some control over the resulting simulation. Just a little bit.
Group Markers
You could add additional marker group for better control over stiffness and damping on different part of limbs, which then decides how your input animation affects simulation.
"},{"location":"tutorials/manikin_ragdoll_blender/#bonus-pin-constraint","title":"Bonus: Pin Constraint","text":"Constraint
panel, click Pin Marker
(or Pin All Selected
) button.Other Constraints?
At this moment (2023.08 release), only Pin Constraint
works, other type of constraints coming soon!
We don't cover this yet, as it's partly CreatureFX and Technical Animation - something I've wanted to steer clear of. But there is value for animators here, a lot of animators are stuck with this because a studio simply cannot afford (or understand) technical animation.
So we'll need a character that we'll apply motion capture to, and only worry about secondary effects. The character would look somewhere along the lines of the below. Familiar, common in the animation field, with things we can make dynamic.
We'd combine this with general dynamics on limbs too, like swings and trajectories for jumps, that kind of thing. Maybe we can repurpose Skye for this?
"},{"location":"tutorials/masterclass/#human-masterclass","title":"Human Masterclass","text":"Topics Description Hinges Knees and elbows Spherical Hips and shoulders Fingers Palm and thumb, up to individual fingers Facial Fleshy cheeks, lips, jaw Usage Leave some pose stiffness, soft limits, soft translation
This one would focus on anatomy and what people most associate with \"ragdolls\". People getting struck, falling, lying on things that move, floating, the Jedi-grip, crash-dummy. That kind of thing.
For this we'll need a realistic character, not necessarily with clothing as our focus would be on the body itself and not so much on the input animation or character.
"},{"location":"tutorials/masterclass/#mecha-masterclass-series","title":"Mecha Masterclass Series","text":"Topics Description Linear limits Like hydraulics Spherical Hips and shoulders Animation How to animate something to look like a robotWe can do a really strong job here, animating things to look robotic is a lot easier and forgiving than a human. As a robot generally needs to move one limb at a time, in a controlled manner. Which is funny, as it's a look that's based on how difficult it is to approximate human motion. A heavily controlled, slow movement. We'll have overshoots and jiggles, because that's just how motors work in real life.
For feet, I think we'll do especially well too, as we can stick with the pointed feet like with Locomotion, and rely on contacts to animate anything coming into contact with the ground.
I found these which will serve as an excellent foundation for this.
https://www.artstation.com/marketplace/p/k1yK9/10-sci-fi-robot-models
"},{"location":"tutorials/masterclass/#weightlessness-series","title":"Weightlessness Series","text":"Using the setups from the previous 3 masterclasses, put them underwater, in space and thrown around with magic/Jedi force.
"},{"location":"tutorials/mecha_series/","title":"Mecha series","text":"Steps
Walk through how to do these signs with Ragdoll. :) https://youtu.be/xPDGoVml5RU?t=10
"},{"location":"tutorials/mocap_chap/","title":"Mocap Chap","text":""},{"location":"tutorials/mocap_chap/#mocap-chap","title":"Mocap Chap","text":"In the previous tutorials we've turned a character rig into a full ragdoll, driven by your animation.
This time we'll look at applying physics to only parts of a character, like the upper body of this mocap clip found in Maya's default Content Browser.
Version 1.1 - Up to date
Written for Ragdoll 2021.12.10
and above.
Estimated Time
You will learn
Where to find help
If you find or run into any issues with these tutorials, here's what you can do.
When and why would you even want simulation on parts of a character?
Are three simple and somewhat obvious examples, more complex examples include what we're about to do in this tutorial. Namely, edit the mass of an object picked up during the original motion capture.
Download Final Scene "},{"location":"tutorials/mocap_chap/#setup","title":"Setup","text":"Let's start by importing our motion capture clip; this can be any clip but if you'd like to follow along here's what you do.
Windows -> General Editors -> Content Browser
Smash.fbx
Make sure the fbxmaya.mll
plug-in is loaded via the Maya Plug-in Manager.
Here's what this clip looks like.
"},{"location":"tutorials/mocap_chap/#symmetry-optional","title":"Symmetry (optional)","text":"In order for Ragdoll to recognise symmetry later when we edit the shapes using the Manipulator
, we'll need to assign markers in a symmetrical pose.
Translate X
and Translate Z
to 0Select -> Select Hierarchy
Assume Preferred Angle
In this case, I'm ignoring fingers along with the center joint in each limb, like the lower arms and upper legs.
From here, we can move our simulation to frame to 1
. We don't need frame 0
anymore.
In this tutorial, we're only going to worry about the upper body, so let's turn those legs into 100% animation via the Animated
behaviour.
The stage is set, it's time to tune!
"},{"location":"tutorials/mocap_chap/#shapes","title":"Shapes","text":"Nothing special here, and since we have no geometry to fill we have some creative freedom in how we want our character to look!
Let's have a look at where defaults values gets us.
Not bad! But since we want our simulation to be close to the original mocap, we'll need to make some changes.
"},{"location":"tutorials/mocap_chap/#stiffness-and-substeps","title":"Stiffness and Substeps","text":"The default solver substeps and iterations get you to a Stiffness
of about 10
. In order to achieve a higher stiffness, we'll need more of those.
rSolver
Substeps = 8
Iterations = 8
Hips_rGroup
Rotate Stiffness = 40
Rotate Damping = 0.25
Let's get the box in on the action.
"},{"location":"tutorials/mocap_chap/#attach-hands-to-box","title":"Attach Hands to Box","text":"He does a good job holding onto that box through friction between hand and box alone, but let's help him out by \"glueing\" the two together using a Distance Constraint
Ragdoll -> Constrain -> Distance
The default distance will be From Start
, meaning it will try and keep whatever the distance was between the box and the hands at the start of the simulation.
What we want however is for the Maximum
distance to be 0
, and for it to only start having an effect once the hands overlap the box.
Now let's edit the point at which the hand and box snap together.
Parent Offset
Since we selected the box first, it is considered the \"parent\".
"},{"location":"tutorials/mocap_chap/#animate-on-and-off","title":"Animate On and Off","text":"Next, let's activate this constraint once hands are in place.
80
Stiffness = 0
81
Stiffness = 0.5
Likewise, we'll want the hands to release the box at some point later.
178
Stiffness = 0.5
179
Stiffness = 0
And that's it! We've now massaged our original motion capture into carrying a box of similar weight to the motion.
Let's make some changes and see what happens.
"},{"location":"tutorials/mocap_chap/#more-mass","title":"More Mass","text":"What if the box was heavier?
rMarker_pCube1
in the Channel BoxT
on your keyboardMass = 10
When tuning single values like this, it can be helpful to leave the Maya timeline in place and let the simulation update independently.
"},{"location":"tutorials/mocap_chap/#next-steps","title":"Next Steps","text":"At this point, you're able to turn any old motion capture hierarchy into a partial or fully-fledged ragdoll. Why not try a few more from the Content Browser? Or download any of the hundreds of freely available clips from here.
In this tutorial, we'll rig a character from scratch and assign meshes and limits to it.
Version 1.0 - Up to date
Written for Ragdoll 2022.03.14
and above.
Estimated Time
You will need
You will learn
Where to find help
If you find or run into any issues with these tutorials, here's what you can do.
Here's the video on YouTube.
This technique applies to any mesh you can find and is suitable for animators to go at themselves, so go crazy!
"},{"location":"tutorials/rookie_wasp/","title":"Rookie Wasp","text":""},{"location":"tutorials/rookie_wasp/#rookie-wasp","title":"Rookie Wasp","text":"In this tutorial, we'll make an animation cycle using Ragdoll.
Version 1.1 - Up to date
Written for Ragdoll 2021.12.13
and above.
Estimated Time
You will learn
Where to find help
If you find or run into any issues with these tutorials, here's what you can do.
See here for part 1 and 2 of this tutorial.
In this tutorial, we'll make a self-walking character using our Rhino asset.
Version 1.0 - Up to date
Written for Ragdoll 2022.03.14
and above.
Estimated Time
You will need
You will learn
Where to find help
If you find or run into any issues with these tutorials, here's what you can do.
See here for part 1 of 1 this tutorial.
Timeline
Why not put a few of them together with Solver Linking?
Learn by watching.
The forum is a goldmine of learning material, have a look here next!
Then have a look at the videos and examples by following along with each released version of Ragdoll!
Heads up
The below were recorded just before Markers were finalised, but are still applicable to 2021.12.12 and above.
Tutorial Duration Description Markers 101 01:23 What are markers? Markers 101 - Key Concepts 03:23 Overview of Input Type and Pose Space Markers 101 - Local and World 03:00 Overview of the two Pose Spaces, local and world Overlapping Motion I 02:27 The very basics or Capture and Record Overlapping Motion II 02:21 Animation layers Full Ragdoll I 04:08 Hierarchy and volume Full Ragdoll II 04:05 Kinematic and animation Full Ragdoll III 04:30 Self collisions and recording IK I 03:00 Capturing the skeleton IK II 01:59 Retargeting to IK controls IK III 01:59 Record both Translation and Rotation Practical Example I 06:53 Fix table and elbow intersection in this dialog performance Replace Reference Workflow 01:34 An ideal workflow for Ragdoll in a production pipeline with animators."}]} \ No newline at end of file +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Home","text":"Learn
RAGDOLL
Real-time physics for Autodesk\u00ae Maya 2018-2022
Ragdoll provides animators with real-time physics for fast, automatic overlapping motion.
Learn more Download News"},{"location":"about/","title":"About","text":"
Here's a brief overview of how Ragdoll came to be.
In 2008 Marcus Ottosson graduated from BTH in Blekinge, Sweden and ventured into the world as character animator at Meindbender; to work on The Duplicators and The Pirate amongst others.
In 2012 He joined Framestore and familiarised himself with the world of physics simulation, developing the technology behind the tethers for Alfonso Cuaron's feature film Gravity, and later completed work on the Cloak of Leviation in Doctor Strange.
In 2015 He started a company called Abstract Factory developing tools in Python for use in production pipelines, including Avalon, Pyblish, Qt.py, cmdx and Allzpark; later recieving the \"Best Tool\" award for Pyblish at the 2020 DigiPro/The Pipeline Conference.
In 2017 He started a company called WeightShift with co-founders Danny Chapman and Tim Daust. They had just wrapped up the Endorphin and Euphoria projects at Natural Motion.
Like Euphoria, WeightShift developed a physically based animation tool, except this one was tailored to Autodesk Maya and got adopted by major feature film studios including Framestore (Harry Potter, Gravity et. al.) and Weta Digital (Avatar, Lord of the Rings et. al.)
In 2020 WeightShift is purchased by Epic Games
In 2020 Ragdoll enters chat
Ragdoll carries on where WeightShift left off, but turns things on its head. Rather than targeting riggers and technical animators, Ragdoll adopts a \"no-rigging required\" approach.
July 28th 2021 Ragdoll is launched.
"},{"location":"about/#london-on-craigslist","title":"London on Craigslist","text":"In 2012, Marcus travelled to London after 5 years of character animation experience in Sweden and \u00a315,000 of life savings in order to secure a job at Framestore, the studio he'd been looking up to since before venturing out into the real-world. He booked a crummy hotel around Hyde Park for 2 weeks during which time he expected to find a permanent residence somewhere in town, but it wasn't so easy! After days of viewing flats and hours after finally checking out - in desperation - he transferred a majority of his life savings for 6 months of rent up-front to a listing he found on Craigslist. That luckily wasn't a scam.
With his foot firmly on the ground, Marcus applied to work for Framestore; only to find that they weren't looking for animators! Instead, they needed \"Creature FX\" artists, to begin work right away on a project taking place in space. Creatures? In space? Done deal! That's when he learned that \"creature\" actually meant \"tether\" and FX means \"simulation\" and that the project was Gravity.
It was during that time when the character animator was introduced to physics simulation and with it an idea to bring this marvel of technology to the otherwise non-physically simulated world of character animation.
"},{"location":"about/#early-prototypes","title":"Early Prototypes","text":"With Maya and nCloth under his belt, he had all the tools necessary to begin working on an adaptation for animators. Or so he thought!
First Prototype
Utilising the Bend Resistance
and Attract to Matching Mesh
features of nCloth. The challenge was tailoring the edges such that they carried the weight of the character and the motion he was to perform. More rigidity meant less performance, thus he always ended up too squishy.
nCloth to IK
This time using follicles on the simulated geometry to derive positions for a skeleton to be attached and used to skin the final character geometry. Don't let the fps counter fool you, this version was point-cached. The interactive performance was less than 5 fps.
Alternative Setup
Same idea, now interacting with another nCloth object in the scene.
A few prototypes later, he realised this wasn't going to fly. To tackle this, one would need a firm grasp on software development, but that would take time.
As they say; two steps forward, one step back.
"},{"location":"about/#lets-start-small","title":"\"Let's start small\"","text":"Inspired by the manner and amount of automation taking place at Framestore, he set out to bring automation to the masses, using skills less reliant on maths and algorithms and more reliant on workflow.
3 years later, Pyblish is a technically and practically successful product, another 3 years it would go on to win the DigiPro 2020 award for Best Pipeline Tool, even though it would yield very little money; lessons learnt in running a business on open-source software. (Namely don't)
He was now somewhat technically savvy with a greater understanding of the challenge that lies ahead, what he needed now was a team.
"},{"location":"about/#team-avalon","title":"Team Avalon","text":"Building on his prior connections in Sweden, he reached out to the founders of a former workplace for aid. They were interested in branching out into software development and was a suitable customer to the technology I had in mind; they offered to invest. By happenstance, he found a character rigger with multiple feature film projects behind her, interested in trying something new. Finally, the technology was to be based heavily on machine learning for which he found a lecturer at Oxford University interested in dedicating time and resources to our cause.
Months of pitching at events in search for a team (Startup Weekend ftw!), everything was now in place. But there was a hitch; in order to offer investment, they wanted something in return. A pipeline. Marcus spent the next 3 months developing Avalon, which was later open sourced and is now a moderately successful pipeline framework powering dozens of studios around the globe, including Colorbleed, Moonshine and Kredenc.
Ready, set, go; the team was set, a customer waiting and investment ready to go. But there was a problem. After signing for a shared office space and days before moving in to start working, the investor couldn't live up to his end of the bargain and the deal blew up.
Two steps forward, one step back.
"},{"location":"about/#team-weightshift","title":"Team Weightshift","text":"After having to let everyone go, Marcus remembered one of the prospects he interviewed for this team; a senior figure at Natural Motion - developers of physics simulation software Endorphin and Euphoria - which was just about to be absorbed by the mobile-games goliath Zynga, scrapping their work on character animation technology.
They spent two weeks putting together a prototype of their aspirations and went on to form a company to develop WeightShift Dynamics
2 years later and WeightShift had been adopted by Weta Digital in New Zealand and Framestore in London. But there was a hitch; visions no longer aligned, conflict arose and the team disbanded.
The silver lining was that Epic Games was interested purchasing the technology, providing enough of a runway to restart development and try again.
Two steps forward, one step back.
"},{"location":"about/#team-ragdoll","title":"Team Ragdoll","text":"After a brief stint developing Allzpark for the Japanese Studio Anima and then animating for Redfall and Horizon Zero Dawn II at Goodbye Kansas it was now 2020. With funding and experience spanning animation, programming, business and now physics all the pieces were in place. What he could not do in 2012 was now made possible.
"},{"location":"api/","title":"API Reference","text":"Ragdoll consists of custom nodes written in C++, but everything involved in connecting these up and generating the dependency network happens in Python. This API is exposed to you for integration with auto-rigging, tools development and to generally just extend the capabilities of the system.
The full source code of everything Python is also available on GitHub, where you may also submit issues and pull-requests to improve the tooling for everyone.
See Also
There are 3 supported methods of integrating Ragdoll into your pipeline. Each with its own flare.
api.py
- Public interfacecommands.py
- Low-level commandsinteractive.py
- User-facing commandsThe publicly facing programming interface to Ragdoll. Use this for tools integrated with other tools that rely on heavy compatibility between versions and few surprises on what goes in and out.
maya.cmds
, including camelCase
from maya import cmds\nfrom ragdoll import api as rd\n\ncube, _ = cmds.polyCube()\ncmds.move(0, 10, 0)\ncmds.rotate(35, 50, 30)\n\nsolver = rd.createSolver()\nmarker = rd.assignMarker(cube, solver)\n\nrd.record()\n\ncmds.evalDeferred(cmds.play)\n
Member Reference
The api.py
module builds on commands.py
, but wraps it in a string-based interface so as to make it compatible with your everyday calls to maya.cmds
.
All of api.py
is present in commands.py
, along with a few extras that may or may not change over time. It is best suited for tight integration and control but is primarily used internally for implementing interactive.py
and tools.py
.
api.py
for identical memberscmdx
typescommands.py
uses the highly performant cmdx
library to communicate with Maya and all return values are instances of cmdx
.
from maya import cmds\nfrom ragdoll import commands as rc\nfrom ragdoll.vendor import cmdx\n\ncmds.file(new=True, force=True)\n\ncube, _ = map(cmdx.encode, cmds.polyCube())\ncube[\"translateY\"] = 10\ncube[\"rotate\", cmdx.Degrees] = (35, 50, 30)\n\n# Every simulation needs a solver\nsolver = rc.create_solver(\"mySolver\")\nassert isinstance(solver, cmdx.DagNode)\nassert solver.isA(\"rdSolver\")\n\n# Every solver needs one or more marker bodies\nmarker = rc.assign_marker(cube, solver)\nassert isinstance(marker, cmdx.DagNode)\nassert marker.isA(\"rdMarker\")\n\n# Allow start frame to evaluate before progressing\ncmds.evalDeferred(cmds.play)\n
"},{"location":"api/#interactivepy","title":"interactive.py","text":"Finally, this module is used for UI elements like the main Ragdoll menu. Every function takes selection into account, along with any preferences set via the Option Dialogs.
It's useful for when you want to replicate what the menu does, including taking selection into account and outputting warning messages in the Script Editor. It won't raise exceptions like api
and commands
, instead each function return either True
for success or nothing for failure. Failures typically follow one or more warning messages.
from maya import cmds\nfrom ragdoll import interactive as ri\n\ncube, _ = cmds.polyCube()\ncmds.move(0, 10, 0)\ncmds.rotate(35, 50, 30)\n\ncmds.select(cube)\nri.assign_marker()\n\ncmds.evalDeferred(cmds.play)\n
Pro Tip
Whenever you click a menu item, this Python command is printed in the Script Editor!
"},{"location":"api/#members","title":"Members","text":"Currently available members of ragdoll.api
.
help()
for usage instructions# Fundamentals\napi.createSolver(name=\"mySolver\")\napi.assignMarker(transform, solver)\napi.assignMarkers([transform1, transform2], solver)\n\n# Constraints\napi.createFixedConstraint(marker1, marker2)\napi.createDistanceConstraint(marker2, marker2)\napi.createPinConstraint(marker1)\n\n# Edit\napi.reconnect(child_marker, parent_marker)\napi.retarget(marker, new_transform)\napi.replaceMesh(marker, new_mesh)\n\n# IO\napi.recordPhysics()\napi.exportPhysics()\napi.reinterpretPhysics() # A.k.a. Import Physics\napi.extractPhysics()\n
"},{"location":"api/#environment-variables","title":"Environment Variables","text":"Gain more control over the integration of Ragdoll into your pipeline with these optional environment variables. For example, to avoid the startup dialog on first launch, set RAGDOLL_NO_STARTUP_DIALOG=1
before loading the plug-in.
MAYA_PLUG_IN_PATH
\"ragdoll\"
RAGDOLL_NO_STARTUP_DIALOG Do not display the startup-dialog on first launch. False
RAGDOLL_AUTO_SERIAL Automatically activate Ragdoll on install using this serial number. Unset RAGDOLL_TELEMETRY Help development by uploading usage data. Enabled for non-commercial licences, optional for commercial licences."},{"location":"api_reference/","title":"Api reference","text":""},{"location":"api_reference/#api-member-reference","title":"API Member Reference","text":"The complete Ragdoll API.
from maya import cmds\nimport ragdoll.api as rd\n\nbox = cmds.polyCube()\n\nsolver = rd.createSolver()\nmarker = rd.assignMarker(box[0], solver)\n\nrd.recordPhysics()\n
Function Description createSolver Create a new rdSolver node createGroup Create a new group under solver
with name
and opts
assignMarkers Assign markers to transforms
belonging to solver
assignMarker Convenience function for passing and recieving a single transform
createDistanceConstraint Create a new distance constraint between parent
and child
createPinConstraint Create a new constraint for parent
and optionally parent
createFixedConstraint Create a new fixed constraint between parent
and child
linkSolver Link solver a
with b
unlinkSolver Unlink solver
retargetMarker Retarget marker
to transform
untargetMarker Remove parent from child
reparentMarker Make new_parent
the new parent of child
unparentMarker Remove parent from child
replaceMesh Replace the 'Mesh' shape type in marker
with mesh
. assignCollisionGroup Assign markers
to a new collision group
addToCollisionGroup Assign markers
to a new collision group
removeFromCollisionGroup Assign markers
to a new collision group
exportPhysics Export everything Ragdoll-related into fname
importPhysics Recreate Maya scene from exported Ragdoll file updatePhysics Update existing physics from an exported Ragdoll file recordPhysics Transfer simulation from solver
to animation land reinterpretPhysics Recreate Maya scene from exported Ragdoll file loadPhysics Create a Maya scene from an exported Ragdoll file extractPhysics Generate an animated joint hierarchy from solver
deletePhysics Delete Ragdoll from anything related to nodes
deleteAllPhysics Nuke it from orbit "},{"location":"api_reference/#argument-signatures","title":"Argument Signatures","text":"A more in-depth view on each function.
"},{"location":"api_reference/#createsolver","title":"createSolver","text":"Create a new rdSolver node
def createSolver(name, opts):\n \"\"\"Create a new rdSolver node\n ____\n / \\\n / | |\n ---/----\\____/\n / /\n ---/-------/---\n / /\n\n The solver is where the magic happens. Markers are connected to it\n and solved within; populating its .outputMatrix attribute with the\n final result.\n\n Arguments:\n name (str, optional): Override the default name of this solver\n opts (dict, optional): Configure the solver with these options\n\n Options:\n frameskipMethod (int): Method to use whenever a frame is skipped,\n can be either api.FrameskipPause or api.FrameskipIgnore\n\n \"\"\"\n
"},{"location":"api_reference/#creategroup","title":"createGroup","text":"Create a new group under solver
with name
and opts
def createGroup(solver, opts):\n \"\"\"Create a new group under `solver` with `name` and `opts`\n\n Arguments:\n solver (rdSolver): Owning solver of this group\n name (str, optional): A custom name for this group\n opts (dict, optional): Default attributes of this group\n\n Options:\n selfCollide (bool): Whether or not members of this\n group should collide with each other.\n\n \"\"\"\n
"},{"location":"api_reference/#assignmarkers","title":"assignMarkers","text":"Assign markers to transforms
belonging to solver
def assignMarkers(transforms, solver, opts):\n \"\"\"Assign markers to `transforms` belonging to `solver`\n\n Each marker transfers the translation and rotation of each transform\n and generates its physical equivalent, ready for recording.\n\n Arguments:\n transforms (list): One or more transforms to assign markers onto\n solver (rdSolver or rdGroup): Add newly created markers to this solver\n opts (dict, optional): Options, see below\n\n Options:\n autoLimit (bool): Transfer locked channels into physics limits\n preventIdenticalMarker (bool): Skip transforms with identical position\n and orientation, typically sub-controls.\n defaults (dict): Key/value pairs of default attribute values\n\n \"\"\"\n
"},{"location":"api_reference/#assignmarker","title":"assignMarker","text":"Convenience function for passing and recieving a single transform
def assignMarker(transform, solver, opts):\n \"\"\"Convenience function for passing and recieving a single `transform`\n\n \"\"\"\n
"},{"location":"api_reference/#createdistanceconstraint","title":"createDistanceConstraint","text":"Create a new distance constraint between parent
and child
def createDistanceConstraint(parent, child, opts):\n \"\"\"Create a new distance constraint between `parent` and `child`\n\n \"\"\"\n
"},{"location":"api_reference/#createpinconstraint","title":"createPinConstraint","text":"Create a new constraint for parent
and optionally parent
def createPinConstraint(child, parent, opts):\n \"\"\"Create a new constraint for `parent` and optionally `parent`\n\n Arguments:\n child (rdMarker): Affected Marker\n parent (rdMarker, optional): Attach child to parent, otherwise to world\n transform (dagNode, optional): Parent the constraint shape node here\n opts (dict, optional): User options\n\n \"\"\"\n
"},{"location":"api_reference/#createfixedconstraint","title":"createFixedConstraint","text":"Create a new fixed constraint between parent
and child
def createFixedConstraint(parent, child, opts):\n \"\"\"Create a new fixed constraint between `parent` and `child`\n\n \"\"\"\n
"},{"location":"api_reference/#linksolver","title":"linkSolver","text":"Link solver a
with b
def linkSolver(a, b, opts):\n \"\"\"Link solver `a` with `b`\n\n This will make `a` part of `b`, allowing markers to interact.\n\n Arguments:\n a (rdSolver): The \"child\" solver\n b (rdSolver): The \"parent\" solver\n\n Returns:\n Nothing\n\n \"\"\"\n
"},{"location":"api_reference/#unlinksolver","title":"unlinkSolver","text":"Unlink solver
def unlinkSolver(solver, opts):\n \"\"\"Unlink `solver`\n\n From any other solver it may be connected to.\n\n Arguments:\n a (rdSolver): The solver to unlink from any other solver\n\n Returns:\n Nothing\n\n \"\"\"\n
"},{"location":"api_reference/#retargetmarker","title":"retargetMarker","text":"Retarget marker
to transform
def retargetMarker(marker, transform, opts):\n \"\"\"Retarget `marker` to `transform`\n\n When recording, write simulation from `marker` onto `transform`,\n regardless of where it is assigned.\n\n \"\"\"\n
"},{"location":"api_reference/#untargetmarker","title":"untargetMarker","text":"Remove parent from child
def untargetMarker(marker, opts):\n \"\"\"Remove parent from `child`\n\n Meaning `child` will be a free marker, without a parent.\n\n \"\"\"\n
"},{"location":"api_reference/#reparentmarker","title":"reparentMarker","text":"Make new_parent
the new parent of child
def reparentMarker(child, parent, opts):\n \"\"\"Make `new_parent` the new parent of `child`\n\n Arguments:\n child (rdMarker): The marker whose about to have its parent changed\n new_parent (rdMarker): The new parent of `child`\n\n \"\"\"\n
"},{"location":"api_reference/#unparentmarker","title":"unparentMarker","text":"Remove parent from child
def unparentMarker(child, opts):\n \"\"\"Remove parent from `child`\n\n Meaning `child` will be a free marker, without a parent.\n\n \"\"\"\n
"},{"location":"api_reference/#replacemesh","title":"replaceMesh","text":"Replace the 'Mesh' shape type in marker
with mesh
.
def replaceMesh(marker, mesh, opts):\n \"\"\"Replace the 'Mesh' shape type in `marker` with `mesh`.\n\n Arguments:\n marker (cmdx.Node): Rigid whose mesh to replace\n mesh (cmdx.Node): Mesh to replace with\n clean (bool, optional): Remove other inputs, such as curve\n or surface node. Multiple inputs are supported, so this\n is optional. Defaults to True.\n\n Returns:\n Nothing\n\n \"\"\"\n
"},{"location":"api_reference/#assigncollisiongroup","title":"assignCollisionGroup","text":"Assign markers
to a new collision group
def assignCollisionGroup(markers, group, delete_orphans):\n \"\"\"Assign `markers` to a new collision `group`\n\n Arguments:\n markers (list): Markers to assign\n group (rdCollisionGroup, optional): The group to add Markers to,\n if none is given a new one is created.\n delete_orphans (bool, optional): Delete any orphaned groups\n\n \"\"\"\n
"},{"location":"api_reference/#addtocollisiongroup","title":"addToCollisionGroup","text":"Assign markers
to a new collision group
def addToCollisionGroup(markers, group, delete_orphans):\n \"\"\"Assign `markers` to a new collision `group`\n\n Arguments:\n markers (list): Markers to assign\n group (rdCollisionGroup, optional): The group to add Markers to,\n if none is given a new one is created.\n delete_orphans (bool, optional): Delete any orphaned groups\n\n \"\"\"\n
"},{"location":"api_reference/#removefromcollisiongroup","title":"removeFromCollisionGroup","text":"Assign markers
to a new collision group
def removeFromCollisionGroup(markers, group, delete_orphans):\n \"\"\"Assign `markers` to a new collision `group`\n\n Arguments:\n markers (list): Markers to assign\n group (rdCollisionGroup, optional): The group to add Markers to,\n if none is given a new one is created.\n delete_orphans (bool, optional): Delete any orphaned groups\n\n \"\"\"\n
"},{"location":"api_reference/#exportphysics","title":"exportPhysics","text":"Export everything Ragdoll-related into fname
def exportPhysics(fname, opts):\n \"\"\"Export everything Ragdoll-related into `fname`\n\n Arguments:\n fname (str, optional): Write to this file,\n or console if no file is provided\n data (dict, optional): Export this dictionary instead\n\n Returns:\n data (dict): Exported data as a dictionary\n\n \"\"\"\n
"},{"location":"api_reference/#importphysics","title":"importPhysics","text":"Recreate Maya scene from exported Ragdoll file
def importPhysics(fname, opts):\n \"\"\"Recreate Maya scene from exported Ragdoll file\n\n User-interface attributes like `density` and display settings\n are restored from a file otherwise mostly contains the raw\n simulation data.\n\n \"\"\"\n
"},{"location":"api_reference/#updatephysics","title":"updatePhysics","text":"Update existing physics from an exported Ragdoll file
def updatePhysics(fname, opts):\n \"\"\"Update existing physics from an exported Ragdoll file\n\n \"\"\"\n
"},{"location":"api_reference/#recordphysics","title":"recordPhysics","text":"Transfer simulation from solver
to animation land
def recordPhysics(solver, opts):\n \"\"\"Transfer simulation from `solver` to animation land\n\n Options:\n start_time (int, optional): Record from this time\n end_time (int, optional): Record to this time\n include (list, optional): Record these transforms only\n exclude (list, optional): Do not record these transforms\n kinematic (bool, optional): Record kinematic frames too\n maintain_offset (bool, optional): Maintain whatever offset is\n between the source and destination transforms, default\n value is True\n\n \"\"\"\n
"},{"location":"api_reference/#reinterpretphysics","title":"reinterpretPhysics","text":"Recreate Maya scene from exported Ragdoll file
def reinterpretPhysics(fname, opts):\n \"\"\"Recreate Maya scene from exported Ragdoll file\n\n User-interface attributes like `density` and display settings\n are restored from a file otherwise mostly contains the raw\n simulation data.\n\n \"\"\"\n
"},{"location":"api_reference/#loadphysics","title":"loadPhysics","text":"Create a Maya scene from an exported Ragdoll file
def loadPhysics(fname, opts):\n \"\"\"Create a Maya scene from an exported Ragdoll file\n\n New transforms are generated and then assigned Markers.\n\n \"\"\"\n
"},{"location":"api_reference/#extractphysics","title":"extractPhysics","text":"Generate an animated joint hierarchy from solver
def extractPhysics(solver, opts):\n \"\"\"Generate an animated joint hierarchy from `solver`\n\n This will generate a new joint hierarchy and apply the full\n simulation as keyframes onto it, for a complete replica of\n the simulation in a Ragdoll-independent way.\n\n \"\"\"\n
"},{"location":"api_reference/#deletephysics","title":"deletePhysics","text":"Delete Ragdoll from anything related to nodes
def deletePhysics(nodes):\n \"\"\"Delete Ragdoll from anything related to `nodes`\n\n This will delete anything related to Ragdoll from your scenes, including\n any attributes added (polluted) onto your animation controls.\n\n Arguments:\n nodes (list): Delete physics from these nodes\n dry_run (bool, optional): Do not actually delete anything,\n but still run through the process and throw exceptions\n if any, and still return the results of what *would*\n have been deleted if it wasn't dry.\n\n \"\"\"\n
"},{"location":"api_reference/#deleteallphysics","title":"deleteAllPhysics","text":"Nuke it from orbit
def deleteAllPhysics():\n \"\"\"Nuke it from orbit\n\n Return to simpler days, days before physics, with this one command.\n\n \"\"\"\n
"},{"location":"api_reference/#constants","title":"Constants","text":"Some functions take constants for arguments.
from ragdoll import api\napi.assign_marker(a, b, opts={\"density\": api.DensityFlesh})\n
Constant Value FrameskipPause 0 FrameskipIgnore 1 DisplayDefault 0 DisplayWire 1 DisplayConstant 2 DisplayShaded 3 DisplayMass 4 DisplayFriction 5 DisplayRestitution 6 DisplayVelocity 7 DisplayContacts 8 InputInherit 0 InputKinematic 2 InputDynamic 3 PGSSolverType 0 TGSSolverType 1 BoxShape 0 SphereShape 1 CapsuleShape 2 MeshShape 4 ConvexHullShape 4 DensityOff 0 DensityCotton 1 DensityWood 2 DensityFlesh 3 DensityUranium 4 DensityBlackHole 5 DensityCustom 6 StartTimeRangeStart 0 StartTimeAnimationStart 1 StartTimeCustom 2 Lod0 0 Lod1 1 Lod2 2 LodCustom 3 MatchByName 0 MatchByHierarchy 1 RecordConstraintMethod 0 RecordMatchMethod 1 InputOff 3 InputGuide 3"},{"location":"blender-beta/","title":"Blender Beta","text":"Thanks to Blender Studio for the Dragonfly rig \u2764\ufe0f
"},{"location":"blender-beta/#beta-testing-ragdoll-in-blender","title":"Beta Testing Ragdoll in Blender \ud83e\udd73","text":""},{"location":"blender-beta/#welcome","title":"Welcome","text":"Ragdoll is a real-time physics solver for Maya, and now it's coming to Blender. At this moment, we are working hard to port features from the Maya version of Ragdoll into the Blender one. In the meantime, we invite you to join us in shaping its final form for Blender animators!
"},{"location":"blender-beta/#addon-status","title":"AddOn Status","text":"Blender Version Windows macOS (Intel) macOS (Apple Silicon) Linux 3.4 \u2705 \u2705 \u2705 \u274c 3.5 \u2705 \u274c \u274c \u274c"},{"location":"blender-beta/#a-quick-warm-up","title":"A Quick Warm Up","text":"From left to right:
And that's basically what Ragdoll is for \u2014 adding the fun of physics to your animation workflow!
To learn more about this Ragdoll Dragonfly, read below!
"},{"location":"blender-beta/#interface","title":"Interface","text":"Since we are playing with physics, you can find Ragdoll in the Physics Properties
tab, if the current active object is compatible with Ragdoll.
What types of things can work with Ragdoll (assign marker to)?
At this moment, only Mesh-type objects and Pose-Bones can. NURBS or Empty may be supported in the future.
Mesh
When the current active object is already in Ragdoll, the Physics Properties
tab will display associated properties.
Pose Bone
To work with Pose-Bones, enter Pose Mode
and select the bone you want to use with Ragdoll.
You can, and mostly would, select multiple bones and click on the Assign and Connect
button. It will give you a chain of markers.
Note that the Ragdoll solver (and all its friends) can be found in a collection called RagdollCol
. The solver node is responsible for simulating physical interactions between all its associated markers and more.
Currently, when clicking the Assign and Connect
button with multiple objects/pose-bones, a Group is created with them.
A group allows you to batch tweak some common properties like Stiffness
and Damping
for convenience.
Please visit the Learn Ragdoll website for more details about them. Especially this page which discusses the cornerstone of Ragdoll \u2014 Marker.
"},{"location":"blender-beta/#manipulator-tool","title":"Manipulator Tool","text":"The Ragdoll manipulator tool provides a direct way to tweak some common marker properties. It will become more feature-rich in the future, and you can expect to spend more time using it when working with Ragdoll.
The tool can be activated through here:
And the solver node needs to be selected to bring up the GUI.
"},{"location":"blender-beta/#tips-to-make-dragonfly-fly","title":"Tips to Make Dragonfly Fly","text":"Full walkthrough video: https://www.youtube.com/watch?v=vAAiqxYW9Us
Here's a short list of tips that could help:
"},{"location":"blender-beta/#connecting-marker","title":"Connecting Marker","text":"When assigning multiple markers, those markers will be chained together, and the first one will be set to Kinematic. And if a marker's behavior is set to Kinematic, it will 100% follow the input animation.
Since we will only apply an up-down movement to the rig base, just pick the torax (chest) of the Dragonfly for the first marker to follow that animation.
Then, when assigning the next chain of markers, remember to also start from that torax bone.
"},{"location":"blender-beta/#offset-solver","title":"Offset Solver","text":"Other than changing the Display Type
property to Wire
in the Solver for a cleaner view, sometimes you may want a side-by-side view when editing markers. If that's the case, simply move the Solver node and all the marker shapes will step aside.
You may want to uncheck Lock Object Modes
for faster object and bone selection.
Once done, move back and then activate the Manipulator tool for matching marker shapes to geometry.
"},{"location":"blender-beta/#ik-legs","title":"IK Legs","text":"You may also reference this page.
Simply put, we don't want to assign markers directly to IK controllers since physics is more like an FK thing. So instead, we would assign them to the bones that are driven by IK controls.
With this Dragonfly rig, although we can find them, they are basically locked. To work around that, the idea is to add an extra bone (the gray one in the middle) and make our own FK to drive IK.
"},{"location":"blender-beta/#scene-scale","title":"Scene Scale","text":"This Dragonfly is quite a big one. To get a much real-world result, we have to tune down the scene scale.
That's it!
We hope you have fun, and please don't hesitate to ask questions on the forum!
"},{"location":"crack-torrent/","title":"Ragdoll Crack Torrent","text":"Looking for a crack for Ragdoll, to use it for free without reprocussions? Look no further! Here's a torrent you can use to download it for free.
The Record Simulation
command consists of 4 steps.
Extract
Extract Simulation onto a new joint hierarchy 2 Attach
Constrain rig controls to joint hierarchy 3 Bake
Call cmds.bakeResults
4 Cleanup
Delete joint hierarchy and constraints The final result is keyframes on the rig controls, in a new Animation Layer.
Version 2.0 - Up to date
Written for Ragdoll 2022.05.04
and above.
Here's what it looks like to do manually, for 1 control.
Repeat the Attach
step for each control, and take locked channels into account, and you've entirely replicated what Record Simulation
does.
The Attach
step can be overridden to accommodate for custom constraints, for when your studio rigs cannot use the native cmds.parentConstraint
and cmds.orientConstraint
nodes that ship with Maya.
Here's how it works.
# 1 - Import the Record Simulation command\nfrom ragdoll import recording\n\n# 2 - Write your own command to attach\ndef custom_attach(...):\n ...\n\n# 3 - Replace the default attach\nrecording._Recorder._attach = custom_attach\n
Here's an example of the default implementation, pay special attention to the calls to cmds.parentConstraint
and cmds.orientConstraint
; these are the ones you want to replace with your own commands.
from ragdoll.vendor import cmdx\nfrom ragdoll import recording\n\n\ndef custom_attach(self, marker_to_dagnode):\n \"\"\"Constrain rig controls to simulation\n\n Arguments:\n marker_to_dagnode (dict): Dictionary with marker: dagnode, the dagnode\n is the animation control, e.g. L_hand_ctl\n\n Returns:\n new_constraints (list): Newly created constraints as cmdx.Node instances\n\n \"\"\"\n\n # Constraints created by this function\n # This list is used to delete the constraints after recording is complete\n new_constraints = []\n\n # Attach animation controls at the start time,\n # that's where the simulation and animation overlap\n initial_time = cmdx.current_time()\n cmdx.current_time(self._solver_start_frame)\n\n for dst, marker in self._dst_to_marker.items():\n src = marker_to_dagnode.get(marker, None)\n\n if not src:\n continue\n\n # dst == your rig control\n # src == the extracted transform\n\n skip_rotate = set()\n skip_translate = set()\n\n for chan, plug in zip(\"xyz\", dst[\"rotate\"]):\n if plug.locked:\n skip_rotate.add(chan)\n\n for chan, plug in zip(\"xyz\", dst[\"translate\"]):\n if plug.locked:\n skip_translate.add(chan)\n\n if skip_translate != {\"x\", \"y\", \"z\"}:\n\n #\n # REPLACE ME\n #\n pcon = cmds.parentConstraint(\n src.shortest_path(),\n dst.shortest_path(),\n maintainOffset=True,\n skipTranslate=list(skip_translate) or \"none\",\n skipRotate=list(\"xyz\"),\n )\n\n # Store reference to this node\n pcon = cmdx.encode(pcon[0])\n new_constraints.append(pcon)\n\n if skip_rotate != {\"x\", \"y\", \"z\"}:\n\n #\n # REPLACE ME\n #\n ocon = cmds.orientConstraint(\n src.shortest_path(),\n dst.shortest_path(),\n maintainOffset=True,\n skip=list(skip_rotate) or \"none\",\n )\n\n ocon = cmdx.encode(ocon[0])\n new_constraints.append(ocon)\n\n cmdx.current_time(initial_time)\n\n return new_constraints\n\n\n# Store original attach, just in case\ntry:\n old_attach\nexcept NameError:\n old_attach = recording._Recorder._attach\n\n# Replace with custom implementation\nrecording._Recorder._attach = custom_attach\n
"},{"location":"custom-attach/#usage","title":"Usage","text":"Copy/paste the above snippet into your Script Editor and call Record Simulation
. Nothing should have changed, because the above is a near-exact copy of the original.
From here, start editing the snippet. Keep executing the script in your Script Editor as you make changes, and call Record Simulation
from the Ragdoll
menu to try it out.
To restore the original implementation, either use old_attach
or reload the plug-in.
The src
variable is the extracted simulation, the joint. The dst
variable is your rig control, what you want to constrain to src
. The skip_translate
and skip_rotate
variables are two sets
containing the channels on your rig controls were locked (if any). Use these if your constraint commands needs them (like cmds.parentConstraint
does).
The default implementation uses cmds.parentConstraint
for the Translate
channels, and cmds.orientConstraint
for the Rotate
channels to accommodate for when one or more Rotate
channels are locked. As it happens, the cmds.parentConstraint
produces gimbal locks in situations like that.
You may use a single constraint command for all channels, if available, to try and see whether those also run into gimbal issues - such as randomly flipping 180 degrees. If they do, consider using a different constraint for the rotate channel.
"},{"location":"custom-attach/#return-value","title":"Return Value","text":"The command MUST return new_constraint
which MUST be of list
type and contain any and all nodes created by this function. In the default implementation, we call on maya.cmds
to create the constraint, but convert the resulting string
types to cmdx.Node
via cmdx.encode()
. You MUST do the same.
See the original command, along with available members of self
on GitHub.
mottosso/ragdoll/ragdoll/tools/markers_tool.py
Read all about each feature of Ragdoll in detail here.
Here I'll collect any third-party tutorials written or recorded for Ragdoll.
Resource Description Review by Amedeo Beretta General overview, covering the basics of the tool just as it's coming out of private early access"},{"location":"download/","title":"Download","text":"DownloadPick an integration
Autodesk Maya 2019-2024
DownloadBlender 3.4-4.0
DownloadRagdoll Core Installer
DownloadRagdoll Core Python SDK
Read MoreRagdoll Core C++ SDK
Coming SoonJoin the community of ragdollers on Discord and/or Discourse.
Chat Forums"},{"location":"examples/","title":"Examples","text":""},{"location":"examples/#examples","title":"Examples","text":"Download and have a go!
6.78 mb
Example 1 | Just a Girl An example of hair simulation with Ragdoll.
Download2.93 mb
Example 2 | mGirl An example of cloth simulation with Ragdoll.
Download2.77 mb
Example 3 | Muscle An example of muscle simulation with Ragdoll.
Download1.18 mb
Example 4 | Overview Some basic object types to fool around with.
Download0.16 mb
Example 5 | Parkour An animated Ragdoll \"parkour\" character.
Download4.15 mb
Example 6 | mHair Basic character setup with basic hair controls.
Download0.44 mb
Example 7 | Mechanical An accurate mechanical contraption.
Download0.40 mb
Example 8 | Driving A late night drive on a busy country road.
Download0.05 mb
Example 9 | Dynamic Control A regular animation control. With dynamics!
Download2.91 mb
Example 10 | Dance, Baby Fool around with guide strength to affect this dance performance!
Download0.24 mb
Example 11 | Slowmo Manipulate time with the timeMultiplier
attribute.
Congratulations on your purchase of a floating licence for Ragdoll Dynamics!
"},{"location":"floating-licence/#overview","title":"Overview","text":"This page will help you get set-up with a licence server, on-premise, and instruct Ragdoll to \"lease\" a licence from it. The server itself can run on any machine and any platform, including Windows, Linux and MacOS, so long as it is accessible from the machine running Ragdoll.
Windows, Linux and MacOS
The server can run on a different operating system than your workstations. For example, a common scenario is having the server running on Linux and workstations run on a combination of Windows, MacOS and Linux.
On each platform, the procedure is the same.
Product Key
The server will need to remain running in order for Ragdoll to lease licences.
"},{"location":"floating-licence/#linux","title":"Linux","text":"Here's a typical series of commands for an x64 system, look inside the .zip for alternative Linux-based platforms.
Requirements
Make sure you have unzip
and wget
at the ready, or use alternatives like curl
and tar
at your own leisure.
mkdir turbofloat\ncd turbofloat\nwget https://files.ragdolldynamics.com/api/public/dl/hAlavAOP/TurboFloat-Server-Linux.zip\nwget https://files.ragdolldynamics.com/api/public/dl/6lMDDMdn/TurboActivate.dat\nunzip TurboFloat-Server-Linux.zip\nmv bin-linux/x64/turbofloatserver ./\nchmod +x turbofloatserver\n./turbofloatserver -a=\"YOUR-SERIAL-NUMBER\"\n./turbofloatserver -x\n# Floating license server for Ragdoll Dynamics (TFS v4.4.4.0)\n
You can optionally pass -silent
after -x
for less verbosity.
The licence server can be activated offline.
From here, you'll likely want turbofloatserver -x
called automatically on reboot, such that Ragdoll and Maya can lease licences from it. The exact procedure varies between Linux distributions and company preferences, see the systemd section for tips on the most common approach.
More Details
Here's what you need to do in order to run the licence server on the Windows platform.
"},{"location":"floating-licence/#download","title":"Download","text":"TurboFloat-Server-Windows.zip
Inside of this file you will find this.
Edit the .xml
file with a port
you would like to use.
Port number
Make note of this port number as you will need it later when connecting to it from Maya.
64-bit Server
If you need a 32-bit version of the server, find the appropriate TurboFloat
binaries here.
Next we'll need to activate the server. Open a cmd.exe
or PowerShell prompt and type in the following.
TurboFloatServer.exe -a=\"YOUR-SERIAL-NUMBER\"\n
There should be no output from the command, unless there's a problem.
No internet?The licence server can be activated offline.
Now you're ready to launch the server!
"},{"location":"floating-licence/#start","title":"Start","text":"This next command will launch the server.
TurboFloatServer.exe -x\n# Floating license server for Ragdoll Dynamics (TFS v4.4.3.0)\n
Test
This is a good place to test Ragdoll from within Maya, so scroll to the Maya section, test it out and then come back here to finish things up.
All good? Great.
Optional
At this point, you can optionally have the server restart itself and run in the background by installing it as a \"service\".
TurboFloatServer.exe -i\n# 2021-05-12, 07:47:26 <error>: OpenSCManager failed (5)\n
To do that, you'll need to launch PowerShell/cmd as Administrator.
# As Administrator\nTurboFloatServer.exe -i\n# 2021-05-12, 07:48:40 <notification>: Service installed successfully.\n
From here you can try launching Ragdoll Dynamics in Maya to see whether it manages to successfully lease a licence.
More Details
With a licence server running, your next step is having Ragdoll connect to it.
On each platform, the procedure is the same.
RAGDOLL_FLOATING
Example
# From Python\nos.environ[\"RAGDOLL_FLOATING\"] = \"127.0.0.1:13\"\ncmds.loadPlugin(\"ragdoll\")\n
# From an environment like bash\nexport RAGDOLL_FLOATING=127.0.0.1:13\nmaya\n
The format of RAGDOLL_FLOATING
is <ip-address>:<port-number>
.
Everything ok?
Failed to initialise floating licenceIf this message appears in your Script Editor upon loading the plug-in, take a closer look at your Output Window on Windows or terminal on Unix.
# Error: ragdoll._install_floating() - Failed to initialise floating licence, error code '1' #\n
Could not load ragdollfloat.dll Windows users may experience this issue, which indicates a broken install. In your distribution, you should have seen both a ragdoll.mll
and ragdollfloat.dll
. Make sure this file exists, else contact us and we'll help you sort it.
Just like with a node-locked licence, you can control the leasing of licences via Python.
from ragdoll import licence\n\n# Activate this machine\nlicence.request_lease()\n\n# Deactivate this machine\nlicence.drop_lease()\n
"},{"location":"floating-licence/#troubleshooting","title":"Troubleshooting","text":"Let's have a look at a few common errors and how to solve them.
"},{"location":"floating-licence/#failed-to-save-activation-request","title":"Failed to Save Activation Request","text":"This can happen when attempting to generate an activation request for offline activation.
./turbofloatserver -a=\"KWVT-U5RS-...\" -areq=\"/bad/path/request.xml\"\n# <error>: Failed to save the activation request file.\n# <error>: Error code 0x1. Contact support or your system administrator.\n
The path given, in this case /bad/path/request.xml
might not be writable. Try a different path.
This can happen when attempting to activate a floating licence
./turbofloatserver -a=\"KWVT-U5RS-...\"\n# <error>: Failed to load the product details file.\n# <error>: Failed to load the settings.\n
The turbofloatserver
executable wasn't able to find the TurboActivate.dat
file. This file should reside in the same folder as turbofloatserver
and can be downloaded from here.
Let's cover some common scenarios.
"},{"location":"floating-licence/#how-can-i-test-connectivity-between-my-machines","title":"How can I test connectivity between my machines?","text":"To test whether machine A is accessible from machine B, try ping
.
ping 10.0.0.13\n# Reply from 10.0.0.13: bytes=32 time=1ms TTL=117\n
"},{"location":"floating-licence/#can-i-limit-the-internet-access-of-my-licence-server","title":"Can I limit the internet access of my licence server?","text":"If you're in a secure network, you may want to limit the licence server to the least amount of external access. You can do so by \"whitelisting\" it in your firewall, using this URL and port number.
https://wyday.com
443
More details here: https://wyday.com/limelm/help/turbofloat-server/
"},{"location":"floating-licence/#can-i-activate-my-server-offline","title":"Can I activate my server offline?","text":"Lifetime licences, yes. Monthly licences, no.
Like node-locked licences, the floating licence server can be activated without an internet connection to the machine running the server.
The procedure is the same on each platform.
Here's how to generate the request.
./turbofloatserver -areq=\"/path/to/ActivationRequest.xml\" -a=\"YOUR-SERIAL-NUMBER\"\n
And here's how to apply the response.
./turbofloatserver -aresp=\"/path/to/ActivationResponse.xml\" -a\n
Absolute Path
Take care to replace the path in the above commands, and use an absolute path rather than anything relative or special such as ~/
. The turbofloatserver
command can get a little cranky about those things.
If you are offline and changes has been made to your licence on our end, such as the number of seats changing or a new expiry date has been set, here is what you need to do.
1. Deactivate locally and remotely
Run the following command, replacing the path with one that can be written to.
./turbofloatserver -deact=\"/path/to/DeactivationRequest.xml\"\n
This should generate the file DeactivationRequest.xml
that should look something like this.
<DeactivationRequest>blablabla</DeactivationRequest>\n
Now paste the contents of this file into to https://ragdolldynamics.com/offline along with your serial and press Deactivate.
Your licence is now deactivated both on locally and remotely.
Warning
If you forget to pass the DeactivationRequest.xml
into the offline deactivation page, Ragdoll will not know about your deactivation. It will continue to believe that your licence remains activated, and may prevent you from activating it twice.
If this happens, contact us such that we can manually deactivate your licence on our end.
2. Activate
Next, follow the steps in Can I activate my server offline as usual.
"},{"location":"floating-licence/#how-do-i-reactivate-my-licence-online","title":"How do I reactivate my licence online?","text":"If your licence has been activated online and has been updated on our end, you may need to reactivate your licence.
./turbofloatserver -deact\n./turbofloatserver -a=\"KWVT-U5RS-...\"\n
This will refresh your local licence with whatever changes occured on our end.
"},{"location":"floating-licence/#failed-to-deactivate-old-product-key","title":"Failed to Deactivate Old Product Key","text":"Can happen during offline activation if your local machine is activated twice.
./turbofloatserver -areq=\"/path/to/ActivationRequest.xml\" -a=\"XXXX-XXXX-XXXX-XXXX-XXXX-XXXX-XXXX\"\n./turbofloatserver -areq=\"/path/to/ActivationRequest.xml\" -a=\"XXXX-XXXX-XXXX-XXXX-XXXX-XXXX-XXXX\"\n# Failed to deactivate old product key.\n
If this happens, locally deactivate your machine and try again.
./turbofloatserver -deact\n./turbofloatserver -areq=\"/path/to/ActivationRequest.xml\" -a=\"XXXX-XXXX-XXXX-XXXX-XXXX-XXXX-XXXX\"\n
"},{"location":"floating-licence/#failed-to-parse-the-configuration-xml-file","title":"Failed to Parse the Configuration XML File","text":"Can happen if the activation request is passed in as a response.
turbofloatserver
and is uploaded to https://ragdolldynamics.com/offlineturbofloatserver
./turbofloatserver -areq=\"/path/to/ActivationRequest.xml\" -a=\"XXXX-XXXX-XXXX-XXXX-XXXX-XXXX-XXXX\"\n
Should instead be:
./turbofloatserver -areq=\"/path/to/ActivationResponse.xml\" -a=\"XXXX-XXXX-XXXX-XXXX-XXXX-XXXX-XXXX\"\n
Note the \"Response\" and not \"Request\"
"},{"location":"floating-licence/#what-happens-when-my-server-is-offline","title":"What happens when my server is offline?","text":"Leasing will attempt to connect for about 2 seconds until giving up. During that time, Maya may appear frozen.
"},{"location":"floating-licence/#what-happens-when-my-server-goes-offline","title":"What happens when my server goes offline?","text":"Leasing is re-done once every 30 minutes.
30 minutes is the default value (see below), which means that if the server goes down whilst an artist is using it, the solver will be disabled within 30 minutes.
The duration can be adjusted, however it is a balance since the time is also how long it takes for the server to free a lease as a result of a Maya crash.
Yes.
The default port is 13
and can be edited via the TurboFloatServer-config.xml
file residing in the same directory as the server executable.
<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<config>\n ...\n <bind port=\"13\"/>\n ...\n</config>\n
Yes.
To move a licence, you can deactivate it and then activate it again someplace else.
TurboFloatServer -deact\n
This will deactivate the server. The same can be done if your licence server is offline, by passing a filename to the command.
TurboFloatServer -deact=\"deactivation_request.xml\"\n
Open this file and paste the contents of it into the offline deactivation wizard here.
Complete, Unlimited and Batch have their own serial numbers and each serial number needs its own server.
From there, provide each of your clients with the full server address to the pool it should lease licences from.
For example.
# Render farm\nRAGDOLL_FLOATING=10.0.0.4:601\n\n# Artist workstations\nRAGDOLL_FLOATING=10.0.0.5:601\n
"},{"location":"floating-licence/#can-i-disable-the-splash-screen","title":"Can I disable the splash screen?","text":"Yes.
Consumers of floating licences generally won't need to manage licenses themselves, and so the startup dialog can be avoided altogether for a smoother experience when inside of Maya.
export RAGDOLL_NO_STARTUP_DIALOG=1\nmaya\n
Yes.
Cloud workstations can pick up licences from your locally hosted licence server. It is not recommended nor supported to run your licence server on a virtual machine.
# Cloud workstation example\nexport RAGDOLL_FLOATING=local.server:8001\nmaya\n
In this example, the cloud workstation is referencing your locally hosted licence server via an IP on your VPN.
"},{"location":"floating-licence/#what-happens-to-a-lease-when-maya-crashes","title":"What happens to a lease when Maya crashes?","text":"A lease is automatically dropped upon unloading the plug-in or shutting down Maya. In the event of a Maya crash, a lease will automatically drop after 30 minutes per default.
The time can be edited via the configuration file; a lower time means more compute and file resources are consumed on the server, the lowest value is 30 seconds.
<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<config>\n ...\n <lease length=\"30\"/><!-- seconds -->\n ...\n</config>\n
"},{"location":"floating-licence/#can-i-fall-back-to-a-node-locked-licence","title":"Can I fall back to a node-locked licence?","text":"Yes.
Remove the RAGDOLL_FLOATING
environment variable and reload the plug-in or restart Maya to attempt activation of a node-locked licence.
No.
The server cannot distinguish between two virtual machines which would make it possible to activate an endless amount of them with their own duplicate pools of licences.
Although the server cannot run on a VM, clients can. E.g. running Docker for testing in a continous-integration environment or automation for simulation baking or rendering etc.
"},{"location":"floating-licence/#can-i-monitor-my-licence-server","title":"Can I monitor my licence server?","text":"Yes.
With a logging level set to \"notification\", you'll get real-time output from the server whenever a lease is requested and dropped, including..
The expiry is when the lease will be renewed. Normally not something you need to worry about, unless Maya crashes. This is then the time it'll take the server to realise the lease has been freed.
<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<config>\n ...\n <log file=\"tfs-log.txt\" level=\"notification\"/>\n ...\n</config>\n
2021-05-12, 11:58:47 <notification>: New connection from IP: ::ffff:127.0.0.1\n2021-05-12, 11:58:47 <notification>: New lease assigned (marcus, 1, IP=::ffff:127.0.0.1, PID=14328). Expires: 2021-05-12 11:28:47 (in UTC). Used / Total leases: 1 / 1\n2021-05-12, 11:58:51 <notification>: New connection from IP: ::ffff:127.0.0.1\n2021-05-12, 11:58:51 <notification>: Lease was released by client (marcus, 1, IP=::ffff:127.0.0.1, PID=14328). Used / Total leases: 0 / 1\n
The tfs-log.txt
file is dynamically updated as users lease and drop licences, and includes mention of how many licences are in use and remaining. You can monitor the tail of this file for real-time updates, and use any tooling to parse these notifications into your own infrastructure.
See Also
With level=\"notification\"
it'll say this.
2021-05-16, 14:52:50 <notification>: License lease request rejected because no more free slots, numTotalLics=9, pkey=YOUR-SERIAL-NUMBER\n
"},{"location":"floating-licence/#how-do-i-run-my-server-in-the-background-using-systemd","title":"How do I run my server in the background using systemd?","text":"systemd is a common option for running background processes on Linux. Here's a quick run-down how to get turbofloatserver
running with it.
Prerequisities
turbofloatserver -x
alreadyturbofloatserver
, here we will assume /turbofloat
Ok, with that out of the way, create a new file called /etc/systemd/system/turbofloat.service
with the content below.
turbofloat.service
[Unit]\nDescription=TurboFloat server for CI\nAfter=network.target\n\n[Service]\nType=simple\nUser=root\nWorkingDirectory=/root\nExecStart=/turbofloat/turbofloatserver -x -s\nRestart=on-failure\n\n[Install]\nWantedBy=multi-user.target\n
Replace with your Path
Here we use /turbofloat/turbofloatserver -x -s
but your path will likely be different!
Now let's start it.
systemctl start turbofloat\n
You may need sudo
Unless you are logged in as a root/administrator user, you may need to use sudo
with this command. E.g. sudo systemctl
If there are no complaints, we're set to have this automatically run in the background whenever the computer restarts.
systemctl enable turbofloat\n
And that's it. You should now have access to this server in the exact same way as you did when calling turbofloatserver -x
manually.
To check the status of your server, try this.
~/turbofloat$ systemctl status turbofloat\n\u25cf turbofloat.service - TurboFloat server for CI\n Loaded: loaded (/etc/systemd/system/turbofloat.service; enabled; vendor preset: enabled)\n Active: active (running) since Wed 2023-10-18 13:31:21 BST; 37s ago\n Main PID: 81594 (turbofloatserve)\n Tasks: 17 (limit: 35692)\n Memory: 1.1M\n CPU: 18ms\n CGroup: /system.slice/turbofloat.service\n \u2514\u250081594 /home/marcus/turbofloat/turbofloatserver -x -s\n\nOct 18 13:31:21 minilinux systemd[1]: Started TurboFloat server for CI.\nOct 18 13:31:21 minilinux turbofloatserver[81594]: 2023-10-18, 13:31:21 <notification>: Auto-detected 16 CPU cores; creating a thread pool that large.\nOct 18 13:31:21 minilinux turbofloatserver[81594]: Floating license server for Ragdoll Dynamics (TFS v4.4.4.0)\n
You can also use journalctl
to follow the log interactively, as though it was running in the local terminal.
~/turbofloat$ journalctl --follow --unit turbofloat\nOct 18 13:31:21 minilinux systemd[1]: Started TurboFloat server for CI.\nOct 18 13:31:21 minilinux turbofloatserver[81594]: 2023-10-18, 13:31:21 <notification>: Auto-detected 16 CPU cores; creating a thread pool that large.\nOct 18 13:31:21 minilinux turbofloatserver[81594]: Floating license server for Ragdoll Dynamics (TFS v4.4.4.0)\n
"},{"location":"licencing/","title":"Licencing","text":""},{"location":"licencing/#overview","title":"Overview","text":"Let's cover the basics..
About activation..
Product Key
Product Key
by purchasing a licenceSee also
Once activated without a Product Key
, Ragdoll enters \"Apprentice Mode\", and is limited to the following.
See the Ragdoll EULA for details.
"},{"location":"licencing/#faq","title":"FAQ","text":"Let's dive into specifics.
"},{"location":"licencing/#how-does-it-work","title":"How does it work?","text":"On first launch, Ragdoll will try and connect to the Ragdoll Licence Server and register your trial version. This version is node-locked to the particular machine you are on.
Once you've acquired a product key, you can either:
Ragdoll
menu item (bottom)Activate
Or if you prefer:
from ragdoll import licence\nlicence.activate(key)\n
"},{"location":"licencing/#what-happens-when-my-trial-expires","title":"What happens when my trial expires?","text":"Any rdScene.enabled
attribute will be set to False
.
Scenes will still load just fine and nothing else in your scene is affected. Once activated, the .enabled
attribute will return to normal.
Possibly. Reach out to us if this is relevant to you.
"},{"location":"licencing/#can-i-open-scenes-made-with-the-trial-version-in-the-commercial-version","title":"Can I open scenes made with the trial version in the commercial version?","text":"No.
Files made with Ragdoll Apprentice will appear scrambled with a commercial version. Ragdoll Apprentice is however able to read files saved with a commercial version.
"},{"location":"licencing/#can-i-use-my-licence-on-more-than-one-machine","title":"Can I use my licence on more than one machine?","text":"One licence, one machine.
Ragdoll is licenced per simultaneous use, so for use on two or more machines in parallel you will need 2 licences - a.k.a. \"seats\".
When purchasing multiple seats, you may receive a single serial number containing all seats. For floating licences, you'd host a single licence server using this serial to accommodate each machine. For node-locked licences, you'd activate each individual machine using the same serial.
"},{"location":"licencing/#can-i-move-a-licence-between-two-machines","title":"Can I move a licence between two machines?","text":"Yes.
For node-locked licences, you can hit the Deactivate
button (which is same as the Activate
button once you've activated) and the serial may be used to activate another machine.
Floating licences are dynamically activated on any machine requesting a licence from your centralised licence server.
"},{"location":"licencing/#do-i-need-an-internet-connection-to-use-ragdoll","title":"Do I need an internet connection to use Ragdoll?","text":"No.
Activation can happen either offline or online, online happening from within Maya at the click of a button and offline being a 4-step process, see below.
"},{"location":"licencing/#how-do-i-use-my-floating-licence","title":"How do I use my floating licence?","text":"Floating licences have two parts.
Whenever Ragdoll is loaded from Maya, it connects to your licence server in order to \"lease\" a licence. If you own 10 licences, then one of them will remain leased until the plug-in is unloaded from Maya.
See also
Yes.
See Offline Activation below.
"},{"location":"licencing/#when-exactly-is-internet-required","title":"When exactly is internet required?","text":"A connection is made in one of two separate occasions.
ragdoll.licence.install()
from Pythoninstall()
is typically called when the plug-in is loaded and menu is installed.
That is, Maya can open a scene with Ragdoll in it without making a connection to the internet if neither of these things happen. This means you can simulate on one machine, bake or otherwise disable the solver and send it off to a farm (e.g. local or cloud) without worrying about licences.
The alternative would be having to erase any trace of Ragdoll from a scene which would be such a pain.
"},{"location":"licencing/#disabled-network-devices","title":"\"Disabled Network Devices\"","text":"The licence software used by Ragdoll (WyDay TurboActivate) uses your network devices to associate your serial number with a unique fingerprint of your machine. In order for it to do that, it needs access to each of them.
Try running your DCC as admin while activating Ragdoll, and then run Maya as normal.
Alternatively, have a look at your network connections and make sure they are all enabled while activating Ragdoll, then they can be disabled again.
"},{"location":"licencing/#can-i-manage-my-licence-via-python","title":"Can I manage my licence via Python?","text":"Sure can, see below.
"},{"location":"licencing/#licence-api","title":"Licence API","text":"As a user, you'll generally use the UI. But the UI is ultimately making calls to Python (which is making calls to C++) and you can bypass the UI using these same calls.
from ragdoll import licence\n\n# Called once before calling any other licencing function\n# This is automatically called on Ragdoll Python initialisation\n# and simulation start, but needs calling manually if simulation\n# hasn't yet started.\nlicence.install()\n\n# Retrieve the currently activated product key\nlicence.current_key()\n\n# Activate using your product ket\nlicence.activate(key)\n\n# Activation for those without access to Internet\nlicence.activation_request_to_file(key, fname)\nlicence.activate_from_file(fname)\n\n# Deactivate whatever key is currently activated\nlicence.deactivate()\n\n# Deactivate offline, to e.g. move a licence from one machine to another\nlicence.deactivation_request_to_file(fname)\n\n# Dictionary of useful information\ndata = licence.data()\n\n{\n # Same as current_key\n \"key\": \"Your-Key\",\n\n # Is the current licence activated?\n \"isActivated\": True,\n\n # Is the current licence a trial licence?\n \"isTrial\": False,\n\n # Has the licence not been tampered with?\n \"isGenuine\": True,\n\n # Has the licence been verified with the server\n # (requires a connection to the internet)?\n \"isVerified\": True,\n\n # How many days until this trial expires?\n \"trialDays\": 23\n}\n
"},{"location":"licencing/#offline-activation","title":"Offline Activation","text":"Lifetime licences may be activated offline.
What about monthly licences?These require an internet connection. Floating licences require internet only for the licence server itself, meaning your workstations can remain disconnected and protected. Node-locked licences require internet on the machine being activated.
Similar to Activation, Deactivation happens via the Offline Deactivation Wizard.
Caution
Once you press Deactivate
, then from Maya's perspective your licence will be deactivated. However, the licence server will not know of your deactivation until you paste the request into online deactivation page.
This means that it is possible to deactivate a licence but forget to tell the licence server about it, which means you will not be able to reactivate it elsewhere.
If this happens, reach out to support@ragdolldynamics.com and we may manually deactivate it for you.
"},{"location":"menu/","title":"Menu Reference","text":"All items found in the Ragdoll
menu at the top of Maya's main window.
Add menu items to your shelf with Ctrl + Shift + Click
Stay up to date with the latest improvements and fixes to Ragdoll.
You've just been redirected from a JavaScript-heavy landing page because your browser won't permit JavaScript.
Continue Try again"},{"location":"nodes/","title":"Nodes","text":"
Detailed information about all of Ragdoll's custom nodes along with the most commonly used attributes. For full attribute reference, see the link at the bottom of each node type, such as rdRigid.
Each Ragdoll node starts with rd
, e.g. rdRigid
Container of all rigids, constraints and forces that interact.
The scene represents the knowledge each simulation has, including rigids and their properties, constraints, forces. The works. There can be more than one Ragdoll scene in your Maya scene, but much like Maya scenes they cannot interact. The order in which scenes are simulated is also undefined, so you cannot expect e.g. fingers in one solver to run after the body in another solver.
Parallelism
Ragdoll scenes support both scene-level parallelism and node-level parallelism.
Scene-level parallelism happens when there are more than one Ragdoll scene present, each scene is then run in parallel for improved performance. For that reason, prefer using as many scenes as possible, especially if they are unlikely to interact.
Node-level Parallelism happens internally, whereby a single simulation is distributed over multiple threads. The behavior can be tuned via the rdScene.threadCount
attribute. Keep this at 0 when your scenes are small, i.e. < 100 rigids. The overhead of splitting up a simulation outweighs the benefit unless there is a lot to split. You should notice a performance difference in either direction as you manipulate this attribute.
.airDensity
Global multiplier to the linearDamping
and angularDamping
of every rigid part of this scene. This is a convenience attribute to the same attribute found in the rdRigid
node for global effects, like the whole scene turning into honey. float
.currentTime
Ragdoll's knowledge of time. This is typically connected automatically and needn't be touched, but it is technically possible to animate this and achieve complex slow-motion or time-related effects. time
.enabled
State of the solver. An enabled solver will update whenever time changes. bool
.gravity
Default gravity, in Maya's current distance unit (typically centimeters). Because native Maya shapes are generally quite small - e.g. 1 centimeter for a polyCube - the default gravity is less than the realistic 986.0 cm/s2. If your characters are real-world scaled - e.g. 2 meters tall - then gravity should be closer to 986.0 instead. distance3
.groundFriction
Friction of the ground. float
.groundRestitution
Bounciness of the ground plane. float
.substeps
Divide changes in time by this many. Ragdoll simulates once per frame (or generally once per change in time, including sub-frame changes), but multiples the number of steps taken by this amount for greater accuracy at a (possible) cost to performance. int
.useGround
Automatically add a static ground shape to this scene. This has a very similar effect to making your own plane and turning that into a Passive Rigid. The ground responds to changes in translation of the scene, but cannot be animated. bool
Full Reference "},{"location":"nodes/#rigid","title":"Rigid","text":"A single transform in or out of Ragdoll.
The rigid is the physical equivalent of native Maya geometry. It can either feed into the simulation (passive) or come out of the simulation (active).
Active Rigid
pass data from Ragdoll to MayaPassive Rigid
pass data from Maya to Ragdoll.airDensity
Multiplier of both linearDamping
and angularDamping
. The two damping attributes are typically used together, but can also be used separately in which case this attribute could be left at 1.0 and forgotten. float
.angularDamping
Resistance along the opposite direction of rotation for a rigid. Like linearDamping
but along the rotation axes. float
.collide
Whether this rigid should collide with other rigids. This can be useful in areas of many overlapping rigids that aren't necessarily constrained, such as a shoulder or hip. bool
.friction
The resistance at which two rigids rub against each other. A value of 0 creates an appearance of ice, whereas a value of 1.0 represents 100% friction, no sliding allowed. The value may exceed 1.0, but it is unclear what happens. Use at your own risk. float
.inputMatrix
Passive position and orientation, this may be animated. matrix
.inputParentInverseMatrix
Used to cancel out any Maya parent prior to outputting the outputMatrix. matrix
.kinematic
Whether this rigid should be affected by contacts, constraints and forces. bool
.linearDamping
Resistance in the opposite direction of travel for a rigid. This creates an underwater look, or at high-enough values resembles honey or eventually cement. float
.mass
The 'weight' of a rigid. Except 'weight' is technically the result of mass and gravity, and a rigid still has mass even when there isn't any gravity. This attribute is mostly relevant when two active rigids interact, think of a pool table where one of the balls is heavier than another. On the other hand, dropping a feather from high on up onto a static ground yields an identical result to dropping much heavier bowling ball. The ground being static will not move regardless and the speed at which your rigid falls to the ground is independent of its mass given there is no actual air in the simulation to apply counterforce like in the real world. float
.restitution
The 'bounciness' of a rigid body. Bounce is an opposite force applied whenever two rigids come into contact. The bounce is however also dependent on the rdScene.bounceThresholdVelocity
which determines how strong a contact must be in order for an opposing force to be added. Without a threshold, a rigid would bounce at increasingly small intervals into infinity. However, for high-frequency bounces, like a billiard ball bouncing on a marble floor, don't forget to increase your substeps so as to capture the very small and fast motion happening towards the end of its bounce lifetime. float
.shapeExtents
The dimensions of the 'Box' shapeType
. float3
.shapeLength
Length of the 'Capsule' and 'Cylinder' shapeType
. float
.shapeOffset
Position of a shape relative the rigid. Think of the shape as being a child of the rigid, and this is its child position. It'll be in the orientation of the parent, as you would expect. double3
.shapeRadius
Radius of the 'Sphere', 'Capsule' and 'Cylinder' shapeType
. float
.shapeType
Shape used for collision detection and automatic computation of centerOfMass
and angularMass
. The 'Mesh' option converts any input to inputMesh
or inputCurve
to a suitable physical representation called 'Convex Hull'. As the name implies, the hull cannot be concave. To model concave shapes, like a torus, use multiple rigids and parent them together to form a compound shape. enum
.thickness
Additional offset from the surface of a shape. Think of this as the shape being extruded by this amount along the surface normals. It's meant to create some padding between two rigids that collide and can help stabilise complex or strong contacts. float
Full Reference "},{"location":"nodes/#constraint","title":"Constraint","text":"A relationship between two rigids.
Typically this relationship is something to limit one or more axes - e.g. translateXYZ
and rotateZ
- of one rigid relative another rigid, like a door \"constrained\" to a wall. In that case, the wall would be considered a \"parent\" and the door a \"child\".
However it is important to keep in mind that in the real world, there is no such thing. The door is as constrained to the wall as the wall is constrained to the door. This is especially apparent when the two constrained rigids are both active and have a similar mass, such as your upper and lower leg. As you bend your knee, both the thigh and lower leg are affected equally.
Attribute Description Type.angularDriveDamping
Angular damping of the drive. float
.angularDriveStiffness
Angular stiffness of the drive. float
.angularLimitDamping
Damping of contacts with the limit. It is an opposing force to whatever direction a contact is applied. A low value produces a springy appearance, whereas a high value resists any and all motion. float
.angularLimitStiffness
Stiffness of contacts with the angular limit. A low value makes limits appear soft. Values are relative the mass of your rigid and the amount of force being applied by contacts and other constraints. But with a mass of 1.0 and under normal gravity, the default value should produce a somewhat hard response. float
.driveEnabled
Whether or not to try and follow the driveMatrix
attribute. Drives (a.k.a. Guides) are used to follow an input animation by applying forces relative the delta between your animation and the simulation. The further your animation is from the current state of the simulation, the stronger the force. It's a spring-like force. bool
.driveMatrix
A target position and orientation for the childRigid
, relative the parentFrame
. The constraint can apply a spring-like force to both parent and child to try and match this matrix as though the childRigid
was an actual child of the parentRigid
. matrix
.driveStrength
Multipler to linearDriveStiffness
, linearDriveDamping
, angularDriveStiffness
and angularDriveDamping
. This is a convenience attribute to simplify manipulation (and animation) of the overall drive behaviour. The same result can be achieved by manually multiplying these values. The equation is strength * strength * stiffness
and the same for damping. float
.limitEnabled
Whether any of the specified limits are enabled or not. Think of this as a convenience override for linear (position) and angular (rotation) limits. You can achieve the same effect by setting each limit to a value of 0. bool
.limitStrength
Multiplier for the linearLimitStiffness
, linearLimitDamping
, angularLimitStiffness
and angularLimitDamping
attributes. float
.linearDriveDamping
Linear damping of the drive. A high value produces a slimy, slow-moving motion. float
.linearDriveStiffness
Linear stiffness of the drive. If you think of the drive as a spring, then the stiffness determines the thickness of the coil of that spring. A thick coil yields a fast, springy motion. float
.linearLimitDamping
Damping factor for contacts with the limit. float
.linearLimitStiffness
Stiffness of contacts with linear limit. Whenever the linear limit is hit, this attribute determines how soft/hard to response should be. A low value (e.g. 10) yields a soft appearance, whereas a high (e.g. 1'000'000) yields a metal-versus-marble contact. float
Full Reference "},{"location":"nodes/#control","title":"Control","text":"A placeholder for drawing a rigid under a different transform.
This node is cosmetic only. It helps you spot the rigid and rigid orientation in the viewport for a standalone controller, like a Guide
. It also draws the node with a special icon in the outliner. But that's about it!
Multiply one or more attributes of one or more constraints.
This node enables you to animate one attribute that affect many attributes, like Translate Guide Stiffness
across an entire character or limb.
.angularDriveDamping
Multiplier for rdConstraint.angularDriveDamping
float
.angularDriveStiffness
Multiplier for rdConstraint.angularDriveStiffness
float
.angularLimitDamping
Multiplier for rdConstraint.angularLimitDamping
float
.angularLimitStiffness
Multiplier for rdConstraint.angularLimitStiffness
float
.driveStrength
Multiplier for rdConstraint.driveStrength
float
.limitStrength
Multiplier for rdConstraint.limitStrength
float
.linearDriveDamping
Multiplier for rdConstraint.linearDriveDamping
float
.linearDriveStiffness
Multiplier for rdConstraint.linearDriveStiffness
float
.linearLimitDamping
Multiplier for rdConstraint.linearLimitDamping
float
.linearLimitStiffness
Multiplier for rdConstraint.linearLimitStiffness
float
Full Reference "},{"location":"nodes/#rigid-multiplier","title":"Rigid Multiplier","text":"Multiply one or more attributes of one or more rigids.
This node enables you to animate one attribute that affect many attributes, like Air Density
across an entire character or limb.
.airDensity
Multiplier for rdRigid.airDensity
float
.angularDamping
Multiplier for rdRigid.angularDamping
float
.linearDamping
Multiplier for rdRigid.linearDamping
float
Full Reference "},{"location":"nodes/#other","title":"Other","text":"Notes on general concepts used in Ragdoll.
"},{"location":"nodes/#backwards-compatibility","title":"Backwards Compatibility","text":"This means previously authored scenes will always behave the same, whilst still enabling new default values for future versions and future authored physics.
"},{"location":"nodes/#exclusive-nodes","title":"Exclusive Nodes","text":"Ragdoll consists of a few new native types, like rdRigid
and rdConstraint
. During creation, Ragdoll may generate Maya-native types too, like multMatrix
and composeMatrix
. Those nodes are exclusive to Ragdoll and should be removed alongside them. This is managed via the so-called .exclusiveNodes
attribute on each Ragdoll node type.
Whenever Ragdoll attributes appear on your original animation controls, they are referred to as \"user attributes\" by Ragdoll and tracked via the .userAttributes
attribute on each Ragdoll node. These attributes are exclusive to Ragdoll and are removed alongside the Ragdoll node types they interact with.
MIT License
Copyright \u00a9 2013-2020 Ryo Suzuki reputeless@gmail.com
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
https://github.com/skypjack/entt The MIT License (MIT)
Copyright \u00a9 2017-2020 Michele Caini
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copy of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copy or substantial portions of the Software.
THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
https://github.com/bulletphysics/bullet3 The files in this repository are licensed under the zlib license, except for the files under 'Extras' and examples/ThirdPartyLibs.
Bullet Continuous Collision Detection and Physics Library http://bulletphysics.org
This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
NVIDIA PhysX SDK Copyright \u00a9 2019 NVIDIA Corporation. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of NVIDIA CORPORATION nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Open Dynamics Engine Copyright \u00a9 2001-2004, Russell L. Smith. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
Neither the names of ODE's copyright owner nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
https://github.com/stack-of-tasks/pinocchio BSD 2-Clause License
Copyright \u00a9 2014-2020, CNRS Copyright \u00a9 2018-2020, INRIA All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of the Pinocchio project.
https://github.com/mosra/magnum Copyright \u00a9 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Vladim\u00edr Vondru\u0161 mosra@centrum.cz
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"},{"location":"overview/","title":"Overview","text":"Ragdoll is a real-time physics solver for Maya and Blender, similar the native nCloth and nHair solvers except it works on transforms rather than points. That makes it better equipt to integrate with your existing animation controls and doesn't require translating from points like people did in the 90's.
This domain contains Ragdoll learning resources, for a more general overview see the Product Page.
"},{"location":"overview/#where-to-find-help","title":"Where to Find Help?","text":"Depending on where you are and what you are looking for, one of these should fit the bill.
# Source Description Chat Come join the party on Discord! Release Notes Every new release has examples of every new feature and squashed bug. Search Top of every page, you know what to do \u261d\ufe0f YouTube Videos Long-form walkthroughs and examples. Community Inspire and be inspired via the Ragdoll forums Support Get us involved and let's make some waves "},{"location":"overview/#whats-next","title":"What's Next?","text":"Here are some options for getting into Ragdoll.
Route Description Install & Explore Tried and true, who reads documentation anyway? Watch & Learn We've made a number of videos demonstrating how to use Ragdoll. Read All About It Keep clicking that next button at the bottom of every page. "},{"location":"overview/#press","title":"Press","text":"Mentions of Ragdoll in the press.
Date Source Title 2022-11-29 gfxspeak Manipulate Maya character rigs with real-time physics in seconds 2022-11-29 digitalmediaworld Ragdoll Dynamics 3.0 Develops Real-Time Character Physics for Animators 2022-11-29 cgsociety.org Ragdoll Dynamics 3.0 Adds Real-Time Character Physics Animators Can Steer Like a Puppeteer 2022-11-29 80.lv Ragdoll Dynamics 3.0 for Maya Released 2022-11-29 redsharknews Ragdoll Dynamics 3.0: steer like a puppeteer 2022-11-29 postperspective Ragdoll 3.0: Fast Automation of Character Physics in Maya 2022-11-29 postperspective Ragdoll Dynamics 3.0 \u0434\u043b\u044f Maya 2022-11-29 blog.superrendersfarm Ragdoll Dynamics 3.0 released 2022-11-29 render.ru Ragdoll Dynamics sort en version 3.0! 2022-11-29 swiss.dayfr Ragdoll Dynamics is released in version 3.0! 2022-11-29 germany.detailzero From 'Gravity' tethers to, literally, Ragdoll Dynamics 2022-11-29 beforesandafters Ragdoll Dynamics 3.0 released 2022-11-29 cgchannel Imbalance releases Ragdoll Dynamics 3.0 for Maya 2022-11-29 cgbucket Ragdoll Dynamics 3.0 released 2022-11-29 cgpress.org Ragdoll Dynamics erscheint in der Version 3.0! 2022-11-29 digitalproduction Imbalance Releases Ragdoll Dynamics 3.0 2022-11-29 boxreview Imbalance Releases Ragdoll Dynamics 3.0 2022-11-29 afnews Imbalance Releases Ragdoll Dynamics 3.0 2022-11-29 animationmagazine Ragdoll Dynamics 3.0 Adds Real-Time Character Physics Animators Can Steer Like a Puppeteer 2022-11-29 awn Imbalance Releases Ragdoll Dynamics 3.0 2022-11-29 facebook 80 Level - Imbalance has released Ragdoll Dynamics 3.0 2022-11-29 facebook Imbalance Releases Ragdoll... - Animation World Network 2022-11-29 facebook Are you a Befores & Afters PLUS Patron 2022-11-29 facebook Check out Ragdoll Dynamics 3.0 for Maya. The ace real-time physics tool now lets you pose charact... 2022-11-29 facebook CGPress - Imbalance has announced the release of Ragdoll... 2022-11-29 facebook Ragdoll Dynamics 3.0 Develops Real-Time Character Physics for Animators 2022-11-29 facebook Ragdoll Dynamics erscheint in der... - Digital Production 2022-11-29 80level Tweet by @80Level 2022-11-29 afnewsinfo Tweet by @afnewsinfo 2022-11-29 afnewsinfo Tweet by @animag 2022-11-29 animag Tweet by @ANIMATIONWorld 2022-11-29 animationworld Tweet by @beforesmag 2022-11-29 beforesmag Tweet by @BoxReview_ 2022-11-29 boxreview_ Tweet by @theCGchannel 2022-11-29 dig_prod Tweet by @dig_prod 2022-11-29 thecgchannel Tweet by @RedSharkNews 2022-11-29 redsharknews 2022-11-29 linkedin 80.lv on LinkedIn 2022-11-29 youtube From 'Gravity' tethers to Ragdoll Dynamics 2022-11-29 postperspective 2022-12-18 Escape Studios Ragdoll Dynamics for Maya 2022-09-21 80lv Development and Capabilities of Ragdoll Dynamics 2021-08-03 CGChannel Ragdoll Dynamics adds real-time physics to your Maya rigs 2021-07-30 CGPress Ragdoll Dynamics plugin for Maya 2021-07-28 80lv New Tool Lets You Animate With Physics in Real-TimeShare your sources
Know of anywhere else Ragdoll got mentioned? Let us know and we'll add it to the list!
Contact Us
"},{"location":"parallel/","title":"Parallel","text":""},{"location":"parallel/#overview","title":"Overview","text":"This guide describes the Maya features for accelerating playback and manipulation of animated scenes. It covers key concepts, shares best practices/usage tips, and lists known limitations that we aim to address in subsequent versions of Maya.
This guide will be of interest to riggers, TDs, and plug-in authors wishing to take advantage of speed enhancements in Maya.
If you would like an overview of related topics prior to reading this document, check out Supercharged Animation Performance in Maya 2016.
"},{"location":"parallel/#key-concepts","title":"Key Concepts","text":"Starting from Maya 2016, Maya accelerates existing scenes by taking better advantage of your hardware. Unlike previous versions of Maya, which were limited to node-level parallelism, Maya now includes a mechanism for scene-level analysis and parallelization. For example, if your scene contains different characters that are unconstrained to one another, Maya can evaluate each character at the same time.
Similarly, if your scene has a single complex character, it may be possible to evaluate rig sub-sections simultaneously. As you can imagine, the amount of parallelism depends on how your scene has been constructed. We will get back to this later. For now, let\u2019s focus on understanding key Maya evaluation concepts.
At the heart of Maya\u2019s new evaluation architecture is an Evaluation Manager (EM), responsible for handling the parallel-friendly representation of your scene. It maintains (and updates while the scene is edited) a few data structures (described below) used for efficient evaluation.
The basic description of the scene is the Dependency Graph (DG), consisting of DG nodes and connections. Nodes can have multiple attributes, and instances of these attributes on a specific node are called plugs. The DG connections are at the plug level, that is, two nodes can be connected to one another multiple ways through different plugs. Generally speaking, these connections represent data flow through the nodes as they evaluate. The following image shows an example DG:
The dotted arrows inside the nodes represent an implicit computation dependency between an output attribute (on the right of the node) and the input attributes (on the left) being read to compute the result stored in the output.
Before Parallel Maya, the DG was used to evaluate the scene using a Pull Model or Pull Evaluation. In this model, the data consumer (for instance the renderer) queries data from a given node. If the data is already evaluated, the consumer receives it directly. However, if the data is dirty, the node must first recompute it. It does so by pulling on the inputs required to compute the requested data. These inputs can also be dirty, in which case the evaluation request will then be forwarded to those dirty sources until it reaches the point where the data can be evaluated. The result then propagates back up in the graph, as the data is being \u201cpulled\u201d.
This evaluation model relies on the ability to mark node data as invalid and therefore requiring new evaluation. This mechanism is known as the Dirty Propagation in which the invalid data status propagates to all downstream dependencies. The two main cases where dirty propagation happened in the Pull Evaluation model were when:
The Pull Evaluation model is not well suited for efficient parallel evaluation because of potential races that can arise from concurrent pull evaluations.
To have tighter control over evaluation, Maya now uses a Forward Evaluation model to enable concurrent evaluation of multiple nodes. The general idea is simple: if all a node\u2019s dependencies have been evaluated before we evaluate the given node, pull evaluation will not be triggered when accessing evaluated node data, so evaluation remains contained in the node and is easier to run concurrently.
All data dependencies between the nodes must be known to apply this evaluation model, and this information is captured in the Evaluation Graph (EG), containing Evaluation Nodes. The EM uses dirty propagation to capture dependency information between the nodes, as well as which attributes are animated. EG connections represent node-level dependencies; destination nodes employ data from source nodes to correctly evaluate the scene. One important distinction between the DG and the EG is that the former uses plug-level connections, while the latter uses node-level connections. For example, the previous DG would create the following EG:
A valid EG may not exist or become invalid for various reasons. For example, you have loaded a new scene and no EG has been built yet, or you have changed your scene, invalidating a prior EG. However, once the EG is built, unlike previous versions of Maya that propagated dirty on every frame, Maya now disables dirty propagation, reusing the EG until it becomes invalid.
Tip
If your scene contains expression nodes that use getAttr
, the DG graph will be missing explicit dependencies. This results in an incorrect EG. Expression nodes also reduce the amount of parallelism in your scenes (see Scheduling Types for details). Consider removing getAttr
from expressions and/or using utility nodes.
While the EG holds the dependency information, it is not ready to be evaluated concurrently as-is. The EM must first create units of work that can be scheduled, that is, tasks. The main types of task created are:
This step, called partitioning, is where the EM creates the individual pieces of work that will have to be executed. Each of these tasks will map to a Scheduling Node in the Scheduling Graph (SG), where connections represent dependencies between the tasks:
The SG is an acyclic graph, otherwise it would be impossible to schedule nodes in a cycle since there would be no starting point for which all dependencies could be evaluated. In addition to the dependencies that come directly from the EG, the SG can have additional scheduling constraints to prevent concurrent evaluation of subsets of nodes (see Scheduling Types for details).
"},{"location":"parallel/#supported-evaluation-modes","title":"Supported Evaluation Modes","text":"Starting in Maya 2016, 3 evaluation modes are supported:
Mode What does it do? DG Uses the legacy Dependency Graph-based evaluation of your scene. This was the default evaluation mode prior to Maya 2016 Serial Evaluation Manager Serial mode. Uses the EG but limits scheduling to a single core. Serial mode is a troubleshooting mode to pinpoint the source of evaluation errors. Parallel Evaluation Manager Parallel mode. Uses the EG and schedules evaluation across all available cores. This mode is the new Maya default since 2016.When using either Serial or Parallel EM modes, you can also activate GPU Override to accelerate deformations on your GPU. You must be in Viewport 2.0 to use this feature (see GPU Override).
To switch between different modes, go to the Preferences window (Windows > Settings/Preferences > Preferences > Animation). You can also use the evaluationManager MEL/Python command; see documentation for supported options.
To see the evaluation options that apply to your scene, turn on the Heads Up Display Evaluation options (Display > Heads Up Display > Evaluation).
"},{"location":"parallel/#first-make-it-right-then-make-it-fast","title":"First Make it Right Then Make it Fast","text":"Before discussing how to make your Maya scene faster using Parallel evaluation, it is important to ensure that evaluation in DG and EM modes generates the same results. If you see different results in the viewport during animation (as compared to previous versions of Maya), or tests reveal numerical errors, it is critical to understand the cause of these errors. Errors may be due to an incorrect EG, threading related problems, or other issues.
Below, we review Evaluation Graph Correctness and Thread Safety, two important concepts to understand errors.
"},{"location":"parallel/#evaluation-graph-correctness","title":"Evaluation Graph Correctness","text":"If you see evaluation errors, first test your scene in Serial evaluation mode (see Supported Evaluation Modes). Serial evaluation mode uses the EM to build an EG of your scene, but limits evaluation to a single core to eliminate threading as the possible source of differences. Note that since Serial evaluation mode is provided for debugging, it has not been optimized for speed and scenes may run slower in Serial than in DG evaluation mode. This is expected.
If transitioning to Serial evaluation eliminates errors, this suggests that differences are most likely due to threading-related issues. However, if errors persist (even after transitioning to Serial evaluation) this suggests that the EG is incorrect for your scene. There are a few possible reasons for this:
Custom Plugins. If your scene uses custom plug-ins that rely on the mechanism provided by the MPxNode::setDependentsDirty
function to manage attribute dirtying, this may be the source of problems. Plug-in authors sometimes use MPxNode::setDependentsDirty
to avoid expensive calculations in MPxNode::compute
by monitoring and/or altering dependencies and storing computed results for later re-use.
Since the EM relies on dirty propagation to create the EG, any custom plug-in logic that alters dependencies may interfere with the construction of a correct EG. Furthermore, since the EM evaluation does not propagate dirty messages, any custom caching or computation in MPxNode::setDependentsDirty
is not called while the EM is evaluating.
If you suspect that your evaluation errors are related to custom plug-ins, temporarily remove the associated nodes from your scene and validate that both DG and Serial evaluation modes generate the same result. Once you have made sure this is the case, revisit the plug-in logic. The API Extensions section covers Maya SDK changes that will help you adapt plug-ins to Parallel evaluation.
Another debugging option is to use \u201cscheduling type\u201d overrides to force custom nodes to be scheduled more conservatively. This approach enables the use of Parallel evaluation even if only some of the nodes are thread-safe. Scheduling types are described in more detail in the Thread Safety section.
Errors in Autodesk Nodes. Although we have done our best to ensure that all out-of-the-box Autodesk Maya nodes correctly express dependencies, sometimes a scene uses nodes in an unexpected manner. If this is the case, we ask you make us aware of scenes where you encounter problems. We will do our best to address problems as quickly as possible.
"},{"location":"parallel/#thread-safety","title":"Thread Safety","text":"Prior to Maya 2016, evaluation was single-threaded and developers did not need to worry about making their code thread-safe. At each frame, evaluation was guaranteed to proceed serially and computation would finish for one node prior to moving onto another. This approach allowed for the caching of intermediate results in global memory and using external libraries without considering their ability to work correctly when called simultaneously from multiple threads.
These guarantees no longer apply. Developers working in recent versions of Maya must update plug-ins to ensure correct behavior during concurrent evaluation.
Two things to consider when updating plug-ins:
Different instances of a node type should not share resources. Unmanaged shared resources can lead to evaluation errors since different nodes, of the same type, can have their compute()
methods called at the same time.
Avoid non thread-safe lazy evaluation. In the EM, evaluation is scheduled from predecessors to successors on a per-node basis. Once computation has been performed for predecessors, results are cached, and made available to successors via connections. Any attempt to perform non-thread safe lazy evaluation could return different answers to different successors or, depending on the nature of the bug, instabilities.
Here\u2019s a concrete example for a simple node network consisting of 4 nodes:
In this graph, evaluation first calculates outputs for Node1 (that is, Node1.A, Node1.B, Node1.C), followed by parallel evaluation of Nodes 2, 3, and 4 (that is, Read Node1.A to use in Node2, Read Node1.B to use in Node3, and so on).
Knowing that making legacy code thread-safe requires time, we have added new scheduling types to provide control over how the EM schedule nodes. Scheduling types provide a straightforward migration path, so you do not need to hold off on performance improvements, just because a few nodes still need work.
There are 4 scheduling types:
Scheduling Type What are you telling the scheduler? Parallel Asserts that the node and all third-party libraries used by the node are thread-safe. The scheduler may evaluate any instances of this node at the same time as instances of other nodes without restriction. Serial Asserts it is safe to run this node with instances of other nodes. However, all nodes with this scheduling type should be executed sequentially within the same evaluation chain. Globally Serial Asserts it is safe to run this node with instances of other node types but only a single instance of this node type should be run at a time. Use this type if the node relies on static state, which could lead to unpredictable results if multiple node instances are simultaneously evaluated. The same restriction may apply if third-party libraries store state. Untrusted Asserts this node is not thread-safe and that no other nodes should be evaluated while an instance of this node is evaluated. Untrusted nodes are deferred as much as possible (that is, until there is nothing left to evaluate that does not depend on them), which can introduce costly synchronization.By default, nodes scheduled as Serial provide a middle ground between performance and stability/safety. In some cases, this is too permissive and nodes must be downgraded to GloballySerial or Untrusted. In other cases, some nodes can be promoted to Parallel. As you can imagine, the more parallelism supported by nodes in your graph, the higher level of concurrency you are likely to obtain.
Tip
When testing your plug-ins with Parallel Maya, a simple strategy is to schedule nodes with the most restrictive scheduling type (that is, Untrusted), and then validate that evaluation produces correct results. Raise individual nodes to the next scheduling level, and repeat the experiment.
There are three ways to alter the scheduling level of your nodes:
Evaluation Toolkit. Use this tool to query or change the scheduling type of different node types.
C++/Python API methods. Use the OpenMaya API to specify the desired node scheduling by overriding the MPxNode::schedulingType
method. This function should return one of the enumerated values specified by MPxNode::schedulingType
. See the Maya MPxNode class reference for more details.
MEL/Python Commands. Use the evaluationManager command to change the scheduling type of nodes at runtime. Below, we illustrate how you can change the scheduling of scene transform nodes:
Scheduling Type Command ParallelevaluationManager -nodeTypeParallel on \"transform\"
Serial evaluationManager -nodeTypeSerialize on \"transform\"
GloballySerial evaluationManager -nodeTypeGloballySerialize on \"transform\"
Untrusted evaluationManager -nodeTypeUntrusted on \"transform\"
The Evaluation Toolkit and MEL/Python Commands method to alter node scheduling level works using node type overrides. They add an override that applies to all nodes of a given type. Using C++/Python API methods and overriding the MPxNode::schedulingType
function gives the flexibility to change the scheduling type for each node instance. For example, expression nodes are marked as globally serial if the expression outputs are a purely mathematical function of its inputs.
The expression engine is not thread-safe so only one expression can run at a time, but it can run in parallel with any other nodes. However, if the expression uses unsafe commands (expressions could use any command to access any part of the scene), the node is marked as untrusted because nothing can run while the expression is evaluated.
This changes the way scheduling types should be queried. Using the evaluationManager
command with the above flags in query mode will return whether an override has been set on the node type, using either the Evaluation Toolkit or the MEL/Python commands.
The Evaluation Toolkit window lets you query both the override type on the node type (which cannot vary from one node of the same type to the other), or the actual scheduling type used for a node when building the scheduling graph (which can change from one node instance to the other).
"},{"location":"parallel/#safe-mode","title":"Safe Mode","text":"On rare occasions you may notice that Maya switches from Parallel to Serial evaluation during manipulation or playback. This is due to Safe Mode, which attempts to trap errors that possibly lead to instabilities. If Maya detects that multiple threads are attempting to simultaneously access a single node instance, evaluation will be forced to Serial execution to prevent problems.
Tip
If Safe Mode forces your scene into Serial mode, the EM may not produce the expected incorrect results when manipulating. In such cases you can either disable the EM:
cmds.evaluationManager(mode=\"off\")
or disable EM-accelerated manipulation:
cmds.evaluationManager(man=0)
While Safe Mode exposes many problems, it cannot catch them all. Therefore, we have also developed a special Analysis Mode that performs a more thorough (and costly) check of your scene. Analysis mode is designed for riggers/TDs wishing to troubleshoot evaluation problems during rig creation. Avoid using Analysis Mode during animation since it will slow down your scene.
"},{"location":"parallel/#evaluation-graph-invalidation","title":"Evaluation Graph Invalidation","text":"As previously described, the EG adds necessary node-level scheduling information to the DG. To make sure evaluation is correct, it\u2019s critical the EG always be up-to-date, reflecting the state of the scene. The process of detecting things that have changed and rebuilding the EG is referred to as graph invalidation.
Different actions may invalidate the EG, including:
Other, less obvious, actions include:
Frequent graph invalidations may limit parallel evaluation performance gains or even slow it down (see Idle Actions), since Maya requires DG dirty propagation and evaluation to rebuild the EG. To avoid unwanted graph rebuilds, consider adding 2 keys, each with slightly different values, on rig attributes that you expect to use frequently. You can also lock static channels to prevent creation of static animation curves during keying. We expect to continue tuning this area of Maya, with the goal of making the general case as interactive as possible.
Tip
You can use the controller command to identify objects that are used as animation sources in your scene. If the Include controllers in evaluation graph option is set (see Windows > Settings/Preferences > Preferences, then Settings > Animation), the objects marked as controllers will automatically be added to the evaluation graph even if they are not animated yet. This allows Parallel evaluation for manipulation even if they have not yet been keyed.
"},{"location":"parallel/#idle-actions","title":"Idle Actions","text":"In this section, we discuss the different idle actions available in Maya that helps rebuild the EG without any intervention from the user. Prior to Maya 2019, only one idle action, the EG rebuild, was available, but it was not enabled by default. Since Maya 2019, we have added another idle action, the EG preparation for manipulation, and both of these are enabled by default.
Here is a description of the idle actions:
Idle Action Description EG Rebuild Builds the graph topology. This idle action is executed after a file load operation, or after a graph topology invalidation. EG Preparation for manipulation Partitions and schedules the graph. This idle action is executed after a graph rebuild (either manually or through the idle action), or after a partitioning invalidation.Tip
You can use the evaluationManager command to change which idle actions are enabled. You can enable and disable both idle actions individually.
"},{"location":"parallel/#benefits","title":"Benefits","text":"To make use of the Parallel Evaluation and GPU deformation during manipulation, the EG needs to be properly built, partitioned and scheduled, otherwise it will revert to DG. These idle actions allow the EG to automatically build and be ready to use when needed, since they are triggered at file load and after graph invalidation.
If you use Cached Playback, your cache automatically refills, too. This way, you can start playing from cache as soon as the scene is loaded or after you modify to the scene.
"},{"location":"parallel/#caveats","title":"Caveats","text":"In a typical frame evaluation, temporary values that are set on keyed attributes are restored to their original values, that is, the values on their associated curves. With the idle actions, this is an unwanted behavior, otherwise you would not be able to do any modifications to keyed attributes. To circumvent that issue, we had to add some special behaviougs One of these is the dirty propagation from stale plugs after an idle preparation for manipulation. When not in idle preparation for manipulation, this operation is done during the partitioning and scheduling phase. With idle preparation for manipulation, this operation is done at the next complete evaluation. Therefore, if you have many static curves, you might experience a slowdown on the first frame of playback.
If you do frequent operations that invalidate the graph or partitioning, you may experience some slowdowns due to the graph always being rebuilt. In such cases, it is advised that you disable the offending idle action until you are done.
"},{"location":"parallel/#custom-evaluators","title":"Custom Evaluators","text":"In this section, we describe mechanisms to perform targeted evaluation of node sub-graphs. This approach is used by Maya to accelerate deformations on the GPU and to catch evaluation errors for scenes with specific nodes. Maya 2017 also introduced new Open API extensions, allowing user-defined custom evaluators.
Tip
Use the evaluator command to query the available/active evaluators or modify currently active evaluators. Some evaluators support using the nodeType flag to filter out or include nodes of certain types. Query the info flag on the evaluator for more information on what it supports.
# Returns a list of all currently available evaluators.\nimport maya.cmds as cmds\ncmds.evaluator( query=True )\n# Result: [u'invisibility',\nu'frozen',\n...\nu'transformFlattening',\nu'pruneRoots'] #\n\n# Returns a list of all currently enabled evaluators.\ncmds.evaluator( query=True, enable=True )\n# Result: [u'invisibility',\nu'timeEditorCurveEvaluator',\n...\nu'transformFlattening',\nu'pruneRoots'] #\n
Note: Enabling or disabling custom evaluators only applies to the current Maya session: the state is not saved in the scene nor in the user preferences. The same applies to configuration done using the evaluator
command and the configuration flag.
Maya contains a custom deformer evaluator that accelerates deformations in Viewport 2.0 by targeting deformation to the GPU. GPUs are ideally suited to tackle problems such as mesh deformations that require the same operations on streams of vertex and normal data. We have included GPU implementations for several of the most commonly-used deformers in animated scenes: skinCluster, blendShape, cluster, tweak, groupParts, softMod, deltaMush, lattice, nonLinear and tension.
Unlike Maya\u2019s previous deformer stack that performed deformations on the CPU and subsequently sent deformed geometry to the graphics card for rendering, the GPU override sends undeformed geometry to the graphics card, performs deformations in OpenCL and then hands off the data to Viewport 2.0 for rendering without read-back overhead. We have observed substantial speed improvements from this approach in scenes with dense geometry.
Even if your scene uses only supported deformers, GPU override may not be enabled due to the use of unsupported node features in your scene. For example, with the exception of softMod, there is no support for incomplete group components. Additional deformer-specific limitations are listed below:
Deformer
Limitation(s)
skinCluster
The following attribute values are ignored:
- bindMethod
- bindPose
- bindVolume
- dropOff
- heatmapFalloff
- influenceColor
- lockWeights
- maintainMaxInfluences
- maxInfluences
- nurbsSamples
- paintTrans
- smoothness
- weightDistribution
blendShape
The following attribute values are ignored:
- baseOrigin
- icon
- normalizationId
- origin
- parallelBlender
- supportNegativeWeights
- targetOrigin
- topologyCheck
cluster
n/a
tweak
Only relative mode is supported. relativeTweak must be set to 1.
groupParts
n/a
softMod
Only volume falloff is supported when distance cache is disabled
Falloff must occur on all axes
Partial resolution must be disabled
deltaMush
n/a
lattice
n/a
nonLinear
n/a
tension
n/a
A few other reasons that can prevent GPU override from accelerating your scene:
Meshes not sufficiently dense. Unless meshes have a large number of vertices, it is still faster to perform deformations on the CPU. This is due to the driver-specific overhead incurred when sending data to the GPU for processing. For deformations to happen on the GPU, your mesh needs over 500/2000 vertices, on AMD/NVIDIA hardware respectively. Use the MAYA_OPENCL_DEFORMER_MIN_VERTS
environment variable to change the threshold. Setting the value to 0 sends all meshes connected to supported deformation chains to the GPU.
Downstream graph nodes required deformed mesh results. Since GPU read-back is a known bottleneck in GPGPU, no node, script, or Viewport can read the mesh data computed by the GPU override. This means that GPU override is unable to accelerate portions of the EG upstream of deformation nodes, such as follicle or pointOnPolyConstraint, that require information about the deformed mesh. We will re-examine this limitation as software/hardware capabilities mature. When diagnosing GPU Override problems, this situation may appear as an unsupported fan-out pattern. See deformerEvaluator command, below, for details.
Animated Topology. If your scene animates the number of mesh edges, vertices, and/or faces during playback, corresponding deformation chains are removed from the GPU deformation path.
Maya Catmull-Clark Smooth Mesh Preview is used. We have included acceleration for OpenSubDiv (OSD)-based smooth mesh preview, however there is no support for Maya\u2019s legacy Catmull-Clark. To take advantage of OSD OpenCL acceleration, select OpenSubDiv Catmull-Clark as the subdivision method and make sure that OpenCL Acceleration is selected in the OpenSubDiv controls.
Unsupported streams are found. Depending on which drawing mode you select for your geometry (for example, shrunken faces, hedge-hog normals, and so on) and the material assigned, Maya must allocate and send different streams of data to the graphics card. Since we have focused our efforts on common settings used in production, GPU override does not currently handle all stream combinations. If meshes fail to accelerate due to unsupported streams, change display modes and/or update the geometry material.
Back face culling is enabled.
Driver-related issues. We are aware of various hardware issues related to driver support/stability for OpenCL. To maximize Maya\u2019s stability, we have disabled GPU Override in the cases that will lead to problems. We expect to continue to eliminate restrictions in the future and are actively working with hardware vendors to address detected driver problems.
You can also increase support for new custom/proprietary deformers by using new API extensions (refer to Custom GPU Deformers for details).
If you enable GPU Override and the HUD reports Enabled (0 k), this indicates that no deformations are happening on the GPU. There could be several reasons for this, such as those mentioned above.
To troubleshoot factors that limit the use of GPU override for your particular scene, use the deformerEvaluator command. Supported options include:
Command
What does it do?
deformerEvaluator
Prints the chain or each selected node is not supported.
deformerEvaluator -chains
Prints all active deformation chains.
deformerEvaluator -meshes
Prints a chain for each mesh or a reason if it is not supported.
"},{"location":"parallel/#dynamics-evaluator","title":"Dynamics Evaluator","text":"Starting in Maya 2017, the dynamics evaluator fully supports parallel evaluation of scenes with Nucleus (nCloth, nHair, nParticles), Bullet, and Bifrost dynamics. Legacy dynamics nodes (for example, particles, fluids) remain unsupported. If the dynamics evaluator finds unsupported node types in the EG, Maya will revert to DG-based evaluation. The dynamics evaluator also manages the tricky computation necessary for correct scene evaluation. This is one of the ways custom evaluators can be used to change Maya\u2019s default evaluation behavior.
The dynamics evaluator supports several configuration flags to control its behavior.
Flag
What does it do?
disablingNodes
specifies the set of nodes that will force the dynamics evaluator to disable the EM. Valid values are: legacy2016
, unsupported
, and none
.
handledNodes
specifies the set of nodes that are going to be captured by the dynamics evaluator and scheduled in clusters that it will manage. Valid values are: dynamics
and none
.
action
specifies how the dynamics evaluator will handle its nodes. Valid values are: none
, evaluate
, and freeze
.
In Maya 2017, the default configuration corresponds to:
cmds.evaluator(name=\"dynamics\", c=\"disablingNodes=unsupported\")\ncmds.evaluator(name=\"dynamics\", c=\"handledNodes=dynamics\")\ncmds.evaluator(name=\"dynamics\", c=\"action=evaluate\")\n
where unsupported (that is, blacklisted) nodes are:
This configuration disables evaluation if any unsupported nodes are encountered, and performs evaluation for the other handled nodes in the scene.
To revert to Maya 2016 / 2016 Extension 2 behavior, use the configuration:
cmds.evaluator(name=\"dynamics\", c=\"disablingNodes=legacy2016\")\ncmds.evaluator(name=\"dynamics\", c=\"handledNodes=none\")\ncmds.evaluator(name=\"dynamics\", c=\"action=none\")\n
where unsupported (that is, blacklisted) nodes are:
Tip
To get a list of nodes that cause the dynamics evaluator to disable the EM in its present configuration, use the following command:
cmds.evaluator(name=\"dynamics\", valueName=\"disabledNodes\", query=True)\n
You can configure the dynamics evaluator to ignore unsupported nodes. If you want to try Parallel evaluation on a scene where it is disabled because of unsupported node types, use the following commands:
cmds.evaluator(name=\"dynamics\", c=\"disablingNodes=none\")\ncmds.evaluator(name=\"dynamics\", c=\"handledNodes=dynamics\")\ncmds.evaluator(name=\"dynamics\", c=\"action=evaluate\")\n
Note: Using the dynamics evaluator on unsupported nodes may cause evaluation problems and/or application crashes; this is unsupported behavior. Proceed with caution.
Tip
If you want the dynamics evaluator to skip evaluation of all dynamics nodes in the scene, use the following commands:
cmds.evaluator(name=\"dynamics\", c=\"disablingNodes=unsupported\")\ncmds.evaluator(name=\"dynamics\", c=\"handledNodes=dynamics\")\ncmds.evaluator(name=\"dynamics\", c=\"action=freeze\")\n
This can be useful to quickly disable dynamics when the simulation impacts animation performance.
Dynamics simulation results are very sensitive to evaluation order, which may differ between DG and EM-based evaluation. Even for DG-based evaluation, evaluation order may depend on multiple factors. For example, in DG-mode when rendering simulation results to the Viewport, the evaluation order may be different than when simulation is performed in \u2018headless mode\u2019. Though EM-based evaluation results are not guaranteed to be identical to DG-based, evaluation order is consistent; once the evaluation order is scheduled by the EM, it will remain consistent regardless of whether results are rendered or Maya is used in batch. This same principle applies to non-dynamics nodes that are order-dependent.
"},{"location":"parallel/#reference-evaluator","title":"Reference Evaluator","text":"When a reference is unloaded it leaves several nodes in the scene representing reference edits to preserve. Though these nodes may inherit animation from upstream nodes, they do not contribute to what is rendered and can be safely ignored during evaluation. The reference evaluator ensures all such nodes are skipped during evaluation.
"},{"location":"parallel/#invisibility-evaluator","title":"Invisibility Evaluator","text":"Toggling scene object visibility is a critical artist workflow used to reduce visual clutter and accelerate performance. To bring this workflow to parallel evaluation, Maya 2017 and above includes the invisibility evaluator, whose goal is to skip evaluation of any node that does not contribute to a visible object.
The invisibility evaluator will skip evaluation of DAG nodes meeting any of the below criteria:
visibility
attribute is false.intermediateObject
attribute is true.overrideEnabled
attribute is true and overrideVisibility
attribute is false.enabled
attribute is true and visibility
attribute is false.As of Maya 2018, the invisibility evaluator supports the isolate select
method of hiding objects. If there is only a single Viewport, and it has one or more objects isolated, then all of the other, unrelated objects are considered invisible by the evaluator.
There is also support in Maya (2018 and up) for the animated
attribute on expression nodes. When this attribute is set to 1, the expression node is not skipped by the invisibility evaluator, even if only invisible objects are connected to it.
Note: The default value of the animated
attribute is 1, so in an expression-heavy scene you may see a slowdown from Maya 2017 to Maya 2018. To restore performance, run the script below to disable this attribute on all expression nodes. (It is only required when the expression has some sort of side-effect external to the connections, such as printing a message or checking a cache file size.)
for node in cmds.ls( type='expression' ):\n cmds.setAttr( '{}.animated'.format(node), 0 )\n
Tip: The invisibility evaluator is off by default in Maya 2017. Use the Evaluation Toolkit or this:
cmds.evaluator(enable=True, name='invisibility')\n
to enable the evaluator.
The invisibility evaluator only considers static visibility; nodes with animated visibility are still evaluated, even if nodes meet the above criteria. If nodes are in a cycle, all cycle nodes must be considered invisible for evaluation to be skipped. Lastly, if a node is instanced and has at least one visible path upward, then all upward paths will be evaluated.
Tip: The invisibility evaluator determines visibility solely from the node\u2019s visibility state; if your UI or plug-in code requires invisible nodes to evaluate, do not use the invisibility evaluator.
"},{"location":"parallel/#frozen-evaluator","title":"Frozen Evaluator","text":"The frozen evaluator allows users to tag EG subsections as not needing evaluation. It enhances the frozen
attribute by propagating the frozen state automatically to related nodes, according to the rules defined by the evaluator\u2019s configuration. It should only be used by those comfortable with the concepts of connection and propagation in the DAG and Evaluation Graph. Many users may prefer the invisibility evaluator; it is a simpler interface/workflow for most cases.
The frozen attribute has existed on nodes since Maya 2016. It can be used to control whether node is evaluated in Serial or Parallel EM evaluation modes. In principle, when the frozen attribute is set, the EM skips evaluation of that node. However, there are additional nuances that impact whether or not this is the case:
Warning: All the frozen attribute does is skip evaluation, nothing is done to preserve the current node data during file store; if you load a file with frozen attributes set, the nodes may not have the same data as when you stored them.
"},{"location":"parallel/#operation","title":"Operation","text":"The evaluation manager does not evaluate any node that has its frozen
attribute set to True, referred to here as explicitly frozen nodes. An implicitly frozen node is one that is disabled because of the operation of the frozen evaluator, but whose frozen
attribute is not set to True. When the frozen evaluator is enabled it will also prevent evaluation of related nodes according to the rules corresponding to the enabled options, in any combination.
The frozen evaluator operates in three phases. In phase one, it gathers together all of the nodes flagged by the invisible and displayLayers options as being marked for freezing. In phase two, it propagates the freezing state outwards through the evaluation graph according to the values of the downstream and upstream options.
"},{"location":"parallel/#phase-1-gathering-the-nodes","title":"Phase 1: Gathering The Nodes","text":"The list of nodes for propagation is gathered as follows:
frozen
attribute set to True are found. (Note: This does not include those whose frozen attribute is animated. They are handled via Phase 3.)The list gathered by Phase 1 will all be implicitly frozen. In addition, the downstream and upstream options may implicitly freeze nodes related to them. For each of the nodes gathered so far, the evaluation graph will be traversed in both directions, implicitly freezing nodes encountered according to the following options:
If a node has its frozen or visibility states animated, the evaluator still has to schedule it. The runtime freezing can still assist at this point in preventing unnecessary evaluation. Normally any explicitly frozen node will have its evaluation skipped, with all other nodes evaluating normally. When the runtime option is enabled, after skipping the evaluation of an explicitly frozen node no further scheduling of downstream nodes will occur. As a result, if the downstream nodes have no other unfrozen inputs they will also be skipped.
Note: The runtime option does not really modify the evaluator operation, it modifies the scheduling of nodes for evaluation. You will not see nodes affected by this option in the evaluator information (for example, the output from cmds.evaluator( query=True, clusters=True, name='frozen' )
)
Options can be set for the frozen evaluator in one of two ways:
Accessing them through the Evaluation Toolkit
Using the evaluator command\u2019s configuration option:
cmds.evaluator( name='frozen', configuration='KEY=VALUE' )\n
Legal KEY and VALUE values are below, and correspond to the options as described above:
KEY
VALUES
DEFAULT
runtime
True/False
False
invisible
True/False
False
displayLayers
True/False
False
downstream
\u2018off\u2019/\u2018safe\u2019/\u2018force\u2019
\u2018off\u2019
upstream
\u2018off\u2019/\u2018safe\u2019/\u2018force\u2019
\u2018off\u2019
Unlike most evaluators the frozen evaluator options are stored in user preferences and persists between sessions.
"},{"location":"parallel/#limitations","title":"Limitations","text":"frozen
attribute to True to instruct the frozen evaluator to shut off evaluation on affected nodes. The most practical use of this would be on a display layer so that nodes can be implicitly frozen as a group.frozen
attribute, or any of the attributes used to define related implicit nodes for freezing (for example, visibility
) are animated then the evaluator will not remove them from evaluation. They will still be scheduled and only the runtime option will help in avoiding unnecessary evaluation.The curve manager evaluator can be used to include additional nodes in the Evaluation Graph, which can have two main benefits:
To achieve those benefits efficiently, the curve manager evaluator performs two main tasks:
To illustrate this result, let\u2019s compare the three following situations.
The third situation is where we are trying to take advantage of the curve manager evaluator to have an Evaluation Graph that is already set up to allow parallel evaluation when the controllers will be manipulated.
The following table summarizes the differences between the situations and the compromises provided by the curve manager evaluator.
Situation
# of nodes in EG
Playback
EM Manip
Rebuild when keying
Static curves + curve manager off
Lowest
Fastest
No
Yes
Animated curves
Highest
Slowest
Yes
No
Static curves + curve manager on
Highest
Middle
Yes
No
In summary, the curve manager evaluator benefits from having the Evaluation Graph already populated with nodes so it is ready to evaluate interactive manipulation, while paying as little of a cost as possible for those constant nodes during playback.
It can be activated using:
cmds.evaluator(\n name=\"curveManager\",\n enable=True\n )\ncmds.evaluator(\n name=\"curveManager\",\n configuration=\"forceAnimatedCurves=keyed\"\n )\n
The available values for forceAnimatedCurves
are:
Another option, forceAnimatedNodes
, can be used:
This allows tagging nodes to be added with a boolean dynamic attribute. By default, the name of this attribute is forcedAnimated
. If it is present on a node and set to true, the node is added to the graph. The name of the attribute can be controlled by using the \u201cforcedAnimatedAttributeName\u201d option.
By default, the curve manager evaluator tries to skip the evaluation of the static parts of the graph. For debugging or performance measurement purposes, this optimization can be disabled:
cmds.evaluator(\n name=\"curveManager\",\n configuration=\"skipStaticEvaluation=disable\"\n )\n
"},{"location":"parallel/#other-evaluators","title":"Other Evaluators","text":"In addition to evaluators described above, additional evaluators exist for specialized tasks:
Evaluator
What does it do?
cache
Constitutes the foundation of Cached Playback. See the Maya Cached Playback whitepaper for more information.
timeEditorCurveEvaluator
Finds all paramCurves connected to time editor nodes and puts them into a cluster that will prevent them from evaluating at the current time, since the time editor will manage their evaluation.
ikSystem
Automatically disables the EM when a multi-chain solver is present in the EG. For regular IK chains it will perform any lazy update prior to parallel execution.
disabling
Automatically disables the EM if user-specified nodes are present in the EG. This evaluator is used for troubleshooting purposes. It allows Maya to keep working stably until issues with problem nodes can be addressed.
hik
Handles the evaluation of HumanIK characters in an efficient way by recognizing HumanIK common connection patterns.
cycle
Unrolls cycle clusters to augment the opportunity for parallelism and improve performance. Likely gives the best performance improvements when large cycle clusters are present in the scene. Prototype, work in progress.
transformFlattening
Consolidates deep transform hierarchies containing animated parents and static children, leading to faster evaluation. Consolidation takes a snapshot of the relative parent/child transformations, allowing concurrent evaluation of downstream nodes.
pruneRoots
We found that scenes with several thousand paramCurves become bogged down because of scheduling overhead from resulting EG nodes and lose any potential gain from increased parallelism. To handle this situation, special clusters are created to group paramCurves into a small number of evaluation tasks, thus reducing overhead.
Custom evaluator names are subject to change as we introduce new evaluators and expand these functionalities.
"},{"location":"parallel/#evaluator-conflicts","title":"Evaluator Conflicts","text":"Sometimes, multiple evaluators will want to \u201cclaim responsibility\u201d for the same node(s). This can result in conflict, and negatively impact performance. To avoid these conflicts, upon registration each evaluator is associated with a priority; nodes are assigned to the evaluator with the highest priority. Internal evaluators have been ordered to prioritize correctness and stability over speed.
"},{"location":"parallel/#api-extensions","title":"API Extensions","text":"Several API extensions and tools have been added to help you make the most of the EM in your pipeline. This section reviews API extensions for Parallel Evaluation, Custom GPU Deformers, Custom Evaluator API, VP2 Integration and Profiling Plug-ins.
"},{"location":"parallel/#parallel-evaluation","title":"Parallel Evaluation","text":"If your plug-in plays by the DG rules, you will not need many changes to make the plug-in work in Parallel mode. Porting your plug-in so that it works in Parallel may be as simple as recompiling it against the latest version of OpenMaya!
If the EM generates different results than DG-based evaluation, make sure that your plug-in:
Overrides MPxNode::compute()
. This is especially true of classes extending MPxTransform
which previously relied on asMatrix()
. See the rockingTransform SDK sample. For classes deriving from MPxDeformerNode
and MPxGeometryFilter
, override the deform()
method.
Handles requests for evaluation at all levels of the plug tree. While the DG can request plug values at any level, the EM always requests the root plug. For example, for plug N.gp[0].p[1] your compute() method must handle requests for evaluation of N.gp, N.gp[0], N.gp[0].p, and N.gp[0].p[1].
If your plug-in relies on custom dependency management, you need to use new API extensions to ensure correct results. As described earlier, the EG is built using the legacy dirty-propagation mechanism. Therefore, optimizations used to limit dirty propagation during DG evaluation, such as those found in MPxNode::setDependentsDirty
, may introduce errors in the EG. Use MEvaluationManager::graphConstructionActive() to detect if this is occurring.
There are new virtual methods you will want to consider implementing:
MPxNode::preEvaluation
. To avoid performing expensive calculations each time the evaluation method MPxNode::compute()
is called, one strategy plug-in authors use is to store results from previous evaluations and then rely on MPxNode::setDependentsDirty
to trigger re-computation. As discussed previously, once the EG has been built, dirty propagation is disabled and the EG is re-used. Threrefore, any custom logic in your plug-in that depends on setDependentsDirty no longer applies.
MPxNode::preEvaluation
allows your plug-in to determine which plugs/attributes are dirty and if any action is needed. Use the new MEvaluationNode class to determine what has been dirtied.
Refer to the simpleEvaluationNode devkit example for an illustration of how to use MPxNode::preEvaluation
.
MPxNode::postEvaluation
. Until now, it was difficult to determine at which point all processing for a node instance was complete. Users sometimes resorted to complex bookkeeping/callback schemes to detect this situation and perform additional work, such as custom rendering. This mechanism was cumbersome and error-prone.
Once all computations have been performed on a specific node instance, a new method, MPxNode::postEvaluation
, is called. Since this method is called from a worker thread, it performs calculations for downstream graph operations without blocking other Maya processing tasks of non-dependent nodes.
See the simpleEvaluationDraw devkit example to understand how to use this method. If you run this example in regular evaluation, Maya slows down, since evaluation is blocked whenever expensive calculations are performed. When you run in Parallel Evaluation Mode, a worker thread calls the postEvaluation method and prepares data for subsequent drawing operations. When testing, you will see higher frame rates in Parallel evaluation versus regular or Serial evaluation. Please note that code in postEvaluation should be thread-safe.
Other recommended best practices include:
Avoid storing state in static variables. Store node state/settings in attributes. This has the additional benefit of automatically saving/restoring the plug-in state when Maya files are written/read.
Node computation should not have any dependencies beyond input values. Maya nodes should be like functions. Output values should be computed from input state and node-specific internal logic. Your node should never walk the graph or try to circumvent the DG.
To make GPU Override work on scenes containing custom deformers, Maya provides new API classes that allow the creation of fast OpenCL deformer back-ends.
Though you still need to have a CPU implementation for the times when it is not possible to target deformations on the GPU (see GPU Override), you can augment this with an alternate deformer implementation inheriting from MPxGPUDeformer. This applies to your own nodes as well as to standard Maya nodes.
The GPU implementation will need to:
When you have done this, do not forget to load your plug-in at startup. Two working devkit examples (offsetNode and identityNode) have been provided to get you started.
Tip
To get a sense for the maximum speed increase you can expect by providing a GPU backend for a specific deformer, tell Maya to treat specific nodes as passthrough. Here\u2019s an example applied to polySoftEdge:
cmds.GPUBuiltInDeformerControl(\n name=\"polySoftEdge\",\n inputAttribute=\"inputPolymesh\",\n outputAttribute=\"output\",\n passthrough=True\n )\n
Although results will be incorrect, this test will confirm if it is worth investing time implementing an OpenCL version of your node.
"},{"location":"parallel/#custom-evaluator-api","title":"Custom Evaluator API","text":"API classes and methods introduced in Maya 2017 let you define custom evaluators that allow control over how the Maya scene is computed.
To create a custom evaluator, you must define a plug-in that extends the MPxCustomEvaluator
class. The key class methods to override are described below.
Before you can use the new evaluators, they must be registered:
MStatus registerEvaluator(\n // name of the evaluator\n const char * evaluatorName,\n\n // evaluator priority. Higher priority evaluators get 'first-dibs'\n unsigned int uniquePriority,\n\n // function pointer to method returning a new evaluator instance\n MCreatorFunction creatorFunction\n)\n
and deregistered:
MStatus deregisterEvaluator(\n // name of the evaluator\n const char* evaluatorName\n)\n
using MFnPlugin
methods. These functions should be used during plug-in initialization:
MStatus initializePlugin( MObject obj )\n{\n MFnPlugin plugin( obj, PLUGIN_COMPANY, \"3.0\", \"Any\");\n MStatus status = plugin.registerEvaluator(\n \"SimpleEvaluator\",\n 40,\n simpleEvaluator::creator);\n if (!status)\n status.perror(\"registerEvaluator\");\n return status;\n}\n
and uninitialization:
MStatus uninitializePlugin( MObject obj )\n{\n MFnPlugin plugin( obj );\n MStatus status = plugin.deregisterEvaluator( \"SimpleEvaluator\" );\n if (!status)\n status.perror(\"deregisterEvaluator\");\n return status;\n}\n
as illustrated above.
Once the plug-in has been loaded, use Python or MEL commands to enable:
import maya.cmds as cmds\ncmds.evaluator(enable=True, name='SimpleEvaluator')\n\n# Result: False #\n
disable:
cmds.evaluator(enable=False, name='SimpleEvaluator')\n\n# Result: True #\n
and query information about evaluators:
print cmds.evaluator(query=True)\n\n[u'invisibility', ... u'SimpleEvaluator']\n
NOTE: The evaluator command returns the previous state of the evaluator (as described in the documentation). This command fails if the evaluator cannot be enabled.
To view the priorities of all loaded evaluators, use the priority flag on the evaluator command:
for evaluatorName in cmds.evaluator():\n print \"%-25s : %d\" % (\n evaluatorName,\n cmds.evaluator(name=evaluatorName, query=True, priority=True))\n\ninvisibility : 1003000\nfrozen : 1002000\ncurveManager : 1001000\ncache : 1000000\ntimeEditorCurveEvaluator : 104000\ndynamics : 103000\nikSystem : 102000\ndisabling : 100000\nhik : 7000\nreference : 6000\ndeformer : 5000\ncycle : 4000\ntransformFlattening : 3000\npruneRoots : 1000\nSimpleEvaluator : 40\n
"},{"location":"parallel/#api-reference","title":"API Reference","text":"This section provides more detail on different MPxCustomEvaluator
API methods.
During EG partitioning, each evaluator gets to claim evaluation nodes, using the:
bool MPxCustomEvaluator::markIfSupported(const MEvaluationNode* node)\n
method. You can safely cause evaluation in this call but doing so increases partitioning and evaluation time. The developer can decide whether evaluation is required (call .inputValue
/ .inputArrayValue
), or the previously-evaluated datablock values can be re-used (call .outputValue
/ .outputArrayValue
). If multiple evaluators mark a specific node, which evaluator is assigned a node at run-time is determined by priority. For example, if you have two evaluators, A and B, mark node C of interest, if evaluator A has priority 100, and evaluator B has priority 10, during graph partitioning, evaluator A will get the opportunity to grab node C before evaluator B. Evaluators should not try to grab a node already grabbed by a higher-priority evaluator.
To determine if an evaluator can evaluate clusters in Parallel, use:
MCustomEvaluatorClusterNode::SchedulingType schedulingType(\n // a disjoint set of nodes on a custom evaluator layer\n const MCustomEvaluatorClusterNode * cluster\n)\n
where:
SchedulingType
Details
kParallel
any number of nodes of the same type can run in parallel
kSerial
all nodes of this type should be chained and executed sequentially
kGloballySerial
only one node of this type can be run at a time
kUntrusted
nothing else can execute with this node since we cannot predict what will happen
During EG scheduling:
bool MPxCustomEvaluator::clusterInitialize(\n // evaluation cluster node\n const MCustomEvaluatorClusterNode* cluster\n)\n
can be used to perform the required cluster preparation. The pointer to the cluster remains valid until graph invalidation, such as when the scene topology changes.
Before the cluster is deleted,
void MPxCustomEvaluator::clusterTerminate(\n // the cluster to terminate\n const MCustomEvaluatorClusterNode* cluster\n)\n
is called to allow needed cleanup, for example, releasing evaluator-specific resources. It is up to the custom evaluator to decide if it wants to clear its internal representation.
"},{"location":"parallel/#execution","title":"Execution","text":"There are 3 main methods used during execution.
Prior to graph execution, the EM calls:
void MPxCustomEvaluator::preEvaluate(\n // the graph about to be evaluated\n const MEvaluationGraph* graph\n)\n
during execution, the EM calls:
void MPxCustomEvaluator::clusterEvaluate(\n // the cluster to be evaluated\n const MCustomEvaluatorClusterNode* cluster\n)\n
You will only receive clusters that belong to this evaluator. This call always happens after clusterInitialize
and never after clusterTerminate
. Finally,
void MPxCustomEvaluator::postEvaluate(\n // the graph that was evaluated\n const MEvaluationGraph* graph\n)\n
is called just after a graph evaluation is finished.
"},{"location":"parallel/#simpleevaluator-api-example","title":"SimpleEvaluator API Example","text":"Now that we have reviewed relevant API methods, the following example limits evaluation by caching previous results. simpleEvaluator
assumes the existence of scene nodes that tag controller nodes with animation and works as follows:
In clusterInitialize
, we-2\">ld a list of translation and rotation attribute plugs.
// Build a list of plugs by scanning the scene for controller nodes.\n// This gets called during scheduling.\nbool simpleEvaluator::clusterInitialize(\n const MCustomEvaluatorClusterNode* cluster\n )\n{\n if (fControllerPlugs.length() == 0)\n buildPlugListWithControllerTag();\n return true;\n}\n\n// Scan the scene for any controller nodes, populating the plug list.\n// Called during the scheduling phase\nvoid simpleEvaluator::buildPlugListWithControllerTag()\n{\n MStatus stat;\n MItDependencyNodes dgIter(MFn::kControllerTag, &stat);\n if (stat != MS::kSuccess)\n return;\n\n const char* values[] = {\n \"translateX\",\n \"translateY\",\n \"translateZ\",\n \"rotateX\",\n \"rotateY\",\n \"rotateZ\"\n };\n\n for (; !dgIter.isDone(); dgIter.next())\n {\n MFnDependencyNode controllerTagNode(dgIter.thisNode(), &stat);\n if (stat != MS::kSuccess)\n continue;\n\n MPlug currControllerTagPlug =\n controllerTagNode.findPlug(\"controllerObject\", &stat);\n if (stat != MS::kSuccess)\n continue;\n\n // found controller tag node, now get its source controller\n MPlugArray source;\n bool retval = currControllerTagPlug.connectedTo(\n source,\n true /* asDst */,\n false /* asSrc */,\n &stat)\n if ((retval == false) || (stat != MS::kSuccess))\n continue;\n\n // there should only be one source with the controller tag node\n // as destination\n MObject controllerNode = source[0].node(&stat);\n if (stat != MS::kSuccess)\n continue;\n\n MFnDependencyNode currControllerNode(controllerNode, &stat);\n if (stat != MS::kSuccess)\n continue;\n\n for (unsigned int j = 0; j < 6; j++)\n {\n MPlug currPlug = currControllerNode.findPlug(values[j], &stat);\n if (stat == MS::kSuccess)\n fControllerPlugs.append(currPlug);\n else\n std::cerr\n << \"NO PLUG: \"\n << currControllerNode.name().asChar()\n << \".\"\n << values[j]\n << std::endl;\n }\n }\n}\n
Later, during preEvaluate
, which is called per-frame, a hash value is calculated based on the plug values of the current frame.
void simpleEvaluator::preEvaluate(const MEvaluationGraph* graph)\n{\n buildHashValue();\n}\n\nvoid simpleEvaluator::buildHashValue()\n{\n unsigned int length = fControllerPlugs.length();\n MStatus stat = MS::kSuccess;\n\n for (unsigned int i = 0; i < length; i++)\n {\n float value = 0;\n stat = fControllerPlugs[i].getValue(value);\n\n if (stat == MS::kSuccess)\n {\n boost::hash_combine(fCurrentHashValue, value);\n }\n else\n {\n std::cerr\n << \"NO VALUE: \"\n << fControllerPlugs[i].name().asChar()\n << std::endl;\n }\n }\n}\n
This value is compared with the previous frame\u2019s hash in clusterEvaluate
. If the hash is different, the evaluation proceeds, otherwise we do nothing.
void simpleEvaluator::clusterEvaluate(\n const MCustomEvaluatorClusterNode* cluster\n )\n{\n if (fOldHashValue != fCurrentHashValue)\n cluster->evaluate();\n}\n
To make sure the hash value is up-to-date, the hash value is stored in postEvaluate
.
void simpleEvaluator::postEvaluate(const MEvaluationGraph* graph)\n{\n fOldHashValue = fCurrentHashValue;\n fCurrentHashValue = 0;\n}\n
Finally, when the graph topology becomes invalid, we call clusterTerminate
to clear the cached list of plugs.
void simpleEvaluator::clusterTerminate(\n const MCustomEvaluatorClusterNode* cluster\n )\n{\n if (fControllerPlugs.length() > 0)\n fControllerPlugs.clear();\n}\n
Since simpleEvaluator
claims control over the entire graph, markIfSupported
returns true for all nodes. Additionally, nothing special is done to alter the cluster\u2019s scheduling behavior.
bool simpleEvaluator::markIfSupported(const MEvaluationNode* node)\n{\n return true;\n}\n\nMCustomEvaluatorClusterNode::SchedulingType\nsimpleEvaluator::schedulingType(const MCustomEvaluatorClusterNode* cluster)\n{\n return cluster->schedulingType();\n}\n
See the provided simpleEvaluator devkit example for more details and complete source code.
"},{"location":"parallel/#vp2-integration","title":"VP2 Integration","text":"Evaluation Manager Parallel Evaluation executes the Dependency Graph in parallel. Internally, Maya nodes begin preparing render data for VP2 immediately after a node is evaluated, and before the rest of the graph has finished evaluation. This is exposed to users as Evaluation Manager Parallel Update in the MPxGeometryOverride API (this feature may also be referred to as \u201cDirect Update\u201d). Supporting Evaluation Manager Parallel Update can significantly reduce time spent in Vp2BuildRenderLists and improve overall scene performance.
The following profiler images were created from the same scene (100 footPrintNode_GeometryOverride nodes with animated \u201csize\u201d attributes). In the first image Evaluation Manager Parallel Update is not enabled, and a large amount of time is spent serially preparing draw data for each footPrint node in Vp2BuildRenderLists.
In the second image the footPrintNode_GeometryOverride has been modified to support Evaluation Manager Parallel Update. You can see that the long serial execution time in Vp2BuildRenderLists has been eliminated. All the data marshalling for VP2 is occurring in parallel while the Evaluation Manager is evaluating the Dependency Graph.
The footPrintNode_GeometryOverride example plug-in provides a detailed example for you to create an efficient MPxGeometryOverride plugin which supports Evaluation Manager Parallel Update and gives excellent performance in VP2.
Supporting Evaluation Manager Direct Update adds some restrictions to which operations can safely be performed from MPxGeometryOverride function calls. All MPxGeometryOverride functions (except cleanUp() and the destructor) may be called from a worker thread in parallel with other Maya execution. These methods must all be thread safe. An MPxGeometryOverride object is guaranteed to have at most one of its member functions called at a time. If two different MPxGeometryOverride objects \u201cA\u201d and \u201cB\u201d both require updating, then any member function on \u201cA\u201d could be called at the same time as any member function on \u201cB\u201d.
Furthermore, because these methods may be called from a worker thread, direct access to the rendering context is prohibited. MVertexBuffer and MIndexBuffer can still be used, but some of their features are prohibited from use when in Evaluation Manager Parallel Update. Details about which features are safe to use are provided in the documentation for MVertexBuffer and MIndexBuffer.
"},{"location":"parallel/#tracking-topology","title":"Tracking Topology","text":"Evaluation Manager Parallel Update currently has the limitation that it can only be used on geometries that do not have animated topology. The status of whether topology is animated or not needs to be tracked from the geometry\u2019s origin to its display shape.
If the nodes in the graph are built-in nodes, Maya can know if an animated input will affect the output geometry topology. Similarly, deformers (even custom ones derived from MPxDeformerNode), are assumed to simply deform their input in their output, keeping the same topology.
However, more generic nodes can also generate geometries. When a custom node is a MPxNode, Maya cannot know whether an output geometry has animated topology. It therefore assumes the worst and treats the topology as animated. While this approach is the safest, it can prevent optimizations such as Evaluation Manager Parallel Update.
As of Maya 2019, a new API has been added to inform Maya about attributes that might not affect the topology of an output geometry.
Using this new API helps Maya to know that it is safe to use Evaluation Manager Parallel Update and benefit from its performance boost in more situations.
"},{"location":"parallel/#profiling-plug-ins","title":"Profiling Plug-ins","text":"To visualize how long custom plug-ins take in the new profiling tools (see Profiling Your Scene) you will need to instrument your code. Maya provides C++, Python, and MEL interfaces for you to do this. Refer to the Profiling using MEL or Python or the API technical docs for more details.
"},{"location":"parallel/#profiling-your-scene","title":"Profiling Your Scene","text":"In the past, it could be challenging to understand where Maya was spending time. To remove the guess-work out of performance diagnosis, Maya includes a new integrated profiler that lets you see exactly how long different tasks are taking.
Open the Profiler by selecting:
Once the Profiler window is visible:
Tip
By default, the Profiler allocates a 20MB buffer to store results. The record buffer can be expanded in the UI or by using the profiler -b value;
command, where value is the desired size in MB. You may need this for more complex scenes.
The Profiler includes information for all instrumented code, including playback, manipulation, authoring tasks, and UI/Qt events. When profiling your scene, make sure to capture several frames of data to ensure gathered results are representative of scene bottlenecks.
The Profiler supports several views depending on the task you wish to perform. The default Category View, shown below, classifies events by type (e.g., dirty, VP1, VP2, Evaluation, etc). The Thread and CPU views show how function chains are subdivided amongst available compute resources. Currently the Profiler does not support visualization of GPU-based activity.
![][image1.jpg]
"},{"location":"parallel/#understanding-your-profile","title":"Understanding Your Profile","text":"Now that you have a general sense of what the Profiler tool does, let\u2019s discuss key phases involved in computing results for your scene and how these are displayed. By understanding why scenes are slow, you can target scene optimizations.
Every time Maya updates a frame, it must compute and draw the elements in your scene. Hence, computation can be split into one of two main categories:
When the main bottleneck in your scene is evaluation, we say the scene is evaluation-bound. When the main bottleneck in your scene is rendering, we say the scene is render-bound.
"},{"location":"parallel/#profiler-colors","title":"Profiler Colors","text":"Each event recorded by the profiler has an associated color. Each color represents a different type of event. By understanding event colors you can quickly interpret profiler results. Some colors are re-used and so have different meanings in different categories.
We can\u2019t see every different type of event in a single profile, because some events like Dirty Propagation only occur with Evaluation Manager off, and other events like GPU Override CPU usage only occur with Evaluation Manager on. In the following example profiles we will show DG Evaluation, Evaluation Manager Parallel Evaluation, GPU Override Evaluation, Evaluation Cached Evaluation and VP2 Cached Evaluation. Through these examples we\u2019ll see how to interpret a profile based on graph colors and categories, and we\u2019ll learn how each performance optimization in Maya can impact a scene\u2019s performance. The following example profiles are all generated from the same simple FK character playing back.
"},{"location":"parallel/#dg-evaluation","title":"DG Evaluation","text":"In this profile of DG Evaluation we can see several types of event.
A significant fraction of each frame is spent on Dirty Propagation, a problem which is alleviated by Evaluation Manager.
"},{"location":"parallel/#em-parallel-evaluation","title":"EM Parallel Evaluation","text":"In this profile of EM Parallel Evaluation we can see all the purple and pink dirty propagation is gone.
In this profile we see much less time spent on Vp2SceneRender (4). This occurs because time spent reading data from dependency nodes has been moved from rendering to EM Parallel Evaluation (1). DG evaluation uses a data pull model, while EM Evaluation uses a data push model. Additionally, some geometry translation (2), is also moved from rendering to evaluation. We call geometry translation during evaluation \u201cVP2 Direct Update\u201d. A significant portion of each frame is spent deforming and translating the geometry data, a problem which is alleviated by GPU Override.
"},{"location":"parallel/#em-parallel-evaluation-with-gpu-override","title":"EM Parallel Evaluation with GPU Override","text":"In this profile of EM Parallel Evaluation we can see one major new difference from the previous profile of EM Parallel Evaluation.
In this profile of EM Evaluation Cached Playback we can see several new types of event.
When the main bottleneck in your scene is evaluation, we say the scene is evaluation-bound. There are several different problems that may lead to evaluation-bound performance.
Lock Contention. When many threads try to access a shared resource you may experience Lock Contention, due to lock management overhead. One clue that this may be happening is that evaluation takes roughly the same duration regardless of which evaluation mode you use. This occurs since threads cannot proceed until other threads are finished using the shared resource.
Here the Profiler shows many separate identical tasks that start at nearly the same time on different threads, each finishing at different times. This type of profile offers a clue that there might be some shared resource that many threads need to access simultaneously.
Below is another image showing a similar problem.
In this case, since several threads were executing Python code, they all had to wait for the Global Interpreter Lock (GIL) to become available. Bottlenecks and performance loses caused by contention issues may be more noticeable when there is a high concurrency level, such as when your computer has many cores.
If you encounter contention issues, try to fix the code in question. For the above example, changing node scheduling converted the above profile to the following one, providing a nice performance gain. For this reason, Python plug-ins are scheduled as Globally Serial by default. As a result, they will be scheduled one after the other and will not block multiple threads waiting for the GIL to become available.
Clusters. As mentioned earlier, if the EG contains node-level circular dependencies, those nodes will be grouped into a cluster which represents a single unit of work to be scheduled serially. Although multiple clusters may be evaluated at the same time, large clusters limit the amount of work that can be performed simultaneously. Clusters can be identified in the Profiler as bars wiip.opaqueTaskEvaluation label, shown below.
If your scene contains clusters, analyze your rig\u2019s structure to understand why circularities exist. Ideally, you should strive to remove coupling between parts of your rig, so rig sections (e.g., head, body, etc.) can be evaluated independently.
Tip
When troubleshooting scene performance issues, you can temporarily disable costly nodes using the per-node frozen
attribute. This removes specific nodes from the EG. Although the result you see will change, it is a simple way to check that you have found the bottleneck for your scene.
When the main bottleneck in your scene is rendering, we say the scene is render-bound. The following is an illustration of a sample result from the Maya Profiler, zoomed to a single frame measured from a large scene with many animated meshes. Because of the number of objects, different materials, and the amount of geometry, this scene is very costly to render.
![][image6.jpeg]
The attached profile has four main areas:
In this scene, a substantial number of meshes are being evaluated with GPU Override and some profiler blocks appear differently from what they would otherwise.
Evaluation. Area A depicts the time spent computing the state of the Maya scene. In this case, the scene is moderately well-parallelized. The blocks in shades of orange and green represent the software evaluation of DG nodes. The blocks in yellow are the tasks that initiate mesh evaluation via GPU Override. Mesh evaluation on the GPU starts with these yellow blocks and continues concurrently with the other work on the CPU.
An example of a parallel bottleneck in the scene evaluation appears in the gap in the center of the evaluation section. The large group of GPU Override blocks on the right depend on a single portion of the scene and must wait until that is complete.
Area A2 (above area A), depicts blue task blocks that show the work that VP2 does in parallel to the scene evaluation. In this scene, most of the mesh work is handled by GPU Override so it is mostly empty. When evaluating software meshes, this section shows the preparation of geometry buffers for rendering.
GPUOverridePostEval. Area B is where GPU Override finalizes some of its work. The amount of time spent in this block varies with different GPU and driver combinations. At some point there will be a wait for the GPU to complete its evaluation if it is heavily loaded. This time may appear here or it may show as additional time spent in the Vp2BuildRenderLists section.
Vp2BuildRenderLists. Area C. Once the scene has been evaluated, VP2 builds the list of objects to render. Time in this section is typically proportional to the number of objects in the scene.
Vp2PrepareToUpdate. Area C2, very small in this profile. VP2 maintains an internal copy of the world and uses it to determine what to draw in the viewport. When it is time to render the scene, we must ensure that the objects in the VP2 database have been modified to reflect changes in the Maya scene. For example, objects may have become visible or hidden, their position or their topology may have changed, and so on. This is done by VP2 Vp2PrepareToUpdate.
Vp2PrepareToUpdate is slow when there are shape topology, material, or object visibility changes. In this example, Vp2PrepareToUpdate is almost invisible since the scene objects require little extra processing.
Vp2ParallelEvaluationTask is another profiler block that can appear in this area. If time is spent here, then some object evaluation has been deferred from the main evaluation section of the Evaluation Manager (area A) to be evaluated later. Evaluation in this section uses traditional DG evaluation.
Common cases for which Vp2BuildRenderLists or Vp2PrepareToUpdate can be slow during Parallel Evaluation are:
Vp2Draw3dBeautyPass. Area D. Once all data has been prepared, it is time to render the scene. This is where the actual OpenGL or DirectX rendering occurs. This area is broken into subsections depending on viewport effects such as depth peeling, transparency mode, and screen space anti-aliasing.
Vp2Draw3dBeautyPass can be slow if your scene:
Other Considerations. Although the key phases described above apply to all scenes, your scene may have different performance characteristics.
For static scenes with limited animation, or for non-deforming animated objects, consolidation is used to improve performance. Consolidation groups objects that share the same material. This reduces time spent in both Vp2BuildRenderLists and Vp2Draw3dBeatyPass, since there are fewer objects to render.
"},{"location":"parallel/#saving-and-restoring-profiles","title":"Saving and Restoring Profiles","text":"Profile data can be saved at any time for later analysis using the Edit -> Save Recording...
or Edit -> Save Recording of Selected Events...
menu items in the Profiler window. Everything is saved as plain string data (see the appendix describing the profiler file format for a description of how it is stored) so that you can load profile data from any scene using the Edit -> Load Recording...
menu item without loading the scene that was profiled.
The purpose of Analysis Mode is to perform more rigorous inspection of your scene to catch evaluation errors. Since Analysis Mode introduces overhead to your scene, only use this during debugging activities; animators should not enable Analysis Mode during their day-to-day work. Note that Analysis Mode is not thread-safe, so it is limited to Serial; you cannot use analysis mode while in Parallel evaluation.
The key function of Analysis Mode is to:
Tip
To activate Analysis Mode, use the dbtrace -k evalMgrGraphValid;
MEL command.
Once active, error detection occurs after each evaluation. Missing dependencies are saved to a file in your machine\u2019s temporary folder (e.g., %TEMP%\\_MayaEvaluationGraphValidation.txt
on Windows). The temporary directory on your platform can be determined using the internalVar -utd;
MEL command.
To disable Analysis Mode, type: dbtrace -k evalMgrGraphValid -off;
Let\u2019s assume that your scene contains the following three nodes. Because of the dependencies, the evaluation manager must compute the state of nodes B and C prior to calculating the state of A.
Now let\u2019s assume Analysis Mode returns the following report:
Detected missing dependencies on frame 56\n{\n A.output <-x- B\n A.output <-x- C [cluster]\n}\nDetected missing dependencies on frame 57\n{\n A.output <-x- B\n A.output <-x- C [cluster]\n}\n
The <-x-
symbol indicates the direction of the missing dependency. The [cluster]
term indicates that the node is inside of a cycle cluster, which means that any nodes from the cycles could be responsible for attribute access outside of evaluation order
In the above example, B accesses the output
attribute of A, which is incorrect. These types of dependency do not appear in the Evaluation Graph and could cause a crash when running an evaluation in Parallel mode.
There are multiple reasons that missing dependencies occur, and how you handle them depends on the cause of the problem. If Analysis Mode discovers errors in your scene from bad dependencies due to:
There are two primary methods of displaying the graph execution order.
The simplest is to use the \u2018compute\u2019 trace object to acquire a recording of the computation order. This can only be used in Serial mode, as explained earlier. The goal of compute trace is to compare DG and EM evaluation results and discover any evaluation differences related to a different ordering or missing execution between these two modes.
Keep in mind that there will be many differences between runs since the EM executes the graph from the roots forward, whereas the DG uses values from the leaves. For example in the simple graph shown earlier, the EM guarantees that B and C will be evaluated before A, but provides no information about the relative ordering of B and C. However in the DG, A pulls on the inputs from B and C in a consistent order dictated by the implementation of node A. The EM could show either \"B, C, A\" or \"C, B, A\" as their evaluation order and although both might be valid, the user must decide if they are equivalent or not. This ordering of information can be even more useful when debugging issues in cycle computation since in both modes a pull evaluation occurs, which will make the ordering more consistent.
"},{"location":"parallel/#the-evaluation-toolkit","title":"The Evaluation Toolkit","text":"A set of debugging tools used to be shipped as a special shelf in Maya Bonus Tools, but they are now built-in within Maya. The Evaluation Toolkit provides features to query and analyze your scene and to activate / deactivate various modes. See the accompanying Evaluation Toolkit documentation for a complete list of all helper features.
"},{"location":"parallel/#known-limitations","title":"Known Limitations","text":"This section lists known limitations for the new evaluation system.
The profiler stores its recording data in human-readable strings. The format is versioned so that older format files can still be read into newer versions of Maya (though not necessarily vice-versa).
This is a description of the version 1 format.
First, a content example:
1 #File Version, # of events, # of CPUs\n2 2\\t12345\\t8\n3 Main\\tDirty\n4 #Comment mapping---------\n5* @27 = MainMayaEvaluation\n6 #End comment mapping---------\n7 #Event time, Comment, Extra comment, Category id, Duration, \\\n Thread Duration, Thread id, Cpu id, Color id\n8* 1234567\\t@12\\t@0\\t2\\t12345\\t11123\\t36\\t1\\t14\n9 #Begin Event Tag Mapping---------\n10 #Event ID, Event Tag\n11* 123\\tTaggy McTagface\n12 #End Event Tag Mapping---------\n13 #Begin Event Tag Color Mapping---------\n14 #Tag Label, Tag Color\n15* Taggy\\tMcTagface\\t200\\t200\\t13\n16 #End Event Tag Color Mapping---------\nEOF\n
The following table describes the file format structure by referring to the previous content:
Line(s)
Description
1
A header line with general file information names
2
A tab-separated line containing the header information
3
A tab-separated line containing the list of categories used by the events (category ID is the index of the category in the list)
4
A header indicating the start of comment mapping (a mapping from an ID to the string it represents)
5*
Zero or more lines lines mapping a number onto a string in the form @LINE = STRING
. The IDs do not correspond to anything outside of the file.
6
A footer indicating the end of comment mapping
7
A header indicating the start of event information. The names are the titles of the event columns.
8*
Zero or more tab-separated lines mapping to all of the events that were stored in the file
9
A header indicating the start of the event tag maps
10
A title line showing what values are in the event tag map columns
11*
Zero or more tab-separated lines attaching an event tag, defined through the profiler tool, to a specific event ID. The event ID will correspond to the ID given to it in the comment mapping section.
12
A footer indicating the end of the event tag maps
13
A header indicating the start of the event tag color maps
14
A title line showing what values are in the event tag color map columns
15*
Zero or more tab-separated lines mapping a tag label defined above to an R,G,B color
16
A header indicating the end of the event tag color maps
EOF
Sample version 2 file on 4 CPUs containing a single event of type \u201cETName\u201d, description \u201cETDescription\u201d, in category \u201cETCategory\u201d with description \u201cCategory description\u201d, using color 7, of duration 100 ticks, starting at tick 999, on a single thread with ID 22, tagged with \u201cTagMe\u201d which has color red (255 0 0)
#File Version, # of events, # of CPUs\n2 1 4\nETCategory\nCategory description\n#Comment mapping---------\n@0 = ETName\n#End comment mapping---------\n999 @0 @0 1 100 100 22 1 7\n#Begin comment description mapping---------\n@1 = ETDescription\n#End comment description mapping---------\n#Begin Event Tag Mapping---------\n#Event ID, Event Tag\n1 TagMe\n#End Event Tag Mapping---------\n#Begin Event Tag Color Mapping---------\n#Tag Label, Tag Color\nTagMe 255 0 0\n#End Event Tag Color Mapping---------\n
"},{"location":"parallel/#debugging-commands","title":"Debugging Commands","text":"Several commands can be used to help display information about your scene to help in debugging or optimizations. This is a summary of some of the more common ones, and represents only the available runtime information. Consult the command documentation in Maya\u2019s online technical documentation for more information about each command.
"},{"location":"parallel/#dbcount","title":"dbcount","text":"Maintains embedded code location counters for higher-level debugging of scene operation. Generally, this uses specialized code that is only available in custom builds.
Synopsis: dbcount [flags]\nFlags:\n -e -enabled on|off\n -f -file String\n -k -keyword String\n -l -list \n -md -maxdepth UnsignedInt\n -q -quick \n -r -reset \n -s -spreadsheet\n\nCommand Type: Command\n
"},{"location":"parallel/#dbmessage","title":"dbmessage","text":"Monitors messaging that adds and removes DAG and DG nodes.
Synopsis: dbmessage [flags]\nFlags:\n -f -file String\n -l -list \n -m -monitor on|off\n -t -type String\n\nCommand Type: Command\n
"},{"location":"parallel/#dbtrace","title":"dbtrace","text":"Turns on conditional code, typically to print out status information or to take different code paths when enabled.
To find available trace objects use dbtrace \u2013q to list currently-enabled traces, and dbtrace \u2013q \u2013off to list currently-disabled traces.
To find the current trace output target, use dbtrace -q -k keyword -o.
See below for information on specific keywords.
Note: Work is currently in progress to make these trace objects more flexible. It is a current design constraint that sometimes they are visible in a release, even though they only function internally, and some cannot be used when using Parallel evaluation.
Synopsis: dbtrace [flags]\nFlags:\n -q -query\n -f -filter String\n -i \u2013info\n -k -keyword String (multi-use)\n (Query Arg Optional)\n -m -mark \n -o -output String\n -off - \n -t -title String\n -tm -timed on|off\n -v -verbose\n\nCommand Type: Command\n
Keyword
Description
Contents (Default Output File)
OGSPolyGhosts
Shows progress of data extraction from the evaluation of poly ghosts through OGS
(stdout)
cacheConfig
Shows cache configuration rules evaluation
Result of cache configuration rules for each evaluation node (_Trace_CacheConfig.txt)
cipEM
Shows what Customer Improvement Program data is being collected.
Generic usage information. No longer being used (stdout)
cmdTracking
Enables the tracking of counts of commands. Use the dbpeek \u2018cmdTracking\u2019 operation to view the results.
No output, but enables tracking of the counts for all commands being executed. (For example, you can turn it on during file load to get a count of the number of createNode calls, including those in referenced files, a task that is difficult to do manually) (stdout)
compute
High level trace of the compute path
Nested output showing compute methods being called. Typically in EM mode you should see nesting only in cycles. DG mode will show the full set of nodes triggered by a single evaluation request (_Trace_Compute.txt)
dbCache
Data block manipulation
Details of the creation and manipulation of datablock information (_Trace_DataBlockCache.txt)
deformerEvaluator
Statistics for the deformer evaluator setup
Shows statistics on what the deformer evaluator was able to ingest, once enabled (stderr)
evalMgr
Evaluation manager interactions
(_Trace_EvalManager.txt)
evalMgrGraphInvalid
Evaluation manager graph invalidation
(stdout)
evalMgrGraphValid
Evaluation manager execution graph validation errors and warnings
Nodes that were evaluated while in EMS mode using the pull (DG) model. This indicates missing dependencies in the evaluation graph, possibly caused by custom dirty propagation (_MayaEvaluationGraphValidation.txt)
evalMgrSched
Internal use only
(_MayaScheduling.txt)
idleBuild
Operation of the idle build mechanism for the evaluation graph
When the idle build is active, this appears when the idle build is triggered and executed (_Trace_EGBuild.txt)
nodeTracking
Enables tracking of counts of created nodes. Use the dbpeek \u2018nodeTracking\u2019 operation to view results.
(stdout)
peekCache
Shows progress of the dbpeek -op cache operation
Dumps data collected by the dbpeek operation, and how (_Trace_DbPeekCache.txt)
peekContext
Shows progress of the dbpeek -op context operation
Dumps data collected by the dbpeek operation, and how (stdout)
peekData
Shows progress of the dbpeek -op data operation
Dumps data collected by the dbpeek operation, and how (_Trace_DbPeekData.txt)
peekMesh
Shows progress of the dbpeek -op mesh operation
Dumps data collected by the dbpeek operation, and with what flags (_Trace_DbPeekMesh.txt)
"},{"location":"parallel/#dgdebug","title":"dgdebug","text":"Historical debugging command; not robust or documented. Deprecated: Use the newer dbpeek command.
No help is provided for this command.\n
"},{"location":"parallel/#dgdirty","title":"dgdirty","text":"Forces dirty/clean states onto specified plugs and everything downstream from them. Meant to be a safety net for restoring proper states to your scene when something has gone wrong.
You should not need to use this command, but it will continue to exist as a \u201creset button\u201d, just in case.
Synopsis: dgdirty [flags] [String...]\nFlags:\n -q -query\n -a -allPlugs \n -c -clean \n -i -implicit \n -l -list String\n -p -propagation\n -st -showTiming \n -v -verbose\n\nCommand Type: Command\n
"},{"location":"parallel/#dgeval","title":"dgeval","text":"Forces the node to compute certain plugs. Like dgdirty, this command is meant to be a safety net if computation has not occurred in the proper order. Similar in function to the getAttr command, but since it returns no results, it can handle all attribute types, not only those supported by getAttr.
Synopsis: dgeval [flags] String...\nFlags:\n -src - \n -v -verbose\n\nCommand Type: Command\n
"},{"location":"parallel/#dginfo","title":"dgInfo","text":"Dumps information about the current state of the graph. Be aware that when plug dirty states are reported, they represent the connection associated with the plug. In fan-out or in-out connections there will be more than one dirty state associated with the connection attached to the plug. This means it is legal to see A->B as dirty but B->A as clean if A has multiple connections. Being Deprecated: Use the newer dbpeek command.
Synopsis: dgInfo [flags] [String...]\nFlags:\n -all -allNodes \n -c -connections \n -d -dirty on|off\n -n -nodes \n -nd -nonDeletable\n -nt -type String\n -of -outputFile String\n -p -propagation on|off\n -s -short \n -sub -subgraph \n -sz -size\n\nCommand Type: Command\n
"},{"location":"parallel/#dgmodified","title":"dgmodified","text":"Checks on the reason a file requests saving when no changes have been made.
Synopsis: dgmodified\n\nNo Flags.\n
"},{"location":"parallel/#dbpeek","title":"dbpeek","text":"This command is called out intentionally, as it combines multiple operations into a single command by use of various operations.
It runs one of several operations that provide a view into the data internals in the scene. This is the most useful and flexible of the debugging commands, and new variations of it are often being introduced. Use dbpeek -q -op to show a list of currently available operations and dbpeek -op X -q to show detailed help for operation X.
See below for information on specific keywords.
Note: The syntax of the argument flag allows for both keyword argument=\u2019key\u2019 and keyword/value argument=\u2019key=value\u2019 forms.
Synopsis: dbpeek [flags] [String...]\nFlags:\n -q -query\n -a -argument String (multi-use) (Query Arg Mandatory)\n -all -allObjects \n -c -count UnsignedInt\n -eg -evaluationGraph\n -of -outputFile String\n -op -operation String (Query Arg Optional)\n\nCommand Type: Command\n
"},{"location":"parallel/#dbpeek-op-attributes","title":"dbpeek -op attributes","text":"Analyzes node or node-type attributes and dumps information about them based on what the selected operation type.
Various arguments to the operation change the content of the output. The essence remains the same; the attributes belong to the node or node type.
Argument
Meaning
detail
Adds all internal details from attributes being dumped, otherwise dumps only the names and structure. The details are output as object members of the attribute, including the children.
nodeType
Dumps all attributes belonging to the selected node(s) types. If nothing is selected, it dumps the attributes for all available node types. This includes all node types up the hierarchy to the base node class.
noDynamic
Skips dynamic attributes in all output.
noExtension
Skips extension attributes in all output.
noStatic
Skips static attributes in all output.
onlyPlugins
Restricts any output to nodes and node types that originate from a plug-in.
type=affects
Dumps attribute structure and affects relationships in the graphical .dot format.
type=detail
Dumps attribute information in .json format. This is the default if no type is specified.
type=validate
Validates flags and structure for consistency and validity.
If no nodes are selected, then this command prints the list of all attributes on all nodes. For example, if you had a node type called reversePoint with a vector input and a vector output.
type=detail would output this JSON data:
{\n \"nodes\" :\n {\n \"reversePoint\" :\n {\n \"staticAttributes\" : [\n { \"pointInput\" : [\n \"pointInputX\",\n \"pointInputY\",\n \"pointInputZ\",\n ]\n },\n { \"pointOutput\" :\n [\n15\"> \"pointOutputX\",\n \"pointOutputY\",\n \"pointOutputZ\",\n ]\n }\n ],\n \"extensionAttributes\" : []\n }\n }\n }\n
type=affects would output this DOT data:
digraph G\n{\n compound=true;\n subgraph cluster_NODENAME\n {\n label=\"Node NODENAME, Type NODETYPE\";\n color=\".7 .0 .0\";\n ia [label=\"ia/inputAttribute\",style=\"rounded\",shape=ellipse];\n oa [label=\"oa/outputAttribute\",style=\"rounded\",shape=rectangle];\n ia -> oa;\n }\n}\n
and type=validate would output this JSON validation summary:
{\n \"Attribute Validation\" :\n {\n \"NODENAME\" :\n {\n \"staticAttributes\" :\n [\n {\n \"Both input and output attributes in compound\" :\n [\n { \"root\" : \"rootAttribute\",\n \"inputs\" : [\"inputChild\"],\n \"outputs\" : [\"outputChild\"],\n }\n ]\n }\n ]\n }\n }\n}\n
"},{"location":"parallel/#dbpeek-op-cache","title":"dbpeek -op cache","text":"This operation is explained in detail in the Debugging section of the Maya Cached Playback whitepaper.
"},{"location":"parallel/#dbpeek-op-cmdtracking","title":"dbpeek -op cmdTracking","text":"By default, when no detail argument is present it shows a list of all commands run since the last reset as well as a count of how many of each type were executed.
Outputs in command/count pair form, one per line, with a tab character separating them.
Argument
Meaning
reset
Set all of the command tracking statistics to zero
"},{"location":"parallel/#dbpeek-op-connections","title":"dbpeek -op connections","text":"By default, when no type argument is present, shows a list of all connections in the DG.
Argument
Meaning
summary
Reduces the output to show only the connection counts on the nodes. It separates by single and multi but no further information is added. Useful for getting basic usage information.
verbose
Shows extra information about every connection, including dirty/propagation states, plug ownership, and type connectivity of the connection. Connections can be single or multi, and be connected either to each other or to plugs.
"},{"location":"parallel/#dbpeek-op-data","title":"dbpeek -op data","text":"Dumps the current contents of a node\u2019s plug data in a standard format. By default the output is in CSV format consisting of 5 columns: NODE PLUG DATA_TYPE CLEAN_STATE DATA_AS_TEXT
Example for a simple integer attribute with a dirty value of 5: MyNode MyPlug Int32 0 5
Argument
Meaning
eval
Evaluates plugs first to guarantee that they are clean. Note: Some plugs are always dirty so there may still be plugs that show a dirty value.
full
Includes plugs with default values in the output.
json
Uses JSON format for the output. The general form is { \"NODE\" : { \"PLUG\" : { \"TYPE\", \"CLEAN\", \"VALUE\" } } }
. For example, a simple numeric attribute with a dirty value of 5 { \"MyNode\" : { \"MyPlug\", \"0\", \"5\" } }
matrix
Includes all plugs with a \u201cmatrix\u201d data type in the output. This does not include generic data that may have a matrix value at runtime, only attributes that are exclusively matrix types.
number
Includes all plugs with any numerical data type in the output. This does not include any generic data that may have numerical value at runtime, only attributes that are exclusively numeric types. It includes all types of numeric values, including linear, angular, time, and unitless values.
state
Includes the current dirty state of the data in the output.
time=TIME
Rather than evaluating at the normal context, evaluates at a context using the given time. This is somewhat equivalent to getAttr -t TIME.
vector
Includes all plugs with a \u201cvector\u201d data type in the output. Does not include generic data that may have a vector value at runtime, only attributes that are exclusively double[3] types.
"},{"location":"parallel/#dbpeek-op-context","title":"dbpeek -op context","text":"Analyzes context evaluation to detect various errors violating the design.
Argument
Meaning
isolationType=animatedAttributes
Filters errors, reporting only those involving animated attributes
isolationType=animatedNodes
Filters errors, reporting only those involving animated nodes
isolationType=staticAndAnimated
Reports all errors
test=isolation
During evaluation, detects when evaluation context is violated causing data to be read or written into a state that belongs to some other evaluation context
test=correctness
Evaluates the scene in the background, comparing evaluation data stored for background and main context; compares traversing evaluation graph visiting nodes only if all upstream nodes generate equivalent data in both the background and the main context
time=TIME
Takes a string value indicating the frame time at which evaluation should be performed.
verbose
Adds extra information to output report. Each test will have its own verbose data. Isolation: Adds callstack information to the report for each detected error. Correctness: Adds attributes which compare failed to compare (due to missing logic)
Sample output for isolation tests:
{\n \"context isolation\": {\n \"frame\": 5.0,\n \"type\": \"animatedNodes\",\n \"verbose\": true,\n \"errors\": [\n {\n \"node\": \"ikHandle1\",\n \"type\": \"ikHandle\",\n \"attribute\": \"ikFkManipulation\",\n \"call stack\": [\n \"METHOD Line NUMBER\",\n \"METHOD Line NUMBER\",\n \"METHOD Line NUMBER\"\n ]\n },\n {\n \"node\": \"shape\",\n \"type\": \"mesh\",\n \"attribute\": \"displaySmoothMesh\",\n \"call stack\": [\n \"METHOD Line NUMBER\",\n \"METHOD Line NUMBER\",\n \"METHOD Line NUMBER\"\n ]\n }\n ],\n \"time out\": true\n }\n}\n
Sample output for correctness tests:
{\n \"context correctness\": {\n \"frame\": 14.0,\n \"verbose\": true,\n \"errors\": [\n {\n \"node\": \"IKSpineCurveShape\",\n \"type\": \"nurbsCurve\",\n \"attributes\": [\n \"worldSpace\"\n ]\n }\n ],\n \"failed to compare\": [\n \"input\",\n \"clusterXforms\",\n \"clusterTransforms\",\n \"target\",\n \"mySpecialAttribute\"\n ],\n \"time out\": true\n }\n}\n
"},{"location":"parallel/#dbpeek-op-edits","title":"dbpeek -op edits","text":"Shows a list of all nodes for which tracking is currently enabled. The \u201ctrack\u201d flag is mandatory.
Argument
Meaning
track
Shows a list of all nodes for which tracking is currently enabled.
"},{"location":"parallel/#dbpeek-op-evalmgr","title":"dbpeek -op evalMgr","text":"Outputs the current state of all of the custom evaluators used by the Evaluation Manager.
Argument
Meaning
custom
Outputs the custom evaluators registered with the evaluation manager.
global
Adds output that is independent of scene contents, for example, node types enabled for the custom evaluators.
local
Adds output that is specific to the scene contents, for example, nodes supported by a custom evaluator.
"},{"location":"parallel/#dbpeek-op-graph","title":"dbpeek -op graph","text":"Gets a list of nodes or connections from either the dependency graph or the underlying evaluation graph.
Argument
Meaning
connections
Dumps the list of all connections in the chosen graph. The sorting order is alphabetical by destination plug name.
dot
Dumps the graph information in .dot format for parsing and display by an external application such as graphViz.
evaluationGraph
Gets the structure information from the evaluation graph, otherwise uses the raw dependency graph. The dbpeek command flag \u201cevaluationGraph\u201d does the same thing.
graph
Dumps the graph state and contents, not including what is dumped by any of the other flags.
nodes
Dumps the list of all nodes in the chosen type of graph, in alphabetical order by full node name.
plugs
For the evaluation graph option, dumps the list of all plugs in its dirty plug list in the evaluation nodes. For the DG option, dumps the list of plugs currently in the plug trees.
scheduling
Dumps the scheduling type used for all nodes in the type of graph in the form NODE = SCHEDULING_TYPE. If a node type is specified, the default scheduling type for nodes of that specific node type is returned in the same format.
verbose
When dumping the scheduling graph in .dot format, adds all of the names of the nodes to the clusters. Otherwise, it is only a count of nodes in each cluster
"},{"location":"parallel/#dbpeek-op-mesh","title":"dbpeek -op mesh","text":"Dumps the current contents of the mesh to a standard format. There are two types of formatting and two levels of detail to present.
Argument
Meaning
eval
Evaluates mesh plugs first to guarantee they are clean. Otherwise the values currently present in the mesh shape are used as-is.
json
Dumps data in JSON format instead of CSV.
verbose
Puts full values for all of the data in the output. Otherwise, only a number count of each type is returned. See the flag descriptions for more information on which data can be requested and what is returned for each type.
vertex
Includes vertex position or vertex count in the output. The short return is a count of vertices in the mesh. The verbose values are a list of vertex number and the {X,Y,Z} positions of the vertex, with W factored in, if appropriate.
For the default level of detail, the default CSV format output will look like this:
NODE_NAME,DATA_TYPE,DATA_COUNT\n
For example, a cube containing 32 vertices would have these lines:
Node,DataType,Count\npCubeShape1,outMesh,32\n
The JSON equivalent format would look like this:
{\n \"pCubeShape1\" : {\n \"outMesh\" : \"32\"\n }\n}\n
If the full detail is requested, then the (abbreviated) output for CSV format will look like this:
Node,Plug,Clean,Value\npCubeShape1,outMesh[0],1,0.0 0.0 0.0\npCubeShape1,outMesh[1],1,0.0 0.5 0.0\n...\npCubeShape1,outMesh[32],1,1.0 1.0 1.0\n
and like this for JSON format:
{\n \"pCubeShape1\" : {\n \"outMesh\" : {\n \"clean\" : 1,\n \"0\" : [0.0, 0.0, 0.0],\n \"1\" : [0.0, 0.5, 0.0],\n \"...\" : \"...\",\n \"32\": [1.0, 1.0, 1.0]\n }\n }\n}\n
"},{"location":"parallel/#dbpeek-op-metadata","title":"dbpeek -op metadata","text":"Shows node metadata. The default operation shows a list of all nodes containing metadata.
Argument
Meaning
summary
Shows a single line per node, with metadata indicating how many channels, streams, and values are present in the metadata.
verbose
Shows a detailed list of all metadata on nodes, including a dump in the debug serialization format for each of the metadata streams.
"},{"location":"parallel/#dbpeek-op-node","title":"dbpeek -op node","text":"Show select debugging information on DG nodes. See also the \u201cplug\u201d and \u201cconnection\u201d operations for display of information specific to those facets of a node. If no arguments are used then the ones marked as [default] will all be enabled, for convenience.
Argument
Meaning
datablock
[default] Shows the values in the datablock(s)
datablockMemory
Shows raw datablock memory. This is independent of the other other datablock flags.
dynamicAttr
Shows dynamic attributes.
evaluationGraph
[default] Includes evaluation graph information on the node
extensionAttr
Shows the extension attributes
node
[default] Shows information specific to individual node types, such internal caches, flags, or special relationships it maintains. All other data shown is common to all node types
plug
[default] Shows the nodes plug information
skipClean
Does not include datablock values that are clean
skipDirty
[default] Does not include the datablock values that are dirty
skipMulti
Does not include the datablock values that are multi (array) attributes
staticAttr
Shows the static attributes
verbose
Shows much more detail where available. This will include things such as flags set on objects, full detail on heavy data, and any extra detail specific to a node type, such as caches.
"},{"location":"parallel/#dbpeek-op-nodes","title":"dbpeek -op nodes","text":"By default, when no detail argument is present, shows a list of all currently registered node types.
Argument
Meaning
binary
Also includes the IFF tag used to identify each node type in the \u201c.mb\u201d file format
"},{"location":"parallel/#dbpeek-op-nodetracking","title":"dbpeek -op nodeTracking","text":"By default, when no argument is present, shows a list of all nodes created since the last reset along with a count of how many of each type were created. Output is in the form of nodeType/count pairs, one per line, with a tab character separating them.
Argument
Meaning
reset
Erases all of the node tracking statistics.
"},{"location":"parallel/#dbpeek-op-plugs","title":"dbpeek -op plugs","text":"Shows information about all of the plugs in a scene. By default, when no argument is present, shows static plug footprint. A lot of this is only displayed in specially-instrumented builds, and generally only of use internally.
Argument
Meaning
details
Includes the full plug/node name information in the output. Otherwise only the total and summary counts are dumped.
group=stat
Groups all output by statistic name
group=node
Groups all output by node name
mode=footprint
Reports size information for currently-existing networked plugs.
mode=usage
Reports dynamic code path statistics, if they have been enabled in the current build
mode=reset
When used in conjunction with \u201cusage\u201d, resets the statistics back to zero.
mode=state
Gets unevaluated state information for boolean plugs. Only available on specially-built cuts.
nodeType=TYPE
Restricts the operation to the node types specified in the argument. This includes inherited types, for example if the value is \u201ctransform\u201d, then the operation also applies to \u201cjoint\u201d nodes, as the node type \u201cjoint\u201d inherits from the node type \u201ctransform\u201d. See the node type documentation or the nodeType command for complete information on which node types inherit from each other.
stat=STAT
If this argument has no STAT, then sorts by the name of the statistic. If this argument does have a STAT, for example, \u201cstat=addToNet\u201d, then only reports that statistic. Only available on specially-built cuts.
"},{"location":"parallel/#revisions","title":"Revisions","text":""},{"location":"parallel/#2020","title":"2020","text":"Every object in the real world can move along 6 different axes, or 6 \"degrees of freedom\".
A constraint limits one or more of these axes.
In Maya, the most typical form of constraint is locking a channel. This prevents this axis from changing.
LOCKED
, meaning it may not move along this axisFREE
, meaning it may freely move along this axisLIMITED
, meaning it may move within the limited range of this axisLimits above 0 are referred to as \"soft\", because their amount of influence can be tuned using the Stiffness
and Damping
attributes. These can safely flex and can approach that of a hard constraint given enough stiffness and damping, but would struggle to reach a given target 100%.
Limits below 0, typically -1, are referred to as \"hard\", because their influence is infinite. These should never flex, as even the slightest amount of flex means the constraint has broken. Leaving the solver in a poor state, struggling to keep up.
"},{"location":"quick-tail-setup/","title":"Quick tail setup","text":"In this tutorial you'll learn how to setup a tail with physics and how to steer the look and feel of the simulation using normal keyframing techniques. We'll use one of the excellent rigs by Truong CG Artist.
Optional example files
Let's start with a walkcycle, and move towards interacting with the environment.
"},{"location":"quick-tail-setup/#apply-simulation","title":"Apply Simulation","text":"Select the hip followed by each tail control along the tail in order, and click Create Dynamic Control.
"},{"location":"quick-tail-setup/#reduce-gravity","title":"Reduce Gravity","text":"This particular rig is very small, about 1.6 cm tall, so we need to reduce the default Gravity to reflect this.
"},{"location":"quick-tail-setup/#global-strength","title":"Global Strength","text":"The first selected Dynamic Control contains a Guide Multiplier to influence the strength on all of the tail controls at the same time.
"},{"location":"quick-tail-setup/#local-strength","title":"Local Strength","text":"You can also adjust the strength values individually for each joints, to taper their stiffness along the length of the tail.
"},{"location":"quick-tail-setup/#strength-falloff","title":"Strength Falloff","text":"Let's taper the strength along the length of the tail.
"},{"location":"quick-tail-setup/#result","title":"Result","text":"Let's see how it looks.
"},{"location":"quick-tail-setup/#sitting-down","title":"Sitting Down","text":"Now let's see how to steer our simulation with regular keyframes.
"},{"location":"quick-tail-setup/#switch-to-animation","title":"Switch to Animation","text":"The simulation will try to follow your keyframe animation. Just switch off the Simulated
attribute on the root control while you're animating, then switch it back on to see how it looks.
You can see the animation input on the left and the resulting simulation on the right. With just 3 keyframed poses we end up with this result. Note that I had to overcompensate my animation poses to fight gravity when the tail swings around.
"},{"location":"quick-tail-setup/#advanced-control","title":"Advanced Control","text":"Gain even more fine-grained control with these advanced topics.
"},{"location":"quick-tail-setup/#flex-and-relax-muscles","title":"Flex and Relax Muscles","text":"By keyframing the root strength multiplier you can flex or relax the muscles in the tail. The higher the value the stiffer it gets and the lower the value the more relaxed it becomes, allowing gravity to drop it to the ground.
"},{"location":"quick-tail-setup/#damping","title":"Damping","text":"Damping controls how fleshy and sluggish your simulation behaves.
Low or zero damping preserves more energy in the system, making a simulation more elastic or rubbery. Creatures and humans tend to look best with moderate to high damping values.
"},{"location":"sdk/","title":"SDK","text":"The Ragdoll SDK is not Object Oriented, it is Data-Oriented in the form of an Entity Component System (ECS).
Concept Is A Description Entityunsigned int
Represents a \"thing\", like a marker, group and solver Component struct
Represents some data, like a name, position and color System for-loop
Represents some operation on said data Stay Tuned
This is where you'll find documentation for Ragdoll Core.
"},{"location":"tutorials/","title":"Tutorials","text":"Learn about Ragdoll from the ground up with these short videos.
This addon is licenced under the MIT licence
Windows & LinuxRagdoll 2024.04.15 awaits. Read about it - Previous versions
Join the community of ragdollers on Discord and/or Discourse.
GitHub Chat Forums "},{"location":"blender/download/#install","title":"Install","text":"Ragdoll for Blender is a bridge between Ragdoll Core and Blender, and ships as a platform independent Addon.
To install the addon, you do what you'd normally do for addons, via the \"Install\" button in Blender's preferences.
Edit > Preferences...
Add-ons
pageInstall..
and select RagdollBlender.zip
you downloaded aboveRagdoll
Next, you'll need Ragdoll Core. Which is the engine that performs the actual physics computations.
When a new version of Ragdoll hits the shelves, here's what you do.
Upon loading the addon, Ragdoll will automatically start the clock on a 1-month trial.
To carry on from your trial, you can purchase a new licence via our website.
You'll receive a serial which you can enter via the bottom item of the Ragdoll menu.
Enter your serial in the bottom text field and press Activate.
Issues?
Let us know if you run into any issues at licencing@ragdolldynamics.com
"},{"location":"blender/download/#using-ragdoll","title":"Using Ragdoll","text":"Once the addon has been enabled, you'll find a few new elements in your Blender UI.
We're working on material explicitly for Blender, until then feel free to enjoy the tutorials for Maya, as the workflow is near identical:
Let us know on our forums, we'll keep updating this page with new releases.
"},{"location":"blender/home/","title":"Blender","text":""},{"location":"blender/home/#ragdoll-in-blender","title":"Ragdoll in Blender","text":"Welcome to Ragdoll in Blender, first released in February of 2024 and with support for versions 3.4 up to 4.0.
"},{"location":"blender/reference/","title":"Reference","text":""},{"location":"blender/reference/#manipulator","title":"Manipulator","text":"With Industry Standard keymapping, the Manipulator has a default interaction model.
With native Blender keymapping, the Middle-mouse button is occupied so instead:
Action Key Translate Ctrl + LMB Scale Ctrl + Shift + LMB Rotate Ctrl + Alt + LMB "},{"location":"blender/reference/#properties","title":"Properties","text":"Ragdoll exposes several properties you can use to tune your simulation, divided into several \"archetypes\". One of which is the physics solver itself, responsible for overall settings like start and end frames and quality parameters such as Substeps
.
Responsible for overall simulation settings and keep track of what to include in the physics world.
Property Description Enabled Whether to simulate or not Export Include this solver when exporting the Ragdoll file to disk Cache Keep simulated frames for the next time you playback your scene Start Time When to start simulating Simulate Every X Frames Enable stop-motion like simulation Substeps Divide every Blender frame into this many \"sub steps\", improves quality at the expense of performance Iterations Try this many times to solve each internal physics constraint Air Density The effect of air, 0 means space and 10 means water Gravity Force applied to all Markers in the solver, to emulate gravity Time Scale Slow motion, or not Scene Scale When your character is not at a realistic e.g. 1.8m height, use this to compensate "},{"location":"blender/reference/#rmarker","title":"rMarker","text":"Tracker for your animation controls, like the red pill in The Matrix. This transmits information about each control to Ragdolll, such that it knows where to go and at which strength.
Property Description Enabled Whether to include this rMarker in the rSolver Export Include this Marker when exporting Behaviour Whether to simulate the control, or treat it as pure animation. The default is to inherit the value from the rGroup Translate Motion Should the control be allowed to translate? Rotate Stiffness The \"strength\" at which to follow the animation control Rotate Damping The \"resistance\" at which to follow the animation control "},{"location":"blender/reference/#rgroup","title":"rGroup","text":"Control the stiffness of multiple markers at once.
Property Description Enabled Whether to include this rMarker in the rSolver Export Include this Group when exporting Self Collide Allow contained Markers to collide with each other Translate Motion Should the controls in this group be allowed to translate? Rotate Stiffness Multiply this value with every Markers contained in the group Rotate Damping Likewise, multiply this value with every Markers contained in the group "},{"location":"blender/reference/#workspace-tool","title":"Workspace Tool","text":"On the left-hand side you'll find the Ragdoll Manipulator
. This is where you can manipulate shapes and limits, along with entering into Live Mode to interactively pose your character and verify thet contacts and limits behave to your liking.
Any new Ragdoll object is automatically added to a Ragdoll
collection.
An advanced course in how to setup a character in Blender with Ragdoll.
Comments
\"Make your own motion reference\"
In this tutorial, we will setup a human-like character for use as reference or constraint target to your rig. You will be able to pose and position this Manikin like you would a real Manikin, and drop it from various heights and onto various obstacles to produce realistic poses as it falls.
Something the animator can import and throw around for reference on how it would look like.
Version 1.0 - Up to date
Written for Ragdoll 2024.02.25
and above.
Estimated Time
You will learn
Where to find help
If you find or run into any issues with this tutorials, here's what you can do.
Follow this tutorial either using our provided Manikin rig, or your own character. It can have any number of limbs.
Download Manikin Download Final Scene "},{"location":"blender/tutorials/manikin/#motivation","title":"Motivation","text":"Why should we even bother simulating a character?
Finding motion reference is one of the most important activities for any animator. And yet I can safely challenge you to find reference for perhaps the most common motion in all blockbuster movies today, something that is either impossible or dangerous for actors or animators alike.
Or how about reference of someone simply falling over, perhaps from heat stroke or staring into the sun.
This is, after all, one of the major reasons for pursuing computer graphics in storytelling rather than real people.
Animators bring life to characters, but of equal challenge is that of lifelessness. Of natural and realistic motion without someone behind the wheel. Be it getting hit or shot, blasted or thrown, animating lifelessness is enough to challenge even the most senior of animators.
As you will find, there is a lot more we can do once our motion reference is in 3D, on our actual character rig within Maya and infinitely customisable. As opposed to some video on the internet.
"},{"location":"blender/tutorials/manikin/#setup","title":"Setup","text":"Open your chosen character rig or download the above Manikin rig to get started.
Play around with the controls to get a feel for what we're working with.
FK or IK
Use FK for this tutorial
This Manikin rig has FK and IK (legs) controls, but we will focus on FK controls for this tutorial to keep things simple.
"},{"location":"blender/tutorials/manikin/#simulation","title":"Simulation","text":"The stage is set, now let's apply physics!
"},{"location":"blender/tutorials/manikin/#torso","title":"Torso","text":"Let's start with the Torso.
hip_ctl
torso_ctl
head_ctl
Assign and Connect
This will produce our first Group
, which is a collection of connected Markers
.
New Concept
Group
The rdGroup
node contains attributes that affect all contained markers. It's where you'd edit the overall look and feel of your character, like how stiff it should be and whether or not body parts should collide with each other.
Each Marker can either inherit or otherwise override these values.
Assignable Objects
These objects can have Markers assigned to them in Blender.
Next we will continue from the torso_ctl
and out into the arms.
torso_ctl
L_clavicle_ctl
L_upperArm_ctl
L_lowerArm_ctl
L_hand_ctl
Assign and Connect
Yes, the order in which you select will determine how the markers are connected.
Your first selection is extra important, as it determines whether to start a new group, like for the hip_ctl
, or to add to an existing group, like the torso_ctl
.
In this case, we would very much like our arm to be connected to the torso.
Can I skip the clavicles?Yes, if you have extra controls - such as twist
or bend
- you can skip these if you don't care to simulate them.
Simply skip over them as you select, from torso_ctl
directly to L_upperarm_ctl
.
Now repeat the above process for the other arm.
"},{"location":"blender/tutorials/manikin/#legs","title":"Legs","text":"Now let's continue down the hips and into the legs.
hip_ctl
L_thigh_ctl
L_knee_ctl
L_foot_ctl
Assign and Connect
That's enough setup, let's drop him!
New Concept
Behaviour
Each Marker has a \"behaviour\", which tells Ragdoll it should interpret the control it has been assigned. Should it fall with gravity? Should it try and match the pose? Should it remain fully animated, even in simulation?
rMarker_Armature_hip_ctl
Behaviour = Simulated
of the MarkerThe default behaviour for Assign and Connect
is to give the first selection - the \"root\" - a Animated
behaviour.
What does Animated mean?
Animated means \"copy the animation into simulation and make no changes to it\"
By instead setting this to Simulated
, then Ragdoll will only use the animation for the starting position and orientation of the simulation.
Inherit
Alternatively, you can set it to Inherit
to have it inherit the value of the rGroup
node that was created for the whole character.
Next let's address the elephant in the room; the shapes. They look awful.
"},{"location":"blender/tutorials/manikin/#volumes","title":"Volumes","text":"The shape of each collider affects your simulation in 2 ways.
The contact point can be important if your character interacts with an environment or another character. Like in this case where the feet are incorrectly colliding with the ground because of a bad shape.
That's not always the case though, sometimes you just want overlapping motion without contacts in which case the shapes won't matter.
They do however also affect their resistance to rotation. Consider this.
Here, we rotate the exact same shapes, the exact same amount in the exact same amount of time. And yet they respond differently.
This shape has vastly different dimensions in the X, Y and Z directions, resulting in a different rotation mass for each one. As a result, the effort required to rotate it in each axis differs too.
In practice, you'll find this for just about any limb on a character, which is typically longer in one axis. For our Manikin, this is especially true for the default clavicle shapes.
Override Rotate Mass
In some cases, you have a shape but want it to act like a different shape. Rotate Mass
is very similar to normal Mass
, except in 3 dimensions. Where the position of an object is affected equal in X, Y and Z directions, rotations have 3 separate masses.
With this in mind, let's tune some shapes.
This brings up the Manipulator interface, where you can manipulate shapes interactively.
Great, now let's turn those hands and feet into boxes.
Translate, Rotate and Scale
Notice I'm using the..
Translate
Rotate
Scale
The help text screen-right will help you remember these.
Greater Value Step
While dragging the value on Manipulator UI panel, you may hold Shift
to increase value changing step.
Symmetry
Also notice the edits are symmetrical; even when they don't start out that way like the feet!
"},{"location":"blender/tutorials/manikin/#recording","title":"Recording","text":"That's all there is for setting up your character rig for simulation! Let's now transfer the simulation back onto the rig.
Record Simulation
Visit our forums and YouTube channel for latest up to date material!
An example of how to setup a character, append it twice to one scene, and merge their solvers for character-to-character interactions.
A few weeks ago, Kojima Productions dropped a first trailer for Death Stranding 2, where they leveraged Ragdoll for a puppet being tossed around.
While we await a breakdown from Kojima, we threw together our own breakdown and tutorial of how it could be made with Blender.
Enjoy :)
Comments
For Blender users but also applicable to Maya. This one is about tweaking existing animation, such as motion capture, with physical parameters to create variations and generally just have fun.
It uses a motion capture clip from Mixamo and applies physics to just one arm at first, followed by the second arm for some different kind of dance moves.
Any questions, feel free to ask here or on YouTube, we'll be on the lookout!
Comments
A continuation of Slap'n'Sass 1 from the other day, this time simulating the entire character rather than just the arms, covering:
Comments
Talk about cmdx and why it's necessary.
"},{"location":"blog/20201215_cmdx/#overview","title":"Overview","text":"Some idea of what cmdx even is.
"},{"location":"blog/20201215_cmdx/#end","title":"End","text":""},{"location":"blog/20201216_high_dpi_and_px/","title":"20201216 high dpi and px","text":""},{"location":"blog/20201216_high_dpi_and_px/#ui-and-resolution-scaling","title":"UI and Resolution Scaling","text":"Read about how Ragdoll implements resolution scaling, to support scalable UIs on modern high-resolution displays.
"},{"location":"blog/20201216_high_dpi_and_px/#tldr","title":"TL;DR","text":"Here's a standalone version of the function I'll be walking you through, requires Maya 2017 (Qt 5) and above (due to QScreen
).
def px(value):\n if not hasattr(px, \"dpi\"):\n any_widget = QtWidgets.QWidget()\n any_widget.setWindowFlags(QtCore.Qt.ToolTip)\n any_widget.show()\n window = any_widget.windowHandle()\n scale = window.screen().logicalDotsPerInch() / 96.0\n px.dpi = scale\n\n return value * px.dpi\n
"},{"location":"blog/20201216_high_dpi_and_px/#what-is-resolution-scaling","title":"What is Resolution Scaling?","text":"Most displays have resolutions beyond the traditional 1080p, which makes text and graphics overly small. To account for this, operating systems have implemented \"resolution scaling\"; which is some factor to scale text and graphics by when drawing it on screen.
Maya added (early and crude) support for resolution scaling in Maya 2016 with a usable and mostly transparent version landing in 2018 and beyond.
Building UIs with Maya's native MEL-based UI tools account for scaling automatically, so you generally don't have to think about it. Unfortunately, for any non-trivial Qt project however you'll need to actively implement and maintain support for it.
Ragdoll does this, and here's how.
"},{"location":"blog/20201216_high_dpi_and_px/#implementation","title":"Implementation","text":"In short, any mention pixels run through a conversion function like this.
# setFixedWidth(50) # Before\nsetFixedWidth(px(50)) # After\n
Where px()
looks something like this.
def px(value):\n return value * 1.5\n
That goes for stylesheets as well.
style = \"\"\"\n QPushButton {\n width: 50px;\n }\n\"\"\"\nstyle = convert_px(style)\nsetStyleSheet(style)\n
Where convert_px()
looks something like..
def convert_px(style):\n lines = []\n for line in style.splitlines();\n if \"px\" in line:\n # Find them and destroy them\n return \"\\n\".join(lines)\n
But where does this magical 1.5
value come from? The value depends on your display scale factor, or more precisely whichever scale factor Maya is currently working with.
On Windows, the scale factor is set under your Display settings and Linux's various display managers have something like it.
You can read this straight from the operating system, but the more cross-platform method would be to lean on Qt. Unfortunately, the Qt documentation for resolution scaling is a good representation of how confusing resolution scaling is amongst UI developers at large.
Because you have (1) an application scale, (2) an operating system scale and (3) a physical monitor scale; each of which combine in non-obvious ways to produce the final pixel coordinate on screen.
What is the difference between \"Physical DPI\" and \"Logical DPI\"? Where does \"Device Pixel Ratio\" come into the picture?
Here's what you need to know.
scale = logicalDpi / 96.0\n
The value you'll end up with is 1.0
for a non-scaled display, such as your everyday 1080p monitor, and 1.5
or 2.0
for greater resolutions. If your OS allows, you could get values inbetween or greater, and although text scales somewhat well to any value, graphics shipped with Ragdoll is scaled at 2.0
which means it'll look best at 1.0
, 1.5
and 2.0
. Anything else will likely introduce blur.
But wait, where does logicalDpi
come from, and what's this magical 96.0
?
Qt can provide that for you, but not without a fight.
window.\n
"},{"location":"blog/20201217_option_dialogs/","title":"20201217 option dialogs","text":"Talk about qargparse and why it's necessary.
"},{"location":"blog/20201218_optionvar/","title":"20201218 optionvar","text":"Maya's native persistent preferences, with support for access from C++.
"},{"location":"blog/20201219_pythonreload/","title":"20201219 pythonreload","text":"Talk about how you iterate in Maya, reloading all modules by namespace and what to look out for. Especially undo. And always having an uninstall.
"},{"location":"blog/20210325_view_to_pixmap/","title":"20210325 view to pixmap","text":"Write about this.
def view_to_pixmap(size=None):\n \"\"\"Render currently active 3D viewport as a QPixmap\"\"\"\n\n # Python 2 backwards compatibility\n try:\n long\n except NameError:\n long = int\n\n image = om.MImage()\n view = omui.M3dView.active3dView()\n view.readColorBuffer(image, True)\n\n # Translate from Maya -> Qt jargon\n image.verticalFlip()\n\n osize = size or QtCore.QSize(512, 256)\n isize = image.getSize()\n buf = ctypes.c_ubyte * isize[0] * isize[1]\n buf = buf.from_address(long(image.pixels()))\n\n qimage = QtGui.QImage(\n buf, isize[0], isize[1], QtGui.QImage.Format_RGB32\n ).rgbSwapped()\n\n return QtGui.QPixmap.fromImage(qimage).scaled(\n osize.width(), osize.height(),\n QtCore.Qt.KeepAspectRatio,\n QtCore.Qt.SmoothTransformation\n )\n\n\ndef pixmap_to_base64(pixmap):\n array = QtCore.QByteArray()\n buffer = QtCore.QBuffer(array)\n\n buffer.open(QtCore.QIODevice.WriteOnly)\n pixmap.save(buffer, \"png\")\n\n return bytes(array.toBase64())\n\n\ndef base64_to_pixmap(base64):\n data = QtCore.QByteArray.fromBase64(base64)\n pixmap = QtGui.QPixmap()\n pixmap.loadFromData(data)\n return pixmap\n
"},{"location":"blog/20210409_littlebits_locatorshotkey/","title":"20210409 littlebits locatorshotkey","text":"Write about the script for toggling locators in the viewport, alongside curves and meshes. A workflow tip. A short one. A \"Little Bits\". :D
"},{"location":"blog/20210420_bugfree/","title":"20210420 bugfree","text":"The bug-free software guarantee.
Requirements:
Always give users a way to circumvent protections and to workaround issues without waiting for a new update (which could be days or weeks).
"},{"location":"blog/20210531_backend/","title":"20210531 backend","text":"The month of May 2021 was spent authoring the frontend and backend of the ragdolldynamics.com website. Let's have a look at what makes it tick.
"},{"location":"blog/20210531_backend/#overview","title":"Overview","text":"Here's life of the website in a nutshell.
That is, we want a user to put the versions and amount of seats for Ragdoll into a \"cart\" and for that \"cart\" to be passed on to Stripe for the transaction to take place. Once Stripe is done, we'll want to generate a serial to go with it.
With a serial in hand, we'd then like to generate a web page specifically for this one purchase. Ideally something the user can revisit later if they forget their key(s).
Because many things can go wrong in these few steps, we need to record each step of the way, including log messages, such that we can debug any such issue.
And that's it. Let's have a look at practicalities.
"},{"location":"blog/20210531_backend/#static-website","title":"Static Website","text":"Because most of the site - namely the landing page and contact page - is static I opted to use the same static site generator I use for https://learn.ragdolldynamics.com. Namely mkdocs.
Unlike the learn domain, this one wouldn't require a theme as we're laying everything out ourselves.
One of the pages need purchase-specific information - namely your serial numbers - so that needs a \"dynamic site generator\", and for that I'll use flask because of my brief excursion many years ago for Pyblish Events.
"},{"location":"blog/20210708_limitations/","title":"20210708 limitations","text":"Document and offer alternatives to these.
On July 28th 2021, animators around the world will finally get something new. Something that isn't just your average incremental workflow improvement, but an entirely new way to animate.
"},{"location":"blog/20210713_july28/#the-past","title":"The Past","text":"30 years ago there was innovation in character animation, much like the innovation we see today - modelers went from box modeling to sculpting, lighting artists nowadays reflect light and simulate the material properties in textures made with simulated wear-and-tear based on natural weather conditions and concept artists generate imagery through machine learning.
But what are animators doing?
That's right! The dopesheet, the graph editor, inverse kinematics, rigs that run at 5 fps. We're still animating like it's 1995!
As a result, every part of the filmmaking process has seen a massively reduced cost, except animation. Animation of today is often the most expensive and time consuming part of the pipeline; and when it isn't it really ought to be because despite accurate models, realistic lighting and pixel perfect textures, motion is what makes a character truly come alive.
"},{"location":"blog/20210713_july28/#the-present","title":"The Present","text":"Ragdoll was made to address this need. The need for more believable characters with less effort. The need for animators to spend time where it matters - on telling story. Here is where and how I expect animators spend their time today in 2021.
Story (10%) Performance (10%) Physics (80%) Message Body language Balance Delivery Timing Contacts Continuity Interactions Force Continuity Momentum PropagationSee that 80%? Let's get rid of that.
"},{"location":"blog/20210713_july28/#the-future","title":"The Future","text":"Mark your calendars, spread the word. Roughly 2 weeks from now we will embark on a journey together to resume innovating. To ensure that 30 years from now we'll look back at today and not recognise a thing.
Best, Marcus Ottosson CEO and Founder Ragdoll Dynamics
"},{"location":"blog/20210727_debugging/","title":"20210727 debugging","text":"Quick sanity check for overlapping shapes and an initial state residing within limits.
Welcome to Ragdoll Dynamics, the real-time physics solver for Maya.
Website Download "},{"location":"blog/20210728_announce_1_0/#july-28th-2021","title":"July 28th 2021","text":"Today marks the launch of Ragdoll Dynamics and you are reading the announcement post for this moment. With Ragdoll, you'll be able to achieve faster and more realistic character animation with less work.
Read on to find out what it's all about.
"},{"location":"blog/20210728_announce_1_0/#background","title":"Background","text":"In 2012 I had an idea for a physics system suitable for animators.
The idea sprung from the mind of a Character Animator landing a job in Creature FX and being exposed to nCloth in Maya. The goal was simple; animate a piece of string in space. But, traditional tools failed us. The desired motion was too subtle and the level of control we had was too fine. Like laying bricks with a tweezer.
So we turned to physics simulation as a means of automating subtlety and focusing on how we wanted the animation to feel and what we wanted it to do, rather than spending time making it look like it belonged in the real world. But now we had the opposite problem; although the results were subtle, they were hard to control. Like playing Jenga with a tractor.
The process was highly technical, very few animators would endure that kind of process. If this was to become accessible to animators, something drastic needed to happen. Something to transform highly technical concepts into creative choices, something that could leverage the computational power of our workstations without overburdening the artist with nonsense.
It is now July 28th 2021 - the birthday of Ragdoll - and we may (finally) begin our journey towards exactly that.
More "},{"location":"blog/20210728_announce_1_0/#what-is-early-access","title":"What is Early Access?","text":"Ragdoll is now in \"Early Access\" for the next 1-3 months.
During this time, we'll round off corners and improve the overall experience - including more tutorials, more documentation and generally being here for you as we both take our first steps into this together. Unlike most new technology, there has never been a physics solver for animators before; everything we do from here on out will be unexplored pastures, ripe with new discoveries.
So, if you're happy to dive into the unknown and learn the old-fashioned-way of trial-and-error, Ragdoll is yours. Alternatively, sit back, relax and watch other people suffer through the growing pains of an early-stage startup for the next 1-3 months.
We'll post updates both here and on LinkedIn during this time.
"},{"location":"blog/20210728_announce_1_0/#early-bird","title":"Early Bird","text":"During these first 1-3 months, there's carrot.
Ragdoll Unlimited is the unrestricted, full version of Ragdoll. The full price of which is \u00a31950 for a floating licence. But because it's early, the price is lowered to the price of Ragdoll Complete - \u00a3499 for a node-locked licence. This will be reflected in the total price during checkout.
Once early access is over - about 1 to 3 months from now - the price will return to normal.
Buy it Try it "},{"location":"blog/20210728_announce_1_0/#immediate-roadmap","title":"Immediate Roadmap","text":"The next 1-3 months will have a singular focus.
That means tutorials, documenation, interface tweaks, bug fixing, performance improvements and everything in between. If you find yourself struggling with something, it's not you, it's Ragdoll. Let us know via chat or forum here and we'll aim for same-day or same-week fixes. That's what Early Access is all about.
Chat Forums "},{"location":"blog/20210728_announce_1_0/#product-tiers","title":"Product Tiers","text":"Ragdoll comes in 5 flavours.
Each flavour is priced differently to enable access to everyone. For non-commercial users - namely anyone wanting to fool around with physics for their personal or student projects at home - there's a special version of Ragdoll. This version is identical to a node-locked version of Ragdoll Unlimited plus having free upgrades forever.
Trial Personal Complete Unlimited Batch Commercial Use \u274c \u274c \u2714\ufe0f \u2714\ufe0f \u2714\ufe0f Interactive Tools \u2714\ufe0f \u2714\ufe0f \u2714\ufe0f \u2714\ufe0f \u274c Python API \u2714\ufe0f \u2714\ufe0f \u274c \u2714\ufe0f \u274c Multi-Threading \u2714\ufe0f \u2714\ufe0f \u274c \u2714\ufe0f \u274c JSON Import/Export \u2714\ufe0f \u2714\ufe0f \u274c \u2714\ufe0f \u274c Per-process Licence \u274c \u274c \u274c \u274c \u2714\ufe0f Perpetual Pricing \u274c \u00a399 \u00a3499 \u00a31299 \u00a3199 Floating Licence \u274c \u274c \u00a3750 \u00a31950 \u00a3250 Monthly Pricing \u274c \u274c \u00a355 \u00a380 \u00a320 Annual Upgrade Plan \u274c \u00a30 \u00a3250 \u00a3650 \u00a399 "},{"location":"blog/20210728_announce_1_0/#next-steps","title":"Next Steps","text":"Ready?
Click here to download and install Ragdoll for Windows and Linux, Maya versions 2018-2022. You'll have a whole month to experiment before having to make up your mind, so go nuts!
Try it Buy it"},{"location":"blog/20210730/","title":"Documentation Writers, Ahoy!","text":"Hey you!
We launched our animation software Ragdoll Dynamics the other day and are on now the lookout for someone to author learning material on either a full-time or part-time basis.
It would involve:
To qualify, you don't need experience with Autodesk Maya although it wouldn't hurt. What you would need however is:
We could compensate you in various ways.
Is this you? Do you know someone?
"},{"location":"blog/20210821/","title":"Maya Developers, ahoy!","text":"Hello!
We've recently launched our animation software Ragdoll Dynamics and are on now the lookout for a motivated Maya Developer, on either a full-time or part-time basis.
"},{"location":"blog/20210821/#about-us","title":"About Us","text":"At the time of this writing, Ragdoll is me - Marcus - doing all things Maya along with handling just about every other aspect of running the business - like marketing, licencing, web development, design, animation, documentation.. too many things! And recently Kostas, doing secret things related to robotics in Maya.
What I'd like to do is hand over my Maya-development role to you. It would involve all manner of challenges, from UI and UX to physics and low-level optimisations to workflow enhancements and tools development. The more you fancy the better.
You will be given a great deal of agency and resonsibility that shape the future of Ragdoll in these early days. How should animators interact with physics? What parts of their workflow can be enhanced or even replaced with physics? These are questions you and I will explore, and the earlier you get involved the greater your influence.
"},{"location":"blog/20210821/#about-you","title":"About You","text":"What I'd like to see from you is examples of your work along with some motivation for wanting to come on this journey. Startup-life is unlike corporate-life in a few key ways, primarily in being able to create and execute your own set of tasks, of not only implement a solution but also understanding the problem and finding a optimal solution to an otherwise muddy and unexplored problem. It also heavily relies on our pace and progress; if you and I don't make it, it's all over! Hah! On the upside it also means that our success is ours alone, and let me tell you that is incredibly rewarding!
To cope with this, you should have some of these.
Bonus Points
If you have experience or interest in one or more of these, you're in.
The Offer
Like the position, the offer is flexible.
\u00a350,000-80,000/year
is fair game.\u00a3300-600/day
is fair game.And that's it! If this tickles your curiosity, feel free to get in touch. We can setup a call and talk things through. Maybe all you do is low-level optimisations in x86 assembly, and none of that fancy-pants UX and Python stuff? Or maybe you've got the fanciest pants in town? As an early part of the Ragdoll Dynamics team there's plenty of space in all manner of pants.
Email Contact FormBest, Marcus
"},{"location":"blog/20220809/","title":"SIGGRAPH 2022 Schedule","text":""},{"location":"blog/20220809/#schedule","title":"Schedule","text":"Here's what we'll be doing at SIGGRAPH 2022!
"},{"location":"blog/20220809/#tuesday-9th-august","title":"Tuesday - 9th August","text":"First day, we'll be ready and waiting at booth 442.
Time # Demo 11:00 Intro with Manikin - I'll walk through the basics of Ragdoll Dynamics, the physics solver for animators working in Autodesk Maya. We'll take a hand-animated Manikin character rig through to completion with physics for secondary motion. 13:00 Dragon Rig Setup - We'll take things to the next level, and turn a production-level Dragon rig into a complete ragdoll, something we can play around with interactively and have almost completely automated via turbulence and wind 14:00 RAGDOLL FOR FIRST TIMERS by Vanessa Rossi - I recently tried out Ragdoll as an animator at DNEG, and wanted to share my experience on the basics of it from an user perspective.1. Ragdoll set up using manikin2. Throwing a ball at Manikin with a walk or run cycle mocap - I'll play around with values of the ball in the channel box, in order to show some of the many different results we can get (and say how you can quickly get a few blocking pass options in minutes)3. Falling from a ladder - I'll do a simple constraint set up, and watch Manikin fall from the ladder with variations depending on when the constraint is released. 15:00 Requests - During each demo, we welcome any requests or questions at which point this is where we'll demonstrate their answer. Come join and make requests in real-time! 16:00 Live Mode - Next generation of rigging and animation, come visit us at 16:00 for the reveal! 18:30 End - The conference is done for the day, see you tomorrow! "},{"location":"blog/20220809/#wednesday-10th-august","title":"Wednesday - 10th August","text":"It's been a whirlwind of a day, and here's the next whirlwind!
Time # Demo 10:00 Hands and Fingers - We'll setup hands and fingers to see how much we can get out of contacts with itself and the environment. 11:00 Self-Walking Manikin - Wouldn't it be nice if your character could walk on its own? Or balance on its own, as the environment moves around? That's what we'll attempt in this demo! 14:00 DNEG - Rafael Cardenas Rivera and Vanessa Rossi is joining us at this time to take you through a fun demo! 15:00 Requests - We'll demo any requests having come in from you, the audience, during this block of time. Feel free to drop by and make requests \"on-air\"! 16:00 Technology Preview - Have a look at what life will be like in Unreal Engine from now on. 18:00 End - The conference is done for the day, one day left, see you tomorrow!! "},{"location":"blog/20220809/#thursday-11th-august","title":"Thursday - 11th August","text":"Final day! Come join and make requests in real-time.
Time # Demo 10:00 Locomotion - We'll share some technical details behind how Locomotion - the automatic walk, run and jump solver - works under the hood, and demonstrate how to use it on a Boston Dynamics-like character. 11:00 DNEG - Rafael Cardenas Rivera and Vanessa Rossi is joining us at this time to take you through a fun demo! 13:00 Requests - An improvised session, showcasing some of the best of what we've seen so far and taking requests from you in the audience in real-time. Any last requests? Come join at this time! 16:00 End - SIGGRAPH is done and dusted, hope you had fun! "},{"location":"blog/20220809/#overview","title":"Overview","text":"We're heading to SIGGRAPH this year!
To everyone who visits, there will be:
We'll be there from 9th to 11th August at:
Vancouver Convention Centre 1055 Canada Place Vancouver, BC, Canada.
Booth 442, here's us!
"},{"location":"blog/20220809/#meet","title":"Meet","text":"Reach out to us if you'd like to arrange a meet and greet, we'd love to meet you.
See you there!
"},{"location":"blog/20231018_building_a_business/","title":"On Building a Business in VFX and Games","text":""},{"location":"blog/20231018_building_a_business/#prelude","title":"Prelude","text":"I want more artists making tools for other artists, so I'll share the answers to what is normally sensitive information with everyone here and on the web in the interest of encouraging that. Let's go!
From a legal standpoint, what [do] the original software vendor (Autodesk / Foundry / SideFX) think about someone selling a plugin that uses their API. Are there any legal issues connected with it?
In short, anything you write is yours and can be distributed freely in any way you choose.
The part about \"using their API\" is interesting; the thing to keep in mind here is that law and licencing mostly applies to distributing other people's code. And by \"using\" their API, you are not distributing their API.
For example:
my_software.py
print(\"Hello World\")\n
Here, I'm \"using\" the Python API to emit messages to the console of anyone running my software. You may argue that I do not own the right to Python's source code and thus cannot distribute this file, but the Python source code is not included in what I distribute. Only my own characters, written on my own keyboard. It is the user, running my_software.py
, who has Python on their machine and who is the one who agreed to whatever licence was involved when installing Python such that they can run my software.
Let's take a look at another example.
my_other_software.py
import maya\nprint(maya)\n
Now I'm \"using\" the Maya Python API. But again, this file contains only characters written on my own keyboard which means I can distribute this freely with absolutely no restrictions. In fact, what does \"maya\" refer to in this case? Is it the Python API of Autodesk Maya, or is it this Python package?
Or maybe this file is part of a Python package you've written, in which there is a maya.py
that my_other_software.py
is calling on. At the end of the day, it cannot be known and doesn't matter. These written characters are mine, I wrote them.
If you only ever distribute code you write, you can stop reading here and live a merry life.
Where licencing does become relevant however, is when you do distribute other people's code. For example, in Ragdoll, we use several open source libraries, like this one.
When it comes to distributing other people's code, there are usually two categories.
Most projects are specific about what you can do with both of these. For example, you are able to freely download and use an LGPL licenced project, but if you distribute it you must also distribute the source code; Qt is a good example, Autodesk has made modifications to it for Maya which is why Autodesk then also distributes it alongside every other project is uses for its software projects.
The prevalent reason for GPL-style licencing is for making additions to a library; the author wants those additions to be free like the original, so as to benefit the project and everyone using it. Other common licence types are MIT and BSD which you may distribute, both in source and compiled form, so long as you include their licence. As a form of credit.
The RapidJSON licence is here, which includes mention of this obligation.
For Ragdoll, we include this with each release of Ragdoll, and looks something like this.
How are you handling taxes as part of your sale? This question may sound silly, but does it require you to open some legal business to handle the tax of selling plugins from your website?
This would depend on country and state but in general whenever you have income, you need to declare it to the government. In the UK, you can have income as an individual, that's called a sole trader - for example:
Whenever you declare income to the government, they will want a slice of that income in the form of taxes, and there comes a point when opening a separate business will yield more money for you and less for them. If you operate a \u00a3100/year business, you are likely better off as a sole trader. The tax you pay will become part of your personal tax declaration (i.e. self assessment). Depending on how much that is, you're looking at roughly 30% of your income to taxes. 30% of \u00a3100 is nothing to lose sleep over, it's the cost of doing business. If you operate a \u00a31mil/year business however, it won't be 30% but 60% and above, and suddenly taxes are no joke. Somewhere between \u00a3100/year and \u00a31mil/year will it become sensible for you to open a separate business - probably around the \u00a310,000 and \u00a3100,000 mark. In the UK that would/should be a \"limited\" company.
A company is like a person. It will earn income just like a person, except taxes are slightly different. A company can earn income and spend it before paying any taxes; in fact most companies spend all of their income for the sole purpose of not having to pay any tax. Any percentage of tax on \u00a30 is still \u00a30. And that's good for the economy as well, it means more money in circulation. For example, if you charge customers \u00a310/licence and you sell 100 licences over the course of a year, your company will have \u00a31,000 in the bank. By the end of the year, the tax man will stop by and ask for 30% in what's called \"corporation tax\". 30% of \u00a31,000 is \u00a3300. The rest you get to keep, the tax man is now done and will return next year to take another 30% of whatever you make that year. If instead you sell 100 licences, get \u00a31,000 and then spend that \u00a31,000 on e.g. a new computer, then the tax man will stop by and find you have \u00a30 in the bank, and promptly leave without asking for any payment. So now you (or your company, rather) have a brand new computer worth \u00a31,000 in your belongings.
And I say \"your company\" because that's important to remember. Again, a company is like a person, and all that you are to your company is a director. A director is like an employee, and like any employee you would have responsibilities towards this company, primarily in doing what is essentially a self-assessment but for the company, called a corporation tax return.
For developers in our field, there are other ways in which to lower that 30% number, such as government grants and paying for your home office through the company and things such as:
Which is one of the many ways in which a limited company is different from being a sole trader, and your main consideration for whether to start one comes down to that yearly revenue figure.
"},{"location":"blog/20231018_building_a_business/#payment-processor","title":"Payment Processor","text":"You can take cash, and you can have people transfer money to you via bank transfer. But for online businesses (and offline, for that matter) card payments are more common and you can't do these yourself. For that, you need some service capable of facilitating the transfer of money from customer to yourself.
For that, we use Stripe.
There's a bunch of options here too, like PayPal and Square. What it comes down to is cost; they all want a slice of your sale. Stripe is rather expensive, but makes up for it in convenience and features. For example, handling subscriptions is no small task.
There are even services that combine the payment processor and licence management; we initially used https://www.sendowl.com but found that (1) their method of bundling licencing and downloads were limiting and (2) their UI for payments is lacking and (3) they are basically a wrapper on-top of Stripe and Stripe has a really nice API so we opted to simply use that directly.
"},{"location":"blog/20231018_building_a_business/#software-licencing-vs-pirates","title":"Software Licencing vs Pirates","text":"How are you handling the licensing of your tools? I mean the piracy part. It is an issue, and running some RLM servers is not an option when discussing some relatively small plugins for Maya.
It's great question with many answers; some subjective others strategical.
For Ragdoll, we use LimeLM by WyDay.
It's based on a DLL file (SO file on Linux) that ships alongside Ragdoll, and this DLL file has already been cracked. Meaning if you get hold of this cracked DLL and replace the file shipped with Ragdoll, Ragdoll will believe you are a legit commercial user.
We're able to spot the when, where and who of this happening on our end and do keep an eye on it in case we need to take action, but so far it's under control.
At the end of the day, we don't use LimeLM to keep pirates out, we do it to keep honest people honest. Not everyone agrees with this approach, and that's okay. I personally believe that if someone wants to use your software illegally, they will. If there isn't a way to do it, they will find a way to do it. I also believe that if someone wants to use your software legally, they will. What they won't do is jump through too many hoops to get there. If using it legally becomes more difficult than using it illegally, you'll turn honest users dishonest because what matters in the end is getting their job done. So, Ragdoll was cracked weeks after the release of 1.0 and we are aware of it (flattered, you might say!). Are we losing sales because of it, probably. Are we gaining sales from keeping licencing simple? Most definitely. So given that you cannot completely eliminate piracy, it becomes a matter of figuring out the balance which I today believe we've found. But again, this is subjective and will vary based on person and product.
"},{"location":"blog/20231018_building_a_business/#was-it-worth-it","title":"Was it Worth it?","text":"Was it beneficial for you? I mean developing and selling those plugins from your website commercially. I mean, understand me correctly, I'm not interested in any numbers - that's out of the question and not my business, I mean overall.
Without numbers, no answer I could give would mean anything to anyone, because whether it is beneficial will depend on your personal goals. Some want wealth, others want freedom.
I've now spent 10 years down this path; from prototyping with nCloth in Maya with my limited skills as an animator to realising it wasn't enough and having taught myself programming and how to run a business and manage a team of developers; if we look at the total figure in 10 years of earning income working for someone else, then I only recently reached the point where I have earned as much via Ragdoll as I would have as an employee.
Which, as you can see from my fancy graph, involves a large up-front cost. In my case, I never had to dip below 0, which many do in the form of taking on investment or loan.
As an aside, let's have a look at some other ways in which this graph can and often do go:
Bad idea, bad execution, or both
You use up all of your savings/investment but never manage to sell any copies.
Not worth it
You manage to sell product, but would have made more money as an employee. This may still be a win, if all you want is freedom and don't care about money.
No savings, no investment
This was me 4 times in a row for 7 years; restarting can be easy (like it was for me) but heavily depends on life circumstances (e.g. kids).
In my case and the first graph, what happens after today is obviously highly optimistic, but you'll need a lot of optimism if you are to run a business.
Moving on, I was earning \u00a340-70k/year as an animator in 2006-2013, which I expect would have increased with those 10 years of experience and perhaps change of role into something more technical, so let's be generous and say on average I would have made \u00a3100k/year and that I worked full-time for 10 years, that's \u00a31,000,000. On average, companies take 5 years to become profitable. As in, 5 years until you've covered the cost of developing the first version and reached plus/minus 0 and can start saving again, so add another couple of years to reach the point you would have been at if you had just taken those initial 5 years and saved money along the way.
I heard this exact thing 10 years ago but never believed it could take this long, and here I am 10 years later repeating it to you.
In my case, I never made \u00a370k in a year, but rather spent 2-4 months each year on freelance earning roughly \u00a320k followed by 8-9 months of living off of that (in London, i.e. very frugally) to try and develop what is today known as Ragdoll. Once cash ran out, rinse and repeat and 7 years later I had developed the first version of Ragdoll.
Early Website
It was a bug-ridden mess with very few features. But, it solved a real problem, for real customers. There is a lot more to say on the topic of how to develop and launch, so feel free to ask if that's interesting. I publicly launched Ragdoll in 2021 and generated \u00a3200k in the first 3 months of trading, far exceeding my expectation and more than covering the cost of development up until that point. Since then revenue has ebbed and flowed; there are a few key players out there more willing to take risks on startups (the early adopters) and once you've crossed that threshold you are left with the realists; the bulk of the market with higher demands and less patience. This is where the real work begins.
Overall I feel the timing was just right; for me personally, given that I get to utilise every skill and experience I've had as an artist and programmer, from modeling to animating for showcase material, to pipeline development and Python tooling, to web design and development for our landing page, to writing documentation via my work in open source (e.g. Pyblish and Allzpark), to managing people as a lead and co-founder in previous companies, to devops and setting up build servers, to making music for announcement trailers, to having enough of a network that I could rather easily find my first set of customers. The timing was right commercially and technically as well; hardware is more than capable of doing what Ragdoll requires in real-time and realism in film and animation is in dire need of tooling; it is simply too expensive and challenging to match the expectations of our audience and to follow the leads of rendering and modeling and texturing, which have gotten so far ahead of where character animation is today. There is a lot more to say on that too, so feel free to ask.
With this in mind, was developing and selling software beneficial to me? I enjoy working with others and not having to think about what to do next; being given a task and executing it to the best of my abilities. I know studios enjoy hiring me, I do a good job. But oh man, it does not compare to having built your own thing and seeing it help others. Putting all of my experience, and lately the experience of my staff, together into single .zip file to be distributed to peers in the industry I know and love; there is nothing more rewarding.
I take it you didn't expect a reply like this, but believe you me; founders are happy to share. I speak to some of them myself on a regular basis (shoutout to JangaFX, Polygonflow and Inbibo!) and reached out to many more before starting Ragdoll, including Ziva and Pixologic (shoutout to James and Ofer!), they love talking about their experiences too. Running a company can be a lonely endeavour; there are far more employees than employers, so you'll naturally find more conversations about being an employee but at the end of the day we're all human.
One of the reasons I chose to get into detail here is because one of the things that bothers me about starting a business is how black box it is. In your case, the legal aspect alone can understandably drive you away from even trying. In others, the financial aspect such as \"do I need investment?\" - which seems really common but does not have to be! - can drive someone away. I also had these questions. For the first year or two of Ragdoll, I stood prepared for the UK government to come crashing through my door due to having forgotten some obligation for running a business - some missed tax payment or missing bit on our website. Or for Autodesk to require I only sell software on their their own app store and demand compensation for not having done so already. And there are still threats out there, things that can cripple any business in an instant for things not already done in the past - especially for things related to law which is why your questions are so important.
It is necessary to read licence agreements, like the MIT and GPL walls of text, and the Autodesk EULA when developing for Autodesk software. Some of those texts are trivial and clearly a non-issue, others will be challenging to understand which is when you do need an accountant and/or lawyer. But these people are out there for you, so when that time comes it really is as simple as reaching out to ask. It is unlikely you will need any of that before you generate any revenue, and by the time you do you also have money to spend which turns it not into a question of \"can I afford it\" but rather \"how much more will I earn by having an accountant? By hiring this lawyer for a couple of hours?\". When everything you spend can and often does make you more money, that's when you know you've got a successful business. At the end of they day, nobody is expected to know everything; mistakes can and will be made. Even law is built around this, because law is built around us being human. What matters is not that you know everything up-front, but how you deal with mistakes. If a payment is due, you will be reminded. If some law is broken, you will be notified. At no point will you be punished before being given a chance to remedy the mistake.
Bottom line is, you can do it. Aside from an idea, all you need is perseverance. Where there's a will there's a way, true in life as it is in business.
"},{"location":"blog/20231018_building_a_business/#podcast","title":"Podcast","text":"Finally, in the interest of completeness, there's a podcast between me and Miguel Campos from a few months back talking about many of these things and more at depth.
https://www.youtube.com/watch?v=PMWvM9-vbgA&list=PL9LaIDCCDjfhZa-a_rT74cFDAk2R0Sf4S&index=3
Hope it helps, and feel free to continue asking questions here!
"},{"location":"blog/20240101_omx_vs_cmdx/","title":"cmdx v omx","text":""},{"location":"blog/20240101_omx_vs_cmdx/#omx-by-animal-logic","title":"omx by Animal Logic","text":"The appearance of omx
gave me an excellent opportunity to shed some light on the Maya API and how undo is implemented, along with finding some inspiration for things to improve in cmdx
.
omx and cmdx provide an alternative to maya.cmds
and pymel
that is both faster and - in the case of cmds
- more convenient.
One of the big failings of cmds
is nodes being referenced by name; such that when a name changes, the variable containing your node is no longer valid.
from maya import cmds\nnode = cmds.createNode(\"transform\", name=\"name\")\ncmds.rename(node, \"newName\")\ncmds.setAttr(node + \".translateX\", 5)\n# \"name\" does not exist!\n
PyMEL solved this, and added a boatload of additional features like exposing Maya's native math classes for e.g. easy vector addition.
from pymel import core as pm\nvec1 = pm.dt.Vector(1, 2, 3)\nvec2 = pm.dt.Vector(4, 5, 6)\nresult = vec1 + vec2\n
But it also added a performance overhead - importing the library can take seconds and generally using the library made code take several times longer than it would have via cmds
.
Performance Comparison
See below for a brief comparison, along with the README for cmdx
and documentation for omx
for more.
For Ragdoll, we needed both performance and maths.
For example, the Load Physics
command can read a JSON and generate a complete Maya scene with Maya nodes, Ragdoll nodes, connections between them and attributes restored from disk in a handful of milliseconds. On par with how long it takes Maya to load a .ma
or .mb
file off disk.
We built cmdx
to provide the terse readability of PyMEL with the performance of cmds
. Actually even better than cmds
, as you'll find below, due to leveraging the Maya Python API 2.0.
About two weeks ago, Animal Logic announced another open source contender called omx
and this page is a comparison between the two. To compare them, we'll need a better understanding of Maya, undo and the \"modifiers\", so you'll also learn about how these work!
More alternatives
The complete list of all other alternatives I know of, let me know if you know any more!
Let's start with a quick side-by-side.
omx
import omx\nfrom maya.api import OpenMaya as om2\n\nmod = omx.currentModifier()\njoint = mod.createNode(\"joint\", name=\"joint\")\n\nfn = om2.MFnNumericAttribute()\nattr = fn.create(\"flash\", \"flash\",\n om2.MFnNumericData.kInt)\nfn.setMin(0)\nfn.setMax(10)\n\nmod.addAttribute(joint.object(), attr)\n\njoint.radius.setFloat(1.5)\njoint.translate.setCompoundDouble((1, 2, 3))\n\nmod.commandToExecute(\n f\"setKeyframe -at tx -t 1 -v 10 {joint}\"\n)\nmod.commandToExecute(\n f\"setKeyframe -at tx -t 5 -v 15 {joint}\"\n)\nmod.commandToExecute(\n f\"setKeyframe -at tx -t 10 -v 10 {joint}\"\n)\n\nmod.doIt()\n
cmdx
import cmdx\n\nwith cmdx.DagModifier() as mod:\n joint = mod.createNode(\"joint\", name=\"joint\")\n attr = cmdx.Integer(\"flash\", min=0, max=10)\n mod.addAttr(joint, attr)\n mod.setAttr(joint[\"radius\"], 1.5)\n mod.setAttr(joint[\"translate\"], (1, 2, 3))\n mod.setAttr(joint[\"tx\"], {\n 1: 10,\n 5: 15,\n 10: 10\n })\n
Highlights
Feature omx cmdx Maya Support 2022-2024 2016-2024 Attribute Access Dot-access,.attr
Dict-access, [\"attr\"]
Attribute Setter node.attr.setInt(5)
node[\"attr\"] = 5
Attribute Getter if node.attr
if node[\"attr\"]
Animation mod.commandToExecute
mod.setAttr
Undo MPxCommand
+ MDGModifier
Same "},{"location":"blog/20240101_omx_vs_cmdx/#performance","title":"Performance","text":"Both omx and cmdx performs better than cmds, PyMEL and MEL. They also all scale linearly with the number of nodes, so let's see how they compare on the heaviest of cases.
10,000 nodes
Units are in seconds.
Test cmds cmdx cmdx noundo omx omx immediate Create 5.66 3.89 2.68 3.17 4.38 Edit 4.8 4.44 3.13 3.19 7.03 Rename 1.29 0.66 0.65 0.47 0.77 Query 0.73 0.52 0.52 0.68 0.66 Remove 0.89 0.61 0.62 0.41 0.70 Overall 13.5 10.1 7.67 7.94 13.6Both omx and cmdx thinly wrap the Maya API, so both of their bottlenecks is Maya itself.
Source
Tested on Maya 2024, Windows, source here
Bad performance
The AL performance comparison of cmds
ability to create is off by 3x, clocking in at 15 seconds.
Let's take a closer look, starting with syntax.
"},{"location":"blog/20240101_omx_vs_cmdx/#syntax","title":"Syntax","text":"# omx\nnode.t.x = 5;\n\n# cmdx\nnode[\"tx\"] = 5\n
Somewhat subjective, and we've learnt from PyMEL that accessing attributes via the dot-syntax does work. But not without cost.
Consider this.
# Attribute, function or property?\nnode.visible = True\nnode.flash.keyable = True\nnode.translate(1, 2, 3)\n
..did these even exist, or did we just add new variables to the Python object?
Wouldn't my IDE warn about it?
Consider readers on GitHub, GitLab or BitBucket; including the source code on this page.
Whenever you call .something
on a node, the __getattribute__
method of the object is called. In the case of omx, here's what this looks like.
AL/omx/_xnode.py#L75
class XNode:\n def __getattribute__(self, name):\n # (1)\n if hasattr(XNode, name):\n return object.__getattribute__(self, name)\n\n mob = object.__getattribute__(self, \"object\")()\n\n # (2)\n if name == \"apiTypeStr\":\n # ...\n\n if mob == om2.MObject.kNullObj:\n # ...\n\n nodeClass = XNode._NODE_CLASS_CACHE[mayaType]\n attrs = XNode._ATTRIBUTE_CACHE[mayaType]\n attr = attrs.get(name, None)\n\n # (3)\n if attr is None:\n if not nodeClass.hasAttribute(name):\n plug = _plugs.findPlug(name, mob)\n if plug:\n return _xplug.XPlug(plug)\n\n raise AttributeError(f\"Node {mayaType} has no attribute called {name}\")\n\n attr = nodeClass.attribute(name)\n attrs[name] = attr\n\n # (4)\n return _xplug.XPlug(mob, attr)\n
Some highlights
node.apiTypeStr
in which case we return a special caseXPlug
if soXPlug
Here, attributes are shadowed by native functions and properties, and as the count of both native functions and user attributes increases name clashes are inevitable.
It's also not clear when you assign whether you are assigning to a Python property or Maya attribute.
node.name = \"My Name\"\n
Conversely, cmdx uses __getitem__
instead. Here's what happens when you call node[\"attr\"]
cmdx.py#L570
class Node:\n def __getitem__(self, key):\n unit = None\n cached = False\n\n # (1)\n if isinstance(key, (list, tuple)):\n # ...\n\n # (2)\n if cached:\n # ...\n\n assert isinstance(key, str), (\n \"%s was not the name of an attribute\" % key\n )\n\n try:\n plug = self.findPlug(key)\n except RuntimeError:\n raise ExistError(\"%s.%s\" % (self.path(), key))\n\n # (3)\n return Plug(self, plug, unit=unit, key=key)\n
Some highlights.
node[\"tx\", Meters]
or node[\"rx\", Degrees\"]
cmdx.Plug
The first surprise when working with maya.api.OpenMaya
is the lack of undo.
from maya import cmds\nfrom maya.api import OpenMaya as om\nom.MFnDependencyNode().create(\"transform\")\ncmds.undo() # Nope!\n
We take it for granted with cmds
and pymel
but with naked access to OpenMaya
we are on our own. And it just so happens that undo/redo is (or, can be) really hard.
To understand why, we need to look closer at undo in general, and how Maya implements this with MPxCommand
and MDGModifier
.
The basic premise of undo in any application is that for every action there is an equal and opposite reaction. Wait, that's Newtons Third Law. But it does apply!
def do():\n createNode()\n\ndef undo():\n deleteNode()\n
Maya implements undo via the \"Command Pattern\".
Alternatives
There are other ways to implement undo, such as the \"Memento Pattern\" utilised by Blender.
Here are some excellent resources on it for deeper diving!
In a nutshell, it looks like this.
class Command:\n def __init__(self, name):\n self._name = name\n self._node = None\n\n def do(self):\n self._node = createNode(self._name)\n\n def undo(self):\n deleteNode(self._node)\n
And that's about all there is to it! What makes this pattern work, is that we can keep a list of previous commands..
previous_commands = list()\n\ndef execute(cmd):\n cmd.do()\n previous_commands.append(cmd)\n\nexecute(Command(\"hello\"))\nexecute(Command(\"world\"))\nexecute(Command(\"bye\"))\n
..and call their undo
in the reverse order!
def undo():\n last_command = previous_commands.pop() # Get and remove last item\n last_command.undo()\n\nundo()\nundo()\nundo()\n
There's one additional list for redo()
but the premise is the same. Append and pop.
Here's a real example of how this is implemented in the Maya Python API 2.0.
# my_command.py\nfrom maya.api import OpenMaya as om\n\nclass MyCommand(om.MPxCommand):\n kPluginCmdName = \"myCommand\"\n\n def __init__(self):\n super(MyCommand, self).__init__()\n self._node = None\n self._name = None\n\n def doIt(self, args):\n self.redoIt()\n print(\"Created '%s'\" % self._name)\n\n def undoIt(self):\n om.MGlobal.deleteNode(self._node)\n print(\"Deleted '%s'\" % self._name)\n\n def redoIt(self):\n fn = om.MFnDagNode()\n self._node = fn.create(\"transform\")\n self._name = fn.name()\n print(\"Re-created '%s'\" % self._name)\n\n def isUndoable(self):\n return True\n\n @staticmethod\n def cmdCreator():\n return MyCommand()\n\n\ndef initializePlugin2(plugin):\n pluginFn = om.MFnPlugin(plugin)\n pluginFn.registerCommand(MyCommand.kPluginCmdName, MyCommand.cmdCreator)\n\n\ndef uninitializePlugin2(plugin):\n pluginFn = om.MFnPlugin(plugin)\n pluginFn.deregisterCommand(MyCommand.kPluginCmdName)\n
Apart from a few syntactical differences, this is pretty vanilla Command Pattern.
You can call it like this.
from maya import cmds\ncmds.loadPlugin(\"my_command.py\")\ncmds.myCommand() # doIt is called\ncmds.undo()\ncmds.redo()\n# Created transform1\n# Deleted transform1\n# Re-created transform1\n
There are however two problems with this approach that make it unsuitable for use in scripting with Python. For starters, we must register each command as a plug-in, and the name of each plug-in must be unique as it will be present in Maya's own maya.cmds
module. Secondly, you have to implement the opposite command for every command you do!
Consider the case of an auto rigger.
class CreateRig(om.MPxCommand):\n kPluginCmdName = \"createRig\"\n\n def doIt(self, args):\n spine = self.create_limb()\n left_arm = self.create_limb(parent=spine)\n right_arm = self.create_limb(parent=spine)\n left_leg = self.create_limb(parent=spine)\n right_leg = self.create_limb(parent=spine)\n head = self.create_head(parent=spine)\n\n def undoIt(self):\n # Undo everything we just did!\n pass\n
Imagine the amount of state you would need to keep track of in order to undo such a thing. No longer just a self._node
but many dependent nodes and attributes, that need to be deleted and reset in the proper order (children first) and attributes potentially created on nodes outside of those created by this one command.
You'd have to be pretty dedicated to go this route, even Autodesk (Alias, rather) thought so too, which is why they gave us the modifier.
"},{"location":"blog/20240101_omx_vs_cmdx/#modifier-primer","title":"Modifier Primer","text":"Maya provides a means of wrapping one or more commands into an undoable chunk called a \"modifier\".
There are 2 flavours.
MDGModifier
for DG related modificationsMDagModifier
for DAG related modificationsThe DG handles things like creating DG nodes, connecting things, renaming things. Whereas the DAG version handles parenting and creating DAG nodes.
mod = maya.api.OpenMaya.MDagModifier()\nnode1 = mod.createNode(\"transform\", name=\"hello1\")\nnode2 = mod.createNode(\"transform\", name=\"hello2\")\nmod.doIt()\n
Points of interest:
doIt
is calledMDagModifier
But this still doesn't grant you the ability to undo. Instead, you have:
mod.undoIt()\n
Which has nothing to do with undo you know - i.e. Ctrl + Z - it's merely a command you can call yourself do undo whatever was done up until doIt
. The modifier has been keeping a log of every command you've done, so as to perform the opposite in the same order as you did. So to incorporate this with what you know as undo you need one more ingredient, the command.
Here's one way to couple the modifier and command.
class MyUndoCommand(maya.api.OpenMaya.MPxCommand):\n def __init__(self):\n self._modifier = None\n\n def doIt(self, args):\n self._modifier = _GLOBAL_MODIFIER\n _GLOBAL_MODIFIER = None\n\n def undoIt(self, args):\n self._modifier.undoIt()\n\n def redoIt(self, args):\n self._modifier.redoIt()\n
Maya will create an instance of this command and store it, so by storing the last modifier inside of it, Maya will ensure the right modifier is called at the right time.
Aside from some minutia, this is how both cmdx and omx solves this problem.
from AL import omx\nmod = omx.XModifier(immediate=False)\nmod.createDagNode(\"transform\")\ncmds.AL_OMXCommand() # Fetch and store this latest modifier\n\nimport cmdx\nmod = cmdx.DagModifier()\nmod.createNode(\"transform\")\ncmds.cmdx_0_6_3_command()\n
And in both cases, this command is hidden from view and is automatically called.
from AL import omx\nmod = omx.XModifier(immediate=False)\nmod.createDagNode(\"transform\")\n\nimport cmdx\nwith cmdx.DagModifier() as mod:\n mod.createNode(\"transform\")\n
"},{"location":"blog/20240101_omx_vs_cmdx/#modifiers","title":"Modifiers","text":"Given what we now know, you might be thinking \"modifiers, where have you been all my life!?\". And it's true they provide something rather unique, but they can be both a blessing and a curse.
"},{"location":"blog/20240101_omx_vs_cmdx/#blessing","title":"Blessing","text":"Since nothing happens until you call doIt()
that also means that if anything goes wrong up until that point, your Maya scene will be unaffected by anything that preceeded it.
mod.createNode(\"transform\")\ncond = mod.createNode(\"condition\")\nmod.addAttr(cond, attr)\nmod.createNode(\"BAD\") # <---\nmod.doIt()\n
With MEL, cmds and Pymel, the above would produce an error and leave your scene is a dirty state. As a user, you never know what has been created and what has not; was it enough to carry on? Do you need to undo and try again? Can you even undo, or has the undo queue been disrupted already?
With a modifier, an error is produced..
Traceback (most recent call last):\n File \"C:\\github\\test.py\", line 8, in <module>\n a = mod.createNode(\"BAD\")\nTypeError: invalid node type\n
..and since doIt()
was never called nothing will have happened! This is very nice.
Consider the case of an auto-rigger, where multiple functions and multiple modules call on each other to produce the final result. If anything breaks, an error is produced and nothing will have changed.
"},{"location":"blog/20240101_omx_vs_cmdx/#curse","title":"Curse","text":"There are however 2 main drawbacks to this approach.
(2) means that there are things you cannot do with a modifier, and thus cannot capture their undo. For example, you cannot cmds.play()
and you cannot manipulate the Maya UI in any way and you cannot change the min and max of attributes.
(1) however is the most damning.
Consider the case of a real-world production project, 15 modules, 150 functions, thousands of calls to generate a character rig. Creating nodes, adding and connecting attributes, setting values; the works.
from maya.api import OpenMaya as om\n\nmod = om.MDagModifier()\na = mod.createNode(\"transform\")\n\nfn1 = om.MFnDependencyNode(a)\n\nplug1 = fn1.findPlug(\"tx\", False)\nplug2 = fn1.findPlug(\"rx\", False)\nplug3 = fn1.findPlug(\"sx\", False)\n\n# Locked attributes cannot be connected\nplug2.isLocked = True\n\nmod.connect(plug1, plug2)\nmod.connect(plug2, plug3)\n\nmod.doIt()\n
And then, an error is thrown. Here's what you'll see.
Error: Connection not made: 'unitConversion1.output' -> 'transform2.rotateX'. Destination is locked.\nTraceback (most recent call last):\n File \"example.py\", line 18, in <module>\n mod.doIt()\nRuntimeError: (kFailure): Unexpected Internal Failure\n
And here's the kicker; the error occurs at line 18. At mod.doIt()
.
In this example - with only 1 call to connect
- the source is obvious. But you can already see how unitConversion1.output
is not what you wrote. It's automatically created by the modifier, and is part of the error message. In this hypotethical production example, these errors can start to get near impossible to debug.
Other times, you won't get an error at all until it's too late.
"},{"location":"blog/20240101_omx_vs_cmdx/#silently-adding-duplicate-attributes","title":"Silently adding duplicate attributes","text":"mod = om.MDGModifier()\nnode1 = mod.createNode(\"multMatrix\")\n\nfn = om.MFnNumericAttribute()\nattr1 = fn.create(\"myAttr\", \"at\", om.MFnNumericData.kFloat)\nattr2 = fn.create(\"myAttr\", \"at\", om.MFnNumericData.kDouble)\n\nmod.addAttribute(node1, attr1)\nmod.addAttribute(node1, attr2)\n\nmod.doIt()\n# No error\n
Now you're left with 2 duplicate attributes. This is not allowed by the Maya API and will likely segfault if you try and operate on either of these once they are done.
Under normal, non-modifier circumstances, an error would occur when attempting to add an attribute that already exists.
from maya import cmds\ncmds.addAttr(\"persp\", ln=\"myAttr\", at=\"float\")\ncmds.addAttr(\"persp\", ln=\"myAttr\", at=\"double\")\n# Warning: Name 'myAttr' of new attribute clashes with an existing attribute of node 'persp'.\n# Traceback (most recent call last):\n# File \"<stdin>\", line 1, in <module>\n# RuntimeError: Found no valid items to add the attribute to.\n
"},{"location":"blog/20240101_omx_vs_cmdx/#interoperability-with-non-modifiers","title":"Interoperability with non-modifiers","text":"Modifiers know about the surrounding API, but the surrounding API does not know about modifiers.
from maya.api import OpenMaya as om\n\nmod = om.MDagModifier()\nnode = mod.createNode(\"transform\")\n\n# (1)\nfn = om.MFnNumericAttribute()\nlength = fn.create(\"length\", \"le\", om.MFnNumericData.kFloat)\nmod.addAttribute(node, length)\n\n# (2)\nfn = om.MFnDependencyNode(node)\nplug = fn.findPlug(\"at\", False)\nmod.newPlugValueFloat(plug, 5.3)\n\nprint(plug.asFloat())\n
In this case, (1) is a modifier given data created outside of the modifier, this is fine.
But at (2), a non-modifier is operating on modifier data; this won't work because the data has not yet been created. We haven't yet called doIt()
. Neither the attribute nor node exists yet. The MObject
passed to MFnDependencyNode
is essentially invalid.
We can work around this by calling doIt()
multiple times.
from maya.api import OpenMaya as om\n\nmod = om.MDagModifier()\nnode = mod.createNode(\"transform\")\n\n# (1)\nfn = om.MFnNumericAttribute()\nlength = fn.create(\"length\", \"le\", om.MFnNumericData.kFloat)\nmod.addAttribute(node, length)\nmod.doIt() # Prepare attribute for the below call\n\n# (2)\nfn = om.MFnDependencyNode(node)\nplug = fn.findPlug(\"at\", False)\nmod.newPlugValueFloat(plug, 5.3)\nmod.doIt() # Again prepare the the *next* call\n\nprint(plug.asFloat())\n
Each time doIt()
is called, it will only perform the newly created operations since the last doIt()
. The undoIt()
on the other hand will undo all operations. Just as one would expect.
Both omx
and cmdx
had the same brilliant idea of recording commands made with the modifier, such that they can be printed out on error. Something Maya really should be doing already.
node[\"rx\"].lock()\n\nwith cmdx.DagModifier() as mod:\n mod.connect(node[\"tx\"], node[\"rx\"])\n\n# cmdx.ModifierError: An unexpected internal failure occurred, these tasks were attempted:\n# - connect('|transform1.translateX', '|transform1.rotateX')\n# - connect('|transform1.rotateX', '|transform1.scaleX')\n
cmdx
incorporates common sources of error into the modifier, so the above for example would error immediately.
# cmdx.LockedError: Channel locked, cannot connect 'rotateX'\n
"},{"location":"blog/20240101_omx_vs_cmdx/#comparison","title":"Comparison","text":"Let's compare the use of modifiers and commands between cmdx and omx.
"},{"location":"blog/20240101_omx_vs_cmdx/#mdgmodifier","title":"MDGModifier","text":"Let's look at how users interface with modifiers through cmdx and omx.
omx
import omx\nfrom maya.api import OpenMaya as om2\n\nmod = omx.currentModifier()\nmod.createNode(...)\nmod.addAttribute(...)\n\n# Current modifier implicitly called\njoint.radius.setFloat(...)\n\nmod.commandToExecute(...)\nmod.doIt()\n
cmdx
import cmdx\n\nwith cmdx.DagModifier() as mod:\n joint = mod.createNode(...)\n mod.addAttr(...)\n mod.setAttr(...)\n
When I first started writing cmdx
I desperately wanted to avoid exposing the modifier directly, as it added another layer of complexity compared to cmds
and PyMEL
. By having a \"current\" modifier somewhere globally accessible, you can make naked calls like joint.radius.setFloat
take advantage of it without the user explicitly calling on it.
# omx/_xplug.py:119\ndef setFloat(self, value):\n _currentModifier().newPlugValueFloat(self, value)\n
The problem is that it was never clear which call made use of this global modifier and which did not.
# We know this does\njoint.radius.setFloat(3.5)\n\n# But how about this?\njoint.myArray.append(5)\n\n# ..and this?\njoint.tx.locked = True\n\n# hmm..\njoint.visibility.setDoNotWrite(True)\n
With cmdx
, all undoable things are encapsulated in the modifier. Things outside of it are not immediately undoable.
with cmdx.DagModifier() as mod:\n mod.createNode(...) # Undoable\n mod.addAttr(...) # Undoable\n mod.setAttr(...) # Undoable\n\nnode[\"myArray\"].append(5) # Not undoable\nnode[\"attr\"].storable = False # Not undoable\n
For hand-rolled undoable operations, there is cmdx.commit
.
import cmdx\n\nhistory = []\nhistory.append(cmdx.createNode(\"transform\"))\nhistory.append(cmdx.createNode(\"condition\"))\nhistory.append(cmdx.createNode(\"multMatrix\"))\n\ndef undo():\n cmdx.delete(history)\n\ncmdx.commit(undo)\n
Which is what cmdx.DagModifier
uses too.
class Modifier:\n # ...\n\n def __exit__(...):\n cmdx.commit(self.undoIt, self.redoIt)\n
Although in practice I have never had to use this in Ragdoll.
"},{"location":"blog/20240101_omx_vs_cmdx/#mpxcommand","title":"MPxCommand","text":"Another subtle difference between omx and cmdx is how they store their modifiers.
omx
_xcommand.py#L40
Highlight Comment Implicit list of modifiers There exists this notion of a \"current\" modifier, and apparently there can be many. They are stored together in the same command. Instances Modifier instances themselves are stored alongside the command. Potentially problematic given that one cannot inspect what commands are in Maya's undo buffer at any given time and thus cannot confirm they do what you expect.def getAndClearModifierStack():\n global _CURRENT_MODIFIER_LIST\n existingMods = []\n for xmod in _CURRENT_MODIFIER_LIST:\n if isinstance(xmod, XModifier):\n if xmod.isClean():\n continue\n mmod = xmod._modifier # NOQA\n else:\n mmod = None\n logger.debug(\"Retrieving mod %r from list for execution\", mmod)\n existingMods.append(DoItModifierWrapper(xmod, mmod))\n _CURRENT_MODIFIER_LIST = []\n return existingMods\n\nclass XCommand(om2.MPxCommand):\n def __init__(self):\n # ...\n self._modifiers = _xmodifier.getAndClearModifierStack()\n\ncmds.AL_OMXCommand()\n
cmdx
The undo
and redo
commands are stored in a shared location, accessible to both the cmdx
module and plug-ins made with cmdx
.
cmdx.py#L8407
Highlight Commentunique_command
cmdx supports vendoring, whereby there may be multiple instances of cmdx
on the sys.path
any given time, of different versions. Therefore, they each use a unique name for their command. Addresses Undo and redo addresses are stored in a shared memory location, accessible from outside of Maya's undo queue for inspection, along with inside of new Maya commands made with cmdx
. class _apiUndo(om.MPxCommand):\n def doIt(self, args):\n self.undoId = shared.undoId\n self.redoId = shared.redoId\n\ndef commit(undo, redo=lambda: None):\n shared.undoId = \"%x\" % id(undo)\n shared.redoId = \"%x\" % id(redo)\n shared.undos[shared.undoId] = undo\n shared.redos[shared.redoId] = redo\n\n getattr(cmds, unique_command)()\n
To the end user, the behavious is identical. There really only is 1 way to undo and redo, anything else is a bug.
"},{"location":"blog/20240101_omx_vs_cmdx/#omx-and-the-current-modifier","title":"omx and the \"Current Modifier\"","text":"Given what we know know about undo inside of Maya, with modifiers and commands, it was interesting to see the notion of a \"current\" modifier in omx
.
Consider this.
# module1.py\ndef function1():\n mod = omx.currentModifier()\n mod.createNode(...)\n\n# module2.py\ndef function2():\n mod = omx.currentModifier()\n mod.setAttr(...)\n
To the naked eye, both of these functions, in these two separate Python modules, call on the same \"current\" modifier. In which case, by the end of your multi-file, multi-function call you must be incredibly lucky to not have encountered a single error - user or otherwise - for the function to have executed perfectly and without error. Only then will you get undo and only then will your scene state be safe. Because yes - as opposed to errors occurring prior to calling doIt()
- modifiers will still have executed all commands prior to the one that failed, leaving you with a mess and no undo.
But having looked closer at the omx source code, this is not the case. Instead, doIt
is frequently called automatically - such as when both creating and deleting new nodes - leaving me wondering what the purpose of a \"current\" modifier is, given that there is also a omx.newModifier()
?
cmdx deals with this by encouraging small batches of modifiers.
def function1():\n with cmdx.DagModifier() as mod:\n mod.createNode(...)\n\ndef function2():\n with cmdx.DagModifier() as mod:\n mod.setAttr(...)\n
"},{"location":"blog/20240101_omx_vs_cmdx/#xmodifier-implementation","title":"XModifier Implementation","text":"omx provides:
omx.newModifier()
omx.currentModifier()
Whereby currentModifier
will create a new modifier if there is no modifier. I was expecting this to keep returning the same modifier until I call newModifier
, but this wasn't the case.
mod = omx.currentModifier()\nassert mod is omx.currentModifier()\nmod.createDagNode(\"joint\")\nassert mod is omx.currentModifier() # AssertionError\n
Furthermore, the documentation states:
If AL.omx.XModifier._immediate
is True, whenever you call its method to edit Maya\u2019s scene data, it will call doIt()
to apply the edit to the scene immediately. On the other hand, if AL.omx.XModifier._immediate
is False, then you\u2019ll have to manually call AL.omx.doIt()
or XModifier.doIt()
to apply the edit.
However this does not appear true.
mod = omx.XModifier(immediate=False)\nassert not mod._immediate\nmod.createDagNode(\"joint\") # Still creates the joint\n# mod.doIt()\n
There is a comment in the source explaining why.
\"To get a valid MObjectHandle in XNode the creation needs to happen right away\" - Source
"},{"location":"blog/20240101_omx_vs_cmdx/#extras","title":"Extras","text":"Let's highlight some other points of interest.
"},{"location":"blog/20240101_omx_vs_cmdx/#commandtoexecute","title":"commandToExecute","text":"One of the things I struggled with was incorporating non-modifier commands in a modifier context, like locking attributes.
omx
handles this by utilising MDGModifier.commandToExecute
which queues a (MEL) command to execute at the right time, which I thought was very nice.
omx
Elegant method of handling this scenario.
class Modifier:\n def setLocked(self, locked):\n cmd = f\"setAttr -locked {locked} {self}\"\n _currentModifier().commandToExecute(cmd)\n
There is also pythonCommandToExecute
which does the same but with a Python command instead.
cmdx
Manual way, which will likely be converted to pythonCommandToExecute
instead.
class Modifier:\n def setLocked(self, plug, value=True):\n self._lockAttrs.append((plug, value))\n\n def _doLockAttrs(self):\n while self._lockAttrs:\n plug, value = self._lockAttrs.pop(0)\n elements = plug if plug.isArray or plug.isCompound else [plug]\n\n for el in elements:\n cmds.setAttr(el.path(), lock=value)\n\n def __exit__(self):\n self.redoIt()\n self._doLockAttrs()\n
"},{"location":"blog/20240101_omx_vs_cmdx/#animation","title":"Animation","text":"Shorthand for animating values.
node = cmdx.createNode(\"transform\")\nnode[\"tx\"] = {\n 1: 0.0,\n 5: 1.0,\n 10: 0.0\n}\n
This sets keyframes on frames 1, 5 and 10, with values 0, 1 and 0 respectively.
It might surprise you to know that cmds
returns units relative the units your UI is configured to.
# cm, meters or feet?\nheight = cmds.getAttr(\"persp.ty\")\n
Which is convenient sometimes, but not often!
cmdx
on the other hand always returns cm
and radians
, unless you specify otherwide.
height = persp[\"ty\", cmdx.Centimeters]\nheight = persp[\"ty\", cmdx.Meters]\n
All of the Maya math classes are available via cmdx
and may be directly passed (and gotten) as attribute values.
node = cmdx.createNode(\"transform\")\nnode[\"ty\"] = 5\nmtx = node[\"worldMatrix\"][0].as_matrix()\n\n# Store Y-transform as offset\nnode[\"offsetParentMatrix\"] = mtx\nnode[\"ty\"] = 0\n\n# Do some math\nmtx_inverse = node[\"worldMatrix\"][0].as_matrix_inverse()\nnode[\"newAttr\"] = cmdx.MatrixType()\nnode[\"newAttr\"] = mtx * mtx_inverse\n
All of cmdx
is available both as Maya-standard camelCase but also as camel_case
.
cmdx.createNode(\"transform\")\ncmdx.create_node(\"transform\")\n
As such, it'll fit into any codebase, no matter the convention!
Under the hood, the members are simply aliases of each other, so the functionality remains the same.
def createNode(...):\n pass\n\n# Alias\ncreate_node = createNode\n
Generate curves with a lot less code than the Maya API!
import cmdx\n\nparent = cmdx.createNode(\"transform\")\nshape = cmdx.curve(parent, [\n (0, 0, 0), # first CV point\n (0, 1, 0), # second CV point\n (0, 2, 0), # ...\n])\n
Have a look at the little brother of cmdx called cmdc
, a complete re-implementation of Maya's API, a.k.a. \"Maya Python API 3.0\"
Read more about cmdx and the tons of quality-of-life features incorporated over the years here.
Let me know what you think of the above summary! You can reach me at marcus@ragdolldynamics.com or via the Ragdoll forums. The post is intended for Maya developers at large, but also the developers of omx and anyone using omx or cmdx with a desire to better understand the things it does for you, under that hood.
"},{"location":"blog/20240101_omx_vs_cmdx/#try-it","title":"Try it","text":"That's all I got! Take both cmdx and omx for a spin via pip.
mayapy -m pip install AL_omx\nmayapy -m pip install cmdx\n
There's a topic created in the omx repository with some more discussion.
How to make yourself known without unethical practices.
Saying you are somewhere, but are actually somewhere else. For example, advertising that you are in London when you are really in Italy. Why? Because London is known, familiar and ripe with the tools of your industry. Because money. Manipulation for money. That's unethical.
Or how about advertising that you are in Cyprus when you are really in Russia. Why? Because Russa isn't too hot right now, so it may impact your brand. I.e. money. Manipulation for money. That's unethical.
"},{"location":"blog/20240319_ethical_branding/#features","title":"Features","text":"Advertising that something is done in X amount of time, when really it's X+n amount of time (e.g. Adonis and the \"2 clicks\" which was 10+ clicks). Why? Faster is better. Therefore, money. Manipulation for money. That's unethical.
"},{"location":"documentation/cache/","title":"Cache","text":"The fundamental building block to Ragdoll, for \"reverse motion capture\" or Animation Capture.
"},{"location":"documentation/cache/#caching","title":"Caching","text":"Ragdoll runs alongside your character animation, but sometimes it can be useful to keep the results from a previous run and stop being so interactive.
Meet Cache
and Uncache
.
Caching is entirely non-destructive, and in fact leverages the very same cache you've been enjoying all this time whenever rewinding.
The menu commands toggle an attribute on your solver node, called .cache
and automatically plays the entire timeline for you. But the same result can be achieved by setting the attribute and playing it yourself.
The minimal HUD will show you what's been cached, and like before once you resume playback from a cached to an uncached frame, Ragdoll will continue filling up the cache as one would expect.
Look forward to a future release where caching happens in the background, as you work. Something that can also be handy from time to time (pun!).
"},{"location":"documentation/constraints/","title":"Constraints","text":"Establish a relationship between two markers.
"},{"location":"documentation/constraints/#constraints","title":"Constraints","text":"You can constrain one marker to another!
Constraint Type Description Weld Constraint Simplest of constraints, welds two markers together; no change to their distance or relative orientation is allowed. This is akin to the MayaParent Constraint
Distance Constraint Maintain a minimum, maximum or total distance between two markers. Pin Constraint Match a position and orientation in worldspace, similar to Drive Space = World
. "},{"location":"documentation/constraints/#weld","title":"Weld","text":"Maintain the position and orientation of one marker relative another from the first frame onwards.
"},{"location":"documentation/constraints/#distance","title":"Distance","text":"A simple but versatile constraint with animatable distance.
Maintain Start Distance
Whatever the distance between two markers, it will be maintained throughout a simulation.
Minimum Distance
Alternatively, only respond to when two controls get too close.
Maximum Distance
Conversely, keep markers from getting too far away from each other.
Custom Distance
Or go all-in, with both a minimum and maximum distance, for the most complex behavior.
Offsets
Control at which point on a control to measure the distance.
Animated Distance
Both min and max distance, along with stiffness and damping, can be animated for some pretty rad effects.
Hard Distance
A Stiffness = -1
means the constraint is \"hard\". It will not accept any slack or \"springiness\".
In this example, the distance is animated whilst soft, and transitioned into a hard constraint. Notice how it snaps into place once hard.
Limitation
A limitation of a hard constraint is that the distance cannot be animated whilst hard. You can however animate it between values of -1 and above, to transition to and from hard to soft.
"},{"location":"documentation/constraints/#pin","title":"Pin","text":"Pin the translation and/or rotation of a Marker in worldspace.
"},{"location":"documentation/environment/","title":"Environment","text":"Collide against complex but immovable geometry.
"},{"location":"documentation/environment/#environment","title":"Environment","text":"Ragdoll supports static environments; meaning environments that cannot move or deform, but allow for normal polygonal geometry without the need for a simplified \"convex hull\".
As you might expect, this works well for environments like terrain and other complex geometry that is otherwise hard to turn into a rounded mesh.
"},{"location":"documentation/environment/#performance","title":"Performance","text":"It's fast.
Normal shapes are limited in how complex they can get, and as such you never really run into a situation where the shape noticeably affects performance.
Triangle meshes are different; they can be of any complexity. Up to millions of polygons and beyond. So it falls upon you to decide where to make the performance/quality tradeoff!
Vertex Count Cooking Time Run-time performance 400 0.39 ms 685 fps 8'000 3.51 ms 599 fps 16'000 14.3 ms 594 fps 64'000 61.5 ms 327 fps 256'000 287.7 ms 40 fps 1'000'000 1490 ms 2 fpsWhat is cooking time?
The time it takes for Ragdoll to convert your polygonal geometry into the internal representation needed for collision detection. It involves splitting up the mesh into areas or \"zones\" for faster lookup.
This only happens when the mesh actively changes and when first opening the Maya scene, and won't affect playback speed.
"},{"location":"documentation/export_physics/","title":"Export Physics","text":"Export physics from one scene, for import into another scene.
Coming Soon
Scheduled for release in January 2022
"},{"location":"documentation/fields/","title":"Fields","text":"Environmental effects like Wind and Turbulence for your Markers.
"},{"location":"documentation/fields/#fields","title":"Fields","text":"Ragdoll supports all of Maya's native \"fields\"
What are fields?
A field represents a set of forces applied to each Marker. Ranging from Gravity
to Turbulence
, each field carries unique properties you can use to emulate some environment or environmental effect, like wind and gravity fields along a curve.
What is the difference from regular Maya fields?
They are the very same!
If you're already familiar with them, from e.g. nParticles of nCloth, then you can leverage your experience with Ragdoll, and vice versa if you ever venture into nCloth and friends.
"},{"location":"documentation/fields/#overview","title":"Overview","text":"Let's walk through these fields one-by-one.
"},{"location":"documentation/fields/#turbulence","title":"Turbulence","text":"The perhaps most interesting field. Apply forces in \"random\" directions, based on the worldspace positions of your Markers.
The way to think of turbulence is as Perlin Noise you may have seen in images such as this.
Where the amount of white determines the amount of force being applied. As a Marker travels across this field, both the magnitude and direction changes in interesting ways.
"},{"location":"documentation/fields/#drag","title":"Drag","text":"Apply an opposite force to any motion.
The faster things move, the greater the force.
Pro tip
This field is similar to Ragdoll's Air Density
. Not technically, but practically.
Apply a uniform force, at a given speed, in a given direction. Like wind, including a kitchen fan with some Spread
.
A familiar force, except this one can be also be animated!
"},{"location":"documentation/fields/#newton","title":"Newton","text":"Force Markers towards or away from a point in space.
"},{"location":"documentation/fields/#radial","title":"Radial","text":"A more curious field; with a force which increases as it gets farther from the source.
"},{"location":"documentation/fields/#uniform","title":"Uniform","text":"Apply a constant force. That's all.
"},{"location":"documentation/fields/#vortex","title":"Vortex","text":"Apply forces in a circular pattern.
"},{"location":"documentation/fields/#volume-axis-field","title":"Volume Axis Field","text":"A field for when you don't know what field you want.
A true Swiss Army Knife of fields, can do everything from Vortex, to Newton to Turbulence in one convenient node.
"},{"location":"documentation/fields/#volume-curve","title":"Volume Curve","text":"Have some fun with this curve-based field. Perhaps to emulate an underwater current?
In this example, I'm also using a Drag
field to keep things from flying off into space.
Pro tip
The curve is a normal Maya NURBS curve. If you need more points, right click and add points as you normally would.
"},{"location":"documentation/fields/#combined-fields","title":"Combined Fields","text":"Make two or more fields to combine their effect and create complex forces or series of forces!
"},{"location":"documentation/fields/#centroids","title":"Centroids","text":"Where within each Marker should a field apply forces?
At the center, forces will be nice and predictable; except they won't be able to introduce rotations to your Marker, which may or may not be what you want. For the most realistic fields, use volumetric centroids.
Here's another example using the Turbulence Field.
Which is better?
Up to you! There is a tiny performance penalty for volumetric origins, as the number of forces increase. But you shouldn't notice much if any impact on performance.
"},{"location":"documentation/fields/#centroid-seed","title":"Centroid Seed","text":"For complex meshes, centroids can end up in unwanted locations or gather in an area with dense vertices. That's when you can give the algorithm a little jolt to try and see whether there is a better alternative out there.
"},{"location":"documentation/fields/#use-selected-as-source","title":"Use Selected as Source","text":"Some forces act according to their position in the world. Attach a field to a Marker to create an interesting relationship between the two.
Non-commercial Ragdoll
This feature is limited to 100 frames in non-commercial versions of Ragdoll.
Distance constrain two markers, and attach a field to the outer-most Marker for a doubly-interesting effect. That also wrecks your brain. \ud83d\ude43
"},{"location":"documentation/fields/#field-scale","title":"Field Scale","text":"If forces start becoming large, you may find yourself in a situation where the visualisation needs to tone down just a bit.
In the solver settings, you will find options to scale those lines (i.e. Field Scale
), as well as control how many steps into the future (i.e. Field Iterations
) it should draw for you.
Fine-tune the effect of fields by having one or more Markers ignore the effect of fields.
"},{"location":"documentation/fields/#more","title":"More","text":"Being native to Maya, Autodesk has some documentation of its own here.
You may also search for fields on YouTube or ask your colleagues about them; any trick they've learnt may very well apply to Ragdoll as well!
"},{"location":"documentation/group/","title":"Group","text":"Ragdolls are combined into what's called a \"group\", with attributes to control the overall behavior of all contained Markers.
"},{"location":"documentation/group/#self-collision","title":"Self Collision","text":"Previously, it was very important that your shapes did not overlap any shape other than it's immediate neighbour. If they did, chaos ensued.
Before
Clavicles intersect their parent spine, but also each other!
After
With the new Self Collision = Off
, this is no longer a problem.
This can be taken into the extreme!
And here's another example to fill out a large volume in the center of a character.
Attention
Notice how the spine is made up of many shapes, some of which cover the width of the body, others the depth. An overlapping mess that would never have simply not have been possible without self-collision support!
Original asset created by Mehmet Tayfur T\u00fcrkmeno\u011fluwe and Dr. Reel, licensed by The Rookies.
"},{"location":"documentation/import_physics/","title":"Import Physics","text":"Import physics onto existing controllers from disk.
"},{"location":"documentation/import_physics/#import","title":"Import","text":"You can import a Ragdoll setup exported from Maya, back into Maya. It'll re-create everything just the way it was.
What is included in the export?Just about everything.
Very little.
Yes, anything else is a bug.
More precisely, determinism depends on (1) the type and number of items in the solver along with (2) the order in which these are created. Both of these are part of the exported file format and is taken into account during import. Meaning you should get identical results so long as the content is the same.
"},{"location":"documentation/import_physics/#example","title":"Example","text":"Here's an exported Ragdoll setup for the free CG Spectrum Tiger rig.
2.8 mb
)To use it, download the rig and import the Ragdoll file.
It contains 2 levels of detail.
Level Content Level 0 Body and feet Level 1 Everything on Level 0, plus toes "},{"location":"documentation/import_physics/#workflow","title":"Workflow","text":"Here's the rundown.
On import, Ragdoll will try and find the names of what you exported in your currently opened scene.
Namespace
dropdown menu.Search and Replace
fields to modify the names searched for by Ragdoll.Export
Once you're happy with your character, it's time to export. Towards the bottom of the UI, you'll get a preview of what is about to be exported. This can help clarify that what ends up on disk is what you expect.
Import
In a new scene, with the same character, same names and everything, import as you'd expect. At the bottom of this UI, you'll get a preview of what's in the file on disk, along with how it will associate the node names found in the file with what you have on disk.
"},{"location":"documentation/import_physics/#namespace-from-file","title":"Namespace from File","text":"Odds are, the character you're importing either has no namespace, or has a different namespace to what you've currently got in your scene. As in this example here, with 3 copies of the same character, each with its own namespace.
Use the Namespace
dropdown to select one of the current namespaces in your scene, or Custom
to type one in yourself.
Per default, Ragdoll will import the file into the current solver in your scene, if any. Or, you can import the original solver from the source file.
"},{"location":"documentation/import_physics/#known-limitations","title":"Known Limitations","text":"Here are a few things that will be addressed over time. Let us know if you encounter anything else!
Light-weight or heavy-duty? How about both!
"},{"location":"documentation/level_of_detail/#level-of-detail","title":"Level of Detail","text":"Setup your character once with all bells-and-whistles, and interactively pick which level of detail to use for your simulation in a given situation.
Usecases
Level 0
, fingers at Level 1
Level 1
, muscles at Level 2
Level 0
, extremities at Level 1
and Level 2
For example, here's a Wasp character with 3 levels of increasing detail.
As you'd expect, it'll record only the currently active markers.
"},{"location":"documentation/level_of_detail/#workflow","title":"Workflow","text":"Here's how it works.
1
1
And that's it! Any marker with a matching level is simulated and recorded.
"},{"location":"documentation/level_of_detail/#operators","title":"Operators","text":"What does each level mean? The answer lies in the \"operator\".
Operator DescriptionLess Than
If the Marker Level
is less than (or equal) to the Solver Level
, simulate it. Greater Than
If the Marker Level
is greater than (or equal) to the Solver Level
, simulate it. Equal
If the Marker Level
is equal to the Solver Level
, simulate it. NotEqual
If the Marker Level
is not equal to the Solver Level
, simulate it. With these, you can use each level for..
With Equal
and NotEqual
operators, you can have some markers appear or disappear on particular levels, enabling endless combinations.
Roadmap
This should cover a majority of cases, but there are things you cannot yet do, but will be able to in the future.
Capsule
on one level, Mesh
on another. For higher-resolution contacts.For the geeks out there, here's what the underlying algorithm looks like in Python.
# Membership types\nMinimum = 1 # Present at this level and higher\nMaximum = 3 # Present at this level and lower\nOnly = 4 # Only present at this level\nNot = 5 # Present at all levels *except* this one\n\nmarkers = [\n {\"name\": \"hip\", \"level\": 0, \"membership\": Minimum},\n {\"name\": \"spine\", \"level\": 0, \"membership\": Minimum},\n {\"name\": \"neck\", \"level\": 0, \"membership\": Minimum},\n {\"name\": \"head\", \"level\": 0, \"membership\": Minimum},\n {\"name\": \"L_upper_leg\", \"level\": 0, \"membership\": Minimum},\n {\"name\": \"L_lower_leg\", \"level\": 0, \"membership\": Minimum},\n {\"name\": \"R_hand\", \"level\": 1, \"membership\": Minimum},\n {\"name\": \"L_foot_box\", \"level\": 1, \"membership\": Maximum},\n {\"name\": \"L_foot_convex\", \"level\": 2, \"membership\": Minimum},\n {\"name\": \"R_toe_capsule\", \"level\": 2, \"membership\": Not},\n {\"name\": \"R_toe_convex\", \"level\": 2, \"membership\": Only},\n]\n\ndef resolve(level):\n print(\"Level %d\" % level)\n for marker in markers:\n if marker[\"membership\"] == Minimum and marker[\"level\"] <= level:\n print(\" - {name} ({level})\".format(**marker))\n\n if marker[\"membership\"] == Maximum and marker[\"level\"] >= level:\n print(\" - {name} ({level})\".format(**marker))\n\n if marker[\"membership\"] == Only and marker[\"level\"] == level:\n print(\" - {name} ({level})\".format(**marker))\n\n if marker[\"membership\"] == Not and marker[\"level\"] != level:\n print(\" - {name} ({level})\".format(**marker))\n\nresolve(0)\nresolve(1)\nresolve(2)\n
Run this, and this is what you'll find.
Level 0\n - hip (0)\n - spine (0)\n - neck (0)\n - head (0)\n - L_upper_leg (0)\n - L_lower_leg (0)\n - L_foot_box (1)\n - R_toe_capsule (2)\nLevel 1\n - hip (0)\n - spine (0)\n - neck (0)\n - head (0)\n - L_upper_leg (0)\n - L_lower_leg (0)\n - R_hand (1)\n - L_foot_box (1)\n - R_toe_capsule (2)\nLevel 2\n - hip (0)\n - spine (0)\n - neck (0)\n - head (0)\n - L_upper_leg (0)\n - L_lower_leg (0)\n - R_hand (1)\n - L_foot_convex (2)\n - R_toe_convex (2)\n
"},{"location":"documentation/link/","title":"Link","text":"Combine, or \"merge\" multiple solvers together, to simulate them as one.
"},{"location":"documentation/link/#linking","title":"Linking","text":"Reference two characters, link their solvers.
Until now, you've been able to author physics using Active Chain
and combine scenes using the Combine Scene
menu item. That would transfer all connected rigids from one scene to another.
But, that feature is destructive. There's no way to \"uncombine\" and even if you could, there's no record of what was originally combined.
Let me introduce Solver Linking
, a lightweight and non-destructive alternative.
Linking
This fellow is referenced twice, and get their solvers linked together.
Unlinking
Unlinking restores their previous behavior exactly.
That's neat, but can you..
I know exactly what you're thinking, I was thinking the same thing.
Can you link a solver to another solver that is also linked? So that I can build a network of simple solvers that all work together to form one complex solver?
Yes. Yes, you can. \ud83e\udd2d See below.
"},{"location":"documentation/link/#example","title":"Example","text":"Here are 2 assets, a manikin and a backpack.
Manikin BackbackThe backback and manikin has been combined into one, which is then referenced twice into the final scene for a total of 4 unique solvers.
Non-destructively link solvers
Notice the hierarchy of solvers formed here, enabling you to build complex solvers out of many small solvers.
Non-destructively unlinking too
Likewise, safely deconstruct a network of solvers by just removing the connection.
Technically, a solver is added to another solver in the same manner a marker, group and constraint is added. One big happy family.
"},{"location":"documentation/live_mode/","title":"Live Mode","text":"Interact with your simulation in real-time.
"},{"location":"documentation/live_mode/#live-mode","title":"Live Mode","text":"Here's \"Live Mode\" in a nutshell.
Traditional Rig
And here's the equivalent task with the traditional rig.
If you don't make it through all of the 95 seconds that the traditional method takes, I don't blame you. Not only is posing with Live Mode already 3x faster, it also has the following benefits.
But perhaps most importantly.
This same workflow applies to plain joint hierarchies, meaning an animator could:
For example, here's 30 seconds of \"rigging\" a character from scratch.
And that's where things are going.
Let's have a closer look at what this thing can do today.
"},{"location":"documentation/live_mode/#general-posing","title":"General Posing","text":"Clicking and dragging on any marker will affect it the way you'd expect.
"},{"location":"documentation/live_mode/#reset","title":"Reset","text":"Exiting out of the mode or changing from the Manipulator to e.g. the Maya Translate tool (W hotkey) will reset the simulation to where it originally started.
"},{"location":"documentation/live_mode/#drop-press-hold","title":"Drop Press & Hold","text":"Towards the bottom, you'll find a number buttons, one of which is called Drop
. This \"drops\" the character. In other words, it temporarily enables gravity. This can help ease a character onto the ground or generally relax things that are hovering. It's also fun to play with.
Hold Shift to toggle gravity on, such that you can throw things around! Also fun to play with
"},{"location":"documentation/live_mode/#tense-press-hold","title":"Tense Press & Hold","text":"Next up is Tense
. This tenses the character.
What's really happening is that it tries to reach whatever pose your rig is in at that time.
"},{"location":"documentation/live_mode/#tense-toggle","title":"Tense Toggle","text":"Like Drop
, the Tense
button can be toggled, which would leave the character tense.
Hold Ctrl whilst clicking to \"mask\" a Marker. This prevents it from moving at all, it's technically turning the Marker into a Kinematic object temporarily.
Pro tip
You can also press Ctrl whilst dragging and release to leave the Marker you are currently dragging in place, for some cool posing mechanic!
"},{"location":"documentation/live_mode/#unmask-all","title":"Unmask All","text":"Next up is \"unmask\" which involves \"masking\" via Ctrl + Clicking on a Marker. It's how you prevent a Marker from moving.
How does it work?
It temporarily turns any marker Kinematic
, identical to the Behaviour = Kinematic
attribute.
Hold Shift whilst dragging to isolate the effect to a marker and it's children.
"},{"location":"documentation/live_mode/#transfer-pose","title":"Transfer Pose","text":"The final button is the Transfer
button. It's what transfers the simulation back onto your animation controls.
Like Drop and Tense, this button can also be toggled, meaning the pose is transferred as soon as you let go of the mouse cursor.
"},{"location":"documentation/live_mode/#animation","title":"Animation","text":"And these are the tools you use to animate.
"},{"location":"documentation/live_mode/#visual-undo","title":"Visual Undo","text":"The timeline helps you understand where undo will take you.
You can also interact with the timeline, for fine control over where in history you want to go.
"},{"location":"documentation/live_mode/#recording-live-mode","title":"Recording Live Mode","text":"Use Live Mode with Cache = Static
to enable recording of your interactions!
Toggle the Lock button far-right to keep simulating outside of the Manipulator.
This enables you to use Ragdoll as a normal Maya deformer, and see real-time updates on contacts and limb limits.
Here are some more examples!
"},{"location":"documentation/live_mode/#rigging-for-live-mode","title":"Rigging for Live Mode","text":"In order for your characters to work with Live Mode, you'll need to take a few things into consideration. Primarily that your character has FK controls with the ability to disable space switches and other mechanics that differ from a straightforward parent/child relationship.
A quick tutorial on how to setup a character using Maya's multi-cut, and then export and load this character to assemble it alongside our favourite Manikin!
Here's an example of how you can \"trick\" Live Mode into working for you with any traditional Maya rig.
At the bottom-left hand corner of Live Mode, you'll find a set of experimental controls.
"},{"location":"documentation/live_mode/#magnet-tuning","title":"Magnet Tuning","text":"Whenever you click and drag, you are dynamically creating and destroying a Pin Constraint. The settings for this Pin Constraint can be customised here.
These can also affect the Modifier keys on the right-hand center of the Live Mode UI, such as how strong gravity should be or how tense the character should get when pressing the Tense
button.
In Live Mode, all constraints are disabled. This way, they will not interfere with the primary purpose of Live Mode, which is to pose your character. However, outside of Live Mode, such as in Interactive Mode, it may be useful to keep these active.
See example here
Like Pin Constraints, Fields are disabled in Live Mode per default, but can be re-enabled using this button.
"},{"location":"documentation/live_mode/#workflows","title":"Workflows","text":"These are having a hard time finding a good default or place in the UI. They affect the overall workflow of Live Mode, so play with them but don't put too much faith into them.
Button Description Synchronise Keep the Live Timeline in sync with the Maya timeline Reset on Time Changed Keep the simulation in sync with the Maya scene whenever time changes Force Viewport Update Improved interaction when in Interactive Mode "},{"location":"documentation/locomotion/","title":"Locomotion","text":"Automatic walking, running, jumping and more with Locomotion.
"},{"location":"documentation/locomotion/#usage","title":"Usage","text":"Here's what you do.
Assign Plan
What is a \"Plan\"?
The generated locomotion is the result of a \"plan\", meaning each of the inputs you give it. Including this initial selection.
"},{"location":"documentation/locomotion/#examples","title":"Examples","text":"Let's start with a quick look at what you can get out of this new toy.
Locobot
Modeling by Christophe Desse.
Spot and Friends
Happy Box
Yes, you can give it a terrain.
Two Happy Boxes
Locoboy
A 2-legged quadruped, look at 'em go!
Locomotion & Physics
Playing well together.
Humanoid Locomotion
As you can tell, quadrupeds fair much better!
Human Dynamics
But with some physics, it's starting to look nice. :)
"},{"location":"documentation/locomotion/#abilities","title":"Abilities","text":"Here's what we're aiming for with this feature.
To achieve this, you've got control over:
Step Sequence
Terrain
upon which to walkThere can be any number of feet and it can travel any amount of distance. The Step Sequence
is how you're able to achieve different kind of walks.
And the Terrain
is how it can do this across geometry of any complexity.
Let's talk about what cannot be solved with Ragdoll Locomotion
.
Currently, it only understands 2 things.
And for feet, it only understand the position of the foot, not its orientation.
Most importantly, it does not understand arms! Arms are critical to human locomotion, they swing in tandem with each step. This version of Ragdoll does not understand arms. Yet. Meaning it's good for locomotion involving any creature that does not have arms.
But Marcus, that doesn't leave much room for many creatures. They all have arms!
Think again!
With that out of the way, let's look at what it can do!
"},{"location":"documentation/locomotion/#press-t","title":"Press T","text":"Locomotion also has a manipulator, accessible by selecting the rPlan
node and pressing T
on your keyboard.
Locomotion is computed in the background.
Normally, it'll take a second or two to compute 4-12 seconds worth of locomotion, and you can safely interact with Maya whilst it's running. It has zero impact on your overall Maya or character rig performance.
"},{"location":"documentation/locomotion/#rig-compatibility","title":"Rig Compatibility","text":"Anything from a box with a sphere for feet to the most complex digi-double will do.
The rig in the above example is nothing special, as you've seen from the examples above this works on \"rigs\" as complex as a box and 2 spheres.
"},{"location":"documentation/locomotion/#multiple-characters","title":"Multiple Characters","text":"You can have as many characters in the scene as you like.
"},{"location":"documentation/locomotion/#parallel-processing","title":"Parallel Processing","text":"That's right! If 1 character takes 2 seconds to compute, 5 characters also take 2 seconds to compute. Or 10 characters, or 100 characters. 2 seconds in total, that's all you'd have to wait, up to the number of cores on your system.
As core-count continues to increase in our machines, you can expect the number of characters being run in parallel to increase as well, up to the level of full crowds; each individual character a unique and precise sequence of steps that conform to their environment.
Juice Left
There is still a little bit of juice left to squeeze.
At the moment, if Ragdoll detects any relation between one plan and another, it will run these one-by-one.
Normally, this is not the case, but if you for example connect the output of one plan to the input of another, there isn't much that can be done other than wait for one to finish. However this can also happen when unrelated things are connected, such as your character being connected to two plans, such that you can blend between them. This is too much, and will be addressed in a future release. Subtle balance!
"},{"location":"documentation/locomotion/#physics","title":"Physics","text":"Locomotion is an entirely separate \"brain\" that you may, or may not, want to combine with regular Markers.
Body and/or feet can be Kinematic
or driven by a Pin Constraint
, or anything inbetween.
Unlike a simulation, Locomotion
is entirely time independent. So it isn't strictly necessary to record; it will run directly on your character rig.
You can edit the locomotion as keyframes via Maya's native Bake Results
command.
This will become your new best friend. With an easily recognisable pattern for when to move your feet.
Sequencer Mode
Shift
to paintCtrl
to eraseIt can be used to produce a wide variety of locomotion, such as this frog sequence.
"},{"location":"documentation/locomotion/#targets","title":"Targets","text":"Once you've figured how to get somewhere, next up is figuring out where to go.
Target Mode
Start
or End
of the body or footTranslate
gizmo to control the position of either body
or foot
Rotate
gizmo to control the start and end orientation of the body
Use the Rotate
gizmo to control the orientation of the body at the start or end positions.
Is your character jumping or limping? Maybe dancing? Limits control the area in which each foot is allowed to move.
Limit Mode
body
to adjust the size of your characterfoot
to adjust the amount of motion a foot is allowed to haveHere's an example of how a short limit on one foot, and long steps with the other foot, can generate a wounded or limping locomotion.
"},{"location":"documentation/locomotion/#terrain","title":"Terrain","text":"Things can easily get more interesting by swapping out that flat ground with some geometry.
"},{"location":"documentation/locomotion/#shift-to-toggle","title":"Shift to Toggle","text":"You can choose whether to use the Shift and Control keys to add and remove steps in the Locomotion Step Sequencer, or whether to use Shift for both. Dragging over a filled step will erase it, whereas dragging over an unfilled step will fill it. A toggle!
"},{"location":"documentation/manipulator/","title":"Manipulator","text":"Interactively manipulate shapes and limits using the Manipulator.
"},{"location":"documentation/manipulator/#manipulator","title":"Manipulator","text":"One of the most challenging aspects of Ragdoll to date is editing shapes and limits. These have now been greatly simplified via the use of \"manipulators\", similar to your standard Translate/Rotate/Scale manipulators. Except on steroids.
Here's a 21 second overview.
"},{"location":"documentation/manipulator/#activate","title":"Activate","text":"You have a few options for activating the manipulator.
Ragdoll -> Manipulator
T
on your keyboardShow Manipulator Tool
in the ToolbarAny of the Ragdoll nodes can be selected in order to enable the manipulator via the T
keyboard shortcut.
rdSolver
rdGroup
rdMarker
rdDistanceConstraint
rdPinConstraint
rdFixedConstraint
Manipulator UI Scale
If the Manipulator's UI is too big or too small, you can change that via Ragdoll > System > Ragdoll Preferences > Resolution Scale
. Make sure to restart Maya or reload Ragdoll after changing the Resolution Scale.
Solver Shape
At the time of this writing, the solver needs its shape selected, not the parent transform. This will be addressed in a future release.
A comfortable workflow is..
T
The selected Marker will be pre-selected in the manipulator.
Alternatively, press the Show Manipulator Tool
button in the Toolbar.
This release introduces a manipulator with two \"modes\".
Mode Description Shape Mode Edit shape properties, likeLength
, Radius
, Position
and Orientation
Limit Mode Edit limit properties, like Twist
and Swing
along with their pivots. In Shape Mode, you currently have 5 manipulators.
Manipulator DescriptionTranslate
Affects the Shape Offset
attribute Rotate
Affects the Shape Rotation
attribute Scale
Affects the Shape Radius
and Shape Extents
attributes Length
Affects the Shape Length
attribute, for the Capsule
shape HUD
Individual control over primary attributes, like Shape Extents
axes Translate
Hold the middle-mouse button to translate.
Rotate
Hold Ctrl + middle-mouse button to rotate.
Scale
Hold Ctrl + left-mouse button to scale.
Length
The Capsule
shape have additional in-view manipulators you can drag to affect each side independently.
HUD
Finally, attributes without a visual handle can be edited via the viewport HUD.
"},{"location":"documentation/manipulator/#limit-mode","title":"Limit Mode","text":"In Limit Mode, you currently have 2 manipulators.
Manipulator DescriptionLimit
Affects the Limit Range XYZ
attributes HUD
For locking and enabling of limits Enable and Disable
Click the Axis
button to limit the rotation about a particular axis.
Lock and Unlock
Click the Lock
button to prevent all rotation about the axis.
Asymmetrical Edits
Hold Ctrl
to make asymmetrical edits
Some limbs start out at the center of their limit. Like your hip and neck. They are typically modeled to enable equal movement in each axis.
Other limbs, like the elbow and knee, are typically modeled in the extreme of their limit. Able to only rotate in one direction. For these cases, they need an asymmetrical limit.
With limits in multiple axes, keep an eye out for how asymmetrical edits to one axis affect the others.
Why are they moving?
Under the hood, each axis must still be symmetrical; edits only appear to be asymmetrical for your convenience. What's really happening is the entire limit is both changing shape and also rotating and the rotation is causing all axes to move.
This is an inherent limitation (pun!) of limits in Ragdoll and is unlikely to be addressed in the future, so we'll have to work with it.
If you mess up and want to start from scratch, hit the Reset
button, also found under..
Ragdoll -> Utilities -> Reset Constraint Frames
Enabled per default, symmetry will mirror your edits across an axis.
There are 2 types of symmetry at the time of this writing.
Type DescriptionWorld
Look for a marker across the current axis in worldspace Pose
Based on the pose at the time of assigning markers, which is typically symmetrical. Each of which can be made symmetrical in either the X, Y or Z axes. The Pose
axis means you can make changes even if a character has been posed after having been assigned. A feature particularly useful when assigning to the A- or T-pose of a character rig.
Pose Based Symmetry
Because these controls were assigned in the T-pose of the rig, you can use Pose-based symmetry to make changes even when the character is currently asymmetrical.
Multiple Rigs
If two or more characters are present in the scene, and they were all rigged in the same pose, at the center of the world, then Ragdoll will only look at markers in the same rdGroup
as the selected Marker.
Search Distance
On the right-hand side of the Enable Symmetry
button, there is a Search Distance
gizmo.
Drag to edit this value
When you select a marker on one side, it will search for a marker at the opposite side of the axis you've chosen. Because positions are all approximate, it uses a maximum search distance to look for it.
Matches
Ideally, there should only be one match. But in a crowded hierarchy there may be several. Tune the Search Distance
to control the number of matches, to ensure it doesn't pick the wrong one.
Disable Symmetry
to enable multi-select
Hold Shift
to select and manipulate multiple markers at once.
Drag Select?
Not yet! But will be added in a future release.
"},{"location":"documentation/manipulator/#undo-redo","title":"Undo & Redo","text":"No surprises here.
Changes made using the manipulator are undoable as you would expect, with the exception that it currently does not let you undo the selection itself like normal Maya selection does; this will be addressed in a future release.
"},{"location":"documentation/manipulator/#fit-to-view","title":"Fit-to-view","text":"Tap the F
key to fit any selected Marker(s) to the view, like you would expect from selected Maya nodes.
Caveat
This currently only applies if you've activated the manipulator using the Ragdoll -> Manipulator
menu item, or have the rdSolver
shape node selected.
Click the Select Node
button to select this node in Maya
Per default, Ragdoll and Maya selection are separate. You can have Maya select the node(s) currently seleted in Ragdoll by pressing the Select Node
button.
You can automate this using the Synchronise
button at the far-left of the HUD.
Why is this not on per default?
The solver is what is actually being fitted. If the selection is changed to a marker (which is not a DAG node, and therefore lacks a visual representation) then fit-to-view no longer works.
This will be addressed in a future release and made into the default.
With Multi-select or symmetry enabled, all selected markers will be selected in Maya, to make bulk edits via the Channel Box easier.
"},{"location":"documentation/manipulator/#manipulator-help","title":"Manipulator Help","text":"On the right-hand side is an overview of the hotkeys and mouse button combinations you can use, and what they do.
It can be hidden via the HUD button on the upper right-hand side.
"},{"location":"documentation/marker/","title":"Marker","text":"Markers form the fundamental building block of Ragdoll, to achieve Animation Capture a.k.a. \"reverse motion capture\".
"},{"location":"documentation/marker/#animation-capture","title":"Animation Capture","text":"Capture your character rig, as though it was a live action actor.
Inspired by Motion Capture - Animation Capture is a new way to think about and work with physics in Maya. To learn about it, let's first understand how Motion Capture generally works.
Here is a typical data pipeline for motion capture, from real-life actor to final character animation.
# Description 1 Markers are attached to an actor 2 Markers are \"captured\" 3 A pointcloud is generated 4 A hierarchy of joints is generated 5 Joints drive a typical character rig 6 Rig drives final geometry for renderEach \"Marker\" is a dud. Nothing of any complexity. Something for the camera(s) to recognise and track as it moves through space. Once tracked, it's able to translate this Marker from a 2D image into a 3D position, and continues to do so for each Marker. The real processing to take place inside software.
Once the capture is complete, the human actor can remove the markers and go enjoy the rest of their day. The rest is up to the computer.
With 3D positions generated, software takes over to translate these points into a hierarchy; the FK joint hierarchy you may be familiar with if you've ever worked with mocap. The joint hierarchy can then be used to either drive the final geometry, or to drive a more complex character rig which in turn drives the final geometry.
Animation Capture is just like that, but in reverse. Instead of capturing a person, it captures your character rig.
# Description 1 Markers are attached to a character rig 2 Markers are \"captured\" 3 A rigid body is generated for each Marker 4 A hierarchy of constraints is generated to connect them 5 Simulation is recorded back onto the original character rigUnlike motion capture, we'd like the result mapped back onto our character rig again, which is how animators iterate with physics.
"},{"location":"documentation/marker/#example-1-basics","title":"Example 1 - Basics","text":"Here's how to simulate a box.
Assign
Once you're happy with what you see..
Record Simulation
Here's how to setup a full Ragdoll.
1. Setup hierarchy
Select controls in the order you'd like them attached.
2. Edit shapes
Fit the shapes to your character model.
3. Record
Once your happy with the way the simulation looks, record it back onto your rig.
"},{"location":"documentation/marker/#behaviour","title":"Behaviour","text":"The Behaviour
is how Ragdoll should interpret the controls you assign. Did you mean for them to remain animated, i.e. Animated
? Or should they follow the control around, i.e. Simulated
?
The Behaviour
can be set either for a whole group of markers, or each Marker individually.
Simulated
if there is no group Animated Follow the input exactly, physics need not apply Simulated Follow the input approximately, with some Stiffness
and Damping
"},{"location":"documentation/marker/#animated","title":"Animated","text":"Follow the input exactly, no exceptions. Not even collisions.
"},{"location":"documentation/marker/#simulated","title":"Simulated","text":"Follow the local pose of your animation.
"},{"location":"documentation/marker/#pose-space","title":"Pose Space","text":"Pose matching happens in either Local
or World
space.
Look, it's Ragdoll Blaine!
This is an example of Worldspace Pose Stiffness. Ragdoll will try and reach the worldspace position and orientation of your rig, rather than only looking at the relative angles between each limb.
Here's another example of the difference between Local
and World
space.
Notice how in Local
space, the controls arms remain relative the torso. And with World
space they instead follow the worldspace orientation of the controls.
This attribute is also animatable, and is how you can transition from animation into simulation and back again.
Here's a more complete example:
Frame Transition 100 Starts as a regular animated character 125 Transitions into physics as he jumps, for a physically-correct trajectory 155 Transitions back to animation once he rolls over on that cabinet 160 Transitions back to physics until he stands up 170 Transitions back into animation to match an exact pose 200 Partially transitions into physics, for secondary motion in the upper body as his arm is raised. "},{"location":"documentation/marker/#overlap-group","title":"Overlap Group","text":"Specify which markers may overlap rather than collide. This can be useful to enable dense areas of a character, like the clavicles, where there is natural overlap amongst large shapes like with the neck and spine.
Value Meaning-1
No overlap allowed 0
Default, respects self-collision on the group (if any) 1-255
Overlap everything with the same number An rdMarker
part of a rdGroup
can get an overlap group assigned procedurally, based on other members of that group. For example, in a complete ragdoll, all markers are part of the same group. So a Self Collide = On
means these will all be given the same overlap group.
If it isn't in a group, then 0
is the same as -1
, in that it will collide with everything.
Let's have a look at a few scenarios.
"},{"location":"documentation/marker/#collide-with-everything","title":"Collide with Everything","text":"In this example, every Marker is part of the same group. The group has Self Collide = Off
, which is fine for just about every Marker except the fingers. In that case, we do want self-collision, so they are given the group -1
.
In this case, we're happy with a default group of 0
since we don't need anything to self collide. Especially these clavicles that overlap significantly!
Finally, for the very specific cases of wanting two or more markers to overlap. Notice how we give both the ground and 3 of the boxes an Overlap Group = 5
.
Each Marker has a \"material\" to control how it interacts with other markers.
"},{"location":"documentation/marker/#mass","title":"Mass","text":"How much influence one Marker should have over another during contact.
Pro tip 1 - Misconception about Mass
A common misconception in physics is that Mass
affects how quickly something falls to the ground. But in Ragdoll - like in real-life - mass is only relevant during interaction with another Marker and when forces are applied, like Guide Strength
.
Have a look at this video of a bowling ball falling in a vacuum alongside a feather.
Pro tip 2 - Making something fall fasterSo how do you make something fall faster?
Scene Scale
under the solver nodeGravity
, also under the solver nodeTo make something \"bend\" faster, like an arm flexing, that would be controlled via the Guide Strength
and typically what causes it to reach a given speed and then stay there is governed by the Rotate Damping
. That's how much of any motion should be cancelled out, to stabilise the motion. A very fast motion would have very little damping, but then also run the risk of \"overshooting\". That is, of passing the point at which you wanted it to reach.
Ragdoll can automatically compute a suitable mass for each Marker, based on the volume of your shape and a density of your choosing.
In other words, big objects become heavy, small objects become light.
Before
After
"},{"location":"documentation/marker/#presets","title":"Presets","text":"Enter any value, or pick one from these pre-defined ones.
Density Value DescriptionCotton
0.05 Very sparse, 0.05 grams per cubic centimeter Wood
0.2 Sparse, 0.2 grams per cubic centimeter Flesh
1.0 Default, 1.0g/cm3 Uranium
19.0 Dense, 19.0g/cm3 Black Hole
1000.0 Very, very dense Mass is computed based on the volume of your shape, along with a density of your choosing.
"},{"location":"documentation/marker/#options","title":"Options","text":"Choose between various densities either at creation-time or after creation.
"},{"location":"documentation/marker/#visualise","title":"Visualise","text":"The computed mass updates interactively as you change the size and type of your shape, including convex hulls!
In the Manipulator, you'll be able to not only edit the density, but preview the computed mass given the current shape volume and density you provide.
"},{"location":"documentation/marker/#friction","title":"Friction","text":"Control how much resistance should be added between two rigids rubbing against each other.
"},{"location":"documentation/marker/#bounciness","title":"Bounciness","text":"Control how much rigids should repel each other when coming into contact.
Values beyond 1.0
Here's a tip!
Bounciness can be greater than 1.0, which means they will gain energy during contact.
In practice, energy will always dissipate in some way. The most-bouncy character in the GIF above has a bounciness of 2.0
, which in theory means that for every contact it should fly 200%
faster away than it did coming in, and keep doing this forever.
If you try and balance something on your finger, but the \"center of mass\" is off center, it would fall over.
It is the point at which the weight of an object is equal in all directions.
Ragdoll automatically computes this point based on what the shape looks like. For meshes, it will voxelise your geometry to figure out the physically accurate volumetric center of mass, assuming the density of the object is uniform throughout (rather than hollow or variadic, like swiss cheese).
You now override this point using the attribute Center of Mass
found under the Advanced tab.
Guidelines
0
to compute the point automatically based on the shapeIn real life, if you spin a broom 180 degrees along its length; that's easy. But if you spin it 180 degrees along any other axis, like a ninja, it's considerably heavier.
The reason is something called \"angular mass\", also known as \"moment of inertia\". It's like mass, but in terms of rotation rather than position. The broom has a low angular mass along its length axis. It takes more force to affect a \"heavier\" axis than a lighter one which is why a broom spins more easily along its length.
This effect happens in Ragdoll too and is typically automatically computed for you based on the shape you use. If it looks like the broom, it will act like a broom.
With this release, you can now customise this for greater control of your rotations.
When would you want to do that?
Or any combination in between. :) Generally, a broom or any thin shape is more easily spun along its length, so you may find stability in setting your angular mass to (1.0, 1.0, 1.0)
, at the expense of realism.
Guidelines
-1
to automatically compute the angular massConvert a simulation into keyframes using Record Simulation
.
Markers can be recorded all together, or independently. For example, say you wanted animation from frame 1-100, simulate 101-150 and return to animation from 151-200. You can do that.
Furthermore, say you liked what the simulation was doing, but only on one half of the body. Or only on the hip, driving the main trajectory in a physically-plausible way. Keeping the rest of your animation intact.
Record All
With nothing selected, Ragdoll will record all marked controls to the current Maya playback range.
Record Selected Markers
Select a few controls to control what gets recorded.
Record Range
Limit the Maya playback range for control over when recording takes place.
Record Selected Range
Or, select an explicit range interactively.
Record to Animation Layer
Ragdoll will record to a layer per default.
Mode
Update the viewport whilst recording, or not. That's Nice and Steady
and Fast and Loose
respectively. There's a performance benefit to not updating the viewport, however some character rigs depend on viewport updates to evaluate properly, so it may not always work.
Here's an example with an almost 2x performance difference!
"},{"location":"documentation/record_simulation/#transitions","title":"Transitions","text":"Let's have a look at how you would use markers to transition between simulation and animation.
Notice how we're animated up until the jump, and then Ragdoll takes over.
Pose Space
from Local
to World
and have him reach the target pose in worldspace.Behaviour
to Kinematic
and kinematically move him.Guide
, this time with Pose Space = Local
.Sometimes, rotation isn't coming from Rotate X
but rather a custom Ball Roll
attribute on a different IK control.
As Ragdoll only understands Translate
and Rotate
, how would you go about recording onto this attribute!? Here's what you can do.
Locator.rotateX -> R_foot_CTL.ballRoll
Now Ragdoll will record onto a familiar channel, and Maya will handle the conversion back onto the rig.
"},{"location":"documentation/record_simulation/#extract-simulation","title":"Extract Simulation","text":"Get data out of the solver and into a baked joint hierarchy.
You can use this to build a library of animations, or to handle the retargeting from simulation to animation manually by just constraining to the resulting joint hierarchy.
Performance
Notice how fast this is!
A Debugging Companion
It can also be used for situations where Record Simulation
doesn't do what you need it to. The extracted skeleton will be a plain joint hierarchy, with no scale, and guaranteed to match the simulation exactly. So you can extract it, and constrain your rig to it.
Assign to joints, record to controls.
"},{"location":"documentation/retargeting/#retarget","title":"Retarget","text":"You can visually see where keyframes go upon running Record Simulation
.
Let's take a look at what this UI is, what it can do for you and when to use it.
The UI can help you spot problems with recording, before recording happens.
In this case, some of our markers are retargeted onto joints that are driven by some other object. If we were to attempt to record these, it's unclear what the result should be.
Neither of these are a great pick, since we don't want to break the rig, but we also want our simulation to go somewhere.
"},{"location":"documentation/retargeting/#workflow","title":"Workflow","text":"Once you've assigned your markers, grab a clean slate and gain complete control over where animation is to be recorded.
And finally, here's a longer-form example of a full setup of the Truong Dragon that we did a livestream on a while back.
The opposite of Retarget.
Rather than assigning to joints and retargeting to IK controls, we assign to IK controls and reassign to joints. Same coin, different side; which one do you prefer?
"},{"location":"documentation/retargeting/#reparent","title":"Reparent","text":"Use Reparent
when you selected things in the wrong order and want a do-over.
Success!
"},{"location":"documentation/retargeting/#untarget","title":"Untarget","text":"For when you don't want anything recorded for this Marker. Useful for utility Markers, like twist joints or extra spine controls or just Markers without a corresponding control.
"},{"location":"documentation/snap_to_simulation/","title":"Snap to Simulation","text":"Snap a character to wherever the simulation is currently at.
"},{"location":"documentation/snap_to_simulation/#snap-to-simulation","title":"Snap to Simulation","text":"Yet another way to work with physics, by transferring individual poses from the solver into your animation. You can use it to pose or layout a scene.
Coming Up
An upcoming release will enable you to advance time in the simulation, without affecting time in Maya. Such that you can \"relax\" a pose, for example. \ud83d\ude01
"},{"location":"documentation/solver/","title":"Solver","text":"Markers connect to a solver, and anything connected to one solver is able to interact.
"},{"location":"documentation/solver/#solver","title":"Solver","text":"Where the magic happens.
The rdSolver
node is akin to the motion capture camera(s). It'll monitor any markers in your Maya scene and show you what their physical equivalent version looks like.
Ragdoll needs a consistent progression of time to provide reliable results. So per default, if it notices a frame being skipped, it kindly pauses and waits until you revisit the last simulated frame.
Alternatively, you can let it look the other way and pretend time has progressed linearly, like nCloth and countless other solvers do.
"},{"location":"documentation/solver/#pause","title":"Pause","text":"The default. It's safe, predictable, but requires Play Every Frame
to work.
The nCloth and nHair default, of trying its best to simulate even though it wasn't given the frames inbetween. Unpredictable, unreliable but may handle playing along with sound.
Aside from not giving you the same result each time you play, if too many frames are skipped your simulation can completely explode. You can semi-work around this by increasing the number of substeps, forcing more simulation frames to fill for the missing frames.
Non-deterministic
Bear in mind that the Ignore
method cannot give you the same results each playthrough. The Pause
method is guaranteed to give you the same results, and are identical to what you get when you use the Record Simulation
or Cache
commands.
Rather than having to specify which frame to start simulating at, Ragdoll can keep track of your animation start frame. Either the start of the range, or the full timeline. Or, you can still set a Custom
start time for when you do care about specifics.
solverType
Differences","text":"Type Description Strong Better for characters, it makes the Rotate Stiffness
stronger; more capable of matching the animated pose. It can become unstable if there are too many loose objects in the scene. Stable Better for many independent objects, like a destruction scene. You can find solverType
under the Channel Box and the Attribute Editor.
The fundamental building block to Ragdoll, for \"reverse motion capture\" or Animation Capture.
"},{"location":"documentation/utilities/#replace-mesh","title":"Replace Mesh","text":"You can now replace the original geometry assigned to your marker, just like you could with Rigids.
"},{"location":"documentation/utilities/#auto-limits","title":"Auto Limits","text":"Markers are now able to infer which axes to lock in the simulation, based on the locked channels of your control or joint.
Notice in this example how some of the channels are locked. With the Auto Limit
option checked, the corresponding limit axes will be locked too, such as to prevent the simulation from rotating around those axes.
If you forget or want to detect locked axes on an existing marker, you can use the Utility option too.
"},{"location":"maya/download/","title":"Download","text":"Download for Autodesk Maya 2019 to 2024If you agree with the Ragdoll Dynamics EULA, you may select a platform below.
Windows Linux MacOSRagdoll 2024.02.10 awaits. Read about it - Previous versions
Join the community of ragdollers on Discord and/or Discourse.
Chat Forums "},{"location":"maya/download/#install","title":"Install","text":"Ragdoll ships as a Maya Module for Windows, Linux and MacOS.
Installation for Windows
On the Windows platform, there's an executable you can run.
.msi
installerAlternatively, download the Linux distribution above and unzip it into your ~/maya
directory. You should end up with something like this.
c:\\Users\\marcus\\Documents\\maya\\modules\\Ragdoll.mod\n
Installation for Linux On Linux, installation and upgrades are done in the same fashion.
.zip
into your ~/maya
directoryYou should end up with something like this.
/home/marcus/maya/modules/Ragdoll.mod\n
Installation for MacOS On MacOS, installation and upgrades are done in the same fashion.
/modules
into /Users/Shared/Autodesk/modules/maya
You should end up with something like this.
/Users/Shared/Autodesk/modules/maya/Ragdoll-2021_11_15.mod\n
Gatekeeper
Ragdoll is still in the process of being verified by Apple, until then you may need to tell Gatekeeper \"everything is OK\" for both the ragdoll.dylib
which is the physics solver, and loco3d
which is the Locomotion module. It may also ask about TurboFloat
and TurboActivate
which is the licencing system.
The plug-in is now available via the Plug-in Manager.
Everything ok?
No menuYou've booted up Maya, loaded the plug-in via the Plug-in Manager, but there is no menu, what gives?
Maya Modules work in mysterious ways. Try installing it the old fashioned way.
from ragdoll import interactive\ninteractive.install()\n
No module named 'ragdoll' A clue! Let's go deeper.
import os\nmodules_path = r\"c:\\Users\\marcus\\Documents\\maya\\modules\"\nragdoll_path = os.path.join(modules_path, \"Ragdoll-Maya-2021_11_06\\scripts\")\n\nimport sys\nsys.path.insert(0, ragdoll_path)\n\nfrom ragdoll import interactive\ninteractive.install()\n
Make sure you replace the version number (date) with the version you are using. At this point, I expect you've uncovered why your module wasn't working in the first place and should probably revisit that as this process would require you to manually update the version number in that path each time you upgrade. No fun.
Something else happenedOh no! I'd like to know about what happened, please let me know here.
"},{"location":"maya/download/#faq","title":"FAQ","text":"What are my workstation requirements?Anything capable of running Maya can run Ragdoll.
See Pricing.
What happens when my licence runs out?Your scenes will still open, but the solver will be disabled. Contact licence@ragdolldynamics.com for renewal of your licence.
What happens when I skip frames?The simulation gracefully pauses until you revisit the last simulated frame. See the Frameskip Method
attribute on the rdSolver
node for another option, Ignore
. This will continue simulating, and ignore any skipped frames. Good for real-time playback with audio.
Yes, the only environment variable needed for Rez is MAYA_MODULE_PATH
, such as:
env[\"MAYA_MODULE_PATH\"].append(\"{root}\")\n
Where the Ragdoll-2021_07_28
folder and Ragdoll-2021_07_28.mod
file resides at {root}
.
Ragdoll simulates your translate and rotate channels, whereas nHair simulates point geometry. You can convert those points into translation and rotation, but given the choice why would you? Besides, Ragdoll has far more robust collisions, control and constraints than nHair or nCloth could ever hope to achieve, at much greater performance.
"},{"location":"maya/download/#limitations","title":"Limitations","text":"As of Ragdoll 2024.02.29
these are the current known limitations of Ragdoll.
Welcome to Ragdoll in Maya, first released in July of 2021 and with support for versions 2019 up to 2024.
"},{"location":"maya/home/#where-to-find-help","title":"Where to Find Help?","text":"Depending on where you are and what you are looking for, one of these should fit the bill.
# Source Description Chat Come join the party on Discord! Documentation Read about each command available to you in Maya Release Notes Every new release has examples of every new feature and squashed bug. Search Top of every page, you know what to do \u261d\ufe0f UI Help Find help without leaving Maya YouTube Videos Long-form walkthroughs and examples. Tutorials Long-form, written tutorials for learning Ragdoll from the ground up. Reference The Reference page lists all menu items, item options and node attributes of Ragdoll along with descriptions and examples. Community Inspire and be inspired via the Ragdoll forums Support Get us involved and let's make some waves"},{"location":"releases/2020.11.10/","title":"Multi-threading","text":"Performance!
Ragdoll is now multi-threaded!
There are two mechanisms for managing performance.
With 2 or more Ragdoll solvers in the same Maya scene, Maya will run these in parallel. Which means they will both run independently, on separate hardware cores on your CPU. Currently, you can expect a 2-3x performance increase through use of multiple solvers, with more optimisation to come.
A single Ragdoll solver can be automatically broken up into simulation \"islands\" that run in parallel. Islands are created when two or more groups of rigid bodies are unlikely or unable to interact. For example, two characters in the same solver far away from each other. To leverage solver-level parallelism, adjust the rdScene.threadCount
attribute (under Advanced in the Attribute Editor). A value of 0
(default) means it will run on a single thread, on the same thread as the rest of Ragdoll and Maya.
For small scenes, with less than 100 rigid bodies, you should expect improved performance from a single thread. Each thread comes with some amount of overhead.
"},{"location":"releases/2020.11.10/#option-dialogs","title":"Option Dialogs","text":"
Some menu items now have option dialog boxes for further customisation. Settings are stored with Maya's preferences and persists across scenes and between application launches.
"},{"location":"releases/2020.11.10/#animation-influence","title":"Animation Influence","text":"
The \"Dynamic Control\" feature now enables control of the simulation using the animation used for blending.
The highlight for this release is Cached Playback!
jointOrient
being proper for joints, gone are the days.Box
shape does now draw correctly with a custom rdRigid.shapeRotation
"},{"location":"releases/2020.11.16/#cached-playback","title":"Cached Playback","text":"
Maya 2019 introduced support for Cached Playback, and Maya 2020 added support for Cached Simulation, which is now supported by Ragdoll!
Create new rigids
Edit existing rigids
Trajectories can be enabled with the rdScene.drawTrajectories
attribute, under Visualisation
of the Attribute Editor
There is still work to be done. Currently, animated visualisations aren't updating in cached mode. However the simulation still runs correctly and your driven character animation will behave identically to non-cached mode.
The animation of the slice visualisation doesn't represent the current, animated state
The connection visualisation is not up-to-date, you can disable the drawing with rdConstraint.drawConnection
The guide delta drawn to represent the difference between simulation and your animation only draws the latest result, rather than the result on the current frame.
Note that these are only visual and does not affect the simulation. These will all be addressed in a future release!
rdRigid.ouputGeometry
Remove any geometries when working with cached playback, these cause instant death to Maya and it's still unclear why.
"},{"location":"releases/2020.11.16/#help-videos","title":"Help Videos","text":"
Find out more about a command, by seeing an example of how to use it. There's only one video at the moment, with more to come. Including videos for different ways of using the same command.
The goal is to never have to leave Maya to learn about Ragdoll.
"},{"location":"releases/2020.11.16/#shape-orientation","title":"Shape Orientation","text":"
Shapes typically align with the Maya node, but in the case of joints that isn't always what you want. Maya separates between joint orientation and drawing; it'll always draw joints facing its child. When the orientation and visual orientation of a joint differs, you would end up with correct but unexpected results.
This release fixes that by properly updating..
rdRigid.shapeOffset
rdRigid.shapeRotation
..to mimic how joints appear in the Maya viewport.
"},{"location":"releases/2020.11.17/","title":"Splash Screen","text":"Minor release.
Ragdoll | Character
menu item has been fixed and is operating at 100%"},{"location":"releases/2020.11.17/#install-confirmation","title":"Install Confirmation","text":"
It isn't obvious to new users that Ragdoll installed successfully, so here's what the splash screen looks like that you'll see on first launch.
"},{"location":"releases/2020.11.22/","title":"Bugfixes","text":"Minor release, no breaking changes.
Auto
option to Convert Rigid
, to toggle a rigid between dynamic and kinematicrdRigid.kinematic
attribute is now up-top, better indicating its importanceRagdoll | Convert
menu item is now split into Convert Rigid
and Convert Constraint
Convex Hull
-> Mesh
, should make more sense now"},{"location":"releases/2020.11.22/#capsule-orientation","title":"Capsule Orientation","text":"
Fixed a bug where the capsule of a joint would face the wrong way.
"},{"location":"releases/2020.11.22/#what-is-rigid-body-dynamics","title":"What is Rigid Body Dynamics?","text":"
Loose thoughts that will eventually transform into a quick 10 second video.
Rigid Body Dynamics is a branch of computer science which \"studies the movement of systems of interconnected bodies under the action of external forces\". It differs from your typical simulation - such as nHair and nCloth - in that it simulates the translate
and rotate
channels of a given transform node rather than points of the geometry.
The main advantage is that it is well suited for animation and rigging, since animation and rigging is all about translate and rotate.
Ragdoll Jargon
Dynamic Rigid Body
is a transform affected by forces. Forces like Wind, but also contacts and constraints which are both considered forces, in that they happen instantaneously rather than continuously.Kinematic Rigid Body
is a transform affected by animation. It does not respect forces, but enables you to animate Box
, Sphere
, Capsule
or Mesh
. Shape attributes are prefixed Shape *
e.g. Shape Length
affects the length of the Capsule
, whereas Shape Extents
affects the dimensions of the Box
translate
or rotate
or both channels to each other.Wind
or Push
you can use to affect a Dynamic Rigid Body
"},{"location":"releases/2020.11.22/#performance-tips","title":"Performance Tips","text":"
Many things are currently unoptimised and these are the lowest hanging fruit you can reap for greater performance.
rdRigid
shape once you're done tweakingOther things come down to scene-by-scene basis.
rdRigid.positionIterations
is how many iterations are given to each related constraint. Greater numbers means you can use higher values for Guide Strength
and Limit Strength
, at the expense of performanceThe headline of this release is Dynamic Control 2.0
"},{"location":"releases/2020.11.23/#dynamic-control-20","title":"Dynamic Control 2.0","text":"
Ragdoll is currently very technical.
It is exposing features of an underlying mathematical framework for solving \"Rigid-Body Dynamics\" (wiki) and tries to be as friendly about it as possible, but there is always a tradeoff in usability and flexibility.
Dynamic Control was made to bridge that gap.
It combines a user-selection with a series of commands to automatically try and figure out your intentions when those intentions are \"add some dynamics to my animation control\".
Dynamic Control has been with Ragdoll for a few weeks now, and have undergone a series of changes to try and increase its intuitiveness whilst reducing complexity. It's hard! But in this release I'd like to present what I'm dubbing the \"2.0\" of Dynamic Control.
The main differences are:
stiffness
is the \"springiness\" whereas damping
is the \"plasticity\". A control can have 0 damping and be very springy and active. It can also have 0 stiffness, but that would basically disable it.
On a technical note, the attributes exposed on your animation control are \"proxy\" attributes. Which means they can be animated either from your control, or from the source node, such as the rSocketConstraint
shape node under your control.
Here are some more videos to get you familiar with the tool.
Some limitations in this current version, yell if these affect you.
The same goes for all things Ragdoll at the moment.
"},{"location":"releases/2020.11.23/#center-of-mass","title":"Center of Mass","text":"If you try and balance something on your finger, but the \"center of mass\" is off center, it would fall over.
It is the point at which the weight of an object is equal in all directions.
Ragdoll automatically computes this point based on what the shape looks like. For meshes, it will voxelise your geometry to figure out the physically accurate volumetric center of mass, assuming the density of the object is uniform throughout (rather than hollow or variadic, like swiss cheese).
You can now override this point using rdRigid.centerOfMass
.
Guidelines
0
to compute the point automatically based on the shapeIn real life, if you spin a broom 180 degrees along its length; that's easy. But if you spin it 180 degrees along any other axis, like a ninja, it's considerably heavier.
The reason is something called \"angular mass\", also known as \"moment of inertia\". It's like mass, but in terms of rotation rather than position. The broom has a low angular mass along its length axis. It takes more force to affect a \"heavier\" axis than a lighter one which is why a broom spins more easily along its length.
This effect happens in Ragdoll too and is typically automatically computed for you based on the shape you use. If it looks like the broom, it will act like a broom.
With this release, you can now customise this for greater control of your rotations.
When would you want to do that?
Or any combination in between. :) Generally, a broom or any thin shape is more easily spun along its length, so you may find stability in setting your angular mass to (1.0, 1.0, 1.0)
, at the expense of realism.
Guidelines
-1
to automatically compute the angular massThe \"Auto Connect\" option now enables you to specify whether to connect joints, or any selected object.
"},{"location":"releases/2020.11.24/","title":"Hotfix","text":"Hotfix, the last release broke a few things.
That's all, have mercy.
"},{"location":"releases/2020.12.01/","title":"Character 2.0","text":"Lots of good stuff!
Delete all Physics
now also deletes Ragdoll's attributes on your animation controls, for that squeaky clean feelingrdRigid
The rigids should now clean up after themselves betterThe terminology for \"Rigid\" and \"Collider\" wasn't clear. Surely, a \"Rigid\" collides too?
With this release, I've updated the jargon to make a little more sense.
Active Rigid
A rigid that moves is activePassive Rigid
A rigid that doesn't move is passiveThis also goes for the kinematic
attribute which has been renamed passive
, highlighting that an active rigid can made passive by flicking this switch. Backwards compatibility is preserved by keeping the underlying attribute name, and only changing it in the Channel Box and Attribute Editor (i.e. the \"nice name\").
This release expands on the \"Character\" tool with some nifty new features. But since I haven't mentioned what 1.0 was capable of, here's an overall round down of what it is and when to use it.
Character
is a one-click character creation tool - and auto-rigger (or auto-ragger, if you will). It's designed to give you the essential tools for turning any native Maya skeleton into an animatable rigid body hierarchy.
Read more about it on this new dedicated page I've made for it.
Now Dynamic Control can be configured to generate capsules between selected controls, instead of assuming that the NURBS CVs neatly wrap around the model.
Current and Default behaviour
The tool uses the Mesh
shape per default like before.
Alternative Capsules
But if your controls do not have volume, or do not nicely wrap the underlying model, you can now use Capsules instead.
The caveat with capsules is that the tool cannot know how long to make your capsules. Therefore, there is an option to use the last-selected node as a hint for how long to make it.
In this example, 5 nodes selected, 1 passive and 3 active rigids comes out. If you don't use a last selection for length, the last selected capsule will have a length of 0 (it'll be a sphere). That can work in some cases, but is generally discouraged. The center of mass would be wrong and you should expect unrealistic results until you tweak it to fit your model.
Gathering information about Dynamic Control on the..
An early version of the \"Normalise Sizes\" tool, meant to more evenly distribute sizes of shapes across a hierarchy. Per default, shapes are sized based on the geometry of the Maya node. If it's a box, it'll get the dimensions of the box. If it's a joint, it'll get the length and radius of that joint.
But because this mechanism can't see past the one node it's looking at, it's an uphill battle making shapes evenly distributed in a greater network.
The \"Normalise Sizes\" tool is meant to address that.
It's still early, and a few things are missing.
Now you can speed up or slow down your simulation with a multiplier attribute found on the rdScene
node!
Substeps
.Continuous Collision Detection
to prevent it from flying through stuff without noticing.For anything slower than real-time, remember contacts and constraints are solved each frame, so more frames means more accurate simulation. If you don't like that, you can either (1) half the substeps alongside halving time or (2) bake out the simulation and scale the bake instead.
Example Scene
Now rigids play well with non-standard rotation orders, very common your everyday character animation rigs to ensure axes don't go gimbal.
Thanks to Peter Jemstedt for help on this one!
"},{"location":"releases/2020.12.01/#auto-orient","title":"Auto Orient","text":"Shapes and constraints can now be automatically oriented based on the parent and child of each joint (soon coming to controls). This should help sort out those pesky joint orientations any manner of skeletons.
"},{"location":"releases/2020.12.01/#undo-bug","title":"Undo Bug","text":"There was this nasty bug that caused rdRigid
nodes to remain behind after creating and then undoing. But what got left behind wasn't your normal nodes. They only appeared in the Node Editor and could not be selected or even deleted. They would show themselves out when re-opening the Maya scene which is great.
This visibility isn't a problem in itself, if it wasn't for them also being visible from Python. If any command needed to know \"hey, animation control, are you connected to a rigid?\" then it would happily reply \"yes! for sure!\".
And that's bad. But not anymore, because it's fixed!
"},{"location":"releases/2020.12.01/#stick-figures","title":"Stick Figures","text":"In a previous release I touched on \"angular mass\" and what it meant for your simulations.
Let's look at this in practice.
Here's one character with identical settings, the only difference is the radius of her capsules, and yet the move differently. Why is that?
Remember that angular mass is 3-dimensional. Just like normal mass, when mass is high, more force is required to introduce motion. In the case of angular mass, the force required is divided into three axes.
In this illustration, the angular mass along the X axis is much larger than Y and Z, so in to rotate around this axis you need much more force than the other two axes.
There is however only 1 value for \"guide strength\". You can think of this force as being distributed across each axis, relative its mass.
For example, if your Guide Strength
is 10.0, then the distribution might look something like this.
X Strength = 10\nY Strength = 2\nZ Strength = 1\n
Whereas if angularMassX
was equal like a square cube..
X Strength = 10\nY Strength = 10\nZ Strength = 10\n
In light of this, what are your options?
angularMass
The least intrusive but perhaps most complex option is to manually specify a preferred angular mass.Here's the scene and one more gif to keep you warm at night.
Some things to experiment with:
Guide Strength
was halved?Guide Strength
on her hip?Guide
to her head?Stumbled upon this (thanks Jarl!) which I think is a great example of what I think we're ready to move away from as an industry. :)
Here's a prediction for you - about a year from now, you won't be keyframing anymore. You'll be recording.
"},{"location":"releases/2020.12.07/","title":"Dynamic Control Improvements","text":"Small release with important changes if you use Dynamic Controls on complex rigs with pre-existing animation.
Non-destructive guidance from your original animation when making active rigid bodies. This works much like Dynamic Control, except the guidance is in worldspace. :)
Look at this example of driving an IK handle with physics.
You can blend between simulation and animation using the blendSimulation
node in the Channel Box.
Change shape type, after creation. No matter the starting type.
In the previous release, I added an option for generating dynamic controls as capsules instead of using the actual NURBS geometry. The usecase is for controls that don't have enough geometry to sufficiently wrap around the underlying geometry.
This release enables the user to switch between capsules and mesh after having made the dynamic control. Previously, it was only possible to switch from Capsule to Mesh, not the other way around.
"},{"location":"releases/2020.12.07/#dynamic-control-and-undo","title":"Dynamic Control and Undo","text":"You couldn't undo, now you can.
I found and patched a nasty bug that affected any Dynamic Control - and in fact any Rigid - created with anyhting that had pre-existing animation or connections of any kind, breaking undo.
"},{"location":"releases/2020.12.07/#dynamic-control-and-orient","title":"Dynamic Control and Orient","text":"Orientations were whack, now they're back.
Previously, the orientation of dynamic controls were determined by the physical hierarchy of the control. If the immediate parent was the expected parent control, all was well. But in real-world rigs, there are typically several intermediate groups - some empty, some constrained, some offsets. In such cases, the immediate parent can't be assumed to be the visible parent control the animator sees on screen.
This releases solves this by treating the user-selection as the hierarchy, regardless of what the actual hierarchy looks like. This means you the animator get to control how things are oriented, just like you control what is to be simulated.
"},{"location":"releases/2020.12.18/","title":"Documentation","text":"Documentation documentation documentation!
maya.cmds
Ctrl + Shift + Click
This version expires January 10 2021
"},{"location":"releases/2020.12.18/#documentation","title":"Documentation","text":"Since the last release I've added a boatload of documentation to Ragdoll, including the very website you are visiting now!
This is where I'll aggregate anything there is to know about Ragdoll, including links to the upcoming forums and chat rooms, YouTube series and more. More more more!
Documentation is generated dynamically from the same source used to generate the in-Maya menu and graphical dialogs, so whenever you want quick help from within Maya without breaking your flow, you can! And when you're on the train without access to Maya wanting to know more about a particular button or feature, you can!
Overview "},{"location":"releases/2020.12.18/#help-page","title":"Help Page","text":"Every menu item now comes with the Help
sub-menu active.
The page can also be accessed by clicking on the top description.
I also added hints to the labels of attributes, rather than just the widgets themselves.
All of the information is generated from the same source as the website, so they'll tell you the same thing except closer to where you are.
For example, the Active Rigid
menu item:
Multiple videos are now visible in the UI, to shed more light onto how things work.
Hints
Hovering over the currently playing video displays a description of what it is about.
Real-time scrubbing
I've added real-time scrubbing too!
The caveat however is that it consumes a lot of RAM, this dialog of about 1,000 frames takes 1.5 GB of RAM, and a hefty delay to showing the option dialog.
"},{"location":"releases/2020.12.18/#api-and-cmds","title":"API and cmds","text":"The API used to take and return instances of cmdx
, the high-performance alternative to PyMEL. The API now integrates seamlessly with maya.cmds
, both taking and returning node paths (i.e. strings) rather than instances, which means you can now do this!
from maya import cmds\nfrom ragdoll import api as rd\n\ncube, _ = cmds.polyCube()\ncmds.move(0, 10, 0)\ncmds.rotate(35, 50, 30)\n\nscene = rd.createScene()\nrigid = rd.createRigid(cube, scene)\n\ncmds.evalDeferred(cmds.play)\n
The performance advantage of cmdx
is still intact, and can be accessed via commands.py
which contains identical members and argument signatures, except returning instanced of cmdx
instead. This is what's used internally for both performance and readability.
In addition, there is now support for interactive.py
for quick-and-dirty one-off scripts. This module contains all of what is provided by the Ragdoll menu and work similarly to api.py
except they take (1) user selection and (2) user preferences into account.
Menu items can now be added to the shelf by holding Ctrl + Shift + Click. Menu items also reveal the equivalent Python command to use for your scripts!
"},{"location":"releases/2020.12.18/#helper-warnings","title":"Helper Warnings","text":"If nodes have custom pivots or if your Maya scene is set to DG evaluation mode, Ragdoll will tell you about why that's a bad idea.
"},{"location":"releases/2021.01.04/","title":"Licencing","text":"This release introduces proper licencing to Ragdoll.
Happy New Year, the year of Ragdoll. :)
I've launched the next generation of Ragdoll's website. Something a little more flashy and intended to wet people's appetite for what lies ahead. Feel free to tell people about it, I've added a note about when it'll become a reality.
Also see this news coverage happening in Japan! :D
The old website can still be accessed, although it is a little crippled.
If any link fails, just make sure it's prefixed with ragdoll-web/
as the landing page, e.g. https://alanjfs.github.io/ragdoll-web/howto
Ragdoll is growing up and now understands the \"product key\" which means users can now purchase a copy and register it to themselves.
Here's the short version, with a longer version below.
Now let's cover the nitty gritty details, at the time of this writing.
You won't notice a change, other than a new UI.
Rather than Ragdoll expiring on a fixed date, it'll now expire 30 days after first launch, unless you activate.
Activation requires a product key
which you get by either purchasing a licence or being really awesome.
On first launch, Ragdoll will try and connect to the Ragdoll Licence Server (internet connection required, offline activation coming soon) and register your trial version. This version is node-locked to the particular machine you are on. It'll stick with the machine even across re-installs of your operating system.
Once you've acquired a product key, you can either:
Ragdoll
menu item (bottom)Activate
Or if you prefer:
from ragdoll import licence\nlicence.activate(key)\n
"},{"location":"releases/2021.01.04/#can-i-use-it-on-more-than-one-machine","title":"Can I use it on more than one machine?","text":"Yes. You can activate and use Ragdoll on up to 3 machines. You just can't run a simulation on more than 1 at a time, that could lead to suspension of the licence.
"},{"location":"releases/2021.01.04/#can-i-move-a-licence-between-two-machines","title":"Can I move a licence between two machines?","text":"Yes. If you've activated 3 licences, you can hit the Deactivate
button (which is same as the Activate
button once you've actiavted) and the activation will be released.
Yes and no.
That key is all that is required to run Ragdoll on any machine. If someone takes your key and activates 3 of their own machines, you won't be able to activate it yourself. If this happens, email us with proof of ownership (e.g. via the email used when purchasing) and you'll get a new one.
"},{"location":"releases/2021.01.04/#can-i-have-a-floating-licence","title":"Can I have a floating licence?","text":"Yep, get in touch with licencing@ragdolldynamics.com. Later on, these will be as trivial as node-locked licences. All I need is you.
"},{"location":"releases/2021.01.04/#can-i-activate-offline","title":"Can I activate offline?","text":"Yes. As soon as someone needs it, I'll add it. Get in touch with licencing@ragdolldynamics.com
Offline will be a 4-step process.
activation_request_to_file()
from you local machineactivate_from_file(fname)
on the same local machine.Floating offline is also be possible, again get in touch.
"},{"location":"releases/2021.01.04/#when-exactly-is-internet-required","title":"When exactly is internet required?","text":"A connection is made in one of two separate occasions.
ragdoll.licence.install()
install()
is typically called on Maya startup when the plug-in is loaded and menu is installed. You can disable this.
That is, Maya can open a scene with Ragdoll in it without making a connection to the internet if neither of these things happen. This means you can simulate on one machine, bake or otherwise disable the solver and send it off to a farm (e.g. local or cloud) without worrying about licences.
The alternative would be having to erase any trace of Ragdoll from a scene which would be such a pain.
"},{"location":"releases/2021.01.04/#can-i-manage-my-licence-via-python","title":"Can I manage my licence via Python?","text":"Sure can, see below.
"},{"location":"releases/2021.01.04/#licence-api","title":"Licence API","text":"As a user, you'll generally use the UI. But the UI is ultimately making calls to Python (which is making calls to C++) and you can bypass the UI using these same calls.
from ragdoll import licence\n\n# Called once before calling any other licencing function\n# This is automatically called on Ragdoll Python initialisation\n# and simulation start, but needs calling manually if simulation\n# hasn't yet started.\nlicence.install()\n\n# Retrieve the currently activated product key\nlicence.current_key()\n\n# Activate using your product ket\nlicence.activate(key)\n\n# Deactivate whatever key is currently activated\nlicence.deactivate()\n\n# Dictionary of useful information\ndata = licence.data()\n\n{\n # Same as current_key\n \"key\"\n\n # Is the current licence activated?\n \"isActivated\"\n\n # Is the current licence a trial licence?\n \"isTrial\"\n\n # Has the licence not been tampered with?\n \"isGenuine\"\n\n # Has the licence been verified with the server\n # (requires a connection to the internet)?\n \"isVerified\"\n\n # How many days until this trial expires?\n \"trialDays\"\n}\n
"},{"location":"releases/2021.01.04/#locked-rotate-pivot","title":"Locked Rotate Pivot","text":"Ragdoll doesn't support a custom rotatePivot
attribute and would zero this out whenever a transform is turned dynamic. It'll provide a warning to the end user that this would happen.
But, it wasn't taking into account the rotatePivot
being connected or locked. If that happened, Ragdoll would flat out refuse and print something cryptic in the Script Editor.
This has now been fixed.
Ragdoll still doesn't actually support a custom rotate pivot. So this fixes only the situation where..
rotatePivot
is zero (default), and..rotatePivot
is lockedHighlight for this release are the new Multiplier Nodes!
Rotate Limit
of Dynamic Controls? No longer!Work procedurally, with this centralised place to edit any number of rigids or constraints simultaneously. The idea is to facilitate a top-level node which govern the overall look of your simulation; withouth having to find and select each control individually.
Workflow
Multiply Selected Constraints
(or Rigids
)The order in which you select matters, the first selection gets the node. The recommended workflow is to start with the root and work your way out. But your selection can span multiple hierarchies or even the whole character. A quick \"Select Hierarchy\" across an entire character is possible also.
A constraint and rigid can only have 1 multiplier connected at any one time.
Demo
The most common attributes are made available currently, let me know if you find something missing!
YouTube
Added these suckers for you to play around with.
Variable Description Default RAGDOLL_PLUGIN Absolute path to binary plugin, .mll on Windows .so on Linux. This overrides whatever is onMAYA_PLUG_IN_PATH
\"ragdoll\"
RAGDOLL_NO_AUTOLOAD Do not automatically load the plug-in and add the menu on startup of Maya. False
RAGDOLL_NO_STARTUP_DIALOG Do not display the startup-dialog on first launch. False
RAGDOLL_AUTO_SERIAL Automatically activate Ragdoll on install using this serial number. Unset For up to date information, see here.
Getting some more recognition on the interwebs from EnTT, the library used to keep Ragdoll fast and clean!
Now only relevant attributes are visible in the Channel Box, dynamically based on the current type.
I've added an option to disable this in the Global Preferences.
"},{"location":"releases/2021.01.14/#bounding-box","title":"Bounding Box","text":"Maya uses bounding box information to avoid drawing things that aren't visible in camera. The previous version of Ragdoll didn't provide Maya with any bounding box, which left Maya with no choice but to draw these always; even when behind the camera.
Now this isn't so. You shouldn't notice much for smaller scenes, but drawing typically consumes 20-30% of the total CPU impact Ragdoll has on your character rigs. So for larger scenes this should reap a significant performance boost.
Pro tip: You can also disable drawing of all Ragdoll primitives by disabling Locators
in your viewport; that's how Maya classifies any and all Ragdoll nodes.
TLDR; you should now experience fewer cycle warnings.
Whenever you create a rigid from any Maya node, like an animation control, Ragdoll makes a note of the position and orientation of that control. It takes into account that you may not be on the start frame when you create the control, which is what you most likely intended to do. When that happens, Maya will silently roll back time in the background to query an attribute at the start frame.
This silent roll-back has a tendency to trigger evaluation of unrelated nodes, like IK handles, which in turn trigger other nodes, ultimately leading back to where it came from, and thus cause a cycle. These were somewhat harmless, but could mask a real cycle from happening.
In this release, this silent roll back only happens when you actually aren't on the start frame. So you should see less of it. There's still room for improvement however, so if you still find warnings or any odd behaviors being due to cycles, do reach out!
"},{"location":"releases/2021.01.14/#nan","title":"NaN","text":"If you've ever gotten these, you can now rest easy. They are gone. They could happen on occasion, especially after repeated undo. It had to do with memory access violation by Maya being naughty, something it really shouldn't be able to do in the first place. We now guard against this, so all is well.
"},{"location":"releases/2021.01.15/","title":"Dynamic Control 3.0","text":"The gift that keeps on giving, the highlight for this release is Dynamic Control 3.0!
Another step forward for Dynamic Controls.
"},{"location":"releases/2021.01.15/#default-capsule","title":"Default Capsule","text":"Ragdoll now defaults to the newer Capsule
shape type for dynamic controls. It's faster and applies more generally to most rigs; even those that do have NURBS curves wrapping around the underlying character geometry.
Before
After
"},{"location":"releases/2021.01.15/#automatic-multiplier","title":"Automatic Multiplier","text":"The previous release introduced Multiplier Nodes. This release add a multiplier to each new dynamic control chain per default, on the root control, which means you can now do stuff like this!
"},{"location":"releases/2021.01.15/#centralised-blend-simulation","title":"Centralised Blend Simulation","text":"
Previously, to blend between animation and simulation you needed to select the controls to blend and edit each individually. But it's rather uncommon (and probably not very useful) to want independent control over each blend.
In this release, there is 1 central Blend Simulation
attribute on the root dynamic control. This can be changed in the Options, but will probably disappear unless someone says they like it and wants to keep it!
Previously, Ragdoll wasn't able to figure out how long to make the last control. Now it borrows length, radius and orientation from the parent capsule, which should be what you expect for the majority of cases.
Meaning you can now expect this.
Before
After
You can change the shape type after creation, and modify the default value in the options dialog.
"},{"location":"releases/2021.01.15/#transparent-root","title":"Transparent Root","text":"The first selection of a dynamic control chain is passive, and it used to also collide with the first child. But, most of the time, that root isn't useful as a collider. It would be a global hip control or some particular shoulder/clavicle gizmo.
So the root is now set to Collide = False
, meaning this is now ok.
You can still enable it afterwards if you'd like.
"},{"location":"releases/2021.01.15/#convert-and-restore","title":"Convert and Restore","text":"I've merge the Convert Rigid
and Convert Constraint
buttons into the rigid and constraint creation buttons.
Turn a passive into an active rigid, or vice versa.
Passive
to convert it into a passive rigidIf it's already passive, nothing happens. If you wanted to make a passive rigid active, you know what to do.
"},{"location":"releases/2021.01.15/#convert-constraint","title":"Convert Constraint","text":"Turn a Socket Constraint into a Hinge Constraint, or any other type, on-the-fly.
Socket
to turn it into a socket constraint, regardless of what it wasSometimes you just want to start from scratch. And using the same convert feature you can also restore a constraint to its original settings.
Spot passive rigids by their colors, now all passive rigids are gray.
That means..
Sometimes you want to make bulk changes to all rigids or all constraints at once. You could select each of them, or you could turn to Python and say..
cmds.select(cmds.ls(type=\"rdRigid\"))\n
Now there's a menu item for it too!
That means you can either find everything all at once and make great big changes, or you can zone in on a particular hierarchy or character and affect all rigids or constraints in just that hierarchy!
Fire Wolf rig courtesy of Truong CG Artist
"},{"location":"releases/2021.01.17/","title":"Hotfix","text":"Minor maintenance release.
The startup code for Ragdoll since 2021.01.14 didn't play well with other userSetup.py
files, like the ones you might have in a major production pipeline.
If you were having any issues with the os
module, then this is the fix for you.
The previous release made it possible for the last selected Dynamic Control to inherit its size and orientation from the previously selected control.
This only worked if you have 3 controls selected. This release makes it work on just 2 controls!
"},{"location":"releases/2021.01.27/","title":"Message Board","text":"Focus of this release is Solver Iterations, and some UI additions too!
Ever opened the Script Editor to find Ragdoll screaming for help? I've added a new Message Board to help Ragdoll stand out from the overall messy or hidden messages from rigs and Maya and all else.
Your goal then is to never have any messages appear in the Message Board.
A silent Message Board means a happy simulation. :)
"},{"location":"releases/2021.01.27/#solver-iterations","title":"Solver Iterations","text":"Anything called strength
in Ragdoll is a multipler for stiffness
and damping
. And currently there's a ceiling to how high stiffness
and damping
values can go, after which point they just stop having an effect.
The values are limited by how many \"iterations\" you let the solver perform. Per default, they are set to 8
and can be found at rdRigid.positionIterations
. This release sheds some more light on this somewhat obscure attribute by exposing it directly on the solver, right next to Substeps
.
This value multiplies each rdRigid.positionIterations
attribute, meaning a value of 2
yields a total iteration count for every rigid in the solver of 16
(i.e. 2 * 8
).
Which means you can now do this!
You can further customise iteration counts per rigid, under the Advanced tab.
There's no limit to how many iterations you can allow; more iterations means greater accuracy. However, I have found that values beyond 128 tend to get funky.
Iteration Count Strength Range Description8
(default) 0-5 Default, sensible for most uses 16
0-10 High 32
0-500 Really, really high 64
0-1000 Ultra Nightmare For completeness, here's how Iterations
differ from Substeps
.
They both provide accuracy in slightly different ways. With a greater amount of substeps, the solver is effectively working in slow-motion. Everything is easier in slow-motion. Resolving constraints is independent of time and a little more technical to describe, so you can instead kind of think of it a little bit like rubbing dirt of a silver platter. The first rub, you'll get most of it off. But the more you rub, the shinier it gets. There's no limit to how much you can rub, but eventually rubbing will stop having a visible effect.
"},{"location":"releases/2021.01.27/#help-line","title":"Help Line","text":"Hovering over any menu item now reveals a short description of what it does in the native Maya Help Line (typically at the bottom of the Maya window).
This is the same information as can be found in the Menu Reference.
"},{"location":"releases/2021.01.27/#delete-from-selection","title":"Delete From Selection","text":"The Delete All Physics
menu-item has gotten an option box, now it can be used to limit deletion to currently selected nodes!
The previous release would bark at you whenever trying to turn any transform dynamic if it had any of its translate
or rotate
channels locked. This was a problem when you didn't necessarily care for some of them. For example, with a dynamic control, you really only cared for the rotate
channels but would be prevented from simulating them if the sibling translate
channels were locked. No longer!
That said, the simulation does still produce both translate and rotate values. There's no way around it. And locked channels cannot be connected or edited. Even though you might want to. If the transform is referenced, then there's nothing you can do.
Warnings will be emitted (and made visible in the new Message Board!) if this happens, so it's still true that if your Message Board is silent, all is well.
"},{"location":"releases/2021.01.27/#multiple-cmdx","title":"Multiple cmdx","text":"This should only really affect users of WeightShift, which also uses cmdx
. The previous release was adamant on being the one and only physics solver for Maya. But it has now become more lenient and accepting of other lifestyle choices. :D
Heads up! This got removed. Stay tuned for a re-appearance in a later release
In the previous release, you could animate your dynamic controls, but you couldn't change the initial pose unless you explicitly called Set Initial Pose
from the Ragdoll | Rigging
menu. With this release, you can!
Limitations
This currently only works reliably with strict FK control hierarchies.
The animation is translated into an initial state, but in doing so we are effectively recreating the parent/child relationship between controls. And sometimes - perhaps a lot of times - this isn't a direct FK hierarchy.
Here you can see how the physics and animation controls disagree on what the pose should be. The animation controls aren't in a hierarchy, they are constrained in a complex manner. It isn't accurately reproduced in the initial state.
So if you notice your the simulated initial state to differ from the first pose of your animation, it's the best you can get at the moment.
"},{"location":"releases/2021.01.27/#worldspace-dynamic-control","title":"Worldspace Dynamic Control","text":"Heads up! This got removed. Stay tuned for a re-appearance in a later release
Guide forces in dynamic controls are all local. Which means it'll maintain a pose, even if that pose is upside down or sideways.
And since many versions ago, you've been able to append these \"Guide\" controls, that are in worldspace (per default). These look at the worldspace position and rotation of the control, and use that to line up the simulation. Much like IK!
Now these are built-in to each Dynamic Control (toggle in the option dialog).
These can help keep a character closer to an animated pose. But they are \"cheats\". Forces that appear out of nowhere, as opposed to the local forces which behave like muscles. Muscles can tense and relax whilst still appearing natural, but these are not natural. You can however use them to fake natural.
One more thing; world spaces have strength in either translation or rotation, or both. A worldspace rotation could for example keep a head facing a certain direction, not unlike how IK works. Except physical!
Limitations
This feature uses the same \"virtual hierarchy\" as the animated initial state and suffers from the same limitations.
"},{"location":"releases/2021.02.07/","title":"Scale","text":"Highlight of this release is Support for Scale!
This has been an epic challenge, but it finally happened!
Up till now, any scale other than (1, 1, 1) at any level of a hierarchy would have either broken a simulation or refused to work outright. Not anymore! Now you can simulate scaled transforms, including scaled rigs and all of what it entails.
Here's a brief on what works and what doesn't.
Feature Example \u2714\ufe0f Uniform Scale1.5, 1.5, 1.5
\u2714\ufe0f Non-uniform Scale 0.5, 0.6, 0.12
\u2714\ufe0f Scaled parent(s) Scaled root control \u2714\ufe0f Mixed Scale & Constraints Scaled box to differently-scaled capsule \u2796 Zero Scale 0.0, 0.0, 0.0
\u2796 Mixed Zero Scale 1.0, 0.0, 1.0
\u2796 Negative Scale -1.5, -1.5, -1.5
\u2796 Mixed Positive/Negative Scale 0.9, -1.5, -1.1
\u2796 Non-uniform Negative Scale -1.0, 1.0, -2.0
\u274c Non Object-Space Scale Scale in World
mode There are a few caveats.
Commonly found in parent hierarchies that attempt to mirror the behavior of a control or hierarchy of controls. I'd like to better support this, but it is currently limited by math. More specifically, in that a transformation matrix simply cannot distinguish between negative and positive scale.
So this one is semi-supported. The problem is for Ragdoll to distinguish between scale and rotation. It's a bit mathy, but you know how you can achieve the same pose by either scaling something negatively or rotate it 180 degrees along one or more axes? Ragdoll currently cannot know which of the possible outcomes you wanted.
Here's a visual to help illustrate this point. (Reference)
Here's what can happen in practice.
Notice how both the scale and rotation values changed, even though the object in the viewport remains in the same orientation. That's because these values are both correct scale and orientation for this particular transform.
You might think..
Well, whatever. So long as it's oriented right, why should I care?
Well, what if you had animated a realistically looking horse locomotion, rotating around the X-axis?
Did you spot it? Both X and Z got their scale neutralised and X got 180 degrees steeper, compensating for the neutralised scale values. Also Z got flipped too! You can work around it, by accepting the new Z and offsetting your animation by 180 degrees.
There's also the issue with it flying off for the first few frames. It's unclear why this happens, this may be a bug in the solver itself, trying to reconcile an orientation that is 180 degrees wrong.
So, negative scale works, but it's painful. Avoid if possible.
"},{"location":"releases/2021.02.07/#zero-scale","title":"Zero Scale","text":"This is \"supported\" in that it doesn't fatal crash your Maya session. Ragdoll is a 3D solver, it cannot operate on anything without volume and mass.
Here's an example of what to expect should you find the need for zero scale.
"},{"location":"releases/2021.02.07/#scaled-rotation","title":"Scaled Rotation","text":"TLDR; if you animate something from 0-45 degrees, it will rotate 45 degrees, regardless of scale.
This should be what you expect and won't need remembering, but for completeness here's what happening under the hood.
Ragdoll strips scale from most internal computations. It's kept mostly so that it can be outputted again, as well as for rendering. See, custom Maya nodes render in the space of the transform. So rendering a point at coordinate (0, 0, 0) ends up in the middle of the transform node. Even as you move that transform around with the translate tool. That's problematic if you need to draw something uniformly, like the limits and drive visualisations. Even more so when you attempt to draw a line from one transform to another.. at different scales!
But stripping it early is beneficial for both readability of code, but also usability for you. Uniform scale normally doesn't affect rotation, but non-uniform scale could.
Consider this.
Here, we've got a single angle of 45 degrees. If you were to scale this horizontally, you can see how the angle now changes! At a scale of 0, the angle has gone from 45 degrees to 90 degrees.
This complicates things a lot, and Ragdoll saves you from that by not taking non-uniform scale into consideration for its rotations. A 45 degree angle will remain 45 degree regardless of scale; with the exception of negative scales which still flip the angle as you'd expect.
"},{"location":"releases/2021.02.07/#non-object-space-scale","title":"Non Object-Space Scale","text":"You probably don't do this, but for completeness here's what doesn't work.
"},{"location":"releases/2021.02.07/#nurbs-surfaces","title":"NURBS Surfaces","text":"
Ragdoll could translate polygon meshes and NURBS curves into collision meshes, and today I'm happy to announce that it now also supports the latest trend in computer graphics, heavily used in the 90s at Dreamworks for critically acclaimed feature animation films Antz and Shark Tale.
Join the future!
"},{"location":"releases/2021.02.07/#output-attributes","title":"Output Attributes","text":"The Attribute Editor now displays the output translate, rotate and scale attributes from each rigid body. In both local and world space coordinates.
These are the values that feed into your animation control, or any transform you're simulating.
"},{"location":"releases/2021.02.07/#zombie-attributes","title":"Zombie Attributes","text":"Minor bug fix.
The Delete All Physics
menu item didn't catch the last remaining Local Strength
attribute created by Create Dynamic Control
. This is all patched up!
It's been an epic month of problem-solving, but it finally happened. :D Highlight for this release is.. drumroll.. Automatic Initial State!
Tiger Rig courtesy of www.cgspectrum.com
"},{"location":"releases/2021.03.01/#auto-initial-state","title":"Auto Initial State","text":"Have you ever used the Set Initial State
button? It's useful, isn't it? It's what enables you to turn something dynamic but then change your mind about where it should start simulating.
With this release, that process is automatic! It's more or less what you expected would happen anyway. I mean, obviously the box should drop from where you left it, rather than where it was originally turned dynamic?
"},{"location":"releases/2021.03.01/#disable-feature","title":"Disable Feature","text":"If you would rather have none of it, or if it gives you trouble, you can switch it off like this.
NOTE: Changes take effect on next scene open and newly created rigids.
"},{"location":"releases/2021.03.01/#parallel-only","title":"Parallel Only","text":"That's right, automatic initial state will only work in Maya's Parallel Evaluation mode.
It may end up getting support for DG later on, the trouble lies in the callback we use to read an edited initial state is not reliable in DG. It's possible we'll find another means of achieving the same goal in the future, although DG really is part of the past. Ragdoll works best under Parallel for other reasons too; primarily performance but also stability and robustness.
"},{"location":"releases/2021.03.01/#constraints-stay-behind","title":"Constraints Stay Behind","text":"Constraints currently show you the true position of rigid bodies.
They stay behind because hierarchy preservation is \"artificial\". It's just for you and Maya. In a later release, I'll make rigids also stay behind, and only have your controls move with hierarchy, so that you get to visualise where rigid bodies really are (even when your controls have locked channels, like translate) whilst at the same time letting you move and see your controls and how they reflect that true position.
"},{"location":"releases/2021.03.01/#caveat","title":"Caveat","text":"There's one known \"gotcha\" with the automated initial state.
Namely, the initial state is \"recorded\" whenever you transition from the start time to the next frame. Evaluation on the next frame will automatically read whatever was evaluated previously, and store that as the initial state.
However! It is possible to trigger evaluation without actually changing time. Maya loves doing that. You can do it by either scrubbing the timeline, or holding K
and dragging (effectively scrubbing) the viewport. As you scrub, even if time isn't actually changing, Maya will go ahead and re-evaluated the time.
When that happens, it won't actually record a new initial state, but instead restore the original value. Something to be aware of.
"},{"location":"releases/2021.03.01/#journey","title":"Journey","text":"For the technically inclined, here you can witness last month's struggle first hand and all the kinks uncovered in Maya's API and evaluation graph.
"},{"location":"releases/2021.03.01/#hierarchy-preservation","title":"Hierarchy Preservation","text":"Like in the real world, physics happens in worldspace. There are no \"children\" and no \"parents\". As a result, as soon as you turn any of your controls dynamic, they start acting that way. But we don't want that.
With this release, you'll now get realism along with that familiar feeling of having children and being a parent!
Before
After
"},{"location":"releases/2021.03.01/#caveat_1","title":"Caveat","text":"There is one known case to be aware of when it comes to children.
Passive Rigids
Hierarchy is currently preserved only if a rigid is active. The reason being.. well, I'll just show you.
In this case, the passive rigid bodies are driven by an external transform, those blue \"controls\". Hierarchy is coming from the blue rigids, so we wouldn't want the passive rigids to mess with that.
But now when we move the rigids themselves (gray, in this example) we aren't getting our hierarchy preservation.. :(
At the other extreme, if we do account for hierarchy then the problem pops up at the other end instead.
I trust experience and feedback will light the way here for a more intuitive experience working with external controls.
"},{"location":"releases/2021.03.01/#worldspace-constraints","title":"Worldspace Constraints","text":"If you thought automatic initial state was enough, think again! If your controls have animation already applied, Ragdoll will now translate it into physics in world- and local-space.
"},{"location":"releases/2021.03.01/#default-behavior","title":"Default Behavior","text":"Local animation, like a rotated arm, are imbued with a \"local constraint\" to preserve the relative angle between it and its parent. World animation, like in this case where there is no parent, get imbued with a \"world constraint\".
"},{"location":"releases/2021.03.01/#world-only","title":"World Only","text":"Here's what you get when constraining the child to its worldspace pose. Notice how it assumes the angle you give it regardless of whatever the parent is doing.
"},{"location":"releases/2021.03.01/#local-only","title":"Local Only","text":"Conversely, with just the local constraint, it'll assume the relative angle and respects its parent.
"},{"location":"releases/2021.03.01/#world-local","title":"World + Local","text":"Things get interesting when you combine the two!
"},{"location":"releases/2021.03.01/#world-world-local","title":"World + World + Local","text":"..or combine the three! Here's the lower arm trying to adhere to both its worldspace and local orientation. Notice the constraint coming out of alignment at the root; the constraints are of equal strength per default so it'll end up averaging the desired poses.
There's one more thing happening here that I'll touch on in an upcoming release, which is the concept of world space forces. Notice how the joint chain follows animation
"},{"location":"releases/2021.03.01/#dg-viewport-bug","title":"DG Viewport Bug","text":"If you've ever had the viewport \"remember\" old frames as you scrub the timeline, this fix is for you.
"},{"location":"releases/2021.03.01/#unload-plug-in","title":"Unload Plug-in","text":"In the previous release, licencing was implemented as a Python binding. The trouble with compiled Python bindings in Maya is that they cannot be unloaded. As a result, Ragdoll could not be unloaded.
Licencing is now implemented as a native Maya command, accessible as ragdollLicence
from MEL and cmds.ragdollLicence()
from Python.
Three new commands was added in this release, they are primarily intended for TDs and technically minded folk.
cmds.ragdollLicence()
cmds.ragdollPeek()
cmds.ragdollDump()
Synopsis: ragdollLicence [flags]\nFlags:\n -q -query\n -a -activate String\n -d -deactivate \n -h -help \n -i -init \n -ia -isActivated \n -ig -isGenuine \n -it -isTrial \n -iv -isVerified \n -md -magicDays \n -r -reverify \n -s -serial \n -td -trialDays \n
You still typically interact with ragdoll.licence
, as documented here. But under the hood, this is now the native Maya command being called.
from maya import cmds\ncmds.ragdollLicence(serial=True, query=True)\n# Your-Serial-Number-Here\n
"},{"location":"releases/2021.03.01/#cmdsragdollpeek","title":"cmds.ragdollPeek","text":"Synopsis: ragdollPeek [flags]\nFlags:\n -e -entity UnsignedInt\n -h -help \n -ps -physicsStatistics \n -ss -sceneStatistics\n
Gain insight into what Maya sees in Ragdoll.
cmds.ragdollPeek(sceneStatistics=True)\n\n# Ragdoll Peek Scene\n ____________ ___________________________ _______________\n| Id | Scene | Name |\n|------------|---------------------------|---------------|\n| 71 | rSceneShape | rSceneShape |\n| 70 | rSceneShape | rRigid18 |\n| 69 | rSceneShape | rRigid17 |\n| 67 | rSceneShape | rRigid |\n| 65 | rSceneShape | rRigid7 |\n| 63 | rSceneShape | rRigid8 |\n| 61 | rSceneShape | rRigid14 |\n| 59 | rSceneShape | rRigid15 |\n| 57 | rSceneShape | rRigid16 |\n| 55 | rSceneShape | rRigid11 |\n| 53 | rSceneShape | rRigid12 |\n| 51 | rSceneShape | rRigid13 |\n| 49 | rSceneShape | rRigid9 |\n| 46 | rSceneShape | rRigid10 |\n| 44 | rSceneShape | rRigid4 |\n| 42 | rSceneShape | rRigid5 |\n| 40 | rSceneShape | rRigid6 |\n| 38 | rSceneShape | rRigid1 |\n| 36 | rSceneShape | rRigid2 |\n| 34 | rSceneShape | rRigid3 |\n| 15 | rSceneShape | rRigid27 |\n| 14 | rSceneShape | rRigid28 |\n| 13 | rSceneShape | rRigid29 |\n| 12 | rSceneShape | rRigid30 |\n| 11 | rSceneShape | rRigid31 |\n| 10 | rSceneShape | rRigid32 |\n| 9 | rSceneShape | rRigid33 |\n| 8 | rSceneShape | rRigid34 |\n| 7 | rSceneShape | rRigid19 |\n| 6 | rSceneShape | rRigid20 |\n| 5 | rSceneShape | rRigid21 |\n| 4 | rSceneShape | rRigid22 |\n| 3 | rSceneShape | rRigid23 |\n| 1048576 | rSceneShape | rRigid24 |\n| 1048578 | rSceneShape | rRigid25 |\n| 1048577 | rSceneShape | rRigid26 |\n|____________|___________________________|_______________|\n
cmds.ragdollPeek(physicsStatistics=True)\n\n# Ragdoll Peek Solver\n- Number of scenes: 1\n- Number of shapes: 36\n- Number of materials: 36\n- Number of convex meshes: 0\n- scene[71]\n - Number of dynamic actors: 35\n - Number of static actors: 1\n - Number of constraints: 18 # \n
"},{"location":"releases/2021.03.01/#cmdsragdolldump","title":"cmds.ragdollDump","text":"Synopsis: ragdollDump\n -h -help \n
This is more of a teaser of what's to come, but let me tell you about it for completeness of these release notes.
ragdollDumps
is the start of an integration effort of Ragdoll into any and all external software, like Unreal and Blender. Anything able to parse JSON. Including web-applications.
What if you could rig and/or animate in Maya, but then export the physics setup into e.g. Unreal? I'm not talking about baking your animation and playing it back somewhere else. But of exporting the internal physics objects from Ragdoll, translating them to whatever the third-party software uses for physics, and re-using it there!
With that, you could bypass all of the horrible authoring tools of those applications and transfer a physics scene or setup across applications.
Later, you'll be able to load these into a standalone Ragdoll desktop and web-based application. Useful for sharing your creations and animations with others, and for debugging too!
import json\nfrom maya import cmds\n\ncmds.ragdollDump()\n# {\n# \"scenes\": {\n# \"0\": {\n# \"id\": 0,\n# \"name\": \"rSceneShape\",\n# \"entities\": {\n# \"0\": {\n# \"id\": 0,\n# \"components\": {\n# \"NameComponent\": {\n# \"type\": \"NameComponent\",\n# \"members\": {\n# \"value\": \"rSceneShape\"\n# }\n# }\n# }\n# },\n# \"1\": {\n# \"id\": 1,\n# \"components\": {\n# \"NameComponent\": {\n# \"type\": \"NameComponent\",\n# \"members\": {\n# \"value\": \"rRigid\"\n# }\n# }\n# }\n# },\n# \"2\": {\n# \"id\": 2,\n# \"components\": {\n# \"NameComponent\": {\n# \"type\": \"NameComponent\",\n# \"members\": {\n# \"value\": \"rGuideConstraint\"\n# }\n# }\n# }\n# }\n# }\n# }\n# }\n# }\n
Turn this string into json, with the native Python json
module.
import json\nfrom maya import cmds\n\ndump = cmds.ragdollDump()\ndump = json.loads(dump) # From string to dictionary\n\n# The format is internal and yet to be documented, stay tuned\nscene = dump[\"scenes\"][\"0\"]\nrigid = scene[\"entities\"][\"1\"]\nname = rigid[\"components\"][\"NameComponent\"][\"members\"][\"value\"]\nprint(name)\n# rRigid\n
Expect the output to grow throughout later releases as more internals get serialised to JSON.
"},{"location":"releases/2021.03.04/","title":"Passive to Active Transitions","text":"Small fixes and tweaks, with one pretty cool new feature - the ability to animate the transition between active and passive mode for any rigid!
Active rigid bodies can now be made passive interactively, and continue to be animated as passive, and then - here's the cool part! - once they transition from passive to active, they inherit the animated velocity you gave it!
Pay special attention to the fact that we can key the simulated values, such that we can continue animating from exactly where they left off. Making for a clean transition both to and from physics!
"},{"location":"releases/2021.03.04/#more-scene-visualisation","title":"More Scene Visualisation","text":"The rdScene
node has been able to draw velocities, trajectories and constraints to help you track down problems or gain better insight into the inner workings of the solver. Now it can also draw the current position and orientation of rigids, regardless of where your animation controls are.
This can be especially helpful if your controls have locked channels, such as translate, as they would be unable to show you the translation of the physical version of the control.
Here's how it works.
See how the box as-seen from the scene falls down, whereas the original box doesn't? Because the translate channels were locked, they weren't able to fully represent the simulation.
Here's a more practical example of a tail.
Notice that because the translate channels of the tail are locked, they remain positioned according to the rig. And the rig has some clever mechanics going on to keep the tail attached to the body even when the hip control moves away.
Here's a close-up of that mechanic.
The solver shows you what is actually going on physically and can help track down controls that misbehave.
"},{"location":"releases/2021.03.04/#better-scaled-shape-rendering","title":"Better Scaled Shape Rendering","text":"Small, but important. When you scale things, rendering needs to keep up and descale the normals of the geometry.
"},{"location":"releases/2021.03.11/","title":"Localspace Simulation","text":"Highlight for this release is Local Space Simulation!
Sunny Side Up
Just a wolf, for breakfast.
Waterproof Fire Fox
If you squint, it almost looks like he's underwater!
Collision Volumes
The automatically-generated colliders you get when turning animation NURBS controls dynamic.
"},{"location":"releases/2021.03.11/#ragdog-tutorial","title":"Ragdog Tutorial","text":"That's no typo, this is a Ragdoll-dog! :D Learn about how to achieve the above simulation in this 2-part series on using Dynamic Control.
Spotted an animation on LinkedIn the other day by Radovan Zivkovic, and wanted to see whether it would work with Ragdoll. Here's about 15 minutes of work from launch of Maya to final playblast.
TLDR; This will keep simulation of children intact whilst manipulating parents.
Up until this release, simulation has taken place in worldspace. The last few releases has tried translating worldspace into localspace to try and mimic that familiar feeling of moving the parent and having children follow.
This release moves simulation altogether into local space which means a seamless integration with he parent/child hierarchy that your animation controls are normally in!
"},{"location":"releases/2021.03.11/#before","title":"Before","text":"Pay special attention to how you can edit the master control mid-way through a simulation, but then have that change completely ignored as you return to frame 1.
"},{"location":"releases/2021.03.11/#after","title":"After","text":"Now, with simulation resting in the local space, it behaves as you would expect.
"},{"location":"releases/2021.03.11/#rotate-order-warning","title":"Rotate Order Warning","text":"A while back, support was implemented for a custom rotateOrder
, such as ZYX
or YXZ
. As it turns out, this support was rather incomplete. Solving for a custom rotate order is much more involved than I'd hoped it would be, so for the time being you are advised not to use them.
If you do, you may run into issues such as this.
"},{"location":"releases/2021.03.11/#animated-rigid-attributes","title":"Animated Rigid Attributes","text":"The previous release broke your ability to animate anything on a rigid, e.g. rdRigid.linearDamping
. That's been all patched up!
A bug in a prior version caused frames ahead of the start frame to not reset correctly, unless you explicitly visited the start frame. E.g. skipping from frame 100 directly to 1 rather than from 2 to 1 wouldn't look right. Coupled with the next auto-initial-state feature, this could break a pose. This has now been patched up!
"},{"location":"releases/2021.03.11/#explosion-on-initial-state","title":"Explosion on Initial State","text":"Ragdoll could mistakenly treat a broken simulated first frame as the new and correct initial state. Detecting that stuff is hard! Now it's doing a better job, but keep an eye out for when your start pose breaks, that should never happen.
Also don't forget that this fancy new shiny feature can be disabled under Ragdoll -> System -> Ragdoll Preferences.
"},{"location":"releases/2021.03.11/#shear","title":"Shear","text":"The enemy of any animation, shear is scale's ugly brother. Ragdoll now accounts for shear, even though you are strongly advised never to introduce it willingly.
"},{"location":"releases/2021.03.23/","title":"JSON Export","text":"Highlight for this release is JSON Export, this one's for you game developers out there!
Important!
This version won't self-install like the past releases, see Dynamic Install on how you need to load the plug-in via Maya's Plug-in Manager from now on.
Ragcar
It's a ragcar allright. You can tell by how bouncy it is!
Knocking things around
No obstacle is too tall for ragcar.
A look underneath
The parts are all there, it's how it would work in real life if you put an engine in it. :D
Vehicle model from Mecabricks.
"},{"location":"releases/2021.03.23/#json-export","title":"JSON Export","text":"In 2021.03.01 we introduced cmds.ragdollDump
to get a copy of all rigids in the form of a JSON dictionary.
This release includes all initial state for the simulation, such that you can reproduce the results you see in Maya in a game engine, like Unreal, Unity, CryEngine or your own custom game engine. Or why not Houdini, Blender or 3dsMax?
This enables you to use Maya as an authoring platform for physics anywhere.
from maya import cmds\ndump = cmds.ragdollDump()\n\n# Convert big string to structured dictionary\nimport json\ndump = json.loads(dump)\n\nfor entity, data in dump.items():\n components = data[\"components\"]\n name = components[\"NameComponents\"][\"members\"][\"path\"]\n print(name)\n\n# |root|pelvis|rRigid1\n# |root|pelvis|spine|rRigid2\n# |root|pelvis|spine2|rRigid3\n# ...\n
Here's an example of what to expect from the output.
output_example.json
{\n \"entities\": {\n \"10\": {\n \"components\": {\n \"NameComponent\": \"upperArm\",\n \"ColorComponent\": [1.0, 0.0, 0.0],\n \"GeometryDescriptionComponent\": \"Capsule\",\n ...\n }\n },\n \"15\": {\n \"components\": {\n \"NameComponent\": \"lowerArm\",\n \"ColorComponent\": [0.0, 1.0, 0.0],\n \"GeometryDescriptionComponent\": \"Box\",\n ...\n }\n }\n}\n
See the new Serialisation documentation for an overview, examples and data reference.
Previous releases shipped with a userSetup.py
that triggered on launch of Maya. This made it easy to get setup, but made it challenging to uninstall without physically removing files off of the file system (hint: ~/Documents/maya/modules/Ragdoll.mod
).
This release associates install with plug-in load.
Install
Uninstall
"},{"location":"releases/2021.03.23/#active-chain","title":"Active Chain","text":"Dynamic Control has been renamed Active Chain
.
Turns out, what Dynamic Control was really all about was a generic chain that can also be turned into hierarchies of chains - or \"branches\" - to form a tree. Even a literal one!
"},{"location":"releases/2021.03.23/#dynamic-constraint-attributes","title":"Dynamic Constraint Attributes","text":"
Now whatever attributes are relevant show up in the Channel Box, and stay relevant as you make changes. Similar to how the rdRigid.shapeType
attribute updates the shapeExtents
and shapeOffset
attributes!
Ragdoll now understands when the up-axis is Z rather than the default Y.
"},{"location":"releases/2021.03.23/#simplified-menu","title":"Simplified Menu","text":"Items have been re-arranged and grouped together to be easier to find and less cluttered.
"},{"location":"releases/2021.03.23/#greater-guide-strength","title":"Greater Guide Strength","text":"The solver Iterations
determines how high your Guide Strength
attribute can go. Per default, Iterations
was set to 1
which enabled strengths between 0-5
or so until their effect dimished.
This release increases this default value to 4
for ranges between 0-100
, which means \"incredibly high!\". The change comes at a minor performance impact - estimated between 1-5% - so if you find the need to optimise, lower this value back to 2 or 1.
Hint
Bear in mind that the number of iterations are spread across all rigid in your scene. Meaning twice the number of rigids would half the amount of iterations dedicated to each one.
"},{"location":"releases/2021.03.23/#before","title":"Before","text":""},{"location":"releases/2021.03.23/#after","title":"After","text":""},{"location":"releases/2021.03.23/#crash-on-cleanup","title":"Crash on Cleanup","text":"In rare cases, Ragdoll could crash Maya due to accessing memory it had no business accessing. Those have now been patched up and refactored for a more stable, crash-free experience!
"},{"location":"releases/2021.03.23/#bad-initial-state-on-load","title":"Bad Initial State on Load","text":"In rare cases, opening a scene could lead to some controls being badly positioned. This could happen if the control you made dynamic was parented to a group with no values. That made the parent and local matrices cancel out, producing an identity matrix. Maya doesn't normally save attributes that are equal to their default values, and this includes matrices whose defaults are the identity matrix.
This has now been fixed.
"},{"location":"releases/2021.03.23/#rotate-order-improvement","title":"Rotate Order Improvement","text":"In previous releases, any rotation order other than XYZ (the default) would make your rotations all whack. Ragdoll didn't know how to translate physics into any order other than XYZ, so it would put them in the wrong place.
In the last release, I added a warning for that and in this release I've lifted that warning somewhat. Most rotation orders works well, but I have spotted rare instances of one axis flipping.
Here's the problem.
See how arms and torso flips? It tends to happen around the 90 and 180 degree values, values below that normally look fine. This will be fixed in a future release, one way or another!
"},{"location":"releases/2021.03.25/","title":"Maya 2022","text":"Highlight for this release is support for Maya 2022!
cmds.ragdollDump()
Ready when you are, Python 3 and all!
"},{"location":"releases/2021.03.25/#ragdoll-on-github","title":"Ragdoll on GitHub","text":"Ragdoll is a high-performance C++ plug-in with a flexible Python API.
The API is what powers all user interfaces and all menu items, including the tools themselves. It's what generates Ragdoll nodes and hooks them up to other nodes, translating your selection into physics.
This API is now available on GitHub and will soon open for contributions too!
What does breaking backwards compatibility of a dynamics solver look like?
Original
Last Release
He's the same person! Only the circumstances have changed. :D This has now been fixed, and all previous examples now open and run as expected!
Still pretty cool though I thought, that even though it's broken it still gives you an interesting result. Look at how he initially falls over, it looks like he's attempting to hold onto the seat for balance, and also takes a step back before landing on his butt. :D
"},{"location":"releases/2021.03.25/#accurate-gravity","title":"Accurate Gravity","text":"The indicator used to face in the Y-axis of wherever the node was facing. That wasn't true. It's now accurate no matter how you spin it around, including a potential Z-up axis!
Before
After
"},{"location":"releases/2021.03.25/#ragdoll-explorer","title":"Ragdoll Explorer","text":"Added an early version of a visual interface for the cmds.ragdollDump()
command, something to inspect the internals of the solver. Mostly intended for game developers but also advanced users and techincal directors. Expect an Outliner-like appearance and use for this explorer, more to come!
Highlight for this release is import of physics from one character to another!
Head's up Game Developers
NameComponent
was changed, and entity
values are now a fully-fledged type.
See Backwards Incompatibility for details.
Import onto Selected Character
Import onto the Ragcar
Import limbs of Tiger
"},{"location":"releases/2021.04.11/#import","title":"Import","text":"Animators can now setup physics one character, export it, and then import onto another.
The usecase is having spent time setting up a perfect ragdoll and then wanting to reuse this setup across multiple scenes, on multiple instances of the same referenced character, or on characters with similar naming scheme and anatomy. It can also be used to import parts of a character or individual objects.
Demo
Here's an 18 second run-down of the complete workflow, from authoring to import.
"},{"location":"releases/2021.04.11/#features","title":"Features","text":"Anything you can apply physics to can be exported.
The nodes onto which physics is imported..
It will remember..
Guide Strength
It will not remember..
Convex hulls, those triangulated versions of your Maya shapes - the Mesh
shape type - are re-generated onto whatever character you import onto. This is probably what you want, and enables you to apply physics onto characters with different geometry from when you originally authored the physics. Although sometimes it's not, which is why this we be augmented in a future release.
The root in any chain is the first in your selection when creating the chain. If you build a network of chains - a \"tree\" - which is common for any character of more than 1 limb, the exported file will not remember which the original root was. It will figure out new roots procedurally based on their parent/child relationship which may or may not be the same as your original. For importing a full character, this makes no difference. Only for the advanced case of exporting a full character but then wanting to apply only the arm or leg of that character onto another character makes this problematic. This will be addressed in a future release.
And that's about it! It doesn't even have to be a \"character\", any combination of Maya nodes you can apply physics to can have their physics exported. Like a (rag)car, or just a (rag)box.
"},{"location":"releases/2021.04.11/#user-interface","title":"User Interface","text":"In addition to import everything found in an exported file, there's a UI for more control.
The UI resembles native Maya and Ragdoll option dialogs, with two interesting bits.
"},{"location":"releases/2021.04.11/#1-file-browser","title":"1. File Browser","text":"The top part displays other Ragdoll scene (.rag
) files in the same directory as the selected file, along with the thumbnail stored during the time of export. The thumbnail currently isn't visible during export, it is captured from the currently active viewport. An Export UI with thumbnail preview (and more!) will be added in a future release.
This sections shows you the contents of the physics scene, ahead of actually importing it.
It will visualise a number of things.
nurbsCurve
or mesh
?Shape Type
of the exported rigid, e.g Capsule
?Did you see Snyder's Justice League? In it, they introduce and explain the \"mother box\" and how it is capable of turning the dust of a burnt house back into a house.
This Import
feature is the Mother Box of Ragdoll.
The export format is identical to what game developers use to author physics in Maya and import it into their game engine. It contains all data managed by Ragdoll in full detail. Enough detail to reverse-engineer it back into a Maya scene, which is exactly what's going on here.
Example Files
mytiger.rag
mycharacter.rag
ragcar.rag
Each export captures the currently active 3d viewport for use as a thumbnail. So, whenever you export, remember to smile and wave! :D
"},{"location":"releases/2021.04.11/#context-sensitive","title":"Context Sensitive","text":"The visualisations will update as you select different nodes and edit the various options in the UI.
To illustrate this, let's import onto the same scene we exported.
Export
Only one character is physicalised and exported.
Import
Notice that importing is not possible, since the character is already physicalised. Unless we replace the namespace, by selecting another character.
"},{"location":"releases/2021.04.11/#use-selection","title":"Use Selection","text":"Import onto selected nodes with Use Selection
toggled (it's the default).
Every node is stored along with its full path, such as..
|root_grp|spine_grp|spine_ctrl\n
And in most cases can get quite long, with one or more namespaces and tens to hundreds of levels deep in hierarchy.
|_:Group|_:Main|_:DeformationSystem|_:Root_M|_:RootPart1_M|_:RootPart2_M|_:Spine1_M|_:Spine1Part1_M|_:Spine1Part2_M|_:Chest_M|_:Scapula_L|_:Shoulder_L|_:ShoulderPart1_L|_:ShoulderPart2_L|_:Elbow_L|_:ElbowPart1_L|_:ElbowPart2_L|_:Wrist_L|_:IndexFinger1_L\n
Here, the namespace is simply _:
The Search and Replace
boxes of the UI can be used to replace parts of each path, to try and map the original path to whatever path is currently available in the scene.
One challenge with export/import it remapping names from the original scene onto your new scene. Ragdoll solves the typical case of only the namespace being different with \"Auto Namespace\".
\"Auto Namespace\" will replace any namespace in the original file with whatever namespace is currently selected. Neat! If there are multiple namespaces, it'll use the last namespace. Let me know how you find that, there's room left to explore here. Most often, you only ever have a single namespace, but Maya does allow you to tie yourself into a knot if you really wanted to.
"},{"location":"releases/2021.04.11/#auto-scene","title":"Auto Scene","text":"Locate and use the original physics scene from the original file, so as to preserve your multi-scene setups.
For example, if your one character has 3 physics scenes - one for the right arm, one for the left and a single one for both legs - then \"Auto Scene\" will preserve these scenes for you.
Performance Tip
Using more than one scene can improve performance significantly, as Ragdoll will parallelise each invidual scene. The caveat is that rigids in different scenes cannot interact with each other.
"},{"location":"releases/2021.04.11/#ragdoll-clean","title":"Ragdoll Clean","text":"Here's a quick way you can use this feature to \"clean\" a physics scene.
The resulting scene will be \"clean\" in that it will have been broken down into its componens and reassembled again, not taking into account anything Ragdoll doesn't know about.
(I may just add a menu item for this, called Clean
to do this in one go :)
A few things became apparent as I rounded off this feature
Anything the UI can do can be done via Python, using the new dump.Loader
object.
from ragdoll import dump\nloader = dump.Loader()\nloader.read(r\"c:\\path\\to\\myRagdoll.rag\")\n\n# Search and replace these terms from the full node path\n# E.g. |root_grp|arm_left -> |root_grp|arm_right\nloader.set_replace((\n (\"_left\", \"_right\"),\n (\"_ik\", \"_fk\"),\n))\n\n# An automatic method of search-and-replace, that replaces\n# any namespaces found in the file with this.\n# E.g. |char1:root_grp -> |char2:root_grp\nloader.set_namespace(\"char2:\")\n\n# Limit imported nodes to those with an absolute path \n# starting with *any* of these\nloader.set_roots((\n \"|char1:root_grp\",\n \"|char2:root_grp\"\n))\n\n# Deconstruct the provided `.rag` file\n# (This is what is visualised in the UI)\n# (The exact layout of this data may change)\nanalysis = loader.analyse()\nassert isinstance(analysis, dict)\n\n# Print a brief human-readable summary of the current analysis\nloader.report()\n
Heads up
Consider this a version 0.1 of the API, it will likely change in the future.
"},{"location":"releases/2021.04.11/#ragdoll-stability","title":"Ragdoll Stability","text":"Implementing import put a lot of strain on Ragdoll.
Whereas before, authoring physics was a matter of calling one command at a time, playing around with the result, calling another. Maybe undoing every so often.
Import on the other hand calls tens to hundreds of commands at once, undoing them en masse, redoing them en masse. It exposed a ton of flaws in the system that had gone unnoticed in all but the rarest of occasions. Crashes, a ton of them. The worst kind, the kind that doesn't tell you anyhing about why it crashes.
The above an example of:
I'm happy to say these have all been resolved, and the automated test-suite has grown 10x since the last release. Every command is tested, and tested again with undo, and again with redoing an undone redo. It is rock solid, and fast.
You can now undo any command as-one, any number of times, redo it any number of times, undo your redo any number of times. Ragdoll will not be the cause of any crashes.
"},{"location":"releases/2021.04.11/#maya-2022-stability","title":"Maya 2022 Stability","text":"Maya 2022 in its current state has proven incapable of reliably supporting Ragdoll.
Maya 2022 may crash with Ragdoll
That's right. Maya 2022 isn't quite baked yet, and needs a Service Pack. Until then, Ragdoll will run reliably so long as you don't delete anything, or try and open a new scene.
In addition to that, the multiplier nodes didn't quite work with Maya 2022, or more specifically with Python 3.
from ragdoll import interactive as ri\nri.multiply_rigids()\n# Error: 'filter' object is not subscriptable\n# Traceback (most recent call last):\n# File \"<maya console>\", line 2, in <module>\n# File \"C:\\Users\\marcus\\Documents\\maya\\modules\\Ragdoll\\python\\ragdoll\\interactive.py\", line 2112, in multiply_rigids\n# root = rigids[0].parent()\n# TypeError: 'filter' object is not subscriptable #\n
There were also crashes happening on deleting rigid bodies from your scene, these got swept away alongside a number of other fixes to the handling of nodes.
So one step forward, one step back. :)
"},{"location":"releases/2021.04.11/#edit-shape","title":"Edit Shape","text":"A new menu item got added for manipulating shapes with a native Maya transform, as an alternative to fiddling with numbers in the Channel Box.
"},{"location":"releases/2021.04.11/#proxy-attributes","title":"Proxy Attributes","text":"In Maya 2018 and 2020, the attributes added to your original animation controls that mirror those of Ragdoll were \"proxy attributes\". That is, they could be edited from either their original attribute, or the one connected to by your control.
That's really convenient.
Turns out, it is also really unstable. Most of the crashes happening so far, especially on deleting physics or starting a new scene, has come from proxy attributes messing everything up. It should't be surprising, even Maya struggles with them.
node = cmds.createNode(\"transform\")\nshape = cmds.createNode(\"nurbsCurve\", parent=node)\ncmds.addAttr(node, ln=\"proxyVisibility\", proxy=shape + \".visibility\")\nassert cmds.objExists(node + \".proxyVisibility\")\nassert cmds.getAttr(node + \".proxyVisibility\") == 1\n\n# What should happen to the proxy attribute? :O\ncmds.delete(shape)\n\ncmds.getAttr(node + \".proxyVisibility\")\n# RuntimeError: The value for the attribute could not be retrieved. # \n
The same thing applies with access from the API. It just doesn't know what's going on. If we're lucky - which we have been so far - it'll just fail and tell you about it. Other times it'll fail and take Maya down with it. That's just bad.
In Maya 2019, the problem was so severe that proxy attributes were simply not used. With this release, no proxy attributes are used.
I hope to reintroduce them at a later date, once I discover is a safe method (read: workaround) to using them.
"},{"location":"releases/2021.04.11/#python-api-consistency","title":"Python API Consistency","text":"The good news is, the Python API is maturing. The bad news is, this release introduces backwards incompatible changes.
from maya import cmds\nfrom ragdoll import api\n\ncube, _ = cmds.polyCube()\ncmds.move(0, 5, 0)\ncmds.rotate(0, 45, 45)\nscene = api.createScene()\nrigid = api.createRigid(cube)\n
So far so good.
# Before\napi.socketConstraint(parent, child, maintain_offset=False)\n\n# After\napi.socketConstraint(parent, child, opts={\"maintainOffset\": False})\n
Here's the change. These behavior-like arguments have been moved into an opts={}
argument, and is now consistent across any commands that take \"options\". It's to faciliate a large number of options, both from the UI and scripting and enhance compatibility over time; with a dictionary, you can test for availability of arguments at run-time, as opposed to suffer the consequences of not being able to call an update function.
I'm still exploring ways of getting more options into commands, without polluting the argument signature, without changing their order when an argument is deprecated, or changing an argument name when jargon inevitably changes. Using a dictionary for options-like arguments enables us to pass arbitrary sized options to functions, they can also be passed to functions that don't necessarily need all contained options, meaning you can establish a single options dictionary up-front and pass that to all relevant functions.
It's too soon to tell whether the cons of this approach outweighs the pros. This is one reason for the API still going through changes.
The non-optional arguments are those that are never intended to change, like the createRigid(node)
argument. Every rigid needs something to make rigid. (Or so you'd think, as you can now also create a rigid from a new empty transform).
So, the API has changed and will continue changing for a while longer.
Node/Attribute format
The Ragdoll scene format is stable and has been for months. It will remain compatible with future versions of Ragdoll, which means anything you build today (or months ago) will continue to work identically.
The Python API on the other hand is not yet refined and is still changing. So when you build tools ontop of Ragdoll, keep in mind that nodes, their attributes and their connections are stable, but the means of creating those connections are not. So if you need stability today, look at what nodes and connections are made by the API, and do it yourself.
"},{"location":"releases/2021.04.11/#ragdoll-explorer","title":"Ragdoll Explorer","text":"For developers
Explorer has gotten an update, inching its way towards Outliner-like behavior and feel. Eventually maybe even an integration with the Outliner, similar to how USD slots into Maya 2022. That's quite neat!
"},{"location":"releases/2021.04.11/#logging-level","title":"Logging Level","text":"You can now tune the way Ragdoll communicates with you.
Off
means it won't tell you anything, not even warningsDefault
is what you've gotten used to so farLess
only shows you important messages that require you to take actionMore
is the full monty, performance metrics, detailed messages, you name itThese are animator-friendly jargon for the native logging.INFO
and logging.WARNING
levels. \"Off\" means logging.CRITICAL
since Ragdoll does not emit any critical messages.
A few things has been improved for those using Ragdoll as an authoring platform for other software like Unreal and general game engines.
"},{"location":"releases/2021.04.11/#new-components","title":"New Components","text":"The export format has been graced with new components to accommodate for the import feature. As the name suggests, these are stricly related to UI and aren't required for reproducing the physics in another application or engine.
They are meant to cover user elements in Maya such that they can be accurately reproduced on re-import back into Maya.
New Components
RigidUIComponent
ConstraintUIComponent
LimitUIComponent
DriveUIComponent
RigidMultiplierUIComponent
ConstraintMultiplierUIComponent
Here's what the new components may look like in your exported file.
{\n \"type\": \"RigidUIComponent\",\n \"members\": {\n \"shaded\": false,\n \"airDensity\": 1.0,\n \"shapeIcon\": \"transform\",\n \"multiplierEntity\": {\n \"type\": \"Entity\",\n \"value\": 0\n }\n }\n},\n{\n \"type\": \"ConstraintUIComponent\",\n \"members\": {\n \"multiplierEntity\": {\n \"type\": \"Entity\",\n \"value\": 0\n },\n \"childIndex\": 2\n }\n},\n \"type\": \"LimitUIComponent\",\n \"members\": {\n \"strength\": 1.0,\n \"angularStiffness\": 1000000.0,\n \"angularDamping\": 10000.0,\n \"linearStiffness\": 1000000.0,\n \"linearDamping\": 10000.0\n }\n},\n \"type\": \"DriveUIComponent\",\n \"members\": {\n \"strength\": 0.5,\n \"angularStiffness\": 10000.0,\n \"angularDamping\": 1000.0,\n \"linearStiffness\": 0.0,\n \"linearDamping\": 0.0\n }\n}\n
There's also an added section for \"ui\" related data, most interestingly a base64-encoded QPixmap of a thumbnail
.
\"ui\": {\n \"description\": \"\",\n \"filename\": \"C:/scenes/demo/advancedskeleton5.rag\",\n \"thumbnail\": \"iVBORw0KGgoAAAAN ... lots more characters ...\"\n }\n
That can be converted like this.
from ragdoll import ui\nqpixmap = ui.base64_to_pixmap(data[\"ui\"][\"thumbnail\"])\n
"},{"location":"releases/2021.04.11/#backwards-incompatibility","title":"Backwards Incompatibility","text":"The export format has changed slightly, here's what you need to know.
NameComponent.path
was changed from the full path + Ragdoll node to just full path.Example
# Before\n|root_grp|spine1_ctrl|upperArm_ctrl|rRigid3\n\n# After\n|root_grp|spine1_ctrl|upperArm_ctrl\n
Some values were entities themselves, but there wasn't any way of knowing unless you explicitly new that JointComponent.parent
is in fact an entity. This has now been addressed, and all entities now carry a [\"type\"]
signature.
# Before\n{\n \"type\": \"JointComponent\",\n \"members\": {\n \"disableCollision\": true,\n \"parent\": 16\n \"child\": 15\n }\n}\n\n# After\n{\n \"type\": \"JointComponent\",\n \"members\": {\n \"disableCollision\": True,\n \"parent\": {\n \"type\": \"Entity\",\n \"value\": 16\n },\n \"child\": {\n \"type\": \"Entity\",\n \"value\": 15\n }\n }\n}\n
"},{"location":"releases/2021.04.23/","title":"No Limits and Improved Performance","text":"Highlight for this release is No Limits and Greater Performance!
10 Second Ragdoll
Here's the absolute quickest way to turn a fresh mesh into a full ragdoll.
And here's a more practical example of using this feature to clean up a bad mocap clip.
It'll endure changes to the environment too, with little to no modification of the physics settings or the original animation.
"},{"location":"releases/2021.04.23/#no-more-limits","title":"No More Limits!","text":"That's right!
It used to be the case that if your character had a non-default Rotate Order
, or a tweaked Rotate Pivot
or maybe made use of the handy Rotate Axis
or the joints you were using had a non-zero Joint Orient
, then you were out of luck! Ragdoll just couldn't handle those. It would aggressively reset those to their defaults, or flat-out refuse to work.
This release adds support for these missing members, which just so happens to be the very last major limitations of Ragdoll when used with your everyday character rigs!
From now on, if it doesn't work with your rig, that's a bug (let me know!).
"},{"location":"releases/2021.04.23/#rotate-pivot","title":"Rotate Pivot","text":"This release introduces support for both the .rotatePivot
and rotatePivotTranslate
attributes, letting you do things like..
I've also added an option to actually use the rotate pivot (for greater good?) such that you can do this.
"},{"location":"releases/2021.04.23/#rotate-axis","title":"Rotate Axis","text":"The advanced rigger will know of his lesser-known feature of Maya transform nodes, with the ability to modify the axis around which the Rotate XYZ
channels operate.
Finally cracked this one, it has been far too long and is a far-too used feature of Maya transform nodes to not support. But it's done! You should now be able to pick any rotate order and experience no flipping or issue of any kind. Don't even bother getting in touch if you do, because I will not believe you. xD
This tiger (courtesy of www.cgspectrum.com) has a different rotate order on nearly every control.
Before
After
Hold on a second!
That final flip of the spine is coming from the rig itself, the joints driven by the controllers we're simulating. Ragdoll isn't the only one having issues with flipping. :)
"},{"location":"releases/2021.04.23/#joint-orient","title":"Joint Orient","text":"When simulating joints, it can be important to retain the original jointOrient
values. Especially if those joints are later used for IK or if you want or need to zero out those rotate values. But it is perhaps most important for an already-animated skeleton, like what you get out of motion capture.
Some motion capture libraries, like Rokoku, do a good job not having any jointOrient
in which case they would already work well with Ragdoll. But for animated skeletons with a non-default jointOrient
you would have been out of luck..
Until now!
"},{"location":"releases/2021.04.23/#30-greater-performance","title":"30% Greater Performance","text":"Ragdoll used to be really really fast, and is now really really really fast!
Rendering is one of two areas where Ragdoll spends time computing (the other being simulating), and rendering performance has been improved by 400%, making Ragdoll 30% faster overall!
Here you can see the improvement up-close, notice how much time was spent simulating versus rendering each frame in the previous version; almost half the time was spent just rendering!
And if you're wondering...
Ok, but what features did you remove?
On the contrary! Rendering now includes..
Even More Performance?
You'll notice that the rendering square isn't entirely gone.
If 4 ms just to render is too much to ask, you'll get even more of a performance jolt by simply hiding anything Ragdoll related, in particular the rdRigid
and rdConstraint
nodes. The simulated result is independent of whether or not it is visible in the viewport.
If you are a rigger, this can be handy for your animators once you've finished setting things up, as they may not benefit from seeing these things anyway and could use all of the performance you can give.
"},{"location":"releases/2021.04.23/#simulated-attribute","title":"Simulated Attribute","text":"Whenever you make a new chain, an attribute is created on the root of that chain to control whether or not the chain should be Simulated
or animated.
With this release, Simulated = Off
means:
Additions to the physics solver can only happen on the start frame, and if you in previous version created anything on any other frame Ragdoll would yell at you.
This release aids in this process, in that rather then telling you you are wrong, it helps you make it right by automatically returning to the start frame when necessary.
"},{"location":"releases/2021.04.23/#cycle-protection","title":"Cycle Protection","text":"Cycle warnings are generally bad but especially bad for Ragdoll. Understanding when they happen and where they come from can be difficult, especially in complex setups.
Ragdoll now includes Cycle Protection to help you spot potential cycles before they happen!
Notice how making a passive rigid here would have resulted in it becoming a child of an otherwise active hierarchy. That would have been bad!
"},{"location":"releases/2021.04.23/#protected-commands","title":"Protected Commands","text":"These commands will try and protect your from cycles.
All other commands is already safe to use and shouldn't cause any cycles.
"},{"location":"releases/2021.04.23/#faq","title":"FAQ","text":"These are some of the things you might want to learn more about.
How does it work?Whenever a new Passive Rigid or Active Chain (with passive root) is being created, Ragdoll is asked to evaluate the world transformation of the node you are attempting to make dynamic. The solver should not be bothered to simulate anything during this encounter, because if it did then that would mean a cycle is about to happen.
Why?
Because passive rigids pass data into the solver. Namely, the position and orientation of the node you are attempting to turn into a passive rigid. It cannot both pass and receive data. If it is to receive translate/rotate from the solver, then that's an active rigid.
Is it accurate?Very.
Character rigs can get very complex; how can Ragdoll distinguish between an actual parent being active, and a node acting like a parent via something like Maya's Parent Constraints (i.e. a \"broken rig\")?
The answer is that the feature builds on Maya's own evaluation mechanism to figure out whether a node is dependent on the solver or not. The mechanism is surprisingly simple.
def is_dynamic(transform, scene):\n \"\"\"Does `transform` in any way affect `scene`?\"\"\"\n scene[\"clean\"] = True\n\n # Pull, but do not bother actually serialising it\n transform[\"worldMatrix\"].pull()\n\n return not scene[\"clean\"].read()\n
By pulling on worldMatrix
we ensure all hierarchy and constraints is taken into account, and by not actually retrieving value we limit the computational cost to dirty propagation only - as opposed to actually reading and serialising the 16 values that make up the matrix.
Yes.
The protection is only happening when interacting with Ragdoll via the UI menu items. The API remains unaffected and there is an option in the Preferences to disable it in the UI as well.
"},{"location":"releases/2021.04.23/#new-constraints","title":"New Constraints","text":"Have more fun with more control. \ud83d\ude18
These were previously available under a different names and less intuitive usage
"},{"location":"releases/2021.04.23/#hard-pin","title":"Hard Pin","text":"When you want a rigid to be at an exact place at an exact time, use Hard Pin.
Limitations
Previously called Passive Control
.
When you want a rigid to be at an approximate place at an approximate time, whilst still respecting the laws of physics including contacts and gravity, use Soft Pin.
Soft pins are nothing more than a constraint with a guide position towards the newly created transform.
Limitations
Previously called Guide Control
.
In the the previous releases I've been experimenting with the idea of turning the Maya translate/rotate channels directly into a guide constraint.
There are three possible scenarios with subtle differences.
In the above, the parent of the newly created rigid with an animation constraint is non-dynamic, it's got nothing to do with Ragdoll. Just your everyday (boring) Maya transform. In this case, the channel is successfully converted to a worldspace position and orientation from your translate/rotate channels.
Here on the other hand, the immediate parent is a Passive Rigid
which is a little more flexible, and gives you an option to actually collide with the parent.
Finally, the parent is active. This is also OK and quite fun. Now the new rigid will affect the parent, since it adds weight onto it. Like a backback.
Dynamic Grandparent
Here's where things get less predictable. If the parent of the control you want physics to follow along with your translate/rotate channels is non-dynamic, but one or more of its parent are active rigids, then the channel box values no longer align.
This will be addressed in a future release.
"},{"location":"releases/2021.04.23/#character-multiplier","title":"Character Multiplier","text":"Making a new character now includes a default multiplier for all constraints (just like chains do!), meaning you can more easily create effects like this!
"},{"location":"releases/2021.04.23/#import-bugs","title":"Import Bugs","text":"Two issues were found with the importer introduced in the last version.
Passive versus Rigid
When importing a passive rigid, odds are it got imported as a active rigid instead. This could get very messy, as it could end up creating passive rigids as children of active ones, which could reak all kinds of havoc, including cycle warnings.
2-link chains
Any \"chain\" with more than one child (head) is a special case of each chain only having 1 rigid each, as opposed to longer chains like arms and legs. Now these can be imported too!
Export is Unchanged
This and the above import fix were only related to importing of physics, both your existing Maya scenes and exported .rag
files are unchanged and were already in good condition. Yay!
Whenever you make a rigid or chain, some attributes are forwarded onto your animation controls. These attributes are called \"User Attributes\" and the previous release changed these from Maya proxy-attributes to plain-attributes.
In doing so, they lost their nice names and default values. :( This has now been fixed!
"},{"location":"releases/2021.04.23/#looped-playback-bug","title":"Looped Playback Bug","text":"If you've ever had both passive and active rigids and let playback run on a loop, you might have encountered something like this.
Whereas if you rewound and playback without looping, everything would be allright. This bug got squashed in this release, letting you loop things to your hearts content!
"},{"location":"releases/2021.04.23/#auto-cleanup","title":"Auto-cleanup","text":"Whenever you Delete All Physics
anything created by Ragdoll disappears, including User Attributes. What wasn't included however was the handles that appears when you Edit Constraint Pivot
and Edit Shape
.
These now also vanish with delete-all, making your life just a little bit better!
Thanks to Remi Comtois for pointing this out!
"},{"location":"releases/2021.04.23/#offline-activation","title":"Offline Activation","text":"Activation is streamlined by happening inside of Maya at the paste of a serial and press of a button. Unless you are one of those without access to the internet, in which case we'll need to do a little dance. :)
Step 1 - Generate Request
from ragdoll import licence\nkey = \"YOUR-VERY-LONG-KEY-HERE\"\nfname = r\"c:\\ragdoll_activation_request.xml\"\nlicence.activation_request_to_file(key, fname)\n
Step 2 - Email Request
Send this file to licencing@ragdolldynamics.com. We'll abrakadabra this file before you can say Taumatawhakatangi\u00adhangakoauauotamatea\u00adturipukakapikimaunga\u00adhoronukupokaiwhen\u00aduakitanatahu.
Step 3 - Activate
Once you've got a response, activate your licence like this.
from ragdoll import licence\nfname = r\"c:\\ragdoll_activation_response.xml\"\nlicence.activate_from_file(fname)\n
Linux users, you'll know what to do about that Windows-like path.
Full documentation
The last release included a callback for synchronising the Import Options UI with the Maya selection. As a result, a bug slipped in which could - in rare cases - produce the following error messages in your Script Editor whenever you changed selection.
../ragdoll/vendor/qargparse.py line 654: Internal C++ object (WidgetHoverFactory) already deleted. //\n
This has now been patched up, but do shout out if this or anything like it happens to you!
Thanks to Rafael Villar for finding this bug!
"},{"location":"releases/2021.04.23/#low-dpi-cosmetics","title":"Low-DPI Cosmetics","text":"The Import Options UI didn't quite live up to the hype at 720p and 1080p, now it does!
Whenever you make a Guide control (now called Soft Pin
) you are technically creating a constraint between a rigid and the world. That's what makes it worldspace.
Until now, constraints assumed the world didn't move. But you z-up folks out there know that, sometimes, it does! Ragdoll is now OK with that.
Before
After
Thanks to Jason Snyman for finding this bug!
"},{"location":"releases/2021.04.23/#tree-multipliers","title":"Tree Multipliers","text":"There was a minor bug with multipliers for any chain branching off of another chain (e.g. an arm from a spine) which caused the default multiplier to not correctly affect every link in those chains.
This has now been fixed!
"},{"location":"releases/2021.04.23/#known-issues","title":"Known Issues","text":"At the time of this release, these are the known issues that will be addressed in a future release.
"},{"location":"releases/2021.04.23/#evaluation-graph-controllers","title":"Evaluation Graph Controllers","text":"If you use \"controllers\" in your rig, there is a possibility Ragdoll will be drawing things incorrectly.
This can be addressed by either not (1) using controllers, (2) disabling controllers in the evaluation or (3) awaiting a future update. The problem appears visual-only and should have no effect on the simulation itself.
"},{"location":"releases/2021.04.23/#scale-pivot","title":"Scale Pivot","text":"When you hold the D
key and move the pivot, there are 4 attributes being edited.
If scalePivot
and scalePivotTranslate
result in zero change to a nodes position (the default) then all is well. But, if you edit these independently then that will in turn affect the final position of the node, in which case Ragdoll will struggle to simulate it.
I've narrowed down a particularly annoying behavior (likely a bug) in Maya that can affect users of auto-key and Ragdoll.
This will be fixed in a future release, and if anyone knows of any workaround please let me know!
"},{"location":"releases/2021.04.23/#joint-orient-non-linear-hierarchy","title":"Joint Orient & Non-linear Hierarchy","text":"When joints do not immediately follow each other, the rotate channel isn't entirely accurate.
Notice how there is a joint inbetween the two rigids? Avoid this edge case for now, or zero out the jointOrient
.
Solved
Solved in 2021.04.28
Guiding the translation
of an Active Rigid
with a Passive Rigid
is currently problematic and creates an unrealistic increase of acceleration.
The current workaround is to swap solvers under the Advanced tab of the scene.
"},{"location":"releases/2021.04.28/","title":"Solver Upgrade","text":"This release introduces more robustness, in exchange for changes to the default values for any Stiffness
and Damping
parameters.
The solver has been upgraded for more accuracy and stability. Unfortunately, this changes the default values Stiffness
and Damping
attributes, which may require changes in your scene.
ATTENTION: Backwards Incompatibility
Ragdoll takes backwards compatibility very seriously. At no point should a scene you have created break because of an update. This however is an exception to that rule, one that I expect never to happen again.
"},{"location":"releases/2021.04.28/#what-has-changed","title":"What has changed?","text":"Stiffness
and Damping
need higher values.
So far, we've used the Iterations
value on the solver to control how strong our constraints could be. As it happens, this isn't right. Iterations shouldn't control strength, it should only control how close the solution is to the true analytical solution.
Iterations
optionally bringing it closer to the true solution.In practice, not much has changed. You should still increase stiffness/damping when relevant, and still increase Iterations
if you find the values aren't being respected.
Stiffness
by 3-10xDamping
by 3-10xThat is, if Stiffness
was previously 1'000, make it 10'000.
Exceptions
Projected Gauss-Seidel
(Advanced) remains unchanged.It's not an exact science, in some cases you only need 3x, like in this case here.
Where the Yellow
line is from the previous version at 1'000 stiffness and 100 damping, the Blue
line has 3'000 stiffnes and 300 damping.
The previous version was subtly faulty, so this was inevitable. In practice however, under a very particular - but useful - circumstance the solver would struggle to obey.
Circumstance
Active Rigid
Passive Rigid
On
Use Cases
Here was the result.
Notice how the active rigid does what the active rigid does, but is a little too excited? One workaround was to use \"Projected Gauss-Seidel\" in place of the default \"Temporal Gauss-Seidel\", however that solver isn't as accurate or fast.
You might be thinking..
Well that's an awefully specific case, when would I even hit that?
Which is when you realise..
This was previously only possible with Projected Gauss-Seidel which is less performant and less able to handle large networks of constraints like a full ragdoll.
Result
This behavior was due to a subtle bug in how constraints were solved, a deeply rooted bug that once sorted out was what caused this change to the overall behavior of Stiffness
and Damping
values.
In this release, the bug has been squashed and muscles and props now follow their passive counterpart much more accurately and without surprises.
"},{"location":"releases/2021.04.28/#frameskip-protection","title":"Frameskip Protection","text":"The simulation is like a train running on a train track. It absolute must not miss a stop, else it can't realistically figure how how to get to the subsequent stop.
Allow me to demonstrate.
Notice how everything falls apart when skipping just a handful of frames? It's trying to catch up, but the time difference is just too great to produce accurate values.
This release adds support for pausing the solver whenever a frame is skipped, meaning you either get a (A) good solve or (B) a patient solver, awaiting your return.
The behavior can be disabled in the Preferences.
"},{"location":"releases/2021.04.28/#why-should-i-care","title":"Why should I care?","text":"Consider your everyday situation of adding dynamics to a tail.
Whenever a frame is skipped, the result is garbage. This can get even more extreme during more extreme movements. But, what's worse, this garbage is expensive! It's still simulating, and trying to solve these skipped frames is more expensive than non-skipped frames. That's a bad deal.
Here what happens with frameskip protection.
See how it just stays put? It'll remember the last simulated frame, awaiting your return.
"},{"location":"releases/2021.04.28/#clear-initial-state","title":"Clear Initial State","text":"Setting the initial state can be used to relax a physics character or scene.
But once relaxed, you had no way to returning to its original creation state, until now!
Thanks to Jason Snyman for this suggestion!
"},{"location":"releases/2021.04.28/#passive-visualisation","title":"Passive Visualisation","text":"Rigids will now turn gray when made passive, making it easier to understand what's going on visually.
"},{"location":"releases/2021.04.28/#start-frame-explosion","title":"Start Frame Explosion","text":"In a specific and rare circumstance, a passive rigid body could appear to have velocity on the start frame.
Notice here how animation starts immediately from the start frame, giving it an upwards velocity? The active rigids connected to the root on the other hand gets an even stronger velocity, for some reason.
If we move the animation to just one frame after the start frame, all is well.
A subtle bug, having to do with the rigid body being created on the second frame of the simulation, which in this case had a position the was different from the start frame. However! The animation started at the start frame, so the velocity got inherited from there instead. Yes, it's complicated. :)
And is now fixed!
"},{"location":"releases/2021.04.28/#negative-scale","title":"Negative Scale","text":"Ragdoll has supported scale, but negative scale has been unreliable. This release extends this support to negative scale used to mirror controls and behavior across a rig.
Before
This whole arm has a negative scale in the X-axis, from when it was mirrored across from the other side. Notice here how it look like the arm is about to move forwards, and instead move backwards.
After
This has now been fixed.
It also means you can flip entire performances with a little more ease. :)
"},{"location":"releases/2021.04.28/#caveat","title":"Caveat","text":"Avoid negative scale on the control you are animating.
You are still better off not having any negative scales in your rig, as there is still at least one special case I found that might jump up and bite you.
And that is if the animated control itself has negative local scale.
Typically, one or more of the parents have negative scale, so as to mirror a whole hierarchy of controls. And that is \u2714\ufe0f. But if the control you are animating also have negative scale, you might experience this.
Notice how on rewind, it twitches at the start of playback every other time? That's because it cannot tell the whether the control has negative scale or whether it is rotated 180 degrees.
This will be addressed in a future release.
"},{"location":"releases/2021.04.28/#rotate-order","title":"Rotate Order","text":"The animation constraint is what translates your keyframes into physics and with the introduction of support for Rotate Order in the previous few releases it has been possible for Ragdoll to output rotations onto any control with a custom rotate order.
This release now includes support for input of custom rotate order into the simulation.
Before
Notice how changing the rotate order should have changed the axis around which the Y-animation was happening, but didn't?
After
Now it does!
"},{"location":"releases/2021.04.28/#draw-shaded","title":"Draw Shaded","text":"The previous release revamped the rendering system in Ragdoll, but left out a the convenience attribute to disable shading when rigid bodies were used alongside animation controls.
Before AfterManual Override
The behavior can be manually adjusted to taste via the Attribute Editor.
"},{"location":"releases/2021.05.10/","title":"Mimic","text":"Highlight for this release is Mimic!
Some awesome simulations, courtesy of Jason Snyman, a.k.a. The Wizard. xD
Facial Rigging
Move lips, pull muscles. Collides with the teeth too!
Ragdolls have feelings too
Zilla is nothing with Kong, Kong is nothing without Zilla.
Wreck-it Zilla
Old recovered footage from the 60s!
Wreck-it Warm-up
Ever wondered how Zilla prepares for world domination?
"},{"location":"releases/2021.05.10/#mimic","title":"Mimic","text":"Transition in and out of physics, in both pose-space and world-space, with the newly added Mimic.
Options In-Depth
A step-by-step guide on what each option mean, there's quite a few of them!
Production Rig Example
A closer look at the Fire Wolf.
Courtesy of Truong CG Artist
"},{"location":"releases/2021.05.10/#multiple-mimic","title":"Multiple Mimic","text":"Mimic is a replica of your control hierarchy, and there's no limit to the number of replicas you can make. The final force applied to your rigid bodies is the sum of constraints applied.
"},{"location":"releases/2021.05.10/#order-independent","title":"Order Independent","text":"The controls in character rigs typically don't form a linear hierarchy. They're in some offset group, or in a different part altogether hanging together with constraints. That are animated, for space switching and what not.
Mimics don't mind.
"},{"location":"releases/2021.05.10/#partial-chain","title":"Partial Chain","text":"Sometimes you only want a little bit of control.
"},{"location":"releases/2021.05.10/#bake-simulation","title":"Bake Simulation","text":"You can now convert physics into keyframes with Bake Simulation
.
I did not edit this GIF, it really was that fast! :D
Tutorial
Bake Duration
It'll tell you how much time was spent baking too.
Bake Options
There are a few more options to choose from, with more to come.
"},{"location":"releases/2021.05.10/#import-additions","title":"Import Additions","text":"The import mechanic got an upgrade, you're now able to choose whether or not to re-apply changes to attributes and more finely import onto part of a larger chain hierarchy.
"},{"location":"releases/2021.05.10/#preserve-attributes","title":"Preserve Attributes","text":"You now have the option to preserve attributes when importing, for when you'd rather stick with the default values.
"},{"location":"releases/2021.05.10/#preserve-roots","title":"Preserve Roots","text":"Exported files now remember what their original roots were.
The original root of chains aren't important to Ragdoll. Whether the spine was a chain followed by the left and right arm, or whether the spine and left arm were part of one chain followed by the neck and right arm makes no difference.
Consider these two characters.
Notice how in the front character, one chain starts at the hip and goes out into the arm, whereas in the back character the spine is a single chain as you may expect?
Regardless of how you authored it, to Ragdoll these characters are identical. Ragdoll doesn't bother with hierarchies, everything happens in worldspace. The hierarchy is between you and Maya.
However
What if you wanted to import just one of the roots? You can import only onto the selected controls, but you can't import part of a network of chains like a full ragdoll. It's either a complete character, or no character at all.
In the case of the foreground character, you could import the screen-left arm, but not the screen-right. Not without importing the whole spine.
This release preserves the original root, such that you can isolate an import onto the same chain you originally authored.
"},{"location":"releases/2021.05.10/#sleep","title":"Sleep","text":"It is now possible to reap additional performance benefits in situations where one or more rigids remain immobile for a given number of frames.
The behavior can be tuned via two attributes on each rdRigid
node.
Wake Counter
How many frames of inactivity before I fall asleep? Sleep Threshold
How low of a force should be applied before I start counting? In practice, you'll likely only want to tweak the Wake Counter to some reasonable value like 5 or 20 frames of immobility. The default value of 0 means they'll never fall asleep. Like a proper insomniac or new parent.
Caveat
Currently, the wake counter is not reset when you rewind, so it's possible to have them fall asleep on frame 20, rewind to frame 19 and have the counter reset and keep them awake past frame 20. It's unlikely to affect you, and will be addressed in a later release.
"},{"location":"releases/2021.05.10/#textures","title":"Textures","text":"As you author your ragdolls, the distribution of mass can play a big role. But it can be tricky to balance something you cannot see, smell or touch.
With this release, you're able to see (but not smell, I promise) the masses in each rigid using the handy new Texture
attribute and when your viewport is set to Textured mode (the 6
key on your keyboard).
Thanks to Jason Snyman for the idea!
Normalised Distribution
Notice how the colors even out to always give you pure white for the maximum weight in any of the rigids in the scene they are part of, and approaching black for anything less. No need to manually specify min/max values!
Friction and Restitution
These can be visualised too.
Maya 2018 Caveat
In Maya 2018, consolidation is disabled to facilitate this shader. It shouldn't affect anything of value, you probably don't even know what it is. But if you'd rather it didn't do that, untick the \"Maya 2018 Consolidate World Fix\" in the Ragdoll Preferences and reload the plug-in or restart Maya.
"},{"location":"releases/2021.05.10/#vertex-limit","title":"Vertex Limit","text":"Meshes are the slowest to compute and have an upper-limit of 256 vertices. You can now lower this limit for meshes that would normally result in 256 for greater performance.
"},{"location":"releases/2021.05.10/#collide-off","title":"Collide Off","text":"Rigids have always been able to ignore contacts with Collide: Off
The problem here is subtle, but has been present since the beginning of Ragdoll. It mostly makes itself known once there is a constraint between a rigid with Collide: On
and a rigid with Collide: Off
.
Notice how with Collide: Off
the upper part of the \"creature\" is more wobbly? As if the effect of the constraint has somehow dimished? That's not right. Unless there are contacts involved, disabling them shouldn't have an effect on the simulation.
With this release, it behaves as you would expect.
"},{"location":"releases/2021.05.10/#quality-of-life","title":"Quality of Life","text":"A number of improvements were made to make working with Ragdoll more pleasant!
"},{"location":"releases/2021.05.10/#translate-limit-rendering","title":"Translate Limit Rendering","text":"The translate limit is making an appearance!
This should make it just a tiny bit easier to work with, now that it's clear which axes are actually free. Letting you see whether they are constrained in 3D, 2D or 1D. All the D's!
Edit Limit
Using the same method as editing rotate limits, they can be rotated (and moved!).
Soft Limit
Like rotate limits, these can also be made soft!
"},{"location":"releases/2021.05.10/#constraint-rendering","title":"Constraint Rendering","text":"Have you ever noticed constraints looking real nervous?
You now needn't lose any more sleep over it, as they now render flicker-free. :D
Before
After
"},{"location":"releases/2021.05.10/#constraint-interactivity","title":"Constraint Interactivity","text":"You may also have noticed how when you edit one of two constrained rigids, how things get all whack?
Before
Best case you'd at least get constraints to stick together as you make changes.
After
And oh golly how ugly it was. No more! Yay! \ud83e\udd29
"},{"location":"releases/2021.05.10/#constraint-colors","title":"Constraint Colors","text":"When rigids have multiple constraints, it can be hard to tell them apart visually given they all share the same red/green colors. And if you're amongst the colorblinds things are even more challenging.
This release enables you to give some extra flare to your constriants, by editing the Twist
(X-axis) and Swing
(YZ-axes).
"},{"location":"releases/2021.05.10/#trajectory-on-selected","title":"Trajectory on Selected","text":"
There's now an option to isolate trajectories to selected rigids only.
"},{"location":"releases/2021.05.10/#less-explosive","title":"Less Explosive","text":"Overlaps are resolved by moving one or both rigids away from each other. The force with which that resolution happens could be infinite, resulting in what looks like explosions.
This release addresses this, by compromising between realism and aesthetics.
Before
After
Editable
The behavior can be restored or tweaked further by adjusting the Max Depenetration Velocity
attribute of the rigid.
There are 3 ways to load Ragdoll.
cmds.loadPlugin(\"ragdoll\")
When Ragdoll is loaded, it appends to a special environment variable Maya uses to look for icons in the Outliner called XBMLANGPATH
. Because of course that's what it is called, why do you have that look on your face?
Anyway, as it happens, if the Outliner was given a chance to draw icons before Ragdoll added this variable then it'd go ahead and draw a generic, non-pleasant-looking icon like this.
This release fixes that. \ud83e\udd70
Before After "},{"location":"releases/2021.05.10/#upgrade-on-file-open","title":"Upgrade on File Open","text":"Like above, there was another issue when loading the plug-in alonside opening of scenes, which had to do with upgrades.
Normally, what happens is this.
But since the plug-in is loaded during scene open, Ragdoll wasn't given a chance to check it first.
This has now been fixed.
Install on Idle
This changes the initialisation mechanism somewhat, if this causes any issues for you, set the RAGDOLL_INSTALL_ON_IDLE
environment variable to revert to the old behavior. It won't be able to upgrade on scene open unless you load the plug-in first, but that's the only thing you're missing out on.
Our precious icons now appear in the node editor too!
Before After "},{"location":"releases/2021.05.10/#passive-initial-state","title":"Passive Initial State","text":"Here's a subtle one.
In previous releases, the initial state is automatically updated on the 2nd frame of the simulation to wherever a rigid was on the 1st frame. Even if you modified the position interactively with manipulators, or via curves in the Graph Editor, or the channel box, and so on.
It even updated when a rigid was affected by passive input, like a Hard Pin, which meant you lost track of the original initial state whenever you disabled the hard pin.
This release addresses that by only automatically updating the initial state if a rigid is active on the start frame.
Notice how I can disable Hard Pin and have the rigids return to where they were before they got pinnned? It's what you would expect.
"},{"location":"releases/2021.05.10/#passive-to-active-and-back-again","title":"Passive to Active and Back Again","text":"Ragdoll tries to clean up after itself by removing constraints no longer in use. When a rigid is passive, it can no longer be affected by constraints, so those constraints are deleted.
However, active rigids can still be influenced by a passive rigid, and Ragdoll was a little too aggressive in removing those constraints too.
This release fixes that.
"},{"location":"releases/2021.05.10/#undo-and-attribute-order","title":"Undo and Attribute Order","text":"Whenever you delete physics and undo, the order in which proxy attributes would appear on your controllers would go all whack.
This is basic-Maya, it loves doing this. But now love goes both ways, and we are much happier. \ud83e\udd70
Before
After
"},{"location":"releases/2021.05.10/#control-rendering","title":"Control Rendering","text":"Controls give you a preview of what the rigid they control look like.
These are special in that Maya doesn't actually need them. Ragdoll doesn't actually need them either. They are exclusively for-your-eyes-only.
And due to Maya only updating things it absolutely needs to whenever rendering anything, these won't get updated unless Ragdoll explicitly tells them to. So far, they've been told to update whenever the selection changed, which can end up looking bad.
This has now been improved!
Before
After
"},{"location":"releases/2021.05.10/#fixed-startup-crash","title":"Fixed Startup Crash","text":"On plug-in load, Ragdoll would check your licence. Under rare circumstances (2 out of 100 users reported it happening) this would be enough to put Maya under, instantly and without warning.
This has now been fixed.
"},{"location":"releases/2021.05.10/#fixed-initial-state","title":"Fixed Initial State","text":"An error was introduced between 2021.04.23 and 2021.04.28 leading to an issue with updating the initial pose via the Channel Box or Graph Editor.
This got addressed on the same day and released unofficially as 2021.04.30, and is now officially part of the latest version.
Thanks to Niels Dervieux for reporting this bug!
Before
After
"},{"location":"releases/2021.05.10/#fixed-qt","title":"Fixed Qt","text":"Whenever you clicked Import Physics
in the Import Physics Option Window, it would needlessly shout at you.
# RuntimeError: Internal C++ object (WidgetHoverFactory) already deleted.\n
No more!
"},{"location":"releases/2021.05.10/#scene-drawing-in-2019","title":"Scene Drawing in 2019","text":"Maya was misbehaving in 2018-2019, refused to draw the scene visualisation correctly. No longer!
Before
After
"},{"location":"releases/2021.05.17/","title":"Floating Licence Support","text":"Highlight for this release is support for Floating Licences!
So far, Ragdoll has been activated on a per-machine basis. It's been node-locked.
But in many cases, you are a studio with a team of artists using Ragdoll. That's when it becomes impractical for each artist to manage their own licences, or for licences to become associated with a single machine.
Floating licences solve this problem. With it, you register a fixed amount of licences with a server somewhere on your network, and then have Maya \"lease\" licences off of it. For example, with 10 floating licences, 10 artists can use Ragdoll in parallel. On Maya shutdown or plug-in unload, the lease is \"dropped\" meaning it can be picked up by another artist, on some other machine.
Heads-up SysAdmins
On Windows, the floating licence mechanism is currently a dedicated DLL.
This will be merged into the plug-in like on Linux in a future release.
See also
The Mimic introduced in the last release generated a clean hierarchy of transforms.
This release introduced \"mimik\", which is a joint hierarchy suitable for skinning and IK. It's got a proper Joint Orient too, irregardless of what the original animation controls looked like.
They're great if IK is what you want, but they do make the overall hierarchy more complex and introduce an additional jointOrient
offset onto the joints themselves. For that reason, Transform
is the default node type and is currently the most simple mimic to work with.
Room for Improvement
There's still room for improvement, the user attributes remain on the blue control nodes rather than the joints themselves for now. This will be addressed in a future release.
"},{"location":"releases/2021.05.17/#quality-of-life","title":"Quality of Life","text":"More quality, less problems. Hacuna matata!
"},{"location":"releases/2021.05.17/#constraint-outliner-style","title":"Constraint Outliner Style","text":"You can now choose how constraints appear in the outliner.
Style ResultnConstraint
At the root of the outliner, as its own transform Maya Constraint
As a child transform Ragdoll
As a shape The rRigid
node appears as a shape of any node you apply physics to, and normally constraints appear alongside them. But normal Maya constraints do not, and neither does the constraints you get with nCloth and nHair. So which do you prefer?
Ragdoll Style
As a shape, alongside the rRigid
node.
Maya Constraint Style
As a child, similar to native Maya constraints.
nConstraint Style
As a new transform at the root of the scene, similar to nCloth and nHair constraints. Group them, hide them; if you can imagine it, you can achieve it!
Subjective
Whichever you prefer, it has no effect on the simulation and is strictly related to the Outliner only. They can also be re-parented after being created, it really doesn't matter where they are. So organise away!
"},{"location":"releases/2021.05.17/#constraint-scale-rendering","title":"Constraint Scale Rendering","text":"The last release made constraints render poorly if the node they were parented to was scaled. The simulation was still fine, but you couldn't see what you were doing.
Before
After
"},{"location":"releases/2021.05.17/#constraint-maintain-offset","title":"Constraint Maintain Offset","text":"Constraints typically maintain their offset on creation, such that rigids do not abruptly snap together on simulation start.
But it's optional, and if you don't maintain offset then they would snap together. With this release, the default behavior is now soft as opposed to infinitely strong.
"},{"location":"releases/2021.05.17/#installer-improvements","title":"Installer Improvements","text":"On Windows, the MSI installer can now be used to install multiple versions of Ragdoll simultaneously, with a dedicated uninstall option each.
This should also help clear out issues with upgrading using the MSI, which has been problematic in the past since the installer really didn't like overwriting files.
On all platforms, multiple Maya module files now co-exist, which means that if you want to disable or switch versions you can do that by removing the offending version - rather than editing the text file itself like in previous versions of Ragdoll.
"},{"location":"releases/2021.05.17/#rigid-scale-rendering","title":"Rigid Scale Rendering","text":"Rendering of non-uniformly scaled rigid bodies has been improved and now respond interactively to scale changes. Notice in particular how scale is translated into sphere radius only along the X-axis. For non-uniform scale of a sphere, switch to Shape Type = Mesh
.
Before
After
"},{"location":"releases/2021.05.17/#scene-scale","title":"Scene Scale","text":"The default distance unit in Maya is centimeters. Meaning Translate X=5.0
means \"5 centimeters along the X axis\". And in some cases, characters get modeled by this unit too, to an average height of 160-190cm.
But often this unit is ignored and now Ragdoll can too.
Default Value
Ragdoll has assumed a scene scale of 0.1 so far, meaning 10 centimeters meant 1 meter. That's the typical scale of most rigs, some having smaller - like the Fire Wolf at 0.01 - and some larger - like a real-world scale of 1.0.
This value used to be reflected in Gravity Y
as 98.2
meaning 98.2 cm/s2
. Which means that an object falling for 1 second would reach a velocity of 98.2 cm/s and keep increasing by the amount each second until reaching terminal velocity.
It is now reflected in Scene Scale instead as 0.1. For a real-world scale, simply set this value to 1.0 and leave gravity unchanged.
"},{"location":"releases/2021.05.17/#quick-select","title":"Quick Select","text":"The quick-select commands now feature an option to ignore whatever is currently selected.
rdRigid
rdRigid
Filtering grows more useful as your scenes grow large. When you have e.g. 2 characters and want to edit all constraints in one of them, then filtering is what you're looking for.
"},{"location":"releases/2021.05.17/#bulk-edits","title":"Bulk Edits","text":"The Maya Channel Box is great for editing multiple nodes at once.
Select two or more nodes, change an attribute in the Channel Box, and the change is applied to each of the selected nodes at once. Win!
But what about attributes that aren't in the Channel Box?
Here are 3 ways in which you can bulk-edit a class of Ragdoll nodes in one-go. In each case, I'm using the Ragdoll -> Select
menu item to bulk-select all rigid bodies in the scene.
Also known as \"the slow way\". Simply edit each attribute, one at a time. Like watching paint dry. It's slow.
"},{"location":"releases/2021.05.17/#2-channel-editor","title":"2. Channel Editor","text":"All attributes found in the Attribute Editor are also available in the Channel Editor. The most-commonly used ones are already exposed, but you can expose more.
"},{"location":"releases/2021.05.17/#3-attribute-spreadsheet","title":"3. Attribute Spreadsheet","text":"For total control, irregardless of the Channel Box and with searchability amongst attributes, you can also try the lesser-known Attribute Spreadsheet.
"},{"location":"releases/2021.06.07/","title":"Minor Bugfixes","text":"Highlight for this release is minor bugfixes, in preparation for launch.
It's been almost a month, and this is all you have to show for it?
Yes! The past few weeks has been \"Less C++, more HTML\". The website is getting an overhaul, along with documentation and tutorials. Stay tuned, and for early access users: keep on reporting any issues you encounter!
"},{"location":"releases/2021.06.07/#broken-scale","title":"Broken Scale","text":"Sometimes, when animation controls has been scaled the default values and drawing of rigids and constraints did not look right. This has now been fixed.
Before
As you can see, the rigids are far away from their control, and the constraint visualisation is all whack. These are exactly 10x wrong, which is how scaled the top-level group is.
After
Thanks to @mariia for reporting this issue!
"},{"location":"releases/2021.06.07/#zero-length-spheres","title":"Zero Length Spheres","text":"When making a chain for a tail, there was a specific circumstance that could trip-up Ragdoll when trying to figure out how large to make the tip of that tail, resulting in a rigid body of zero length and width.
These don't simulate well and didn't communicate that it had happened. This has now been fixed!
Thanks to Amedeo Beretta for reporting this issue!
"},{"location":"releases/2021.06.07/#crash-on-playback","title":"Crash on Playback","text":"The previous release intoduced interactive re-generation of rigid body meshes when scaling. It was really neat! Unfortunately, the Maya feature used to support this feature had a critical fault in Maya 2020.
Leaving mention of the culprit here should anyone surf the interwebs and arrive to at similar fate.
MDagMessage::addWorldMatrixModifiedCallback()
As such, in order to scale a rigid body of Shape Type = Mesh
you must trigger a rebuild. The simplest way of doing that at the time of this writing is to jiggle the vertex limit.
Other options include:
rdRigid
nodeWhen referencing another file, the nodes are \"locked\". Meaning they have some restrictions on what you can do with them, like not being able to delete them.
Ragdoll would happily attempt to delete these but not tell you that it had failed. It simply isn't allowed to do it.
This release communicates this to you.
It also applies to deletion happening indirectly, such that when you want physics removed after baking.
"},{"location":"releases/2021.06.10/","title":"Telemetry","text":"Highlight for this release is telemetry.
Ragdoll is now able to gather usage statistics so that I can strip menu items that aren't used, pay more attention to the ones that are and get an overall understanding of how Ragdoll performs out in the wild.
"},{"location":"releases/2021.06.10/#faq","title":"FAQ","text":"What is telemetry?
It's the term coined for gathering anonymous usage statistics and send it to a product vendor for a greater understanding of how their product is used.
Do I need it?
No, this won't help you. Not directly. But it will help you and others indirectly, in that it allows me to spend more time on features you use, and less time on those you don't.
What does it collect?
Mostly performance numbers, nothing personal. See Data below.
How is it collected?
Mostly through C++, but some of it through Python. You can read about exactly what it does in telemetry.py
What if I'm offline?
Then the file will still be written to your home directory, and you'd be welcome to email it at your own leisure to telemetry@ragdolldynamics.com
"},{"location":"releases/2021.06.10/#opt-in","title":"Opt-in","text":"It is currently opt-in while I work out the kinks, so if you're interested in helping out put this in your maya.env
or type it into your script editor before loading the plug-in.
Maya.env
RAGDOLL_TELEMETRY = Yes\n
Script Editor
os.environ[\"RAGDOLL_TELEMETRY\"] = \"Yes\"\n
"},{"location":"releases/2021.06.10/#data","title":"Data","text":"Data is gathered and stored in 2 places.
~/.ragdoll/telemetry_10-06-2021-100402.json
It is gathered and stored when Maya closes. Or more precisely, when the plug-in is unloaded.
Here's what the complete data currently looks like.
~/.ragdoll/telemetry_10-06-2021-100402
{\n \"maya\": {\n \"crashed\": false,\n \"version\": 20200200,\n \"errors\": 0,\n \"warnings\": 0\n },\n \"system\": {\n \"time\": \"10-06-2021, 10:04:39\",\n \"memory_cpu\": \"31010.8 MB\",\n \"machine\": \"AMD64\",\n \"memory_gpu\": \"24576 MB\",\n \"gpu\": \"GeForce RTX 3090/PCIe/SSE2\",\n \"os\": \"win32\",\n \"processor\": \"AMD64 Family 23 Model 49 Stepping 0, AuthenticAMD\",\n \"render_api\": \"OpenGL V.4.6\"\n },\n \"ragdoll\": {\n \"simulationTimeMax\": 1.2327,\n \"computeTimeMax\": 1.6763,\n \"setupTimeMin\": 0.301,\n \"computeTimeMin\": 0.7595,\n \"setupTimeMax\": 0.4756,\n \"simulationTimeMin\": 0.4697,\n \"rigidCountMax\": 15,\n \"constraintCountMax\": 16,\n \"version\": 20210606,\n \"computeTimeAvg\": 0.949111823737213,\n \"simulationTimeAvg\": 0.597494786145304,\n \"setupTimeAvg\": 0.25006875,\n \"rigidCountMin\": 15,\n \"constraintCountMin\": 16\n }\n}\n
This was generated from that throbbing heart simulation above.
There are currently 3 categories of data gathered.
\"maya\"
As you can see, it'll capture how many errors and warnings were emitted from the plug-in whilst the plug-in was loaded. It'll also include whether Maya crashed the last time Ragdoll was loaded. Ragdoll's goal is to keep crashes at 0.
\"system\"
It'll also include system information such that I know how restrained to keep Ragdoll, both in terms of memory and CPU power. If everyone's running on an integrated Intel chip, then Ragdoll simply wouldn't try to benefit from the GPU that much. These numbers also help put the next category into perspective.
\"ragdoll\"
The ragdoll
category is perhaps the most interesting, as it sheds light on how much you are willing to suffer haha! Ragdoll is a real-time solver and is designed to be operated without waiting. So if I see these numbers climb too high, I'll crank up the number of optimisations to bring them back down again. Simple!
There will be a publicly available website for this information - with graphs and charts - such that we can all witness just how fast Ragdoll is and get some perspective on the kind of workload it typically deals with. From this overview, development can then focus on exactly those.
"},{"location":"releases/2021.06.10/#fractional-start-time","title":"Fractional Start Time","text":"You wouldn't normally set your start time to 0.8
or 16.351
, but it can happen whether you like it or not if e.g. physics was made in one scene and later referenced into another with differing frame rates. Such as 24 fps in one, and 30 fps in another.
If that happened, then best case your simulation flickers on the first frame, worst case you're looking at a fatal crash.
Why?
In this illustration, you can see how the simulation (blue) progresses alongside time (red). As we reach just beyond a whole frame, such as 1.1, you'll notice how the simulation immediately fills in that whole frame; even though we haven't actually reached the end yet!
The result is a simulation that operates on incomplete information. Your animation at frame 1.1
is not where it is at frame 2
.
In this release, here's what happens instead.
Now we're only simulating once we've actually reached a whole frame step. Your animation has reached the full pose at that frame and that's what will be used to compute the simulation. As you would expect.
Does this mean I can playback in fractional frames?
Not yet, simulation happens on whole frames and won't output anything until the next whole frame. At a later date, fractional frames will be automatically interpolated, similar to when you bake a simulation and set keys to linear
.
This isn't typically useful for animation, but can help with motion blur during the rendering of fast-moving objects; especially spinning objects like propellers and wheels.
That said, you can achieve some pretty surreal effects with this. :D
Stay tuned for real-time interpolation, and do let me know if this is something you're interested in.
Thanks to Amedeo Beretta for spotting this issue!
"},{"location":"releases/2021.06.10/#suspend-on-bake","title":"Suspend on Bake","text":"Baking is fast and light with the default option for disabling the viewport as it runs, but should you also opt to delete physics once baking is complete you would find suspension to have no effect. :(
This was due to deletion of physics also suspending the viewport as it deletes things and - wanting to be helpful - went ahead and resumed rendering of the viewport before baking got a chance to get started.
This has now been fixed.
Speed!
0.51 seconds versus 0.13 seconds, a 4x speedup!
"},{"location":"releases/2021.06.10/#more-resilient-constraint-rendering","title":"More Resilient Constraint Rendering","text":"You are unlikely to end up with zero scaled things, but if you do you could also run into visual flicker like this.
Before
After
Not only is this gone, it's fast too. It is as fast as though the constraints were never visible to begin with, giving you another option for hiding them. Scaling them down. Hah!
"},{"location":"releases/2021.07.02/","title":"Quality of Life","text":"Highlight for this release is quality of life.
In preparation for the upcoming website, there are 4 new animations in progress. Here's just a taste. :)
"},{"location":"releases/2021.07.02/#replace-mesh","title":"Replace Mesh","text":"When you turn a mesh dynamic, the vertices are plugged into the rigid node.
mesh
nodes plug into rdRigid.inputMesh
nurbsCurve
nodes plug into rdRigid.inputCurve
nurbsSurface
nodes plug into rdRigid.inputSurface
But what if you wanted a different mesh? What if there was no mesh, such as for a joint or empty transform?
I give you, Replace Mesh
. \ud83d\udc4f
Here's a more practical example, of a dynamic joint being replaced with the mesh of a car wheel.
"},{"location":"releases/2021.07.02/#freeze-evaluation","title":"Freeze Evaluation","text":"Rigid bodies have an Enabled
state to exclude it from a simulation, but it will still partake in most evaluation and still cost precious CPU cycles.
In Maya 2016, an attribute was introduced for exclude nodes from Parallel Evaluation called .frozen
. Ragdoll now supports this attribute to a limited extent.
This operation is completely non-destructive and affects nothing but the nodes you select.
Important
The more you freeze, the more performance you gain, and that includes Maya's native nodes. So go ahead and freeze the controls as well.
Caveat
The optimisations are coming from deep within Maya and is mostly outside of our control. And it isn't perfect. How Maya chooses to evaluate nodes is sometimes a mystery, and sometimes even frozen nodes get included in evaluation. For the technically minded, you can read more about the attribute and behavior here.
Sometimes, you find yourself with rigid bodies that could run separately, in parallel. Either for performance, or because they could benefit from independent solver settings like iterations and substeps, or time scale and more.
Now you can extract rigid bodies from one scene into a new scene, akin to extracting polygons from one mesh into another.
Extract
Move one or more rigids out of one scene, and into another.
Move
Move one rigid between two scenes.
Merge
Collapse two or more scenes into the first-selected scene.
Constraints
For constraints to work, both rigids must be in the same scene and currently extracting only one rigid from a constrained pair would break the constraint. In a later version, the rigid will automatically become a Passive rigid in the extracted scene, such that it can still be constrained albeit indirectly.
This will enable you to extract parts of a simulation, like muscle and cloth, from an overall dynamic character without breaking anything.
"},{"location":"releases/2021.07.02/#ignore-contact-constraint","title":"Ignore Contact Constraint","text":"You can now select two rigids and say \"Hey, ignore each other, ok?\"
Technically, this is just a constraint but with both the Limit
and Guide
disabled, and Allow Overlap
kept enabled.
The Bake Simulation tool now allows you to bake either all or selected scenes.
"},{"location":"releases/2021.07.02/#multi-mesh-shapes","title":"Multi-mesh Shapes","text":"The rdRigid
node has an attribute called .inputMesh
which takes a normal Maya mesh, like a polyCube, and turns it into a volume suitable for simulation. It's also got a .inputCurve
and .inputSurface
attribute, to treat NURBS curves and surfaces in the same way.
Until now, only one of these could be connected at a time. Connecting to one when another was already connected would lead to undefined behavior. In this release, the behavior is defined! If you want two meshes, you can have'm!
"},{"location":"releases/2021.07.02/#edit-constraint-and-chain","title":"Edit Constraint and Chain","text":"When you make a chain, attributes from rigids and constraints are mapped to the original animation control as attributes. When you then want to edit the constraint pivot of any of those constraints, it would overwrite that connection so as to make it easier/possible to edit values directly from the locators that appear representing the pivots.
This no longer breaks your connections, at the expense of having to edit values on the original constraints instead. This will be addressed in a future release, once we get a proper manipulator in place instead of the makeshift Maya transform.
"},{"location":"releases/2021.07.02/#constraints-and-focus","title":"Constraints and Focus","text":"The F-key zooms and centers and object in the viewport. But trying that on constraints would have you flying through the cosmos until NaN
appears in your channel box.
Before
After
"},{"location":"releases/2021.07.02/#skinweight-painting","title":"Skinweight Painting","text":"Any joint with a shape causes the right-click menu to stop working. It's typical Maya, and has been the case for years.
Ragdoll nodes are mostly shapes of the control they drive, including joints. As a result, you weren't able to right-click on a dynamic joint to select its skinweights..
Before
After
"},{"location":"releases/2021.07.02/#referenced-physics","title":"Referenced Physics","text":"The previous releases tried adding any new physics added to a referenced physics scene, but was unable to! This release fixes that.
"},{"location":"releases/2021.07.02/#two-users-one-machine","title":"Two Users, One Machine","text":"When Ragdoll starts for the first time, a file is written into your temp-directory. The undo plug-in for cmdx
. The file is written using the permissions of the currently logged on user and cannot be touched by anyone else.
When another user logs in to the same machine, Ragdoll will attempt to overwrite this file but cannot! It doesn't have permission! The result is a limit of 1 user able to leverage Ragdoll per machine. And that's no good.
This release fixes that!
"},{"location":"releases/2021.07.02/#export-initialisation","title":"Export Initialisation","text":"If you author physics and immediately export, without playing back, the results could be incomplete. \ud83e\udd14 The reason is that Maya only evaluates what it has to, and until you actually run the simulation a lot of things are left unevaluated. To Ragdoll, it's as if they never existed in the first place.
This has now been fixed.
"},{"location":"releases/2021.07.02/#center-of-mass-visualisation","title":"Center Of Mass Visualisation","text":"With the recent upgrade and performance improvements to rendering, a small but necessary visualisation feature of the rigid bodies was the COM or center of mass.
This has now been restored!
"},{"location":"releases/2021.07.02/#something-went-wrong","title":"Something Went Wrong","text":"The order in which Maya evaluates Ragdoll nodes is important, and whenever it tries doing that in some unexpected way it'll tell you.
# Warning: ragdoll._on_cycle() - Something is not right!\n
The reason it happens is difficult to say. The evaluation order is something Maya dynamically generates on the first frame of your animation, and it's based on the way nodes are connected. Cycles are the most common culprit. Ragdoll cannot stand cycles.
But another reason was discovered in this release which was that when you constrain A to B but then delete B, A is left constrained to a broken constraint. This could throw off evaluation, and break the scene.
This particular situation has now been fixed!
"},{"location":"releases/2021.07.02/#more-accurate-auto-mass","title":"More Accurate Auto Mass","text":"Rigid bodies have an option to have their masses automatically computed from their initial shape. This value was 10,000x wrong, and is now roughly 1-2x wrong. It is 100% accurate for boxes, but diverges from there as it does not take into account the negative volume within its bounding box.
Choose Density
Be like water, my friend.
Responds to Scale
The computed mass will respect the size of the object, and the overall scene scale.
Important
Remember that large mass differences between two rigids that interact can result in instabilities.
In the real world, an object with the density of air under a much heavier object with the density of water would crumble. However, it cannot do that here. Instead, it will bounce around and act unnaturally.
The recommended max difference is 10x. E.g. one rigid can weigh 10 kg, whereas the other can weigh 100 kg. That's at the edge of what the solver (and the real-world) considers manageable.
"},{"location":"releases/2021.07.15/","title":"Launch Tweaks","text":"Highlight for this release is improved Rotate Pivot support.
In a previous release support for the .rotatePivot
attribute was added. But it was only partial. It only applied to solo rigid bodies, like the one in that example.
Once rigids form a hierarchy, things get more complex, but also more realistic. A lot of character rigs make use of it, some even going as far as to leave NURBS controls at the origin, moving the CVs to where the character is and compensating with the .rotatePivot
to make it appear in the right place.
This didn't gel with Ragdoll, who uses the center of a control to determine how to draw chains.
What is this \"rotate pivot\"?
Just so we're all on the same page, here's me creating a control by moving the rotate pivot and CVs rather than translating/rotating the node.
Notice how I'm not actually moving it to the hip, but rather hold the D
-key and move the rotate pivot. Then I'm moving the CVs to where the rotate pivot is to make it both act and appear at the hip.
Why would anyone do this?
Hah! Yes that was my thought too!
As you can see, to make this work you really have to work at it. My guess is this isn't something riggers do by hand but rather via scripting. Done that way, you don't really notice how odd it is.
Either way, there are rigs out there that works like this and it shouldn't limit your use of Ragdoll.
Next, I'll repeat this process for each of my controls.
Pay special attention to how all of my controls are still technically at the origin. Their rotate/translate channels are all zero.
Let's have a look at what the current version of Ragdoll does in this situation.
Before
Notice how nothing appears! That's because Ragdoll tried figuring out where to generate capsules and how large to make them based on the center of each control. But! The controls are all at the origin. They lie there, right on top of each other, with zero distance from each other.
So Ragdoll does what it thinks you want. It generates a series of rigid bodies at the origin with 0 size. When what you really meant was for it to use the center plus this \"rotate pivot\".
After
This release recognises this, here's what it looks like now.
Win!
"},{"location":"releases/2021.07.15/#re-scale","title":"Re-scale","text":"Sometimes you're experimenting and aren't quite sure that the scale of an object is what you'd like it to be until you see it in action.
Currently, whenever you make something dynamic it'll use the current scale of the NURBS curve or mesh as part of the collision geometry. But! If you change the size after making it dynamic, Ragdoll won't know about that.
This was especially damning for geometry that needed to be tesselated, namely the Mesh
shape type. The most convenient way of refreshing that was to edit the .shapeVertexLimit
attribute, forcing a re-tesselation.
That's because Ragdoll cannot know when you resize something. You have to explicitly say you did. That is, until now.
Caveat
It still isn't perfect.
Ragdoll still cannot know when you scale the object. Instead, it queries the current scale on the 1st frame of the simulation, which means it won't actually recognise a new scale until the 2nd playthrough.
That's because once the simulation starts, the initial state is automatically set. Only then can it know that scale has changed, but by then it is too late! Simulation has already begun. So instead, the change is picked up on the next playthrough.
Of course manually setting the initial state (via the Rigging sub-menu) or re-opening the scene will have the same effect so you really shouldn't have to struggle with this in practice.
"},{"location":"releases/2021.07.15/#scene-tolerance","title":"Scene Tolerance","text":"Ragdoll assumes you're working with human characters in centimeters, meaning a value of 170 means 170 cm and 0.1 cm is a small distance. If that's true, then you typically won't have to worry about \"tolerances\".
But if you're characters are 17,000 units tall or 0.017 units short odd things start to happen.
Notice how it initially slides around for no apparent reason? In this case, the cube is much smaller than Ragdoll expects and we can address this by decreasing the global scene scale.
Likewise, for very large cubes you will notice similar artifacts. For that, you'd increase the scale.
Currently, there exists a Scene Scale
on the solver node, which is saved in your scene, and a Scene Scale
in the global preferences which is not. The intention is for global scene scale to rarely change, to change alongside a studio's or project's convention, whereas the solver scene scale is more flexible.
The default value is 10.0
but it's possible smaller values such as 0.1
is better suited. It's also possible they both belong under global preferences. Give this a try and let me know what you think.
There are two kinds of limits; twist and swing.
Twist is great for hinge-like limits, like knees and elbows, whereas swing is great for more complex 2D limits like shoulders and hips. The current position of a rigid body in terms of swing and twist have always been drawn as a green/red line, but it could sometimes be hard to know which was which. If the red line starts out in the twist limit, then Ragdoll will promptly snap it back into the swing limit.
This release colors the twist and swing shapes using the same colors as the current twist and swing axes, making it just a tad easier to see which belongs where.
Before
After
Also notice how the twist axis is now confined into the twist shape itself, making it just a bit more clear how close it is to colliding with that limit.
Here's a more complete example of a full set of constraints.
"},{"location":"releases/2021.07.15/#unique-names","title":"Unique Names","text":"Prior to a recent release, all new nodes generated by Ragdoll was given a unique name. That really shouldn't matter to Maya, as nodes are distinguished by their parent. For the most part. But sometimes not!
For example, cycle warnings produce a message only containing the name of the node itself, not its hierarchy. So you wouldn't be able to tell which of the many rigid nodes were at the root of any cycle by merely looking at this message. And don't get me started on the connection editor. It's perfectly capable of making and breaking connections, but refuses to auto-fill the currently selected nodes if they happen to have the same name as any other node in the scene!
In any case, this has now been fixed and all nodes are once again unique. Automated tests have also been put in place to prevent this slip-up from happening again; but do let me know if you find any duplicates as Ragdoll generates a lot of nodes, and it's possible one may have yet slipped through!
"},{"location":"releases/2021.07.15/#passive-constraints","title":"Passive Constraints","text":"Select two rigid to create a constraint.
But if one of those rigids was passive, or even animated between passive and active, and had a different passive animation than the initial state, and your constraint could end up like this.
Before
Especially notice how the passive pose differs from the initial active pose. The active pose was used to compute how to draw the constraint, whereas the passive pose was used during the simulation.
After
This has now been fixed!
"},{"location":"releases/2021.07.15/#single-joint-shapes","title":"Single Joint Shapes","text":"In the rare case of turning solo-joints dynamic, you could end up with results like this.
Before
After
This has now been fixed!
"},{"location":"releases/2021.07.15/#bake-static-rigids","title":"Bake Static Rigids","text":"There was a bug when baking simulation for any rigid what started out passive, e.g. it was hard pinned, but animated active. The Bake Simulation command would mistake these later-simulated rigids as passive, and simply not bake them.
This has now been fixed!
"},{"location":"releases/2021.07.27/","title":"Launch","text":"Highlight for this release is the Launch of 1.0!
Out with the old, in with the new. As they say! Ragdoll is finally here!
Read Announcement Try it "},{"location":"releases/2021.07.27/#evolution","title":"Evolution","text":"For the fun of it, here's a look at how the website has evolved since day 0.
"},{"location":"releases/2021.07.27/#september-2020","title":"September 2020","text":"Soil was fresh, seeds planted.
"},{"location":"releases/2021.07.27/#january-2021","title":"January 2021","text":"Flowers were blossoming, sun was shining.
"},{"location":"releases/2021.07.27/#july-2021","title":"July 2021","text":"Fruits were ripe, table is set.
"},{"location":"releases/2021.08.06/","title":"New Documentation","text":"Highlight for this release is new documentation!
Put together this example of animating a Pinocchio-like character recently, which is trending on LinkedIn. :D
"},{"location":"releases/2021.08.06/#linkedin","title":"LinkedIn","text":"The Ragdoll page on LinkedIn is getting some more attention since launch - keep refreshing that page if you'd like to stay up to date with the latest and greatest, including new version releases and cool simulations to inspire and delight.
3,000% haha, let's see if we can keep that up!
"},{"location":"releases/2021.08.06/#menu-documentation","title":"Menu Documentation","text":"Items from the Ragdoll menu are getting some spotlight in the new Documentation
section in the learning material!
In it, you'll find basic tutorials, basic information and tips and tricks on how to use each item, such as the Active Rigid. Along with supplementary information such as Debugging Tips and details about the Cycle Protection.
\ud83d\udc48 See new navigation to the left
"},{"location":"releases/2021.08.06/#non-commercial-telemetry","title":"Non-Commercial Telemetry","text":"Opt-in telemetry was added to Ragdoll a few releases ago via the environment variable RAGDOLL_TELEMETRY
. This behavior is now default for Trial and Personal licences of Ragdoll, and remains opt-in for Complete and Unlimited licences.
The following bugs were harmed in the making of this release.
"},{"location":"releases/2021.08.06/#add-to-referenced-scene","title":"Add to Referenced Scene","text":"A minor but critical bug was discovered whereby you couldn't add a new rigid body to a referenced Ragdoll scene. It had to do with Ragdoll needing to know which scenes are present whenever a new rigid is made, something it keeps track of by listening to an event for \"Maya Open Scene\". But this wasn't triggered for \"Reference Scene\" which led to some confusion.
This has now been fixed!
"},{"location":"releases/2021.08.06/#maya-20221","title":"Maya 2022.1","text":"Finally that service pack was released for Maya, addressing a critical but which led many users to experience fatal crashes when attempting to delete rigids from their scene.
This has now been fixed (by Autodesk!).
"},{"location":"releases/2021.08.06/#import-physics-in-maya-2022","title":"Import Physics in Maya 2022","text":"A Python 3-related error was discovered in Maya 2022, meaning you couldn't use the UI to browse for Ragdoll files. :(
This has now been fixed!
"},{"location":"releases/2021.08.28/","title":"New Tutorials","text":"Highlight for this release is new tutorials!
Sphere
shape typeThree new tutorials from basics to intermediate, with more to come!
"},{"location":"releases/2021.08.28/#bouncing-ball","title":"Bouncing Ball","text":"Learn the fundamentals of Ragdoll in this classic animation tutorial.
View Tutorial "},{"location":"releases/2021.08.28/#rally-car","title":"Rally Car","text":"Build upon the skills learnt with a bouncing ball to combine several rigids into a car (with an engine!)
View Tutorial "},{"location":"releases/2021.08.28/#manikin","title":"Manikin","text":"Construct a full ragdoll from any rig, even your own custom one!
View Tutorial "},{"location":"releases/2021.08.28/#personal-ui","title":"Personal UI","text":"The Licence Window at the bottom of the Ragdoll menu now accurately displays your current licence, including Personal, Complete, Unlimited and Batch, along with the licence type - Floating
or Node Locked
.
Can you believe it. A clear sign of success, not everyone is on Twitter! If you're one of the lucky few, you can now follow along with updates to the project, documentation and general company news from there!
The only question is, who's going to be the first to follow? \ud83d\ude31
"},{"location":"releases/2021.08.28/#pivot-editor","title":"Pivot Editor","text":"In making he tutorials, the main bottleneck in terms of time taken was editing constraints. They are both complex and difficult to manage.
This release addresses this problem with the Pivot Editor GUI.
"},{"location":"releases/2021.08.28/#basics","title":"Basics","text":"Here's how to use it to tune a broken knee.
"},{"location":"releases/2021.08.28/#spin-swap","title":"Spin & Swap","text":"One of the main reasons to want to edit constraint pivots is to align the Twist axis with the main rotation of a knee or elbow.
"},{"location":"releases/2021.08.28/#mirror","title":"Mirror","text":"If the pivots face in opposite directions, orientations can be un-mirrored with the Mirror
option.
Tuning limits alongside pivots works well too, middle-click drag attributes from the Channel Box like you normally would, whilst dragging in the UI to compensate.
"},{"location":"releases/2021.08.28/#snap","title":"Snap","text":"Use the snap option to make precise adjustment to specific angles.
"},{"location":"releases/2021.08.28/#worldspace-trajectories","title":"Worldspace Trajectories","text":"Trajectories used to follow the scene wherever it went. Now they'll stay put, where they belong.
Before
After
"},{"location":"releases/2021.08.28/#sphere-rendering","title":"Sphere Rendering","text":"This fixes a minor annoyance you may have noticed, of the outline of spheres visible in shaded mode.
Before
After
"},{"location":"releases/2021.08.28/#floating-server-details","title":"Floating Server Details","text":"When you first lease a licence from your licence server, the IP and port details are stored on the local machine for quicker access the next time.
However, if you then later needed to change those details, then any local machine previously leasing a licence would not be able to update their details.
This has now been fixed!
"},{"location":"releases/2021.09.27/","title":"Animation Capture pt. 1/4","text":"Highlight for this release is Animation Capture.
Let's start with some eye-candy, thanks to Jason Snyman for the gorilla rig! :)
"},{"location":"releases/2021.09.27/#introduction","title":"Introduction","text":"Lighter, faster, stronger. This release introduces a new way of thinking about physics, and is part \u00bc.
Something amazing has happened.
Since release only a few weeks ago, Ragdoll is now used in production across the globe in over a dozen countries at the most major of studios, several dozens of mid-sized studios wanting to gain an advantage and hundreds of independent animators and riggers alike.
And that is amazing, it is. But something even more amazing has happened; Ragdoll has leaped forward. And that will be what the next 4-part release is about.
See, since launch I've had conversations with animators using Ragdoll for the very first time. One of those animators made a request that at first glance didn't look like much.
Quote
\"I don't like working with green channels, as it is not ideal for animating. Is there a way to I can overcome this?\" - Christopher Page
Here's what he was referring to.
Notice how the nodes with physics applied got green channels? The reason they are green is because Ragdoll is driving them. They are green rather than yellow because you can still edit them, at the same time as Ragdoll is editing them. Your changes will be reflected in the simulation, this is how you control the simulation as it is running.
Can we get rid of that connection? Well.. No? This is Ragdoll's connection to your controls. Without those.. there is no physics.
I quickly dismissed the idea and carried on with my day.. But then something clicked.. What if..?
In the next section, I'll dive into how this works and why this change goes far beyond just getting rid of green channels.
Benefits at a glance
From here, this list has no end, because anything capable of affecting the worldspace position and orientation of your controls is natively supported with this workflow. Anything.
I'm a techy, gimme the deetsThe reason this works is because Ragdoll will consider the .worldMatrix
attribute of any control and this is the same attribute Maya itself uses for just about anything.
Inspired by Motion Capture - Animation Capture is a new way to think about and work with physics in Maya. To learn about it, let's first understand how Motion Capture generally works.
Here is a typical data pipeline for motion capture, from real-life actor to final character animation.
# Description 1 Markers are attached to an actor 2 Markers are \"captured\" 3 A pointcloud is generated 4 A hierarchy of joints is generated 5 Joints drive a typical character rig 6 Rig drives final geometry for renderEach \"marker\" is a dud. Nothing of any complexity. Something for the camera(s) to recognise and track as it moves through space. Once tracked, it's able to translate this marker from a 2D image into a 3D position, and continues to do so for each marker, for the real processing to take place inside software.
Once the capture is complete, the human actor can remove the markers and go enjoy the rest of their day. The rest is up to the computer.
With 3D positions generated, software takes over to translate these points into a hierarchy; the FK joint hierarchy you may be familiar with if you've ever worked with mocap. The joint hierarchy can then be used to either drive the final geometry, or to drive a more complex character rig which in turn drives the final geometry.
Animation Capture is just like that, but in reverse. Instead of capturing a person, it captures your character rig.
# Description 1 Markers are attached to a character rig 2 Markers are \"captured\" 3 A rigid is generated for each marker 4 A hierarchy of constraints is generated 5 Simulation is recorded back onto the original character rigUnlike motion capture, we'd like the result mapped back onto our character rig again, which is how animators iterate with physics.
"},{"location":"releases/2021.09.27/#demo-1-basics","title":"Demo 1 - Basics","text":"Ok, enough prelude, let's dive in.
Before
Here's what life was like before, with Active Rigid
.
After
And here's life with Markers
.
Notice how the channels are left alone?
This is the key difference between Marker
and Rigid
. Although you still provide Ragdoll with controls, Ragdoll no longer drives your controls directly. Instead, it shows you what they would look like if they were driven with physics.
Once you're happy with what you see, you Record
.
Let's have a look at how Markers
work with a full ragdoll.
1. Setup hierarchy
The first step is nothing new, you've seen it before.
2. Edit shapes
This too, it's second nature by now.
Except!
Notice how the shapes overlap? That's ok! No longer will you have to worry about self-intersecting shapes. Unless you want it to, with the new Self Collide
attribute. :D I'll touch on this a bit more below, under #self-collide
Double Except!
Release 4/4 in this series will deal with the channel box, and make editing these values interactive in the viewport for a superior experience and a lot less clicks and fiddling with numbers.
3. Animate
Now things are getting interesting. To keep our viewport clean, we can offset the simulation slightly. The offset is purely visual and won't affect the simulation or subsequent recording.
4. Record
Finally, and this is what separates Markers
from Rigids
, we record our simulation back onto our controls.
That last example was contrived. No rig is without IK, so how does Markers
work here?
1. No IK
Since we put markers on the FK controls, Ragdoll doesn't know about what the IK controls are doing.
2. Reassign
So let's put markers on the joints driven by both IK and FK, such that when you switch between the two, Ragdoll knows how to follow along. So let's Reassign
.
3. Retarget
But recording still targets our original FK controls, and what we want is to record our IK controls. So we can Retarget
.
4. Record Translation
Unlike FK, IK isn't just rotation, but translation too. So let's tell Ragdoll to record the translation from these markers too.
And there you have it! This works with IK, SpineIK, Follicles, Geometry Constraints; anything you can throw at it.
"},{"location":"releases/2021.09.27/#demo-4-real-world-example","title":"Demo 4 - Real World Example","text":"Here's a work-in-progress animation from Christopher Page (thanks for lending it to me!) Let's see how we can use Ragdoll to help improve upon it.
1. The Problem
Notice how the elbow intersects the table as he moves his torso around? A difficult problem and moving target as you need to keep tweaking both the torso and hand IK handle to tune your animation.
2. Isolate Timeline
Since this animation is over 600 frames, we'll isolate our work to a small portion of it. For both performance and cleanliness; Ragdoll will only record onto the current timeline (or selected portion of it).
3. Assign Markers
Like before, we'll assign markers to the underlying skeleton to respect what the IK solver does. We'll also make the hand Kinematic
to respect the original animation exactly. The clavicle is also Kinematic
per default, as it was the first assigned control - and is thus the \"root\" of our dynamic hierarchy.
4. Include Table
Since we're interacting with the table, we'll include this too. Also Kinematic
, no dynamics will be affecting it, and also as a Box
shape to speed up and improve the stability of the simulation.
5. Tune Shapes
Next we'll isolate contacts with just the elbow area, to respect the hand and lower arm animation.
6. Tune Material
In this case, we'd like for the elbow to slide across the table, no friction.
More Realism?In the real world, there would be friction and it could come in handy here too. But what should we expect from the elbow rubbing against the table? We should include the torso for this as well, which you absolutely can (and maybe should!). But to keep things simple, we'll let the clavicle preserve it's original animation exactly.
7. Retargeting
Ragdoll will record onto the nodes you originally assign, but like before we want recording to go elsewhere; from joints to IK controls.
8. Record Translation
Likewise, we'd also like translation included. And we don't care for the shoulder and clavicle animation; all we want is the IK handle and Pole Vector.
9. Record Simulation
We're all set! Let's hit Record
!
10. Before And After
And there we go! 2 minutes or less, and you've got a reusable setup for correcting the elbow whenever the animation changes. IK is intact and you can keep working with keyframes. Keeping Ragdoll attached to your rig has zero impact on performance (as you can see by looking at the fps counter near the bottom of the two comparisons), and once hidden it has no impact on your Outliner either. All clean!
Here's one more I couldn't find room for, an earlier version of the animation with stepped keys and finger simulation. Look at all that juicy finger interaction with the table. \ud83d\ude0a
Rig and Model courtesy of Ramon Arango - Apollo Rig
"},{"location":"releases/2021.09.27/#new-menu","title":"New Menu","text":"Let's take a moment to reflect on what we've just seen. There are 3 new nodes in Ragdoll.
# Node DescriptionrdSolver
The \"camera\" that monitors \"Markers\" and performs all heavy-lifting. rdMarker
A tracking marker, something to monitor an individual control. rdGroup
A collection of markers, with high-level control over many markers. Here's the new menu. If all goes well, it will completely replace the Active Rigid
and Active Chain
menu items, along with Controls
including Mimic
. All of those things are made possible in a much easier and performant way using Markers.
The most important elements are at the top.
# Item DescriptionAssign Single
Monitor a single object in the Maya scene. Use this for props, environment and other free-falling things. Assign Group
Monitor a series of connected objects, like a limb. Record
Transfer simulation to marked objects Like Active Chain
, the order of selection determines the order in which markers assume your objects are connected. And adding more markers to a group is done by starting your selection from any point in an existing group and working your way outwards. Just like Active Chain
.
Limitations
You currently cannot create multiple rdSolver
nodes, but can work around it by importing one from another Maya scene file.
The Guide Space
is somewhat complicated. The group has one too that affects all markers, and per default it's set to -1
for Localspace
. The benefit is that you can quickly change the space for all markers by changing this one attribute. The downside is that if you want to change it for just one marker, you first need to reset this attribute to 0
.
These will be addressed in the upcoming few releases.
"},{"location":"releases/2021.09.27/#recording","title":"Recording","text":"Markers can be recorded all together, or independently. For example, say you wanted animation from frame 1-100, simulate 101-150 and return to animation from 151-200. You can do that.
Furthermore, say you liked what the simulation was doing, but only on one half of the body. Or only on the hip, driving the main trajectory in a physically-plausible way. Keeping the rest of your animation intact.
Record All
With nothing selected, Ragdoll will record all marked controls to the current Maya playback range.
Record Selected Markers
Select a few controls to control what gets recorded.
Record Range
Limit the Maya playback range for control over when recording takes place.
Record Selected Range
Or, select an explicit range interactively.
Intelligent Range
A Kinematic
marker is entirely animated, so there's no need to actually record those. Ragdoll will ensure only non-kinematic frames are recorded, so you can do things like this.
Record to Animation Layer
Ragdoll will record to whichever layer is currently active.
"},{"location":"releases/2021.09.27/#input-type","title":"Input Type","text":"In the above examples, I mentioned Kinematic
and you probably spotted a few other options too, like Inherit
and Guide
. What are those?
The Input Type
is how Ragdoll should interpret the controls you assign. Did you mean for them remain animated, i.e. Kinematic
? Or should they follow the control around, i.e. Guide
? Or should they just fall with gravity, ignoring the original control altogether, i.e. Off
?
The Input Type
can be set either for a whole group of markers, or each marker individually.
Kinematic
if there is no group Off Do nothing, just fall under gravity Kinematic Follow the input exactly, physics need not apply Guide Follow the input approximately, with some Stiffness
and Damping
Off
Treat the input as a starting position, but nothing else.
Kinematic
Follow the input exactly, no exceptions. Not even collisions.
Guide Space -1
Follow the local angles of the input.
Guide Space +1
Follow the world position and orientation of the input.
"},{"location":"releases/2021.09.27/#retarget","title":"Retarget","text":"We've talked a lot about \"retargeting\". But what is that?
Per default, markers are recorded onto the controls you assigned, this is called Rig to Rig
.
But often times, rigs are more complicated and what you want is for the simulation to look at one set of nodes, but record onto another. This is called Joint to Rig
, but can be from any source. Even other controls (like FK to IK).
The Old Days
Think about how you would accomplish this using the Active Rigid
or Active Chain
commands. That would be a huge pain, but not with markers!
Over in Demo 2 - Ragdoll we \"reassigned\" already marked controls. What does that mean?
In that example, we've assigned our FK controls directly, which means Ragdoll would grab the translation and rotation from those controls during simulation. But what we really wanted was the IK controls.
But! We couldn't just assign to the IK controls directly, since they are indirectly rotating a characters limbs. So instead, we Reassign
the markers previously made onto the underlying joints that follow IK around.
We then also Retarget
them, since they would have otherwise been recorded onto the original FK controls.
Sometimes, you change your mind.
Success!
"},{"location":"releases/2021.09.27/#guide-space","title":"Guide Space","text":"Now let's talk about a few things you haven't seen yet.
Look, it's Ragdoll Blaine!
So what's happening here? Well, it looks like a Soft Pin to his head, along with a slight Guide Strength
on the rest of his body. But unlike the Rigid
, another significant advantage to Markers
is their ability to capture both local and worldspace position and orientation of your controls. And because of this, you are able to interactively choose whether a marker should look at the Worldspace or Localspace position of your controls.
Notice how with a Guide Space = -1
the controls arms remain relative the torso. And with Guide Space = 1
they instead follow the worldspace orientation of the controls. Just like a Soft Pin.
This attribute is also animatable, and is how you can transition from animation into simulation and back again.
Here's a more complete example:
Frame Transition 100 Starts as a regular animated character 125 Transitions into physics as he jumps, for a physically-correct trajectory 155 Transitions back to animation once he rolls over on that cabinet 160 Transitions back to physics until he stands up 170 Transitions back into animation to match an exact pose 200 Partially transitions into physics, for secondary motion in the upper body as his arm is raised. "},{"location":"releases/2021.09.27/#transitions","title":"Transitions","text":"Let's have a look at how you would use markers to transition between simulation and animation.
Notice how we're animated up until the jump, and then Ragdoll takes over. Once he approaches that box, we turn our Guide Space
from -1
to 1
and have him reach the target pose in worldspace. Once he's close, we switch Input Type
to Kinematic
and kinematically move him until we once again transition to Guide
, this time with a Guide Space
or -1
for pose space.
Previously, it was very important that your shapes did not overlap any shape other than it's immediate neighbour. If they did, chaos ensued.
Before
Clavicles intersect their parent spine, but also each other!
After
With the new Self Collision = Off
, this is no longer a problem.
This can be taken into the extreme!
And here's a another example to fill out a large volume in the center of a character.
Attention
Notice how the spine is made up of many shapes, some of which cover the width of the body, others the depth. An overlapping mess that would never have simply not have been possible without self-collision support!
Original asset created by Mehmet Tayfur T\u00fcrkmeno\u011fluwe and Dr. Reel, licensed by The Rookies.
"},{"location":"releases/2021.09.27/#no-graph-editor-mess","title":"No Graph Editor Mess","text":"Because Rigids
were children of your controls, Maya had a funny way of including them in the Graph Editor that rightly drove animators, myself included, absolutely mad.
Before
Just look at this; why-oh-why would I want channels from a completely unrelated node when working with the hip?
After
Contrast that to this, whereby only the nodes you actually select are made visible. You can even select Markers
via the Channel Box and deselect your controls to get up real close.
A significant effort was made to make the simulation start where you expected it to.
Under the hood, simulation and animation were at odds with one another. Ragdoll needed to know where to start, but it was also telling your controls where to start. It's an inherent cycle, which was finally broken.
Read More
You can read all about the month-long journey in the release notes from March
Nowadays, you barely have to think about it, but it does occasionally rear its ugly head. It is a hack.
With Markers
there isn't any cycle to begin with. Ragdoll only reads from your controls, it doesn't write to anything. Under the hood, recording is a 2-step process; first it simulates, and then it writes animation back onto the controls. That's how this cycle is broken, without having any effect on the overall workflow.
With the previous version, because Rigids
both read and wrote to each control, you could sometimes run into a situation where the parent depends on a child.
Before
Here, I'll try and make a second chain in the opposite direction of how the controls are laid out hierarchically. This cannot work; because in order for Ragdoll to figure out where the Passive hand should be, it would first need to consult the upper arm, which is both dynamic and a child of the spine, which is also dynamic. It's a lovely cycle. \u2764\ufe0f
After
With Markers
, this isn't a problem because to Ragdoll every limb can now be independently evaluated, in parallel.
Sometimes, markers are added to an already busy control with tons of Channel Box entries. Lollipop controls can help organise things a little better.
These can be moved around and scaled to suit your needs, and will provide access to the same marker node in the channel box, so you can select and edit the marker from either the originally marked control or this lollipop control.
"},{"location":"releases/2021.09.27/#rotate-pivot","title":"Rotate Pivot","text":"Use the default Maya rotate pivot to control where to pin a simulation, both in worldspace and localspace.
Attention
Take care about scale, especially the scale pivot. Ragdoll can sometimes struggle when the scale pivot differs from the rotate pivot. This will be addressed in a future release.
"},{"location":"releases/2021.09.27/#quality-of-life","title":"Quality of Life","text":"Some minor things to brighten your day.
"},{"location":"releases/2021.09.27/#real-ground","title":"Real Ground","text":"With Rigids
, the ground was embedded into the scene. With Markers
, an actual ground is created to for more stability and more control over its physical parameters. Something that can also be animated, and that dynamically appears right underneath your markers.
The Attribute Editor doesn't show you Rigids
related to Maya joints because of a Maya UI quirk.
With Markers
, this is no longer a problem!
Hiding the solver completely removes all overhead of having Ragdoll in your scene. Previously, with rdScene
and rdRigid
, because they were directly connected to your controls, hiding things made little difference. But now, because we no longer have this direct connection, all computations come from explicitly seeing the rdSolver
node.
No visible rdSolver
node, no computations. Period.
TLDR
Sometimes, re-opening the scene could lead to different results. This has now been fixed.
Each time you play a simulation starting from the beginning, the results are the same. This is an important characteristic of any simulation and is called \"determinism\". It used to be the case however that when you re-opened the scene, there was a small chance the results would differ from when you last saved it.
This has now been fixed. The determinism is now dependent on the order in which rigid bodies connect to the rdSolver
node. It's an array attribute, whose order is saved with the Maya scene.
Whenever a machine connected to your floating licence server, the host and IP were stored on the machine in an effort to speed up subsequent connections made. However, this also meant that you weren't able to update those details.
Despite providing new details, Ragdoll would favour the already-stored details. Worse yet, the Ragdoll UI would lie to you, by repeating the connection details provided in the RAGDOLL_FLOATING
environment variable, despite those not actually being used.
This release addresses this by always using the details you provide, and not bother reusing any previously provided details. In addition, you now have the option to explicitly query and set server details directly.
# Will query the *actual* server used by Ragdoll, rather\n# than return the environment variable you provided\ncmds.ragdollLicence(getServer=True)\n\n# Will manipulate the currently-in-use key, meaning it will\n# try and drop a licence from this address as well\ncmds.ragdollLicence(setServer=(\"localhost\", 1313))\n
"},{"location":"releases/2021.09.27/#next-release","title":"Next Release","text":"This release is part \u00bc, for next 2/4 release you can expect Performance Improvements.
In this release, simulation and overall Maya scenegraph performance has seen a 200x performance boost, the performance is already there. You'll notice it as you try them on your rigs.
However, rendering performance has dropped significantly, cancelling out most of that performance gain. Here's what performance looks like now.
Rendering mostly Maya default shading, rendeing its own things. Unrelated to Ragdoll. The Rig Evaluation on the other hand is almost entirely Ragdoll. It's connected to every control in this rig, forcing each control to be evaluated in serial; one after the other.
Here's what it looks like with Markers
.
Notice the huge pile of lines to the left? Those are all running parallel and almost entirely default Maya evaluations; things your rig would do without Ragdoll. Rendering on the other hand is almost entirely Ragdoll, it is very slow.
To properly compare performance between Rigids
and Markers
, here's what you should be looking at.
This is the only thing Ragdoll does to your rig. This is the entire overhead, the added load onto your rig. 16 microseconds. That's 0.016 ms
. For a rig to run at 30 fps, it'll need 1,000/30 = 33 ms
per frame. This overhead, 0.016 ms/frame
is all Ragdoll needs to solve an entire character, contacts and constraints and forces, all of it. In this particular profiling, that's 430x faster than Rigids
, which not only took longer to solve but made everything else slower by just being connected to your controls.
So how about we get this rendering performance sorted, shall we?
"},{"location":"releases/2021.09.27/#limitations","title":"Limitations","text":"These are some of the things lacking from Markers
in this release that we'll be working on for subsequent releases.
Highlight for this release is Performance, and is part 2/4 of the new Markers.
You know the drill, we'll start with some eye candy. \ud83c\udf6c
New Shading
Now more like actual candy. Nom nom nom!
Raining Ragdolls
Quick! Get inside!
Do the Robot
Model and Rig courtesy of Amedeo Beratta
Vehicular Render
Made by @tris
Guide Space Mania
Oh the trickery you can get up to. \ud83e\udd73
"},{"location":"releases/2021.10.07/#anniversary","title":"Anniversary","text":"That's right! Ragdoll turned 1 this week! \ud83e\udd73
In my original business plan, I had written..
\"Revenue, year 1: \u00a320,000\"
..which was blissfully optimistic. However! I'm happy to say that Ragdoll blew past this in the first 6 days into launch, on the 28th of July this year. Very few startups achieve this amount of revenue in year 1; the vast majority achieve \u00a30 for the first number of years (I watch a lot of Dragon's Den \ud83d\ude05), the expectation being that they will regain their investment once enough value has been created. But given we're past this point already, this to me is validation that you want this.
So, let's keep it going, shall we? :)
"},{"location":"releases/2021.10.07/#manikin-rig","title":"Manikin Rig","text":"Throughout these notes, I'll be using this guy here. Feel free to download and play around with it.
Download Manikin "},{"location":"releases/2021.10.07/#performance","title":"Performance","text":"This release was all about performance, so how did we do?
In short, very well! We're now a lot closer to the capabilities of your hardware with a lot less waste. Because you see, software development is a lot like Jenga. You start off with a tower full of bricks, but every brick adds to the overall weight of the tower. And not every brick is necessary to keep it standing. The Eiffel Tower is an example of what a structure can look like with the absolute minimal amount of material. It is an optimal shape; anything added is wasted weight, anything removed would sacrifice stability. That is the structure we've been working towards with this release.
In terms of time spent, Ragdoll has three stages.
# Stage Description 1Evaluation
This is primarily your character rig - the transform hierarchy, constraints, any deformers, and so forth. It is how data is passed from Maya into Ragdoll. 2 Simulation
Once data has been aquired, Ragdoll considers all of it and applies forces, solves constraints, contacts, that kind of thing. 3 Rendering
Finally, we need pixels. In the case of Ragdoll, this means generating and uploading geometry to the GPU; including capsules but also your meshes which are converted into \"convex hulls\". Simulation has always been fast and in the previous release, we focused entirely on workflow which had an indirect impact on Evaluation
and Rendering
. One got faster, but the other got slower.
Changes in Part \u00bc
Let's recap what happened in the previous release.
We tackled Evaluation which boosted performance by 2-10x by unlocking parallelism. Before, the better your character rig benefited from multithreading the worse it would perform with Ragdoll. Ragdoll would force any control you simulated into serial evaluation - to compute one after another - because the solver was fundamentally single-threaded.
With Markers, Ragdoll separated from the overall rig evaluation, which meant (1) your rig can continue running in parallel and (2) Ragdoll could also run in parallel.
Consider this example.
Rigids MarkersThis is how Maya scheduled evaluation for this scene with Rigid
versus Marker
. To the left, everything runs one after the other. It's terrible. To the right, every box is evaluated in parallel. Which means the more boxes and cores you have, the better utilisation you get.
The scene itself is very simple, it's this one here.
So evaluation got faster, but rendering got slower. All-in-all we gained about 100% performance.
With this release, we'll tackle that rendering block. Let's have a look at what's changed, in order of most-to-least significance.
Topic Savings Description Less CPU to GPU communication 1550x More buffers, less uniforms Connection Monitoring 40x Less dependence on time, more on physical connections being made and unmade Change Monitoring 40x Ignore anything that hasn't actually changed Less Dirty Propagation 3x Less of a shotgun blast, more like a sniper "},{"location":"releases/2021.10.07/#cpu-to-gpu-communication","title":"CPU to GPU Communication","text":"The previous release, and each one before it, had 1 shader per rigid. In the case of 600 rigid bodies, that meant 600 shaders. 600 shaders means 600 parameter updates of primarily color and 600 unique draw calls.
On top of this, all geometry was regenerated and re-uploaded to the GPU on every frame. Robust, but not very fast.
This release consolidates all shaders into one, colors are uploaded only once alongside their geometry and rendered using a custom GLSL shader (i.e. OpenGL 3.3).
What about DirectX?If you are on Windows and can't use OpenGL for whichever reason, there is backwards compatibility built-in.
from ragdoll import options\noptions.write(\"useShaders\", False)\n
Or via the Ragdoll Preferences.
Bearing in mind this will cost you 50% of the rendering performance and won't benefit from future shading related features and improvements. The option will remain until it's clear whether and how much it is actually used. (Let us know in the chat!)
Let's have a look at how this change affects your overall experience.
Before (7fps)
After (130 fps)
A closer look reveals exactly where this improvement comes from.
Before
This block is what we control, it's the Ragdoll rendering pipeline taking a whopping 93 ms per refresh.
After
With this release, this number dropped to 0.06ms (58 microseconds) that's an improvement of 1550x (!).
What about the other blocks?
The bottleneck has now moved to that green one and all of those blue, and those are Maya's internal rendering pipeline.
There isn't much we can do to directly impact it; it's mostly out of our hands. However, by massaging our data more and making life easier for Maya it should be possible to reduce these as well.
See Future Work for details on next steps, and if this is something you, fellow reader, is familiar with do get in touch!
Finally, as a result of having complete control over the shader running on the GPU, we're now able to more intimately design it to look the way we want. Expect more refinements here over time.
Before After "},{"location":"releases/2021.10.07/#connection-change-monitoring","title":"Connection & Change Monitoring","text":"In the previous release, and all versions of Ragdoll so far, we've tasked Maya with evaluating every plug on every frame, including the heavy-duty plugs between Rigid Body
-> Solver
.
Here's what this felt like in a scenario of 600 unique objects.
Before (5 fps)
Painful! The reason is because even though we're only moving a single box, Ragdoll checks-in with all other boxes too.
After (90 fps)
Blissful. In this case, only one of the boxes is actually updated, as one would expect.
Let's have a closer look at where performance is going here.
Before
Oh that's ghastly. Not only does it spend time evaluating all of those boxes, but it's making the solver take much longer consolidating the results taking a whopping 56 ms.
After
Whereas now, as one would expect, we're only evaluating this one box in a total of 0.7ms, resulting in a performance improvement 80x.
That looks like 3?
And that's true, it still makes three separate calls to this one box. Which means there's more room to optimise here, and we'll get there.
Needless to say, this happened before as well but was obscured by how many calls there actually are. Luckily, at least two of these calls happen in parallel.
600 capsules
The current framerate on 600 unique objects, something for future Ragdoll to try and compete with. For reference, an average ragdoll consists of about 20-30 objects.
"},{"location":"releases/2021.10.07/#future-work","title":"Future Work","text":"There is at least 4-16x performance left on the table for specialised cases.
Work Savings Benefit Optimised Render Items 4x Native Maya still renders 4x faster than us, which means there's more things we can do. Instancing for Rendering 2-4x Every render item is currently unique which means neither Maya nor your GPU is able to reuse geometry. Instancing is how games is able to render millions of objects on-screen at 60 fps, and best we can hope for is thousands. Instancing for Simulation 2-4x Likewise, every physics object is unique and, again, instancing in simulation is how games is able to run destruction and have thousands of objects interact in real-time.The challenge in both of these is deduplication; of identifying which of the many shapes you use can reuse their geometry.
"},{"location":"releases/2021.10.07/#overlap-group","title":"Overlap Group","text":"Specify which markers may overlap rather than collide. This can be useful to enable dense areas of a character, like the clavicles, where there is natural overlap amongst large shapes like with the neck and spine.
Value Meaning-1
No overlap allowed 0
Default, respects self-collision on the group (if any) 1-255
Overlap everything with the same number An rdMarker
part of a rdGroup
can get an overlap group assigned procedurally, based on other members of that group. For example, in a complete ragdoll, all markers are part of the same group. So a Self Collide = On
means these will all be given the same overlap group.
If it isn't in a group, then 0
is the same as -1
, in that it will collide with everything.
Let's have a look at a few scenarios.
"},{"location":"releases/2021.10.07/#collide-with-everything","title":"Collide with Everything","text":"In this example, every marker is part of the same group. The group has Self Collide = Off
, which is fine for just about every marker except the fingers. In that case, we do want self-collision, so they are given the group -1
.
In this case, we're happy with a default group of 0
since we don't need anything to self collide. Especially these clavicles that overlap significantly!
Finally, for the very specific cases of wanting two or more markers to overlap. Notice how we give both the ground and 3 of the boxes an Overlap Group = 5
.
Sometimes, you want things to stay put until something comes into contact with it. That's when you can tell a marker to start asleep, and \"wake up\" when necessary.
"},{"location":"releases/2021.10.07/#ignore-gravity","title":"Ignore Gravity","text":"It surrounds us. It penetrates us. It binds the galaxy together. But sometimes, you just don't care.
"},{"location":"releases/2021.10.07/#quality-of-life","title":"Quality of Life","text":"A few things to make your day that much more bright. \ud83c\udf1e
"},{"location":"releases/2021.10.07/#guide-space-20","title":"Guide Space 2.0","text":"In the previous release, we introduced Guide Space
. Which was a quick way of controlling whether a simulation should follow your animation in..
But it was challenging to control, not very obvious. Especially with how it was also taking into account its \"group\" guide space. This release addresses this by enabling you to specify a guide space for all markers and selectively override only the ones you're interested in. Just like how the Input Space
works.
Group Guide Space
Override all guide spaces, by editing the group.
Marker Guide Space
Or gain surgical control over guide space per-marker.
Have Fun
\ud83e\udd2d
"},{"location":"releases/2021.10.07/#auto-delete","title":"Auto Delete","text":"The Delete All Physics
menu command does what it says on the tin; it deletes all Ragdoll nodes from your Maya scene. But deleting a node, such as the new rSolver
left behind anything associated with it, like rGroup
and any rMarker
nodes.
This releases addresses this by automatically removing anything that depends on the node you delete. For example..
rMarker
node also deletes any associated lollipop controlsrGroup
also deletes the associated rMarker
nodesrSolver
deletes all rGroup
and rMarker
nodesTherefore, deleting a solver is now equivalent to Delete All Physics
, making it much more intuitive to delete things on a whim.
Minor cosmetic improvement, the Reset to Default
button now has an icon so you can actually tell it's a reset button (and not a bug, as many have pointed out \ud83d\ude05).
The default plane and solver offset was a off in the previous release, this fixes that. You can also manually re-adjust the plane and remove and orientation from the solver node to fix it locally, the solver itself is A-OK.
"},{"location":"releases/2021.10.07/#auto-time","title":"Auto Time","text":"Rather than having to specify which frame to start simulating at, Ragdoll can now keep track of your animation start frame. Either the start of the range, or the full timeline. Or, you can still set a Custom
start time for when you do care about specifics.
Monitoring for and responding to changes is a hard problem.
Odds are some things aren't updating the way you expect, which could affect viewport rendering, or worse, the actual simulation. If you encounter any such issues, please let us know in the chat or ping me directly at marcus@ragdolldynamics.com
Here are the currently known issues that we'll be fixing once a solution presents itself.
"},{"location":"releases/2021.10.07/#motion-blur","title":"Motion Blur","text":"As an unintended consequence of the optimisation and shader work, we're currently compliant with Maya's requirement for motion blur. Since all of our simulation is transform-based, it means all of what you simulate can be motion blurred, as opposed to deformer and particle-based motion.
It won't work with any animated attributes, which makes it rather limited in what you can use it for. \ud83e\udd14
"},{"location":"releases/2021.10.07/#maintain-offset-ikfk","title":"Maintain Offset IK/FK","text":"If you retarget a marker, the difference between the original and target is stored.
When you record, you have the option to Maintain Offset
. That's important if the assigned control has a different position and/or orientation than the destination control. For example, you can assign to a joint, but record onto a NURBS control.
For example, IK joints are assigned markers but are retargeted onto FK controls, it's important that you retarget when they are both in a similar pose. Otherwise, the difference between them will remain after recording.
To combat this, you have two options.
Retarget
(1) may not always be an option. If the position and/or orientation of an assigned control is simply different, then there isn't much you can do. :(
(2) is your best option. If you make a mistake, you can always re-retarget to the same control again, and the offset will be updated.
"},{"location":"releases/2021.10.07/#recording-kinematic-markers","title":"Recording Kinematic Markers","text":"When a marker treats the input as Kinematic
, it means it won't simulate it. It'll be 100% locked to animation. If that's the case, then there's really no point in recording those keys, right? Because they'd be 100% identical to the animation?
Except! If there's a parent, then we'll still need those keys to compensate for the parent not being kinematic.
Problem
Let's record without kinematic keys. Notice how the hand isn't given any keys, even though it needed them?
Solution
Record all keys, and the hand - even though kinematic - will still get recorded.
"},{"location":"releases/2021.10.07/#record-to-custom-attributes","title":"Record to Custom Attributes","text":"Sometimes, rotation isn't coming from Rotate X
but rather a custom Ball Roll
attribute on a different IK control.
As Ragdoll only understands Translate
and Rotate
, how would you go about recording onto this attribute!? Here's what you can do.
Locator.rotateX -> R_foot_CTL.ballRoll
Now Ragdoll will record onto a familiar channel, and Maya will handle the conversion back onto the rig.
"},{"location":"releases/2021.10.07/#slow-constraints","title":"Slow Constraints","text":"Like in earlier versions, drawing constraints are the slowest part. If you don't need them, disable them. You can do that either on the rSolver
node, or individually per rMarker
node.
Some well-hidden but essential resources for any of the above. If you are into anything related to Maya plug-in development and performance, you'll treasure these as I have.
Highlight for this release is Linking and Caching, and is part 3 out of 4 of the new Markers.
Let's start these notes with some examples of what you can do with all of the new features added. \ud83e\udd70
Best Friends, No Matter What
Two referenced characters, their solvers linked.
Hang On!
The new Distance Constraint
at work.
Dance Baby!
The new Pin Constraint
working alongside a Distance Constraint
and regular old pose matching.
Updated with limits from this release.
As before, this guy can either be opened or referenced into your scene. See Solver Linking for how you can reference multiple characters into the same simulation.
Download Manikin "},{"location":"releases/2021.10.25/#new-tutorials","title":"New Tutorials","text":"Markers have one part left before being considered complete, at which point they can completely succeed Active Rigid
and Active Chain
.
Until then, here's how you can get started with Markers today.
Tutorial Duration Description Markers 101 01:23 What are markers? Markers 101 - Key Concepts 03:23 Overview of Input Type and Pose Space Markers 101 - Local and World 03:00 Overview of the two Pose Spaces, local and world Overlapping Motion I 02:27 The very basics or Capture and Record Overlapping Motion II 02:21 Animation layers Full Ragdoll I 04:08 Hierarchy and volume Full Ragdoll II 04:05 Kinematic and animation Full Ragdoll III 04:30 Self collisions and recording IK I 03:00 Capturing the skeleton IK II 01:59 Retargeting to IK controls IK III 01:59 Record both Translation and Rotation Practical Example I 06:53 Fix table and elbow intersection in this dialog performance "},{"location":"releases/2021.10.25/#solver-linking","title":"Solver Linking","text":"Reference two characters, link their solvers.
Until now, you've been able to author physics using Active Chain
and combine scenes using the Combine Scene
menu item. That would transfer all connected rigids from one scene to another.
But, that feature is destructive. There's no way to \"uncombine\" and even if you could, there's no record of what was originally combined.
Let me introduce Solver Linking
, a lightweight and non-destructive alternative.
Linking
This fellow is referenced twice, and get their solvers linked together.
Unlinking
Unlinking restores their previous behavior exactly.
That's neat, but can you..
I know exactly what you're thinking, I was thinking the same thing.
Can you link a solver to another solver that is also linked? So that I can build a network of simple solvers that all work together to form one complex solver?
Yes. Yes, you can. \ud83e\udd2d See below.
"},{"location":"releases/2021.10.25/#example","title":"Example","text":"Here are 2 assets, a manikin and a backpack.
Manikin BackbackThe backback and manikin has been combined into one, which is then referenced twice into the final scene for a total of 4 unique solvers.
Non-destructively link solvers
Notice the hierarchy of solvers formed here, enabling you to build complex solvers out of many small solvers.
Non-destructively unlinking too
Likewise, safely deconstruct a network of solvers by just removing the connection.
Technically, a solver is added to another solver in the same manner a marker, group and constraint is added. One big happy family.
"},{"location":"releases/2021.10.25/#solver-caching","title":"Solver Caching","text":"Ragdoll runs alongside your character animation, but sometimes it can be useful to keep the results from a previous run and stop being so interactive.
Meet Cache
and Uncache
.
Caching is entirely non-destructive, and in fact leverages the very same cache you've been enjoying all this time whenever rewinding.
The menu commands toggle an attribute on your solver node, called .cache
and automatically plays the entire timeline for you. But the same result can be achieved by setting the attribute and playing it yourself.
The minimal HUD will show you what's been cached, and like before once you resume playback from a cached to an uncached frame, Ragdoll will continue filling up the cache as one would expect.
Look forward to a future release where caching happens in the background, as you work. Something that can also be handy from time to time (pun!).
"},{"location":"releases/2021.10.25/#limitations","title":"Limitations","text":"The viewport HUD currently draws relative the solver node in your Outliner. Moving this node also moves the HUD, which isn't right. Moving it along the Z-axis can actually cause the HUD to vanish due to being outside of the camera frustrum.
Other than that, if you encounter odd behavior let me know. This should work just fine in all cases where Ragdoll works, since the underlying mechanics are the same.
"},{"location":"releases/2021.10.25/#marker-limits","title":"Marker Limits","text":"Markers now support the limits you've grown accustomed to from chains and constraints. They are much easier to work with, now that they are built-in to each marker and have an understanding for what a \"parent\" is.
You should find a lot less need to use Edit Pivots
from here on, and in the next release you'll also get some interactive manipulators to avoid the Channel Box even more.
Limit Type
"},{"location":"releases/2021.10.25/#hinge-limit","title":"Hinge Limit","text":"The simplest of limits, allow a limb to rotate along a single axis. Like hinges on a door.
Use this for knees and elbows.
"},{"location":"releases/2021.10.25/#ragdoll-limit","title":"Ragdoll Limit","text":"For more complex anatomical limits, such as shoulders and hips, use the \"ragdoll\" limit for control over each of the 3 rotate axes.
Defaults
A good place to start is to just play with default settings and get an idea of what it looks like.
Customise
In this case, we'll keep the leg from crossing over too far, and from bending too far backwards. Like a real human leg.
"},{"location":"releases/2021.10.25/#custom-limit","title":"Custom Limit","text":"The Hinge and Ragdoll limits should cover the vast majority of limit needs, but sometimes you need more control. The Custom
limit lets you control the parent and child frames independently, similar to the \"traditional\" Rigid constraints let you do.
Here's an example of replicating the Ragdoll
constraint with a custom limit.
Specify the \"main\" axis for your limit.
Different rigs follow different conventions, and this attribute enables you to keep Ragdoll in the loop. It should typically align with whatever axis your joint or control points in the direction of the child joint or control.
"},{"location":"releases/2021.10.25/#rotation-vs-offset","title":"Rotation vs Offset","text":"You can either rotate or offset the limit.
Rotation
rotates both parent and child framesOffset
rotates only the parent frameRemember
The Parent Frame
is the space in which a Child Frame
is allowed to move.
You can now constrain one marker to anothe!
Constraint Type Description Weld Constraint Simplest of constraints, welds two markers together; no change to their distance or relative orientation is allowed. This is akin to the MayaParent Constraint
Distance Constraint Maintain a minimum, maximum or total distance between two markers. Pin Constraint Match a position and orientation in worldspace, similar to Drive Space = World
. "},{"location":"releases/2021.10.25/#weld","title":"Weld","text":"Maintain the position and orientation of one marker relative another from the first frame onwards.
"},{"location":"releases/2021.10.25/#distance","title":"Distance","text":"A simple but versatile constraint with animatable distance.
Maintain Start Distance
Whatever the distance between two markers, it will be maintained throughout a simulation.
Minimum Distance
Alternatively, only respond to when two controls get too close.
Maximum Distance
Conversely, keep markers from getting too far away from each other.
Custom Distance
Or go all-in, with both a minimum and maximum distance, for the most complex behavior.
Offsets
Control at which point on a control to measure the distance.
Animated Distance
Both min and max distance, along with stiffness and damping, can be animated for some pretty rad effects.
Hard Distance
A Stiffness = -1
means the constraint is \"hard\". It will not accept any slack or \"springiness\".
In this example, the distance is animated whilst soft, and transitioned into a hard constraint. Notice how it snaps into place once hard.
Limitation
A limitation of a hard constraint is that the distance cannot be animated whilst hard. You can however animate it between values of -1 and above, to transition to and from hard to soft.
"},{"location":"releases/2021.10.25/#pin","title":"Pin","text":"Similar to the Soft Pin
used with Rigids, this creates a new position and orientation a marker will try and reach. It's exactly what you get using Guide Space = World
on the markers themselves, but with the convenience of a new transform you can animate. They will both try and pull on the marker, greatest stiffness wins!
Sometimes, you want to tweak the overall look of an entire simulation at once, rather than tweaking or modifying individual nodes. Now you can.
All guides, limits and constraints now have their values combined with equivalent values on the solver node.
Edit One
Here's how you edit just a single marker or constraint.
Edit Many
And here's how you can edit them all.
Animation
Guides and Constraints can be animated, however Limits cannot.
This behavior is consistent with the rdGroup
node too, here's the complete attribute hierarchy.
A mere 15% boost to Recording performance.
Before
After
More was expected, and odds are there's room to optimise this further. But, the bottleneck is writing keyframes which cannot happen across multiple threads. It also needs to happen alongside evaluating your rig, which is dirtied with setting of each key, else it cannot take into account the various constraints, offset groups and IK solvers happening in there.
On the upside, the more complex your rig, the more benefit you should see from this optimisation. What happens in the above examples are extremely lightweight rigs with no animation, hence the difference is minor.
"},{"location":"releases/2021.10.25/#remainder","title":"Remainder","text":"Markers are almost feature complete. Most if not all things you could do with Rigids are now possible with markers.
Except for:
These will be addressed in an upcoming release. The next release will focus on getting those darn shape and limit attributes out of the Channel Box and into the viewport for interactive control.
"},{"location":"releases/2021.11.15/","title":"Animation Capture pt. 4/4","text":"Highlight for this release is Markers part 4 of 4!
Previous Parts
PATH
and Windows If you don't know what this is, you don't have to worry about itIn with the new, out with the old
The next few releases will slowly but surely replace Rigids with Markers. So if there is anything you find yourself unable to do with Markers, let us know and we'll get that in there as soon as possible.
Let's start off with some eye candy. \ud83d\ude07
Spiderman
Courtesy of Jason Snyman, a.k.a. the wizard.
Piggyback Ride
Thought it was fun to see how the simulation would look with the previous simulation as input!
Motion Graphics
Courtesy of Peter Crowther, for their client
Design company. Art direction Matt Walpole.
Halloween
And another from Jason!
"},{"location":"releases/2021.11.15/#recap","title":"Recap","text":"We did it! We're at part 4 out of 4 of the new Markers. Just about. \ud83e\udd70
This release here was intended to round off the interactive manipulators - so that you didn't have to fiddle around the channel box to edit shapes, constraints and limits - but we ran into a wall with our drawing API (see Robust Rendering below) which led us to throw everything out and start from scratch. \ud83d\ude14
On the upside, we've now got a significantly stronger foundation upon which to build manipulators, you will see these in action in the next release. Part 5 out of 4! \ud83e\udd70
These are the things scheduled for the next releases.
Next Release Description Interactive Manipulators Editing shapes is hard, constraints too. And limits. Export & Import Rigids could be exported and later imported, Markers does not have this ability yet Forces Next up, native Maya fields for Ragdoll Mechanical Constraints Like vehicle suspension are nowhere to be seen just yet."},{"location":"releases/2021.11.15/#new-terminology","title":"New Terminology","text":"A few things found a more representative name in this release.
Before After Guide-->
Pose, e.g. Pose Space
Input Type -->
Behaviour, e.g. Kinematic
and Pose Match
Assign Single -->
Assign Individual Assign Group -->
Assign Hierarchy What does it mean?
Still fuzzy on what \"assign\" means? Refer back to the introductory tutorials from the last release here. (hint: it's motion capture terminology)
"},{"location":"releases/2021.11.15/#future-of-rigids","title":"Future of Rigids","text":"
When Markers was first discovered, it wasn't clear whether they would live alongside Rigids, or replace them. But at this point it's safe to say Markers is applicable to everything rigids can do with far greater performance and usability.
Which is why from this release onwards Rigids
are now to be considered deprecated.
Long live Markers!
The following few releases will be about transitioning from Rigids to Markers. Tutorials will be updated, the documentation too and you're encouraged to start using Markers for your everyday animation tasks.
Rigids will live on for the next few releases and eventually end up in a Legacy
sub-menu until being completely removed in February 2022.
February 2022 Deadline
If you didn't read the above, remember this date for when Active Rigid
and Active Chain
goes bye-bye.
There is now an option to download Ragdoll for MacOS! \ud83c\udf4e
Download for MacHeads Up
If you are a Mac user, please let us know how you get along. The builds were made on Big Sur and should work well with Big Sur, but Autodesk recommends El Capitan.
"},{"location":"releases/2021.11.15/#robust-rendering","title":"Robust Rendering","text":"This release has taken quite a while, and not because of MacOS support but because of rendering.
In short, we've had to throw out and rebuild a significant chunk of Ragdoll for this release. Everything related to lines, everything!
The reason is that an unlucky few of you have had the following experience with Ragdoll.
Those lines don't look quite right.. \ud83e\udd14
In short, the reason for this is that the Maya API for drawing lines ends up looking different across various graphics cards and versions of Maya. Maya 2019 was especially egregious.
But let's dig deeper.
"},{"location":"releases/2021.11.15/#digging-deeper","title":"Digging Deeper","text":"Animator?
This next part is mostly for techies, feel free to skip ahead.
Whenever Ragdoll drew shapes, like capsules and convex hulls, it used part of Maya's drawing API called MRenderItem
. Lines on the other hand - like those for limits and guides - were drawn using a simplified API called MUIDrawManager
.
drawManager->circle(point, radius);\ndrawManager->line(pointA, pointB, thickness);\n// And so on..\n
Which is a fantastic, well-designed API that has worked great for the past year. Until it didn't. As it happens, this API is broken.. Reports were coming in from all across the globe about lines looking like.. Well, like this.
Some if it I could replicate, this here is Maya 2019 in which the behavior is erratic. But the same could be said for some hardware and driver combinations; most of which I have never been able to replicate here.
This version throws all of that out the window, and reimplements it from scratch. It's a pity, because the API was very easy to work with and a great way to get started rendering in Maya.
That said, our new API is not only much faster but also much more powerful. You can expect to see a lot of new 2D rendering, including fully interactive UI elements in 3D space.
Until then, if you've been having issues with Ragdoll and lines, you can now breathe easy.
Caveat
This is great and all, but it no longer supports DirectX.
In the previous release, we already started moving away from DirectX, and if you've been using it you would have gotten some warnings about it. If not, then you've got nothing to worry about for this release.
OpenGL is where the action is at, and is supported equally on each platform; including MacOS!
"},{"location":"releases/2021.11.15/#robust-recording","title":"Robust Recording","text":"Recording now automatically ends up on an Animation Layer per default, with only the simulated controls associated with it. It is also at least 2x faster and less sensitive to quirks in a rig or skeletal hierarchy.
Here are the things it didn't take into account before, but does now.
And that should cover it!
Important
Recording is the most important aspect of Markers; if you can't get the simulation out then it's all for nothing. So do reach out via the..
..if you have any issues with this, and a fix will be crafted in a hot minute.
"},{"location":"releases/2021.11.15/#performance","title":"Performance","text":"I mentioned a 200% increase in performance, didn't I? Let's have a quick look (pun!).
Before
A solid 49 fps.
After
135 fps. The numbers speak for themselves.
At the end of the day, the main bottlenecks are out of Ragdoll's hands:
Sometimes, the simulation is really fast; it will usually be the fastest of the four. Other times, evaluating the rig is fast; such as if there are no keyframes and no fancy processing like follicles or spline IK. But the overhead from recording should approach zero as time goes on.
About (3), Ragdoll must evaluate your rig twice. Once to provide the simulation with your animation, and a second time to bake the resulting simulation back onto your controls.
Why so slow?
Interestingly, this is what made Active Rigid and Active Chain so slow. It was doing recording every frame, whether you wanted to or not. It was how the simulation was made visible to you; by continuously recording it.
With Markers, we delay the recording until you hit Record Simulation
, which is the primary way in which they enable us to reap this crazy amount of performance out of Maya.
Several improvements were made to Caching, introduced in the last version.
Caching whilst standing on the start frame could cause hiccups on occasion, this release fixes that.
Before
There was also a minor issue whereby if you cached half-way, revisited the start frame and then went back to resume caching, it would resume from the wrong spot and thus break the cache.
In either of these cases, one could disable and re-enable the cache to \"fix\" it, but now you don't have to!
Notice how it doesn't update the cache when standing on the start frame?
After
And, like before, you can enable caching via the solver. The only difference is that the menu item automatically plays through the entire timeline for you.
"},{"location":"releases/2021.11.15/#snap-to-simulation","title":"Snap to Simulation","text":"Yet another way to work with physics, by transferring individual poses from the solver into your animation. You can use it to pose or layout a scene.
Coming Up
An upcoming release will enable you to advance time in the simulation, without affecting time in Maya. Such that you can \"relax\" a pose, for example. \ud83d\ude01
"},{"location":"releases/2021.11.15/#frameskip-method","title":"Frameskip Method","text":"Ragdoll needs a consistent progression of time to provide reliable results. So per default, if it notices a frame being skipped, it kindly pauses and waits until you revisit the last simulated frame.
Alternatively, you can let it look the other way and pretend time has progressed linearly, like nCloth and countless other solvers do.
"},{"location":"releases/2021.11.15/#pause","title":"Pause","text":"The default. It's safe, predictable, but requires Play Every Frame
to work.
The nCloth and nHair default, of trying its best to simulate even though it wasn't given the frames inbetween. Unpredictable, unreliable but may handle playing along with sound.
Aside from not giving you the same result each time you play, if too many frames are skipped your simulation can completely explode. You can semi-work around this by increasing the number of substeps, forcing more simulation frames to fill for the missing frames.
Non-deterministic
Bear in mind that the Ignore
method cannot give you the same results each playthrough. The Pause
method is guaranteed to give you the same results, and are identical to what you get when you Record Simulation
too.
Get data out of the solver and into a baked joint hierarchy.
You can use this to build a library of animations, or to handle the retargeting from simulation to animation manually by just constraining to the resulting joint hierarchy.
Performance
Notice how fast this is!
"},{"location":"releases/2021.11.15/#a-debugging-companion","title":"A Debugging Companion","text":"It can also be used for situations where Record Simulation
doesn't do what you need it to. The extracted skeleton will be a plain joint hierarchy, with no scale, and guaranteed to match the simulation exactly. So you can extract it, and constrain your rig to it.
You've already given Ragdoll a go many moons ago, but really like where things have gone since? Well you're in luck. You can now request a re-trial!
You can now replace the original geometry assigned to your marker, just like you could with Rigids.
"},{"location":"releases/2021.11.15/#auto-limits","title":"Auto Limits","text":"Markers are now able to infer which axes to lock in the simulation, based on the locked channels of your control or joint.
Notice in this example how some of the channels are locked. With the Auto Limit
option checked, the corresponding limit axes will be locked too, such as to prevent the simulation from rotating around those axes.
If you forget or want to detect locked axes on an existing marker, you can use the Utility option too.
"},{"location":"releases/2021.11.15/#scale-mastery","title":"Scale Mastery","text":"Simplified and more robust, scale now handles well for all manner of shapes.
"},{"location":"releases/2021.11.15/#unloading-on-linux","title":"Unloading on Linux","text":"Linux users were not able to unload and later reload Ragdoll, without experiencing a fatal crash. This was a problem related to the dynamic licensing library not letting go of its TCP handle and forcing the plug-in to remain loaded, even though you kindly asked it to unload.
This has now been fixed, and the plug-in can safely be unloaded and reloaded and unloaded and reloaded over and over and over again. Enjoy!
"},{"location":"releases/2021.11.15/#path-and-windows","title":"PATH and Windows","text":"For TDs
The following is meant for administrators and TDs
With the introduction of Mac support a change was made to the way LimeLM - the licencing software used by Ragdoll - is distributed. Rather than being statically linked on Linux and dynamically linked but programatically located on Windows, it is now dynamically linked and automatically located on all platforms.
Windows Only
This only applies to Windows. Linux and Mac references the libraries relative the plug-in location. In short, you don't have to worry about it.
You don't have to care about this, unless you are on Windows and care about what's on your PATH
to which this happens.
# Windows\nos.environ[\"PATH\"] += \";\\\\Ragdoll\\\\shared\\\\windows\"\n
The change is coming from the Ragdoll.mod
file.
Why am I telling you this?
In the wildly unlikely chance that there is another plug-in using a different version of LimeLM in your arsenal, there may be a conflict whereby:
PATH
PATH
v0.5beta
v0.5beta
This will be resolved in a later version of Ragdoll, but until then, in the unlikely event there is a conflict, here's what you can do.
import os\nbefore = os.environ[\"PATH\"]\nos.environ[\"PATH\"] = \"/path/to/Ragdoll/shared:%s\" % before\ncmds.loadPlugin(\"ragdoll\")\nos.environ[\"PATH\"] = before\n
Namely, rather than loading Ragdoll from your plug-in manager, load it using this wrapper script. It will ensure Ragdoll's path is picked up ahead of any third-party plug-in, without negatively affecting anything around it.
"},{"location":"releases/2021.12.12/","title":"Interactive Manipulators","text":"Highlight for this release is The Manipulator!
This release marks the end of Active Rigid
and Active Chain
.
Important
If you read only one paragraph in this document, read this.
Tutorials have been updated, documentation as well and you are encouraged to use Markers
which are far superior in both performance and usability.
Legacy
submenu in the Ragdoll menuLet's kick things off with some eye candy!
Flying Lizard
A work-in-progress clip from Jason Snyman.
Ragdoll in 30 Seconds
A brief overview of what Ragdoll is.
Mocap Chap
Footage from one of the the new tutorials.
Now watch what happens when we increase the mass of the box by 50x. \ud83d\ude01
"},{"location":"releases/2021.12.12/#new-tutorials","title":"New Tutorials","text":"Have a look!
"},{"location":"releases/2021.12.12/#manipulators","title":"Manipulators","text":"
One of the most challenging aspect of Ragdoll to date is editing shapes and limits. These have now been greatly simplified via the use of \"manipulators\", similar to your standard Translate/Rotate/Scale manipulators. Except on steroids.
Here's a 21 second overview.
Before
Here's the equivalent process in the last version. Sped up by 4x.
It's is about as boring to watch as it was to make. \ud83d\ude04 Notice how shapes and limits need manual adjustment on both sides, because there was no symmetry. And notice how many clicks it takes to make one change, keep expanding that item in the Channel Box over and over and over.
"},{"location":"releases/2021.12.12/#activate","title":"Activate","text":"You have a few options for activating the manipulator.
Ragdoll -> Manipulator
T
on your keyboardShow Manipulator Tool
in the ToolbarAny of the Ragdoll nodes can be selected in order to enable the manipulator via the T
keyboard shortcut.
Solver Shape
At the time of this writing, the solver needs its shape selected, not the parent transform. This will be addressed in a future release.
A comfortable workflow is..
T
The selected Marker will be pre-selected in the manipulator.
Alternatively, press the Show Manipulator Tool
button in the Toolbar.
This release introduces a manipulator with two \"modes\".
Mode Description Shape Mode Edit shape properties, likeLength
, Radius
, Position
and Orientation
Limit Mode Edit limit properties, like Twist
and Swing
along with their pivots. In Shape Mode, you currently have 5 manipulators.
Manipulator DescriptionTranslate
Affects the Shape Offset
attribute Rotate
Affects the Shape Rotation
attribute Scale
Affects the Shape Radius
and Shape Extents
attributes Length
Affects the Shape Length
attribute, for the Capsule
shape HUD
Individual control over primary attributes, like Shape Extents
axes Translate
Hold the middle-mouse button to translate.
Rotate
Hold Ctrl + middle-mouse button to rotate.
Scale
Hold Ctrl + left-mouse button to scale.
Length
The Capsule
shape have additional in-view manipulators you can drag to affect each side independently.
HUD
Finally, attributes without a visual handle can be edited via the viewport HUD.
"},{"location":"releases/2021.12.12/#limit-mode","title":"Limit Mode","text":"In Limit Mode, you currently have 2 manipulators.
Manipulator DescriptionLimit
Affects the Limit Range XYZ
attributes HUD
For locking and enabling of limits Enable and Disable
Click the Axis
button to limit the rotation about a particular axis.
Lock and Unlock
Click the Lock
button to prevent all rotation about the axis.
Asymmetrical Edits
Hold Ctrl
to make asymmetrical edits
Some limbs start out at the center of their limit. Like your hip and neck. They are typically modeled to enable equal movement in each axis.
Other limbs, like the elbow and knee, are typically modeled in the extreme of their limit. Able to only rotate in one direction. For these cases, they need an asymmetrical limit.
With limits in multiple axes, keep an eye out for how asymmetrical edits to one axis affect the others.
Why are they moving?
Under the hood, each axis must be still be symmetrical; edits only appear to be asymmetrical for your convenience. What's really happening is the entire limit is both changing shape and also rotating and the rotation is causing all axes to move.
This is an inherent limitation of limits (pun!) in Ragdoll and is unlikely to be addressed in the future, so we'll have to work with it.
If you mess up and want to start from scratch, hit the Reset
button, also found under Ragdoll -> Utilities -> Reset Constraint Frames
Enabled per default, symmetry will mirror your edits across an axis.
There are 2 types of symmetry at the time of this writing.
Type DescriptionWorld
Look for a marker across the current axis in worldspace Pose
Based on the pose at the time of assigning markers, which is typically symmetrical. Each of which can be made symmetrical in either the X, Y or Z axes. The Pose
axis means you can make changes even if a character has been posed after having been assigned. A feature particularly useful when assigning to the A- or T-pose of a character rig.
Pose Based Symmetry
Because these controls were assigned in the T-pose of the rig, you can use Pose-based symmetry to make changes even when the character is currently asymmetrical.
Multiple Rigs
If two or more characters are present in the scene, and they were all rigged in the same pose, at the center of the world, then Ragdoll will only look at markers in the same rdGroup
as the selected Marker.
Search Distance
On the right-hand side of the Enable Symmetry
button, there is a Search Distance
gizmo.
Drag to edit this value
When you select a marker on one side, it will search for a marker at the opposite side of the axis you've chosen. Because positions are all approximate, it uses a maximum search distance to look for it.
Matches
Ideally, there should only be one match. But in a crowded hierarchy there may be several. Tune the Search Distance
to control the number of matches, to ensure it doesn't pick the wrong one.
Disable Symmetry
to enable multi-select
Hold Shift
to select and manipulate multiple markers at once.
Drag-select
Will be added in a future release.
"},{"location":"releases/2021.12.12/#undo-redo","title":"Undo & Redo","text":"No surprises here.
Changes made using the manipulator is undoable as you would expect, with the exception that it currently does not let you undo the selection itself like normal Maya selection does; this will be addressed in a future release.
"},{"location":"releases/2021.12.12/#fit-to-view","title":"Fit-to-view","text":"Tap the F
key to fit any selected Marker(s) to the view, like you would expect from selected Maya nodes.
Caveat
This currently only applies if you've activated the manipulator using the Ragdoll -> Manipulator
menu item, or have the rdSolver
shape node selected.
Click the Select Node
button to select this node in Maya
Per default, Ragdoll and Maya selection are separate. You can have Maya select the node(s) currently seleted in Ragdoll by pressing the Select Node
button.
You can automate this using the Synchronise
button at the far-left of the HUD.
Why is this not on per default?
The solver is what is actually being fitted. If the selection is changed to a marker (which is not a DAG node, and therefore lacks a visual representation) then fit-to-view no longer works.
This will be addressed in a future release and made into the default.
With Multi-select or symmetry enabled, all selected markers will be selected in Maya, to make bulk edits via the Channel Box easier.
"},{"location":"releases/2021.12.12/#manipulator-help","title":"Manipulator Help","text":"On the right-hand side is an overview of the hotkeys and mouse button combinations you can use, and what they do.
It can be hidden via the HUD button on the upper right-hand side.
"},{"location":"releases/2021.12.12/#quality-of-life","title":"Quality of Life","text":"More of this!
"},{"location":"releases/2021.12.12/#1d-2d-and-3d-limits","title":"1D, 2D and 3D Limits","text":"Ragdoll used to have a preference as to which axes you use for limits.
X
is great for 1D limits, like a hinge, elbow or kneeYZ
is great for 2D limits, like a shoulder or hipBut XY
is no good. XZ
is also bad. And god forbid you should attempt use Y
or Z
as a hinge limit. Ragdoll would try, but try in vain.
Knowing which combination to use is not easy, and now you no longer have to. Pick an axis, any axis or combination of axes and Ragdoll will figure things out on its end. You don't have to worry about it.
As an added bonus, the limit axis now aligns with your Maya axis! (with one caveat, see below)
Here's a table to make this absolutely clear. \ud83e\udd70
Maya Rotate Axis Ragdoll Limit AxisX
= X
Y
= Y
Z
= Z
Caveat
With one exception, see Asymmetrical Limits under Limit Mode above. As soon as they rotate, they will no longer align with Maya; which isn't a problem most of the time, but can be.
"},{"location":"releases/2021.12.12/#cache-on-record","title":"Cache On Record","text":"Previously, when you recorded your simulation back onto your character rig, a new simulation would kick in the next time you played. And because your character rig has now changed - to follow the original simulation - the new simulation will be different.
This makes logical sense but can be unexpected. So now, the Cache
attribute on the solver is automatically enabled to let you compare and contrast your character rig with the simulation; and avoid needless re-simulating when what you really wanted was to record-and-forget.
Once you're ready to re-simulate, run the Uncache
command or set the Cache
attribute back to Off
.
Pose Deltas are now cleaner and more performant (up to 10x).
Deltas are the triangular-looking shapes drawn to visualise the difference between your animation and the current simulation. They are now only drawn when there is at least some difference, which means the vast majority of them in a complex scene are now not drawn, speeding up your viewport significantly.
Before
After
Notice how they only appear if there is actually a difference between the animation and simulation.
"},{"location":"releases/2021.12.12/#ground-fits-grid","title":"Ground Fits Grid","text":"Previous releases would put a ground underneath the first assigned controls, with a size relative the size of your selection.
Turns out, this wasn't great in practice and usually ended up being too small. In this release, the ground inherits whatever size your viewport grid is.
"},{"location":"releases/2021.12.12/#auto-limits-ii","title":"Auto Limits II","text":"The previous release introduced Auto Limits whereby Ragdoll would look at the locked-state of your Rotate
channels and try to figure out how to replicate this effect physically.
This sometimes worked, sometimes not. This release fixes that, covering all combinations of locked channels, with any manner of joint or rotate axis.
Here's what locking the Rotate channels will result in.
Unlocking them, we can see how much of an effect it has.
Thanks to the more robust and predictable limits in this release, the Maya axis will now always align with the Ragdoll limit axes!
"},{"location":"releases/2021.12.12/#lollipop-hierarchy","title":"Lollipop Hierarchy","text":"The Create Lollipop
option of Markers generates an extra control shape in the viewport that you can use to manipulate a Marker. The goal being to make it easier to spot a Marker in a potentially busy channel box.
But the last release didn't let you use Assign Hierarchy
with Create Lollipop
without ending up with a broken hierarchy.
Before
After
"},{"location":"releases/2021.12.12/#disappearing-limits","title":"Disappearing Limits","text":"The limit indicator is drawn using a 2D drawing API which is initialised whenever a Solver is created. It was however uninitialized whenever any Solver was deleted, so if you had 2 solvers you were out of luck. A re-open of the scene would fix it, but it was annoying and incorrect.
This has now been fixed.
"},{"location":"releases/2021.12.12/#replace-intermediate-mesh","title":"Replace Intermediate Mesh","text":"In the previous release, if a mesh had a second \"intermediate\" mesh it would be more difficult to use it with the Replace Mesh
command.
Before
After
Here's it working with intermediate shapes, and the new Maintain History
option which was always true in the previous release.
Without it, modifications to the original mesh are ignored; such as a skinned mesh.
"},{"location":"releases/2021.12.12/#transform-limits","title":"Transform Limits","text":"Recording onto transforms with Maya's native limits on them could result in this.
This has now been fixed.
How?Since you asked, they are simply disabled. I've never seen or heard of anyone actually using these and was surprised to find they were in active use by the native motion capture library that ships with Maya.
If you or anyone you know do use them, let me know and they will be given support.
"},{"location":"releases/2021.12.12/#separate-translate-xyz-amount","title":"Separate Translate XYZ Amount","text":"The Pose Stiffness
in World
space affected each axis equally.
You can now control each axis independently, to for example follow an input animation closely along the ground plane, the X and Z-axes, but allow for it to deviate along the Y-axis,
"},{"location":"releases/2021.12.12/#separate-twist-and-swing-amount","title":"Separate Twist and Swing Amount","text":"The Pose Stiffness
and Pose Damping
parameters of Markers apply to both Swing and Twist - that is, rotations around the X and YZ axes.
You can now control these independently, for an even finer control over the resulting simulation.
"},{"location":"releases/2021.12.12/#maya-exit","title":"Maya Exit","text":"There was a memory leak, whereby Maya would sometimes freeze on exit, with an anomymous-looking dialog box appearing on Windows.
This has been fixed.
"},{"location":"releases/2021.12.12/#customised-recording","title":"Customised Recording","text":"Some rigs don't work with Maya's default Parent and Orient constraint. As a result, neither does Record Simulation
or Snap to Simulation
because those commands use these default constraints.
If this is you, then I have good news. You can now override the command responsible for creating these constraints with one that uses your custom in-house constraints instead.
Minor maintenance release.
As is tradition, we must start with candy. Now, it's only been 3 days so all I have for you today is this amazing piece of animation here. \ud83d\ude05
Wyvern 2
Follow-up to the WIP from last release from The Wizard, a.k.a. Jason Snyman.
Wasp
Here's a response to a question on LinkedIn about whether or not you can use Ragdoll to make animation cycles. So here are 3 parts.
Total time spent 1h, including rigging and skinning. The model is a default Maya model from the Content Browser.
"},{"location":"releases/2021.12.15/#clean-channel-box","title":"Clean Channel Box","text":"With the manipulator in the last release, the Channel Box saw a huge spring cleaning.
Before AfterIt was, however, a little too aggressive. Some of the attributes were still useful, especially for making sweeping changes across lots of markers at once. So in this release, you know have the option of:
Assign
via the Option DialogRagdoll -> Utilities -> Toggle Marker Attributes
More specifically, the environment variable MAYA_ENABLE_VP2_PLUGIN_LOCATOR_LEGACY_DRAW
, is still in use in some studios. This variable would cause the Manipulator UI to be unselectable.
This has now been fixed.
"},{"location":"releases/2021.12.15/#collision-group","title":"Collision Group","text":"Lone markers, like boxes and other environment assets and props have an Overlap Group
like any other. But unless they are also part of a group, they would sometimes not respect the Overlap Group
, requiring a scene re-open in order to take effect.
This has now been fixed.
"},{"location":"releases/2021.12.15/#z-up","title":"Z-up","text":"The default ground now correctly fits the grid even in a Z-up Maya scene.
"},{"location":"releases/2021.12.15/#double-hud","title":"Double HUD","text":"The Manipulator HUD could sometimes fight with Maya's default HUD. Now it'll step aside temporarily until the manipulator is done.
Room to improve
It will temporarily toggle the Maya HUD on/off in the currently active viewport, based on the viewport your mouse is currently hovering. This can get finnicky sometimes. If it does, the option toggled is the one under Display -> HUD
in the Maya viewport.
This will be improved in a future release.
"},{"location":"releases/2021.12.15/#robust-viewport-icons","title":"Robust Viewport Icons","text":"The viewport icons would sometimes be unselectable.
This was due to Maya being unable to provide Ragdoll with the correct \"Active View\", which Ragdoll uses to map your mouse to 3D. This has now been fixed, by no longer relying on the Active View.
"},{"location":"releases/2021.12.15/#edit-constraint-frames","title":"Edit Constraint Frames","text":"The previous release simplified limits by a lot, but there are still cases where the default orientation of some rig controls ends up in a funny situation.
Note
This does not matter to the simulation. It is only a rendering artefact.
To make this a little easier to work with, you can rotate the entire limit like this.
Note
You don't need the locators once you are done editing them, you should definitely delete them.
This will be made redundant in a future version as it gets much too technical and too easy to shoot yourself in the foot. If you make a mistake, delete the locators and call Reset Constraint Frames
in the same menu to start again.
Highlight for this release is Ragdoll 2.0!
Let's start with the good stuff.
Medusa Breakdown
Excellent Animation and breakdown by Andras Ormos.
Batman Learning Cursive
Animation by Jason Snyman, with a very interesting approach to getting ink out of a pen digitally. \ud83d\ude04
DMV Lady
Courtesy of Dragana Mandic.
Scalable Rig, Scalable Ragdoll
No special setup required, if your rig is scalable then so is Ragdoll.
Circus Import
Toying with the ability to import characters into the same solver.
The Ocean
Give a man a fish, and you'll feed him for 2 ragdolls.
Noodles
Something from the Linux world.
"},{"location":"releases/2022.01.17/#ragdoll-20","title":"Ragdoll 2.0","text":"Since 28th July 2021, Ragdoll has been publicly available under the \"early bird\" umbrella. It started out with a reduced price point for those brave enough to venture into new territory and expect a few left turns every now and then as kinks are worked out in the software.
Now the time has come to step into the world as an adult piece of software with the guarantees of any commercially available software and a pricing to reflect that.
And as Ragdoll has grown significantly since those days - given the new Markers - it's only reasonable to consider this Ragdoll 2.0.
"},{"location":"releases/2022.01.17/#january-voucher","title":"January Voucher","text":"Pricing has now reached its intended price point, leaving Early Bird behind. For the next two weeks however, you can use this voucher code to get the Early Bird discount before the deadline.
Ragdoll Unlimited
uX1bFhjZ
The Ragdoll of today is very different from the Ragdoll of July 2021.
Back then, I had no idea that this amount of performance and usability was possible and was prepared to cram tutorials and documentation until everyone was accustomed to the complexity of physics simulation. \ud83d\ude04
But then something happened - Markers. Like lightning from a clear sky, it unexpectedly changed everything. Performance is now far beyond what Maya is expected to handle, with physics much much faster than simply skinning of a character, and close to the performance of native IK handles. This opens up a lot of possibilities.
The problems faced back then..
None of those problems are a problem with Markers. Because Markers look at the world from a different perspective, they just work. It made Ragdoll not only more user friendly and significantly faster but also simpler to develop and smaller in size. The code for Markers is about \u2153 of the equivalent for Rigids. Just think about that!
And most of all, it opened up for all the things you are about to see happen for Ragdoll in the coming months. \ud83d\ude43
"},{"location":"releases/2022.01.17/#ragdoll-flavours","title":"Ragdoll Flavours","text":"Let's take a quick look at the different versions of Ragdoll and how they differ.
Flavour Description Ragdoll Unlimited The fully-featured, unrestricted version of Ragdoll. When people talk about Ragdoll, this is the version they mean. Ragdoll Complete The cost-effective flavour of Ragdoll, suitable for freelancers and indie studios. It lacks studio-conveniences such as a Python API for pipeline integration, export to JSON for sharing of physics configurations and is less performant than \"Ragdoll Unlimited\", being unable to operate in parallel across multiple cores. Ragdoll Batch A non-interactive version without ability to render into the viewport. Suitable for automation and pipeline integration. Ragdoll Personal A non-commercial version, suitable for students and anyone wanting to fool around with Ragdoll at home. It is identical to Unlimited, except that it has limits on how much can be recorded and exported. Ragdoll Educational A non-commercial version of Ragdoll Unlimited whose saved scenes cannot be opened with a commercial licence. Ragdoll Trial A non-commercial first experience with Ragdoll; this is what you get when downloading Ragdoll onto a new machine and use it without activating it first. Similar limitations to Personal, except it also expires about a month after first use. "},{"location":"releases/2022.01.17/#ragdoll-unlimited","title":"Ragdoll Unlimited","text":"This is the version you want.
It contains everything mentioned on any website, is capable of doing everything you've seen Ragdoll do and is the unrestricted, unlimited and gold standard of Ragdoll.
"},{"location":"releases/2022.01.17/#ragdoll-complete","title":"Ragdoll Complete","text":"This is the version for freelancers.
It is Ragdoll Unlimited, with a few limitations.
Performance is limited in how quickly Ragdoll is able to read from your character. Ragdoll is natively parallel, but Complete turns any character you assign markers to into a Serial affair. Limiting performance by the number of cores you have in your machine.
The advantage of export is that your rigs don't need physics built-in. They can remain simple and without physics, until the animator actually needs it. This feature is limited to 10 markers; for the time being. Generally, export is reserved for Unlimited and users in need of pipeline integration. But Complete let's you get at least a taste of the comfort and flexibility of exporting your physics contraptions from one scene and importing onto an unsuspecting character in another.
Like Export, the ability to interact with Ragdoll through Python is an important part of any production pipeline; not so much for the individual animator of small indie studio.
Info
At the time of this writing, this limitation is not yet in place, and users of Complete is currently able to utilise the Python API just like users of Unlimited. This will be addressed in an upcoming release.
"},{"location":"releases/2022.01.17/#ragdoll-batch","title":"Ragdoll Batch","text":"This is the version for your render farm.
It's a low-cost alternative to Ragdoll Unlimited, without the ability to render into the viewport. Making it effectively useful only via Python. It is also unable to export and lacks the parallelism of Unlimited.
Unlike all other flavours, a Batch licence is reserved per-process; meaning that if you spin up 2 mayapy
instances on the same machine, it will occupy 2 licences. This obviously only works if your licences are floating, as otherwise a machine can only carry a single node-locked licence, limiting it to a single process running Ragdoll Batch.
Leaving Early Access, Ragdoll is stepping into the world as a 1.0. Here's an overview of what you can expect from now on.
Feature Trial Personal Complete Unlimited Batch Commercial Use \u274c \u274c \u2714\ufe0f \u2714\ufe0f \u2714\ufe0f Interactive Tools \u2714\ufe0f \u2714\ufe0f \u2714\ufe0f \u2714\ufe0f \u274c Python API \u2714\ufe0f \u2714\ufe0f \u274c \u2714\ufe0f \u2714\ufe0f Multi-Threading \u2714\ufe0f \u2714\ufe0f \u274c \u2714\ufe0f \u274c JSON Import/Export \u2714\ufe0f \u2714\ufe0f \u274c \u2714\ufe0f \u274c Per-machine Licence \u2714\ufe0f \u2714\ufe0f \u2714\ufe0f \u2714\ufe0f \u274cBatch
has a per-process licence, meaning it will occupy one seat per individually running process.
Trial and Personal licences are non-commercial, meaning they can't be used for commercial purposes. Such as in a studio, or for anything where money is involved.
When a file saved with a non-commercial licence of Ragdoll is opened in a commercial licence, it'll temporarily turn your licence into a non-commercial licence.
Feature Unlimited Complete Non-commercial Export Unlimited markers Up to 10 markers Up to 10 markers Record Unlimited frames Unlimited frames Up to 100 framesEarly Birds
Did you purchase a Ragdoll Personal licence before this release?
Then as thanks for believing in us and joining early, these limits do not apply to you. Your version is still unrestricted for non-commercial use.
Enjoy! \ud83e\udd70
"},{"location":"releases/2022.01.17/#import","title":"Import","text":"You can now import a Ragdoll setup exported from Maya, back into Maya. It'll re-create everything just the way it was.
Can I export scenes I made with an earlier version?Yes, anything made with Markers can be exported regardless of when it was made.
What is included in the export?Just about everything.
Very little.
Yes, anything else is a bug.
More precisely, determinism depends on (1) the type and number of items in the solver along with (2) the order in which these are created. Both of these are part of the exported file format and is taken into account during import. Meaning you should get identical results so long as the content is the same.
"},{"location":"releases/2022.01.17/#example","title":"Example","text":"Here's an exported Ragdoll setup for the free CG Spectrum Tiger rig.
2.8 mb
)To use it, download the rig and import the Ragdoll file.
It contains 2 levels of detail.
Level Content Level 0 Body and feet Level 1 Everything on Level 0, plus toes "},{"location":"releases/2022.01.17/#workflow","title":"Workflow","text":"Here's the rundown.
On import, Ragdoll will try and find the names of what you exported in your currently opened scene.
Namespace
dropdown menu.Search and Replace
fields to modify the names searched for by Ragdoll.Export
Once you're happy with your character, it's time to export. Towards the bottom of the UI, you'll get a preview of what is about to be exported. This can help clarify that what ends up on disk is what you expect.
Import
In a new scene, with the same character, same names and everything, import as you'd expect. At the bottom of this UI, you'll get a preview of what's in the file on disk, along with how it will associate the node names found in the file with what you have on disk.
"},{"location":"releases/2022.01.17/#namespace-from-file","title":"Namespace from File","text":"Odds are, the character you're importing either has no namespace, or has a different namespace to what you've currently got in your scene. As in this example here, with 3 copies of the same character, each with its own namespace.
Use the Namespace
dropdown to select one of the current namespaces in your scene, or Custom
to type one in yourself.
Per default, Ragdoll will import the file into the current solver in your scene, if any. Or, you can import the original solver from the source file.
"},{"location":"releases/2022.01.17/#known-limitations","title":"Known Limitations","text":"Here are a few things that will be addressed over time. Let us know if you encounter anything else!
Ragdoll can now automatically compute a suitable mass for each Marker, based on the volume of your shape and a density of your choosing.
In other words, big objects become heavy, small objects become light.
Before
After
"},{"location":"releases/2022.01.17/#presets","title":"Presets","text":"Provide a custom density, or choose from one of the provided ones.
Density ValueOff
Do not compute, use the Mass
attribute Cotton
Very sparse, 0.05 grams per cubic centimeter Wood
Sparse, 0.2 grams per cubic centimeter Flesh
Default, 1.0g/cm3 Uranium
Dense, 19.0g/cm3 Black Hole
Very, very dense Custom
You pick Mass is computed based on the volume of your shape, along with a density of your choosing.
"},{"location":"releases/2022.01.17/#options","title":"Options","text":"Choose between various densities either at creation-time or after creation.
"},{"location":"releases/2022.01.17/#visualise","title":"Visualise","text":"The computed mass updates interactively as you change the size and type of your shape, including convex hulls!
In the Manipulator, you'll be able to not only only edit the density, but preview the computed mass given the current shape volume and density you provide.
"},{"location":"releases/2022.01.17/#level-of-detail","title":"Level of Detail","text":"Setup your character once with all bells-and-whistles, and interactively pick which level of detail to use for your simulation in a given situation.
Usecases
Level 0
, fingers at Level 1
Level 1
, muscles at Level 2
Level 0
, extremities at Level 1
and Level 2
For example, here's a Wasp character with 3 levels of increasing detail.
As you'd expect, it'll record only the currently active markers.
"},{"location":"releases/2022.01.17/#workflow_1","title":"Workflow","text":"Here's how it works.
1
1
And that's it! Any marker with a matching level is simulated and recorded.
"},{"location":"releases/2022.01.17/#operators","title":"Operators","text":"What does each level mean? The answer lies in the \"operator\".
Operator DescriptionLess Than
If the Marker Level
is less than (or equal) to the Solver Level
, simulate it. Greater Than
If the Marker Level
is greater than (or equal) to the Solver Level
, simulate it. Equal
If the Marker Level
is equal to the Solver Level
, simulate it. NotEqual
If the Marker Level
is not equal to the Solver Level
, simulate it. With these, you can use each level for..
With Equal
and NotEqual
operators, you can have some markers appear or disappear on particular levels, enabling endless combinations.
Roadmap
This should cover a majority of cases, but there are things you cannot yet do, but will be able to in the future.
Capsule
on one level, Mesh
on another. For higher-resolution contacts.For the geeks out there, here's what the underlying algorithm looks like in Python.
# Membership types\nMinimum = 1 # Present at this level and higher\nMaximum = 3 # Present at this level and lower\nOnly = 4 # Only present at this level\nNot = 5 # Present at all levels *except* this one\n\nmarkers = [\n {\"name\": \"hip\", \"level\": 0, \"membership\": Minimum},\n {\"name\": \"spine\", \"level\": 0, \"membership\": Minimum},\n {\"name\": \"neck\", \"level\": 0, \"membership\": Minimum},\n {\"name\": \"head\", \"level\": 0, \"membership\": Minimum},\n {\"name\": \"L_upper_leg\", \"level\": 0, \"membership\": Minimum},\n {\"name\": \"L_lower_leg\", \"level\": 0, \"membership\": Minimum},\n {\"name\": \"R_hand\", \"level\": 1, \"membership\": Minimum},\n {\"name\": \"L_foot_box\", \"level\": 1, \"membership\": Maximum},\n {\"name\": \"L_foot_convex\", \"level\": 2, \"membership\": Minimum},\n {\"name\": \"R_toe_capsule\", \"level\": 2, \"membership\": Not},\n {\"name\": \"R_toe_convex\", \"level\": 2, \"membership\": Only},\n]\n\ndef resolve(level):\n print(\"Level %d\" % level)\n for marker in markers:\n if marker[\"membership\"] == Minimum and marker[\"level\"] <= level:\n print(\" - {name} ({level})\".format(**marker))\n\n if marker[\"membership\"] == Maximum and marker[\"level\"] >= level:\n print(\" - {name} ({level})\".format(**marker))\n\n if marker[\"membership\"] == Only and marker[\"level\"] == level:\n print(\" - {name} ({level})\".format(**marker))\n\n if marker[\"membership\"] == Not and marker[\"level\"] != level:\n print(\" - {name} ({level})\".format(**marker))\n\nresolve(0)\nresolve(1)\nresolve(2)\n
Run this, and this is what you'll find.
Level 0\n - hip (0)\n - spine (0)\n - neck (0)\n - head (0)\n - L_upper_leg (0)\n - L_lower_leg (0)\n - L_foot_box (1)\n - R_toe_capsule (2)\nLevel 1\n - hip (0)\n - spine (0)\n - neck (0)\n - head (0)\n - L_upper_leg (0)\n - L_lower_leg (0)\n - R_hand (1)\n - L_foot_box (1)\n - R_toe_capsule (2)\nLevel 2\n - hip (0)\n - spine (0)\n - neck (0)\n - head (0)\n - L_upper_leg (0)\n - L_lower_leg (0)\n - R_hand (1)\n - L_foot_convex (2)\n - R_toe_convex (2)\n
"},{"location":"releases/2022.01.17/#markers-api","title":"Markers API","text":"With the retirement of the legacy Python API, a new Markers API is now available.
from maya import cmds\nimport ragdoll.api as rd\n\nbox = cmds.polyCube()\n\nsolver = rd.createSolver()\nmarker = rd.assignMarker(box[0], solver)\n\nrd.recordPhysics()\n
The new export and import mechanic can be accessed from here too.
import ragdoll.api as rd\nfname = r\"c:\\path\\to\\my_ragdoll.rag\"\n\n# Get everything out\nrd.exportPhysics(fname)\n\n# Remove everything\nrd.deleteAllPhysics()\n\n# Bring everything back\nrd.reinterpretPhysics(fname)\n
"},{"location":"releases/2022.01.17/#legacy-api","title":"Legacy API","text":"The old Rigid API is still accessible under a new home.
from ragdoll.legacy import commands\ncommands.create_active_rigid()\ncommands.create_point_constraint()\n# ...\n
But will be removed entirely soon, so do transition away from it ASAP.
"},{"location":"releases/2022.01.17/#quality-of-life","title":"Quality of Life","text":"Make it more difficult to make mistakes with these new additions. \ud83d\ude0a
"},{"location":"releases/2022.01.17/#max-mass-ratio","title":"Max Mass Ratio","text":"With Density
, there's a chance Markers get Ragdoll into a situation it does not like; namely that the difference between masses are too great.
As you wish. \ud83e\udd13
Ragdoll doesn't like differences any greater than 10x, sometimes 100x, else it can fail or become unstable. For example, if the torso of your character has a mass of 100kg, and the foot Marker has a mass of 0.5kg, that's a ratio of 100/0.5 = 200x which is far greater than Ragdoll would like. As a result, the body would crush the foot which would be unable to properly hold the entire body up.
Up until now, the masses on all Markers have had a default value of 1kg. Meaning that regardless of the size of a Marker - be it the torso, the head or tip of a finger - it would always have a mass of 1.0. As a result, hands would typically end up far heavier than the rest of the body.
Before
Here's an example of the solver failing. There are three identical chains, the tip of the last one having a mass of 10,000. That's 10,000x greater then each link in the chain. As a result, Markers separate; that is incorrect.
After
If we limit the maximum ratio to just 1000x, we get the correct behavior. You can also see how it affected the other two chains. They now behave more similarly, because in order to ensure a mass ratio across the whole system, the mass of their tips need to be reduced as well.
The new Max Mass Ratio
attribute protects against these situations, letting you give objects a suitable mass and only have to worry about which should weigh more, and which should weigh less. Ragdoll will balance everything out before passing it along to be simulated.
What are the consequences?
Sometimes, large mass ratios are what you want. For example, a heavy weight on a string tends to do quite well with ratios up to 1000x. But markers being crushed by another marker 1000x its weight tends to not do as well.
So the result is less of an effect at the extreme ratios.
In the Manipulator, you can preview the final mass used given the density and the ratio you specified.
"},{"location":"releases/2022.01.17/#directx","title":"DirectX","text":"Look. Closely. Look. Closlier.
That's right! You've now got the option to use Ragdoll with Maya in DirectX viewport mode.
"},{"location":"releases/2022.01.17/#truly-non-keyable","title":"Truly Non-keyable","text":"Some Ragdoll attributes are keyable, others are not. Which is which? Impossible to say. Until now!
On attempting to keyframe a non-keyable attribute, you'll now see an error message along with a visual cue things might not work out the way you expect. As opposed to happily setting that keyframe but then ignoring it once the simulation starts, like it used to.
A little quality of life for ya'!
Pro-tip for Riggers
There are at least 2 ways to prevent non-keyable attributes from being keyframed.
MFnAttribute::setConnectable(false);
MPxNode::legalConnection()
The former means you are also unable to make a control and connect it to multiple non-keyable attributes. Like if you wanted to control Mass
of a series of markers from a single source, or the Overlap Group
.
The latter on the other hand is more flexible. It allows Ragdoll to prevent connections to specific attributes or types of nodes, like animCurve
nodes, which means animators won't be able to keyframe it but you'll still be able to build controls for it.
And that's exactly how it works.
"},{"location":"releases/2022.01.17/#delta-drawing-bug","title":"Delta Drawing Bug","text":"The worldspace deltas were drawn separate from the marker they affected, which could produce a jarring effect especially when the solver position had been offset.
Before
After
This has now been fixed.
More Performance
As an added bonus, we're now also doing 2 matrix multiplications less per frame, per marker. That kind of thing adds up quickly.
"},{"location":"releases/2022.01.17/#shape-sync","title":"Shape Sync","text":"If you play, pause and then change the Shape
from Box
to Capsule
nothing happens. Because the shape, like many other attributes, can only be changed on the start frame.
But, when you later returned to the start frame, the shape would still not update. This has now been fixed.
"},{"location":"releases/2022.01.17/#profiler-view","title":"Profiler View","text":"Mostly meant to keep the development of Ragdoll fast and interactive, you can now spot where most time is spent via the built-in Maya Profiler.
Here's what one frame of this looks like; 5 ms to both simulate and render Ragdoll in the viewport.
"},{"location":"releases/2022.01.17/#removed-attributes","title":"Removed Attributes","text":"These attributes were no longer relevant in the last release, but were still present in the Channel Editor. These have now been hidden and will no longer be saved with your file. A few weeks from now, they will be removed.
limitAutoOrient
limitType
limitAxis
limitOffsetX
limitOffsetY
limitOffsetZ
limitOffset
limitRotationX
limitRotationY
limitRotationZ
limitRotation
It has come to my attention that the first thing every new user of Ragdoll sees is this dialog, with this message for a serial number.
And yet..
Nobody has said a thing! \ud83e\udd23
Correction shout-out to @Rosaline for pointing this out just a few days ago!
According to my Mandarin-speaking friends, this is jibberish (or at least should be!) and is a result of badly translated Unicode to ASCII characters.
This has now been fixed!
"},{"location":"releases/2022.01.21/","title":"Maintenance Release","text":"Minor release with some fixed for you, especially Floating Licence users.
In addition to recording your simulation, you can also snap your rig to wherever the simulation is currently at.
However this only applied to things that aren't yet keyframed. Useful to layout and setting of an initial pose for your character.
With this release, it will also keyframe your rig, such that you can use it to interactively animate a character on specific frames, as you simulate. You know what, it's easier to just show you. \ud83d\ude04
"},{"location":"releases/2022.01.21/#commercial-floating-licence","title":"Commercial Floating Licence","text":"A glitch was found that turned Floating Licences into non-commercial licences, imposing the recording and exporting limits of 100 frames and 10 markers.
This has now been fixed.
"},{"location":"releases/2022.01.21/#limits-and-export","title":"Limits and Export","text":"The new Import functionality introduced in the last version neglected to include limits, this has now been fixed!
"},{"location":"releases/2022.01.21/#z-up-is-inconsistent","title":"Z-up is Inconsistent","text":"One user experienced having their gravity turned sideways, thinking Maya was configured with Z-up when really it was Y-up. It still unclear exactly why this happened, but the one potential edgecase has now been strengthened. If you experience gravity facing the wrong way, or the ground plane being orthogonal to your viewport grid, let us know!
"},{"location":"releases/2022.01.21/#scaled-limits","title":"Scaled Limits","text":"When your rig or controls are scaled, the Manipulator wasn't able to accurately provide you with the limit handles. This has now been fixed.
"},{"location":"releases/2022.01.21/#manipulator-and-viewport-shadows","title":"Manipulator and Viewport Shadows","text":"It used to be the case that the manipulator became invisible whenever viewport shadows was enabled. This has now been fixed!
"},{"location":"releases/2022.02.01/","title":"Quality of Life","text":"Highlight for this release is Quality of Life!
Let's start with the good stuff.
Pounce
Our Manikin is stuck!
Batman Writes
A behind-the-scenes from Jason's cool constraint setup.
"},{"location":"releases/2022.02.01/#kinematic-dynamic","title":"Kinematic & Dynamic","text":"Also known as \"Animated\" and \"Simulated\"
Marker behaviour has been simplified.
Groups are now either Kinematic
- for fully animated, no physics involved - or Dynamic
for having things affected by gravity and contacts with other Markers.
In the above example, I'm alternating between Kinematic
and Dynamic
for the entire character.
Changed
As part of this simplification, two things have changed.
Initial State
was removedPose Match
was renamed to Dynamic
Initial State can be achieved with Dynamic
and a Pose Stiffness
of 0
.
And like before, individual markers can be overridden to be either Kinematic
or Dynamic
. When set to Inherit
it continues to use whatever value was found in the group.
..speaking of which!
"},{"location":"releases/2022.02.01/#group","title":"Group","text":"In the previous version, a group was automatically created whenever you assign to a connected series of controls.
This release enables you to group standalone markers too, and to retroactively group markers in any way you please.
"},{"location":"releases/2022.02.01/#new-group","title":"New Group","text":"Select some markers, put them in a group.
"},{"location":"releases/2022.02.01/#move-to-group","title":"Move To Group","text":"Select one or more markers, along with a destination group, and move them.
"},{"location":"releases/2022.02.01/#group-on-assign","title":"Group on Assign","text":"When assigning markers, you are now also able to pick which group to put it into, or whether to make a new group. Or no group!
"},{"location":"releases/2022.02.01/#lollipop-20","title":"Lollipop 2.0","text":"Lollipops now feature Marker and Group attributes in the Channel Box; less clicks!
"},{"location":"releases/2022.02.01/#customisable","title":"Customisable","text":"Rotate and scale the resulting lollipops to fit your rig and workflow.
"},{"location":"releases/2022.02.01/#retroactive-lollipops","title":"Retroactive Lollipops","text":"Should you have markers without a lollipop, assign them afterwards using the Lollipop menu item. This is also where you can customise which attributes should appear on them.
Pro tip
The Use Proxy Attributes
option makes attributes editable both on the Lollipop and on the original Marker. The downside however is that they make life in the Graph Editor less pleasant. \ud83e\udd14
Some improvements and reshufflings to make your life more complete. \ud83e\udd70
"},{"location":"releases/2022.02.01/#robust-recording","title":"Robust Recording","text":"There hasn't yet been any rig not supported by Ragdoll, until last week when @mandala got in touch with a new challenge. A rig made with an rigging system plug-in called Contour.
Recording this rig results in cycle warnings, presumably because part of how it operates depends on viewport updates.
In this update, there is a (default) Nice and Steady
option for recording which ensures the viewport stays up-to-date with the dependency graph, and that did the trick!
Importing markers onto a character in a different group, or a different character altogether, could be tricky since their hierarchies would differ.
There is now an option to find a matching control by name rather than its full path.
In this example, the character has a different parent group than when it was exported, changing all of the full paths to each control.
"},{"location":"releases/2022.02.01/#scale-replace","title":"Scale Replace","text":"In the case of scaled markers with a replaced mesh, this happened.
Before
But no longer!
After
"},{"location":"releases/2022.02.01/#offline-activation-wizard","title":"Offline Activation Wizard","text":"The offline activation process has now been streamlined; no longer requiring an email conversation back and forth. It should take some of our load off, whilst at the same time enabling you to offline activate when we are sleeping. \ud83d\ude05
Activation
Deactivation
"},{"location":"releases/2022.02.01/#offline-trial-notification","title":"Offline Trial Notification","text":"Whenever someone attempts to trial Ragdoll, but their machine is not connected to the internet, they would receive a message about how their Trial has expired.. Even though it was never activated in the first place!
This has now been fixed.
"},{"location":"releases/2022.02.01/#world-translate-visualisation","title":"World Translate Visualisation","text":"The translation component of the World Pose Space wasn't very visible before, now it is! It's also drawn using the color of the Marker it's associated with, to aid in figuring out what it's actually affecting. And also make things a little nicer to look at.
Before
After
"},{"location":"releases/2022.02.01/#record-leaving-joints-behind","title":"Record Leaving Joints Behind","text":"Sometimes, Ragdoll could leave some remains after recording your simulation. This has now been fixed.
"},{"location":"releases/2022.02.01/#existing-constraints-deleted-on-record","title":"Existing Constraints Deleted on Record","text":"Under rare circumstances, it's possible to assign a marker onto a control that's been constrained. It wouldn't make sense to record onto this control; because what should you expect to have happen? The control is either animated or it is constrained.
At the moment, this constraint is also recorded and once complete your original constraint is deleted. If possible! If the constraint is from a referenced file, then you'll instead see an error. \ud83e\udd14
"},{"location":"releases/2022.02.01/#record-range-options","title":"Record Range Options","text":"The Record UI has seen some updates. It used to always record your current playback range, but can now be customised.
Record To Selected Range
You can now drag-select on the timeline to record only that specific region.
Record Full Range
The minimum and maximum range on your timeline, beyond what is played back.
Record Playback Range
Record only the range currently played back, this is the default and current behaviour.
Customise Range
And finally, provide your own values. These values, along with the option of which range to pick from, is remembered alongside your Maya preferences just like all other Ragdoll options.
"},{"location":"releases/2022.02.01/#existing-constraints","title":"Existing Constraints","text":"In the rare circumstance of:
Record
You would find yourself with a missing constraint. As it happens, when Maya encounters an existing constraint it won't actually create a new constraint when you try and constrain again. Instead, it will append to this constraint.
As a result, since Recording constrains your character to the simulation and then bakes the keyframes, once it was complete and went on to clean up any new constraints it had made, it also deleted yours.
This has now been fixed.
"},{"location":"releases/2022.02.01/#manipulator-multiple-viewports","title":"Manipulator & Multiple Viewports","text":"The Ragdoll Manipulator didn't like multiple viewports being present at the same time, resulting in a similar situation as 2021.12.15.
Ragdoll now draws and responds to the manipulator in the currently active viewport.
"},{"location":"releases/2022.02.01/#plug-in-unload-and-new-scene","title":"Plug-in Unload and New Scene","text":"Sometimes, especially on a floating licence, you'd like to release your licence such that another artist can pick it up.
To do that, you can either go to the Ragdoll UI and Drop Lease
for a floating licence of Deactivate
for a node-locked licence. Or, you can simply unload the plug-in.
As it happens, if you did then Ragdoll would clear your scene. Without confirmation. \ud83d\ude35
This has now been fixed. You'll still need to ensure no Ragdoll nodes are present in your scene though, like any normal plug-in.
"},{"location":"releases/2022.02.01/#delete-from-selection","title":"Delete from Selection","text":"A new menu item has been added to delete physics only from the current selection.
Pro tip I
This was possible using the Use Selection
option within the Delete Physics
option dialog.
Pro tip II
Markers can also be manually deleted in the Outliner, they are DG nodes.
Pro tip III
Another way of deleting an individual marker is:
Delete
or Backspace
on your keyboardPro tip IV
Yet another way of deleting an individual marker is:
Delete Node
Drive Space Custom
appears under in the channel box when Drive Space = Custom
Include Kinematic
option for record has been fixedopts
argument of api.reinterpret
is repairedHighlight for this release is Fields!
Today I'm happy to announce that Jason Snyman joins Ragdoll Dynamics! \ud83c\udf89
Jason is a wizard of an animator with 20 years of experience in the industry - from King Kong and Avatar to Game of Thrones - and will be helping you become the best animator you can be, with Ragdoll at your side. That means tutorials, live streams and more of these awesome demos you may already have seen on LinkedIn!
Batman and Shark Dragon and Kong Dragon on Branch "},{"location":"releases/2022.02.14/#showcase","title":"Showcase","text":"You know the drill. Let's get into it.
Live Stream
We hosted a live stream last Friday! If you couldn't make it, it's been recorded and is made available here. :)
Dragon
Jason's latest animation, using the newly added Fields! Model by Antoine Verney-Carron
Dragon \u2764\ufe0f Kong
I just can't stop watching this.
Manikin Marine
He's packing!
Tentacle Field
"},{"location":"releases/2022.02.14/#manikin-30","title":"Manikin 3.0","text":"The Manikin has been updated to leverage the new goodies from this release, go ahead and grab it here!
Features
Ragdoll now supports all of Maya's native fields.
What are fields?
A field represents a set of forces applied to each Marker. Ranging from Gravity
to Turbulence
, each field carries unique properties you can use to emulate some environment or environmental effect, like wind and gravity fields along a curve.
What is the difference from regular Maya fields?
They are the very same!
If you're already familiar with them, from e.g. nParticles of nCloth, then you can leverage your experience with Ragdoll, and vice versa if you ever venture into nCloth and friends.
Let's walk through these fields one-by-one!
"},{"location":"releases/2022.02.14/#turbulence","title":"Turbulence","text":"The perhaps most interesting field. Apply forces in \"random\" directions, based on the worldspace positions of your Markers.
The way to think of turbulence is as Perlin Noise you may have seen in images such as this.
Where the amount of white determines the amount of force being applied. As a Marker travels across this field, both the magnitude and direction changes in interesting ways.
"},{"location":"releases/2022.02.14/#drag","title":"Drag","text":"Apply an opposite force to any motion.
The faster things move, the greater the force.
Pro tip
This field is similar to Ragdoll's Air Density
. Not technically, but practically.
Apply a uniform force, at a given speed, in a given direction. Like wind, including a kitchen fan with some Spread
.
A familiar force, except this one can be also be animated!
"},{"location":"releases/2022.02.14/#newton","title":"Newton","text":"Force Markers towards or away from a point in space.
"},{"location":"releases/2022.02.14/#radial","title":"Radial","text":"A more curious field; with a force which increases as it gets farther from the source.
"},{"location":"releases/2022.02.14/#uniform","title":"Uniform","text":"Apply a constant force. That's all.
"},{"location":"releases/2022.02.14/#vortex","title":"Vortex","text":"Apply forces in a circular pattern.
"},{"location":"releases/2022.02.14/#volume-axis-field","title":"Volume Axis Field","text":"A field for when you don't know what field you want.
A true Swiss Army Knife of fields, can do everything from Vortex, to Newton to Turbulence in one convenient node.
"},{"location":"releases/2022.02.14/#volume-curve","title":"Volume Curve","text":"Have some fun with this curve-based field. Perhaps to emulate an underwater current?
In this example, I'm also using a Drag
field to keep things from flying off into space.
Pro tip
The curve is a normal Maya NURBS curve. If you need more points, right click and add points as you normally would.
"},{"location":"releases/2022.02.14/#combined-fields","title":"Combined Fields","text":"Make two or more fields to combine their effect and create complex forces or series of forces!
"},{"location":"releases/2022.02.14/#centroids","title":"Centroids","text":"Where within each Marker should a field apply forces?
At the center, forces will be nice and predictable; except they won't be able to introduce rotations to your Marker, which may or may not be what you want. For the most realistic fields, use volumetric centroids.
Here's another example using the Turbulence Field.
Which is better?
Up to you! There is a tiny performance penalty for volumetric origins, as the number of forces increase. But you shouldn't notice much if any impact on performance.
"},{"location":"releases/2022.02.14/#centroid-seed","title":"Centroid Seed","text":"For complex meshes, centroids can end up in unwanted locations or gather in an area with dense vertices. That's when you can give the algorithm a little jolt to try and see whether there is a better alternative out there.
"},{"location":"releases/2022.02.14/#use-selected-as-source","title":"Use Selected as Source","text":"Some forces act according to their position in the world. Attach a field to a Marker to create an interesting relationship between the two.
Non-commercial Ragdoll
This feature is limited to 100 frames in non-commercial versions of Ragdoll.
Distance constrain two markers, and attach a field to the outer-most Marker for a doubly-interesting effect. That also wrecks your brain. \ud83d\ude43
"},{"location":"releases/2022.02.14/#field-scale","title":"Field Scale","text":"If forces start becoming large, you may find yourself in a situation where the visualisation needs to tone down just a bit.
In the solver settings, you will find options to scale those lines (i.e. Field Scale
), as well as control how many steps into the future (i.e. Field Iterations
) it should draw for you.
Fine-tune the effect of fields by having one or more Markers ignore the effect of fields.
"},{"location":"releases/2022.02.14/#force-modes","title":"Force Modes","text":"Fields can apply to your markers in 2 different ways.
Mode Description Math Force Traditional forcemass * distance / time^2
Impulse Typically used for contacts mass * distance / time
Which should I use?
The default is Force
, whereas Impulse
is what is typically used for collision handling. Experiment, and let us know which you prefer!
Combine multiple meshes for a complex \"compound shape\".
Vertices connected by edges are considered an \"island\", each island is then turned into an independent convex hull. Like this complex endevour.
434 islands in 147 ms
That's how long it took Ragdoll to generate the simulation volumes for the above meshes.
You can slice an dice any mesh to introduce new islands at will, for complete control.
Performance?
If you're wondering what effect this many meshes has on your simulation, the answer is we haven't noticed any. Go crazy, and if you do notice anything, let us know!
"},{"location":"releases/2022.02.14/#mesh-decomposition","title":"Mesh Decomposition","text":"Collision shapes are generated from each individual \"island\"; that is, groups of vertices that are connected by at least one edge. When you combine two or more meshes together, they will naturally form individal islands.
Sometimes, you'd rather treat the entire mesh as one big shape and for that you can use the Mesh Decomposition = Mesh Islands
.
Shape Vertex Limit
Also notice how the vertex limit is applied to each island. Meaning that you can achieve much higher resolution for your collision shapes by cutting things up into pieces!
"},{"location":"releases/2022.02.14/#quality-of-life","title":"Quality of Life","text":"Let's brighten up your day, shall we? \ud83e\udd70
"},{"location":"releases/2022.02.14/#robust-frame-skips","title":"Robust Frame Skips","text":"Anyone playing back their simulation to audio may prefer Ragdoll with a Frameskip Method = Ignore
. Such that it'll keep simulating, even though the result won't be 100% reproducible.
But! If you did, you may have ran into this.
Notice how it sometimes fails to keep up with fast time changes? Well, no longer!
Caveat
Like before however, the simulated result you get when frames are skipped will still differ from the result when frames are not skipped, or when different frames get skipped.
The final recorded result will not skip any frames, so you should use this while working but ensure there aren't any frames skipped when you tune and tweak the final values.
"},{"location":"releases/2022.02.14/#manipulator-and-hud","title":"Manipulator and HUD","text":"The View Cube and other viewport ornaments are automatically and temporarily hidden whenever you use the Manipulator. But sometimes, Ragdoll could get confused and leave you having to manually re-enable the viewport HUD.
This has now been fixed, and Ragdoll will more predictably re-enable any HUD it hides.
"},{"location":"releases/2022.02.14/#kinematic-stiffness","title":"Kinematic Stiffness","text":"Markers set to Kinematic
would also lose their stiffness with their parent.
Before
After
This has now been fixed.
Pro tip
To achieve the effect from the previous version, set Pose Stiffness
to 0
Users of Maya 2022 would experience this dialog when getting started with Ragdoll.
This has now been fixed.
"},{"location":"releases/2022.02.14/#negative-scale-edgecase","title":"Negative Scale Edgecase","text":"A rare case was discovered by @BigRoy whereby negatively scaled controllers would yield an incorrect shape drawing. The simulation was fine, but it wasn't looking quite right in the viewport.
Before
After
This has now been fixed!
"},{"location":"releases/2022.02.14/#import-additions","title":"Import Additions","text":"These attributes were added to the export and import mechanism.
Nice Name Long Name World Pose Translate XdriveAbsoluteLinearX
World Pose Translate Y driveAbsoluteLinearY
World Pose Translate Z driveAbsoluteLinearZ
Pose Twist Amount driveAngularAmountTwist
Pose Swing Amount driveAngularAmountSwing
"},{"location":"releases/2022.02.14/#capsule-length","title":"Capsule Length","text":"All this time, capsules had been scaled in an axis that didn't align with your scale manipulator.
No longer!
Before
After
"},{"location":"releases/2022.02.28/","title":"Environment","text":"Highlight for this release is Complex Geometry!
Before we get into the new features of this release, let's have a look back at some highlights of the week.
For the Love of Ragdoll
Animation by Kevin Taylor, model by Shaun Keenan.
Dragon Setup Livestream
The dragon from the latest livestream last Friday!
Chewsday
A little experiment with worldspace rotation stiffness.
Rhino Workout
Soft joints for some belly-jiggle.
Rhino Walk
Nice self-walking rhino.
Self Walking Manikin
Same trick, different character. :)
Soft Joints
Jason experimenting with the new Soft Joints feature.
Facial Animation
Getting some nice secondary motion out of moving the head and jaw around!
"},{"location":"releases/2022.02.28/#environment","title":"Environment","text":"Ragdoll now supports static environments; meaning environments that cannot move or deform, but allow for normal polygonal geometry without the need for a simplified \"convex hull\".
As you might expect, this works well for environments like terrain and other complex geometry that is otherwise hard to turn into a rounded mesh.
"},{"location":"releases/2022.02.28/#performance","title":"Performance","text":"It's fast.
Normal shapes are limited in how complex they can get, and as such you never really run into a situation where the shape noticeably affects performance.
Triangle meshes are different; they can be of any complexity. Up to millions of polygons and beyond. So it falls upon you to decide where to make the performance/quality tradeoff!
Vertex Count Cooking Time Run-time performance 400 0.39 ms 685 fps 8'000 3.51 ms 599 fps 16'000 14.3 ms 594 fps 64'000 61.5 ms 327 fps 256'000 287.7 ms 40 fps 1'000'000 1490 ms 2 fpsWhat is cooking time?
The time it takes for Ragdoll to convert your polygonal geometry into the internal representation needed for collision detection. It involves splitting up the mesh into areas or \"zones\" for faster lookup.
This only happens when the mesh actively changes and when first opening the Maya scene, and won't affect playback speed.
"},{"location":"releases/2022.02.28/#automatic-mesh-islands","title":"Automatic Mesh Islands","text":"Ragdoll needs \"convex\" meshes for anything that moves.
What is a convex mesh?Think of it like a shrink-wrapped version of your mesh.
In 2D, it might look something like this.
Notice how the points in the middle are excluded? This is an optimal shape for collision detection, as you can draw a straight line from anywhere in the world and know that if it ever hits this shape, it hits it in only 1 spot.
In the previous release, \"Mesh Islands\" were introduced to turn each separate polygonal island into its own convex hull and glued together as one complex shape.
With that, you have a great deal of control over the final collision shape
Multi-cut settingsTick the Extract Faces
box, and zero out those values to get Maya to perform an actual split in the geometry as you cut. Otherwise, it will only insert new edge-loops and not actually create two separate meshes.
It did, however, mean that you had to take the time to manually slice up the mesh, which may not always be feasible. This release introduces an automatic method of slicing up a given mesh, into a close approximation of the original mesh.
"},{"location":"releases/2022.02.28/#attributes","title":"Attributes","text":"There are a number of parameters to tune when generating your convex hulls, here's what they mean.
Attribute DescriptionResolution
The number of \"voxels\" to generate from a given volume; the greater the number the more accurate the resulting representation. At the expense of time. Values between 100-1000 are normally sufficient. Concavity
The maximum allowed different in angle across the surface of the resulting meshes. It might be thought of as \"roundness\". Symmetry Bias
Slices are made either horizontally and vertically, or radially. This value controls how much to favour the former. Revolute Bias
And this value controls how much to favour the latter Min Volume
Ignore computed volumes that are smaller than this. It can help reduce the number of very tiny meshes. Max Convex Hulls
How many separate meshes to make. This will depend on the complexity of your mesh, but generally the lower the better. Plane Downsampling
Performance related, lower values take longer Hull Downsampling
Also perforamnce related, lower values take longer Fill Mode
Various ways to deal with geometry that isn't a closed volume. A sphere for example is a closed volume, whereas a plane is not. Approximate Hull
Performance related, faster when ticked. Project Hull Vertices
See what the generated meshes look like before they are \"shrink-wrapped\" back onto your model. These give you a good sense of how large the voxel resolution is. Complexity
Over time, as we learn more about which parameters work best in the most general case, I'd like to reduce the number of attributes here. Ideally we would only have a Quality
attribute with Low
, Medium
and High
settings.
It's slow.
The process of automatically slicing your geometry is not real-time, it can take up to a few seconds or more. On the upside, it only ever happens when the mesh changes and does not affect playback performance.
Here are some timings for the meshes in the below simulation.
Object Pieces TimerMarker_Barrels
30 1.9 s rMarker_Ceratopsia
16 0.7 s rMarker_FingerPlates
64 6.1 s rMarker_LeaflessTree
183 6.3 s rMarker_bull
16 0.8 s rMarker_fish
16 0.7 s rMarker_hand_basemesh
16 0.3 s rMarker_horse
16 0.9 s rMarker_humanBody
32 2.9 s rMarker_jetFighter
16 0.5 s rMarker_polySurface9
16 1.6 s rMarker_shirt
16 0.9 s Faster performance is on the map
This method is new to us, and we expect to find faster - ideally real-time - alternatives to this in the future.
"},{"location":"releases/2022.02.28/#soft-joints","title":"Soft Joints","text":"To balance out the talk of complex but hard geometry, let's talk about \"soft joints\".
Once I set Translate Motion = Soft
and the feet hits the ground, notice how:
Here's a more extreme example.
"},{"location":"releases/2022.02.28/#general-purpose","title":"General Purpose","text":"We're calling it \"soft joints\" when in reality this is Pose Stiffness
but for translation rather than rotation. Which means you could use it for tentacles and other appendages that depend on not just rotating limbs but squishy and compressed limbs. Potentially stretchy limbs and spines too?
We haven't yet explored this fully, so take it for a spin and let us know what you come up with. \ud83d\ude0a
"},{"location":"releases/2022.02.28/#caveat","title":"Caveat","text":"When stiffness goes too low, limbs detach.
This is unintended behaviour and will be addressed in a future release. Proper breakable constraints are on the map, but this isn't it. So use with caution, and limit it to create softness between your limbs.
"},{"location":"releases/2022.02.28/#forum","title":"Forum","text":"The forum has gotten a face-lift! This will henceforth be where tutorials and showcases appear, along with notifications for new releases!
So sign up, subscribe to the News
category to receive notifications when things happen in Ragdoll-land!
Out of beta and available to all.
If you need a more low-cost but commercial introduction to Ragdoll in your studio, then this is for you.
You can now make groups via the API.
from maya import cmds\nfrom ragdoll import api\n\nsolver = api.createSolver()\nground = api.createGround(solver)\ngroup = api.createGroup(solver)\nsphere, _ = cmds.polySphere()\ncmds.move(0, 10, 0)\nmarker = api.assignMarker(sphere, group)\n\ncmds.evalDeferred(cmds.play)\n
The assignMarker
command has also been simplified and does not longer implicitly create a group.
A few more things to make your day that much more bright.
"},{"location":"releases/2022.02.28/#merge-solvers","title":"Merge Solvers","text":"You can now merge two solvers together, move markers from one solver to another and extract markers into a new solver.
"},{"location":"releases/2022.02.28/#extract-markers","title":"Extract Markers","text":"Sometimes, you want some of your markers to be part of a separate solvers.
"},{"location":"releases/2022.02.28/#move-to-solver","title":"Move to Solver","text":"Rather than merge two solvers in its entirety, move specific markers from one solver to another.
"},{"location":"releases/2022.02.28/#manipulator-with-multiple-solvers","title":"Manipulator with Multiple Solvers","text":"The Manipulator can now be used in scenes with two or more solvers in them!
"},{"location":"releases/2022.02.28/#manipulator-selection","title":"Manipulator Selection","text":"You can now use the Manipulator to select both the Marker and Maya node, such that attributes can be edited in the Channel Box.
"},{"location":"releases/2022.02.28/#manipulator-fit-to-view","title":"Manipulator Fit-to-view","text":"Using the manipulator via the Ragdoll menu enabled you to also benefit from the F
key, to fit your selection to the current camera.
But if a Marker or Group was selected and editable in the Channel Box, that no longer worked. Because under the hood, what you were really fitting in view was the solver shape node.
This has now been fixed such that you can fit any selected Marker, regardless of whether the solver shape node is selected or not!
"},{"location":"releases/2022.02.28/#select-during-playback","title":"Select During Playback","text":"The Manipulator can now be used to select Markers during playback.
Caveat
Selection is based on the current simulated state and doesn't understand rewind. To fix this, step at least 1 frame forward whenever you attempt to select, to ensure the selection and simulation is staying in sync.
This will be addressed in a future release.
"},{"location":"releases/2022.02.28/#reset-shape","title":"Reset Shape","text":"Whenever you assign a Marker, a default shape is computed based on your selection and available geometry or NURBS curves.
"},{"location":"releases/2022.02.28/#refit-assignment","title":"Refit Assignment","text":"Likewise, when you branched off into a tree-like structure for your markers, you could easily end up with something like this.
This has now been addressed, whereby the marker which forms a fork now being reset automatically.
"},{"location":"releases/2022.02.28/#licence-conservation","title":"Licence Conservation","text":"Applies to
This feature only applies to Floating Licence customers.
In the previous release, a licence was leased on plug-in load.
The problem was that, sometimes, an artist merely opens a scene with Ragdoll in it. Maya will determine that this file requires the Ragdoll plug-in to be loaded, and loads it. Upon load, Ragdoll would go ahead and check out a licence. But this artist doesn't necessarily want to interact with Ragdoll, it could have been a texture artist opening up an animator's scene, or someone rendering it.
This release introduces \"licence conservation\" which only tries to lease a licence upon a simulation taking place. That means a lease is not made on plug-in load, nor on scene open. If a solver is hidden from view, nor does it take place on playback start.
Only once simulation visibly begins is a lease requested, helping you save those precious seats for the artists that need it most.
Markers are still rendered in the viewport on the start frame for everyone, without a lease. The Solver is automatically hidden upon failure to lease a licence, pausing any further requests until it is made visible again.
"},{"location":"releases/2022.02.28/#minor-releases","title":"Minor Releases","text":"Inbetween this release and the previous release there were a few minor releases made.
rdGroup
nodeRequest Lease
button in the Ragdoll UI now actually worksThe menu items for the old Legacy interface to Ragdoll Dynamics has now been removed. Scenes created with this interface will still open, so this is your last chance to save your work and transition to the current Marker-based workflow.
"},{"location":"releases/2022.03.14/","title":"Quality of Life","text":"Highlight for this release is Quality of Life!
Let's catch up on a few highlights over the past 2 weeks.
Instict
Andrei got Ragdoll introduced to this beautiful thing.
Some nice stills.
Rhinos
Jason's working on a new tutorial for how to make self-walking quadrupeds.
Let's have some more, shall we? \ud83e\udd73
"},{"location":"releases/2022.03.14/#manipulator-and-multiple-solvers","title":"Manipulator and Multiple Solvers","text":"The Manipulator operates on 1 solver at a time.
When there are two or more manipulator in the scene, Ragdoll will now be more kind and smart about which one you mean.
Select any..
..and the manipulator will figure out which solver you mean.
When unsure, it will ask you to clarify.
"},{"location":"releases/2022.03.14/#selection-highlight","title":"Selection Highlight","text":"Each marker have 3 possible nodes you can select.
Selecting the marker and source transforms gave you a handy selection highlighting in the viewport, confirming what you had selected. But so far, selecting a destination transform did no such thing. Until now!
Notice how this also helps you detect whether something has a target at all, like the upper legs here. These remain unrecorded, as they are connected to the hip and driven by IK.
"},{"location":"releases/2022.03.14/#contact-visualisation","title":"Contact Visualisation","text":"You can now visualise when and where contacts occur.
This can help spot self-collisions too!
"},{"location":"releases/2022.03.14/#import-symmetry","title":"Import Symmetry","text":"Symmetry is now preserved on import.
For any character authored in a symmetrical pose, the Ragdoll Manipulator would let you operate on this character on both sides at once.
But until now, this symmetry was lost if at any point an import was made on a character was not symmetrical, such as an animated character.
This changes today!
"},{"location":"releases/2022.03.14/#manipulator-deselect","title":"Manipulator Deselect","text":"With nothing selected, you now have access to the Solver in the Channel Box.
"},{"location":"releases/2022.03.14/#clean-abort-on-record","title":"Clean Abort on Record","text":"Almost rhymes. If recording takes too long and you hit the ESC key to cancel, Ragdoll no longer leaves a mess behind. It's clean!
"},{"location":"releases/2022.03.14/#coloured-limits","title":"Coloured Limits","text":"The manipulator now colors limits by their axis. Where X is red, Y is green and Z is blue; just as you'd expect.
"},{"location":"releases/2022.03.14/#auto-cache","title":"Auto Cache","text":"There is now an option to disable auto cache upon completed record.
This will let the simulation continue running after recording, using your newly recorded controls as input.
"},{"location":"releases/2022.03.14/#on-location-pin","title":"On-Location Pin","text":"Whenever you make a new Pin Constraint, it would appear at the location of your animation. But now, it will appear wherever the simulated version of your animation is.
"},{"location":"releases/2022.03.14/#limit-on-select","title":"Limit on Select","text":"Limits are now only visible when selected, making things a little less messy in the viewport.
"},{"location":"releases/2022.03.14/#fixes","title":"Fixes","text":"Some house cleaning of minor things that could sometimes trip you up.
"},{"location":"releases/2022.03.14/#nested-namespaces-and-import","title":"Nested Namespaces and Import","text":"Ragdoll is now happy to import physics onto any number of namespaces.
"},{"location":"releases/2022.03.14/#animated-pose-space","title":"Animated Pose Space","text":"The previous release broke any transition between Local
and World
, this has now been fixed.
When you want a marker to follow your animation in worldspace in all but one or two axes, you can use World Pose Translation
. However, in the previous release, the axes were aligned with the control rather than the world. This has now been fixed.
Linking two solvers is a non-destructive method of getting multiple characters to interact in the same scene. As it happens, you haven't been able to unlink until now.
"},{"location":"releases/2022.03.14/#export-without-rag","title":"Export without .rag","text":"As it happens, the Import Options will only show you files that have a .rag
extension. But! The Export Options would permit export of files without this extension.
As a result, it could appear as though nothing was exported. :(
This has now been fixed.
"},{"location":"releases/2022.03.14/#euler-filter","title":"Euler Filter","text":"To keep gimbal locks from happening in your recorded simulation, an \"Euler Filter\" could be automatically applied. This hasn't been the case so far, but has now been fixed.
"},{"location":"releases/2022.03.14/#0-density","title":"0 Density","text":"Giving markers a density of 0 would make it infinitely light, or infinitely heavy depending on your perspective. Such things does not exist in the real world and cannot be simulated.
Ragdoll will now protect you against this.
"},{"location":"releases/2022.05.04/","title":"Retargeting 2.0 and Maya 2023","text":"Highlight for this release is a new Retargeting UI and support for Maya 2023
We've got a lot of new content since last release, so let's break it down.
Pirate
New livestream from last Friday!
And a new start-to-finish asset and breakdown on the forums for this guy!
Woody
Another gem from @Andrei on the forums!
Ice Dragon
This one from Jack Preston on the forums!
Gundam
And one more, also from Jack The Magnificent!
VR Rabbit
Jason took a spin in virtual reality to come up with this nightmare of a rabbit.
Rhino Companion
The Manikin got a friend.
"},{"location":"releases/2022.05.04/#retargeting-ui","title":"Retargeting UI","text":"You can now visually see where keyframes go upon running Record Simulation
.
Let's take a look at what this UI is, what it can do for you and when to use it.
The UI can help you spot problems with recording, before recording happens.
In this case, some of our markers are retargeted onto joints that are driven by some other object. If we were to attempt to record these, it's unclear what the result should be.
Neither of these are a great pick, since we don't want to break the rig, but we also want our simulation to go somewhere.
"},{"location":"releases/2022.05.04/#workflow","title":"Workflow","text":"Once you've assigned your markers, grab a clean slate and gain complete control over where animation is to be recorded.
And finally, here's a longer-form example of a full setup of the Truong Dragon that we did a livestream on a while back.
Ragdoll now ships with plug-ins for Maya 2023, enjoy!
Heads up
Maya 2018 is still included in this release, but should be considered deprecated and will be removed entirely by July 2022.
"},{"location":"releases/2022.05.04/#moar-performance","title":"Moar Performance","text":"Ragdoll now renders up to 20% faster.
Before
It used to be the case that each frame uploaded vertices and colors to the GPU.
After
But now, there is zero memory allocations. The programmers amongst you will appreciate the benefit and difficulty of such an improvement. This lays the foundation for future performance advances, in particular related to instancing and crowd simulation. \ud83e\udd2b
For the techies amongst you, here's what the improvement looks like in the Profiler.
Before
After
The top two layers is Ragdoll, notice the slight reduction in length. Win!
"},{"location":"releases/2022.05.04/#quality-of-life","title":"Quality of Life","text":"Here's a summary of changes designed to make your day just a little more bright.
"},{"location":"releases/2022.05.04/#following-pin-constraint","title":"Following Pin Constraint","text":"You now have the option of automatically constraining the Pin Constraint to your animation, giving you a similar look to Pose Space = World
except with a new dedicated transform node.
Multiple Pins
There can be many of these for the same marker!
Pin to Current Animation Pose
The default, put a pin wherever the animation currently is.
Pin to Current Simulation Pose
Alternatively, put it wherever the simulation is.
Ragdoll Non-Commercial
This option can only find the simulated pose for the first 100 frames unless you've got a commercial licence, like Ragdoll Complete or Ragdoll Unlimited.
Constrain Pin to Animation
Follow your animation interactively, by putting a Parent Constraint between pin and control.
"},{"location":"releases/2022.05.04/#select-group-members","title":"Select Group Members","text":"You can now select the members of a group, to aid in organising your scene.
"},{"location":"releases/2022.05.04/#visualise-environment","title":"Visualise Environment","text":"You can now see where the environment is when the solver is offset.
Before
After
"},{"location":"releases/2022.05.04/#manipulator-ordered-selection","title":"Manipulator & Ordered Selection","text":"The Manipulator now remembers the order in which you select, meaning you can use it for ordinary tasks like reparenting and constraining markers!
For example, consider this character here. He's symmetrical, and yet seem heavier on one side..
Let's take a closer look at the updated Hierarchy visualisation to see whether there is something wrong with the hierarchy we have created.
Aha! Let's fix this, by..
Reparent
All from the comfort of the Manipulator.
Here are some more funky hierarchies to solidify the point.
"},{"location":"releases/2022.05.04/#manipulator-symmetry-on-enter","title":"Manipulator & Symmetry on Enter","text":"Ragdoll will now look for symmetry right after entering the Manipulator. Especially helpful if you enter with some marker already selected, and especially if you use the T-hotkey to enter into the Manipulator!
"},{"location":"releases/2022.05.04/#manipulator-symmetry-toggle","title":"Manipulator & Symmetry Toggle","text":"Ragdoll will now look for a symmetrical partner when toggling the Enabled checkbox. Win!
"},{"location":"releases/2022.05.04/#manipulator-delete","title":"Manipulator & Delete","text":"You can now delete markers from within the Manipulator!
"},{"location":"releases/2022.05.04/#environment-node-crash","title":"Environment Node & Crash","text":"In the case of having more than 1 environment, you may have experienced a crash!
Before
After
This has now been patched up!
"},{"location":"releases/2022.05.04/#mesh-protection","title":"Mesh Protection","text":"Ragdoll can take meshes of any complexity.
Sometimes meshes have no volume. And that's fine; Ragdoll will generate a flat surface with some volume to it, to try and interpret what you want. However, under rare circumstances, those volume-less meshes could cause trouble for Ragdoll.
New attributes have been added to try and protect you from these. These will jiggle the vertices to try and discard anything suspicious. You normally won't have to interact with these, the defaults should keep you safe. But if you find vertices missing from your colliders, try editing these.
"},{"location":"releases/2022.05.04/#recording-start-frame","title":"Recording & Start Frame","text":"In some situations, you could find yourself with recorded keyframes all over the place.
Before
Notice how all of the destination controls - the joints, in this case - are all mangled! This would happen when the current time and the start frame of the simulation did not align. Not always, but in this particular case, and likely others too!
After
Now working as you'd expect. Phew!
"},{"location":"releases/2022.05.04/#recording-initial-pose","title":"Recording & Initial Pose","text":"When deleting a recorded layer, Maya would sometimes forget where your character was prior to recording.
Before
Notice how our character remains on the ground when deleting the layer, even though that's clearly one of the simulated poses.
After
This is instead what we expect, for it to return to where it was prior to recording.
"},{"location":"releases/2022.05.04/#linked-solver-stability","title":"Linked Solver Stability","text":"Solver linking is when the contents of two or more solvers participate in the same physical world; for example, reference two characters and link their solvers. Viola, you've got a single simulation with the two characters interacting with each other. Great!
However, under some circumstances this didn't always work. Especially with referenced files. It had to do with the order in which the solvers were created, and which solver was created when. It could happen that the link was ignored. Sometimes it behaved differently on scene re-open.
No longer! Now solver linking is robust, as you would expect.
"},{"location":"releases/2022.05.04/#inches","title":"Inches","text":"Using the manipulator in a Maya configured for inches, or any other unit than millimeters..
..could result in funky behaviour. This has now been fixed!
"},{"location":"releases/2022.06.09/","title":"Locomotion","text":"The highlight for this release is Locomotion!
The above animation is automatically generated, given just a handful of parameters to ragdoll.
Start
and End Position
Step Sequence
Limits
I'll walk through what each of these mean in the rest of this documentation.
"},{"location":"releases/2022.06.09/#examples","title":"Examples","text":"Let's start with a quick look at what you can get out of this new toy.
Locobot
Modeling by Christophe Desse.
Spot and Friends
Happy Box
Yes, you can give it a terrain.
Two Happy Boxes
Locoboy
A 2-legged quadruped, look at'em go!
Locomotion & Physics
Playing well together.
Humanoid Locomotion
As you can tell, quadrupeds fair much better!
Human Dynamics
But with some physics, it's starting to look nice. :)
"},{"location":"releases/2022.06.09/#abilities","title":"Abilities","text":"Here's what we're aiming for with this release.
To achieve this, you've got control over:
Step Sequence
Terrain
upon which to walkThere can be any number of feet and it can travel any amount of distance. The Step Sequence
is how you're able to achieve different kind of walks.
And the Terrain
is how it can do this across geometry of any complexity.
Let's talk about what cannot be solved with Ragdoll Locomotion
.
As of this release, it only understands 2 things.
And for feet, it only understand the position of the foot, not its orientation.
Most importantly, it does not understand arms! Arms are critical to human locomotion, they swing in tandem with each step. This version of Ragdoll does not understand arms. Yet. Meaning it's good for locomotion involving any creature that does not have arms.
But Marcus, that doesn't leave much room for many creatures. They all have arms!
Think again!
With that out the way, let's look at what it can do!
"},{"location":"releases/2022.06.09/#workflow","title":"Workflow","text":"Here's what you do.
Assign Plan
Plan?
The generated locomotion is the result of a \"plan\", meaning each of the inputs you give it. Including this initial selection.
"},{"location":"releases/2022.06.09/#press-t","title":"Press T","text":"Locomotion also has a manipulator, accessible by selecting the rPlan
node and pressing T
on your keyboard.
Locomotion is computed in the background.
Normally, it'll take a second or two to compute 4-12 seconds worth of locomotion, and you can safely interact with Maya whilst it's running. It has zero impact on your overall Maya or character rig performance.
"},{"location":"releases/2022.06.09/#rig-compatibility","title":"Rig Compatibility","text":"Anything from a box with a sphere for feet to the most complex digi-double will do.
The rig in the above example is nothing special, as you've seen from the examples above this works on \"rigs\" as complex as a box and 2 spheres.
"},{"location":"releases/2022.06.09/#multiple-characters","title":"Multiple Characters","text":"You can have as many characters in the scene as you like.
Parallelism
These currently run 1 at a time, but the next release will unlock this to 1-per-core. Meaning you can have 128 characters computed in parallel on a 64-core AMD CPU. Now for what purpose could you ever need that many?
"},{"location":"releases/2022.06.09/#physics","title":"Physics","text":"Locomotion is an entirely separate \"brain\" that you may, or may not, want to combine with regular Markers.
Body and/or feet can be Kinematic
or driven by a Pin Constraint
, or anything inbetween.
Unlike a simulation, Locomotion
is entirely time independent. So it isn't strictly necessary to record; it will run directly on your character rig.
You can edit the locomotion as keyframes via Maya's native Bake Results
command.
This will become your new best friend. With an easily recognisable pattern for when to move your feet.
Sequencer Mode
Shift
to paintCtrl
to eraseIt can be used to produce a wide variety of locomotion, such as this frog sequence.
"},{"location":"releases/2022.06.09/#targets","title":"Targets","text":"Once you've figured how to get somewhere, next up is figuring out where to go.
Target Mode
Start
or End
of the body or footTranslate
gizmo to control the position of either body
or foot
Rotate
gizmo to control the start and end orientation of the body
Use the Rotate
gizmo to control the orientation of the body at the start or end positions.
Is your character jumping or limping? Maybe dancing? Limits control the area in which each foot is allowed to move.
Limit Mode
body
to adjust the size of your characterfoot
to adjust the amount of motion a foot is allowed to haveHere's an example of how a short limit on one foot, and long steps with the other foot, can generate a wounded or limping locomotion.
"},{"location":"releases/2022.06.09/#terrain","title":"Terrain","text":"Things can easily get more interesting by swapping out that flat ground with some geometry.
"},{"location":"releases/2022.06.09/#known-issues","title":"Known Issues","text":"Sometimes, Locomotion can get stuck Thinking...
. Let us know if this happens, along how you got to that point. We're working on narrowing this down.
In addition to locomotion, a few minor things were improved in this release.
"},{"location":"releases/2022.06.09/#manipulator-constraints","title":"Manipulator & Constraints","text":"With the previous release keeping track of the order in which you select things using the manipulator, this release carries on the trend by enabling constraints to be made from within the comfort of the Manipulator. \ud83e\udd17
"},{"location":"releases/2022.06.09/#manipulator-namespaces","title":"Manipulator & Namespaces","text":"If you had 2 controls of the same name but in different namespaces, the Manipulator could get confused about which one you were actually editing.
This has now been fixed.
"},{"location":"releases/2022.06.09/#new-defaults","title":"New Defaults","text":"In response to feedback on the default values, 3 of them has seen an upgrade.
Air Density = 1.0 -> 0.1
Substeps = 4 -> 8
Iterations = 4 -> 8
These can all be found on the rSolver
node. And will result in more accurate simulation and less explosions. Bearing in mind that many simulations do not require this amount of substeps and iterations, and they come at the expense of performance. So if you find yourself in need of more juice, lower these back down to 4 or lower. If it looks right, it is right.
As it happens, MacOS users were getting a much too small Manipulator HUD!
This has now been addressed.
If you encounter any issues like this, please let us know in the forums!
"},{"location":"releases/2022.06.15/","title":"Parallel Locomotion","text":"The highlight for this release is Parallel Locomotion!
You know the drill, let's start with the good stuff! \ud83e\udd70
Model by Christophe Desse
"},{"location":"releases/2022.06.15/#parallel-locomotion","title":"Parallel Locomotion","text":"That's right! If 1 character takes 2 seconds to compute, 5 characters now also takes 2 seconds to compute. Or 10 characters, or 100 characters. 2 seconds in total, that's all you'd have to wait, up to the number of cores on your system.
As core-count continues to increase in our machines, you can expect the number of characters being run in parallel to increase as well, up to the level of full crowds; each individual character a unique and precise sequence of steps that conform to their environment.
Juice Left
There is still a little bit of juice left to squeeze.
At the moment, if Ragdoll detects any relation between one plan and another, it will run these one-by-one.
Normally, this is not the case, but if you for example connect the output of one plan to the input of another, there isn't much that can be done other than wait for one to finish. However this can also happen when unrelated things are connected, such as your character being connected to two plans, such that you can blend between them. This is too much, and will be addressed in a future release. Subtle balance!
"},{"location":"releases/2022.06.15/#locomotion-for-macos","title":"Locomotion for MacOS","text":"Go nuts!
"},{"location":"releases/2022.06.15/#determinism-restored","title":"Determinism Restored","text":"A bug was introduced in the last release, which could have resulted in your simulation returning different results when:
This has now been fixed.
"},{"location":"releases/2022.06.15/#endless-thinking","title":"Endless Thinking","text":"Sometimes Locomotion could simply never stop thinking, and you know how too much thinking is bad for you? The same applies to Locomotion.
This has now been fixed!
"},{"location":"releases/2022.06.15/#shift-to-toggle","title":"Shift to Toggle","text":"You can now choose whether to use the Shift and Control keys to add and remove steps in the Locomotion Step Sequencer, or whether to use Shift for both. Dragging over a filled step will erase it, whereas dragging over an unfilled step will fill it. A toggle!
"},{"location":"releases/2022.06.15/#updating-the-duration","title":"Updating the Duration","text":"You used to have Locomotion a kick in the butt whenever changing the Duration
attribute, to give your locomotion more time to reach the goal position.
This has now been fixed. :)
"},{"location":"releases/2022.06.15/#scale-factor","title":"Scale Factor","text":"The last release attempted to scale the viewport HUD automatically for your Mac users out there, but as it happens the built-in Mac display and an external display give different values to the mechanism we use to detect that scale. So, I leave it to you to tweak to your hearts content.
All things are scaled interactively, except the font which needs a plug-in reload to remain crisp.
"},{"location":"releases/2022.06.15/#optimised-rendering","title":"Optimised Rendering","text":"Hiding the rSolver
node automatically halts simulation, freeing up resources for your character rigs. The same applies to..
With this release, simulation now also takes a backseat with the viewport Plugin Shapes
unticked.
You'll no longer see warnings from Firefox or Chrome when downloading our plug-in, nor when using our .msi
installer to install it, nor will anti-virus ever thing our software is anything but authentic.
Hurray!
For Mac users with \"Gatekeeper\" enabled, a solution is headed your way soon!
DigiCertUtil
This is for search engines, and developers working with DigiCertUtil.exe
Animators, look away
As it happens, you can use DigiCertUtil.exe
from the command-line. As is mentioned here, https://www.digicert.com/kb/util/utility-code-signing-command-line.htm
But what's this? It just causes the GUI to appear? No message? What did you do wrong? Well, as it happens..
# Before\ndigicertutil /noInput sign loco3d.exe\n\n# After\ndigicertutil sign /noInput loco3d.exe\n
This matters. The order in which you pass the sign
argument. I must come first. And that's it, really. Pass it first, and then it will tell you what's wrong and what to do about it. You've also got.
digicertutil /?\n
Which does not need the sign
argument, apparently, but will provide you with a separate window with details about each argument to sign
possible.
There, search engines, index this and save the hour or more I lost investigating and scratching my head about this.
"},{"location":"releases/2022.07.20/","title":"Meshes Meshes Meshes","text":"Highlight for this release is Meshes meshes meshes!
Leave any comments and report any issues here.
We've launched a Ragdoll Challenge since the last release, here are some highlights!
Crabomotion
From the ongoing competition by Kaehwai.
Hands
By V4NDL0 on the forums.
Jason
Some clips from Jason's LinkedIn feed over the past 2 weeks.
"},{"location":"releases/2022.07.20/#raggraph","title":"Raggraph","text":"In August, we're heading to Siggraph 2022 in Vancouver!
We'll be over here, at booth 442.
Running a handful of demos of how Locomotion works under the hood (hint: robotics tech!) along with the basics of Ragdoll.
Our booth will look something like this.
We'll be wearing t-shirts that look like this.
And have some nice banners that look like this.
Preliminary schedule looks like this.
The most important and complex aspect of Ragdoll are the Pose parameters.
Pose Stiffness
Pose Damping
Pose Space
In an effort to simplify these attributes, you'll now find an alternative - experimental - set of attributes.
Translate Stiffness
Translate Damping
Rotate Stiffness
Rotate Damping
A Translate Stiffness = -1
means \"infinite\" or \"locked\". It's the equivalent of Translate Motion = Locked
.
Use the new option in the Assign
option box to enable these.
Any replaced mesh is now included in the exported .rag
file, enabling you to import meshes onto characters that are missing the originally replaced mesh.
This should help keep both scene files and rag files clean and self-contained!
To the programmers out there, the .rag
file now features this section.
\"ConvexMeshComponents\": {\n \"members\": {\n \"indices\": {\n \"type\": \"UintArray\",\n \"values\": [\n 0,\n 1,\n 2,\n ]\n },\n \"vertices\": {\n \"type\": \"PointArray\",\n \"values\": [\n 1.8463890552520752,\n -0.5881761908531189,\n -0.28559789061546326,\n ]\n }\n },\n \"type\": \"ConvexMeshComponents\"\n},\n
These are unique vertex positions of one or more meshes. Ragdoll separates them into individual convex hulls by looking towards their connectivity, as per the indices
array.
As a side-effect, you are now also able to delete the mesh you used with Replace Mesh
. Keeping your scene a little more clean.
The automated convex hull mechanic has been updated and is now both faster and easier to work with.
Before
After
Furthermore, you now have the option of baking the automatically computed convex hull so as to avoid recomputing it each time you open the Maya scene file.
For example, here we've got a decomposited human mesh.
And here you can see how we get to keep the collider, but lose both the connection and the automatic decomposition. File-open times are now optimised, as well as file size. As we only store the bare essential vertices for the convex hulls!
"},{"location":"releases/2022.07.20/#convert-to-mesh","title":"Convert to Mesh","text":"You can now convert any Marker geometry - including convex hulls - into Maya geometry!
"},{"location":"releases/2022.07.20/#attach-constraint","title":"Attach Constraint","text":"The Pin Constraint has been expanded and can now pin one marker to another.
Under the hood
This is exactly the same as calling Reparent
to parent one marker to another. Except a marker can be attached to many other markers, and their relationship can be animated!
Here's how it works.
Let's take a closer look.
Here we've got two independent markers. No parent and child relationship. Now let's attach the box to the torus.
As you'd expect, the box is now a child of the torus. You can use the handle to reposition exactly where this box is attached onto the torus.
The position and orientation can be animated too. It's a rather complex little constraint, but very powerful!
"},{"location":"releases/2022.07.20/#quality-of-life","title":"Quality of Life","text":"Next up, let's have a look at some of the minor improvements made to put a smile on your face.
"},{"location":"releases/2022.07.20/#closed-loop-recording","title":"Closed Loop Recording","text":"If you parent the tip to the root, you'll get a closed loop. Something Maya natively cannot do, but Ragdoll can. And for good reason, since you can do things like this!
However, it wasn't able to record it. Until now. :)
Why make this an option?
Yes, if it's able to do more than why not just leave this as default and remove the option?
Well, as it happens, there are times when closed loop recording performs worse than regular recording. Keep an eye out for what happens between frames, your rotation channels might be under stress, and let us know in the forums how it got that way. It's something I'd like to sort out.
You can now control individual axes of a pin constraint, just like you can with Pose Space = World
on normal markers.
For example, here's what happens if we pin it along X and Z, but ignore the Y axis.
Likewise, here we only pin the Z axis. Notice how it's only allowed to move along the Z plane, staying at wherever the pin is in Z.
And similarly for X.
The rotation works the same, except Twist represents the X axis and Swing is both Y and Z.
"},{"location":"releases/2022.07.20/#predictable-enabled-state","title":"Predictable Enabled State","text":"Every Ragdoll node has an Enabled
attribute for you to temporarily and non-destructively enable and disable the node without physically removing it from the scene. It acts indentically to physically deleting that node, but is safe to do even on a referenced node.
However, in the previous release you could find yourself..
Enabled = Off
Enabled = On
Only to then not actually having it enabled. What's up with that? When you..
Enabled = On
a second timeIt works. That isn't particularly intuitive, and has now been fixed!
"},{"location":"releases/2022.07.20/#infinite-terrain","title":"Infinite Terrain","text":"If you provide Locomotion with a terrain, it will generate a heightmap from it. Where there wasn't geometry, such as outside the borders of the geometry or inside of holes, it would struggle to figure out what to do.
This release now extends your terrain in every direction, such that you get more what you'd expect.
Notice how he's able to start outside of the terrain, and step on missing parts of the terrain!
"},{"location":"releases/2022.07.20/#simplified-density","title":"Simplified Density","text":"Fewer options for working with density, now it's just a single number.
As it turns out, the presets were really limiting and was rarely a good fit for anything. And they didn't make intuitive sense either. \"Uranium\"? I don't know how heavy that is, when should I use it?
So instead, a single Density
value with a default value of 1
remains. This is the previous Density Custom
attribute with a shorter name, so if you were already using this attribute then you already know what to expect.
With a special density of 0
you'll be greeted by the Mass
attribute to disable automatically computing mass from the size and volume of your shape.
You can now choose to work with Stiffness
values without worrying about the weight of markers.
This can help get a better understanding of what a value of 1 means, as it would no longer depend on the mass of a marker, which is automatically computed per default. The marker would retain its mass, such that if a heavy marker fell on a light marker it would still act accordingly. But the stiffness values would act as though they weighed the same.
Should this be enabled per default? What are the consequences of this option? Let's find out!
"},{"location":"releases/2022.07.20/#frameskip-default","title":"Frameskip Default","text":"When a frame is skipped, Ragdoll would normally pause simulation and wait for you to return to the last successfully simulated frame. This ensures that the simulation always produces the same result each time you play. But also means it is unable to solve if Maya skips a frame, as can happen when a rig is especially heavy or when playing back with Audio.
This mode is called Pause
and the alternative is a mode called Ignore
which will continue solving even though it isn't given each and every frame.
Ignore
is now the new default, to avoid surprises especially for beginners who might not know why simulation suddenly stops for no apparent reason. You are still advised to stick with Pause
especially towards the end of fine-tuning your work. That's the only mode in which Ragdoll can guarantee that each and every playthrough is identical unless you have actually changed something in your animation.
The two lines towards the bottom tell you two things.
Ideally, for the most accurate and consistent results, these two should be identical. And when they are, they are hidden. They can be explicitly enabled via the Solver Display settings, called Draw Buffer
.
In addition to the Convert to Mesh
menu option, advanced users can now also experiment with the new rMarker.outputGeometry
attribute which provides access to the computed convex hull!
This is a live attribute, regenerating the mesh whenever anything affects the convex hull generated for collisions.
"},{"location":"releases/2022.07.20/#cache-hud","title":"Cache HUD","text":"You'll now find buttons in the viewport for manipulating the solver cache.
"},{"location":"releases/2022.07.20/#record-stuck-at-0","title":"Record Stuck at 0%","text":"Some users experienced recording getting stuck before it even began.
This should solve that!
Behind the scenes
For you programmers and riggers out there; as it turns out, calling OpenMayaAnim.MAnimControl.setCurrentTime
is not safe. When Maya wants to compute one or more things in parallel, this call could cause a deadlock. The simple solution, and the one employed here, was to instead use cmds.currentTime
. It was the strangest thing.
The alternative solution was to use Serial or DG evaluation modes.
"},{"location":"releases/2022.07.20/#import-solver-attributes","title":"Import Solver Attributes","text":"A bug was found whereby the attributes from your solver would get exported properly, but not imported! This has now been fixed.
"},{"location":"releases/2022.07.20/#use-selection-for-record","title":"Use Selection for Record","text":"The previous release broke the Use Selection
option for Record Simulation
and Snap to Simulation
commands. This has now been fixed!
A bug was found (thanks Andrei!) whereby having fields on your scene could cause a crash. This was related to the field trying to also affect the \"world\" rather than just the markers. This has now been fixed.
"},{"location":"releases/2022.07.20/#solver-bounding-box","title":"Solver Bounding Box","text":"Minor nitpick, if you had 2 or more solvers, unselected, and tried to \"Fit all\" (the F or A-key), it may not have actually fit all of the solvers. This has now been fixed.
The problem was that each solver was taking every marker into account, even those that did not belong to it.
"},{"location":"releases/2022.07.20/#locomotion-on-linux","title":"Locomotion On Linux","text":"We spent a lot of effort getting Locomotion running on Linux, only to trip over our own feet for release and include a spelling error in the Maya .mod
file causing Ragdoll to not find the Locomotion executable!
This has now been fixed, Linux users unite!
"},{"location":"releases/2022.07.20/#viewport-refresh","title":"Viewport Refresh","text":"Disabling and enabling a marker could sometimes leave it behind in the viewport, until the solver was hidden and unhidden, or the scene reloaded.
This has now been fixed.
"},{"location":"releases/2022.07.20/#locomotion-crash","title":"Locomotion Crash","text":"Ragdoll could sometimes bring Maya down when opening a scene containing a plan, for locomotion. This happened due to some really intricate memory and threading issues that you would not be interested in knowing more about. Rest assured, this has now been fixed!
"},{"location":"releases/2022.11.29/","title":"Live Mode","text":"Highlight for this release is Live Mode!
As is tradition, let's have a look at some of the things people have been up to with Ragdoll since the last release.
Ragdoll 3 Trailer
A 2 minute summary of what you'll find in this document!
Pavel Orsher
Some excellent mechanical work by Pavel on the forums.
Live Wyvern
Made with the beta version of Live Mode by @emi on the forums.
Live Dance
Animated with Live Mode, and re-simulated for balance!
Catfish
Made with a beta version of Live Mode by @riccardo_p on the forums.
Halloween
This happened.
Ho Ho Ho
A little early, or is it?
Live Mode Workflow
One example of how to use the new Live Mode from this release.
Interactive Wyvern
Animated in Interactive Mode, with caching enabled.
"},{"location":"releases/2022.11.29/#ragdoll-30","title":"Ragdoll 3.0","text":"That's right, this is a big one!
Last major release was the introduction of Markers back in January of this year. A major overhaul to both performance and usability of Ragdoll. This release is no different, with the introduction of Live Mode.
This is the direction we have in mind for Ragdoll and, dare I say, for character animation at large. We believe now is the perfect time to leverage much of the untapped technology from the past few decades and throw out much of what we know about animation - starting with how characters are posed.
"},{"location":"releases/2022.11.29/#ragdoll-freelancer","title":"Ragdoll Freelancer","text":"A new limited edition pricing tier for the individual out there wanting to take Ragdoll to work.
Details
Who is this for?
It's exclusively for individuals who work on a project-basis and wants to take their Ragdoll licence with them as they move between studios. It
Is this you? Click here to get yours today!
Buy "},{"location":"releases/2022.11.29/#live-mode","title":"Live Mode","text":"Here's \"Live Mode\" in a nutshell.
Traditional Rig
And here's the equivalent task with the traditional rig.
If you don't make it through all of the 95 seconds that the traditional method takes, I don't blame you. Not only is posing with Live Mode already 3x faster, it also has the following benefits.
But perhaps most importantly.
This same workflow applies to plain joint hierarchies, meaning an animator could:
For example, here's 30 seconds of \"rigging\" a character from scratch.
And that's where things are going.
Let's have a closer look at what this thing can do today.
"},{"location":"releases/2022.11.29/#general-posing","title":"General Posing","text":"Clicking and dragging on any marker will affect it the way you'd expect.
"},{"location":"releases/2022.11.29/#reset","title":"Reset","text":"Exiting out of the mode or changing from the Manipulator to e.g. the Maya Translate tool (W hotkey) will reset the simulation to where it originally started.
"},{"location":"releases/2022.11.29/#drop-press-hold","title":"Drop Press & Hold","text":"Towards the bottom, you'll find a number buttons, one of which is called Drop
. This \"drops\" the character. In other words, it temporarily enables gravity. This can help ease a character onto the ground or generally relax things that are hovering. It's also fun to play with.
Hold Shift to toggle gravity on, such that you can throw things around! Also fun to play with
"},{"location":"releases/2022.11.29/#tense-press-hold","title":"Tense Press & Hold","text":"Next up is Tense
. This tenses the character.
What's really happening is that it tries to reach whatever pose your rig is in at that time.
"},{"location":"releases/2022.11.29/#tense-toggle","title":"Tense Toggle","text":"Like Drop
, the Tense
button can be toggled, which would leave the character tense.
Hold Ctrl whilst clicking to \"mask\" a Marker. This prevents it from moving at all, it's technically turning the Marker into a Kinematic object temporarily.
Pro tip
You can also press Ctrl whilst dragging and release to leave the Marker you are currently dragging in place, for some cool posing mechanic!
"},{"location":"releases/2022.11.29/#unmask-all","title":"Unmask All","text":"Next up is \"unmask\" which involves \"masking\" via Ctrl + Clicking on a Marker. It's how you prevent a Marker from moving.
How does it work?
It temporarily turns any marker Kinematic
, identical to the Behaviour = Kinematic
attribute.
Hold Shift whilst dragging to isolate the effect to a marker and it's children.
"},{"location":"releases/2022.11.29/#transfer-pose","title":"Transfer Pose","text":"The final button is the Transfer
button. It's what transfers the simulation back onto your animation controls.
Like Drop and Tense, this button can also be toggled, meaning the pose is transferred as soon as you let go of the mouse cursor.
"},{"location":"releases/2022.11.29/#animation","title":"Animation","text":"And these are the tools you use to animate.
"},{"location":"releases/2022.11.29/#visual-undo","title":"Visual Undo","text":"The timeline helps you understand where undo will take you.
You can also interact with the timeline, for fine control over where in history you want to go.
"},{"location":"releases/2022.11.29/#recording-live-mode","title":"Recording Live Mode","text":"Use Live Mode with Cache = Static
to enable recording of your interactions!
Toggle the Lock button far-right to keep simulating outside of the Manipulator.
This enables you to use Ragdoll as a normal Maya deformer, and see real-time updates on contacts and limb limits.
Here are some more examples!
"},{"location":"releases/2022.11.29/#rigging-for-live-mode","title":"Rigging for Live Mode","text":"In order for your characters to work with Live Mode, you'll need to take a few things into consideration. Primarily that your character has FK controls with the ability to disable space switches and other mechanics that differ from a straightforward parent/child relationship.
A quick tutorial on how to setup a character using Maya's multi-cut, and then export and load this character to assemble it alongside our favourite Manikin!
Here's an example of how you can \"trick\" Live Mode into working for you with any traditional Maya rig.
The viewport rendering pipeline has seen an overhaul - replacing much of Maya's own API for our own based on OpenGL 4 and DirectX 11.
The result is a much nicer presentation of Markers, especially those with a Mesh.
But that's not all.
It also resulted in a 4x performance improvement to rendering, which means that playback performance is now 2x faster!
"},{"location":"releases/2022.11.29/#selection-outline","title":"Selection Outline","text":"Selection and anything \"wireframe\" in general has been significantly improved.
Before
After
"},{"location":"releases/2022.11.29/#group-selection","title":"Group Selection","text":"This has also seen a major face lift since the last release, resulting in a much more clear idea of what's included in a given group. Rather than the lasso from the prior release, which was great! But, it wasn't able to clearly visualise markers inbetween many other markers, since the lasso would encapsulate those too!
Before
After
Old Rendering
If you prefer, you can still enable the old group drawing. It's merely disabled in the Solver Display section of the Attribute Editor.
"},{"location":"releases/2022.11.29/#2x-performance","title":"2x Performance","text":"Here's a simple performance test to give you some idea!
Before
After
Here's one with only rendering and no simulation, meaning that navigating the viewport is even faster than the overall performance improvements.
Before
After
OpenGL vs DirectX
OpenGL is the quickest, use it if you can. DirectX clocks in at 120 fps, versus 200 fps for OpenGL. That's almost half the speed if you desperately need DirectX! But, still faster than the previous version.
"},{"location":"releases/2022.11.29/#parallelism","title":"Parallelism","text":"Here's what you can expect from parallelism with multiple solvers in this release.
1 Solver
25 solvers
We'd expect a 25x speedup here, but are only getting on the order of 3-4x. Useful, but room to grow!
"},{"location":"releases/2022.11.29/#load-physics","title":"Load Physics","text":"You can now open a .rag
file without anything already existing in your scene.
Before, you could export the layer of physics wrapping around your character rig, and later re-apply this layer via the Import Physics
menu item. With this release, you can throw away your character rigs and import and use the physics layer independently!
Asset Library Backend
This is the functionality the new Asset Library builds upon!
"},{"location":"releases/2022.11.29/#asset-library","title":"Asset Library","text":"You've now got a number of assets at your fingertips, ready for import.
"},{"location":"releases/2022.11.29/#version-history","title":"Version History","text":"Spot which version you are on, and read more about past versions to see how Ragdoll has evolved over time.
Clicking on a version will take you to the web page for it, assuming you've got internet access. Otherwise, you can copy the resulting address into somewhere you do.
"},{"location":"releases/2022.11.29/#licence-information","title":"Licence Information","text":"The Asset Library is where you'll now also find information about your licence.
"},{"location":"releases/2022.11.29/#multiple-loads","title":"Multiple Loads","text":"Load one or load many, they'll all interact with each other and can be manipulated with Live Mode too!
"},{"location":"releases/2022.11.29/#assets","title":"Assets","text":"Along with the new library, and your ability to add your own assets, we've got some default ones for you to play with!
"},{"location":"releases/2022.11.29/#alien","title":"Alien","text":"Let's have a look at what assets you've got to play with in this release, first up is the \"Alien\".
"},{"location":"releases/2022.11.29/#dog","title":"Dog","text":"A friendly dog, ready for posing.
"},{"location":"releases/2022.11.29/#manikin","title":"Manikin","text":"The classic Ragdoll Manikin character as a ragfile.
"},{"location":"releases/2022.11.29/#spaceman","title":"Spaceman","text":"A zero-gravity astronaut, waiting to be tossed around in space!
"},{"location":"releases/2022.11.29/#pirate","title":"Pirate","text":"Argghhhhh! This one's got fingers and a face.
"},{"location":"releases/2022.11.29/#rhino","title":"Rhino","text":"A quadruped as well, with fatty bits for some nice secondary motion.
"},{"location":"releases/2022.11.29/#wasp","title":"Wasp","text":"The wasp from the tutorial section!
"},{"location":"releases/2022.11.29/#cowboy","title":"Cowboy","text":"A plastic doll with gun and hat!
"},{"location":"releases/2022.11.29/#dragon","title":"Dragon","text":"A deconstructed version of Antoine Verney-Carron's wyvern, used in one of our early Live Streams.
"},{"location":"releases/2022.11.29/#batty","title":"Batty","text":"What do you get if you combine a bat with a frog?
"},{"location":"releases/2022.11.29/#shark","title":"Shark","text":"It's the Rag Shark!
"},{"location":"releases/2022.11.29/#dude","title":"Dude","text":"If Rag Shark had a friend, it'd be the Dude!
"},{"location":"releases/2022.11.29/#lion","title":"Lion","text":"A generic lion, in bad need of limits. Can you help him?
"},{"location":"releases/2022.11.29/#beta-videos","title":"Beta Videos","text":"A series of videos made during the beta, some of which are out of date but still potentially useful!
We've making a change to how you animate with the \"stiffness\" attributes.
Primarily, we're removing the Pose Space
attribute. If you hadn't yet used it, good on you. It was far too complicated of an attribute to make sense of.
If you have been using it, you'll be pleased to know that the behaviour is now entirely consolidated into the Pin Constraint which performs exactly the same behaviour except without the mental overhead of figuring out what a \"Custom\" space actually is.
Before
After
"},{"location":"releases/2022.11.29/#backwards-compatibility","title":"Backwards Compatibility","text":"The previous Pose Stiffness
attributes are still available for the time being.
To use it, untick the Use Translate/Rotate Stiffness
in the Assign
menu options.
Like removing a pebble from your shoe, the api.replaceMesh()
command now automatically changes your rMarker.shapeType
attribute to Mesh
. A small but helpful change!
Prior to this release, whenever you Export Physics
you'd get absolutely everything that Ragdoll knows about. Every Marker, every group and every solver too.
With this release, you can cherry-pick the things you want included in your export, via the new Export
attribute, found on all Ragdoll nodes. On
by default, if Off
then it will be invisible to the export process.
You'd use it when you have things in your scene you know aren't interesting to export. The Ground Plane for example is Off
per default, since it's unlikely you'd want that included in a new scene.
Two components has seen an update with new members and deprecated members.
These won't affect external use of .rag
files in e.g. game engines, and shouldn't have effect anywhere really. They are used as a means of passing Maya-specific values in and out of the .rag
file for import and export.
\"MarkerUIComponent\": {\n \"driveStiffness\": \"is now -> angularStiffness\",\n \"driveDampingRatio\": \"is now -> angularDampingRatio\",\n}\n\n\"GroupUIComponent\": {\n \"driveStiffness\": \"is now -> angularStiffness\",\n \"driveDampingRatio\": \"is now -> angularDampingRatio\",\n}\n
The prior members remain, but should not be used.
"},{"location":"releases/2022.11.29/#import-attach-constraint","title":"Import Attach Constraint","text":"You can now export and import the Attach Constraint!
"},{"location":"releases/2022.11.29/#scale-attach-constraint","title":"Scale Attach Constraint","text":"You can now scale characters that use the Attach Constraint.
"},{"location":"releases/2022.11.29/#scale-distance-constraints","title":"Scale Distance Constraints","text":"The minimum and maximum values of the Distance Constraint is now scaled alongside your character, just as you'd expect!
Pro tip
Notice how as the character grows in size, the effect of the Distance Constraint diminishes. That's because with greater size comes greater mass. You can control this via Density = 0
which allows you to give a character a fixed mass regardless of size, which you may or may not want!
A tiny little typo slipped in with the prior release, 2022.07.20, which led to you being unable to import anything with replaced meshes. \ud83d\ude2d This has now been fixed! \ud83e\udd73
ri.import_physics()\n// ragdoll._create_solvers() - Creating solver(s)..\n// ragdoll._create_groups() - Creating group(s)..\n// ragdoll._create_markers() - Creating marker(s)..\n// Warning: ragdoll._import_physics_wrapper() - Traceback (most recent call last):\n// File \"C:\\Users\\marcus\\Documents\\maya\\modules\\Ragdoll-2022_07_20\\scripts\\ragdoll\\interactive.py\", line 3604, in _import_physics_wrapper\n// _singleton_import_loader.reinterpret()\n// File \"C:\\Users\\marcus\\Documents\\maya\\modules\\Ragdoll-2022_07_20\\scripts\\ragdoll\\internal.py\", line 441, in _undo_chunk\n// return func(*args, **kwargs)\n// File \"C:\\Users\\marcus\\Documents\\maya\\modules\\Ragdoll-2022_07_20\\scripts\\ragdoll\\dump.py\", line 450, in reinterpret\n// rdmarkers = self._create_markers(rdgroups, rdsolvers)\n// File \"C:\\Users\\marcus\\Documents\\maya\\modules\\Ragdoll-2022_07_20\\scripts\\ragdoll\\dump.py\", line 665, in _create_markers\n// self._apply_marker(mod, entity, rdmarker)\n// File \"C:\\Users\\marcus\\Documents\\maya\\modules\\Ragdoll-2022_07_20\\scripts\\ragdoll\\dump.py\", line 1272, in _apply_marker\n// mobj = meshes_to_mobj(Meshes)\n// File \"C:\\Users\\marcus\\Documents\\maya\\modules\\Ragdoll-2022_07_20\\scripts\\ragdoll\\dump.py\", line 1299, in meshes_to_mobj\n// for index in range(len(polygon_connects) / 3):\n// TypeError: 'float' object cannot be interpreted as an integer\n// Warning: ragdoll._import_physics_wrapper() - An unexpected error occurred, see Script Editor\n
"},{"location":"releases/2022.11.29/#known-issue-render-gliches-from-the-inside","title":"Known Issue - Render Gliches from the Inside","text":"Moving the camera inside of a marker with an outline can look a little freaky!
"},{"location":"releases/2022.11.29/#minor-releases","title":"Minor Releases","text":"Following this release, here are some minor changes made.
2022.12.01
Revert incomplete Locomotion 2.0, coming up in the next larger release.
2022.12.05
Repair broken Educational licences, they were acting like trial/non-commercial licences.
2022.12.13
Keep fields with 0 magnitude from affecting anything.
"},{"location":"releases/2023.04.01/","title":"Locomotion 2.0","text":"Highlight for this release is Locomotion 2.0
As is tradition, let's start off with some of the cool Ragdoll material surfacing across the interwebs since the last release.
Mechanical Spider
\"Mechanical Spider\" by vertexmonster
60s Marionettes
Some excellent use of Ragdoll here by Ernst-Jan on the forums
Human Ball
Zombies + Radial field = This, by Jason
Oh Deer
Another one by Jason from last Christmas.
Fast Food
Jason has been on fire lately, here's another knockout!
A Whale of a Time
Jason jason jason.
"},{"location":"releases/2023.04.01/#locomotion-20","title":"Locomotion 2.0","text":"First released in June 2022, this automated method of generating complete character locomotion has seen a major update!
With a new and much more intuitive workflow, ability to locomote along a path, with feet snapping to terrain and interactive updates as the solver works, you'll be able to achieve much greater results with far less headaches.
"},{"location":"releases/2023.04.01/#new-workflow","title":"New Workflow","text":"Locomotion Markers.
Borrowing from Markers, Locomotion no longer occupies your animation channels directly. Instead, a preview is shown for you to evaluate and later record.
"},{"location":"releases/2023.04.01/#iterative-updates","title":"Iterative Updates","text":"More insight into while you wait.
Locomotion will now show you each result it comes up with, as it searches for one that both looks great and fulfils each of your requirement; targets, limits, mass and gravity.
"},{"location":"releases/2023.04.01/#new-manipulators","title":"New Manipulators","text":"Editing targets and limits was a huge chore with Locomotion 1.0. This new release makes authoring plans much less error prone and more fun.
"},{"location":"releases/2023.04.01/#translate","title":"Translate","text":"Drag the gizmo to translate a target. Notice how it is no longer possible to author invalid targets that hover above the ground, a significant burden to anyone trying to achieve nice results has been lifted!
"},{"location":"releases/2023.04.01/#rotate","title":"Rotate","text":"Hold Ctrl (on Windows and Linux, Cmd on Mac) to rotate a target.
"},{"location":"releases/2023.04.01/#height","title":"Height","text":"Hold Shift to adjust the height of the body. Feet must always touch the ground.
"},{"location":"releases/2023.04.01/#terrain-snapping","title":"Terrain Snapping","text":"Aligning feet to the ground in the case of having a terrain was even more daunting; but no longer! Now feet automatically snap to any terrain.
"},{"location":"releases/2023.04.01/#multi-target","title":"Multi-target","text":"Go there, then here. Do a twirl, and then go over there!
In Locomotion 1.0, you were able to specify a start and end position for your character. But now, you can specify any number of points inbetween, effectively a path!
"},{"location":"releases/2023.04.01/#timing","title":"Timing","text":"Start fast, then walk slowly. Then finish fast!
With more than 1 target, you also need to decide at when you intend on a target being reached. Click and drag on the targets in the UI to adjust.
Shading
You'll notice that each target has two shades, a top and bottom.
Shade Meaning Top Distance, dark is less Bottom Timing, dark is less "},{"location":"releases/2023.04.01/#pin","title":"Pin","text":"Targets are guidelines to Locomotion. It'll try to follow them, but if some are physically impossible or there are conflicting goals then it will try and find a compromise. Sometimes, you need the target to be more respected, and that's when you can \"pin\" a target.
"},{"location":"releases/2023.04.01/#multi-plan","title":"Multi-plan","text":"Create complex locomotion by stringing together two or more plans.
Complete the illusion by blending them all together with traditional Marker physics.
Here's how it works.
The command will start the second plan where the first plan ends, creating one continuous motion.
"},{"location":"releases/2023.04.01/#animation-to-plan","title":"Animation to Plan","text":"A \"make good\" button?
We've talked about generating an animation from a plan, but what about the reverse? What if we could use your animation as input to the plan, and output a refined version of it?
The Animation to Plan
menu item evaluates your animation and converts it into (1) targets and (2) stepsequence; the ingredients to a fully defined plan.
Plans now more accurately follows your terrain and enables you to visualise what Locomotion sees.
"},{"location":"releases/2023.04.01/#reset-starting-position","title":"Reset Starting Position","text":"If you change the starting position of your plan, or move the character after having assigned a plan, you can re-align the two with the Reset Starting Position command.
"},{"location":"releases/2023.04.01/#terrain-debugging","title":"Terrain Debugging","text":"If your terrain has two sides, Locomotion can struggle to snap its feet to the one you intend.
Here's a problematic result.
If we look at the feet snapping, we can see how they tend to snap towards the lower side of this terrain.
We can resolve this by removing the lower side altogether.
And presto, all good!
"},{"location":"releases/2023.04.01/#new-tutorials","title":"New Tutorials","text":"Mohamed Elbebawy has produced a new series of tutorials for Ragdoll, available here.
Released just a few days ago, Ragdoll is fully onboard.
On the other hand, Maya 2018 has left the chat and is no longer supported by Ragdoll (or Autodesk, for that matter!)
"},{"location":"releases/2023.04.01/#account-management","title":"Account Management","text":"You can now monitor and manage your account with us, starting with performing remote deactivation of your node-locked licences.
Features
Checked items are ready for you, unchecked are coming soon!
For the time being, please contact us for login details.
"},{"location":"releases/2023.04.01/#blend-simulation","title":"Blend Simulation","text":"There are now 2 ways in which to blend between simulation and animation; before or after.
"},{"location":"releases/2023.04.01/#before","title":"Before","text":"There is now an option to blend between animation and simulation before recording!
Here are some more examples.
This will also work alongside Translate Motion = Soft
.
Ragdoll typically records your simulation onto a layer, and this layer has a Weight
attribute that you can animate to blend between simulation and animation.
But, most of the time, it isn't doing what you'd expect.
A new option has been added to the Record Simulation option dialog to solve this.
Here you can see the effect in action.
"},{"location":"releases/2023.04.01/#stepped-simulation","title":"Stepped Simulation","text":"Japanese anime, and 2D animation in general, is normally animated on 2's, 3's and sometimes 4's and sometimes at arbitrary times altogether.
Previously, Ragdoll was only ever able to produce 1 frame per Maya frame, meaning the animator would retroactively need to reduce the keys to only happen when animation happens. No longer!
"},{"location":"releases/2023.04.01/#smooth-input-stepped-output","title":"Smooth input, Stepped output","text":"In the simplest case, Ragdoll can be instructed to output simulation ever other or every third frame, or every fourth. Creating a 2D or stopmotion kind of look.
"},{"location":"releases/2023.04.01/#stepped-input-stepped-output","title":"Stepped input, Stepped output","text":"In the more complex case, consider this animation.
Notice how there are pauses between frames, and that keyframes are not distributed evenly. Some have a 2 frame pause, some a 5 frame pause. Here's what would happen if you were to try and simulate this.
Notice how the torso and especially the tail gets jerked around. Because during each pause, Ragdoll goes ahead and simulates it as though the character came to a complete halt. And then kicks off again when it moves, at a very high velocity.
You can now match simulation to when animation occurs, via the new Warp Time
menu item.
Now simulation only happens when the character actually moves. You can control the frequency and time delta of each frame by tuning the resulting animation curve.
Restore Time
Use Restore Time
to get back to a non-stepped simulation.
Time is controlled via a normal animation curve, and there's no reason it cannot also go backwards.
Let your creativity out!
"},{"location":"releases/2023.04.01/#time-method","title":"Time Method","text":"Normally, during playback Maya will transition from one frame to the next. For example, from frame 1 to 2. But sometimes, when a rig is too heavy, Maya may skip a frame or two. For example from 1 to 3, without first visiting frame 2.
To Maya, the different in time between frame 1 and 2 is about 1/24 seconds, with a playback rate of 24 fps; that is, about 41 milliseconds. The difference between frames 1 and 3 is 83 milliseconds.
To Ragdoll, the difference is always 41 milliseconds. No matter the difference in Maya. Why does that matter? Well, consider this.
At frame 17, the character hits the ground. But what if we go to frame 17 immediately, and skip a few more frames?
Now the character hits the ground at frame 78! To Maya, 78 frames has passed; about 3 seconds. But to Ragdoll, barely a second has passed.
With the new Time Method
attribute, you can now choose to handle this in a realistic way instead.
You can now more easily manage which Markers collide, and which does not!
Create New Collision Group
Assign to two or more Markers to create a new collision group.
Add to Existing Collision Group
Select a collision group along with one or more Markers to add.
Remove from Existing Collision Group
Similarly remove Markers.
Multiple Collision Groups
Select multiple groups to visualise them together. They will each occupy a (customisable) color.
Merge Collision Groups
Assign to two or more groups to combine them.
"},{"location":"releases/2023.04.01/#trajectories","title":"Trajectories","text":"You can now visualise the trajectories of your Markers via the Solver Display attribute.
"},{"location":"releases/2023.04.01/#mass-independent-fields","title":"Mass Independent Fields","text":"Fields were introduced in Ragdoll 2022.02.14 to help apply environment effects such as wind and turbulence to your animations.
Forces are applied as they would in real life... which isn't always practical!
Consider this.
Here, as the character grows in size, so does its mass. As the mass increases, the effect of the turbulence force diminishes. Since the same force is applied to a now much-heavier object. Like if you pushed on a woodden door and then tried pushing a car; your muscles remain as strong, but the object is now much heavier.
With this release, forces are instead applied evenly regardless of mass, which should result is more control and predictability of your simulation.
You can revert to the old (realistic) behaviour by changing Force Mode
from Velocity Change
to Force
in the rSolver
node.
Ragdoll supports 4 geometry types for collisions.
Assign to a control, and then use Replace Mesh
alongside any geometry to use this geometry for collision detection.
However!
Sometimes collisions are more complex and require multiple meshes to make up 1 physical collision shape. You can now achieve this with ease.
You can now select any number of meshes and use the combination of them as a collision shape.
"},{"location":"releases/2023.04.01/#pin-constraint-pivot","title":"Pin Constraint Pivot","text":"You can now control where on a Marker to Pin Constrain it.
Hold D
to edit the position of the rotate pivot
Like the Pin Constraint, Attach Constraints can have their pivots edited too. Especially useful if you are looking to attach two Markers at a specific location.
"},{"location":"releases/2023.04.01/#quality-of-life","title":"Quality of Life","text":"Last but not least, a few minor things to make your life easier.
"},{"location":"releases/2023.04.01/#new-behaviour-names","title":"New Behaviour Names","text":"The options for a Marker's Behaviour
attribute has been updated for more clarity.
Inherit
-> Use Group
Kinematic
-> Animated
Dynamic
-> Simulated
The name \"kinematic\" is the technical term for when something is animated, so we figured we may as well call it what it is! A Marker set to Animated
is entirely animated, with no simulation applied. It may affect other Simulated
Markers, but cannot be affected by them.
Some things in Ragdoll can be animated, others cannot. Those that cannot can also not be changed on any frame other than the start frame.
This used to be a chore, and is no longer! Ragdoll will now automatically return to the start frame when it needs to, leaving you with less to worry about.
"},{"location":"releases/2023.04.01/#symmetry-and-undo","title":"Symmetry and Undo","text":"You can now undo both sides at once, as you'd expect!
"},{"location":"releases/2023.04.01/#z-up-assets","title":"Z-up Assets","text":"You can now export assets from a Y-up Maya scene, and load it into a Z-up Maya scene! This means our default assets, which were made in a Y-up environment, will now load perfectly fine in your Z-up scenes.
Before
After
"},{"location":"releases/2023.04.01/#linked-solver-crash","title":"Linked Solver Crash","text":"Many linked solvers could potentially crash Maya, no longer!
"},{"location":"releases/2023.04.01/#deprecating-max-mass-ratio","title":"Deprecating Max Mass Ratio","text":"Ragdoll likes when the masses of objects that interact are somewhat similar. A 60kg character sitting on a 100kg horse is \ud83d\udc4c. But a million ton planet falling onto a 60g ant is less than OK.
To combat this, an attribute was introduced a while back called Max Mass Ratio
whose job it was to even out the differences (\"ratio\") between masses. But it didn't work that great, the simulation was no happier because of it.
So in this release, we are deprecating this attribute. It will still exist in your scene, and can be found at the very bottom of the Solver node in the Attribute Editor. If you find yourself needing it, let us know. If not, you have one less thing to worry about.
"},{"location":"releases/2023.04.01/#restore-t-key","title":"Restore T Key","text":"There's an option to restore the functionality of the T key, and to change it to something else.
"},{"location":"releases/2023.04.01/#one-off-bug","title":"One-off bug","text":"Ragdoll was reading values from Maya that were 1 frame too old.
Before
I'm stepping through the simulation, notice how the pelvis is set to Animated
(Kinematic) but how it doesn't actually have an effect until the next frame?
After
This has now been fixed.
"},{"location":"releases/2023.04.01/#solver-update","title":"Solver Update","text":"The underlying maths behind your physics has been modernised to resolve subtle issues but primarily lay the foundation for new things to come. You shouldn't notice much of any difference, apart from subtle things like this.
For the Python folk out there, these members were added to the Python API.
from ragdoll import api\n\n# Create a new group\ngroup = api.assign_collision_group(markers)\n\n# Add some more markers\napi.add_to_collision_group(other_markers, group)\n\n# Remove some markers\napi.remove_from_collision_group(markers, group)\n
"},{"location":"releases/2023.10.03/","title":"Beyond Ragdoll","text":"Highlight for this release is.. lots of releases!
And we're back! This release is going to be a little different. Over the past few months, we've expanded upon Ragdoll's reach. It used to be written as a Maya-only plug-in, but is now written as a software development toolkit, an SDK, and re-integrated into Maya. This means that we can reuse the Ragdoll \"core\" in other software, such as Blender. It also means we can use it without Maya, and without Blender. As its own independent application! It also means developers out there can incorporate Ragdoll into their own software, as a dedicated ragdoll-simulation solution.
To summarise, \"Ragdoll\" is now:
Product Description Ragdoll Maya Autodesk Maya integration, the one you know! Ragdoll Blender New integration for Blender Ragdoll Standalone Ragdoll without strings Ragdoll Web Ragdoll in your browser and on your phone Ragdoll SDK Software Development Kit (SDK)So, lots of new potential!
"},{"location":"releases/2023.10.03/#releases","title":"Releases","text":"We'll be releasing each new product separately, so to kick things off starting with the new Maya release which boasts a lot of new fixes and improvements.
Read more
The next release will be Ragdoll for Blender, follow us on LinkedIn for live updates.
Highlight for this release is.. Blender!
After months of labour, we're pleased to announce Ragdoll for Blender is now generally available.
"},{"location":"releases/2024.02.29/#blender","title":"Blender","text":"Find a full breakdown of this new release here.
It's a little different from previous releases, in that it does not assume prior knowledge of Ragdoll since Blender is an entirely new audience for us.
"},{"location":"releases/2024.02.29/#open-source","title":"Open Source","text":"You'll now find much of the source code for Blender's Ragdoll on GitHub, to serve as a reference implementation for the forthcoming Ragdoll SDK that you/developers can use to incorporate Ragdoll into new DCCs and games.
Developers out there may recognise bpx
as the Blender equivalent to cmdx
we developed for Maya, to cope with the performance and maintainence burden of Ragdoll.
Contacts now include the direction and magnitude of the force being applied, helping you understand how strong (or weak) forces are at specific locations.
"},{"location":"releases/blender/2024.02.29/","title":"Ragdoll x Blender","text":"Today we are pleased to announce Ragdoll for Blender!
Ragdoll is a real-time physics solver for animators originally built for Autodesk Maya and now available to Blender!
Started development in 2021 by animator/programmer Marcus Ottosson, Ragdoll has since been adopted by just about every large visual effects company in the world and several AAA and indie games studios too.
If you've been to the theatres at any point in the past few years, it is highly likely you've witnessed Ragdoll-powered animations!
Now we're extending the reach of Ragdoll to those outside of the Maya domain, to you lovely bunch in the Blender camp. Our hope is that more animators will be able to benefit from Ragdoll, whilst also encouraging new animators to join the field with access to more tools to help simplify the animation process.
"},{"location":"releases/blender/2024.02.29/#showcase","title":"Showcase","text":"Here are some examples of Ragdoll in the wild.
Character animation is hard.
You've got the techincal barrier of understanding your computer and software, which on its own is hard, but then you've got the artistic choices involved in communicating your story. There are poses and there is timing - critical to any performance. But then you have momentum, contacts and a sense of weight.
Equally critical but boring.
Your audience has a keen eye for things like momentum and contacts, often without realising it. It feels either right or wrong. And it is incredibly hard - as an animator - to get it right.
This is where Ragdoll can help.
Animation is all about breathing life into inanimate objects, but also lifelessness. It's a spectrum, and Ragdoll can almost entirely handle a large part of this spectrum on its own.
0% Life 100% Life\n|--------------------------------------------------------------------|\n^ ^\n| |\n|=======================================|\n Ragdoll\n
In its most simple form, Ragdoll can entirely generate lifeless animation.
With keyframes for input, it can generate semi-lifeless animation.
"},{"location":"releases/blender/2024.02.29/#how-does-it-work","title":"How does it work?","text":"Ragdoll monitors your animation and provides you with a preview of what it would look like if you let physics take the wheel.
In this example, the blue character is your animation. It's the \"guide\" for the simulated version of your animation.
Here's what that might look like in practice.
Here's a more elaborate example, animation versus simulation towards the end.
Points of interest.
Ok, with that out of the way, let's get you going with Ragdoll!
We aim to get Ragdoll to users on all platforms, the one lagging behind is MacOS due to its recent transition to Metal for rendering into the viewport.
Blender Windows Linux macOS 3.4 \u2714\ufe0f \u2714\ufe0f \u274c 3.5 \u2714\ufe0f \u2714\ufe0f \u274c 3.6 \u2714\ufe0f \u2714\ufe0f \u274c 4.0 \u2714\ufe0f \u2714\ufe0f \u274cMacOS
Tim Apple made it difficult with their transition to Metal, and Blender followed suit with version 3.5. Ragdoll was originally built with OpenGL and DirectX support and it'll take a moment to re-do all of this work (again!) for Metal.
"},{"location":"releases/blender/2024.02.29/#quickstart","title":"Quickstart","text":"In the Ragdoll menu, load some asset and fool around.
You can also enter into the \"Manipulator\" to fool around even more.
Tense
Hold Shift to toggle the \"Tense\" icon, having the character try to reach its current Blender pose.
"},{"location":"releases/blender/2024.02.29/#first-steps","title":"First steps","text":"With our beak wet, let's have a look at how this actually works.
Step 1
Make a cube.
Step 2
Assign a \"Marker\"
Step 3
Record Simulation.
And that's it! You'll now find keyframes on your cube.
"},{"location":"releases/blender/2024.02.29/#second-steps","title":"Second Steps","text":"With your first steps out of the way, let's have a look at how this applies to a real-world scenario, to achieve this:
We'll use one of the Animation Fundamental rigs.
Step 1
Once you've loaded your character, you can start assigning to the controls you normally use to animate with.
Step 2
Next, we tune our shapes to better fit our character. This helps distribute mass and make things move more realistically, as though your character was an actual physical being.
In this case, we'll also use some of the meshes of the character directly, as opposed to simple capsules.
Step 3
If your character didn't already have animation, let's add some!
Step 4
Finally, we can record the simulation onto keyframes to witness the result.
"},{"location":"releases/blender/2024.02.29/#third-steps","title":"Third Steps","text":"Many new concepts in the above few steps, here's a full walkthrough of all steps.
If you are already familiar with Ragdoll from Maya, here's what's carried over versus missing so far.
Feature Status Notes Solver \u2714\ufe0f Marker \u2714\ufe0f Group \u2714\ufe0f Manipulator \u2714\ufe0f Live Mode \u2714\ufe0f Constraints \u2714\ufe0f Export Physics \u2714\ufe0f Load Physics \u2714\ufe0f Record Simulation \u2714\ufe0f Retargeting \u2714\ufe0f Licencing \u2714\ufe0f Collision Group \u274c But you can use Marker'sOverlap Group
instead Force Fields \u274c Coming Soon \u2122 Snap to Simulation \u2714\ufe0f Import Physics \u274c Export Physics \u2714\ufe0f Update Physics \u274c "},{"location":"releases/blender/2024.02.29/#performance","title":"Performance","text":"Ragdoll in Blender runs at 0.6x performance compared to Maya, which is far greater than we'd hoped considering that much of the addon is written in Python whereas the Maya plug-in is entirely written in a compiled language.
Compared to Blender's native physics, the comparison is more difficult because Ragdoll does more than Blender, primarily steering the simulation with your animation. What we do share however is a general simulation of loose objects with a high amount of substeps. In this regard, Ragdoll is both more stable (less explosions) and more accurate (automatically computed mass and center of mass).
In this scenario, ragdoll runs about 30% faster than native Blender physics.
That said, this scene features heavy interpenetrations of objects which require Split Impulse
to be enabled (Ragdoll does something similar). Without it, Blender struggles with intersections but runs much faster, on the order of 10x quicker than Ragdoll.
With this in mind, native physics is better suited for large scenes of loose objects, like building destruction and the like.
"},{"location":"releases/blender/2024.02.29/#open-source","title":"Open Source","text":"The Blender Addon is licenced under MIT, and so is bpx
; the library we developed specifically for Ragdoll. They can both be found on GitHub, here.
You're all set. We'll work towards more tutorials, including how to achieve this effect from Kojima's Death Stranding 2.
See also
Enjoy, and speak soon! :party:
"},{"location":"releases/blender/2024.03.07/","title":"Patch 1","text":"Minor patch release for Blender with common issues patched up and ready to go! :party:
Check out this awesome thread on the forums from user @Manikandan_Rajendran!
We've got a new tutorial, live and available on YouTube!
Ragdoll will now tell you when exceeding the 100 frame limit during trial, it'll also tell you when it expires which for those of you who started the trial on the 1st of March should happen around the 1st of April. Minor things that solve a lot confusion.
The binaries we shipped are now also \"code signed\", meaning Windows will be familiar with them and not warn about potential threats. This should have happened before but we've had a bit of an office move in the past week so things have been up in the air!
You'll also find instructions on how to activate your licence on the Download page for Blender.
Download links are in the usual places, right here:
Stay tuned for more, and please report any issues or feature requests on our forums, here:
Enjoy, and see you soon!
"},{"location":"releases/blender/2024.04.09/","title":"Patch 2","text":"Minor patch release for Blender with common issues patched up and ready to go! \ud83e\udd73
Let's start with some goodies!
"},{"location":"releases/blender/2024.04.09/#new-tutorials","title":"New Tutorials","text":"The above goodies are part of the new tutorials since last release!
You'll now find a more pleasant looking geometry for convex meshes.
"},{"location":"releases/blender/2024.04.09/#merge-solvers","title":"Merge Solvers","text":"You can now append one character into scene with an existing solver, and either continue to simulate each independently or merge their solvers to have them interact.
See Maya release notes for the same feature for more details.
You can now export your Ragdoll character and load it back in.
This can be helpful to debug complex characters, but it can also be used for inter-application export and load, like this one to Maya.
The file format will be compatible with the Standalone and Web versions of Ragdoll too, anything you export will work everywhere!
"},{"location":"releases/blender/2024.04.09/#record-quaternions","title":"Record Quaternions","text":"Ragdoll will now respect the choice of rotation interpolation, rather than setting them to Euler/XYZ upon recording.
"},{"location":"releases/blender/2024.04.09/#download","title":"Download","text":"As always, you can find the latest download on the Downloads page.
Note
This update involves both Ragdoll for Blender and Ragdoll Core, so be sure to get both up to 2024.04.09 for this to work.
"},{"location":"releases/core/2023.07.xx/","title":"Ragdoll Core","text":"No longer just a Maya plug-in. Today we are announcing Ragdoll Core, a Ragdoll software development kit (SDK) to enable third-parties to integrate Ragdoll into their own projects, from Games to DCCs.
We extracted all of what was unique about Ragdoll from Maya and turned it into its own project. Ragdoll Core is the enginer that powers Ragdoll, and now you can benefit from this engine too. If you develop your own software or game and are interested in utilising Ragdoll for your character animation needs, contact us!
Highlight for this release is Universal Transfer!
These release notes are the Maya-specific notes from the overall notes here.
For minor patch notes, e.g. 2023.10.06 see the announcement thread.
Let's start with the good stuff!
Jasons Spider
Jason's Monkey
Skeletons
Excellent work by Hirokazu-san!
Davy Jones
Enother excellent piece by Nithin_Piano on our forums.
Retro
Finished work by Erns-Jan on our forums.
Ragdoll will now happily simulate without requiring a licence.
This has 2 main implications.
Licences now only become relevant when getting simulation out of Ragdoll, primarily to record your simulation. This way, you can learn and experiment with simulation to your hearts content and only pay for a licence and seat when you are happy with the result. How great is that?
"},{"location":"releases/maya/2023.10.03/#universal-transfer","title":"Universal Transfer","text":"Live Mode now works with native Maya rigs!
Rig from https://agora.community/content/stormtrooper-may
Rig from https://www.cgspectrum.com/resources/tiger-animation-rig
IK too
Notice how all controllers, including IK, is transferred. This was not possible before!
"},{"location":"releases/maya/2023.10.03/#distraction-free-posing","title":"Distraction Free Posing","text":"Use Live Mode as a substitute for your normal animation controls, by SHIFT clicking on the transfer button. This overlays Ragdoll over your character and automatically transfers upon releasing the mouse cursor.
At this point, we can go distraction-free and hide all NURBS control to work entirely with Live Mode.
"},{"location":"releases/maya/2023.10.03/#background","title":"Background","text":"So, wasn't this the case already?
Live Mode was released with Ragdoll 2022.11.29 as a means of experimenting and gaining intuition of limits and contacts. With it came the ability to transfer the live poses back onto the Maya character. However, it only supported characters loaded natively with Ragdoll, or at best very simplistic native Maya rigs. Those that consisted of a plain FK hierarchy, such as a joint hierarchy.
At the time, it seemed this mechanic would not be possible with native Maya rigs, since Ragdoll relies on this hierarchy to figure out the final position and orientation of each body part. For example, to know where the hand is, Ragdoll first needs to know where the arm is, which needs to know where the torso is and where the hip is and so on. The hand depend on those positions.
Native Maya rigs don't work like that; they rarely form a linear hierarchy like this, with IK and space switching constraints and stretchy limbs all complicating the transformation path from hip to hand.
"},{"location":"releases/maya/2023.10.03/#tuning","title":"Tuning","text":"The universal transfer is an \"iterative\" solver. Here's how it works:
The challenge is that some control cause other controls to move. For example, after Ragdoll has matched the foot, matching the upper leg would move the foot again. And so the process needs to be repeated until each cyclic dependency is resolved.
Per default, Ragdoll will iterate up to 4 times, and stop as soon as controls get \"close enough\". The distance Ragdoll considers \"close enough\" is called \"tolerance\" and the number of times it attempts to reach that position is called \"iterations\".
Here's the normal circumstances.
And here's what happens when you tune iterations.
Notice how that with just 1 iteration, it isn't enough to transfer once. You'll have to keep pressing the transfer button until your character is close enough. That's that's exactly what iterations do; they keep pressing the button until it's close enough.
"},{"location":"releases/maya/2023.10.03/#iterations","title":"Iterations","text":"Here's one more visual to help you understand the effect of iterations.
Here, iterations are set to 1, meaning that each time we click we run exactly 1 iteration.
Pro Tip
You can manually type in an iteration count, such as 8 or 16, in case 4 is not enough. Generally, it depends on the number of cycles in your rig that contradicts the hierarchy. For example, if the upper leg is affected by the foot, then that's a cycle. This is also the most common cycle for IK-based rigs, where the upper leg is affected by the pole vector which is typically affected by the foot.
"},{"location":"releases/maya/2023.10.03/#minimum-iterations","title":"Minimum Iterations","text":"Sometimes, Ragdoll thinks it finds a close match, but you as a human know better. That's when you can force Ragdoll to keep trying to find a match for X number of times. This number is the minimum number of iterations.
"},{"location":"releases/maya/2023.10.03/#limitations","title":"Limitations","text":"Some rigs are still out of bounds for Ragdoll, no matter how many iterations. Here are a few things you can potentially expect depending on the complexity of your rigs.
Notice how the arm sometimes doesn't match, until you hit the transfer button a few more times.
Help
If you find a pattern, something small that consistently fails, let us know. We'd like to solve this!
"},{"location":"releases/maya/2023.10.03/#update-physics","title":"Update Physics","text":"Work faster and in parallel with your peers using this new feature.
Rag files can now be used presets and save-states for your characters, enabling updates to your character as you animate.
"},{"location":"releases/maya/2023.10.03/#options","title":"Options","text":"Everything is updated per default, minus any attribute that is already keyframed or otherwise locked. For more control, see the options provided in the UI.
Option Description Include Materials Friction, restitution and collide attributes Include Shapes Extents, radius and shape type Include Limits On/off state, angles, frames Include Springs Stiffness and damping Include Solvers Whether to include solver attributes at all Include Markers Whether to include any Marker attributes at all Include Constraints Whether to include pin constraints et. al. Include Groups Whether to include groups Include Targets If Markers have been retargeted, include the new target "},{"location":"releases/maya/2023.10.03/#update-api","title":"Update API","text":"Since this is suitable for pipeline automation, here's what you tech gurus can do.
from ragdoll import api\napi.update_physics(fname, opts)\n
Where fname
is the full path to a .rag
file, such as c:\\assets\\storm1.rag
and opts
is an optional dictionary with the same options as for import_physics
.
Options
You'll generally want to match these with whatever options you used to originally import your .rag
file.
opts = {\n \"roots\": [],\n \"matchBy\": constants.MatchByHierarchy,\n \"searchAndReplace\": [\"\", \"\"],\n \"namespace\": None,\n \"preserveAttributes\": True,\n \"retarget\": True,\n\n \"overrideSolver\": \"\",\n \"createMissingTransforms\": False,\n\n \"includeSprings\": True,\n \"includeLimits\": True,\n \"includeShapes\": True,\n \"includeMarkers\": True,\n \"includeGroups\": True,\n \"includeSolvers\": True,\n \"includeConstraints\": True,\n \"includeMaterials\": True,\n \"includeTargets\": True,\n}\n
"},{"location":"releases/maya/2023.10.03/#snap-to-simulation","title":"Snap to Simulation","text":"This button has seen an upgrade too, and now works like the Live Mode transfer!
"},{"location":"releases/maya/2023.10.03/#ghosting","title":"Ghosting","text":"Gain greater control over your animation by visualising past and present.
"},{"location":"releases/maya/2023.10.03/#caching","title":"Caching","text":"Cache your simulation to see the future too, this can be helpful when making tweaks without changing time to see the effects of your tweaks with very high precision.
"},{"location":"releases/maya/2023.10.03/#past-future","title":"Past & Future","text":"Tune the number of frames to look ahead or into the past.
"},{"location":"releases/maya/2023.10.03/#increment","title":"Increment","text":"Choose how many frames in between each frame to skip.
"},{"location":"releases/maya/2023.10.03/#colors","title":"Colors","text":"Finally, tune the colors of your ghosts to fit your preference.
"},{"location":"releases/maya/2023.10.03/#live-mode-precision","title":"Live Mode Precision","text":"You'll now find greater precision when posing your character in Live Mode, along with an improved IK behaviour.
IK will now lock the grandparent of anything you drag, just like traditional IK, in addition to keeping the Marker you drag from rotating.
Pro Tip
Hold the SHIFT key for a \"full-body IK\" type behaviour.
"},{"location":"releases/maya/2023.10.03/#additive-recording","title":"Additive Recording","text":"You can now record physics onto an additive layer, meaning layers can be combine, blended and kept active even when changing the underlying animation.
"},{"location":"releases/maya/2023.10.03/#scene-scale","title":"Scene Scale","text":"There is now an interactive widget to configure Ragdoll to fit your character.
When creating your first scene, Ragdoll will automatically try and detect your scene scale based on your first assignments.
See this option in the UI for how to control this.
"},{"location":"releases/maya/2023.10.03/#mass-units","title":"Mass Units","text":"Units now make physical sense.
Kilograms all around
Notice how values are in kg
This not only enables you to get a clear sense of what scale simulation happens at, but also provides accurate values of mass, in kilograms. A typical human weighs 60-100 kg and Ragdoll's forces depend on this being an accurate measure. Previously, mass was rather fixed at 6-10 kg as Ragdoll assumed your characters were roughly 18 cm tall, as is the norm in visual effects and animation (strangely enough!).
You'll also see the effect of making your character a giant, via the new Scene Scale manipulator.
With this release, characters of any scale will produce identical results.
Pro Tip
Because a giant weighs more, it also has an effect on any forces that act upon it. Like trying to push a car versus pushing a planet; the same amount of push will affect the object differently.
"},{"location":"releases/maya/2023.10.03/#rotation-mass","title":"Rotation Mass","text":"You'll also notice a new member to the property panel; Rotate Mass
. This can help you understand how easily an object starts to spin and how strongly it is affected by Rotate Stiffness
in which axis.
An axis with little mass will move more quickly and with less force; it will also affect other objects less. Just like Mass
, except for rotations!
Pro Tip
This is also called Moment of Inertia and Angular Momentum, if you would like to Google it.
"},{"location":"releases/maya/2023.10.03/#influence","title":"Influence","text":"The Attach Constraint has a new attribute called Influence
that lets you control the amount of influence the child has over its parent.
You can use it when you want one Marker to reach another, without the other being influenced by it. Notice here for example how the monkey limbs reach for the limb, without the limb being affected (until eventually reaching, at which point the influence is animated back to 0.5).
And yes, you can animate this attribute!
"},{"location":"releases/maya/2023.10.03/#resizable-uis","title":"Resizable UIs","text":"Sometimes names of things gets too long, and the UI is unable to fully show it to you. Until now, when you can (finally) resize the UI horizontally!
"},{"location":"releases/maya/2023.10.03/#root-stiffness","title":"Root Stiffness","text":"The first controller in your character hierarchy can now make use of Rotate and Translate Stiffness, just like any of its children. The difference is, the parent of the root is the world; so it will behave just like it was Pin Constrained.
"},{"location":"releases/maya/2023.10.03/#quality-of-life","title":"Quality of Life","text":"A number of smaller things have been addressed, take a look!
"},{"location":"releases/maya/2023.10.03/#multi-select-replace-mesh","title":"Multi-select Replace Mesh","text":"Sometimes, you need more than just a single mesh for your Marker. That's when you can combine your meshes and use the resulting combined mesh to replace with. We've saved you the extra clicks in this release, making it possible to do this!
Each mesh will be combined into a single Marker mesh.
"},{"location":"releases/maya/2023.10.03/#prevent-duplicate-markers","title":"Prevent Duplicate Markers","text":"Sometimes, you accidentally assign
"},{"location":"releases/maya/2023.10.03/#attach-constraint-parent","title":"Attach Constraint Parent","text":"You can now unparent an attach constraint, leaving it at the root of your Outliner. There's also a new option called \"Parent\" in the UI you can use to set the default.
"},{"location":"releases/maya/2023.10.03/#record-translation-rotation","title":"Record Translation & Rotation","text":"When Markers were first added to Ragdoll, they came with two attributes called:
Record Translation
Record Rotation
The idea being that you can choose whether controls should receive translation keyframes, rotation keyframes or both. It didn't work; because the way we recorded was somewhat limited.
This changes today, and you are now able to use these attribute to selectively skip or include channels that would otherwise receive keyframes.
"},{"location":"releases/maya/2023.10.03/#api-changes","title":"API Changes","text":"There is now an alias for reinterpret_physics
, which has already had a bit of a difficult name. The word \"import\" has special meaning in Python, hence it was mostly avoided. But alongside _physics
it is now available as:
from ragdoll import api\napi.import_physics(fname, opts)\n
"},{"location":"releases/maya/2023.10.03/#deprecated","title":"Deprecated","text":"Less attributes to worry about in this release; if you use them you are adviced to transition away from these.
Mass Ratio
on the rdSolver
node has been deprecatedDrive Per Substep
attribute on the Solver node turned out to be a success and is now always-on!Frameskip Method
attribute on the Solver node has been removed, turns out Pausing the simulation is never really that useful!Highlight for this release is ...!
The rendering pipeline has been upgraded with some new bells and whistles!
There's a new window to control the overall render settings under Ragdoll
-> System
-> Ragdoll Rendering
that look like this.
Contacts now include the direction and magnitude of the force being applied, helping you understand how strong (or weak) forces are at specific locations.
"},{"location":"releases/maya/2023.11.xx/#translate-and-rotate-drag","title":"Translate and Rotate Drag","text":"Previously called \"Translate Damping\" and \"Rotate Damping\", these attribute lets you block motion of an individual Marker, similar to the Air Density
attribute on the Solver except applied to an individual Marker.
You can override the scale of your UI in Maya's global preferences.
Ragdoll wasn't aware of this, and used your display scaling directly. Now it is away, and scales with Maya as you would expect!
Programmers
For the programmers out there, the trick is to query maya.MQtUtil.dpiScale
, instead of going through native Qt, e.g. QWindow.QScreen().logicalDotsPerInch() / 96.0
since Maya overrides this value.
Typically, Markers are assigned to a hierarchy of controls in a character rig, and thus translation is only relevant to the root control. But when assigning to a series of objects part of, say, a brick wall then you would expect all objects to have translation recorded as well.
That is now the case!
"},{"location":"sdk/download/","title":"Download","text":"Download Ragdoll CoreIf you agree with the Ragdoll Dynamics EULA, you may select a platform below.
Windows LinuxRagdoll 2024.04.15 awaits. Read about it - Previous versions
Join the community of ragdollers on Discord and/or Discourse.
Chat Forums "},{"location":"sdk/download/#install-on-windows","title":"Install on Windows","text":"To install Ragdoll Core, double-click the RagdollCore.msi
you downloaded from above, and click through the dialogs.
Ragdoll core installation on Linux is basically two steps:
RagdollCore*.zip
above/home/user-name
, replacing user-name
with your usernameFor example, to install current latest core:
cd ~/\nwget https://content.ragdolldynamics.com/6fb6a202-bd24-4db0-8d03-40e8c306c20c/RagdollCore-linux-2024.03.07.zip\nunzip RagdollCore-linux-2024.03.07.zip\n
If you prefer to place core libraries in elsewhere, environment variable RAGDOLL_CORE_PATH
can be used.
For example:
export RAGDOLL_CORE_PATH=/home/user-name/ragdolldynamics/core/2024.03.07/lib\n
"},{"location":"sdk/home/","title":"SDK","text":"The Ragdoll SDK is not Object Oriented, it is Data-Oriented in the form of an Entity Component System (ECS).
Concept Is A Description Entityunsigned int
Represents a \"thing\", like a marker, group and solver Component struct
Represents some data, like a name, position and color System for-loop
Represents some operation on said data Stay Tuned
This is where you'll find documentation for Ragdoll Core.
"},{"location":"sdk/serialisation/","title":"Serialisation","text":"Serialise all rigid bodies to JSON, for import into external software such as Unreal, Unity, Godot, CryEngine or any other engine able to read and parse JSON, including your own custom game engine.
Units
centimeters
radians
XYZW
On playback, Ragdoll generates a physical representation of your Maya scene, suitable for simulation. You can gain access to that representation, independent of Maya, for use in your own software and for your own purposes.
This enables you to use Maya as an authoring environment for general-purpose physics scenes, including full or partial ragdolls, for characters or props and even full environments.
"},{"location":"sdk/serialisation/#target-audience","title":"Target Audience","text":"Once a ragdoll has been authored in Maya, it can be exported for later import into external software for a variety of purposes.
Ragdoll internally stores data as \"entities\" and \"components\".
The exported format reflects this relationship and looks something like this.
{\n \"entities\": {\n \"10\": {\n \"components\": {\n \"NameComponent\": \"upperArm\",\n \"ColorComponent\": [1.0, 0.0, 0.0],\n \"GeometryDescriptionComponent\": \"Capsule\",\n ...\n }\n },\n \"15\": {\n \"components\": {\n \"NameComponent\": \"lowerArm\",\n \"ColorComponent\": [0.0, 1.0, 0.0],\n \"GeometryDescriptionComponent\": \"Box\",\n ...\n }\n }\n}\n
"},{"location":"sdk/serialisation/#rigid-body","title":"Rigid Body","text":"A single translation/rotation pair.
Components
Component DescriptionNameComponent
Name and path in Maya ColorComponent
Used in Maya viewport SceneComponent
Reference to the scene entity this rigid belongs to RestComponent
Initial transformation RigidComponent
Physics attributes GeometryDescriptionComponent
Shape attributes \"RigidComponent\": {\n \"type\": \"RigidComponent\",\n \"members\": {\n \"enabled\": true,\n \"mass\": 1.0,\n \"friction\": 0.80,\n \"restitution\": 0.10,\n \"thickness\": 0.0,\n \"disableGravity\": false,\n \"collide\": true,\n \"kinematic\": false,\n \"dynamic\": true,\n \"sleeping\": false,\n \"linearDamping\": 0.5,\n \"angularDamping\": 1.0,\n \"positionIterations\": 8,\n \"velocityIterations\": 1,\n \"maxContactImpulse\": -1.0,\n \"maxDepenetrationVelocity\": -1.0,\n \"sleepThreshold\": 0.00,\n \"enableCCD\": false,\n\n # A value of -1 means \"automatically computed\"\n \"angularMass\": {\n \"type\": \"Vector3\",\n \"values\": [-1.0, -1.0, -1.0]\n },\n\n # A value of 0 means \"automatically computed\"\n \"centerOfMass\": {\n \"type\": \"Vector3\",\n \"values\": [0.0, 0.0, 0.0]\n }\n }\n}\n
"},{"location":"sdk/serialisation/#shape","title":"Shape","text":"Every rigid has exactly one collision shape. The transformation of this shape can be optionally offset, and that offset happens in the frame of the rigid.
________\n ^ |\\ \\\n | | \\_______\\\n | | | |\n o--\\-|-> |\n \\ \\|______|\n \\\n v\n
In this example, the center of the box is offset from the center of the rigid along the X axis. Notice how the geometry is relative the axis of the rigid, so rotating the rigid along the Z axis would naturally take the geometry with it.
\"GeometryDescriptionComponent\": {\n \"type\": \"GeometryDescriptionComponent\",\n \"members\": {\n \"type\": \"Capsule\",\n\n # Used by Capsule\n \"length\": 0.123,\n\n # Used by Sphere\n \"radius\": 0.012,\n\n # Used by Box\n \"extents\": {\n \"type\": \"Vector3\",\n \"values\": [0.123, 0.024, 0.0247]\n },\n\n # Translation relative the associated rigid\n \"offset\": {\n \"type\": \"Vector3\",\n \"values\": [0.033, -0.05, 0.00]\n },\n\n # Rotation relative the associated rigid\n # Ordered as XYZW\n \"rotation\": {\n \"type\": \"Quaternion\",\n \"values\": [0.87, -0.47, 0.00, 0.00]\n }\n }\n}\n
"},{"location":"sdk/serialisation/#constraint","title":"Constraint","text":"A relationship between two rigid bodies is referred to as a \"constraint\". A constraint constrains the way two rigid bodies move relative each other.
For example, the position of the lower arm is typically associated with the tip of the upper arm. Wherever the upper arm goes, the lower arm must follow. It may also be further limited in how it is oriented, to e.g. prevent a lower arm from bending past the natural elbow limit; i.e. to rotate between 20-180 degrees along the Z axis, and 0-10 degrees around the X and Y axis (as that rotation would normally come from twisting the upper arm).
parentFrame
childFrame
Despite the name, there is no notion of hierarchy or \"parent\" in Ragdoll; the naming reflects the hierarchy as represented in Maya, where constraints are parented to the rigid representing the childFrame
.
Components
Component DescriptionJointComponent
References to associated rigids and frame matrices LimitComponent
Optional limits on translation and/or rotation DriveComponent
Optional target transformation, i.e. the animation \"JointComponent\": {\n \"type\": \"JointComponent\",\n \"members\": {\n\n # Reference to the associated rigid body entities\n \"parent\": 1048586,\n \"child\": 1048584,\n\n # The translate/rotate of the parent\n # rigid in the frame of child rigid\n \"parentFrame\": {\n \"type\": \"Matrix44\",\n \"values\": [\n 0.760, -0.594, -0.259, 0.0,\n -0.648, -0.680, -0.340, 0.0,\n 0.0262, 0.4274, -0.903, 0.0,\n 10.51, -0.646, 0.0, 1.0\n ]\n },\n\n # The translate/rotate of the child\n # rigid in the frame of parent rigid\n \"childFrame\": {\n \"type\": \"Matrix44\",\n \"values\": [\n 0.606, -0.751, -0.259, 0.0,\n -0.785, -0.515, -0.340, 0.0,\n 0.122, 0.4103, -0.903, 0.0,\n 0.0, 0.0, 0.0, 1.0\n ]\n },\n\n # Allow intersections between connected rigids\n \"disableCollision\": true\n }\n}\n
"},{"location":"sdk/serialisation/#limit","title":"Limit","text":"Constraints may optionally have a \"limit\", which means it can keep a rigid within a given angle (\"angular limit\") or position (\"linear limit\").
Min & Max
Values represent a upper end of a range. With x=5
the minimum value of the linear X axis is -5
.
\"LimitComponent\": {\n \"type\": \"LimitComponent\",\n \"members\": {\n \"enabled\": true,\n \"x\": -1.0, # Linear limit along the X-axis\n \"y\": -1.0,\n \"z\": -1.0,\n \"twist\": 0.78, # Angular limit along the X-axis\n \"swing1\": 0.78, # ..Y\n \"swing2\": 0.78, # ..Z\n \"angularStiffness\": 1000000.0,\n \"angularDamping\": 10000.0,\n \"linearStiffness\": 1000000.0,\n \"linearDamping\": 10000.0\n }\n}\n
Locked, Free or Limited
A value of -1
means the axis is \"Locked\", i.e. the value along this axis cannot change. A Point Constraint is typically locked on all linear axes, but free on the angular axes. A value of 0
means the axis if \"Free\", meaning it has no effect. It is \"limitless\". A value above 0
indicates the range of a given limit.
<0
means Locked=0
means Free>0
means LimitedA constraint may optionally have a \"drive\", which means having one rigid reach a target
position and/or angle relative another rigid. The typical use case is having simulation match your input animation, where the animation provides the positions and angles.
\"DriveComponent\": {\n \"type\": \"DriveComponent\",\n \"members\": {\n \"enabled\": true,\n \"linearStiffness\": 0.0,\n \"linearDamping\": 0.0,\n \"angularStiffness\": 10000.0,\n \"angularDamping\": 1000.0,\n \"acceleration\": true,\n \"target\": {\n \"type\": \"Matrix44\",\n \"values\": [\n 0.973, 0.2267, 0.0, 0.0,\n -0.226, 0.973, 0.0, 0.0,\n 0.0, 0.0, 0.999, 0.0,\n 0.1051, -0.006, 0.0, 1.0\n ]\n }\n }\n}\n
"},{"location":"sdk/serialisation/#data-types","title":"Data Types","text":"In addition to the plain-old-data types int
, double
and bool
, these are all possible data types found in the exported JSON.
{\n \"type\": \"Color4\",\n \"values\": [\n 0.4429999887943268, # red\n 0.7049999833106995, # green\n 0.9520000219345093 # blue\n 1.0 # alpha\n ]\n}\n\n{\n \"type\": \"Vector3\",\n \"values\": [\n 100.00001788139201, # x\n 100.00001788139201, # y\n 100.00000000000003 # z\n ]\n}\n\n{\n \"type\": \"Quaternion\",\n \"values\": [\n 0.8791841887437938, # x\n -0.47648206919348187, # y\n -2.7953360940182678e-8, # z\n 1.191501461145112e-7 # w\n ]\n}\n\n{\n # Unscaled, unsheared matrix\n \"type\": \"Matrix44\",\n \"values\": [\n 1.0, # rotation matrix\n 0.0, # rotation matrix\n 0.0, # rotation matrix\n 0.0,\n 0.0, # rotation matrix\n 1.0, # rotation matrix\n 0.0, # rotation matrix\n 0.0,\n 0.0, # rotation matrix\n 0.0, # rotation matrix\n 1.0, # rotation matrix\n 0.0,\n 0.0, # translateX\n 0.0, # translateY\n 0.0, # translateZ\n 1.0\n ]\n}\n
"},{"location":"sdk/serialisation/#reference","title":"Reference","text":""},{"location":"sdk/serialisation/#components","title":"Components","text":"These are all possible types of components found in the exported JSON.
SolverComponent
SceneComponent
NameComponent
ColorComponent
RestComponent
ScaleComponent
RigidComponent
GeometryDescriptionComponent
JointComponent
DriveComponent
LimitComponent
ConstraintUIComponent
RigidUIComponent
DriveUIComponent
LimitUIComponent
Here's an example of what a complete dump looks like.
Test your dump, by re-building the scene in Maya.
from maya import cmds\nfrom ragdoll.vendor import cmdx\n\n\nclass Component(dict):\n \"\"\"Simplified access to component members\"\"\"\n def __getattr__(self, key):\n value = self[\"members\"][key]\n\n if not isinstance(value, dict):\n return value\n\n if value[\"type\"] == \"Vector3\":\n return cmdx.Vector(value[\"values\"])\n\n elif value[\"type\"] == \"Color4\":\n return cmdx.Color(value[\"values\"])\n\n elif value[\"type\"] == \"Matrix44\":\n return cmdx.Matrix4(value[\"values\"])\n\n elif value[\"type\"] == \"Quaternion\":\n return cmdx.Quaternion(*value[\"values\"])\n\n else:\n raise TypeError(\"Unsupported type: %s\" % value)\n\n\ndef dedump(dump):\n with cmdx.DagModifier() as mod:\n root = mod.createNode(\"transform\", name=\"dump\")\n\n for entity, data in dump[\"entities\"].items():\n comps = data[\"components\"]\n\n if \"RigidComponent\" not in comps:\n continue\n\n name = Component(comps[\"NameComponent\"])\n\n if not name.path:\n # Bad export\n continue\n\n joint = name.path.rsplit(\"|\", 3)[-2]\n\n scale = Component(comps[\"ScaleComponent\"])\n rest = Component(comps[\"RestComponent\"])\n desc = Component(comps[\"GeometryDescriptionComponent\"])\n\n # Establish rigid transformation\n tm = cmdx.TransformationMatrix(rest.matrix)\n\n # Establish shape\n if desc.type in (\"Cylinder\", \"Capsule\"):\n radius = desc.radius * scale.absolute.x\n length = desc.length * scale.absolute.y\n geo, _ = cmds.polyCylinder(axis=(1, 0, 0),\n radius=radius,\n height=length,\n roundCap=True,\n subdivisionsCaps=5)\n\n elif desc.type == \"Box\":\n extents = desc.extents\n extents.x *= scale.absolute.x\n extents.y *= scale.absolute.y\n extents.z *= scale.absolute.z\n geo, _ = cmds.polyCube(width=extents.x,\n height=extents.y,\n depth=extents.z)\n\n elif desc.type == \"Sphere\":\n radius = desc.radius * scale.absolute.x\n geo, _ = cmds.polySphere(radius=radius)\n\n else:\n print(\"Unsupported shape type: %s.type=%s\" % (name.path, desc.type))\n continue\n\n with cmdx.DagModifier() as mod:\n transform = mod.createNode(\"transform\", name=joint, parent=root)\n transform[\"translate\"] = tm.translation()\n transform[\"rotate\"] = tm.rotation()\n\n # Establish shape transformation\n offset = desc.offset\n offset.x *= scale.absolute.x\n offset.y *= scale.absolute.y\n offset.z *= scale.absolute.z\n\n geo = cmdx.encode(geo)\n geo[\"translate\"] = offset\n geo[\"rotate\"] = desc.rotation\n\n transform.addChild(geo)\n\n\n# Usage Example\nimport json\ndump = cmds.ragdollDump()\ndump = json.loads(dump)\ndedump(dump)\n
"},{"location":"sdk/serialisation/#more-examples","title":"More Examples","text":""},{"location":"sdk/serialisation/#tiger","title":"Tiger","text":"Courtesy of www.cgspectrum.com
mytiger.rag
Model from https://mecabricks.com
ragcar.rag
A generic human character, rigged with AS.
mycharacter.rag
Jason worked on this shot of bombs falling from an airplane.
https://youtu.be/98Ys1aI9a_Y?t=56
"},{"location":"tutorials/20240308_rebelmoon/","title":"20240308 rebelmoon","text":"One or more shots in Rebel Moon used Ragdoll. Ask Jason.
"},{"location":"tutorials/20240309_houseofdragon/","title":"20240309 houseofdragon","text":"Something about a dragon eating bits. Ask Jason.
"},{"location":"tutorials/20240310_avatarii/","title":"20240310 avatarii","text":"It was used on Avatar II, but where? Ask Jason.
"},{"location":"tutorials/20240311_buffalokids/","title":"20240311 buffalokids","text":"Was used here:
It 's scheduled to be released in August the 30th. We used Ragdoll in the movie to create secondaries animations, specially for movement of Dress, hairs, etc. This way this kind of secondary animations don't depend on every animator as we give the same style with Ragdoll.
"},{"location":"tutorials/bouncing_ball/","title":"Bouncing Ball","text":""},{"location":"tutorials/bouncing_ball/#bouncing-ball","title":"Bouncing Ball","text":"The fundamentals of animation
In this tutorial, we will reproduce a classic animation tutorial, the Bouncing Ball. With it, we will explore various material properties of a ball whilst learning about the inner workings of Ragdoll.
Version 1.0 - Up to date
Written for Ragdoll 2022.05.04
and above.
Estimated Time
You will learn
polySphere
Where to find help
If you find or run into any issues with these tutorials, here's what you can do.
Why should an animator simulate a ball bouncing, rather than just keyframe it?
If you are new to animation or in a neighbouring field such as modeling or lighting, it might seem silly to consider such a trivial task for simulation. But as the more seasoned animator knows, getting the trajectory of any free-flying object right is incredibly hard. It can mean the difference between a believable character, and a character that looks like Earths gravity varies for the duration of a single jump, or one that appears to be on a different planet altogether.
With that in mind, although a single ball bouncing on a flat plane may seem trivial, it can be enough to challenge even the most senior of animators.
"},{"location":"tutorials/bouncing_ball/#setup","title":"Setup","text":"For this tutorial, all you need is an empty Maya scene. So go ahead and clear out all of those references and meshes with hours of history on it and let's get crackin'!
"},{"location":"tutorials/bouncing_ball/#poly-sphere","title":"Poly Sphere","text":"Let's make our ball out of a regular Maya polySphere
.
Sphere
from the Polygon Primitives
submenu of the Create
main menuTranslate Y = 5.0
Yes, if you prefer, you can also use a NURBS sphere.
"},{"location":"tutorials/bouncing_ball/#dynamics","title":"Dynamics","text":"With our sphere in place, let's give it some physical properties by turning it into a Active Rigid
.
pSphere1
Assign Marker
from the Ragdoll
MenuThat's great! Except hm.. It's not really a bouncing ball just yet.
"},{"location":"tutorials/bouncing_ball/#bounciness","title":"Bounciness","text":"Default settings make the ball rather dull, so let's try introducing some bounciness via its material properties.
pSphere1
rMarker_pSphere1
in the Channel BoxBounciness = 1.0
It means 100%! Technically, it means any force produced by the ball hitting the ground is reversed in its entirety with no loss of energy what-so-ever.
"},{"location":"tutorials/bouncing_ball/#infinite-bounciness","title":"Infinite Bounciness","text":"The reason the ball stops bouncing is that even though our ball is 100% bouncy, the ground is not. Like dropping a bowling ball on grass or a wooden floor. For perfect bounce, they both need to be 100% bouncy.
rGround
rMarker_rGround
in the Channel BoxBounciness = 1.0
Ragdoll creates this ground automatically for you whenever the first marker is assigned. It can be disabled by setting Create Ground = Off
in the Assign Marker
option dialog.
Now that we have complete control over our ball, let's put it to good use.
You have learnt
polySphere
Give the ball a little push.
pSphere1
Behaviour
from Animated
to Simulated
Translate X
0.0
0.5
Behaviour
Animated
Simulated
"},{"location":"tutorials/bouncing_ball/#trajectory","title":"Trajectory","text":"With our bouncing ball underway, let's gain a deeper understanding of what it looks like over time.
Record Simulation
from the Ragdoll menupSphere1
Create Editable Motion Trail
from Maya's Visualize menuNow, as every animator knows, this is not the trajectory of a bouncing ball. It looks as if the ball isn't actually touching the floor half the time, what's up with that? \ud83e\udd14
Expected Result\u2714\ufe0f Actual Result\u274cThis is a problem of resolution. Cameras have this problem too.
See how despite this most definitely not being a simulation (or is it?) we are still getting bounces that don't actually touch the ground! The reason is simply that a camera can only capture moments of reality. It can only sample it.
In this case, the ball did touch the floor, but the camera caught at a slightly different time. Shortly before and after contact. This is how you can think of Ragdoll too; a camera for physics.
Can you overeducate me?With pleasure. \ud83d\ude01 Let's look at audio.
Notice how sound itself, represented by the curved line, is continuous - of infinite resolution - and that what we capture in our computers are samples of it, at some fixed resolution - typically at 44,000 fps or as it is more commonly known 44khz
.
Ragdoll works like this too. Physics is continuous, but Ragdoll can only provide you with snapshots of physics at a fixed resolution; the resolution of your framerate.
Is every bouncing ball tutorial on YouTube wrong?A typical bouncing ball tutorial has the ball come into contact on whole frames. But because the time between each bounce is decreasing, it is impossible for every bounce to land on a whole frame.
So in a way, yes, they are wrong! Science says so!
Should I change the way I animate?Well, it depends. Take motion blur for example.
Because you see, the final position from a video recorded tennis ball is only half the story. Motion blur isn't the result of only these samples, but of the actual continuous motion. As light hits the lens inbetween the shutter opening and closing, the ball is still moving.
To accurately reproduce this effect in your animation or with Ragdoll, you still need those inbetween positions of the ball. Just so that your renderer can throw those away once it's done computing motion blur.
Even without motion blur, your eyes and brain still interprets the ball not hitting the ground as though it floats or hits an invisible obstacle. So for the greatest sense of realism when everything has been said and done and the images actually reach your eyes (brain), you may still want to defy physics and realism.
Because at the end of the day, the animation curves isn't what you are making. They are mere tools for you to achieve realism in the final output picture.
"},{"location":"tutorials/bouncing_ball/#tennis-ball","title":"Tennis Ball","text":"Now that we've got some reference for a tennis ball, let's tune our settings to match.
pSphere1
rMarker_pSphere1
in the Channel BoxBounciness = 0.4
Let's also take it out of orbit and into Earths atmosphere by restoring the Air Density
rSolver
Air Density = 1.0
Now that we've got a ball, what could we possibly do with it?
"},{"location":"tutorials/bouncing_ball/#soft-bounce","title":"Soft Bounce","text":"Notice our trajectory now has a smooth transition from being in contact to lifting off the ground.
By playing around with the density, we can get different effects.
Or playing around with this invisible collision sphere we've created.
So what's going on here?
pSphere2
pSphere2
under pSphere1
Next, let's assign to pSphere2
with pSphere1
as its parent.
pSphere1
and pSphere2
Assign and Connect
Not much happens, they both move together. Let's change that.
pSphere2
Translate Motion = Soft
pSphere1
Collide = Off
I found values of Translate Stiffness = 0.1
and Translate Damping = 0.1
to look decent.
And that does it! This same technique can be used on full ragdolls too to achieve all manner of soft contacts, have fun.
"},{"location":"tutorials/bouncing_ball/#troubleshooting","title":"Troubleshooting","text":"Let's have a look at some common issues.
"},{"location":"tutorials/bouncing_ball/#vibrating-at-rest","title":"Vibrating at Rest","text":"There is no right value for Bounce Threshold
, it's an art. And it depends on the size of your scene and rigids, their shape, how fast they move and the look you are after.
When the threshold is too low, Ragdoll can get into an infinite bounce like this.
To address this, increase the threshold until it stops.
"},{"location":"tutorials/cloth_emulation/","title":"Cloth Emulation","text":""},{"location":"tutorials/cloth_emulation/#cloth-emulation","title":"Cloth Emulation","text":"In this tutorial, we'll use many interconnected Markers to emulate cloth.
Version 1.0 - Up to date
Written for Ragdoll 2022.03.14
and above.
Estimated Time
You will need
You will learn
Where to find help
If you find or run into any issues with these tutorials, here's what you can do.
See here for part 1 of 1 this tutorial.
This has been a tutorial on how to emulate - not simulate - cloth. Because Ragdoll currently does not understand deformations. It only understands hard objects.
So, how else can you make hard objects appear like cloth? Share your experiences with the community!
\"Make your own motion reference\"
In this tutorial, we will setup a human-like character for use as reference or constraint target to your rig. You will be able to pose and position this Manikin like you would a real Manikin, and drop it from various heights and onto various obstacles to produce realistic poses as it falls.
Something the animator can import and throw around for reference on how it would look like.
Version 1.2 - Up to date
Written for Ragdoll 2023.08.01
and above.
Estimated Time
You will learn
Where to find help
If you find or run into any issues with this tutorials, here's what you can do.
There are two ways to spell \"Manikin\", this tutorial is based on this term here.
Follow this tutorial either using our provided Manikin rig, or your own character. It can have any number of limbs.
Download Manikin Download Final Scene "},{"location":"tutorials/manikin/#motivation","title":"Motivation","text":"Why should we even bother simulating a character?
Finding motion reference is one of the most important activities for any animator. And yet I can safely challenge you to find reference for perhaps the most common motion in all blockbuster movies today, something that is either impossible or dangerous for actors or animators alike.
Or how about reference of someone simply falling over, perhaps from heat stroke or staring into the sun.
This is, after all, one of the major reasons for pursuing computer graphics in storytelling rather than real people.
Animators bring life to characters, but of equal challenge is that of lifelessness. Of natural and realistic motion without someone behind the wheel. Be it getting hit or shot, blasted or thrown, animating lifelessness is enough to challenge even the most senior of animators.
As you will find, there is a lot more we can do once our motion reference is in 3D, on our actual character rig within Maya and infinitely customisable. As opposed to some video on the internet.
"},{"location":"tutorials/manikin/#setup","title":"Setup","text":"Create a new reference of your chosen character rig or download this Manikin rig to get started.
Play around with the controls to get a feel for what we're working with. This character is entirely FK which will make simulating it straightforward.
"},{"location":"tutorials/manikin/#simulation","title":"Simulation","text":"The stage is set, now let's apply physics!
"},{"location":"tutorials/manikin/#torso","title":"Torso","text":"Let's start with the Torso.
hip_ctl
torso_ctl
head_ctl
Assign and Connect
This will produce our first Group
, which is a collection of connected Markers
.
New Concept
Group
The rdGroup
node contains attributes that affect all contained markers. It's where you'd edit the overall look and feel of your character, like how stiff it should be and whether or not body parts should collide with each other.
Each Marker can either inherit or otherwise override these values.
"},{"location":"tutorials/manikin/#left-arm","title":"Left Arm","text":"Next we will continue from the torso_ctl
and out into the arms.
torso_ctl
L_clavicle_ctl
L_upperArm_ctl
L_lowerArm_ctl
L_hand_ctl
Assign and Connect
Yes, the order in which you select will determine how the markers are connected.
Your first selection is extra important, as it determines whether to start a new group, like for the hip_ctl
, or to add to an existing group, like the torso_ctl
.
In this case, we would very much like our arm to be connected to the torso.
Can I skip the clavicles?Yes, if you have extra controls - such as twist
or bend
- you can skip these if you don't care to simulate them.
Simply skip over them as you select, from torso_ctl
directly to L_upperarm_ctl
.
Now repeat the above process for the other arm.
"},{"location":"tutorials/manikin/#legs","title":"Legs","text":"Now let's continue down the hips and into the legs.
hip_ctl
L_thigh_ctl
L_knee_ctl
L_foot_ctl
Assign and Connect
We will address those long feet shortly. \ud83d\udc43
"},{"location":"tutorials/manikin/#drop-test","title":"Drop Test","text":"That's enough setup, let's drop him!
New Concept
Behaviour
Each Marker has a \"behaviour\", which tells Ragdoll it should interpret the control it has been assigned. Should it fall with gravity? Should it try and match the pose? Should it remain fully animated, even in simulation?
hip_ctl
Behaviour = Simulated
The default behaviour for Assign and Connect
is to give the first selection - the \"root\" - a Animated
behaviour.
What does Animated mean?
Animated means \"copy the animation into simulation and make no changes to it\"
By instead setting this to Simulated
, then Ragdoll will only use the animation for the starting position and orientation of the simulation.
Inherit
Alternatively, you can set it to Inherit
to have it inherit the value of the rGroup
node that was created for the whole character.
Next let's address the elephant in the room; the shapes. They look awful.
"},{"location":"tutorials/manikin/#volumes","title":"Volumes","text":"The shape of each collider affects your simulation in 2 ways.
The contact point can be important if your character interacts with an environment or another character. Like in this case where the feet are incorrectly colliding with the ground because of a bad shape.
That's not always the case though, sometimes you just want overlapping motion without contacts in which case the shapes won't matter.
They do however also affect their resistance to rotation. Consider this.
Here, we rotate the exact same shapes, the exact same amount in the exact same amount of time. And yet they respond differently.
This shape has vastly different dimensions in the X, Y and Z directions, resulting in a different rotation mass for each one. As a result, the effort required to rotate it in each axis differs too.
In practice, you'll find this for just about any limb on a character, which is typically longer in one axis. For our Manikin, this is especially true for the default clavicle shapes.
Override Rotate Mass
In some cases, you have a shape but want it to act like a different shape. Rotate Mass
is very similar to normal Mass
, except in 3 dimensions. Where the position of an object is affected equal in X, Y and Z directions, rotations have 3 separate masses.
With this in mind, let's tune some shapes.
Manipulator
from the Ragdoll
menuAlternatively
Select a rMarker
node in the Channel Box, or the rGroup
node in your Outliner, and hit the T
key on your keyboard. You can also select the shape of the rSolver
node.
This brings up the Manipulator interface, where you can manipulate shapes using mouse gestures.
Great, now let's turn those hands and feet into boxes.
Translate, Rotate and Scale
Notice I'm using the..
Translate
Rotate
Scale
The help text screen-right will help you remember these.
Greater Value Step
While dragging the value on Manipulator UI panel, you may hold Shift
to increase value changing step.
Symmetry
Also notice the edits are symmetrical; even when they don't start out that way like the feet!
"},{"location":"tutorials/manikin/#recording","title":"Recording","text":"That's all there is for setting up your character rig for simulation! Let's now transfer the simulation back onto the rig.
Record Simulation
The recorded simulation ends up on an Animation Layer, and is also Cached. To start over, delete this layer and disable the cache.
"},{"location":"tutorials/manikin/#next-steps","title":"Next Steps","text":"In the next tutorial, we'll take this a bit further. As you play around with the Rotate Stiffness
on either the rGroup
or individual rMarker
nodes, you'll find some limbs start to misbehave. Especially the knees and elbows, that normally won't allow rotations past a certain angle in a real human (or Manikin for that matter!).
That isn't the case here, because we've left out a critical part of any ragdoll - \"limits\".
See you there!
"},{"location":"tutorials/manikin_blender/","title":"Blender Manikin I","text":""},{"location":"tutorials/manikin_blender/#manikin","title":"Manikin","text":"\"Make your own motion reference\"
In this tutorial, we will setup a human-like character for use as reference or constraint target to your rig. You will be able to pose and position this Manikin like you would a real Manikin, and drop it from various heights and onto various obstacles to produce realistic poses as it falls.
Something the animator can import and throw around for reference on how it would look like.
Estimated Time
You will learn
Where to find help
If you find or run into any issues with this tutorials, here's what you can do.
There are two ways to spell \"Manikin\", this tutorial is based on this term here.
Follow this tutorial either using our provided Manikin rig, or your own character. It can have any number of limbs.
Download Manikin Download Final Scene "},{"location":"tutorials/manikin_blender/#motivation","title":"Motivation","text":"Why should we even bother simulating a character?
Finding motion reference is one of the most important activities for any animator. And yet I can safely challenge you to find reference for perhaps the most common motion in all blockbuster movies today, something that is either impossible or dangerous for actors or animators alike.
Or how about reference of someone simply falling over, perhaps from heat stroke or staring into the sun.
This is, after all, one of the major reasons for pursuing computer graphics in storytelling rather than real people.
Animators bring life to characters, but of equal challenge is that of lifelessness. Of natural and realistic motion without someone behind the wheel. Be it getting hit or shot, blasted or thrown, animating lifelessness is enough to challenge even the most senior of animators.
As you will find, there is a lot more we can do once our motion reference is in 3D, on our actual character rig within Blender/Maya and infinitely customisable. As opposed to some video on the internet.
"},{"location":"tutorials/manikin_blender/#setup","title":"Setup","text":"Open your chosen character rig or download the above Manikin rig to get started.
Play around with the controls to get a feel for what we're working with.
FK or IK
Use FK for this tutorial
This Manikin rig has FK and IK (legs) controls, but we will focus on FK controls for this tutorial because it makes simulating much straightforward.
"},{"location":"tutorials/manikin_blender/#simulation","title":"Simulation","text":"The stage is set, now let's apply physics.
"},{"location":"tutorials/manikin_blender/#torso","title":"Torso","text":"Let's start with the Torso.
hip_FK
torso_FK
head_FK
Physics Properties
panel, run Assign and Connect
This will produce our first Group
(named as hip_FK_rGroup
, in Ragdoll
collection), which is a set of connected Markers
.
New Concept
Group
The Group
object contains properties that affect all contained markers. It's where you'd edit the overall look and feel of your character, like how stiff it should be and whether or not body parts should collide with each other.
Each Marker can either inherit or otherwise override these values.
Markable Objects
Who can have Marker assigned?
Next we will continue from the torso_FK
and out into the arms.
torso_FK
L_clavicle_FK
L_upperArm_FK
L_lowerArm_FK
L_hand_FK
Assign and Connect
Yes, the order in which you select will determine how the markers are connected.
Your first selection is extra important, as it determines whether to start a new group, like for the hip_FK
, or to add to an existing group, like the torso_FK
.
In this case, we would very much like our arm to be connected to the torso.
Can I skip the clavicles?Yes, if you have extra controls - such as twist
or bend
- you can skip these if you don't care to simulate them.
Simply skip over them as you select, from torso_FK
directly to L_upperArm_FK
.
Now repeat the above process for the other arm.
"},{"location":"tutorials/manikin_blender/#legs","title":"Legs","text":"Now let's continue down the hips and into the legs.
hip_FK
L_thigh_FK
L_knee_FK
L_foot_FK
Assign and Connect
That's enough setup, let's drop him!
hip_FK
Behaviour = Simulated
New Concept
Behaviour
Each Marker has a \"behaviour\", which tells Ragdoll it should interpret the control it has been assigned. Should it fall with gravity? Should it try and match the pose? Should it remain fully animated, even in simulation?
The default behaviour for Assign and Connect
is to give the first selection - the \"root\" - an Animated
behaviour.
What does 'Animated'/'Simulated' mean?
Animated means \"copy the animation into simulation and make no changes to it\"
By instead setting this to Simulated
, then Ragdoll will only use the animation for the starting position and orientation of the simulation.
Use Group
Alternatively, you can set it to Use Group
to have it use the value of the rGroup
node that was created for the whole character.
Next let's address the elephant in the room; the shapes. They look awful.
"},{"location":"tutorials/manikin_blender/#volumes","title":"Volumes","text":"The shape of each collider affects your simulation in 2 ways.
The contact point can be important if your character interacts with an environment or another character. Like in this case where the feet are incorrectly colliding with the ground because of a bad shape.
That's not always the case though, sometimes you just want overlapping motion without contacts in which case the shapes won't matter.
They do however also affect their resistance to rotation. Consider this.
Here, we rotate the exact same shapes, the exact same amount in the exact same amount of time. And yet they respond differently.
This shape has vastly different dimensions in the X, Y and Z directions, resulting in a different rotation mass for each one. As a result, the effort required to rotate it in each axis differs too.
In practice, you'll find this for just about any limb on a character, which is typically longer in one axis. For our Manikin, this is especially true for the default clavicle shapes.
Override Rotate Mass
In some cases, you have a shape but want it to act like a different shape. Rotate Mass
is very similar to normal Mass
, except in 3 dimensions. Where the position of an object is affected equal in X, Y and Z directions, rotations have 3 separate masses.
With this in mind, let's tune some shapes.
rSolver
object, within Ragdoll
collection.Manipulator
tool at the ToolbarThis brings up the Manipulator interface, where you can manipulate shapes using mouse gestures.
Great, now let's turn those hands and feet into boxes.
Translate, Rotate and Scale
Notice I'm using the..
Translate
Rotate
Scale
The help text screen-right will help you remember these.
Greater Value Step
While dragging the value on Manipulator UI panel, you may hold Shift
to increase value changing step.
Symmetry
Also notice the edits are symmetrical; even when they don't start out that way like the feet!
"},{"location":"tutorials/manikin_blender/#recording","title":"Recording","text":"That's all there is for setting up your character rig for simulation! Let's now transfer the simulation back onto the rig.
Record Simulation
Recording options?
By holding Ctrl
while clicking Record Simulation
, a dialog pops up provides you more control over recording process.
The simulation was recorded into the NLA Track of each marker assigned object with Solo enabled for playback. To start over, disable Solo mode for those tracks (or delete them).
Initial Key
By default, Ragdoll adds one keyframe on the simulation starting frame, this is to keep original pose intact after playback recorded animation.
Auto Cache
If you have recording option Auto Cache
enabled while recording, solver will remember simulation result after recorded, which can be helpful if you wish to compare the simulation against baked result. If so, don't forget to turn it off before next simulation.
In the next tutorial, we'll take this a bit further. As you play around with the Rotate Stiffness
on either the rGroup
or individual rMarker
nodes, you'll find some limbs start to misbehave. Especially the knees and elbows, that normally won't allow rotations past a certain angle in a real human (or Manikin for that matter!). That isn't the case here, because we've left out a critical part of any complete ragdoll.
See you there!
"},{"location":"tutorials/manikin_ik/","title":"Manikin and IK","text":""},{"location":"tutorials/manikin_ik/#manikin-and-ik","title":"Manikin and IK","text":"In the previous tutorial we turned a character rig into a ragdoll, driven by your animation.
In this tutorial, we'll have a look at how we apply this to the IK controls of a rig.
Version 1.1 - Up to date
Written for Ragdoll 2021.12.10
and above.
Estimated Time
You will learn
Where to find help
If you find or run into any issues with these tutorials, here's what you can do.
Follow this tutorial either using our provided Manikin rig, or your own character. It can have any number of limbs.
Download Manikin Download Final Scene "},{"location":"tutorials/manikin_ik/#setup","title":"Setup","text":"Let's start fresh, with a non-dynamic character rig. In this case, the IK controls are disabled per default, so let's enable them.
master_ctl
Left Leg Fk Ik = 1
Right Leg Fk Ik = 1
As per usual, let's assign markers onto the FK controls in the upper body.
"},{"location":"tutorials/manikin_ik/#find-ik-joints","title":"Find IK Joints","text":"The legs are different. We don't want to pass the position of the IK controls in the solver, instead what we want are the joints they drive.
Where are the joints in my rig?
The location of these will differ in every rig. What's important is that they are the ones that move when you move your IK controls. Any joints that do that will suffice.
In the case of the Manikin, these will be located under the skeleton_grp
.
Once you've found a suitable set of joints, assign to them as per usual. Starting from the hip.
"},{"location":"tutorials/manikin_ik/#recording","title":"Recording","text":"Per default, Ragdoll will record onto the control you assign.
However, we don't want keyframes on our IK joints. We want keyframes on our IK controls. Therefore, we aren't ready to record just yet.
Notice how our IK controls didn't get any keyframes?
"},{"location":"tutorials/manikin_ik/#retarget","title":"Retarget","text":"Because we did not assign to our IK controls, we'll need to retarget the joints onto the controls.
Now when we record, our retargeted IK controls will be getting keyframes from our simulated IK joints.
Not Just IK
This will work between any controls or joints. Even from one rig to another, or more complex IK like Spline IK. The Record Simulation
command uses a native Maya Parent Constraint
between the assigned and retargeted controls, so anywhere you could manually do this will work with this command.
That's it for this tutorial! Here's some test animation.
"},{"location":"tutorials/manikin_ik/#shapes","title":"Shapes","text":"Grab the manipulator and tweak those shapes to fit your character.
"},{"location":"tutorials/manikin_ik/#test-animation","title":"Test Animation","text":"Then drop some keys on our IK rig to see it in action.
"},{"location":"tutorials/manikin_ragdoll/","title":"Manikin II","text":""},{"location":"tutorials/manikin_ragdoll/#manikin-ragdoll","title":"Manikin Ragdoll","text":"In the previous tutorial we assigned markers onto a rig such that you can achieve overlapping motion.
That's enough for some things, but other times you don't want any animation. You just want to drop a ragdoll someplace dangerous and watch it go.
Version 1.2 - Up to date
Written for Ragdoll 2023.08.01
and above.
Estimated Time
You will learn
Where to find help
If you find or run into any issues with these tutorials, here's what you can do.
Either continue from the last tutorial or start anew with your own rig.
Download Manikin Download Final Scene "},{"location":"tutorials/manikin_ragdoll/#limits","title":"Limits","text":"Next let's see how our character behaves when there isn't any animation around to steer it.
hip_ctl_rGroup
Rotate Stiffness = 0.0
As in our last tutorial when we changed the hip_ctl
from Animated
to Simulated
, now we do the same but for the whole character!
Yikes! That's a mess. No longer is the animation holding a pose together, it's all up to gravity and the anatomy of our character now.
The way we will address this is via \"limits\", which is like locked rotate channels except they also lock a range of values. We can use this to replicate natural limits in our human joints.
"},{"location":"tutorials/manikin_ragdoll/#legs","title":"Legs","text":"Let's start at legs and work our way up. First, let's figure out what axis we want to rotate, and which we want to lock.
Ok, great. The Z axis should rotate but X and Y should be locked.
Ragdoll -> Manipulator
Limit Mode
X
, Y
and Z
X
and Y
Next, tune the minimum and maximum values of the limit.
Tune Minimum and Maximum Separately
By holding the Ctrl key, you can manipulate one bound at a time.
Then we can do the same for the feet.
Something like that should do the trick.
"},{"location":"tutorials/manikin_ragdoll/#clavicles","title":"Clavicles","text":"Let's keep the clavicles simple. We'll allow only 1 axis of rotation by locking the others.
Ragdoll -> Manipulator
We'll lock the X
and Y
axes of the lower arm like we did for the lower leg.
Ragdoll -> Manipulator
Both the hip and spine should be allowed to rotate around all three axes, so we can leave these at their default values for now.
Ragdoll -> Manipulator
And that's it! From here, we can hide the limits to have another look at contacts.
"},{"location":"tutorials/manikin_ragdoll/#contacts","title":"Contacts","text":"If we hide away our limits for a moment, we can see something that's not right. Notice how the arms and legs intersecting each other? That's because, per default, limbs within a single group are allowed to overlap.
Should I enable Self Collision?Normally the answer is \"no\", but when you do, this can be overridden on the rGroup
node.
Let's address this by having these overlap with Nothing
.
You now know enough to construct any character of any anatomy!
You have learnt
As you tune, try dropping the Manikin from different heights and angles. Put an obstacle underneath for more detail and to catch more edge cases. Once you are unable to produce an unnatural pose, you are done!
Download Completed Scene
For your reference, here is the completed scene with the Manikin file referenced.
Download Manikin Download Final Scene "},{"location":"tutorials/manikin_ragdoll/#damped-limits","title":"Damped Limits","text":"You can tune the behaviour of each limit to capture the look you're after, such as making things a little more damped.
Global Damping
This, and other stiffness and damping-related attributes, can be controlled globally - for every limit in your scene - via the rSolver
node.
Sometimes, a limit is hard. Like your elbow. It won't allow you to continue rotating it once it's straightened out. You'll break it!
Other limits are more flexible. Let's reflect this in our simulation by reducing their range and lowering their Stiffness
, accepting that they will exceed it, but get gently pushed back.
Feet contact with the ground is often more important than other contacts. For such cases, a box or capsule shape may not be enough.
So let's use Replace Mesh
to fix that.
L_foot_jnt
Replace Mesh
In most cases, you'll want some control over the resulting simulation. Just a little bit.
Group Markers
You could add/remove groups as you go for better control, each group multiplies stiffnesses and damping on each contained Marker.
"},{"location":"tutorials/manikin_ragdoll_blender/","title":"Blender Manikin II","text":""},{"location":"tutorials/manikin_ragdoll_blender/#manikin-ragdoll","title":"Manikin Ragdoll","text":"In the previous tutorial we assigned markers onto a rig such that you can achieve overlapping motion.
That's enough for some things, but other times you don't want any animation. You just want to drop a ragdoll someplace dangerous and watch it go.
Estimated Time
You will learn
Where to find help
If you find or run into any issues with these tutorials, here's what you can do.
Either continue from the last tutorial or start anew with your own rig.
Download Manikin Download Final Scene "},{"location":"tutorials/manikin_ragdoll_blender/#limits","title":"Limits","text":"Next let's see how our character behaves when there isn't any animation around to steer it.
hip_FK_rGroup
Behaviour = Simulated
Rotate Stiffness = 0.0
As in our last tutorial when we changed the hip_FK
from Animated
to Simulated
, now we do the same but for the whole character!
Yikes! That's a mess. No longer is the animation holding a pose together, it's all up to gravity and the anatomy of our character now.
The way we will address this is via \"limits\", which is like locked rotate channels except they also lock a range of values. We can use this to replicate natural limits in our human joints.
"},{"location":"tutorials/manikin_ragdoll_blender/#legs","title":"Legs","text":"Let's start at legs and work our way up. First, let's figure out what axis we want to rotate, and which we want to lock.
Ok, great. The Z axis should rotate but X and Y should be locked.
Except... no. Because Ragdoll uses different axis system at the moment, so we better head right into Limit Mode
and find out!
Manipulator
Limit Mode
X
, Y
and Z
X
and Z
Next, tune the minimum and maximum values of the limit.
Tune Minimum and Maximum Separately
By holding the Ctrl key, you can manipulate one bound at a time.
Then we can do the same for the feet.
Something like that should do the trick.
"},{"location":"tutorials/manikin_ragdoll_blender/#clavicles","title":"Clavicles","text":"Let's keep the clavicles simple. We'll allow only 1 axis of rotation by locking the others.
Manipulator
We'll lock the X
and Z
axes of the lower arm like we did for the lower leg.
Manipulator
Both the hip and spine should be allowed to rotate around all three axes, so we can leave these at their default values for now.
Manipulator
And that's it! From here, we can hide the limits to have another look at contacts.
"},{"location":"tutorials/manikin_ragdoll_blender/#contacts","title":"Contacts","text":"If we hide away our limits for a moment, we can see something that's not right. Notice how the arms and legs intersecting each other? That's because, per default, the limbs within a single group are allowed to overlap.
Should I enable Self Collision?Normally the answer is \"no\", but when you do, this can be overridden on the rGroup
node.
Let's address this by having these overlap with Nothing
.
You now know enough to construct any character of any anatomy!
You have learnt
As you tune, try dropping the Manikin from different heights and angles. Put an obstacle underneath for more detail and to catch more edge cases. Once you are unable to produce an unnatural pose, you are done!
Download Completed Scene
For your reference, here is the completed scene with the Manikin file referenced.
Download Manikin Download Final Scene "},{"location":"tutorials/manikin_ragdoll_blender/#damped-limits","title":"Damped Limits","text":"You can tune the behaviour of each limit to capture the look you're after, such as making things a little more damped.
Global Damping
This, and other stiffness and damping-related attributes, can be controlled globally - for every limit in your scene - via the rSolver
node.
Sometimes, a limit is hard. Like your elbow. It won't allow you to continue rotating it once it's straightened out. You'll break it!
Other limits are more flexible. Let's reflect this in our simulation by reducing their range and lowering their Stiffness
, accepting that they will exceed it, but get gently pushed back.
Feet contact with the ground is often more important than other contacts. For such cases, a box or capsule shape may not be enough.
So let's use Replace Mesh
to fix that.
L_foot_blend_jnt
Default Shape
and find Custom mesh shape
propertyL_foot_geo
Shape
to Mesh
typeIn most cases, you'll want some control over the resulting simulation. Just a little bit.
Group Markers
You could add additional marker group for better control over stiffness and damping on different part of limbs, which then decides how your input animation affects simulation.
"},{"location":"tutorials/manikin_ragdoll_blender/#bonus-pin-constraint","title":"Bonus: Pin Constraint","text":"Constraint
panel, click Pin Marker
(or Pin All Selected
) button.Other Constraints?
At this moment (2023.08 release), only Pin Constraint
works, other type of constraints coming soon!
We don't cover this yet, as it's partly CreatureFX and Technical Animation - something I've wanted to steer clear of. But there is value for animators here, a lot of animators are stuck with this because a studio simply cannot afford (or understand) technical animation.
So we'll need a character that we'll apply motion capture to, and only worry about secondary effects. The character would look somewhere along the lines of the below. Familiar, common in the animation field, with things we can make dynamic.
We'd combine this with general dynamics on limbs too, like swings and trajectories for jumps, that kind of thing. Maybe we can repurpose Skye for this?
"},{"location":"tutorials/masterclass/#human-masterclass","title":"Human Masterclass","text":"Topics Description Hinges Knees and elbows Spherical Hips and shoulders Fingers Palm and thumb, up to individual fingers Facial Fleshy cheeks, lips, jaw Usage Leave some pose stiffness, soft limits, soft translation
This one would focus on anatomy and what people most associate with \"ragdolls\". People getting struck, falling, lying on things that move, floating, the Jedi-grip, crash-dummy. That kind of thing.
For this we'll need a realistic character, not necessarily with clothing as our focus would be on the body itself and not so much on the input animation or character.
"},{"location":"tutorials/masterclass/#mecha-masterclass-series","title":"Mecha Masterclass Series","text":"Topics Description Linear limits Like hydraulics Spherical Hips and shoulders Animation How to animate something to look like a robotWe can do a really strong job here, animating things to look robotic is a lot easier and forgiving than a human. As a robot generally needs to move one limb at a time, in a controlled manner. Which is funny, as it's a look that's based on how difficult it is to approximate human motion. A heavily controlled, slow movement. We'll have overshoots and jiggles, because that's just how motors work in real life.
For feet, I think we'll do especially well too, as we can stick with the pointed feet like with Locomotion, and rely on contacts to animate anything coming into contact with the ground.
I found these which will serve as an excellent foundation for this.
https://www.artstation.com/marketplace/p/k1yK9/10-sci-fi-robot-models
"},{"location":"tutorials/masterclass/#weightlessness-series","title":"Weightlessness Series","text":"Using the setups from the previous 3 masterclasses, put them underwater, in space and thrown around with magic/Jedi force.
"},{"location":"tutorials/mecha_series/","title":"Mecha series","text":"Steps
Walk through how to do these signs with Ragdoll. :) https://youtu.be/xPDGoVml5RU?t=10
"},{"location":"tutorials/mocap_chap/","title":"Mocap Chap","text":""},{"location":"tutorials/mocap_chap/#mocap-chap","title":"Mocap Chap","text":"In the previous tutorials we've turned a character rig into a full ragdoll, driven by your animation.
This time we'll look at applying physics to only parts of a character, like the upper body of this mocap clip found in Maya's default Content Browser.
Version 1.1 - Up to date
Written for Ragdoll 2021.12.10
and above.
Estimated Time
You will learn
Where to find help
If you find or run into any issues with these tutorials, here's what you can do.
When and why would you even want simulation on parts of a character?
Are three simple and somewhat obvious examples, more complex examples include what we're about to do in this tutorial. Namely, edit the mass of an object picked up during the original motion capture.
Download Final Scene "},{"location":"tutorials/mocap_chap/#setup","title":"Setup","text":"Let's start by importing our motion capture clip; this can be any clip but if you'd like to follow along here's what you do.
Windows -> General Editors -> Content Browser
Smash.fbx
Make sure the fbxmaya.mll
plug-in is loaded via the Maya Plug-in Manager.
Here's what this clip looks like.
"},{"location":"tutorials/mocap_chap/#symmetry-optional","title":"Symmetry (optional)","text":"In order for Ragdoll to recognise symmetry later when we edit the shapes using the Manipulator
, we'll need to assign markers in a symmetrical pose.
Translate X
and Translate Z
to 0Select -> Select Hierarchy
Assume Preferred Angle
In this case, I'm ignoring fingers along with the center joint in each limb, like the lower arms and upper legs.
From here, we can move our simulation to frame to 1
. We don't need frame 0
anymore.
In this tutorial, we're only going to worry about the upper body, so let's turn those legs into 100% animation via the Animated
behaviour.
The stage is set, it's time to tune!
"},{"location":"tutorials/mocap_chap/#shapes","title":"Shapes","text":"Nothing special here, and since we have no geometry to fill we have some creative freedom in how we want our character to look!
Let's have a look at where defaults values gets us.
Not bad! But since we want our simulation to be close to the original mocap, we'll need to make some changes.
"},{"location":"tutorials/mocap_chap/#stiffness-and-substeps","title":"Stiffness and Substeps","text":"The default solver substeps and iterations get you to a Stiffness
of about 10
. In order to achieve a higher stiffness, we'll need more of those.
rSolver
Substeps = 8
Iterations = 8
Hips_rGroup
Rotate Stiffness = 40
Rotate Damping = 0.25
Let's get the box in on the action.
"},{"location":"tutorials/mocap_chap/#attach-hands-to-box","title":"Attach Hands to Box","text":"He does a good job holding onto that box through friction between hand and box alone, but let's help him out by \"glueing\" the two together using a Distance Constraint
Ragdoll -> Constrain -> Distance
The default distance will be From Start
, meaning it will try and keep whatever the distance was between the box and the hands at the start of the simulation.
What we want however is for the Maximum
distance to be 0
, and for it to only start having an effect once the hands overlap the box.
Now let's edit the point at which the hand and box snap together.
Parent Offset
Since we selected the box first, it is considered the \"parent\".
"},{"location":"tutorials/mocap_chap/#animate-on-and-off","title":"Animate On and Off","text":"Next, let's activate this constraint once hands are in place.
80
Stiffness = 0
81
Stiffness = 0.5
Likewise, we'll want the hands to release the box at some point later.
178
Stiffness = 0.5
179
Stiffness = 0
And that's it! We've now massaged our original motion capture into carrying a box of similar weight to the motion.
Let's make some changes and see what happens.
"},{"location":"tutorials/mocap_chap/#more-mass","title":"More Mass","text":"What if the box was heavier?
rMarker_pCube1
in the Channel BoxT
on your keyboardMass = 10
When tuning single values like this, it can be helpful to leave the Maya timeline in place and let the simulation update independently.
"},{"location":"tutorials/mocap_chap/#next-steps","title":"Next Steps","text":"At this point, you're able to turn any old motion capture hierarchy into a partial or fully-fledged ragdoll. Why not try a few more from the Content Browser? Or download any of the hundreds of freely available clips from here.
In this tutorial, we'll rig a character from scratch and assign meshes and limits to it.
Version 1.0 - Up to date
Written for Ragdoll 2022.03.14
and above.
Estimated Time
You will need
You will learn
Where to find help
If you find or run into any issues with these tutorials, here's what you can do.
Here's the video on YouTube.
This technique applies to any mesh you can find and is suitable for animators to go at themselves, so go crazy!
"},{"location":"tutorials/rookie_wasp/","title":"Rookie Wasp","text":""},{"location":"tutorials/rookie_wasp/#rookie-wasp","title":"Rookie Wasp","text":"In this tutorial, we'll make an animation cycle using Ragdoll.
Version 1.1 - Up to date
Written for Ragdoll 2021.12.13
and above.
Estimated Time
You will learn
Where to find help
If you find or run into any issues with these tutorials, here's what you can do.
See here for part 1 and 2 of this tutorial.
In this tutorial, we'll make a self-walking character using our Rhino asset.
Version 1.0 - Up to date
Written for Ragdoll 2022.03.14
and above.
Estimated Time
You will need
You will learn
Where to find help
If you find or run into any issues with these tutorials, here's what you can do.
See here for part 1 of 1 this tutorial.
Timeline
Why not put a few of them together with Solver Linking?
Learn by watching.
The forum is a goldmine of learning material, have a look here next!
Then have a look at the videos and examples by following along with each released version of Ragdoll!
Heads up
The below were recorded just before Markers were finalised, but are still applicable to 2021.12.12 and above.
Tutorial Duration Description Markers 101 01:23 What are markers? Markers 101 - Key Concepts 03:23 Overview of Input Type and Pose Space Markers 101 - Local and World 03:00 Overview of the two Pose Spaces, local and world Overlapping Motion I 02:27 The very basics or Capture and Record Overlapping Motion II 02:21 Animation layers Full Ragdoll I 04:08 Hierarchy and volume Full Ragdoll II 04:05 Kinematic and animation Full Ragdoll III 04:30 Self collisions and recording IK I 03:00 Capturing the skeleton IK II 01:59 Retargeting to IK controls IK III 01:59 Record both Translation and Rotation Practical Example I 06:53 Fix table and elbow intersection in this dialog performance Replace Reference Workflow 01:34 An ideal workflow for Ragdoll in a production pipeline with animators."}]} \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml index f9ac19be..784ada64 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -2,797 +2,797 @@^;