Blender V5.0
hydra/curves.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2022 NVIDIA Corporation
2 * SPDX-FileCopyrightText: 2022 Blender Foundation
3 *
4 * SPDX-License-Identifier: Apache-2.0 */
5
6#include "hydra/curves.h"
7#include "hydra/attribute.h"
8#include "hydra/geometry.inl"
9#include "scene/hair.h"
10
11#include <pxr/imaging/hd/extComputationUtils.h>
12
14
15HdCyclesCurves::HdCyclesCurves(const SdfPath &rprimId
16#if PXR_VERSION < 2102
17 ,
18 const SdfPath &instancerId
19#endif
20 )
21 : HdCyclesGeometry(rprimId
22#if PXR_VERSION < 2102
23 ,
24 instancerId
25#endif
26 )
27{
28}
29
31
33{
35 bits |= HdChangeTracker::DirtyPoints | HdChangeTracker::DirtyWidths |
36 HdChangeTracker::DirtyPrimvar | HdChangeTracker::DirtyTopology;
37 return bits;
38}
39
40HdDirtyBits HdCyclesCurves::_PropagateDirtyBits(HdDirtyBits bits) const
41{
42 if (bits & (HdChangeTracker::DirtyTopology)) {
43 // Changing topology clears the geometry, so need to populate everything again
44 bits |= HdChangeTracker::DirtyPoints | HdChangeTracker::DirtyWidths |
45 HdChangeTracker::DirtyPrimvar;
46 }
47
48 return bits;
49}
50
51void HdCyclesCurves::Populate(HdSceneDelegate *sceneDelegate, HdDirtyBits dirtyBits, bool &rebuild)
52{
53 if (HdChangeTracker::IsTopologyDirty(dirtyBits, GetId())) {
54 PopulateTopology(sceneDelegate);
55 }
56
57 if (dirtyBits & HdChangeTracker::DirtyPoints) {
58 PopulatePoints(sceneDelegate);
59 }
60
61 if (dirtyBits & HdChangeTracker::DirtyWidths) {
62 PopulateWidths(sceneDelegate);
63 }
64
65 if (dirtyBits & HdChangeTracker::DirtyPrimvar) {
66 PopulatePrimvars(sceneDelegate);
67 }
68
69 rebuild = (_geom->curve_keys_is_modified()) || (_geom->curve_radius_is_modified());
70}
71
72void HdCyclesCurves::PopulatePoints(HdSceneDelegate *sceneDelegate)
73{
74 VtValue value;
75
76 for (const HdExtComputationPrimvarDescriptor &desc :
77 sceneDelegate->GetExtComputationPrimvarDescriptors(GetId(), HdInterpolationVertex))
78 {
79 if (desc.name == HdTokens->points) {
80 auto valueStore = HdExtComputationUtils::GetComputedPrimvarValues({desc}, sceneDelegate);
81 const auto valueStoreIt = valueStore.find(desc.name);
82 if (valueStoreIt != valueStore.end()) {
83 value = std::move(valueStoreIt->second);
84 }
85 break;
86 }
87 }
88
89 if (value.IsEmpty()) {
90 value = GetPrimvar(sceneDelegate, HdTokens->points);
91 }
92
93 if (!value.IsHolding<VtVec3fArray>()) {
94 TF_WARN("Invalid points data for %s", GetId().GetText());
95 return;
96 }
97
98 const auto &points = value.UncheckedGet<VtVec3fArray>();
99
100 array<float3> pointsDataCycles;
101 pointsDataCycles.reserve(points.size());
102
103 for (const GfVec3f &point : points) {
104 pointsDataCycles.push_back_reserved(make_float3(point[0], point[1], point[2]));
105 }
106
107 _geom->set_curve_keys(pointsDataCycles);
108}
109
110void HdCyclesCurves::PopulateWidths(HdSceneDelegate *sceneDelegate)
111{
112 const VtValue value = GetPrimvar(sceneDelegate, HdTokens->widths);
113 const HdInterpolation interpolation = GetPrimvarInterpolation(sceneDelegate, HdTokens->widths);
114
115 if (!value.IsHolding<VtFloatArray>()) {
116 TF_WARN("Invalid widths data for %s", GetId().GetText());
117 return;
118 }
119
120 const auto &widths = value.UncheckedGet<VtFloatArray>();
121
122 array<float> radiusDataCycles;
123 radiusDataCycles.reserve(widths.size());
124
125 if (interpolation == HdInterpolationConstant) {
126 TF_VERIFY(widths.size() == 1);
127
128 const float constantRadius = widths[0] * 0.5f;
129
130 for (size_t i = 0; i < _geom->num_keys(); ++i) {
131 radiusDataCycles.push_back_reserved(constantRadius);
132 }
133 }
134 else if (interpolation == HdInterpolationVertex) {
135 TF_VERIFY(widths.size() == _geom->num_keys());
136
137 for (size_t i = 0; i < _geom->num_keys(); ++i) {
138 radiusDataCycles.push_back_reserved(widths[i] * 0.5f);
139 }
140 }
141
142 _geom->set_curve_radius(radiusDataCycles);
143}
144
145void HdCyclesCurves::PopulatePrimvars(HdSceneDelegate *sceneDelegate)
146{
147 Scene *const scene = (Scene *)_geom->get_owner();
148
149 const std::pair<HdInterpolation, AttributeElement> interpolations[] = {
150 std::make_pair(HdInterpolationVertex, ATTR_ELEMENT_CURVE_KEY),
151 std::make_pair(HdInterpolationVarying, ATTR_ELEMENT_CURVE_KEY),
152 std::make_pair(HdInterpolationUniform, ATTR_ELEMENT_CURVE),
153 std::make_pair(HdInterpolationConstant, ATTR_ELEMENT_OBJECT),
154 };
155
156 for (const auto &interpolation : interpolations) {
157 for (const HdPrimvarDescriptor &desc :
158 GetPrimvarDescriptors(sceneDelegate, interpolation.first))
159 {
160 // Skip special primvars that are handled separately
161 if (desc.name == HdTokens->points || desc.name == HdTokens->widths) {
162 continue;
163 }
164
165 const VtValue value = GetPrimvar(sceneDelegate, desc.name);
166 if (value.IsEmpty()) {
167 continue;
168 }
169
170 const ustring name(desc.name.GetString());
171
173 if (desc.role == HdPrimvarRoleTokens->textureCoordinate) {
174 std = ATTR_STD_UV;
175 }
176 else if (desc.name == HdTokens->displayColor &&
177 interpolation.first == HdInterpolationConstant)
178 {
179 if (value.IsHolding<VtVec3fArray>() && value.GetArraySize() == 1) {
180 const GfVec3f color = value.UncheckedGet<VtVec3fArray>()[0];
181 _instances[0]->set_color(make_float3(color[0], color[1], color[2]));
182 }
183 }
184
185 // Skip attributes that are not needed
186 if ((std != ATTR_STD_NONE && _geom->need_attribute(scene, std)) ||
187 _geom->need_attribute(scene, name))
188 {
189 ApplyPrimvars(_geom->attributes, name, value, interpolation.second, std);
190 }
191 }
192 }
193}
194
195void HdCyclesCurves::PopulateTopology(HdSceneDelegate *sceneDelegate)
196{
197 // Clear geometry before populating it again with updated topology
198 _geom->clear(true);
199
200 const HdBasisCurvesTopology topology = GetBasisCurvesTopology(sceneDelegate);
201
202 _geom->reserve_curves(topology.GetNumCurves(), topology.CalculateNeededNumberOfControlPoints());
203
204 const VtIntArray vertCounts = topology.GetCurveVertexCounts();
205
206 for (int curve = 0, key = 0; curve < topology.GetNumCurves(); ++curve) {
207 // Always reference shader at index zero, which is the primitive material
208 _geom->add_curve(key, 0);
209
210 key += vertCounts[curve];
211 }
212}
213
struct Scene Scene
HdCyclesCurves(const PXR_NS::SdfPath &rprimId, const PXR_NS::SdfPath &instancerId={})
PXR_NS::HdDirtyBits GetInitialDirtyBitsMask() const override
~HdCyclesCurves() override
HdCyclesGeometry(const PXR_NS::SdfPath &rprimId, const PXR_NS::SdfPath &instancerId)
Definition geometry.inl:22
PXR_NS::HdInterpolation GetPrimvarInterpolation(PXR_NS::HdSceneDelegate *sceneDelegate, const PXR_NS::TfToken &name) const
Definition geometry.inl:242
PXR_NS::HdDirtyBits GetInitialDirtyBitsMask() const override
Definition geometry.inl:48
ccl_device_forceinline float3 make_float3(const float x, const float y, const float z)
HDCYCLES_NAMESPACE_OPEN_SCOPE void ApplyPrimvars(AttributeSet &attributes, const ustring &name, VtValue value, AttributeElement elem, AttributeStandard std)
#define HDCYCLES_NAMESPACE_CLOSE_SCOPE
AttributeStandard
@ ATTR_STD_UV
@ ATTR_STD_NONE
@ ATTR_ELEMENT_CURVE_KEY
@ ATTR_ELEMENT_OBJECT
@ ATTR_ELEMENT_CURVE
const char * name
i
Definition text_draw.cc:230