Support multimaterials on one mesh #44

Merged
Bogdan Nagirniak merged 11 commits from BLEN-417 into hydra-render 2023-05-24 07:07:39 +02:00
3 changed files with 70 additions and 97 deletions
Showing only changes of commit 49896dfa07 - Show all commits

View File

@ -46,6 +46,10 @@ pxr::GfMatrix4d BlenderSceneDelegate::GetTransform(pxr::SdfPath const &id)
pxr::VtValue BlenderSceneDelegate::Get(pxr::SdfPath const &id, pxr::TfToken const &key) pxr::VtValue BlenderSceneDelegate::Get(pxr::SdfPath const &id, pxr::TfToken const &key)
{ {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s, %s", id.GetText(), key.GetText()); CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s, %s", id.GetText(), key.GetText());
MeshData *m_data = mesh_data(id);
if (m_data) {
return m_data->get_data(id, key);
}
ObjectData *obj_data = object_data(id); ObjectData *obj_data = object_data(id);
if (obj_data) { if (obj_data) {
return obj_data->get_data(key); return obj_data->get_data(key);

View File

@ -29,22 +29,23 @@ void MeshData::init()
if (object->type == OB_MESH && object->mode == OB_MODE_OBJECT && if (object->type == OB_MESH && object->mode == OB_MODE_OBJECT &&
BLI_listbase_is_empty(&object->modifiers)) BLI_listbase_is_empty(&object->modifiers))
{ {
write_mesh((Mesh *)object->data); write_submeshes((Mesh *)object->data);
} }
else { else {
Mesh *mesh = BKE_object_to_mesh(nullptr, object, false); Mesh *mesh = BKE_object_to_mesh(nullptr, object, false);
if (mesh) { if (mesh) {
write_mesh(mesh); write_submeshes(mesh);
} }
BKE_object_to_mesh_clear(object); BKE_object_to_mesh_clear(object);
} }
write_transform(); write_transform();
write_materials();
Review

The order is important here?

The order is important here?
Review

No

No
} }
void MeshData::insert() void MeshData::insert()
{ {
/* Empty, because insertion of rprims happen in update_sub_meshes() */ /* Empty, because insertion of rprims happen in write_submeshes() */
} }
void MeshData::remove() void MeshData::remove()
@ -83,17 +84,17 @@ void MeshData::update()
} }
} }
pxr::VtValue MeshData::get_data(pxr::TfToken const &key) const pxr::VtValue MeshData::get_data(pxr::SdfPath const &id, pxr::TfToken const &key) const
{ {
pxr::VtValue ret; pxr::VtValue ret;
if (key == pxr::HdTokens->points) { if (key == pxr::HdTokens->points) {
ret = vertices_; ret = vertices_;
} }
else if (key == pxr::HdTokens->normals) { else if (key == pxr::HdTokens->normals) {
ret = normals_; ret = submesh(id).normals;
} }
else if (key == pxr::HdPrimvarRoleTokens->textureCoordinate) { else if (key == pxr::HdPrimvarRoleTokens->textureCoordinate) {
ret = uvs_; ret = submesh(id).uvs;
} }
return ret; return ret;
} }
@ -130,11 +131,11 @@ pxr::HdPrimvarDescriptorVector MeshData::primvar_descriptors(
} }
} }
else if (interpolation == pxr::HdInterpolationFaceVarying) { else if (interpolation == pxr::HdInterpolationFaceVarying) {
if (!normals_.empty()) { if (!submeshes_[0].normals.empty()) {
primvars.emplace_back( primvars.emplace_back(
pxr::HdTokens->normals, interpolation, pxr::HdPrimvarRoleTokens->normal); pxr::HdTokens->normals, interpolation, pxr::HdPrimvarRoleTokens->normal);
} }
if (!uvs_.empty()) { if (!submeshes_[0].uvs.empty()) {
primvars.emplace_back(pxr::HdPrimvarRoleTokens->textureCoordinate, primvars.emplace_back(pxr::HdPrimvarRoleTokens->textureCoordinate,
interpolation, interpolation,
pxr::HdPrimvarRoleTokens->textureCoordinate); pxr::HdPrimvarRoleTokens->textureCoordinate);
@ -181,84 +182,6 @@ void MeshData::available_materials(std::set<pxr::SdfPath> &paths) const
} }
} }
void MeshData::write_mesh(Mesh *mesh)
{
vertices_.clear();
normals_.clear();
uvs_.clear();
update_sub_meshes(mesh);
if (submeshes_.empty()) {
return;
}
/* vertices */
vertices_.reserve(mesh->totvert);
blender::Span<blender::float3> verts = mesh->vert_positions();
for (blender::float3 v : verts) {
vertices_.push_back(pxr::GfVec3f(v.x, v.y, v.z));
}
write_normals(mesh);
write_uv_maps(mesh);
write_materials();
}
void MeshData::write_materials()
{
Object *object = (Object *)id;
for (int i = 0; i < submeshes_.size(); ++i) {
SubMesh &m = submeshes_[i];
if (m.face_vertex_counts.empty()) {
continue;
}
Material *mat = BKE_object_material_get_eval(object, m.mat_index);
if (!mat) {
m.mat_data = nullptr;
continue;
}
pxr::SdfPath p_id = scene_delegate_->material_prim_id(mat);
m.mat_data = scene_delegate_->material_data(p_id);
if (!m.mat_data) {
scene_delegate_->materials_[p_id] = std::make_unique<MaterialData>(
scene_delegate_, mat, p_id);
m.mat_data = scene_delegate_->material_data(p_id);
m.mat_data->init();
m.mat_data->insert();
}
}
}
void MeshData::write_uv_maps(Mesh *mesh)
{
blender::Span<MLoopTri> loopTris = mesh->looptris();
const float(*luvs)[2] = (float(*)[2])CustomData_get_layer(&mesh->ldata, CD_PROP_FLOAT2);
if (luvs) {
uvs_.reserve(loopTris.size() * 3);
for (MLoopTri lt : loopTris) {
uvs_.push_back(pxr::GfVec2f(luvs[lt.tri[0]]));
uvs_.push_back(pxr::GfVec2f(luvs[lt.tri[1]]));
uvs_.push_back(pxr::GfVec2f(luvs[lt.tri[2]]));
}
}
}
void MeshData::write_normals(Mesh *mesh)
{
BKE_mesh_calc_normals_split(mesh);
blender::Span<MLoopTri> loopTris = mesh->looptris();
const float(*lnors)[3] = (float(*)[3])CustomData_get_layer(&mesh->ldata, CD_NORMAL);
if (lnors) {
normals_.reserve(loopTris.size() * 3);
for (MLoopTri lt : loopTris) {
normals_.push_back(pxr::GfVec3f(lnors[lt.tri[0]]));
normals_.push_back(pxr::GfVec3f(lnors[lt.tri[1]]));
normals_.push_back(pxr::GfVec3f(lnors[lt.tri[2]]));
}
}
}
pxr::SdfPath MeshData::submesh_prim_id(int index) const pxr::SdfPath MeshData::submesh_prim_id(int index) const
{ {
char name[16]; char name[16];
@ -273,12 +196,13 @@ const MeshData::SubMesh &MeshData::submesh(pxr::SdfPath const &id) const
return submeshes_[index]; return submeshes_[index];
} }
void MeshData::update_sub_meshes(Mesh *mesh) void MeshData::write_submeshes(Mesh *mesh)
{ {
int sub_meshes_prev_count = submeshes_.size(); int sub_meshes_prev_count = submeshes_.size();
submeshes_.clear();
vertices_.clear();
/* Insert base submeshes */ /* Insert base submeshes */
submeshes_.clear();
int mat_count = BKE_object_material_count_eval((Object *)id); int mat_count = BKE_object_material_count_eval((Object *)id);
for (int i = 0; i < std::max(mat_count, 1); ++i) { for (int i = 0; i < std::max(mat_count, 1); ++i) {
SubMesh sm; SubMesh sm;
@ -291,15 +215,32 @@ void MeshData::update_sub_meshes(Mesh *mesh)
const int *looptri_polys = BKE_mesh_runtime_looptri_polys_ensure(mesh); const int *looptri_polys = BKE_mesh_runtime_looptri_polys_ensure(mesh);
blender::Span<int> corner_verts = mesh->corner_verts(); blender::Span<int> corner_verts = mesh->corner_verts();
blender::Span<MLoopTri> looptris = mesh->looptris(); blender::Span<MLoopTri> looptris = mesh->looptris();
BKE_mesh_calc_normals_split(mesh);
const float(*lnors)[3] = (float(*)[3])CustomData_get_layer(&mesh->ldata, CD_NORMAL);
const float(*luvs)[2] = (float(*)[2])CustomData_get_layer(&mesh->ldata, CD_PROP_FLOAT2);
for (size_t i = 0; i < looptris.size(); ++i) { for (size_t i = 0; i < looptris.size(); ++i) {
int mat_ind = material_indices ? material_indices[looptri_polys[i]] : 0; int mat_ind = material_indices ? material_indices[looptri_polys[i]] : 0;
const MLoopTri &lt = looptris[i]; const MLoopTri &lt = looptris[i];
SubMesh &sm = submeshes_[mat_ind]; SubMesh &sm = submeshes_[mat_ind];
sm.face_vertex_counts.push_back(3); sm.face_vertex_counts.push_back(3);
sm.face_vertex_indices.push_back(corner_verts[lt.tri[0]]); sm.face_vertex_indices.push_back(corner_verts[lt.tri[0]]);
sm.face_vertex_indices.push_back(corner_verts[lt.tri[1]]); sm.face_vertex_indices.push_back(corner_verts[lt.tri[1]]);
sm.face_vertex_indices.push_back(corner_verts[lt.tri[2]]); sm.face_vertex_indices.push_back(corner_verts[lt.tri[2]]);
if (lnors) {
sm.normals.push_back(pxr::GfVec3f(lnors[lt.tri[0]]));
sm.normals.push_back(pxr::GfVec3f(lnors[lt.tri[1]]));
sm.normals.push_back(pxr::GfVec3f(lnors[lt.tri[2]]));
}
if (luvs) {
sm.uvs.push_back(pxr::GfVec2f(luvs[lt.tri[0]]));
sm.uvs.push_back(pxr::GfVec2f(luvs[lt.tri[1]]));
sm.uvs.push_back(pxr::GfVec2f(luvs[lt.tri[2]]));
}
} }
/* Remove submeshes without faces */ /* Remove submeshes without faces */
@ -312,6 +253,15 @@ void MeshData::update_sub_meshes(Mesh *mesh)
} }
} }
if (!submeshes_.empty()) {
/* vertices */
vertices_.reserve(mesh->totvert);
blender::Span<blender::float3> verts = mesh->vert_positions();
for (blender::float3 v : verts) {
vertices_.push_back(pxr::GfVec3f(v.x, v.y, v.z));
}
}
/* Update prims in render index */ /* Update prims in render index */
auto &render_index = scene_delegate_->GetRenderIndex(); auto &render_index = scene_delegate_->GetRenderIndex();
int i; int i;
@ -332,4 +282,26 @@ void MeshData::update_sub_meshes(Mesh *mesh)
} }
} }
void MeshData::write_materials()
{
Object *object = (Object *)id;
for (int i = 0; i < submeshes_.size(); ++i) {
SubMesh &m = submeshes_[i];
Material *mat = BKE_object_material_get_eval(object, m.mat_index + 1);
if (!mat) {
m.mat_data = nullptr;
continue;
}
pxr::SdfPath p_id = scene_delegate_->material_prim_id(mat);
m.mat_data = scene_delegate_->material_data(p_id);
if (!m.mat_data) {
scene_delegate_->materials_[p_id] = std::make_unique<MaterialData>(
scene_delegate_, mat, p_id);
m.mat_data = scene_delegate_->material_data(p_id);
m.mat_data->init();
m.mat_data->insert();
}
}
}
} // namespace blender::render::hydra } // namespace blender::render::hydra

