260 lines
9.7 KiB
Plaintext
Executable File
260 lines
9.7 KiB
Plaintext
Executable File
-----------------------------------------------------------------------------------
|
|
-- Parallax Occlusion Map Curvature Masker tool
|
|
--
|
|
-- Masks out parts of selected meshes that have highly
|
|
-- convex/concave normals, as curved areas don't POM well.
|
|
--
|
|
-- James O'Hare (R* Leeds) 01/2014
|
|
-----------------------------------------------------------------------------------
|
|
|
|
try(destroyDialog RsPOMCurvatureMaskerUI)catch()
|
|
|
|
--/////////////////////////////////////////
|
|
-- UI
|
|
--/////////////////////////////////////////
|
|
rollout RsPOMCurvatureMaskerUI "POM Curvature Masker" width:300 height:150
|
|
(
|
|
--/////////////////////////////////////////
|
|
-- CONTROLS
|
|
--/////////////////////////////////////////
|
|
--dotNetControl rsBannerPanel "Panel" pos:[0,0] height:32 width:RsPOMCurvatureMaskerUI.width
|
|
--local banner = makeRsBanner dn_Panel:rsBannerPanel wiki:"POM Curvature Masker" versionNum:1.04 versionName:"Nostalgic Curtain" filename:(getThisScriptFilename())
|
|
timer ctrlState interval:5000 active:false
|
|
|
|
group "POM Curvature Masker"
|
|
(
|
|
dotnetControl btnMaskPOM "Button" text:"Apply POM Mask to Selection" height:dnStyle.stdButtonHeight --offset:[-10, 0]
|
|
)
|
|
group "Options"
|
|
(
|
|
checkbox preserveExisting "Preserve Existing Mask" align:#left offset:[0, -2]
|
|
checkbox maskMaterialSeams "Mask POM/Non-POM Material Joins" align:#left offset:[0, -2] checked:True \
|
|
Tooltip:"Add POM-scale mask (on red channel) to fade parallax effect at seams between POM/non-POM materials"
|
|
)
|
|
|
|
-- If preserveOriginal == true, then set the blend mode to additive. Otherwise overwrite entirely.
|
|
-- If maskJoins == true, then set all verts at a POM - nonPOM material boundary to white.
|
|
fn maskPOM preserveOriginal:false maskJoins:false =
|
|
(
|
|
if (tension == undefined) do
|
|
(
|
|
messageBox "Please install the 'Tension' modifier plugin to run this tool.\n\nSee wiki for details (click [i] icon on banner)" title:"Error: Plugin Missing" beep:false
|
|
return False
|
|
)
|
|
|
|
-- Collect selected Editable Poly/Mesh or PolyMeshObject objects:
|
|
local myobjs = for obj in selection where (isEditPolyMesh obj) collect obj
|
|
|
|
if (myobjs.count == 0) do
|
|
(
|
|
messageBox "No mesh objects are selected" title:"Error: Invalid Selection" beep:false
|
|
return False
|
|
)
|
|
|
|
-- Do any objects have modifiers?
|
|
local HasModifiers = False
|
|
for obj in myobjs while (not HasModifiers) do
|
|
(
|
|
HasModifiers = (obj.Modifiers.Count != 0)
|
|
)
|
|
|
|
if HasModifiers and (not queryBox "A selected object has modifiers applied.\n\nThis tool will collapse its modifier-stack, do you want to continue?" title:"Warning: Object has modifiers") do
|
|
(
|
|
return False
|
|
)
|
|
|
|
-- Channel 4 is what we're using for the POM masker. This might vary depending on the material (sometimes channel 3?) but I think it's mostly 4.
|
|
local vchannel = 4
|
|
|
|
-- Cache refs to oft-used functions.
|
|
local refGetMapVert = polyop.getMapVert
|
|
local refSetMapVert = polyop.setMapVert
|
|
local refGetFacesUsingVert = polyop.getFacesUsingVert
|
|
local refGetFaceMatID = polyop.getFaceMatID
|
|
local refGetFaceVerts = polyOp.getFaceVerts
|
|
local refGetMapFace = polyOp.getMapFace
|
|
|
|
local convscale = 1.0 -- Convex scale.
|
|
local convexp = 1.0 -- Convex exponent.
|
|
local concscale = 1.0 -- Concave scale. Plugin calls it delta.
|
|
local concexp = 1.0 -- Concave exponent.
|
|
local blurStrength = 1.0 -- Blur strength.
|
|
local blurAmount = 0 -- Blur amount - integer value.
|
|
|
|
undo "Apply POM Curvature Mask" on
|
|
(
|
|
for myobj in myobjs do
|
|
(
|
|
if (not isKindOf myobj Editable_Poly) then
|
|
(
|
|
-- The modifier works with Editable Mesh, although it's slower as it internally converts it to Editable Poly anyway.
|
|
convertToPoly(myobj)
|
|
)
|
|
else
|
|
(
|
|
collapseStack myobj
|
|
)
|
|
|
|
-- Apply Tension modifier to generate vertcolours, and collapse to bake data into model:
|
|
local tensionmodifier = tension mappingChannel:vchannel mappingChannelConvex:vchannel doExpansionGreen:on doCompressRed:on doConvex:on convexIsComparitive:off doNormalisedConvex:off deltaScale:concscale deltaExponent:concexp convexgreenscale:convscale concaveExponent:convexp convblurValue:blurStrength convexblur:blurAmount additiveComp:preserveOriginal compositeOp:1
|
|
addModifier myobj tensionmodifier
|
|
collapseStack myobj
|
|
|
|
-- Tidy away dead structs that might confuse vert/face-counts:
|
|
polyOp.collapseDeadStructs myobj
|
|
|
|
local NumMapVerts = (polyop.getNumMapVerts myobj vchannel)
|
|
local FaceCount = (polyOp.getNumFaces myobj)
|
|
|
|
-- Get materials on this shader then loop through verts and mask any that are on joins between POM and non-POM materials.
|
|
-- Checks material type for each material ID, and stores an array of true/false values for each material ID to be checked later on.
|
|
local SeamMapVerts = #{}
|
|
SeamMapVerts.Count = NumMapVerts
|
|
|
|
if maskJoins do
|
|
(
|
|
-- Get list of materials used on object, and bitarrays of the faces they're used on:
|
|
local ObjMats = #()
|
|
local MatFaces = #()
|
|
RsGetMaterialsOnObjFaces myobj materials:ObjMats faceLists:MatFaces
|
|
|
|
-- No need to mask joins if object only uses one material...
|
|
if (ObjMats.Count > 1) do
|
|
(
|
|
-- Make blank bitarrays for recording POM/non-POM faces:
|
|
local PomFaces = #{}
|
|
local NonPomFaces = #{}
|
|
PomFaces.Count = FaceCount
|
|
NonPomFaces.Count = FaceCount
|
|
|
|
-- Find out which materials have a POM shader, and take note of their faces:
|
|
for n = 1 to ObjMats.Count do
|
|
(
|
|
local ThisMat = ObjMats[n]
|
|
local ThisMatFaces = MatFaces[n]
|
|
|
|
local isPOM = False
|
|
|
|
-- Is this a POM shader?
|
|
if (isKindOf ThisMat Rage_Shader) do
|
|
(
|
|
local ShaderName = RstGetShaderName ThisMat
|
|
isPOM = (matchPattern ShaderName pattern:"*pxm*")
|
|
)
|
|
|
|
-- Add material face-list to relevant bitarray:
|
|
if isPOM then
|
|
(
|
|
PomFaces += ThisMatFaces
|
|
)
|
|
else
|
|
(
|
|
NonPomFaces += ThisMatFaces
|
|
)
|
|
)
|
|
|
|
-- If both lists are non-zero, then we have a mixture of POM/non-POM faces:
|
|
if (PomFaces.NumberSet != 0) and (NonPomFaces.NumberSet != 0) do
|
|
(
|
|
local VertCount = polyop.getNumVerts myobj
|
|
|
|
-- This will list bitarrays of map-verts corresponding to each geometry-vert:
|
|
local mapVertLookup = for n = 1 to VertCount collect #{}
|
|
|
|
-- Build geometry-to-UV vertex-lookup list, to allow us to find equivalent indexes quickly...
|
|
for FaceNum = 1 to FaceCount do
|
|
(
|
|
local GeomFaceVerts = refGetFaceVerts myobj FaceNum
|
|
local MapFaceVerts = refGetMapFace myobj vchannel FaceNum
|
|
|
|
for n = 1 to GeomFaceVerts.Count do
|
|
(
|
|
mapVertLookup[GeomFaceVerts[n]][MapFaceVerts[n]] = True
|
|
)
|
|
)
|
|
|
|
-- Find verts on border of POM/non-POM faces...
|
|
for VertNum = 1 to VertCount do
|
|
(
|
|
local FacesUsingVert = refGetFacesUsingVert myobj VertNum
|
|
|
|
-- Find union of POM-faces and this vert's faces:
|
|
local VertPomFaces = (FacesUsingVert * PomFaces)
|
|
local VertPomFaceCount = VertPomFaces.NumberSet
|
|
|
|
-- Does this vert's faces include a mixture of POM/non-POM materials?
|
|
if (VertPomFaceCount != 0) and (VertPomFaceCount != FacesUsingVert.NumberSet) do
|
|
(
|
|
-- If this is a POM-seam geometry-vert, add its map-vert(s) to the to-mask list:
|
|
SeamMapVerts += mapVertLookup[VertNum]
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
for MapVert = 1 to NumMapVerts do
|
|
(
|
|
-- Get baked-in vertex-colour, and start blank vertcolour for making reformatted version:
|
|
local VertClr = (refGetMapVert myobj vchannel MapVert)
|
|
local EditVertClr = [0,0,0]
|
|
|
|
-- The settings of the curvature map mean it's applied in 0 - 1 range from concave - convex in the blue channel, with 0.5 being "flat".
|
|
-- So I'll expand it out to -1 - 1 range and get the absolute value to force it into 0 - 1 range with 0 being "flat" and 1 being "non-flat".
|
|
-- Then create a new point3 and fill G with the curvature value and assign that back to the vertex.
|
|
EditVertClr.y = amax (amin (abs ((VertClr.z * 2) - 1)) 1) 0 -- GREEN: Curvature Mask
|
|
|
|
-- RED: POM Scale, used to fade POM effect between POM/non-POM materials (0-1:On-Off)
|
|
if maskJoins and SeamMapVerts[MapVert] do
|
|
(
|
|
EditVertClr.x = 1.0
|
|
)
|
|
|
|
-- Don't bother applying colour if it isn't changing:
|
|
if (EditVertClr != VertClr) do
|
|
(
|
|
-- Set vertex to edited colour:
|
|
refSetMapVert myobj vchannel MapVert EditVertClr
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
return true
|
|
)
|
|
|
|
|
|
--/////////////////////////////////////////
|
|
-- EVENTS
|
|
--/////////////////////////////////////////
|
|
on btnMaskPOM click do
|
|
(
|
|
dnStyle.setExecuteStyle btnMaskPOM
|
|
local success = maskPOM preserveOriginal:preserveExisting.state maskJoins:maskMaterialSeams.state
|
|
ctrlState.active = true
|
|
if success then dnStyle.setSuccessStyle btnMaskPOM else dnStyle.setErrorStyle btnMaskPOM
|
|
)
|
|
|
|
--/////////////////////////////////////////
|
|
-- Switch control state on timer trigger
|
|
--/////////////////////////////////////////
|
|
on ctrlState tick do
|
|
(
|
|
dnStyle.setDormantStyle btnMaskPOM
|
|
ctrlState.active = false
|
|
)
|
|
|
|
--/////////////////////////////////////////
|
|
-- INITIALISATION
|
|
--/////////////////////////////////////////
|
|
on RsPOMCurvatureMaskerUI open do
|
|
(
|
|
--banner.setup()
|
|
dnStyle.initButtonStyle btnMaskPOM
|
|
|
|
|
|
windows.processPostedMessages()
|
|
)
|
|
)
|
|
|
|
--createDialog RsPOMCurvatureMaskerUI |