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)
|
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);
|
||||||
|
@ -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();
|
||||||
|
|||||||
}
|
}
|
||||||
|
|
||||||
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 < = looptris[i];
|
const MLoopTri < = 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
|
||||||
|
@ -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_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user
The order is important here?
No