-- Morph targets: the Khronos AnimatedMorphCube. Left, its own animation blending the two -- targets; right, the same model with weights set from the script. local font = fontLoad("Singe/FreeSansBold.ttf", 28) local frames = 0 fontSelect(font) discPlay() sceneEnable(true) sceneSetBackground(18, 18, 30, 255) sceneSetAmbient(70, 70, 85) local cubeModel = modelLoad("testScripts/Models/AnimatedMorphCube.glb") local animated = modelInstance(cubeModel) nodeSetPosition(animated, -1.6, 0, 0) nodeSetScale(animated, 0.9) animationPlay(animated, 1, true) local scripted = modelInstance(cubeModel) nodeSetPosition(scripted, 1.6, 0, 0) nodeSetScale(scripted, 0.9) local meshNode = nodeGetChildren(scripted)[1] local names = nodeGetMorphs(meshNode) debugPrint("morph targets: " .. #names) local sun = lightNew(LIGHT_DIRECTIONAL) nodeSetPosition(sun, -3, 5, 4) nodeLookAt(sun, 0, 0, 0) lightSetIntensity(sun, 1.3) local camera = nodeNew() nodeSetPosition(camera, 0, 2.2, 6) nodeLookAt(camera, 0, 0, 0) cameraSet(camera) function onOverlayUpdate() frames = frames + 1 -- The scripted cube sweeps target 1 up while target 2 comes down. local t = (frames % 120) / 120 nodeSetMorph(meshNode, 1, t) nodeSetMorph(meshNode, 2, 1 - t) nodeRotate(animated, 0, 0.8, 0) nodeRotate(scripted, 0, -0.8, 0) overlayClear() fontPrint(20, 20, string.format("Morph targets, frame %d scripted: %.2f / %.2f", frames, nodeGetMorph(meshNode, 1), nodeGetMorph(meshNode, 2))) if frames == 20 or frames == 80 or frames == 140 then singeScreenshot() end if frames == 150 then singeQuit() end end