forked from blender/blender
Export volumes from object modifier (quick effect) #62
@ -89,6 +89,8 @@ set(SRC
|
|||||||
scene_delegate/image.cc
|
scene_delegate/image.cc
|
||||||
scene_delegate/volume.h
|
scene_delegate/volume.h
|
||||||
scene_delegate/volume.cc
|
scene_delegate/volume.cc
|
||||||
|
scene_delegate/volume_modifier.h
|
||||||
|
scene_delegate/volume_modifier.cc
|
||||||
)
|
)
|
||||||
|
|
||||||
set(LIB
|
set(LIB
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "mesh.h"
|
#include "mesh.h"
|
||||||
#include "object.h"
|
#include "object.h"
|
||||||
#include "volume.h"
|
#include "volume.h"
|
||||||
|
#include "volume_modifier.h"
|
||||||
#include "world.h"
|
#include "world.h"
|
||||||
|
|
||||||
namespace blender::render::hydra {
|
namespace blender::render::hydra {
|
||||||
|
@ -25,8 +25,8 @@ std::unique_ptr<ObjectData> ObjectData::create(BlenderSceneDelegate *scene_deleg
|
|||||||
{
|
{
|
||||||
std::unique_ptr<ObjectData> data;
|
std::unique_ptr<ObjectData> data;
|
||||||
|
|
||||||
if (VolumeData::is_volume_modifier(object)) {
|
if (VolumeModifierData::is_volume_modifier(object)) {
|
||||||
return std::make_unique<VolumeData>(scene_delegate, object, prim_id);
|
return std::make_unique<VolumeModifierData>(scene_delegate, object, prim_id);
|
||||||
DagerD marked this conversation as resolved
Outdated
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (object->type) {
|
switch (object->type) {
|
||||||
|
@ -34,7 +34,7 @@ class ObjectData : public IdData {
|
|||||||
bool visible = true;
|
bool visible = true;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void write_transform();
|
virtual void write_transform();
|
||||||
};
|
};
|
||||||
|
|
||||||
using ObjectDataMap = Map<pxr::SdfPath, std::unique_ptr<ObjectData>>;
|
using ObjectDataMap = Map<pxr::SdfPath, std::unique_ptr<ObjectData>>;
|
||||||
|
@ -9,31 +9,15 @@
|
|||||||
#include <pxr/usdImaging/usdVolImaging/tokens.h>
|
#include <pxr/usdImaging/usdVolImaging/tokens.h>
|
||||||
|
|
||||||
#include "BKE_material.h"
|
#include "BKE_material.h"
|
||||||
#include "BKE_mesh.hh"
|
|
||||||
#include "BKE_modifier.h"
|
|
||||||
#include "BKE_object.h"
|
|
||||||
#include "BKE_volume.h"
|
#include "BKE_volume.h"
|
||||||
#include "BLI_index_range.hh"
|
#include "BLI_index_range.hh"
|
||||||
#include "BLI_path_util.h"
|
|
||||||
#include "DNA_fluid_types.h"
|
|
||||||
#include "DNA_scene_types.h"
|
|
||||||
#include "DNA_volume_types.h"
|
#include "DNA_volume_types.h"
|
||||||
|
|
||||||
#include "blender_scene_delegate.h"
|
#include "blender_scene_delegate.h"
|
||||||
#include "volume.h"
|
#include "volume.h"
|
||||||
|
|
||||||
PXR_NAMESPACE_OPEN_SCOPE
|
|
||||||
TF_DEFINE_PRIVATE_TOKENS(grid_tokens_, (density)(flame)(shadow)(temperature)(velocity));
|
|
||||||
PXR_NAMESPACE_CLOSE_SCOPE
|
|
||||||
|
|
||||||
namespace blender::render::hydra {
|
namespace blender::render::hydra {
|
||||||
|
|
||||||
const Set<pxr::TfToken> supported_grids = {pxr::grid_tokens_->density,
|
|
||||||
pxr::grid_tokens_->flame,
|
|
||||||
pxr::grid_tokens_->shadow,
|
|
||||||
pxr::grid_tokens_->temperature,
|
|
||||||
pxr::grid_tokens_->velocity};
|
|
||||||
|
|
||||||
VolumeData::VolumeData(BlenderSceneDelegate *scene_delegate,
|
VolumeData::VolumeData(BlenderSceneDelegate *scene_delegate,
|
||||||
Object *object,
|
Object *object,
|
||||||
pxr::SdfPath const &prim_id)
|
pxr::SdfPath const &prim_id)
|
||||||
@ -41,26 +25,33 @@ VolumeData::VolumeData(BlenderSceneDelegate *scene_delegate,
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VolumeData::is_volume_modifier(Object *object)
|
|
||||||
{
|
|
||||||
FluidModifierData *volume_modifier = (FluidModifierData *)BKE_modifiers_findby_type(
|
|
||||||
object, eModifierType_Fluid);
|
|
||||||
return volume_modifier && volume_modifier->type & MOD_FLUID_TYPE_DOMAIN &&
|
|
||||||
volume_modifier->domain->type == FLUID_DOMAIN_TYPE_GAS;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VolumeData::init()
|
void VolumeData::init()
|
||||||
{
|
{
|
||||||
ID_LOG(1, "");
|
ID_LOG(1, "");
|
||||||
write_transform();
|
Volume *volume = (Volume *)((Object *)this->id)->data;
|
||||||
if (is_volume_modifier((Object *)this->id)) {
|
Main *main = CTX_data_main(scene_delegate_->context);
|
||||||
init_from_modifier();
|
if (!BKE_volume_load(volume, main)) {
|
||||||
}
|
return;
|
||||||
else {
|
|
||||||
init_from_volume();
|
|
||||||
}
|
}
|
||||||
|
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();
|
write_materials();
|
||||||
|
|
||||||
|
BKE_volume_unload(volume);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VolumeData::insert()
|
void VolumeData::insert()
|
||||||
@ -101,7 +92,6 @@ void VolumeData::update()
|
|||||||
}
|
}
|
||||||
if (id->recalc & ID_RECALC_TRANSFORM) {
|
if (id->recalc & ID_RECALC_TRANSFORM) {
|
||||||
write_transform();
|
write_transform();
|
||||||
assign_volume_transform();
|
|
||||||
bits |= pxr::HdChangeTracker::DirtyTransform;
|
bits |= pxr::HdChangeTracker::DirtyTransform;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,97 +176,4 @@ void VolumeData::write_materials()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string VolumeData::get_cached_file_path(std::string directory, int frame)
|
|
||||||
{
|
|
||||||
char file_path[FILE_MAX];
|
|
||||||
char file_name[32];
|
|
||||||
strcat(strcat(strcpy(file_name, FLUID_NAME_DATA), "_####"), FLUID_DOMAIN_EXTENSION_OPENVDB);
|
|
||||||
BLI_path_frame(file_name, sizeof(file_name), frame, 0);
|
|
||||||
BLI_path_join(file_path, sizeof(file_path), directory.c_str(), FLUID_DOMAIN_DIR_DATA, file_name);
|
|
||||||
|
|
||||||
return file_path;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VolumeData::init_from_modifier()
|
|
||||||
{
|
|
||||||
Object *object = (Object *)this->id;
|
|
||||||
FluidModifierData *volume_modifier = (FluidModifierData *)BKE_modifiers_findby_type(
|
|
||||||
object, eModifierType_Fluid);
|
|
||||||
|
|
||||||
if ((volume_modifier->domain->cache_data_format & FLUID_DOMAIN_FILE_OPENVDB) == 0) {
|
|
||||||
CLOG_WARN(LOG_RENDER_HYDRA_SCENE,
|
|
||||||
"Volume %s is't exported: only OpenVDB file format supported",
|
|
||||||
prim_id.GetText());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
filepath_ = get_cached_file_path(volume_modifier->domain->cache_directory,
|
|
||||||
scene_delegate_->scene->r.cfra);
|
|
||||||
|
|
||||||
for (auto &grid_name : supported_grids) {
|
|
||||||
field_descriptors_.emplace_back(grid_name,
|
|
||||||
pxr::UsdVolImagingTokens->openvdbAsset,
|
|
||||||
prim_id.AppendElementString("VF_" + grid_name.GetString()));
|
|
||||||
}
|
|
||||||
|
|
||||||
assign_volume_transform();
|
|
||||||
}
|
|
||||||
|
|
||||||
void VolumeData::init_from_volume()
|
|
||||||
{
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BKE_volume_unload(volume);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VolumeData::assign_volume_transform()
|
|
||||||
{
|
|
||||||
Object *object = (Object *)this->id;
|
|
||||||
Mesh *mesh = BKE_object_to_mesh(nullptr, object, false);
|
|
||||||
|
|
||||||
pxr::GfMatrix4d fixed_transform = pxr::GfMatrix4d(1.0f).SetScale(0.5) *
|
|
||||||
pxr::GfMatrix4d(1.0f).SetTranslate(pxr::GfVec3d(0.5));
|
|
||||||
double det = fixed_transform.GetDeterminant();
|
|
||||||
pxr::GfMatrix4d inversed = fixed_transform.GetInverse(&det);
|
|
||||||
|
|
||||||
float scale[3] = {0.5f, 0.5f, 0.5f};
|
|
||||||
if (object->scale[0] != 0.0f) {
|
|
||||||
scale[0] = 0.5f / object->scale[0];
|
|
||||||
}
|
|
||||||
if (object->scale[1] != 0.0f) {
|
|
||||||
scale[1] = 0.5f / object->scale[1];
|
|
||||||
}
|
|
||||||
if (object->scale[2] != 0.0f) {
|
|
||||||
scale[2] = 0.5f / object->scale[2];
|
|
||||||
}
|
|
||||||
pxr::GfMatrix4d scale_matrix = pxr::GfMatrix4d(1.0f).SetScale(
|
|
||||||
pxr::GfVec3d(scale[0], scale[1], scale[2]));
|
|
||||||
pxr::GfMatrix4d texture_trans = pxr::GfMatrix4d(1.0f).SetTranslate(pxr::GfVec3d(
|
|
||||||
mesh->texspace_location[0], mesh->texspace_location[1], mesh->texspace_location[2]));
|
|
||||||
pxr::GfMatrix4d texture_scale = pxr::GfMatrix4d(1.0f).SetScale(
|
|
||||||
pxr::GfVec3d(mesh->texspace_size[0], mesh->texspace_size[1], mesh->texspace_size[2]));
|
|
||||||
|
|
||||||
transform = scale_matrix * inversed * texture_scale * texture_trans * transform;
|
|
||||||
|
|
||||||
BKE_object_to_mesh_clear(object);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace blender::render::hydra
|
} // namespace blender::render::hydra
|
||||||
|
@ -13,7 +13,6 @@ class VolumeData : public ObjectData {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
VolumeData(BlenderSceneDelegate *scene_delegate, Object *object, pxr::SdfPath const &prim_id);
|
VolumeData(BlenderSceneDelegate *scene_delegate, Object *object, pxr::SdfPath const &prim_id);
|
||||||
static bool is_volume_modifier(Object *object);
|
|
||||||
|
|
||||||
void init() override;
|
void init() override;
|
||||||
void insert() override;
|
void insert() override;
|
||||||
@ -27,12 +26,8 @@ class VolumeData : public ObjectData {
|
|||||||
pxr::SdfPath material_id() const;
|
pxr::SdfPath material_id() const;
|
||||||
void available_materials(Set<pxr::SdfPath> &paths) const;
|
void available_materials(Set<pxr::SdfPath> &paths) const;
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
void write_materials();
|
void write_materials();
|
||||||
std::string get_cached_file_path(std::string directory, int frame);
|
|
||||||
void init_from_modifier();
|
|
||||||
void init_from_volume();
|
|
||||||
void assign_volume_transform();
|
|
||||||
|
|
||||||
std::string filepath_;
|
std::string filepath_;
|
||||||
pxr::HdVolumeFieldDescriptorVector field_descriptors_;
|
pxr::HdVolumeFieldDescriptorVector field_descriptors_;
|
||||||
|
124
source/blender/render/hydra/scene_delegate/volume_modifier.cc
Normal file
124
source/blender/render/hydra/scene_delegate/volume_modifier.cc
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
/* 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_mesh.hh"
|
||||||
|
#include "BKE_modifier.h"
|
||||||
|
#include "BKE_object.h"
|
||||||
|
#include "BKE_volume.h"
|
||||||
|
#include "BLI_index_range.hh"
|
||||||
|
#include "BLI_path_util.h"
|
||||||
|
#include "DNA_fluid_types.h"
|
||||||
|
#include "DNA_scene_types.h"
|
||||||
|
#include "DNA_volume_types.h"
|
||||||
|
|
||||||
|
#include "blender_scene_delegate.h"
|
||||||
|
#include "volume_modifier.h"
|
||||||
|
|
||||||
|
PXR_NAMESPACE_OPEN_SCOPE
|
||||||
|
TF_DEFINE_PRIVATE_TOKENS(grid_tokens_, (density)(flame)(shadow)(temperature)(velocity));
|
||||||
|
PXR_NAMESPACE_CLOSE_SCOPE
|
||||||
|
|
||||||
|
namespace blender::render::hydra {
|
||||||
|
|
||||||
|
const Set<pxr::TfToken> supported_grids = {pxr::grid_tokens_->density,
|
||||||
|
pxr::grid_tokens_->flame,
|
||||||
|
pxr::grid_tokens_->shadow,
|
||||||
|
pxr::grid_tokens_->temperature,
|
||||||
|
pxr::grid_tokens_->velocity};
|
||||||
|
|
||||||
|
VolumeModifierData::VolumeModifierData(BlenderSceneDelegate *scene_delegate,
|
||||||
|
Object *object,
|
||||||
|
pxr::SdfPath const &prim_id)
|
||||||
|
: VolumeData(scene_delegate, object, prim_id)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VolumeModifierData::is_volume_modifier(Object *object)
|
||||||
|
{
|
||||||
|
FluidModifierData *volume_modifier = (FluidModifierData *)BKE_modifiers_findby_type(
|
||||||
|
object, eModifierType_Fluid);
|
||||||
|
return volume_modifier && volume_modifier->type & MOD_FLUID_TYPE_DOMAIN &&
|
||||||
|
volume_modifier->domain->type == FLUID_DOMAIN_TYPE_GAS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VolumeModifierData::init()
|
||||||
|
{
|
||||||
|
ID_LOG(1, "");
|
||||||
|
|
||||||
|
Object *object = (Object *)this->id;
|
||||||
|
FluidModifierData *volume_modifier = (FluidModifierData *)BKE_modifiers_findby_type(
|
||||||
|
object, eModifierType_Fluid);
|
||||||
|
|
||||||
|
if ((volume_modifier->domain->cache_data_format & FLUID_DOMAIN_FILE_OPENVDB) == 0) {
|
||||||
|
CLOG_WARN(LOG_RENDER_HYDRA_SCENE,
|
||||||
|
"Volume %s is't exported: only OpenVDB file format supported",
|
||||||
|
prim_id.GetText());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
filepath_ = get_cached_file_path(volume_modifier->domain->cache_directory,
|
||||||
|
scene_delegate_->scene->r.cfra);
|
||||||
|
|
||||||
|
for (auto &grid_name : supported_grids) {
|
||||||
|
field_descriptors_.emplace_back(grid_name,
|
||||||
|
pxr::UsdVolImagingTokens->openvdbAsset,
|
||||||
|
prim_id.AppendElementString("VF_" + grid_name.GetString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
write_transform();
|
||||||
|
write_materials();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VolumeModifierData::write_transform()
|
||||||
|
{
|
||||||
|
Object *object = (Object *)this->id;
|
||||||
|
Mesh *mesh = BKE_object_to_mesh(nullptr, object, false);
|
||||||
|
|
||||||
|
pxr::GfMatrix4d fixed_transform = pxr::GfMatrix4d(1.0f).SetScale(0.5) *
|
||||||
|
pxr::GfMatrix4d(1.0f).SetTranslate(pxr::GfVec3d(0.5));
|
||||||
|
double det = fixed_transform.GetDeterminant();
|
||||||
|
pxr::GfMatrix4d inversed = fixed_transform.GetInverse(&det);
|
||||||
|
|
||||||
|
float scale[3] = {0.5f, 0.5f, 0.5f};
|
||||||
|
if (object->scale[0] != 0.0f) {
|
||||||
|
scale[0] = 0.5f / object->scale[0];
|
||||||
|
}
|
||||||
|
if (object->scale[1] != 0.0f) {
|
||||||
|
scale[1] = 0.5f / object->scale[1];
|
||||||
|
}
|
||||||
|
if (object->scale[2] != 0.0f) {
|
||||||
|
scale[2] = 0.5f / object->scale[2];
|
||||||
|
}
|
||||||
|
pxr::GfMatrix4d scale_matrix = pxr::GfMatrix4d(1.0f).SetScale(
|
||||||
|
pxr::GfVec3d(scale[0], scale[1], scale[2]));
|
||||||
|
pxr::GfMatrix4d texture_trans = pxr::GfMatrix4d(1.0f).SetTranslate(pxr::GfVec3d(
|
||||||
|
mesh->texspace_location[0], mesh->texspace_location[1], mesh->texspace_location[2]));
|
||||||
|
pxr::GfMatrix4d texture_scale = pxr::GfMatrix4d(1.0f).SetScale(
|
||||||
|
pxr::GfVec3d(mesh->texspace_size[0], mesh->texspace_size[1], mesh->texspace_size[2]));
|
||||||
|
|
||||||
|
transform = scale_matrix * inversed * texture_scale * texture_trans *
|
||||||
|
gf_matrix_from_transform(object->object_to_world);
|
||||||
|
|
||||||
|
BKE_object_to_mesh_clear(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string VolumeModifierData::get_cached_file_path(std::string directory, int frame)
|
||||||
|
{
|
||||||
|
char file_path[FILE_MAX];
|
||||||
|
char file_name[32];
|
||||||
|
strcat(strcat(strcpy(file_name, FLUID_NAME_DATA), "_####"), FLUID_DOMAIN_EXTENSION_OPENVDB);
|
||||||
|
BLI_path_frame(file_name, sizeof(file_name), frame, 0);
|
||||||
|
BLI_path_join(file_path, sizeof(file_path), directory.c_str(), FLUID_DOMAIN_DIR_DATA, file_name);
|
||||||
|
|
||||||
|
return file_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace blender::render::hydra
|
28
source/blender/render/hydra/scene_delegate/volume_modifier.h
Normal file
28
source/blender/render/hydra/scene_delegate/volume_modifier.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/* SPDX-License-Identifier: Apache-2.0
|
||||||
|
* Copyright 2011-2022 Blender Foundation */
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <pxr/imaging/hd/sceneDelegate.h>
|
||||||
|
|
||||||
|
#include "object.h"
|
||||||
|
#include "volume.h"
|
||||||
|
|
||||||
|
namespace blender::render::hydra {
|
||||||
|
|
||||||
|
class VolumeModifierData : public VolumeData {
|
||||||
|
|
||||||
|
public:
|
||||||
|
VolumeModifierData(BlenderSceneDelegate *scene_delegate, Object *object, pxr::SdfPath const &prim_id);
|
||||||
|
static bool is_volume_modifier(Object *object);
|
||||||
|
|
||||||
|
void init() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void write_transform() override;
|
||||||
|
|
||||||
|
std::string get_cached_file_path(std::string directory, int frame);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace blender::render::hydra
|
Loading…
Reference in New Issue
Block a user
Propose to create
class VolumeModifierData::public VolumeData
and separate logic in these two classes