Blender  V3.3
usd_writer_abstract.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2019 Blender Foundation. All rights reserved. */
3 #include "usd_writer_abstract.h"
5 #include "usd_writer_material.h"
6 
7 #include <pxr/base/tf/stringUtils.h>
8 
9 #include "BKE_customdata.h"
10 #include "BLI_assert.h"
11 
12 #include "DNA_mesh_types.h"
13 
14 /* TfToken objects are not cheap to construct, so we do it once. */
15 namespace usdtokens {
16 /* Materials */
17 static const pxr::TfToken diffuse_color("diffuseColor", pxr::TfToken::Immortal);
18 static const pxr::TfToken metallic("metallic", pxr::TfToken::Immortal);
19 static const pxr::TfToken preview_shader("previewShader", pxr::TfToken::Immortal);
20 static const pxr::TfToken preview_surface("UsdPreviewSurface", pxr::TfToken::Immortal);
21 static const pxr::TfToken roughness("roughness", pxr::TfToken::Immortal);
22 static const pxr::TfToken surface("surface", pxr::TfToken::Immortal);
23 } // namespace usdtokens
24 
25 static std::string get_mesh_active_uvlayer_name(const Object *ob)
26 {
27  if (!ob || ob->type != OB_MESH || !ob->data) {
28  return "";
29  }
30 
31  const Mesh *me = static_cast<Mesh *>(ob->data);
32 
33  const char *name = CustomData_get_active_layer_name(&me->ldata, CD_MLOOPUV);
34 
35  return name ? name : "";
36 }
37 
38 namespace blender::io::usd {
39 
41  : usd_export_context_(usd_export_context), frame_has_been_written_(false), is_animated_(false)
42 {
43 }
44 
45 bool USDAbstractWriter::is_supported(const HierarchyContext * /*context*/) const
46 {
47  return true;
48 }
49 
51 {
53 }
54 
56 {
57  if (is_animated_) {
59  }
60  /* By using the default timecode USD won't even write a single `timeSample` for non-animated
61  * data. Instead, it writes it as non-timesampled. */
62  static pxr::UsdTimeCode default_timecode = pxr::UsdTimeCode::Default();
63  return default_timecode;
64 }
65 
67 {
71  }
72  else if (!is_animated_) {
73  /* A frame has already been written, and without animation one frame is enough. */
74  return;
75  }
76 
78 
80 }
81 
82 const pxr::SdfPath &USDAbstractWriter::usd_path() const
83 {
85 }
86 
89 {
90  static pxr::SdfPath material_library_path("/_materials");
91  pxr::UsdStageRefPtr stage = usd_export_context_.stage;
92 
93  /* Construct the material. */
94  pxr::TfToken material_name(usd_export_context_.hierarchy_iterator->get_id_name(&material->id));
95  pxr::SdfPath usd_path = material_library_path.AppendChild(material_name);
96  pxr::UsdShadeMaterial usd_material = pxr::UsdShadeMaterial::Get(stage, usd_path);
97  if (usd_material) {
98  return usd_material;
99  }
100  usd_material = pxr::UsdShadeMaterial::Define(stage, usd_path);
101 
102  if (material->use_nodes && this->usd_export_context_.export_params.generate_preview_surface) {
103  std::string active_uv = get_mesh_active_uvlayer_name(context.object);
105  this->usd_export_context_, material, usd_material, active_uv);
106  }
107  else {
108  create_usd_viewport_material(this->usd_export_context_, material, usd_material);
109  }
110 
111  return usd_material;
112 }
113 
115  const pxr::UsdTimeCode timecode,
116  pxr::UsdGeomImageable &usd_geometry)
117 {
118  pxr::UsdAttribute attr_visibility = usd_geometry.CreateVisibilityAttr(pxr::VtValue(), true);
119 
120  const bool is_visible = context.is_object_visible(
122  const pxr::TfToken visibility = is_visible ? pxr::UsdGeomTokens->inherited :
123  pxr::UsdGeomTokens->invisible;
124 
125  usd_value_writer_.SetAttribute(attr_visibility, pxr::VtValue(visibility), timecode);
126 }
127 
128 bool USDAbstractWriter::mark_as_instance(const HierarchyContext &context, const pxr::UsdPrim &prim)
129 {
130  BLI_assert(context.is_instance());
131 
132  if (context.export_path == context.original_export_path) {
133  printf("USD ref error: export path is reference path: %s\n", context.export_path.c_str());
134  BLI_assert_msg(0, "USD reference error");
135  return false;
136  }
137 
138  pxr::SdfPath ref_path(context.original_export_path);
139  if (!prim.GetReferences().AddInternalReference(ref_path)) {
140  /* See this URL for a description for why referencing may fail"
141  * https://graphics.pixar.com/usd/docs/api/class_usd_references.html#Usd_Failing_References
142  */
143  printf("USD Export warning: unable to add reference from %s to %s, not instancing object\n",
144  context.export_path.c_str(),
145  context.original_export_path.c_str());
146  return false;
147  }
148 
149  return true;
150 }
151 
152 } // namespace blender::io::usd
CustomData interface, see also DNA_customdata_types.h.
const char * CustomData_get_active_layer_name(const struct CustomData *data, int type)
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition: BLI_assert.h:53
@ CD_MLOOPUV
@ OB_MESH
virtual std::string get_id_name(const ID *id) const
virtual bool check_is_animated(const HierarchyContext &context) const
pxr::UsdShadeMaterial ensure_usd_material(const HierarchyContext &context, Material *material)
virtual void do_write(HierarchyContext &context)=0
const pxr::SdfPath & usd_path() const
void write_visibility(const HierarchyContext &context, const pxr::UsdTimeCode timecode, pxr::UsdGeomImageable &usd_geometry)
virtual bool mark_as_instance(const HierarchyContext &context, const pxr::UsdPrim &prim)
pxr::UsdTimeCode get_export_time_code() const
pxr::UsdUtilsSparseValueWriter usd_value_writer_
USDAbstractWriter(const USDExporterContext &usd_export_context)
virtual void write(HierarchyContext &context) override
virtual bool is_supported(const HierarchyContext *context) const
const USDExporterContext usd_export_context_
const pxr::UsdTimeCode & get_export_time_code() const
EvaluationStage stage
Definition: deg_eval.cc:89
Material material
void create_usd_preview_surface_material(const USDExporterContext &usd_export_context, Material *material, pxr::UsdShadeMaterial &usd_material, const std::string &default_uv)
void create_usd_viewport_material(const USDExporterContext &usd_export_context, Material *material, pxr::UsdShadeMaterial &usd_material)
static const pxr::TfToken preview_shader("previewShader", pxr::TfToken::Immortal)
static const pxr::TfToken surface("surface", pxr::TfToken::Immortal)
static const pxr::TfToken roughness("roughness", pxr::TfToken::Immortal)
static const pxr::TfToken metallic("metallic", pxr::TfToken::Immortal)
static const pxr::TfToken diffuse_color("diffuseColor", pxr::TfToken::Immortal)
static const pxr::TfToken preview_surface("UsdPreviewSurface", pxr::TfToken::Immortal)
CustomData ldata
void * data
bool export_animation
Definition: usd.h:26
enum eEvaluationMode evaluation_mode
Definition: usd.h:34
const USDHierarchyIterator * hierarchy_iterator
static std::string get_mesh_active_uvlayer_name(const Object *ob)