Blender V5.0
geometry.inl
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/geometry.h"
7#include "hydra/instancer.h"
8#include "hydra/material.h"
9#include "hydra/session.h"
10#include "scene/geometry.h"
11#include "scene/object.h"
12#include "scene/scene.h"
13#include "util/hash.h"
14
15#include <pxr/imaging/hd/sceneDelegate.h>
18
19extern Transform convert_transform(const GfMatrix4d &matrix);
20
21template<typename Base, typename CyclesBase>
23#if PXR_VERSION < 2102
24 ,
25 const SdfPath &instancerId
26#endif
27 )
28 : Base(rprimId
29#if PXR_VERSION < 2102
31 ,
32 instancerId
33#endif
34 ),
35 _geomTransform(1.0)
36{
37}
38
39template<typename Base, typename CyclesBase>
41 HdDirtyBits *dirtyBits)
42{
43 TF_UNUSED(reprToken);
44 TF_UNUSED(dirtyBits);
45}
46
47template<typename Base, typename CyclesBase>
49{
50 return HdChangeTracker::DirtyPrimID | HdChangeTracker::DirtyTransform |
51 HdChangeTracker::DirtyMaterialId | HdChangeTracker::DirtyVisibility |
52 HdChangeTracker::DirtyInstancer;
53}
54
55template<typename Base, typename CyclesBase>
57{
58 return bits;
59}
60
61template<typename Base, typename CyclesBase>
62void HdCyclesGeometry<Base, CyclesBase>::Sync(HdSceneDelegate *sceneDelegate,
63 HdRenderParam *renderParam,
64 HdDirtyBits *dirtyBits,
65 const TfToken &reprToken)
66{
67 TF_UNUSED(reprToken);
68
69 if (*dirtyBits == HdChangeTracker::Clean) {
70 return;
71 }
72
73 Initialize(renderParam);
74
75#if PXR_VERSION >= 2102
76 Base::_UpdateInstancer(sceneDelegate, dirtyBits);
77 HdInstancer::_SyncInstancerAndParents(sceneDelegate->GetRenderIndex(), Base::GetInstancerId());
78#endif
79 Base::_UpdateVisibility(sceneDelegate, dirtyBits);
80
81 const SceneLock lock(renderParam);
82
83 if (*dirtyBits & HdChangeTracker::DirtyMaterialId) {
84#if HD_API_VERSION >= 37 && PXR_VERSION >= 2105
85 Base::SetMaterialId(sceneDelegate->GetMaterialId(Base::GetId()));
86#else
87 Base::_SetMaterialId(sceneDelegate->GetRenderIndex().GetChangeTracker(),
88 sceneDelegate->GetMaterialId(Base::GetId()));
89#endif
90
91 const auto *const material = static_cast<const HdCyclesMaterial *>(
92 sceneDelegate->GetRenderIndex().GetSprim(HdPrimTypeTokens->material,
93 Base::GetMaterialId()));
94
95 array<Node *> usedShaders(1);
96 if (material && material->GetCyclesShader()) {
97 usedShaders[0] = material->GetCyclesShader();
98 }
99 else {
100 usedShaders[0] = lock.scene->default_surface;
101 }
102
103 for (Node *shader : usedShaders) {
104 static_cast<Shader *>(shader)->tag_used(lock.scene);
105 }
106
107 _geom->set_used_shaders(usedShaders);
108 }
109
110 const SdfPath &id = Base::GetId();
111
112 if (HdChangeTracker::IsPrimIdDirty(*dirtyBits, id)) {
113 // This needs to be corrected in the AOV
114 _instances[0]->set_pass_id(Base::GetPrimId() + 1);
115 }
116
117 if (HdChangeTracker::IsTransformDirty(*dirtyBits, id)) {
118 _geomTransform = sceneDelegate->GetTransform(id);
119 }
120
121 if (HdChangeTracker::IsTransformDirty(*dirtyBits, id) ||
122 HdChangeTracker::IsInstancerDirty(*dirtyBits, id))
123 {
124 auto *const instancer = static_cast<HdCyclesInstancer *>(
125 sceneDelegate->GetRenderIndex().GetInstancer(Base::GetInstancerId()));
126
127 // Make sure the first object attribute is the instanceId
128 assert(_instances[0]->attributes.size() >= 1 &&
129 _instances[0]->attributes.front().name() == HdAovTokens->instanceId.GetString());
130
131 VtMatrix4dArray transforms;
132 if (instancer) {
133 transforms = instancer->ComputeInstanceTransforms(id);
134 _instances[0]->attributes.front() = ParamValue(HdAovTokens->instanceId.GetString(), +0.0f);
135 }
136 else {
137 // Default to a single instance with an identity transform
138 transforms.push_back(GfMatrix4d(1.0));
139 _instances[0]->attributes.front() = ParamValue(HdAovTokens->instanceId.GetString(), -1.0f);
140 }
141
142 const size_t oldSize = _instances.size();
143 const size_t newSize = transforms.size();
144
145 // Resize instance list
146 for (size_t i = newSize; i < oldSize; ++i) {
147 lock.scene->delete_node(_instances[i]);
148 }
149 _instances.resize(newSize);
150 for (size_t i = oldSize; i < newSize; ++i) {
151 _instances[i] = lock.scene->create_node<Object>();
152 InitializeInstance(static_cast<int>(i));
153 }
154
155 // Update transforms of all instances
156 for (size_t i = 0; i < transforms.size(); ++i) {
157 const float metersPerUnit =
158 static_cast<HdCyclesSession *>(renderParam)->GetStageMetersPerUnit();
159
160 const Transform tfm = transform_scale(make_float3(metersPerUnit)) *
161 convert_transform(_geomTransform * transforms[i]);
162 _instances[i]->set_tfm(tfm);
163 }
164 }
165
166 if (HdChangeTracker::IsVisibilityDirty(*dirtyBits, id)) {
167 for (Object *instance : _instances) {
168 instance->set_visibility(Base::IsVisible() ? ~0 : 0);
169 }
170 }
171
172 // Must happen after material ID update, so that attribute decisions can be made
173 // based on it (e.g. check whether an attribute is actually needed)
174 bool rebuild = false;
175 Populate(sceneDelegate, *dirtyBits, rebuild);
176
177 if (_geom->is_modified() || rebuild) {
178 _geom->tag_update(lock.scene, rebuild);
179 }
180
181 for (Object *instance : _instances) {
182 instance->tag_update(lock.scene);
183 }
184
185 *dirtyBits = HdChangeTracker::Clean;
186}
187
188template<typename Base, typename CyclesBase>
189void HdCyclesGeometry<Base, CyclesBase>::Finalize(HdRenderParam *renderParam)
190{
191 if (!_geom && _instances.empty()) {
192 return;
193 }
194
195 const SceneLock lock(renderParam);
196 const bool keep_nodes = static_cast<const HdCyclesSession *>(renderParam)->keep_nodes;
197
198 if (!keep_nodes) {
199 lock.scene->delete_node(_geom);
200 }
201 _geom = nullptr;
202
203 if (!keep_nodes) {
204 lock.scene->delete_nodes(set<Object *>(_instances.begin(), _instances.end()));
205 }
206 _instances.clear();
207 _instances.shrink_to_fit();
208}
209
210template<typename Base, typename CyclesBase>
211void HdCyclesGeometry<Base, CyclesBase>::Initialize(HdRenderParam *renderParam)
212{
213 if (_geom) {
214 return;
215 }
216
217 const SceneLock lock(renderParam);
218
219 // Create geometry
220 _geom = lock.scene->create_node<CyclesBase>();
221 _geom->name = Base::GetId().GetString();
222
223 // Create default instance
224 _instances.push_back(lock.scene->create_node<Object>());
225 InitializeInstance(0);
226}
227
228template<typename Base, typename CyclesBase>
229void HdCyclesGeometry<Base, CyclesBase>::InitializeInstance(int index)
230{
231 Object *instance = _instances[index];
232 instance->set_geometry(_geom);
233
234 instance->attributes.emplace_back(HdAovTokens->instanceId.GetString(),
235 _instances.size() == 1 ? -1.0f : static_cast<float>(index));
236
237 instance->set_color(make_float3(0.8f, 0.8f, 0.8f));
238 instance->set_random_id(hash_uint2(hash_string(_geom->name.c_str()), index));
239}
240
241template<typename Base, typename CyclesBase>
243 HdSceneDelegate *sceneDelegate, const TfToken &name) const
244{
245 for (int i = 0; i < HdInterpolationCount; ++i) {
246 for (const HdPrimvarDescriptor &desc :
247 Base::GetPrimvarDescriptors(sceneDelegate, static_cast<HdInterpolation>(i)))
248 {
249 if (desc.name == name) {
250 return static_cast<HdInterpolation>(i);
251 }
252 }
253 }
254
255 return HdInterpolationCount;
256}
257
volatile int lock
static void Initialize(const btConvexTemplate &a, const btConvexTemplate &b, btGjkEpaSolver3::sResults &results, MinkowskiDiff< btConvexTemplate > &shape)
Definition btGjkEpa3.h:878
HdCyclesGeometry(const PXR_NS::SdfPath &rprimId, const PXR_NS::SdfPath &instancerId)
Definition geometry.inl:22
PXR_NS::HdDirtyBits _PropagateDirtyBits(PXR_NS::HdDirtyBits bits) const override
Definition geometry.inl:56
void Finalize(PXR_NS::HdRenderParam *renderParam) override
Definition geometry.inl:189
void _InitRepr(const PXR_NS::TfToken &reprToken, PXR_NS::HdDirtyBits *dirtyBits) override
Definition geometry.inl:40
PXR_NS::HdInterpolation GetPrimvarInterpolation(PXR_NS::HdSceneDelegate *sceneDelegate, const PXR_NS::TfToken &name) const
Definition geometry.inl:242
virtual void Populate(PXR_NS::HdSceneDelegate *sceneDelegate, PXR_NS::HdDirtyBits dirtyBits, bool &rebuild)=0
CyclesBase * _geom
PXR_NS::HdDirtyBits GetInitialDirtyBitsMask() const override
Definition geometry.inl:48
void Sync(PXR_NS::HdSceneDelegate *sceneDelegate, PXR_NS::HdRenderParam *renderParam, PXR_NS::HdDirtyBits *dirtyBits, const PXR_NS::TfToken &reprToken) override
Definition geometry.inl:62
std::vector< CCL_NS::Object * > _instances
ccl_device_forceinline float3 make_float3(const float x, const float y, const float z)
HDCYCLES_NAMESPACE_OPEN_SCOPE Transform convert_transform(const GfMatrix4d &matrix)
#define assert(assertion)
static uint hash_string(const char *str)
Definition hash.h:637
ccl_device_inline uint hash_uint2(const uint kx, const uint ky)
Definition hash.h:139
#define HDCYCLES_NAMESPACE_CLOSE_SCOPE
const char * name
vector< ParamValue > attributes
i
Definition text_draw.cc:230
ccl_device_inline Transform transform_scale(const float3 s)
Definition transform.h:280