6 #include <pxr/usd/usdGeom/mesh.h>
7 #include <pxr/usd/usdShade/material.h>
8 #include <pxr/usd/usdShade/materialBindingAPI.h>
49 bool needsfree =
false;
52 if (
mesh ==
nullptr) {
105 void USDGenericMeshWriter::write_uv_maps(
const Mesh *
mesh, pxr::UsdGeomMesh usd_mesh)
110 for (
int layer_idx = 0; layer_idx < ldata->
totlayer; layer_idx++) {
120 pxr::TfToken primvar_name(pxr::TfMakeValidIdentifier(layer->
name));
121 pxr::UsdGeomPrimvar uv_coords_primvar = usd_mesh.CreatePrimvar(
122 primvar_name, pxr::SdfValueTypeNames->TexCoord2fArray, pxr::UsdGeomTokens->faceVarying);
125 pxr::VtArray<pxr::GfVec2f> uv_coords;
126 for (
int loop_idx = 0; loop_idx <
mesh->
totloop; loop_idx++) {
127 uv_coords.push_back(pxr::GfVec2f(mloopuv[loop_idx].uv));
130 if (!uv_coords_primvar.HasValue()) {
131 uv_coords_primvar.Set(uv_coords, pxr::UsdTimeCode::Default());
133 const pxr::UsdAttribute &uv_coords_attr = uv_coords_primvar.GetAttr();
134 usd_value_writer_.SetAttribute(uv_coords_attr, pxr::VtValue(uv_coords), timecode);
138 void USDGenericMeshWriter::write_mesh(HierarchyContext &
context,
Mesh *
mesh)
141 pxr::UsdTimeCode defaultTime = pxr::UsdTimeCode::Default();
145 pxr::UsdGeomMesh usd_mesh = pxr::UsdGeomMesh::Define(
stage,
usd_path);
148 USDMeshData usd_mesh_data;
149 get_geometry_data(
mesh, usd_mesh_data);
161 assign_materials(
context, usd_mesh, usd_mesh_data.face_groups);
167 pxr::UsdAttribute attr_points = usd_mesh.CreatePointsAttr(pxr::VtValue(),
true);
168 pxr::UsdAttribute attr_face_vertex_counts = usd_mesh.CreateFaceVertexCountsAttr(pxr::VtValue(),
170 pxr::UsdAttribute attr_face_vertex_indices = usd_mesh.CreateFaceVertexIndicesAttr(pxr::VtValue(),
173 if (!attr_points.HasValue()) {
176 attr_points.Set(usd_mesh_data.points, defaultTime);
177 attr_face_vertex_counts.Set(usd_mesh_data.face_vertex_counts, defaultTime);
178 attr_face_vertex_indices.Set(usd_mesh_data.face_indices, defaultTime);
181 usd_value_writer_.SetAttribute(attr_points, pxr::VtValue(usd_mesh_data.points), timecode);
183 attr_face_vertex_counts, pxr::VtValue(usd_mesh_data.face_vertex_counts), timecode);
185 attr_face_vertex_indices, pxr::VtValue(usd_mesh_data.face_indices), timecode);
187 if (!usd_mesh_data.crease_lengths.empty()) {
188 pxr::UsdAttribute attr_crease_lengths = usd_mesh.CreateCreaseLengthsAttr(pxr::VtValue(),
true);
189 pxr::UsdAttribute attr_crease_indices = usd_mesh.CreateCreaseIndicesAttr(pxr::VtValue(),
true);
190 pxr::UsdAttribute attr_crease_sharpness = usd_mesh.CreateCreaseSharpnessesAttr(pxr::VtValue(),
193 if (!attr_crease_lengths.HasValue()) {
194 attr_crease_lengths.Set(usd_mesh_data.crease_lengths, defaultTime);
195 attr_crease_indices.Set(usd_mesh_data.crease_vertex_indices, defaultTime);
196 attr_crease_sharpness.Set(usd_mesh_data.crease_sharpnesses, defaultTime);
200 attr_crease_lengths, pxr::VtValue(usd_mesh_data.crease_lengths), timecode);
202 attr_crease_indices, pxr::VtValue(usd_mesh_data.crease_vertex_indices), timecode);
204 attr_crease_sharpness, pxr::VtValue(usd_mesh_data.crease_sharpnesses), timecode);
207 if (!usd_mesh_data.corner_indices.empty() &&
208 usd_mesh_data.corner_indices.size() == usd_mesh_data.corner_sharpnesses.size()) {
209 pxr::UsdAttribute attr_corner_indices = usd_mesh.CreateCornerIndicesAttr(pxr::VtValue(),
true);
210 pxr::UsdAttribute attr_corner_sharpnesses = usd_mesh.CreateCornerSharpnessesAttr(
211 pxr::VtValue(),
true);
213 if (!attr_corner_indices.HasValue()) {
214 attr_corner_indices.Set(usd_mesh_data.corner_indices, defaultTime);
215 attr_corner_sharpnesses.Set(usd_mesh_data.corner_sharpnesses, defaultTime);
219 attr_corner_indices, pxr::VtValue(usd_mesh_data.corner_indices), timecode);
221 attr_corner_sharpnesses, pxr::VtValue(usd_mesh_data.crease_sharpnesses), timecode);
225 write_uv_maps(
mesh, usd_mesh);
228 write_normals(
mesh, usd_mesh);
230 write_surface_velocity(
mesh, usd_mesh);
237 usd_mesh.CreateSubdivisionSchemeAttr().Set(pxr::UsdGeomTokens->
none);
240 assign_materials(
context, usd_mesh, usd_mesh_data.face_groups);
250 usd_mesh_data.
points.push_back(pxr::GfVec3f(
verts[i].co));
258 bool construct_face_groups =
mesh->
totcol > 1;
268 for (
int j = 0; j < mpoly->
totloop; ++j, ++loop) {
272 if (construct_face_groups) {
280 const float factor = 1.0f / 255.0f;
284 for (
int edge_idx = 0, totedge =
mesh->
totedge; edge_idx < totedge; ++edge_idx, ++edge) {
285 if (edge->crease == 0) {
289 if (edge->crease == 255) {
290 sharpness = pxr::UsdGeomMesh::SHARPNESS_INFINITE;
293 sharpness =
static_cast<float>(edge->crease) * factor;
312 const float sharpness = creases[i];
314 if (sharpness != 0.0f) {
321 void USDGenericMeshWriter::get_geometry_data(
const Mesh *
mesh, USDMeshData &usd_mesh_data)
329 void USDGenericMeshWriter::assign_materials(
const HierarchyContext &
context,
330 pxr::UsdGeomMesh usd_mesh,
331 const MaterialFaceGroups &usd_face_groups)
333 if (
context.object->totcol == 0) {
340 bool mesh_material_bound =
false;
341 pxr::UsdShadeMaterialBindingAPI material_binding_api(usd_mesh.GetPrim());
342 for (
int mat_num = 0; mat_num <
context.object->totcol; mat_num++) {
349 material_binding_api.Bind(usd_material);
353 usd_mesh.CreateDoubleSidedAttr(
356 mesh_material_bound =
true;
360 if (!mesh_material_bound) {
362 usd_mesh.CreateDoubleSidedAttr(pxr::VtValue(
true));
365 if (!mesh_material_bound || usd_face_groups.size() < 2) {
373 for (
const MaterialFaceGroups::value_type &face_group : usd_face_groups) {
374 short material_number = face_group.first;
375 const pxr::VtIntArray &face_indices = face_group.second;
383 pxr::TfToken material_name = usd_material.GetPath().GetNameToken();
385 pxr::UsdGeomSubset usd_face_subset = material_binding_api.CreateMaterialBindSubset(
386 material_name, face_indices);
387 pxr::UsdShadeMaterialBindingAPI(usd_face_subset.GetPrim()).Bind(usd_material);
391 void USDGenericMeshWriter::write_normals(
const Mesh *
mesh, pxr::UsdGeomMesh usd_mesh)
396 pxr::VtVec3fArray loop_normals;
399 if (lnors !=
nullptr) {
401 for (
int loop_idx = 0, totloop =
mesh->
totloop; loop_idx < totloop; ++loop_idx) {
402 loop_normals.push_back(pxr::GfVec3f(lnors[loop_idx]));
410 for (
int poly_idx = 0, totpoly =
mesh->
totpoly; poly_idx < totpoly; ++poly_idx, ++mpoly) {
415 pxr::GfVec3f pxr_normal(face_normals[poly_idx]);
416 for (
int loop_idx = 0; loop_idx < mpoly->
totloop; ++loop_idx) {
417 loop_normals.push_back(pxr_normal);
422 for (
int loop_idx = 0; loop_idx < mpoly->
totloop; ++loop_idx, ++mloop) {
423 loop_normals.push_back(pxr::GfVec3f(vert_normals[mloop->
v]));
429 pxr::UsdAttribute attr_normals = usd_mesh.CreateNormalsAttr(pxr::VtValue(),
true);
430 if (!attr_normals.HasValue()) {
431 attr_normals.Set(loop_normals, pxr::UsdTimeCode::Default());
433 usd_value_writer_.SetAttribute(attr_normals, pxr::VtValue(loop_normals), timecode);
434 usd_mesh.SetNormalsInterpolation(pxr::UsdGeomTokens->faceVarying);
437 void USDGenericMeshWriter::write_surface_velocity(
const Mesh *
mesh, pxr::UsdGeomMesh usd_mesh)
444 if (velocity_layer ==
nullptr) {
448 const float(*velocities)[3] =
reinterpret_cast<float(*)[3]
>(velocity_layer->
data);
451 pxr::VtVec3fArray usd_velocities;
454 for (
int vertex_idx = 0, totvert =
mesh->
totvert; vertex_idx < totvert; ++vertex_idx) {
455 usd_velocities.push_back(pxr::GfVec3f(velocities[vertex_idx]));
459 usd_mesh.CreateVelocitiesAttr().Set(usd_velocities, timecode);
typedef float(TangentPoint)[2]
Generic geometry attributes built on CustomData.
struct CustomDataLayer * BKE_id_attribute_find(const struct ID *id, const char *name, int type, eAttrDomain domain)
CustomData interface, see also DNA_customdata_types.h.
void * CustomData_get_layer(const struct CustomData *data, int type)
void BKE_id_free(struct Main *bmain, void *idv)
General operations, lookup, etc. for materials.
struct Material * BKE_object_material_get(struct Object *ob, short act)
const float(* BKE_mesh_poly_normals_ensure(const struct Mesh *mesh))[3]
const float(* BKE_mesh_vertex_normals_ensure(const struct Mesh *mesh))[3]
General operations, lookup, etc. for blender objects.
struct Mesh * BKE_object_get_evaluated_mesh(const struct Object *object)
__forceinline bool none(const avxb &b)
ATTR_WARN_UNUSED_RESULT const BMVert * v
pxr::UsdShadeMaterial ensure_usd_material(const HierarchyContext &context, Material *material)
bool frame_has_been_written_
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_
const USDExporterContext usd_export_context_
USDGenericMeshWriter(const USDExporterContext &ctx)
virtual void do_write(HierarchyContext &context) override
virtual bool is_supported(const HierarchyContext *context) const override
virtual Mesh * get_export_mesh(Object *object_eval, bool &r_needsfree)=0
virtual void free_export_mesh(Mesh *mesh)
USDMeshWriter(const USDExporterContext &ctx)
virtual Mesh * get_export_mesh(Object *object_eval, bool &r_needsfree) override
static void get_loops_polys(const Mesh *mesh, USDMeshData &usd_mesh_data)
static void get_vert_creases(const Mesh *mesh, USDMeshData &usd_mesh_data)
static void get_vertices(const Mesh *mesh, USDMeshData &usd_mesh_data)
static void get_edge_creases(const Mesh *mesh, USDMeshData &usd_mesh_data)
enum eEvaluationMode evaluation_mode
bool visible_objects_only
const USDExportParams & export_params
const pxr::SdfPath usd_path
const pxr::UsdStageRefPtr stage
pxr::VtIntArray face_vertex_counts
pxr::VtIntArray crease_vertex_indices
pxr::VtIntArray face_indices
pxr::VtIntArray crease_lengths
pxr::VtFloatArray corner_sharpnesses
std::map< short, pxr::VtIntArray > face_groups
pxr::VtFloatArray crease_sharpnesses
pxr::VtIntArray corner_indices
pxr::VtArray< pxr::GfVec3f > points