441 lines
11 KiB
Plaintext
Executable File
441 lines
11 KiB
Plaintext
Executable File
filein (RsConfigGetWildWestDir() + "script/3dsMax/_common_functions/fn_vertexpaint.ms")
|
|
|
|
struct LightSampleStruct
|
|
(
|
|
pos,
|
|
intensity
|
|
)
|
|
|
|
struct StreetBakeDownStruct
|
|
(
|
|
someVar = undefined,
|
|
bakeSLODs = #(),
|
|
bakeChannel = -1,
|
|
sampleBomb = false,
|
|
|
|
loColCutoff = 0.5,
|
|
|
|
blend_LowThresh = 0.01,
|
|
blend_HighThresh = 0.95,
|
|
blend_DiffThresh = 0.6,
|
|
blend_Power = 5.0,
|
|
|
|
lightCloud = #(),
|
|
sampleRadius = 1.0, --m
|
|
blendGamma = 0.1,
|
|
|
|
UIHandle = undefined,
|
|
|
|
--/////////////////////////////////////////
|
|
--
|
|
--/////////////////////////////////////////
|
|
fn colourSampleFn samples =
|
|
(
|
|
local result = [0, 0, 0]
|
|
local sampCount = 0
|
|
for val in samples do
|
|
(
|
|
if (distance [0, 0, 0] val) > loColCutoff do
|
|
(
|
|
result += val
|
|
sampCount += 1
|
|
)
|
|
)
|
|
|
|
--average based on the samples used
|
|
result /= sampCount
|
|
),
|
|
|
|
--/////////////////////////////////////////
|
|
--
|
|
--/////////////////////////////////////////
|
|
fn harvestLightCloud objList:selection =
|
|
(
|
|
for obj in objList do
|
|
(
|
|
local objMesh = snapshotAsMesh obj
|
|
meshop.deleteIsoMapVertsAll objMesh
|
|
|
|
--get the vert colours
|
|
for vtx in objMesh.verts do
|
|
(
|
|
--position
|
|
local vtxPos = meshop.getVert objmesh vtx.index
|
|
|
|
--light value
|
|
meshop.getmapVert objMesh -1 vtx.index
|
|
local geoFaces = meshop.getFacesUsingVert objMesh vtx.index
|
|
|
|
local mapVerts = #()
|
|
|
|
for face = geoFaces do
|
|
(
|
|
local geoFaceVerts = (meshop.getVertsUsingFace objMesh face) as Array
|
|
local mapFaceVerts = meshop.getMapFace objMesh -1 face
|
|
--format "%\n" mapFaceVerts
|
|
|
|
--local mapVert = (for gv=1 to geoFaceVerts.count where (geoFaceVerts[gv] == vtx.index) collect mapFaceVerts[gv])[1]
|
|
local mapVert = case of
|
|
(
|
|
(geoFaceVerts[1] == vtx.index): mapFaceVerts.x
|
|
(geoFaceVerts[2] == vtx.index): mapFaceVerts.y
|
|
(geoFaceVerts[3] == vtx.index): mapFaceVerts.z
|
|
)
|
|
|
|
append mapVerts mapVert
|
|
)
|
|
|
|
--save a lightSample
|
|
local lightSample = LightSampleStruct()
|
|
lightSample.pos = vtxPos
|
|
local lightval = [0,0,0]
|
|
local skipMapVert = false
|
|
try
|
|
(
|
|
lightval = (meshop.getMapVert objMesh -1 mapVerts[1]) as Point3
|
|
format "lightVal: % \n" lightVal
|
|
)
|
|
catch
|
|
(
|
|
print "."
|
|
skipMapVert = true
|
|
)
|
|
|
|
if not skipMapVert do
|
|
(
|
|
lightSample.intensity = lightVal
|
|
append lightCloud lightSample
|
|
)
|
|
|
|
)
|
|
)
|
|
|
|
--print lightCloud.count
|
|
),
|
|
|
|
--/////////////////////////////////////////
|
|
--
|
|
--/////////////////////////////////////////
|
|
fn compareIntensity v1 v2 =
|
|
(
|
|
case of
|
|
(
|
|
((length v1) > (length v2)):-1
|
|
((length v1) < (length v2)):1
|
|
default:0
|
|
)
|
|
),
|
|
|
|
--/////////////////////////////////////////
|
|
--
|
|
--/////////////////////////////////////////
|
|
fn blendLocality objList:selection =
|
|
(
|
|
blendGamma = 1.0 / UIHandle.spnSampleGamma.value
|
|
|
|
UIHandle.prgBar.value = 1
|
|
local counter = 1
|
|
|
|
for obj in objList do
|
|
(
|
|
local objOp = RsMeshPolyOp obj
|
|
|
|
for vtx in obj.verts do
|
|
(
|
|
local vertPos = objOp.getvert obj vtx.index
|
|
local currentIntensity = [0,0,0]
|
|
|
|
local lightSamples = #()
|
|
for sample in lightCloud do
|
|
(
|
|
local dist = distance vertPos sample.pos
|
|
|
|
if dist < 0.00001 do currentIntensity = sample.intensity
|
|
if (not (dist < 0.00001)) and (not (dist > sampleRadius)) then
|
|
(
|
|
--Append the lightsample scaled by inverse square distance
|
|
append lightSamples (sample.intensity * (1.0 / (dist * dist)))
|
|
)
|
|
)
|
|
--format "lightSamples count:% \n" lightSamples.count
|
|
local sampleDiff = 0
|
|
if lightSamples.count > 0 do
|
|
(
|
|
--sort the samples
|
|
qsort lightSamples compareIntensity
|
|
|
|
--if the difference between the highest and lowest value are greater than blend_DiffThresh then average the values
|
|
sampleDiff = length(lightSamples[lightSamples.count] - lightSamples[1])
|
|
)
|
|
|
|
--blend
|
|
local lightVal = currentIntensity
|
|
local sampleCount = 0
|
|
for s=1 to lightSamples.count do
|
|
(
|
|
--print lightSamples[s]
|
|
if (lightSamples[s].x > blend_LowThresh) do
|
|
(
|
|
lightVal += [(lightSamples[s].x ^ blendGamma), (lightSamples[s].y ^ blendGamma), (lightSamples[s].z ^ blendGamma)]
|
|
sampleCount += 1
|
|
)
|
|
)
|
|
|
|
if (sampleDiff > blend_DiffThresh) do
|
|
(
|
|
lightVal /= sampleCount
|
|
)
|
|
|
|
--lightVal = lightVal / sampleCount
|
|
--Cap intensity at 1.0
|
|
if (length lightVal) > 1.73205 then lightVal = [1.0, 1.0, 1.0]
|
|
|
|
--set the colour
|
|
objOp.setVertColor obj -1 vtx.index (([lightVal.x, lightVal.x, lightVal.x] as Point4) as Color)
|
|
|
|
)
|
|
update obj
|
|
|
|
counter += 1
|
|
UIHandle.prgBar.value = (100.0 * (counter / (objList.count as float)))
|
|
)
|
|
|
|
UIHandle.prgBar.value = 0
|
|
),
|
|
|
|
--/////////////////////////////////////////
|
|
--
|
|
--/////////////////////////////////////////
|
|
fn blendUp objIn =
|
|
(
|
|
local obj = snapshotasmesh objIn
|
|
|
|
local objOp = RsMeshPolyOp objIn
|
|
|
|
local newMap = #()
|
|
|
|
for vtx in obj.verts do
|
|
(
|
|
local geoFaces = meshop.getFacesUsingVert obj vtx.index
|
|
|
|
local mapVerts = #()
|
|
|
|
for face = geoFaces do
|
|
(
|
|
local geoFaceVerts = (meshop.getVertsUsingFace obj face) as Array
|
|
local mapFaceVerts = meshop.getMapFace obj -1 face
|
|
--format "%\n" mapFaceVerts
|
|
|
|
--local mapVert = (for gv=1 to geoFaceVerts.count where (geoFaceVerts[gv] == vtx.index) collect mapFaceVerts[gv])[1]
|
|
local mapVert = case of
|
|
(
|
|
(geoFaceVerts[1] == vtx.index): mapFaceVerts.x
|
|
(geoFaceVerts[2] == vtx.index): mapFaceVerts.y
|
|
(geoFaceVerts[3] == vtx.index): mapFaceVerts.z
|
|
)
|
|
|
|
append mapVerts mapVert
|
|
)
|
|
|
|
--print mapVerts
|
|
--find the brightest coloursample and set all the
|
|
local colourSamples = #()
|
|
for mv in mapVerts do
|
|
(
|
|
appendIfUnique colourSamples (meshop.getMapVert obj -1 mv)
|
|
)
|
|
|
|
--sort them
|
|
qsort colourSamples compareIntensity
|
|
--break()
|
|
local hiColour = if(colourSamples.count != 0) then colourSamples[1] else [0,0,0] --set it to the brightest sample to begin with
|
|
/*
|
|
local sampleWeight = 0
|
|
local notFinished = true
|
|
|
|
--ignore any blacks
|
|
--weight brighter ones based on how bright they are so we drive up the intensity.
|
|
local sampleCount = 0
|
|
for sample in colourSamples while notFinished do
|
|
(
|
|
if (sample.x > blend_LowThresh) do
|
|
(
|
|
hiColour += [(sample.x ^ blend_Power), (sample.y ^ blend_Power), (sample.z ^ blend_Power)]
|
|
--hiColour += sample
|
|
sampleWeight += (1.0 - sample.x)
|
|
--weights[sampleCount] = sample.x
|
|
)
|
|
)
|
|
|
|
hiColour /= sampleWeight
|
|
if (length hiColour) > 1.73205 then hiColour = [1.0, 1.0, 1.0]
|
|
*/
|
|
newMap[vtx.index] = ([hiColour.x, hiColour.x, hiColour.x, 0]) as Color
|
|
|
|
--collect for lightCloud
|
|
--save a lightSample
|
|
local lightSample = LightSampleStruct()
|
|
lightSample.pos = objOp.getVert objIn vtx.index
|
|
lightSample.intensity = hiColour
|
|
append lightCloud lightSample
|
|
)
|
|
|
|
for vtx in objIn.verts do
|
|
(
|
|
objOp.setVertColor objIn -1 vtx.index newMap[vtx.index]
|
|
)
|
|
|
|
update objIn
|
|
),
|
|
|
|
--/////////////////////////////////////////
|
|
--
|
|
--/////////////////////////////////////////
|
|
fn bakeDown =
|
|
(
|
|
UIHandle.prgBar.value = 1
|
|
local counter = 1
|
|
for SLOD in bakeSLODs do
|
|
(
|
|
--find the target LODs
|
|
local LODS = #()
|
|
RsSceneLink.GetChildren 0 SLOD &LODS
|
|
|
|
if (LODS.count != 0) do
|
|
(
|
|
local childLOD = snapshot LODS[1]
|
|
childLOD.material = copy LODS[1].material
|
|
|
|
--Merge the LODS together into a temporary object to bake from them
|
|
if LODS.count > 1 then
|
|
(
|
|
--childLOD = snapshot LODS[1]
|
|
for l=2 to LODS.count do
|
|
(
|
|
attach childLOD (snapshotasmesh LODS[l])
|
|
)
|
|
)
|
|
|
|
--Projects the data
|
|
RsProjectFaceMap childLOD SLOD SRCchannel:bakeChannel TGTchannel:bakeChannel sampleBomb:sampleBomb bombSamples:2 --samplingFn:colourSampleFn
|
|
|
|
--blend the vert illumination values within SLOD
|
|
blendUp SLOD
|
|
|
|
--delete the childLOD temporary mesh
|
|
delete childLOD
|
|
|
|
counter += 1
|
|
UIHandle.prgBar.value = (100.0 * (counter / (bakeSLODs.count as float)))
|
|
)
|
|
)
|
|
|
|
UIHandle.prgBar.value = 0
|
|
|
|
--harvestLightCloud()
|
|
--blendLocality()
|
|
)
|
|
)
|
|
|
|
--/////////////////////////////////////////
|
|
-- UI
|
|
--/////////////////////////////////////////
|
|
try(destroyDialog StreetBakeDownUI)catch()
|
|
rollout StreetBakeDownUI "Street BakeDown" width:250 height:220
|
|
(
|
|
--/////////////////////////////////////////
|
|
-- VARIABLES
|
|
--/////////////////////////////////////////
|
|
local streetBakeDown = StreetBakeDownStruct()
|
|
|
|
|
|
--/////////////////////////////////////////
|
|
-- CONTROLS
|
|
--/////////////////////////////////////////
|
|
dotNetControl rsBannerPanel "Panel" pos:[0,0] height:32 width:StreetBakeDownUI.width
|
|
local banner = makeRsBanner dn_Panel:rsBannerPanel wiki:"CHANGEME" filename:(getThisScriptFilename()) versionNum:1.0 versionName:"Luxurient Burn"
|
|
|
|
group "Samples"
|
|
(
|
|
checkbox chkSampleBomb "SampleBomb" across:2
|
|
spinner spnSamples "Samples:" range:[1, 10, 2] type:#integer
|
|
)
|
|
|
|
group ""
|
|
(
|
|
button btnBake "BakeDown" width:(StreetBakeDownUI.width - 20) offset:[0, -8]
|
|
progressBar prgBar
|
|
)
|
|
|
|
group "Locality Blend"
|
|
(
|
|
spinner spnSampleRad "Sample Radius" range:[1.0, 25.0, 5.0] type:#float offset:[10,0] across:2
|
|
spinner spnSampleGamma "Gamma" range:[0.1, 4.0, 1.0] type:#float
|
|
button btnBlendLocal "Blend" width:(StreetBakeDownUI.width - 20)
|
|
)
|
|
|
|
--/////////////////////////////////////////
|
|
-- FUNCTIONS
|
|
--/////////////////////////////////////////
|
|
|
|
|
|
--/////////////////////////////////////////
|
|
-- EVENTS
|
|
--/////////////////////////////////////////
|
|
|
|
on spnSampleGamma changed val do
|
|
(
|
|
streetBakeDown.blendGamma = val
|
|
)
|
|
|
|
--/////////////////////////////////////////
|
|
--
|
|
--/////////////////////////////////////////
|
|
on spnSampleRad changed val do
|
|
(
|
|
streetBakeDown.sampleRadius = val
|
|
)
|
|
|
|
--/////////////////////////////////////////
|
|
--
|
|
--/////////////////////////////////////////
|
|
on btnBlendLocal pressed do
|
|
(
|
|
streetBakeDown.blendLocality()
|
|
)
|
|
|
|
--/////////////////////////////////////////
|
|
--
|
|
--/////////////////////////////////////////
|
|
on chkSampleBomb changed state do
|
|
(
|
|
streetBakeDown.sampleBomb = state
|
|
)
|
|
|
|
--/////////////////////////////////////////
|
|
--
|
|
--/////////////////////////////////////////
|
|
on btnBake pressed do
|
|
(
|
|
--check selection is valid
|
|
if selection.count == 0 do
|
|
(
|
|
messagebox "Nothing selected for baking" title:"No Selection"
|
|
return false
|
|
)
|
|
|
|
streetBakeDown.bakeSLODs = selection
|
|
streetBakeDown.bakeDown()
|
|
)
|
|
|
|
--/////////////////////////////////////////
|
|
--
|
|
--/////////////////////////////////////////
|
|
on StreetBakeDownUI open do
|
|
(
|
|
banner.setup()
|
|
streetBakeDown.UIHandle = StreetBakeDownUI
|
|
)
|
|
)
|
|
createDialog StreetBakeDownUI
|