Files
gtav-src/tools_ng/wildwest/script/3dsMax/Lighting/StreetBakeDown.ms
T
2025-09-29 00:52:08 +02:00

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