forked from blender/blender
BLEN-359: Implement updates for instances in viewport #20
@ -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
|
||||
|
157
source/blender/render/hydra/scene_delegate/instancer.cc
Normal file
157
source/blender/render/hydra/scene_delegate/instancer.cc
Normal 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
|
43
source/blender/render/hydra/scene_delegate/instancer.h
Normal file
43
source/blender/render/hydra/scene_delegate/instancer.h
Normal 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
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ class MaterialData : IdData {
|
||||
|
||||
private:
|
||||
pxr::SdfAssetPath mtlx_path;
|
||||
pxr::VtValue material_network_map;
|
||||
};
|
||||
|
||||
using MaterialDataMap =
|
||||
|
@ -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;
|
||||
|
@ -42,7 +42,7 @@ class MeshData : public ObjectData {
|
||||
|
||||
pxr::SdfPath instancer_id;
|
||||
|
||||
private:
|
||||
protected:
|
||||
void set_mesh(Mesh *mesh);
|
||||
void set_material();
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user