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