©Anton Podvalny

Table of Contents

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:

SettingsOutput {
  img_width=400;
  img_height=400;
  anim_start=1;
  anim_end=10;
  anim_frame_padding=4;
  anim_renumber_on=0;
  anim_renumber_start=0;
  anim_renumber_step=1;
  anim_ren_frame_start=0;
  frame_start=1;
  frames_per_second=1;
  frames=List(
      List(1, 10)
  );
}

 

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:

 

# Compatibility with Python 2.7.
from __future__ import print_function

# The directory containing the vray shared object should be present in the PYTHONPATH environment variable.
# Try to import the vray module from VRAY_SDK/python, if it is not in PYTHONPATH
import sys, os
VRAY_SDK = os.environ.get('VRAY_SDK')
if VRAY_SDK:
    sys.path.append(os.path.join(VRAY_SDK, 'python'))
import vray

SCENE_PATH = os.path.join(os.environ.get('VRAY_SDK'), 'scenes')
# Change process working directory to SCENE_PATH in order to be able to load relative scene resources.
os.chdir(SCENE_PATH)

def onStateChanged(renderer, oldState, newState, instant):
    if newState == vray.RENDERER_STATE_IDLE_FRAME_DONE or newState == vray.RENDERER_STATE_IDLE_DONE:
        print('Image Ready, frame ' + str(renderer.frame) + ' (sequenceEnd = ' + str(renderer.sequenceEnded) + ')')
        if newState == vray.RENDERER_STATE_IDLE_FRAME_DONE:
            # If the sequence has NOT finished - continue with next frame.
            renderer.continueSequence()

# Create an instance of VRayRenderer with default options.
# The renderer is automatically closed after the `with` block.
with vray.VRayRenderer() as renderer:
    # Register a simple log callback. Always useful for debugging.
    def dumpMsg(renderer, message, level, instant):
        if level == vray.LOGLEVEL_ERROR:
            print("[ERROR]", message)
        elif level == vray.LOGLEVEL_WARNING:
            print("[Warning]", message)
        elif level == vray.LOGLEVEL_INFO:
            print("[info]", message)
        # Uncomment for testing, but you might want to ignore these in real code
        #else: print("[debug]", message)
    renderer.setOnLogMessage(dumpMsg)
    # 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.
    renderer.setOnStateChanged(onStateChanged)
    # Load scene from a file.
    renderer.load(os.path.join(SCENE_PATH, 'animation.vrscene'))
    # Maximum paths per pixel for interactive mode. Set a low sample level to complete rendering faster.
    # The default value is unlimited. We have to call this *after* loading the scene.
    renderer.setInteractiveSampleLevel(1)
    # 'useAnimatedValues' is used so that setting different value of the same property 
    # will result in making it an animated value instead of replacing the value.
    renderer.useAnimatedValues = True
    # Obtain a reference to the Node plugin, containing the cube geometry.
    cubeShapeNode = renderer.plugins['pCubeShape1@node']
    # Move the cube for each step of the animation.
    for i in range(1, 21):
        # Increase the time point with 1 every iteration.
        # The current frame is updated automatically based on the
        # 'frames_per_second' property of the 'SettingsOutput' plugin, if set.
        renderer.time = i
        # Obtain a copy of the cubeShapeNode transform.
        updatedTransform = cubeShapeNode.transform
        # Modify the copy of the cubeShapeNode transform.
        # The changes do not affect the scene directly since updatedTransform is a copy of the actual transform.
        updatedTransform = updatedTransform.replaceOffset(updatedTransform.offset + vray.Vector(0, 0, -3 * i))
        # Update the transform value in cubeShapeNode (applying the changes above).
        cubeShapeNode.transform = updatedTransform
    # Set 'start' and 'end' of the sequence. 'step' is omitted and defaults to 1.
    # For all possible use cases of 'renderSequence' check the documentation for VRayRenderer.renderSequence.
    renderer.renderSequence({'start': 1, 'end': 20})
    # Wait until the entire sequence has finished rendering.
    renderer.waitForSequenceEnd()
#define VRAY_RUNTIME_LOAD_PRIMARY
#include "vraysdk.hpp"
#include "vrayplugins.hpp"
#include "utils.h"

using namespace VRay;
using namespace VRay::Plugins;
using namespace std;

const char *BASE_PATH = getenv("VRAY_SDK");
string SCENE_PATH = (BASE_PATH ? string(BASE_PATH) : string(".")) + PATH_DELIMITER + "scenes";

