Code

Published Autodesk Maya Code

Systematically Sampling Joint Poses

See Supplementary Method S1 from my paper in Proc B for full instructions. Please cite Manafzadeh & Padian (2018) when used.

``````{
int \$i;
int \$j;
int \$k;
int \$frame = 1;
currentTime -edit 1;
for (\$i = -180; \$i < 181; \$i = \$i + 5) //increment FE from -180° to 180° at 5-degree intervals
{
for (\$j = -90; \$j < 91; \$j = \$j + 5) //increment ABAD from -90° to 90° at 5-degree intervals
{
for (\$k = -180; \$k < 181; \$k = \$k + 5) //increment LAR from -180° to 180° at 5-degree intervals
{
setKeyframe -at rotateZ -v \$i -t \$frame myJoint; //set FE
setKeyframe -at rotateY -v \$j -t \$frame myJoint; //set ABAD
setKeyframe -at rotateX -v \$k -t \$frame myJoint; //set LAR
\$frame = \$frame + 1;
}
}
}
}``````

Automatically Checking for Mesh Model Interpenetration

See Supplementary Method S2 from my paper in Proc B for full instructions. Please cite Manafzadeh & Padian (2018) when used.

``````float \$area[] = `polyEvaluate -area boo`; //compute surface area of intersection mesh
if (\$area[0] >0) setKeyframe -at viable -v 0 myJoint; //if the mesh exists (i.e., has a positive surface area), the pose is inviable
else setKeyframe -at viable -v 1 myJoint; //if the mesh does not exist (i.e., has zero surface area), the pose is viable``````

Measuring Dynamically Simulated Ligament Fibers (Maya)

See Supplementary Method S4 from my paper in Proc B for full instructions. Please cite Manafzadeh & Padian (2018) when used.

``````{
float \$start[];
float \$end[];
float \$lengthVal[];
float \$length;
float \$total;
int \$i;
int \$j;
for (\$i=4; \$i < 555; \$i = \$i+11) //the first vertex queried is vertex four, the fifth in the first row of the plane. By incrementing by 11 vertices, we
move to the fifth vertex in the following row.
{
\$j = \$i+11; //the fifth vertex in the next row
\$start = `pointPosition ("lig1.vtx["+\$i+"]")`; //find the position of the fifth vertex in the first row
\$end = `pointPosition ("lig1.vtx["+\$j+"]")`; //find the position of the fifth vertex in the following row
\$lengthVal[0] = \$start[0]-\$end[0];
\$lengthVal[1] = \$start[1]-\$end[1];
\$lengthVal[2] = \$start[2]-\$end[2];
\$length = `mag <<\$lengthVal[0],\$lengthVal[1],\$lengthVal[2]>>`; //find the distance between the vertices
\$total = \$total + \$length; //sum the whole column of vertex distances to find the total fiber length
}
print \$total;
setKeyframe -at length -v \$total lig1;
}``````

Published Matlab Code

Creating a ROM Map

See Supplementary Method S3 from my paper in Proc B for full instructions. Please cite Manafzadeh & Padian (2018) when used.

``````shape1 = alphaShape(rz1,ry1,rx1); %create a 3-D alpha shape using the first set of (FE°, ABAD°, LAR°) points
plot(shape1); %plot the first alpha shape
hold on;
shape2 = alphaShape(rz2,ry2,rx2); %create a 3-D alpha shape using second set of (FE°, ABAD°, LAR°) points
plot(shape2); %plot the second alpha shape on the same axes
hold off;
shape1vol = volume(shape1); %compute the volume of the first alpha shape
disp(shape1vol);
shape2vol = volume(shape2); %compute the volume of the second alpha shape
disp(shape2vol);
percent = shape1vol/shape2vol; %compare volumes
disp(percent)``````

Unpublished Code: Use at your own risk!

Convert Tait-Bryan angles to cosine-corrected Euler space (Matlab)

Import three sequential Tait-Bryan rotations (in degrees) into Matlab as column vectors named “first” (first rotation), “second” (second rotation), and “third” (third rotation). For XROMM studies, these are likely Z, Y, and X rotations, respectively. This code will generate a table of cosine-corrected rotations in a cosine-corrected Euler space with alphaCentral = 0.