View File

@ -17,6 +17,8 @@ class MeshData : public ObjectData {
struct SubMesh { struct SubMesh {
pxr::VtIntArray face_vertex_counts; pxr::VtIntArray face_vertex_counts;
pxr::VtIntArray face_vertex_indices; pxr::VtIntArray face_vertex_indices;
pxr::VtVec3fArray normals;
pxr::VtVec2fArray uvs;
int mat_index = 0; int mat_index = 0;
MaterialData *mat_data = nullptr; MaterialData *mat_data = nullptr;
}; };
@ -29,7 +31,7 @@ class MeshData : public ObjectData {
void remove() override; void remove() override;
void update() override; void update() override;
pxr::VtValue get_data(pxr::TfToken const &key) const override; pxr::VtValue get_data(pxr::SdfPath const &id, pxr::TfToken const &key) const;
bool update_visibility() override; bool update_visibility() override;
pxr::HdMeshTopology mesh_topology(pxr::SdfPath const &id) const; pxr::HdMeshTopology mesh_topology(pxr::SdfPath const &id) const;
@ -42,17 +44,12 @@ class MeshData : public ObjectData {
pxr::HdCullStyle cull_style = pxr::HdCullStyleBackUnlessDoubleSided; pxr::HdCullStyle cull_style = pxr::HdCullStyleBackUnlessDoubleSided;
private: private:
void write_mesh(Mesh *mesh);
void write_materials();
void write_uv_maps(Mesh *mesh);
void write_normals(Mesh *mesh);
pxr::SdfPath submesh_prim_id(int index) const; pxr::SdfPath submesh_prim_id(int index) const;
const SubMesh &submesh(pxr::SdfPath const &id) const; const SubMesh &submesh(pxr::SdfPath const &id) const;
void update_sub_meshes(Mesh *mesh); void write_submeshes(Mesh *mesh);
void write_materials();
pxr::VtVec3fArray vertices_; pxr::VtVec3fArray vertices_;
pxr::VtVec2fArray uvs_;
pxr::VtVec3fArray normals_;
std::vector<SubMesh> submeshes_; std::vector<SubMesh> submeshes_;
}; };