Files
opennurbs/opennurbs_render_content.cpp
2023-07-14 02:54:08 -07:00

1560 lines
46 KiB
C++

//
// Copyright (c) 1993-2022 Robert McNeel & Associates. All rights reserved.
// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert
// McNeel & Associates.
//
// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
// MERCHANTABILITY ARE HEREBY DISCLAIMED.
//
// For complete openNURBS copyright information see <http://www.opennurbs.org>.
//
////////////////////////////////////////////////////////////////
#include "opennurbs.h"
#include "opennurbs_internal_defines.h"
#if !defined(ON_COMPILING_OPENNURBS)
// This check is included in all opennurbs source .c and .cpp files to insure
// ON_COMPILING_OPENNURBS is defined when opennurbs source is compiled.
// When opennurbs source is being compiled, ON_COMPILING_OPENNURBS is defined
// and the opennurbs .h files alter what is declared and how it is declared.
#error ON_COMPILING_OPENNURBS must be defined when compiling opennurbs
#endif
ON_OBJECT_IMPLEMENT(ON_Environment, ON_Object, "94BCA4D5-0FC7-435E-95F9-22F3927F9B2E");
class ON_Environment::CImpl
{
public:
CImpl();
CImpl(const CImpl& src);
public:
ON_Color m_back_col;
ON_Texture m_back_image;
BackgroundProjections m_back_proj = BackgroundProjections::Planar;
};
ON_Environment::CImpl::CImpl()
:
m_back_col(ON_Color(160, 160, 160))
{
}
ON_Environment::CImpl::CImpl(const CImpl& src)
{
m_back_col = src.m_back_col;
m_back_proj = src.m_back_proj;
m_back_image = src.m_back_image;
}
ON_Environment::ON_Environment()
{
m_impl = new CImpl;
}
ON_Environment::ON_Environment(const ON_Environment& src)
{
m_impl = new CImpl(*src.m_impl);
}
ON_Environment::~ON_Environment()
{
delete m_impl;
m_impl = nullptr;
}
static ON__UINT32 CRCOnlyRGB(ON__UINT32 current_remainder, const ON_Color& c)
{
const auto x = (unsigned int)c & 0x00FFFFFF;
return ON_CRC32(current_remainder, sizeof(x), &x);
}
ON__UINT32 ON_Texture_CRC(const ON_Texture& tex)
{
ON_wString file(tex.m_image_file_reference.FullPath());
#ifdef ON_RUNTIME_WIN
file.MakeLower();
#endif
ON__UINT32 crc = file.DataCRC(0);
crc = ON_CRC32(crc, sizeof(tex.m_mapping_channel_id), &tex.m_mapping_channel_id);
crc = ON_CRC32(crc, sizeof(tex.m_bOn), &tex.m_bOn);
crc = ON_CRC32(crc, sizeof(tex.m_type), &tex.m_type);
crc = ON_CRC32(crc, sizeof(tex.m_minfilter), &tex.m_minfilter);
crc = ON_CRC32(crc, sizeof(tex.m_magfilter), &tex.m_magfilter);
crc = ON_CRC32(crc, sizeof(tex.m_wrapu), &tex.m_wrapu);
crc = ON_CRC32(crc, sizeof(tex.m_wrapv), &tex.m_wrapv);
crc = ON_CRC32(crc, sizeof(tex.m_wrapw), &tex.m_wrapw);
crc = CRCOnlyRGB(crc, tex.m_border_color);
crc = CRCOnlyRGB(crc, tex.m_transparent_color);
crc = CRCOnlyRGB(crc, tex.m_blend_constant_RGB);
crc = ON_CRC32(crc, sizeof(tex.m_blend_order), &tex.m_blend_order);
const double amount = int(tex.m_blend_constant_A * 100.0) / 100.0;
crc = ON_CRC32(crc, sizeof(amount), &amount);
crc = ON_CRC32(crc, sizeof(tex.m_bump_scale), &tex.m_bump_scale);
crc = ON_CRC32(crc, sizeof(tex.m_uvw), &tex.m_uvw);
crc = ON_CRC32(crc, sizeof(tex.m_blend_A0), &tex.m_blend_A0);
crc = ON_CRC32(crc, sizeof(tex.m_blend_RGB0), &tex.m_blend_RGB0);
crc = ON_CRC32(crc, sizeof(tex.m_blend_A1), &tex.m_blend_A1);
crc = ON_CRC32(crc, sizeof(tex.m_blend_RGB1), &tex.m_blend_RGB1);
crc = ON_CRC32(crc, sizeof(tex.m_blend_A2), &tex.m_blend_A2);
crc = ON_CRC32(crc, sizeof(tex.m_blend_RGB2), &tex.m_blend_RGB2);
crc = ON_CRC32(crc, sizeof(tex.m_blend_A3), &tex.m_blend_A3);
crc = ON_CRC32(crc, sizeof(tex.m_blend_RGB3), &tex.m_blend_RGB3);
crc = ON_CRC32(crc, sizeof(tex.m_bTreatAsLinear), &tex.m_bTreatAsLinear);
return crc;
}
bool ON_Environment::operator == (const ON_Environment& env) const
{
if (m_impl->m_back_col < env.m_impl->m_back_col)
return false;
if (m_impl->m_back_col > env.m_impl->m_back_col)
return false;
if (m_impl->m_back_proj != env.m_impl->m_back_proj)
return false;
if (ON_Texture_CRC(m_impl->m_back_image) != ON_Texture_CRC(env.m_impl->m_back_image))
return false;
return true;
}
bool ON_Environment::operator != (const ON_Environment& env) const
{
return !(operator == (env));
}
const ON_Environment& ON_Environment::operator = (const ON_Environment& src)
{
if (this != &src)
{
delete m_impl;
m_impl = new CImpl(*src.m_impl);
}
return *this;
}
ON_Color ON_Environment::BackgroundColor(void) const
{
return m_impl->m_back_col;
}
void ON_Environment::SetBackgroundColor(const ON_Color& col)
{
m_impl->m_back_col = col;
}
const ON_Texture& ON_Environment::BackgroundImage(void) const
{
return m_impl->m_back_image;
}
void ON_Environment::SetBackgroundImage(const ON_Texture& tex)
{
m_impl->m_back_image = tex;
}
ON_Environment::BackgroundProjections ON_Environment::BackgroundProjection(void) const
{
return m_impl->m_back_proj;
}
void ON_Environment::SetBackgroundProjection(ON_Environment::BackgroundProjections proj)
{
m_impl->m_back_proj = proj;
}
ON_Environment::BackgroundProjections ON_Environment::ProjectionFromString(const wchar_t* wsz) // Static.
{
if (0 == on_wcsicmp(ON_ENVIRONMENT_PROJECTION_PLANAR, wsz)) return BackgroundProjections::Planar;
if (0 == on_wcsicmp(ON_ENVIRONMENT_PROJECTION_SPHERICAL, wsz)) return BackgroundProjections::Spherical;
if (0 == on_wcsicmp(ON_ENVIRONMENT_PROJECTION_EMAP, wsz)) return BackgroundProjections::Emap;
if (0 == on_wcsicmp(ON_ENVIRONMENT_PROJECTION_BOX, wsz)) return BackgroundProjections::Box;
if (0 == on_wcsicmp(ON_ENVIRONMENT_PROJECTION_LIGHT_PROBE, wsz)) return BackgroundProjections::LightProbe;
if (0 == on_wcsicmp(ON_ENVIRONMENT_PROJECTION_CUBE_MAP, wsz)) return BackgroundProjections::CubeMap;
if (0 == on_wcsicmp(ON_ENVIRONMENT_PROJECTION_CUBE_MAP_VERT, wsz)) return BackgroundProjections::VerticalCrossCubeMap;
if (0 == on_wcsicmp(ON_ENVIRONMENT_PROJECTION_CUBE_MAP_HORZ, wsz)) return BackgroundProjections::HorizontalCrossCubeMap;
if (0 == on_wcsicmp(ON_ENVIRONMENT_PROJECTION_HEMISPHERICAL, wsz)) return BackgroundProjections::Hemispherical;
ON_ASSERT(false);
return BackgroundProjections::Planar;
}
const wchar_t* ON_Environment::StringFromProjection(BackgroundProjections proj) // Static.
{
switch (proj)
{
case BackgroundProjections::Planar: return ON_ENVIRONMENT_PROJECTION_PLANAR;
case BackgroundProjections::Spherical: return ON_ENVIRONMENT_PROJECTION_SPHERICAL;
case BackgroundProjections::Emap: return ON_ENVIRONMENT_PROJECTION_EMAP;
case BackgroundProjections::Box: return ON_ENVIRONMENT_PROJECTION_BOX;
case BackgroundProjections::LightProbe: return ON_ENVIRONMENT_PROJECTION_LIGHT_PROBE;
case BackgroundProjections::CubeMap: return ON_ENVIRONMENT_PROJECTION_CUBE_MAP;
case BackgroundProjections::VerticalCrossCubeMap: return ON_ENVIRONMENT_PROJECTION_CUBE_MAP_VERT;
case BackgroundProjections::HorizontalCrossCubeMap: return ON_ENVIRONMENT_PROJECTION_CUBE_MAP_HORZ;
case BackgroundProjections::Hemispherical: return ON_ENVIRONMENT_PROJECTION_HEMISPHERICAL;
default: break;
}
ON_ASSERT(false);
return ON_ENVIRONMENT_PROJECTION_PLANAR;
}
void* ON_Environment::EVF(const wchar_t* wszFunc, void* pvData)
{
return nullptr;
}
ON_UUID RdkPlugInId(void)
{
static ON_UUID uuid = { 0x16592D58, 0x4A2F, 0x401D, { 0xBF, 0x5E, 0x3B, 0x87, 0x74, 0x1C, 0x1B, 0x1B } };
return uuid;
}
ON_UUID UniversalRenderEngineId(void)
{
static ON_UUID uuid = { 0x99999999, 0x9999, 0x9999, { 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99 } };
return uuid;
}
class ON_RenderContentPrivate
{
public:
ON_RenderContentPrivate(ON_RenderContent& rc, const wchar_t* kind);
virtual ~ON_RenderContentPrivate();
void SetXMLNode(const ON_XMLNode& node);
const ON_XMLNode* XMLNode_Simulation(void) const;
ON_RenderContent& TopLevel(void);
bool AddChild(ON_RenderContent& rc);
void DeleteAllChildren(void);
ON_XMLVariant GetPropertyValue(const wchar_t* name) const;
void SetPropertyValue(const wchar_t* name, const ON_XMLVariant& value);
ON_RenderContent* FindChild(const wchar_t* child_slot_name) const;
bool SetChild(ON_RenderContent* child, const wchar_t* child_slot_name);
bool ChangeChild(ON_RenderContent* old_child, ON_RenderContent* new_child);
public:
void InternalSetPropertyValue(const wchar_t* name, const ON_XMLVariant& value);
static void SetRenderContentNodeRecursive(const ON_RenderContent& rc, ON_XMLNode& node);
static void BuildXMLHierarchy(const ON_RenderContent& rc, ON_XMLNode& node);
static ON_XMLNode* NewXMLNodeRecursive(const ON_RenderContent& rc);
static void SetModel(const ON_RenderContent& rc, ONX_Model& model);
static ON_RenderContent* NewRenderContentFromNode(const ON_XMLNode& node);
private:
ON_RenderContent* FindLastChild(void) const;
ON_RenderContent* FindPrevSibling(ON_RenderContent* child) const;
public:
ONX_Model* m_model = nullptr;
ON_XMLNode m_node;
ON_RenderContent& m_render_content;
ON_RenderContent* m_parent = nullptr;
ON_RenderContent* m_first_child = nullptr;
ON_RenderContent* m_next_sibling = nullptr;
mutable std::recursive_mutex m_mutex;
};
ON_RenderContentPrivate::ON_RenderContentPrivate(ON_RenderContent& rc, const wchar_t* kind)
:
m_node(kind),
m_render_content(rc)
{
}
ON_RenderContentPrivate::~ON_RenderContentPrivate()
{
DeleteAllChildren();
}
const ON_XMLNode* ON_RenderContentPrivate::XMLNode_Simulation(void) const
{
return m_node.GetNamedChild(ON_RENDER_CONTENT_SIMULATION);
}
ON_XMLVariant ON_RenderContentPrivate::GetPropertyValue(const wchar_t* name) const
{
// Gets a property from the content node. This is one of:
//
// - the material node <material... >
// - the environment node <environment... >
// - the texture node <texture... >
std::lock_guard<std::recursive_mutex> lg(m_mutex);
ON_XMLVariant v;
const ON_XMLProperty* pProp = m_node.GetNamedProperty(name);
if (nullptr != pProp)
{
v = pProp->GetValue();
}
return v;
}
void ON_RenderContentPrivate::SetPropertyValue(const wchar_t* name, const ON_XMLVariant& value)
{
std::lock_guard<std::recursive_mutex> lg(m_mutex);
InternalSetPropertyValue(name, value);
}
void ON_RenderContentPrivate::InternalSetPropertyValue(const wchar_t* name, const ON_XMLVariant& value)
{
// Sets a property on the content node. This is one of:
//
// - the material node <material... >
// - the environment node <environment... >
// - the texture node <texture... >
ON_XMLProperty* pProp = m_node.GetNamedProperty(name);
if (nullptr != pProp)
{
pProp->SetValue(value);
}
else
{
pProp = m_node.AttachProperty(new ON_XMLProperty(name, value));
}
}
void ON_RenderContentPrivate::SetXMLNode(const ON_XMLNode& node)
{
std::lock_guard<std::recursive_mutex> lg(m_mutex);
// Copy the incoming XML node. The render content will only store a copy of its own XML, so
// we will have to prune this copy as we find children and create render content children
// for all the XML children.
ON_XMLNode node_copy = node;
// Iterate over the child nodes of the XML node being set to this content.
auto it = node_copy.GetChildIterator();
ON_XMLNode* child_node = nullptr;
while (nullptr != (child_node = it.GetNextChild()))
{
// See if the child node is a content node.
const ON_wString& name = child_node->TagName();
if ((ON_KIND_MATERIAL == name) || (ON_KIND_ENVIRONMENT == name) || (ON_KIND_TEXTURE == name))
{
// Yes, so we are going to add a new render content to this hierarchy (recursively)
// and remove this child node from the copy of the XML node.
ON_RenderContent* child_rc = NewRenderContentFromNode(*child_node);
if (nullptr != child_rc)
{
// Add the new content as a child of this content.
AddChild(*child_rc);
}
delete node_copy.DetachChild(*child_node);
}
}
// Copy the pruned copy of the XML node. This node does not have any child content nodes.
m_node = node_copy;
// Copy the XML instance name to the component name.
m_render_content.SetName(GetPropertyValue(ON_RENDER_CONTENT_INSTANCE_NAME).AsString());
// Copy the XML instance id to the component id.
m_render_content.SetId(GetPropertyValue(ON_RENDER_CONTENT_INSTANCE_ID).AsUuid());
}
bool ON_RenderContentPrivate::AddChild(ON_RenderContent& child)
{
if ((nullptr != child._private->m_model) || (nullptr != child._private->m_parent) || (nullptr != child._private->m_next_sibling))
return false;
if (nullptr == m_first_child)
{
m_first_child = &child;
}
else
{
ON_RenderContent* last_child = FindLastChild();
if (nullptr == last_child)
return false;
last_child->_private->m_next_sibling = &child;
}
child._private->m_next_sibling = nullptr;
child._private->m_parent = &m_render_content;
return true;
}
void ON_RenderContentPrivate::DeleteAllChildren(void)
{
std::lock_guard<std::recursive_mutex> lg(m_mutex);
if (nullptr == m_first_child)
return;
ON_RenderContent* child_rc = m_first_child;
while (nullptr != child_rc)
{
auto* delete_rc = child_rc;
child_rc = child_rc->_private->m_next_sibling;
delete delete_rc;
}
m_first_child = nullptr;
}
ON_RenderContent* ON_RenderContentPrivate::FindLastChild(void) const
{
ON_RenderContent* result = nullptr;
ON_RenderContent* candidate = m_first_child;
while (nullptr != candidate)
{
result = candidate;
candidate = candidate->_private->m_next_sibling;
}
return result;
}
ON_RenderContent* ON_RenderContentPrivate::FindPrevSibling(ON_RenderContent* child) const
{
if (child != m_first_child)
{
ON_RenderContent* candidate = m_first_child;
while (nullptr != candidate)
{
if (child == candidate->_private->m_next_sibling)
return candidate;
candidate = candidate->_private->m_next_sibling;
}
}
return nullptr;
}
ON_RenderContent& ON_RenderContentPrivate::TopLevel(void)
{
if (nullptr != m_parent)
{
return m_parent->_private->TopLevel();
}
return m_render_content;
}
bool ON_RenderContentPrivate::ChangeChild(ON_RenderContent* old_child, ON_RenderContent* new_child)
{
if (nullptr == old_child)
return false;
if (old_child == m_first_child)
{
if (nullptr != new_child)
{
m_first_child = new_child;
}
else
{
m_first_child = old_child->_private->m_next_sibling;
}
}
else
{
const ON_RenderContent* prev_sibling = FindPrevSibling(old_child);
if (nullptr == prev_sibling)
return false;
if (nullptr != new_child)
{
prev_sibling->_private->m_next_sibling = new_child;
}
else
{
prev_sibling->_private->m_next_sibling = old_child->_private->m_next_sibling;
}
}
if (nullptr != new_child)
{
new_child->_private->m_next_sibling = old_child->_private->m_next_sibling;
new_child->_private->m_parent = old_child->_private->m_parent;
}
delete old_child;
return true;
}
ON_RenderContent* ON_RenderContentPrivate::FindChild(const wchar_t* child_slot_name) const
{
std::lock_guard<std::recursive_mutex> lg(m_mutex);
ON_RenderContent* child_rc = m_first_child;
while (nullptr != child_rc)
{
if (child_rc->ChildSlotName() == child_slot_name)
return child_rc;
child_rc = child_rc->_private->m_next_sibling;
}
return nullptr;
}
bool ON_RenderContentPrivate::SetChild(ON_RenderContent* child, const wchar_t* child_slot_name)
{
std::lock_guard<std::recursive_mutex> lg(m_mutex);
if (nullptr != child)
{
if (nullptr != child->_private->m_model)
return false;
if (nullptr != child->_private->m_parent)
return false;
if ((nullptr == child_slot_name) || (0 == child_slot_name[0]))
return false;
child->_private->SetPropertyValue(ON_RENDER_CONTENT_CHILD_SLOT_NAME, child_slot_name);
}
// Get any existing child with the same child slot name (may be null).
auto* existing_child = FindChild(child_slot_name);
if (nullptr != existing_child)
{
// There is an existing child with the same child slot name; replace it.
if (!ChangeChild(existing_child, child)) // Deletes existing_child.
return false;
}
else
{
// No existing child; just add the new one.
if (nullptr != child)
{
if (!AddChild(*child))
return false;
}
}
if (nullptr != child)
{
auto* pModel = TopLevel()._private->m_model;
child->_private->m_model = pModel;
}
return true;
}
void ON_RenderContentPrivate::SetRenderContentNodeRecursive(const ON_RenderContent& rc, ON_XMLNode& node) // Static.
{
// Copy the component name to the XML instance name.
rc._private->SetPropertyValue(ON_RENDER_CONTENT_INSTANCE_NAME, rc.Name());
// Copy the component id to the XML instance id.
rc._private->SetPropertyValue(ON_RENDER_CONTENT_INSTANCE_ID, rc.Id());
auto* child_node = new ON_XMLNode(rc.XMLNode());
node.AttachChildNode(child_node);
auto it = rc.GetChildIterator();
ON_RenderContent* child_rc;
while (nullptr != (child_rc = it.GetNextChild()))
{
SetRenderContentNodeRecursive(*child_rc, *child_node);
}
}
void ON_RenderContentPrivate::BuildXMLHierarchy(const ON_RenderContent& rc, ON_XMLNode& node) // Static.
{
// Recursively builds 'node' from the tree structure of the XML nodes in 'rc' and its children.
node = rc._private->m_node;
auto* child_rc = rc._private->m_first_child;
while (nullptr != child_rc)
{
auto* child_node = new ON_XMLNode(L"");
BuildXMLHierarchy(*child_rc, *child_node);
node.AttachChildNode(child_node);
child_rc = child_rc->_private->m_next_sibling;
}
}
ON_XMLNode* ON_RenderContentPrivate::NewXMLNodeRecursive(const ON_RenderContent& rc) // Static.
{
ON_XMLNode* node = new ON_XMLNode(rc._private->m_node);
ON_RenderContent* child_rc = rc._private->m_first_child;
while (nullptr != child_rc)
{
ON_XMLNode* child_node = NewXMLNodeRecursive(*child_rc);
if (nullptr != child_node)
{
node->AttachChildNode(child_node);
}
child_rc = child_rc->_private->m_next_sibling;
}
return node;
}
void ON_RenderContentPrivate::SetModel(const ON_RenderContent& rc, ONX_Model& model) // Static.
{
rc._private->m_model = &model;
auto it = rc.GetChildIterator();
ON_RenderContent* child_rc = nullptr;
while (nullptr != (child_rc = it.GetNextChild()))
{
SetModel(*child_rc, model);
}
}
ON_RenderContent* ON_RenderContentPrivate::NewRenderContentFromNode(const ON_XMLNode& node) // Static.
{
ON_RenderContent* rc = nullptr;
const ON_wString& kind = node.TagName();
if (ON_KIND_MATERIAL == kind)
rc = new ON_RenderMaterial;
else
if (ON_KIND_ENVIRONMENT == kind)
rc = new ON_RenderEnvironment;
else
if (ON_KIND_TEXTURE == kind)
rc = new ON_RenderTexture;
if (nullptr != rc)
{
rc->_private->SetXMLNode(node);
}
return rc;
}
ON_VIRTUAL_OBJECT_IMPLEMENT(ON_RenderContent, ON_ModelComponent, "A98DEDDA-E4FA-4E1E-9BD3-2A0695C6D4E9");
ON_RenderContent::ON_RenderContent(const wchar_t* kind)
:
ON_ModelComponent(ON_ModelComponent::Type::RenderContent)
{
_private = new (_PRIVATE) ON_RenderContentPrivate(*this, kind); PRIVATE_CHECK(ON_RenderContentPrivate);
// Set a unique instance id.
ON_UUID uuid;
ON_CreateUuid(uuid);
SetId(uuid);
// Set the plug-in id to the RDK plug-in id.
_private->InternalSetPropertyValue(ON_RENDER_CONTENT_PLUG_IN_ID, RdkPlugInId());
// Set the render engine id to 'universal'.
_private->InternalSetPropertyValue(ON_RENDER_CONTENT_RENDER_ENGINE_ID, UniversalRenderEngineId());
}
ON_RenderContent::ON_RenderContent(const ON_RenderContent& rc)
:
ON_ModelComponent(ON_ModelComponent::Type::RenderContent, rc)
{
_private = new (_PRIVATE) ON_RenderContentPrivate(*this, L""); PRIVATE_CHECK(ON_RenderContentPrivate);
operator = (rc);
}
ON_RenderContent::~ON_RenderContent()
{
_private->~ON_RenderContentPrivate();
_private = nullptr;
}
const ON_RenderContent& ON_RenderContent::operator = (const ON_RenderContent& rc)
{
if (this != &rc)
{
ON_XMLRootNode root;
ON_RenderContentPrivate::BuildXMLHierarchy(rc, root);
_private->SetXMLNode(root);
}
return *this;
}
ON_wString ON_RenderContent::TypeName(void) const
{
return _private->GetPropertyValue(ON_RENDER_CONTENT_TYPE_NAME).AsString();
}
void ON_RenderContent::SetTypeName(const wchar_t* name)
{
_private->SetPropertyValue(ON_RENDER_CONTENT_TYPE_NAME, name);
}
ON_wString ON_RenderContent::Notes(void) const
{
return _private->GetPropertyValue(ON_RENDER_CONTENT_NOTES).AsString();
}
void ON_RenderContent::SetNotes(const wchar_t* notes)
{
_private->SetPropertyValue(ON_RENDER_CONTENT_NOTES, notes);
}
ON_wString ON_RenderContent::Tags(void) const
{
return _private->GetPropertyValue(ON_RENDER_CONTENT_TAGS).AsString();
}
void ON_RenderContent::SetTags(const wchar_t* tags)
{
_private->SetPropertyValue(ON_RENDER_CONTENT_TAGS, tags);
}
ON_UUID ON_RenderContent::TypeId(void) const
{
return _private->GetPropertyValue(ON_RENDER_CONTENT_TYPE_ID).AsUuid();
}
void ON_RenderContent::SetTypeId(const ON_UUID& uuid)
{
_private->SetPropertyValue(ON_RENDER_CONTENT_TYPE_ID, uuid);
}
ON_UUID ON_RenderContent::RenderEngineId(void) const
{
return _private->GetPropertyValue(ON_RENDER_CONTENT_RENDER_ENGINE_ID).AsUuid();
}
void ON_RenderContent::SetRenderEngineId(const ON_UUID& uuid)
{
_private->SetPropertyValue(ON_RENDER_CONTENT_RENDER_ENGINE_ID, uuid);
}
ON_UUID ON_RenderContent::PlugInId(void) const
{
return _private->GetPropertyValue(ON_RENDER_CONTENT_PLUG_IN_ID).AsUuid();
}
void ON_RenderContent::SetPlugInId(const ON_UUID& uuid)
{
_private->SetPropertyValue(ON_RENDER_CONTENT_PLUG_IN_ID, uuid);
}
ON_UUID ON_RenderContent::GroupId(void) const
{
return _private->GetPropertyValue(ON_RENDER_CONTENT_GROUP_ID).AsUuid();
}
void ON_RenderContent::SetGroupId(const ON_UUID& group)
{
_private->SetPropertyValue(ON_RENDER_CONTENT_GROUP_ID, group);
}
bool ON_RenderContent::Hidden(void) const
{
return _private->GetPropertyValue(ON_RENDER_CONTENT_HIDDEN).AsBool();
}
void ON_RenderContent::SetHidden(bool hidden)
{
_private->SetPropertyValue(ON_RENDER_CONTENT_HIDDEN, hidden);
}
bool ON_RenderContent::Reference(void) const
{
return _private->GetPropertyValue(ON_RENDER_CONTENT_REFERENCE).AsBool();
}
void ON_RenderContent::SetReference(bool ref)
{
_private->SetPropertyValue(ON_RENDER_CONTENT_REFERENCE, ref);
}
bool ON_RenderContent::AutoDelete(void) const
{
return _private->GetPropertyValue(ON_RENDER_CONTENT_AUTO_DELETE).AsBool();
}
void ON_RenderContent::SetAutoDelete(bool autodel)
{
_private->SetPropertyValue(ON_RENDER_CONTENT_AUTO_DELETE, autodel);
}
ON_XMLVariant ON_RenderContent::GetParameter(const wchar_t* name) const
{
std::lock_guard<std::recursive_mutex> lg(_private->m_mutex);
ON_XMLVariant value;
value.SetNull();
// Try to get the new V8 parameter section.
const ON_XMLNode* node = _private->m_node.GetNamedChild(ON_RENDER_CONTENT_PARAMETERS_V8);
if (nullptr != node)
{
// Got it, so use the new ON_XMLParametersV8 to get the parameter's value.
ON_XMLParametersV8 p(*node);
p.GetParam(name, value);
}
else
{
// Either no V8 section was found or the parameter isn't there yet.
// Try to get the legacy parameter section. This should not fail.
node = _private->m_node.GetNamedChild(ON_RENDER_CONTENT_PARAMETERS);
if (nullptr != node)
{
// Got it, so use the legacy ON_XMLParameters to get the parameter's value.
ON_XMLParameters p(*node);
p.GetParam(name, value);
}
}
return value;
}
bool ON_RenderContent::SetParameter(const wchar_t* name, const ON_XMLVariant& value)
{
std::lock_guard<std::recursive_mutex> lg(_private->m_mutex);
bool success = false;
// Create / get the new V8 parameter section.
auto* node = _private->m_node.CreateNodeAtPath(ON_RENDER_CONTENT_PARAMETERS_V8);
if (nullptr != node)
{
// Use the new ON_XMLParametersV8 to write the parameter's value.
ON_XMLParametersV8 p(*node);
if (nullptr != p.SetParam(name, value))
success = true;
}
// Create / get the legacy parameter section.
node = _private->m_node.CreateNodeAtPath(ON_RENDER_CONTENT_PARAMETERS);
if (nullptr != node)
{
// Use the legacy ON_XMLParameters to write the parameter's value.
ON_XMLParameters p(*node);
if (nullptr != p.SetParam(name, value))
success = true;
}
return success;
}
ON_RenderContent::ChildIterator ON_RenderContent::GetChildIterator(void) const
{
return ChildIterator(this);
}
ON_RenderContent* ON_RenderContent::Parent(void) const
{
return _private->m_parent;
}
ON_RenderContent* ON_RenderContent::FirstChild(void) const
{
return _private->m_first_child;
}
ON_RenderContent* ON_RenderContent::NextSibling(void) const
{
return _private->m_next_sibling;
}
ON_RenderContent& ON_RenderContent::TopLevel(void) const
{
return _private->TopLevel();
}
bool ON_RenderContent::IsTopLevel(void) const
{
return nullptr == _private->m_parent;
}
bool ON_RenderContent::IsChild(void) const
{
return nullptr != _private->m_parent;
}
bool ON_RenderContent::SetChild(const ON_RenderContent& child, const wchar_t* child_slot_name)
{
return _private->SetChild(child.Duplicate(), child_slot_name);
}
bool ON_RenderContent::DeleteChild(const wchar_t* child_slot_name)
{
return _private->SetChild(nullptr, child_slot_name);
}
ON_wString ON_RenderContent::ChildSlotName(void) const
{
return _private->GetPropertyValue(ON_RENDER_CONTENT_CHILD_SLOT_NAME).AsString();
}
void ON_RenderContent::SetChildSlotName(const wchar_t* csn)
{
_private->SetPropertyValue(ON_RENDER_CONTENT_CHILD_SLOT_NAME, csn);
}
#define MAT_POSTFIX_ON L"on"
#define MAT_POSTFIX_AMOUNT L"amount"
#define MAT_POSTFIX_DOUBLE_AMOUNT L"double-amount"
#define MAT_POSTFIX_FILTER_ON L"filter-on"
bool ON_RenderContent::ChildSlotOn(const wchar_t* child_slot_name) const
{
const auto s = ON_wString(child_slot_name) + L"-" MAT_POSTFIX_ON;
return GetParameter(s).AsBool();
}
bool ON_RenderContent::SetChildSlotOn(bool on, const wchar_t* child_slot_name)
{
const auto s = ON_wString(child_slot_name) + L"-" MAT_POSTFIX_ON;
return SetParameter(s, on);
}
double ON_RenderContent::ChildSlotAmount(const wchar_t* child_slot_name, double default_value) const
{
// This is complicated. See https://mcneel.myjetbrains.com/youtrack/issue/RH-58417
// Try to get the new double amount value in the range 0..1.
auto s = ON_wString(child_slot_name) + L"-" MAT_POSTFIX_DOUBLE_AMOUNT;
auto v = GetParameter(s);
if (!v.IsNull())
{
// Got it, so return it in the range 0..100.
return v.AsDouble() * 100.0;
}
// Couldn't get it so get the legacy amount value. This value is problematic (which is why we added
// the new double amount). The reason is that originally, the value was supposed to be in the range
// 0..100, and the Physically Based material is an example of a material that does this. But due to
// an oversight, the Custom Material saved this in the range 0..1. This means that here, in generic
// code that doesn't know which class saved the data, we have to figure out what range it's in by
// looking at the variant's type.
s = ON_wString(child_slot_name) + L"-" MAT_POSTFIX_AMOUNT;
v = GetParameter(s);
if (!v.IsNull())
{
if (v.Type() == ON_XMLVariant::Types::Integer)
{
// Got it as an integer so it's already in the range 0..100.
return double(v.AsInteger());
}
else
{
// The double value is in the range 0..1. Return it in the range 0..100.
return v.AsDouble() * 100.0;
}
}
return default_value;
}
bool ON_RenderContent::SetChildSlotAmount(double amount, const wchar_t* child_slot_name)
{
const auto s = ON_wString(child_slot_name) + L"-" MAT_POSTFIX_DOUBLE_AMOUNT;
return SetParameter(s, amount / 100.0);
}
const ON_RenderContent* ON_RenderContent::FindChild(const wchar_t* child_slot_name) const
{
return _private->FindChild(child_slot_name);
}
ON_wString ON_RenderContent::XML(bool recursive) const
{
ON_XMLNode* node = &_private->m_node;
if (recursive)
{
node = ON_RenderContentPrivate::NewXMLNodeRecursive(*this);
}
const ON__UINT32 logical_count = node->WriteToStream(nullptr, 0);
auto* stream = new wchar_t[size_t(logical_count) + 1];
node->WriteToStream(stream, logical_count);
stream[logical_count] = 0;
const ON_wString xml = stream;
delete[] stream;
if (recursive)
delete node;
return xml;
}
bool ON_RenderContent::SetXML(const wchar_t* xml)
{
ON_XMLRootNode node;
if (ON_XMLNode::ReadError == node.ReadFromStream(xml))
return false;
_private->SetXMLNode(node);
return true;
}
const ON_XMLNode& ON_RenderContent::XMLNode(void) const
{
return _private->m_node;
}
ON_wString ON_RenderContent::Kind(void) const
{
return _private->m_node.TagName();
}
const ON_RenderContent* ON_RenderContent::FromModelComponentRef(const ON_ModelComponentReference& ref,
const ON_RenderContent* none_return_value) // Static.
{
const auto* rc = ON_RenderContent::Cast(ref.ModelComponent());
if (nullptr != rc)
return rc;
return none_return_value;
}
void* ON_RenderContent::EVF(const wchar_t* func, void* data)
{
return nullptr;
}
// ON_RenderContent::ChildIterator
class ON_RenderContentChildIteratorPrivate final
{
public:
ON_RenderContent* _current = nullptr;
};
ON_RenderContent::ChildIterator::ChildIterator(const ON_RenderContent* parent_rc)
{
_private = new ON_RenderContentChildIteratorPrivate;
if (nullptr != parent_rc)
{
_private->_current = parent_rc->_private->m_first_child;
}
}
ON_RenderContent::ChildIterator::~ChildIterator()
{
delete _private;
}
ON_RenderContent* ON_RenderContent::ChildIterator::GetNextChild(void)
{
ON_RenderContent* rc = _private->_current;
if (nullptr != rc)
{
_private->_current = rc->_private->m_next_sibling;
}
return rc;
}
void* ON_RenderContent::ChildIterator::EVF(const wchar_t*, void*)
{
return nullptr;
}
void SetModel(const ON_RenderContent& rc, ONX_Model& model)
{
ON_RenderContentPrivate::SetModel(rc, model);
}
ON_RenderContent* NewRenderContentFromNode(const ON_XMLNode& node)
{
return ON_RenderContentPrivate::NewRenderContentFromNode(node);
}
void SetRenderContentNodeRecursive(const ON_RenderContent& rc, ON_XMLNode& node)
{
ON_RenderContentPrivate::SetRenderContentNodeRecursive(rc, node);
}
// ON_RenderMaterial
ON_OBJECT_IMPLEMENT(ON_RenderMaterial, ON_RenderContent, "493E6601-F95B-4A5D-BB6F-2F6633076907");
ON_RenderMaterial::ON_RenderMaterial()
:
ON_RenderContent(ON_KIND_MATERIAL)
{
}
ON_RenderMaterial::ON_RenderMaterial(const ON_RenderMaterial& mat)
:
ON_RenderContent(mat)
{
}
ON_RenderMaterial::~ON_RenderMaterial()
{
}
const ON_RenderContent& ON_RenderMaterial::operator = (const ON_RenderContent& c)
{
ON_RenderContent::operator = (c);
return *this;
}
const ON_RenderMaterial& ON_RenderMaterial::operator = (const ON_RenderMaterial& mat)
{
ON_RenderContent::operator = (mat);
return *this;
}
ON_XMLVariant ParamHelper(const ON_XMLParameters& p, const wchar_t* name)
{
ON_XMLVariant value;
if (!p.GetParam(name, value))
value = L"";
return value;
}
ON_Material ON_RenderMaterial::ToOnMaterial(void) const
{
std::lock_guard<std::recursive_mutex> lg(_private->m_mutex);
ON_Material mat;
const ON_XMLNode* sim_node = _private->XMLNode_Simulation();
if (nullptr != sim_node)
{
ON_XMLParameters p(*sim_node);
mat.m_ambient = ParamHelper(p, ON_MATERIAL_AMBIENT ).AsColor();
mat.m_diffuse = ParamHelper(p, ON_MATERIAL_DIFFUSE ).AsColor();
mat.m_emission = ParamHelper(p, ON_MATERIAL_EMISSION ).AsColor();
mat.m_specular = ParamHelper(p, ON_MATERIAL_SPECULAR ).AsColor();
mat.m_shine = ParamHelper(p, ON_MATERIAL_SHINE ).AsDouble() * ON_Material::MaxShine;
mat.m_reflection = ParamHelper(p, ON_MATERIAL_SIM_REFLECTION_COLOR ).AsColor();
mat.m_reflectivity = ParamHelper(p, ON_MATERIAL_REFLECTIVITY_AMOUNT ).AsDouble();
mat.m_transparency = ParamHelper(p, ON_MATERIAL_TRANSPARENCY_AMOUNT ).AsDouble();
mat.m_transparent = ParamHelper(p, ON_MATERIAL_SIM_TRANSPARENT_COLOR).AsColor();
mat.m_index_of_refraction = ParamHelper(p, ON_MATERIAL_IOR ).AsDouble();
mat.m_reflection_glossiness = 1.0 - ParamHelper(p, ON_MATERIAL_POLISH_AMOUNT ).AsDouble();
mat.m_refraction_glossiness = 1.0 - ParamHelper(p, ON_MATERIAL_CLARITY_AMOUNT ).AsDouble();
mat.SetFresnelReflections ( ParamHelper(p, ON_MATERIAL_FRESNEL_ENABLED ).AsBool());
mat.SetDisableLighting ( ParamHelper(p, ON_MATERIAL_DISABLE_LIGHTING ).AsBool());
mat.m_fresnel_index_of_refraction = 1.56;
if (ParamHelper(p, ON_MATERIAL_IS_PHYSICALLY_BASED).AsBool())
{
mat.ToPhysicallyBased();
auto pbm = mat.PhysicallyBased();
auto brdf = ON_PhysicallyBasedMaterial::BRDFs::GGX;
const ON_wString s = ParamHelper(p, ON_PBR_MATERIAL_BRDF).AsString();
if (s == ON_PBR_MATERIAL_BRDF_WARD)
brdf = ON_PhysicallyBasedMaterial::BRDFs::Ward;
pbm->SetBRDF(brdf);
pbm->SetBaseColor (ParamHelper(p, ON_PBR_MATERIAL_BASE_COLOR).AsColor());
pbm->SetSubsurface (ParamHelper(p, ON_PBR_MATERIAL_SUBSURFACE).AsDouble());
pbm->SetSubsurfaceScatteringColor (ParamHelper(p, ON_PBR_MATERIAL_SUBSURFACE_SCATTERING_COLOR).AsColor());
pbm->SetSubsurfaceScatteringRadius(ParamHelper(p, ON_PBR_MATERIAL_SUBSURFACE_SCATTERING_RADIUS).AsDouble());
pbm->SetSpecular (ParamHelper(p, ON_PBR_MATERIAL_SPECULAR).AsDouble());
pbm->SetSpecularTint (ParamHelper(p, ON_PBR_MATERIAL_SPECULAR_TINT).AsDouble());
pbm->SetMetallic (ParamHelper(p, ON_PBR_MATERIAL_METALLIC).AsDouble());
pbm->SetRoughness (ParamHelper(p, ON_PBR_MATERIAL_ROUGHNESS).AsDouble());
pbm->SetAnisotropic (ParamHelper(p, ON_PBR_MATERIAL_ANISOTROPIC).AsDouble());
pbm->SetAnisotropicRotation (ParamHelper(p, ON_PBR_MATERIAL_ANISOTROPIC_ROTATION).AsDouble());
pbm->SetSheen (ParamHelper(p, ON_PBR_MATERIAL_SHEEN).AsDouble());
pbm->SetSheenTint (ParamHelper(p, ON_PBR_MATERIAL_SHEEN_TINT).AsDouble());
pbm->SetClearcoat (ParamHelper(p, ON_PBR_MATERIAL_CLEARCOAT).AsDouble());
pbm->SetClearcoatRoughness (ParamHelper(p, ON_PBR_MATERIAL_CLEARCOAT_ROUGHNESS).AsDouble());
pbm->SetOpacity (ParamHelper(p, ON_PBR_MATERIAL_OPACITY).AsDouble());
pbm->SetOpacityIOR (ParamHelper(p, ON_PBR_MATERIAL_OPACITY_IOR).AsDouble());
pbm->SetOpacityRoughness (ParamHelper(p, ON_PBR_MATERIAL_OPACITY_ROUGHNESS).AsDouble());
pbm->SetEmission (ParamHelper(p, ON_PBR_MATERIAL_EMISSION_COLOR).AsColor());
pbm->SetAlpha (ParamHelper(p, ON_PBR_MATERIAL_ALPHA).AsDouble());
pbm->SetUseBaseColorTextureAlphaForObjectAlphaTransparencyTexture(ParamHelper(p, ON_PBR_MATERIAL_USE_BASE_COLOR_TEXTURE_ALPHA).AsBool());
}
mat.SetName(Name());
mat.m_textures.Destroy();
// Iterator over the children.
int count = 1;
while (true)
{
ON_Texture tex;
ON_XMLVariant v;
ON_wString s;
s.Format(ON_RENDER_MATERIAL_TEXTURE_SIMULATION_FORMAT, count);
if (!p.GetParam(s + ON_RENDER_MATERIAL_TEXTURE_SIMULATION_FILENAME, v))
break; // Not ideal.
tex.m_image_file_reference.SetFullPath(v.AsString(), false);
if (p.GetParam(s + ON_RENDER_MATERIAL_TEXTURE_SIMULATION_ON, v))
tex.m_bOn = v;
if (p.GetParam(s + ON_RENDER_MATERIAL_TEXTURE_SIMULATION_AMOUNT, v))
tex.m_blend_constant_A = v;
if (p.GetParam(s + ON_RENDER_MATERIAL_TEXTURE_SIMULATION_TYPE, v))
tex.m_type = ON_Texture::TYPE(v.AsInteger());
if (p.GetParam(s + ON_RENDER_MATERIAL_TEXTURE_SIMULATION_FILTER, v))
tex.m_minfilter = tex.m_magfilter = ON_Texture::FILTER(v.AsInteger());
if (p.GetParam(s + ON_RENDER_MATERIAL_TEXTURE_SIMULATION_MODE, v))
tex.m_mode = ON_Texture::MODE(v.AsInteger());
if (p.GetParam(s + ON_RENDER_MATERIAL_TEXTURE_SIMULATION_UVW, v))
tex.m_uvw = v.AsXform();
if (p.GetParam(s + ON_RENDER_MATERIAL_TEXTURE_SIMULATION_WRAP_U, v))
tex.m_wrapu = ON_Texture::WRAP(v.AsInteger());
if (p.GetParam(s + ON_RENDER_MATERIAL_TEXTURE_SIMULATION_WRAP_V, v))
tex.m_wrapv = ON_Texture::WRAP(v.AsInteger());
mat.m_textures.Append(tex);
count++;
}
}
return mat;
}
ON_RenderContent* ON_RenderMaterial::NewRenderContent(void) const
{
return new ON_RenderMaterial;
}
// ON_RenderEnvironment
ON_OBJECT_IMPLEMENT(ON_RenderEnvironment, ON_RenderContent, "A0AB8EF9-5FD4-4320-BBDA-A1200D1846E4");
ON_RenderEnvironment::ON_RenderEnvironment()
:
ON_RenderContent(ON_KIND_ENVIRONMENT)
{
}
ON_RenderEnvironment::ON_RenderEnvironment(const ON_RenderEnvironment& env)
:
ON_RenderContent(env)
{
}
ON_RenderEnvironment::~ON_RenderEnvironment()
{
}
const ON_RenderContent& ON_RenderEnvironment::operator = (const ON_RenderContent& c)
{
ON_RenderContent::operator = (c);
return *this;
}
const ON_RenderEnvironment& ON_RenderEnvironment::operator = (const ON_RenderEnvironment& env)
{
ON_RenderContent::operator = (env);
return *this;
}
ON_Environment ON_RenderEnvironment::ToOnEnvironment(void) const
{
std::lock_guard<std::recursive_mutex> lg(_private->m_mutex);
ON_Environment env;
const ON_XMLNode* sim_node = _private->XMLNode_Simulation();
if (nullptr != sim_node)
{
ON_XMLVariant v;
ON_XMLParameters p(*sim_node);
if (p.GetParam(ON_ENVIRONMENT_SIMULATION_BACKGROUND_COLOR, v))
env.SetBackgroundColor(v.AsColor());
if (p.GetParam(ON_ENVIRONMENT_SIMULATION_BACKGROUND_IMAGE, v))
{
ON_Texture tex;
tex.m_image_file_reference.SetFullPath(v.AsString(), false);
// TODO: What other ON_Texture params need to be set?
env.SetBackgroundImage(tex);
}
if (p.GetParam(ON_ENVIRONMENT_SIMULATION_BACKGROUND_PROJECTION, v))
{
const auto proj = ON_Environment::ProjectionFromString(v.AsString());
env.SetBackgroundProjection(proj);
}
}
return env;
}
ON_RenderContent* ON_RenderEnvironment::NewRenderContent(void) const
{
return new ON_RenderEnvironment;
}
// ON_RenderTexture
ON_OBJECT_IMPLEMENT(ON_RenderTexture, ON_RenderContent, "677D9905-CC8C-41E6-A7AD-2409DDE68ED0");
ON_RenderTexture::ON_RenderTexture()
:
ON_RenderContent(ON_KIND_TEXTURE)
{
}
ON_RenderTexture::ON_RenderTexture(const ON_RenderTexture& tex)
:
ON_RenderContent(tex)
{
}
ON_RenderTexture::~ON_RenderTexture()
{
}
const ON_RenderContent& ON_RenderTexture::operator = (const ON_RenderContent& c)
{
ON_RenderContent::operator = (c);
return *this;
}
const ON_RenderTexture& ON_RenderTexture::operator = (const ON_RenderTexture& tex)
{
ON_RenderContent::operator = (tex);
return *this;
}
ON_Texture ON_RenderTexture::ToOnTexture(void) const
{
std::lock_guard<std::recursive_mutex> lg(_private->m_mutex);
ON_Texture tex;
const ON_XMLNode* sim_node = _private->XMLNode_Simulation();
if (nullptr != sim_node)
{
ON_XMLVariant v;
ON_XMLParameters p(*sim_node);
if (p.GetParam(ON_TEXTURE_SIMULATION_FILENAME, v))
{
tex.m_image_file_reference.SetFullPath(v.AsString(), false);
}
if (p.GetParam(ON_TEXTURE_SIMULATION_OFFSET, v))
{
ON_3dVector offset, rotation, repeat;
tex.m_uvw.DecomposeTextureMapping(offset, repeat, rotation);
const auto pt = v.As2dPoint();
offset.x = pt[0];
offset.y = pt[1];
tex.m_uvw = ON_Xform::TextureMapping(offset, repeat, rotation);
}
if (p.GetParam(ON_TEXTURE_SIMULATION_REPEAT, v))
{
ON_3dVector offset, rotation, repeat;
tex.m_uvw.DecomposeTextureMapping(offset, repeat, rotation);
const auto pt = v.As2dPoint();
repeat.x = pt[0];
repeat.y = pt[1];
tex.m_uvw = ON_Xform::TextureMapping(offset, repeat, rotation);
}
if (p.GetParam(ON_TEXTURE_SIMULATION_ROTATION, v))
{
ON_3dVector offset, rotation, repeat;
tex.m_uvw.DecomposeTextureMapping(offset, repeat, rotation);
const auto pt = v.As2dPoint();
rotation.z = pt[0] * ON_RADIANS_TO_DEGREES;
tex.m_uvw = ON_Xform::TextureMapping(offset, repeat, rotation);
}
if (p.GetParam(ON_TEXTURE_SIMULATION_WRAP_TYPE, v))
{
const auto wt = ON_Texture::WRAP(v.AsInteger());
tex.m_wrapu = wt;
tex.m_wrapv = wt;
tex.m_wrapw = wt;
}
if (p.GetParam(ON_TEXTURE_SIMULATION_MAPPING_CHANNEL, v))
{
tex.m_mapping_channel_id = v.AsInteger();
}
if (p.GetParam(ON_TEXTURE_SIMULATION_TRANSPARENT_COLOR, v))
{
tex.m_transparent_color = v.AsColor();
}
}
tex.m_mode = ON_Texture::MODE::decal_texture;
tex.m_transparency_texture_id = ON_nil_uuid;
//tex.m_bTreatAsLinear ??? Andy: This is on CRhRdkTexture. John: It's computed; not in the XML.
//tex.m_blend_constant_RGB ???
const ON_XMLVariant v = GetParameter(L"filter");
tex.m_minfilter = tex.m_magfilter = v.AsBool() ? ON_Texture::FILTER::linear_filter
: ON_Texture::FILTER::nearest_filter;
const ON_wString child_slot_name = ChildSlotName();
if (child_slot_name == ON_TEXTURE_CHILD_SLOT_NAME_BITMAP_TEXTURE)
tex.m_type = ON_Texture::TYPE::bitmap_texture;
else
if (child_slot_name == ON_TEXTURE_CHILD_SLOT_NAME_BUMP_TEXTURE)
tex.m_type = ON_Texture::TYPE::bump_texture;
else
if (child_slot_name == ON_TEXTURE_CHILD_SLOT_NAME_TRANSPARENCY_TEXTURE)
tex.m_type = ON_Texture::TYPE::transparency_texture;
else
if (child_slot_name == ON_TEXTURE_CHILD_SLOT_NAME_ENVIRONMENT_TEXTURE)
{
tex.m_type = ON_Texture::TYPE::emap_texture;
// emap_texture is OBSOLETE - set m_mapping_channel_id = ON_MappingChannel::emap_mapping
// tex.m_mapping_channel_id = ON_MappingChannel::emap_mapping; // ERROR!
}
const auto* parent = Parent();
if (nullptr != parent)
{
tex.m_bOn = parent->ChildSlotOn(child_slot_name);
tex.m_blend_constant_A = parent->ChildSlotAmount(child_slot_name, 100.0) / 100.0;
}
return tex;
}
ON_wString ON_RenderTexture::Filename(void) const
{
const ON_XMLVariant v = GetParameter(ON_RENDER_TEXTURE_FILENAME);
if (v.IsNull())
return L"";
return v.AsString();
}
bool ON_RenderTexture::SetFilename(const wchar_t* f)
{
return SetParameter(ON_RENDER_TEXTURE_FILENAME, f);
}
ON_RenderContent* ON_RenderTexture::NewRenderContent(void) const
{
return new ON_RenderTexture;
}
int ONX_Model::AddRenderMaterial(const wchar_t* mat_name)
{
static ON_UUID uuidPB = { 0x5a8d7b9b, 0xcdc9, 0x49de, { 0x8c, 0x16, 0x2e, 0xf6, 0x4f, 0xb0, 0x97, 0xab } };
ON_RenderMaterial mat;
mat.SetTypeId(uuidPB);
const ON_wString unused_name = m_manifest.UnusedName(mat.ComponentType(), ON_nil_uuid, mat_name, nullptr, nullptr, 0, nullptr);
mat.SetName(unused_name);
const ON_ModelComponentReference mcr = AddModelComponent(mat, true);
const auto* model_mat = ON_RenderMaterial::Cast(mcr.ModelComponent());
if (nullptr == model_mat)
{
ON_ERROR("Failed to add render material; AddModelComponent() failed");
return ON_UNSET_INT_INDEX;
}
return model_mat->Index();
}
int ONX_Model::AddRenderEnvironment(const wchar_t* env_name)
{
static ON_UUID uuidBE = { 0xba51ce00, 0xba51, 0xce00, { 0xba, 0x51, 0xce, 0xba, 0x51, 0xce, 0x00, 0x00 } };
ON_RenderEnvironment env;
env.SetTypeId(uuidBE);
const ON_wString unused_name = m_manifest.UnusedName(env.ComponentType(), ON_nil_uuid, env_name, nullptr, nullptr, 0, nullptr);
env.SetName(unused_name);
const ON_ModelComponentReference mcr = AddModelComponent(env, true);
const auto* model_env = ON_RenderEnvironment::Cast(mcr.ModelComponent());
if (nullptr == model_env)
{
ON_ERROR("Failed to add render environment; AddModelComponent() failed");
return ON_UNSET_INT_INDEX;
}
return model_env->Index();
}
int ONX_Model::AddRenderTexture(const wchar_t* fn)
{
static const ON_UUID uuidBM = { 0x57e0ed08, 0x1907, 0x4529, { 0xb0, 0x1b, 0x0c, 0x4a, 0x24, 0x24, 0x55, 0xfd } };
const auto filename = ON_FileSystemPath::CleanPath(fn);
if (!ON_FileSystem::PathExists(filename))
{
ON_ERROR("Failed to add render texture; file does not exist");
return ON_UNSET_INT_INDEX;
}
ON_RenderTexture tex;
tex.SetTypeId(uuidBM);
tex.SetParameter(ON_RENDER_TEXTURE_FILENAME, filename);
const ON_wString tex_name = ON_FileSystemPath::FileNameFromPath(filename, false);
tex.SetName(tex_name);
const ON_wString unused_name = m_manifest.UnusedName(tex.ComponentType(), ON_nil_uuid, tex_name, nullptr, nullptr, 0, nullptr);
tex.SetName(unused_name);
const ON_ModelComponentReference mcr = AddModelComponent(tex, true);
const auto* model_tex = ON_RenderTexture::Cast(mcr.ModelComponent());
if (nullptr == model_tex)
{
ON_ERROR("Failed to add render texture; AddModelComponent() failed");
return ON_UNSET_INT_INDEX;
}
return model_tex->Index();
}