From 24b8c988cc4eb43922f6bae29dcee016667a493a Mon Sep 17 00:00:00 2001 From: Bozo The Builder Date: Fri, 19 May 2023 16:14:53 -0700 Subject: [PATCH] Sync changes from upstream repository Co-authored-by: croudyj Co-authored-by: Dale Fugier Co-authored-by: Dale Lear Co-authored-by: Greg Arden Co-authored-by: jlasor Co-authored-by: Joshua Kennedy Co-authored-by: Pierre Cuvilliers Co-authored-by: Steve Baer --- opennurbs_3dm_attributes.cpp | 112 ++++- opennurbs_3dm_attributes.h | 15 +- opennurbs_3dm_settings.cpp | 38 +- opennurbs_3dm_settings.h | 1 + opennurbs_arccurve.h | 3 + opennurbs_bezier.cpp | 278 ++++++++++++ opennurbs_bezier.h | 47 +++ opennurbs_curveproxy.h | 1 + opennurbs_decals.cpp | 225 ++++------ opennurbs_defines.cpp | 15 + opennurbs_defines.h | 19 + opennurbs_dithering.cpp | 4 +- opennurbs_dithering.h | 2 +- opennurbs_embedded_file.cpp | 5 +- opennurbs_extensions.cpp | 25 +- opennurbs_ground_plane.cpp | 40 +- opennurbs_ground_plane.h | 4 +- opennurbs_internal_defines.h | 10 +- opennurbs_layer.cpp | 61 ++- opennurbs_layer.h | 13 +- opennurbs_linear_workflow.cpp | 10 +- opennurbs_linear_workflow.h | 5 +- opennurbs_mesh.cpp | 51 ++- opennurbs_mesh.h | 55 ++- opennurbs_post_effects.cpp | 8 +- opennurbs_post_effects.h | 2 +- opennurbs_public_version.h | 16 +- opennurbs_render_channels.cpp | 6 +- opennurbs_render_channels.h | 2 +- opennurbs_render_content.cpp | 343 +++++---------- opennurbs_safe_frame.cpp | 6 +- opennurbs_safe_frame.h | 2 +- opennurbs_skylight.cpp | 4 +- opennurbs_skylight.h | 2 +- opennurbs_statics.cpp | 7 +- opennurbs_string.h | 5 +- opennurbs_subd.cpp | 132 ++++++ opennurbs_subd.h | 213 +++++++++- opennurbs_subd.natvis | 24 ++ opennurbs_subd_data.cpp | 4 +- opennurbs_subd_data.h | 2 + opennurbs_subd_fragment.cpp | 369 ++++++++++++++-- opennurbs_sun.cpp | 769 +++++++++++++++++++++++----------- opennurbs_sun.h | 53 +-- opennurbs_unicode.h | 9 +- opennurbs_viewport.cpp | 112 +++++ opennurbs_viewport.h | 71 ++-- opennurbs_xml.cpp | 103 +++-- opennurbs_xml.h | 172 +++++++- 49 files changed, 2582 insertions(+), 893 deletions(-) diff --git a/opennurbs_3dm_attributes.cpp b/opennurbs_3dm_attributes.cpp index 5f2b0a2b..74957a46 100644 --- a/opennurbs_3dm_attributes.cpp +++ b/opennurbs_3dm_attributes.cpp @@ -36,11 +36,13 @@ public: ON::ClipParticipationSource m_clip_participation_source = ON::ClipParticipationSource::FromLayer; ON_UuidList m_clipplane_list; bool m_clipping_proof = false; + bool m_clipplane_list_is_participation = true; ON::SectionAttributesSource m_section_attributes_source = ON::SectionAttributesSource::FromLayer; double m_linetype_scale = 1.0; ON_Color m_hatch_background_fill; bool m_hatch_boundary_visible = false; + ON::SectionLabelStyle m_section_label_style = ON::SectionLabelStyle::None; std::shared_ptr m_custom_linetype; std::shared_ptr m_custom_section_style; @@ -64,6 +66,9 @@ bool ON_3dmObjectAttributesPrivate::operator==(const ON_3dmObjectAttributesPriva if (m_clipplane_list != other.m_clipplane_list) return false; + if (m_clipplane_list_is_participation != other.m_clipplane_list_is_participation) + return false; + if (m_clipping_proof != other.m_clipping_proof) return false; @@ -79,6 +84,9 @@ bool ON_3dmObjectAttributesPrivate::operator==(const ON_3dmObjectAttributesPriva if (m_hatch_boundary_visible != other.m_hatch_boundary_visible) return false; + if (m_section_label_style != other.m_section_label_style) + return false; + { const ON_SectionStyle* customThis = m_custom_section_style.get(); const ON_SectionStyle* customOther = other.m_custom_section_style.get(); @@ -433,9 +441,15 @@ enum ON_3dmObjectAttributesTypeCodes : unsigned char // 18 Apr 2023 S. Baer // file version 2.11: custome section style CustomSectionStyle = 39, + // 10 May 2023 S. Baer + // file version 2.12: ClippingPlaneLabelStyle + ClippingPlaneLabelStyle = 40, + // 11 May 2023 S. Baer + // file version 2.13: how the participation list for clipping planes is interpreted + SelectiveClippingListType = 41, // add items here - LastAttributeTypeCode = 39 + LastAttributeTypeCode = 41 }; bool ON_3dmObjectAttributes::Internal_ReadV5( ON_BinaryArchive& file ) @@ -707,7 +721,7 @@ bool ON_3dmObjectAttributes::Internal_ReadV5( ON_BinaryArchive& file ) { if (selectiveClipping.Count() > 0) { - SetClipParticipationList(selectiveClipping.Array(), selectiveClipping.Count()); + SetClipParticipationList(selectiveClipping.Array(), selectiveClipping.Count(), true); } } rc = file.ReadChar(&itemid); @@ -868,6 +882,36 @@ bool ON_3dmObjectAttributes::Internal_ReadV5( ON_BinaryArchive& file ) if (minor_version <= 11) break; + if (ON_3dmObjectAttributesTypeCodes::ClippingPlaneLabelStyle == itemid) // 40 + { + unsigned char c = 0; + rc = file.ReadChar(&c); + if (!rc) break; + SetClippingPlaneLabelStyle(ON::SectionLabelStyleFromUnsigned(c)); + + rc = file.ReadChar(&itemid); + if (!rc || 0 == itemid) break; + } + + if (minor_version <= 12) + break; + + if (ON_3dmObjectAttributesTypeCodes::SelectiveClippingListType == itemid) // 41 + { + bool b = true; + rc = file.ReadBool(&b); + if (!rc) break; + if (nullptr == m_private) + m_private = new ON_3dmObjectAttributesPrivate(this); + m_private->m_clipplane_list_is_participation = b; + + rc = file.ReadChar(&itemid); + if (!rc || 0 == itemid) break; + } + + if (minor_version <= 13) + break; + // Add new item reading above and increment the LastAttributeTypeCode value // in the enum. Be sure to test reading of old and new files by old and new // code, before checking in your changes. @@ -1066,7 +1110,11 @@ bool ON_3dmObjectAttributes::Internal_WriteV5( ON_BinaryArchive& file ) const // Chunk version = 2.10 to support custom linetype // 18 Apr 2023 S. Baer // Chunk version = 2.11 to support custom section style - bool rc = file.Write3dmChunkVersion(2,11); + // 10 May 2023 S. Baer + // Chunk version = 2.12 to support ClippingPlaneLabelStyle + // 11 May 2023 S. Baer + // Chunk version = 2.13 to support SelectiveClippingListType + bool rc = file.Write3dmChunkVersion(2,13); while(rc) { if (!rc) break; @@ -1290,7 +1338,8 @@ bool ON_3dmObjectAttributes::Internal_WriteV5( ON_BinaryArchive& file ) const bool forAllClippingPlanes = true; bool forNoClippingPlanes = false; ON_UuidList selectiveClipping; - GetClipParticipation(forAllClippingPlanes, forNoClippingPlanes, selectiveClipping); + bool isParticipationList = true; + GetClipParticipation(forAllClippingPlanes, forNoClippingPlanes, selectiveClipping, isParticipationList); if (!forAllClippingPlanes) { c = ON_3dmObjectAttributesTypeCodes::SelectiveClippingData; // 28 @@ -1433,6 +1482,24 @@ bool ON_3dmObjectAttributes::Internal_WriteV5( ON_BinaryArchive& file ) const if (!rc) break; } + if (ClippingPlaneLabelStyle() != ON::SectionLabelStyle::None) + { + c = ON_3dmObjectAttributesTypeCodes::ClippingPlaneLabelStyle; // 40 + rc = file.WriteChar(c); + if (!rc) break; + rc = file.WriteChar((unsigned char)(ClippingPlaneLabelStyle())); + if (!rc) break; + } + + if (m_private && false == m_private->m_clipplane_list_is_participation) + { + c = ON_3dmObjectAttributesTypeCodes::SelectiveClippingListType; //41 + rc = file.WriteChar(c); + if (!rc) break; + rc = file.WriteBool(m_private->m_clipplane_list_is_participation); + if (!rc) break; + } + // 0 indicates end of attributes - this should be the last item written c = 0; rc = file.WriteChar(c); @@ -1905,26 +1972,28 @@ unsigned int ON_3dmObjectAttributes::ApplyParentalControl( bool forAll = false; bool forNone = false; ON_UuidList list; - parent_layer.GetClipParticipation(forAll, forNone, list); + bool isParticipationList = true; + parent_layer.GetClipParticipation(forAll, forNone, list, isParticipationList); if (forAll) SetClipParticipationForAll(); else if (forNone) SetClipParticipationForNone(); else if (list.Count() > 0) - SetClipParticipationList(list.Array(), list.Count()); + SetClipParticipationList(list.Array(), list.Count(), isParticipationList); } if (ON::ClipParticipationSource::FromObject == ClipParticipationSource()) { bool forAll = false; bool forNone = false; ON_UuidList list; - parents_attributes.GetClipParticipation(forAll, forNone, list); + bool isParticipationList = true; + parents_attributes.GetClipParticipation(forAll, forNone, list, isParticipationList); if (forAll) SetClipParticipationForAll(); else if (forNone) SetClipParticipationForNone(); else if (list.Count() > 0) - SetClipParticipationList(list.Array(), list.Count()); + SetClipParticipationList(list.Array(), list.Count(), isParticipationList); } } } @@ -2332,6 +2401,7 @@ void ON_3dmObjectAttributes::SetClipParticipationForAll() return; m_private->m_clipplane_list.Empty(); + m_private->m_clipplane_list_is_participation = true; m_private->m_clipping_proof = false; } void ON_3dmObjectAttributes::SetClipParticipationForNone() @@ -2339,12 +2409,16 @@ void ON_3dmObjectAttributes::SetClipParticipationForNone() if (nullptr == m_private) m_private = new ON_3dmObjectAttributesPrivate(this); m_private->m_clipplane_list.Empty(); + m_private->m_clipplane_list_is_participation = true; m_private->m_clipping_proof = true; } -void ON_3dmObjectAttributes::SetClipParticipationList(const ON_UUID* clippingPlaneIds, int count) +void ON_3dmObjectAttributes::SetClipParticipationList(const ON_UUID* clippingPlaneIds, int count, bool isParticipationList) { if (nullptr == clippingPlaneIds || count < 1) + { SetClipParticipationForAll(); + return; + } if (nullptr == m_private) m_private = new ON_3dmObjectAttributesPrivate(this); @@ -2352,13 +2426,16 @@ void ON_3dmObjectAttributes::SetClipParticipationList(const ON_UUID* clippingPla for (int i = 0; i < count; i++) m_private->m_clipplane_list.AddUuid(clippingPlaneIds[i], true); + m_private->m_clipplane_list_is_participation = isParticipationList; m_private->m_clipping_proof = false; } void ON_3dmObjectAttributes::GetClipParticipation( bool& forAllClippingPlanes, bool& forNoClippingPlanes, - ON_UuidList& specificClipplaneList) const + ON_UuidList& specificClipplaneList, + bool& listIsParticipation) const { + listIsParticipation = true; if (nullptr == m_private) { forAllClippingPlanes = true; @@ -2368,6 +2445,7 @@ void ON_3dmObjectAttributes::GetClipParticipation( } specificClipplaneList = m_private->m_clipplane_list; + listIsParticipation = m_private->m_clipplane_list_is_participation; if (specificClipplaneList.Count() > 0) { forAllClippingPlanes = false; @@ -2490,6 +2568,20 @@ void ON_3dmObjectAttributes::SetHatchBoundaryVisible(bool on) m_private->m_hatch_boundary_visible = on; } +ON::SectionLabelStyle ON_3dmObjectAttributes::ClippingPlaneLabelStyle() const +{ + return m_private ? m_private->m_section_label_style : DefaultAttributesPrivate.m_section_label_style; +} +void ON_3dmObjectAttributes::SetClippingPlaneLabelStyle(ON::SectionLabelStyle style) +{ + if (ClippingPlaneLabelStyle() == style) + return; + + if (nullptr == m_private) + m_private = new ON_3dmObjectAttributesPrivate(this); + m_private->m_section_label_style = style; +} + //https://mcneel.myjetbrains.com/youtrack/issue/RH-20531 ON_Plane ON_3dmObjectAttributes::ObjectFrame(const ON_COMPONENT_INDEX& ci) const diff --git a/opennurbs_3dm_attributes.h b/opennurbs_3dm_attributes.h index 55384a75..d5b3fd29 100644 --- a/opennurbs_3dm_attributes.h +++ b/opennurbs_3dm_attributes.h @@ -373,7 +373,13 @@ public: void SetClipParticipationForNone(); // Set the object to only be clipped by a specific set of clipping planes. - void SetClipParticipationList(const ON_UUID* clippingPlaneIds, int count); + // Paramters: + // clippingPlaneIds [in] - array of ON_UUIDs for clipping planes + // count [in] - number of elements in clippingPlaneIds + // listIsParticipation [in] - is the list clipping planes that the object + // participates with or an exclusion list of clipping planes to not + // participate with + void SetClipParticipationList(const ON_UUID* clippingPlaneIds, int count, bool listIsParticipation); // Get details on how the object will interact with clipping planes // Parameters: @@ -384,10 +390,13 @@ public: // specificClipplaneList [out] - if the object interacts with only a // specific set of clipping planes, this list will have the uuids of // those clipping plane objects + // listIsParticipation [out] - is specificClipplaneList a participation + // list or an exclusion list void GetClipParticipation( bool& forAllClippingPlanes, bool& forNoClippingPlanes, - ON_UuidList& specificClipplaneList) const; + ON_UuidList& specificClipplaneList, + bool& listIsParticipation) const; // Source for clip participation details ON::ClipParticipationSource ClipParticipationSource() const; @@ -461,6 +470,8 @@ public: void SetHatchBoundaryVisible(bool on); #pragma endregion + ON::SectionLabelStyle ClippingPlaneLabelStyle() const; + void SetClippingPlaneLabelStyle(ON::SectionLabelStyle style); ON_Plane ObjectFrame(const ON_COMPONENT_INDEX& ci) const; void SetObjectFrame(const ON_COMPONENT_INDEX& ci, const ON_Xform& wcs_to_ocs); diff --git a/opennurbs_3dm_settings.cpp b/opennurbs_3dm_settings.cpp index b4942074..0169c3f2 100644 --- a/opennurbs_3dm_settings.cpp +++ b/opennurbs_3dm_settings.cpp @@ -831,17 +831,17 @@ unsigned int ON_3dmUnitsAndTolerances::SetInvalidTolerancesToDefaultValues() static const wchar_t* XMLPathBack360(void) // Not used for 'override'. { - return ON_RDK_DOCUMENT ON_RDK_SLASH ON_RDK_CURRENT_CONTENT; + return ON_RDK_DOCUMENT ON_XML_SLASH ON_RDK_CURRENT_CONTENT; } static const wchar_t* XMLPathReflRefr(void) { - return ON_RDK_DOCUMENT ON_RDK_SLASH ON_RDK_SETTINGS ON_RDK_SLASH ON_RDK_RENDERING; + return ON_RDK_DOCUMENT ON_XML_SLASH ON_RDK_SETTINGS ON_XML_SLASH ON_RDK_RENDERING; } static const wchar_t* XMLPathSkylight(void) { - return ON_RDK_DOCUMENT ON_RDK_SLASH ON_RDK_SETTINGS ON_RDK_SLASH ON_RDK_SUN; + return ON_RDK_DOCUMENT ON_XML_SLASH ON_RDK_SETTINGS ON_XML_SLASH ON_RDK_SUN; } ON_EnvironmentsImpl::ON_EnvironmentsImpl(const ON_EnvironmentsImpl& ei) @@ -937,7 +937,7 @@ ON_DECL ON__UINT_PTR ON_GetDocumentObjectSpecializer(const ON_3dmRenderSettings& } ON_DECL void ON_SpecializeDocumentObjects(ON__UINT_PTR specializer, - ON_GroundPlane& gp, ON_LinearWorkflow& lw, ON_SunEx& sun) + ON_GroundPlane& gp, ON_LinearWorkflow& lw, ON_Sun& sun) { auto* priv = reinterpret_cast(specializer); ON_ASSERT(nullptr != priv); @@ -986,20 +986,22 @@ const ON_3dmRenderSettingsPrivate& ON_3dmRenderSettingsPrivate::operator = (cons // Copy the entire document XML. _rdk_document_data = p._rdk_document_data; - // Invalidate any document object caches. The pointers to these objects are never null because - // they are created in every constructor. See CreateDocumentObjects(). + // Notify the document objects that the XML has changed. Some of these objects maintain caches and + // other data structures that must be kept in synch with the XML. This gives them a chance to update + // any such information. Note that the pointers to these objects are never null because they are + // created in every constructor. See CreateDocumentObjects(). // It's critical that the document objects do not get deleted or recreated here because there can be // clients storing temporary pointers to them around this call. What's more, this function can never // change the class of the document objects. For example, if the ground plane is a specialized one, // it will always be the _same_ specialized one. They never get deleted during the lifetime of this. - _ground_plane ->InvalidateCache(); - _dithering ->InvalidateCache(); - _safe_frame ->InvalidateCache(); - _skylight ->InvalidateCache(); - _linear_workflow->InvalidateCache(); - _render_channels->InvalidateCache(); - _sun ->InvalidateCache(); - _post_effects ->InvalidateCache(); + _ground_plane ->OnInternalXmlChanged(p._ground_plane ); + _dithering ->OnInternalXmlChanged(p._dithering ); + _safe_frame ->OnInternalXmlChanged(p._safe_frame ); + _skylight ->OnInternalXmlChanged(p._skylight ); + _linear_workflow->OnInternalXmlChanged(p._linear_workflow); + _render_channels->OnInternalXmlChanged(p._render_channels); + _sun ->OnInternalXmlChanged(p._sun ); + _post_effects ->OnInternalXmlChanged(p._post_effects ); // Check that all the document objects now have matching properties. ON_ASSERT(*_ground_plane == *p._ground_plane); @@ -1034,7 +1036,7 @@ void ON_3dmRenderSettingsPrivate::CreateDocumentObjects(void) _skylight = new ON_Skylight (_rdk_document_data); _linear_workflow = new ON_LinearWorkflow (_rdk_document_data); _render_channels = new ON_RenderChannels (_rdk_document_data); - _sun = new ON_SunEx (_rdk_document_data); + _sun = new ON_Sun (_rdk_document_data); _environments = new ON_EnvironmentsImpl(_rdk_document_data); _post_effects = new ON_PostEffects (_rdk_document_data); } @@ -1169,7 +1171,7 @@ void ON_3dmRenderSettingsPrivate::SpecializeLinearWorkflow(ON_LinearWorkflow& lw _lw_specialized = true; } -void ON_3dmRenderSettingsPrivate::SpecializeSun(ON_SunEx& sun) +void ON_3dmRenderSettingsPrivate::SpecializeSun(ON_Sun& sun) { // This is called from ON_SpecializeDocumentObjects() and is only called once during the lifetime of this. ON_ASSERT(!_sun_specialized); @@ -1852,7 +1854,7 @@ extern ON_UUID uuidRenderPreset_Custom; extern ON_UUID uuidRenderPreset_Exterior; extern ON_UUID uuidRenderPreset_Interior; -static const wchar_t* rendering = ON_RDK_DOCUMENT ON_RDK_SLASH ON_RDK_SETTINGS ON_RDK_SLASH ON_RDK_RENDERING; +static const wchar_t* rendering = ON_RDK_DOCUMENT ON_XML_SLASH ON_RDK_SETTINGS ON_XML_SLASH ON_RDK_RENDERING; ON_UUID ON_3dmRenderSettings::CurrentRenderPreset(void) const { @@ -3110,6 +3112,8 @@ bool ON_StandardDisplayModeId::IsStandardDisplayModeId( return true; if ( ON_StandardDisplayModeId::Pen == id ) return true; + if (ON_StandardDisplayModeId::Monochrome == id) + return true; if ( ON_StandardDisplayModeId::AmbientOcclusion == id) return true; if ( ON_StandardDisplayModeId::Raytraced == id) diff --git a/opennurbs_3dm_settings.h b/opennurbs_3dm_settings.h index d4a9015e..3fe1608e 100644 --- a/opennurbs_3dm_settings.h +++ b/opennurbs_3dm_settings.h @@ -526,6 +526,7 @@ public: static const ON_UUID Technical; // {63612C72-778F-4afd-B81B-17426FDFE8A6} static const ON_UUID Artistic; // {B46AB226-05A0-4568-B454-4B1AB721C675} static const ON_UUID Pen; // {F4616FA5-A831-4620-A97E-9B807D5EC376} + static const ON_UUID Monochrome; // {E1B5C8A2-ED43-4872-9A01-814E612D5363} static const ON_UUID AmbientOcclusion; // {C32B72C3-41BD-4ADC-82A8-B7AEF4456A37} static const ON_UUID Raytraced; // {69E0C7A5-1C6A-46C8-B98B-8779686CD181} diff --git a/opennurbs_arccurve.h b/opennurbs_arccurve.h index 3481f03d..3c02ab41 100644 --- a/opennurbs_arccurve.h +++ b/opennurbs_arccurve.h @@ -378,6 +378,9 @@ public: // The dimension of a arc curve can be 2 or 3. // (2 so ON_ArcCurve can be used as a trimming curve) int m_dim = 3; + + // TODO ON_LineCurve::GetClosestPoint( ON_Curve&...) doesn't need an override. + #pragma warning(suppress : 4266) }; diff --git a/opennurbs_bezier.cpp b/opennurbs_bezier.cpp index 1bd33e04..ce001211 100644 --- a/opennurbs_bezier.cpp +++ b/opennurbs_bezier.cpp @@ -3686,6 +3686,284 @@ bool ON_BezierCurve::Ev2Der( // returns false if unable to evaluate return rc; } +#define Internal_ON_BezierSurfaceInterpolateMaxOrder 10U + +static bool Internal_CalculateON_BezierSurfaceGridInterploationMatrix( + unsigned order0, + unsigned order1, + ON_Matrix& T + ) +{ + const unsigned max_order = Internal_ON_BezierSurfaceInterpolateMaxOrder; + if (order0 < 2 || order0 > max_order || order1 < 2 || order1 > max_order) + { + ON_ERROR("Invalid input point grid size."); + return false; + } + + // TWODEX() converts 0 <= k < order0*order1 into (0<=i maxe) + maxe = e; + } + } + } + } + + text_log.Print("order = (%u,%u). Maximimum normalized interpolation error = %g.\n", order0, order1, maxe); +#endif + +#undef TWODEX + + return true; +} + +static const ON_Matrix* Internal_ON_BezierSurfaceGridInterploationMatrix( + unsigned order0, unsigned order1 +) +{ + if ( + order0 < 2 || order0 > Internal_ON_BezierSurfaceInterpolateMaxOrder + || + order1 < 2 || order1 > Internal_ON_BezierSurfaceInterpolateMaxOrder) + { + ON_ERROR("Invalid input point grid size."); + return nullptr; + } + + static ON_Matrix* Tcache[Internal_ON_BezierSurfaceInterpolateMaxOrder - 1U][Internal_ON_BezierSurfaceInterpolateMaxOrder - 1U] = {}; + if (nullptr == Tcache[order0-2][order1-2]) + { + ON_Matrix T; + if (Internal_CalculateON_BezierSurfaceGridInterploationMatrix(order0,order1,T)) + { + // The Tcache[][] matrices are created as needed and then used for the lifetime of the instance. + // The memory used to store the matrices is app workspace memory and is not leaked. + ON_MemoryAllocationTracking disable_tracking(false); + Tcache[order0 - 2][order1 - 2] = new ON_Matrix(T); + } + } + + return Tcache[order0 - 2][order1 - 2]; +} + + + +ON_BezierSurface* ON_BezierSurface::InterpolateGrid( + const double* point_grid, + int dim, + int point_count0, int point_count1, + size_t point_stride0, size_t point_stride1, + ON_BezierSurface* dest +) +{ + const unsigned max_order = Internal_ON_BezierSurfaceInterpolateMaxOrder; + + if (nullptr == point_grid) + return nullptr; + if (dim < 1) + return nullptr; + if (point_count0 < 2 || point_count0 > max_order) + return nullptr; + if (point_count1 < 2 || point_count1 > max_order) + return nullptr; + if (point_stride0 < dim) + return nullptr; + if (point_stride1 < dim) + return nullptr; + if (point_stride0 < point_stride1 * dim && point_stride1 < point_stride0 * dim) + return nullptr; + + const ON_Matrix* T = Internal_ON_BezierSurfaceGridInterploationMatrix(point_count0, point_count1); + if (nullptr == T) + return nullptr; + + ON_BezierSurface* bez = (nullptr != dest) ? dest : new ON_BezierSurface(); + if ( + dim != bez->m_dim + || 0 != bez->m_is_rat + || point_count0 != bez->m_order[0] + || point_count1 != bez->m_order[1] + || nullptr == bez->m_cv + || bez->m_cv_stride[0] < dim + || bez->m_cv_stride[1] < dim + || (bez->m_cv_stride[0] < bez->m_cv_stride[1]*dim && bez->m_cv_stride[1] < bez->m_cv_stride[0] * dim) + ) + { + bez->ReserveCVCapacity(point_count0 * point_count1 * dim); + bez->m_dim = dim; + bez->m_is_rat = 0; + bez->m_order[0] = point_count0; + bez->m_order[1] = point_count1; + bez->m_cv_stride[0] = bez->m_dim * bez->m_order[1]; + bez->m_cv_stride[1] = bez->m_dim; + } + + const int Tcount = point_count0 * point_count1; + for (int Ti = 0; Ti < Tcount; ++Ti) + { + const ON_2dex cvdex( Ti % point_count0, Ti / point_count0 ); + double* bezcv = bez->CV(cvdex.i, cvdex.j); + for (int k = 0; k < dim; ++k) + bezcv[k] = 0.0; + const double* Trow = T->m[Ti]; + for (int Tj = 0; Tj < Tcount; ++Tj) + { + const double t = Trow[Tj]; + if (0.0 == t) + continue; + const ON_2dex griddex(Tj % point_count0, Tj / point_count0); + const double* G = point_grid + (griddex.i * point_stride0 + griddex.j * point_stride1); + for (int k = 0; k < dim; ++k) + bezcv[k] += t * G[k]; + } + } + + return bez; +} + + +ON_BezierSurface* ON_BezierSurface::InterpolateGrid( + const ON_3dPoint* point_grid, + int point_count0, int point_count1, + size_t point_stride0, size_t point_stride1, + ON_BezierSurface* dest +) +{ + return ON_BezierSurface::InterpolateGrid( + (const double*)point_grid, + 3, + point_count0, point_count1, + point_stride0*3, point_stride1*3, + dest + ); +} diff --git a/opennurbs_bezier.h b/opennurbs_bezier.h index eabb187b..faec9390 100644 --- a/opennurbs_bezier.h +++ b/opennurbs_bezier.h @@ -1319,6 +1319,53 @@ public: */ bool GetSurfaceSize(double* width, double* height) const; + /// + /// Interpolate arectangular grid of points so that + /// bez(i/(point_count0 - 1), i/(point_count1 - 1))) = point_grid[i][j]. + /// The returned bezier has order (point_count0,point_count1). + /// Be aware that interpolation of irregular grids can create surfaces with extreme oscillations. + /// + /// Grid points + /// dimension of grid points and returned bezier surface (dim >= 1) + /// Number of grid points in the "i" direction. + /// Number of grid points in the "j" direction. + /// "i" direction stride in doubles. + /// "j" direction stride in doubles. + /// If dest is not nullptr, then the bezier will be created in this instance. Otherwise + /// new ON_BezierSurface(dim,0,point_count0,point_count1) will be used to allocate a bezier. + /// + /// If the input is valid, a bezier surface is returned such that + /// bez(i/(point_count0 - 1), i/(point_count1 - 1))) = point_grid[i][j]. + /// Otherwise nullptr is returned. + /// + static ON_BezierSurface* InterpolateGrid( + const double* point_grid, + int dim, + int point_count0, int point_count1, + size_t point_stride0, size_t point_stride1, + ON_BezierSurface* dest + ); + + + /// + /// Interpolate arectangular grid of 3d points so that + /// bez(i/(point_count0 - 1), i/(point_count1 - 1))) = point_grid[i][j] + /// + /// Grid points + /// Number of grid points "i" direction. + /// Number of grid points in the "j" direction. + /// "i" direction stride in ON_3dPoints. + /// "j" direction stride in ON_3dPoints. + /// If dest is not nullptr, then the bezier will be created in this instance. Otherwise + /// new ON_BezierSurface(dim,0,point_count0,point_count1) will be used to allocate a bezier. + /// + static ON_BezierSurface* InterpolateGrid( + const ON_3dPoint* point_grid, + int point_count0, int point_count1, + size_t point_stride0, size_t point_stride1, + ON_BezierSurface* dest + ); + ///////////////////////////////////////////////////////////////// // Implementation public: diff --git a/opennurbs_curveproxy.h b/opennurbs_curveproxy.h index 61bda601..749fdf62 100644 --- a/opennurbs_curveproxy.h +++ b/opennurbs_curveproxy.h @@ -458,6 +458,7 @@ public: double, // curve_t double* // nurbs_t ) const override; + }; diff --git a/opennurbs_decals.cpp b/opennurbs_decals.cpp index 7fee6f16..b4360487 100644 --- a/opennurbs_decals.cpp +++ b/opennurbs_decals.cpp @@ -22,47 +22,6 @@ #error ON_COMPILING_OPENNURBS must be defined when compiling opennurbs #endif - #define ON_DECALS L"decals" - #define ON_DECAL L"decal" - #define ON_DECAL_CUSTOM L"custom" - #define ON_DECAL_CUSTOM_RENDERER L"renderer" - #define ON_DECAL_CUSTOM_PARAMS L"parameters" - - #define ON_DECAL_MAPPING L"mapping" - //----- +++++++++++++++++++ - #define ON_DECAL_MAPPING_PLANAR L"planar" - #define ON_DECAL_MAPPING_CYLINDRICAL L"cylindrical" - #define ON_DECAL_MAPPING_SPHERICAL L"spherical" - #define ON_DECAL_MAPPING_UV L"uv" - #define ON_DECAL_MAPPING_NONE L"none" - - #define ON_DECAL_PROJECTION L"projection" - //----- ++++++++++++++++++++++ - #define ON_DECAL_PROJECTION_FORWARD L"forward" - #define ON_DECAL_PROJECTION_BACKWARD L"backward" - #define ON_DECAL_PROJECTION_BOTH L"both" - #define ON_DECAL_PROJECTION_NONE L"none" - - #define ON_DECAL_MAP_TO_INSIDE_ON L"map-to-inside-on" - #define ON_DECAL_TRANSPARENCY L"transparency" - #define ON_DECAL_TEXTURE_INSTANCE L"texture-instance" - #define ON_DECAL_HEIGHT L"height" - #define ON_DECAL_ORIGIN L"origin" - #define ON_DECAL_RADIUS L"radius" - #define ON_DECAL_HORZ_SWEEP_STA L"latitude-start" - #define ON_DECAL_HORZ_SWEEP_END L"latitude-stop" - #define ON_DECAL_VERT_SWEEP_STA L"longitude-start" - #define ON_DECAL_VERT_SWEEP_END L"longitude-stop" - #define ON_DECAL_VECTOR_UP L"vector-up" - #define ON_DECAL_VECTOR_ACROSS L"vector-across" - #define ON_DECAL_MIN_U L"min-u" - #define ON_DECAL_MIN_V L"min-v" - #define ON_DECAL_MAX_U L"max-u" - #define ON_DECAL_MAX_V L"max-v" - #define ON_DECAL_IS_TEMPORARY L"is-temporary" - #define ON_DECAL_IS_VISIBLE L"is-visible" - #define ON_DECAL_INSTANCE_ID L"instance-id" - // ON_Decal static ON_4dPoint UNSET_4D_POINT = ON_4dPoint(ON_UNSET_VALUE, ON_UNSET_VALUE, ON_UNSET_VALUE, ON_UNSET_VALUE); @@ -106,7 +65,7 @@ public: ON_XMLVariant GetParameter(const wchar_t* param_name, const ON_XMLVariant& def) const; void SetParameter(const wchar_t* param_name, const ON_XMLVariant& value); ON_XMLNode* FindCustomNodeForRenderEngine(const ON_UUID& renderEngineId) const; - virtual ON_wString NameOfRootNode(void) const override { return ON_DECAL; } + virtual ON_wString NameOfRootNode(void) const override { return ON_RDK_DECAL; } static const int unset_bool = 2; mutable struct Cache @@ -136,11 +95,11 @@ private: static ON_Decal::Mappings MappingFromString(const ON_wString& s) { - if (s == ON_DECAL_MAPPING_PLANAR) return ON_Decal::Mappings::Planar; - else if (s == ON_DECAL_MAPPING_SPHERICAL) return ON_Decal::Mappings::Spherical; - else if (s == ON_DECAL_MAPPING_CYLINDRICAL) return ON_Decal::Mappings::Cylindrical; - else if (s == ON_DECAL_MAPPING_UV) return ON_Decal::Mappings::UV; - else if (s == ON_DECAL_MAPPING_NONE) return ON_Decal::Mappings::None; + if (s == ON_RDK_DECAL_MAPPING_PLANAR) return ON_Decal::Mappings::Planar; + else if (s == ON_RDK_DECAL_MAPPING_SPHERICAL) return ON_Decal::Mappings::Spherical; + else if (s == ON_RDK_DECAL_MAPPING_CYLINDRICAL) return ON_Decal::Mappings::Cylindrical; + else if (s == ON_RDK_DECAL_MAPPING_UV) return ON_Decal::Mappings::UV; + else if (s == ON_RDK_DECAL_MAPPING_NONE) return ON_Decal::Mappings::None; ON_ASSERT(false); return ON_Decal::Mappings::None; @@ -163,7 +122,7 @@ ON_UUID ON_Decal::CImpl::TextureInstanceId(void) const { if (!_cache.texture_instance_id_set) { - _cache.texture_instance_id = GetParameter(ON_DECAL_TEXTURE_INSTANCE, ON_nil_uuid).AsUuid(); + _cache.texture_instance_id = GetParameter(ON_RDK_DECAL_TEXTURE_INSTANCE, ON_nil_uuid).AsUuid(); _cache.texture_instance_id_set = true; } @@ -176,7 +135,7 @@ void ON_Decal::CImpl::SetTextureInstanceId(const ON_UUID& id) { _cache.texture_instance_id = id; _cache.texture_instance_id_set = true; - SetParameter(ON_DECAL_TEXTURE_INSTANCE, id); + SetParameter(ON_RDK_DECAL_TEXTURE_INSTANCE, id); } } @@ -184,7 +143,7 @@ ON_Decal::Mappings ON_Decal::CImpl::Mapping(void) const { if (Mappings::None == _cache.mapping) { - const ON_wString s = GetParameter(ON_DECAL_MAPPING, ON_DECAL_MAPPING_UV).AsString(); + const ON_wString s = GetParameter(ON_RDK_DECAL_MAPPING, ON_RDK_DECAL_MAPPING_UV).AsString(); _cache.mapping = MappingFromString(s); } @@ -201,14 +160,14 @@ void ON_Decal::CImpl::SetMapping(Mappings m) switch (m) { default: ON_ASSERT(false); - case Mappings::None: s = ON_DECAL_MAPPING_NONE; break; - case Mappings::Planar: s = ON_DECAL_MAPPING_PLANAR; break; - case Mappings::Spherical: s = ON_DECAL_MAPPING_SPHERICAL; break; - case Mappings::Cylindrical: s = ON_DECAL_MAPPING_CYLINDRICAL; break; - case Mappings::UV: s = ON_DECAL_MAPPING_UV; break; + case Mappings::None: s = ON_RDK_DECAL_MAPPING_NONE; break; + case Mappings::Planar: s = ON_RDK_DECAL_MAPPING_PLANAR; break; + case Mappings::Spherical: s = ON_RDK_DECAL_MAPPING_SPHERICAL; break; + case Mappings::Cylindrical: s = ON_RDK_DECAL_MAPPING_CYLINDRICAL; break; + case Mappings::UV: s = ON_RDK_DECAL_MAPPING_UV; break; } - SetParameter(ON_DECAL_MAPPING, s); + SetParameter(ON_RDK_DECAL_MAPPING, s); } } @@ -216,11 +175,11 @@ ON_Decal::Projections ON_Decal::CImpl::Projection(void) const { if (Projections::None == _cache.projection) { - const ON_wString s = GetParameter(ON_DECAL_PROJECTION, ON_DECAL_PROJECTION_NONE).AsString(); - if (s == ON_DECAL_PROJECTION_FORWARD) _cache.projection = ON_Decal::Projections::Forward; - else if (s == ON_DECAL_PROJECTION_BACKWARD) _cache.projection = ON_Decal::Projections::Backward; - else if (s == ON_DECAL_PROJECTION_BOTH) _cache.projection = ON_Decal::Projections::Both; - else if (s == ON_DECAL_PROJECTION_NONE) _cache.projection = ON_Decal::Projections::None; + const ON_wString s = GetParameter(ON_RDK_DECAL_PROJECTION, ON_RDK_DECAL_PROJECTION_NONE).AsString(); + if (s == ON_RDK_DECAL_PROJECTION_FORWARD) _cache.projection = ON_Decal::Projections::Forward; + else if (s == ON_RDK_DECAL_PROJECTION_BACKWARD) _cache.projection = ON_Decal::Projections::Backward; + else if (s == ON_RDK_DECAL_PROJECTION_BOTH) _cache.projection = ON_Decal::Projections::Both; + else if (s == ON_RDK_DECAL_PROJECTION_NONE) _cache.projection = ON_Decal::Projections::None; else ON_ASSERT(false); } @@ -237,13 +196,13 @@ void ON_Decal::CImpl::SetProjection(Projections v) switch (v) { default: ON_ASSERT(false); - case ON_Decal::Projections::None: s = ON_DECAL_PROJECTION_NONE; break; - case ON_Decal::Projections::Forward: s = ON_DECAL_PROJECTION_FORWARD; break; - case ON_Decal::Projections::Backward: s = ON_DECAL_PROJECTION_BACKWARD; break; - case ON_Decal::Projections::Both: s = ON_DECAL_PROJECTION_BOTH; break; + case ON_Decal::Projections::None: s = ON_RDK_DECAL_PROJECTION_NONE; break; + case ON_Decal::Projections::Forward: s = ON_RDK_DECAL_PROJECTION_FORWARD; break; + case ON_Decal::Projections::Backward: s = ON_RDK_DECAL_PROJECTION_BACKWARD; break; + case ON_Decal::Projections::Both: s = ON_RDK_DECAL_PROJECTION_BOTH; break; } - SetParameter(ON_DECAL_PROJECTION, s); + SetParameter(ON_RDK_DECAL_PROJECTION, s); } } @@ -251,7 +210,7 @@ bool ON_Decal::CImpl::MapToInside(void) const { if (unset_bool == _cache.map_to_inside) { - _cache.map_to_inside = GetParameter(ON_DECAL_MAP_TO_INSIDE_ON, false).AsBool() ? 1 : 0; + _cache.map_to_inside = GetParameter(ON_RDK_DECAL_MAP_TO_INSIDE_ON, false).AsBool() ? 1 : 0; } return 0 != _cache.map_to_inside; @@ -263,7 +222,7 @@ void ON_Decal::CImpl::SetMapToInside(bool b) if (_cache.map_to_inside != i) { _cache.map_to_inside = i; - SetParameter(ON_DECAL_MAP_TO_INSIDE_ON, b); + SetParameter(ON_RDK_DECAL_MAP_TO_INSIDE_ON, b); } } @@ -271,7 +230,7 @@ double ON_Decal::CImpl::Transparency(void) const { if (ON_UNSET_VALUE == _cache.transparency) { - _cache.transparency = GetParameter(ON_DECAL_TRANSPARENCY, 0.0).AsDouble(); + _cache.transparency = GetParameter(ON_RDK_DECAL_TRANSPARENCY, 0.0).AsDouble(); } return _cache.transparency; @@ -282,7 +241,7 @@ void ON_Decal::CImpl::SetTransparency(double v) if (_cache.transparency != v) { _cache.transparency = v; - SetParameter(ON_DECAL_TRANSPARENCY, v); + SetParameter(ON_RDK_DECAL_TRANSPARENCY, v); } } @@ -290,7 +249,7 @@ ON_3dPoint ON_Decal::CImpl::Origin(void) const { if (ON_3dPoint::UnsetPoint == _cache.origin) { - _cache.origin = GetParameter(ON_DECAL_ORIGIN, ON_3dPoint::Origin).As3dPoint(); + _cache.origin = GetParameter(ON_RDK_DECAL_ORIGIN, ON_3dPoint::Origin).As3dPoint(); } return _cache.origin; @@ -301,7 +260,7 @@ void ON_Decal::CImpl::SetOrigin(const ON_3dPoint& pt) if (_cache.origin != pt) { _cache.origin = pt; - SetParameter(ON_DECAL_ORIGIN, pt); + SetParameter(ON_RDK_DECAL_ORIGIN, pt); } } @@ -309,7 +268,7 @@ ON_3dVector ON_Decal::CImpl::VectorUp(void) const { if (ON_3dVector::UnsetVector == _cache.vector_up) { - _cache.vector_up = GetParameter(ON_DECAL_VECTOR_UP, ON_3dPoint::Origin).As3dPoint(); + _cache.vector_up = GetParameter(ON_RDK_DECAL_VECTOR_UP, ON_3dPoint::Origin).As3dPoint(); } return _cache.vector_up; @@ -320,7 +279,7 @@ void ON_Decal::CImpl::SetVectorUp(const ON_3dVector& v) if (_cache.vector_up != v) { _cache.vector_up = v; - SetParameter(ON_DECAL_VECTOR_UP, ON_3dPoint(v)); + SetParameter(ON_RDK_DECAL_VECTOR_UP, ON_3dPoint(v)); } } @@ -328,7 +287,7 @@ ON_3dVector ON_Decal::CImpl::VectorAcross(void) const { if (ON_3dVector::UnsetVector == _cache.vector_across) { - _cache.vector_across = GetParameter(ON_DECAL_VECTOR_ACROSS, ON_3dPoint::Origin).As3dPoint(); + _cache.vector_across = GetParameter(ON_RDK_DECAL_VECTOR_ACROSS, ON_3dPoint::Origin).As3dPoint(); } return _cache.vector_across; @@ -339,7 +298,7 @@ void ON_Decal::CImpl::SetVectorAcross(const ON_3dVector& v) if (_cache.vector_across != v) { _cache.vector_across = v; - SetParameter(ON_DECAL_VECTOR_ACROSS, ON_3dPoint(v)); + SetParameter(ON_RDK_DECAL_VECTOR_ACROSS, ON_3dPoint(v)); } } @@ -347,7 +306,7 @@ double ON_Decal::CImpl::Height(void) const { if (ON_UNSET_VALUE == _cache.height) { - _cache.height = GetParameter(ON_DECAL_HEIGHT, 1.0).AsDouble(); + _cache.height = GetParameter(ON_RDK_DECAL_HEIGHT, 1.0).AsDouble(); } return _cache.height; @@ -358,7 +317,7 @@ void ON_Decal::CImpl::SetHeight(double v) if (_cache.height != v) { _cache.height = v; - SetParameter(ON_DECAL_HEIGHT, v); + SetParameter(ON_RDK_DECAL_HEIGHT, v); } } @@ -366,7 +325,7 @@ double ON_Decal::CImpl::Radius(void) const { if (ON_UNSET_VALUE == _cache.radius) { - _cache.radius = GetParameter(ON_DECAL_RADIUS, 1.0).AsDouble(); + _cache.radius = GetParameter(ON_RDK_DECAL_RADIUS, 1.0).AsDouble(); } return _cache.radius; @@ -377,7 +336,7 @@ void ON_Decal::CImpl::SetRadius(double v) if (_cache.radius != v) { _cache.radius = v; - SetParameter(ON_DECAL_RADIUS, v); + SetParameter(ON_RDK_DECAL_RADIUS, v); } } @@ -385,7 +344,7 @@ bool ON_Decal::CImpl::IsVisible(void) const { if (unset_bool == _cache.visible) { - _cache.visible = GetParameter(ON_DECAL_IS_VISIBLE, true).AsBool(); + _cache.visible = GetParameter(ON_RDK_DECAL_IS_VISIBLE, true).AsBool(); } return 0 != _cache.visible; @@ -397,7 +356,7 @@ void ON_Decal::CImpl::SetIsVisible(bool b) if (_cache.visible != i) { _cache.visible = i; - SetParameter(ON_DECAL_IS_VISIBLE, b); + SetParameter(ON_RDK_DECAL_IS_VISIBLE, b); } } @@ -405,8 +364,8 @@ void ON_Decal::CImpl::GetHorzSweep(double& sta, double& end) const { if (ON_2dPoint::UnsetPoint == _cache.horz_sweep) { - _cache.horz_sweep.x = GetParameter(ON_DECAL_HORZ_SWEEP_STA, 0.0).AsDouble(); - _cache.horz_sweep.y = GetParameter(ON_DECAL_HORZ_SWEEP_END, 0.0).AsDouble(); + _cache.horz_sweep.x = GetParameter(ON_RDK_DECAL_HORZ_SWEEP_STA, 0.0).AsDouble(); + _cache.horz_sweep.y = GetParameter(ON_RDK_DECAL_HORZ_SWEEP_END, 0.0).AsDouble(); } sta = _cache.horz_sweep.x; @@ -419,8 +378,8 @@ void ON_Decal::CImpl::SetHorzSweep(double sta, double end) if (_cache.horz_sweep != sweep) { _cache.horz_sweep = sweep; - SetParameter(ON_DECAL_HORZ_SWEEP_STA, sta); - SetParameter(ON_DECAL_HORZ_SWEEP_END, end); + SetParameter(ON_RDK_DECAL_HORZ_SWEEP_STA, sta); + SetParameter(ON_RDK_DECAL_HORZ_SWEEP_END, end); } } @@ -428,8 +387,8 @@ void ON_Decal::CImpl::GetVertSweep(double& sta, double& end) const { if (ON_2dPoint::UnsetPoint == _cache.vert_sweep) { - _cache.vert_sweep.x = GetParameter(ON_DECAL_VERT_SWEEP_STA, 0.0).AsDouble(); - _cache.vert_sweep.y = GetParameter(ON_DECAL_VERT_SWEEP_END, 0.0).AsDouble(); + _cache.vert_sweep.x = GetParameter(ON_RDK_DECAL_VERT_SWEEP_STA, 0.0).AsDouble(); + _cache.vert_sweep.y = GetParameter(ON_RDK_DECAL_VERT_SWEEP_END, 0.0).AsDouble(); } sta = _cache.vert_sweep.x; @@ -442,8 +401,8 @@ void ON_Decal::CImpl::SetVertSweep(double sta, double end) if (_cache.vert_sweep != sweep) { _cache.vert_sweep = sweep; - SetParameter(ON_DECAL_VERT_SWEEP_STA, sta); - SetParameter(ON_DECAL_VERT_SWEEP_END, end); + SetParameter(ON_RDK_DECAL_VERT_SWEEP_STA, sta); + SetParameter(ON_RDK_DECAL_VERT_SWEEP_END, end); } } @@ -451,10 +410,10 @@ void ON_Decal::CImpl::GetUVBounds(double& min_u, double& min_v, double& max_u, d { if (UNSET_4D_POINT == _cache.uv_bounds) { - _cache.uv_bounds.x = GetParameter(ON_DECAL_MIN_U, 0.0).AsDouble(); - _cache.uv_bounds.y = GetParameter(ON_DECAL_MIN_V, 0.0).AsDouble(); - _cache.uv_bounds.z = GetParameter(ON_DECAL_MAX_U, 1.0).AsDouble(); - _cache.uv_bounds.w = GetParameter(ON_DECAL_MAX_V, 1.0).AsDouble(); + _cache.uv_bounds.x = GetParameter(ON_RDK_DECAL_MIN_U, 0.0).AsDouble(); + _cache.uv_bounds.y = GetParameter(ON_RDK_DECAL_MIN_V, 0.0).AsDouble(); + _cache.uv_bounds.z = GetParameter(ON_RDK_DECAL_MAX_U, 1.0).AsDouble(); + _cache.uv_bounds.w = GetParameter(ON_RDK_DECAL_MAX_V, 1.0).AsDouble(); } min_u = _cache.uv_bounds.x; @@ -469,10 +428,10 @@ void ON_Decal::CImpl::SetUVBounds(double min_u, double min_v, double max_u, doub if (_cache.uv_bounds != bounds) { _cache.uv_bounds = bounds; - SetParameter(ON_DECAL_MIN_U, min_u); - SetParameter(ON_DECAL_MIN_V, min_v); - SetParameter(ON_DECAL_MAX_U, max_u); - SetParameter(ON_DECAL_MAX_V, max_v); + SetParameter(ON_RDK_DECAL_MIN_U, min_u); + SetParameter(ON_RDK_DECAL_MIN_V, min_v); + SetParameter(ON_RDK_DECAL_MAX_U, max_u); + SetParameter(ON_RDK_DECAL_MAX_V, max_v); } } @@ -482,9 +441,9 @@ ON_XMLNode* ON_Decal::CImpl::FindCustomNodeForRenderEngine(const ON_UUID& render auto it = Node().GetChildIterator(); while (nullptr != (child_node = it.GetNextChild())) { - if (child_node->TagName() == ON_DECAL_CUSTOM) + if (child_node->TagName() == ON_RDK_DECAL_CUSTOM) { - const ON_XMLProperty* prop = child_node->GetNamedProperty(ON_DECAL_CUSTOM_RENDERER); + const ON_XMLProperty* prop = child_node->GetNamedProperty(ON_RDK_DECAL_CUSTOM_RENDERER); if ((nullptr != prop) && (prop->GetValue().AsUuid() == renderEngineId)) return child_node; } @@ -500,7 +459,7 @@ ON_Decal::ON_Decal() ON_Decal::ON_Decal(ON_DecalCollection& dc, ON_XMLNode& node) { - ON_ASSERT(node.TagName() == ON_DECAL); + ON_ASSERT(node.TagName() == ON_RDK_DECAL); _impl = new CImpl(dc, node); } @@ -728,14 +687,14 @@ ON__UINT32 ON_Decal::DataCRC(ON__UINT32 current_remainder) const void ON_Decal::GetCustomXML(const ON_UUID& renderEngineId, ON_XMLNode& custom_param_node) const { custom_param_node.Clear(); - custom_param_node.SetTagName(ON_DECAL_CUSTOM_PARAMS); + custom_param_node.SetTagName(ON_RDK_DECAL_CUSTOM_PARAMS); // Find the node for 'renderEngineId'. const ON_XMLNode* custom_node = _impl->FindCustomNodeForRenderEngine(renderEngineId); if (nullptr != custom_node) { // Get the parameter node and copy it to 'custom_param_node'. - const ON_XMLNode* param_node = custom_node->GetNamedChild(ON_DECAL_CUSTOM_PARAMS); + const ON_XMLNode* param_node = custom_node->GetNamedChild(ON_RDK_DECAL_CUSTOM_PARAMS); if (nullptr != param_node) { custom_param_node = *param_node; @@ -745,7 +704,7 @@ void ON_Decal::GetCustomXML(const ON_UUID& renderEngineId, ON_XMLNode& custom_pa bool ON_Decal::SetCustomXML(const ON_UUID& renderEngineId, const ON_XMLNode& custom_param_node) { - if (custom_param_node.TagName() != ON_DECAL_CUSTOM_PARAMS) + if (custom_param_node.TagName() != ON_RDK_DECAL_CUSTOM_PARAMS) return false; // If there is already a custom node for 'renderEngineId' then delete it. @@ -760,8 +719,8 @@ bool ON_Decal::SetCustomXML(const ON_UUID& renderEngineId, const ON_XMLNode& cus } // Attach the new custom node and set its 'renderer' property to be the render engine id. - custom_node = _impl->Node().AttachChildNode(new ON_XMLNode(ON_DECAL_CUSTOM)); - ON_XMLProperty prop(ON_DECAL_CUSTOM_RENDERER, renderEngineId); + custom_node = _impl->Node().AttachChildNode(new ON_XMLNode(ON_RDK_DECAL_CUSTOM)); + ON_XMLProperty prop(ON_RDK_DECAL_CUSTOM_RENDERER, renderEngineId); custom_node->SetProperty(prop); // Attach a copy of the custom param node to the custom node. @@ -854,27 +813,27 @@ class ON_DecalNodeReader public: ON_DecalNodeReader(const ON_XMLNode* p) : m_pNode(p) { } - ON_XMLVariant Mapping(void) const { return Value(ON_DECAL_MAPPING, ON_DECAL_MAPPING_NONE); } - ON_XMLVariant Projection(void) const { return Value(ON_DECAL_PROJECTION, ON_DECAL_PROJECTION_NONE); } - ON_XMLVariant MapToInside(void) const { return Value(ON_DECAL_MAP_TO_INSIDE_ON, m_def.MapToInside()); } - ON_XMLVariant Transparency(void) const { return Value(ON_DECAL_TRANSPARENCY , m_def.Transparency()); } - ON_XMLVariant TextureInstanceId(void) const { return Value(ON_DECAL_TEXTURE_INSTANCE, m_def.TextureInstanceId()); } - ON_XMLVariant Height(void) const { return Value(ON_DECAL_HEIGHT , m_def.Height()); } - ON_XMLVariant Radius(void) const { return Value(ON_DECAL_RADIUS , m_def.Radius()); } - ON_XMLVariant Origin(void) const { return Value(ON_DECAL_ORIGIN , m_def.Origin()); } - ON_XMLVariant VectorUp(void) const { return Value(ON_DECAL_VECTOR_UP , ON_3dPoint(m_def.VectorUp())); } - ON_XMLVariant VectorAcross(void) const { return Value(ON_DECAL_VECTOR_ACROSS , ON_3dPoint(m_def.VectorAcross())); } - ON_XMLVariant HorzSweepSta(void) const { return Value(ON_DECAL_HORZ_SWEEP_STA , DefaultHorzSweepSta()); } - ON_XMLVariant HorzSweepEnd(void) const { return Value(ON_DECAL_HORZ_SWEEP_END , DefaultHorzSweepEnd()); } - ON_XMLVariant VertSweepSta(void) const { return Value(ON_DECAL_VERT_SWEEP_STA , DefaultVertSweepSta()); } - ON_XMLVariant VertSweepEnd(void) const { return Value(ON_DECAL_VERT_SWEEP_END , DefaultVertSweepEnd()); } - ON_XMLVariant MinU(void) const { return Value(ON_DECAL_MIN_U , DefaultMinU()); } - ON_XMLVariant MinV(void) const { return Value(ON_DECAL_MIN_V , DefaultMinV()); } - ON_XMLVariant MaxU(void) const { return Value(ON_DECAL_MAX_U , DefaultMaxU()); } - ON_XMLVariant MaxV(void) const { return Value(ON_DECAL_MAX_V , DefaultMaxV()); } - ON_XMLVariant IsTemporary(void) const { return Value(ON_DECAL_IS_TEMPORARY , false); } - ON_XMLVariant IsVisible(void) const { return Value(ON_DECAL_IS_VISIBLE , m_def.IsVisible()); } - ON_XMLVariant InstanceId(void) const { return Value(ON_DECAL_INSTANCE_ID , m_def.Id()); } + ON_XMLVariant Mapping(void) const { return Value(ON_RDK_DECAL_MAPPING, ON_RDK_DECAL_MAPPING_NONE); } + ON_XMLVariant Projection(void) const { return Value(ON_RDK_DECAL_PROJECTION, ON_RDK_DECAL_PROJECTION_NONE); } + ON_XMLVariant MapToInside(void) const { return Value(ON_RDK_DECAL_MAP_TO_INSIDE_ON, m_def.MapToInside()); } + ON_XMLVariant Transparency(void) const { return Value(ON_RDK_DECAL_TRANSPARENCY , m_def.Transparency()); } + ON_XMLVariant TextureInstanceId(void) const { return Value(ON_RDK_DECAL_TEXTURE_INSTANCE, m_def.TextureInstanceId()); } + ON_XMLVariant Height(void) const { return Value(ON_RDK_DECAL_HEIGHT , m_def.Height()); } + ON_XMLVariant Radius(void) const { return Value(ON_RDK_DECAL_RADIUS , m_def.Radius()); } + ON_XMLVariant Origin(void) const { return Value(ON_RDK_DECAL_ORIGIN , m_def.Origin()); } + ON_XMLVariant VectorUp(void) const { return Value(ON_RDK_DECAL_VECTOR_UP , ON_3dPoint(m_def.VectorUp())); } + ON_XMLVariant VectorAcross(void) const { return Value(ON_RDK_DECAL_VECTOR_ACROSS , ON_3dPoint(m_def.VectorAcross())); } + ON_XMLVariant HorzSweepSta(void) const { return Value(ON_RDK_DECAL_HORZ_SWEEP_STA , DefaultHorzSweepSta()); } + ON_XMLVariant HorzSweepEnd(void) const { return Value(ON_RDK_DECAL_HORZ_SWEEP_END , DefaultHorzSweepEnd()); } + ON_XMLVariant VertSweepSta(void) const { return Value(ON_RDK_DECAL_VERT_SWEEP_STA , DefaultVertSweepSta()); } + ON_XMLVariant VertSweepEnd(void) const { return Value(ON_RDK_DECAL_VERT_SWEEP_END , DefaultVertSweepEnd()); } + ON_XMLVariant MinU(void) const { return Value(ON_RDK_DECAL_MIN_U , DefaultMinU()); } + ON_XMLVariant MinV(void) const { return Value(ON_RDK_DECAL_MIN_V , DefaultMinV()); } + ON_XMLVariant MaxU(void) const { return Value(ON_RDK_DECAL_MAX_U , DefaultMaxU()); } + ON_XMLVariant MaxV(void) const { return Value(ON_RDK_DECAL_MAX_V , DefaultMaxV()); } + ON_XMLVariant IsTemporary(void) const { return Value(ON_RDK_DECAL_IS_TEMPORARY , false); } + ON_XMLVariant IsVisible(void) const { return Value(ON_RDK_DECAL_IS_VISIBLE , m_def.IsVisible()); } + ON_XMLVariant InstanceId(void) const { return Value(ON_RDK_DECAL_INSTANCE_ID , m_def.Id()); } private: ON_XMLVariant Value(const wchar_t* wszName, const ON_XMLVariant& vDefault) const; @@ -966,10 +925,10 @@ ON__UINT32 ON_Decal::ComputeDecalCRC(ON__UINT32 crc, const ON_XMLNode& node) // ON_XMLNode* pChildNode = nullptr; while (nullptr != (pChildNode = it.GetNextChild())) { - if (pChildNode->TagName() != ON_DECAL_CUSTOM) + if (pChildNode->TagName() != ON_RDK_DECAL_CUSTOM) continue; // Not a custom data node. - ON_XMLProperty* prop = pChildNode->GetNamedProperty(ON_DECAL_CUSTOM_RENDERER); + ON_XMLProperty* prop = pChildNode->GetNamedProperty(ON_RDK_DECAL_CUSTOM_RENDERER); if (nullptr != prop) { // Include the render engine id. @@ -978,7 +937,7 @@ ON__UINT32 ON_Decal::ComputeDecalCRC(ON__UINT32 crc, const ON_XMLNode& node) // } // Find the custom parameter node. - const ON_XMLNode* pParamNode = pChildNode->GetNamedChild(ON_DECAL_CUSTOM_PARAMS); + const ON_XMLNode* pParamNode = pChildNode->GetNamedChild(ON_RDK_DECAL_CUSTOM_PARAMS); if (nullptr != pParamNode) { // Iterate over the nodes inside the custom parameter node. @@ -1088,7 +1047,7 @@ void ON_DecalCollection::Populate(void) const if (GetEntireDecalXML(*m_attr, m_root_node)) { - const wchar_t* path = ON_RDK_UD_ROOT ON_RDK_SLASH ON_DECALS; + const wchar_t* path = ON_RDK_UD_ROOT ON_XML_SLASH ON_RDK_DECALS; ON_XMLNode* decals_node = m_root_node.GetNodeAtPath(path); if (nullptr != decals_node) { @@ -1119,11 +1078,11 @@ ON_Decal* ON_DecalCollection::AddDecal(void) ON_Decal* decal = nullptr; - ON_XMLNode* decals_node = m_root_node.CreateNodeAtPath(ON_RDK_UD_ROOT ON_RDK_SLASH ON_DECALS); + ON_XMLNode* decals_node = m_root_node.CreateNodeAtPath(ON_RDK_UD_ROOT ON_XML_SLASH ON_RDK_DECALS); if (nullptr != decals_node) { // Add an XML node for the new decal. - auto* decal_node = new ON_XMLNode(ON_DECAL); + auto* decal_node = new ON_XMLNode(ON_RDK_DECAL); decals_node->AttachChildNode(decal_node); // Add the new decal. It stores a pointer to the new XML node. This is safe because diff --git a/opennurbs_defines.cpp b/opennurbs_defines.cpp index abf31973..e79ea1c3 100644 --- a/opennurbs_defines.cpp +++ b/opennurbs_defines.cpp @@ -2863,6 +2863,21 @@ ON::SectionAttributesSource ON::SectionAttributesSourceFromUnsigned( return ON::SectionAttributesSource::FromLayer; } +ON::SectionLabelStyle ON::SectionLabelStyleFromUnsigned( + unsigned int section_label_style_as_unsigned +) +{ + switch (section_label_style_as_unsigned) + { + ON_ENUM_FROM_UNSIGNED_CASE(ON::SectionLabelStyle::None); + ON_ENUM_FROM_UNSIGNED_CASE(ON::SectionLabelStyle::TextDotFromName); + ON_ENUM_FROM_UNSIGNED_CASE(ON::SectionLabelStyle::TextFromName); + } + ON_ERROR("invalid section_label_style_as_unsigned parameter."); + return ON::SectionLabelStyle::None; +} + + ON::ViewSectionBehavior ON::ViewSectionBehaviorFromUnsigned( unsigned int view_section_behavior_as_unsigned ) diff --git a/opennurbs_defines.h b/opennurbs_defines.h index c7b09b9b..14c46509 100644 --- a/opennurbs_defines.h +++ b/opennurbs_defines.h @@ -2536,6 +2536,25 @@ public: unsigned int section_attributes_source_as_unsigned ); +#pragma region RH_C_SHARED_ENUM [ON::SectionLabelStyle] [Rhino.DocObjects.SectionLabelStyle] + /// + /// The source of sectioning attributes on an object. + /// + /// 8.0 + enum class SectionLabelStyle : unsigned char + { + /// No label + None = 0, + /// Label shown as a text dot with content from name + TextDotFromName = 1, + /// Label shown as text with content from name + TextFromName = 2, + }; +#pragma endregion + + static SectionLabelStyle SectionLabelStyleFromUnsigned( + unsigned int section_label_style_as_unsigned + ); #pragma region RH_C_SHARED_ENUM [ON::ViewSectionBehavior] [Rhino.DocObjects.ViewSectionBehavior] /// diff --git a/opennurbs_dithering.cpp b/opennurbs_dithering.cpp index 0e3cf70a..f3cdd705 100644 --- a/opennurbs_dithering.cpp +++ b/opennurbs_dithering.cpp @@ -31,7 +31,7 @@ public: static const wchar_t* XMLPathDit(void) { - return ON_RDK_DOCUMENT ON_RDK_SLASH ON_RDK_SETTINGS ON_RDK_SLASH ON_RDK_RENDERING; + return ON_RDK_DOCUMENT ON_XML_SLASH ON_RDK_SETTINGS ON_XML_SLASH ON_RDK_RENDERING; } ON_Dithering::ON_Dithering() @@ -124,6 +124,6 @@ void* ON_Dithering::EVF(const wchar_t* func, void* data) return nullptr; } -void ON_Dithering::InvalidateCache(void) +void ON_Dithering::OnInternalXmlChanged(const ON_Dithering*) { } diff --git a/opennurbs_dithering.h b/opennurbs_dithering.h index cc5a5c52..ef195036 100644 --- a/opennurbs_dithering.h +++ b/opennurbs_dithering.h @@ -49,7 +49,7 @@ public: private: // For internal use only. friend class ON_3dmRenderSettingsPrivate; - virtual void InvalidateCache(void); + virtual void OnInternalXmlChanged(const ON_Dithering*); private: class CImpl; diff --git a/opennurbs_embedded_file.cpp b/opennurbs_embedded_file.cpp index c57c63a1..0c41d3e3 100644 --- a/opennurbs_embedded_file.cpp +++ b/opennurbs_embedded_file.cpp @@ -306,8 +306,9 @@ const ON_EmbeddedFile* ON_EmbeddedFile::FromModelComponentRef(const ON_ModelComp return none_return_value; } -// This ON_Buffer stuff was already in file opennurbs_embedded_file.cpp even though it has nothing to do with files. -// I need this file for actual EMBEDDED FILE code so I'm hijacking it. This ON_Buffer stuff should be moved. +// This ON_Buffer stuff was already in file opennurbs_embedded_file.cpp even though it has nothing +// to do with embedded files. I need this file for actual embedded file code so I'm hijacking it. +// TODO: This ON_Buffer stuff should be moved. ON_Buffer::ON_Buffer() : m_buffer_size(0) diff --git a/opennurbs_extensions.cpp b/opennurbs_extensions.cpp index c4b9ce0c..82dfb1f3 100644 --- a/opennurbs_extensions.cpp +++ b/opennurbs_extensions.cpp @@ -423,9 +423,30 @@ bool ON_InternalXMLImpl::InternalSetParameter(const wchar_t* path_to_node, const return success; } +bool ON_InternalXMLImpl::RemoveParameter(const wchar_t* path_to_node, const wchar_t* param_name) +{ + std::lock_guard lg(_mutex); + + bool success = false; + + ON_XMLNode* node = Node().GetNodeAtPath(path_to_node); + if (nullptr != node) + { + ON_XMLNode* child = node->GetNamedChild(param_name); + success = node->RemoveChild(child); + } + + return success; +} + +// ONX_Model + ONX_Model::ONX_Model() { m_private = new ONX_ModelPrivate(*this); + + // Tell the sun in our render settings to use the earth anchor point in our settings. + m_settings.m_RenderSettings.Sun().UseEarthAnchorPoint(m_settings.m_earth_anchor_point); } ONX_Model::~ONX_Model() @@ -4944,7 +4965,7 @@ static bool ContentIsKind(const ON_RenderContent* pContent, RenderContentKinds k ON_XMLNode* ONX_ModelPrivate::GetPostEffectSectionNode(ON_XMLNode& docNode, ON_PostEffect::Types type) const { - ON_wString s = ON_RDK_DOCUMENT ON_RDK_SLASH ON_RDK_SETTINGS ON_RDK_SLASH ON_RDK_POST_EFFECTS ON_RDK_SLASH; + ON_wString s = ON_RDK_DOCUMENT ON_XML_SLASH ON_RDK_SETTINGS ON_XML_SLASH ON_RDK_POST_EFFECTS ON_XML_SLASH; s += ON_PostEffectTypeString(type); return docNode.CreateNodeAtPath(s); @@ -4952,7 +4973,7 @@ ON_XMLNode* ONX_ModelPrivate::GetPostEffectSectionNode(ON_XMLNode& docNode, ON_P ON_XMLNode* ONX_ModelPrivate::GetRenderContentSectionNode(ON_XMLNode& docNode, RenderContentKinds kind) const { - ON_wString s = ON_RDK_DOCUMENT ON_RDK_SLASH; + ON_wString s = ON_RDK_DOCUMENT ON_XML_SLASH; s += RenderContentKindString(kind); s += ON_RDK_POSTFIX_SECTION; diff --git a/opennurbs_ground_plane.cpp b/opennurbs_ground_plane.cpp index ba942e1f..46de5293 100644 --- a/opennurbs_ground_plane.cpp +++ b/opennurbs_ground_plane.cpp @@ -24,7 +24,7 @@ static const wchar_t* XMLPath(void) { - return ON_RDK_DOCUMENT ON_RDK_SLASH ON_RDK_SETTINGS ON_RDK_SLASH ON_RDK_GROUND_PLANE; + return ON_RDK_DOCUMENT ON_XML_SLASH ON_RDK_SETTINGS ON_XML_SLASH ON_RDK_GROUND_PLANE; } class ON_GroundPlane::CImpl : public ON_InternalXMLImpl @@ -34,25 +34,17 @@ public: CImpl(const CImpl& i) = delete; CImpl(ON_XMLNode& n) : ON_InternalXMLImpl(&n) { } - bool On(void) const { return GetParameter(XMLPath(), ON_RDK_GP_ON, false).AsBool(); } - bool ShowUnderside(void) const { return GetParameter(XMLPath(), ON_RDK_GP_SHOW_UNDERSIDE, false).AsBool(); } - double Altitude(void) const { return GetParameter(XMLPath(), ON_RDK_GP_ALTITUDE, 0.0).AsDouble(); } - bool AutoAltitude(void) const { return GetParameter(XMLPath(), ON_RDK_GP_AUTO_ALTITUDE, false).AsBool(); } - bool ShadowOnly(void) const { return GetParameter(XMLPath(), ON_RDK_GP_SHADOW_ONLY, true).AsBool(); } - bool TextureOffsetLocked(void) const { return GetParameter(XMLPath(), ON_RDK_GP_TEXTURE_OFFSET_LOCKED, false).AsBool(); } - bool TextureSizeLocked(void) const { return GetParameter(XMLPath(), ON_RDK_GP_TEXTURE_SIZE_LOCKED, false).AsBool(); } - double TextureRotation(void) const { return GetParameter(XMLPath(), ON_RDK_GP_TEXTURE_ROTATION, false).AsDouble(); } - ON_2dVector TextureOffset(void) const { return ON_2dVector(GetParameter(XMLPath(), ON_RDK_GP_TEXTURE_OFFSET, ON_nil_uuid).As2dPoint()); } - ON_2dVector TextureSize(void) const { return ON_2dVector(GetParameter(XMLPath(), ON_RDK_GP_TEXTURE_SIZE, ON_nil_uuid).As2dPoint()); } - - ON_UUID MaterialInstanceId(void) const - { - const auto u = GetParameter(XMLPath(), ON_RDK_GP_MATERIAL_ID, ON_nil_uuid).AsUuid(); - if (ON_nil_uuid != u) - return u; - - return ON_UuidDefaultMaterialInstance; - } + bool On(void) const { return GetParameter(XMLPath(), ON_RDK_GP_ON, false).AsBool(); } + bool ShowUnderside(void) const { return GetParameter(XMLPath(), ON_RDK_GP_SHOW_UNDERSIDE, false).AsBool(); } + double Altitude(void) const { return GetParameter(XMLPath(), ON_RDK_GP_ALTITUDE, 0.0).AsDouble(); } + bool AutoAltitude(void) const { return GetParameter(XMLPath(), ON_RDK_GP_AUTO_ALTITUDE, false).AsBool(); } + bool ShadowOnly(void) const { return GetParameter(XMLPath(), ON_RDK_GP_SHADOW_ONLY, true).AsBool(); } + bool TextureOffsetLocked(void) const { return GetParameter(XMLPath(), ON_RDK_GP_TEXTURE_OFFSET_LOCKED, false).AsBool(); } + bool TextureSizeLocked(void) const { return GetParameter(XMLPath(), ON_RDK_GP_TEXTURE_SIZE_LOCKED, false).AsBool(); } + double TextureRotation(void) const { return GetParameter(XMLPath(), ON_RDK_GP_TEXTURE_ROTATION, false).AsDouble(); } + ON_UUID MaterialInstanceId(void) const { return GetParameter(XMLPath(), ON_RDK_GP_MATERIAL_ID, ON_nil_uuid).AsUuid(); } + ON_2dVector TextureOffset(void) const { return ON_2dVector(GetParameter(XMLPath(), ON_RDK_GP_TEXTURE_OFFSET, ON_nil_uuid).As2dPoint()); } + ON_2dVector TextureSize(void) const { return ON_2dVector(GetParameter(XMLPath(), ON_RDK_GP_TEXTURE_SIZE, ON_nil_uuid).As2dPoint()); } void SetOn(bool v) { SetParameter(XMLPath(), ON_RDK_GP_ON, v); } void SetShowUnderside(bool v) { SetParameter(XMLPath(), ON_RDK_GP_SHOW_UNDERSIDE, v); } @@ -94,7 +86,7 @@ const ON_GroundPlane& ON_GroundPlane::operator = (const ON_GroundPlane& gp) if (this != &gp) { // When copying the object, we need to directly copy the underlying XML. So we can't allow - // virtual overrides to execute because they might shadow the real values we want to copy. + // virtual overrides to execute because they might hide the real values we want to copy. _impl->SetOn (gp._impl->On()); _impl->SetShowUnderside (gp._impl->ShowUnderside()); _impl->SetAltitude (gp._impl->Altitude()); @@ -113,8 +105,8 @@ const ON_GroundPlane& ON_GroundPlane::operator = (const ON_GroundPlane& gp) bool ON_GroundPlane::operator == (const ON_GroundPlane& gp) const { - // When checking equality, we need to directly check the underlying XML. So we can't allow - // virtual overrides to execute because they might shadow the real values we want to check. + // When checking equality, we need to directly check the underlying storage. So we can't allow + // virtual overrides to execute because they might hide the real values we want to check. if (_impl->On() != gp._impl->On() ) return false; if (_impl->ShowUnderside() != gp._impl->ShowUnderside() ) return false; if (_impl->AutoAltitude() != gp._impl->AutoAltitude() ) return false; @@ -262,6 +254,6 @@ void* ON_GroundPlane::EVF(const wchar_t* func, void* data) return nullptr; } -void ON_GroundPlane::InvalidateCache(void) +void ON_GroundPlane::OnInternalXmlChanged(const ON_GroundPlane*) { } diff --git a/opennurbs_ground_plane.h b/opennurbs_ground_plane.h index 1b656068..5f7ae731 100644 --- a/opennurbs_ground_plane.h +++ b/opennurbs_ground_plane.h @@ -101,10 +101,12 @@ public: // Emergency virtual function for future expansion. virtual void* EVF(const wchar_t* func, void* data); + // For internal use only. + virtual void OnInternalXmlChanged(const ON_GroundPlane*); + private: // For internal use only. friend class ON_3dmRenderSettingsPrivate; void SetXMLNode(ON_XMLNode& node) const; - virtual void InvalidateCache(void); private: class CImpl; diff --git a/opennurbs_internal_defines.h b/opennurbs_internal_defines.h index c78e05fd..e58bb168 100644 --- a/opennurbs_internal_defines.h +++ b/opennurbs_internal_defines.h @@ -80,6 +80,8 @@ public: ON_XMLVariant GetParameter_NoType(const wchar_t* path_to_node, const wchar_t* param_name, const wchar_t* default_type, const ON_XMLVariant& def) const; bool SetParameter_NoType(const wchar_t* path_to_node, const wchar_t* param_name, const ON_XMLVariant& value); + bool RemoveParameter(const wchar_t* path_to_node, const wchar_t* param_name); + ON_XMLNode& Node(void) const; void SetModelNode(ON_XMLNode& node); @@ -186,7 +188,7 @@ public: void SpecializeGroundPlane(ON_GroundPlane& gp); void SpecializeLinearWorkflow(ON_LinearWorkflow& lw); - void SpecializeSun(ON_SunEx& sun); + void SpecializeSun(ON_Sun& sun); static ON_3dmRenderSettingsPrivate& Get(const ON_3dmRenderSettings& rs); @@ -204,9 +206,9 @@ public: ON_Skylight* _skylight = nullptr; ON_LinearWorkflow* _linear_workflow = nullptr; ON_RenderChannels* _render_channels = nullptr; - ON_SunEx* _sun = nullptr; - ON_EnvironmentsImpl* _environments; - ON_PostEffects* _post_effects; + ON_Sun* _sun = nullptr; + ON_EnvironmentsImpl* _environments = nullptr; + ON_PostEffects* _post_effects = nullptr; bool _gp_specialized = false; bool _lw_specialized = false; bool _sun_specialized = false; diff --git a/opennurbs_layer.cpp b/opennurbs_layer.cpp index 65c74517..fb972dc3 100644 --- a/opennurbs_layer.cpp +++ b/opennurbs_layer.cpp @@ -31,6 +31,7 @@ public: bool operator!=(const ON_LayerPrivate&) const; ON_UuidList m_clipplane_list; + bool m_clipplane_list_is_participation = true; bool m_clipping_proof = false; std::shared_ptr m_custom_section_style; @@ -49,6 +50,9 @@ bool ON_LayerPrivate::operator==(const ON_LayerPrivate& other) const if (m_clipplane_list != other.m_clipplane_list) return false; + if (m_clipplane_list_is_participation != other.m_clipplane_list_is_participation) + return false; + if (m_clipping_proof != other.m_clipping_proof) return false; @@ -273,7 +277,8 @@ void ON_Layer::Dump( ON_TextLog& dump ) const bool clipAll = true; bool clipNone = false; ON_UuidList cliplist; - GetClipParticipation(clipAll, clipNone, cliplist); + bool isSelectiveList = true; + GetClipParticipation(clipAll, clipNone, cliplist, isSelectiveList); if (clipAll) { dump.Print("participates with all clipping planes\n"); @@ -325,8 +330,11 @@ enum ON_LayerTypeCodes : unsigned char // 22 Apr 2023 S. Baer // chunk version 1.15: custom section style CustomSectionStyle = 35, + // 11 May 2023 S. Baer + // New selective clipping data with bool for list type + SelectiveClippingListType = 36, - LastLayerTypeCode = 35 + LastLayerTypeCode = 36 }; bool ON_Layer::Write( @@ -335,6 +343,11 @@ bool ON_Layer::Write( { int i; + // 11 May 2023 S. Baer + // Do not write a minor chunk version greater than 15. Chunk versions are actually + // two values packed into a single unsigned char. The use of type codes for I/O + // with layers makes it so the minor version isn't really necessary. Just stop at + // a minor version of 15 bool rc = file.Write3dmChunkVersion(1,15); while(rc) { @@ -486,7 +499,8 @@ bool ON_Layer::Write( bool forAllClippingPlanes = true; bool forNoClippingPlanes = false; ON_UuidList selectiveList; - GetClipParticipation(forAllClippingPlanes, forNoClippingPlanes, selectiveList); + bool isParticipationList = true; + GetClipParticipation(forAllClippingPlanes, forNoClippingPlanes, selectiveList, isParticipationList); // only write selective clipping data if it is not default if (false == forAllClippingPlanes || true == forNoClippingPlanes || selectiveList.Count() > 0) { @@ -578,6 +592,15 @@ bool ON_Layer::Write( if (!rc) break; } + if (m_private && false == m_private->m_clipplane_list_is_participation) + { + c = ON_LayerTypeCodes::SelectiveClippingListType; //36 + rc = file.WriteChar(c); + if (!rc) break; + rc = file.WriteBool(m_private->m_clipplane_list_is_participation); + if (!rc) break; + } + // 0 indicates end of new non-default attributes c = 0; rc = file.WriteChar(c); @@ -774,7 +797,7 @@ bool ON_Layer::Read( if (noClippingPlanes) SetClipParticipationForNone(); else if (selectiveList.Count() > 0) - SetClipParticipationList(selectiveList.Array(), selectiveList.Count()); + SetClipParticipationList(selectiveList.Array(), selectiveList.Count(), true); else SetClipParticipationForAll(); @@ -884,11 +907,18 @@ bool ON_Layer::Read( if (!rc || 0 == itemid) break; } - // break if minor_version<=15. If itemid is non-zero and - // minor_version is not > 15, then we know we have an I/O - // reading bug that needs to be tracked down - if (minor_version <= 15) - break; + if (ON_LayerTypeCodes::SelectiveClippingListType == itemid) + { + bool b = true; + file.ReadBool(&b); + if (!rc) break; + if (nullptr == m_private) + m_private = new ON_LayerPrivate(); + m_private->m_clipplane_list_is_participation = b; + + rc = file.ReadChar(&itemid); + if (!rc || 0 == itemid) break; + } // Add new item reading above and increment the LastLayerTypeCode value // in the enum. Be sure to test reading of old and new files by old and new @@ -2475,6 +2505,7 @@ void ON_Layer::SetClipParticipationForAll() return; m_private->m_clipplane_list.Empty(); + m_private->m_clipplane_list_is_participation = true; m_private->m_clipping_proof = false; } void ON_Layer::SetClipParticipationForNone() @@ -2482,12 +2513,16 @@ void ON_Layer::SetClipParticipationForNone() if (nullptr == m_private) m_private = new ON_LayerPrivate(); m_private->m_clipplane_list.Empty(); + m_private->m_clipplane_list_is_participation = true; m_private->m_clipping_proof = true; } -void ON_Layer::SetClipParticipationList(const ON_UUID* clippingPlaneIds, int count) +void ON_Layer::SetClipParticipationList(const ON_UUID* clippingPlaneIds, int count, bool listIsParticipation) { if (nullptr == clippingPlaneIds || count < 1) + { SetClipParticipationForAll(); + return; + } if (nullptr == m_private) m_private = new ON_LayerPrivate(); @@ -2495,13 +2530,16 @@ void ON_Layer::SetClipParticipationList(const ON_UUID* clippingPlaneIds, int cou for (int i = 0; i < count; i++) m_private->m_clipplane_list.AddUuid(clippingPlaneIds[i], true); + m_private->m_clipplane_list_is_participation = listIsParticipation; m_private->m_clipping_proof = false; } void ON_Layer::GetClipParticipation( bool& forAllClippingPlanes, bool& forNoClippingPlanes, - ON_UuidList& specificClipplaneList) const + ON_UuidList& specificClipplaneList, + bool& listIsParticipation) const { + listIsParticipation = true; if (nullptr == m_private) { forAllClippingPlanes = true; @@ -2511,6 +2549,7 @@ void ON_Layer::GetClipParticipation( } specificClipplaneList = m_private->m_clipplane_list; + listIsParticipation = m_private->m_clipplane_list_is_participation; if (specificClipplaneList.Count() > 0) { forAllClippingPlanes = false; diff --git a/opennurbs_layer.h b/opennurbs_layer.h index 5d886b1c..0f95f766 100644 --- a/opennurbs_layer.h +++ b/opennurbs_layer.h @@ -796,7 +796,13 @@ public: void SetClipParticipationForNone(); // Set objects on layer to only be clipped by a specific set of clipping planes. - void SetClipParticipationList(const ON_UUID* clippingPlaneIds, int count); + // Paramters: + // clippingPlaneIds [in] - array of ON_UUIDs for clipping planes + // count [in] - number of elements in clippingPlaneIds + // listIsParticipation [in] - is the list clipping planes that the layer + // participates with or an exclusion list of clipping planes to not + // participate with + void SetClipParticipationList(const ON_UUID* clippingPlaneIds, int count, bool listIsParticipation); // Get details on how the objects on layer will interact with clipping planes // Parameters: @@ -807,10 +813,13 @@ public: // specificClipplaneList [out] - if the objects interact with only a // specific set of clipping planes, this list will have the uuids of // those clipping plane objects + // listIsParticipation [out] - is specificClipplaneList a participation + // list or an exclusion list void GetClipParticipation( bool& forAllClippingPlanes, bool& forNoClippingPlanes, - ON_UuidList& specificClipplaneList) const; + ON_UuidList& specificClipplaneList, + bool& listIsParticipation) const; #pragma region Section Attributes // Sections are the product of intersecting a plane with an object. diff --git a/opennurbs_linear_workflow.cpp b/opennurbs_linear_workflow.cpp index 77dd11b7..3e87c79d 100644 --- a/opennurbs_linear_workflow.cpp +++ b/opennurbs_linear_workflow.cpp @@ -31,7 +31,7 @@ public: static const wchar_t* XMLPath(void) { - return ON_RDK_DOCUMENT ON_RDK_SLASH ON_RDK_SETTINGS ON_RDK_SLASH ON_RDK_RENDERING; + return ON_RDK_DOCUMENT ON_XML_SLASH ON_RDK_SETTINGS ON_XML_SLASH ON_RDK_RENDERING; } ON_LinearWorkflow::ON_LinearWorkflow() @@ -61,7 +61,7 @@ const ON_LinearWorkflow& ON_LinearWorkflow::operator = (const ON_LinearWorkflow& if (this != &lw) { // When copying the object, we need to directly copy the underlying XML. So we can't allow - // virtual overrides to execute because they might shadow the real values we want to copy. + // virtual overrides to execute because they might hide the real values we want to copy. using LW = ON_LinearWorkflow; LW::SetPreProcessTexturesOn (lw.LW::PreProcessTexturesOn()); LW::SetPreProcessColorsOn (lw.LW::PreProcessColorsOn()); @@ -77,8 +77,8 @@ const ON_LinearWorkflow& ON_LinearWorkflow::operator = (const ON_LinearWorkflow& bool ON_LinearWorkflow::operator == (const ON_LinearWorkflow& lw) const { - // When checking equality, we need to directly check the underlying XML. So we can't allow - // virtual overrides to execute because they might shadow the real values we want to check. + // When checking equality, we need to directly check the underlying storage. So we can't allow + // virtual overrides to execute because they might hide the real values we want to check. using LW = ON_LinearWorkflow; if (LW::PreProcessTexturesOn() != lw.LW::PreProcessTexturesOn()) return false; if (LW::PreProcessColorsOn() != lw.LW::PreProcessColorsOn()) return false; @@ -208,6 +208,6 @@ void* ON_LinearWorkflow::EVF(const wchar_t* func, void* data) return nullptr; } -void ON_LinearWorkflow::InvalidateCache(void) +void ON_LinearWorkflow::OnInternalXmlChanged(const ON_LinearWorkflow*) { } diff --git a/opennurbs_linear_workflow.h b/opennurbs_linear_workflow.h index 5ccba899..d62ac49b 100644 --- a/opennurbs_linear_workflow.h +++ b/opennurbs_linear_workflow.h @@ -79,11 +79,12 @@ public: // Emergency virtual function for future expansion. virtual void* EVF(const wchar_t* func, void* data); -private: // For internal use only. + virtual void OnInternalXmlChanged(const ON_LinearWorkflow*); + +private: // For internal use only. friend class ON_3dmRenderSettingsPrivate; void SetXMLNode(ON_XMLNode& node) const; - virtual void InvalidateCache(void); private: class CImpl; diff --git a/opennurbs_mesh.cpp b/opennurbs_mesh.cpp index 52548607..7ca1a864 100644 --- a/opennurbs_mesh.cpp +++ b/opennurbs_mesh.cpp @@ -6277,6 +6277,9 @@ void ON_MeshParameters::SetComputeCurvature( ) { Internal_SetBoolHelper(bComputeCurvature, &m_bComputeCurvature); + ON_SubDDisplayParameters smp = this->SubDDisplayParameters(); + smp.SetComputeCurvature(bComputeCurvature); + this->SetSubDDisplayParameters(smp); } @@ -6905,7 +6908,16 @@ int ON_MeshParameters::CompareGeometrySettings( const ON_MeshParameters& b ) { - return ON_SHA1_Hash::Compare(a.GeometrySettingsHash(), b.GeometrySettingsHash()); + return CompareGeometrySettings(a, b, false); +} + +int ON_MeshParameters::CompareGeometrySettings( + const ON_MeshParameters& a, + const ON_MeshParameters& b, + const bool bIgnoreSubDParameters + ) +{ + return ON_SHA1_Hash::Compare(a.GeometrySettingsHash(bIgnoreSubDParameters), b.GeometrySettingsHash(bIgnoreSubDParameters)); } ON_SHA1_Hash ON_MeshParameters::ContentHash() const @@ -7021,8 +7033,28 @@ ON_SHA1_Hash ON_MeshParameters::GeometrySettingsHash(bool bIgnoreSubDParameters) if (false == bIgnoreSubDParameters) { - // SubD meshing parameters - sha1.AccumulateBytes(&m_subd_mesh_parameters_as_char, sizeof(m_subd_mesh_parameters_as_char)); + // 2023-05-12, Pierre: Changes in RH-50501 make ON_MeshParameters::SetComputeCurvature also + // act on the SubD mesh parameters, and I believe this is good (keeping the compute curvature bit + // in sync between Brep meshing parameters and SubD mesh parameters). This means Breps with + // compute curvature on also have non-default SubD meshing parameters (they always have the SubD + // parameters, they just used to be default). + // These values are intentionally ignored: + // m_reserved + // m_context + // m_bComputeCurvature + // m_reserved3 + // m_reserved4 + // m_reserved5 + // m_reserved6 + // m_reserved7 + // m_terminator + // m_progress_reporter + // m_progress_reporter_interval + ON_SubDDisplayParameters subd_params{ + ON_SubDDisplayParameters::DecodeFromUnsignedChar(m_subd_mesh_parameters_as_char)}; + sha1.AccumulateBool(subd_params.DisplayDensityIsAbsolute()); + sha1.AccumulateUnsigned8((ON__UINT8)subd_params.GetRawDisplayDensityForExperts()); // display density fits in a char + sha1.AccumulateBool(subd_params.MeshLocation() == ON_SubDComponentLocation::ControlNet); } if (ON_UuidIsNotNil(m_mesher_id)) @@ -7339,7 +7371,7 @@ bool ON_MeshParameters::Read( ON_BinaryArchive& file ) bool ON_SubDDisplayParameters::Write(class ON_BinaryArchive& archive) const { - if (false == archive.BeginWrite3dmAnonymousChunk(2)) + if (false == archive.BeginWrite3dmAnonymousChunk(3)) return false; bool rc = false; for(;;) @@ -7356,6 +7388,9 @@ bool ON_SubDDisplayParameters::Write(class ON_BinaryArchive& archive) const if (false == archive.WriteBool(this->m_bDisplayDensityIsAbsolute)) break; + if (false == archive.WriteBool(this->m_bComputeCurvature)) + break; + rc = true; break; } @@ -7394,6 +7429,14 @@ bool ON_SubDDisplayParameters::Read(class ON_BinaryArchive& archive) break; if (bDisplayDensityIsAbsolute) this->SetAbsoluteDisplayDensity(display_density); + + if (chunk_version >= 3) + { + bool bComputeCurvature = false; + if (false == archive.ReadBool(&bComputeCurvature)) + break; + this->SetComputeCurvature(bComputeCurvature); + } } rc = true; diff --git a/opennurbs_mesh.h b/opennurbs_mesh.h index 801bf957..1c3668e4 100644 --- a/opennurbs_mesh.h +++ b/opennurbs_mesh.h @@ -347,6 +347,19 @@ public: const class ON_SubD& subd ) const; + /* + Returns: + The raw value of m_display_density. + Remarks: + This function is only intended to get + public raw access to that value (for example when comparing meshing parameters) + and should not be used in any place where the returned value will be used + to compute a SubD display density. + + Use DisplayDensity(subd) instead! + */ + const unsigned char GetRawDisplayDensityForExperts() const; + ON_DEPRECATED_MSG("Use SetAdaptiveDisplayDensity()") void SetDisplayDensity( unsigned int adaptive_display_density @@ -398,6 +411,20 @@ public: */ void SetMeshLocation(ON_SubDComponentLocation mesh_location); + /* + Description: + The ComputeCurvature() property determines if the mesh has curvature values. + */ + bool ComputeCurvature() const; + + /* + Description: + The ComputeCurvature() property determines if the mesh has curvature values. + Parameters: + compute_curvature - [in] + */ + void SetComputeCurvature(bool compute_curvature); + unsigned char EncodeAsUnsignedChar() const; static const ON_SubDDisplayParameters DecodeFromUnsignedChar( unsigned char encoded_parameters @@ -411,6 +438,7 @@ private: subd_mesh_density_mask = 0x07, subd_mesh_location_bit = 0x08, subd_mesh_absolute_density_bit = 0x10, + subd_mesh_compute_curvature_bit = 0x20, // If this bit set, then the settings are not current defaults. subd_mesh_nondefault_bit = 0x80 @@ -475,7 +503,7 @@ public: private: ON_SubDDisplayParameters::Context m_context = ON_SubDDisplayParameters::Context::Unknown; - unsigned char m_reserved2 = 0; + bool m_bComputeCurvature = false; unsigned char m_reserved3 = 0; unsigned int m_reserved4 = 0; unsigned int m_reserved5 = 0; @@ -875,14 +903,35 @@ public: Description: Compares all meshing parameters that control mesh geometry. Does not compare m_bCustomSettings, CustomSettingsEnabled(), - m_bComputeCurvature, m_bDoublePrecision, MinimumTolerance(), - m_texture_range, m_srf_domain0 and m_srf_domain1. + m_bComputeCurvature, m_bDoublePrecision, MinimumTolerance(), + m_texture_range, m_srf_domain0 and m_srf_domain1; and + from the SubD meshing parameters in m_subd_mesh_parameters_as_char, + does not compare m_context, m_bComputeCurvature, m_terminator, + m_progress_reporter, and m_progress_reporter_interval. */ static int CompareGeometrySettings( const ON_MeshParameters& a, const ON_MeshParameters& b ); + /* + Description: + Compares all meshing parameters that control mesh geometry. + Does not compare m_bCustomSettings, CustomSettingsEnabled(), + m_bComputeCurvature, m_bDoublePrecision, MinimumTolerance(), + m_texture_range, m_srf_domain0 and m_srf_domain1; and + from the SubD meshing parameters in m_subd_mesh_parameters_as_char, + does not compare m_context, m_bComputeCurvature, m_terminator, + m_progress_reporter, and m_progress_reporter_interval. + If bIgnoreSubDParameters is true, ignores all settings in + m_subd_mesh_parameters_as_char. + */ + static int CompareGeometrySettings( + const ON_MeshParameters& a, + const ON_MeshParameters& b, + const bool bIgnoreSubDParameters + ); + /* Returns: A hash of every ON_MeshParameters setting. diff --git a/opennurbs_post_effects.cpp b/opennurbs_post_effects.cpp index 9151b7a7..67435a5e 100644 --- a/opennurbs_post_effects.cpp +++ b/opennurbs_post_effects.cpp @@ -95,7 +95,7 @@ const ON_XMLParameters& ON_PostEffectParams::AsXMLParameters(void) const ON__UINT32 ON_PostEffectParams::DataCRC(ON__UINT32 current_remainder) const { - return _impl->_node.DataCRC(current_remainder); + return _impl->_node.DataCRC(current_remainder, true); } void* ON_PostEffectParams::EVF(const wchar_t*, void*) @@ -109,7 +109,7 @@ static ON_XMLRootNode g_panic_node; static const wchar_t* XMLPathPeps(void) { - return ON_RDK_DOCUMENT ON_RDK_SLASH ON_RDK_SETTINGS ON_RDK_SLASH ON_RDK_POST_EFFECTS; + return ON_RDK_DOCUMENT ON_XML_SLASH ON_RDK_SETTINGS ON_XML_SLASH ON_RDK_POST_EFFECTS; } static const wchar_t* PostEffectTypeString(ON_PostEffect::Types type) @@ -426,7 +426,7 @@ const ON_XMLNode& ON_PostEffect::XMLNode(void) const ON__UINT32 ON_PostEffect::DataCRC(ON__UINT32 crc) const { - return XMLNode().DataCRC(crc); + return XMLNode().DataCRC(crc, true); } // ON_PostEffects @@ -803,7 +803,7 @@ void* ON_PostEffects::EVF(const wchar_t*, void*) return nullptr; } -void ON_PostEffects::InvalidateCache(void) +void ON_PostEffects::OnInternalXmlChanged(ON_PostEffects*) { _impl->Clear(); } diff --git a/opennurbs_post_effects.h b/opennurbs_post_effects.h index 8994908a..ead76334 100644 --- a/opennurbs_post_effects.h +++ b/opennurbs_post_effects.h @@ -195,7 +195,7 @@ private: // For internal use only. friend class ON_3dmRenderSettingsPrivate; friend class ON_PostEffect; ON_XMLNode& WritablePostEffectsNode(void); - virtual void InvalidateCache(void); + virtual void OnInternalXmlChanged(ON_PostEffects*); public: class CImpl; diff --git a/opennurbs_public_version.h b/opennurbs_public_version.h index 09fa718f..a47c167a 100644 --- a/opennurbs_public_version.h +++ b/opennurbs_public_version.h @@ -14,10 +14,10 @@ // first step in each build. // #define RMA_VERSION_YEAR 2023 -#define RMA_VERSION_MONTH 4 -#define RMA_VERSION_DATE 26 -#define RMA_VERSION_HOUR 6 -#define RMA_VERSION_MINUTE 32 +#define RMA_VERSION_MONTH 5 +#define RMA_VERSION_DATE 19 +#define RMA_VERSION_HOUR 16 +#define RMA_VERSION_MINUTE 2 //////////////////////////////////////////////////////////////// // @@ -35,8 +35,8 @@ // 3 = build system release build #define RMA_VERSION_BRANCH 0 -#define VERSION_WITH_COMMAS 8,0,23116,6320 -#define VERSION_WITH_PERIODS 8.0.23116.06320 +#define VERSION_WITH_COMMAS 8,0,23139,16020 +#define VERSION_WITH_PERIODS 8.0.23139.16020 #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.23116.06320" -#define RMA_VERSION_WITH_PERIODS_WSTRING L"8.0.23116.06320" +#define RMA_VERSION_WITH_PERIODS_STRING "8.0.23139.16020" +#define RMA_VERSION_WITH_PERIODS_WSTRING L"8.0.23139.16020" diff --git a/opennurbs_render_channels.cpp b/opennurbs_render_channels.cpp index 19ab4cd5..9d4870b1 100644 --- a/opennurbs_render_channels.cpp +++ b/opennurbs_render_channels.cpp @@ -37,8 +37,8 @@ public: static const wchar_t* XMLPath(void) { - return ON_RDK_DOCUMENT ON_RDK_SLASH ON_RDK_SETTINGS ON_RDK_SLASH - ON_RDK_RENDERING ON_RDK_SLASH ON_RDK_RENDER_CHANNELS; + return ON_RDK_DOCUMENT ON_XML_SLASH ON_RDK_SETTINGS ON_XML_SLASH + ON_RDK_RENDERING ON_XML_SLASH ON_RDK_RENDER_CHANNELS; } ON_RenderChannels::ON_RenderChannels() @@ -179,6 +179,6 @@ void* ON_RenderChannels::EVF(const wchar_t* func, void* data) return nullptr; } -void ON_RenderChannels::InvalidateCache(void) +void ON_RenderChannels::OnInternalXmlChanged(const ON_RenderChannels*) { } diff --git a/opennurbs_render_channels.h b/opennurbs_render_channels.h index 2cfa9391..952e8ae9 100644 --- a/opennurbs_render_channels.h +++ b/opennurbs_render_channels.h @@ -52,7 +52,7 @@ public: private: // For internal use only. friend class ON_3dmRenderSettingsPrivate; - virtual void InvalidateCache(void); + virtual void OnInternalXmlChanged(const ON_RenderChannels*); private: class CImpl; diff --git a/opennurbs_render_content.cpp b/opennurbs_render_content.cpp index 57b8413b..2c9560bc 100644 --- a/opennurbs_render_content.cpp +++ b/opennurbs_render_content.cpp @@ -22,125 +22,6 @@ #error ON_COMPILING_OPENNURBS must be defined when compiling opennurbs #endif -#define ON_TYPE_NAME L"type-name" -#define ON_TYPE_ID L"type-id" -#define ON_INSTANCE_ID L"instance-id" -#define ON_RENDER_ENGINE_ID L"render-engine-id" -#define ON_PLUG_IN_ID L"plug-in-id" -#define ON_GROUP_ID L"group-id" -#define ON_INSTANCE_NAME L"instance-name" -#define ON_CHILD_SLOT_NAME L"child-slot-name" -#define ON_NOTES L"notes" -#define ON_TAGS L"tags" -#define ON_HIDDEN L"hidden" -#define ON_REFERENCE L"reference" -#define ON_AUTO_DELETE L"auto-delete" -#define ON_ENV_BACKGROUND_COLOR L"background-color" -#define ON_POSTFIX_SECTION L"-section" -#define ON_PARAMETERS L"parameters" -#define ON_PARAMETERS_V8 L"parameters-v8" -#define ON_SIMULATION L"simulation" - -#define ON_POSTFIX_SECTION L"-section" -#define ON_PARAMETERS L"parameters" -#define ON_PARAMETERS_V8 L"parameters-v8" -#define ON_SIMULATION L"simulation" - -#define ON_ENV_PROJ_BOX L"box" -#define ON_ENV_PROJ_CUBE_MAP L"cubemap" -#define ON_ENV_PROJ_CUBE_MAP_HORZ L"horizontal-cross-cubemap" -#define ON_ENV_PROJ_CUBE_MAP_VERT L"vertical-cross-cubemap" -#define ON_ENV_PROJ_EMAP L"emap" -#define ON_ENV_PROJ_HEMISPHERICAL L"hemispherical" -#define ON_ENV_PROJ_LIGHT_PROBE L"lightprobe" -#define ON_ENV_PROJ_PLANAR L"planar" -#define ON_ENV_PROJ_SPHERICAL L"spherical" - -// General parameters used by materials that simulate ON_Material. -// -// These are copied from the FS_ strings in the RDK. Perhaps the RDK should start -// using these instead of the FS_ ones. Or the FS_ ones can be defined as these. -// Remember, they are in the RDK SDK. Check with Andy. - -#define ON_MAT_ALPHA_TRANSPARENCY L"alpha-transparency" -#define ON_MAT_AMBIENT L"ambient" -#define ON_MAT_DIFFUSE L"diffuse" -#define ON_MAT_DISABLE_LIGHTING L"disable-lighting" -#define ON_MAT_EMISSION L"emission" -#define ON_MAT_FLAMINGO_LIBRARY L"flamingo-library" -#define ON_MAT_FRESNEL_ENABLED L"fresnel-enabled" -#define ON_MAT_CLARITY_AMOUNT L"clarity-amount" -#define ON_MAT_IOR L"ior" -#define ON_MAT_POLISH_AMOUNT L"polish-amount" -#define ON_MAT_SHINE L"shine" // Value is 0.0..1.0, NOT ON_Material::MaxShine. -#define ON_MAT_SPECULAR L"specular" -#define ON_MAT_REFLECTIVITY_AMOUNT L"reflectivity" -#define ON_MAT_REFLECTION L"reflection" // Simulation is different to Custom Material. -#define ON_MAT_TRANSPARENCY_AMOUNT L"transparency" -#define ON_MAT_TRANSPARENT L"transparent" // Simulation is different to Custom Material. -#define ON_MAT_IS_PHYSICALLY_BASED L"is-physically-based" - -#define ON_MAT_POSTFIX_ON L"on" -#define ON_MAT_POSTFIX_AMOUNT L"amount" -#define ON_MAT_POSTFIX_FILTER_ON L"filter-on" - -#define ON_MAT_BITMAP_TEXTURE L"bitmap-texture" -#define ON_MAT_BUMP_TEXTURE L"bump-texture" -#define ON_MAT_TRANSPARENCY_TEXTURE L"transparency-texture" -#define ON_MAT_ENVIRONMENT_TEXTURE L"environment-texture" - -#define ON_MAT_PBR_BRDF L"pbr-brdf" -#define ON_MAT_PBR_BRDF_GGX L"ggx" -#define ON_MAT_PBR_BRDF_WARD L"ward" -#define ON_MAT_PBR_ALPHA L"pbr-alpha" -#define ON_MAT_PBR_ANISOTROPIC L"pbr-anisotropic" -#define ON_MAT_PBR_ANISOTROPIC_ROTATION L"pbr-anisotropic-rotation" -#define ON_MAT_PBR_BASE_COLOR L"pbr-base-color" -#define ON_MAT_PBR_CLEARCOAT L"pbr-clearcoat" -#define ON_MAT_PBR_CLEARCOAT_ROUGHNESS L"pbr-clearcoat-roughness" -#define ON_MAT_PBR_EMISSION_COLOR L"pbr-emission" -#define ON_MAT_PBR_METALLIC L"pbr-metallic" -#define ON_MAT_PBR_OPACITY L"pbr-opacity" -#define ON_MAT_PBR_OPACITY_IOR L"pbr-opacity-ior" -#define ON_MAT_PBR_OPACITY_ROUGHNESS L"pbr-opacity-roughness" -#define ON_MAT_PBR_ROUGHNESS L"pbr-roughness" -#define ON_MAT_PBR_SHEEN L"pbr-sheen" -#define ON_MAT_PBR_SHEEN_TINT L"pbr-sheen-tint" -#define ON_MAT_PBR_SPECULAR L"pbr-specular" -#define ON_MAT_PBR_SPECULAR_TINT L"pbr-specular-tint" -#define ON_MAT_PBR_SUBSURFACE L"pbr-subsurface" -#define ON_MAT_PBR_SUBSURFACE_SCATTERING_COLOR L"pbr-subsurface-scattering-color" -#define ON_MAT_PBR_SUBSURFACE_SCATTERING_RADIUS L"pbr-subsurface-scattering-radius" -#define ON_MAT_PBR_USE_BASE_COLOR_TEXTURE_ALPHA L"pbr-use-base-color-texture-alpha" - -#define ON_TEX_FILENAME L"filename" - -// Material's texture simulation (check with Andy what the heck this is even for). -#define ON_MAT_TEXSIM_FORMAT L"Texture-%u-" -#define ON_MAT_TEXSIM_FILENAME L"filename" -#define ON_MAT_TEXSIM_ON L"on" -#define ON_MAT_TEXSIM_AMOUNT L"amount" -#define ON_MAT_TEXSIM_TYPE L"type" -#define ON_MAT_TEXSIM_FILTER L"filter" -#define ON_MAT_TEXSIM_MODE L"mode" -#define ON_MAT_TEXSIM_UVW L"uvw" -#define ON_MAT_TEXSIM_WRAP_U L"wrap-u" -#define ON_MAT_TEXSIM_WRAP_V L"wrap-v" - -// Environment simulation. -#define ON_ENVSIM_BACKGROUND_COLOR L"background-color" -#define ON_ENVSIM_BACKGROUND_IMAGE L"background-image" -#define ON_ENVSIM_BACKGROUND_PROJECTION L"background-projection" - -// Texture simulation. -#define ON_TEXSIM_FILENAME L"filename" -#define ON_TEXSIM_REPEAT L"repeat" -#define ON_TEXSIM_OFFSET L"offset" -#define ON_TEXSIM_ROTATION L"rotation" -#define ON_TEXSIM_WRAP_TYPE L"wrap-type" -#define ON_TEXSIM_MAPPING_CHANNEL L"mapping-channel" -#define ON_TEXSIM_PROJECTION_MODE L"projection-mode" // Still have to write this out. - 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) @@ -407,15 +288,15 @@ void ON_Environment::SetBackgroundProjection(ON_Environment::BackgroundProjectio ON_Environment::BackgroundProjections ON_Environment::ProjectionFromString(const wchar_t* wsz) // Static. { - if (0 == on_wcsicmp(ON_ENV_PROJ_PLANAR, wsz)) return BackgroundProjections::Planar; - if (0 == on_wcsicmp(ON_ENV_PROJ_SPHERICAL, wsz)) return BackgroundProjections::Spherical; - if (0 == on_wcsicmp(ON_ENV_PROJ_EMAP, wsz)) return BackgroundProjections::Emap; - if (0 == on_wcsicmp(ON_ENV_PROJ_BOX, wsz)) return BackgroundProjections::Box; - if (0 == on_wcsicmp(ON_ENV_PROJ_LIGHT_PROBE, wsz)) return BackgroundProjections::LightProbe; - if (0 == on_wcsicmp(ON_ENV_PROJ_CUBE_MAP, wsz)) return BackgroundProjections::CubeMap; - if (0 == on_wcsicmp(ON_ENV_PROJ_CUBE_MAP_VERT, wsz)) return BackgroundProjections::VerticalCrossCubeMap; - if (0 == on_wcsicmp(ON_ENV_PROJ_CUBE_MAP_HORZ, wsz)) return BackgroundProjections::HorizontalCrossCubeMap; - if (0 == on_wcsicmp(ON_ENV_PROJ_HEMISPHERICAL, wsz)) return BackgroundProjections::Hemispherical; + 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; @@ -425,20 +306,20 @@ const wchar_t* ON_Environment::StringFromProjection(BackgroundProjections proj) { switch (proj) { - case BackgroundProjections::Planar: return ON_ENV_PROJ_PLANAR; - case BackgroundProjections::Spherical: return ON_ENV_PROJ_SPHERICAL; - case BackgroundProjections::Emap: return ON_ENV_PROJ_EMAP; - case BackgroundProjections::Box: return ON_ENV_PROJ_BOX; - case BackgroundProjections::LightProbe: return ON_ENV_PROJ_LIGHT_PROBE; - case BackgroundProjections::CubeMap: return ON_ENV_PROJ_CUBE_MAP; - case BackgroundProjections::VerticalCrossCubeMap: return ON_ENV_PROJ_CUBE_MAP_VERT; - case BackgroundProjections::HorizontalCrossCubeMap: return ON_ENV_PROJ_CUBE_MAP_HORZ; - case BackgroundProjections::Hemispherical: return ON_ENV_PROJ_HEMISPHERICAL; + 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_ENV_PROJ_PLANAR; + return ON_ENVIRONMENT_PROJECTION_PLANAR; } void* ON_Environment::EVF(const wchar_t* wszFunc, void* pvData) @@ -511,7 +392,7 @@ ON_RenderContent::CImpl::~CImpl() const ON_XMLNode* ON_RenderContent::CImpl::XMLNode_Simulation(void) const { - return m_node.GetNamedChild(ON_SIMULATION); + return m_node.GetNamedChild(ON_RENDER_CONTENT_SIMULATION); } ON_XMLVariant ON_RenderContent::CImpl::GetPropertyValue(const wchar_t* name) const @@ -596,10 +477,10 @@ void ON_RenderContent::CImpl::SetXMLNode(const ON_XMLNode& node) m_node = node_copy; // Copy the XML instance name to the component name. - m_render_content.SetName(GetPropertyValue(ON_INSTANCE_NAME).AsString()); + 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_INSTANCE_ID).AsUuid()); + m_render_content.SetId(GetPropertyValue(ON_RENDER_CONTENT_INSTANCE_ID).AsUuid()); } bool ON_RenderContent::CImpl::AddChild(ON_RenderContent& child) @@ -759,7 +640,7 @@ bool ON_RenderContent::CImpl::SetChild(ON_RenderContent* child, const wchar_t* c if ((nullptr == child_slot_name) || (0 == child_slot_name[0])) return false; - child->m_impl->SetPropertyValue(ON_CHILD_SLOT_NAME, child_slot_name); + child->m_impl->SetPropertyValue(ON_RENDER_CONTENT_CHILD_SLOT_NAME, child_slot_name); } // Get any existing child with the same child slot name (may be null). @@ -792,10 +673,10 @@ bool ON_RenderContent::CImpl::SetChild(ON_RenderContent* child, const wchar_t* c void SetRenderContentNodeRecursive(const ON_RenderContent& rc, ON_XMLNode& node) { // Copy the component name to the XML instance name. - rc.m_impl->SetPropertyValue(ON_INSTANCE_NAME, rc.Name()); + rc.m_impl->SetPropertyValue(ON_RENDER_CONTENT_INSTANCE_NAME, rc.Name()); // Copy the component id to the XML instance id. - rc.m_impl->SetPropertyValue(ON_INSTANCE_ID, rc.Id()); + rc.m_impl->SetPropertyValue(ON_RENDER_CONTENT_INSTANCE_ID, rc.Id()); auto* child_node = new ON_XMLNode(rc.XMLNode()); node.AttachChildNode(child_node); @@ -839,10 +720,10 @@ ON_RenderContent::ON_RenderContent(const wchar_t* kind) SetId(uuid); // Set the plug-in id to the RDK plug-in id. - m_impl->InternalSetPropertyValue(ON_PLUG_IN_ID, RdkPlugInId()); + m_impl->InternalSetPropertyValue(ON_RENDER_CONTENT_PLUG_IN_ID, RdkPlugInId()); // Set the render engine id to 'universal'. - m_impl->InternalSetPropertyValue(ON_RENDER_ENGINE_ID, UniversalRenderEngineId()); + m_impl->InternalSetPropertyValue(ON_RENDER_CONTENT_RENDER_ENGINE_ID, UniversalRenderEngineId()); } ON_RenderContent::ON_RenderContent(const ON_RenderContent& rc) @@ -873,102 +754,102 @@ const ON_RenderContent& ON_RenderContent::operator = (const ON_RenderContent& rc ON_wString ON_RenderContent::TypeName(void) const { - return m_impl->GetPropertyValue(ON_TYPE_NAME).AsString(); + return m_impl->GetPropertyValue(ON_RENDER_CONTENT_TYPE_NAME).AsString(); } void ON_RenderContent::SetTypeName(const wchar_t* name) { - m_impl->SetPropertyValue(ON_TYPE_NAME, name); + m_impl->SetPropertyValue(ON_RENDER_CONTENT_TYPE_NAME, name); } ON_wString ON_RenderContent::Notes(void) const { - return m_impl->GetPropertyValue(ON_NOTES).AsString(); + return m_impl->GetPropertyValue(ON_RENDER_CONTENT_NOTES).AsString(); } void ON_RenderContent::SetNotes(const wchar_t* notes) { - m_impl->SetPropertyValue(ON_NOTES, notes); + m_impl->SetPropertyValue(ON_RENDER_CONTENT_NOTES, notes); } ON_wString ON_RenderContent::Tags(void) const { - return m_impl->GetPropertyValue(ON_TAGS).AsString(); + return m_impl->GetPropertyValue(ON_RENDER_CONTENT_TAGS).AsString(); } void ON_RenderContent::SetTags(const wchar_t* tags) { - m_impl->SetPropertyValue(ON_TAGS, tags); + m_impl->SetPropertyValue(ON_RENDER_CONTENT_TAGS, tags); } ON_UUID ON_RenderContent::TypeId(void) const { - return m_impl->GetPropertyValue(ON_TYPE_ID).AsUuid(); + return m_impl->GetPropertyValue(ON_RENDER_CONTENT_TYPE_ID).AsUuid(); } void ON_RenderContent::SetTypeId(const ON_UUID& uuid) { - m_impl->SetPropertyValue(ON_TYPE_ID, uuid); + m_impl->SetPropertyValue(ON_RENDER_CONTENT_TYPE_ID, uuid); } ON_UUID ON_RenderContent::RenderEngineId(void) const { - return m_impl->GetPropertyValue(ON_RENDER_ENGINE_ID).AsUuid(); + return m_impl->GetPropertyValue(ON_RENDER_CONTENT_RENDER_ENGINE_ID).AsUuid(); } void ON_RenderContent::SetRenderEngineId(const ON_UUID& uuid) { - m_impl->SetPropertyValue(ON_RENDER_ENGINE_ID, uuid); + m_impl->SetPropertyValue(ON_RENDER_CONTENT_RENDER_ENGINE_ID, uuid); } ON_UUID ON_RenderContent::PlugInId(void) const { - return m_impl->GetPropertyValue(ON_PLUG_IN_ID).AsUuid(); + return m_impl->GetPropertyValue(ON_RENDER_CONTENT_PLUG_IN_ID).AsUuid(); } void ON_RenderContent::SetPlugInId(const ON_UUID& uuid) { - m_impl->SetPropertyValue(ON_PLUG_IN_ID, uuid); + m_impl->SetPropertyValue(ON_RENDER_CONTENT_PLUG_IN_ID, uuid); } ON_UUID ON_RenderContent::GroupId(void) const { - return m_impl->GetPropertyValue(ON_GROUP_ID).AsUuid(); + return m_impl->GetPropertyValue(ON_RENDER_CONTENT_GROUP_ID).AsUuid(); } void ON_RenderContent::SetGroupId(const ON_UUID& group) { - m_impl->SetPropertyValue(ON_GROUP_ID, group); + m_impl->SetPropertyValue(ON_RENDER_CONTENT_GROUP_ID, group); } bool ON_RenderContent::Hidden(void) const { - return m_impl->GetPropertyValue(ON_HIDDEN).AsBool(); + return m_impl->GetPropertyValue(ON_RENDER_CONTENT_HIDDEN).AsBool(); } void ON_RenderContent::SetHidden(bool hidden) { - m_impl->SetPropertyValue(ON_HIDDEN, hidden); + m_impl->SetPropertyValue(ON_RENDER_CONTENT_HIDDEN, hidden); } bool ON_RenderContent::Reference(void) const { - return m_impl->GetPropertyValue(ON_REFERENCE).AsBool(); + return m_impl->GetPropertyValue(ON_RENDER_CONTENT_REFERENCE).AsBool(); } void ON_RenderContent::SetReference(bool ref) { - m_impl->SetPropertyValue(ON_REFERENCE, ref); + m_impl->SetPropertyValue(ON_RENDER_CONTENT_REFERENCE, ref); } bool ON_RenderContent::AutoDelete(void) const { - return m_impl->GetPropertyValue(ON_AUTO_DELETE).AsBool(); + return m_impl->GetPropertyValue(ON_RENDER_CONTENT_AUTO_DELETE).AsBool(); } void ON_RenderContent::SetAutoDelete(bool autodel) { - m_impl->SetPropertyValue(ON_AUTO_DELETE, autodel); + m_impl->SetPropertyValue(ON_RENDER_CONTENT_AUTO_DELETE, autodel); } ON_XMLVariant ON_RenderContent::GetParameter(const wchar_t* name) const @@ -979,7 +860,7 @@ ON_XMLVariant ON_RenderContent::GetParameter(const wchar_t* name) const value.SetNull(); // Try to get the new V8 parameter section. - const ON_XMLNode* node = m_impl->m_node.GetNamedChild(ON_PARAMETERS_V8); + const ON_XMLNode* node = m_impl->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. @@ -990,7 +871,7 @@ ON_XMLVariant ON_RenderContent::GetParameter(const wchar_t* name) const { // 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 = m_impl->m_node.GetNamedChild(ON_PARAMETERS); + node = m_impl->m_node.GetNamedChild(ON_RENDER_CONTENT_PARAMETERS); if (nullptr != node) { // Got it, so use the legacy ON_XMLParameters to get the parameter's value. @@ -1009,7 +890,7 @@ bool ON_RenderContent::SetParameter(const wchar_t* name, const ON_XMLVariant& va bool success = false; // Create / get the new V8 parameter section. - auto* node = m_impl->m_node.CreateNodeAtPath(ON_PARAMETERS_V8); + auto* node = m_impl->m_node.CreateNodeAtPath(ON_RENDER_CONTENT_PARAMETERS_V8); if (nullptr != node) { // Use the new ON_XMLParametersV8 to write the parameter's value. @@ -1019,7 +900,7 @@ bool ON_RenderContent::SetParameter(const wchar_t* name, const ON_XMLVariant& va } // Create / get the legacy parameter section. - node = m_impl->m_node.CreateNodeAtPath(ON_PARAMETERS); + node = m_impl->m_node.CreateNodeAtPath(ON_RENDER_CONTENT_PARAMETERS); if (nullptr != node) { // Use the legacy ON_XMLParameters to write the parameter's value. @@ -1078,23 +959,23 @@ bool ON_RenderContent::DeleteChild(const wchar_t* child_slot_name) ON_wString ON_RenderContent::ChildSlotName(void) const { - return m_impl->GetPropertyValue(ON_CHILD_SLOT_NAME).AsString(); + return m_impl->GetPropertyValue(ON_RENDER_CONTENT_CHILD_SLOT_NAME).AsString(); } void ON_RenderContent::SetChildSlotName(const wchar_t* csn) { - m_impl->SetPropertyValue(ON_CHILD_SLOT_NAME, csn); + m_impl->SetPropertyValue(ON_RENDER_CONTENT_CHILD_SLOT_NAME, csn); } bool ON_RenderContent::ChildSlotOn(const wchar_t* child_slot_name) const { - const auto s = ON_wString(child_slot_name) + L"-" ON_MAT_POSTFIX_ON; + const auto s = ON_wString(child_slot_name) + L"-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_MAT_POSTFIX_ON; + const auto s = ON_wString(child_slot_name) + L"-on"; return SetParameter(s, on); } @@ -1307,55 +1188,55 @@ ON_Material ON_RenderMaterial::SimulatedMaterial(void) const { ON_XMLParameters p(*sim_node); - mat.m_ambient = ParamHelper(p, ON_MAT_AMBIENT ).AsColor(); - mat.m_diffuse = ParamHelper(p, ON_MAT_DIFFUSE ).AsColor(); - mat.m_emission = ParamHelper(p, ON_MAT_EMISSION ).AsColor(); - mat.m_specular = ParamHelper(p, ON_MAT_SPECULAR ).AsColor(); - mat.m_reflection = ParamHelper(p, ON_MAT_REFLECTION ).AsColor(); - mat.m_reflectivity = ParamHelper(p, ON_MAT_REFLECTIVITY_AMOUNT).AsDouble(); - mat.m_shine = ParamHelper(p, ON_MAT_SHINE ).AsDouble() * ON_Material::MaxShine; - mat.m_transparency = ParamHelper(p, ON_MAT_TRANSPARENCY_AMOUNT).AsDouble(); - mat.m_index_of_refraction = ParamHelper(p, ON_MAT_IOR ).AsDouble(); - mat.m_reflection_glossiness = 1.0 - ParamHelper(p, ON_MAT_POLISH_AMOUNT ).AsDouble(); - mat.m_refraction_glossiness = 1.0 - ParamHelper(p, ON_MAT_CLARITY_AMOUNT ).AsDouble(); - mat.m_transparent = ParamHelper(p, ON_MAT_TRANSPARENT ).AsColor(); - mat.SetFresnelReflections ( ParamHelper(p, ON_MAT_FRESNEL_ENABLED ).AsBool()); - mat.SetDisableLighting ( ParamHelper(p, ON_MAT_DISABLE_LIGHTING ).AsBool()); + 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_MAT_IS_PHYSICALLY_BASED).AsBool()) + 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_MAT_PBR_BRDF).AsString(); - if (s == ON_MAT_PBR_BRDF_WARD) + 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_MAT_PBR_BASE_COLOR).AsColor()); - pbm->SetSubsurface (ParamHelper(p, ON_MAT_PBR_SUBSURFACE).AsDouble()); - pbm->SetSubsurfaceScatteringColor (ParamHelper(p, ON_MAT_PBR_SUBSURFACE_SCATTERING_COLOR).AsColor()); - pbm->SetSubsurfaceScatteringRadius(ParamHelper(p, ON_MAT_PBR_SUBSURFACE_SCATTERING_RADIUS).AsDouble()); - pbm->SetSpecular (ParamHelper(p, ON_MAT_PBR_SPECULAR).AsDouble()); - pbm->SetSpecularTint (ParamHelper(p, ON_MAT_PBR_SPECULAR_TINT).AsDouble()); - pbm->SetMetallic (ParamHelper(p, ON_MAT_PBR_METALLIC).AsDouble()); - pbm->SetRoughness (ParamHelper(p, ON_MAT_PBR_ROUGHNESS).AsDouble()); - pbm->SetAnisotropic (ParamHelper(p, ON_MAT_PBR_ANISOTROPIC).AsDouble()); - pbm->SetAnisotropicRotation (ParamHelper(p, ON_MAT_PBR_ANISOTROPIC_ROTATION).AsDouble()); - pbm->SetSheen (ParamHelper(p, ON_MAT_PBR_SHEEN).AsDouble()); - pbm->SetSheenTint (ParamHelper(p, ON_MAT_PBR_SHEEN_TINT).AsDouble()); - pbm->SetClearcoat (ParamHelper(p, ON_MAT_PBR_CLEARCOAT).AsDouble()); - pbm->SetClearcoatRoughness (ParamHelper(p, ON_MAT_PBR_CLEARCOAT_ROUGHNESS).AsDouble()); - pbm->SetOpacity (ParamHelper(p, ON_MAT_PBR_OPACITY).AsDouble()); - pbm->SetOpacityIOR (ParamHelper(p, ON_MAT_PBR_OPACITY_IOR).AsDouble()); - pbm->SetOpacityRoughness (ParamHelper(p, ON_MAT_PBR_OPACITY_ROUGHNESS).AsDouble()); - pbm->SetEmission (ParamHelper(p, ON_MAT_PBR_EMISSION_COLOR).AsColor()); - pbm->SetAlpha (ParamHelper(p, ON_MAT_PBR_ALPHA).AsDouble()); - pbm->SetUseBaseColorTextureAlphaForObjectAlphaTransparencyTexture(ParamHelper(p, ON_MAT_PBR_USE_BASE_COLOR_TEXTURE_ALPHA).AsBool()); + 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()); @@ -1370,35 +1251,35 @@ ON_Material ON_RenderMaterial::SimulatedMaterial(void) const ON_XMLVariant v; ON_wString s; - s.Format(ON_MAT_TEXSIM_FORMAT, count); + s.Format(ON_RENDER_MATERIAL_TEXTURE_SIMULATION_FORMAT, count); - if (!p.GetParam(s + ON_MAT_TEXSIM_FILENAME, v)) + 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_MAT_TEXSIM_ON, v)) + if (p.GetParam(s + ON_RENDER_MATERIAL_TEXTURE_SIMULATION_ON, v)) tex.m_bOn = v; - if (p.GetParam(s + ON_MAT_TEXSIM_AMOUNT, v)) + if (p.GetParam(s + ON_RENDER_MATERIAL_TEXTURE_SIMULATION_AMOUNT, v)) tex.m_blend_constant_A = v; - if (p.GetParam(s + ON_MAT_TEXSIM_TYPE, 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_MAT_TEXSIM_FILTER, v)) + 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_MAT_TEXSIM_MODE, v)) + if (p.GetParam(s + ON_RENDER_MATERIAL_TEXTURE_SIMULATION_MODE, v)) tex.m_mode = ON_Texture::MODE(v.AsInteger()); - if (p.GetParam(s + ON_MAT_TEXSIM_UVW, v)) + if (p.GetParam(s + ON_RENDER_MATERIAL_TEXTURE_SIMULATION_UVW, v)) tex.m_uvw = v.AsXform(); - if (p.GetParam(s + ON_MAT_TEXSIM_WRAP_U, v)) + 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_MAT_TEXSIM_WRAP_V, v)) + 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); @@ -1453,10 +1334,10 @@ ON_Environment ON_RenderEnvironment::SimulatedEnvironment(void) const ON_XMLVariant v; ON_XMLParameters p(*sim_node); - if (p.GetParam(ON_ENVSIM_BACKGROUND_COLOR, v)) + if (p.GetParam(ON_ENVIRONMENT_SIMULATION_BACKGROUND_COLOR, v)) env.SetBackgroundColor(v.AsColor()); - if (p.GetParam(ON_ENVSIM_BACKGROUND_IMAGE, v)) + if (p.GetParam(ON_ENVIRONMENT_SIMULATION_BACKGROUND_IMAGE, v)) { ON_Texture tex; tex.m_image_file_reference.SetFullPath(v.AsString(), false); @@ -1464,7 +1345,7 @@ ON_Environment ON_RenderEnvironment::SimulatedEnvironment(void) const env.SetBackgroundImage(tex); } - if (p.GetParam(ON_ENVSIM_BACKGROUND_PROJECTION, v)) + if (p.GetParam(ON_ENVIRONMENT_SIMULATION_BACKGROUND_PROJECTION, v)) { const auto proj = ON_Environment::ProjectionFromString(v.AsString()); env.SetBackgroundProjection(proj); @@ -1518,12 +1399,12 @@ ON_Texture ON_RenderTexture::SimulatedTexture(void) const ON_XMLVariant v; ON_XMLParameters p(*sim_node); - if (p.GetParam(ON_TEXSIM_FILENAME, v)) + if (p.GetParam(ON_TEXTURE_SIMULATION_FILENAME, v)) { tex.m_image_file_reference.SetFullPath(v.AsString(), false); } - if (p.GetParam(ON_TEXSIM_OFFSET, v)) + if (p.GetParam(ON_TEXTURE_SIMULATION_OFFSET, v)) { XF xf; ON_DeconstructXform(tex.m_uvw, xf); @@ -1533,7 +1414,7 @@ ON_Texture ON_RenderTexture::SimulatedTexture(void) const ON_ConstructXform(xf, tex.m_uvw); } - if (p.GetParam(ON_TEXSIM_REPEAT, v)) + if (p.GetParam(ON_TEXTURE_SIMULATION_REPEAT, v)) { XF xf; ON_DeconstructXform(tex.m_uvw, xf); @@ -1543,7 +1424,7 @@ ON_Texture ON_RenderTexture::SimulatedTexture(void) const ON_ConstructXform(xf, tex.m_uvw); } - if (p.GetParam(ON_TEXSIM_ROTATION, v)) + if (p.GetParam(ON_TEXTURE_SIMULATION_ROTATION, v)) { XF xf; ON_DeconstructXform(tex.m_uvw, xf); @@ -1551,7 +1432,7 @@ ON_Texture ON_RenderTexture::SimulatedTexture(void) const ON_ConstructXform(xf, tex.m_uvw); } - if (p.GetParam(ON_TEXSIM_WRAP_TYPE, v)) + if (p.GetParam(ON_TEXTURE_SIMULATION_WRAP_TYPE, v)) { const auto wt = ON_Texture::WRAP(v.AsInteger()); tex.m_wrapu = wt; @@ -1559,7 +1440,7 @@ ON_Texture ON_RenderTexture::SimulatedTexture(void) const tex.m_wrapw = wt; } - if (p.GetParam(ON_TEXSIM_MAPPING_CHANNEL, v)) + if (p.GetParam(ON_TEXTURE_SIMULATION_MAPPING_CHANNEL, v)) { tex.m_mapping_channel_id = v.AsInteger(); } @@ -1624,7 +1505,7 @@ int ONX_Model::AddRenderTexture(const wchar_t* fn) ON_RenderTexture tex; tex.SetTypeId(uuidBM); - tex.SetParameter(ON_TEX_FILENAME, filename); + tex.SetParameter(ON_RENDER_TEXTURE_FILENAME, filename); const ON_wString tex_name = ON_FileSystemPath::FileNameFromPath(filename, false); tex.SetName(tex_name); diff --git a/opennurbs_safe_frame.cpp b/opennurbs_safe_frame.cpp index 3421447e..271e3dd7 100644 --- a/opennurbs_safe_frame.cpp +++ b/opennurbs_safe_frame.cpp @@ -37,14 +37,14 @@ public: static const wchar_t* XMLPathBase(void) { - return ON_RDK_DOCUMENT ON_RDK_SLASH ON_RDK_SETTINGS ON_RDK_SLASH ON_RDK_SAFE_FRAME; + return ON_RDK_DOCUMENT ON_XML_SLASH ON_RDK_SETTINGS ON_XML_SLASH ON_RDK_SAFE_FRAME; } static ON_wString XMLPath(const ON_wString& section_name) { ON_wString s = XMLPathBase(); ON_ASSERT(section_name.IsNotEmpty()); - s += ON_RDK_SLASH; + s += ON_XML_SLASH; s += section_name; return s; @@ -262,6 +262,6 @@ void* ON_SafeFrame::EVF(const wchar_t* func, void* data) return nullptr; } -void ON_SafeFrame::InvalidateCache(void) +void ON_SafeFrame::OnInternalXmlChanged(const ON_SafeFrame*) { } diff --git a/opennurbs_safe_frame.h b/opennurbs_safe_frame.h index 147a1d80..85999089 100644 --- a/opennurbs_safe_frame.h +++ b/opennurbs_safe_frame.h @@ -108,7 +108,7 @@ public: private: // For internal use only. friend class ON_3dmRenderSettingsPrivate; - virtual void InvalidateCache(void); + virtual void OnInternalXmlChanged(const ON_SafeFrame*); private: class CImpl; diff --git a/opennurbs_skylight.cpp b/opennurbs_skylight.cpp index 47e4f276..5a2ef97d 100644 --- a/opennurbs_skylight.cpp +++ b/opennurbs_skylight.cpp @@ -31,7 +31,7 @@ public: static const wchar_t* XMLPath(void) { - return ON_RDK_DOCUMENT ON_RDK_SLASH ON_RDK_SETTINGS ON_RDK_SLASH ON_RDK_SUN; + return ON_RDK_DOCUMENT ON_XML_SLASH ON_RDK_SETTINGS ON_XML_SLASH ON_RDK_SUN; } ON_Skylight::ON_Skylight() @@ -125,6 +125,6 @@ void ON_Skylight::SetEnvironmentId(const ON_UUID& id) m_impl->SetParameter(XMLPath(), ON_RDK_SUN_SKYLIGHT_ENVIRONMENT_ID, id); } -void ON_Skylight::InvalidateCache(void) +void ON_Skylight::OnInternalXmlChanged(const ON_Skylight*) { } diff --git a/opennurbs_skylight.h b/opennurbs_skylight.h index d2f2422f..2e59428f 100644 --- a/opennurbs_skylight.h +++ b/opennurbs_skylight.h @@ -51,7 +51,7 @@ public: // These methods are only here to support deprecated C# SDK methods. private: // For internal use only. friend class ON_3dmRenderSettingsPrivate; - virtual void InvalidateCache(void); + virtual void OnInternalXmlChanged(const ON_Skylight*); private: class CImpl; diff --git a/opennurbs_statics.cpp b/opennurbs_statics.cpp index 94fe92ad..20e6b955 100644 --- a/opennurbs_statics.cpp +++ b/opennurbs_statics.cpp @@ -328,6 +328,8 @@ const double ON_SubDEdgeSharpness::Tolerance = 0.01; const ON_SubDEdgeSharpness ON_SubDEdgeSharpness::Smooth; +const ON_SubDEdgeSharpness ON_SubDEdgeSharpness::Maximum = ON_SubDEdgeSharpness::FromConstant(ON_SubDEdgeSharpness::MaximumValue); + const ON_SubDEdgeSharpness ON_SubDEdgeSharpness::Nan = ON_SubDEdgeSharpness::FromConstant(ON_DBL_QNAN); const ON_SubDEdgeSharpness ON_SubDEdgeSharpness::Crease = ON_SubDEdgeSharpness::FromConstant(ON_SubDEdgeSharpness::CreaseValue); @@ -340,7 +342,6 @@ const ON_SubDSectorId ON_SubDSectorId::Invalid = ON_SubDSectorId::Create(nullptr const ON_SubDHash ON_SubDHash::Empty; - // {C3D8DD54-F8C8-4455-BB0E-2A2F4988EC81} const ON_UUID ON_SubD::FastAndSimpleFacePackingId = { 0xc3d8dd54, 0xf8c8, 0x4455, { 0xbb, 0xe, 0x2a, 0x2f, 0x49, 0x88, 0xec, 0x81 } }; @@ -411,6 +412,10 @@ const ON_UUID ON_StandardDisplayModeId::Artistic = const ON_UUID ON_StandardDisplayModeId::Pen = { 0xF4616FA5,0xA831,0x4620,{ 0xA9,0x7E,0x9B,0x80,0x7D,0x5E,0xC3,0x76 } }; +// {E1B5C8A2-ED43-4872-9A01-814E612D5363} +const ON_UUID ON_StandardDisplayModeId::Monochrome = +{ 0xE1B5C8A2, 0xED43, 0x4872, { 0x9A, 0x1, 0x81, 0x4E, 0x61, 0x2D, 0x53, 0x63 } }; + // {C32B72C3-41BD-4ADC-82A8-B7AEF4456A37} const ON_UUID ON_StandardDisplayModeId::AmbientOcclusion = { 0xc32b72c3, 0x41bd, 0x4adc, { 0x82, 0xa8, 0xb7, 0xae, 0xf4, 0x45, 0x6a, 0x37 } }; diff --git a/opennurbs_string.h b/opennurbs_string.h index 98314e4a..06ab249a 100644 --- a/opennurbs_string.h +++ b/opennurbs_string.h @@ -2642,7 +2642,10 @@ public: /// DEGREE SIGN U+00B0 (X°) (Rhino annotation degree symbol) static const wchar_t DegreeSymbol = (wchar_t)ON_UnicodeCodePoint::ON_DegreeSymbol; - + + /// Place of interest sign/looped square. (Used to indicate the command key on Mac) + static const wchar_t PlaceOfInterestSign = (wchar_t)ON_UnicodeCodePoint::ON_PlaceOfInterestSign; + /// PLUS-MINUS SIGN U+00B1 (±) (Rhino annotation plus/minus symbol) static const wchar_t PlusMinusSymbol = (wchar_t)ON_UnicodeCodePoint::ON_PlusMinusSymbol; diff --git a/opennurbs_subd.cpp b/opennurbs_subd.cpp index 75161299..b3c7d406 100644 --- a/opennurbs_subd.cpp +++ b/opennurbs_subd.cpp @@ -4057,6 +4057,44 @@ bool ON_SubDEdgeSharpness::IsConstant(bool bCreaseResult) const ); } +bool ON_SubDEdgeSharpness::IsConstant( + const ON_SimpleArray& edges, + bool bCreaseResult +) +{ + return ON_SubDEdgeSharpness::IsConstant( + edges.Count(), + edges.Array(), + bCreaseResult + ); +} + +bool ON_SubDEdgeSharpness::IsConstant( + size_t edge_count, + const ON_SubDEdgePtr* edges, + bool bCreaseResult +) +{ + if (edge_count < 1 || nullptr == edges) + return false; + + ON_SubDEdgeSharpness s = edges[0].RelativeSharpness(true); + if (false == s.IsConstant(bCreaseResult)) + return false; + const double c = s[0]; + if (nullptr == edges[0].RelativeVertex(0)) + return false; // not an edge chain + for (size_t i = 0; i < edge_count; ++i) + { + s = edges[i].RelativeSharpness(true); + if ( false == (c == s.EndSharpness(0) && c == s.EndSharpness(1))) + return false; + } + + return true; +} + + bool ON_SubDEdgeSharpness::IsIncreasing() const { return (m_edge_sharpness[0] < m_edge_sharpness[1]); @@ -6315,6 +6353,66 @@ unsigned int ON_SubDFace::SetEdgeMarks(bool bMark) const return changed_mark_count; } +bool ON_SubDFace::HasSharpEdges() const +{ + const ON_SubDEdgePtr* eptr = m_edge4; + for (unsigned short fei = 0; fei < m_edge_count; ++fei, ++eptr) + { + if (4 == fei) + { + eptr = m_edgex; + if (nullptr == eptr) + break; + } + const ON_SubDEdge* e = ON_SUBD_EDGE_POINTER(eptr->m_ptr); + if (nullptr != e && e->IsSharp()) + return true; + } + return false; +} + +unsigned int ON_SubDFace::SharpEdgeCount(ON_SubDEdgeSharpness& sharpness_range) const +{ + sharpness_range = ON_SubDEdgeSharpness::Smooth; + unsigned int sharp_edge_count = 0; + const ON_SubDEdgePtr* eptr = m_edge4; + for (unsigned short fei = 0; fei < m_edge_count; ++fei, ++eptr) + { + if (4 == fei) + { + eptr = m_edgex; + if (nullptr == eptr) + break; + } + const ON_SubDEdge* e = ON_SUBD_EDGE_POINTER(eptr->m_ptr); + if (nullptr == e || false == e->IsSharp()) + continue; + const ON_SubDEdgeSharpness s = e->Sharpness(false); + sharpness_range = ON_SubDEdgeSharpness::Union(sharpness_range, s); + ++sharp_edge_count; + } + return sharp_edge_count; +} + +unsigned int ON_SubDFace::SharpEdgeCount() const +{ + unsigned int sharp_edge_count = 0; + const ON_SubDEdgePtr* eptr = m_edge4; + for (unsigned short fei = 0; fei < m_edge_count; ++fei, ++eptr) + { + if (4 == fei) + { + eptr = m_edgex; + if (nullptr == eptr) + break; + } + const ON_SubDEdge* e = ON_SUBD_EDGE_POINTER(eptr->m_ptr); + if (nullptr != e && e->IsSharp()) + ++sharp_edge_count; + } + return sharp_edge_count; +} + unsigned int ON_SubDFace::GetEdgeArray( ON_SimpleArray< ON_SubDEdgePtr >& face_edge_array ) const @@ -19595,6 +19693,7 @@ bool ON_SubDVertexQuadSector::Subdivide() const unsigned subdivision_level = center_vertex->SubdivisionLevel() + 1U; for (unsigned vi = 0; vi < sector_vertex_count; ++vi) { + m_v[vi].ClearSavedSubdivisionPoints(); // <- 2023-May-5 Dale Lear. This line fixes RH-74520. m_v[vi].SetControlNetPoint(R[vi],false); m_v[vi].SetSubdivisionLevel(subdivision_level); if (1 == vi) @@ -24675,6 +24774,39 @@ bool ON_SubDEdgeChain::IsSingleEdgeChain( return ON_SubDEdgeChain::IsSingleEdgeChain(edges, bIsClosed, bIsSorted); } +bool ON_SubDEdgeChain::IsClosed( + const ON_SimpleArray& edges +) +{ + return ON_SubDEdgeChain::IsClosed( edges.Count(), edges.Array()); +} + +bool ON_SubDEdgeChain::IsClosed( + size_t edge_count, + const ON_SubDEdgePtr* edges +) +{ + if (edge_count < 3 || nullptr == edges) + return false; + const ON_SubDVertex* v = edges[0].RelativeVertex(0); + if (nullptr == v) + return false; + if (v != edges[edge_count - 1].RelativeVertex(1)) + return false; + + v = edges[0].RelativeVertex(1); + for (size_t i = 1; i < edge_count; ++i) + { + if (nullptr == v) + return false; + if (v != edges[i].RelativeVertex(0)) + return false; + v = edges[i].RelativeVertex(1); + } + + return true; + +} class ON_SubDEdgePtrLink { diff --git a/opennurbs_subd.h b/opennurbs_subd.h index 66aeb119..9385750e 100644 --- a/opennurbs_subd.h +++ b/opennurbs_subd.h @@ -286,10 +286,12 @@ public: /// static const ON_SubDEdgeSharpness Smooth; + /// - /// An edge sharpness with both end values = ON_DBL_QNAN. + /// An edge sharpness with contant value ON_SubDEdgeSharpness::MaximumValue. + /// This is the maximum sharpness that can be applied to an edge. /// - static const ON_SubDEdgeSharpness Nan; + static const ON_SubDEdgeSharpness Maximum; /// /// An edge sharpness with both end values = ON_SubDEdgeSharpness::CreaseValue. @@ -301,6 +303,13 @@ public: /// static const ON_SubDEdgeSharpness Crease; + /// + /// An edge sharpness with both end values = ON_DBL_QNAN. + /// + static const ON_SubDEdgeSharpness Nan; + + + /// /// Create a text string describing the sharpness as a percentage. /// This is useful in user interface code that experesses sharpness in percentages. @@ -474,6 +483,35 @@ public: const class ON_SubDEdgePtr& eptr1 ); + + /// + /// Determine if all the input edges have idential constant sharpeness. + /// + /// + /// + /// Result to return if all the edges are creases. + /// + /// True if all edges have identical constant sharpness. + static bool IsConstant( + const ON_SimpleArray& edges, + bool bCreaseResult + ); + + /// + /// Determine if all the input edges have idential constant sharpeness. + /// + /// + /// + /// + /// Result to return if all the edges are creases. + /// + /// True if all edges have identical constant sharpness. + static bool IsConstant( + size_t edge_count, + const ON_SubDEdgePtr* edges, + bool bCreaseResult + ); + /// True if the sharpness is zero. bool IsZero() const; @@ -702,7 +740,7 @@ public: /// /// Get the sharpness at the start or end. /// - /// + /// 0 or 1. /// Sharpness or ON_DBL_QNAN if end_index is out of range. double EndSharpness(int end_index) const; @@ -10422,7 +10460,7 @@ public: /* Description: Sets number of fragment vertices available (number of elements available in the m_P[], m_N[], and m_T[] arrays). - The memory for the arrays is managed by something besides this ON_SubDManagedMeshFragment instance. + The memory for the arrays is managed by something besides this ON_SubDMeshFragment instance. Parameters: vertex_capacity - [in] A value no larger than ON_SubDMeshFragment::MaximumVertexCount. @@ -10434,8 +10472,8 @@ public: /* Description: - Sets number of fragment vertices available (number of elements available in the m_P[], m_N[], and m_T[] arrays). - The memory for the arrays is managed by something besides this ON_SubDManagedMeshFragment instance. + Sets number of fragment vertices available (number of elements available in the m_P[], m_N[], m_T[], and m_C[] arrays). + The memory for the arrays is managed by something besides this ON_SubDMeshFragment instance. Parameters: vertex_capacity - [in] A value no larger than ON_SubDMeshFragment::MaximumVertexCount. @@ -10444,9 +10482,22 @@ public: */ bool ReserveManagedVertexCapacity(size_t vertex_capacity); + + /* + Description: + Sets number of fragment vertices available (number of elements available in the m_P[], m_N[], m_T[], m_C[], and m_K[] arrays). + The memory for the arrays is managed by something besides this ON_SubDMeshFragment instance. + Parameters: + vertex_capacity - [in] + A value no larger than ON_SubDMeshFragment::MaximumVertexCount. + Returns: + True if successful + */ + bool ReserveManagedVertexCapacity(size_t vertex_capacity, bool bWithCurvature); + /* Returns: - True if the memory in the m_P[], m_N[], and m_T[] is managed by this ON_SubDManagedMeshFragment instance. + True if the memory in the m_P[], m_N[], and m_T[] is managed by this ON_SubDMeshFragment instance. */ bool ManagedArrays() const; @@ -10454,7 +10505,7 @@ public: /* Returns: - True if the memory in the m_P[], m_N[], and m_T[] is managed by something besides this ON_SubDManagedMeshFragment instance. + True if the memory in the m_P[], m_N[], and m_T[] is managed by something besides this ON_SubDMeshFragment instance. */ bool UnmanagedArrays() const; @@ -10472,25 +10523,55 @@ private: /// 3 double for the vertex texture coordinate /// 1 double (4 bytes used for vertex color and 4 bytes currently not used) /// + /// + /// This does not hold space for curvature information. + /// Interlaced managed arrays will not work with curvature. + /// ManagedDoublesPerVertex = 10, + /// + /// 3 double for the vertex point + /// 3 double for the vertex normal + /// 3 double for the vertex texture coordinate + /// 1 double (4 bytes used for vertex color and 4 bytes currently not used) + /// 2 doubles for the curvatures + /// + ManagedDoublesPerVertexWithCurvature = 12, + /// /// Number of doubles between successive 3d points in m_P[]/m_N[]/m_T[]. /// When managed arrays are not interlaced, this value must be 3. - /// When managed arraays are interlaced, this value must be ManagedDoublesPerPoint. + /// When managed arrays are interlaced, this value must be ManagedDoublesPerVertex(WithCurvature). /// Managed_3d_stride = 3, /// /// Number of ON_Color elements between successive colors in m_C[]. - /// When managed arrays are not interlaced, this value must be 1. - /// When managed arraays are interlaced, this value must be ManagedDoublesPerPoint*sizeof(double)/sizeof(ON_Color). + /// When managed arrays are not interlaced, this value must be 1 (or 2, see remarks). + /// When managed arrays are interlaced, this value must be + /// ManagedDoublesPerVertex(WithCurvature)*sizeof(double)/sizeof(ON_Color). /// + /// + /// Setting this value to 1 for non-interlaced arrays means that + /// there will be a block of vertexCount ON_Color-sized values that are set, + /// then a block of vertexCount ON_Color-sized unset values. This allows + /// ManagedDoublesPerVertex(WithCurvature) to only count doubles, not doubles and floats. + /// The PNTC(K) array should always be of size ManagedDoublesPerVertex(WithCurvature) * vertexCount. + /// Managed_color_stride = 1, + + /// + /// Number of ON_SurfaceCurvature elements between successive curvatures in m_K[]. + /// When managed arrays are not interlaced, this value must be 1. + /// When managed arrays are interlaced, this value must be + /// ManagedDoublesPerVertex(WithCurvature)*sizeof(double)/sizeof(ON_SurfaceCurvature). + /// + Managed_curvature_stride = 1, }; static bool Internal_ManagedArraysAreInterlaced(); static size_t Internal_Managed3dArrayOffset(size_t vertex_capacity); + static size_t Internal_ManagedColorArrayOffset(size_t vertex_capacity); /* Parameters: @@ -10503,6 +10584,38 @@ private: size_t vertex_capacity ); + /* + Parameters: + PNTCK_array[] - [in] + An array of + (bWithCurvature ? ManagedDoublesPerVertexWithCurvature : ManagedDoublesPerVertex) + * vertex_capacity + doubles. + */ + void Internal_LayoutArrays( + bool bManagedArray, + bool bWithCurvature, + double* PNTCK_array, + size_t vertex_capacity + ); + + /* + Parameters: + PNTC_array[] - [in] + K_array[] - [in] + Two arrays with total space for + (K_array == nullptr ? ManagedDoublesPerVertex : ManagedDoublesPerVertexWithCurvature) + * vertex_capacity + doubles. + They may point to diferent positions in the same array. + */ + void Internal_LayoutArrays( + bool bManagedArray, + double* PNTC_array, + ON_SurfaceCurvature* K_array, + size_t vertex_capacity + ); + enum : unsigned short { /// @@ -11009,7 +11122,7 @@ private: // // Per vertex colors // - // Depending on the strides, m_P[], m_N[], m_T[] and m_C[] can be separate or interlaced. + // Depending on the strides, m_P[], m_N[], m_T[], m_C[] and m_K[] can be separate or interlaced. // // If m_C is not nullptr and m_C_stride>0, then m_C[] can accommodate up to m_P_capacity // elements. @@ -11017,12 +11130,11 @@ private: // Never modify m_C_stride, m_C. // Use m_grid functions to get color indices and quad face indices. // - // m_C[] is rarely used and typically managed with ReserveManagedColorCapacity() / DeleteManagedColorCapacity(). // NOTE WELL: // When m_C is interlaced with something containing doubles, m_C_stride must be // a multiple of 2 to keep the doubles 8 bytes aligned. // When m_C is not interlaced, m_C_stride is typically 1. If this is confusing, - // please learn more about algnment and interlacing before working on this code. + // please learn more about alignment and interlacing before working on this code. mutable ON_Color* m_C; mutable size_t m_C_stride; // stride for m_C[] as an array of 4 bytes ON_Color elements (so 0 or >= 1). @@ -11089,22 +11201,20 @@ private: // // Principal curvatures // - // If m_K is not nullptr and m_K_stride>0, then m_K[] can accommodate up to m_P_capacity - // principal curvatures and sectional curvatures (four doubles, k1,k2,sx,sy). - // Otherwise there are no principal curvatures or sectional curvatures. - // (sx = sectional curvature in grid "x" direction, sy = sectional curvature in grid "y" direction.) + // If m_K is not nullptr and m_K_stride>0, then m_K[] can accommodate up to m_P_capacity + // principal curvatures (two doubles k1, k2). Otherwise there are no principal curvatures. // At exceptional points, the curvature values may be nan. // Never modify m_K_stride, m_K. // Use m_grid functions to get principal curvature indices and quad face indices. // // m_K[] is rarely used and typically managed with ReserveManagedCurvatureCapacity() / DeleteManagedCurvatureCapacity(). // NOTE WELL: - // If m_K[] is interlacesd, the number of bytes between successive elements of m_K[] must be a multiple of 16 + // If m_K[] is interlaced, the number of bytes between successive elements of m_K[] must be a multiple of 16 // because sizeof(m_K) = 16 AND m_K_stride is the stride between elements of m_K[] // This is different than m_P_stride, m_N_stride, and m_T_stride, which count the number of doubles between successive // points/normals/texture points in m_P[]/m_N[]/m_T[]. mutable ON_SurfaceCurvature* m_K; - size_t m_K_stride; // stride for m_K[] as an array of 16 byte ON_SurfaceCurvature elements (so 0 or >= 1). + mutable size_t m_K_stride; // stride for m_K[] as an array of 16 byte ON_SurfaceCurvature elements (so 0 or >= 1). public: /* @@ -11133,7 +11243,7 @@ public: /* Returns: - True if vertex color values are set on this fragment. + True if vertex curvature values are set on this fragment. */ bool CurvaturesExist() const; @@ -11145,6 +11255,12 @@ public: */ void SetCurvaturesExist(bool bSetCurvaturesExist) const; + /* + Description: + Computes curvature values at grid points for this fragment. + */ + void SetCurvatures() const; + public: // Normalized grid parameters useful for appling a texture to the grid are available @@ -11203,6 +11319,11 @@ public: unsigned int mesh_density ) ON_NOEXCEPT; + bool ReserveCapacity( + unsigned int mesh_density, + bool bWithCurvature + ) ON_NOEXCEPT; + private: void CopyHelper(const ON_SubDMeshFragment& src); size_t m_storage_capacity = 0; @@ -14641,6 +14762,32 @@ public: ) const; + /// + /// Determine if this SubD face has sharp edges. + /// See ON_SubDEdge::IsSharp() for more information about sharp edges. + /// + /// True if this SubD face at lease one sharp edge. + bool HasSharpEdges() const; + + /// + /// Get the range of sharpness values assigned to this face's sharp edges + /// and return the number of sharp edges. + /// See ON_SubDEdge::IsSharp() for more information about sharp edges. + /// + /// The range of sharpness values is returned here. + /// (0,0) is returned if there are no sharp edges. + /// + /// Number of sharp edges attached to this face. + unsigned int SharpEdgeCount(ON_SubDEdgeSharpness& sharpness_range) const; + + /// + /// Number of sharp edges attached to this face. + /// See ON_SubDEdge::IsSharp() for more information about sharp edges. + /// + /// Number of sharp edges attached to this face. + unsigned int SharpEdgeCount() const; + + const class ON_SubDVertex* Vertex( unsigned int i ) const; @@ -18420,6 +18567,30 @@ public: const ON_SimpleArray& edges ); + + /// + /// Returns true if edges[] has 3 or more edges, the edges form a single chain, + /// and the chain begins and ends at the same vertex. + /// + /// + /// True if edges[] forms a closed edge chain. + static bool IsClosed( + const ON_SimpleArray& edges + ); + + /// + /// Returns true if edges[] has 3 or more edges, the edges form a single chain, + /// and the chain begins and ends at the same vertex. + /// + /// Number of elements in the edges[] array. + /// + /// True if edges[] forms a closed edge chain. + static bool IsClosed( + size_t edge_count, + const ON_SubDEdgePtr* edges + ); + + /* Description: Sort edges into a chains diff --git a/opennurbs_subd.natvis b/opennurbs_subd.natvis index 36634b30..0f0e2a5e 100644 --- a/opennurbs_subd.natvis +++ b/opennurbs_subd.natvis @@ -89,4 +89,28 @@ + + + {{fragment {m_face_fragment_index+1}/{m_face_fragment_count} (face id={m_face>8?m_face->m_id:0})}}} + + (short int)(m_vertex_count_etc&0x1FFF) + (short int)(m_vertex_capacity_etc&0x1FFF) + (bool)(m_vertex_count_etc&0x8000) + (bool)(m_vertex_count_etc&0x4000) + (bool)(m_vertex_capacity_etc&0x2000) + (bool)(m_vertex_capacity_etc&0x4000) + (bool)(m_vertex_capacity_etc&0x8000) + + + diff --git a/opennurbs_subd_data.cpp b/opennurbs_subd_data.cpp index cc64164b..784a0715 100644 --- a/opennurbs_subd_data.cpp +++ b/opennurbs_subd_data.cpp @@ -980,7 +980,9 @@ bool ON_SubDMeshFragment::Transform( } } } - if (0 != (ON_SubDMeshFragment::EtcControlNetQuadBit & m_vertex_capacity_etc)) + // Pierre, 2023-04-13: This was wrongly looking at ON_SubDMeshFragment::EtcControlNetQuadBit & m_vertex_capacity_etc) + // That is actually already defined for the EtcManagedArraysBit + if (0 != (ON_SubDMeshFragment::EtcControlNetQuadBit & m_vertex_count_etc)) { const ON_3dVector A(m_ctrlnetN); if (A.IsNotZero()) diff --git a/opennurbs_subd_data.h b/opennurbs_subd_data.h index 68a58dbe..529799aa 100644 --- a/opennurbs_subd_data.h +++ b/opennurbs_subd_data.h @@ -2888,6 +2888,7 @@ public: ON_SubDMeshImpl(); ~ON_SubDMeshImpl() = default; ON_SubDMeshImpl(const ON_SubDMeshImpl& src); + ON_SubDMeshImpl(const bool has_curvatures); private: // no operator = @@ -2905,6 +2906,7 @@ public: unsigned int m_fragment_point_count = 0; ON_SubDMeshFragment* m_first_fragment = nullptr; ON_SubDMeshFragment* m_last_fragment = nullptr; + const bool m_has_curvatures = false; bool ReserveCapacity( unsigned int subd_fragment_count, diff --git a/opennurbs_subd_fragment.cpp b/opennurbs_subd_fragment.cpp index 58f937e0..417a4d23 100644 --- a/opennurbs_subd_fragment.cpp +++ b/opennurbs_subd_fragment.cpp @@ -73,11 +73,56 @@ size_t ON_SubDMeshFragment::Internal_Managed3dArrayOffset(size_t vertex_capacity : 0; } +size_t ON_SubDMeshFragment::Internal_ManagedColorArrayOffset(size_t vertex_capacity) +{ + return (vertex_capacity > 0) + // NB: 2 ON_Color floats in a double + ? (2 * (ON_SubDMeshFragment::Internal_ManagedArraysAreInterlaced() ? 1 : vertex_capacity)) + : 0; +} + void ON_SubDMeshFragment::Internal_LayoutArrays( bool bManagedArray, double* PNTC_array, size_t vertex_capacity ) +{ + Internal_LayoutArrays(bManagedArray, false, PNTC_array, vertex_capacity); +} + +void ON_SubDMeshFragment::Internal_LayoutArrays( + bool bManagedArray, + bool bWithCurvature, + double* PNTCK_array, + size_t vertex_capacity +) +{ + + if (nullptr == PNTCK_array || vertex_capacity < 4 || vertex_capacity > ((size_t)ON_SubDMeshFragment::MaximumVertexCount) ) + { + PNTCK_array = nullptr; + vertex_capacity = 0; + bManagedArray = false; + bWithCurvature = false; + } + const size_t offset_to_curvature = + 3 * ON_SubDMeshFragment::Internal_Managed3dArrayOffset(vertex_capacity) + + ON_SubDMeshFragment::Internal_ManagedColorArrayOffset(vertex_capacity) * + // NB: 2 ON_Color floats in a double + sizeof(ON_Color) / sizeof(double); + Internal_LayoutArrays( + bManagedArray, PNTCK_array, + bWithCurvature ? (ON_SurfaceCurvature*)(PNTCK_array + offset_to_curvature) + : nullptr, + vertex_capacity); +} + +void ON_SubDMeshFragment::Internal_LayoutArrays( + bool bManagedArray, + double* PNTC_array, + ON_SurfaceCurvature* K_array, + size_t vertex_capacity +) { this->SetVertexCount(0); @@ -108,12 +153,17 @@ void ON_SubDMeshFragment::Internal_LayoutArrays( m_T_stride = ON_SubDMeshFragment::Managed_3d_stride; m_C = (ON_Color*)(m_T + offset_3d); m_C_stride = ON_SubDMeshFragment::Managed_color_stride; + if (nullptr != K_array) { + m_K = K_array; + m_K_stride = ON_SubDMeshFragment::Managed_curvature_stride; + } } bool ON_SubDMeshFragment::ManagedArrays() const { const size_t vertex_capacity = (ON_SubDMeshFragment::ValueMask & m_vertex_capacity_etc); const size_t offset_3d = ON_SubDMeshFragment::Internal_Managed3dArrayOffset(vertex_capacity); + const size_t offset_color = ON_SubDMeshFragment::Internal_ManagedColorArrayOffset(vertex_capacity); return ( 0 != (ON_SubDMeshFragment::EtcManagedArraysBit & m_vertex_capacity_etc) && vertex_capacity > 0 @@ -125,6 +175,13 @@ bool ON_SubDMeshFragment::ManagedArrays() const && m_N == m_P + offset_3d && m_T == m_N + offset_3d && m_C == (const ON_Color*)(m_T + offset_3d) + && ( + m_K == nullptr ? + m_K_stride == 0 : ( + m_K_stride == ON_SubDMeshFragment::Managed_curvature_stride + && m_K == (const ON_SurfaceCurvature*)(m_C + offset_color) + ) + ) ) ? true : false; } @@ -140,11 +197,12 @@ bool ON_SubDMeshFragment::DeleteManagedArrays() m_N = nullptr; m_T = nullptr; m_C = nullptr; - m_K = nullptr; + // m_K = nullptr; // Deleted in DeleteManagedCurvatureCapacity() m_P_stride = 0; m_N_stride = 0; m_T_stride = 0; m_C_stride = 0; + // m_K_stride = 0; // Deleted in DeleteManagedCurvatureCapacity() if (nullptr != managed_array) { // Allocated in ON_SubDMeshFragment::ReserveManagedVertexCapacity() @@ -169,7 +227,7 @@ bool ON_SubDMeshFragment::SetUnmanagedVertexCapacity(size_t vertex_capacity) return ON_SUBD_RETURN_ERROR(false); if (ManagedArrays()) { - // attempting to internally managed memory to externally managed memory + // attempting to convert internally managed memory to externally managed memory return ON_SUBD_RETURN_ERROR(false); } unsigned short etc = m_vertex_capacity_etc &= ON_SubDMeshFragment::EtcMask; @@ -179,6 +237,11 @@ bool ON_SubDMeshFragment::SetUnmanagedVertexCapacity(size_t vertex_capacity) } bool ON_SubDMeshFragment::ReserveManagedVertexCapacity(size_t vertex_capacity) +{ + return ReserveManagedVertexCapacity(vertex_capacity, false); +} + +bool ON_SubDMeshFragment::ReserveManagedVertexCapacity(size_t vertex_capacity, bool bWithCurvature) { if (vertex_capacity < 0 || vertex_capacity >(size_t)ON_SubDMeshFragment::MaximumVertexCount) return ON_SUBD_RETURN_ERROR(false); @@ -197,19 +260,30 @@ bool ON_SubDMeshFragment::ReserveManagedVertexCapacity(size_t vertex_capacity) DeleteManagedArrays(); } + const size_t capacity = + (bWithCurvature + ? ON_SubDMeshFragment::ManagedDoublesPerVertexWithCurvature + : ON_SubDMeshFragment::ManagedDoublesPerVertex) * + vertex_capacity; // p will be deleted in ON_SubDMeshFragment::DeleteManagedArrays(). - double* managed_doubles = new(std::nothrow) double[ON_SubDMeshFragment::ManagedDoublesPerVertex * vertex_capacity]; - Internal_LayoutArrays(true, managed_doubles, vertex_capacity); + double* managed_doubles = new(std::nothrow) double[capacity]; + Internal_LayoutArrays(true, bWithCurvature, managed_doubles, vertex_capacity); return (this->VertexCapacity() >= vertex_capacity); } bool ON_SubDMeshFragment::ReserveManagedCurvatureCapacity() const { + if (UnmanagedArrays()) + { + // attempting to convert externally managed memory to internally managed memory. + return ON_SUBD_RETURN_ERROR(false); + } const size_t current_capacity = (size_t)(ON_SubDMeshFragment::ValueMask & m_vertex_capacity_etc); if (nullptr == m_K && current_capacity > 0) { m_K = new(std::nothrow) ON_SurfaceCurvature[current_capacity]; m_vertex_capacity_etc &= ~ON_SubDMeshFragment::EtcCurvaturesExistBit; // m_K[] content is unset. + m_K_stride = ON_SubDMeshFragment::Managed_curvature_stride; } return (nullptr != m_K && current_capacity > 0); } @@ -217,11 +291,28 @@ bool ON_SubDMeshFragment::ReserveManagedCurvatureCapacity() const void ON_SubDMeshFragment::DeleteManagedCurvatureCapacity() const { + if (UnmanagedArrays()) + { + // attempting to convert externally managed memory to internally managed memory. + return ON_SubDIncrementErrorCount(); + } if (nullptr != m_K) { + if (ManagedArrays()) { + // m_K was allocated as part of the PNTCK array, it's not safe to delete it here + memset(m_K, 0, + m_K_stride * (size_t)(ON_SubDMeshFragment::ValueMask & + m_vertex_capacity_etc)); + m_vertex_capacity_etc &= + ~ON_SubDMeshFragment::EtcCurvaturesExistBit; // m_K[] content is + // unset. + return; + } + // TODO: Should we ever get here? delete[] m_K; m_K = nullptr; m_vertex_capacity_etc &= ~ON_SubDMeshFragment::EtcCurvaturesExistBit; // m_K[] content is unset. + m_K_stride = 0; } } @@ -241,43 +332,43 @@ bool ON_SubDMeshFragment::SetVertexCount(size_t vertex_count) unsigned int ON_SubDMeshFragment::PointCount() const { - return (nullptr != m_P && m_P_stride >= 3) ? VertexCount() : 0U; + return (nullptr != m_P && m_P_stride >= ON_SubDMeshFragment::Managed_3d_stride) ? VertexCount() : 0U; } unsigned int ON_SubDMeshFragment::NormalCount() const { - return (nullptr != m_N && m_N_stride >= 3) ? VertexCount() : 0U; + return (nullptr != m_N && m_N_stride >= ON_SubDMeshFragment::Managed_3d_stride) ? VertexCount() : 0U; } unsigned int ON_SubDMeshFragment::CurvatureCount() const { - return (nullptr != m_K) ? VertexCount() : 0U; + return (nullptr != m_K && m_K_stride >= ON_SubDMeshFragment::Managed_curvature_stride) ? VertexCount() : 0U; } unsigned int ON_SubDMeshFragment::ColorCount() const { - return (nullptr != m_C && m_C_stride >= 1) ? VertexCount() : 0U; + return (nullptr != m_C && m_C_stride >= ON_SubDMeshFragment::Managed_color_stride) ? VertexCount() : 0U; } unsigned int ON_SubDMeshFragment::PointCapacity() const { - return (nullptr != m_P && m_P_stride >= 3) ? VertexCapacity() : 0U; + return (nullptr != m_P && m_P_stride >= ON_SubDMeshFragment::Managed_3d_stride) ? VertexCapacity() : 0U; } unsigned int ON_SubDMeshFragment::NormalCapacity() const { - return (nullptr != m_N && m_N_stride >= 3) ? VertexCapacity() : 0U; + return (nullptr != m_N && m_N_stride >= ON_SubDMeshFragment::Managed_3d_stride) ? VertexCapacity() : 0U; } unsigned int ON_SubDMeshFragment::CurvatureCapacity() const { - return (nullptr != m_K) ? VertexCapacity() : 0U; + return (nullptr != m_K && m_K_stride >= ON_SubDMeshFragment::Managed_curvature_stride) ? VertexCapacity() : 0U; } unsigned int ON_SubDMeshFragment::ColorCapacity() const { - return (nullptr != m_C && m_C_stride >= 1) ? VertexCapacity() : 0U; + return (nullptr != m_C && m_C_stride >= ON_SubDMeshFragment::Managed_color_stride) ? VertexCapacity() : 0U; } const double* ON_SubDMeshFragment::PointArray(ON_SubDComponentLocation subd_appearance)const @@ -320,7 +411,6 @@ unsigned ON_SubDMeshFragment::CurvatureArrayCount(ON_SubDComponentLocation subd_ return (ON_SubDComponentLocation::ControlNet == subd_appearance) ? 4U : CurvatureCount(); } - const ON_Color* ON_SubDMeshFragment::ColorArray(ON_SubDComponentLocation subd_appearance) const { return (ON_SubDComponentLocation::ControlNet == subd_appearance) ? &m_ctrlnetC[0] : m_C; @@ -331,7 +421,6 @@ size_t ON_SubDMeshFragment::ColorArrayStride(ON_SubDComponentLocation subd_appea return (ON_SubDComponentLocation::ControlNet == subd_appearance) ? 1 : m_C_stride; } - unsigned ON_SubDMeshFragment::ColorArrayCount(ON_SubDComponentLocation subd_appearance) const { return (ON_SubDComponentLocation::ControlNet == subd_appearance) ? 4U : ColorCount(); @@ -595,7 +684,7 @@ const ON_SubDMeshFragment ON_SubDMeshFragment::ControlNetQuadFragmentForExperts( q.m_vertex_count_etc = 4; q.m_vertex_count_etc |= ON_SubDMeshFragment::EtcControlNetQuadBit; - q.m_vertex_count_etc |= (ON_SubDMeshFragment::EtcTextureCoordinatesExistBit&m_vertex_count_etc); + q.m_vertex_count_etc |= (ON_SubDMeshFragment::EtcTextureCoordinatesExistBit & m_vertex_count_etc); q.m_vertex_capacity_etc = 4; q.m_vertex_capacity_etc |= (ON_SubDMeshFragment::EtcColorsExistBit & m_vertex_capacity_etc); @@ -617,6 +706,7 @@ const ON_SubDMeshFragment ON_SubDMeshFragment::ControlNetQuadFragmentForExperts( q.m_C_stride = 1; q.m_K = const_cast(&m_ctrlnetK[0]); + q.m_K_stride = 1; // The grid is a single quad q.m_grid = ON_SubDMeshFragmentGrid::OneQuadGrid; @@ -841,6 +931,14 @@ ON_SubDManagedMeshFragment& ON_SubDManagedMeshFragment::operator=( ON_SubDManage bool ON_SubDManagedMeshFragment::ReserveCapacity( unsigned int display_density ) ON_NOEXCEPT +{ + return ReserveCapacity(display_density, false); +} + +bool ON_SubDManagedMeshFragment::ReserveCapacity( + unsigned int display_density, + bool bWithCurvature +) ON_NOEXCEPT { Clear(); @@ -870,8 +968,12 @@ bool ON_SubDManagedMeshFragment::ReserveCapacity( //const size_t T_stride = 3; //const size_t C_stride = 1; - // storage_capacity holds = 3 point coords + 3 normal coords + 3 texture point coords + an ON_Color + unused 4 bytes. - size_t storage_capacity = ON_SubDMeshFragment::ManagedDoublesPerVertex * V_capacity; + // storage_capacity holds = 3 point coords + 3 normal coords + 3 texture point coords + an ON_Color + unused 4 bytes (+ a 16-byte ON_SurfaceCurvature). + size_t storage_capacity = + (bWithCurvature + ? ON_SubDMeshFragment::ManagedDoublesPerVertexWithCurvature + : ON_SubDMeshFragment::ManagedDoublesPerVertex) * + V_capacity; if (storage_capacity > m_storage_capacity || nullptr == m_storage) { if (m_storage_capacity > 0 && nullptr != m_storage) @@ -887,10 +989,10 @@ bool ON_SubDManagedMeshFragment::ReserveCapacity( } UnsetControlNetQuad(); - // ON_SubDManagedMeshFragment manages m_storage and m_P[]/m_N[]/m_T[]/m_C[] are not managed by ON_SubDMeshFragment. + // ON_SubDManagedMeshFragment manages m_storage and m_P[]/m_N[]/m_T[]/m_C[](/m_K[]) are not managed by ON_SubDMeshFragment. // (ON_SubDManagedMeshFragment is a legacy class that should not be used and this confusing situation is // an artifact from early code.) - Internal_LayoutArrays(false, m_storage, V_capacity); + Internal_LayoutArrays(false, bWithCurvature, m_storage, V_capacity); SetVertexCount(V_capacity); m_surface_bbox = ON_BoundingBox::NanBoundingBox; @@ -918,6 +1020,8 @@ void ON_SubDManagedMeshFragment::Destroy() ON_NOEXCEPT void ON_SubDManagedMeshFragment::CopyHelper(const ON_SubDMeshFragment& src) { + //TODO: Should this also work when src and dest do not have the same number of vertices? See ON_SubDMeshFragment::CopyFrom() + if (this == &src) return; @@ -932,6 +1036,8 @@ void ON_SubDManagedMeshFragment::CopyHelper(const ON_SubDMeshFragment& src) m_C = nullptr; m_C_stride = 0; m_surface_bbox = ON_BoundingBox::NanBoundingBox; + m_K = nullptr; + m_K_stride = 0; const size_t V_count = src.VertexCount(); if (0 == V_count) return; @@ -964,6 +1070,19 @@ void ON_SubDManagedMeshFragment::CopyHelper(const ON_SubDMeshFragment& src) return; } + const unsigned K_count = src.CurvatureCount(); + if (0 != K_count && V_count != K_count) + { + ON_SUBD_ERROR("invalid counts"); + return; + } + + if (src.m_vertex_count_etc & ON_SubDMeshFragment::EtcControlNetQuadBit) { + m_vertex_count_etc |= ON_SubDMeshFragment::EtcControlNetQuadBit; + } else { + m_vertex_count_etc &= ~ON_SubDMeshFragment::EtcControlNetQuadBit; + } + m_ctrlnetT[0][0] = src.m_ctrlnetT[0][0]; m_ctrlnetT[0][1] = src.m_ctrlnetT[0][1]; m_ctrlnetT[0][2] = src.m_ctrlnetT[0][2]; @@ -999,8 +1118,12 @@ void ON_SubDManagedMeshFragment::CopyHelper(const ON_SubDMeshFragment& src) m_surface_bbox = src.m_surface_bbox; m_grid = src.m_grid; - // 10 = 3 point coordinates + 3 normal coordinates + 3 texture coordinates + a double to provide double aligned color memory - const size_t storage_capacity = 10U * V_count; + // 10 (12) = 3 point coordinates + 3 normal coordinates + 3 texture coordinates + a double to provide double aligned color memory (+ 2 doubles for an ON_SurfaceCurvature) + const size_t storage_capacity = + (K_count == 0 + ? ON_SubDMeshFragment::ManagedDoublesPerVertex + : ON_SubDMeshFragment::ManagedDoublesPerVertexWithCurvature) * + V_count; m_storage = new(std::nothrow) double[storage_capacity]; if (nullptr == m_storage) { @@ -1018,9 +1141,9 @@ void ON_SubDManagedMeshFragment::CopyHelper(const ON_SubDMeshFragment& src) double* p1; m_P = m_storage; - m_P_stride = 3; + m_P_stride = ON_SubDMeshFragment::Managed_3d_stride; p = m_P; - p1 = p + (m_P_stride*V_count); + p1 = p + (m_P_stride * V_count); if ( P_count > 0 ) { src_p = src.m_P; @@ -1048,14 +1171,15 @@ void ON_SubDManagedMeshFragment::CopyHelper(const ON_SubDMeshFragment& src) } else { - buffer3[0] = buffer3[1] = buffer3[2] = 0.0; + // Pierre, 2023-04-13: Set to Nan when empty source, to stay similar to ON_SubDMeshFragment::CopyFrom() + buffer3[0] = buffer3[1] = buffer3[2] = ON_DBL_QNAN; src_p = buffer3; src_p_stride = 0; } - m_N = m_storage + (3* V_count); - m_N_stride = 3; + m_N = m_storage + Internal_Managed3dArrayOffset(V_count); + m_N_stride = ON_SubDMeshFragment::Managed_3d_stride; p = m_N; - p1 = p + (m_N_stride*V_count); + p1 = p + (m_N_stride * V_count); while (p < p1) { p[0] = src_p[0]; @@ -1069,17 +1193,19 @@ void ON_SubDManagedMeshFragment::CopyHelper(const ON_SubDMeshFragment& src) { src_p = src.m_T; src_p_stride = src.m_T_stride; + SetTextureCoordinatesExist(src.TextureCoordinatesExist()); } else { buffer3[0] = buffer3[1] = buffer3[2] = ON_DBL_QNAN; src_p = buffer3; src_p_stride = 0; + SetTextureCoordinatesExist(false); } - m_T = m_storage + (6*V_count); - m_T_stride = 3; + m_T = m_N + Internal_Managed3dArrayOffset(V_count); + m_T_stride = ON_SubDMeshFragment::Managed_3d_stride; p = m_T; - p1 = p + (m_T_stride*V_count); + p1 = p + (m_T_stride * V_count); while (p < p1) { p[0] = src_p[0]; @@ -1095,14 +1221,16 @@ void ON_SubDManagedMeshFragment::CopyHelper(const ON_SubDMeshFragment& src) { src_c = src.m_C; src_c_stride = src.m_C_stride; + SetColorsExist(src.ColorsExist()); } else { src_c = &ON_Color::UnsetColor; src_c_stride = 0; + SetColorsExist(false); } - m_C = (ON_Color*)(m_storage + (9 * V_count)); - m_C_stride = 1; + m_C = (ON_Color*)(m_T + Internal_Managed3dArrayOffset(V_count)); + m_C_stride = ON_SubDMeshFragment::Managed_color_stride; ON_Color* c = m_C; ON_Color* c1 = c + (m_C_stride * V_count); while (c < c1) @@ -1112,7 +1240,31 @@ void ON_SubDManagedMeshFragment::CopyHelper(const ON_SubDMeshFragment& src) src_c += src_c_stride; } - // TODO - copy m_K as needed + const ON_SurfaceCurvature* src_k; + size_t src_k_stride; + if (K_count > 0) + { + src_k = src.m_K; + src_k_stride = src.m_K_stride; + m_K = (ON_SurfaceCurvature*)(m_C + Internal_ManagedColorArrayOffset(V_count)); + m_K_stride = ON_SubDMeshFragment::Managed_curvature_stride; + ON_SurfaceCurvature* k = m_K; + ON_SurfaceCurvature* k1 = k + (m_K_stride * V_count); + while (k < k1) + { + *k = *src_k; + k += m_K_stride; + src_k += src_k_stride; + } + SetCurvaturesExist(src.CurvaturesExist()); + } + else + { + // No space for curvatures has been allocated in m_storage + m_K = nullptr; + m_K_stride = 0; + SetCurvaturesExist(false); + } ON_3dPoint quad_points[4]; ON_3dVector quad_normal; @@ -2179,9 +2331,8 @@ void ON_SubDMeshImpl::ClearFragmentFacePointers( //} bool ON_SubDMeshImpl::ReserveCapacity( - unsigned int subd_fragment_count, - unsigned int absolute_subd_display_density - ) + unsigned int subd_fragment_count, + unsigned int absolute_subd_display_density) { ClearTree(); @@ -2198,16 +2349,20 @@ bool ON_SubDMeshImpl::ReserveCapacity( return ON_SUBD_RETURN_ERROR(false); // note sizeof(double) = 2*sizeof(ON_Color) so we have - // room for 3d poitns, 3d normals, 3d texture points, a color array - // and a currently unused array of 32 bit elements. - size_t sizeof_PNTC = ON_SubDMeshFragment::ManagedDoublesPerVertex*fragment_point_count*sizeof(double); + // room for 3d points, 3d normals, 3d texture points, a color array + // and a currently unused array of 32 bit elements, and 2d curvatures. + size_t sizeof_PNTCK = m_has_curvatures + ? ON_SubDMeshFragment::ManagedDoublesPerVertexWithCurvature * + fragment_point_count * sizeof(double) + : ON_SubDMeshFragment::ManagedDoublesPerVertex * + fragment_point_count * sizeof(double); size_t sizeof_fragment = sizeof(ON_SubDMeshFragment); if (0 != sizeof_fragment % sizeof(double)) { sizeof_fragment = (1 + sizeof_fragment / sizeof(double))*sizeof(double); } - if( false == m_fsp.Create(sizeof_fragment + sizeof_PNTC,subd_fragment_count,0)) + if( false == m_fsp.Create(sizeof_fragment + sizeof_PNTCK,subd_fragment_count,0)) return ON_SUBD_RETURN_ERROR(false); m_absolute_subd_display_density = absolute_subd_display_density; @@ -2323,9 +2478,19 @@ bool ON_SubDMeshFragment::CopyFrom( if (VertexCapacity() < V_count) { if (false == this->ReserveManagedVertexCapacity(V_count)) + //if (false == this->ReserveManagedVertexCapacity(V_count, src_fragment.CurvatureCapacity() > 0)) return ON_SUBD_RETURN_ERROR(false); } - if ( V_count > VertexCapacity() || V_count > src_fragment.VertexCount()) + if (V_count > VertexCapacity() || V_count > src_fragment.VertexCount()) + return ON_SUBD_RETURN_ERROR(false); + + if (CurvatureCapacity() < src_fragment.CurvatureCount()) + { + if (false == this->ReserveManagedCurvatureCapacity()) + return ON_SUBD_RETURN_ERROR(false); + } + if ((CurvatureCapacity() > 0 && V_count > CurvatureCapacity()) || + (src_fragment.CurvaturesExist() && V_count > src_fragment.CurvatureCount())) return ON_SUBD_RETURN_ERROR(false); m_grid = grid; @@ -2399,6 +2564,60 @@ bool ON_SubDMeshFragment::CopyFrom( ON_SubDMeshFragment::Internal_Set3dPointArrayToNan(m_T, V_count, m_T_stride); } } + + if (V_count <= ColorCapacity()) + { + if (V_count == src_fragment.ColorCount() && src_fragment.ColorsExist()) + { + // copy m_C[] + SetColorsExist(true); + ON_Color* c = m_C; + const size_t c_stride = m_C_stride; + ON_Color* src_c = src_fragment.m_C; + size_t src_c_stride = src_fragment.m_C_stride; + ON_Color* src_c1 = src_c + src_c_stride * src_V_count; + while (src_c < src_c1) + { + c = src_c; + c += c_stride; + src_c += src_c_stride; + } + } + else + { + SetColorsExist(false); + ON_Color* c = m_C; + for (ON_Color* c1 = c + V_count * m_C_stride; c < c1; c += m_C_stride) + *c = ON_Color::UnsetColor; + } + } + + if (V_count <= CurvatureCapacity()) + { + if (V_count == src_fragment.CurvatureCount() && src_fragment.CurvaturesExist()) + { + // copy m_K[] + SetCurvaturesExist(true); + ON_SurfaceCurvature* k = m_K; + const size_t k_stride = m_K_stride; + ON_SurfaceCurvature* src_k = src_fragment.m_K; + size_t src_k_stride = src_fragment.m_K_stride; + ON_SurfaceCurvature* src_k1 = src_k + src_k_stride * src_V_count; + while (src_k < src_k1) + { + k = src_k; + k += k_stride; + src_k += src_k_stride; + } + } + else + { + SetCurvaturesExist(false); + ON_SurfaceCurvature* k = m_K; + for (ON_SurfaceCurvature* k1 = k + V_count * m_K_stride; k < k1; k += m_K_stride) + *k = ON_SurfaceCurvature::Nan; + } + } } else { @@ -2516,6 +2735,36 @@ bool ON_SubDMeshFragment::CopyFrom( *c = ON_Color::UnsetColor; } } + + if (V_count <= CurvatureCapacity()) + { + // copy from src_fragment.m_K[] to this->m_K[] + if (V_count <= src_fragment.CurvatureCount() && src_fragment.CurvaturesExist()) + { + SetCurvaturesExist(true); + ON_SurfaceCurvature* k = m_K; + const size_t k_stride = m_K_stride; + i_stride = di * src_fragment.m_K_stride; + j_stride = m * dj * src_fragment.m_K_stride; + for (unsigned int j = 0; j < m; j += dj) + { + const ON_SurfaceCurvature* src_k = src_fragment.m_K + j * j_stride; + for (unsigned int i = 0; i < m; i += di) + { + *k = *src_k; + k += k_stride; + src_k += i_stride; + } + } + } + else + { + SetCurvaturesExist(false); + ON_SurfaceCurvature* k = m_K; + for (ON_SurfaceCurvature* k1 = k + V_count * m_K_stride; k < k1; k += m_K_stride) + *k = ON_SurfaceCurvature::Nan; + } + } } SetVertexCount(V_count); @@ -2537,13 +2786,13 @@ ON_SubDMeshFragment* ON_SubDMeshImpl::CopyCallbackFragment( if ( 0 == callback_fragment->PointCount() || 0 == callback_fragment->NormalCount() ) return ON_SUBD_RETURN_ERROR(nullptr); - // m_fsp.AllocateElement() allocates room for the fragment and the m_P[], m_N[], m_T[], and m_C[] arrays. + // m_fsp.AllocateElement() allocates room for the fragment and the m_P[], m_N[], m_T[], m_C[], and m_K[] (as needed) arrays. ON_SubDMeshFragment* fragment = (ON_SubDMeshFragment*)m_fsp.AllocateElement(); if ( nullptr == fragment) return ON_SUBD_RETURN_ERROR(nullptr); // The memory for the arrays in this case is managed by m_fsp[]. - fragment->Internal_LayoutArrays(false, (double*)(fragment + 1), m_fragment_point_count); + fragment->Internal_LayoutArrays(false, m_has_curvatures, (double*)(fragment + 1), m_fragment_point_count); fragment->CopyFrom(*callback_fragment); ChangeContentSerialNumber(); @@ -2892,10 +3141,18 @@ ON_SubDMeshImpl::ON_SubDMeshImpl() ChangeContentSerialNumber(); } -ON_SubDMeshImpl::ON_SubDMeshImpl( const class ON_SubDMeshImpl& src ) +ON_SubDMeshImpl::ON_SubDMeshImpl(const bool has_curvatures) + : m_has_curvatures(has_curvatures) { ChangeContentSerialNumber(); - if ( nullptr != src.m_first_fragment && ReserveCapacity((unsigned int)src.m_fsp.ActiveElementCount(), src.m_absolute_subd_display_density) ) +} + +ON_SubDMeshImpl::ON_SubDMeshImpl( const class ON_SubDMeshImpl& src ) + : m_has_curvatures(src.m_has_curvatures) +{ + ChangeContentSerialNumber(); + if (nullptr != src.m_first_fragment && + ReserveCapacity((unsigned int)src.m_fsp.ActiveElementCount(),src.m_absolute_subd_display_density)) { for (const ON_SubDMeshFragment* src_fragment = src.m_first_fragment; nullptr != src_fragment; src_fragment = src_fragment->m_next_fragment) { @@ -3476,6 +3733,11 @@ unsigned int ON_SubDDisplayParameters::DisplayDensity(const ON_SubD& subd) const ; } +const unsigned char ON_SubDDisplayParameters::GetRawDisplayDensityForExperts() const +{ + return m_display_density; +} + void ON_SubDDisplayParameters::SetDisplayDensity(unsigned int adaptive_display_density) { SetAdaptiveDisplayDensity(adaptive_display_density); @@ -3507,6 +3769,14 @@ void ON_SubDDisplayParameters::SetMeshLocation(ON_SubDComponentLocation mesh_loc m_bControlNetMesh = (ON_SubDComponentLocation::ControlNet == mesh_location) ? true : false; } +bool ON_SubDDisplayParameters::ComputeCurvature() const { + return m_bComputeCurvature; +} + +void ON_SubDDisplayParameters::SetComputeCurvature(bool compute_curvature) { + m_bComputeCurvature = false != compute_curvature ? true : false; +} + unsigned char ON_SubDDisplayParameters::EncodeAsUnsignedChar() const { const unsigned char max_display_density = ((unsigned char)ON_SubDDisplayParameters::MaximumDensity); @@ -3516,6 +3786,7 @@ unsigned char ON_SubDDisplayParameters::EncodeAsUnsignedChar() const (default_display_density == m_display_density || m_display_density > max_display_density) && ON_SubDDisplayParameters::Default.DisplayDensityIsAdaptive() == DisplayDensityIsAdaptive() && ON_SubDDisplayParameters::Default.MeshLocation() == MeshLocation() + && ON_SubDDisplayParameters::Default.ComputeCurvature() == ComputeCurvature() ) { // use defaults @@ -3541,12 +3812,18 @@ unsigned char ON_SubDDisplayParameters::EncodeAsUnsignedChar() const ? ON_SubDDisplayParameters::subd_mesh_absolute_density_bit : 0; + const unsigned char compute_curvature_as_char + = m_bComputeCurvature + ? ON_SubDDisplayParameters::subd_mesh_compute_curvature_bit + : 0; + const unsigned char nondefault_settings = ON_SubDDisplayParameters::subd_mesh_nondefault_bit; encoded_parameters = nondefault_settings | density_as_char | absoute_density_as_char + | compute_curvature_as_char | location ; } @@ -3564,10 +3841,12 @@ const ON_SubDDisplayParameters ON_SubDDisplayParameters::DecodeFromUnsignedChar( const unsigned char density_is_absolute = (ON_SubDDisplayParameters::subd_mesh_absolute_density_bit & encoded_parameters); const unsigned char density_as_char = (ON_SubDDisplayParameters::subd_mesh_density_mask & encoded_parameters); const unsigned char location_ctrl_net = (ON_SubDDisplayParameters::subd_mesh_location_bit & encoded_parameters); + const unsigned char compute_curvature = (ON_SubDDisplayParameters::subd_mesh_compute_curvature_bit & encoded_parameters); p.m_bDisplayDensityIsAbsolute = (0 != density_is_absolute) ? true : false; p.m_display_density = density_as_char; if (0 != location_ctrl_net) p.SetMeshLocation(ON_SubDComponentLocation::ControlNet); + p.SetComputeCurvature(0 != compute_curvature); } return p; diff --git a/opennurbs_sun.cpp b/opennurbs_sun.cpp index 74197424..bf4869d1 100644 --- a/opennurbs_sun.cpp +++ b/opennurbs_sun.cpp @@ -22,24 +22,10 @@ #error ON_COMPILING_OPENNURBS must be defined when compiling opennurbs #endif -#define ON_RDK_SUN_ENABLE_ALLOWED L"enable-allowed" -#define ON_RDK_SUN_ENABLE_ON L"enable-on" -#define ON_RDK_SUN_MANUAL_CONTROL_ALLOWED L"manual-control-allowed" -#define ON_RDK_SUN_MANUAL_CONTROL_ON L"manual-control-on" -#define ON_RDK_SUN_NORTH L"north" -#define ON_RDK_SUN_AZIMUTH L"sun-azimuth" -#define ON_RDK_SUN_ALTITUDE L"sun-altitude" -#define ON_RDK_SUN_DATE_YEAR L"year" -#define ON_RDK_SUN_DATE_MONTH L"month" -#define ON_RDK_SUN_DATE_DAY L"day" -#define ON_RDK_SUN_TIME_HOURS L"time" -#define ON_RDK_SUN_DAYLIGHT_SAVING_ON L"daylight-saving-on" -#define ON_RDK_SUN_DAYLIGHT_SAVING_MINUTES L"daylight-saving-minutes" -#define ON_RDK_SUN_OBSERVER_LATITUDE L"observer-latitude" -#define ON_RDK_SUN_OBSERVER_LONGITUDE L"observer-longitude" -#define ON_RDK_SUN_OBSERVER_TIMEZONE L"observer-timezone" -#define ON_RDK_SUN_SHADOW_INTENSITY L"shadow-intensity" -#define ON_RDK_SUN_INTENSITY L"intensity" +static const wchar_t* XMLPath_Sun(void) +{ + return ON_RDK_DOCUMENT ON_XML_SLASH ON_RDK_SETTINGS ON_XML_SLASH ON_RDK_SUN; +} static double Sin(double deg) { return sin(ON_RadiansFromDegrees(deg)); } static double Cos(double deg) { return cos(ON_RadiansFromDegrees(deg)); } @@ -133,6 +119,59 @@ inline static double Unwind(double dDegrees) return dDegrees; } +static bool IsVectorEqual(const ON_3dVector& v1, const ON_3dVector& v2) +{ + return IsDoubleEqual(v1.x, v2.x) && IsDoubleEqual(v1.y, v2.y) && IsDoubleEqual(v1.z, v2.z); +} + +static ON_3dVector PerpendicularVectorOnXYPlane(const ON_3dVector& vec) +{ + return ON_2dVector(vec.x, vec.y).IsTiny() ? ON_3dVector(vec.z, 0.0, -vec.x) : ON_3dVector(-vec.y, vec.x, 0.0); +} + +static double AngleFromVectors(const ON_3dVector& v1, const ON_3dVector& v2, ON_3dVector normal) +{ + if (IsVectorEqual(v1, v2)) + return 0.0; + + normal.Unitize(); + + const double numerator = v1 * v2; + const double denominator = v1.Length() * v2.Length(); + + auto cross = ON_CrossProduct(v1, v2); + cross.Unitize(); + + if (IsVectorEqual(cross, ON_3dVector::ZeroVector)) + { + if (IsDoubleEqual(numerator, +1.0)) + return 0.0; + + if (IsDoubleEqual(numerator, -1.0)) + return ON_PI; + } + + double division = numerator / denominator; + + if (division > 1.0) + division = 1.0; + else + if (division < -1.0) + division = -1.0; + + if (IsDoubleEqual(division, -1.0)) + return ON_PI; + + double angle = acos(division); + + // Check if cross is parallel or anti-parallel to normal vector. If anti-parallel then angle = 360 - angle. + const double dot = cross * normal; + if (IsDoubleEqual(dot, -1.0)) + angle = (ON_PI * 2.0) - angle; + + return angle; +} + // Reference: Jean Meeus - 'Astronomical Algorithms', second edition. class ON_SunEngine::CImpl final @@ -516,11 +555,375 @@ class ON_Sun::CImpl : public ON_InternalXMLImpl public: CImpl() { } CImpl(ON_XMLNode& n) : ON_InternalXMLImpl(&n) { } + + bool EnableAllowed(void) const; + void SetEnableAllowed(bool allowed); + bool EnableOn(void) const; + void SetEnableOn(bool on); + bool ManualControlAllowed(void) const; + void SetManualControlAllowed(bool allowed); + bool ManualControlOn(void) const; + void SetManualControlOn(bool manual); + double Azimuth(void) const; + void SetAzimuth(double azi); + double Altitude(void) const; + void SetAltitude(double alt); + double TimeZone(void) const; + void SetTimeZone(double hours); + double North(void) const; + void SetNorth(double); + double Latitude(void) const; + void SetLatitude(double); + double Longitude(void) const; + void SetLongitude(double); + bool DaylightSavingOn(void) const; + void SetDaylightSavingOn(bool on); + int DaylightSavingMinutes(void) const; + void SetDaylightSavingMinutes(int minutes); + void LocalDateTime(int& year, int& month, int& day, double& hours) const; + bool SetLocalDateTime(int year, int month, int day, double hours); + double Intensity(void) const; + void SetIntensity(double d); + double ShadowIntensity(void) const; + void SetShadowIntensity(double d); + bool IsUsingManualControl(void) const { return ManualControlAllowed() && ManualControlOn(); } + +private: + void UpdateAziAlt(void) const; + void GetEarthAnchorPlane(ON_3dVector& anchor_north, ON_Plane& plane) const; + +public: + mutable double _azimuth = 0.0; + mutable double _altitude = 0.0; + mutable bool _calc_dirty = true; + ON_EarthAnchorPoint* _earth_anchor_point = nullptr; + ON_SunEngine::Accuracy _accuracy = ON_SunEngine::Accuracy::Minimum; }; -static const wchar_t* XMLPath_Sun(void) +void ON_Sun::CImpl::GetEarthAnchorPlane(ON_3dVector& anchor_north, ON_Plane& plane) const { - return ON_RDK_DOCUMENT ON_RDK_SLASH ON_RDK_SETTINGS ON_RDK_SLASH ON_RDK_SUN; + ON_3dVector anchor_east = _earth_anchor_point->ModelEast(); + + anchor_north = _earth_anchor_point->ModelNorth(); + + // Keeps original vector length if feasible. + double east_len = anchor_east .LengthAndUnitize(); + double north_len = anchor_north.LengthAndUnitize(); + + // Compute normal of the plane P that contains m_model_east & m_model_north. + plane.zaxis = ON_CrossProduct(anchor_east, anchor_north); + + if (plane.zaxis.IsTiny()) + { + // Recompute a valid North and East vector. + if (!anchor_north.IsTiny()) + { + // North and east are equal or east is tiny. + anchor_east = -PerpendicularVectorOnXYPlane(anchor_north); + east_len = north_len; + } + else + { + if (!anchor_east.IsTiny()) + { + // North and east are equal or north is tiny. + anchor_north = PerpendicularVectorOnXYPlane(anchor_east); + north_len = east_len; + } + else + { + // Both are identity. + east_len = north_len = 1.0; + anchor_east = ON_3dVector::XAxis; + anchor_north = ON_3dVector::YAxis; + } + } + + plane.zaxis = ON_CrossProduct(anchor_east, anchor_north); + } + + plane.xaxis = PerpendicularVectorOnXYPlane(plane.zaxis); + plane.yaxis = ON_CrossProduct(plane.zaxis, plane.xaxis); + + // Restores original vector length if were valid. + plane.xaxis *= east_len; + plane.yaxis *= north_len; + plane.zaxis *= east_len * north_len; + + plane.origin = _earth_anchor_point->ModelPoint(); + plane.UpdateEquation(); +} + +void ON_Sun::CImpl::UpdateAziAlt(void) const +{ + if (_calc_dirty) + { + ON_SunEngine engine(_accuracy); + engine.SetLatitude (Latitude()); + engine.SetLongitude(Longitude()); + engine.SetTimeZoneHours(TimeZone()); + + const int dsm = DaylightSavingOn() ? DaylightSavingMinutes() : 0; + engine.SetDaylightSavingMinutes(dsm); + + int y = 0, m = 0, d = 0; double h = 0.0; + LocalDateTime(y, m, d, h); + engine.SetLocalDateTime(y, m, d, h); + + _azimuth = engine.Azimuth(); + _altitude = engine.Altitude(); + + _calc_dirty = false; + } +} + +bool ON_Sun::CImpl::EnableAllowed(void) + const { return GetParameter(XMLPath_Sun(), ON_RDK_SUN_ENABLE_ALLOWED, false); } + +void ON_Sun::CImpl::SetEnableAllowed(bool allowed) +{ + SetParameter(XMLPath_Sun(), ON_RDK_SUN_ENABLE_ALLOWED, allowed); +} + +bool ON_Sun::CImpl::EnableOn(void) + const { return GetParameter(XMLPath_Sun(), ON_RDK_SUN_ENABLE_ON, false); } + +void ON_Sun::CImpl::SetEnableOn(bool on) +{ + SetParameter(XMLPath_Sun(), ON_RDK_SUN_ENABLE_ON, on); +} + +bool ON_Sun::CImpl::ManualControlAllowed(void) const + { return GetParameter(XMLPath_Sun(), ON_RDK_SUN_MANUAL_CONTROL_ALLOWED, false); } + +void ON_Sun::CImpl::SetManualControlAllowed(bool allowed) +{ + SetParameter(XMLPath_Sun(), ON_RDK_SUN_MANUAL_CONTROL_ALLOWED, allowed); +} + +bool ON_Sun::CImpl::ManualControlOn(void) + const { return GetParameter(XMLPath_Sun(), ON_RDK_SUN_MANUAL_CONTROL_ON, false); } + +void ON_Sun::CImpl::SetManualControlOn(bool manual) +{ + SetParameter(XMLPath_Sun(), ON_RDK_SUN_MANUAL_CONTROL_ON, manual); +} + +double ON_Sun::CImpl::Azimuth(void) const +{ + if (IsUsingManualControl()) + return GetParameter(XMLPath_Sun(), ON_RDK_SUN_AZIMUTH, 0.0).AsDouble(); + + UpdateAziAlt(); + + return _azimuth; +} + +void ON_Sun::CImpl::SetAzimuth(double azimuth) +{ + SetParameter(XMLPath_Sun(), ON_RDK_SUN_AZIMUTH, azimuth); +} + +double ON_Sun::CImpl::Altitude(void) const +{ + if (IsUsingManualControl()) + return GetParameter(XMLPath_Sun(), ON_RDK_SUN_ALTITUDE, 0.0).AsDouble(); + + UpdateAziAlt(); + + return _altitude; +} + +void ON_Sun::CImpl::SetAltitude(double altitude) +{ + SetParameter(XMLPath_Sun(), ON_RDK_SUN_ALTITUDE, altitude); +} + +double ON_Sun::CImpl::TimeZone(void) + const { return GetParameter(XMLPath_Sun(), ON_RDK_SUN_OBSERVER_TIMEZONE, 0.0); } + +void ON_Sun::CImpl::SetTimeZone(double hours) +{ + SetParameter(XMLPath_Sun(), ON_RDK_SUN_OBSERVER_TIMEZONE, hours); + _calc_dirty = true; +} + +bool ON_Sun::CImpl::DaylightSavingOn(void) + const { return GetParameter(XMLPath_Sun(), ON_RDK_SUN_DAYLIGHT_SAVING_ON, false); } + +void ON_Sun::CImpl::SetDaylightSavingOn(bool on) +{ + SetParameter(XMLPath_Sun(), ON_RDK_SUN_DAYLIGHT_SAVING_ON, on); + _calc_dirty = true; +} + +int ON_Sun::CImpl::DaylightSavingMinutes(void) const +{ return GetParameter(XMLPath_Sun(), ON_RDK_SUN_DAYLIGHT_SAVING_MINUTES, 0); } + +void ON_Sun::CImpl::SetDaylightSavingMinutes(int minutes) +{ + SetParameter(XMLPath_Sun(), ON_RDK_SUN_DAYLIGHT_SAVING_MINUTES, minutes); + _calc_dirty = true; +} + +void ON_Sun::CImpl::LocalDateTime(int& year, int& month, int& day, double& hours) const +{ + const wchar_t* s = XMLPath_Sun(); + year = GetParameter(s, ON_RDK_SUN_DATE_YEAR, 2000); + month = GetParameter(s, ON_RDK_SUN_DATE_MONTH, 1); + day = GetParameter(s, ON_RDK_SUN_DATE_DAY, 1); + hours = GetParameter(s, ON_RDK_SUN_TIME_HOURS, 0.0); +} + +bool ON_Sun::CImpl::SetLocalDateTime(int year, int month, int day, double hours) +{ + year = std::max(MinYear(), std::min(MaxYear(), year)); + month = std::max(1, std::min(12, month)); + day = std::max(1, std::min(ON_SunEngine::DaysInMonth(month, year), day)); + + const wchar_t* s = XMLPath_Sun(); + SetParameter(s, ON_RDK_SUN_DATE_YEAR, year); + SetParameter(s, ON_RDK_SUN_DATE_MONTH, month); + SetParameter(s, ON_RDK_SUN_DATE_DAY, day); + SetParameter(s, ON_RDK_SUN_TIME_HOURS, hours); + + _calc_dirty = true; + + return true; +} + +double ON_Sun::CImpl::Intensity(void) const +{ + return GetParameter(XMLPath_Sun(), ON_RDK_SUN_INTENSITY, 1.0); +} + +void ON_Sun::CImpl::SetIntensity(double d) +{ + SetParameter(XMLPath_Sun(), ON_RDK_SUN_INTENSITY, std::max(0.0, d)); +} + +double ON_Sun::CImpl::ShadowIntensity(void) const +{ + return GetParameter(XMLPath_Sun(), ON_RDK_SUN_SHADOW_INTENSITY, 1.0); +} + +void ON_Sun::CImpl::SetShadowIntensity(double d) +{ + SetParameter(XMLPath_Sun(), ON_RDK_SUN_SHADOW_INTENSITY, std::max(0.0, std::min(1.0, d))); +} + +double ON_Sun::CImpl::North(void) const +{ + if (nullptr != _earth_anchor_point) + { + // Calculate north angle from earth anchor point. + ON_Plane plane; + ON_3dVector true_north; + GetEarthAnchorPlane(true_north, plane); + return ON_DegreesFromRadians(AngleFromVectors(plane.xaxis, true_north, plane.zaxis)); + } + + // No earth anchor point is set; just return the value in the XML. + return GetParameter(XMLPath_Sun(), ON_RDK_SUN_NORTH, 90.0).AsDouble(); +} + +void ON_Sun::CImpl::SetNorth(double north) +{ + if (nullptr != _earth_anchor_point) + { + // Store the north in the earth anchor point. This is more complicated than just setting one value. + ON_Plane plane; + ON_3dVector true_north; + GetEarthAnchorPlane(true_north, plane); + + // 29 January 2013 - Kike: Don't use ON_Plane::Rotate without origin. + // This function doesn't keep the vector length if the axis is the plane's z axis. + plane.Rotate(ON_RadiansFromDegrees(north - 90.0), plane.zaxis, plane.origin); + + if (!IsVectorEqual(_earth_anchor_point->ModelEast(), plane.xaxis) || + !IsVectorEqual(_earth_anchor_point->ModelNorth(), plane.yaxis)) + { + _earth_anchor_point->SetModelEast (plane.xaxis); + _earth_anchor_point->SetModelNorth(plane.yaxis); + } + + // Make sure this value never appears in the XML. This will clean old documents that were + // incorrectly saving this value in the XML as well as the earth anchor point. + RemoveParameter(XMLPath_Sun(), ON_RDK_SUN_NORTH); + } + else + { + // No earth anchor point is set; store the value in the XML. + SetParameter(XMLPath_Sun(), ON_RDK_SUN_NORTH, north); + } + + _calc_dirty = true; +} + +double ON_Sun::CImpl::Latitude(void) const +{ + if (nullptr != _earth_anchor_point) + { + // Retrieve the latitude from the earth anchor point. + const double unset_latitude = 0.0; + return _earth_anchor_point->Latitude(unset_latitude); + } + + // No earth anchor point is set; just return the value in the XML. + return GetParameter(XMLPath_Sun(), ON_RDK_SUN_OBSERVER_LATITUDE, 0.0).AsDouble(); +} + +void ON_Sun::CImpl::SetLatitude(double lat) +{ + if (nullptr != _earth_anchor_point) + { + // Store the latitude in the earth anchor point. + _earth_anchor_point->SetLatitude(lat); + + // Make sure this value never appears in the XML. This will clean old documents that were + // incorrectly saving this value in the XML as well as the earth anchor point. + RemoveParameter(XMLPath_Sun(), ON_RDK_SUN_OBSERVER_LATITUDE); + } + else + { + // No earth anchor point is set; store the value in the XML. + SetParameter(XMLPath_Sun(), ON_RDK_SUN_OBSERVER_LATITUDE, lat); + } + + _calc_dirty = true; +} + +double ON_Sun::CImpl::Longitude(void) const +{ + if (nullptr != _earth_anchor_point) + { + // Retrieve the longitude from the earth anchor point. + const double unset_longitude = 0.0; + return _earth_anchor_point->Longitude(unset_longitude); + } + + // No earth anchor point is set; just return the value in the XML. + return GetParameter(XMLPath_Sun(), ON_RDK_SUN_OBSERVER_LONGITUDE, 0.0).AsDouble(); +} + +void ON_Sun::CImpl::SetLongitude(double lon) +{ + if (nullptr != _earth_anchor_point) + { + // Store the longitude in the earth anchor point. + _earth_anchor_point->SetLongitude(lon); + + // Make sure this value never appears in the XML. This will clean old documents that were + // incorrectly saving this value in the XML as well as the earth anchor point. + RemoveParameter(XMLPath_Sun(), ON_RDK_SUN_OBSERVER_LONGITUDE); + } + else + { + // No earth anchor point is set; store the value in the XML. + SetParameter(XMLPath_Sun(), ON_RDK_SUN_OBSERVER_LONGITUDE, lon); + } + + _calc_dirty = true; } ON_Sun::ON_Sun() @@ -528,6 +931,12 @@ ON_Sun::ON_Sun() _impl = new CImpl; } +ON_Sun::ON_Sun(ON_EarthAnchorPoint& eap) +{ + _impl = new CImpl; + _impl->_earth_anchor_point = &eap; +} + ON_Sun::ON_Sun(ON_XMLNode& model_node) { _impl = new CImpl(model_node); @@ -560,7 +969,7 @@ const ON_Sun& ON_Sun::operator = (const ON_Sun& sun) if (this != &sun) { // When copying the object, we need to directly copy the underlying XML. So we can't allow - // virtual overrides to execute because they might shadow the real values we want to copy. + // virtual overrides to execute because they might hide the real values we want to copy. ON_Sun::SetEnableOn (sun.ON_Sun::EnableOn()); ON_Sun::SetEnableAllowed (sun.ON_Sun::EnableAllowed()); ON_Sun::SetEnableOn (sun.ON_Sun::EnableOn()); @@ -580,6 +989,10 @@ const ON_Sun& ON_Sun::operator = (const ON_Sun& sun) int y = 0, m = 0, d = 0; double h = 0.0; sun.ON_Sun::LocalDateTime(y, m, d, h); ON_Sun::SetLocalDateTime(y, m, d, h); + + _impl->_azimuth = sun._impl->_azimuth; + _impl->_altitude = sun._impl->_altitude; + _impl->_calc_dirty = sun._impl->_calc_dirty; } return *this; @@ -587,20 +1000,19 @@ const ON_Sun& ON_Sun::operator = (const ON_Sun& sun) bool ON_Sun::operator == (const ON_Sun& sun) const { - // When checking equality, we need to directly check the underlying XML. So we can't allow - // virtual overrides to execute because they might shadow the real values we want to copy. - if (ON_Sun::EnableAllowed() != sun.ON_Sun::EnableAllowed()) return false; - if (ON_Sun::EnableOn() != sun.ON_Sun::EnableOn()) return false; - if (ON_Sun::ManualControlAllowed() != sun.ON_Sun::ManualControlAllowed()) return false; - if (ON_Sun::ManualControlOn() != sun.ON_Sun::ManualControlOn()) return false; - if (ON_Sun::DaylightSavingOn() != sun.ON_Sun::DaylightSavingOn()) return false; - if (ON_Sun::DaylightSavingMinutes() != sun.ON_Sun::DaylightSavingMinutes()) return false; + // When checking equality, we need to directly check the underlying storage. So we can't allow + // virtual overrides to execute because they might hide the real values we want to copy. + + if (ON_Sun::EnableAllowed() != sun.ON_Sun::EnableAllowed()) return false; + if (ON_Sun::EnableOn() != sun.ON_Sun::EnableOn()) return false; + if (ON_Sun::ManualControlAllowed() != sun.ON_Sun::ManualControlAllowed()) return false; + if (ON_Sun::ManualControlOn() != sun.ON_Sun::ManualControlOn()) return false; + if (ON_Sun::DaylightSavingOn() != sun.ON_Sun::DaylightSavingOn()) return false; + if (ON_Sun::DaylightSavingMinutes() != sun.ON_Sun::DaylightSavingMinutes()) return false; if (!IsDoubleEqual(ON_Sun::North() , sun.ON_Sun::North())) return false; if (!IsDoubleEqual(ON_Sun::Latitude() , sun.ON_Sun::Latitude())) return false; if (!IsDoubleEqual(ON_Sun::Longitude() , sun.ON_Sun::Longitude())) return false; - if (!IsDoubleEqual(ON_Sun::Azimuth() , sun.ON_Sun::Azimuth())) return false; - if (!IsDoubleEqual(ON_Sun::Altitude() , sun.ON_Sun::Altitude())) return false; if (!IsDoubleEqual(ON_Sun::TimeZone() , sun.ON_Sun::TimeZone())) return false; if (!IsDoubleEqual(ON_Sun::Intensity() , sun.ON_Sun::Intensity())) return false; if (!IsDoubleEqual(ON_Sun::ShadowIntensity(), sun.ON_Sun::ShadowIntensity())) return false; @@ -611,10 +1023,16 @@ bool ON_Sun::operator == (const ON_Sun& sun) const if ((y1 != y2) || (m1 != m2) || (d1 != d2)) return false; - + if (!IsDoubleEqual(h1, h2)) return false; + if (_impl->IsUsingManualControl()) + { + if (!IsDoubleEqual(ON_Sun::Azimuth() , sun.ON_Sun::Azimuth())) return false; + if (!IsDoubleEqual(ON_Sun::Altitude() , sun.ON_Sun::Altitude())) return false; + } + return true; } @@ -625,71 +1043,67 @@ bool ON_Sun::operator != (const ON_Sun& sun) const bool ON_Sun::EnableAllowed(void) const { - return _impl->GetParameter(XMLPath_Sun(), ON_RDK_SUN_ENABLE_ALLOWED, false).AsBool(); + return _impl->EnableAllowed(); } bool ON_Sun::EnableOn(void) const { - return _impl->GetParameter(XMLPath_Sun(), ON_RDK_SUN_ENABLE_ON, false).AsBool(); + return _impl->EnableOn(); } bool ON_Sun::ManualControlAllowed(void) const { - return _impl->GetParameter(XMLPath_Sun(), ON_RDK_SUN_MANUAL_CONTROL_ALLOWED, false).AsBool(); + return _impl->ManualControlAllowed(); } bool ON_Sun::ManualControlOn(void) const { - return _impl->GetParameter(XMLPath_Sun(), ON_RDK_SUN_MANUAL_CONTROL_ON, false).AsBool(); -} - -double ON_Sun::North(void) const -{ - return _impl->GetParameter(XMLPath_Sun(), ON_RDK_SUN_NORTH, 90.0).AsDouble(); + return _impl->ManualControlOn(); } double ON_Sun::Azimuth(void) const { - return _impl->GetParameter(XMLPath_Sun(), ON_RDK_SUN_AZIMUTH, 0.0).AsDouble(); + return _impl->Azimuth(); } double ON_Sun::Altitude(void) const { - return _impl->GetParameter(XMLPath_Sun(), ON_RDK_SUN_ALTITUDE, 0.0).AsDouble(); -} - -double ON_Sun::Latitude(void) const -{ - return _impl->GetParameter(XMLPath_Sun(), ON_RDK_SUN_OBSERVER_LATITUDE, 0.0).AsDouble(); -} - -double ON_Sun::Longitude(void) const -{ - return _impl->GetParameter(XMLPath_Sun(), ON_RDK_SUN_OBSERVER_LONGITUDE, 0.0).AsDouble(); + return _impl->Altitude(); } double ON_Sun::TimeZone(void) const { - return _impl->GetParameter(XMLPath_Sun(), ON_RDK_SUN_OBSERVER_TIMEZONE, 0.0).AsDouble(); + return _impl->TimeZone(); +} + +double ON_Sun::North(void) const +{ + return _impl->North(); +} + +double ON_Sun::Latitude(void) const +{ + return _impl->Latitude(); +} + +double ON_Sun::Longitude(void) const +{ + return _impl->Longitude(); } bool ON_Sun::DaylightSavingOn(void) const { - return _impl->GetParameter(XMLPath_Sun(), ON_RDK_SUN_DAYLIGHT_SAVING_ON, false).AsBool(); + return _impl->DaylightSavingOn(); } int ON_Sun::DaylightSavingMinutes(void) const { - return _impl->GetParameter(XMLPath_Sun(), ON_RDK_SUN_DAYLIGHT_SAVING_MINUTES, 0).AsInteger(); + return _impl->DaylightSavingMinutes(); } void ON_Sun::LocalDateTime(int& year, int& month, int& day, double& hours) const { - const wchar_t* s = XMLPath_Sun(); - year = _impl->GetParameter(s, ON_RDK_SUN_DATE_YEAR, 2000); - month = _impl->GetParameter(s, ON_RDK_SUN_DATE_MONTH, 1); - day = _impl->GetParameter(s, ON_RDK_SUN_DATE_DAY, 1); - hours = _impl->GetParameter(s, ON_RDK_SUN_TIME_HOURS, 0.0); + _impl->LocalDateTime(year, month, day, hours); } void ON_Sun::UTCDateTime(int& year, int& month, int& day, double& hours) const @@ -698,7 +1112,7 @@ void ON_Sun::UTCDateTime(int& year, int& month, int& day, double& hours) const LocalDateTime(year, month, day, hours); // Set the local time, timezone and daylight into a helper 'sun'. - ON_SunEngine engine; + ON_SunEngine engine(_impl->_accuracy); engine.SetLocalDateTime(year, month, day, hours); engine.SetTimeZoneHours(TimeZone()); engine.SetDaylightSavingMinutes(DaylightSavingOn() ? DaylightSavingMinutes() : 0); @@ -710,92 +1124,83 @@ void ON_Sun::UTCDateTime(int& year, int& month, int& day, double& hours) const double ON_Sun::Intensity(void) const { - return _impl->GetParameter(XMLPath_Sun(), ON_RDK_SUN_INTENSITY, 1.0).AsDouble(); + return _impl->Intensity(); } double ON_Sun::ShadowIntensity(void) const { - return _impl->GetParameter(XMLPath_Sun(), ON_RDK_SUN_SHADOW_INTENSITY, 1.0).AsDouble(); + return _impl->ShadowIntensity(); } void ON_Sun::SetEnableAllowed(bool allowed) { - _impl->SetParameter(XMLPath_Sun(), ON_RDK_SUN_ENABLE_ALLOWED, allowed); + _impl->SetEnableAllowed(allowed); } void ON_Sun::SetEnableOn(bool on) { - _impl->SetParameter(XMLPath_Sun(), ON_RDK_SUN_ENABLE_ON, on); + _impl->SetEnableOn(on); } void ON_Sun::SetManualControlAllowed(bool allowed) { - _impl->SetParameter(XMLPath_Sun(), ON_RDK_SUN_MANUAL_CONTROL_ALLOWED, allowed); + _impl->SetManualControlAllowed(allowed); } void ON_Sun::SetManualControlOn(bool manual) { - _impl->SetParameter(XMLPath_Sun(), ON_RDK_SUN_MANUAL_CONTROL_ON, manual); + _impl->SetManualControlOn(manual); } -void ON_Sun::SetNorth(double north) +void ON_Sun::SetAzimuth(double azi) { - _impl->SetParameter(XMLPath_Sun(), ON_RDK_SUN_NORTH, north); + _impl->SetAzimuth(azi); } -void ON_Sun::SetAzimuth(double azimuth) +void ON_Sun::SetAltitude(double alt) { - _impl->SetParameter(XMLPath_Sun(), ON_RDK_SUN_AZIMUTH, azimuth); -} - -void ON_Sun::SetAltitude(double altitude) -{ - _impl->SetParameter(XMLPath_Sun(), ON_RDK_SUN_ALTITUDE, altitude); -} - -void ON_Sun::SetLatitude(double latitude) -{ - _impl->SetParameter(XMLPath_Sun(), ON_RDK_SUN_OBSERVER_LATITUDE, latitude); -} - -void ON_Sun::SetLongitude(double longitude) -{ - _impl->SetParameter(XMLPath_Sun(), ON_RDK_SUN_OBSERVER_LONGITUDE, longitude); + _impl->SetAltitude(alt); } void ON_Sun::SetTimeZone(double hours) { - _impl->SetParameter(XMLPath_Sun(), ON_RDK_SUN_OBSERVER_TIMEZONE, hours); + _impl->SetTimeZone(hours); +} + +void ON_Sun::SetNorth(double north) +{ + _impl->SetNorth(north); +} + +void ON_Sun::SetLatitude(double latitude) +{ + _impl->SetLatitude(latitude); +} + +void ON_Sun::SetLongitude(double longitude) +{ + _impl->SetLongitude(longitude); } void ON_Sun::SetDaylightSavingOn(bool on) { - _impl->SetParameter(XMLPath_Sun(), ON_RDK_SUN_DAYLIGHT_SAVING_ON, on); + return _impl->SetDaylightSavingOn(on); } void ON_Sun::SetDaylightSavingMinutes(int minutes) { - _impl->SetParameter(XMLPath_Sun(), ON_RDK_SUN_DAYLIGHT_SAVING_MINUTES, minutes); + return _impl->SetDaylightSavingMinutes(minutes); } bool ON_Sun::SetLocalDateTime(int year, int month, int day, double hours) { - if ((year < MinYear()) || (year > MaxYear())) - return false; - - const wchar_t* s = XMLPath_Sun(); - _impl->SetParameter(s, ON_RDK_SUN_DATE_YEAR, year); - _impl->SetParameter(s, ON_RDK_SUN_DATE_MONTH, month); - _impl->SetParameter(s, ON_RDK_SUN_DATE_DAY, day); - _impl->SetParameter(s, ON_RDK_SUN_TIME_HOURS, hours); - - return true; + return _impl->SetLocalDateTime(year, month, day, hours); } bool ON_Sun::SetUTCDateTime(int year, int month, int day, double hours) { // Set the UTC date and time into a helper 'sun' assuming 'local' means 'Greenwich' and get the UTC JD. - ON_SunEngine engine; + ON_SunEngine engine(_impl->_accuracy); engine.SetLocalDateTime(year, month, day, hours); // Convert the UTC JD to local JD by adding the timezone and daylight offset, @@ -808,20 +1213,20 @@ bool ON_Sun::SetUTCDateTime(int year, int month, int day, double hours) return SetLocalDateTime(year, month, day, hours); } -void ON_Sun::SetShadowIntensity(double intensity) +void ON_Sun::SetIntensity(double d) { - _impl->SetParameter(XMLPath_Sun(), ON_RDK_SUN_SHADOW_INTENSITY, std::max(0.0, std::min(1.0, intensity))); + _impl->SetIntensity(d); } -void ON_Sun::SetIntensity(double intensity) +void ON_Sun::SetShadowIntensity(double d) { - _impl->SetParameter(XMLPath_Sun(), ON_RDK_SUN_INTENSITY, std::max(0.0, intensity)); + _impl->SetShadowIntensity(d); } ON__UINT32 ON_Sun::DataCRC(ON__UINT32 crc) const { - // We need to calculate the CRC of the underlying XML. So we can't allow virtual overrides to - // execute because they might shadow the real values we want to use. + // We need to calculate the CRC of the underlying storage, so we can't allow virtual overrides to + // execute because they might hide the real values we want to use. crc = UpdateCRC(crc, ON_Sun::EnableAllowed()); crc = UpdateCRC(crc, ON_Sun::EnableOn()); @@ -1037,144 +1442,30 @@ void ON_Sun::SetXMLNode(ON_XMLNode& node) const _impl->SetModelNode(node); } +void ON_Sun::UseEarthAnchorPoint(ON_EarthAnchorPoint& eap) +{ + _impl->_earth_anchor_point = &eap; +} + +void ON_Sun::SetAccuracy(ON_SunEngine::Accuracy acc) +{ + _impl->_accuracy = acc; +} + void* ON_Sun::EVF(const wchar_t* func, void* data) { return nullptr; } -// ON_SunEx - -class ON_SunEx::CImpl +void ON_Sun::OnInternalXmlChanged(const ON_Sun* sun) { -public: - void UpdateAziAlt(const ON_Sun& sun); - - double _azimuth = 0.0; - double _altitude = 0.0; - ON__UINT32 _azi_alt_crc = 0; - mutable std::recursive_mutex m_mutex; -}; - -ON_SunEx::ON_SunEx() -{ - _impl = new CImpl; - _impl->_azimuth = ON_Sun::Azimuth(); - _impl->_altitude = ON_Sun::Altitude(); -} - -ON_SunEx::ON_SunEx(ON_XMLNode& model_node) - : - ON_Sun(model_node) -{ - _impl = new CImpl; - _impl->_azimuth = ON_Sun::Azimuth(); - _impl->_altitude = ON_Sun::Altitude(); -} - -ON_SunEx::ON_SunEx(const ON_SunEx& sun) -{ - _impl = new CImpl; - - operator = (sun); -} - -ON_SunEx::~ON_SunEx() -{ - delete _impl; - _impl = nullptr; -} - -const ON_Sun& ON_SunEx::operator = (const ON_Sun& sun) -{ - ON_Sun::operator = (sun); - - return *this; -} - -const ON_SunEx& ON_SunEx::operator = (const ON_SunEx& sun) -{ - ON_Sun::operator = (sun); - - _impl->_azimuth = sun._impl->_azimuth; - _impl->_altitude = sun._impl->_altitude; - _impl->_azi_alt_crc = sun._impl->_azi_alt_crc; - - return *this; -} - -static ON__UINT32 AziAltCRC(const ON_Sun& sun) -{ - ON__UINT32 crc = 0; - - const double latitude = sun.Latitude(); - const double longitude = sun.Longitude(); - const double time_zone = sun.TimeZone(); - const int dsm = sun.DaylightSavingOn() ? sun.DaylightSavingMinutes() : 0; - - int y = 0, m = 0, d = 0; double h = 0.0; - sun.LocalDateTime(y, m, d, h); - - crc = ON_CRC32(crc, sizeof(latitude) , &latitude); - crc = ON_CRC32(crc, sizeof(longitude), &longitude); - crc = ON_CRC32(crc, sizeof(time_zone), &time_zone); - crc = ON_CRC32(crc, sizeof(dsm) , &dsm); - - crc = ON_CRC32(crc, sizeof(y), &y); - crc = ON_CRC32(crc, sizeof(m), &m); - crc = ON_CRC32(crc, sizeof(d), &d); - crc = ON_CRC32(crc, sizeof(h), &h); - - return crc; -} - -void ON_SunEx::CImpl::UpdateAziAlt(const ON_Sun& sun) -{ - const auto crc = AziAltCRC(sun); - if (_azi_alt_crc != crc) + if (nullptr != sun) { - _azi_alt_crc = crc; - - ON_SunEngine engine; - engine.SetLatitude (sun.Latitude()); - engine.SetLongitude(sun.Longitude()); - engine.SetTimeZoneHours(sun.TimeZone()); - - const int dsm = sun.DaylightSavingOn() ? sun.DaylightSavingMinutes() : 0; - engine.SetDaylightSavingMinutes(dsm); - - int y = 0, m = 0, d = 0; double h = 0.0; - sun.LocalDateTime(y, m, d, h); - engine.SetLocalDateTime(y, m, d, h); - - _azimuth = engine.Azimuth(); - _altitude = engine.Altitude(); + // The XML has been bulk-overwritten from other XML by the client code. We must now copy the + // north, latitude and longitude values from the other sun into this one in case one or the + // other sun is using the earth anchor point for those values instead of the XML. + SetNorth(sun->North()); + SetLatitude(sun->Latitude()); + SetLongitude(sun->Longitude()); } } - -double ON_SunEx::Azimuth(void) const -{ - std::lock_guard lg(_impl->m_mutex); - - if (ManualControlAllowed() && ManualControlOn()) - return ON_Sun::Azimuth(); - - _impl->UpdateAziAlt(*this); - - return _impl->_azimuth; -} - -double ON_SunEx::Altitude(void) const -{ - std::lock_guard lg(_impl->m_mutex); - - if (ManualControlAllowed() && ManualControlOn()) - return ON_Sun::Altitude(); - - _impl->UpdateAziAlt(*this); - - return _impl->_altitude; -} - -void ON_SunEx::InvalidateCache(void) -{ -} diff --git a/opennurbs_sun.h b/opennurbs_sun.h index a3141adc..7deab256 100644 --- a/opennurbs_sun.h +++ b/opennurbs_sun.h @@ -14,10 +14,7 @@ #if !defined(ON_SUN_INC_) #define ON_SUN_INC_ -// Class ON_SunEngine is a sun calculation engine. It's responsible for doing the astronomical calculations -// used by the sun. Note that most ON_Sun methods don't use this class. Only the utility methods use -// this because generally, ON_Sun is a simple sun object that merely gets and sets stored values. -// If you want to do sun calculations with OpenNURBS you should use this class or ON_SunEx instead of ON_Sun. +// Class ON_SunEngine is a sun astronomical calculation engine. class ON_CLASS ON_SunEngine { @@ -28,7 +25,7 @@ public: Maximum, // Suitable for generating accurate tables of sun positions (e.g., an ephemeris). }; - ON_SunEngine(Accuracy a = Accuracy::Minimum); + ON_SunEngine(Accuracy a); ON_SunEngine(const ON_SunEngine&); virtual ~ON_SunEngine(); @@ -109,15 +106,15 @@ private: CImpl* _impl; }; -// Class ON_Sun represents a 'sun'. Note that generally it does not perform any astronomical calculations; -// it merely allows the programmer to get and set the various sun properties. Only the utility methods -// at the end of the class perform calculations (by using ON_SunEngine). If you want to do general sun -// calculations with OpenNURBS you should use ON_SunEngine or ON_SunEx instead of this class. +// Class ON_Sun represents a 'sun'. It can calculate the apparent position of the sun in the sky +// at a particular instant for a particular location on the Earth's surface. It can also be used +// to get the sun's color, a light representing the sun, or to generate an ephemeris. class ON_CLASS ON_Sun { public: ON_Sun(); + ON_Sun(ON_EarthAnchorPoint& eap); ON_Sun(ON_XMLNode& model_node); ON_Sun(const ON_Sun& sun); virtual ~ON_Sun(); @@ -257,6 +254,18 @@ public: // Emergency virtual function for future expansion. virtual void* EVF(const wchar_t* func, void* data); + // For internal use only. + virtual void OnInternalXmlChanged(const ON_Sun*); + + // Set the accuracy of the sun calculations. The default is minimum accuracy (for more speed). + virtual void SetAccuracy(ON_SunEngine::Accuracy acc); + + // Get a color for rendering a sun light when the sun is at a particular altitude in the sky. + static ON_4fColor SunColorFromAltitude(double altitude); + + // Returns true if the specified time is within the range supported by ON_Sun. + static bool IsValidDateTime(int year, int month, int day, int hour, int min, int sec); + public: // These utility methods are provided for convenience and perform calculations by using ON_SunEngine. // Get an ON_Light which represents the sun. Note that this does not actually calculate the sun's @@ -289,34 +298,29 @@ public: // These utility methods are provided for convenience and perform calcul // Calculates and sets the sun's azimuth and altitude taking into account the direction of north. virtual void SetAzimuthAndAltitudeFromVector(const ON_3dVector& v); - // Get a color for rendering a sun light when the sun is at a particular altitude in the sky. - static ON_4fColor SunColorFromAltitude(double altitude); - - // Returns true if the specified time is within the range supported by ON_Sun. - static bool IsValidDateTime(int year, int month, int day, int hour, int min, int sec); - -private: - // For internal use only. +private: // For internal use only. friend class ON_3dmRenderSettingsPrivate; void SetXMLNode(ON_XMLNode& node) const; + friend class ONX_Model; + void UseEarthAnchorPoint(ON_EarthAnchorPoint& eap); private: class CImpl; CImpl* _impl; }; -// Class ON_SunEx is the same as ON_Sun except that it overrides Azimuth() and Altitude() to calculate +// Class ON_SunExCombine is the same as ON_Sun except that it overrides Azimuth() and Altitude() to calculate // the sun's azimuth / altitude. -class ON_CLASS ON_SunEx : public ON_Sun +class ON_CLASS ON_SunExCombine : public ON_Sun { public: - ON_SunEx(); - ON_SunEx(ON_XMLNode& model_node); - ON_SunEx(const ON_SunEx& sun); - virtual ~ON_SunEx(); + ON_SunExCombine(); + ON_SunExCombine(ON_XMLNode& model_node); + ON_SunExCombine(const ON_SunExCombine& sun); + virtual ~ON_SunExCombine(); virtual const ON_Sun& operator = (const ON_Sun& sun) override; - virtual const ON_SunEx& operator = (const ON_SunEx& sun); + virtual const ON_SunExCombine& operator = (const ON_SunExCombine& sun); // Returns the azimuth of the sun in the sky (in degrees) as viewed by an observer on Earth. The value // increases Eastwards with North as zero. This value is not affected by the sun's 'north' setting. @@ -333,7 +337,6 @@ public: private: // For internal use only. friend class ON_3dmRenderSettingsPrivate; - virtual void InvalidateCache(void); private: class CImpl; diff --git a/opennurbs_unicode.h b/opennurbs_unicode.h index 23a1af29..6b0aa13c 100644 --- a/opennurbs_unicode.h +++ b/opennurbs_unicode.h @@ -259,8 +259,11 @@ enum ON_UnicodeCodePoint ON_GreekOmega = 0x03C9, /// CYRILLIC CAPITAL LETTER YU U+042E (Ю) (Used in Cyrillic code point tests) - ON_CyrillicCapitalYu = 0x042E, - + ON_CyrillicCapitalYu = 0x042E, + + /// Place of interest sign/looped square. (Used to indicate the command key on Mac) + ON_PlaceOfInterestSign = 0x2318, + /// Simplified Chinese logogram for tree U+6881 (梁) (Used in CJK code point tests) ON_SimplifiedChineseTree = 0x6881, @@ -353,7 +356,7 @@ enum ON_UnicodeCodePoint /// The Unicode specification states that 0x10FFFF is <not a character>. /// ON_MaximumCodePoint = 0x10FFFF, - + /// /// The maximum valid unicode code point value is 0x10FFFF. /// See ON_IsValidUnicodeCodepoint() for additional restrictions. diff --git a/opennurbs_viewport.cpp b/opennurbs_viewport.cpp index 7d8544b3..3a7ad8be 100644 --- a/opennurbs_viewport.cpp +++ b/opennurbs_viewport.cpp @@ -5042,3 +5042,115 @@ int ON_Viewport::InViewFrustum( return 0; return cr.InViewFrustum(count,p); } + + +bool ON_DollyExtents( + const ON_Viewport& current_vp, + ON_BoundingBox camcoord_bbox, + ON_Viewport& zoomed_vp +) +{ + if (&zoomed_vp != ¤t_vp) + zoomed_vp = current_vp; + + if (!camcoord_bbox.IsValid() || !zoomed_vp.IsValid()) + return false; + + double aspect = 0.0; + if (!current_vp.GetFrustumAspect(aspect)) + return false; + + if (!ON_IsValid(aspect) || 0.0 == aspect) + return false; + + // Handle non-uniform viewport scaling + ON_3dVector scale(1.0, 1.0, 0.0); + current_vp.GetViewScale(&scale.x, &scale.y); + + const double xmin = camcoord_bbox.m_min.x; + const double xmax = camcoord_bbox.m_max.x; + const double ymin = camcoord_bbox.m_min.y; + const double ymax = camcoord_bbox.m_max.y; + double dx = 0.5 * (xmax - xmin) * scale.x; + double dy = 0.5 * (ymax - ymin) * scale.y; + if (dx <= ON_SQRT_EPSILON && dy <= ON_SQRT_EPSILON) + dx = dy = 0.5; + + if (dx < dy * aspect) + dx = dy * aspect; + else + dy = dx / aspect; + + // Pad depths a bit so clippling plane are not coplanar with displayed geometry + // zmax is on frustum near and zmin is on frustum far + double zmin = camcoord_bbox.m_min.z; + double zmax = camcoord_bbox.m_max.z; + + double dz = (zmax - zmin) * 0.00390625; // 0.00390625 = 1/256 + if (ON::perspective_view == current_vp.Projection()) + { + // Do not increase zmax too much or you make zooming to small + // objects in perspective views impossible. To test any + // changes, make a line from (0,0,0) to (0.001,0.001,0.001). + // Make a perspective view with a 50mm lens angle. If you + // can't ZEA on the line, then you've adjusted dz too much. + if (dz <= 1.0e-6) + dz = 1.0e-6; + } + else if (dz <= 0.125) + { + // In parallel projection it is ok to be generous. + dz = 0.125; + } + zmax += dz; + + // It is ok to adjust zmin by more generous amount because it + // does not effect the ability to zoom in on small objects a + // perspective view. + if (dz <= 0.125) + dz = 0.125; + zmin -= dz; + dz = zmax - zmin; + + double frus_near = 0.0; + if (ON::parallel_view == current_vp.Projection()) + { + // parallel projection + //double cota = 50.0/12.0; // 50 mm lens angle + //frus_near = ((dx > dy) ? dx : dy)*cota; + frus_near = 0.125 * dz; + } + else if (ON::perspective_view == current_vp.Projection()) + { + // perspective projection + double ax, ay; + if (current_vp.GetCameraAngle(NULL, &ay, &ax)) + { + double zx = (ON_IsValid(ax) && ax > 0.0) ? dx / tan(ax) : 0.0; + double zy = (ON_IsValid(ay) && ay > 0.0) ? dy / tan(ay) : 0.0; + frus_near = (zx > zy) ? zx : zy; + } + } + + bool rc = false; + if (!ON_IsValid(frus_near) || frus_near <= ON_SQRT_EPSILON) + { + frus_near = 1.0; + } + + ON_3dPoint camloc = current_vp.CameraLocation(); + if (camloc.IsValid()) + { + ON_3dVector dolly = 0.5 * (xmax + xmin) * zoomed_vp.CameraX() + + 0.5 * (ymax + ymin) * zoomed_vp.CameraY() + + (frus_near + zmax) * zoomed_vp.CameraZ(); + camloc += dolly; + if (zoomed_vp.SetCameraLocation(camloc)) + { + double frus_far = frus_near + dz; + rc = zoomed_vp.SetFrustum(-dx, dx, -dy, dy, + frus_near, frus_far); + } + } + return rc; +} diff --git a/opennurbs_viewport.h b/opennurbs_viewport.h index 37144422..7ca8c41f 100644 --- a/opennurbs_viewport.h +++ b/opennurbs_viewport.h @@ -1732,30 +1732,28 @@ private: }; ON_DECL -bool -ON_GetViewportRotationAngles( - const ON_3dVector&, // X, // X,Y,Z must be a right handed orthonormal basis - const ON_3dVector&, // Y, - const ON_3dVector&, // Z, - double*, // angle1, // returns rotation about world Z - double*, // angle2, // returns rotation about world X ( 0 <= a2 <= pi ) - double* // angle3 // returns rotation about world Z - ); +bool ON_GetViewportRotationAngles( + const ON_3dVector&, // X, // X,Y,Z must be a right handed orthonormal basis + const ON_3dVector&, // Y, + const ON_3dVector&, // Z, + double*, // angle1, // returns rotation about world Z + double*, // angle2, // returns rotation about world X ( 0 <= a2 <= pi ) + double* // angle3 // returns rotation about world Z +); ON_DECL -bool -ON_ViewportFromRhinoView( // create ON_Viewport from legacy Rhino projection info - ON::view_projection, // projection, - const ON_3dPoint&, // rhvp_target, // 3d point - double, // rhvp_angle1 in radians - double, // rhvp_angle2 in radians - double, // rhvp_angle3 in radians - double, // rhvp_viewsize, // > 0 - double, // rhvp_cameradist, // > 0 - int, // screen_width, - int, // screen_height, - ON_Viewport& - ); +bool ON_ViewportFromRhinoView( // create ON_Viewport from legacy Rhino projection info + ON::view_projection, // projection, + const ON_3dPoint&, // rhvp_target, // 3d point + double, // rhvp_angle1 in radians + double, // rhvp_angle2 in radians + double, // rhvp_angle3 in radians + double, // rhvp_viewsize, // > 0 + double, // rhvp_cameradist, // > 0 + int, // screen_width, + int, // screen_height, + ON_Viewport& +); /* Description: @@ -1774,12 +1772,29 @@ Returns: may be zero if the plane and frustum do not intersect. */ ON_DECL -bool -ON_IntersectViewFrustumPlane( - const ON_Viewport& vp, - const ON_PlaneEquation& plane_equation, - ON_SimpleArray& points - ); +bool ON_IntersectViewFrustumPlane( + const ON_Viewport& vp, + const ON_PlaneEquation& plane_equation, + ON_SimpleArray& points +); + +/* + Dolly the camera location and so that the view frustum contains + camcoord_bbox and the volume of camcoord_bbox fills the frustum. + If the projection is perspective, the camera angle is not changed. +Parameters: + current_vp - [in] Current projection, must be valid. + camcoord_bbox - [in] Valid bounding box in current_vp camera coordinates. + zoomed_vp - [out] Can be the same as current_vp projection. +Returns: + True if successful. +*/ +ON_DECL +bool ON_DollyExtents( + const ON_Viewport& current_vp, + ON_BoundingBox camcoord_bbox, + ON_Viewport& zoomed_vp +); #endif diff --git a/opennurbs_xml.cpp b/opennurbs_xml.cpp index f7605381..451a758f 100644 --- a/opennurbs_xml.cpp +++ b/opennurbs_xml.cpp @@ -346,7 +346,7 @@ public: ON::LengthUnitSystem m_units = ON::LengthUnitSystem::None; ON__UINT8* m_raw_buffer = nullptr; bool m_bTypePending = false; - bool m_bReserved[3] = { false }; + bool m_bVaries = false; Types m_type = Types::Null; }; @@ -619,6 +619,7 @@ void ON_XMLVariant::SetValue(int v) ClearBuffers(); m_impl->m_type = Types::Integer; m_impl->m_iVal = v; + m_impl->m_bVaries = false; m_impl->m_bTypePending = false; } @@ -627,6 +628,7 @@ void ON_XMLVariant::SetValue(double v) ClearBuffers(); m_impl->m_type = Types::Double; m_impl->m_dVal = v; + m_impl->m_bVaries = false; m_impl->m_bTypePending = false; } @@ -635,6 +637,7 @@ void ON_XMLVariant::SetValue(float v) ClearBuffers(); m_impl->m_type = Types::Float; m_impl->m_fVal = v; + m_impl->m_bVaries = false; m_impl->m_bTypePending = false; } @@ -643,6 +646,7 @@ void ON_XMLVariant::SetValue(const wchar_t* s) ClearBuffers(); m_impl->m_type = Types::String; m_impl->m_sVal = s; + m_impl->m_bVaries = false; m_impl->m_bTypePending = false; } @@ -651,6 +655,7 @@ void ON_XMLVariant::SetValue(const ON_wString& s) ClearBuffers(); m_impl->m_type = Types::String; m_impl->m_sVal = s; + m_impl->m_bVaries = false; m_impl->m_bTypePending = false; } @@ -682,6 +687,7 @@ void ON_XMLVariant::SetValue(const double* p, ArrayTypes at) case ArrayTypes::Array16: m_impl->m_type = Types::Matrix; Fill(m_impl->m_aVal, p, 16); break; } + m_impl->m_bVaries = false; m_impl->m_bTypePending = false; } @@ -697,6 +703,7 @@ void ON_XMLVariant::SetValue(const float* p, ArrayTypes at) case ArrayTypes::Array16: m_impl->m_type = Types::Matrix; Fill(m_impl->m_aVal, p, 16); break; } + m_impl->m_bVaries = false; m_impl->m_bTypePending = false; } @@ -709,6 +716,7 @@ void ON_XMLVariant::SetValue(const ON_2dPoint& v) m_impl->m_aVal[0] = v.x; m_impl->m_aVal[1] = v.y; + m_impl->m_bVaries = false; m_impl->m_bTypePending = false; } @@ -722,6 +730,7 @@ void ON_XMLVariant::SetValue(const ON_3dPoint& v) m_impl->m_aVal[1] = v.y; m_impl->m_aVal[2] = v.z; + m_impl->m_bVaries = false; m_impl->m_bTypePending = false; } @@ -736,6 +745,7 @@ void ON_XMLVariant::SetValue(const ON_4dPoint& p) m_impl->m_aVal[2] = p.z; m_impl->m_aVal[3] = p.w; + m_impl->m_bVaries = false; m_impl->m_bTypePending = false; } @@ -750,6 +760,7 @@ void ON_XMLVariant::SetValue(const ON_4fColor& c) m_impl->m_aVal[2] = c.Blue(); m_impl->m_aVal[3] = c.Alpha(); + m_impl->m_bVaries = false; m_impl->m_bTypePending = false; } @@ -758,7 +769,9 @@ void ON_XMLVariant::SetValue(bool b) ClearBuffers(); m_impl->m_type = Types::Bool; + m_impl->m_bVal = b; + m_impl->m_bVaries = false; m_impl->m_bTypePending = false; } @@ -767,7 +780,9 @@ void ON_XMLVariant::SetValue(const ON_UUID& uuid) ClearBuffers(); m_impl->m_type = Types::Uuid; + m_impl->m_uuidVal = uuid; + m_impl->m_bVaries = false; m_impl->m_bTypePending = false; } @@ -776,7 +791,9 @@ void ON_XMLVariant::SetValue(time_t time) ClearBuffers(); m_impl->m_type = Types::Time; + m_impl->m_timeVal = time; + m_impl->m_bVaries = false; m_impl->m_bTypePending = false; } @@ -785,6 +802,8 @@ void ON_XMLVariant::SetValue(const void* pBuffer, size_t size) ClearBuffers(); m_impl->m_type = Types::Buffer; + + m_impl->m_bVaries = false; m_impl->m_bTypePending = false; GetBuffer().Write(size, pBuffer); @@ -793,6 +812,8 @@ void ON_XMLVariant::SetValue(const void* pBuffer, size_t size) void ON_XMLVariant::SetValue(const ON_Buffer& buffer) { m_impl->m_type = Types::Buffer; + + m_impl->m_bVaries = false; m_impl->m_bTypePending = false; GetBuffer() = buffer; @@ -803,7 +824,9 @@ void ON_XMLVariant::SetValue(const ON_Xform& xform) ClearBuffers(); m_impl->m_type = Types::Matrix; + m_impl->m_xform = xform; + m_impl->m_bVaries = false; m_impl->m_bTypePending = false; } @@ -1225,6 +1248,23 @@ bool ON_XMLVariant::IsEmpty(void) const return AsString().IsEmpty() ? true : false; } +bool ON_XMLVariant::Varies(void) const +{ + return m_impl->m_bVaries; +} + +void ON_XMLVariant::SetVaries(void) +{ + if (IsNull()) + { + ON_ERROR("Can't set ON_XMLVariant as VARIES when it's NULL"); + } + else + { + m_impl->m_bVaries = true; + } +} + ON::LengthUnitSystem ON_XMLVariant::Units(void) const { return m_impl->m_units; @@ -1716,7 +1756,7 @@ public: void MoveBefore(ON_XMLNode& other); void MoveAfter(ON_XMLNode& other); bool RecurseChildren(ON_XMLRecurseChildrenCallback callback, void* pv) const; - ON__UINT32 DataCRC(ON__UINT32 crc, int depth) const; + ON__UINT32 DataCRC(ON__UINT32 crc, bool recursive) const; static bool AssertValidTag(const ON_wString& sTag); static void AttemptToFixTag(ON_wString& tag); @@ -1772,7 +1812,7 @@ static const wchar_t* StringFromPropType(ON_XMLVariant::Types vt) } } -ON__UINT32 ON_XMLNode::CImpl::DataCRC(ON__UINT32 crc, int depth) const // [MARKER] This is probably wrong. +ON__UINT32 ON_XMLNode::CImpl::DataCRC(ON__UINT32 crc, bool recursive) const { crc = TagName().DataCRCLower(crc); @@ -1780,29 +1820,16 @@ ON__UINT32 ON_XMLNode::CImpl::DataCRC(ON__UINT32 crc, int depth) const // [MARKE ON_XMLProperty* prop = nullptr; while (nullptr != (prop = pit.GetNextProperty())) { - crc = prop->Name().DataCRCLower(crc); - crc = prop->GetValue().DataCRC(crc); + crc = prop->DataCRC(crc); } - ON_XMLParameters p(m_node); - auto* pIt = p.NewIterator(); - - ON_wString name; - ON_XMLVariant value; - while (pIt->Next(name, value)) - { - crc = value.DataCRC(crc); - } - - delete pIt; - - if (depth < 2) + if (recursive) { auto cit = m_node.GetChildIterator(); ON_XMLNode* child = nullptr; while (nullptr != (child = cit.GetNextChild())) { - crc = child->m_impl->DataCRC(crc, depth + 1); + crc = child->m_impl->DataCRC(crc, recursive); } } @@ -2683,15 +2710,15 @@ ON_XMLNode* ON_XMLNode::DetachChild(ON_XMLNode& child) return m_impl->DetachChild(child); } -bool ON_XMLNode::RemoveChild(ON_XMLNode* pChild) +bool ON_XMLNode::RemoveChild(ON_XMLNode* child) { - if (nullptr == pChild) + if (nullptr == child) return false; - auto* pDetach = m_impl->DetachChild(*pChild); - if (nullptr != pDetach) + ON_XMLNode* detach = m_impl->DetachChild(*child); + if (nullptr != detach) { - delete pDetach; + delete detach; return true; } @@ -2810,13 +2837,13 @@ ON_XMLNode* ON_XMLNode::GetNamedChild(const wchar_t* name) const { std::lock_guard lg(m_impl->m_mutex); - ON_XMLNode* pNode = nullptr; + ON_XMLNode* node = nullptr; auto it = GetChildIterator(); - while (nullptr != (pNode = it.GetNextChild())) + while (nullptr != (node = it.GetNextChild())) { - if (on_wcsicmp(name, pNode->TagName()) == 0) - return pNode; + if (on_wcsicmp(name, node->TagName()) == 0) + return node; } return nullptr; @@ -3307,7 +3334,7 @@ ON_XMLNode* ON_XMLNode::NextSibling(void) const return m_impl->m_next_sibling; } -ON__UINT32 ON_XMLNode::DataCRC(ON__UINT32 crc) const +ON__UINT32 ON_XMLNode::DataCRC(ON__UINT32 crc, bool recursive) const { return m_impl->DataCRC(crc, 0); } @@ -4567,7 +4594,7 @@ bool ON_RdkUserData::DeleteAfterRead(const ON_BinaryArchive& archive, ON_Object* pOnMaterial->SetMaterialPlugInId(uuidUniversalRenderEngine); // Fixes RH-27240 'V4 RDK materials do not work correctly in V6' // Transfer the instance id from the user data to the new member variable. - const auto* wsz = ON_RDK_UD_ROOT ON_RDK_SLASH ON_RDK_UD_MATERIAL; + const auto* wsz = ON_RDK_UD_ROOT ON_XML_SLASH ON_RDK_UD_MATERIAL; const auto uuidInstance = Value(wsz, ON_RDK_UD_INSTANCE_ID).AsUuid(); ON_ASSERT(pOnMaterial->RdkMaterialInstanceIdIsNil() || (uuidInstance == pOnMaterial->RdkMaterialInstanceId())); pOnMaterial->SetRdkMaterialInstanceId(uuidInstance); @@ -5227,24 +5254,24 @@ void ON_RdkDocumentDefaults::CreateXML(void) p.SetParam(ON_RDK_SUN_DAYLIGHT_SAVING_ON, false); p.SetParam(ON_RDK_SUN_DAYLIGHT_SAVING_MINUTES, 60); - ON_SunEngine e; - e.SetLocalDateTime(2000, 1, 1, 12.0); + ON_SunEngine engine(ON_SunEngine::Accuracy::Minimum); + engine.SetLocalDateTime(2000, 1, 1, 12.0); int y = 0, m = 0, d = 0; double h = 0.0; - e.LocalDateTime(y, m, d, h); + engine.LocalDateTime(y, m, d, h); p.SetParam(ON_RDK_SUN_DATE_YEAR, y); p.SetParam(ON_RDK_SUN_DATE_MONTH, m); p.SetParam(ON_RDK_SUN_DATE_DAY, d); p.SetParam(ON_RDK_SUN_TIME_HOURS, h); - p.SetParam(ON_RDK_SUN_AZIMUTH, e.Azimuth()); - p.SetParam(ON_RDK_SUN_ALTITUDE, e.Altitude()); - p.SetParam(ON_RDK_SUN_OBSERVER_LATITUDE, e.Latitude()); - p.SetParam(ON_RDK_SUN_OBSERVER_LONGITUDE, e.Longitude()); - p.SetParam(ON_RDK_SUN_OBSERVER_TIMEZONE, e.TimeZoneHours()); + p.SetParam(ON_RDK_SUN_AZIMUTH, engine.Azimuth()); + p.SetParam(ON_RDK_SUN_ALTITUDE, engine.Altitude()); + p.SetParam(ON_RDK_SUN_OBSERVER_TIMEZONE, engine.TimeZoneHours()); p.SetParam(ON_RDK_SUN_SKYLIGHT_ON, (_major_version < 6) ? false : true); p.SetParam(ON_RDK_SUN_SKYLIGHT_SHADOW_INTENSITY, 1.0); p.SetParam(ON_RDK_SUN_SKYLIGHT_ENVIRONMENT_OVERRIDE, (_major_version < 6) ? false : true); p.SetParam(ON_RDK_SUN_SKYLIGHT_ENVIRONMENT_ID, ON_nil_uuid); + + // Don't create defaults for North, Latitude or Longitude because they are stored in the earth anchor point. } // Safe frame. diff --git a/opennurbs_xml.h b/opennurbs_xml.h index fb1f5a4c..9129f5fe 100644 --- a/opennurbs_xml.h +++ b/opennurbs_xml.h @@ -16,6 +16,8 @@ typedef bool (*ON_XMLRecurseChildrenCallback)(class ON_XMLNode*, void*); +#define ON_XML_SLASH L"/" + // This is the structure of the RDK document XML. #define ON_RDK_DOCUMENT L"render-content-manager-document" @@ -84,7 +86,7 @@ typedef bool (*ON_XMLRecurseChildrenCallback)(class ON_XMLNode*, void*); #define ON_RDK_POST_PROCESS_GAMMA L"gamma" // Keep original XML tag. #define ON_RDK_CUSTOM_REFLECTIVE_ENVIRONMENT_ON L"custom-env-for-refl-and-refr-on" - #define ON_RDK_CUSTOM_REFLECTIVE_ENVIRONMENT L"custom-env-for-refl-and-refr" + #define ON_RDK_CUSTOM_REFLECTIVE_ENVIRONMENT L"custom-env-for-refl-and-refr" #define ON_RDK_SUN L"sun" #define ON_RDK_SUN_ENABLE_ALLOWED L"enable-allowed" @@ -135,8 +137,158 @@ typedef bool (*ON_XMLRecurseChildrenCallback)(class ON_XMLNode*, void*); #define ON_RDK_GP_TEXTURE_SIZE_LOCKED L"repeat-lock" // Keep old string. #define ON_RDK_GP_TEXTURE_ROTATION L"texture-rotation" +// Decals (stored in object attributes user data). + +#define ON_RDK_DECALS L"decals" + + #define ON_RDK_DECAL L"decal" + + #define ON_RDK_DECAL_CUSTOM L"custom" + #define ON_RDK_DECAL_CUSTOM_RENDERER L"renderer" + #define ON_RDK_DECAL_CUSTOM_PARAMS L"parameters" + + #define ON_RDK_DECAL_MAPPING L"mapping" + //----- +++++++++++++++++++ + #define ON_RDK_DECAL_MAPPING_PLANAR L"planar" + #define ON_RDK_DECAL_MAPPING_CYLINDRICAL L"cylindrical" + #define ON_RDK_DECAL_MAPPING_SPHERICAL L"spherical" + #define ON_RDK_DECAL_MAPPING_UV L"uv" + #define ON_RDK_DECAL_MAPPING_NONE L"none" + + #define ON_RDK_DECAL_PROJECTION L"projection" + //----- ++++++++++++++++++++++ + #define ON_RDK_DECAL_PROJECTION_FORWARD L"forward" + #define ON_RDK_DECAL_PROJECTION_BACKWARD L"backward" + #define ON_RDK_DECAL_PROJECTION_BOTH L"both" + #define ON_RDK_DECAL_PROJECTION_NONE L"none" + + #define ON_RDK_DECAL_MAP_TO_INSIDE_ON L"map-to-inside-on" + #define ON_RDK_DECAL_TRANSPARENCY L"transparency" + #define ON_RDK_DECAL_TEXTURE_INSTANCE L"texture-instance" + #define ON_RDK_DECAL_HEIGHT L"height" + #define ON_RDK_DECAL_ORIGIN L"origin" + #define ON_RDK_DECAL_RADIUS L"radius" + #define ON_RDK_DECAL_HORZ_SWEEP_STA L"latitude-start" + #define ON_RDK_DECAL_HORZ_SWEEP_END L"latitude-stop" + #define ON_RDK_DECAL_VERT_SWEEP_STA L"longitude-start" + #define ON_RDK_DECAL_VERT_SWEEP_END L"longitude-stop" + #define ON_RDK_DECAL_VECTOR_UP L"vector-up" + #define ON_RDK_DECAL_VECTOR_ACROSS L"vector-across" + #define ON_RDK_DECAL_MIN_U L"min-u" + #define ON_RDK_DECAL_MIN_V L"min-v" + #define ON_RDK_DECAL_MAX_U L"max-u" + #define ON_RDK_DECAL_MAX_V L"max-v" + #define ON_RDK_DECAL_IS_TEMPORARY L"is-temporary" + #define ON_RDK_DECAL_IS_VISIBLE L"is-visible" + #define ON_RDK_DECAL_INSTANCE_ID L"instance-id" + +// Render Content. + +#define ON_RENDER_CONTENT_TYPE_NAME L"type-name" +#define ON_RENDER_CONTENT_TYPE_ID L"type-id" +#define ON_RENDER_CONTENT_INSTANCE_ID L"instance-id" +#define ON_RENDER_CONTENT_RENDER_ENGINE_ID L"render-engine-id" +#define ON_RENDER_CONTENT_PLUG_IN_ID L"plug-in-id" +#define ON_RENDER_CONTENT_GROUP_ID L"group-id" +#define ON_RENDER_CONTENT_INSTANCE_NAME L"instance-name" +#define ON_RENDER_CONTENT_CHILD_SLOT_NAME L"child-slot-name" +#define ON_RENDER_CONTENT_NOTES L"notes" +#define ON_RENDER_CONTENT_TAGS L"tags" +#define ON_RENDER_CONTENT_HIDDEN L"hidden" +#define ON_RENDER_CONTENT_REFERENCE L"reference" +#define ON_RENDER_CONTENT_AUTO_DELETE L"auto-delete" + +#define ON_RENDER_CONTENT_PARAMETERS L"parameters" +#define ON_RENDER_CONTENT_PARAMETERS_V8 L"parameters-v8" +#define ON_RENDER_CONTENT_SIMULATION L"simulation" + +// General parameters used by materials that simulate ON_Material. + +#define ON_MATERIAL_ALPHA_TRANSPARENCY L"alpha-transparency" +#define ON_MATERIAL_AMBIENT L"ambient" +#define ON_MATERIAL_DIFFUSE L"diffuse" +#define ON_MATERIAL_DISABLE_LIGHTING L"disable-lighting" +#define ON_MATERIAL_EMISSION L"emission" +#define ON_MATERIAL_FLAMINGO_LIBRARY L"flamingo-library" +#define ON_MATERIAL_FRESNEL_ENABLED L"fresnel-enabled" +#define ON_MATERIAL_CLARITY_AMOUNT L"clarity-amount" +#define ON_MATERIAL_IOR L"ior" +#define ON_MATERIAL_POLISH_AMOUNT L"polish-amount" +#define ON_MATERIAL_SHINE L"shine" // Value is 0.0..1.0, NOT ON_Material::MaxShine. +#define ON_MATERIAL_SPECULAR L"specular" +#define ON_MATERIAL_REFLECTIVITY_AMOUNT L"reflectivity" +#define ON_MATERIAL_REFLECTIVITY_COLOR L"reflectivity-color" +#define ON_MATERIAL_TRANSPARENCY_AMOUNT L"transparency" +#define ON_MATERIAL_TRANSPARENCY_COLOR L"transparency-color" +#define ON_MATERIAL_SIM_REFLECTION_COLOR L"reflection" // Used by simulation, not by Custom Material field. +#define ON_MATERIAL_SIM_TRANSPARENT_COLOR L"transparent" // Used by simulation, not by Custom Material field. + +#define ON_MATERIAL_IS_PHYSICALLY_BASED L"is-physically-based" + +#define ON_PBR_MATERIAL_BRDF L"pbr-brdf" +#define ON_PBR_MATERIAL_BRDF_GGX L"ggx" +#define ON_PBR_MATERIAL_BRDF_WARD L"ward" +#define ON_PBR_MATERIAL_ALPHA L"pbr-alpha" +#define ON_PBR_MATERIAL_ANISOTROPIC L"pbr-anisotropic" +#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_ROUGHNESS L"pbr-clearcoat-roughness" +#define ON_PBR_MATERIAL_EMISSION_COLOR L"pbr-emission" +#define ON_PBR_MATERIAL_METALLIC L"pbr-metallic" +#define ON_PBR_MATERIAL_OPACITY L"pbr-opacity" +#define ON_PBR_MATERIAL_OPACITY_IOR L"pbr-opacity-ior" +#define ON_PBR_MATERIAL_OPACITY_ROUGHNESS L"pbr-opacity-roughness" +#define ON_PBR_MATERIAL_ROUGHNESS L"pbr-roughness" +#define ON_PBR_MATERIAL_SHEEN L"pbr-sheen" +#define ON_PBR_MATERIAL_SHEEN_TINT L"pbr-sheen-tint" +#define ON_PBR_MATERIAL_SPECULAR L"pbr-specular" +#define ON_PBR_MATERIAL_SPECULAR_TINT L"pbr-specular-tint" +#define ON_PBR_MATERIAL_SUBSURFACE L"pbr-subsurface" +#define ON_PBR_MATERIAL_SUBSURFACE_SCATTERING_COLOR L"pbr-subsurface-scattering-color" +#define ON_PBR_MATERIAL_SUBSURFACE_SCATTERING_RADIUS L"pbr-subsurface-scattering-radius" +#define ON_PBR_MATERIAL_USE_BASE_COLOR_TEXTURE_ALPHA L"pbr-use-base-color-texture-alpha" + +#define ON_RENDER_TEXTURE_FILENAME L"filename" + +// Material's texture simulation. +#define ON_RENDER_MATERIAL_TEXTURE_SIMULATION_FORMAT L"Texture-%u-" +#define ON_RENDER_MATERIAL_TEXTURE_SIMULATION_FILENAME L"filename" +#define ON_RENDER_MATERIAL_TEXTURE_SIMULATION_ON L"on" +#define ON_RENDER_MATERIAL_TEXTURE_SIMULATION_AMOUNT L"amount" +#define ON_RENDER_MATERIAL_TEXTURE_SIMULATION_TYPE L"type" +#define ON_RENDER_MATERIAL_TEXTURE_SIMULATION_FILTER L"filter" +#define ON_RENDER_MATERIAL_TEXTURE_SIMULATION_MODE L"mode" +#define ON_RENDER_MATERIAL_TEXTURE_SIMULATION_UVW L"uvw" +#define ON_RENDER_MATERIAL_TEXTURE_SIMULATION_WRAP_U L"wrap-u" +#define ON_RENDER_MATERIAL_TEXTURE_SIMULATION_WRAP_V L"wrap-v" + +// Environment simulation. +#define ON_ENVIRONMENT_SIMULATION_BACKGROUND_COLOR L"background-color" +#define ON_ENVIRONMENT_SIMULATION_BACKGROUND_IMAGE L"background-image" +#define ON_ENVIRONMENT_SIMULATION_BACKGROUND_PROJECTION L"background-projection" + +// Environment projections. +#define ON_ENVIRONMENT_PROJECTION_BOX L"box" +#define ON_ENVIRONMENT_PROJECTION_CUBE_MAP L"cubemap" +#define ON_ENVIRONMENT_PROJECTION_CUBE_MAP_HORZ L"horizontal-cross-cubemap" +#define ON_ENVIRONMENT_PROJECTION_CUBE_MAP_VERT L"vertical-cross-cubemap" +#define ON_ENVIRONMENT_PROJECTION_EMAP L"emap" +#define ON_ENVIRONMENT_PROJECTION_HEMISPHERICAL L"hemispherical" +#define ON_ENVIRONMENT_PROJECTION_LIGHT_PROBE L"lightprobe" +#define ON_ENVIRONMENT_PROJECTION_PLANAR L"planar" +#define ON_ENVIRONMENT_PROJECTION_SPHERICAL L"spherical" + +// Texture simulation. +#define ON_TEXTURE_SIMULATION_FILENAME L"filename" +#define ON_TEXTURE_SIMULATION_REPEAT L"repeat" +#define ON_TEXTURE_SIMULATION_OFFSET L"offset" +#define ON_TEXTURE_SIMULATION_ROTATION L"rotation" +#define ON_TEXTURE_SIMULATION_WRAP_TYPE L"wrap-type" +#define ON_TEXTURE_SIMULATION_MAPPING_CHANNEL L"mapping-channel" +#define ON_TEXTURE_SIMULATION_PROJECTION_MODE L"projection-mode" + #define ON_RDK_POSTFIX_SECTION L"-section" -#define ON_RDK_SLASH L"/" class ON_CLASS ON_XMLVariant { @@ -188,6 +340,9 @@ public: virtual bool IsEmpty(void) const; virtual bool IsNull(void) const; + virtual bool Varies(void) const; + virtual void SetVaries(void); + virtual ON::LengthUnitSystem Units(void) const; virtual void SetUnits(ON::LengthUnitSystem units); @@ -462,12 +617,10 @@ public: // Utilities. virtual int GetNestedDepth(void) const; - // Get the CRC of this node. This assumes the node has the following format: - // - // 1.23456 - // ... - // - virtual ON__UINT32 DataCRC(ON__UINT32 current_remainder) const; + // Get the CRC of this node. + // Param current_remainder is the current remainder value as used by ON_CRC32. + // Param recursive is true to process nodes recursively, false to process only this node. + virtual ON__UINT32 DataCRC(ON__UINT32 current_remainder, bool recursive) const; // Use this when you are looking for a node that is only one child below - non-recursive, but fast. virtual ON_XMLNode* GetNamedChild(const wchar_t* name) const; @@ -479,7 +632,6 @@ public: // Utilities. // Returns the full path to this node. virtual ON_wString GetPathFromRoot(void) const; - ///////////////////////////////////////////////////////////////////////////////////////////////////////// // Gets at nodes deep into the tree using a slash-delimited path, i.e., "child/grandchild/great-grandchild". // There's no checking for multiple nodes with the same name at each level of the tree, so if you use these // methods, you have to make sure you have unique node names at each level. @@ -494,8 +646,6 @@ public: // Utilities. // by the caller. The child node is owned by its immediate parent at that position in the node hierarchy. virtual ON_XMLNode* CreateNodeAtPath(const wchar_t* path); - ///////////////////////////////////////////////////////////////////////////////////////////////////////// - protected: // Emergency virtual function for future expansion. virtual void* EVF(const wchar_t* func, void* data);