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/light.cc
|
||||||
scene_delegate/world.h
|
scene_delegate/world.h
|
||||||
scene_delegate/world.cc
|
scene_delegate/world.cc
|
||||||
|
scene_delegate/instancer.h
|
||||||
|
scene_delegate/instancer.cc
|
||||||
)
|
)
|
||||||
|
|
||||||
set(LIB
|
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);
|
CLOG_INFO(LOG_BSD, 2, "%s", id->name);
|
||||||
|
|
||||||
Light *light = (Light *)((Object *)id)->data;
|
Light *light = (Light *)((Object *)id)->data;
|
||||||
|
data.clear();
|
||||||
|
|
||||||
data[pxr::HdLightTokens->intensity] = scene_delegate->engine_type ==
|
float intensity = light->energy;
|
||||||
BlenderSceneDelegate::EngineType::PREVIEW ?
|
if (scene_delegate->engine_type == BlenderSceneDelegate::EngineType::PREVIEW) {
|
||||||
light->energy / 1000 :
|
intensity *= 0.001;
|
||||||
light->energy;
|
}
|
||||||
|
data[pxr::HdLightTokens->intensity] = intensity;
|
||||||
|
|
||||||
data[pxr::HdLightTokens->color] = pxr::GfVec3f(light->r, light->g, light->b);
|
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;
|
pxr::HdDirtyBits bits = pxr::HdLight::Clean;
|
||||||
if (id->recalc & ID_RECALC_GEOMETRY) {
|
if (id->recalc & ID_RECALC_GEOMETRY) {
|
||||||
data.clear();
|
|
||||||
init();
|
init();
|
||||||
bits = pxr::HdLight::AllDirty;
|
bits = pxr::HdLight::AllDirty;
|
||||||
}
|
}
|
||||||
|
@ -48,40 +48,9 @@ MaterialData::MaterialData(BlenderSceneDelegate *scene_delegate, Material *mater
|
|||||||
void MaterialData::init()
|
void MaterialData::init()
|
||||||
{
|
{
|
||||||
CLOG_INFO(LOG_BSD, 2, "%s", id->name);
|
CLOG_INFO(LOG_BSD, 2, "%s", id->name);
|
||||||
export_mtlx();
|
|
||||||
}
|
|
||||||
|
|
||||||
pxr::VtValue MaterialData::get_data(pxr::TfToken const &key) const
|
material_network_map = pxr::VtValue();
|
||||||
{
|
|
||||||
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()
|
|
||||||
{
|
|
||||||
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() */
|
/* Call of python function hydra.export_mtlx() */
|
||||||
|
|
||||||
PyGILState_STATE gstate;
|
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());
|
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()
|
void MaterialData::insert()
|
||||||
{
|
{
|
||||||
CLOG_INFO(LOG_BSD, 2, "%s", id->name);
|
CLOG_INFO(LOG_BSD, 2, "%s", id->name);
|
||||||
@ -134,7 +133,6 @@ void MaterialData::remove()
|
|||||||
void MaterialData::update()
|
void MaterialData::update()
|
||||||
{
|
{
|
||||||
CLOG_INFO(LOG_BSD, 2, "%s", id->name);
|
CLOG_INFO(LOG_BSD, 2, "%s", id->name);
|
||||||
mtlx_path = pxr::SdfAssetPath("", "");
|
|
||||||
init();
|
init();
|
||||||
scene_delegate->GetRenderIndex().GetChangeTracker().MarkSprimDirty(p_id, pxr::HdMaterial::AllDirty);
|
scene_delegate->GetRenderIndex().GetChangeTracker().MarkSprimDirty(p_id, pxr::HdMaterial::AllDirty);
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,7 @@ class MaterialData : IdData {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
pxr::SdfAssetPath mtlx_path;
|
pxr::SdfAssetPath mtlx_path;
|
||||||
|
pxr::VtValue material_network_map;
|
||||||
};
|
};
|
||||||
|
|
||||||
using MaterialDataMap =
|
using MaterialDataMap =
|
||||||
|
@ -149,6 +149,12 @@ void MeshData::add_instance(DupliObject *dupli)
|
|||||||
|
|
||||||
void MeshData::set_mesh(Mesh *mesh)
|
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);
|
BKE_mesh_calc_normals_split(mesh);
|
||||||
int tris_len = BKE_mesh_runtime_looptri_len(mesh);
|
int tris_len = BKE_mesh_runtime_looptri_len(mesh);
|
||||||
if (tris_len == 0) {
|
if (tris_len == 0) {
|
||||||
@ -265,11 +271,6 @@ void MeshData::update()
|
|||||||
Object *object = (Object *)id;
|
Object *object = (Object *)id;
|
||||||
if ((id->recalc & ID_RECALC_GEOMETRY) || (((ID *)object->data)->recalc & ID_RECALC_GEOMETRY)) {
|
if ((id->recalc & ID_RECALC_GEOMETRY) || (((ID *)object->data)->recalc & ID_RECALC_GEOMETRY)) {
|
||||||
instancer_id = pxr::SdfPath::EmptyPath();
|
instancer_id = pxr::SdfPath::EmptyPath();
|
||||||
face_vertex_counts.clear();
|
|
||||||
face_vertex_indices.clear();
|
|
||||||
vertices.clear();
|
|
||||||
normals.clear();
|
|
||||||
uvs.clear();
|
|
||||||
|
|
||||||
init();
|
init();
|
||||||
bits = pxr::HdChangeTracker::AllDirty;
|
bits = pxr::HdChangeTracker::AllDirty;
|
||||||
|
@ -42,7 +42,7 @@ class MeshData : public ObjectData {
|
|||||||
|
|
||||||
pxr::SdfPath instancer_id;
|
pxr::SdfPath instancer_id;
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
void set_mesh(Mesh *mesh);
|
void set_mesh(Mesh *mesh);
|
||||||
void set_material();
|
void set_material();
|
||||||
|
|
||||||
|
@ -36,7 +36,6 @@ std::unique_ptr<ObjectData> ObjectData::create(BlenderSceneDelegate *scene_deleg
|
|||||||
case OB_MESH:
|
case OB_MESH:
|
||||||
case OB_SURF:
|
case OB_SURF:
|
||||||
case OB_FONT:
|
case OB_FONT:
|
||||||
case OB_CURVES:
|
|
||||||
case OB_CURVES_LEGACY:
|
case OB_CURVES_LEGACY:
|
||||||
case OB_MBALL:
|
case OB_MBALL:
|
||||||
data = std::make_unique<MeshData>(scene_delegate, object);
|
data = std::make_unique<MeshData>(scene_delegate, object);
|
||||||
|
@ -22,7 +22,7 @@ class ObjectData : public IdData {
|
|||||||
|
|
||||||
ObjectData(BlenderSceneDelegate *scene_delegate, Object *object);
|
ObjectData(BlenderSceneDelegate *scene_delegate, Object *object);
|
||||||
|
|
||||||
pxr::GfMatrix4d transform();
|
virtual pxr::GfMatrix4d transform();
|
||||||
virtual bool update_visibility(View3D *view3d);
|
virtual bool update_visibility(View3D *view3d);
|
||||||
|
|
||||||
bool visible;
|
bool visible;
|
||||||
|
@ -55,6 +55,7 @@ void WorldData::init()
|
|||||||
CLOG_INFO(LOG_BSD, 2, "%s", id->name);
|
CLOG_INFO(LOG_BSD, 2, "%s", id->name);
|
||||||
|
|
||||||
World *world = (World *)id;
|
World *world = (World *)id;
|
||||||
|
data.clear();
|
||||||
|
|
||||||
data[pxr::UsdLuxTokens->orientToStageUpAxis] = true;
|
data[pxr::UsdLuxTokens->orientToStageUpAxis] = true;
|
||||||
|
|
||||||
@ -163,7 +164,6 @@ void WorldData::remove()
|
|||||||
void WorldData::update()
|
void WorldData::update()
|
||||||
{
|
{
|
||||||
CLOG_INFO(LOG_BSD, 2, "%s", id->name);
|
CLOG_INFO(LOG_BSD, 2, "%s", id->name);
|
||||||
data.clear();
|
|
||||||
init();
|
init();
|
||||||
scene_delegate->GetRenderIndex().GetChangeTracker().MarkSprimDirty(p_id, pxr::HdLight::AllDirty);
|
scene_delegate->GetRenderIndex().GetChangeTracker().MarkSprimDirty(p_id, pxr::HdLight::AllDirty);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user