forked from blender/blender
Support multimaterials on one mesh #44
@ -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);
|
||||
|
@ -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();
|
||||
|
||||
}
|
||||
|
||||
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 < = 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
|
||||
|
@ -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_;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user
The order is important here?
No