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);
}
}
}
import _rhino3dm
model = _rhino3dm.File3dm.Read(filename_in)
for obj in model.Objects:
for decal in obj.Attributes.Decals:
print(decal.Mapping)
print(decal.Projection)
print(decal.Origin)
print(decal.Transparency)
print()
// node.js
import * as fs from 'fs' //only if running in node.js
import rhino3dm from 'rhino3dm'
const rhino = await rhino3dm()
const buffer = fs.readFileSync( filename_in )
/*
if you are running this in a browser, comment out the first line (the fs import) and replace the above line with these two lines:
const file = await fetch( filename_in )
const buffer = await file.arrayBuffer()
*/
const arr = new Uint8Array( buffer )
const file3dm = rhino.File3dm.fromByteArray( arr )
const objects = file3dm.objects()
for( let i = 0; i < objects.count; i ++ ) {
const attributes = objects.get( i ).attributes()
for( let j = 0; j < attributes.decals().count; j ++ ) {
const decal = attributes.decals().get( j )
console.log( `Decal Mapping: ${decal.mapping.constructor.name}` )
console.log( `Decal Projection: ${decal.projection.constructor.name}`)
console.log( `Decal Origin: ${decal.origin}` )
console.log( `Decal Transparency: ${decal.transparency}` )
}
}
ONX_Model model;
model.Read(filename_in);
ONX_ModelComponentIterator it(model, ON_ModelComponent::Type::ModelGeometry);
const auto* component = it.FirstComponent();
while (nullptr != component)
{
auto* mgc = ON_ModelGeometryComponent::Cast(component);
if (nullptr != mgc)
{
auto* attr = mgc->ExclusiveAttributes();
if (nullptr != attr)
{
const auto& da = attr->GetDecalArray();
for (int i = 0; i < da.Count(); i++)
{
auto* decal = da[i];
const auto mapping = decal->Mapping();
const auto origin = decal->Origin();
}
}
}
component = it.NextComponent();
}
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;
import _rhino3dm
model = _rhino3dm.File3dm.Read(filename_in)
dit = model.Settings.RenderSettings.Dithering
print(dit.Enabled)
print(dit.Method)
dit.Enabled = True
dit.Method = _rhino3dm.DitheringMethods.FloydSteinberg
// node.js
import * as fs from 'fs' //only if running in node.js
import rhino3dm from 'rhino3dm'
const rhino = await rhino3dm()
const buffer = fs.readFileSync( filename_in )
/*
if you are running this in a browser, comment out the first line (the fs import) and replace the above line with these two lines:
const file = await fetch( filename_in )
const buffer = await file.arrayBuffer()
*/
const arr = new Uint8Array( buffer )
const file3dm = rhino.File3dm.fromByteArray( arr )
const dithering = file3dm.settings().renderSettings().dithering
console.log( `Dithering Enabled: ${ dithering.enabled }` )
console.log( `Dithering Method: ${ dithering.method.constructor.name }` )
dithering.enabled = true
dithering.method = rhino.DitheringMethods.SimpleNoise
console.log( `Dithering Enabled: ${ dithering.enabled }` )
console.log( `Dithering Method: ${ dithering.method.constructor.name }` )
ONX_Model model;
model.Read(filename_in);
auto& dit = model.m_settings.m_RenderSettings.Dithering();
const auto on = dit.Enabled();
const auto method = dit.Method();
dit.SetEnabled(true);
dit.SetMethod(ON_Dithering::Methods::FloydSteinberg);
model.Write(filename_out);
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);
import _rhino3dm
model = _rhino3dm.File3dm.Read(filename_in)
gp = model.Settings.RenderSettings.GroundPlane
print(gp.Enabled)
print(gp.Altitude)
gp.Enabled = False
// node.js
import * as fs from 'fs' //only if running in node.js
import rhino3dm from 'rhino3dm'
const rhino = await rhino3dm()
const buffer = fs.readFileSync( filename_in )
/*
if you are running this in a browser, comment out the first line (the fs import) and replace the above line with these two lines:
const file = await fetch( filename_in )
const buffer = await file.arrayBuffer()
*/
const arr = new Uint8Array( buffer )
const file3dm = rhino.File3dm.fromByteArray( arr )
const gp = file3dm.settings().renderSettings().groundPlane
console.log( `Ground Plane Enabled: ${ gp.enabled }` )
console.log( `Ground Plane Altitude: ${ gp.altitude }` )
gp.enabled = false
ONX_Model model;
model.Read(filename_in);
auto& gp = model.m_settings.m_RenderSettings.GroundPlane();
const auto on = gp.Enabled();
const auto alt = gp.Altitude();
gp.SetEnabled(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);
import _rhino3dm
model = _rhino3dm.File3dm.Read(filename_in)
lw = model.Settings.RenderSettings.LinearWorkflow
print(lw.PostProcessGammaOn)
print(lw.PostProcessGamma)
lw.PostProcessGamma = 3.4
// node.js
import * as fs from 'fs' //only if running in node.js
import rhino3dm from 'rhino3dm'
const rhino = await rhino3dm()
const buffer = fs.readFileSync( filename_in )
/*
if you are running this in a browser, comment out the first line (the fs import) and replace the above line with these two lines:
const file = await fetch( filename_in )
const buffer = await file.arrayBuffer()
*/
const arr = new Uint8Array( buffer )
const file3dm = rhino.File3dm.fromByteArray( arr )
const lw = file3dm.settings().renderSettings().linearWorkflow
console.log( `Linear Workflow Post Proces Gamma On: ${ lw.postProcessGammaOn }` )
console.log( `Linear Workflow Post Proces Gamma: ${ lw.postProcessGamma }` )
lw.PostProcessGamma = 3.4
ONX_Model model;
model.Read(filename_in);
auto& lw = model.m_settings.m_RenderSettings.LinearWorkflow();
const auto on = lw.PostProcessGammaOn();
const auto gamma lw.PostProcessGamma();
lw.SetPostProcessGamma(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);
import _rhino3dm
model = _rhino3dm.File3dm.Read(filename_in)
rch = model.Settings.RenderSettings.RenderChannels
print(rch.Mode)
rch.Mode = _rhino3dm.RenderChannelsModes.Custom
// node.js
import * as fs from 'fs' //only if running in node.js
import rhino3dm from 'rhino3dm'
const rhino = await rhino3dm()
const buffer = fs.readFileSync( filename_in )
/*
if you are running this in a browser, comment out the first line (the fs import) and replace the above line with these two lines:
const file = await fetch( filename_in )
const buffer = await file.arrayBuffer()
*/
const arr = new Uint8Array( buffer )
const file3dm = rhino.File3dm.fromByteArray( arr )
const rch = file3dm.settings().renderSettings().renderChannels
console.log( `renderChannels mode: ${ rch.mode.constructor.name }` )
console.log( `renderChannels customIds: ${ rch.customIds }` )
rch.mode = rhino.RenderChannelsModes.Custom
ONX_Model model;
model.Read(filename_in);
auto& rch = model.m_settings.m_RenderSettings.RenderChannels();
const auto mode = rch.Mode();
rch.SetMode(ON_RenderChannels::Modes::Automatic);
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);
import _rhino3dm
model = _rhino3dm.File3dm.Read(filename_in)
sf = model.Settings.RenderSettings.SafeFrame
print(sf.Enabled)
print(sf.ActionFrameXScale)
sf.ActionFrameXScale = 0.45
// node.js
import * as fs from 'fs' //only if running in node.js
import rhino3dm from 'rhino3dm'
const rhino = await rhino3dm()
const buffer = fs.readFileSync( filename_in )
/*
if you are running this in a browser, comment out the first line (the fs import) and replace the above line with these two lines:
const file = await fetch( filename_in )
const buffer = await file.arrayBuffer()
*/
const arr = new Uint8Array( buffer )
const file3dm = rhino.File3dm.fromByteArray( arr )
const sf = file3dm.settings().renderSettings().safeFrame
console.log( `Safe Frame Enabled: ${ sf.enabled }` )
console.log( `Safe Frame ActionFrameXScale: ${ sf.actionFrameXScale }` )
sf.actionFrameXScale = 0.45
ONX_Model model;
model.Read(filename_in);
auto& sf = model.m_settings.m_RenderSettings.SafeFrame();
const auto on = sf.On();
const auto xs = sf.ActionFrameXScale();
sf.SetOn(true);
sf.SetActionFrameXScale(0.1f);
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);
import _rhino3dm
model = _rhino3dm.File3dm.Read(filename_in)
sl = model.Settings.RenderSettings.Skylight
print(sl.Enabled)
print(sl.ShadowIntensity)
sl.ShadowIntensity = 1.4
// node.js
import * as fs from 'fs' //only if running in node.js
import rhino3dm from 'rhino3dm'
const rhino = await rhino3dm()
const buffer = fs.readFileSync( filename_in )
/*
if you are running this in a browser, comment out the first line (the fs import) and replace the above line with these two lines:
const file = await fetch( filename_in )
const buffer = await file.arrayBuffer()
*/
const arr = new Uint8Array( buffer )
const file3dm = rhino.File3dm.fromByteArray( arr )
const sl = file3dm.settings().renderSettings().skylight
console.log( `Skylight Enabled: ${ sl.enabled }` )
console.log( `Skylight Shadow Intensity: ${ sl.shadowIntensity }` )
sl.shadowIntensity = 0.45
ONX_Model model;
model.Read(filename_in);
auto& sl = model.m_settings.m_RenderSettings.Skylight();
const auto on = sl.Enabled();
const auto si = sl.ShadowIntensity();
sl.SetEnabled(false);
sl.SetShadowIntensity(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);
import _rhino3dm
model = _rhino3dm.File3dm.Read(filename_in)
sun = model.Settings.RenderSettings.Sun;
print(sun.EnableOn);
print(sun.TimeZone);
print(sun.Year, sun.Month, sun.Day, sun.Hours)
print(sun.Azimuth)
print("Place sun observer at the Greenwich observatory in London")
sun.Latitude = 51.4769;
sun.Longitude = -0.0005;
print(sun.Azimuth)
sun.TimeZone = 0.0;
// node.js
import * as fs from 'fs' //only if running in node.js
import rhino3dm from 'rhino3dm'
const rhino = await rhino3dm()
const buffer = fs.readFileSync( filename_in )
/*
if you are running this in a browser, comment out the first line (the fs import) and replace the above line with these two lines:
const file = await fetch( filename_in )
const buffer = await file.arrayBuffer()
*/
const arr = new Uint8Array( buffer )
const file3dm = rhino.File3dm.fromByteArray( arr )
const sun = file3dm.settings().renderSettings().sun
console.log( `Sun enableOn: ${ sun.enableOn }` )
console.log( `Sun timeZone: ${ sun.timeZone }` )
console.log( `Sun azimuth: ${ sun.azimuth }` )
console.log( `Sun year: ${ sun.year }` )
console.log( `Sun month: ${ sun.month }` )
console.log( `Sun day: ${ sun.day }` )
console.log( `Sun hours: ${ sun.hours }` )
console.log('Place sun observer at the Greenwich observatory in London')
sun.latitude = 51.4769
sun.longitude = -0.0005
console.log( `Sun azimuth: ${ sun.azimuth }` )
sun.timeZone = 0.0;
ONX_Model model;
model.Read(filename_in);
auto& sun = model.m_settings.m_RenderSettings.Sun();
const auto on = sun.EnableOn();
const auto tz = sun.TimeZone();
sun.SetEnableOn(true);
sun.SetTimeZone(2.0);
sun.SetLocalDateTime(2022, 5, 1, 12.51);
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);
}
}
import _rhino3dm
model = _rhino3dm.File3dm.Read(filename_in)
post_effects = model.Settings.RenderSettings.PostEffects
for pe in post_effects :
print(pe.LocalName)
print("--------------------")
print("Id : ", pe.Id)
print("Type : ", pe.Type)
print("On : ", pe.On)
print("Shown: ", pe.Shown)
print("")
// node.js
import * as fs from 'fs' //only if running in node.js
import rhino3dm from 'rhino3dm'
const rhino = await rhino3dm()
const buffer = fs.readFileSync( filename_in )
/*
if you are running this in a browser, comment out the first line (the fs import) and replace the above line with these two lines:
const file = await fetch( filename_in )
const buffer = await file.arrayBuffer()
*/
const arr = new Uint8Array( buffer )
const file3dm = rhino.File3dm.fromByteArray( arr )
const pes = file3dm.settings().renderSettings().postEffects
for( let i = 0; i < pes.count; i ++ ) {
const pe = pes.get( i )
console.log( `Post Effect localName: ${ pe.localName }` )
console.log( `Post Effect id: ${ pe.id }` )
console.log( `Post Effect type: ${ pe.type.constructor.name }` )
console.log( `Post Effect on: ${ pe.on }` )
console.log( `Post Effect shown: ${ pe.shown }` )
console.log()
}
ONX_Model model;
model.Read(filename_in);
auto& post_effects = model.m_settings.m_RenderSettings.PostEffects();
ON_SimpleArray<ON_PostEffect*> post_effect_array;
post_effects.GetPostEffects(ON_PostEffect::Types::Early, post_effect_array);
for (int i = 0; i < post_effect_array.Count(); i++)
{
auto& post_effect = *post_effect_array[i];
if (post_effect.LocalName().CompareNoCase(L"bloom") == 0)
{
post_effect.SetParameter(SS_PEP_BLOOM_INTENSITY, 123.0f);
const auto v = post_effect.GetParameter(SS_PEP_BLOOM_INTENSITY);
ASSERT(v.AsFloat() == 123.0f);
}
}
model.Write(filename_out);
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);
}
import _rhino3dm
model = _rhino3dm.File3dm.Read(filename_in)
for rc in model.RenderContent :
if isinstance(rc, _rhino3dm.RenderMaterial) :
print(rc.TypeName)
print(rc.GetParameter("ior"))
print("Setting IOR and transparency")
_ = rc.SetParameter("ior", "2.5")
_ = rc.SetParameter("transparency", "0.5")
if isinstance(rc, _rhino3dm.RenderEnvironment) :
e = rc.ToEnvironment()
print(e.BackgroundColor)
if isinstance(rc, _rhino3dm.RenderTexture) :
print(rc.Filename)
// node.js
import * as fs from 'fs' //only if running in node.js
import rhino3dm from 'rhino3dm'
const rhino = await rhino3dm()
const buffer = fs.readFileSync( filename_in )
/*
if you are running this in a browser, comment out the first line (the fs import) and replace the above line with these two lines:
const file = await fetch( filename_in )
const buffer = await file.arrayBuffer()
*/
const arr = new Uint8Array( buffer )
const file3dm = rhino.File3dm.fromByteArray( arr )
for ( let i = 0; i < file3dm.renderContent().count; i ++ ) {
const rc = file3dm.renderContent().get(i)
switch( rc.kind ) {
case 'material':
console.log( `Render Material ior: ${ rc.getParameter( "ior" ) }` )
console.log( 'Setting IOR and transparency' )
rc.setParameter( 'ior', '2.5' )
rc.setParameter( 'transparency', '0.5' )
break
case 'environment':
console.log( `Render Environment Background Color: ${ rc.getParameter( 'background-color' ) }` )
break
case 'texture':
console.log( `Render Texture FileName: ${ rc.fileName }` )
break
}
}
ONX_Model model;
model.Read(filename_in);
ONX_ModelComponentIterator it(model, ON_ModelComponent::Type::RenderContent);
auto* component = it.FirstComponent();
while (nullptr != component)
{
const auto* mat = ON_RenderMaterial::Cast(component);
if (nullptr != mat)
{
const auto typeName = mat->TypeName();
wprintf(L"Type: %s\n", static_cast<const wchar_t*>(typeName));
const auto v = mat->GetParameter(ON_MATERIAL_IOR);
if (!v.IsNull())
{
wprintf(L"Setting IOR and transparency\n");
auto* mat_write = const_cast<ON_RenderMaterial*>(mat);
mat_write->SetParameter(ON_MATERIAL_IOR, 2.5);
mat_write->SetParameter(ON_MATERIAL_TRANSPARENCY_AMOUNT, 0.5);
}
}
component = it.NextComponent();
}
component = it.FirstComponent();
while (nullptr != component)
{
auto* env = ON_RenderEnvironment::Cast(component);
if (nullptr != env)
{
const auto on_env = env->ToOnEnvironment();
const auto col = on_env.BackgroundColor();
wprintf(L"Color: %u, %u, %u\n", col.Red(), col.Green(), col.Blue());
}
component = it.NextComponent();
}
component = it.FirstComponent();
while (nullptr != component)
{
auto* tex = ON_RenderTexture::Cast(component);
if (nullptr != tex)
{
const auto on_tex = tex->ToOnTexture();
const auto& file = on_tex.m_image_file_reference.FullPath();
wprintf(L"%s\n", static_cast<const wchar_t*>(file));
}
component = it.NextComponent();
}
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);
}
import os
import _rhino3dm
model = _rhino3dm.File3dm.Read(filename_in)
for ef in model.EmbeddedFiles :
dir = os.path.dirname(ef.Filename)
file = os.path.basename(ef.Filename)
new_file = os.path.join(dir, "CopyOf_" + file)
ef.Write(new_file)
// node.js
import * as fs from 'fs' //only if running in node.js
import rhino3dm from 'rhino3dm'
const rhino = await rhino3dm()
const buffer = fs.readFileSync( filename_in )
/*
if you are running this in a browser, comment out the first line (the fs import) and replace the above line with these two lines:
const file = await fetch( filename_in )
const buffer = await file.arrayBuffer()
*/
const arr = new Uint8Array( buffer )
const file3dm = rhino.File3dm.fromByteArray( arr )
const embeddedFiles = file3dm.embeddedFiles()
for( let i = 0; i < embeddedFiles.count; i ++ ) {
const ef = embeddedFiles.get( i )
console.log(`Embedded File fileName: ${file.fileName}`)
}
ONX_Model model;
model.Read(filename_in);
ONX_ModelComponentIterator it(model, ON_ModelComponent::Type::EmbeddedFile);
const auto* component = it.FirstComponent();
while (nullptr != component)
{
const auto* ef = ON_EmbeddedFile::Cast(component);
if (nullptr != ef)
{
const auto filename = ef->Filename();
const auto dir = ON_FileSystemPath::VolumeAndDirectoryFromPath(filename);
const auto file = ON_FileSystemPath::FileNameFromPath(filename, true);
const auto new_file = dir + L"CopyOf_" + file;
ef->SaveToFile(new_file);
}
component = it.NextComponent();
}
```d
</div>
</div>