forked from blender/blender
Support multimaterials on one mesh #44
@ -376,8 +376,8 @@ void BlenderSceneDelegate::check_updates()
|
|||||||
DEGIDIterData data = {0};
|
DEGIDIterData data = {0};
|
||||||
data.graph = depsgraph;
|
data.graph = depsgraph;
|
||||||
data.only_updated = true;
|
data.only_updated = true;
|
||||||
ITER_BEGIN (
|
ITER_BEGIN (DEG_iterator_ids_begin, DEG_iterator_ids_next, DEG_iterator_ids_end, &data, ID *, id)
|
||||||
DEG_iterator_ids_begin, DEG_iterator_ids_next, DEG_iterator_ids_end, &data, ID *, id) {
|
{
|
||||||
|
|
||||||
CLOG_INFO(LOG_RENDER_HYDRA_SCENE,
|
CLOG_INFO(LOG_RENDER_HYDRA_SCENE,
|
||||||
2,
|
2,
|
||||||
@ -451,7 +451,8 @@ void BlenderSceneDelegate::add_new_objects()
|
|||||||
DEG_iterator_objects_end,
|
DEG_iterator_objects_end,
|
||||||
&data,
|
&data,
|
||||||
Object *,
|
Object *,
|
||||||
object) {
|
object)
|
||||||
|
{
|
||||||
|
|
||||||
update_objects(object);
|
update_objects(object);
|
||||||
update_instancers(object);
|
update_instancers(object);
|
||||||
@ -476,7 +477,8 @@ void BlenderSceneDelegate::remove_unused_objects()
|
|||||||
DEG_iterator_objects_end,
|
DEG_iterator_objects_end,
|
||||||
&data,
|
&data,
|
||||||
Object *,
|
Object *,
|
||||||
object) {
|
object)
|
||||||
|
{
|
||||||
if (ObjectData::is_supported(object)) {
|
if (ObjectData::is_supported(object)) {
|
||||||
available_objects.insert(object_prim_id(object).GetName());
|
available_objects.insert(object_prim_id(object).GetName());
|
||||||
}
|
}
|
||||||
@ -550,7 +552,8 @@ void BlenderSceneDelegate::update_visibility()
|
|||||||
DEG_iterator_objects_end,
|
DEG_iterator_objects_end,
|
||||||
&data,
|
&data,
|
||||||
Object *,
|
Object *,
|
||||||
object) {
|
object)
|
||||||
|
{
|
||||||
|
|
||||||
if (!object_data(object_prim_id(object))) {
|
if (!object_data(object_prim_id(object))) {
|
||||||
update_objects(object);
|
update_objects(object);
|
||||||
|
@ -66,7 +66,8 @@ void InstancerData::update()
|
|||||||
Object *object = (Object *)id;
|
Object *object = (Object *)id;
|
||||||
if (id->recalc & ID_RECALC_GEOMETRY ||
|
if (id->recalc & ID_RECALC_GEOMETRY ||
|
||||||
(object->data && ((ID *)object->data)->recalc & ID_RECALC_GEOMETRY) ||
|
(object->data && ((ID *)object->data)->recalc & ID_RECALC_GEOMETRY) ||
|
||||||
id->recalc & ID_RECALC_TRANSFORM) {
|
id->recalc & ID_RECALC_TRANSFORM)
|
||||||
|
{
|
||||||
set_instances();
|
set_instances();
|
||||||
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkInstancerDirty(
|
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkInstancerDirty(
|
||||||
prim_id, pxr::HdChangeTracker::AllDirty);
|
prim_id, pxr::HdChangeTracker::AllDirty);
|
||||||
@ -174,7 +175,8 @@ void InstancerData::check_update(Object *object)
|
|||||||
if (l_it != light_instances_.end()) {
|
if (l_it != light_instances_.end()) {
|
||||||
Object *obj = (Object *)l_it->second.data->id;
|
Object *obj = (Object *)l_it->second.data->id;
|
||||||
if (obj->id.recalc & (ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY) ||
|
if (obj->id.recalc & (ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY) ||
|
||||||
((ID *)obj->data)->recalc & ID_RECALC_GEOMETRY) {
|
((ID *)obj->data)->recalc & ID_RECALC_GEOMETRY)
|
||||||
|
{
|
||||||
set_instances();
|
set_instances();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -27,7 +27,8 @@ void MeshData::init()
|
|||||||
|
|
||||||
Object *object = (Object *)id;
|
Object *object = (Object *)id;
|
||||||
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_mesh((Mesh *)object->data);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -43,60 +44,43 @@ void MeshData::init()
|
|||||||
|
|
||||||
void MeshData::insert()
|
void MeshData::insert()
|
||||||
{
|
{
|
||||||
//if (face_vertex_counts_.empty()) {
|
/* Empty, because insertion of rprims happen in update_sub_meshes() */
|
||||||
// return;
|
|
||||||
//}
|
|
||||||
|
|
||||||
ID_LOG(2, "");
|
|
||||||
scene_delegate_->GetRenderIndex().InsertRprim(
|
|
||||||
pxr::HdPrimTypeTokens->mesh, scene_delegate_, prim_id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshData::remove()
|
void MeshData::remove()
|
||||||
{
|
{
|
||||||
if (!scene_delegate_->GetRenderIndex().HasRprim(prim_id)) {
|
for (int i = 0; i < submeshes_.size(); ++i) {
|
||||||
return;
|
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()
|
void MeshData::update()
|
||||||
{
|
{
|
||||||
Object *object = (Object *)id;
|
Object *object = (Object *)id;
|
||||||
pxr::HdDirtyBits bits = pxr::HdChangeTracker::Clean;
|
|
||||||
if ((id->recalc & ID_RECALC_GEOMETRY) || (((ID *)object->data)->recalc & ID_RECALC_GEOMETRY)) {
|
if ((id->recalc & ID_RECALC_GEOMETRY) || (((ID *)object->data)->recalc & ID_RECALC_GEOMETRY)) {
|
||||||
init();
|
init();
|
||||||
bits = pxr::HdChangeTracker::AllDirty;
|
return;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
if (id->recalc & ID_RECALC_SHADING) {
|
pxr::HdDirtyBits bits = pxr::HdChangeTracker::Clean;
|
||||||
write_material();
|
if (id->recalc & ID_RECALC_SHADING) {
|
||||||
bits |= pxr::HdChangeTracker::DirtyMaterialId | pxr::HdChangeTracker::DirtyDoubleSided;
|
write_materials();
|
||||||
}
|
bits |= pxr::HdChangeTracker::DirtyMaterialId | pxr::HdChangeTracker::DirtyDoubleSided;
|
||||||
if (id->recalc & ID_RECALC_TRANSFORM) {
|
}
|
||||||
write_transform();
|
if (id->recalc & ID_RECALC_TRANSFORM) {
|
||||||
bits |= pxr::HdChangeTracker::DirtyTransform;
|
write_transform();
|
||||||
}
|
bits |= pxr::HdChangeTracker::DirtyTransform;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bits == pxr::HdChangeTracker::Clean) {
|
if (bits == pxr::HdChangeTracker::Clean) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!scene_delegate_->GetRenderIndex().HasRprim(prim_id)) {
|
for (int i = 0; i < submeshes_.size(); ++i) {
|
||||||
insert();
|
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkRprimDirty(submesh_prim_id(i), bits);
|
||||||
return;
|
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::TfToken const &key) const
|
||||||
@ -118,20 +102,22 @@ bool MeshData::update_visibility()
|
|||||||
{
|
{
|
||||||
bool ret = ObjectData::update_visibility();
|
bool ret = ObjectData::update_visibility();
|
||||||
if (ret) {
|
if (ret) {
|
||||||
ID_LOG(2, "");
|
for (int i = 0; i < submeshes_.size(); ++i) {
|
||||||
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkRprimDirty(
|
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkRprimDirty(
|
||||||
prim_id, pxr::HdChangeTracker::DirtyVisibility);
|
submesh_prim_id(i), pxr::HdChangeTracker::DirtyVisibility);
|
||||||
|
ID_LOG(2, "%d", i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
pxr::HdMeshTopology MeshData::mesh_topology(pxr::SdfPath const &id) const
|
pxr::HdMeshTopology MeshData::mesh_topology(pxr::SdfPath const &id) const
|
||||||
{
|
{
|
||||||
const SubMesh &m = sub_meshes_[0];
|
const SubMesh &sm = submesh(id);
|
||||||
return pxr::HdMeshTopology(pxr::PxOsdOpenSubdivTokens->none,
|
return pxr::HdMeshTopology(pxr::PxOsdOpenSubdivTokens->none,
|
||||||
pxr::HdTokens->rightHanded,
|
pxr::HdTokens->rightHanded,
|
||||||
m.face_vertex_counts,
|
sm.face_vertex_counts,
|
||||||
m.face_vertex_indices);
|
sm.face_vertex_indices);
|
||||||
}
|
}
|
||||||
|
|
||||||
pxr::HdPrimvarDescriptorVector MeshData::primvar_descriptors(
|
pxr::HdPrimvarDescriptorVector MeshData::primvar_descriptors(
|
||||||
@ -159,38 +145,38 @@ pxr::HdPrimvarDescriptorVector MeshData::primvar_descriptors(
|
|||||||
|
|
||||||
pxr::SdfPath MeshData::material_id(pxr::SdfPath const &id) const
|
pxr::SdfPath MeshData::material_id(pxr::SdfPath const &id) const
|
||||||
{
|
{
|
||||||
const SubMesh &m = sub_meshes_[0];
|
const SubMesh &sm = submesh(id);
|
||||||
if (!m.mat_data) {
|
if (!sm.mat_data) {
|
||||||
return pxr::SdfPath();
|
return pxr::SdfPath();
|
||||||
}
|
}
|
||||||
return m.mat_data->prim_id;
|
return sm.mat_data->prim_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MeshData::double_sided(pxr::SdfPath const &id) const
|
bool MeshData::double_sided(pxr::SdfPath const &id) const
|
||||||
{
|
{
|
||||||
const SubMesh &m = sub_meshes_[0];
|
const SubMesh &sm = submesh(id);
|
||||||
if (m.mat_data) {
|
if (sm.mat_data) {
|
||||||
return m.mat_data->double_sided;
|
return sm.mat_data->double_sided;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshData::update_double_sided(MaterialData *mat_data)
|
void MeshData::update_double_sided(MaterialData *mat_data)
|
||||||
{
|
{
|
||||||
SubMesh &m = sub_meshes_[0];
|
for (int i = 0; i < submeshes_.size(); ++i) {
|
||||||
|
if (submeshes_[i].mat_data == mat_data) {
|
||||||
if (m.mat_data == mat_data) {
|
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkRprimDirty(
|
||||||
ID_LOG(2, "");
|
submesh_prim_id(i), pxr::HdChangeTracker::DirtyDoubleSided);
|
||||||
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkRprimDirty(
|
ID_LOG(2, "%d", i);
|
||||||
prim_id, pxr::HdChangeTracker::DirtyDoubleSided);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshData::available_materials(std::set<pxr::SdfPath> &paths) const
|
void MeshData::available_materials(std::set<pxr::SdfPath> &paths) const
|
||||||
{
|
{
|
||||||
for (auto &m : sub_meshes_) {
|
for (auto &sm : submeshes_) {
|
||||||
if (m.mat_data && !m.mat_data->prim_id.IsEmpty()) {
|
if (sm.mat_data && !sm.mat_data->prim_id.IsEmpty()) {
|
||||||
paths.insert(m.mat_data->prim_id);
|
paths.insert(sm.mat_data->prim_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -201,9 +187,9 @@ void MeshData::write_mesh(Mesh *mesh)
|
|||||||
normals_.clear();
|
normals_.clear();
|
||||||
uvs_.clear();
|
uvs_.clear();
|
||||||
|
|
||||||
BKE_mesh_calc_normals_split(mesh);
|
update_sub_meshes(mesh);
|
||||||
int tris_len = BKE_mesh_runtime_looptri_len(mesh);
|
|
||||||
if (tris_len == 0) {
|
if (submeshes_.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,49 +200,16 @@ void MeshData::write_mesh(Mesh *mesh)
|
|||||||
vertices_.push_back(pxr::GfVec3f(v.x, v.y, v.z));
|
vertices_.push_back(pxr::GfVec3f(v.x, v.y, v.z));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* material meshes */
|
|
||||||
sub_meshes_.clear();
|
|
||||||
int mat_count = BKE_object_material_count_eval((Object *)id);
|
|
||||||
for (int i = 0; i < std::max(mat_count, 1); ++i) {
|
|
||||||
SubMesh m;
|
|
||||||
m.mat_index = i;
|
|
||||||
sub_meshes_.push_back(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
|
||||||
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 &m = sub_meshes_[mat_ind];
|
|
||||||
m.face_vertex_counts.push_back(3);
|
|
||||||
m.face_vertex_indices.push_back(corner_verts[lt.tri[0]]);
|
|
||||||
m.face_vertex_indices.push_back(corner_verts[lt.tri[1]]);
|
|
||||||
m.face_vertex_indices.push_back(corner_verts[lt.tri[2]]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto it = sub_meshes_.begin(); it != sub_meshes_.end();) {
|
|
||||||
if (it->face_vertex_counts.empty()) {
|
|
||||||
it = sub_meshes_.erase(it);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
write_normals(mesh);
|
write_normals(mesh);
|
||||||
write_uv_maps(mesh);
|
write_uv_maps(mesh);
|
||||||
write_material();
|
write_materials();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshData::write_material()
|
void MeshData::write_materials()
|
||||||
{
|
{
|
||||||
Object *object = (Object *)id;
|
Object *object = (Object *)id;
|
||||||
for (int i = 0; i < sub_meshes_.size(); ++i) {
|
for (int i = 0; i < submeshes_.size(); ++i) {
|
||||||
SubMesh &m = sub_meshes_[i];
|
SubMesh &m = submeshes_[i];
|
||||||
if (m.face_vertex_counts.empty()) {
|
if (m.face_vertex_counts.empty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -268,7 +221,8 @@ void MeshData::write_material()
|
|||||||
pxr::SdfPath p_id = scene_delegate_->material_prim_id(mat);
|
pxr::SdfPath p_id = scene_delegate_->material_prim_id(mat);
|
||||||
m.mat_data = scene_delegate_->material_data(p_id);
|
m.mat_data = scene_delegate_->material_data(p_id);
|
||||||
if (!m.mat_data) {
|
if (!m.mat_data) {
|
||||||
scene_delegate_->materials_[p_id] = std::make_unique<MaterialData>(scene_delegate_, mat, p_id);
|
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 = scene_delegate_->material_data(p_id);
|
||||||
m.mat_data->init();
|
m.mat_data->init();
|
||||||
m.mat_data->insert();
|
m.mat_data->insert();
|
||||||
@ -292,6 +246,7 @@ void MeshData::write_uv_maps(Mesh *mesh)
|
|||||||
|
|
||||||
void MeshData::write_normals(Mesh *mesh)
|
void MeshData::write_normals(Mesh *mesh)
|
||||||
{
|
{
|
||||||
|
BKE_mesh_calc_normals_split(mesh);
|
||||||
blender::Span<MLoopTri> loopTris = mesh->looptris();
|
blender::Span<MLoopTri> loopTris = mesh->looptris();
|
||||||
const float(*lnors)[3] = (float(*)[3])CustomData_get_layer(&mesh->ldata, CD_NORMAL);
|
const float(*lnors)[3] = (float(*)[3])CustomData_get_layer(&mesh->ldata, CD_NORMAL);
|
||||||
if (lnors) {
|
if (lnors) {
|
||||||
@ -304,4 +259,77 @@ void MeshData::write_normals(Mesh *mesh)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pxr::SdfPath MeshData::submesh_prim_id(int index) const
|
||||||
|
{
|
||||||
|
char name[16];
|
||||||
|
snprintf(name, 16, "M_%04x", index);
|
||||||
|
return prim_id.AppendElementString(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
const MeshData::SubMesh &MeshData::submesh(pxr::SdfPath const &id) const
|
||||||
|
{
|
||||||
|
int index;
|
||||||
|
sscanf(id.GetName().c_str(), "M_%x", &index);
|
||||||
|
return submeshes_[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
void MeshData::update_sub_meshes(Mesh *mesh)
|
||||||
|
{
|
||||||
|
int sub_meshes_prev_count = submeshes_.size();
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
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();
|
||||||
|
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]]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove submeshes without faces */
|
||||||
|
for (auto it = submeshes_.begin(); it != submeshes_.end();) {
|
||||||
|
if (it->face_vertex_counts.empty()) {
|
||||||
|
it = submeshes_.erase(it);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace blender::render::hydra
|
} // namespace blender::render::hydra
|
||||||
|
@ -43,15 +43,17 @@ class MeshData : public ObjectData {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void write_mesh(Mesh *mesh);
|
void write_mesh(Mesh *mesh);
|
||||||
void write_material();
|
void write_materials();
|
||||||
void write_uv_maps(Mesh *mesh);
|
void write_uv_maps(Mesh *mesh);
|
||||||
void write_normals(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);
|
||||||
|
|
||||||
pxr::VtVec3fArray vertices_;
|
pxr::VtVec3fArray vertices_;
|
||||||
pxr::VtVec2fArray uvs_;
|
pxr::VtVec2fArray uvs_;
|
||||||
pxr::VtVec3fArray normals_;
|
pxr::VtVec3fArray normals_;
|
||||||
|
std::vector<SubMesh> submeshes_;
|
||||||
std::vector<SubMesh> sub_meshes_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace blender::render::hydra
|
} // namespace blender::render::hydra
|
||||||
|
Loading…
Reference in New Issue
Block a user