// =========================================================================== // 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. // =========================================================================== // // // Creation Date: March 13, 2001 // Modified: April 6, 2001 // Creator: Tom Kluyskens tkluyskens@alias.com // // // Procedure Name: // cpvTexture // // Description : // Creates a layered texture or a surface shader for the selected surfaces. // The texture or shader contains color per vertex info. // It allows software rendering of color per vertex. // // Input Value: // none // // Output Value: // None // global proc createCPVtextures(int $undo , int $noHistory , int $deleteUnused , int $cpvTrsp , int $cpvPS2 , string $cpvShader , string $channel) { if ($channel == "cpvInc") { $channel = "incandescence"; } else { $channel = "ambientColor"; } $cpvTrsp = 1-$cpvTrsp; // delete unused shading nodes (speeds up things in case there's dangling UVchooser nodes) if ($deleteUnused) MLdeleteUnused; // Disable undo queue for reducing memory usage. // Applying script to big meshes rapidly fills memory with undo information. if ($undo) undoInfo -state off; // create cpv texture for selected meshes $meshes = `ls -sl`; // get shape nodes (selection is very probably transforms only) $meshes = `listRelatives -s $meshes`; $meshes = `ls -typ mesh $meshes`; // create a layered texture per selected mesh string $colorMesh = ""; for ($colorMesh in $meshes) { // delete history on selected surface if ($noHistory) delete -ch $colorMesh; string $creationMsg = `format -s $colorMesh (uiRes("m_cpvTexture.kCreatingVertexColors"))`; print ("\n\n" + $creationMsg); text -e -l ($creationMsg) cpvTxt; // store current UV set for reset at end of the script $currentSet = `polyUVSet -q -currentUVSet $colorMesh`; // gather info about the mesh int $numVtx[] = `polyEvaluate -v $colorMesh`; int $numFcs[] = `polyEvaluate -f $colorMesh`; $numFcs[0] -=1; string $allFcs = $colorMesh + ".f[0:" + $numFcs[0] + "]"; // get the exact attribute indices for the RG and BA UVsets string $allSets[] = `polyUVSet -q -allUVSets $colorMesh`; int $RGsetIndex = $BAsetIndex = -1; for ($i = 0 ; $i < size($allSets) ; $i++) { if ($allSets[$i] == "RG") $RGsetIndex = $i; if ($allSets[$i] == "BA") $BAsetIndex = $i; } // create the RG (red green) UV set on this mesh if it does not exist yet if ($RGsetIndex < 0) { polyUVSet -create -uvSet "RG" $colorMesh; // make sure there's actual UVs by doing a UV projection polyProjection -type planar -ibd 1 -md x -uvSetName "RG" $allFcs; $allSets = `polyUVSet -q -allUVSets $colorMesh`; $RGsetIndex = size($allSets) - 1; } // same for BA (blue alpha) if ($BAsetIndex < 0) { polyUVSet -create -uvSet "BA" $colorMesh; polyProjection -type planar -ibd 1 -md x -uvSetName "BA" $allFcs; $allSets = `polyUVSet -q -allUVSets $colorMesh`; $BAsetIndex = size($allSets) - 1; } // set RA to be the current UV set polyUVSet -currentUVSet -uvSet "RG" $colorMesh; if ($noHistory) delete -ch $colorMesh; for ($i = 0 ; $i < $numVtx[0] ; $i++) { // for all vertices, copy the red and green color per vertex into the U and V values of the RG UV set if (fmod($i-1,100) == 0) { string $copyRGMsg = `format -s $i -s $numVtx[0] (uiRes("m_cpvTexture.kCopyingRG"))`; print ("\n " + $copyRGMsg); text -e -l $copyRGMsg cpvTxt; } float $RG[] = `polyColorPerVertex -q -r -g ($colorMesh + ".vtx[" + $i + "]")`; // rescale colors for PS2 if ($cpvPS2) { if ($RG[0] > .5) $RG[0] = 3*$RG[0]-1; if ($RG[1] > .5) $RG[1] = 3*$RG[1]-1; } polyEditUV -r 0 -u $RG[0] -v $RG[1] `polyListComponentConversion -fv -tuv ($colorMesh + ".vtx[" + $i + "]")`; } // same, for blue and alpha polyUVSet -currentUVSet -uvSet "BA" $colorMesh; if ($noHistory) delete -ch $colorMesh; for ($i = 0 ; $i < (float)$numVtx[0] ; $i++) { if (fmod($i-1,100) == 0) { string $copyBAMsg = `format -s $i -s $numVtx[0] (uiRes("m_cpvTexture.kCopyingBA"))`; print ("\n " + $copyBAMsg); text -e -l ($copyBAMsg) cpvTxt; } float $BA[] = `polyColorPerVertex -q -b -a ($colorMesh + ".vtx[" + $i + "]")`; // rescale colors for PS2 if ($cpvPS2) if ($BA[0] > .5) $BA[0] = 3*$BA[0]-1; // revert the alpha into transparency for use with a surface shader if ($cpvTrsp) if ($cpvShader == "cpvNew") $BA[1] = 1 - $BA[1]; polyEditUV -r 0 -u $BA[0] -v $BA[1] `polyListComponentConversion -fv -tuv ($colorMesh + ".vtx[" + $i + "]")`; } // create and connect UVchooser nodes if they don't exists yet string $RGch = $colorMesh + "RGchooser"; string $BAch = $colorMesh + "BAchooser"; if (!`objExists $RGch`) $RGch = `createNode uvChooser -n ($colorMesh + "RGchooser")`; if (!`objExists $BAch`) $BAch = `createNode uvChooser -n ($colorMesh + "BAchooser")`; connectAttr -f ($colorMesh + ".uvSet[" + $BAsetIndex + "].uvSetName") ($RGch + ".uvSets[0]"); // to avoid 'already connected' error connectAttr -f ($colorMesh + ".uvSet[" + $RGsetIndex + "].uvSetName") ($BAch + ".uvSets[0]"); // to avoid 'already connected' error connectAttr -f ($colorMesh + ".uvSet[" + $RGsetIndex + "].uvSetName") ($RGch + ".uvSets[0]"); connectAttr -f ($colorMesh + ".uvSet[" + $BAsetIndex + "].uvSetName") ($BAch + ".uvSets[0]"); if ($cpvShader == "cpvNew") { // create 1 CPV surface shader per mesh // following network structure is being built : // mesh -> UVchooser -> placement2d -> surface shader // create and assign a surface shader string $cpvSS = $colorMesh + "CPVshader"; string $cpvSG = $cpvSS + "SG"; if (!`objExists $cpvSS`) { $cpvSS = `shadingNode -asShader surfaceShader`; $cpvSS = `rename $cpvSS ($colorMesh + "CPVshader")`; } if (!`objExists $cpvSG`) { $cpvSG = `sets -renderable true -noSurfaceShader true -empty -name ($cpvSS + "SG")`; connectAttr -f ($cpvSS + ".outColor") ($cpvSG + ".surfaceShader"); } select -r $colorMesh; sets -e -forceElement $cpvSG; // create two placements (necessary to translate UVs into actual RG and BA color values) string $RGpl = $cpvSS + "RGplacement"; string $BApl = $cpvSS + "BAplacement"; if (!`objExists $RGpl`) $RGpl = `createNode place2dTexture -n ($cpvSS + "RGplacement")`; if (!`objExists $BApl`) $BApl = `createNode place2dTexture -n ($cpvSS + "BAplacement")`; // connect the UVchoosers to the placements connectAttr -f ($BAch + ".outUv") ($RGpl + ".uvCoord"); // to avoid 'already connected' error connectAttr -f ($RGch + ".outUv") ($BApl + ".uvCoord"); // to avoid 'already connected' error connectAttr -f ($RGch + ".outUv") ($RGpl + ".uvCoord"); connectAttr -f ($BAch + ".outUv") ($BApl + ".uvCoord"); // connect the placements to the surface shader connectAttr -f ($RGpl + ".outV") ($cpvSS + ".outColorR"); // to avoid 'already connected' error connectAttr -f ($RGpl + ".outU") ($cpvSS + ".outColorG"); // to avoid 'already connected' error connectAttr -f ($BApl + ".outV") ($cpvSS + ".outColorB"); // to avoid 'already connected' error connectAttr -f ($BApl + ".outU") ($cpvSS + ".outTransparencyR"); // to avoid 'already connected' error connectAttr -f ($BApl + ".outU") ($cpvSS + ".outTransparencyG"); // to avoid 'already connected' error connectAttr -f ($BApl + ".outU") ($cpvSS + ".outTransparencyB"); // to avoid 'already connected' error connectAttr -f ($RGpl + ".outU") ($cpvSS + ".outColorR"); connectAttr -f ($RGpl + ".outV") ($cpvSS + ".outColorG"); connectAttr -f ($BApl + ".outU") ($cpvSS + ".outColorB"); if ($cpvTrsp) { connectAttr -f ($BApl + ".outV") ($cpvSS + ".outTransparencyR"); connectAttr -f ($BApl + ".outV") ($cpvSS + ".outTransparencyG"); connectAttr -f ($BApl + ".outV") ($cpvSS + ".outTransparencyB"); } else { disconnectAttr ($BApl + ".outU") ($cpvSS + ".outTransparencyR"); disconnectAttr ($BApl + ".outU") ($cpvSS + ".outTransparencyG"); disconnectAttr ($BApl + ".outU") ($cpvSS + ".outTransparencyB"); setAttr ($cpvSS + ".outTransparencyR") 0; setAttr ($cpvSS + ".outTransparencyG") 0; setAttr ($cpvSS + ".outTransparencyB") 0; } print (`format -s $cpvSS -s $colorMesh (uiRes("m_cpvTexture.kCreatedCPVShader"))` ); } else { // keep existing shaders // following network structure is being built : // mesh -> UVchooser -> doubleSwitch -> placement2d -> layered texture -> material // cycle through all materials assigned to this mesh for ($mat in `getAssignedMaterials ($colorMesh)`) { // create and assign 1 CPV layered texture per shader string $rgbaLT = $mat + "cpvTexture"; if (!`objExists $rgbaLT`) $rgbaLT = `createNode layeredTexture -n ($mat + "cpvTexture")`; // create two placements per shader (necessary to translate UVs into actual RG and BA color values) string $RGpl = $mat + "RGplacement"; string $BApl = $mat + "BAplacement"; if (!`objExists $RGpl`) $RGpl = `createNode place2dTexture -n ($mat + "RGplacement")`; if (!`objExists $BApl`) $BApl = `createNode place2dTexture -n ($mat + "BAplacement")`; // create two switch nodes per shader (so we can use the same layered texture for different incoming UVchooser nodes) string $RGsw = $mat + "RGswitch"; string $BAsw = $mat + "BAswitch"; if (!`objExists $RGsw`) { $RGsw = `createNode doubleShadingSwitch -n ($mat + "RGswitch")`; addAttr -k 1 -ln counter -at short -dv 0 $RGsw; } if (!`objExists $BAsw`) { $BAsw = `createNode doubleShadingSwitch -n ($mat + "BAswitch")`; addAttr -k 1 -ln counter -at short -dv 0 $BAsw; } // this counter attribute helps us to track the number of connections to both switches $cpvCounter = `getAttr ($RGsw + ".counter")`; // check if the mesh is already connected to the switch nodes int $cpvConnect = -1; for ($i = 0 ; $i < $cpvCounter ; $i++) { $cpvListConn = `listConnections -p 1 -c 1 ($RGsw + ".input[" + $i + "].inShape")`; if ($cpvListConn[1] == ($colorMesh + ".instObjGroups")) $cpvConnect = $i; } // connect the mesh and the UVchoosers to the switches if they're not already connected if ($cpvConnect == -1) { connectAttr -f ($colorMesh + ".instObjGroups[0]") ($RGsw + ".input[" + $cpvCounter + "].inShape"); connectAttr -f ($colorMesh + ".instObjGroups[0]") ($BAsw + ".input[" + $cpvCounter + "].inShape"); connectAttr -f ($RGch + ".outUv") ($RGsw + ".input[" + $cpvCounter + "].inDouble"); connectAttr -f ($BAch + ".outUv") ($BAsw + ".input[" + $cpvCounter + "].inDouble"); setAttr ($RGsw + ".counter") ($cpvCounter + 1); } // connect the UVchoosers to the placements connectAttr -f ($BAsw + ".output") ($RGpl + ".uvCoord"); // to avoid 'already connected' error connectAttr -f ($RGsw + ".output") ($BApl + ".uvCoord"); // to avoid 'already connected' error connectAttr -f ($RGsw + ".output") ($RGpl + ".uvCoord"); connectAttr -f ($BAsw + ".output") ($BApl + ".uvCoord"); // break existing connections of layered texture with shaders $cpvConnections = `listConnections -s 0 -d 1 -p 1 $rgbaLT`; for ($i = 0 ; $i < size($cpvConnections) ; $i++) disconnectAttr ($rgbaLT + ".outColor") $cpvConnections[$i]; // make connections between layered texture and material connectAttr -f ($RGpl + ".outV") ($rgbaLT + ".inputs[0].colorR"); // to avoid 'already connected' error connectAttr -f ($RGpl + ".outU") ($rgbaLT + ".inputs[0].colorG"); // to avoid 'already connected' error connectAttr -f ($BApl + ".outV") ($rgbaLT + ".inputs[0].colorB"); // to avoid 'already connected' error connectAttr -f ($BApl + ".outU") ($rgbaLT + ".inputs[0].alpha"); // to avoid 'already connected' error connectAttr -f ($RGpl + ".outU") ($rgbaLT + ".inputs[0].colorR"); connectAttr -f ($RGpl + ".outV") ($rgbaLT + ".inputs[0].colorG"); connectAttr -f ($BApl + ".outU") ($rgbaLT + ".inputs[0].colorB"); if ($cpvTrsp) { connectAttr -f ($BApl + ".outV") ($rgbaLT + ".inputs[0].alpha"); } else { disconnectAttr ($BApl + ".outU") ($rgbaLT + ".inputs[0].alpha"); setAttr ($rgbaLT + ".inputs[0].alpha") 1; } print (`format -s $rgbaLT (uiRes("m_cpvTexture.kCreatedLayeredTexture"))` ); if (`attributeQuery -ex -n $mat $channel`) { connectAttr -f ($rgbaLT + ".outColor") ($mat + "." + $channel); } else { print (`format -s $channel -s $mat -s $rgbaLT (uiRes("m_cpvTexture.kWarningNoChannel"))` ); } } } // reset the original UVset on this mesh polyUVSet -currentUVSet -uvSet $currentSet $colorMesh; // delete history on selected surface if ($noHistory) delete -ch $colorMesh; } print ((uiRes("m_cpvTexture.kVertexColorCopyingFinished")) ); // delete unused shading nodes if ($deleteUnused) MLdeleteUnused; // put undo queue back on if ($undo) undoInfo -state on; } global proc string[] getAssignedMaterials(string $mesh) { // gets all the materials assigned to this mesh string $retval[]; clear $retval; string $plugs[] = `listConnections -s false -d true $mesh`; // Look for a connected shading engine - this is // the jumping off point to get to the rendering nodes // from a selected surface for( $plug in $plugs ) { if ( `nodeType $plug` == "shadingEngine" ) { // Get the shading engine that's connected to this // mesh node, and get the material connected to it string $tmp[] = `listConnections ( $plug + ".surfaceShader" )`; if( $tmp[0] != "" ) $retval[size($retval)] = $tmp[0]; } } $retval = AWRemoveDuplicateStringsFromStringArray ($retval); return $retval; } global proc cpvTexture() { // create interface if (`window -exists "cpvWindow"`) deleteUI -window "cpvWindow"; window -wh 300 325 -s 0 -t " CPV Texture - by Tom Kluyskens" "cpvWindow"; frameLayout -lv 0; columnLayout -co "both" 10 -adj 1; text -l " "; // disable undo for less memory usage - default OFF checkBox -l "Disable Undo (requires less memory)" -v 0 -onc "text -e -l \"CAUTION : flushes entire undo queue!\" cpvTxt;" cpvUndo; // delete history on the meshes (faster, less clutter) - default OFF checkBox -l "Delete History on Mesh (faster)" -v 0 -onc "text -e -l \"CAUTION : deleting history destroys skinning!\" cpvTxt;" cpvHist; // delete unused shading nodes (UVchoosers of previous script execution for example) - default OFF checkBox -l "Delete Unused Shading Nodes" -v 0 -onc "text -e -l \"CAUTION : deletes all unassigned shading nodes!\" cpvTxt;" cpvUnus; text -l " "; // automatically connect layered texture to incandescence of all assigned shaders (default) // or create a surface shader for every selected mesh radioCollection cpvShaders; radioButton -l "Create and Assign New CPV Shader" -onc "columnLayout -e -vis 0 cpvDimmer ; text -e -l \"CAUTION : unassigns all existing shaders!\" cpvTxt;" cpvNew; radioButton -l "Auto-connect Vertex Color to Existing Shader" -sl -onc "columnLayout -e -vis 1 cpvDimmer" cpvConnect; columnLayout -cal left -co left 50 cpvDimmer; radioCollection cpvChannel; radioButton -sl -l "to Incandescence" cpvInc; radioButton -l "to Ambient" cpvAmb; setParent ..; text -l " "; // no transparency calculation - default OFF checkBox -l "No Transparency" -v 0 cpvTrsp; // preview PS2 color values - default OFF checkBox -l "Simulate PS2 Color Values" -v 0 cpvPS2; text -l " "; $btnCmd = "button -e -l \"wait ...\" cpvBtn ; createCPVtextures `checkBox -q -v cpvUndo` `checkBox -q -v cpvHist` `checkBox -q -v cpvUnus` `checkBox -q -v cpvTrsp` `checkBox -q -v cpvPS2` `radioCollection -q -sl cpvShaders` `radioCollection -q -sl cpvChannel`; deleteUI -window \"cpvWindow\";"; button -l "Create Texture" -c $btnCmd cpvBtn; text -l " "; text -l " " cpvTxt; showWindow "cpvWindow"; }