diff --git a/opennurbs_3dm_attributes.cpp b/opennurbs_3dm_attributes.cpp index d48f58d8..f405bf2e 100644 --- a/opennurbs_3dm_attributes.cpp +++ b/opennurbs_3dm_attributes.cpp @@ -1069,6 +1069,17 @@ bool ON_3dmObjectAttributes::Read( ON_BinaryArchive& file ) bool ON_3dmObjectAttributes::Internal_WriteV5( ON_BinaryArchive& file ) const { + if (m_private) + { + // Have the decal collection update the user data if anything has changed and there + // is actually decal data for which a user data object is needed. Note that this is + // not actually needed when running Rhino because the RDK decal UI directly updates + // the user data when changes are made. This is only needed when using ONX_Model and + // File3dm outside of Rhino, in case the programmer sets a decal property. + const unsigned int archive_3dm_version = file.Archive3dmVersion(); + m_private->m_decals.UpdateUserData(archive_3dm_version); + } + unsigned char c; // 29 Nov. 2009 S. Baer // Chunk version updated to 2.1 in order to support m_display_order @@ -1403,10 +1414,6 @@ bool ON_3dmObjectAttributes::Internal_WriteV5( ON_BinaryArchive& file ) const rc = file.WriteBool(HatchBoundaryVisible()); if (!rc) break; } - - // Have the decal collection update the user data if anything has changed. - const unsigned int archive_3dm_version = file.Archive3dmVersion(); - m_private->m_decals.UpdateUserData(archive_3dm_version); } // 15 Jun 2022 S. Baer diff --git a/opennurbs_decals.cpp b/opennurbs_decals.cpp index 2d80514a..3ced2c10 100644 --- a/opennurbs_decals.cpp +++ b/opennurbs_decals.cpp @@ -1057,16 +1057,22 @@ void ON_DecalCollection::RemoveAllDecals(void) void ON_DecalCollection::ClearDecalArray(void) { - for (int i = 0; i < m_decals.Count(); i++) + // 12th July 2023 John Croudy, https://mcneel.myjetbrains.com/youtrack/issue/RH-75697 + // Only call SetChanged() if a decal is actually deleted. + const int count = m_decals.Count(); + if (count > 0) { - delete m_decals[i]; + for (int i = 0; i < count; i++) + { + delete m_decals[i]; + } + + m_decals.Destroy(); + + SetChanged(); } - m_decals.Destroy(); - m_populated = false; - - SetChanged(); } const ON_DecalCollection& ON_DecalCollection::operator = (const ON_DecalCollection& dc) @@ -1129,7 +1135,12 @@ void ON_DecalCollection::UpdateUserData(unsigned int archive_3dm_version) const { if (m_changed) { - SetRDKObjectInformation(*m_attr, m_root_node.String(), archive_3dm_version); + // 12th July 2023 John Croudy, https://mcneel.myjetbrains.com/youtrack/issue/RH-75697 + // For there to be something useful in the XML, the root node must have at least one child node. + if (m_root_node.ChildCount() > 0) + { + SetRDKObjectInformation(*m_attr, m_root_node.String(), archive_3dm_version); + } m_changed = false; } diff --git a/opennurbs_embedded_file.cpp b/opennurbs_embedded_file.cpp index 0c41d3e3..34321343 100644 --- a/opennurbs_embedded_file.cpp +++ b/opennurbs_embedded_file.cpp @@ -206,7 +206,7 @@ bool ON_EmbeddedFile::LoadFromBuffer(ON_Buffer& buf) // Allocate a buffer for the data. auto& d = m_impl->m_data; - d.SetLength(buf.Size()); + d.SetLength(size_t(buf.Size())); // Load the buffer from 'buf'. if (buf.Read(d.m_length, d.m_buffer.get()) != d.m_length) @@ -251,7 +251,7 @@ bool ON_EmbeddedFile::Read(ON_BinaryArchive& archive) if (!archive.ReadCompressedBuffer(uncompressed_size, d.m_buffer.get(), &bFailedCRC) && !bFailedCRC) return false; - d.m_compressed_length = archive.CurrentPosition() - pos_before; + d.m_compressed_length = size_t(archive.CurrentPosition() - pos_before); return true; } diff --git a/opennurbs_material.cpp b/opennurbs_material.cpp index de48aa56..2d6ab5ff 100644 --- a/opennurbs_material.cpp +++ b/opennurbs_material.cpp @@ -2378,6 +2378,61 @@ ON_Texture::WRAP ON_Texture::WrapFromUnsigned( unsigned int wrap_as_unsigned ) return ON_Texture::WRAP::repeat_wrap; } +void ON_Texture::SetRepeat(const ON_2dVector& repeat) +{ + ON_3dVector offset, rotation, r; + + m_uvw.DecomposeTextureMapping(offset, r, rotation); + + m_uvw = ON_Xform::TextureMapping(offset, ON_3dVector(repeat.x, repeat.y, 0.0), rotation); +} + +ON_2dVector ON_Texture::Repeat() const +{ + ON_3dVector offset, rotation, repeat; + + m_uvw.DecomposeTextureMapping(offset, repeat, rotation); + + return ON_2dVector(repeat.x, repeat.y); +} + +void ON_Texture::SetOffset(const ON_2dVector& offset) +{ + ON_3dVector o, rotation, repeat; + + m_uvw.DecomposeTextureMapping(o, repeat, rotation); + + m_uvw = ON_Xform::TextureMapping(ON_3dVector(offset.x, offset.y, 0.0), repeat, rotation); +} + +ON_2dVector ON_Texture::Offset() const +{ + ON_3dVector offset, rotation, repeat; + + m_uvw.DecomposeTextureMapping(offset, repeat, rotation); + + return ON_2dVector(offset.x, offset.y); +} + +void ON_Texture::SetRotation(double rotation) +{ + ON_3dVector offset, r, repeat; + + m_uvw.DecomposeTextureMapping(offset, repeat, r); + + m_uvw = ON_Xform::TextureMapping(offset, repeat, ON_3dPoint(0.0, 0.0, rotation)); +} + +double ON_Texture::Rotation() const +{ + ON_3dVector offset, rotation, repeat; + + m_uvw.DecomposeTextureMapping(offset, repeat, rotation); + + return rotation.z; +} + + bool ON_Texture::Read( ON_BinaryArchive& binary_archive ) @@ -7664,23 +7719,23 @@ const ON_Material& ON_PhysicallyBasedMaterial::Material(void) const return *Implementation().material; } -ON_wString ON_PhysicallyBasedMaterial::ParametersNames::BaseColor(void) { return L"pbr-base-color"; } -ON_wString ON_PhysicallyBasedMaterial::ParametersNames::BRDF(void) { return L"pbr-brdf"; } -ON_wString ON_PhysicallyBasedMaterial::ParametersNames::Subsurface(void) { return L"pbr-subsurface"; } -ON_wString ON_PhysicallyBasedMaterial::ParametersNames::SubsurfaceScatteringColor(void) { return L"pbr-subsurface-scattering-color"; } -ON_wString ON_PhysicallyBasedMaterial::ParametersNames::SubsurfaceScatteringRadius(void) { return L"pbr-subsurface-scattering-radius"; } -ON_wString ON_PhysicallyBasedMaterial::ParametersNames::Specular(void) { return L"pbr-specular"; } -ON_wString ON_PhysicallyBasedMaterial::ParametersNames::SpecularTint(void) { return L"pbr-specular-tint"; } -ON_wString ON_PhysicallyBasedMaterial::ParametersNames::Metallic(void) { return L"pbr-metallic"; } -ON_wString ON_PhysicallyBasedMaterial::ParametersNames::Roughness(void) { return L"pbr-roughness"; } -ON_wString ON_PhysicallyBasedMaterial::ParametersNames::Anisotropic(void) { return L"pbr-anisotropic"; } -ON_wString ON_PhysicallyBasedMaterial::ParametersNames::AnisotropicRotation(void) { return L"pbr-anisotropic-rotation"; } -ON_wString ON_PhysicallyBasedMaterial::ParametersNames::Sheen(void) { return L"pbr-sheen"; } -ON_wString ON_PhysicallyBasedMaterial::ParametersNames::SheenTint(void) { return L"pbr-sheen-tint"; } -ON_wString ON_PhysicallyBasedMaterial::ParametersNames::Clearcoat(void) { return L"pbr-clearcoat"; } -ON_wString ON_PhysicallyBasedMaterial::ParametersNames::ClearcoatRoughness(void) { return L"pbr-clearcoat-roughness"; } -ON_wString ON_PhysicallyBasedMaterial::ParametersNames::ClearcoatBump(void) { return L"pbr-clearcoat-bump"; } -ON_wString ON_PhysicallyBasedMaterial::ParametersNames::OpacityIor(void) { return L"pbr-opacity-ior"; } -ON_wString ON_PhysicallyBasedMaterial::ParametersNames::Opacity(void) { return L"pbr-opacity"; } -ON_wString ON_PhysicallyBasedMaterial::ParametersNames::OpacityRoughness(void) { return L"pbr-opacity-roughness"; } -ON_wString ON_PhysicallyBasedMaterial::ParametersNames::Emission(void) { return L"pbr-emission"; } +ON_wString ON_PhysicallyBasedMaterial::ParametersNames::Anisotropic(void) { return ON_PBR_MATERIAL_ANISOTROPIC ; } +ON_wString ON_PhysicallyBasedMaterial::ParametersNames::AnisotropicRotation(void) { return ON_PBR_MATERIAL_ANISOTROPIC_ROTATION ; } +ON_wString ON_PhysicallyBasedMaterial::ParametersNames::BaseColor(void) { return ON_PBR_MATERIAL_BASE_COLOR ; } +ON_wString ON_PhysicallyBasedMaterial::ParametersNames::BRDF(void) { return ON_PBR_MATERIAL_BRDF ; } +ON_wString ON_PhysicallyBasedMaterial::ParametersNames::Clearcoat(void) { return ON_PBR_MATERIAL_CLEARCOAT ; } +ON_wString ON_PhysicallyBasedMaterial::ParametersNames::ClearcoatBump(void) { return ON_PBR_MATERIAL_CLEARCOAT_BUMP ; } +ON_wString ON_PhysicallyBasedMaterial::ParametersNames::ClearcoatRoughness(void) { return ON_PBR_MATERIAL_CLEARCOAT_ROUGHNESS ; } +ON_wString ON_PhysicallyBasedMaterial::ParametersNames::Emission(void) { return ON_PBR_MATERIAL_EMISSION_COLOR ; } +ON_wString ON_PhysicallyBasedMaterial::ParametersNames::Metallic(void) { return ON_PBR_MATERIAL_METALLIC ; } +ON_wString ON_PhysicallyBasedMaterial::ParametersNames::Opacity(void) { return ON_PBR_MATERIAL_OPACITY ; } +ON_wString ON_PhysicallyBasedMaterial::ParametersNames::OpacityIor(void) { return ON_PBR_MATERIAL_OPACITY_IOR ; } +ON_wString ON_PhysicallyBasedMaterial::ParametersNames::OpacityRoughness(void) { return ON_PBR_MATERIAL_OPACITY_ROUGHNESS ; } +ON_wString ON_PhysicallyBasedMaterial::ParametersNames::Roughness(void) { return ON_PBR_MATERIAL_ROUGHNESS ; } +ON_wString ON_PhysicallyBasedMaterial::ParametersNames::Sheen(void) { return ON_PBR_MATERIAL_SHEEN ; } +ON_wString ON_PhysicallyBasedMaterial::ParametersNames::SheenTint(void) { return ON_PBR_MATERIAL_SHEEN_TINT ; } +ON_wString ON_PhysicallyBasedMaterial::ParametersNames::Specular(void) { return ON_PBR_MATERIAL_SPECULAR ; } +ON_wString ON_PhysicallyBasedMaterial::ParametersNames::SpecularTint(void) { return ON_PBR_MATERIAL_SPECULAR_TINT ; } +ON_wString ON_PhysicallyBasedMaterial::ParametersNames::Subsurface(void) { return ON_PBR_MATERIAL_SUBSURFACE ; } +ON_wString ON_PhysicallyBasedMaterial::ParametersNames::SubsurfaceScatteringColor(void) { return ON_PBR_MATERIAL_SUBSURFACE_SCATTERING_COLOR ; } +ON_wString ON_PhysicallyBasedMaterial::ParametersNames::SubsurfaceScatteringRadius(void) { return ON_PBR_MATERIAL_SUBSURFACE_SCATTERING_RADIUS; } diff --git a/opennurbs_public_version.h b/opennurbs_public_version.h index 2b45578b..b686ca74 100644 --- a/opennurbs_public_version.h +++ b/opennurbs_public_version.h @@ -15,9 +15,9 @@ // #define RMA_VERSION_YEAR 2023 #define RMA_VERSION_MONTH 7 -#define RMA_VERSION_DATE 11 -#define RMA_VERSION_HOUR 10 -#define RMA_VERSION_MINUTE 35 +#define RMA_VERSION_DATE 13 +#define RMA_VERSION_HOUR 18 +#define RMA_VERSION_MINUTE 30 //////////////////////////////////////////////////////////////// // @@ -35,8 +35,8 @@ // 3 = build system release build #define RMA_VERSION_BRANCH 0 -#define VERSION_WITH_COMMAS 8,0,23192,10350 -#define VERSION_WITH_PERIODS 8.0.23192.10350 +#define VERSION_WITH_COMMAS 8,0,23194,18300 +#define VERSION_WITH_PERIODS 8.0.23194.18300 #define COPYRIGHT "Copyright (C) 1993-2023, Robert McNeel & Associates. All Rights Reserved." #define SPECIAL_BUILD_DESCRIPTION "Public OpenNURBS C++ 3dm file IO library." @@ -47,8 +47,8 @@ #define RMA_VERSION_NUMBER_SR_STRING "SR0" #define RMA_VERSION_NUMBER_SR_WSTRING L"SR0" -#define RMA_VERSION_WITH_PERIODS_STRING "8.0.23192.10350" -#define RMA_VERSION_WITH_PERIODS_WSTRING L"8.0.23192.10350" +#define RMA_VERSION_WITH_PERIODS_STRING "8.0.23194.18300" +#define RMA_VERSION_WITH_PERIODS_WSTRING L"8.0.23194.18300" diff --git a/opennurbs_render_content.cpp b/opennurbs_render_content.cpp index 481654ce..732ded46 100644 --- a/opennurbs_render_content.cpp +++ b/opennurbs_render_content.cpp @@ -22,114 +22,6 @@ #error ON_COMPILING_OPENNURBS must be defined when compiling opennurbs #endif -static void ON_ConstructXform(double scale_x, double scale_y, double scale_z, - double angle_x, double angle_y, double angle_z, - double trans_x, double trans_y, double trans_z, ON_Xform& xform) -{ - // All angles in degrees. - - const ON_Xform S = ON_Xform::DiagonalTransformation(scale_x, scale_y, scale_z); - - ON_Xform R; - R.Rotation(ON_RadiansFromDegrees(angle_x), ON_3dVector::XAxis, ON_3dPoint::Origin); - - auto vRotate = ON_3dVector::YAxis; - vRotate.Transform(R.Inverse()); - - ON_Xform Ry; - Ry.Rotation(ON_RadiansFromDegrees(angle_y), vRotate, ON_3dPoint::Origin); - - R = R * Ry; - - vRotate = ON_3dVector::ZAxis; - vRotate.Transform(R.Inverse()); - - ON_Xform Rz; - Rz.Rotation(ON_RadiansFromDegrees(angle_z), vRotate, ON_3dPoint::Origin); - - R = R * Rz; - - const auto T = ON_Xform::TranslationTransformation(-trans_x, -trans_y, -trans_z); - - xform = S * R * T; -} - -static void ON_DeconstructXform(const ON_Xform& xformIn, - double& scale_x, double& scale_y, double& scale_z, - double& angle_x, double& angle_y, double& angle_z, - double& trans_x, double& trans_y, double& trans_z) -{ - // Returns all angles in degrees. - - ON_Xform xform = xformIn; - - scale_x = sqrt(xform[0][0] * xform[0][0] + xform[0][1] * xform[0][1] + xform[0][2] * xform[0][2]); - scale_y = sqrt(xform[1][0] * xform[1][0] + xform[1][1] * xform[1][1] + xform[1][2] * xform[1][2]); - scale_z = sqrt(xform[2][0] * xform[2][0] + xform[2][1] * xform[2][1] + xform[2][2] * xform[2][2]); - - ON_Xform S; - ON_ConstructXform(scale_x, scale_y, scale_z, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, S); - S.Invert(); - - xform = S * xform; - - const double dSinBeta = -xform[2][0]; - - double dCosBeta = sqrt(1.0 - dSinBeta * dSinBeta); - if (dCosBeta < 0.0) - { - dCosBeta = -dCosBeta; - } - - double dSinAlpha, dCosAlpha, dSinGamma, dCosGamma; - - if (dCosBeta < 1e-6) - { - dSinAlpha = -xform[1][2]; - dCosAlpha = xform[1][1]; - dSinGamma = 0.0; - dCosGamma = 1.0; - } - else - { - dSinAlpha = xform[2][1] / dCosBeta; - dCosAlpha = xform[2][2] / dCosBeta; - dSinGamma = xform[1][0] / dCosBeta; - dCosGamma = xform[0][0] / dCosBeta; - } - - angle_x = (ON_DegreesFromRadians(atan2(dSinAlpha, dCosAlpha))); - angle_y = (ON_DegreesFromRadians(atan2(dSinBeta, dCosBeta))); - angle_z = (ON_DegreesFromRadians(atan2(dSinGamma, dCosGamma))); - - ON_Xform R; - ON_ConstructXform(scale_x, scale_y, scale_z, angle_x, angle_y, angle_z, 0.0, 0.0, 0.0, R); - R.Invert(); - - ON_Xform T = R * xformIn; - - trans_x = -T[0][3]; - trans_y = -T[1][3]; - trans_z = -T[2][3]; -} - -struct XF -{ - double scale_x = 0.0, scale_y = 0.0, scale_z = 0.0; - double angle_x = 0.0, angle_y = 0.0, angle_z = 0.0; - double trans_x = 0.0, trans_y = 0.0, trans_z = 0.0; -}; - -static void ON_DeconstructXform(const ON_Xform& xform, XF& xf) -{ - ON_DeconstructXform(xform, xf.scale_x, xf.scale_y, xf.scale_z, xf.angle_x, xf.angle_y, xf.angle_z, xf.trans_x, xf.trans_y, xf.trans_z); -} - -static void ON_ConstructXform(const XF& xf, ON_Xform& xform) -{ - ON_ConstructXform(xf.scale_x, xf.scale_y, xf.scale_z, xf.angle_x, xf.angle_y, xf.angle_z, xf.trans_x, xf.trans_y, xf.trans_z, xform); -} - ON_OBJECT_IMPLEMENT(ON_Environment, ON_Object, "94BCA4D5-0FC7-435E-95F9-22F3927F9B2E"); class ON_Environment::CImpl @@ -1027,18 +919,68 @@ 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"-on"; + 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"-on"; + 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); @@ -1436,30 +1378,31 @@ ON_Texture ON_RenderTexture::ToOnTexture(void) const if (p.GetParam(ON_TEXTURE_SIMULATION_OFFSET, v)) { - XF xf; - ON_DeconstructXform(tex.m_uvw, xf); + ON_3dVector offset, rotation, repeat; + tex.m_uvw.DecomposeTextureMapping(offset, repeat, rotation); const auto pt = v.As2dPoint(); - xf.trans_x = pt[0]; - xf.trans_y = pt[1]; - ON_ConstructXform(xf, tex.m_uvw); + 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)) { - XF xf; - ON_DeconstructXform(tex.m_uvw, xf); + ON_3dVector offset, rotation, repeat; + tex.m_uvw.DecomposeTextureMapping(offset, repeat, rotation); const auto pt = v.As2dPoint(); - xf.scale_x = pt[0]; - xf.scale_y = pt[1]; - ON_ConstructXform(xf, tex.m_uvw); + 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)) { - XF xf; - ON_DeconstructXform(tex.m_uvw, xf); - xf.angle_z = v.AsDouble(); - ON_ConstructXform(xf, tex.m_uvw); + 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)) @@ -1477,36 +1420,43 @@ ON_Texture ON_RenderTexture::ToOnTexture(void) const if (p.GetParam(ON_TEXTURE_SIMULATION_TRANSPARENT_COLOR, v)) { - tex.m_transparent_color = v.AsColor(); // ANDY CHECK -- IS THIS RIGHT? + 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) { - const ON_wString csn = ChildSlotName(); - tex.m_bOn = parent->ChildSlotOn(csn); - -// TODO: Discuss with Andy. -// tex.m_type ??? -// tex.m_mode ??? -// tex.m_bTreatAsLinear ??? -// tex.m_border_color ??? -// tex.m_transparency_texture_id ??? -// tex.m_bump_scale ??? -// tex.m_blend_A0 ??? -// tex.m_blend_A1 ??? -// tex.m_blend_A2 ??? -// tex.m_blend_A3 ??? -// tex.m_blend_RGB0 ??? -// tex.m_blend_RGB1 ??? -// tex.m_blend_RGB2 ??? -// tex.m_blend_RGB3 ??? -// tex.m_blend_order ??? -// tex.m_blend_constant_A ??? -// tex.m_blend_constant_RGB ??? -// tex.m_minfilter ??? -// tex.m_magfilter ??? + tex.m_bOn = parent->ChildSlotOn(child_slot_name); + tex.m_blend_constant_A = parent->ChildSlotAmount(child_slot_name, 100.0) / 100.0; } return tex; diff --git a/opennurbs_render_content.h b/opennurbs_render_content.h index d1843527..f060d7ac 100644 --- a/opennurbs_render_content.h +++ b/opennurbs_render_content.h @@ -204,6 +204,16 @@ public: // Returns: True if successful, else false. virtual bool SetChildSlotOn(bool on, const wchar_t* child_slot_name); + // Returns the blend amount of the texture with the specified child slot name. + // The returned value is typically in the range 0..100 but it can be any positive or negative value. + // If there is no child with the specified child slot name, the method returns 'default_value'. + virtual double ChildSlotAmount(const wchar_t* child_slot_name, double default_value=ON_UNSET_VALUE) const; + + // Sets the blend amount of the texture with the specified child slot name. + // Param amount is typically in the range 0..100 but it can be any positive or negative value. + // Returns: True if successful, else false. + virtual bool SetChildSlotAmount(double amount, const wchar_t* child_slot_name); + // Deletes any existing child with the specified child slot name. // Returns: True if successful, else false. virtual bool DeleteChild(const wchar_t* child_slot_name); diff --git a/opennurbs_subd.cpp b/opennurbs_subd.cpp index df71b709..8e8bf15d 100644 --- a/opennurbs_subd.cpp +++ b/opennurbs_subd.cpp @@ -19877,7 +19877,6 @@ unsigned ON_SubDVertexQuadSector::SubdivisionLevel() const } - static unsigned int Internal_MarkStuffAndMaybeMoveVertices( const ON_SubD& subd, const ON_SubDComponentPtr* cptr_list, @@ -20168,6 +20167,8 @@ static unsigned int Internal_TransformComponents( ); } + + unsigned int ON_SubD::TransformComponents( const ON_Xform& xform, const ON_SubDComponentPtr* cptr_list, diff --git a/opennurbs_subd.h b/opennurbs_subd.h index f374600e..07fdeba9 100644 --- a/opennurbs_subd.h +++ b/opennurbs_subd.h @@ -6655,6 +6655,7 @@ public: ON_SubDComponentLocation component_location ); + /* Description: Extrude entire subd bay adding a ring of faces around the boundary and moving the original subd. diff --git a/opennurbs_texture.h b/opennurbs_texture.h index aa427716..48dd8705 100644 --- a/opennurbs_texture.h +++ b/opennurbs_texture.h @@ -405,6 +405,16 @@ public: // Texture coordinate transformation. ON_Xform m_uvw = ON_Xform::IdentityTransformation; + // These functions are helpers for m_uvw + void SetRepeat(const ON_2dVector&); + ON_2dVector Repeat() const; + + void SetOffset(const ON_2dVector&); + ON_2dVector Offset() const; + + void SetRotation(double); + double Rotation() const; + // If ON_UNSET_COLOR != m_border_color, then this color // is used when the texture coordinates are <=0 or >=1 // and the m_wrap* value is clamp_wrap. diff --git a/opennurbs_xform.cpp b/opennurbs_xform.cpp index 520df9dc..e816f8d3 100644 --- a/opennurbs_xform.cpp +++ b/opennurbs_xform.cpp @@ -1677,6 +1677,85 @@ bool ON_Xform::DecomposeAffine(ON_Xform& L, ON_3dVector& T) const return rc; } +void ON_Xform::DecomposeTextureMapping(ON_3dVector& offset, ON_3dVector& repeat, ON_3dVector& rotation) const +{ + ON_Xform xform = *this; + + repeat.x = sqrt(xform[0][0] * xform[0][0] + xform[0][1] * xform[0][1] + xform[0][2] * xform[0][2]); + repeat.y = sqrt(xform[1][0] * xform[1][0] + xform[1][1] * xform[1][1] + xform[1][2] * xform[1][2]); + repeat.z = sqrt(xform[2][0] * xform[2][0] + xform[2][1] * xform[2][1] + xform[2][2] * xform[2][2]); + + const ON_Xform S = TextureMapping(ON_3dVector::ZeroVector, repeat, ON_3dVector::ZeroVector).Inverse(); + + xform = S * xform; + + const double dSinBeta = -xform[2][0]; + + double dCosBeta = sqrt(1.0 - dSinBeta * dSinBeta); + if (dCosBeta < 0.0) + { + dCosBeta = -dCosBeta; + } + + double dSinAlpha, dCosAlpha, dSinGamma, dCosGamma; + + if (dCosBeta < 1e-6) + { + dSinAlpha = -xform[1][2]; + dCosAlpha = xform[1][1]; + dSinGamma = 0.0; + dCosGamma = 1.0; + } + else + { + dSinAlpha = xform[2][1] / dCosBeta; + dCosAlpha = xform[2][2] / dCosBeta; + dSinGamma = xform[1][0] / dCosBeta; + dCosGamma = xform[0][0] / dCosBeta; + } + + rotation.x = atan2(dSinAlpha, dCosAlpha); + rotation.y = atan2(dSinBeta, dCosBeta); + rotation.z = atan2(dSinGamma, dCosGamma); + + const ON_Xform R = TextureMapping(ON_3dVector::ZeroVector, repeat, rotation).Inverse(); + + const ON_Xform T = R * *this; + + offset.x = -T[0][3]; + offset.y = -T[1][3]; + offset.z = -T[2][3]; +} + +//static +const ON_Xform ON_Xform::TextureMapping(const ON_3dVector& offset, const ON_3dVector& repeat, const ON_3dVector& rotation) +{ + ON_Xform S = ON_Xform::DiagonalTransformation(repeat.x, repeat.y, repeat.z); + + ON_Xform R; + R.Rotation(rotation.x, ON_3dVector::XAxis, ON_3dPoint::Origin); + + ON_3dVector vRotate = ON_3dVector::YAxis; + vRotate.Transform(R.Inverse()); + + ON_Xform Ry; + Ry.Rotation(rotation.y, vRotate, ON_3dPoint::Origin); + + R = R * Ry; + + vRotate = ON_3dVector::ZAxis; + vRotate.Transform(R.Inverse()); + + ON_Xform Rz; + Rz.Rotation(rotation.z, vRotate, ON_3dPoint::Origin); + + R = R * Rz; + + const ON_Xform T = ON_Xform::TranslationTransformation(-offset.x, -offset.y, -offset.z); + + return S * R * T; +} + bool ON_Xform::IsZero() const { diff --git a/opennurbs_xform.h b/opennurbs_xform.h index fd055cdb..8c9bddf9 100644 --- a/opennurbs_xform.h +++ b/opennurbs_xform.h @@ -323,6 +323,9 @@ public: bool DecomposeAffine(ON_3dVector& Translation, ON_Xform& Linear) const; bool DecomposeAffine(ON_Xform& Linear, ON_3dVector& Translation ) const; + // Convert an ON_Xform into the offset, repeat and rotation values used in ON_Texture and similar classes. + void DecomposeTextureMapping(ON_3dVector& offset, ON_3dVector& repeat, ON_3dVector& rotation) const; + // true if this is a proper rotation. bool IsRotation() const; @@ -1016,6 +1019,8 @@ Notes: ON_PlaneEquation mirror_plane ); + static const ON_Xform TextureMapping(const ON_3dVector& offset, const ON_3dVector& repeat, const ON_3dVector& rotation); + // Description: The ChangeBasis() function is overloaded // and provides several // ways to compute a change of basis transformation. diff --git a/opennurbs_xml.cpp b/opennurbs_xml.cpp index 5478ceb4..0860c678 100644 --- a/opennurbs_xml.cpp +++ b/opennurbs_xml.cpp @@ -3947,7 +3947,10 @@ void ON_XMLUserData::SetToDefaultsImpl(int) const bool ON_XMLUserData::Archive(void) const { - return true; + // 12th July 2023 John Croudy, https://mcneel.myjetbrains.com/youtrack/issue/RH-75697 + // We only want to archive the user data if there's something useful in the XML. For there + // to be something useful in the XML, the root node must have at least one child node. + return _private->m_XMLRoot.ChildCount() > 0; } bool ON_XMLUserData::Read(ON_BinaryArchive& archive) diff --git a/opennurbs_xml.h b/opennurbs_xml.h index c500d325..6e71c77c 100644 --- a/opennurbs_xml.h +++ b/opennurbs_xml.h @@ -233,6 +233,7 @@ typedef bool (*ON_XMLRecurseChildrenCallback)(class ON_XMLNode*, void*); #define ON_PBR_MATERIAL_ANISOTROPIC_ROTATION L"pbr-anisotropic-rotation" #define ON_PBR_MATERIAL_BASE_COLOR L"pbr-base-color" #define ON_PBR_MATERIAL_CLEARCOAT L"pbr-clearcoat" +#define ON_PBR_MATERIAL_CLEARCOAT_BUMP L"pbr-clearcoat-bump" #define ON_PBR_MATERIAL_CLEARCOAT_ROUGHNESS L"pbr-clearcoat-roughness" #define ON_PBR_MATERIAL_EMISSION_COLOR L"pbr-emission" #define ON_PBR_MATERIAL_METALLIC L"pbr-metallic" @@ -296,6 +297,12 @@ typedef bool (*ON_XMLRecurseChildrenCallback)(class ON_XMLNode*, void*); #define ON_KIND_ENVIRONMENT L"environment" #define ON_KIND_TEXTURE L"texture" +// Standard texture child slot names. +#define ON_TEXTURE_CHILD_SLOT_NAME_BITMAP_TEXTURE L"bitmap-texture" +#define ON_TEXTURE_CHILD_SLOT_NAME_BUMP_TEXTURE L"bump-texture" +#define ON_TEXTURE_CHILD_SLOT_NAME_TRANSPARENCY_TEXTURE L"transparency-texture" +#define ON_TEXTURE_CHILD_SLOT_NAME_ENVIRONMENT_TEXTURE L"environment-texture" + #define ON_RDK_POSTFIX_SECTION L"-section" class ON_CLASS ON_XMLVariant