Blender  V3.3
usd_reader_stage.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2021 Tangent Animation and. NVIDIA Corporation. All rights reserved. */
3 
4 #include "usd_reader_stage.h"
5 #include "usd_reader_camera.h"
6 #include "usd_reader_curve.h"
7 #include "usd_reader_light.h"
8 #include "usd_reader_mesh.h"
9 #include "usd_reader_nurbs.h"
10 #include "usd_reader_prim.h"
11 #include "usd_reader_volume.h"
12 #include "usd_reader_xform.h"
13 
14 #include <pxr/pxr.h>
15 #include <pxr/usd/usdGeom/camera.h>
16 #include <pxr/usd/usdGeom/curves.h>
17 #include <pxr/usd/usdGeom/mesh.h>
18 #include <pxr/usd/usdGeom/nurbsCurves.h>
19 #include <pxr/usd/usdGeom/scope.h>
20 #include <pxr/usd/usdGeom/xform.h>
21 
22 #if PXR_VERSION >= 2111
23 # include <pxr/usd/usdLux/boundableLightBase.h>
24 # include <pxr/usd/usdLux/nonboundableLightBase.h>
25 #else
26 # include <pxr/usd/usdLux/light.h>
27 #endif
28 
29 #include <iostream>
30 
31 #include "BLI_sort.hh"
32 #include "BLI_string.h"
33 
34 namespace blender::io::usd {
35 
37  const USDImportParams &params,
38  const ImportSettings &settings)
39  : stage_(stage), params_(params), settings_(settings)
40 {
41 }
42 
44 {
45  clear_readers();
46 }
47 
49 {
50  return stage_;
51 }
52 
54 {
55  if (params_.import_cameras && prim.IsA<pxr::UsdGeomCamera>()) {
56  return new USDCameraReader(prim, params_, settings_);
57  }
58  if (params_.import_curves && prim.IsA<pxr::UsdGeomBasisCurves>()) {
59  return new USDCurvesReader(prim, params_, settings_);
60  }
61  if (params_.import_curves && prim.IsA<pxr::UsdGeomNurbsCurves>()) {
62  return new USDNurbsReader(prim, params_, settings_);
63  }
64  if (params_.import_meshes && prim.IsA<pxr::UsdGeomMesh>()) {
65  return new USDMeshReader(prim, params_, settings_);
66  }
67 #if PXR_VERSION >= 2111
68  if (params_.import_lights && (prim.IsA<pxr::UsdLuxBoundableLightBase>() ||
69  prim.IsA<pxr::UsdLuxNonboundableLightBase>())) {
70 #else
71  if (params_.import_lights && prim.IsA<pxr::UsdLuxLight>()) {
72 #endif
73  return new USDLightReader(prim, params_, settings_);
74  }
75  if (params_.import_volumes && prim.IsA<pxr::UsdVolVolume>()) {
76  return new USDVolumeReader(prim, params_, settings_);
77  }
78  if (prim.IsA<pxr::UsdGeomImageable>()) {
79  return new USDXformReader(prim, params_, settings_);
80  }
81 
82  return nullptr;
83 }
84 
85 USDPrimReader *USDStageReader::create_reader(const pxr::UsdPrim &prim)
86 {
87  if (prim.IsA<pxr::UsdGeomCamera>()) {
88  return new USDCameraReader(prim, params_, settings_);
89  }
90  if (prim.IsA<pxr::UsdGeomBasisCurves>()) {
91  return new USDCurvesReader(prim, params_, settings_);
92  }
93  if (prim.IsA<pxr::UsdGeomNurbsCurves>()) {
94  return new USDNurbsReader(prim, params_, settings_);
95  }
96  if (prim.IsA<pxr::UsdGeomMesh>()) {
97  return new USDMeshReader(prim, params_, settings_);
98  }
99 #if PXR_VERSION >= 2111
100  if (prim.IsA<pxr::UsdLuxBoundableLightBase>() || prim.IsA<pxr::UsdLuxNonboundableLightBase>()) {
101 #else
102  if (prim.IsA<pxr::UsdLuxLight>()) {
103 #endif
104  return new USDLightReader(prim, params_, settings_);
105  }
106  if (prim.IsA<pxr::UsdVolVolume>()) {
107  return new USDVolumeReader(prim, params_, settings_);
108  }
109  if (prim.IsA<pxr::UsdGeomImageable>()) {
110  return new USDXformReader(prim, params_, settings_);
111  }
112  return nullptr;
113 }
114 
115 bool USDStageReader::include_by_visibility(const pxr::UsdGeomImageable &imageable) const
116 {
118  /* Invisible prims are allowed. */
119  return true;
120  }
121 
122  pxr::UsdAttribute visibility_attr = imageable.GetVisibilityAttr();
123 
124  if (!visibility_attr) {
125  /* No visibility attribute, so allow. */
126  return true;
127  }
128 
129  /* Include if the prim has an animating visibility attribute or is not invisible. */
130 
131  if (visibility_attr.ValueMightBeTimeVarying()) {
132  return true;
133  }
134 
135  pxr::TfToken visibility;
136  visibility_attr.Get(&visibility);
137  return visibility != pxr::UsdGeomTokens->invisible;
138 }
139 
140 bool USDStageReader::include_by_purpose(const pxr::UsdGeomImageable &imageable) const
141 {
143  /* The options allow any purpose, so we trivially include the prim. */
144  return true;
145  }
146 
147  pxr::UsdAttribute purpose_attr = imageable.GetPurposeAttr();
148 
149  if (!purpose_attr) {
150  /* No purpose attribute, so trivially include the prim. */
151  return true;
152  }
153 
154  pxr::TfToken purpose;
155  purpose_attr.Get(&purpose);
156 
157  if (purpose == pxr::UsdGeomTokens->guide) {
158  return params_.import_guide;
159  }
160  if (purpose == pxr::UsdGeomTokens->proxy) {
161  return params_.import_proxy;
162  }
163  if (purpose == pxr::UsdGeomTokens->render) {
164  return params_.import_render;
165  }
166 
167  return true;
168 }
169 
170 /* Determine if the given reader can use the parent of the encapsulated USD prim
171  * to compute the Blender object's transform. If so, the reader is appropriately
172  * flagged and the function returns true. Otherwise, the function returns false. */
173 static bool merge_with_parent(USDPrimReader *reader)
174 {
175  USDXformReader *xform_reader = dynamic_cast<USDXformReader *>(reader);
176 
177  if (!xform_reader) {
178  return false;
179  }
180 
181  /* Check if the Xform reader is already merged. */
182  if (xform_reader->use_parent_xform()) {
183  return false;
184  }
185 
186  /* Only merge if the parent is an Xform. */
187  if (!xform_reader->prim().GetParent().IsA<pxr::UsdGeomXform>()) {
188  return false;
189  }
190 
191  /* Don't merge Xform and Scope prims. */
192  if (xform_reader->prim().IsA<pxr::UsdGeomXform>() ||
193  xform_reader->prim().IsA<pxr::UsdGeomScope>()) {
194  return false;
195  }
196 
197  /* Don't merge if the prim has authored transform ops. */
198  if (xform_reader->prim_has_xform_ops()) {
199  return false;
200  }
201 
202  /* Flag the Xform reader as merged. */
203  xform_reader->set_use_parent_xform(true);
204 
205  return true;
206 }
207 
208 USDPrimReader *USDStageReader::collect_readers(Main *bmain, const pxr::UsdPrim &prim)
209 {
210  if (prim.IsA<pxr::UsdGeomImageable>()) {
211  pxr::UsdGeomImageable imageable(prim);
212 
213  if (!include_by_purpose(imageable)) {
214  return nullptr;
215  }
216 
217  if (!include_by_visibility(imageable)) {
218  return nullptr;
219  }
220  }
221 
222  pxr::Usd_PrimFlagsPredicate filter_predicate = pxr::UsdPrimDefaultPredicate;
223 
225  filter_predicate = pxr::UsdTraverseInstanceProxies(filter_predicate);
226  }
227 
228  pxr::UsdPrimSiblingRange children = prim.GetFilteredChildren(filter_predicate);
229 
230  std::vector<USDPrimReader *> child_readers;
231 
232  for (const auto &childPrim : children) {
233  if (USDPrimReader *child_reader = collect_readers(bmain, childPrim)) {
234  child_readers.push_back(child_reader);
235  }
236  }
237 
238  if (prim.IsPseudoRoot()) {
239  return nullptr;
240  }
241 
242  /* Check if we can merge an Xform with its child prim. */
243  if (child_readers.size() == 1) {
244 
245  USDPrimReader *child_reader = child_readers.front();
246 
247  if (merge_with_parent(child_reader)) {
248  return child_reader;
249  }
250  }
251 
252  USDPrimReader *reader = create_reader_if_allowed(prim);
253 
254  if (!reader) {
255  return nullptr;
256  }
257 
258  readers_.push_back(reader);
259  reader->incref();
260 
261  /* Set each child reader's parent. */
262  for (USDPrimReader *child_reader : child_readers) {
263  child_reader->parent(reader);
264  }
265 
266  return reader;
267 }
268 
270 {
271  if (!valid()) {
272  return;
273  }
274 
275  clear_readers();
276 
277  /* Iterate through the stage. */
278  pxr::UsdPrim root = stage_->GetPseudoRoot();
279 
280  std::string prim_path_mask(params_.prim_path_mask);
281 
282  if (!prim_path_mask.empty()) {
283  pxr::UsdPrim prim = stage_->GetPrimAtPath(pxr::SdfPath(prim_path_mask));
284  if (prim.IsValid()) {
285  root = prim;
286  }
287  else {
288  std::cerr << "WARNING: Prim Path Mask " << prim_path_mask
289  << " does not specify a valid prim.\n";
290  }
291  }
292 
293  stage_->SetInterpolationType(pxr::UsdInterpolationType::UsdInterpolationTypeHeld);
294  collect_readers(bmain, root);
295 }
296 
298 {
299  for (USDPrimReader *reader : readers_) {
300  if (!reader) {
301  continue;
302  }
303 
304  reader->decref();
305 
306  if (reader->refcount() == 0) {
307  delete reader;
308  }
309  }
310 
311  readers_.clear();
312 }
313 
315 {
317  readers_.begin(), readers_.end(), [](const USDPrimReader *a, const USDPrimReader *b) {
318  const char *na = a ? a->name().c_str() : "";
319  const char *nb = b ? b->name().c_str() : "";
320  return BLI_strcasecmp(na, nb) < 0;
321  });
322 }
323 
324 } // Namespace blender::io::usd
const pxr::UsdPrim & prim() const
std::vector< USDPrimReader * > readers_
USDPrimReader * create_reader(const pxr::UsdPrim &prim)
USDPrimReader * create_reader_if_allowed(const pxr::UsdPrim &prim)
void collect_readers(struct Main *bmain)
USDStageReader(pxr::UsdStageRefPtr stage, const USDImportParams &params, const ImportSettings &settings)
EvaluationStage stage
Definition: deg_eval.cc:89
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
static unsigned a[3]
Definition: RandGen.cpp:78
static bool merge_with_parent(USDPrimReader *reader)
void parallel_sort(RandomAccessIterator begin, RandomAccessIterator end)
Definition: BLI_sort.hh:21
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
Definition: BKE_main.h:121
char * prim_path_mask
Definition: usd.h:55
bool import_render
Definition: usd.h:61
bool import_visible_only
Definition: usd.h:62
bool import_volumes
Definition: usd.h:54
bool import_lights
Definition: usd.h:51
bool import_instance_proxies
Definition: usd.h:57
bool import_guide
Definition: usd.h:59
bool import_meshes
Definition: usd.h:53
bool import_cameras
Definition: usd.h:49
bool import_proxy
Definition: usd.h:60
bool import_curves
Definition: usd.h:50