Export volumes #58

Merged
Bogdan Nagirniak merged 10 commits from BLEN-384 into hydra-render 2023-07-04 09:57:33 +02:00
9 changed files with 264 additions and 8 deletions

View File

@ -87,6 +87,8 @@ set(SRC
scene_delegate/instancer.cc
scene_delegate/image.h
scene_delegate/image.cc
scene_delegate/volume.h
scene_delegate/volume.cc
)
set(LIB

View File

@ -39,7 +39,9 @@ void PreviewEngine::update_render_result(std::vector<float> &pixels)
RenderLayer *layer = (RenderLayer *)result->layers.first;
RenderPass *pass = (RenderPass *)layer->passes.first;
memcpy(pass->buffer.data, pixels.data(), sizeof(float) * pass->rectx * pass->recty * pass->channels);
memcpy(pass->buffer.data,
pixels.data(),
sizeof(float) * pass->rectx * pass->recty * pass->channels);
RE_engine_end_result(bl_engine_, result, false, false, false);
}

View File

@ -63,6 +63,10 @@ pxr::VtValue BlenderSceneDelegate::Get(pxr::SdfPath const &id, pxr::TfToken cons
if (c_data) {
return c_data->get_data(id, key);
}
VolumeData *v_data = volume_data(id);
if (v_data) {
return v_data->get_data(id, key);
}
ObjectData *obj_data = object_data(id);
if (obj_data) {
return obj_data->get_data(key);
@ -122,6 +126,10 @@ pxr::SdfPath BlenderSceneDelegate::GetMaterialId(pxr::SdfPath const &rprim_id)
if (c_data) {
return c_data->material_id();
}
VolumeData *v_data = volume_data(rprim_id);
if (v_data) {
return v_data->material_id();
}
return pxr::SdfPath();
}
@ -192,6 +200,14 @@ pxr::GfMatrix4d BlenderSceneDelegate::GetInstancerTransform(pxr::SdfPath const &
return i_data->transform;
}
pxr::HdVolumeFieldDescriptorVector BlenderSceneDelegate::GetVolumeFieldDescriptors(
pxr::SdfPath const &volume_id)
{
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 3, "%s", volume_id.GetText());
VolumeData *v_data = volume_data(volume_id);
return v_data->field_descriptors();
}
void BlenderSceneDelegate::populate(Depsgraph *deps, bContext *cont)
{
bool is_populated = depsgraph != nullptr;
@ -272,7 +288,9 @@ pxr::SdfPath BlenderSceneDelegate::world_prim_id() const
ObjectData *BlenderSceneDelegate::object_data(pxr::SdfPath const &id) const
{
pxr::SdfPath p_id = (id.GetName().find("SM_") == 0) ? id.GetParentPath() : id;
pxr::SdfPath p_id = (id.GetName().find("SM_") == 0 || id.GetName().find("VF_") == 0) ?
id.GetParentPath() :
id;
auto obj_data = objects_.lookup_ptr(p_id);
if (obj_data) {
return obj_data->get();
@ -333,6 +351,11 @@ InstancerData *BlenderSceneDelegate::instancer_data(pxr::SdfPath const &id, bool
return nullptr;
}
VolumeData *BlenderSceneDelegate::volume_data(pxr::SdfPath const &id) const
{
return dynamic_cast<VolumeData *>(object_data(id));
}
void BlenderSceneDelegate::update_objects(Object *object)
{
if (!ObjectData::is_supported(object)) {
@ -583,6 +606,10 @@ void BlenderSceneDelegate::remove_unused_objects()
if (c_data) {
c_data->available_materials(available_materials);
}
VolumeData *v_data = dynamic_cast<VolumeData *>(val.get());
if (v_data) {
v_data->available_materials(available_materials);
}
}
for (auto &val : instancers_.values()) {
val->available_materials(available_materials);

View File

@ -17,6 +17,7 @@
#include "light.h"
#include "mesh.h"
#include "object.h"
#include "volume.h"
#include "world.h"
namespace blender::render::hydra {
@ -28,6 +29,7 @@ class Engine;
class BlenderSceneDelegate : public pxr::HdSceneDelegate {
friend ObjectData; /* has access to instances */
friend CurvesData; /* has access to materials */
friend VolumeData; /* has access to materials */
friend MeshData; /* has access to materials */
friend MaterialData; /* has access to objects and instancers */
@ -60,6 +62,8 @@ class BlenderSceneDelegate : public pxr::HdSceneDelegate {
pxr::VtIntArray GetInstanceIndices(pxr::SdfPath const &instancer_id,
pxr::SdfPath const &prototype_id) override;
pxr::GfMatrix4d GetInstancerTransform(pxr::SdfPath const &instancer_id) override;
pxr::HdVolumeFieldDescriptorVector GetVolumeFieldDescriptors(
pxr::SdfPath const &volume_id) override;
void populate(Depsgraph *depsgraph, bContext *context);
void clear();
@ -85,6 +89,7 @@ class BlenderSceneDelegate : public pxr::HdSceneDelegate {
LightData *light_data(pxr::SdfPath const &id) const;
MaterialData *material_data(pxr::SdfPath const &id) const;
InstancerData *instancer_data(pxr::SdfPath const &id, bool child_id = false) const;
VolumeData *volume_data(pxr::SdfPath const &id) const;
void update_objects(Object *object);
void update_instancers(Object *object);

View File

@ -26,7 +26,7 @@ void CurvesData::init()
Object *object = (Object *)id;
write_curves((Curves *)object->data);
write_transform();
write_material();
write_materials();
}
void CurvesData::insert()
@ -38,7 +38,7 @@ void CurvesData::insert()
void CurvesData::remove()
{
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 2, "%s", prim_id.GetText());
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 1, "%s", prim_id.GetText());
scene_delegate_->GetRenderIndex().RemoveRprim(prim_id);
}
@ -51,7 +51,7 @@ void CurvesData::update()
bits = pxr::HdChangeTracker::AllDirty;
}
if (id->recalc & ID_RECALC_SHADING) {
write_material();
write_materials();
bits |= pxr::HdChangeTracker::DirtyMaterialId | pxr::HdChangeTracker::DirtyDoubleSided;
}
if (id->recalc & ID_RECALC_TRANSFORM) {
@ -179,7 +179,7 @@ void CurvesData::write_uv_maps(Curves *curves)
}
}
void CurvesData::write_material()
void CurvesData::write_materials()
{
Object *object = (Object *)id;
Material *mat = nullptr;

View File

@ -35,7 +35,7 @@ class CurvesData : public ObjectData {
private:
void write_curves(Curves *curves);
void write_uv_maps(Curves *curves);
void write_material();
void write_materials();
pxr::VtIntArray curve_vertex_counts_;
pxr::VtVec3fArray vertices_;

View File

@ -9,6 +9,7 @@
#include "light.h"
#include "mesh.h"
#include "object.h"
#include "volume.h"
namespace blender::render::hydra {
@ -39,7 +40,9 @@ std::unique_ptr<ObjectData> ObjectData::create(BlenderSceneDelegate *scene_deleg
case OB_LAMP:
data = std::make_unique<LightData>(scene_delegate, object, prim_id);
break;
case OB_VOLUME:
data = std::make_unique<VolumeData>(scene_delegate, object, prim_id);
break;
default:
break;
}
@ -56,6 +59,7 @@ bool ObjectData::is_supported(Object *object)
case OB_CURVES_LEGACY:
case OB_MBALL:
case OB_LAMP:
case OB_VOLUME:
return true;
default:

View File

@ -0,0 +1,179 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2011-2022 Blender Foundation */
#include <pxr/imaging/hd/bprim.h>
#include <pxr/imaging/hd/tokens.h>
#include <pxr/imaging/hd/volumeFieldSchema.h>
#include <pxr/usd/usdHydra/tokens.h>
#include <pxr/usd/usdVol/tokens.h>
#include <pxr/usdImaging/usdVolImaging/tokens.h>
#include "BKE_material.h"
#include "BKE_volume.h"
#include "BLI_index_range.hh"
#include "DNA_volume_types.h"
#include "blender_scene_delegate.h"
#include "volume.h"
namespace blender::render::hydra {
VolumeData::VolumeData(BlenderSceneDelegate *scene_delegate,
Object *object,
pxr::SdfPath const &prim_id)
: ObjectData(scene_delegate, object, prim_id)
{
}
void VolumeData::init()
{
ID_LOG(1, "");
Volume *volume = (Volume *)((Object *)this->id)->data;
Main *main = CTX_data_main(scene_delegate_->context);
if (!BKE_volume_load(volume, main)) {
return;
}
filepath_ = BKE_volume_grids_frame_filepath(volume);
if (volume->runtime.grids) {
const int num_grids = BKE_volume_num_grids(volume);
if (num_grids) {
for (const int i : IndexRange(num_grids)) {
const VolumeGrid *grid = BKE_volume_grid_get_for_read(volume, i);
const std::string grid_name = BKE_volume_grid_name(grid);
field_descriptors_.emplace_back(pxr::TfToken(grid_name),
pxr::UsdVolImagingTokens->openvdbAsset,
prim_id.AppendElementString("VF_" + grid_name));
}
}
}
write_transform();
write_materials();
BKE_volume_unload(volume);
}
void VolumeData::insert()
{
scene_delegate_->GetRenderIndex().InsertRprim(
pxr::HdPrimTypeTokens->volume, scene_delegate_, prim_id);
ID_LOG(1, "");
for (auto &desc : field_descriptors_) {
scene_delegate_->GetRenderIndex().InsertBprim(
desc.fieldPrimType, scene_delegate_, desc.fieldId);
ID_LOG(1, "Volume field %s", desc.fieldId.GetText());
}
}
void VolumeData::remove()
{
for (auto &desc : field_descriptors_) {
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 1, "%s", desc.fieldId.GetText());
scene_delegate_->GetRenderIndex().RemoveBprim(desc.fieldPrimType, desc.fieldId);
}
CLOG_INFO(LOG_RENDER_HYDRA_SCENE, 1, "%s", prim_id.GetText());
scene_delegate_->GetRenderIndex().RemoveRprim(prim_id);
}
void VolumeData::update()
{
Object *object = (Object *)id;
pxr::HdDirtyBits bits = pxr::HdChangeTracker::Clean;
if ((id->recalc & ID_RECALC_GEOMETRY) || (((ID *)object->data)->recalc & ID_RECALC_GEOMETRY)) {
init();
bits = pxr::HdChangeTracker::AllDirty;
}
if (id->recalc & ID_RECALC_SHADING) {
write_materials();
bits |= pxr::HdChangeTracker::DirtyMaterialId | pxr::HdChangeTracker::DirtyDoubleSided;
}
if (id->recalc & ID_RECALC_TRANSFORM) {
write_transform();
bits |= pxr::HdChangeTracker::DirtyTransform;
}
if (bits == pxr::HdChangeTracker::Clean) {
return;
}
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkRprimDirty(prim_id, bits);
ID_LOG(1, "");
}
pxr::VtValue VolumeData::get_data(pxr::SdfPath const &id, pxr::TfToken const &key) const
{
if (key == pxr::HdVolumeFieldSchemaTokens->filePath) {
return pxr::VtValue(pxr::SdfAssetPath(filepath_, filepath_));
}
if (key == pxr::HdVolumeFieldSchemaTokens->fieldName) {
std::string name = id.GetName();
return pxr::VtValue(pxr::TfToken(name.substr(name.find("VF_") + 3)));
}
if (key == pxr::HdVolumeFieldSchemaTokens->fieldIndex) {
return pxr::VtValue(0);
}
if (key == pxr::UsdHydraTokens->textureMemory) {
return pxr::VtValue(0.0f);
}
return pxr::VtValue();
}
Review

rename to field_descriptors

rename to `field_descriptors`
bool VolumeData::update_visibility()
{
bool ret = ObjectData::update_visibility();
if (ret) {
scene_delegate_->GetRenderIndex().GetChangeTracker().MarkRprimDirty(
prim_id, pxr::HdChangeTracker::DirtyVisibility);
ID_LOG(1, "");
}
return ret;
}
pxr::HdVolumeFieldDescriptorVector VolumeData::field_descriptors() const
{
return field_descriptors_;
}
pxr::SdfPath VolumeData::material_id() const
{
if (!mat_data_) {
return pxr::SdfPath();
}
return mat_data_->prim_id;
}
void VolumeData::available_materials(Set<pxr::SdfPath> &paths) const
{
if (mat_data_ && !mat_data_->prim_id.IsEmpty()) {
paths.add(mat_data_->prim_id);
}
}
void VolumeData::write_materials()
{
Object *object = (Object *)id;
Material *mat = nullptr;
/* TODO: Using only first material. Add support for multimaterial. */
if (BKE_object_material_count_eval(object) > 0) {
mat = BKE_object_material_get_eval(object, 0);
}
if (!mat) {
mat_data_ = nullptr;
return;
}
pxr::SdfPath p_id = scene_delegate_->material_prim_id(mat);
mat_data_ = scene_delegate_->material_data(p_id);
if (!mat_data_) {
scene_delegate_->materials_.add_new(
p_id, std::make_unique<MaterialData>(scene_delegate_, mat, p_id));
mat_data_ = scene_delegate_->material_data(p_id);
mat_data_->init();
mat_data_->insert();
}
}
} // namespace blender::render::hydra

View File

@ -0,0 +1,37 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2011-2022 Blender Foundation */
#pragma once
#include <pxr/imaging/hd/sceneDelegate.h>
#include "object.h"
namespace blender::render::hydra {
class VolumeData : public ObjectData {
public:
VolumeData(BlenderSceneDelegate *scene_delegate, Object *object, pxr::SdfPath const &prim_id);
void init() override;
void insert() override;
void remove() override;
void update() override;
pxr::VtValue get_data(pxr::SdfPath const &id, pxr::TfToken const &key) const;
bool update_visibility() override;
pxr::HdVolumeFieldDescriptorVector field_descriptors() const;
pxr::SdfPath material_id() const;
void available_materials(Set<pxr::SdfPath> &paths) const;
private:
void write_materials();
std::string filepath_;
pxr::HdVolumeFieldDescriptorVector field_descriptors_;
MaterialData *mat_data_ = nullptr;
};
} // namespace blender::render::hydra