``````for i = 1:(size(second))
if (second(i) > 90)
first(i) = first(i) - 180;
second(i)  = 180 - second(i);
third(i) = third(i) - 180;
end
end

for i = 1:(size(third))
if (third(i) > 180)
third(i) = -1* (360 - third(i));
end
end

correctedFirst = first .* cosd(second);

cosineCorrectedData = table(correctedFirst,second,third);``````

BETA: A much faster alternative to the current oRel XROMM Shelf Tool (Maya)

Requires that the matrixNodes.mll plugin is loaded. Save script to Maya Scripts folder and call oRelFast from MEL command line. Calculates 6 DoF kinematics between two objects ~instantaneously without playing through the time slider.

``````global proc oRelFast()

/*
created 2020 May 10 by AR Manafzadeh
last updated 2020 May 11
speeds up oRel XROMM shelf tool substantially by using nodes and getAttr command
REQUIRES MATRIX PLUGIN TO BE LOADED
*/

//***********************USER INTERFACE***********************

//modify Dave Baier's XROMM_MayaTools oRel UI
{
int \$height = 220;
int \$width = 500;

if (`window -exists oRelFastWindow` == true) deleteUI oRelFastWindow;

string \$mainWindow = `window -title "Output Relative Motion Faster"-menuBar true
-maximizeButton false -minimizeButton true -sizeable true -resizeToFitChildren false
oRelFastWindow`;

frameLayout -label "Output Relative Motion Faster" -height \$height -width \$width -mw 5 -mh 5;
columnLayout;
menuItem -label "Reset" -command cRec resetButton;
menuItem -label "Close" -command "deleteUI oRelFastWindow" closeButton;
columnLayout;
text "Step 1: Select the fixed and mobile ACSs";
textFieldButtonGrp -label "Fixed ACS" -text "Select fixed ACS and click Insert Selection"
-buttonLabel "Insert Selection" -buttonCommand proxSelectButton proxFieldGroup;
textFieldButtonGrp -label "Mobile ACS" -text "Select mobile ACS and click Insert Selection"
-buttonLabel "Insert Selection" -buttonCommand distSelectButton distFieldGroup;
text "Output Node Name";
textField -width \$width -text  "dataNodeNameHere" outputNameField;
setParent..;
text " ";
button	-label "Output Relative Motion" -enable 1 -w (\$width) -command outputRelMotionFast;
button	-label "Close" -w (\$width) closeButton;
button -edit -command "deleteUI oRelFastWindow" closeButton;

showWindow \$mainWindow;
window -e -width \$width -height \$height \$mainWindow;
}

global proc proxSelectButton()
{
string \$objs[] = `ls -sl`;
textFieldButtonGrp -e -text \$objs[0] proxFieldGroup;
}

global proc distSelectButton()
{
string \$objs[] = `ls -sl`;
textFieldButtonGrp -e -text \$objs[0] distFieldGroup;
}

//*********************RELATIVE MOTION CALCULATION*********************

