forked from blender/blender
Support multimaterials on one mesh #44
@ -23,7 +23,7 @@ pxr::HdMeshTopology BlenderSceneDelegate::GetMeshTopology(pxr::SdfPath const &id
|
||||
{
|
||||
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", id.GetText());
|
||||
MeshData *m_data = mesh_data(id);
|
||||
return m_data->mesh_topology();
|
||||
return m_data->mesh_topology(id);
|
||||
}
|
||||
|
||||
pxr::GfMatrix4d BlenderSceneDelegate::GetTransform(pxr::SdfPath const &id)
|
||||
@ -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);
|
||||
@ -93,7 +97,7 @@ pxr::HdPrimvarDescriptorVector BlenderSceneDelegate::GetPrimvarDescriptors(
|
||||
pxr::SdfPath BlenderSceneDelegate::GetMaterialId(pxr::SdfPath const &rprim_id)
|
||||
{
|
||||
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", rprim_id.GetText());
|
||||
return mesh_data(rprim_id)->material_id();
|
||||
return mesh_data(rprim_id)->material_id(rprim_id);
|
||||
}
|
||||
|
||||
pxr::VtValue BlenderSceneDelegate::GetMaterialResource(pxr::SdfPath const &id)
|
||||
@ -122,7 +126,7 @@ bool BlenderSceneDelegate::GetVisible(pxr::SdfPath const &id)
|
||||
bool BlenderSceneDelegate::GetDoubleSided(pxr::SdfPath const &id)
|
||||
{
|
||||
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", id.GetText());
|
||||
return mesh_data(id)->double_sided();
|
||||
return mesh_data(id)->double_sided(id);
|
||||
}
|
||||
|
||||
pxr::HdCullStyle BlenderSceneDelegate::GetCullStyle(pxr::SdfPath const &id)
|
||||
@ -134,7 +138,7 @@ pxr::HdCullStyle BlenderSceneDelegate::GetCullStyle(pxr::SdfPath const &id)
|
||||
pxr::SdfPath BlenderSceneDelegate::GetInstancerId(pxr::SdfPath const &prim_id)
|
||||
{
|
||||
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", prim_id.GetText());
|
||||
InstancerData *i_data = instancer_data(prim_id.GetParentPath());
|
||||
InstancerData *i_data = instancer_data(prim_id, true);
|
||||
if (i_data) {
|
||||
return i_data->prim_id;
|
||||
}
|
||||
@ -240,11 +244,12 @@ pxr::SdfPath BlenderSceneDelegate::world_prim_id() const
|
||||
|
||||
ObjectData *BlenderSceneDelegate::object_data(pxr::SdfPath const &id) const
|
||||
{
|
||||
auto it = objects_.find(id);
|
||||
pxr::SdfPath p_id = (id.GetName().find("SM_") == 0) ? id.GetParentPath() : id;
|
||||
auto it = objects_.find(p_id);
|
||||
if (it != objects_.end()) {
|
||||
return it->second.get();
|
||||
}
|
||||
InstancerData *i_data = instancer_data(id, true);
|
||||
InstancerData *i_data = instancer_data(p_id, true);
|
||||
if (i_data) {
|
||||
return i_data->object_data(id);
|
||||
}
|
||||
@ -382,7 +387,6 @@ void BlenderSceneDelegate::check_updates()
|
||||
data.only_updated = true;
|
||||
ITER_BEGIN (DEG_iterator_ids_begin, DEG_iterator_ids_next, DEG_iterator_ids_end, &data, ID *, id)
|
||||
{
|
||||
|
||||
CLOG_INFO(LOG_RENDER_HYDRA_SCENE,
|
||||
2,
|
||||
"Update: %s [%s]",
|
||||
@ -516,12 +520,8 @@ void BlenderSceneDelegate::remove_unused_objects()
|
||||
std::set<pxr::SdfPath> available_materials;
|
||||
for (auto &it : objects_) {
|
||||
MeshData *m_data = dynamic_cast<MeshData *>(it.second.get());
|
||||
if (!m_data) {
|
||||
continue;
|
||||
}
|
||||
pxr::SdfPath mat_id = m_data->material_id();
|
||||
if (!mat_id.IsEmpty()) {
|
||||
available_materials.insert(mat_id);
|
||||
if (m_data) {
|
||||
m_data->available_materials(available_materials);
|
||||
}
|
||||
}
|
||||
for (auto &it : instancers_) {
|
||||
|
@ -36,7 +36,7 @@ bool InstancerData::is_supported(Object *object)
|
||||
void InstancerData::init()
|
||||
{
|
||||
ID_LOG(2, "");
|
||||
set_instances();
|
||||
write_instances();
|
||||
}
|
||||
|
||||
void InstancerData::insert()
|
||||
@ -68,7 +68,7 @@ void InstancerData::update()
|
||||
(object->data && ((ID *)object->data)->recalc & ID_RECALC_GEOMETRY) ||
|
||||
id->recalc & ID_RECALC_TRANSFORM)
|
||||
{
|
||||
set_instances();
|
||||
write_instances();
|
||||
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkInstancerDirty(
|
||||
prim_id, pxr::HdChangeTracker::AllDirty);
|
||||
}
|
||||
@ -92,8 +92,9 @@ bool InstancerData::update_visibility()
|
||||
change_tracker.MarkInstancerDirty(prim_id, pxr::HdChangeTracker::DirtyVisibility);
|
||||
for (auto &it : mesh_instances_) {
|
||||
it.second.data->visible = visible;
|
||||
change_tracker.MarkRprimDirty(it.second.data->prim_id,
|
||||
pxr::HdChangeTracker::DirtyVisibility);
|
||||
for (auto &p : it.second.data->submesh_paths()) {
|
||||
change_tracker.MarkRprimDirty(p, pxr::HdChangeTracker::DirtyVisibility);
|
||||
}
|
||||
}
|
||||
char name[16];
|
||||
for (auto &it : light_instances_) {
|
||||
@ -109,9 +110,9 @@ bool InstancerData::update_visibility()
|
||||
|
||||
pxr::GfMatrix4d InstancerData::get_transform(pxr::SdfPath const &id) const
|
||||
{
|
||||
if (id.GetPathElementCount() == 4) {
|
||||
const auto &inst = light_instances_.find(id.GetParentPath())->second;
|
||||
return inst.transforms[light_prim_id_index(id)];
|
||||
LightInstance *l_inst = light_instance(id);
|
||||
if (l_inst) {
|
||||
return l_inst->transforms[light_prim_id_index(id)];
|
||||
}
|
||||
|
||||
/* Mesh instance transform must be identity */
|
||||
@ -131,18 +132,18 @@ pxr::HdPrimvarDescriptorVector InstancerData::primvar_descriptors(
|
||||
|
||||
pxr::VtIntArray InstancerData::indices(pxr::SdfPath const &id) const
|
||||
{
|
||||
return mesh_instances_.find(id)->second.indices;
|
||||
return mesh_instance(id)->indices;
|
||||
}
|
||||
|
||||
ObjectData *InstancerData::object_data(pxr::SdfPath const &id) const
|
||||
{
|
||||
auto m_it = mesh_instances_.find(id);
|
||||
if (m_it != mesh_instances_.end()) {
|
||||
return m_it->second.data.get();
|
||||
MeshInstance *m_inst = mesh_instance(id);
|
||||
if (m_inst) {
|
||||
return m_inst->data.get();
|
||||
}
|
||||
auto l_it = light_instances_.find(id.GetParentPath());
|
||||
if (l_it != light_instances_.end()) {
|
||||
return l_it->second.data.get();
|
||||
LightInstance *l_inst = light_instance(id);
|
||||
if (l_inst) {
|
||||
return l_inst->data.get();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@ -151,7 +152,9 @@ pxr::SdfPathVector InstancerData::prototypes() const
|
||||
{
|
||||
pxr::SdfPathVector paths;
|
||||
for (auto &it : mesh_instances_) {
|
||||
paths.push_back(it.first);
|
||||
for (auto &p : it.second.data->submesh_paths()) {
|
||||
paths.push_back(p);
|
||||
}
|
||||
}
|
||||
return paths;
|
||||
}
|
||||
@ -159,25 +162,25 @@ pxr::SdfPathVector InstancerData::prototypes() const
|
||||
void InstancerData::check_update(Object *object)
|
||||
{
|
||||
pxr::SdfPath path = object_prim_id(object);
|
||||
auto m_it = mesh_instances_.find(path);
|
||||
if (m_it != mesh_instances_.end()) {
|
||||
m_it->second.data->update();
|
||||
MeshInstance *m_inst = mesh_instance(path);
|
||||
if (m_inst) {
|
||||
m_inst->data->update();
|
||||
|
||||
if (m_it->second.data->id->recalc & ID_RECALC_TRANSFORM) {
|
||||
set_instances();
|
||||
if (m_inst->data->id->recalc & ID_RECALC_TRANSFORM) {
|
||||
write_instances();
|
||||
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkInstancerDirty(
|
||||
prim_id, pxr::HdChangeTracker::AllDirty);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
auto l_it = light_instances_.find(path);
|
||||
if (l_it != light_instances_.end()) {
|
||||
Object *obj = (Object *)l_it->second.data->id;
|
||||
LightInstance *l_inst = light_instance(path);
|
||||
if (l_inst) {
|
||||
Object *obj = (Object *)l_inst->data->id;
|
||||
if (obj->id.recalc & (ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY) ||
|
||||
((ID *)obj->data)->recalc & ID_RECALC_GEOMETRY)
|
||||
{
|
||||
set_instances();
|
||||
write_instances();
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -196,7 +199,7 @@ void InstancerData::check_remove(std::set<std::string> &available_objects)
|
||||
ret = true;
|
||||
}
|
||||
if (ret) {
|
||||
set_instances();
|
||||
write_instances();
|
||||
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkInstancerDirty(
|
||||
prim_id, pxr::HdChangeTracker::AllDirty);
|
||||
}
|
||||
@ -216,16 +219,13 @@ void InstancerData::check_remove(std::set<std::string> &available_objects)
|
||||
void InstancerData::available_materials(std::set<pxr::SdfPath> &paths) const
|
||||
{
|
||||
for (auto &it : mesh_instances_) {
|
||||
pxr::SdfPath mat_id = ((MeshData *)it.second.data.get())->material_id();
|
||||
if (!mat_id.IsEmpty()) {
|
||||
paths.insert(mat_id);
|
||||
}
|
||||
((MeshData *)it.second.data.get())->available_materials(paths);
|
||||
}
|
||||
}
|
||||
|
||||
void InstancerData::update_as_parent()
|
||||
{
|
||||
set_instances();
|
||||
write_instances();
|
||||
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkInstancerDirty(
|
||||
prim_id, pxr::HdChangeTracker::AllDirty);
|
||||
}
|
||||
@ -259,7 +259,7 @@ int InstancerData::light_prim_id_index(pxr::SdfPath const &id) const
|
||||
return index;
|
||||
}
|
||||
|
||||
void InstancerData::set_instances()
|
||||
void InstancerData::write_instances()
|
||||
{
|
||||
mesh_transforms_.clear();
|
||||
for (auto &it : mesh_instances_) {
|
||||
@ -279,31 +279,23 @@ void InstancerData::set_instances()
|
||||
|
||||
pxr::SdfPath p_id = object_prim_id(ob);
|
||||
if (ob->type == OB_LAMP) {
|
||||
LightInstance *inst;
|
||||
auto it = light_instances_.find(p_id);
|
||||
if (it == light_instances_.end()) {
|
||||
LightInstance *inst = light_instance(p_id);
|
||||
if (!inst) {
|
||||
inst = &light_instances_[p_id];
|
||||
inst->data = std::make_unique<LightData>(scene_delegate_, ob, p_id);
|
||||
inst->data->init();
|
||||
}
|
||||
else {
|
||||
inst = &it->second;
|
||||
}
|
||||
ID_LOG(2, "Light %s %d", inst->data->id->name, inst->transforms.size());
|
||||
inst->transforms.push_back(gf_matrix_from_transform(dupli->mat));
|
||||
}
|
||||
else {
|
||||
MeshInstance *inst;
|
||||
auto it = mesh_instances_.find(p_id);
|
||||
if (it == mesh_instances_.end()) {
|
||||
MeshInstance *inst = mesh_instance(p_id);
|
||||
if (!inst) {
|
||||
inst = &mesh_instances_[p_id];
|
||||
inst->data = std::make_unique<MeshData>(scene_delegate_, ob, p_id);
|
||||
inst->data->init();
|
||||
inst->data->insert();
|
||||
}
|
||||
else {
|
||||
inst = &it->second;
|
||||
}
|
||||
ID_LOG(2, "Mesh %s %d", inst->data->id->name, mesh_transforms_.size());
|
||||
inst->indices.push_back(mesh_transforms_.size());
|
||||
mesh_transforms_.push_back(gf_matrix_from_transform(dupli->mat));
|
||||
@ -386,4 +378,22 @@ void InstancerData::update_light_instance(LightInstance &inst)
|
||||
}
|
||||
}
|
||||
|
||||
InstancerData::MeshInstance *InstancerData::mesh_instance(pxr::SdfPath const &id) const
|
||||
{
|
||||
auto it = mesh_instances_.find(id.GetPathElementCount() == 4 ? id.GetParentPath() : id);
|
||||
if (it == mesh_instances_.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
return const_cast<MeshInstance *>(&it->second);
|
||||
}
|
||||
|
||||
InstancerData::LightInstance *InstancerData::light_instance(pxr::SdfPath const &id) const
|
||||
{
|
||||
auto it = light_instances_.find(id.GetPathElementCount() == 4 ? id.GetParentPath() : id);
|
||||
if (it == light_instances_.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
return const_cast<LightInstance *>(&it->second);
|
||||
}
|
||||
|
||||
} // namespace blender::render::hydra
|
||||
|
@ -49,8 +49,10 @@ class InstancerData : public ObjectData {
|
||||
pxr::SdfPath object_prim_id(Object *object) const;
|
||||
pxr::SdfPath light_prim_id(LightInstance const &inst, int index) const;
|
||||
int light_prim_id_index(pxr::SdfPath const &id) const;
|
||||
void set_instances();
|
||||
void write_instances();
|
||||
void update_light_instance(LightInstance &inst);
|
||||
MeshInstance *mesh_instance(pxr::SdfPath const &id) const;
|
||||
LightInstance *light_instance(pxr::SdfPath const &id) const;
|
||||
|
||||
pxr::TfHashMap<pxr::SdfPath, MeshInstance, pxr::SdfPath::Hash> mesh_instances_;
|
||||
pxr::TfHashMap<pxr::SdfPath, LightInstance, pxr::SdfPath::Hash> light_instances_;
|
||||
|
@ -29,89 +29,72 @@ 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_material();
|
||||
write_transform();
|
||||
write_materials();
|
||||
|
||||
}
|
||||
|
||||
void MeshData::insert()
|
||||
{
|
||||
if (face_vertex_counts_.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ID_LOG(2, "");
|
||||
scene_delegate_->GetRenderIndex().InsertRprim(
|
||||
pxr::HdPrimTypeTokens->mesh, scene_delegate_, prim_id);
|
||||
/* Empty, because insertion of rprims happen in write_submeshes() */
|
||||
}
|
||||
|
||||
void MeshData::remove()
|
||||
{
|
||||
if (!scene_delegate_->GetRenderIndex().HasRprim(prim_id)) {
|
||||
return;
|
||||
for (int i = 0; i < submeshes_.size(); ++i) {
|
||||
scene_delegate_->GetRenderIndex().RemoveRprim(submesh_prim_id(i));
|
||||
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 2, "%s: %d", prim_id.GetText(), i);
|
||||
}
|
||||
|
||||
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 2, "%s", prim_id.GetText());
|
||||
scene_delegate_->GetRenderIndex().RemoveRprim(prim_id);
|
||||
}
|
||||
|
||||
void MeshData::update()
|
||||
{
|
||||
Object *object = (Object *)id;
|
||||
pxr::HdDirtyBits bits = pxr::HdChangeTracker::Clean;
|
||||
if ((id->recalc & ID_RECALC_GEOMETRY) || (((ID *)object->data)->recalc & ID_RECALC_GEOMETRY)) {
|
||||
init();
|
||||
bits = pxr::HdChangeTracker::AllDirty;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
|
||||
pxr::HdDirtyBits bits = pxr::HdChangeTracker::Clean;
|
||||
if (id->recalc & ID_RECALC_SHADING) {
|
||||
write_material();
|
||||
write_materials();
|
||||
bits |= pxr::HdChangeTracker::DirtyMaterialId | pxr::HdChangeTracker::DirtyDoubleSided;
|
||||
}
|
||||
if (id->recalc & ID_RECALC_TRANSFORM) {
|
||||
write_transform();
|
||||
bits |= pxr::HdChangeTracker::DirtyTransform;
|
||||
}
|
||||
}
|
||||
|
||||
if (bits == pxr::HdChangeTracker::Clean) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!scene_delegate_->GetRenderIndex().HasRprim(prim_id)) {
|
||||
insert();
|
||||
return;
|
||||
for (int i = 0; i < submeshes_.size(); ++i) {
|
||||
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkRprimDirty(submesh_prim_id(i), bits);
|
||||
ID_LOG(2, "%d", i);
|
||||
}
|
||||
}
|
||||
|
||||
if (face_vertex_counts_.empty()) {
|
||||
/* Remove prim without faces */
|
||||
remove();
|
||||
return;
|
||||
}
|
||||
ID_LOG(2, "");
|
||||
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkRprimDirty(prim_id, bits);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@ -120,19 +103,22 @@ bool MeshData::update_visibility()
|
||||
{
|
||||
bool ret = ObjectData::update_visibility();
|
||||
if (ret) {
|
||||
ID_LOG(2, "");
|
||||
for (int i = 0; i < submeshes_.size(); ++i) {
|
||||
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkRprimDirty(
|
||||
prim_id, pxr::HdChangeTracker::DirtyVisibility);
|
||||
submesh_prim_id(i), pxr::HdChangeTracker::DirtyVisibility);
|
||||
ID_LOG(2, "%d", i);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
pxr::HdMeshTopology MeshData::mesh_topology() const
|
||||
pxr::HdMeshTopology MeshData::mesh_topology(pxr::SdfPath const &id) const
|
||||
{
|
||||
const SubMesh &sm = submesh(id);
|
||||
return pxr::HdMeshTopology(pxr::PxOsdOpenSubdivTokens->none,
|
||||
pxr::HdTokens->rightHanded,
|
||||
face_vertex_counts_,
|
||||
face_vertex_indices_);
|
||||
sm.face_vertex_counts,
|
||||
sm.face_vertex_indices);
|
||||
}
|
||||
|
||||
pxr::HdPrimvarDescriptorVector MeshData::primvar_descriptors(
|
||||
@ -145,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);
|
||||
@ -158,116 +144,171 @@ pxr::HdPrimvarDescriptorVector MeshData::primvar_descriptors(
|
||||
return primvars;
|
||||
}
|
||||
|
||||
pxr::SdfPath MeshData::material_id() const
|
||||
pxr::SdfPath MeshData::material_id(pxr::SdfPath const &id) const
|
||||
{
|
||||
if (!mat_data_) {
|
||||
const SubMesh &sm = submesh(id);
|
||||
if (!sm.mat_data) {
|
||||
return pxr::SdfPath();
|
||||
}
|
||||
return mat_data_->prim_id;
|
||||
return sm.mat_data->prim_id;
|
||||
}
|
||||
|
||||
bool MeshData::double_sided() const
|
||||
bool MeshData::double_sided(pxr::SdfPath const &id) const
|
||||
{
|
||||
if (mat_data_) {
|
||||
return mat_data_->double_sided;
|
||||
const SubMesh &sm = submesh(id);
|
||||
if (sm.mat_data) {
|
||||
return sm.mat_data->double_sided;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void MeshData::update_double_sided(MaterialData *mat_data)
|
||||
{
|
||||
if (mat_data_ == mat_data) {
|
||||
ID_LOG(2, "");
|
||||
for (int i = 0; i < submeshes_.size(); ++i) {
|
||||
if (submeshes_[i].mat_data == mat_data) {
|
||||
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkRprimDirty(
|
||||
prim_id, pxr::HdChangeTracker::DirtyDoubleSided);
|
||||
submesh_prim_id(i), pxr::HdChangeTracker::DirtyDoubleSided);
|
||||
ID_LOG(2, "%d", i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MeshData::write_mesh(Mesh *mesh)
|
||||
void MeshData::available_materials(std::set<pxr::SdfPath> &paths) const
|
||||
{
|
||||
face_vertex_counts_.clear();
|
||||
face_vertex_indices_.clear();
|
||||
for (auto &sm : submeshes_) {
|
||||
if (sm.mat_data && !sm.mat_data->prim_id.IsEmpty()) {
|
||||
paths.insert(sm.mat_data->prim_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pxr::SdfPathVector MeshData::submesh_paths() const
|
||||
{
|
||||
pxr::SdfPathVector ret;
|
||||
for (int i = 0; i < submeshes_.size(); ++i) {
|
||||
ret.push_back(submesh_prim_id(i));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
pxr::SdfPath MeshData::submesh_prim_id(int index) const
|
||||
{
|
||||
char name[16];
|
||||
snprintf(name, 16, "SM_%04x", index);
|
||||
return prim_id.AppendElementString(name);
|
||||
}
|
||||
|
||||
const MeshData::SubMesh &MeshData::submesh(pxr::SdfPath const &id) const
|
||||
{
|
||||
int index;
|
||||
sscanf(id.GetName().c_str(), "SM_%x", &index);
|
||||
return submeshes_[index];
|
||||
}
|
||||
|
||||
void MeshData::write_submeshes(Mesh *mesh)
|
||||
{
|
||||
int sub_meshes_prev_count = submeshes_.size();
|
||||
submeshes_.clear();
|
||||
vertices_.clear();
|
||||
normals_.clear();
|
||||
uvs_.clear();
|
||||
|
||||
/* Insert base submeshes */
|
||||
int mat_count = BKE_object_material_count_eval((Object *)id);
|
||||
for (int i = 0; i < std::max(mat_count, 1); ++i) {
|
||||
SubMesh sm;
|
||||
sm.mat_index = i;
|
||||
submeshes_.push_back(sm);
|
||||
}
|
||||
|
||||
/* Fill submeshes data */
|
||||
const int *material_indices = BKE_mesh_material_indices(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);
|
||||
int tris_len = BKE_mesh_runtime_looptri_len(mesh);
|
||||
if (tris_len == 0) {
|
||||
return;
|
||||
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]]));
|
||||
}
|
||||
|
||||
blender::Span<MLoopTri> loopTris = mesh->looptris();
|
||||
|
||||
/* face_vertex_counts */
|
||||
face_vertex_counts_ = pxr::VtIntArray(tris_len, 3);
|
||||
|
||||
/* face_vertex_indices */
|
||||
blender::Span<int> corner_verts = mesh->corner_verts();
|
||||
face_vertex_indices_.reserve(loopTris.size() * 3);
|
||||
for (MLoopTri lt : loopTris) {
|
||||
face_vertex_indices_.push_back(corner_verts[lt.tri[0]]);
|
||||
face_vertex_indices_.push_back(corner_verts[lt.tri[1]]);
|
||||
face_vertex_indices_.push_back(corner_verts[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 */
|
||||
for (auto it = submeshes_.begin(); it != submeshes_.end();) {
|
||||
if (it->face_vertex_counts.empty()) {
|
||||
it = submeshes_.erase(it);
|
||||
}
|
||||
else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
write_normals(mesh);
|
||||
write_uv_maps(mesh);
|
||||
}
|
||||
|
||||
void MeshData::write_material()
|
||||
/* Update prims in render index */
|
||||
auto &render_index = scene_delegate_->GetRenderIndex();
|
||||
int i;
|
||||
for (i = 0; i < submeshes_.size(); ++i) {
|
||||
pxr::SdfPath p = submesh_prim_id(i);
|
||||
if (i < sub_meshes_prev_count) {
|
||||
render_index.GetChangeTracker().MarkRprimDirty(p, pxr::HdChangeTracker::AllDirty);
|
||||
ID_LOG(2, "Update %d", i);
|
||||
}
|
||||
else {
|
||||
render_index.InsertRprim(pxr::HdPrimTypeTokens->mesh, scene_delegate_, p);
|
||||
ID_LOG(2, "Insert %d", i);
|
||||
}
|
||||
}
|
||||
for (; i < sub_meshes_prev_count; ++i) {
|
||||
render_index.RemoveRprim(submesh_prim_id(i));
|
||||
ID_LOG(2, "Remove %d", i);
|
||||
}
|
||||
}
|
||||
|
||||
void MeshData::write_materials()
|
||||
{
|
||||
Object *object = (Object *)id;
|
||||
Material *mat = nullptr;
|
||||
if (BKE_object_material_count_eval(object) > 0) {
|
||||
mat = BKE_object_material_get_eval(object, object->actcol);
|
||||
}
|
||||
|
||||
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) {
|
||||
mat_data_ = nullptr;
|
||||
return;
|
||||
m.mat_data = nullptr;
|
||||
continue;
|
||||
}
|
||||
pxr::SdfPath p_id = scene_delegate_->material_prim_id(mat);
|
||||
mat_data_ = scene_delegate_->material_data(p_id);
|
||||
if (!mat_data_) {
|
||||
scene_delegate_->materials_[p_id] = std::make_unique<MaterialData>(scene_delegate_, mat, p_id);
|
||||
mat_data_ = scene_delegate_->material_data(p_id);
|
||||
mat_data_->init();
|
||||
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)
|
||||
{
|
||||
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]]));
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,15 @@
|
||||
namespace blender::render::hydra {
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
public:
|
||||
MeshData(BlenderSceneDelegate *scene_delegate, Object *object, pxr::SdfPath const &prim_id);
|
||||
|
||||
@ -22,30 +31,27 @@ 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() const;
|
||||
pxr::HdMeshTopology mesh_topology(pxr::SdfPath const &id) const;
|
||||
pxr::HdPrimvarDescriptorVector primvar_descriptors(pxr::HdInterpolation interpolation) const;
|
||||
pxr::SdfPath material_id() const;
|
||||
bool double_sided() const;
|
||||
pxr::SdfPath material_id(pxr::SdfPath const &id) const;
|
||||
bool double_sided(pxr::SdfPath const &id) const;
|
||||
void update_double_sided(MaterialData *mat_data);
|
||||
void available_materials(std::set<pxr::SdfPath> &paths) const;
|
||||
pxr::SdfPathVector submesh_paths() const;
|
||||
|
||||
pxr::HdCullStyle cull_style = pxr::HdCullStyleBackUnlessDoubleSided;
|
||||
|
||||
private:
|
||||
void write_mesh(Mesh *mesh);
|
||||
void write_material();
|
||||
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 write_submeshes(Mesh *mesh);
|
||||
void write_materials();
|
||||
|
||||
pxr::VtIntArray face_vertex_counts_;
|
||||
pxr::VtIntArray face_vertex_indices_;
|
||||
pxr::VtVec3fArray vertices_;
|
||||
pxr::VtVec2fArray uvs_;
|
||||
pxr::VtVec3fArray normals_;
|
||||
|
||||
MaterialData *mat_data_ = nullptr;
|
||||
std::vector<SubMesh> submeshes_;
|
||||
};
|
||||
|
||||
} // namespace blender::render::hydra
|
||||
|
Loading…
Reference in New Issue
Block a user
The order is important here?
No