// SmoothProxy with Radial Symmetry // Author: Robert McDaniel // rob@chaoticmutation.com // // Created: 08.11.2007 // // Procedure Name: // CM_SmoothProxyRadialSymmetry // // Description: // similar to how the native performSmothProxy.mel can do mirroring across an axis // (with the mirrored linked duplicate merged with the original shape), // except with this script, linked duplicates are rotated around one of the object's axis // instead of scaled -1 // // Input Arguments: // none // Return Value: // none // // This is the procedure that does all the real work. It was modified from the performSmoothProxy.mel from Maya 8.5. proc polySmoothProxyRadialSym(int $iAxisType, int $iSegments, float $mergeTolerance) { // Limit the value of $iSegments just in case, less than 2 makes no sense, and 10 seems like large // enough number for general use if (2 > $iSegments) { $iSegments = 2; } else if (10 < $iSegments) { $iSegments = 10; } // Declare a couple of variables, might expose these later int $renderable = 0; // get the selection items string $sel[]=`polyCheckSelection "polySmoothProxy" "o"`; if (size($sel) == 0) { string $msg = (uiRes("m_performSmoothProxy.kSelectMeshError")); error ($msg); return; } else if (size($sel) > 1) { string $msg = (uiRes("m_performSmoothProxy.kSelectMeshWarning")); warning ($msg); select -replace $sel[0]; } string $transform[] = `listRelatives -fullPath -parent $sel[0]`; string $lores = $transform[0]; string $loresShape[] = `listRelatives -pa -shapes $lores`; // check loresShape for an existing output to a smoothProxy string $attachedSmoothProxies[] = `listConnections -type "polySmoothProxy" -s 0 -d 1 $loresShape[0]`; if (size($attachedSmoothProxies)) { string $msg = (uiRes("m_performSmoothProxy.kSelectMultipleError")); error ($msg); return; } // make a hires surface. string $result[] = `polyDuplicateAndConnect -renameChildren`; string $hires = $result[0]; // find the input to the new mesh node (not necessarily a shape, // could be a groupParts node for example); string $incoming[] = eval("listConnections -p on " + $hires + ".inMesh"); // Based on the number of segments, determine the angle of rotation // needed per segement float $AngleSize = 360.0/$iSegments; // Declare array to hold the meshes to combine and add the first mesh to it string $astrMeshesToCombine[]; $astrMeshesToCombine[0] = $hires; // Loop through the new segments for ($i = 1; $i < $iSegments; $i++) { string $segmentNode[] = `duplicate -returnRootsOnly $hires`; eval("connectAttr " + $incoming[0] + " " + $segmentNode[0] + ".inMesh"); switch ($iAxisType) { // object X case 1: xform -relative -os -ro ($i*$AngleSize) 0 0 $segmentNode[0]; break; // object Y case 2: xform -relative -os -ro 0 ($i*$AngleSize) 0 $segmentNode[0]; break; // object Z case 3: xform -relative -os -ro 0 0 ($i*$AngleSize) $segmentNode[0]; break; } // Add the segmentNode the array of meshes $astrMeshesToCombine[size($astrMeshesToCombine)] = $segmentNode[0]; } // combine the hires segmentNodes string $combinedLores[] = `polyUnite -constructionHistory 1 $astrMeshesToCombine`; $hires = $combinedLores[0]; // merge their verts polyMergeVertex -distance $mergeTolerance -constructionHistory 1 $combinedLores[0]; // find the input to the new mesh node (not necessarily a shape, // could be a groupParts node for example); string $incoming[] = eval("listConnections -p on " + $hires + ".inMesh"); // break the surface-surface connections eval("disconnectAttr " + $incoming[0] + " " + $hires + ".inMesh"); // create the polySmooth node and hook up the lores mesh string $smoothNode; $smoothNode = `createNode polySmoothProxy`; eval("setAttr " + $smoothNode + ".maya65Above 1"); eval("connectAttr " + $incoming[0] + " " + $smoothNode + ".inputPolymesh"); // change what the hires object is; // up until this point hires points to the transform - the opposite is // required for the parenting of both shapes under the same transform // to do this, get both the name and the fullPath name to the hiresShape. string $hiresShapeFullPath[] = `listRelatives -fullPath -shapes $hires`; string $hiresShape[] = `listRelatives -pa -shapes $hires`; string $loresTransform[] = `listRelatives -pa -parent $lores`; // parent parent -shape $hiresShape[0] $lores; // delete the hires and change some more names around delete $hires; $hires = $hiresShape[0]; // now hook up output hires poly eval("connectAttr " + $smoothNode + ".out " + $hires + ".inMesh"); // prevent topology operations on the hires mesh eval("setAttr " + $hires + ".allowTopologyMod 0"); // ensure smooth operates on all the faces of the input // geometry. If this were not here and the user added more faces // to the input mesh, the new faces would not be subdivided. string $compAttr = $smoothNode + ".ics"; setAttr $compAttr -type "componentList" 1 "f[*]"; // Need to be able to see the smoothNode for checking if the base mesh // is being used as an smoothProxy already connectAttr -f ($loresShape[0] + ".isHistoricallyInteresting") ($smoothNode + ".isHistoricallyInteresting"); // Set the hires shape to be shaded, reference, and hard edges only setAttr ($hires + ".overrideEnabled") 1; setAttr ($hires + ".overrideShading") 1; setAttr ($hires + ".overrideDisplayType") 2; setAttr ($hires + ".displayEdges") 2; // Turn off shading on the lores mesh setAttr ($loresShape[0] + ".overrideEnabled") 1; setAttr ($loresShape[0] + ".overrideShading") 0; // set lores rendering attributes off if specified // and make sure hires render attrs are on - if user started with mirroring // and then unmirrored and made a new smoothProxy setup without mirroring, // the hires will inherit the rendering attribute settings which are off if ($renderable == 0) { eval("setAttr " + $loresShape[0] + ".castsShadows 0"); setAttr ($loresShape[0] + ".receiveShadows") 0; setAttr ($loresShape[0] + ".primaryVisibility") 0; setAttr ($loresShape[0] + ".visibleInReflections") 0; setAttr ($loresShape[0] + ".visibleInRefractions") 0; setAttr ($hires + ".castsShadows") 1; setAttr ($hires + ".receiveShadows") 1; setAttr ($hires + ".primaryVisibility") 1; setAttr ($hires + ".visibleInReflections") 1; setAttr ($hires + ".visibleInRefractions") 1; } // initial refresh shows hires mesh in component mode, so force it to object mode // then select the lores object for tweaking refresh; select -r $loresShape[0]; return; } // Procedure to get the window's options and send it off to the main procedure global proc polySmoothProxyRadialSymGetSettings() { // Declare the global variables global int $iAxisType; global int $iSegments; global float $MergeVtxTolerance; // Get their values from the window $iAxisType = `radioButtonGrp -q -select AxisOfSymmetry`; $iSegments = `intSliderGrp -q -v AxisSegments`; $MergeVtxTolerance = `floatSliderGrp -q -v MergeVertexTolerance`; // Start the main procedure with the user's preferences polySmoothProxyRadialSym($iAxisType, $iSegments, $MergeVtxTolerance); } // This is the main procedure called by the melscript. Opens a window with tweakable options and // gives the user a button to make the smoothProxy. global proc CM_SmoothProxyRadialSymmetry() { // first delete window if it exists already if( (`window -exists SmoothProxyAxisSymWindow`) == true ) { deleteUI SmoothProxyAxisSymWindow; } // Declare our global variables global int $iAxisType; global int $iSegments; global float $MergeVtxTolerance; // If this is the first time the procedure has been called in this Maya session // then set some default values if (0 == $iAxisType) { $iAxisType = 1; } if (0 == $iSegments) { $iSegments = 2; } // Setup the window window -t "SmoothProxy with Radial Symmetry" -rtf 1 SmoothProxyAxisSymWindow; columnLayout -columnAttach "left" 10 -rowSpacing 10 -columnWidth 300; // The object axis of symmetry to use radioButtonGrp -label "Axis of Symmetry" -nrb 3 -label1 "Object's X" -da1 0 -label2 "Object's Y" -da2 1 -label3 "Object's Z" -da3 2 -sl $iAxisType AxisOfSymmetry; // How many segment repeats around the axis to use intSliderGrp -label "Segments per Axis" -field true -min 2 -max 10 -s 1 -v $iSegments AxisSegments; // The merge vertex tolerance for welding the lowres cages together floatSliderGrp -label "Merge Vtx Tolerance" -field true -minValue 0.001 -maxValue 10.0 -pre 3 -value $MergeVtxTolerance -fieldMinValue 0.001 -fieldMaxValue 100.0 MergeVertexTolerance; // Button to actually do the work on the selected object button -label "Perform SmoothProxy w/Axis Symmetry" -c "polySmoothProxyRadialSymGetSettings"; showWindow; }