Search code examples
3dsmaxmaxscript

Get all animated frames in the interval effectively


I am writing an animation export script for my scene and I need to detect only those frames where animations keys for some objects in the scene appears. I need to export only a part (time interval) of all animation.

Currently I am using the follow code

keys = #()
for o in objects do
(
    join keys o.position.controller.keys
    join keys o.rotation.controller.keys
    join keys o.scale.controller.keys
)

to collect all keys for all objects, and then

timeValues = (for k in keys where k.time >= animationRange.start and k.time <= animationRange.end collect k.time) as array
timeValues = makeUniqueArray timeValues

to select time interval and drop duplications.

But the problem is, that my scene contains about 3000 frames in total with a lot of different animated objects with position, rotation and scale keys. So keys are duplicated many times in my collection "keys" - there are about 1,000,000 keys in total.

I need to select keys in a small time interval (about 50 frames), but as the collection is very big it tooks long (about a minute) to select desired keys and drop duplications.

Is there a way to get all frames with animation keys in the specified time interval more effectively?


Solution

  • As the frame count doesn't often go to the millions, using a bitarray should be both faster and more memory efficient. The trade-off is that it can only store values equal to one or greater - if the keys start at frame zero, store their time + 1; for negative keys, adjust the offset accordingly.

    frames = #{}
    
    for o in objects do
    (
        for key in o.position.controller.keys do append frames key.time
        for key in o.rotation.controller.keys do append frames key.time
        for key in o.scale.controller.keys do append frames key.time
    )
    
    frames.count = animationRange.end
    frames