// =========================================================================== // Copyright 2018 Autodesk, Inc. All rights reserved. // // Use of this software is subject to the terms of the Autodesk license // agreement provided at the time of installation or download, or which // otherwise accompanies this software in either electronic or hard copy form. // =========================================================================== // // Procedure : // To mirror a NURBS curve | surface geometry // about a user specified construction plane. // Usage : Select the nurbs geometry + construction plane before // executing the script. // proc string buildCurve( float $x[], float $y[], float $z[], float $knots[], int $degree, int $spans, int $form, int $rational, int $dimension ) // // Description : // To build a curve. // { int $i ; string $crvName ; $crvName = `createNode nurbsCurve` ; string $crvData = "setAttr " + ".cc" + " -type " + "nurbsCurve " ; // degree. // $crvData += $degree ; $crvData += " " ; // # of spans. // $crvData += $spans ; $crvData += " " ; // open, close, periodic. // $crvData += $form ; $crvData += " " ; // ? rational. // if( $rational == 0 ) $crvData += "no" ; else $crvData += "yes" ; $crvData += " " ; // ? dimension. // $crvData += $dimension ; $crvData += " " ; // throw in the knots ; // $crvData += size($knots) ; $crvData += " " ; for( $i = 0 ; $i < size($knots) ; $i++ ) { $crvData += $knots[$i] ; $crvData += " " ; } // throw in the cvs. // $crvData += size($x) ; $crvData += " " ; for( $i = 0 ; $i < size($x) ; $i++ ) { $crvData += $x[$i] ; $crvData += " " ; $crvData += $y[$i] ; $crvData += " " ; $crvData += $z[$i] ; $crvData += " " ; } setAttr -k off ".v" ; eval($crvData) ; return $crvName ; } proc string buildSurface( float $x[], float $y[], float $z[], float $knotsU[], float $knotsV[], int $degreeU, int $degreeV, int $formU, int $formV, int $rationalU, int $rationalV, int $dimension ) // // Description : // To build a curve. // { int $i ; string $srfName ; $srfName = `createNode nurbsSurface` ; string $srfData = "setAttr " + ".cc" + " -type " + "nurbsSurface " ; // degree. // $srfData += $degreeU ; $srfData += " " ; $srfData += $degreeV ; $srfData += " " ; // # of spans. // //$crvData += $spans ; //$crvData += " " ; // open, close, periodic. // $srfData += $formU ; $srfData += " " ; $srfData += $formV ; $srfData += " " ; // ? rational. // if( $rationalU == 0 && $rationalV == 0 ) $srfData += "no" ; else $srfData += "yes" ; $srfData += " " ; // throw in the knots ; // $srfData += size($knotsU) ; $srfData += " " ; for( $i = 0 ; $i < size($knotsU) ; $i++ ) { $srfData += $knotsU[$i] ; $srfData += " " ; } $srfData += size($knotsV) ; $srfData += " " ; for( $i = 0 ; $i < size($knotsV) ; $i++ ) { $srfData += $knotsV[$i] ; $srfData += " " ; } // throw in the cvs. // $srfData += size($x) ; $srfData += " " ; for( $i = 0 ; $i < size($x) ; $i++ ) { $srfData += $x[$i] ; $srfData += " " ; $srfData += $y[$i] ; $srfData += " " ; $srfData += $z[$i] ; $srfData += " " ; } setAttr -k off ".v" ; eval($srfData) ; return $srfName ; } proc int sketchPlaneNormalAndPoint( string $sketchPlaneParent, float $planeNormal[], float $ptOnPlane[] ) // // // { string $rel[] = `listRelatives $sketchPlaneParent` ; string $sketchPlane = $rel[0] ; string $cAttr = $sketchPlane + ".center" ; $ptOnPlane = `getAttr $cAttr` ; // compute a normal. // string $boxMin = $sketchPlane + ".boundingBoxMin" ; float $min[] = `getAttr $boxMin` ; string $boxMax = $sketchPlane + ".boundingBoxMax" ; float $max[] = `getAttr $boxMax` ; float $x = ( $max[0] - $min[0] ) * 0.5 ; float $y = ( $max[1] - $min[1] ) * 0.5 ; float $z = ( $max[2] - $min[2] ) * 0.5 ; if( $x == 0.0 ) { // YZ plane. // } float $v1[3] ; $v1[0] = $ptOnPlane[0] + $x ; $v1[1] = $ptOnPlane[1] ; $v1[2] = $ptOnPlane[2] ; float $v2[3] ; $v2[0] = $ptOnPlane[0] ; $v2[1] = $ptOnPlane[1] + $y ; $v2[2] = $ptOnPlane[2] ; $planeNormal = crossProduct( $v1, $v2, 0, 0 ) ; // apply matrix on this point treated as a vector. // string $ppm = `createNode pointMatrixMult` ; setAttr ".inPoint" -type double3 $planeNormal[0] $planeNormal[1] $planeNormal[2] ; setAttr ".vectorMultiply" true ; connectAttr ($sketchPlane+".worldMatrix[0]") ($ppm+".inMatrix") ; $planeNormal = `getAttr ($ppm+".output")` ; setAttr ".inPoint" -type double3 $ptOnPlane[0] $ptOnPlane[1] $ptOnPlane[2] ; setAttr ".vectorMultiply" false ; $ptOnPlane = `getAttr ($ppm+".output")` ; delete $ppm ; return 1 ; } proc int isCurveRational( string $crvName ) // // Description : // To check if curve is rational. // { return 0 ; } proc float[] getCvsOnNurbs( int $coordType, string $infoNode ) // // Description : // { float $v[] ; string $base = $infoNode + ".cp[*]" ; string $vAttr ; if( $coordType == 0 ) { $vAttr = $base + ".xv" ; } else if( $coordType == 1 ) { $vAttr = $base + ".yv" ; } else if( $coordType == 2 ) { $vAttr = $base + ".zv" ; } $v = `getAttr $vAttr` ; return $v ; } proc float[] mirrorPoint( float $x, float $y, float $z, float $normal[], float $p[] ) // // // { float $mp[3] ; if( -1 == normalize($normal) ) return $mp ; float $d = $normal[0] * $p[0] + $normal[1] * $p[1] + $normal[2] * $p[2] ; float $dist = $x * $normal[0] + $y * $normal[1] + $z * $normal[2] - $d ; $mp[0] = $x ; $mp[1] = $y ; $mp[2] = $z ; $dist *= -1.0 ; $mp[0] = $x + 2.0 * $normal[0] * ($dist) ; $mp[1] = $y + 2.0 * $normal[1] * ($dist) ; $mp[2] = $z + 2.0 * $normal[2] * ($dist) ; return $mp ; } proc string mirroredCurveObject( string $crvName, float $xv[], float $yv[], float $zv[] ) // // Description : // { float $knots[] ; select -r $crvName ; $knots = nurbsCurveKnots() ; string $dAttr = $crvName + ".degree" ; int $deg = `getAttr $dAttr` ; string $sAttr = $crvName + ".spans" ; int $ns = `getAttr $sAttr` ; string $fAttr = $crvName + ".form" ; int $form = `getAttr $fAttr` ; int $rat = isCurveRational( $crvName ) ; string $mcurve = buildCurve($xv,$yv,$zv,$knots,$deg,$ns,$form,$rat,3) ; return $mcurve ; } proc string mirroredSurfaceObject( string $srfName, float $xv[], float $yv[], float $zv[] ) // // Desc : Mirrored surface. // { float $knotsU[] ; float $knotsV[] ; select -r $srfName ; $knotsU = nurbsSurfaceKnotsAlongU() ; $knotsV = nurbsSurfaceKnotsAlongV() ; string $dAttr = $srfName + ".degreeU" ; int $degU = `getAttr $dAttr` ; $dAttr = $srfName + ".degreeV" ; int $degV = `getAttr $dAttr` ; string $fAttr = $srfName + ".formU" ; int $formU = `getAttr $fAttr` ; $fAttr = $srfName + ".formV" ; int $formV = `getAttr $fAttr` ; int $rat = 0 ; string $msrf = buildSurface($xv,$yv,$zv,$knotsU,$knotsV,$degU,$degV,$formU,$formV,$rat,$rat,3) ; return $msrf ; } // To reflect nurbs geometry about a construction // plane. // global proc string mirrorNurbsGeometry( ) { float $ptOnPlane[3] ; float $planeNormal[3] ; // 0. Grab the select list. // string $selList[] ; $selList = `ls -sl` ; // 1. Run filter looking for a sketchPlane ? // int $i, $j ; int $len = size($selList) ; string $sketchPlane = " " ; for( $i = 0 ; $i < $len ; $i++ ) { string $item = $selList[$i] ; if( `nodeType $item` == "sketchPlane" ) { $sketchPlane = $item ; break ; } string $rel[] = `listRelatives $item` ; for( $j = 0 ; $j < size($rel) ; $j++ ) { string $ritem = $rel[$j] ; if( `nodeType $ritem` == "sketchPlane" ) { $sketchPlane = $item ; break ; } } if( $sketchPlane != " " ) break ; } if( $sketchPlane == " " ) { error((uiRes("m_mirrorNurbsGeometry.kErrorNoSketchPlane")) ); return " " ; } sketchPlaneNormalAndPoint( $sketchPlane, $planeNormal, $ptOnPlane ) ; // 1.1 Run filter to select only the NURBS // curves | surfaces. // global int $gSelectNurbsSurfacesBit ; global int $gSelectNurbsCurvesBit ; int $isCurve = 0 ; select -r $selList ; $selList = `filterExpand -ex true -sm $gSelectNurbsSurfacesBit` ; if( size($selList) == 0 ) { $selList = `filterExpand -ex true -sm $gSelectNurbsCurvesBit` ; if( size($selList) == 0 ) { error (uiRes("m_mirrorNurbsGeometry.kErrorNoCurveOrSurface")) ; return " "; } $isCurve = 1 ; } $len = size($selList) ; string $lastItem = $selList[$len-1] ; if( $len > 1 ) { string $s = "mirroring only object : " + $lastItem ; warning $s ; } // hook the NURBS curve, surface to the info node. // string $infoNode ; string $inAttr = $lastItem + ".ws[0]" ; string $outAttr ; if( $isCurve ) { $infoNode = `createNode curveInfo` ; $outAttr = $infoNode + ".ic" ; } else { $infoNode = `createNode surfaceInfo` ; $outAttr = $infoNode + ".is" ; } connectAttr $inAttr $outAttr ; // get cvs x. int $inC = 0 ; // X coord. float $x[] = getCvsOnNurbs( $inC, $infoNode ) ; // get cvs y. $inC = 1 ; float $y[] = getCvsOnNurbs( $inC, $infoNode ) ; // get cvs z. $inC = 2 ; float $z[] = getCvsOnNurbs( $inC, $infoNode ) ; delete $infoNode ; // Mirror cvs about the specified plane. // float $xm[], $ym[], $zm[] ; int $n = size($x) ; for( $i = 0 ; $i < $n ; $i++ ) { float $m[] = mirrorPoint( $x[$i], $y[$i], $z[$i], $planeNormal, $ptOnPlane ) ; $xm[$i] = $m[0] ; $ym[$i] = $m[1] ; $zm[$i] = $m[2] ; } string $mObject ; if( $isCurve ) { $mOject = mirroredCurveObject($lastItem,$xm,$ym,$zm) ; } else { $mOject = mirroredSurfaceObject($lastItem,$xm,$ym,$zm) ; } return $mObject ; }