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)
{
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);
if (obj_data) {
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 &&
BLI_listbase_is_empty(&object->modifiers))
{
write_mesh((Mesh *)object->data);
write_submeshes((Mesh *)object->data);
}
else {
Mesh *mesh = BKE_object_to_mesh(nullptr, object, false);
if (mesh) {
write_mesh(mesh);
write_submeshes(mesh);
}
BKE_object_to_mesh_clear(object);
}
write_transform();
write_materials();
Review

The order is important here?

The order is important here?
Review

No

No
}
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()
@ -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;
if (key == pxr::HdTokens->points) {
ret = vertices_;
}
else if (key == pxr::HdTokens->normals) {
ret = normals_;
ret = submesh(id).normals;
}
else if (key == pxr::HdPrimvarRoleTokens->textureCoordinate) {
ret = uvs_;
ret = submesh(id).uvs;
}
return ret;
}
@ -130,11 +131,11 @@ pxr::HdPrimvarDescriptorVector MeshData::primvar_descriptors(
}
}
else if (interpolation == pxr::HdInterpolationFaceVarying) {
if (!normals_.empty()) {
if (!submeshes_[0].normals.empty()) {
primvars.emplace_back(
pxr::HdTokens->normals, interpolation, pxr::HdPrimvarRoleTokens->normal);
}
if (!uvs_.empty()) {
if (!submeshes_[0].uvs.empty()) {
primvars.emplace_back(pxr::HdPrimvarRoleTokens->textureCoordinate,
interpolation,
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
{
char name[16];
@ -273,12 +196,13 @@ const MeshData::SubMesh &MeshData::submesh(pxr::SdfPath const &id) const
return submeshes_[index];
}
void MeshData::update_sub_meshes(Mesh *mesh)
void MeshData::write_submeshes(Mesh *mesh)
{
int sub_meshes_prev_count = submeshes_.size();
submeshes_.clear();
vertices_.clear();
/* Insert base submeshes */
submeshes_.clear();
int mat_count = BKE_object_material_count_eval((Object *)id);
for (int i = 0; i < std::max(mat_count, 1); ++i) {
SubMesh sm;
@ -291,15 +215,32 @@ void MeshData::update_sub_meshes(Mesh *mesh)
const int *looptri_polys = BKE_mesh_runtime_looptri_polys_ensure(mesh);
blender::Span<int> corner_verts = mesh->corner_verts();
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) {
int mat_ind = material_indices ? material_indices[looptri_polys[i]] : 0;
const MLoopTri &lt = looptris[i];
SubMesh &sm = submeshes_[mat_ind];
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[1]]);
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 */
@ -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 */
auto &render_index = scene_delegate_->GetRenderIndex();
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

View File

@ -17,6 +17,8 @@ class MeshData : public ObjectData {
struct SubMesh {
pxr::VtIntArray face_vertex_counts;
pxr::VtIntArray face_vertex_indices;
pxr::VtVec3fArray normals;
pxr::VtVec2fArray uvs;
int mat_index = 0;
MaterialData *mat_data = nullptr;
};
@ -29,7 +31,7 @@ class MeshData : public ObjectData {
void remove() 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;
pxr::HdMeshTopology mesh_topology(pxr::SdfPath const &id) const;
@ -42,17 +44,12 @@ class MeshData : public ObjectData {
pxr::HdCullStyle cull_style = pxr::HdCullStyleBackUnlessDoubleSided;
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;
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::VtVec2fArray uvs_;
pxr::VtVec3fArray normals_;
std::vector<SubMesh> submeshes_;
};