5#include <pxr/base/gf/vec2f.h>
6#include <pxr/base/tf/staticTokens.h>
7#include <pxr/imaging/hd/tokens.h>
25static const pxr::TfToken
st(
"st", pxr::TfToken::Immortal);
30 pxr::SdfPath
const &prim_id)
42 write_submeshes(mesh);
72 pxr::HdDirtyBits bits = pxr::HdChangeTracker::Clean;
75 bits |= pxr::HdChangeTracker::DirtyMaterialId | pxr::HdChangeTracker::DirtyDoubleSided;
79 bits |= pxr::HdChangeTracker::DirtyTransform;
82 if (bits == pxr::HdChangeTracker::Clean) {
86 for (
int i = 0; i < submeshes_.size(); ++i) {
87 scene_delegate_->GetRenderIndex().GetChangeTracker().MarkRprimDirty(submesh_prim_id(i), bits);
94 return pxr::VtValue();
99 if (key == pxr::HdTokens->normals) {
100 return pxr::VtValue(submesh(
id).normals);
103 return pxr::VtValue(submesh(
id).uvs);
105 if (key == pxr::HdTokens->points) {
106 return pxr::VtValue(submesh(
id).vertices);
114 const SubMesh &sm = submesh(
id);
116 return pxr::SdfPath();
123 for (
auto &sm : submeshes_) {
124 if (sm.mat_data && !sm.mat_data->prim_id.IsEmpty()) {
125 paths.add(sm.mat_data->prim_id);
132 const SubMesh &sm = submesh(
id);
133 return pxr::HdMeshTopology(pxr::PxOsdOpenSubdivTokens->none,
134 pxr::HdTokens->rightHanded,
140 pxr::HdInterpolation interpolation)
const
142 pxr::HdPrimvarDescriptorVector primvars;
143 if (interpolation == pxr::HdInterpolationVertex) {
144 primvars.emplace_back(pxr::HdTokens->points, interpolation, pxr::HdPrimvarRoleTokens->point);
146 else if (interpolation == pxr::HdInterpolationFaceVarying) {
147 if (!submeshes_[0].normals.empty()) {
148 primvars.emplace_back(
149 pxr::HdTokens->normals, interpolation, pxr::HdPrimvarRoleTokens->normal);
151 if (!submeshes_[0].uvs.empty()) {
152 primvars.emplace_back(
153 usdtokens::st, interpolation, pxr::HdPrimvarRoleTokens->textureCoordinate);
161 const SubMesh &sm = submesh(
id);
165 return pxr::HdCullStyle::HdCullStyleNothing;
170 const SubMesh &sm = submesh(
id);
179 for (
int i = 0; i < submeshes_.size(); ++i) {
180 if (submeshes_[i].mat_data == mat_data) {
183 pxr::HdChangeTracker::DirtyDoubleSided | pxr::HdChangeTracker::DirtyCullStyle);
191 pxr::SdfPathVector
ret;
192 for (
int i = 0; i < submeshes_.size(); ++i) {
193 ret.push_back(submesh_prim_id(i));
201 for (
int i = 0; i < submeshes_.size(); ++i) {
209pxr::SdfPath MeshData::submesh_prim_id(
int index)
const
213 return prim_id.AppendElementString(name);
216const MeshData::SubMesh &MeshData::submesh(pxr::SdfPath
const &
id)
const
219 sscanf(
id.GetName().c_str(),
"SM_%d", &index);
220 return submeshes_[index];
231 static_assert(std::is_trivial_v<T>);
237 switch (mesh.normals_domain()) {
251 const bool copy_all_verts,
255 if (copy_all_verts) {
269 triangles.foreach_index_optimized<
int>(
GrainSize(1024), [&](
const int src,
const int dst) {
270 dst_data[dst] = src_data[tri_faces[src]];
280 triangles.foreach_index_optimized<
int>(
GrainSize(1024), [&](
const int src,
const int dst) {
281 const int3 &tri = corner_tris[src];
282 dst_data[dst * 3 + 0] = src_data[tri[0]];
283 dst_data[dst * 3 + 1] = src_data[tri[1]];
284 dst_data[dst * 3 + 2] = src_data[tri[2]];
302 const bool copy_all_verts = triangles.size() == corner_tris.
size() &&
303 mesh.verts_no_face().count == 0;
307 if (copy_all_verts) {
312 dst_verts_num = vert_positions.
size();
317 verts.reserve(triangles.size());
318 triangles.foreach_index([&](
const int src,
const int dst) {
319 const int3 &tri = corner_tris[src];
324 dst_verts_num =
verts.size();
339 switch (normals.first) {
341 triangles.foreach_index(
GrainSize(1024), [&](
const int src,
const int dst) {
342 std::fill_n(&dst_normals[dst * 3], 3, src_normals[tri_faces[src]]);
346 triangles.foreach_index(
GrainSize(1024), [&](
const int src,
const int dst) {
347 const int3 &tri = corner_tris[src];
348 dst_normals[dst * 3 + 0] = src_normals[corner_verts[tri[0]]];
349 dst_normals[dst * 3 + 1] = src_normals[corner_verts[tri[1]]];
350 dst_normals[dst * 3 + 2] = src_normals[corner_verts[tri[2]]];
365void MeshData::write_submeshes(
const Mesh *mesh)
368 submeshes_.reinitialize(mat_count > 0 ? mat_count : 1);
369 for (
const int i : submeshes_.index_range()) {
370 submeshes_[i].mat_index = i;
373 const Span<float3> vert_positions = mesh->vert_positions();
374 const Span<int> corner_verts = mesh->corner_verts();
375 const Span<int3> corner_tris = mesh->corner_tris();
376 const Span<int> tri_faces = mesh->corner_tri_faces();
377 const std::pair<bke::MeshNormalDomain, Span<float3>> normals =
get_mesh_normals(*mesh);
381 const VArraySpan material_indices = *attributes.lookup<
int>(
"material_index",
384 if (material_indices.is_empty()) {
397 IndexMaskMemory memory;
398 Array<IndexMask> triangles_by_material(submeshes_.size());
399 const int max_index = std::max(mat_count - 1, 0);
403 [&](
const int i) { return std::clamp(material_indices[tri_faces[i]], 0, max_index); },
404 triangles_by_material);
407 for (const int i : range) {
415 triangles_by_material[i],
421 submeshes_.remove_if([](
const SubMesh &submesh) {
return submesh.face_vertex_counts.empty(); });
424void MeshData::update_prims()
426 auto &render_index = scene_delegate_->GetRenderIndex();
428 for (i = 0; i < submeshes_.size(); ++i) {
429 pxr::SdfPath p = submesh_prim_id(i);
430 if (i < submeshes_count_) {
431 render_index.GetChangeTracker().MarkRprimDirty(p, pxr::HdChangeTracker::AllDirty);
435 render_index.InsertRprim(pxr::HdPrimTypeTokens->mesh, scene_delegate_, p);
439 for (; i < submeshes_count_; ++i) {
440 render_index.RemoveRprim(submesh_prim_id(i));
441 ID_LOG(1,
"Remove %d", i);
443 submeshes_count_ = submeshes_.size();
CustomData interface, see also DNA_customdata_types.h.
const char * CustomData_get_active_layer_name(const CustomData *data, eCustomDataType type)
General operations, lookup, etc. for materials.
int BKE_object_material_count_eval(const struct Object *ob)
struct Material * BKE_object_material_get_eval(struct Object *ob, short act)
void BKE_object_to_mesh_clear(Object *object)
Mesh * BKE_object_to_mesh(Depsgraph *depsgraph, Object *object, bool preserve_all_data_layers)
#define BLI_assert_unreachable()
#define SNPRINTF(dst, format,...)
T * resize(size_t newsize)
constexpr MutableSpan< NewT > cast() const
constexpr int64_t size() const
constexpr IndexRange index_range() const
constexpr bool is_empty() const
static void from_groups(const IndexMask &universe, IndexMaskMemory &memory, Fn &&get_group_index, MutableSpan< IndexMask > r_masks)
HydraSceneDelegate * scene_delegate_
pxr::HdCullStyle cull_style() const
pxr::HdMeshTopology topology(pxr::SdfPath const &id) const
void write_materials() override
pxr::VtValue get_data(pxr::TfToken const &key) const override
pxr::SdfPathVector submesh_paths() const
pxr::HdCullStyle cull_style(pxr::SdfPath const &id) const
void update_double_sided(MaterialData *mat_data)
void available_materials(Set< pxr::SdfPath > &paths) const override
pxr::HdPrimvarDescriptorVector primvar_descriptors(pxr::HdInterpolation interpolation) const
bool double_sided(pxr::SdfPath const &id) const
MeshData(HydraSceneDelegate *scene_delegate, const Object *object, pxr::SdfPath const &prim_id)
virtual pxr::SdfPath material_id() const
MaterialData * get_or_create_material(const Material *mat)
virtual void write_transform()
#define ID_LOG(level, msg,...)
#define ID_LOGN(level, msg,...)
void copy(const GVArray &src, GMutableSpan dst, int64_t grain_size=4096)
void gather(const GVArray &src, const IndexMask &indices, GMutableSpan dst, int64_t grain_size=4096)
void vert_tris_from_corner_tris(Span< int > corner_verts, Span< int3 > corner_tris, MutableSpan< int3 > vert_tris)
static const pxr::TfToken st("st", pxr::TfToken::Immortal)
static std::pair< bke::MeshNormalDomain, Span< float3 > > get_mesh_normals(const Mesh &mesh)
static void resize_uninitialized(pxr::VtArray< T > &array, const int new_size)
void gather_vert_data(const Span< int > verts, const bool copy_all_verts, const Span< T > src_data, MutableSpan< T > dst_data)
static void copy_submesh(const Mesh &mesh, const Span< float3 > vert_positions, const Span< int > corner_verts, const Span< int3 > corner_tris, const Span< int > tri_faces, const std::pair< bke::MeshNormalDomain, Span< float3 > > normals, const Span< float2 > uv_map, const IndexMask &triangles, MeshData::SubMesh &sm)
void gather_face_data(const Span< int > tri_faces, const IndexMask &triangles, const Span< T > src_data, MutableSpan< T > dst_data)
void gather_corner_data(const Span< int3 > corner_tris, const IndexMask &triangles, const Span< T > src_data, MutableSpan< T > dst_data)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
pxr::VtVec3fArray normals
pxr::VtVec3fArray vertices
pxr::VtIntArray face_vertex_counts
pxr::VtIntArray face_vertex_indices