forked from blender/blender
BLEN-345-Refactor export process #2
@ -62,10 +62,16 @@ set(SRC
|
|||||||
|
|
||||||
sceneDelegate/blenderSceneDelegate.h
|
sceneDelegate/blenderSceneDelegate.h
|
||||||
sceneDelegate/blenderSceneDelegate.cc
|
sceneDelegate/blenderSceneDelegate.cc
|
||||||
|
sceneDelegate/id.h
|
||||||
|
sceneDelegate/id.cc
|
||||||
sceneDelegate/object.h
|
sceneDelegate/object.h
|
||||||
sceneDelegate/object.cc
|
sceneDelegate/object.cc
|
||||||
sceneDelegate/material.h
|
sceneDelegate/material.h
|
||||||
sceneDelegate/material.cc
|
sceneDelegate/material.cc
|
||||||
|
sceneDelegate/mesh.h
|
||||||
|
sceneDelegate/mesh.cc
|
||||||
|
sceneDelegate/light.h
|
||||||
|
sceneDelegate/light.cc
|
||||||
sceneDelegate/world.h
|
sceneDelegate/world.h
|
||||||
sceneDelegate/world.cc
|
sceneDelegate/world.cc
|
||||||
)
|
)
|
||||||
|
@ -25,75 +25,65 @@ BlenderSceneDelegate::BlenderSceneDelegate(HdRenderIndex* parentIndex, SdfPath c
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlenderSceneDelegate::set_material(ObjectData &obj_data)
|
void BlenderSceneDelegate::set_material(MeshData &mesh_data)
|
||||||
{
|
{
|
||||||
Material *material = obj_data.material();
|
Material *material = mesh_data.material();
|
||||||
if (!material) {
|
if (!material) {
|
||||||
obj_data.set_material_id(SdfPath::EmptyPath());
|
mesh_data.material_id = SdfPath::EmptyPath();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SdfPath mat_id = material_id(material);
|
SdfPath id = MaterialData::prim_id(this, material);
|
||||||
if (!material_data(mat_id)) {
|
MaterialData *mat_data = material_data(id);
|
||||||
MaterialData mat_data(material);
|
if (!mat_data) {
|
||||||
GetRenderIndex().InsertSprim(HdPrimTypeTokens->material, this, mat_id);
|
materials[id] = MaterialData::init(this, material);
|
||||||
mat_data.export_mtlx();
|
mat_data = material_data(id);
|
||||||
materials[mat_id] = mat_data;
|
mat_data->export_mtlx();
|
||||||
LOG(INFO) << "Add material: " << mat_id << ", mtlx=" << mat_data.mtlx_path.GetResolvedPath();
|
mat_data->insert_prim();
|
||||||
}
|
}
|
||||||
obj_data.set_material_id(mat_id);
|
mesh_data.material_id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlenderSceneDelegate::update_material(Material *material)
|
void BlenderSceneDelegate::update_material(Material *material)
|
||||||
{
|
{
|
||||||
SdfPath mat_id = material_id(material);
|
MaterialData *mat_data = material_data(MaterialData::prim_id(this, material));
|
||||||
MaterialData *mat_data = material_data(mat_id);
|
|
||||||
if (mat_data) {
|
if (mat_data) {
|
||||||
mat_data->export_mtlx();
|
mat_data->export_mtlx();
|
||||||
LOG(INFO) << "Update material: " << mat_id << ", mtlx=" << mat_data->mtlx_path.GetResolvedPath();
|
mat_data->mark_prim_dirty(IdData::DirtyBits::AllDirty);
|
||||||
GetRenderIndex().GetChangeTracker().MarkSprimDirty(mat_id, HdMaterial::AllDirty);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlenderSceneDelegate::add_update_world(World *world)
|
void BlenderSceneDelegate::update_world()
|
||||||
{
|
{
|
||||||
SdfPath world_light_id = world_id();
|
World *world = (World *)b_depsgraph->scene().world().ptr.data;
|
||||||
|
|
||||||
LOG(INFO) << "Add world: " << world_light_id;
|
|
||||||
|
|
||||||
if (!world) {
|
|
||||||
world_data = nullptr;
|
|
||||||
GetRenderIndex().RemoveSprim(HdPrimTypeTokens->domeLight, world_light_id);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!world_data) {
|
if (!world_data) {
|
||||||
world_data = make_unique<WorldData>(world, (bContext *)b_context->ptr.data);
|
if (world) {
|
||||||
GetRenderIndex().InsertSprim(HdPrimTypeTokens->domeLight, this, world_light_id);
|
world_data = WorldData::init(this, world, (bContext *)b_context->ptr.data);
|
||||||
|
world_data->insert_prim();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
world_data = make_unique<WorldData>(world, (bContext *)b_context->ptr.data);
|
if (world) {
|
||||||
GetRenderIndex().GetChangeTracker().MarkSprimDirty(world_light_id, HdLight::AllDirty);
|
world_data = WorldData::init(this, world, (bContext *)b_context->ptr.data);
|
||||||
|
world_data->mark_prim_dirty(IdData::DirtyBits::AllDirty);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
world_data->remove_prim();
|
||||||
|
world_data = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BlenderSceneDelegate::GetVisible(SdfPath const &id)
|
bool BlenderSceneDelegate::GetVisible(SdfPath const &id)
|
||||||
{
|
{
|
||||||
ObjectData *obj_data = object_data(id);
|
if (id == WorldData::prim_id(this)) {
|
||||||
LOG(INFO) << "GetVisible: " << id.GetAsString();
|
return true;
|
||||||
|
|
||||||
HdRenderIndex &index = GetRenderIndex();
|
|
||||||
|
|
||||||
if (id == world_id()) {
|
|
||||||
return world_data->is_visible();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return obj_data->is_visible();
|
return object_data(id)->visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlenderSceneDelegate::update_collection()
|
void BlenderSceneDelegate::update_collection()
|
||||||
{
|
{
|
||||||
HdRenderIndex &index = GetRenderIndex();
|
|
||||||
|
|
||||||
/* add new objects */
|
/* add new objects */
|
||||||
std::set<SdfPath> available_objects;
|
std::set<SdfPath> available_objects;
|
||||||
for (auto &inst : b_depsgraph->object_instances) {
|
for (auto &inst : b_depsgraph->object_instances) {
|
||||||
@ -104,8 +94,7 @@ void BlenderSceneDelegate::update_collection()
|
|||||||
if (!supported_object(object)) {
|
if (!supported_object(object)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
SdfPath obj_id = object_id(object);
|
available_objects.insert(ObjectData::prim_id(this, object));
|
||||||
available_objects.insert(obj_id);
|
|
||||||
|
|
||||||
if (!is_populated) {
|
if (!is_populated) {
|
||||||
add_update_object(object, true, true, true);
|
add_update_object(object, true, true, true);
|
||||||
@ -121,13 +110,7 @@ void BlenderSceneDelegate::update_collection()
|
|||||||
if (available_objects.find(it->first) != available_objects.end()) {
|
if (available_objects.find(it->first) != available_objects.end()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
LOG(INFO) << "Remove: " << it->first;
|
it->second->remove_prim();
|
||||||
if (it->second.prim_type() == HdPrimTypeTokens->mesh) {
|
|
||||||
index.RemoveRprim(it->first);
|
|
||||||
}
|
|
||||||
else if (it->second.prim_type() != HdBlenderTokens->empty) {
|
|
||||||
index.RemoveSprim(it->second.prim_type(), it->first);
|
|
||||||
}
|
|
||||||
objects.erase(it);
|
objects.erase(it);
|
||||||
it = objects.begin();
|
it = objects.begin();
|
||||||
}
|
}
|
||||||
@ -135,16 +118,16 @@ void BlenderSceneDelegate::update_collection()
|
|||||||
/* remove unused materials */
|
/* remove unused materials */
|
||||||
std::set<SdfPath> available_materials;
|
std::set<SdfPath> available_materials;
|
||||||
for (auto &obj : objects) {
|
for (auto &obj : objects) {
|
||||||
if (obj.second.has_data(HdBlenderTokens->materialId)) {
|
MeshData *m_data = dynamic_cast<MeshData *>(obj.second.get());
|
||||||
available_materials.insert(obj.second.get_data(HdBlenderTokens->materialId).Get<SdfPath>());
|
if (m_data && !m_data->material_id.IsEmpty()) {
|
||||||
|
available_materials.insert(m_data->material_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (auto it = materials.begin(); it != materials.end(); ++it) {
|
for (auto it = materials.begin(); it != materials.end(); ++it) {
|
||||||
if (available_materials.find(it->first) != available_materials.end()) {
|
if (available_materials.find(it->first) != available_materials.end()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
LOG(INFO) << "Remove material: " << it->first;
|
it->second->remove_prim();
|
||||||
index.RemoveSprim(HdPrimTypeTokens->material, it->first);
|
|
||||||
materials.erase(it);
|
materials.erase(it);
|
||||||
it = materials.begin();
|
it = materials.begin();
|
||||||
}
|
}
|
||||||
@ -152,56 +135,38 @@ void BlenderSceneDelegate::update_collection()
|
|||||||
|
|
||||||
void BlenderSceneDelegate::add_update_object(Object *object, bool geometry, bool transform, bool shading)
|
void BlenderSceneDelegate::add_update_object(Object *object, bool geometry, bool transform, bool shading)
|
||||||
{
|
{
|
||||||
HdRenderIndex &index = GetRenderIndex();
|
SdfPath id = ObjectData::prim_id(this, object);
|
||||||
|
ObjectData *obj_data = object_data(id);
|
||||||
SdfPath obj_id = object_id(object);
|
|
||||||
ObjectData *obj_data = object_data(obj_id);
|
|
||||||
if (!obj_data) {
|
if (!obj_data) {
|
||||||
ObjectData new_obj_data(object);
|
objects[id] = ObjectData::init(this, object);
|
||||||
new_obj_data.update_visibility(view3d);
|
obj_data = object_data(id);
|
||||||
if (new_obj_data.prim_type() == HdPrimTypeTokens->mesh) {
|
obj_data->update_visibility(view3d);
|
||||||
LOG(INFO) << "Add mesh object: " << new_obj_data.name() << " id=" << obj_id;
|
obj_data->insert_prim();
|
||||||
index.InsertRprim(new_obj_data.prim_type(), this, obj_id);
|
MeshData *m_data = dynamic_cast<MeshData *>(obj_data);
|
||||||
set_material(new_obj_data);
|
if (m_data) {
|
||||||
|
set_material(*m_data);
|
||||||
}
|
}
|
||||||
else if (new_obj_data.type() == OB_LAMP) {
|
|
||||||
LOG(INFO) << "Add light object: " << new_obj_data.name() << " id=" << obj_id;
|
|
||||||
index.InsertSprim(new_obj_data.prim_type(), this, obj_id);
|
|
||||||
}
|
|
||||||
objects[obj_id] = new_obj_data;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (geometry) {
|
if (geometry) {
|
||||||
LOG(INFO) << "Full updated: " << obj_id;
|
objects[id] = ObjectData::init(this, object);
|
||||||
ObjectData new_obj_data(object);
|
obj_data = object_data(id);
|
||||||
new_obj_data.update_visibility(view3d);
|
obj_data->update_visibility(view3d);
|
||||||
if (new_obj_data.prim_type() == HdPrimTypeTokens->mesh) {
|
MeshData *m_data = dynamic_cast<MeshData *>(obj_data);
|
||||||
set_material(new_obj_data);
|
if (m_data) {
|
||||||
index.GetChangeTracker().MarkRprimDirty(obj_id, HdChangeTracker::AllDirty);
|
set_material(*m_data);
|
||||||
}
|
}
|
||||||
else if (new_obj_data.type() == OB_LAMP) {
|
obj_data->mark_prim_dirty(IdData::DirtyBits::AllDirty);
|
||||||
index.GetChangeTracker().MarkSprimDirty(obj_id, HdLight::AllDirty);
|
|
||||||
}
|
|
||||||
objects[obj_id] = new_obj_data;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (transform) {
|
if (transform) {
|
||||||
LOG(INFO) << "Transform updated: " << obj_id;
|
obj_data->mark_prim_dirty(IdData::DirtyBits::DirtyTransform);
|
||||||
if (obj_data->prim_type() == HdPrimTypeTokens->mesh) {
|
|
||||||
index.GetChangeTracker().MarkRprimDirty(obj_id, HdChangeTracker::DirtyTransform);
|
|
||||||
}
|
|
||||||
else if (obj_data->type() == OB_LAMP) {
|
|
||||||
index.GetChangeTracker().MarkSprimDirty(obj_id, HdLight::DirtyTransform);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shading) {
|
if (shading) {
|
||||||
LOG(INFO) << "Shading updated: " << obj_id;
|
obj_data->mark_prim_dirty(IdData::DirtyBits::DirtyMaterial);
|
||||||
if (obj_data->prim_type() == HdPrimTypeTokens->mesh) {
|
|
||||||
index.GetChangeTracker().MarkRprimDirty(obj_id, HdChangeTracker::DirtyMaterialId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,7 +176,17 @@ ObjectData *BlenderSceneDelegate::object_data(SdfPath const &id)
|
|||||||
if (it == objects.end()) {
|
if (it == objects.end()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return &it->second;
|
return it->second.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
MeshData *BlenderSceneDelegate::mesh_data(SdfPath const &id)
|
||||||
|
{
|
||||||
|
return static_cast<MeshData *>(object_data(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
LightData *BlenderSceneDelegate::light_data(SdfPath const &id)
|
||||||
|
{
|
||||||
|
return static_cast<LightData *>(object_data(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialData *BlenderSceneDelegate::material_data(SdfPath const &id)
|
MaterialData *BlenderSceneDelegate::material_data(SdfPath const &id)
|
||||||
@ -220,28 +195,7 @@ MaterialData *BlenderSceneDelegate::material_data(SdfPath const &id)
|
|||||||
if (it == materials.end()) {
|
if (it == materials.end()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return &it->second;
|
return it->second.get();
|
||||||
}
|
|
||||||
|
|
||||||
SdfPath BlenderSceneDelegate::object_id(Object *object)
|
|
||||||
{
|
|
||||||
/* Making id of object in form like O_<pointer in 16 hex digits format>. Example: O_000002073e369608 */
|
|
||||||
char str[32];
|
|
||||||
snprintf(str, 32, "O_%016llx", (uint64_t)object);
|
|
||||||
return GetDelegateID().AppendElementString(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
SdfPath BlenderSceneDelegate::material_id(Material *material)
|
|
||||||
{
|
|
||||||
/* Making id of material in form like M_<pointer in 16 hex digits format>. Example: M_000002074e812088 */
|
|
||||||
char str[32];
|
|
||||||
snprintf(str, 32, "M_%016llx", (uint64_t)material);
|
|
||||||
return GetDelegateID().AppendElementString(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
SdfPath BlenderSceneDelegate::world_id()
|
|
||||||
{
|
|
||||||
return GetDelegateID().AppendElementString("World");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BlenderSceneDelegate::supported_object(Object *object)
|
bool BlenderSceneDelegate::supported_object(Object *object)
|
||||||
@ -259,16 +213,14 @@ void BlenderSceneDelegate::Populate(BL::Depsgraph &b_deps, BL::Context &b_cont)
|
|||||||
{
|
{
|
||||||
LOG(INFO) << "Populate " << is_populated;
|
LOG(INFO) << "Populate " << is_populated;
|
||||||
|
|
||||||
view3d = (View3D *)b_cont.space_data().ptr.data;
|
|
||||||
b_depsgraph = &b_deps;
|
b_depsgraph = &b_deps;
|
||||||
b_context = &b_cont;
|
b_context = &b_cont;
|
||||||
|
view3d = (View3D *)b_context->space_data().ptr.data;
|
||||||
|
|
||||||
if (!is_populated) {
|
if (!is_populated) {
|
||||||
/* Export initial objects */
|
/* Export initial objects */
|
||||||
update_collection();
|
update_collection();
|
||||||
|
update_world();
|
||||||
World *world = (World *)b_depsgraph->scene().world().ptr.data;
|
|
||||||
add_update_world(world);
|
|
||||||
|
|
||||||
is_populated = true;
|
is_populated = true;
|
||||||
return;
|
return;
|
||||||
@ -277,13 +229,14 @@ void BlenderSceneDelegate::Populate(BL::Depsgraph &b_deps, BL::Context &b_cont)
|
|||||||
/* Working with updates */
|
/* Working with updates */
|
||||||
bool do_update_collection = false;
|
bool do_update_collection = false;
|
||||||
bool do_update_visibility = false;
|
bool do_update_visibility = false;
|
||||||
|
bool do_update_world = false;
|
||||||
|
|
||||||
for (auto &update : b_depsgraph->updates) {
|
for (auto &update : b_depsgraph->updates) {
|
||||||
BL::ID id = update.id();
|
BL::ID id = update.id();
|
||||||
LOG(INFO) << "Update: " << id.name_full() << " "
|
LOG(INFO) << "Update: " << id.name_full() << " ["
|
||||||
<< update.is_updated_transform()
|
<< update.is_updated_transform()
|
||||||
<< update.is_updated_geometry()
|
<< update.is_updated_geometry()
|
||||||
<< update.is_updated_shading();
|
<< update.is_updated_shading() << "]";
|
||||||
|
|
||||||
if (id.is_a(&RNA_Object)) {
|
if (id.is_a(&RNA_Object)) {
|
||||||
Object *object = (Object *)id.ptr.data;
|
Object *object = (Object *)id.ptr.data;
|
||||||
@ -313,23 +266,21 @@ void BlenderSceneDelegate::Populate(BL::Depsgraph &b_deps, BL::Context &b_cont)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (id.is_a(&RNA_Scene)) {
|
if (id.is_a(&RNA_Scene)) {
|
||||||
World *world = (World *)b_depsgraph->scene().world().ptr.data;
|
|
||||||
add_update_world(world);
|
|
||||||
if (!update.is_updated_geometry() && !update.is_updated_transform() && !update.is_updated_shading()) {
|
if (!update.is_updated_geometry() && !update.is_updated_transform() && !update.is_updated_shading()) {
|
||||||
do_update_visibility = true;
|
do_update_visibility = true;
|
||||||
|
|
||||||
|
Scene *scene = (Scene *)id.ptr.data;
|
||||||
|
if ((scene->world && !world_data) || (!scene->world && world_data)) {
|
||||||
|
do_update_world = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (id.is_a(&RNA_World)) {
|
if (id.is_a(&RNA_World)) {
|
||||||
World *world = (World *)b_depsgraph->scene().world().ptr.data;
|
if (update.is_updated_shading()) {
|
||||||
add_update_world(world);
|
do_update_world = true;
|
||||||
continue;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (id.is_a(&RNA_ShaderNodeTree)) {
|
|
||||||
World *world = (World *)b_depsgraph->scene().world().ptr.data;
|
|
||||||
add_update_world(world);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -340,22 +291,18 @@ void BlenderSceneDelegate::Populate(BL::Depsgraph &b_deps, BL::Context &b_cont)
|
|||||||
if (do_update_visibility) {
|
if (do_update_visibility) {
|
||||||
update_visibility();
|
update_visibility();
|
||||||
}
|
}
|
||||||
|
if (do_update_world) {
|
||||||
|
update_world();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlenderSceneDelegate::update_visibility()
|
void BlenderSceneDelegate::update_visibility()
|
||||||
{
|
{
|
||||||
HdRenderIndex &index = GetRenderIndex();
|
|
||||||
|
|
||||||
/* Check and update visibility */
|
/* Check and update visibility */
|
||||||
for (auto &obj : objects) {
|
for (auto &obj : objects) {
|
||||||
if (obj.second.update_visibility(view3d)) {
|
if (obj.second->update_visibility(view3d)) {
|
||||||
LOG(INFO) << "Visible changed: " << obj.first.GetAsString() << " " << obj.second.is_visible();
|
obj.second->mark_prim_dirty(IdData::DirtyBits::DirtyVisibility);
|
||||||
if (obj.second.prim_type() == HdPrimTypeTokens->mesh) {
|
|
||||||
index.GetChangeTracker().MarkRprimDirty(obj.first, HdChangeTracker::DirtyVisibility);
|
|
||||||
}
|
|
||||||
else if (obj.second.type() == OB_LAMP) {
|
|
||||||
index.GetChangeTracker().MarkSprimDirty(obj.first, HdLight::DirtyParams);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -369,8 +316,7 @@ void BlenderSceneDelegate::update_visibility()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
SdfPath obj_id = object_id(object);
|
if (!object_data(ObjectData::prim_id(this, object))) {
|
||||||
if (!object_data(obj_id)) {
|
|
||||||
add_update_object(object, true, true, true);
|
add_update_object(object, true, true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -378,113 +324,65 @@ void BlenderSceneDelegate::update_visibility()
|
|||||||
|
|
||||||
HdMeshTopology BlenderSceneDelegate::GetMeshTopology(SdfPath const& id)
|
HdMeshTopology BlenderSceneDelegate::GetMeshTopology(SdfPath const& id)
|
||||||
{
|
{
|
||||||
LOG(INFO) << "GetMeshTopology: " << id.GetAsString();
|
MeshData *m_data = mesh_data(id);
|
||||||
ObjectData &obj_data = objects[id];
|
return m_data->mesh_topology();
|
||||||
return HdMeshTopology(PxOsdOpenSubdivTokens->catmullClark, HdTokens->rightHanded,
|
|
||||||
obj_data.get_data<VtIntArray>(HdBlenderTokens->faceCounts),
|
|
||||||
obj_data.get_data<VtIntArray>(HdTokens->pointsIndices));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VtValue BlenderSceneDelegate::Get(SdfPath const& id, TfToken const& key)
|
VtValue BlenderSceneDelegate::Get(SdfPath const& id, TfToken const& key)
|
||||||
{
|
{
|
||||||
LOG(INFO) << "Get: " << id.GetAsString() << " [" << key.GetString() << "]";
|
|
||||||
|
|
||||||
VtValue ret;
|
|
||||||
ObjectData *obj_data = object_data(id);
|
ObjectData *obj_data = object_data(id);
|
||||||
if (obj_data) {
|
if (obj_data) {
|
||||||
if (obj_data->has_data(key)) {
|
return obj_data->get_data(key);
|
||||||
ret = obj_data->get_data(key);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (key.GetString() == "MaterialXFilename") {
|
|
||||||
MaterialData &mat_data = materials[id];
|
MaterialData *mat_data = material_data(id);
|
||||||
if (!mat_data.mtlx_path.GetResolvedPath().empty()) {
|
if (mat_data) {
|
||||||
ret = mat_data.mtlx_path;
|
return mat_data->get_data(key);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (key == HdStRenderBufferTokens->stormMsaaSampleCount) {
|
return VtValue();
|
||||||
// TODO: temporary value, it should be delivered through Python UI
|
|
||||||
ret = 16;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HdPrimvarDescriptorVector BlenderSceneDelegate::GetPrimvarDescriptors(SdfPath const& id, HdInterpolation interpolation)
|
HdPrimvarDescriptorVector BlenderSceneDelegate::GetPrimvarDescriptors(SdfPath const& id, HdInterpolation interpolation)
|
||||||
{
|
{
|
||||||
LOG(INFO) << "GetPrimvarDescriptors: " << id.GetAsString() << " " << interpolation;
|
return mesh_data(id)->primvar_descriptors(interpolation);
|
||||||
HdPrimvarDescriptorVector primvars;
|
|
||||||
ObjectData &obj_data = objects[id];
|
|
||||||
if (interpolation == HdInterpolationVertex) {
|
|
||||||
if (obj_data.has_data(HdTokens->points)) {
|
|
||||||
primvars.emplace_back(HdTokens->points, interpolation, HdPrimvarRoleTokens->point);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (interpolation == HdInterpolationFaceVarying) {
|
|
||||||
if (obj_data.has_data(HdTokens->normals)) {
|
|
||||||
primvars.emplace_back(HdTokens->normals, interpolation, HdPrimvarRoleTokens->normal);
|
|
||||||
}
|
|
||||||
if (obj_data.has_data(HdPrimvarRoleTokens->textureCoordinate)) {
|
|
||||||
primvars.emplace_back(HdPrimvarRoleTokens->textureCoordinate, interpolation, HdPrimvarRoleTokens->textureCoordinate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return primvars;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SdfPath BlenderSceneDelegate::GetMaterialId(SdfPath const & rprimId)
|
SdfPath BlenderSceneDelegate::GetMaterialId(SdfPath const & rprimId)
|
||||||
{
|
{
|
||||||
SdfPath ret;
|
return mesh_data(rprimId)->material_id;
|
||||||
ObjectData *obj_data = object_data(rprimId);
|
|
||||||
if (obj_data && obj_data->has_data(HdBlenderTokens->materialId)) {
|
|
||||||
ret = obj_data->get_data<SdfPath>(HdBlenderTokens->materialId);
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG(INFO) << "GetMaterialId [" << rprimId.GetAsString() << "] = " << ret.GetAsString();
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VtValue BlenderSceneDelegate::GetMaterialResource(SdfPath const& id)
|
VtValue BlenderSceneDelegate::GetMaterialResource(SdfPath const& id)
|
||||||
{
|
{
|
||||||
LOG(INFO) << "GetMaterialResource: " << id.GetAsString();
|
MaterialData *mat_data = material_data(id);
|
||||||
|
if (mat_data) {
|
||||||
|
return mat_data->material_resource();
|
||||||
|
}
|
||||||
return VtValue();
|
return VtValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
GfMatrix4d BlenderSceneDelegate::GetTransform(SdfPath const& id)
|
GfMatrix4d BlenderSceneDelegate::GetTransform(SdfPath const& id)
|
||||||
{
|
{
|
||||||
LOG(INFO) << "GetTransform: " << id.GetAsString();
|
ObjectData *obj_data = object_data(id);
|
||||||
|
if (obj_data) {
|
||||||
HdRenderIndex &index = GetRenderIndex();
|
return obj_data->transform();
|
||||||
|
|
||||||
if (id == world_id()) {
|
|
||||||
return world_data->transform(index.GetRenderDelegate()->GetRendererDisplayName());
|
|
||||||
}
|
}
|
||||||
|
if (id == WorldData::prim_id(this)) {
|
||||||
return objects[id].transform();
|
return world_data->transform();
|
||||||
|
}
|
||||||
|
return GfMatrix4d();
|
||||||
}
|
}
|
||||||
|
|
||||||
VtValue BlenderSceneDelegate::GetLightParamValue(SdfPath const& id, TfToken const& key)
|
VtValue BlenderSceneDelegate::GetLightParamValue(SdfPath const& id, TfToken const& key)
|
||||||
{
|
{
|
||||||
LOG(INFO) << "GetLightParamValue: " << id.GetAsString() << " [" << key.GetString() << "]";
|
LightData *l_data = light_data(id);
|
||||||
VtValue ret;
|
if (l_data) {
|
||||||
|
return l_data->get_data(key);
|
||||||
HdRenderIndex &index = GetRenderIndex();
|
|
||||||
|
|
||||||
ObjectData *obj_data = object_data(id);
|
|
||||||
if (obj_data) {
|
|
||||||
if (obj_data->has_data(key)) {
|
|
||||||
ret = obj_data->get_data(key);
|
|
||||||
}
|
|
||||||
else if (key == HdLightTokens->exposure) {
|
|
||||||
// TODO: temporary value, it should be delivered through Python UI
|
|
||||||
ret = 1.0f;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (id == world_id()) {
|
if (id == WorldData::prim_id(this)) {
|
||||||
if (world_data->has_data(key)) {
|
return world_data->get_data(key);
|
||||||
ret = world_data->get_data(key);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return VtValue();
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace blender::render::hydra
|
} // namespace blender::render::hydra
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
#include "RNA_blender_cpp.h"
|
#include "RNA_blender_cpp.h"
|
||||||
|
|
||||||
#include "object.h"
|
#include "object.h"
|
||||||
|
#include "mesh.h"
|
||||||
|
#include "light.h"
|
||||||
#include "world.h"
|
#include "world.h"
|
||||||
|
|
||||||
using namespace pxr;
|
using namespace pxr;
|
||||||
@ -40,16 +42,15 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
ObjectData *object_data(SdfPath const &id);
|
ObjectData *object_data(SdfPath const &id);
|
||||||
|
MeshData *mesh_data(SdfPath const &id);
|
||||||
|
LightData *light_data(SdfPath const &id);
|
||||||
MaterialData *material_data(SdfPath const &id);
|
MaterialData *material_data(SdfPath const &id);
|
||||||
SdfPath object_id(Object *object);
|
|
||||||
SdfPath material_id(Material *material);
|
|
||||||
SdfPath world_id();
|
|
||||||
bool supported_object(Object *object);
|
bool supported_object(Object *object);
|
||||||
|
|
||||||
void add_update_object(Object *object, bool geometry, bool transform, bool shading);
|
void add_update_object(Object *object, bool geometry, bool transform, bool shading);
|
||||||
void set_material(ObjectData &obj_data);
|
void set_material(MeshData &mesh_data);
|
||||||
void update_material(Material *material);
|
void update_material(Material *material);
|
||||||
void add_update_world(World *world);
|
void update_world();
|
||||||
void update_collection();
|
void update_collection();
|
||||||
void update_visibility();
|
void update_visibility();
|
||||||
|
|
||||||
|
30
source/blender/render/hydra/sceneDelegate/id.cc
Normal file
30
source/blender/render/hydra/sceneDelegate/id.cc
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/* SPDX-License-Identifier: Apache-2.0
|
||||||
|
* Copyright 2011-2022 Blender Foundation */
|
||||||
|
|
||||||
|
#include "BKE_lib_id.h"
|
||||||
|
|
||||||
|
#include "id.h"
|
||||||
|
|
||||||
|
using namespace pxr;
|
||||||
|
|
||||||
|
namespace blender::render::hydra {
|
||||||
|
|
||||||
|
IdData::IdData(pxr::HdSceneDelegate *scene_delegate, ID *id)
|
||||||
|
: scene_delegate(scene_delegate)
|
||||||
|
, id(id)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string IdData::name()
|
||||||
|
{
|
||||||
|
char str[MAX_ID_FULL_NAME];
|
||||||
|
BKE_id_full_name_get(str, id, 0);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
VtValue IdData::get_data(TfToken const &key)
|
||||||
|
{
|
||||||
|
return VtValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace blender::render::hydra
|
44
source/blender/render/hydra/sceneDelegate/id.h
Normal file
44
source/blender/render/hydra/sceneDelegate/id.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/* SPDX-License-Identifier: Apache-2.0
|
||||||
|
* Copyright 2011-2022 Blender Foundation */
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <pxr/base/vt/value.h>
|
||||||
|
#include <pxr/base/tf/token.h>
|
||||||
|
#include <pxr/imaging/hd/sceneDelegate.h>
|
||||||
|
|
||||||
|
#include "DNA_ID.h"
|
||||||
|
|
||||||
|
namespace blender::render::hydra {
|
||||||
|
|
||||||
|
class IdData {
|
||||||
|
public:
|
||||||
|
IdData(pxr::HdSceneDelegate *scene_delegate, ID *id);
|
||||||
|
virtual ~IdData() = default;
|
||||||
|
|
||||||
|
std::string name();
|
||||||
|
virtual pxr::VtValue get_data(pxr::TfToken const &key);
|
||||||
BogdanNagirniak marked this conversation as resolved
|
|||||||
|
template<class T> const T get_data(pxr::TfToken const &key);
|
||||||
|
|
||||||
|
enum class DirtyBits {
|
||||||
|
DirtyTransform = 1,
|
||||||
|
DirtyVisibility,
|
||||||
|
DirtyMaterial,
|
||||||
|
AllDirty
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual void insert_prim() = 0;
|
||||||
|
virtual void remove_prim() = 0;
|
||||||
|
virtual void mark_prim_dirty(DirtyBits dirty_bits) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
pxr::HdSceneDelegate *scene_delegate;
|
||||||
|
ID *id;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T> const T IdData::get_data(pxr::TfToken const &key)
|
||||||
|
{
|
||||||
|
return get_data(key).Get<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace blender::render::hydra
|
173
source/blender/render/hydra/sceneDelegate/light.cc
Normal file
173
source/blender/render/hydra/sceneDelegate/light.cc
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
/* SPDX-License-Identifier: Apache-2.0
|
||||||
|
* Copyright 2011-2022 Blender Foundation */
|
||||||
|
|
||||||
|
#include <boost/algorithm/string/predicate.hpp>
|
||||||
|
|
||||||
|
#include <pxr/imaging/hd/light.h>
|
||||||
|
#include <pxr/imaging/hd/tokens.h>
|
||||||
|
#include <pxr/usd/usdLux/tokens.h>
|
||||||
|
|
||||||
|
#include "glog/logging.h"
|
||||||
|
|
||||||
|
#include "BKE_light.h"
|
||||||
|
#include "DNA_light_types.h"
|
||||||
|
|
||||||
|
#include "light.h"
|
||||||
|
|
||||||
|
using namespace pxr;
|
||||||
|
using namespace boost::algorithm;
|
||||||
|
|
||||||
|
namespace blender::render::hydra {
|
||||||
|
|
||||||
|
LightData::LightData(pxr::HdSceneDelegate *scene_delegate, Object *object)
|
||||||
|
: ObjectData(scene_delegate, object)
|
||||||
|
{
|
||||||
|
Light *light = (Light *)((Object *)id)->data;
|
||||||
|
|
||||||
|
data[HdLightTokens->intensity] = light->energy;
|
||||||
|
data[HdLightTokens->color] = GfVec3f(light->r, light->g, light->b);
|
||||||
|
|
||||||
|
switch (light->type) {
|
||||||
|
case LA_LOCAL:
|
||||||
|
data[HdLightTokens->radius] = light->area_size / 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LA_SUN:
|
||||||
|
data[HdLightTokens->angle] = light->sun_angle * 180.0 / M_PI;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LA_SPOT:
|
||||||
|
data[HdLightTokens->shapingConeAngle] = light->spotsize / 2;
|
||||||
|
data[HdLightTokens->shapingConeSoftness] = light->spotblend;
|
||||||
|
data[UsdLuxTokens->treatAsPoint] = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LA_AREA:
|
||||||
|
switch (light->area_shape) {
|
||||||
|
case LA_AREA_SQUARE:
|
||||||
|
data[HdLightTokens->width] = light->area_size;
|
||||||
|
data[HdLightTokens->height] = light->area_size;
|
||||||
|
break;
|
||||||
|
case LA_AREA_RECT:
|
||||||
|
data[HdLightTokens->width] = light->area_size;
|
||||||
|
data[HdLightTokens->height] = light->area_sizey;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LA_AREA_DISK:
|
||||||
|
data[HdLightTokens->radius] = light->area_size / 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LA_AREA_ELLIPSE:
|
||||||
|
data[HdLightTokens->radius] = (light->area_size + light->area_sizey) / 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
data[HdLightTokens->normalize] = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: temporary value, it should be delivered through Python UI */
|
||||||
|
data[HdLightTokens->exposure] = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
pxr::TfToken LightData::prim_type()
|
||||||
|
{
|
||||||
|
Light *light = (Light *)((Object *)id)->data;
|
||||||
|
TfToken ret;
|
||||||
|
switch (light->type) {
|
||||||
|
case LA_LOCAL:
|
||||||
|
case LA_SPOT:
|
||||||
|
ret = HdPrimTypeTokens->sphereLight;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LA_SUN:
|
||||||
|
ret = HdPrimTypeTokens->distantLight;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LA_AREA:
|
||||||
|
switch (light->area_shape) {
|
||||||
|
case LA_AREA_SQUARE:
|
||||||
|
case LA_AREA_RECT:
|
||||||
|
ret = HdPrimTypeTokens->rectLight;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LA_AREA_DISK:
|
||||||
|
case LA_AREA_ELLIPSE:
|
||||||
|
ret = HdPrimTypeTokens->diskLight;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ret = HdPrimTypeTokens->rectLight;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ret = HdPrimTypeTokens->sphereLight;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
VtValue LightData::get_data(TfToken const &key)
|
||||||
|
{
|
||||||
|
LOG(INFO) << "Get data light: " << name() << " [" << key.GetString() << "]";
|
||||||
|
|
||||||
|
VtValue ret;
|
||||||
|
auto it = data.find(key);
|
||||||
|
if (it != data.end()) {
|
||||||
|
ret = it->second;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::string n = key.GetString();
|
||||||
|
if (contains(n, "object:visibility:")) {
|
||||||
|
if (ends_with(n, "camera") || ends_with(n, "shadow")) {
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LightData::insert_prim()
|
||||||
|
{
|
||||||
|
SdfPath p_id = prim_id(scene_delegate, (Object *)id);
|
||||||
|
scene_delegate->GetRenderIndex().InsertSprim(prim_type(), scene_delegate, p_id);
|
||||||
|
LOG(INFO) << "Add light: " << name() << " id=" << p_id.GetAsString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LightData::remove_prim()
|
||||||
|
{
|
||||||
|
SdfPath p_id = prim_id(scene_delegate, (Object *)id);
|
||||||
|
scene_delegate->GetRenderIndex().RemoveSprim(prim_type(), p_id);
|
||||||
|
LOG(INFO) << "Remove light: " << name();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LightData::mark_prim_dirty(DirtyBits dirty_bits)
|
||||||
|
{
|
||||||
|
HdDirtyBits bits = HdLight::Clean;
|
||||||
|
switch (dirty_bits) {
|
||||||
|
case DirtyBits::DirtyTransform:
|
||||||
|
bits = HdLight::DirtyTransform;
|
||||||
|
break;
|
||||||
|
case DirtyBits::DirtyVisibility:
|
||||||
|
bits = HdLight::DirtyParams;
|
||||||
|
break;
|
||||||
|
case DirtyBits::AllDirty:
|
||||||
|
bits = HdLight::AllDirty;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
SdfPath p_id = prim_id(scene_delegate, (Object *)id);
|
||||||
|
scene_delegate->GetRenderIndex().GetChangeTracker().MarkSprimDirty(p_id, bits);
|
||||||
|
LOG(INFO) << "Update light: " << name() << " [" << (int)dirty_bits << "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace blender::render::hydra
|
28
source/blender/render/hydra/sceneDelegate/light.h
Normal file
28
source/blender/render/hydra/sceneDelegate/light.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/* SPDX-License-Identifier: Apache-2.0
|
||||||
|
* Copyright 2011-2022 Blender Foundation */
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <pxr/usd/sdf/assetPath.h>
|
||||||
|
#include <pxr/usd/sdf/path.h>
|
||||||
|
#include "pxr/base/tf/hashmap.h"
|
||||||
|
|
||||||
|
#include "object.h"
|
||||||
|
|
||||||
|
namespace blender::render::hydra {
|
||||||
|
|
||||||
|
class LightData: public ObjectData {
|
||||||
|
public:
|
||||||
|
LightData(pxr::HdSceneDelegate *scene_delegate, Object *object);
|
||||||
|
|
||||||
|
pxr::VtValue get_data(pxr::TfToken const &key) override;
|
||||||
|
void insert_prim() override;
|
||||||
|
void remove_prim() override;
|
||||||
|
void mark_prim_dirty(DirtyBits dirty_bits) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::map<pxr::TfToken, pxr::VtValue> data;
|
||||||
|
pxr::TfToken prim_type();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace blender::render::hydra
|
@ -3,6 +3,11 @@
|
|||||||
|
|
||||||
#include <Python.h>
|
#include <Python.h>
|
||||||
|
|
||||||
|
#include <pxr/imaging/hd/tokens.h>
|
||||||
|
#include <pxr/imaging/hd/material.h>
|
||||||
|
|
||||||
|
#include "glog/logging.h"
|
||||||
|
|
||||||
#include "BKE_material.h"
|
#include "BKE_material.h"
|
||||||
#include "BKE_lib_id.h"
|
#include "BKE_lib_id.h"
|
||||||
|
|
||||||
@ -12,32 +17,50 @@ using namespace pxr;
|
|||||||
|
|
||||||
namespace blender::render::hydra {
|
namespace blender::render::hydra {
|
||||||
|
|
||||||
MaterialData::MaterialData()
|
std::unique_ptr<MaterialData> MaterialData::init(pxr::HdSceneDelegate *scene_delegate, Material *material)
|
||||||
: material(nullptr)
|
{
|
||||||
|
return std::make_unique<MaterialData>(scene_delegate, material);
|
||||||
|
}
|
||||||
|
|
||||||
|
pxr::SdfPath MaterialData::prim_id(pxr::HdSceneDelegate *scene_delegate, Material *material)
|
||||||
|
{
|
||||||
|
/* Making id of material in form like M_<pointer in 16 hex digits format>.
|
||||||
|
* Example: M_000002074e812088 */
|
||||||
|
char str[32];
|
||||||
|
snprintf(str, 32, "M_%016llx", (uint64_t)material);
|
||||||
|
return scene_delegate->GetDelegateID().AppendElementString(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialData::MaterialData(pxr::HdSceneDelegate *scene_delegate, Material *material)
|
||||||
|
: IdData(scene_delegate, (ID *)material)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialData::MaterialData(Material *material)
|
VtValue MaterialData::get_data(TfToken const &key)
|
||||||
: material(material)
|
|
||||||
{
|
{
|
||||||
|
VtValue ret;
|
||||||
|
if (key.GetString() == "MaterialXFilename") {
|
||||||
|
if (!mtlx_path.GetResolvedPath().empty()) {
|
||||||
|
ret = mtlx_path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string MaterialData::name()
|
pxr::VtValue MaterialData::material_resource()
|
||||||
{
|
{
|
||||||
char str[MAX_ID_FULL_NAME];
|
/* TODO: Implement return of HdMaterialNetwork */
|
||||||
BKE_id_full_name_get(str, (ID *)material, 0);
|
return pxr::VtValue();
|
||||||
return str;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MaterialData::export_mtlx()
|
void MaterialData::export_mtlx()
|
||||||
{
|
{
|
||||||
/* Call of python function hydra.export_mtlx() */
|
/* Call of python function hydra.export_mtlx() */
|
||||||
|
|
||||||
PyObject *module, *dict, *func, *result;
|
|
||||||
|
|
||||||
PyGILState_STATE gstate;
|
PyGILState_STATE gstate;
|
||||||
gstate = PyGILState_Ensure();
|
gstate = PyGILState_Ensure();
|
||||||
|
|
||||||
|
PyObject *module, *dict, *func, *result;
|
||||||
module = PyImport_ImportModule("hydra");
|
module = PyImport_ImportModule("hydra");
|
||||||
dict = PyModule_GetDict(module);
|
dict = PyModule_GetDict(module);
|
||||||
func = PyDict_GetItemString(dict, "export_mtlx");
|
func = PyDict_GetItemString(dict, "export_mtlx");
|
||||||
@ -51,6 +74,36 @@ void MaterialData::export_mtlx()
|
|||||||
PyGILState_Release(gstate);
|
PyGILState_Release(gstate);
|
||||||
|
|
||||||
mtlx_path = SdfAssetPath(path, path);
|
mtlx_path = SdfAssetPath(path, path);
|
||||||
|
LOG(INFO) << "Material export: " << name() << " mtlx=" << mtlx_path.GetResolvedPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MaterialData::insert_prim()
|
||||||
|
{
|
||||||
|
SdfPath p_id = prim_id(scene_delegate, (Material *)id);
|
||||||
|
scene_delegate->GetRenderIndex().InsertSprim(HdPrimTypeTokens->material, scene_delegate, p_id);
|
||||||
|
LOG(INFO) << "Add material: " << name() << " id=" << p_id.GetAsString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MaterialData::remove_prim()
|
||||||
|
{
|
||||||
|
SdfPath p_id = prim_id(scene_delegate, (Material *)id);
|
||||||
|
scene_delegate->GetRenderIndex().RemoveSprim(HdPrimTypeTokens->material, p_id);
|
||||||
|
LOG(INFO) << "Remove material: " << name();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MaterialData::mark_prim_dirty(DirtyBits dirty_bits)
|
||||||
|
{
|
||||||
|
HdDirtyBits bits = HdMaterial::Clean;
|
||||||
|
switch (dirty_bits) {
|
||||||
|
case DirtyBits::AllDirty:
|
||||||
|
bits = HdMaterial::AllDirty;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
SdfPath p_id = prim_id(scene_delegate, (Material *)id);
|
||||||
|
scene_delegate->GetRenderIndex().GetChangeTracker().MarkSprimDirty(p_id, bits);
|
||||||
|
LOG(INFO) << "Update material: " << name() << ", mtlx=" << mtlx_path.GetResolvedPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace blender::render::hydra
|
} // namespace blender::render::hydra
|
||||||
|
@ -3,28 +3,36 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
#include <pxr/usd/sdf/assetPath.h>
|
#include <pxr/usd/sdf/assetPath.h>
|
||||||
#include <pxr/usd/sdf/path.h>
|
#include <pxr/usd/sdf/path.h>
|
||||||
|
#include "pxr/base/tf/hashmap.h"
|
||||||
|
|
||||||
#include "DNA_material_types.h"
|
#include "DNA_material_types.h"
|
||||||
|
|
||||||
|
#include "id.h"
|
||||||
|
|
||||||
namespace blender::render::hydra {
|
namespace blender::render::hydra {
|
||||||
|
|
||||||
class MaterialData {
|
class MaterialData;
|
||||||
|
using MaterialDataMap = pxr::TfHashMap<pxr::SdfPath, std::unique_ptr<MaterialData>, pxr::SdfPath::Hash>;
|
||||||
|
|
||||||
|
class MaterialData: IdData {
|
||||||
public:
|
public:
|
||||||
MaterialData();
|
static std::unique_ptr<MaterialData> init(pxr::HdSceneDelegate *scene_delegate, Material *material);
|
||||||
MaterialData(Material *material);
|
static pxr::SdfPath prim_id(pxr::HdSceneDelegate *scene_delegate, Material *material);
|
||||||
|
|
||||||
std::string name();
|
MaterialData(pxr::HdSceneDelegate *scene_delegate, Material *material);
|
||||||
|
|
||||||
|
pxr::VtValue get_data(pxr::TfToken const &key) override;
|
||||||
|
void insert_prim() override;
|
||||||
|
void remove_prim() override;
|
||||||
|
void mark_prim_dirty(DirtyBits dirty_bits) override;
|
||||||
|
|
||||||
|
pxr::VtValue material_resource();
|
||||||
void export_mtlx();
|
void export_mtlx();
|
||||||
pxr::SdfAssetPath mtlx_path;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Material *material;
|
pxr::SdfAssetPath mtlx_path;
|
||||||
};
|
};
|
||||||
|
|
||||||
using MaterialDataMap = std::map<pxr::SdfPath, MaterialData>;
|
|
||||||
|
|
||||||
} // namespace blender::render::hydra
|
} // namespace blender::render::hydra
|
||||||
|
187
source/blender/render/hydra/sceneDelegate/mesh.cc
Normal file
187
source/blender/render/hydra/sceneDelegate/mesh.cc
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
/* SPDX-License-Identifier: Apache-2.0
|
||||||
|
* Copyright 2011-2022 Blender Foundation */
|
||||||
|
|
||||||
|
#include <pxr/base/gf/vec2f.h>
|
||||||
|
#include <pxr/imaging/hd/tokens.h>
|
||||||
|
|
||||||
|
#include "glog/logging.h"
|
||||||
|
|
||||||
|
#include "BKE_mesh.h"
|
||||||
|
#include "BKE_mesh_runtime.h"
|
||||||
|
#include "BKE_object.h"
|
||||||
|
#include "BKE_material.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include "mesh.h"
|
||||||
|
|
||||||
|
using namespace pxr;
|
||||||
|
|
||||||
|
namespace blender::render::hydra {
|
||||||
|
|
||||||
|
MeshData::MeshData(pxr::HdSceneDelegate *scene_delegate, Object *object)
|
||||||
|
: ObjectData(scene_delegate, object)
|
||||||
|
{
|
||||||
|
if (object->type == OB_MESH && object->mode == OB_MODE_OBJECT &&
|
||||||
|
BLI_listbase_is_empty(&object->modifiers)) {
|
||||||
|
set_mesh((Mesh *)object->data);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Mesh *mesh = BKE_object_to_mesh(nullptr, object, false);
|
||||||
|
set_mesh(mesh);
|
||||||
|
BKE_object_to_mesh_clear(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VtValue MeshData::get_data(TfToken const &key)
|
||||||
|
{
|
||||||
|
VtValue ret;
|
||||||
|
if (key == HdTokens->points) {
|
||||||
|
ret = vertices;
|
||||||
|
}
|
||||||
|
else if (key == HdTokens->normals) {
|
||||||
|
ret = normals;
|
||||||
|
}
|
||||||
|
else if (key == HdPrimvarRoleTokens->textureCoordinate) {
|
||||||
|
ret = uvs;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
Material *MeshData::material()
|
||||||
|
{
|
||||||
|
Object *object = (Object *)id;
|
||||||
|
if (BKE_object_material_count_eval(object) == 0) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return BKE_object_material_get_eval(object, object->actcol);
|
||||||
|
}
|
||||||
|
|
||||||
|
HdMeshTopology MeshData::mesh_topology()
|
||||||
|
{
|
||||||
|
return HdMeshTopology(PxOsdOpenSubdivTokens->catmullClark, HdTokens->rightHanded,
|
||||||
|
face_vertex_counts, face_vertex_indices);
|
||||||
|
}
|
||||||
|
|
||||||
|
HdPrimvarDescriptorVector MeshData::primvar_descriptors(HdInterpolation interpolation)
|
||||||
|
{
|
||||||
|
HdPrimvarDescriptorVector primvars;
|
||||||
|
if (interpolation == HdInterpolationVertex) {
|
||||||
|
if (!vertices.empty()) {
|
||||||
|
primvars.emplace_back(HdTokens->points, interpolation, HdPrimvarRoleTokens->point);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (interpolation == HdInterpolationFaceVarying) {
|
||||||
|
if (!vertices.empty()) {
|
||||||
|
primvars.emplace_back(HdTokens->normals, interpolation, HdPrimvarRoleTokens->normal);
|
||||||
|
}
|
||||||
|
if (!uvs.empty()) {
|
||||||
|
primvars.emplace_back(HdPrimvarRoleTokens->textureCoordinate, interpolation,
|
||||||
|
HdPrimvarRoleTokens->textureCoordinate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return primvars;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MeshData::set_mesh(Mesh *mesh)
|
||||||
|
{
|
||||||
|
BKE_mesh_calc_normals_split(mesh);
|
||||||
|
int tris_len = BKE_mesh_runtime_looptri_len(mesh);
|
||||||
|
if (tris_len == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
blender::Span<MLoopTri> loopTris = mesh->looptris();
|
||||||
|
|
||||||
|
/* face_vertex_counts */
|
||||||
|
face_vertex_counts = VtIntArray(tris_len, 3);
|
||||||
|
|
||||||
|
/* face_vertex_indices */
|
||||||
|
blender::Span<MLoop> loops = mesh->loops();
|
||||||
|
face_vertex_indices.reserve(loopTris.size() * 3);
|
||||||
|
for (MLoopTri lt : loopTris) {
|
||||||
|
face_vertex_indices.push_back(loops[lt.tri[0]].v);
|
||||||
|
face_vertex_indices.push_back(loops[lt.tri[1]].v);
|
||||||
|
face_vertex_indices.push_back(loops[lt.tri[2]].v);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* vertices */
|
||||||
|
vertices.reserve(mesh->totvert);
|
||||||
|
blender::Span<blender::float3> verts = mesh->vert_positions();
|
||||||
|
for (blender::float3 v : verts) {
|
||||||
|
vertices.push_back(GfVec3f(v.x, v.y, v.z));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* normals */
|
||||||
|
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(GfVec3f(lnors[lt.tri[0]]));
|
||||||
|
normals.push_back(GfVec3f(lnors[lt.tri[1]]));
|
||||||
|
normals.push_back(GfVec3f(lnors[lt.tri[2]]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* uvs*/
|
||||||
|
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(GfVec2f(luvs[lt.tri[0]]));
|
||||||
|
uvs.push_back(GfVec2f(luvs[lt.tri[1]]));
|
||||||
|
uvs.push_back(GfVec2f(luvs[lt.tri[2]]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MeshData::insert_prim()
|
||||||
|
{
|
||||||
|
if (face_vertex_counts.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SdfPath p_id = prim_id(scene_delegate, (Object *)id);
|
||||||
|
scene_delegate->GetRenderIndex().InsertRprim(HdPrimTypeTokens->mesh, scene_delegate, p_id);
|
||||||
|
LOG(INFO) << "Add mesh: " << name() << " id=" << p_id.GetAsString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MeshData::remove_prim()
|
||||||
|
{
|
||||||
|
SdfPath p_id = prim_id(scene_delegate, (Object *)id);
|
||||||
|
if (!scene_delegate->GetRenderIndex().HasRprim(p_id)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
scene_delegate->GetRenderIndex().RemoveRprim(p_id);
|
||||||
|
LOG(INFO) << "Remove mesh: " << name();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MeshData::mark_prim_dirty(DirtyBits dirty_bits)
|
||||||
|
{
|
||||||
|
SdfPath p_id = prim_id(scene_delegate, (Object *)id);
|
||||||
|
if (!scene_delegate->GetRenderIndex().HasRprim(p_id)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
HdDirtyBits bits = HdChangeTracker::Clean;
|
||||||
|
switch (dirty_bits) {
|
||||||
BogdanNagirniak marked this conversation as resolved
Georgiy Markelov
commented
consider adding consider adding `map<OurDirty, TheirDirty>` so we can get needed value by key without `switch case`
Bogdan Nagirniak
commented
`switch case` is preferable here
|
|||||||
|
case DirtyBits::DirtyTransform:
|
||||||
|
bits = HdChangeTracker::DirtyTransform;
|
||||||
|
break;
|
||||||
|
case DirtyBits::DirtyVisibility:
|
||||||
|
bits = HdChangeTracker::DirtyVisibility;
|
||||||
|
break;
|
||||||
|
case DirtyBits::DirtyMaterial:
|
||||||
|
bits = HdChangeTracker::DirtyMaterialId;
|
||||||
|
break;
|
||||||
|
case DirtyBits::AllDirty:
|
||||||
|
bits = HdChangeTracker::AllDirty;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
scene_delegate->GetRenderIndex().GetChangeTracker().MarkRprimDirty(p_id, bits);
|
||||||
|
LOG(INFO) << "Update mesh: " << name() << " [" << (int)dirty_bits << "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace blender::render::hydra
|
39
source/blender/render/hydra/sceneDelegate/mesh.h
Normal file
39
source/blender/render/hydra/sceneDelegate/mesh.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/* SPDX-License-Identifier: Apache-2.0
|
||||||
|
* Copyright 2011-2022 Blender Foundation */
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <pxr/base/vt/array.h>
|
||||||
|
#include <pxr/imaging/hd/sceneDelegate.h>
|
||||||
|
|
||||||
|
#include "object.h"
|
||||||
|
|
||||||
|
namespace blender::render::hydra {
|
||||||
|
|
||||||
|
class MeshData: public ObjectData {
|
||||||
|
public:
|
||||||
|
MeshData(pxr::HdSceneDelegate *scene_delegate, Object *object);
|
||||||
|
|
||||||
|
pxr::VtValue get_data(pxr::TfToken const &key) override;
|
||||||
|
|
||||||
|
void insert_prim() override;
|
||||||
|
void remove_prim() override;
|
||||||
|
void mark_prim_dirty(DirtyBits dirty_bits) override;
|
||||||
|
|
||||||
|
Material *material();
|
||||||
|
pxr::HdMeshTopology mesh_topology();
|
||||||
|
pxr::HdPrimvarDescriptorVector primvar_descriptors(pxr::HdInterpolation interpolation);
|
||||||
|
|
||||||
|
pxr::SdfPath material_id;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void set_mesh(Mesh *mesh);
|
||||||
|
|
||||||
|
pxr::VtIntArray face_vertex_counts;
|
||||||
|
pxr::VtIntArray face_vertex_indices;
|
||||||
|
pxr::VtVec3fArray vertices;
|
||||||
|
pxr::VtVec3fArray normals;
|
||||||
|
pxr::VtVec2fArray uvs;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace blender::render::hydra
|
@ -1,173 +1,60 @@
|
|||||||
/* SPDX-License-Identifier: Apache-2.0
|
/* SPDX-License-Identifier: Apache-2.0
|
||||||
* Copyright 2011-2022 Blender Foundation */
|
* Copyright 2011-2022 Blender Foundation */
|
||||||
|
|
||||||
#include <pxr/base/vt/array.h>
|
|
||||||
#include <pxr/base/gf/vec2f.h>
|
|
||||||
#include <pxr/imaging/hd/light.h>
|
|
||||||
#include <pxr/imaging/hd/camera.h>
|
|
||||||
#include <pxr/imaging/hd/tokens.h>
|
|
||||||
#include <pxr/usd/usdLux/tokens.h>
|
|
||||||
|
|
||||||
#include "DNA_light_types.h"
|
|
||||||
#include "DNA_camera_types.h"
|
|
||||||
|
|
||||||
#include "BKE_object.h"
|
#include "BKE_object.h"
|
||||||
#include "BKE_lib_id.h"
|
|
||||||
#include "BKE_material.h"
|
|
||||||
#include "BKE_light.h"
|
|
||||||
#include "BKE_mesh.h"
|
|
||||||
#include "BKE_mesh_runtime.h"
|
|
||||||
#include "BKE_layer.h"
|
|
||||||
|
|
||||||
#include "object.h"
|
#include "object.h"
|
||||||
|
#include "mesh.h"
|
||||||
|
#include "light.h"
|
||||||
#include "../utils.h"
|
#include "../utils.h"
|
||||||
|
|
||||||
PXR_NAMESPACE_OPEN_SCOPE
|
|
||||||
TF_DEFINE_PUBLIC_TOKENS(HdBlenderTokens, HD_BLENDER_TOKENS);
|
|
||||||
PXR_NAMESPACE_CLOSE_SCOPE
|
|
||||||
|
|
||||||
using namespace pxr;
|
using namespace pxr;
|
||||||
|
|
||||||
namespace blender::render::hydra {
|
namespace blender::render::hydra {
|
||||||
|
|
||||||
ObjectData::ObjectData()
|
std::unique_ptr<ObjectData> ObjectData::init(pxr::HdSceneDelegate *scene_delegate, Object *object)
|
||||||
: object(nullptr)
|
|
||||||
, visible(true)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ObjectData::ObjectData(Object *object)
|
|
||||||
: object(object)
|
|
||||||
{
|
{
|
||||||
switch (object->type) {
|
switch (object->type) {
|
||||||
case OB_MESH:
|
case OB_MESH:
|
||||||
if (object->mode == OB_MODE_OBJECT && BLI_listbase_is_empty(&object->modifiers)) {
|
|
||||||
set_as_mesh();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
set_as_meshable();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OB_SURF:
|
case OB_SURF:
|
||||||
case OB_FONT:
|
case OB_FONT:
|
||||||
case OB_CURVES:
|
case OB_CURVES:
|
||||||
case OB_CURVES_LEGACY:
|
case OB_CURVES_LEGACY:
|
||||||
case OB_MBALL:
|
case OB_MBALL:
|
||||||
set_as_meshable();
|
return std::make_unique<MeshData>(scene_delegate, object);
|
||||||
break;
|
|
||||||
|
|
||||||
case OB_LAMP:
|
case OB_LAMP:
|
||||||
set_as_light();
|
return std::make_unique<LightData>(scene_delegate, object);
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ObjectData::name()
|
pxr::SdfPath ObjectData::prim_id(pxr::HdSceneDelegate *scene_delegate, Object *object)
|
||||||
|
{
|
||||||
|
/* Making id of object in form like O_<pointer in 16 hex digits format>. Example:
|
||||||
|
* O_000002073e369608 */
|
||||||
|
char str[32];
|
||||||
|
snprintf(str, 32, "O_%016llx", (uint64_t)object);
|
||||||
|
return scene_delegate->GetDelegateID().AppendElementString(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjectData::ObjectData(pxr::HdSceneDelegate *scene_delegate, Object *object)
|
||||||
|
: IdData(scene_delegate, (ID *)object)
|
||||||
|
, visible(true)
|
||||||
{
|
{
|
||||||
char str[MAX_ID_FULL_NAME];
|
|
||||||
BKE_id_full_name_get(str, (ID *)object, 0);
|
|
||||||
return str;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ObjectData::type()
|
int ObjectData::type()
|
||||||
{
|
{
|
||||||
return object->type;
|
return ((Object *)id)->type;
|
||||||
}
|
|
||||||
|
|
||||||
TfToken ObjectData::prim_type()
|
|
||||||
{
|
|
||||||
TfToken ret = HdBlenderTokens->empty;
|
|
||||||
Light *light;
|
|
||||||
switch (object->type) {
|
|
||||||
case OB_MESH:
|
|
||||||
case OB_SURF:
|
|
||||||
case OB_FONT:
|
|
||||||
case OB_CURVES:
|
|
||||||
case OB_CURVES_LEGACY:
|
|
||||||
case OB_MBALL:
|
|
||||||
if (!has_data(HdTokens->points)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ret = HdPrimTypeTokens->mesh;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OB_LAMP:
|
|
||||||
light = (Light *)object->data;
|
|
||||||
switch (light->type) {
|
|
||||||
case LA_LOCAL:
|
|
||||||
case LA_SPOT:
|
|
||||||
ret = HdPrimTypeTokens->sphereLight;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case LA_SUN:
|
|
||||||
ret = HdPrimTypeTokens->distantLight;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case LA_AREA:
|
|
||||||
switch (light->area_shape) {
|
|
||||||
case LA_AREA_SQUARE:
|
|
||||||
case LA_AREA_RECT:
|
|
||||||
ret = HdPrimTypeTokens->rectLight;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case LA_AREA_DISK:
|
|
||||||
case LA_AREA_ELLIPSE:
|
|
||||||
ret = HdPrimTypeTokens->diskLight;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
ret = HdPrimTypeTokens->rectLight;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
ret = HdPrimTypeTokens->sphereLight;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GfMatrix4d ObjectData::transform()
|
GfMatrix4d ObjectData::transform()
|
||||||
{
|
{
|
||||||
return gf_matrix_from_transform(object->object_to_world);
|
return gf_matrix_from_transform(((Object *)id)->object_to_world);
|
||||||
}
|
|
||||||
|
|
||||||
Material *ObjectData::material()
|
|
||||||
{
|
|
||||||
if (BKE_object_material_count_eval(object) == 0) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return BKE_object_material_get_eval(object, object->actcol);
|
|
||||||
}
|
|
||||||
|
|
||||||
VtValue &ObjectData::get_data(TfToken const &key)
|
|
||||||
{
|
|
||||||
return data[key];
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ObjectData::has_data(TfToken const &key)
|
|
||||||
{
|
|
||||||
return data.find(key) != data.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObjectData::set_material_id(SdfPath const &id)
|
|
||||||
{
|
|
||||||
if (id.IsEmpty()) {
|
|
||||||
data.erase(HdBlenderTokens->materialId);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
data[HdBlenderTokens->materialId] = id;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ObjectData::update_visibility(View3D *view3d)
|
bool ObjectData::update_visibility(View3D *view3d)
|
||||||
@ -177,136 +64,8 @@ bool ObjectData::update_visibility(View3D *view3d)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool prev_visible = visible;
|
bool prev_visible = visible;
|
||||||
visible = BKE_object_is_visible_in_viewport(view3d, object);
|
visible = BKE_object_is_visible_in_viewport(view3d, (Object *)id);
|
||||||
return visible != prev_visible;
|
return visible != prev_visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ObjectData::is_visible()
|
|
||||||
{
|
|
||||||
return visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObjectData::set_as_mesh()
|
|
||||||
{
|
|
||||||
Mesh *mesh = (Mesh *)object->data;
|
|
||||||
set_mesh(mesh);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObjectData::set_as_meshable()
|
|
||||||
{
|
|
||||||
Mesh *mesh = BKE_object_to_mesh(nullptr, object, false);
|
|
||||||
set_mesh(mesh);
|
|
||||||
BKE_object_to_mesh_clear(object);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObjectData::set_mesh(Mesh *mesh)
|
|
||||||
{
|
|
||||||
BKE_mesh_calc_normals_split(mesh);
|
|
||||||
int tris_len = BKE_mesh_runtime_looptri_len(mesh);
|
|
||||||
if (tris_len == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
blender::Span<MLoopTri> loopTris = mesh->looptris();
|
|
||||||
|
|
||||||
/* faceVertexCounts */
|
|
||||||
data[HdBlenderTokens->faceCounts] = VtIntArray(tris_len, 3);
|
|
||||||
|
|
||||||
/* faceVertexIndices */
|
|
||||||
VtIntArray faceVertexIndices;
|
|
||||||
blender::Span<MLoop> loops = mesh->loops();
|
|
||||||
faceVertexIndices.reserve(loopTris.size() * 3);
|
|
||||||
for (MLoopTri lt : loopTris) {
|
|
||||||
faceVertexIndices.push_back(loops[lt.tri[0]].v);
|
|
||||||
faceVertexIndices.push_back(loops[lt.tri[1]].v);
|
|
||||||
faceVertexIndices.push_back(loops[lt.tri[2]].v);
|
|
||||||
}
|
|
||||||
data[HdTokens->pointsIndices] = faceVertexIndices;
|
|
||||||
|
|
||||||
/* vertices */
|
|
||||||
VtVec3fArray vertices;
|
|
||||||
vertices.reserve(mesh->totvert);
|
|
||||||
blender::Span<blender::float3> verts = mesh->vert_positions();
|
|
||||||
for (blender::float3 v : verts) {
|
|
||||||
vertices.push_back(GfVec3f(v.x, v.y, v.z));
|
|
||||||
}
|
|
||||||
data[HdTokens->points] = vertices;
|
|
||||||
|
|
||||||
/* normals */
|
|
||||||
const float(*lnors)[3] = (float(*)[3])CustomData_get_layer(&mesh->ldata, CD_NORMAL);
|
|
||||||
if (lnors) {
|
|
||||||
VtVec3fArray normals;
|
|
||||||
normals.reserve(loopTris.size() * 3);
|
|
||||||
for (MLoopTri lt : loopTris) {
|
|
||||||
normals.push_back(GfVec3f(lnors[lt.tri[0]]));
|
|
||||||
normals.push_back(GfVec3f(lnors[lt.tri[1]]));
|
|
||||||
normals.push_back(GfVec3f(lnors[lt.tri[2]]));
|
|
||||||
}
|
|
||||||
data[HdTokens->normals] = normals;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* UVs*/
|
|
||||||
const float(*luvs)[2] = (float(*)[2])CustomData_get_layer(&mesh->ldata, CD_PROP_FLOAT2);
|
|
||||||
if (luvs) {
|
|
||||||
VtVec2fArray uvs;
|
|
||||||
uvs.reserve(loopTris.size() * 3);
|
|
||||||
for (MLoopTri lt : loopTris) {
|
|
||||||
uvs.push_back(GfVec2f(luvs[lt.tri[0]]));
|
|
||||||
uvs.push_back(GfVec2f(luvs[lt.tri[1]]));
|
|
||||||
uvs.push_back(GfVec2f(luvs[lt.tri[2]]));
|
|
||||||
}
|
|
||||||
data[HdPrimvarRoleTokens->textureCoordinate] = uvs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ObjectData::set_as_light()
|
|
||||||
{
|
|
||||||
Light *light = (Light *)object->data;
|
|
||||||
data[HdLightTokens->intensity] = light->energy;
|
|
||||||
data[HdLightTokens->color] = GfVec3f(light->r, light->g, light->b);
|
|
||||||
|
|
||||||
switch (light->type) {
|
|
||||||
case LA_LOCAL:
|
|
||||||
data[HdLightTokens->radius] = light->area_size / 2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case LA_SUN:
|
|
||||||
data[HdLightTokens->angle] = light->sun_angle * 180.0 / M_PI;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case LA_SPOT:
|
|
||||||
data[HdLightTokens->shapingConeAngle] = light->spotsize / 2;
|
|
||||||
data[HdLightTokens->shapingConeSoftness] = light->spotblend;
|
|
||||||
data[UsdLuxTokens->treatAsPoint] = 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case LA_AREA:
|
|
||||||
switch (light->area_shape) {
|
|
||||||
case LA_AREA_SQUARE:
|
|
||||||
data[HdLightTokens->width] = light->area_size;
|
|
||||||
data[HdLightTokens->height] = light->area_size;
|
|
||||||
break;
|
|
||||||
case LA_AREA_RECT:
|
|
||||||
data[HdLightTokens->width] = light->area_size;
|
|
||||||
data[HdLightTokens->height] = light->area_sizey;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case LA_AREA_DISK:
|
|
||||||
data[HdLightTokens->radius] = light->area_size / 2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case LA_AREA_ELLIPSE:
|
|
||||||
data[HdLightTokens->radius] = (light->area_size + light->area_sizey) / 4;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace blender::render::hydra
|
} // namespace blender::render::hydra
|
||||||
|
@ -3,66 +3,34 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
#include <pxr/base/gf/matrix4d.h>
|
#include <pxr/base/gf/matrix4d.h>
|
||||||
#include <pxr/usd/sdf/path.h>
|
#include "pxr/base/tf/hashmap.h"
|
||||||
#include <pxr/base/vt/value.h>
|
|
||||||
#include "pxr/base/tf/staticTokens.h"
|
|
||||||
|
|
||||||
#include "DNA_object_types.h"
|
#include "DNA_object_types.h"
|
||||||
|
#include "BKE_layer.h"
|
||||||
|
|
||||||
|
#include "id.h"
|
||||||
#include "material.h"
|
#include "material.h"
|
||||||
|
|
||||||
PXR_NAMESPACE_OPEN_SCOPE
|
|
||||||
#define HD_BLENDER_TOKENS \
|
|
||||||
(materialId) \
|
|
||||||
(faceCounts) \
|
|
||||||
(empty)
|
|
||||||
|
|
||||||
TF_DECLARE_PUBLIC_TOKENS(HdBlenderTokens, HD_BLENDER_TOKENS);
|
|
||||||
PXR_NAMESPACE_CLOSE_SCOPE
|
|
||||||
|
|
||||||
namespace blender::render::hydra {
|
namespace blender::render::hydra {
|
||||||
|
|
||||||
|
class ObjectData;
|
||||||
|
using ObjectDataMap = pxr::TfHashMap<pxr::SdfPath, std::unique_ptr<ObjectData>, pxr::SdfPath::Hash>;
|
||||||
|
|
||||||
class ObjectData {
|
class ObjectData: public IdData {
|
||||||
public:
|
public:
|
||||||
ObjectData();
|
static std::unique_ptr<ObjectData> init(pxr::HdSceneDelegate *scene_delegate, Object *object);
|
||||||
ObjectData(Object *object);
|
static pxr::SdfPath prim_id(pxr::HdSceneDelegate *scene_delegate, Object *object);
|
||||||
|
|
||||||
|
ObjectData(pxr::HdSceneDelegate *scene_delegate, Object *object);
|
||||||
|
|
||||||
std::string name();
|
|
||||||
int type();
|
int type();
|
||||||
pxr::TfToken prim_type();
|
|
||||||
pxr::GfMatrix4d transform();
|
pxr::GfMatrix4d transform();
|
||||||
Material *material();
|
|
||||||
|
|
||||||
pxr::VtValue &get_data(pxr::TfToken const &key);
|
|
||||||
template<class T>
|
|
||||||
const T &get_data(pxr::TfToken const &key);
|
|
||||||
bool has_data(pxr::TfToken const &key);
|
|
||||||
|
|
||||||
void set_material_id(pxr::SdfPath const &id);
|
|
||||||
bool update_visibility(View3D *view3d);
|
bool update_visibility(View3D *view3d);
|
||||||
bool is_visible();
|
|
||||||
|
|
||||||
private:
|
|
||||||
Object *object;
|
|
||||||
std::map<pxr::TfToken, pxr::VtValue> data;
|
|
||||||
bool visible;
|
bool visible;
|
||||||
|
|
||||||
void set_as_mesh();
|
|
||||||
void set_as_meshable();
|
|
||||||
void set_mesh(Mesh *mesh);
|
|
||||||
void set_as_light();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
using ObjectDataMap = std::map<pxr::SdfPath, ObjectData>;
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
const T &ObjectData::get_data(pxr::TfToken const &key)
|
|
||||||
{
|
|
||||||
return get_data(key).Get<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace blender::render::hydra
|
} // namespace blender::render::hydra
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <pxr/base/gf/rotation.h>
|
#include <pxr/base/gf/rotation.h>
|
||||||
#include <pxr/imaging/hd/light.h>
|
#include <pxr/imaging/hd/light.h>
|
||||||
#include <pxr/imaging/hd/tokens.h>
|
#include <pxr/imaging/hd/tokens.h>
|
||||||
|
#include <pxr/imaging/hd/renderDelegate.h>
|
||||||
#include <pxr/usd/usdLux/tokens.h>
|
#include <pxr/usd/usdLux/tokens.h>
|
||||||
|
|
||||||
#include "BKE_context.h"
|
#include "BKE_context.h"
|
||||||
@ -19,31 +20,36 @@
|
|||||||
#include "BKE_image.h"
|
#include "BKE_image.h"
|
||||||
#include "NOD_shader.h"
|
#include "NOD_shader.h"
|
||||||
|
|
||||||
|
#include "glog/logging.h"
|
||||||
|
|
||||||
#include "world.h"
|
#include "world.h"
|
||||||
#include "../utils.h"
|
#include "../utils.h"
|
||||||
|
|
||||||
/* TODO : add custom tftoken "transparency"? */
|
/* TODO : add custom tftoken "transparency"? */
|
||||||
|
|
||||||
using namespace pxr;
|
using namespace pxr;
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace blender::render::hydra {
|
namespace blender::render::hydra {
|
||||||
|
|
||||||
WorldData::WorldData()
|
std::unique_ptr<WorldData> WorldData::init(pxr::HdSceneDelegate *scene_delegate,
|
||||||
: b_context(nullptr),
|
World *world, bContext *context)
|
||||||
world(nullptr)
|
|
||||||
{
|
{
|
||||||
|
return std::make_unique<WorldData>(scene_delegate, world, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
WorldData::WorldData(World *world, bContext *b_context)
|
SdfPath WorldData::prim_id(HdSceneDelegate *scene_delegate)
|
||||||
: b_context(b_context),
|
|
||||||
world(world)
|
|
||||||
{
|
{
|
||||||
data.clear();
|
return scene_delegate->GetDelegateID().AppendElementString("World");
|
||||||
|
}
|
||||||
|
|
||||||
|
WorldData::WorldData(pxr::HdSceneDelegate *scene_delegate, World *world, bContext *context)
|
||||||
|
: IdData(scene_delegate, (ID *)world)
|
||||||
|
{
|
||||||
data[UsdLuxTokens->orientToStageUpAxis] = true;
|
data[UsdLuxTokens->orientToStageUpAxis] = true;
|
||||||
|
|
||||||
if (world->use_nodes) {
|
if (world->use_nodes) {
|
||||||
|
/* TODO: Create nodes parsing system */
|
||||||
|
|
||||||
bNode *output_node = ntreeShaderOutputNode(world->nodetree, SHD_OUTPUT_ALL);
|
bNode *output_node = ntreeShaderOutputNode(world->nodetree, SHD_OUTPUT_ALL);
|
||||||
bNodeSocket input_socket = output_node->input_by_identifier("Surface");
|
bNodeSocket input_socket = output_node->input_by_identifier("Surface");
|
||||||
bNodeLink const *link = input_socket.directly_linked_links()[0];
|
bNodeLink const *link = input_socket.directly_linked_links()[0];
|
||||||
@ -69,16 +75,16 @@ WorldData::WorldData(World *world, bContext *b_context)
|
|||||||
Image *image = (Image *)color_input_node->id;
|
Image *image = (Image *)color_input_node->id;
|
||||||
|
|
||||||
if (image) {
|
if (image) {
|
||||||
Main *bmain = CTX_data_main(b_context);
|
Main *bmain = CTX_data_main(context);
|
||||||
Scene *scene = CTX_data_scene(b_context);
|
Scene *scene = CTX_data_scene(context);
|
||||||
|
|
||||||
ReportList reports;
|
ReportList reports;
|
||||||
ImageSaveOptions opts;
|
ImageSaveOptions opts;
|
||||||
opts.im_format.imtype = R_IMF_IMTYPE_PNG;
|
opts.im_format.imtype = R_IMF_IMTYPE_PNG;
|
||||||
|
|
||||||
string cached_image_path = cache_image(bmain, scene, image, &tex->iuser, &opts, &reports);
|
std::string image_path = cache_image(bmain, scene, image, &tex->iuser, &opts, &reports);
|
||||||
if (!cached_image_path.empty()) {
|
if (!image_path.empty()) {
|
||||||
data[HdLightTokens->textureFile] = SdfAssetPath(cached_image_path, cached_image_path);
|
data[HdLightTokens->textureFile] = SdfAssetPath(image_path, image_path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -91,35 +97,55 @@ WorldData::WorldData(World *world, bContext *b_context)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GfMatrix4d WorldData::transform(string const &renderer_name)
|
GfMatrix4d WorldData::transform()
|
||||||
{
|
{
|
||||||
GfMatrix4d transform = GfMatrix4d().SetIdentity();
|
GfMatrix4d transform = GfMatrix4d(GfRotation(GfVec3d(1.0, 0.0, 0.0), -90), GfVec3d());
|
||||||
|
|
||||||
if (has_data(UsdLuxTokens->orientToStageUpAxis)) {
|
|
||||||
transform *= GfMatrix4d(GfRotation(GfVec3d(1.0, 0.0, 0.0), -90), GfVec3d());
|
|
||||||
}
|
|
||||||
/* TODO : do this check via RenderSettings*/
|
/* TODO : do this check via RenderSettings*/
|
||||||
if (renderer_name == "RPR") {
|
if (scene_delegate->GetRenderIndex().GetRenderDelegate()->GetRendererDisplayName() == "RPR") {
|
||||||
transform *= GfMatrix4d(GfRotation(GfVec3d(1.0, 0.0, 0.0), -180), GfVec3d());
|
transform *= GfMatrix4d(GfRotation(GfVec3d(1.0, 0.0, 0.0), -180), GfVec3d());
|
||||||
transform *= GfMatrix4d(GfRotation(GfVec3d(0.0, 0.0, 1.0), 90.0), GfVec3d());
|
transform *= GfMatrix4d(GfRotation(GfVec3d(0.0, 0.0, 1.0), 90.0), GfVec3d());
|
||||||
}
|
}
|
||||||
|
|
||||||
return transform;
|
return transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
VtValue &WorldData::get_data(TfToken const &key)
|
VtValue WorldData::get_data(TfToken const &key)
|
||||||
{
|
{
|
||||||
return data[key];
|
VtValue ret;
|
||||||
|
auto it = data.find(key);
|
||||||
|
if (it != data.end()) {
|
||||||
|
ret = it->second;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WorldData::has_data(TfToken const &key)
|
void WorldData::insert_prim()
|
||||||
{
|
{
|
||||||
return data.find(key) != data.end();
|
SdfPath p_id = prim_id(scene_delegate);
|
||||||
|
scene_delegate->GetRenderIndex().InsertSprim(HdPrimTypeTokens->domeLight, scene_delegate, p_id);
|
||||||
|
LOG(INFO) << "Add World: id=" << p_id.GetAsString();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WorldData::is_visible()
|
void WorldData::remove_prim()
|
||||||
{
|
{
|
||||||
return true;
|
SdfPath p_id = prim_id(scene_delegate);
|
||||||
|
scene_delegate->GetRenderIndex().RemoveSprim(HdPrimTypeTokens->domeLight, p_id);
|
||||||
|
LOG(INFO) << "Remove World";
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorldData::mark_prim_dirty(DirtyBits dirty_bits)
|
||||||
|
{
|
||||||
|
HdDirtyBits bits = HdLight::Clean;
|
||||||
|
switch (dirty_bits) {
|
||||||
|
case DirtyBits::AllDirty:
|
||||||
|
bits = HdLight::AllDirty;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
SdfPath p_id = prim_id(scene_delegate);
|
||||||
|
scene_delegate->GetRenderIndex().GetChangeTracker().MarkSprimDirty(p_id, bits);
|
||||||
|
LOG(INFO) << "Update World";
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace blender::render::hydra
|
} // namespace blender::render::hydra
|
||||||
|
@ -14,33 +14,26 @@
|
|||||||
#include "DNA_view3d_types.h"
|
#include "DNA_view3d_types.h"
|
||||||
#include "DNA_world_types.h"
|
#include "DNA_world_types.h"
|
||||||
|
|
||||||
|
#include "id.h"
|
||||||
|
|
||||||
namespace blender::render::hydra {
|
namespace blender::render::hydra {
|
||||||
|
|
||||||
class WorldData {
|
class WorldData: public IdData {
|
||||||
public:
|
public:
|
||||||
WorldData();
|
static std::unique_ptr<WorldData> init(pxr::HdSceneDelegate *scene_delegate, World *world, bContext *context);
|
||||||
WorldData(World *world, bContext *b_context);
|
static pxr::SdfPath prim_id(pxr::HdSceneDelegate *scene_delegate);
|
||||||
|
|
||||||
pxr::TfToken prim_type();
|
WorldData(pxr::HdSceneDelegate *scene_delegate, World *world, bContext *context);
|
||||||
pxr::GfMatrix4d transform(std::string const &renderer_name);
|
|
||||||
|
|
||||||
pxr::VtValue &get_data(pxr::TfToken const &key);
|
pxr::GfMatrix4d transform();
|
||||||
template<class T>
|
|
||||||
const T &get_data(pxr::TfToken const &key);
|
|
||||||
bool has_data(pxr::TfToken const &key);
|
|
||||||
bool is_visible();
|
|
||||||
|
|
||||||
bContext *b_context;
|
pxr::VtValue get_data(pxr::TfToken const &key) override;
|
||||||
World *world;
|
void insert_prim() override;
|
||||||
|
void remove_prim() override;
|
||||||
|
void mark_prim_dirty(DirtyBits dirty_bits) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::map<pxr::TfToken, pxr::VtValue> data;
|
std::map<pxr::TfToken, pxr::VtValue> data;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class T>
|
|
||||||
const T &WorldData::get_data(pxr::TfToken const &key)
|
|
||||||
{
|
|
||||||
return get_data(key).Get<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace blender::render::hydra
|
} // namespace blender::render::hydra
|
||||||
|
Loading…
Reference in New Issue
Block a user
seems like we can do this
pure virtual
, because we override this method in every subclass ofObjectData
Let it be not virtual, due to IdData classes design