BLEN-359: Implement updates for instances in viewport #20

Merged
Bogdan Nagirniak merged 20 commits from BLEN-359_1 into hydra-render 2023-04-05 11:47:37 +02:00
11 changed files with 249 additions and 47 deletions
Showing only changes of commit 310a758f36 - Show all commits

View File

@ -85,6 +85,8 @@ set(SRC
scene_delegate/light.cc
scene_delegate/world.h
scene_delegate/world.cc
scene_delegate/instancer.h
scene_delegate/instancer.cc
)
set(LIB

View File

@ -0,0 +1,157 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2011-2022 Blender Foundation */
#include <pxr/base/gf/vec2f.h>
#include "blender_scene_delegate.h"
#include "instancer.h"
#include "../utils.h"
using namespace pxr;
namespace blender::render::hydra {
bool InstancerData::supported(Object *object)
{
switch (object->type) {
case OB_MESH:
case OB_SURF:
case OB_FONT:
case OB_CURVES_LEGACY:
case OB_MBALL:
return true;
default:
break;
}
return false;
}
std::unique_ptr<InstancerData> InstancerData::create(BlenderSceneDelegate *scene_delegate, Object *object)
{
auto data = std::make_unique<InstancerData>(scene_delegate, object);
data->init();
data->insert();
return data;
}
SdfPath InstancerData::prim_id(BlenderSceneDelegate *scene_delegate, Object *object)
{
/* Making id of instancer in form like I_<pointer in 16 hex digits format>. Example:
* I_000002073e369608 */
char str[32];
snprintf(str, 32, "I_%016llx", (uint64_t)object);
return scene_delegate->GetDelegateID().AppendElementString(str);
}
InstancerData::InstancerData(BlenderSceneDelegate *scene_delegate, Object *object)
: MeshData(scene_delegate, object)
{
p_id = prim_id(scene_delegate, object);
instancer_id = p_id.AppendElementString("Instancer");
}
void InstancerData::init()
{
MeshData::init();
/* USD hides the prototype mesh when instancing in contrary to the Blender,
so we must add it back implicitly */
transforms.clear();
transforms.push_back(GfMatrix4d(1.0));
}
GfMatrix4d InstancerData::transform()
{
return GfMatrix4d(1.0);
}
VtValue InstancerData::get_data(TfToken const &key) const
{
if (key == HdInstancerTokens->instanceTransform) {
return VtValue(transforms);
}
return MeshData::get_data(key);
}
HdPrimvarDescriptorVector InstancerData::instancer_primvar_descriptors(HdInterpolation interpolation)
{
HdPrimvarDescriptorVector primvars;
if (interpolation == HdInterpolationInstance) {
primvars.emplace_back(
HdInstancerTokens->instanceTransform, interpolation, HdPrimvarRoleTokens->none);
}
return primvars;
}
VtIntArray InstancerData::instance_indices()
{
VtIntArray ret(transforms.size());
for (size_t i = 0; i < ret.size(); ++i) {
ret[i] = i;
}
return ret;
}
size_t InstancerData::sample_instancer_transform(size_t maxSampleCount,
float *sampleTimes,
GfMatrix4d *sampleValues)
{
*sampleTimes = 0.0f;
*sampleValues = GfMatrix4d(1.0);
return 1;
}
size_t InstancerData::sample_instancer_primvar(TfToken const &key,
size_t maxSampleCount,
float *sampleTimes,
VtValue *sampleValues)
{
if (key == HdInstancerTokens->instanceTransform) {
if (maxSampleCount > 0) {
sampleTimes[0] = 0.0f;
sampleValues[0] = transforms;
return 1;
}
}
return 0;
}
void InstancerData::add_instance(DupliObject *dupli)
{
CLOG_INFO(LOG_BSD, 2, "%s - %d", id->name, dupli->random_id);
transforms.push_back(transform().GetInverse() * gf_matrix_from_transform(dupli->mat));
}
void InstancerData::insert()
{
CLOG_INFO(LOG_BSD, 2, "%s", id->name);
MeshData::insert();
if (face_vertex_counts.empty()) {
return;
}
scene_delegate->GetRenderIndex().InsertInstancer(scene_delegate, instancer_id);
}
void InstancerData::remove()
{
CLOG_INFO(LOG_BSD, 2, "%s", id->name);
if (!scene_delegate->GetRenderIndex().HasInstancer(instancer_id)) {
return;
}
scene_delegate->GetRenderIndex().RemoveInstancer(instancer_id);
MeshData::remove();
}
void InstancerData::update()
{
CLOG_INFO(LOG_BSD, 2, "%s", id->name);
MeshData::update();
}
} // namespace blender::render::hydra

View File

@ -0,0 +1,43 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2011-2022 Blender Foundation */
#pragma once
#include "BKE_duplilist.h"
#include "mesh.h"
namespace blender::render::hydra {
class InstancerData: public MeshData {
public:
static bool supported(Object *object);
static std::unique_ptr<InstancerData> create(BlenderSceneDelegate *scene_delegate, Object *object);
static pxr::SdfPath prim_id(BlenderSceneDelegate *scene_delegate, Object *object);
InstancerData(BlenderSceneDelegate *scene_delegate, Object *object);
void init() override;
void insert() override;
void remove() override;
void update() override;
pxr::VtValue get_data(pxr::TfToken const &key) const override;
pxr::GfMatrix4d transform() override;
pxr::HdPrimvarDescriptorVector instancer_primvar_descriptors(pxr::HdInterpolation interpolation);
pxr::VtIntArray instance_indices();
size_t sample_instancer_transform(size_t maxSampleCount, float *sampleTimes, pxr::GfMatrix4d *sampleValues);
size_t sample_instancer_primvar(pxr::TfToken const &key,
size_t maxSampleCount,
float *sampleTimes,
pxr::VtValue *sampleValues);
void add_instance(DupliObject *dupli);
pxr::SdfPath instancer_id;
private:
pxr::VtMatrix4dArray transforms;
};
} // namespace blender::render::hydra

View File

@ -26,11 +26,13 @@ void LightData::init()
CLOG_INFO(LOG_BSD, 2, "%s", id->name);
Light *light = (Light *)((Object *)id)->data;
data.clear();
data[pxr::HdLightTokens->intensity] = scene_delegate->engine_type ==
BlenderSceneDelegate::EngineType::PREVIEW ?
light->energy / 1000 :
light->energy;
float intensity = light->energy;
if (scene_delegate->engine_type == BlenderSceneDelegate::EngineType::PREVIEW) {
intensity *= 0.001;
}
data[pxr::HdLightTokens->intensity] = intensity;
data[pxr::HdLightTokens->color] = pxr::GfVec3f(light->r, light->g, light->b);
@ -170,7 +172,6 @@ void LightData::update()
pxr::HdDirtyBits bits = pxr::HdLight::Clean;
if (id->recalc & ID_RECALC_GEOMETRY) {
data.clear();
init();
bits = pxr::HdLight::AllDirty;
}

View File

@ -48,40 +48,9 @@ MaterialData::MaterialData(BlenderSceneDelegate *scene_delegate, Material *mater
void MaterialData::init()
{
CLOG_INFO(LOG_BSD, 2, "%s", id->name);
export_mtlx();
}
pxr::VtValue MaterialData::get_data(pxr::TfToken const &key) const
{
pxr::VtValue ret;
if (key.GetString() == "MaterialXFilename") {
if (!mtlx_path.GetResolvedPath().empty()) {
ret = mtlx_path;
}
CLOG_INFO(LOG_BSD, 3, "%s", key.GetText());
}
return ret;
}
material_network_map = pxr::VtValue();
pxr::VtValue MaterialData::material_resource()
{
std::string const &path = mtlx_path.GetResolvedPath();
if (!path.empty()) {
pxr::HdRenderDelegate *render_delegate = scene_delegate->GetRenderIndex().GetRenderDelegate();
pxr::TfTokenVector shader_source_types = render_delegate->GetShaderSourceTypes();
pxr::TfTokenVector render_contexts = render_delegate->GetMaterialRenderContexts();
pxr::HdMaterialNetworkMap material_network_map;
HdMtlxConvertToMaterialNetworkMap(
path, shader_source_types, render_contexts, &material_network_map);
return pxr::VtValue(material_network_map);
}
return pxr::VtValue();
}
void MaterialData::export_mtlx()
{
/* Call of python function hydra.export_mtlx() */
PyGILState_STATE gstate;
@ -118,6 +87,36 @@ void MaterialData::export_mtlx()
CLOG_INFO(LOG_BSD, 2, "Export: %s, mtlx=%s", id->name, mtlx_path.GetResolvedPath().c_str());
}
pxr::VtValue MaterialData::get_data(pxr::TfToken const &key) const
{
pxr::VtValue ret;
if (key.GetString() == "MaterialXFilename") {
if (!mtlx_path.GetResolvedPath().empty()) {
ret = mtlx_path;
}
CLOG_INFO(LOG_BSD, 3, "%s", key.GetText());
}
return ret;
}
pxr::VtValue MaterialData::material_resource()
{
if (material_network_map.IsEmpty()) {
const std::string &path = mtlx_path.GetResolvedPath();
if (!path.empty()) {
pxr::HdRenderDelegate *render_delegate = scene_delegate->GetRenderIndex().GetRenderDelegate();
pxr::TfTokenVector shader_source_types = render_delegate->GetShaderSourceTypes();
pxr::TfTokenVector render_contexts = render_delegate->GetMaterialRenderContexts();
pxr::HdMaterialNetworkMap network_map;
HdMtlxConvertToMaterialNetworkMap(path, shader_source_types, render_contexts, &network_map);
material_network_map = network_map;
}
}
return material_network_map;
}
void MaterialData::insert()
{
CLOG_INFO(LOG_BSD, 2, "%s", id->name);
@ -134,7 +133,6 @@ void MaterialData::remove()
void MaterialData::update()
{
CLOG_INFO(LOG_BSD, 2, "%s", id->name);
mtlx_path = pxr::SdfAssetPath("", "");
init();
scene_delegate->GetRenderIndex().GetChangeTracker().MarkSprimDirty(p_id, pxr::HdMaterial::AllDirty);
}

View File

@ -36,6 +36,7 @@ class MaterialData : IdData {
private:
pxr::SdfAssetPath mtlx_path;
pxr::VtValue material_network_map;
};
using MaterialDataMap =

View File

@ -149,6 +149,12 @@ void MeshData::add_instance(DupliObject *dupli)
void MeshData::set_mesh(Mesh *mesh)
{
face_vertex_counts.clear();
face_vertex_indices.clear();
vertices.clear();
normals.clear();
uvs.clear();
BKE_mesh_calc_normals_split(mesh);
int tris_len = BKE_mesh_runtime_looptri_len(mesh);
if (tris_len == 0) {
@ -265,11 +271,6 @@ void MeshData::update()
Object *object = (Object *)id;
if ((id->recalc & ID_RECALC_GEOMETRY) || (((ID *)object->data)->recalc & ID_RECALC_GEOMETRY)) {
instancer_id = pxr::SdfPath::EmptyPath();
face_vertex_counts.clear();
face_vertex_indices.clear();
vertices.clear();
normals.clear();
uvs.clear();
init();
bits = pxr::HdChangeTracker::AllDirty;

View File

@ -42,7 +42,7 @@ class MeshData : public ObjectData {
pxr::SdfPath instancer_id;
private:
protected:
void set_mesh(Mesh *mesh);
void set_material();

View File

@ -36,7 +36,6 @@ std::unique_ptr<ObjectData> ObjectData::create(BlenderSceneDelegate *scene_deleg
case OB_MESH:
case OB_SURF:
case OB_FONT:
case OB_CURVES:
case OB_CURVES_LEGACY:
case OB_MBALL:
data = std::make_unique<MeshData>(scene_delegate, object);

View File

@ -22,7 +22,7 @@ class ObjectData : public IdData {
ObjectData(BlenderSceneDelegate *scene_delegate, Object *object);
pxr::GfMatrix4d transform();
virtual pxr::GfMatrix4d transform();
virtual bool update_visibility(View3D *view3d);
bool visible;

View File

@ -55,6 +55,7 @@ void WorldData::init()
CLOG_INFO(LOG_BSD, 2, "%s", id->name);
World *world = (World *)id;
data.clear();
data[pxr::UsdLuxTokens->orientToStageUpAxis] = true;
@ -163,7 +164,6 @@ void WorldData::remove()
void WorldData::update()
{
CLOG_INFO(LOG_BSD, 2, "%s", id->name);
data.clear();
init();
scene_delegate->GetRenderIndex().GetChangeTracker().MarkSprimDirty(p_id, pxr::HdLight::AllDirty);
}