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:
- Render Material
- Render Environment
- 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); }