//use info from UI and create nodes to calculate relative motion
global proc outputRelMotionFast()
{

string \$axesP = `textFieldButtonGrp -q -text proxFieldGroup`;
string \$axesD = `textFieldButtonGrp -q -text distFieldGroup`;
string \$holder = `textField -q -text outputNameField`;

int \$frame = `findKeyframe -hi both -which first \$axesD` ;
int \$lastframe = `findKeyframe -hi both -which last \$axesD`;

string \$multiplyNode = (\$holder + "MultiplyNode");
string \$decomposeNode = (\$holder + "DecomposeNode");

string \$output = \$holder + "data";
spaceLocator -n \$output;

createNode "decomposeMatrix" -n \$decomposeNode;
connectAttr -f (\$axesD+".worldMatrix[0]") (\$multiplyNode+".matrixIn[0]");
connectAttr -f (\$axesP+".worldInverseMatrix[0]") (\$multiplyNode+".matrixIn[1]");
connectAttr -f (\$multiplyNode+".matrixSum") (\$decomposeNode+".inputMatrix");
connectAttr -f (\$decomposeNode+".outputRotate") (\$output+".rotate");

//store node transforms in an array
float \$transXVals[];
float \$transYVals[];
float \$transZVals[];
float \$rotXVals[];
float \$rotYVals[];
float \$rotZVals[];

for (\$i = \$frame; \$i < \$lastframe+1; \$i++)

{
\$transXVals[\$i] = `getAttr -t \$i \$decomposeNode.outputTranslateX`;
\$transYVals[\$i] = `getAttr -t \$i \$decomposeNode.outputTranslateY`;
\$transZVals[\$i] = `getAttr -t \$i \$decomposeNode.outputTranslateZ`;
\$rotXVals[\$i] = `getAttr -t \$i \$decomposeNode.outputRotateX`;
\$rotYVals[\$i] = `getAttr -t \$i \$decomposeNode.outputRotateY`;
\$rotZVals[\$i] = `getAttr -t \$i \$decomposeNode.outputRotateZ`;

//use the array to set keyframes on the holder locator
setKeyframe -t \$i -at tx -ott "step" -v \$transXVals[\$i] \$output;
setKeyframe -t \$i -at ty -ott "step" -v \$transYVals[\$i] \$output;
setKeyframe -t \$i -at tz -ott "step" -v \$transZVals[\$i] \$output;
setKeyframe -t \$i -at rx -ott "step" -v \$rotXVals[\$i] \$output;
setKeyframe -t \$i -at ry -ott "step" -v \$rotYVals[\$i] \$output;
setKeyframe -t \$i -at rz -ott "step" -v \$rotZVals[\$i] \$output;
}

//delete the utility nodes and select the holder locator
select \$output;
delete \$decomposeNode;
delete \$multiplyNode;

}``````

BETA: UI to change an object’s shader without changing the shaders of its children (Maya)

Save script to Maya Scripts folder and call switchMaterial from MEL command line. Currently only works for one object at a time.

``````global proc switchMaterial()

/*
currently supports only one object at a time
*/

//First build a UI

{
int \$height = 220;
int \$width = 500;

if (`window -exists matSwitchWindow` == true) deleteUI matSwitchWindow;

string \$mainWindow = `window -title "Switch to a New Material"-menuBar true
-maximizeButton false -minimizeButton true -sizeable true -resizeToFitChildren false
matSwitchWindow`;

frameLayout -label "Switch to a New Material" -height \$height -width \$width -mw 5 -mh 5;
columnLayout;
menuItem -label "Reset" -command cRec resetButton;
menuItem -label "Close" -command "deleteUI materialSwitchWindow" closeButton;
columnLayout;
text "Step 1: Select the OBJECT whose material you want to switch";
textFieldButtonGrp -label "Object" -text "Select and click Insert Selection"
-buttonLabel "Insert Selection" -buttonCommand objSelectB objFieldGroup;
text "Step 2: Select the new MATERIAL that you want to switch to";
textFieldButtonGrp -label "Material" -text "Select and click Insert Selection"
-buttonLabel "Insert Selection" -buttonCommand matSelectB matFieldGroup;
setParent..;
text " ";
button	-label "Switch Material" -enable 1 -w (\$width) -command switchMat;
button	-label "Close" -w (\$width) closeButton;
button -edit -command "deleteUI matSwitchWindow" closeButton;

showWindow \$mainWindow;
window -e -width \$width -height \$height \$mainWindow;
}

//Get the object selection button to work

global proc objSelectB()
{
string \$obj[] = `ls -sl`;
textFieldButtonGrp -e -text \$obj[0] objFieldGroup;
}

//Get the material selection button to work

global proc matSelectB()
{
string \$mat[] = `ls -sl`;
textFieldButtonGrp -e -text \$mat[0] matFieldGroup;
}

//Unparent the selected object's children, change its material to the selected material, and then reparent the children

global proc switchMat()
{

string \$obj = `textFieldButtonGrp -q -text objFieldGroup`;
string \$mat = `textFieldButtonGrp -q -text matFieldGroup`;

string \$objKids[] = `listRelatives -c -typ transform \$obj`;
parent -w \$objKids;
select \$obj;