Introduction In this chapter we'll talk about the first type of animations V-Ray can render - these with moving (animated) objects. Generally V-Ray is able to animate all numeric/color values of plugin properties. This means that we'll consider "animation" every plugin property which value is changing over time.
Parameters Generally we need to set some values in the SettingsOutput plugin to have animated properties inside the scene. Here's an example excerpt from a .vrscene file with animated values:
<code><span class="line"><span>SettingsOutput {</span></span> <span class="line"><span> img_width=400;</span></span> <span class="line"><span> img_height=400;</span></span> <span class="line"><span> anim_start=1;</span></span> <span class="line"><span> anim_end=10;</span></span> <span class="line"><span> anim_frame_padding=4;</span></span> <span class="line"><span> anim_renumber_on=0;</span></span> <span class="line"><span> anim_renumber_start=0;</span></span> <span class="line"><span> anim_renumber_step=1;</span></span> <span class="line"><span> anim_ren_frame_start=0;</span></span> <span class="line"><span> frame_start=1;</span></span> <span class="line"><span> frames_per_second=1;</span></span> <span class="line"><span> frames=List(</span></span> <span class="line"><span> List(1, 10)</span></span> <span class="line"><span> );</span></span> <span class="line"><span>}</span></span></code>
Here are the animation related parameters explained:
anim_start - Start of animation range in time units anim_end - End of animation range in time units anim_frame_padding - Animation Frame Name Padding anim_renumber_on - If true, frame renumbering is used anim_renumber_start - Start number for renumber frames anim_renumber_step - Renumber frames step anim_ren_frame_start - First frame of animation range frame_start - The frame number at the start of the animation range frames_per_second - Number of frames per unit time (related to SettingsUnitsInfo::seconds_scale) frames - List of frames to be rendered. May contain intervals in the form of lists with start and end frame Example The above animation is generated by rendering the file "Animated_Object&Camera.vrscene" from the scene bundle . Check the comments inside the file and the included ones to see how GI can be used more optimally in an animation.
Code Example Here we'll show how to render a static scene and animate one of the object's positions:
Python <code data-v-c2b1f83f=""><span data-v-c2b1f83f="" class="line"># Compatibility with Python 2.7.</span><span data-v-c2b1f83f="" class="line">from __future__ import print_function</span><span data-v-c2b1f83f="" class="line"></span><span data-v-c2b1f83f="" class="line"># The directory containing the vray shared object should be present in the PYTHONPATH environment variable.</span><span data-v-c2b1f83f="" class="line"># Try to import the vray module from VRAY_SDK/python, if it is not in PYTHONPATH</span><span data-v-c2b1f83f="" class="line">import sys, os</span><span data-v-c2b1f83f="" class="line">VRAY_SDK = os.environ.get('VRAY_SDK')</span><span data-v-c2b1f83f="" class="line">if VRAY_SDK:</span><span data-v-c2b1f83f="" class="line"> sys.path.append(os.path.join(VRAY_SDK, 'python'))</span><span data-v-c2b1f83f="" class="line">import vray</span><span data-v-c2b1f83f="" class="line"></span><span data-v-c2b1f83f="" class="line">SCENE_PATH = os.path.join(os.environ.get('VRAY_SDK'), 'scenes')</span><span data-v-c2b1f83f="" class="line"># Change process working directory to SCENE_PATH in order to be able to load relative scene resources.</span><span data-v-c2b1f83f="" class="line">os.chdir(SCENE_PATH)</span><span data-v-c2b1f83f="" class="line"></span><span data-v-c2b1f83f="" class="line">def onStateChanged(renderer, oldState, newState, instant):</span><span data-v-c2b1f83f="" class="line"> if newState == vray.RENDERER_STATE_IDLE_FRAME_DONE or newState == vray.RENDERER_STATE_IDLE_DONE:</span><span data-v-c2b1f83f="" class="line"> print('Image Ready, frame ' + str(renderer.frame) + ' (sequenceEnd = ' + str(renderer.sequenceEnded) + ')')</span><span data-v-c2b1f83f="" class="line"> if newState == vray.RENDERER_STATE_IDLE_FRAME_DONE:</span><span data-v-c2b1f83f="" class="line"> # If the sequence has NOT finished - continue with next frame.</span><span data-v-c2b1f83f="" class="line"> renderer.continueSequence()</span><span data-v-c2b1f83f="" class="line"></span><span data-v-c2b1f83f="" class="line"># Create an instance of VRayRenderer with default options.</span><span data-v-c2b1f83f="" class="line"># The renderer is automatically closed after the `with` block.</span><span data-v-c2b1f83f="" class="line">with vray.VRayRenderer() as renderer:</span><span data-v-c2b1f83f="" class="line"> # Register a simple log callback. Always useful for debugging.</span><span data-v-c2b1f83f="" class="line"> def dumpMsg(renderer, message, level, instant):</span><span data-v-c2b1f83f="" class="line"> if level == vray.LOGLEVEL_ERROR:</span><span data-v-c2b1f83f="" class="line"> print("[ERROR]", message)</span><span data-v-c2b1f83f="" class="line"> elif level == vray.LOGLEVEL_WARNING:</span><span data-v-c2b1f83f="" class="line"> print("[Warning]", message)</span><span data-v-c2b1f83f="" class="line"> elif level == vray.LOGLEVEL_INFO:</span><span data-v-c2b1f83f="" class="line"> print("[info]", message)</span><span data-v-c2b1f83f="" class="line"> # Uncomment for testing, but you might want to ignore these in real code</span><span data-v-c2b1f83f="" class="line"> #else: print("[debug]", message)</span><span data-v-c2b1f83f="" class="line"> renderer.setOnLogMessage(dumpMsg)</span><span data-v-c2b1f83f="" class="line"> # Add a listener for the renderer state change event. We will use it to detect when a frame is completed and allow the next one to start.</span><span data-v-c2b1f83f="" class="line"> renderer.setOnStateChanged(onStateChanged)</span><span data-v-c2b1f83f="" class="line"> # Load scene from a file.</span><span data-v-c2b1f83f="" class="line"> renderer.load(os.path.join(SCENE_PATH, 'animation.vrscene'))</span><span data-v-c2b1f83f="" class="line"> # Maximum paths per pixel for interactive mode. Set a low sample level to complete rendering faster.</span><span data-v-c2b1f83f="" class="line"> # The default value is unlimited. We have to call this *after* loading the scene.</span><span data-v-c2b1f83f="" class="line"> renderer.setInteractiveSampleLevel(1)</span><span data-v-c2b1f83f="" class="line"> # 'useAnimatedValues' is used so that setting different value of the same property </span><span data-v-c2b1f83f="" class="line"> # will result in making it an animated value instead of replacing the value.</span><span data-v-c2b1f83f="" class="line"> renderer.useAnimatedValues = True</span><span data-v-c2b1f83f="" class="line"> # Obtain a reference to the Node plugin, containing the cube geometry.</span><span data-v-c2b1f83f="" class="line"> cubeShapeNode = renderer.plugins['pCubeShape1@node']</span><span data-v-c2b1f83f="" class="line"> # Move the cube for each step of the animation.</span><span data-v-c2b1f83f="" class="line"> for i in range(1, 21):</span><span data-v-c2b1f83f="" class="line"> # Increase the time point with 1 every iteration.</span><span data-v-c2b1f83f="" class="line"> # The current frame is updated automatically based on the</span><span data-v-c2b1f83f="" class="line"> # 'frames_per_second' property of the 'SettingsOutput' plugin, if set.</span><span data-v-c2b1f83f="" class="line"> renderer.time = i</span><span data-v-c2b1f83f="" class="line"> # Obtain a copy of the cubeShapeNode transform.</span><span data-v-c2b1f83f="" class="line"> updatedTransform = cubeShapeNode.transform</span><span data-v-c2b1f83f="" class="line"> # Modify the copy of the cubeShapeNode transform.</span><span data-v-c2b1f83f="" class="line"> # The changes do not affect the scene directly since updatedTransform is a copy of the actual transform.</span><span data-v-c2b1f83f="" class="line"> updatedTransform = updatedTransform.replaceOffset(updatedTransform.offset + vray.Vector(0, 0, -3 * i))</span><span data-v-c2b1f83f="" class="line"> # Update the transform value in cubeShapeNode (applying the changes above).</span><span data-v-c2b1f83f="" class="line"> cubeShapeNode.transform = updatedTransform</span><span data-v-c2b1f83f="" class="line"> # Set 'start' and 'end' of the sequence. 'step' is omitted and defaults to 1.</span><span data-v-c2b1f83f="" class="line"> # For all possible use cases of 'renderSequence' check the documentation for VRayRenderer.renderSequence.</span><span data-v-c2b1f83f="" class="line"> renderer.renderSequence({'start': 1, 'end': 20})</span><span data-v-c2b1f83f="" class="line"> # Wait until the entire sequence has finished rendering.</span><span data-v-c2b1f83f="" class="line"> renderer.waitForSequenceEnd()</span></code>
C++ <code data-v-c2b1f83f=""><span data-v-c2b1f83f="" class="line">#define VRAY_RUNTIME_LOAD_PRIMARY</span><span data-v-c2b1f83f="" class="line">#include "vraysdk.hpp"</span><span data-v-c2b1f83f="" class="line">#include "vrayplugins.hpp"</span><span data-v-c2b1f83f="" class="line">#include "utils.h"</span><span data-v-c2b1f83f="" class="line"></span><span data-v-c2b1f83f="" class="line">using namespace VRay;</span><span data-v-c2b1f83f="" class="line">using namespace VRay::Plugins;</span><span data-v-c2b1f83f="" class="line">using namespace std;</span><span data-v-c2b1f83f="" class="line"></span><span data-v-c2b1f83f="" class="line">const char *BASE_PATH = getenv("VRAY_SDK");</span><span data-v-c2b1f83f="" class="line">string SCENE_PATH = (BASE_PATH ? string(BASE_PATH) : string(".")) + PATH_DELIMITER + "scenes";</span><span data-v-c2b1f83f="" class="line"></span><span data-v-c2b1f83f="" class="line">void onStateChanged(VRayRenderer &renderer, RendererState oldState, RendererState newState, double instant, void* userData) {</span><span data-v-c2b1f83f="" class="line"> if (newState == IDLE_FRAME_DONE || newState == IDLE_DONE) {</span><span data-v-c2b1f83f="" class="line"> printf("Image Ready, frame %d (sequenceEnded = %d)\</span><span data-v-c2b1f83f="" class="line">", renderer.getCurrentFrame(), renderer.isSequenceEnded());</span><span data-v-c2b1f83f="" class="line"> if (newState == IDLE_FRAME_DONE) {</span><span data-v-c2b1f83f="" class="line"> // If the sequence has NOT finished - continue with next frame.</span><span data-v-c2b1f83f="" class="line"> renderer.continueSequence();</span><span data-v-c2b1f83f="" class="line"> }</span><span data-v-c2b1f83f="" class="line"> }</span><span data-v-c2b1f83f="" class="line">}</span><span data-v-c2b1f83f="" class="line"></span><span data-v-c2b1f83f="" class="line">int main() {</span><span data-v-c2b1f83f="" class="line"> // Change process working directory to SCENE_PATH in order to be able to load relative scene resources.</span><span data-v-c2b1f83f="" class="line"> changeCurrentDir(SCENE_PATH.c_str());</span><span data-v-c2b1f83f="" class="line"> // Load V-Ray SDK library.</span><span data-v-c2b1f83f="" class="line"> VRayInit init(NULL, true);</span><span data-v-c2b1f83f="" class="line"> // Create an instance of VRayRenderer with default options.</span><span data-v-c2b1f83f="" class="line"> // The renderer is automatically closed at the end of the current scope.</span><span data-v-c2b1f83f="" class="line"> VRayRenderer renderer;</span><span data-v-c2b1f83f="" class="line"> // It's recommended to always have a console log</span><span data-v-c2b1f83f="" class="line"> renderer.setOnLogMessage(logMessage);</span><span data-v-c2b1f83f="" class="line"> // Add a listener for the renderer state change event.</span><span data-v-c2b1f83f="" class="line"> // We will use it to detect when a frame is completed and allow the next one to start.</span><span data-v-c2b1f83f="" class="line"> renderer.setOnStateChanged(onStateChanged);</span><span data-v-c2b1f83f="" class="line"> // Load scene from a file.</span><span data-v-c2b1f83f="" class="line"> renderer.load("animation.vrscene");</span><span data-v-c2b1f83f="" class="line"> // Maximum paths per pixel for interactive mode. Set a low sample level to complete rendering faster.</span><span data-v-c2b1f83f="" class="line"> // The default value is unlimited. We have to call this *after* loading the scene.</span><span data-v-c2b1f83f="" class="line"> renderer.setInteractiveSampleLevel(1);</span><span data-v-c2b1f83f="" class="line"> // 'useAnimatedValues' is used so that setting different value of the same property </span><span data-v-c2b1f83f="" class="line"> // will result in making it an animated value instead of replacing the value.</span><span data-v-c2b1f83f="" class="line"> renderer.useAnimatedValues(true);</span><span data-v-c2b1f83f="" class="line"> // Obtain a reference to the Node plugin, containing the cube geometry.</span><span data-v-c2b1f83f="" class="line"> Node cubeShapeNode = renderer.getPlugin<Node>("pCubeShape1@node");</span><span data-v-c2b1f83f="" class="line"> // Move the cube for each step of the animation.</span><span data-v-c2b1f83f="" class="line"> for (int i = 1; i <= 20; i++) {</span><span data-v-c2b1f83f="" class="line"> // Increase the time point with 1. The current frame is updated</span><span data-v-c2b1f83f="" class="line"> // automatically based on SettingsOutput.frames_per_second, if set.</span><span data-v-c2b1f83f="" class="line"> renderer.setCurrentTime(i);</span><span data-v-c2b1f83f="" class="line"> // Obtain a copy of the cubeShapeNode transform.</span><span data-v-c2b1f83f="" class="line"> Transform updatedTransform = cubeShapeNode.get_transform();</span><span data-v-c2b1f83f="" class="line"> // Modify the copy of the cubeShapeNode transform.</span><span data-v-c2b1f83f="" class="line"> // The changes do not affect the scene directly since updatedTransform is a copy of the actual transform.</span><span data-v-c2b1f83f="" class="line"> updatedTransform.offset += Vector(0.0, 0.0, -3 * i);</span><span data-v-c2b1f83f="" class="line"> // Update the transform value in cubeShapeNode (applying the changes above).</span><span data-v-c2b1f83f="" class="line"> cubeShapeNode.set_transform(updatedTransform);</span><span data-v-c2b1f83f="" class="line"> }</span><span data-v-c2b1f83f="" class="line"> // Set 'start' and 'end' of the sequence.</span><span data-v-c2b1f83f="" class="line"> // For all possible use cases of 'renderSequence' check the documentation for VRayRenderer.renderSequence.</span><span data-v-c2b1f83f="" class="line"> SubSequenceDesc subSequenceDescriptions[1];</span><span data-v-c2b1f83f="" class="line"> subSequenceDescriptions[0].start = 1;</span><span data-v-c2b1f83f="" class="line"> subSequenceDescriptions[0].end = 20;</span><span data-v-c2b1f83f="" class="line"> subSequenceDescriptions[0].step = 1;</span><span data-v-c2b1f83f="" class="line"> renderer.renderSequence(subSequenceDescriptions, 1);</span><span data-v-c2b1f83f="" class="line"> // Wait until the entire sequence has finished rendering.</span><span data-v-c2b1f83f="" class="line"> renderer.waitForSequenceEnd();</span><span data-v-c2b1f83f="" class="line"></span><span data-v-c2b1f83f="" class="line"> return 0;</span><span data-v-c2b1f83f="" class="line">}</span></code>
C#.NET <code data-v-c2b1f83f=""><span data-v-c2b1f83f="" class="line">using System;</span><span data-v-c2b1f83f="" class="line">using System.IO;</span><span data-v-c2b1f83f="" class="line">using VRay;</span><span data-v-c2b1f83f="" class="line">using VRay.Plugins;</span><span data-v-c2b1f83f="" class="line"></span><span data-v-c2b1f83f="" class="line">namespace _02_animate_from_code</span><span data-v-c2b1f83f="" class="line">{</span><span data-v-c2b1f83f="" class="line"> class Program</span><span data-v-c2b1f83f="" class="line"> {</span><span data-v-c2b1f83f="" class="line"> static void Main(string[] args)</span><span data-v-c2b1f83f="" class="line"> {</span><span data-v-c2b1f83f="" class="line"> string SCENE_PATH = Path.Combine(Environment.GetEnvironmentVariable("VRAY_SDK"), "scenes");</span><span data-v-c2b1f83f="" class="line"> // Change process working directory to SCENE_PATH in order to be able to load relative scene resources.</span><span data-v-c2b1f83f="" class="line"> Directory.SetCurrentDirectory(SCENE_PATH);</span><span data-v-c2b1f83f="" class="line"> // Create an instance of VRayRenderer with default options. The renderer is automatically closed after the `using` block.</span><span data-v-c2b1f83f="" class="line"> using (VRayRenderer renderer = new VRayRenderer())</span><span data-v-c2b1f83f="" class="line"> {</span><span data-v-c2b1f83f="" class="line"> // Add a listener for any type of log message.</span><span data-v-c2b1f83f="" class="line"> renderer.LogMessage += new EventHandler<MessageEventArgs>((source, e) =></span><span data-v-c2b1f83f="" class="line"> {</span><span data-v-c2b1f83f="" class="line"> // You can remove the if for testing, but you might want to ignore Debug in real code</span><span data-v-c2b1f83f="" class="line"> if (e.LogLevel != LogLevelType.Debug)</span><span data-v-c2b1f83f="" class="line"> {</span><span data-v-c2b1f83f="" class="line"> Console.WriteLine(String.Format("[{0}] {1}", e.LogLevel.ToString(), e.Message));</span><span data-v-c2b1f83f="" class="line"> }</span><span data-v-c2b1f83f="" class="line"> });</span><span data-v-c2b1f83f="" class="line"> // Add a listener for state changes.</span><span data-v-c2b1f83f="" class="line"> // It is invoked when the renderer prepares for rendering, renders, finishes or fails.</span><span data-v-c2b1f83f="" class="line"> renderer.StateChanged += new EventHandler<StateChangedEventArgs>((source, e) =></span><span data-v-c2b1f83f="" class="line"> {</span><span data-v-c2b1f83f="" class="line"> if (e.NewState == VRayRenderer.RendererState.IDLE_FRAME_DONE || e.NewState == VRayRenderer.RendererState.IDLE_DONE)</span><span data-v-c2b1f83f="" class="line"> {</span><span data-v-c2b1f83f="" class="line"> Console.WriteLine("Image Ready, frame " + renderer.Frame + " (sequenceEnded = " + renderer.IsSequenceEnded + ")");</span><span data-v-c2b1f83f="" class="line"> // If the sequence has NOT finished - continue with next frame.</span><span data-v-c2b1f83f="" class="line"> renderer.ContinueSequence();</span><span data-v-c2b1f83f="" class="line"> }</span><span data-v-c2b1f83f="" class="line"> });</span><span data-v-c2b1f83f="" class="line"> // Load scene from a file.</span><span data-v-c2b1f83f="" class="line"> renderer.Load("animation.vrscene");</span><span data-v-c2b1f83f="" class="line"> // Maximum paths per pixel for interactive mode. Set a low sample level to complete rendering faster.</span><span data-v-c2b1f83f="" class="line"> // The default value is unlimited. We have to call this *after* loading the scene.</span><span data-v-c2b1f83f="" class="line"> renderer.SetInteractiveSampleLevel(1);</span><span data-v-c2b1f83f="" class="line"> // 'UseAnimatedValues' is used so that setting different value of the same property</span><span data-v-c2b1f83f="" class="line"> // will result in making it an animated value instead of replacing the value.</span><span data-v-c2b1f83f="" class="line"> renderer.UseAnimatedValues = true;</span><span data-v-c2b1f83f="" class="line"> // Obtain a reference to the Node plugin, containing the cube geometry.</span><span data-v-c2b1f83f="" class="line"> Node cubeShapeNode = renderer.GetPlugin<Node>("pCubeShape1@node");</span><span data-v-c2b1f83f="" class="line"> // Move the cube for each step of the animation.</span><span data-v-c2b1f83f="" class="line"> for (int i = 1; i <= 20; i++)</span><span data-v-c2b1f83f="" class="line"> {</span><span data-v-c2b1f83f="" class="line"> // Increase the time point with 1. The current frame is updated</span><span data-v-c2b1f83f="" class="line"> // automatically based on the 'frames_per_second' property of the</span><span data-v-c2b1f83f="" class="line"> // 'SettingsOutput' plugin, if set.</span><span data-v-c2b1f83f="" class="line"> renderer.Time = i;</span><span data-v-c2b1f83f="" class="line"> // Obtain a copy of the cubeShapeNode transform.</span><span data-v-c2b1f83f="" class="line"> Transform updatedTransform = cubeShapeNode.Transform;</span><span data-v-c2b1f83f="" class="line"> // Modify the copy of the cubeShapeNode transform.</span><span data-v-c2b1f83f="" class="line"> // The changes do not affect the scene directly since updatedTransform is a copy of the actual transform.</span><span data-v-c2b1f83f="" class="line"> updatedTransform = updatedTransform.ReplaceOffset(updatedTransform.Offset + new Vector(0, 0, -3 * i));</span><span data-v-c2b1f83f="" class="line"> // Update the transform value in cubeShapeNode (applying the changes above).</span><span data-v-c2b1f83f="" class="line"> cubeShapeNode.Transform = updatedTransform;</span><span data-v-c2b1f83f="" class="line"> }</span><span data-v-c2b1f83f="" class="line"> // Set 'start' and 'end' of the sequence. 'step' is omitted and defaults to 1.</span><span data-v-c2b1f83f="" class="line"> // For all possible use cases of 'renderSequence' check the documentation for VRayRenderer.renderSequence.</span><span data-v-c2b1f83f="" class="line"> renderer.RenderSequence(new SubSequenceDesc[] { new SubSequenceDesc(1, 20) });</span><span data-v-c2b1f83f="" class="line"> // Wait until the entire sequence has finished rendering.</span><span data-v-c2b1f83f="" class="line"> renderer.WaitForSequenceEnd();</span><span data-v-c2b1f83f="" class="line"> }</span><span data-v-c2b1f83f="" class="line"> }</span><span data-v-c2b1f83f="" class="line"> }</span><span data-v-c2b1f83f="" class="line">}</span></code>
Node.js <code data-v-c2b1f83f=""><span data-v-c2b1f83f="" class="line">var path = require('path');</span><span data-v-c2b1f83f="" class="line">var vray = require(path.join(process.env.VRAY_SDK, 'node', 'vray'));</span><span data-v-c2b1f83f="" class="line"></span><span data-v-c2b1f83f="" class="line">var SCENE_PATH = path.join(process.env.VRAY_SDK, 'scenes');</span><span data-v-c2b1f83f="" class="line">// Change process working directory to SCENE_PATH in order to be able to load relative scene resources.</span><span data-v-c2b1f83f="" class="line">process.chdir(SCENE_PATH);</span><span data-v-c2b1f83f="" class="line"></span><span data-v-c2b1f83f="" class="line">// Create an instance of VRayRenderer with default options.</span><span data-v-c2b1f83f="" class="line">var renderer = vray.VRayRenderer();</span><span data-v-c2b1f83f="" class="line">// It's recommended to always have a console log callback</span><span data-v-c2b1f83f="" class="line">renderer.on("logMessage", function(message, level, instant) {</span><span data-v-c2b1f83f="" class="line"> if (level == vray.LOGLEVEL_ERROR)</span><span data-v-c2b1f83f="" class="line"> console.log("[ERROR] ", message);</span><span data-v-c2b1f83f="" class="line"> else if (level == vray.LOGLEVEL_WARNING)</span><span data-v-c2b1f83f="" class="line"> console.log("[Warning] ", message);</span><span data-v-c2b1f83f="" class="line"> else if (level == vray.LOGLEVEL_INFO)</span><span data-v-c2b1f83f="" class="line"> console.log("[info] ", message);</span><span data-v-c2b1f83f="" class="line"> // Uncomment for testing, but you might want to ignore these in real code</span><span data-v-c2b1f83f="" class="line"> //else console.log("[debug] ", message);</span><span data-v-c2b1f83f="" class="line">});</span><span data-v-c2b1f83f="" class="line">// Add a listener for the renderer state change event.</span><span data-v-c2b1f83f="" class="line">// We will use it to detect when a frame is completed and allow the next one to start.</span><span data-v-c2b1f83f="" class="line">renderer.on("stateChanged", function(oldState, newState, instant) {</span><span data-v-c2b1f83f="" class="line"> if (newState == "idleFrameDone" || newState == "idleDone") {</span><span data-v-c2b1f83f="" class="line"> console.log("Image Ready, frame " + renderer.frame + " (sequenceEnd = " + renderer.sequenceEnded + ")");</span><span data-v-c2b1f83f="" class="line"> // Check if the sequence has finished rendering.</span><span data-v-c2b1f83f="" class="line"> if (newState == "idleDone") {</span><span data-v-c2b1f83f="" class="line"> renderer.close();</span><span data-v-c2b1f83f="" class="line"> } else {</span><span data-v-c2b1f83f="" class="line"> // If the sequence has NOT finished - continue with next frame.</span><span data-v-c2b1f83f="" class="line"> renderer.continueSequence();</span><span data-v-c2b1f83f="" class="line"> }</span><span data-v-c2b1f83f="" class="line"> } else if (newState.startsWith("idle")) {</span><span data-v-c2b1f83f="" class="line"> console.log("Unexpected end of render sequence: ", newState);</span><span data-v-c2b1f83f="" class="line"> renderer.close();</span><span data-v-c2b1f83f="" class="line"> }</span><span data-v-c2b1f83f="" class="line">});</span><span data-v-c2b1f83f="" class="line">// Load scene from a file asynchronously.</span><span data-v-c2b1f83f="" class="line">renderer.load("animation.vrscene", function(err) {</span><span data-v-c2b1f83f="" class="line"> if (err) throw err;</span><span data-v-c2b1f83f="" class="line"> // Maximum paths per pixel for interactive mode. Set a low sample level to complete rendering faster.</span><span data-v-c2b1f83f="" class="line"> // The default value is unlimited. We have to call this *after* loading the scene.</span><span data-v-c2b1f83f="" class="line"> renderer.setInteractiveSampleLevel(1);</span><span data-v-c2b1f83f="" class="line"> // "useAnimatedValues" is used so that setting different value of the same </span><span data-v-c2b1f83f="" class="line"> // will result in making it an animated value instead of replacing the value.</span><span data-v-c2b1f83f="" class="line"> renderer.useAnimatedValues = true;</span><span data-v-c2b1f83f="" class="line"> // Obtain a reference to the Node plugin, containing the cube geometry.</span><span data-v-c2b1f83f="" class="line"> var cubeShapeNode = renderer.plugins["pCubeShape1@node"]</span><span data-v-c2b1f83f="" class="line"> // Move the cube for each step of the animation.</span><span data-v-c2b1f83f="" class="line"> for (var i = 1; i <= 20; i++) {</span><span data-v-c2b1f83f="" class="line"> // Increase the time point with 1. The current frame is updated</span><span data-v-c2b1f83f="" class="line"> // automatically based on SettingsOutput.frames_per_second, if set.</span><span data-v-c2b1f83f="" class="line"> renderer.time = i;</span><span data-v-c2b1f83f="" class="line"> // Obtain a copy of the cubeShapeNode transform.</span><span data-v-c2b1f83f="" class="line"> var updatedTransform = cubeShapeNode.transform;</span><span data-v-c2b1f83f="" class="line"> // Modify the copy of the cubeShapeNode transform.</span><span data-v-c2b1f83f="" class="line"> // The changes do not affect the scene directly since updatedTransform is a copy of the actual transform.</span><span data-v-c2b1f83f="" class="line"> updatedTransform = updatedTransform.replaceOffset(updatedTransform.offset.add(vray.Vector(0, 0, -3 * i)));</span><span data-v-c2b1f83f="" class="line"> // Update the transform value in cubeShapeNode (applying the changes above).</span><span data-v-c2b1f83f="" class="line"> cubeShapeNode.transform = updatedTransform;</span><span data-v-c2b1f83f="" class="line"> }</span><span data-v-c2b1f83f="" class="line"> // Set "start" and "end" of the sequence. "step" is omitted and defaults to 1.</span><span data-v-c2b1f83f="" class="line"> // For all possible use cases of "renderSequence" check the documentation for VRayRenderer.renderSequence.</span><span data-v-c2b1f83f="" class="line"> renderer.renderSequence({"start": 1, "end": 20});</span><span data-v-c2b1f83f="" class="line"> // Prevent garbage collection and exiting nodejs until the renderer is closed.</span><span data-v-c2b1f83f="" class="line"> renderer.keepAlive();</span><span data-v-c2b1f83f="" class="line">});</span></code>