// =========================================================================== // 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. // =========================================================================== includeEffectsGlobals(); // // lightning // - makeLightning // - makeLightning // - createShader // - createShader proc createLightningSelectHandleExpr( string $group ) // // Description: // // The selection handle for the lightning group gets diplayed at // the center of the lightning bolt. This expression finds that location // and sets the selection handle's position to it. // { // Get the object from which the lightning is coming. // string $fromObjs[] = getLightningFromPoint( $group ); string $fromObj = $fromObjs[0]; string $fromDirs[] = getLightningFromDirection( $group ); string $fromDirection = $fromDirs[0]; // Get the object from which the lightning is ending. // string $toObjs[] = getLightningToPoint( $group ); string $toObj = $toObjs[0]; string $toDirs[] = getLightningToDirection( $group ); string $toDirection = $toDirs[0]; // To display select-handle at the center, create a expression. // string $selectHandleX = ($group+".selectHandleX"); string $selectHandleY = ($group+".selectHandleY"); string $selectHandleZ = ($group+".selectHandleZ"); string $expr = ""; $expr += ("float $fromX = "+$fromObj+".translateX;\n"); $expr += ("float $fromY = "+$fromObj+".translateY;\n"); $expr += ("float $fromZ = "+$fromObj+".translateZ;\n"); $expr += ("float $toX = "+$toObj+".translateX;\n"); $expr += ("float $toY = "+$toObj+".translateY;\n"); $expr += ("float $toZ = "+$toObj+".translateZ;\n"); $expr += ("float $fromDirX = "+$fromDirection+".translateX;\n"); $expr += ("float $fromDirY = "+$fromDirection+".translateY;\n"); $expr += ("float $fromDirZ = "+$fromDirection+".translateZ;\n"); $expr += ("float $toDirX = "+$toDirection+".translateX;\n"); $expr += ("float $toDirY = "+$toDirection+".translateY;\n"); $expr += ("float $toDirZ = "+$toDirection+".translateZ;\n"); $expr += ("vector $from = << $fromX, $fromY, $fromZ>>;\n"); $expr += ("vector $to = << $toX, $toY, $toZ>>;\n"); $expr += ("vector $fromDirP = << $fromDirX, $fromDirY, $fromDirZ>>;\n"); $expr += ("vector $toDirP = << $toDirX, $toDirY, $toDirZ>>;\n"); $expr += ("vector $fromDir = ($fromDirP - $from) * 5.0;\n"); $expr += ("vector $toDir = ($to - $toDirP) * 5.0;\n"); $expr += ("float $start = "+$group+".lightningStart;\n"); $expr += ("float $end = "+$group+".lightningEnd;\n"); $expr += ("float $ratio = $start + ($end - $start) * 0.5;\n"); $expr += ("vector $handleP=hermite($from,$to,$fromDir,$toDir,$ratio);\n"); $expr += ($selectHandleX+" = $handleP.x;\n"); $expr += ($selectHandleY+" = $handleP.y;\n"); $expr += ($selectHandleZ+" = $handleP.z;\n"); expression -alwaysEvaluate false -string $expr; } proc string makeLightningGroup ( string $name, string $fromObj, string $toObj, int $segmentCount, float $thickness, float $maxSpread, float $start, float $end, float $glowIntensity ) { // Create a group node. // group -empty; if( $name == "" ) { rename "Lightning#"; } else { rename $name; } string $group = getSelectedObject( 0 ); // Do not allow to do transformation on the lightning group. // lockTransformations( $group ); // This attribute is for checking if the node is a lightning node. // addAttr -at message -ln "_lightningGroupObject" $group; // Add attributes for management. // addMarkingAttribute( $group, "lightningFromObject", 0 ); addMarkingAttribute( $group, "lightningFromPosition", 0 ); addMarkingAttribute( $group, "lightningFromDirection", 0 ); addMarkingAttribute( $group, "lightningToObject", 0 ); addMarkingAttribute( $group, "lightningToPosition", 0 ); addMarkingAttribute( $group, "lightningToDirection", 0 ); addMarkingAttribute( $group, "lightningParticleObject", 0 ); addMarkingAttribute( $group, "lightningSurface", 0 ); addMarkingAttribute( $group, "lightningShader", 0 ); //addMarkingAttribute( $group, "lightningPointLights", 1 ); // Connect from and end object with the group. // markObjectWithAttribute( $fromObj, $group, "lightningFromObject" ); markObjectWithAttribute( $toObj, $group, "lightningToObject" ); // Add attributes for lightning controls. // addControlAttribute( $group, "thickness", $thickness, 0, 10 ); addControlAttribute( $group, "maxSpread", $maxSpread, 0, 10 ); addControlAttribute( $group, "lightningStart", $start, 0, 1 ); addControlAttribute( $group, "lightningEnd", $end, 0, 1 ); addControlAttribute( $group, "glowIntensity", $glowIntensity, 0, 100 ); addControlAttribute( $group, "lightIntensity", 2.0, 0, 100 ); addControlAttribute( $group, "colorR", 0.5, 0, 1 ); addControlAttribute( $group, "colorG", 1, 0, 1 ); addControlAttribute( $group, "colorB", 1, 0, 1 ); string $sl[]; string $constrainNode[]; //float $fromPos[] = `getAttr ($fromObj+".translate")`; //float $toPos[] = `getAttr ($toObj+".translate")`; float $fromPos[] = `xform -q -ws -t $fromObj`; float $toPos[] = `xform -q -ws -t $toObj`; vector $fromV = << $fromPos[0], $fromPos[1], $fromPos[2] >>; vector $toV = << $toPos[0], $toPos[1], $toPos[2] >>; vector $diffV = $toV - $fromV; float $dist = mag($diffV); // For the start of the lightning. // spaceLocator -p 0 0 0; rename "fromPoint#"; $sl = `ls -sl`; string $fromPoint = $sl[0]; string $fromPointShape = getShapeFromObject( $fromPoint, 0, 0 ); setAttr ($fromPointShape+".visibility") 0; //setAttr ($fromPoint+".template") 1; setAttr ($fromPoint+".inheritsTransform") 0; select $fromObj $fromPoint; $constrainNode = `pointConstraint -weight 1`; setAttr ($constrainNode[0]+".visibility") 0; select $fromObj $fromPoint; $constrainNode = `orientConstraint -weight 1`; setAttr ($constrainNode[0]+".visibility") 0; markObjectWithAttribute($fromPoint, $group, "lightningFromPosition"); select -cl; string $fromJoint1 = `joint -p 0 0 0`; string $fromJoint2 = `joint -p 3 0 0`; joint -e -zso -oj xyz $fromJoint2; setAttr ($fromJoint2+".visibility") 0; setAttr ($fromJoint1+".template") 1; select $fromPoint $fromJoint1; $constrainNode = `pointConstraint -weight 1`; setAttr ($constrainNode[0]+".visibility") 0; // Create a locator as "fromDirectionHandle". // vector $fromHandleP = $fromV + $diffV * 0.2; spaceLocator -p 0 0 0; move ($fromHandleP.x) ($fromHandleP.y) ($fromHandleP.z); rename "fromDirHandle#"; $sl = `ls -sl`; string $fromDirHandle = $sl[0]; parent $fromDirHandle $fromPoint; select $fromDirHandle $fromJoint2; $constrainNode = `pointConstraint -weight 1`; setAttr ($constrainNode[0]+".visibility") 0; // Create a locator as "fromDirection". // "fromDirection" point-constrained to "fromDirectionHandle". // spaceLocator -p 0 0 0; move ($fromHandleP.x) ($fromHandleP.y) ($fromHandleP.z); rename "fromDir#"; $sl = `ls -sl`; string $fromDirection = $sl[0]; setAttr ($fromDirection+".visibility") 0; setAttr ($fromDirection+".inheritsTransform") 0; parent $fromDirection $fromPoint; select $fromDirHandle $fromDirection; $constrainNode = `pointConstraint -weight 1`; setAttr ($constrainNode[0]+".visibility") 0; markObjectWithAttribute($fromDirection, $group, "lightningFromDirection"); // Group the "from" controls. // select $fromJoint1 $fromPoint; group; rename("fromControl#"); string $fromControl = getSelectedObject( 0 ); // For the end of the lightning. // spaceLocator -p 0 0 0; rename "toPoint#"; $sl = `ls -sl`; string $toPoint = $sl[0]; string $toPointShape = getShapeFromObject( $toPoint, 0, 0 ); setAttr ($toPointShape+".visibility") 0; //setAttr ($toPoint+".template") 1; setAttr ($toPoint+".inheritsTransform") 0; select $toObj $toPoint; $constrainNode = `pointConstraint -weight 1`; setAttr ($constrainNode[0]+".visibility") 0; select $toObj $toPoint; $constrainNode = `orientConstraint -weight 1`; setAttr ($constrainNode[0]+".visibility") 0; markObjectWithAttribute($toPoint, $group, "lightningToPosition"); select -cl; string $toJoint1 = `joint -p 0 0 0`; string $toJoint2 = `joint -p 3 0 0`; joint -e -zso -oj xyz $toJoint2; setAttr ($toJoint2+".visibility") 0; setAttr ($toJoint1+".template") 1; select $toPoint $toJoint1; $constrainNode = `pointConstraint -weight 1`; setAttr ($constrainNode[0]+".visibility") 0; // Create a locator as "toDirectionHandle". // vector $toHandleP = $toV - $diffV * 0.2; spaceLocator -p 0 0 0; move ($toHandleP.x) ($toHandleP.y) ($toHandleP.z); rename "toDirHandle#"; $sl = `ls -sl`; string $toDirHandle = $sl[0]; parent $toDirHandle $toPoint; select $toDirHandle $toJoint2; $constrainNode = `pointConstraint -weight 1`; setAttr ($constrainNode[0]+".visibility") 0; // Create a locator as "toDirection". // "toDirection" point-constrained to "toDirectionHandle". // spaceLocator -p 0 0 0; move ($toHandleP.x) ($toHandleP.y) ($toHandleP.z); rename "toDir#"; $sl = `ls -sl`; string $toDirection = $sl[0]; setAttr ($toDirection+".visibility") 0; setAttr ($toDirection+".inheritsTransform") 0; parent $toDirection $toPoint; select $toDirHandle $toDirection; $constrainNode = `pointConstraint -weight 1`; setAttr ($constrainNode[0]+".visibility") 0; markObjectWithAttribute($toDirection, $group, "lightningToDirection"); // Group the "to" controls. // select $toJoint1 $toPoint; group; rename("toControl#"); string $toControl = getSelectedObject( 0 ); // Create lightning curve. // string $curveCmd = "curve -name \"lightningCurve#\" -d 1"; if( $segmentCount < 5 ) $segmentCount = 5; int $i; for( $i = 0; $i <= $segmentCount; $i ++ ) { float $ratio = $i / $segmentCount; vector $newPos = $fromV + $diffV * $ratio; $curveCmd += (" -p "+($newPos.x)+" "+($newPos.y)+" "+($newPos.z)); $curveCmd += (" -k " + $i); } string $curve = eval( $curveCmd ); setAttr ($curve+".visibility") 0; // Extrude lightning surface. // circle -c 0 0 0 -nr 0 0 1 -sw 360 -r .1 -d 3 -ut 0 -tol 0.01 -s 4 -ch 0; string $circles[] = `ls -sl`; string $circle = $circles[0]; setAttr ($circle+".visibility") 0; // Let "thickness" modifys the circle.scale. // connectAttr ($group+".thickness") ($circle+".scaleX"); connectAttr ($group+".thickness") ($circle+".scaleY"); connectAttr ($group+".thickness") ($circle+".scaleZ"); extrude -ch true -rn false -po 0 -et 1 -ucp 1 -fpt 1 -upn 1 -rotation 0 -scale 1 $circle $curve; rename "LightningSurface#"; string $surfaces[] = `ls -sl`; string $surface = $surfaces[0]; //setAttr ($surface+".template") 1; markObjectWithAttribute( $surface, $group, "lightningSurface" ); // Do not allow to do transformation on the lightning group. // lockTransformations( $surface ); // Create soft curve for lightning. // select $curve; string $particleTransform[] = `soft`; select $particleTransform[0]; pickWalk -d down; string $selected[] = `ls -sl`; string $particleShape = $selected[0]; setAttr ($particleTransform[0]+".visibility") 0; markObjectWithAttribute($particleShape, $group, "lightningParticleObject"); // Group lightning geometries. // select $curve $circle; group; rename("controlGeometries#"); string $geometry = getSelectedObject( 0 ); // parenting operations. // parent $fromControl $group; parent $toControl $group; parent $geometry $group; parent $surface $group; // Display the select-handle at the the center of the lightning surface. // vector $handlePos = $fromV + ($diffV * 0.5); float $x = $handlePos.x; float $y = $handlePos.y; float $z = $handlePos.z; setAttr ($group+".selectHandle") -type double3 $x $y $z; setAttr ($group+".displayHandle") 1; // create expression to display group selection handle at the center // of the lightning curve. // createLightningSelectHandleExpr( $group ); return $group; } proc createLightningExpression( string $group ) { // Get the object from which the lightning is coming. // string $fromObjs[] = getLightningFromPoint( $group ); string $fromObj = $fromObjs[0]; string $fromDirs[] = getLightningFromDirection( $group ); string $fromDirection = $fromDirs[0]; // Get the object from which the lightning is ending. // string $toObjs[] = getLightningToPoint( $group ); string $toObj = $toObjs[0]; string $toDirs[] = getLightningToDirection( $group ); string $toDirection = $toDirs[0]; // Get the particle object. // string $particles[] = getLightningParticle( $group ); string $particleShape = $particles[0]; // Add expression to soft curve particle object. // string $expression = ""; $expression += ("vector $from = << "+$fromObj+".translateX, "+$fromObj+".translateY, "+$fromObj+".translateZ >>;\n"); $expression += ("vector $to = << "+$toObj+".translateX, "+$toObj+".translateY, "+$toObj+".translateZ >>;\n"); $expression += ("vector $diffV = $to - $from;\n"); //$expression += ("float $dist = mag($diffV);\n"); $expression += ("float $ratio = id / ( count - 1 );\n"); $expression += ("$ratio = "+$group+".lightningStart + ($ratio * ("+$group+".lightningEnd - "+$group+".lightningStart));\n"); $expression += ("//\n"); $expression += ("// vector $newP = $from + $diffV * $ratio;\n"); $expression += ("//\n"); $expression += ("vector $fromDirP = << "+$fromDirection+".tx, "+$fromDirection+".ty, "+$fromDirection+".tz >>;\n"); $expression += ("vector $toDirP = << "+$toDirection+".tx, "+$toDirection+".ty, "+$toDirection+".tz >>;\n"); $expression += ("vector $fromDir = ( $fromDirP - $from ) * 5.0;\n"); $expression += ("vector $toDir = ( $to - $toDirP ) * 5.0;\n"); $expression += ("$newP = hermite($from,$to,$fromDir,$toDir,$ratio);\n"); $expression += ("// if( ( id != 0 ) && ( id != ( count - 1 ) ) )\n"); $expression += ("{\n"); $expression += ("\tfloat $spread = 0;\n"); $expression += ("\tif( $ratio < .5 )\n"); $expression += ("\t\t$spread = linstep( 0, .5, $ratio ) * " + $group + ".maxSpread;\n"); $expression += ("\telse\n"); $expression += ("\t\t$spread = ( 1.0 - linstep( .5, 1, $ratio ) ) * " + $group + ".maxSpread;\n"); $expression += ("\t$spread = $spread * ( " + $group + ".lightningEnd - " + $group + ".lightningStart );\n"); $expression += ("\t$newP += sphrand( $spread );\n"); $expression += ("}\n"); $expression += ("position = $newP;\n"); dynExpression -c -s $expression $particleShape; dynExpression -r -s $expression $particleShape; } proc addLightningPointLight( string $group ) { // Create a default point light. // defaultPointLight(1, 1,1,1, 0, 0, 0,0,0, 1); string $pointLight = getSelectedObject( 0 ); string $lightShape = getShapeFromObject( $pointLight, 0, 0 ); // connect the pointLight.translate with $group.selectHandle. // parent $pointLight $group; connectAttr -f ($group+".selectHandle") ($pointLight+".translate"); connectAttr -f ($group+".colorR") ($lightShape+".colorR"); connectAttr -f ($group+".colorG") ($lightShape+".colorG"); connectAttr -f ($group+".colorB") ($lightShape+".colorB"); // Create expression to control the light intensity with // lightning.glowIntensity. // string $lightIntensity = ($pointLight+".intensity"); string $expr = ""; $expr += ("float $start = "+$group+".lightningStart;\n"); $expr += ("float $end = "+$group+".lightningEnd;\n"); $expr += ("float $glowIntensity = "+$group+".glowIntensity;\n"); $expr += ("float $lightIntensity = "+$group+".lightIntensity;\n"); $expr += ("float $intensity = $lightIntensity * $glowIntensity;\n"); $expr += ("$glowIntensity = $intensity * (abs($end-$start));\n"); $expr += ($lightIntensity+" = $glowIntensity;\n"); expression -alwaysEvaluate false -string $expr; } proc string makeLightning ( string $name, string $fromObj, string $toObj, int $segmentCount, float $thickness, float $maxSpread, float $start, float $end, float $glowIntensity ) { string $group = makeLightningGroup( $name, $fromObj, $toObj, $segmentCount, $thickness, $maxSpread, $start, $end, $glowIntensity ); // Create the expression in particle object. // createLightningExpression( $group ); // Add a point light at the location of the lightning center. // addLightningPointLight( $group ); return( $group ); } global proc string createShader( string $group ) { string $shader = `shadingNode -asShader lambert -name LightningShader`; markObjectWithAttribute( $shader, $group, "lightningShader" ); string $shadingGroup = `sets -renderable true -noSurfaceShader true -empty -name ($shader+"SG")`; setAttr ($shader+".color") -type double3 0 0 0; setAttr ($shader+".incandescence") -type double3 .5 1 1; setAttr ($shader+".hideSource") 0; connectAttr -f ($group+".glowIntensity") ($shader+".glowIntensity"); connectAttr -f ($group+".colorR") ($shader+".incandescenceR"); connectAttr -f ($group+".colorG") ($shader+".incandescenceG"); connectAttr -f ($group+".colorB") ($shader+".incandescenceB"); connectAttr -f ($group+".colorR") ($shader+".colorR"); connectAttr -f ($group+".colorG") ($shader+".colorG"); connectAttr -f ($group+".colorB") ($shader+".colorB"); connectAttr -f ($shader+".outColor") ($shadingGroup+".surfaceShader"); return $shadingGroup; } global proc int isLightningGroup( string $object ) { if( `objExists $object` == 0 ) return 0; if( `attributeQuery -node $object -exists "_lightningGroupObject"` == 1 ) return 1; else return 0; } global proc string[] getLightningFromObject( string $group ) { string $result[]; clear( $result ); if( isLightningGroup( $group ) == 0 ) { string $fmt = (uiRes("m_lightning.kNotLightningGroup")); error( `format -s $group $fmt` ); return( $result ); } $result = getMarkedObjects( $group, "lightningFromObject" ); return( $result ); } global proc string[] getLightningFromPoint( string $group ) { string $result[]; clear( $result ); if( isLightningGroup( $group ) == 0 ) { error( `format -s $group (uiRes("m_lightning.kNotLightningGroup"))` ); return( $result ); } $result = getMarkedObjects( $group, "lightningFromPosition" ); return( $result ); } global proc string[] getLightningFromDirection( string $group ) { string $result[]; clear( $result ); if( isLightningGroup( $group ) == 0 ) { error( `format -s $group (uiRes("m_lightning.kNotLightningGroup"))` ); return( $result ); } $result = getMarkedObjects( $group, "lightningFromDirection" ); return( $result ); } global proc string[] getLightningToObject( string $group ) { string $result[]; clear( $result ); if( isLightningGroup( $group ) == 0 ) { error( `format -s $group (uiRes("m_lightning.kNotLightningGroup"))` ); return( $result ); } $result = getMarkedObjects( $group, "lightningToObject" ); return( $result ); } global proc string[] getLightningToPoint( string $group ) { string $result[]; clear( $result ); if( isLightningGroup( $group ) == 0 ) { error( `format -s $group (uiRes("m_lightning.kNotLightningGroup"))` ); return( $result ); } $result = getMarkedObjects( $group, "lightningToPosition" ); return( $result ); } global proc string[] getLightningToDirection( string $group ) { string $result[]; clear( $result ); if( isLightningGroup( $group ) == 0 ) { error( `format -s $group (uiRes("m_lightning.kNotLightningGroup"))` ); return( $result ); } $result = getMarkedObjects( $group, "lightningToDirection" ); return( $result ); } global proc string[] getLightningParticle( string $group ) { string $result[]; clear( $result ); if( isLightningGroup( $group ) == 0 ) { error( `format -s $group (uiRes("m_lightning.kNotLightningGroup"))` ); return( $result ); } $result = getMarkedObjects( $group, "lightningParticleObject" ); return( $result ); } global proc string[] getLightningSurface( string $group ) { string $result[]; clear( $result ); if( isLightningGroup( $group ) == 0 ) { error( `format -s $group (uiRes("m_lightning.kNotLightningGroup"))` ); return( $result ); } $result = getMarkedObjects( $group, "lightningSurface" ); return( $result ); } global proc string[] getLightningShader( string $group ) { string $result[]; clear( $result ); if( isLightningGroup( $group ) == 0 ) { error( `format -s $group (uiRes("m_lightning.kNotLightningGroup"))` ); return( $result ); } $result = getMarkedObjects( $group, "lightningShader" ); return( $result ); } global proc addControlAttribute ( string $node, string $attr, float $value, float $min, float $max ) { // Add attributes for lightning controls. // addAttr -ln $attr -at "float" -dv $value -min $min -max $max $node; setAttr -keyable true ($node+"."+$attr); } global proc string[] lightning ( string $name, int $grouping, int $createOption, int $segmentCount, float $thickness, float $maxSpread, float $start, float $end, float $glowIntensity ) // // Description: // // This is the main lightning procedure. It decides how to create // the lightning bolts based on the given arguments. // { string $bolts[]; clear($bolts); string $selectedList[] = getSelectedList( "transforms" ); if( size($selectedList) < 2 ) { error( (uiRes("m_lightning.kNeedTwoTransforms")) ); return $bolts; } int $from, $to; string $fromObj, $toObj, $group, $surface; string $surfaces[]; int $count = size( $selectedList ); // Option 1: create lightning in between all pairs. // if( $createOption == 1 ) { for( $from = 0; $from < ($count - 1); $from ++ ) { $fromObj = $selectedList[$from]; for( $to = ( $from + 1 ); $to < $count; $to ++ ) { $toObj = $selectedList[$to]; // Create a lightning effect from $fromObj to $toObj. // $group = makeLightning( $name, $fromObj, $toObj, $segmentCount, $thickness, $maxSpread, $start, $end, $glowIntensity ); // Add shader for the new lightning surface. // string $shader = createShader( $group ); $surfaces = getLightningSurface( $group ); sets -e -forceElement $shader $surfaces; $bolts[size($bolts)] = $group; } } } // Option 2: create lightning in between two objects "In Order" // of the selected list. else if( $createOption == 2 ) { for( $from = 0; $from < ($count - 1); $from ++ ) { $fromObj = $selectedList[$from]; $toObj = $selectedList[$from + 1]; // Create a lightning effect from $fromObj to $toObj. // $group = makeLightning( $name, $fromObj, $toObj, $segmentCount, $thickness, $maxSpread, $start, $end, $glowIntensity ); // Add shader for the new lightning surface. // string $shader = createShader( $group ); $surfaces = getLightningSurface( $group ); sets -e -forceElement $shader $surfaces; $bolts[size($bolts)] = $group; } } // Option 3: create lightning in between the first selected object // and all others from the second in the selected list. else if( $createOption == 3 ) { $fromObj = $selectedList[0]; for( $to = 1; $to < $count; $to ++ ) { $toObj = $selectedList[$to]; // Create a lightning effect from $fromObj to $toObj. // $group = makeLightning( $name, $fromObj, $toObj, $segmentCount, $thickness, $maxSpread, $start, $end, $glowIntensity ); // Add shader for the new lightning surface. // string $shader = createShader( $group ); $surfaces = getLightningSurface( $group ); sets -e -forceElement $shader $surfaces; $bolts[size($bolts)] = $group; } } if( $grouping && (size($bolts) > 1) ) { select $bolts; group; rename("LightningGroup#"); string $lightningGroup = getSelectedObject( 0 ); select $lightningGroup; } else { select $bolts; } return $bolts; }