Blender  V3.3
usd_reader_xform.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Adapted from the Blender Alembic importer implementation.
3  * Modifications Copyright 2021 Tangent Animation. All rights reserved. */
4 
5 #include "usd_reader_xform.h"
6 
7 #include "BKE_constraint.h"
8 #include "BKE_lib_id.h"
9 #include "BKE_library.h"
10 #include "BKE_modifier.h"
11 #include "BKE_object.h"
12 
13 #include "BLI_math_geom.h"
14 #include "BLI_string.h"
15 #include "BLI_utildefines.h"
16 
17 #include "DNA_cachefile_types.h"
18 #include "DNA_constraint_types.h"
19 #include "DNA_modifier_types.h"
20 #include "DNA_object_types.h"
21 #include "DNA_space_types.h" /* for FILE_MAX */
22 
23 #include <pxr/base/gf/math.h>
24 #include <pxr/base/gf/matrix4f.h>
25 
26 #include <pxr/usd/usdGeom/xform.h>
27 
28 namespace blender::io::usd {
29 
30 void USDXformReader::create_object(Main *bmain, const double /* motionSampleTime */)
31 {
33  object_->empty_drawsize = 0.1f;
34  object_->data = nullptr;
35 }
36 
37 void USDXformReader::read_object_data(Main * /* bmain */, const double motionSampleTime)
38 {
39  bool is_constant;
40  float transform_from_usd[4][4];
41 
42  read_matrix(transform_from_usd, motionSampleTime, import_params_.scale, &is_constant);
43 
44  if (!is_constant) {
48 
49  std::string prim_path = use_parent_xform_ ? prim_.GetParent().GetPath().GetAsString() :
50  prim_path_;
51 
52  BLI_strncpy(data->object_path, prim_path.c_str(), FILE_MAX);
53 
54  data->cache_file = settings_->cache_file;
55  id_us_plus(&data->cache_file->id);
56  }
57 
58  BKE_object_apply_mat4(object_, transform_from_usd, true, false);
59 }
60 
61 void USDXformReader::read_matrix(float r_mat[4][4] /* local matrix */,
62  const float time,
63  const float scale,
64  bool *r_is_constant)
65 {
66  if (r_is_constant) {
67  *r_is_constant = true;
68  }
69 
70  unit_m4(r_mat);
71 
72  pxr::UsdGeomXformable xformable;
73 
74  if (use_parent_xform_) {
75  xformable = pxr::UsdGeomXformable(prim_.GetParent());
76  }
77  else {
78  xformable = pxr::UsdGeomXformable(prim_);
79  }
80 
81  if (!xformable) {
82  /* This might happen if the prim is a Scope. */
83  return;
84  }
85 
86  if (r_is_constant) {
87  *r_is_constant = !xformable.TransformMightBeTimeVarying();
88  }
89 
90  pxr::GfMatrix4d usd_local_xf;
91  bool reset_xform_stack;
92  xformable.GetLocalTransformation(&usd_local_xf, &reset_xform_stack, time);
93 
94  /* Convert the result to a float matrix. */
95  pxr::GfMatrix4f mat4f = pxr::GfMatrix4f(usd_local_xf);
96  mat4f.Get(r_mat);
97 
98  /* Apply global scaling and rotation only to root objects, parenting
99  * will propagate it. */
100  if ((scale != 1.0 || settings_->do_convert_mat) && is_root_xform_) {
101 
102  if (scale != 1.0f) {
103  float scale_mat[4][4];
104  scale_m4_fl(scale_mat, scale);
105  mul_m4_m4m4(r_mat, scale_mat, r_mat);
106  }
107 
108  if (settings_->do_convert_mat) {
109  mul_m4_m4m4(r_mat, settings_->conversion_mat, r_mat);
110  }
111  }
112 }
113 
115 {
116  pxr::UsdGeomXformable xformable(prim_);
117 
118  if (!xformable) {
119  /* This might happen if the prim is a Scope. */
120  return false;
121  }
122 
123  bool reset_xform_stack = false;
124 
125  return !xformable.GetOrderedXformOps(&reset_xform_stack).empty();
126 }
127 
129 {
130  if (!prim_.IsValid()) {
131  return false;
132  }
133 
134  if (prim_.IsInPrototype()) {
135  /* We don't consider prototypes to be root prims,
136  * because we never want to apply global scaling
137  * or rotations to the prototypes themselves. */
138  return false;
139  }
140 
141  if (prim_.IsA<pxr::UsdGeomXformable>()) {
142  /* If this prim doesn't have an ancestor that's a
143  * UsdGeomXformable, then it's a root prim. Note
144  * that it's not sufficient to only check the immediate
145  * parent prim, since the immediate parent could be a
146  * UsdGeomScope that has an xformable ancestor. */
147  pxr::UsdPrim cur_parent = prim_.GetParent();
148 
149  if (use_parent_xform_) {
150  cur_parent = cur_parent.GetParent();
151  }
152 
153  while (cur_parent && !cur_parent.IsPseudoRoot()) {
154  if (cur_parent.IsA<pxr::UsdGeomXformable>()) {
155  return false;
156  }
157  cur_parent = cur_parent.GetParent();
158  }
159 
160  /* We didn't find an xformable ancestor. */
161  return true;
162  }
163 
164  return false;
165 }
166 
167 } // namespace blender::io::usd
struct bConstraint * BKE_constraint_add_for_object(struct Object *ob, const char *name, short type)
Definition: constraint.c:5870
void id_us_plus(struct ID *id)
Definition: lib_id.c:305
General operations, lookup, etc. for blender objects.
void BKE_object_apply_mat4(struct Object *ob, const float mat[4][4], bool use_compat, bool use_parent)
Definition: object.cc:3575
struct Object * BKE_object_add_only_object(struct Main *bmain, int type, const char *name) ATTR_RETURNS_NONNULL
Definition: object.cc:2241
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
Definition: math_matrix.c:259
void unit_m4(float m[4][4])
Definition: rct.c:1090
void scale_m4_fl(float R[4][4], float scale)
Definition: math_matrix.c:2297
#define FILE_MAX
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
@ CONSTRAINT_TYPE_TRANSFORM_CACHE
Object is a sort of wrapper for general info.
@ OB_EMPTY
const std::string & prim_path() const
const ImportSettings * settings_
const USDImportParams & import_params_
void create_object(Main *bmain, double motionSampleTime) override
void read_object_data(Main *bmain, double motionSampleTime) override
void read_matrix(float r_mat[4][4], float time, float scale, bool *r_is_constant)
double time
GREAL mat4f[4][4]
Matrix 4D, row ordered.
Definition: BKE_main.h:121
float empty_drawsize
void * data
float scale
Definition: usd.h:42