glTF Timeline Markers extension and Blender add-on
Blender includes Timeline markers which are quite useful in animations. By default, when exporting a glTF file, these markers are not included in the output. This extension adds support for exporting these markers along with the scene object.
Another useful feature is to map cameras to the markers. This is useful when the camera is animated and the markers are used to switch between different camera views. The extension also saves the mapping with any camera objects in the scene to the timeline markers.
Extension Name - WEBGI_animation_markers
Data format -
type MarkerData = {
name: string,
frame: number,
time: number, // frame/fps
camera?: string
}
The data is added to scene - scene.extensions.WEBGI_animation_markers
as {"markers": MarkerData[]}
and exported in the glTF file.
Download from github - https://github.com/repalash/blender_gltf_timeline_markers_addon
three.js extension to import in GLTFLoader
class GLTFTimelineMarkersExtension implements GLTFLoaderPlugin {
public name: string
public parser: GLTFParser
constructor(parser:GLTFParser) {
this.parser = parser
this.name = 'WEBGI_animation_markers'
}
async afterRoot(result: GLTF) {
const markers: any[] = []
for (const jScene of this.parser.json.scenes) {
if (!jScene.extensions) continue
const params = jScene.extensions[this.name]
for (const marker of params?.markers || []) {
const camera = marker.camera !== undefined ? await this.parser.getDependency('camera', marker.camera) : undefined
markers.push({
name: marker.name,
frame: marker.frame,
camera,
})
}
}
if (markers.length < 1) return
const scene = result.scene ?? result.scenes[0]
if (!scene) return
scene.userData.markers = markers
const fps = 30
const times = markers.map(m=>m.frame / fps)
let i = 0
const values = markers.map(m=>i++)
const duration = Math.max(...times) + 0.01
let temp = -1
const trackName = '.currentTimelineMarker'
Object.defineProperty(scene, 'currentTimelineMarker', {
get: ()=>temp,
set: (v: any)=> scene.dispatchEvent({type: 'animationTimelineMarker', marker: markers[temp = v]}),
})
const track = new NumberKeyframeTrack(trackName, times, values, InterpolateDiscrete)
const anim = new AnimationClip('animationTimelineMarker', duration, [track])
result.animations.push(anim)
}
}
gltfLoader.register((p)=>new GLTFTimelineMarkersExtension(p))
This creates and AnimationClip
(and adds to the scene), which dispatches an event of type animationTimelineMarker
on the scene object when the current marker changes. This can be used to switch cameras or any other action based on the timeline markers.