How can I make this update between frames on render?
I'm working on something to improve working with lights in Max. The sample below is a simplified version of a small part of what I'm doing, but it illustrates the issue I'm having. Basically, this script should allow a light's shadow type to be animated. It works while scrubbing the slider, but not while rendering multiple frames at a time. What is it I'm doing wrong?
-- Function to set a light's shadow type fn setShadowType lit t = ( local sg = &lit.shadowGenerator case t of ( 1: if classOf (*sg) != Adv__Ray_Traced do (*sg) = Adv__Ray_Traced() 2: if classOf (*sg) != mental_ray_Shadow_Map do (*sg) = mental_ray_Shadow_Map() 3: if classOf (*sg) != Area_Shadows do (*sg) = Area_Shadows() 4: if classOf (*sg) != ShadowMap do (*sg) = ShadowMap() 5: if classOf (*sg) != RayTraceShadow do (*sg) = RayTraceShadow() default: () ) ) -- Function called by ddl_ShadowType handler fn h_ddl_ShadowType ctrl = ( local h = ctrl.modifiers[#holder] setShadowType h.lit h.shadowType ) -- Custom attributes for control object ca_ShadowControl = attributes "shadowControl" ( parameters params rollout:RO ( lit type:#maxObject shadowType type:#integer ui:ddl_ShadowType animatable:true default:1 ) rollout RO "Shadow Control" ( local ctrl dropDownList ddl_ShadowType "Shadow Type" \ items:#("Adv. Ray Traced", "mental ray Shadow Map", "Area Shadows", "Shadow Map", "Ray Traced Shadows") on RO open do ( animButtonState = true ctrl = (refs.dependentNodes (custAttributes.getOwner this))[1] ) on ddl_ShadowType selected s do h_ddl_ShadowType ctrl ) ) -- Set up callbacks ------------------- unregisterTimeCallback updateShadows callbacks.removeScripts id:#shadowControl fn updateShadows = ( format "fn updateShadows\n" format " currentTime: %\n" currentTime local ctrl for o in objects where (o.modifiers[#holder] != undefined) do ctrl = o local h = ctrl.modifiers[#holder] local lit = refs.dependentNodes h.lit firstOnly:true local sg = &lit.shadowGenerator case h.shadowType of ( 1: if classOf (*sg) != Adv__Ray_Traced do (*sg) = Adv__Ray_Traced() 2: if classOf (*sg) != mental_ray_Shadow_Map do (*sg) = mental_ray_Shadow_Map() 3: if classOf (*sg) != Area_Shadows do (*sg) = Area_Shadows() 4: if classOf (*sg) != ShadowMap do (*sg) = ShadowMap() 5: if classOf (*sg) != RayTraceShadow do (*sg) = RayTraceShadow() ) format " classOf lit.shadowGenerator: %\n" (classOf lit.shadowGenerator) ) registerTimeCallback updateShadows callbacks.addScript #preRenderEval "updateShadows()" id:#shadowControl -- Set up test scene ( delete objects p = plane pos:[0,0,0] length:200 width:200 s = sphere pos:[37.5,25,50] lit = freeSpot pos:[0,0,200] castShadows:on ctrl = point pos:[0,0,0] size:100 box:on cross:off holder = emptyModifier name:"holder" custAttributes.add holder ca_ShadowControl #unique addModifier ctrl holder holder.lit = lit with animate on for k = 0 to 4 do at time k ( -- General Parameters: (Shadow Types) ctrl.modifiers[#holder].shadowType = k + 1 h_ddl_ShadowType ctrl ) )
Comments
Another scripter
Another scripter (PolyTools3D) helped me out on a previous project, and I thought I might be able to apply what I learned from there to this script.
My idea is that maybe I can create an array of temporary lights, each with its own shadow generator, just prior to rendering, and delete them afterward. When I run the following it works as expected, but it requires the associated function to be run by the user manually. My attempts to incorporate calling the functions directly through the callbacks result in the created script controller executing improperly.
Can anyone take a look at this and see if there is a way to fix that?
I've edited the script to
I've edited the script to output every time the setShadowType function runs, along with the current time and the resulting shadow generator of the light.
As it renders, it displays the following in the listener:
fn updateShadows
currentTime: 0f
classOf lit.shadowGenerator: Adv__Ray_Traced
fn updateShadows
currentTime: 1f
classOf lit.shadowGenerator: mental_ray_Shadow_Map
fn updateShadows
currentTime: 2f
classOf lit.shadowGenerator: Area_Shadows
fn updateShadows
currentTime: 3f
classOf lit.shadowGenerator: shadowMap
fn updateShadows
currentTime: 4f
classOf lit.shadowGenerator: raytraceShadow
So the function is clearly being called, but for whatever reason the resulting changes are being ignored by the renderer. Hopefully this can help someone figure out what the problem is?