void onStateChanged(VRayRenderer &renderer, RendererState oldState, RendererState newState, double instant, void* userData) {
	if (newState == IDLE_FRAME_DONE || newState == IDLE_DONE) {
		printf("Image Ready, frame %d (sequenceEnded = %d)\n", renderer.getCurrentFrame(), renderer.isSequenceEnded());
		if (newState == IDLE_FRAME_DONE) {
			// If the sequence has NOT finished - continue with next frame.
			renderer.continueSequence();
		}
	}
}

int main() {
	// Change process working directory to SCENE_PATH in order to be able to load relative scene resources.
	changeCurrentDir(SCENE_PATH.c_str());
	// Load V-Ray SDK library.
	VRayInit init(NULL, true);
	// Create an instance of VRayRenderer with default options.
	// The renderer is automatically closed at the end of the current scope.
	VRayRenderer renderer;
	// It's recommended to always have a console log
	renderer.setOnLogMessage(logMessage);
	// 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.
	renderer.setOnStateChanged(onStateChanged);
	// Load scene from a file.
	renderer.load("animation.vrscene");
	// Maximum paths per pixel for interactive mode. Set a low sample level to complete rendering faster.
	// The default value is unlimited. We have to call this *after* loading the scene.
	renderer.setInteractiveSampleLevel(1);
	// 'useAnimatedValues' is used so that setting different value of the same property 
	// will result in making it an animated value instead of replacing the value.
	renderer.useAnimatedValues(true);
	// Obtain a reference to the Node plugin, containing the cube geometry.
	Node cubeShapeNode = renderer.getPlugin<Node>("pCubeShape1@node");
	// Move the cube for each step of the animation.
	for (int i = 1; i <= 20; i++) {
		// Increase the time point with 1. The current frame is updated
		// automatically based on SettingsOutput.frames_per_second, if set.
		renderer.setCurrentTime(i);
		// Obtain a copy of the cubeShapeNode transform.
		Transform updatedTransform = cubeShapeNode.get_transform();
		// Modify the copy of the cubeShapeNode transform.
		// The changes do not affect the scene directly since updatedTransform is a copy of the actual transform.
		updatedTransform.offset += Vector(0.0, 0.0, -3 * i);
		// Update the transform value in cubeShapeNode (applying the changes above).
		cubeShapeNode.set_transform(updatedTransform);
	}
	// Set 'start' and 'end' of the sequence.
	// For all possible use cases of 'renderSequence' check the documentation for VRayRenderer.renderSequence.
	SubSequenceDesc subSequenceDescriptions[1];
	subSequenceDescriptions[0].start = 1;
	subSequenceDescriptions[0].end = 20;
	subSequenceDescriptions[0].step = 1;
	renderer.renderSequence(subSequenceDescriptions, 1);
	// Wait until the entire sequence has finished rendering.
	renderer.waitForSequenceEnd();

	return 0;
}
using System;
using System.IO;
using VRay;
using VRay.Plugins;

namespace _02_animate_from_code
{
	class Program
	{
		static void Main(string[] args)
		{
			string SCENE_PATH = Path.Combine(Environment.GetEnvironmentVariable("VRAY_SDK"), "scenes");
			// Change process working directory to SCENE_PATH in order to be able to load relative scene resources.
			Directory.SetCurrentDirectory(SCENE_PATH);
			// Create an instance of VRayRenderer with default options. The renderer is automatically closed after the `using` block.
			using (VRayRenderer renderer = new VRayRenderer())
			{
				// Add a listener for any type of log message.
				renderer.LogMessage += new EventHandler<MessageEventArgs>((source, e) =>
				{
					// You can remove the if for testing, but you might want to ignore Debug in real code
					if (e.LogLevel != LogLevelType.Debug)
					{
						Console.WriteLine(String.Format("[{0}] {1}", e.LogLevel.ToString(), e.Message));
					}
				});
				// Add a listener for state changes.
				// It is invoked when the renderer prepares for rendering, renders, finishes or fails.
				renderer.StateChanged += new EventHandler<StateChangedEventArgs>((source, e) =>
				{
					if (e.NewState == VRayRenderer.RendererState.IDLE_FRAME_DONE || e.NewState == VRayRenderer.RendererState.IDLE_DONE)
					{
						Console.WriteLine("Image Ready, frame " + renderer.Frame + " (sequenceEnded = " + renderer.IsSequenceEnded + ")");
						// If the sequence has NOT finished - continue with next frame.
						renderer.ContinueSequence();
					}
				});
				// Load scene from a file.
				renderer.Load("animation.vrscene");
				// Maximum paths per pixel for interactive mode. Set a low sample level to complete rendering faster.
				// The default value is unlimited. We have to call this *after* loading the scene.
				renderer.SetInteractiveSampleLevel(1);
				// 'UseAnimatedValues' is used so that setting different value of the same property
				// will result in making it an animated value instead of replacing the value.
				renderer.UseAnimatedValues = true;
				// Obtain a reference to the Node plugin, containing the cube geometry.
				Node cubeShapeNode = renderer.GetPlugin<Node>("pCubeShape1@node");
				// Move the cube for each step of the animation.
				for (int i = 1; i <= 20; i++)
				{
					// Increase the time point with 1. The current frame is updated
					// automatically based on the 'frames_per_second' property of the
					// 'SettingsOutput' plugin, if set.
					renderer.Time = i;
					// Obtain a copy of the cubeShapeNode transform.
					Transform updatedTransform = cubeShapeNode.Transform;
					// Modify the copy of the cubeShapeNode transform.
					// The changes do not affect the scene directly since updatedTransform is a copy of the actual transform.
					updatedTransform = updatedTransform.ReplaceOffset(updatedTransform.Offset + new Vector(0, 0, -3 * i));
					// Update the transform value in cubeShapeNode (applying the changes above).
					cubeShapeNode.Transform = updatedTransform;
				}
				// Set 'start' and 'end' of the sequence. 'step' is omitted and defaults to 1.
				// For all possible use cases of 'renderSequence' check the documentation for VRayRenderer.renderSequence.
				renderer.RenderSequence(new SubSequenceDesc[] { new SubSequenceDesc(1, 20) });
				// Wait until the entire sequence has finished rendering.
				renderer.WaitForSequenceEnd();
			}
		}
	}
}
var path = require('path');
var vray = require(path.join(process.env.VRAY_SDK, 'node', 'vray'));

