Accessing Rendering Assets

OpenNURBS and Rhino3dm now provide direct access to rendering information without the need for Rhino. (Prior to this, the only way to access this information outside of Rhino was by getting the data as XML and parsing it.)

This guide outlines classes used to access these rendering assets and provides examples.

Overview

In C++, the following objects are accessible through the use of ONX_Model. In C# the equivalent functionality is provided by File3dm which under the hood is a wrapper around ONX_Model.

C/C++ C# Equivalent Purpose
ON_RenderContent File3dmRenderContent Provides access to generic render content settings.
ON_RenderMaterial File3dmRenderMaterial Provides access to settings specific to render materials.
ON_RenderEnvironment File3dmRenderEnvironment Provides access to settings specific to render environments.
ON_RenderTexture File3dmRenderTexture Provides access to settings specific to render textures.
ON_Decals Rhino.Render.Decals Provides access to a collection of decals stored on object attributes.
ON_Decal Rhino.Render.Decal Provides access to settings for an individual decal in the collection.
ON_Dithering Rhino.Render.Dithering Provides access to dithering settings.
ON_EmbeddedFile File3dmEmbeddedFile Provides access to embedded texture files.
ON_GroundPlane Rhino.Render.GroundPlane Provides access to ground plane settings.
ON_LinearWorkflow Rhino.Render.LinearWorkflow Provides access to gamma and linear workflow settings.
ON_RenderChannels Rhino.Render.RenderChannels Provides access to render channels settings.
ON_SafeFrame Rhino.Render.SafeFrame Provides access to safe frame settings.
ON_Skylight Rhino.Render.Skylight Provides access to skylighting settings.
ON_Sun Rhino.Render.Sun Provides access to sun settings and sun position calculations.
ON_PostEffects Rhino.Render.PostEffects.PostEffectCollection Provides access to the list of post effects.
ON_PostEffect Rhino.Render.PostEffects.PostEffectData Provides access to settings for an individual post effect in the list.

Decals

To access decals you need to get the 3dmObjectAttributes object for the model geometry component that you are interested in and then get the decal collection from its attributes. You can then iterate over all the decals in the collection and get and set their properties:

var file3dm = File3dm.Read(filename_in);
var e = file3dm.Manifest.GetEnumerator(
Rhino.DocObjects.ModelComponentType.ModelGeometry);
while (e.MoveNext())
{
if (e.Current is File3dmObject obj)
{
foreach (var decal in obj.Attributes.Decals)
{
Console.WriteLine(" Mapping: {0}", decal.DecalMapping);
Console.WriteLine(" Projection: {0}", decal.DecalProjection);
Console.WriteLine(" Origin: {0}", decal.Origin);
Console.WriteLine(" Transparency: {0}", decal.Transparency);
}
}
}

Dithering

Dithering information is accessed through 3dmRenderSettings. To access it, you need to get the render settings and call its Dithering method/property to get a reference to a Dithering object. You can then read or write the settings by calling the various methods on the Dithering object. Any changes you make will persist and can be saved to a 3dm file:

var file3dm = File3dm.Read(filename_in);
var dit = file3dm.Settings.RenderSettings.Dithering;
Console.WriteLine("Enabled: {0}", dit.Enabled);
Console.WriteLine("Method: {0}", dit.Method);
dit.Enabled = true;
dit.Method = Dithering.Methods.FloydSteinberg;

Ground Plane

Ground plane information is accessed through 3dmRenderSettings. To access it, you need to get the render settings and call its GroundPlane method/property to get a reference to a GroundPlane object. You can then read or write the settings by calling the various methods on the GroundPlane object. Any changes you make will persist and can be saved to a 3dm file:

var file3dm = File3dm.Read(filename_in);
var gp = file3dm.Settings.RenderSettings.GroundPlane;
Console.WriteLine("Enabled: {0}", gp.Enabled);
Console.WriteLine("Altitude: {0}", gp.Altitude);
gp.Enabled = false;
model.Write(filename_out);

Linear Workflow

Linear workflow information is accessed through 3dmRenderSettings. To access it, you need to get the render settings and call its LinearWorkflow method/property to get a reference to a LinearWorkflow object. You can then read or write the settings by calling the various methods on the LinearWorkflow object. Any changes you make will persist and can be saved to a 3dm file:

var file3dm = File3dm.Read(filename_in);
var lw = file3dm.Settings.RenderSettings.LinearWorkflow;
Console.WriteLine("PostProcessGammaOn: {0}", lw.PostProcessGammaOn);
Console.WriteLine("PostProcessGamma: {0}", lw.PostProcessGamma);
lw.PostProcessGamma = 3.4f;
model.Write(filename_out);

Render Channels

Render channel information is accessed through 3dmRenderSettings. To access it, you need to get the render settings and call its RenderChannels method/property to get a reference to a RenderChannels object. You can then read or write the settings by calling the various methods on the RenderChannels object. Any changes you make will persist and can be saved to a 3dm file:

var file3dm = File3dm.Read(filename_in);
var lw = file3dm.Settings.RenderSettings.RenderChannels;
Console.WriteLine("Mode: {0}", rch.Mode);
rch.Mode = RenderChannels.Modes.Custom;
model.Write(filename_out);

Safe Frame

Safe Frame information is accessed through 3dmRenderSettings. To access it, you need to get the render settings and call its SafeFrame method/property to get a reference to a SafeFrame object. You can then read or write the settings by calling the various methods on the SafeFrame object. Any changes you make will persist and can be saved to a 3dm file:

var file3dm = File3dm.Read(filename_in);
var sf = file3dm.Settings.RenderSettings.SafeFrame;
Console.WriteLine("On: {0}", sf.Enabled);
Console.WriteLine("ActionFrameXScale: {0}", sf.ActionFrameXScale);
sf.ActionFrameXScale = 0.45;
model.Write(filename_out);

Skylight

Skylight information is accessed through 3dmRenderSettings. To access it, you need to get the render settings and call its Skylight method/property to get a reference to a Skylight object. You can then read or write the settings by calling the various methods on the Skylight object. Any changes you make will persist and can be saved to a 3dm file:

var file3dm = File3dm.Read(filename_in);
var sl = file3dm.Settings.RenderSettings.Skylight;
Console.WriteLine("Enabled: {0}", sl.Enabled);
Console.WriteLine("ShadowIntensity: {0}", sl.ShadowIntensity);
sl.ShadowIntensity = 1.4;
model.Write(filename_out);

Sun

Sun information is accessed through 3dmRenderSettings. To access it, you need to get the render settings and call its Sun method/property to get a reference to a Sun object. You can then read or write the settings by calling the various methods on the Sun object. Any changes you make will persist and can be saved to a 3dm file:

var file3dm = File3dm.Read(filename_in);
var sun = file3dm.Settings.RenderSettings.Sun;
Console.WriteLine("On: {0}", sun.Enabled);
Console.WriteLine("Time zone: {0}", sun.TimeZone);
var dt = sun.GetDateTime(DateTimeKind.Local);
var format = "LocalDateTime: {0}.{1}.{2} {3}:{4}";
var message = string.Format(CultureInfo.InvariantCulture,
format, dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute);
Console.WriteLine(message);
Console.WriteLine("Place sun observer at the Greenwich observatory in London");
sun.Latitude = 51.4769;
sun.Longitude = -0.0005;
sun.TimeZone = 0.0;
model.Write(filename_out);

The sun object is able to do sun calculations and, in fact, will automatically do them whenever “manual control” is disabled (this is the default). Whenever certain properties are modified, the sun object will automatically compute the sun’s azimuth and altitude in the sky. The calculation is deferred until you actually ask for the azimuth or altitude whereupon it is performed once and cached until the next time something changes. The properties that cause the calculation to be performed are the direction of north and also any properties that change the observer’s date, time, location, time zone or daylight saving values.

When manual control is enabled, the azimuth and altitude values are under the control of the programmer and no calculations are performed.

The direction of north and the observer’s latitude and longitude are stored inside an earth anchor point object. This object is inside the 3dmSettings of the ONX_Model/File3dm and is therefore loaded and saved with the model.

Post Effects

Post effect information is accessed through 3dmRenderSettings. To access it, you need to get the render settings and call its PostEffects method/property to get a reference to a post effect collection object. This object allows you to iterate over the post effects, change the order of post effects and get and set the post effect selection. Iterating over the post effects retrieves individual post effect objects. You can access and change post effect properties by calling the various methods on the post effect object. Any changes you make will persist and can be saved to a 3dm file:

var file3dm = File3dm.Read(filename_in);
var post_effects = file3dm.Settings.RenderSettings.PostEffects;
foreach (var post_effect in post_effects)
{
Console.WriteLine(pep.LocalName);
Console.WriteLine("--------------------");
Console.WriteLine("Id : {0}", pep.Id);
Console.WriteLine("Type : {0}", pep.Type);
Console.WriteLine("On : {0}", pep.On);
Console.WriteLine("Shown: {0}", pep.Shown);
// If the post effect has a radius parameter, change its value.
var p = pep.GetParameter("radius");
if (p != null)
{
pep.SetParameter("radius", 0.33);
}
}

Render Content

“Render content” is an abstraction that represents one of three different kinds of object. A render content can be a:

  1. Render Material
  2. Render Environment
  3. Render Texture

Render contents are model components and, in C++, can be accessed by iterating over the model components in a model. In C# you iterate over lists of each kind. Each kind is a subclass of the render content class. The base class contains all methods/properties that are common to all three kinds, and each subclass contains only the methods/properties specific to that kind.

var file3dm = File3dm.Read(filename_in);
foreach (var rm in file3dm.RenderMaterials)
{
Console.WriteLine("{0}", rm.TypeName);
IConvertible p = rm.GetParameter("ior");
if (p != null)
{
Console.WriteLine("Setting IOR and transparency");
rm.SetParameter("ior", 2.5);
rm.SetParameter("transparency", 0.5);
}
}
foreach (var re in file3dm.RenderEnvironments)
{
var env = re.ToEnvironment();
var col = env.BackgroundColor;
Console.WriteLine("Color: {0}, {1}, {2}", col.R, col.G, col.B);
}
foreach (var rt in file3dm.RenderTextures)
{
var tex = rt.ToTexture();
Console.WriteLine("{0}", tex.FileReference.FullPath);
}

Embedded Files

Embedded Files (not to be confused with Embedded Bitmaps) are files that are embedded inside a 3dm file. When a render texture is file-based (i.e., most non-procedural textures), then by default, Rhino saves a copy of the referenced file in the 3dm file. This can be disabled during Save As by unchecking the Save textures check box. These files can be accessed by the programmer by iterating over model components of type EmbeddedFile. Although the embedded file object contains a number of methods for loading and saving files in different ways, iterating over the model is probably the most useful way to use it:

var file3dm = File3dm.Read(filename_in);
foreach (var ef in file3dm.EmbeddedFiles)
{
var dir = System.IO.Path.GetDirectoryName(ef.Filename);
var file = System.IO.Path.GetFileName(ef.Filename);
var new_file = System.IO.Path.Combine(dir, "CopyOf_" + file);
ef.SaveToFile(new_file);
}