Compare commits
15 Commits
lineart-ob
...
mesh-to-vo
Author | SHA1 | Date | |
---|---|---|---|
6da9286cc8 | |||
4803466c01 | |||
f798a6c679 | |||
6501b05118 | |||
aad5a79a94 | |||
2629cf12f5 | |||
d525a541a2 | |||
e204f67cf0 | |||
d8d1344d96 | |||
9cbc874062 | |||
0e9e472bbe | |||
95e34d2ebf | |||
11f79038e1 | |||
076c913a3b | |||
c5fca660bc |
@@ -157,4 +157,16 @@ openvdb::GridBase::ConstPtr BKE_volume_grid_openvdb_for_read(const struct Volume
|
|||||||
openvdb::GridBase::Ptr BKE_volume_grid_openvdb_for_write(const struct Volume *volume,
|
openvdb::GridBase::Ptr BKE_volume_grid_openvdb_for_write(const struct Volume *volume,
|
||||||
struct VolumeGrid *grid,
|
struct VolumeGrid *grid,
|
||||||
const bool clear);
|
const bool clear);
|
||||||
|
|
||||||
|
template<typename GridType>
|
||||||
|
typename GridType::Ptr BKE_volume_grid_openvdb_for_write(const struct Volume *volume,
|
||||||
|
struct VolumeGrid *grid,
|
||||||
|
const bool clear)
|
||||||
|
{
|
||||||
|
openvdb::GridBase::Ptr openvdb_grid = BKE_volume_grid_openvdb_for_write(volume, grid, clear);
|
||||||
|
BLI_assert(openvdb_grid->isType<GridType>());
|
||||||
|
typename GridType::Ptr typed_openvdb_grid = openvdb::gridPtrCast<GridType>(openvdb_grid);
|
||||||
|
return typed_openvdb_grid;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -95,6 +95,7 @@ typedef enum ModifierType {
|
|||||||
eModifierType_Weld = 55,
|
eModifierType_Weld = 55,
|
||||||
eModifierType_Fluid = 56,
|
eModifierType_Fluid = 56,
|
||||||
eModifierType_Simulation = 57,
|
eModifierType_Simulation = 57,
|
||||||
|
eModifierType_MeshToVolume = 58,
|
||||||
NUM_MODIFIER_TYPES,
|
NUM_MODIFIER_TYPES,
|
||||||
} ModifierType;
|
} ModifierType;
|
||||||
|
|
||||||
@@ -2208,6 +2209,36 @@ typedef struct SimulationModifierData {
|
|||||||
char *data_path;
|
char *data_path;
|
||||||
} SimulationModifierData;
|
} SimulationModifierData;
|
||||||
|
|
||||||
|
typedef struct MeshToVolumeModifierData {
|
||||||
|
ModifierData modifier;
|
||||||
|
|
||||||
|
/** This is the object that is supposed to be converted to a volume. */
|
||||||
|
struct Object *object;
|
||||||
|
|
||||||
|
/** MeshToVolumeModifierResolutionMode */
|
||||||
|
int resolution_mode;
|
||||||
|
/** Size of a voxel in object space. */
|
||||||
|
float voxel_size;
|
||||||
|
/** The desired amount of voxels along one axis. The actual amount of voxels might be slightly
|
||||||
|
* different. */
|
||||||
|
int voxel_amount;
|
||||||
|
|
||||||
|
/** If true, every cell in the enclosed volume gets a density. Otherwise, the interior_bandwidth
|
||||||
|
* is used. */
|
||||||
|
char fill_volume;
|
||||||
|
char _pad1[3];
|
||||||
|
|
||||||
|
/** Bandwidths are in object space. */
|
||||||
|
float interior_bandwidth;
|
||||||
|
float exterior_bandwidth;
|
||||||
|
} MeshToVolumeModifierData;
|
||||||
|
|
||||||
|
/* MeshToVolumeModifierData->resolution_mode */
|
||||||
|
typedef enum MeshToVolumeModifierResolutionMode {
|
||||||
|
MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_AMOUNT = 0,
|
||||||
|
MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_SIZE = 1,
|
||||||
|
} MeshToVolumeModifierResolutionMode;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@@ -389,6 +389,7 @@ extern StructRNA RNA_MaterialSlot;
|
|||||||
extern StructRNA RNA_Menu;
|
extern StructRNA RNA_Menu;
|
||||||
extern StructRNA RNA_Mesh;
|
extern StructRNA RNA_Mesh;
|
||||||
extern StructRNA RNA_MeshCacheModifier;
|
extern StructRNA RNA_MeshCacheModifier;
|
||||||
|
extern StructRNA RNA_MeshToVolumeModifier;
|
||||||
extern StructRNA RNA_MeshColor;
|
extern StructRNA RNA_MeshColor;
|
||||||
extern StructRNA RNA_MeshDeformModifier;
|
extern StructRNA RNA_MeshDeformModifier;
|
||||||
extern StructRNA RNA_MeshEdge;
|
extern StructRNA RNA_MeshEdge;
|
||||||
|
@@ -193,6 +193,11 @@ const EnumPropertyItem rna_enum_object_modifier_type_items[] = {
|
|||||||
ICON_MOD_WIREFRAME,
|
ICON_MOD_WIREFRAME,
|
||||||
"Wireframe",
|
"Wireframe",
|
||||||
"Convert faces into thickened edges"},
|
"Convert faces into thickened edges"},
|
||||||
|
{eModifierType_MeshToVolume,
|
||||||
|
"MESH_TO_VOLUME",
|
||||||
|
ICON_VOLUME_DATA,
|
||||||
|
"Mesh to Volume",
|
||||||
|
""}, /* TODO: Use correct icon. */
|
||||||
{0, "", 0, N_("Deform"), ""},
|
{0, "", 0, N_("Deform"), ""},
|
||||||
{eModifierType_Armature,
|
{eModifierType_Armature,
|
||||||
"ARMATURE",
|
"ARMATURE",
|
||||||
@@ -6973,6 +6978,73 @@ static void rna_def_modifier_simulation(BlenderRNA *brna)
|
|||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
static void rna_def_modifier_mesh_to_volume(BlenderRNA *brna)
|
||||||
|
{
|
||||||
|
StructRNA *srna;
|
||||||
|
PropertyRNA *prop;
|
||||||
|
|
||||||
|
static EnumPropertyItem resolution_mode_items[] = {
|
||||||
|
{MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_AMOUNT,
|
||||||
|
"VOXEL_AMOUNT",
|
||||||
|
0,
|
||||||
|
"Voxel Amount",
|
||||||
|
"Specify the desired number of voxels along one axis"},
|
||||||
|
{MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_SIZE,
|
||||||
|
"VOXEL_SIZE",
|
||||||
|
0,
|
||||||
|
"Voxel Size",
|
||||||
|
"Specify the desired voxel side length"},
|
||||||
|
{0, NULL, 0, NULL, NULL},
|
||||||
|
};
|
||||||
|
|
||||||
|
srna = RNA_def_struct(brna, "MeshToVolumeModifier", "Modifier");
|
||||||
|
RNA_def_struct_ui_text(srna, "Mesh to Volume Modifier", "");
|
||||||
|
RNA_def_struct_sdna(srna, "MeshToVolumeModifierData");
|
||||||
|
RNA_def_struct_ui_icon(srna, ICON_VOLUME_DATA); /* TODO: Use correct icon. */
|
||||||
|
|
||||||
|
RNA_define_lib_overridable(true);
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
|
||||||
|
RNA_def_property_ui_text(prop, "Object", "Object");
|
||||||
|
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
|
||||||
|
RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Mesh_object_poll");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "resolution_mode", PROP_ENUM, PROP_NONE);
|
||||||
|
RNA_def_property_enum_items(prop, resolution_mode_items);
|
||||||
|
RNA_def_property_ui_text(
|
||||||
|
prop, "Resolution Mode", "Mode for how the desired voxel size is specified");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "voxel_size", PROP_FLOAT, PROP_NONE);
|
||||||
|
RNA_def_property_ui_text(
|
||||||
|
prop, "Voxel Size", "The smaller this number the higher the resolution of the output");
|
||||||
|
RNA_def_property_range(prop, 0.1, FLT_MAX);
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "voxel_amount", PROP_INT, PROP_NONE);
|
||||||
|
RNA_def_property_ui_text(prop, "Voxel Amount", "The desired number of voxels along one axis");
|
||||||
|
RNA_def_property_range(prop, 0, INT_MAX);
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "fill_volume", PROP_BOOLEAN, PROP_NONE);
|
||||||
|
RNA_def_property_ui_text(
|
||||||
|
prop, "Fill Volume", "Initialize the density grid in every cell inside the enclosed volume");
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "interior_bandwidth", PROP_FLOAT, PROP_NONE);
|
||||||
|
RNA_def_property_ui_text(prop, "Interior Bandwidth", "Width of the volume inside of the mesh");
|
||||||
|
RNA_def_property_range(prop, 0.0, FLT_MAX);
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "exterior_bandwidth", PROP_FLOAT, PROP_NONE);
|
||||||
|
RNA_def_property_ui_text(prop, "Exterior Bandwidth", "Width of the volume outside of the mesh");
|
||||||
|
RNA_def_property_range(prop, 0.0, FLT_MAX);
|
||||||
|
RNA_def_property_update(prop, 0, "rna_Modifier_update");
|
||||||
|
|
||||||
|
RNA_define_lib_overridable(false);
|
||||||
|
}
|
||||||
|
|
||||||
void RNA_def_modifier(BlenderRNA *brna)
|
void RNA_def_modifier(BlenderRNA *brna)
|
||||||
{
|
{
|
||||||
StructRNA *srna;
|
StructRNA *srna;
|
||||||
@@ -7104,6 +7176,7 @@ void RNA_def_modifier(BlenderRNA *brna)
|
|||||||
# ifdef WITH_PARTICLE_NODES
|
# ifdef WITH_PARTICLE_NODES
|
||||||
rna_def_modifier_simulation(brna);
|
rna_def_modifier_simulation(brna);
|
||||||
# endif
|
# endif
|
||||||
|
rna_def_modifier_mesh_to_volume(brna);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -67,6 +67,7 @@ set(SRC
|
|||||||
intern/MOD_laplaciansmooth.c
|
intern/MOD_laplaciansmooth.c
|
||||||
intern/MOD_lattice.c
|
intern/MOD_lattice.c
|
||||||
intern/MOD_mask.cc
|
intern/MOD_mask.cc
|
||||||
|
intern/MOD_mesh_to_volume.cc
|
||||||
intern/MOD_meshcache.c
|
intern/MOD_meshcache.c
|
||||||
intern/MOD_meshcache_mdd.c
|
intern/MOD_meshcache_mdd.c
|
||||||
intern/MOD_meshcache_pc2.c
|
intern/MOD_meshcache_pc2.c
|
||||||
@@ -177,6 +178,20 @@ if(WITH_GMP)
|
|||||||
add_definitions(-DWITH_GMP)
|
add_definitions(-DWITH_GMP)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(WITH_OPENVDB)
|
||||||
|
list(APPEND INC
|
||||||
|
../../../intern/openvdb
|
||||||
|
)
|
||||||
|
list(APPEND INC_SYS
|
||||||
|
${OPENVDB_INCLUDE_DIRS}
|
||||||
|
)
|
||||||
|
list(APPEND LIB
|
||||||
|
bf_intern_openvdb
|
||||||
|
${OPENVDB_LIBRARIES}
|
||||||
|
)
|
||||||
|
add_definitions(-DWITH_OPENVDB ${OPENVDB_DEFINITIONS})
|
||||||
|
endif()
|
||||||
|
|
||||||
if(WITH_EXPERIMENTAL_FEATURES)
|
if(WITH_EXPERIMENTAL_FEATURES)
|
||||||
add_definitions(-DWITH_PARTICLE_NODES)
|
add_definitions(-DWITH_PARTICLE_NODES)
|
||||||
add_definitions(-DWITH_HAIR_NODES)
|
add_definitions(-DWITH_HAIR_NODES)
|
||||||
|
@@ -86,6 +86,7 @@ extern ModifierTypeInfo modifierType_MeshSequenceCache;
|
|||||||
extern ModifierTypeInfo modifierType_SurfaceDeform;
|
extern ModifierTypeInfo modifierType_SurfaceDeform;
|
||||||
extern ModifierTypeInfo modifierType_WeightedNormal;
|
extern ModifierTypeInfo modifierType_WeightedNormal;
|
||||||
extern ModifierTypeInfo modifierType_Simulation;
|
extern ModifierTypeInfo modifierType_Simulation;
|
||||||
|
extern ModifierTypeInfo modifierType_MeshToVolume;
|
||||||
|
|
||||||
/* MOD_util.c */
|
/* MOD_util.c */
|
||||||
void modifier_type_init(ModifierTypeInfo *types[]);
|
void modifier_type_init(ModifierTypeInfo *types[]);
|
||||||
|
302
source/blender/modifiers/intern/MOD_mesh_to_volume.cc
Normal file
302
source/blender/modifiers/intern/MOD_mesh_to_volume.cc
Normal file
@@ -0,0 +1,302 @@
|
|||||||
|
/*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
* \ingroup modifiers
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "BKE_lib_query.h"
|
||||||
|
#include "BKE_mesh_runtime.h"
|
||||||
|
#include "BKE_modifier.h"
|
||||||
|
#include "BKE_object.h"
|
||||||
|
#include "BKE_volume.h"
|
||||||
|
|
||||||
|
#include "DNA_mesh_types.h"
|
||||||
|
#include "DNA_meshdata_types.h"
|
||||||
|
#include "DNA_object_types.h"
|
||||||
|
#include "DNA_screen_types.h"
|
||||||
|
#include "DNA_volume_types.h"
|
||||||
|
|
||||||
|
#include "DEG_depsgraph_build.h"
|
||||||
|
|
||||||
|
#include "UI_interface.h"
|
||||||
|
#include "UI_resources.h"
|
||||||
|
|
||||||
|
#include "BLO_read_write.h"
|
||||||
|
|
||||||
|
#include "MEM_guardedalloc.h"
|
||||||
|
|
||||||
|
#include "MOD_modifiertypes.h"
|
||||||
|
#include "MOD_ui_common.h"
|
||||||
|
|
||||||
|
#include "BLI_float4x4.hh"
|
||||||
|
#include "BLI_index_range.hh"
|
||||||
|
#include "BLI_span.hh"
|
||||||
|
|
||||||
|
#include "RNA_access.h"
|
||||||
|
|
||||||
|
#ifdef WITH_OPENVDB
|
||||||
|
# include <openvdb/openvdb.h>
|
||||||
|
# include <openvdb/tools/MeshToVolume.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WITH_OPENVDB
|
||||||
|
namespace blender {
|
||||||
|
/* This class follows the MeshDataAdapter interface from openvdb. */
|
||||||
|
class OpenVDBMeshAdapter {
|
||||||
|
private:
|
||||||
|
Span<MVert> vertices_;
|
||||||
|
Span<MLoop> loops_;
|
||||||
|
Span<MLoopTri> looptris_;
|
||||||
|
float4x4 transform_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
OpenVDBMeshAdapter(Mesh &mesh, float4x4 transform)
|
||||||
|
: vertices_(mesh.mvert, mesh.totvert),
|
||||||
|
loops_(mesh.mloop, mesh.totloop),
|
||||||
|
transform_(transform)
|
||||||
|
{
|
||||||
|
const MLoopTri *looptries = BKE_mesh_runtime_looptri_ensure(&mesh);
|
||||||
|
const int looptries_len = BKE_mesh_runtime_looptri_len(&mesh);
|
||||||
|
looptris_ = Span(looptries, looptries_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t polygonCount() const
|
||||||
|
{
|
||||||
|
return static_cast<size_t>(looptris_.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t pointCount() const
|
||||||
|
{
|
||||||
|
return static_cast<size_t>(vertices_.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t vertexCount(size_t UNUSED(polygon_index)) const
|
||||||
|
{
|
||||||
|
/* All polygons are triangles. */
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
void getIndexSpacePoint(size_t polygon_index, size_t vertex_index, openvdb::Vec3d &pos) const
|
||||||
|
{
|
||||||
|
const MLoopTri &looptri = looptris_[polygon_index];
|
||||||
|
const MVert &vertex = vertices_[loops_[looptri.tri[vertex_index]].v];
|
||||||
|
const float3 transformed_co = transform_ * float3(vertex.co);
|
||||||
|
pos = &transformed_co.x;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace blender
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void initData(ModifierData *md)
|
||||||
|
{
|
||||||
|
MeshToVolumeModifierData *mvmd = reinterpret_cast<MeshToVolumeModifierData *>(md);
|
||||||
|
mvmd->object = NULL;
|
||||||
|
mvmd->resolution_mode = MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_AMOUNT;
|
||||||
|
mvmd->voxel_size = 0.1f;
|
||||||
|
mvmd->voxel_amount = 32;
|
||||||
|
mvmd->fill_volume = true;
|
||||||
|
mvmd->interior_bandwidth = 0.1f;
|
||||||
|
mvmd->exterior_bandwidth = 0.1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
|
||||||
|
{
|
||||||
|
MeshToVolumeModifierData *mvmd = reinterpret_cast<MeshToVolumeModifierData *>(md);
|
||||||
|
DEG_add_modifier_to_transform_relation(ctx->node, "Mesh to Volume Modifier");
|
||||||
|
if (mvmd->object) {
|
||||||
|
DEG_add_object_relation(
|
||||||
|
ctx->node, mvmd->object, DEG_OB_COMP_GEOMETRY, "Mesh to Volume Modifier");
|
||||||
|
DEG_add_object_relation(
|
||||||
|
ctx->node, mvmd->object, DEG_OB_COMP_TRANSFORM, "Mesh to Volume Modifier");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData)
|
||||||
|
{
|
||||||
|
MeshToVolumeModifierData *mvmd = reinterpret_cast<MeshToVolumeModifierData *>(md);
|
||||||
|
walk(userData, ob, &mvmd->object, IDWALK_CB_NOP);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void panel_draw(const bContext *UNUSED(C), Panel *panel)
|
||||||
|
{
|
||||||
|
uiLayout *layout = panel->layout;
|
||||||
|
|
||||||
|
PointerRNA ob_ptr;
|
||||||
|
PointerRNA *ptr = modifier_panel_get_property_pointers(panel, &ob_ptr);
|
||||||
|
MeshToVolumeModifierData *mvmd = static_cast<MeshToVolumeModifierData *>(ptr->data);
|
||||||
|
|
||||||
|
uiLayoutSetPropSep(layout, true);
|
||||||
|
uiLayoutSetPropDecorate(layout, false);
|
||||||
|
|
||||||
|
uiItemR(layout, ptr, "object", 0, NULL, ICON_NONE);
|
||||||
|
|
||||||
|
{
|
||||||
|
uiLayout *col = uiLayoutColumn(layout, false);
|
||||||
|
uiItemR(col, ptr, "fill_volume", 0, NULL, ICON_NONE);
|
||||||
|
uiItemR(col, ptr, "exterior_bandwidth", 0, NULL, ICON_NONE);
|
||||||
|
|
||||||
|
uiLayout *subcol = uiLayoutColumn(col, false);
|
||||||
|
uiLayoutSetEnabled(subcol, !mvmd->fill_volume);
|
||||||
|
uiItemR(subcol, ptr, "interior_bandwidth", 0, NULL, ICON_NONE);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
uiLayout *col = uiLayoutColumn(layout, false);
|
||||||
|
uiItemR(col, ptr, "resolution_mode", 0, NULL, ICON_NONE);
|
||||||
|
if (mvmd->resolution_mode == MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_AMOUNT) {
|
||||||
|
uiItemR(col, ptr, "voxel_amount", 0, NULL, ICON_NONE);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
uiItemR(col, ptr, "voxel_size", 0, NULL, ICON_NONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
modifier_panel_end(layout, ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void panelRegister(ARegionType *region_type)
|
||||||
|
{
|
||||||
|
modifier_panel_register(region_type, eModifierType_MeshToVolume, panel_draw);
|
||||||
|
}
|
||||||
|
|
||||||
|
static float compute_voxel_size(const MeshToVolumeModifierData *mvmd,
|
||||||
|
const blender::float4x4 &transform)
|
||||||
|
{
|
||||||
|
using namespace blender;
|
||||||
|
|
||||||
|
if (mvmd->resolution_mode == MESH_TO_VOLUME_RESOLUTION_MODE_VOXEL_SIZE) {
|
||||||
|
return MAX2(0.0001, mvmd->voxel_size);
|
||||||
|
}
|
||||||
|
BoundBox *bb = BKE_object_boundbox_get(mvmd->object);
|
||||||
|
|
||||||
|
float3 dimensions = float3(bb->vec[6]) - float3(bb->vec[0]);
|
||||||
|
const float3 transformed_dimensions = transform.ref_3x3() * dimensions;
|
||||||
|
const float max_dimension = std::max(
|
||||||
|
{transformed_dimensions.x, transformed_dimensions.y, transformed_dimensions.z});
|
||||||
|
const float approximate_volume_side_length = max_dimension + mvmd->exterior_bandwidth * 2.0f;
|
||||||
|
const float voxel_size = approximate_volume_side_length / MAX2(1, mvmd->voxel_amount);
|
||||||
|
return voxel_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Volume *modifyVolume(ModifierData *md, const ModifierEvalContext *ctx, Volume *input_volume)
|
||||||
|
{
|
||||||
|
#ifdef WITH_OPENVDB
|
||||||
|
using namespace blender;
|
||||||
|
|
||||||
|
MeshToVolumeModifierData *mvmd = reinterpret_cast<MeshToVolumeModifierData *>(md);
|
||||||
|
Object *object_to_convert = mvmd->object;
|
||||||
|
|
||||||
|
if (object_to_convert == NULL) {
|
||||||
|
return input_volume;
|
||||||
|
}
|
||||||
|
/* TODO: Support other object types. */
|
||||||
|
if (object_to_convert->type != OB_MESH) {
|
||||||
|
return input_volume;
|
||||||
|
}
|
||||||
|
|
||||||
|
const float4x4 mesh_to_own_object_space_transform = float4x4(ctx->object->imat) *
|
||||||
|
float4x4(object_to_convert->obmat);
|
||||||
|
const float voxel_size = compute_voxel_size(mvmd, mesh_to_own_object_space_transform);
|
||||||
|
|
||||||
|
float4x4 mesh_to_index_space_transform;
|
||||||
|
scale_m4_fl(mesh_to_index_space_transform.values, 1.0f / voxel_size);
|
||||||
|
mul_m4_m4_post(mesh_to_index_space_transform.values, mesh_to_own_object_space_transform.values);
|
||||||
|
|
||||||
|
Mesh *mesh = static_cast<Mesh *>(object_to_convert->data);
|
||||||
|
OpenVDBMeshAdapter mesh_adapter{*mesh, mesh_to_index_space_transform};
|
||||||
|
|
||||||
|
/* Convert the bandwidths from object in index space. */
|
||||||
|
const float exterior_bandwidth = MAX2(0.001f, mvmd->exterior_bandwidth / voxel_size);
|
||||||
|
const float interior_bandwidth = MAX2(0.001f, mvmd->interior_bandwidth / voxel_size);
|
||||||
|
|
||||||
|
openvdb::FloatGrid::Ptr new_grid;
|
||||||
|
if (mvmd->fill_volume) {
|
||||||
|
/* Setting the interior bandwidth to FLT_MAX, will make it fill the entire volume. */
|
||||||
|
new_grid = openvdb::tools::meshToVolume<openvdb::FloatGrid>(
|
||||||
|
mesh_adapter, {}, exterior_bandwidth, FLT_MAX);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
new_grid = openvdb::tools::meshToVolume<openvdb::FloatGrid>(
|
||||||
|
mesh_adapter, {}, exterior_bandwidth, interior_bandwidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create a new volume object and add the density grid. */
|
||||||
|
Volume *volume = BKE_volume_new_for_eval(input_volume);
|
||||||
|
VolumeGrid *c_density_grid = BKE_volume_grid_add(volume, "density", VOLUME_GRID_FLOAT);
|
||||||
|
openvdb::FloatGrid::Ptr density_grid = BKE_volume_grid_openvdb_for_write<openvdb::FloatGrid>(
|
||||||
|
volume, c_density_grid, false);
|
||||||
|
|
||||||
|
/* Merge the generated grid into the density grid. I could not figure out how to simply replace
|
||||||
|
* it yet. */
|
||||||
|
density_grid->merge(*new_grid);
|
||||||
|
|
||||||
|
/* Change transform so that the index space is correctly transformed to object space. */
|
||||||
|
density_grid->transform().postScale(voxel_size);
|
||||||
|
/* Better align generated grid with the source mesh. */
|
||||||
|
density_grid->transform().postTranslate(openvdb::math::Vec3d(-voxel_size / 2.0f));
|
||||||
|
|
||||||
|
/* Give each grid cell a fixed density for now. */
|
||||||
|
openvdb::tools::foreach (
|
||||||
|
density_grid->beginValueOn(),
|
||||||
|
[](const openvdb::FloatGrid::ValueOnIter &iter) { iter.setValue(1.0f); });
|
||||||
|
|
||||||
|
return volume;
|
||||||
|
|
||||||
|
#else
|
||||||
|
UNUSED_VARS(md, ctx);
|
||||||
|
UNUSED_VARS(compute_voxel_size);
|
||||||
|
BKE_modifier_set_error(md, "Compiled without OpenVDB");
|
||||||
|
return input_volume;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
ModifierTypeInfo modifierType_MeshToVolume = {
|
||||||
|
/* name */ "Mesh to Volume",
|
||||||
|
/* structName */ "MeshToVolumeModifierData",
|
||||||
|
/* structSize */ sizeof(MeshToVolumeModifierData),
|
||||||
|
/* srna */ &RNA_MeshToVolumeModifier,
|
||||||
|
/* type */ eModifierTypeType_Constructive,
|
||||||
|
/* flags */ static_cast<ModifierTypeFlag>(0),
|
||||||
|
/* icon */ ICON_VOLUME_DATA, /* TODO: Use correct icon. */
|
||||||
|
|
||||||
|
/* copyData */ BKE_modifier_copydata_generic,
|
||||||
|
|
||||||
|
/* deformVerts */ NULL,
|
||||||
|
/* deformMatrices */ NULL,
|
||||||
|
/* deformVertsEM */ NULL,
|
||||||
|
/* deformMatricesEM */ NULL,
|
||||||
|
/* modifyMesh */ NULL,
|
||||||
|
/* modifyHair */ NULL,
|
||||||
|
/* modifyPointCloud */ NULL,
|
||||||
|
/* modifyVolume */ modifyVolume,
|
||||||
|
|
||||||
|
/* initData */ initData,
|
||||||
|
/* requiredDataMask */ NULL,
|
||||||
|
/* freeData */ NULL,
|
||||||
|
/* isDisabled */ NULL,
|
||||||
|
/* updateDepsgraph */ updateDepsgraph,
|
||||||
|
/* dependsOnTime */ NULL,
|
||||||
|
/* dependsOnNormals */ NULL,
|
||||||
|
/* foreachObjectLink */ foreachObjectLink,
|
||||||
|
/* foreachIDLink */ NULL,
|
||||||
|
/* foreachTexLink */ NULL,
|
||||||
|
/* freeRuntimeData */ NULL,
|
||||||
|
/* panelRegister */ panelRegister,
|
||||||
|
/* blendWrite */ NULL,
|
||||||
|
/* blendRead */ NULL,
|
||||||
|
};
|
@@ -343,5 +343,6 @@ void modifier_type_init(ModifierTypeInfo *types[])
|
|||||||
INIT_TYPE(SurfaceDeform);
|
INIT_TYPE(SurfaceDeform);
|
||||||
INIT_TYPE(WeightedNormal);
|
INIT_TYPE(WeightedNormal);
|
||||||
INIT_TYPE(Simulation);
|
INIT_TYPE(Simulation);
|
||||||
|
INIT_TYPE(MeshToVolume);
|
||||||
#undef INIT_TYPE
|
#undef INIT_TYPE
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user