var SCENE_PATH = path.join(process.env.VRAY_SDK, 'scenes');
// Change process working directory to SCENE_PATH in order to be able to load relative scene resources.
process.chdir(SCENE_PATH);

// Create an instance of VRayRenderer with default options.
var renderer = vray.VRayRenderer();
// It's recommended to always have a console log callback
renderer.on("logMessage", function(message, level, instant) {
	if (level == vray.LOGLEVEL_ERROR)
		console.log("[ERROR] ", message);
	else if (level == vray.LOGLEVEL_WARNING)
		console.log("[Warning] ", message);
	else if (level == vray.LOGLEVEL_INFO)
		console.log("[info] ", message);
	// Uncomment for testing, but you might want to ignore these in real code
	//else console.log("[debug] ", message);
});
// 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.
renderer.on("stateChanged", function(oldState, newState, instant) {
	if (newState == "idleFrameDone" || newState == "idleDone") {
		console.log("Image Ready, frame " + renderer.frame + " (sequenceEnd = " + renderer.sequenceEnded + ")");
		// Check if the sequence has finished rendering.
		if (newState == "idleDone") {
			renderer.close();
		} else {
			// If the sequence has NOT finished - continue with next frame.
			renderer.continueSequence();
		}
	} else if (newState.startsWith("idle")) {
		console.log("Unexpected end of render sequence: ", newState);
		renderer.close();
	}
});
// Load scene from a file asynchronously.
renderer.load("animation.vrscene", function(err) {
	if (err) throw err;
	// Maximum paths per pixel for interactive mode. Set a low sample level to complete rendering faster.
	// The default value is unlimited. We have to call this *after* loading the scene.
	renderer.setInteractiveSampleLevel(1);
	// "useAnimatedValues" is used so that setting different value of the same 
	// will result in making it an animated value instead of replacing the value.
	renderer.useAnimatedValues = true;
	// Obtain a reference to the Node plugin, containing the cube geometry.
	var cubeShapeNode = renderer.plugins["pCubeShape1@node"]
	// Move the cube for each step of the animation.
	for (var i = 1; i <= 20; i++) {
		// Increase the time point with 1. The current frame is updated
		// automatically based on SettingsOutput.frames_per_second, if set.
		renderer.time = i;
		// Obtain a copy of the cubeShapeNode transform.
		var updatedTransform = cubeShapeNode.transform;
		// Modify the copy of the cubeShapeNode transform.
		// The changes do not affect the scene directly since updatedTransform is a copy of the actual transform.
		updatedTransform = updatedTransform.replaceOffset(updatedTransform.offset.add(vray.Vector(0, 0, -3 * i)));
		// Update the transform value in cubeShapeNode (applying the changes above).
		cubeShapeNode.transform = updatedTransform;
	}
	// Set "start" and "end" of the sequence. "step" is omitted and defaults to 1.
	// For all possible use cases of "renderSequence" check the documentation for VRayRenderer.renderSequence.
	renderer.renderSequence({"start": 1, "end": 20});
	// Prevent garbage collection and exiting nodejs until the renderer is closed.
	renderer.keepAlive();
});

 

 

  • No labels