23 # include <openvdb/tools/Dense.h>
24 # include <openvdb/tools/GridTransformer.h>
25 # include <openvdb/tools/Morphology.h>
76 const int quads_indices[6][4] = {
91 const float3 quads_normals[6] = {
106 static int add_vertex(
int3 v,
109 unordered_map<size_t, int> &used_verts)
111 size_t vert_key =
v.x +
v.y * (res.
x + 1) +
v.z * (res.
x + 1) * (res.
y + 1);
112 unordered_map<size_t, int>::iterator it = used_verts.find(vert_key);
114 if (it != used_verts.end()) {
118 int vertex_offset = vertices.size();
119 used_verts[vert_key] = vertex_offset;
120 vertices.push_back(
v);
121 return vertex_offset;
124 static void create_quad(
int3 corners[8],
128 unordered_map<size_t, int> &used_verts,
132 quad.v0 = add_vertex(corners[quads_indices[face_index][0]], vertices, res, used_verts);
133 quad.v1 = add_vertex(corners[quads_indices[face_index][1]], vertices, res, used_verts);
134 quad.v2 = add_vertex(corners[quads_indices[face_index][2]], vertices, res, used_verts);
135 quad.v3 = add_vertex(corners[quads_indices[face_index][3]], vertices, res, used_verts);
136 quad.normal = quads_normals[face_index];
138 quads.push_back(
quad);
156 openvdb::MaskGrid::Ptr topology_grid;
157 openvdb::CoordBBox bbox;
164 void add_grid(openvdb::GridBase::ConstPtr grid,
bool do_clipping,
float volume_clipping);
172 const float face_overlap_avoidance);
178 const float face_overlap_avoidance);
187 template<
typename Gr
idType>
188 void merge_grid(openvdb::GridBase::ConstPtr grid,
bool do_clipping,
float volume_clipping)
190 typename GridType::ConstPtr typed_grid = openvdb::gridConstPtrCast<GridType>(grid);
194 typename GridType::Ptr
copy = typed_grid->deepCopy();
195 typename GridType::ValueOnIter iter =
copy->beginValueOn();
197 for (; iter; ++iter) {
198 if (iter.getValue() <
ValueType(volume_clipping)) {
206 topology_grid->topologyUnion(*typed_grid);
217 void VolumeMeshBuilder::add_grid(openvdb::GridBase::ConstPtr grid,
219 float volume_clipping)
223 topology_grid = openvdb::MaskGrid::create();
224 topology_grid->setTransform(grid->transform().copy());
230 else if (topology_grid->transform() != grid->transform()) {
231 openvdb::MaskGrid::Ptr temp_grid = topology_grid->copyWithNewTree();
232 temp_grid->setTransform(grid->transform().copy());
233 openvdb::tools::resampleToMatch<openvdb::tools::BoxSampler>(*topology_grid, *temp_grid);
234 topology_grid = temp_grid;
235 topology_grid->setTransform(grid->transform().copy());
238 if (grid->isType<openvdb::FloatGrid>()) {
239 merge_grid<openvdb::FloatGrid>(grid, do_clipping, volume_clipping);
241 else if (grid->isType<openvdb::Vec3fGrid>()) {
242 merge_grid<openvdb::Vec3fGrid>(grid, do_clipping, volume_clipping);
244 else if (grid->isType<openvdb::Vec4fGrid>()) {
245 merge_grid<openvdb::Vec4fGrid>(grid, do_clipping, volume_clipping);
247 else if (grid->isType<openvdb::BoolGrid>()) {
248 merge_grid<openvdb::BoolGrid>(grid, do_clipping, volume_clipping);
250 else if (grid->isType<openvdb::DoubleGrid>()) {
251 merge_grid<openvdb::DoubleGrid>(grid, do_clipping, volume_clipping);
253 else if (grid->isType<openvdb::Int32Grid>()) {
254 merge_grid<openvdb::Int32Grid>(grid, do_clipping, volume_clipping);
256 else if (grid->isType<openvdb::Int64Grid>()) {
257 merge_grid<openvdb::Int64Grid>(grid, do_clipping, volume_clipping);
259 else if (grid->isType<openvdb::Vec3IGrid>()) {
260 merge_grid<openvdb::Vec3IGrid>(grid, do_clipping, volume_clipping);
262 else if (grid->isType<openvdb::Vec3dGrid>()) {
263 merge_grid<openvdb::Vec3dGrid>(grid, do_clipping, volume_clipping);
265 else if (grid->isType<openvdb::MaskGrid>()) {
266 topology_grid->topologyUnion(*openvdb::gridConstPtrCast<openvdb::MaskGrid>(grid));
274 openvdb::tools::dilateVoxels(topology_grid->tree(), pad_size);
283 const float face_overlap_avoidance)
293 topology_grid->tree().voxelizeActiveTiles();
304 (void)face_overlap_avoidance;
312 const openvdb::MaskGrid::TreeType &
tree = topology_grid->tree();
313 tree.evalLeafBoundingBox(bbox);
315 const int3 resolution =
make_int3(bbox.dim().x(), bbox.dim().y(), bbox.dim().z());
317 unordered_map<size_t, int> used_verts;
319 for (
auto iter =
tree.cbeginLeaf(); iter; ++iter) {
320 openvdb::CoordBBox leaf_bbox = iter->getNodeBoundingBox();
322 leaf_bbox.max() = leaf_bbox.max().offsetBy(1);
324 int3 min =
make_int3(leaf_bbox.min().x(), leaf_bbox.min().y(), leaf_bbox.min().z());
325 int3 max =
make_int3(leaf_bbox.max().x(), leaf_bbox.max().y(), leaf_bbox.max().z());
344 static const int LEAF_DIM = openvdb::MaskGrid::TreeType::LeafNodeType::DIM;
345 auto center = leaf_bbox.min() + openvdb::Coord(LEAF_DIM / 2);
348 create_quad(corners, vertices_is, quads, resolution, used_verts,
QUAD_X_MIN);
352 create_quad(corners, vertices_is, quads, resolution, used_verts,
QUAD_X_MAX);
356 create_quad(corners, vertices_is, quads, resolution, used_verts,
QUAD_Y_MIN);
360 create_quad(corners, vertices_is, quads, resolution, used_verts,
QUAD_Y_MAX);
364 create_quad(corners, vertices_is, quads, resolution, used_verts,
QUAD_Z_MIN);
368 create_quad(corners, vertices_is, quads, resolution, used_verts,
QUAD_Z_MAX);
379 const float face_overlap_avoidance)
383 bbox = topology_grid->evalActiveVoxelBoundingBox();
384 openvdb::Coord dim = bbox.dim();
387 float3 point_offset = cell_size * face_overlap_avoidance;
389 out_vertices.reserve(vertices.size());
391 for (
size_t i = 0; i < vertices.size(); ++i) {
395 out_vertices.push_back(vertex + point_offset);
400 (void)face_overlap_avoidance;
408 int index_offset = 0;
409 tris.resize(quads.size() * 6);
410 face_normals.reserve(quads.size() * 2);
412 for (
size_t i = 0; i < quads.size(); ++i) {
413 tris[index_offset++] = quads[i].v0;
414 tris[index_offset++] = quads[i].v2;
415 tris[index_offset++] = quads[i].v1;
417 face_normals.push_back(quads[i].
normal);
419 tris[index_offset++] = quads[i].v0;
420 tris[index_offset++] = quads[i].v3;
421 tris[index_offset++] = quads[i].v2;
423 face_normals.push_back(quads[i].
normal);
430 return !topology_grid || topology_grid->tree().leafCount() == 0;
437 template<
typename Gr
idType>
438 static openvdb::GridBase::ConstPtr openvdb_grid_from_device_texture(
device_texture *image_memory,
439 float volume_clipping,
444 openvdb::CoordBBox dense_bbox(0,
451 typename GridType::Ptr sparse = GridType::create(
ValueType(0.0f));
452 if (dense_bbox.empty()) {
456 openvdb::tools::Dense<ValueType, openvdb::tools::MemoryLayout::LayoutXYZ> dense(
459 openvdb::tools::copyFromDense(dense, *sparse,
ValueType(volume_clipping));
465 sparse->tree().voxelizeActiveTiles();
474 openvdb::Mat4R index_to_world_mat((
double)(voxel_size.
x * transform_3d[0][0]),
479 (
double)(voxel_size.
y * transform_3d[1][1]),
484 (
double)(voxel_size.
z * transform_3d[2][2]),
486 (
double)transform_3d[0][3],
487 (
double)transform_3d[1][3],
488 (
double)transform_3d[2][3],
491 openvdb::math::Transform::Ptr index_to_world_tfm =
492 openvdb::math::Transform::createLinearTransform(index_to_world_mat);
494 sparse->setTransform(index_to_world_tfm);
511 foreach (
Node *
node, volume->get_used_shaders()) {
514 if (!
shader->has_volume) {
521 pad_size =
max(1, pad_size);
524 pad_size =
max(2, pad_size);
537 if (!volume_shader) {
550 bool do_clipping =
false;
556 openvdb::GridBase::ConstPtr grid;
558 grid = vdb_loader->get_grid();
569 grid = openvdb_grid_from_device_texture<openvdb::FloatGrid>(
573 grid = openvdb_grid_from_device_texture<openvdb::Vec3fGrid>(
577 grid = openvdb_grid_from_device_texture<openvdb::Vec4fGrid>(
583 builder.add_grid(grid, do_clipping, volume->get_clipping());
599 const float face_overlap_avoidance = 0.1f *
609 volume->used_shaders.
clear();
610 volume->used_shaders.push_back_slow(volume_shader);
612 for (
size_t i = 0; i < vertices.size(); ++i) {
616 for (
size_t i = 0; i <
indices.size(); i += 3) {
623 for (
size_t i = 0; i < face_normals.size(); ++i) {
624 fN[i] = face_normals[i];
628 VLOG(1) <<
"Memory usage volume mesh: "
629 << ((vertices.size() + face_normals.size()) *
sizeof(
float3) +
630 indices.size() *
sizeof(int)) /
NSNotificationCenter * center
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble z
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
ATTR_WARN_UNUSED_RESULT const BMVert * v
Attribute * add(ustring name, TypeDesc type, AttributeElement element)
list< Attribute > attributes
ImageHandle & data_voxel()
void create_volume_mesh(Volume *volume, Progress &progress)
VDBImageLoader * vdb_loader(const int tile_index=0) const
device_texture * image_memory(const int tile_index=0) const
void set_status(const string &status_, const string &substatus_="")
void convert_quads_to_tris(const vector< QuadData > &quads, vector< int > &tris, vector< float3 > &face_normals)
void add_padding(int pad_size)
void convert_object_space(const vector< int3 > &vertices, vector< float3 > &out_vertices, const float face_overlap_avoidance)
void create_mesh(vector< float3 > &vertices, vector< int > &indices, vector< float3 > &face_normals, const float face_overlap_avoidance)
void generate_vertices_and_quads(vector< int3 > &vertices_is, vector< QuadData > &quads)
IconTextureDrawCall normal
#define CCL_NAMESPACE_END
#define make_int3(x, y, z)
#define make_float3(x, y, z)
void KERNEL_FUNCTION_FULL_NAME() shader(KernelGlobals *kg, uint4 *input, float4 *output, int type, int filter, int i, int offset, int sample)
VecMat::Vec3< double > Vec3d
static void copy(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node)
#define SOCKET_FLOAT(name, ui_name, default_value,...)
#define SOCKET_BOOLEAN(name, ui_name, default_value,...)
@ VOLUME_INTERPOLATION_LINEAR
@ VOLUME_INTERPOLATION_CUBIC
void clear(bool preserve_shaders=false) override
void reserve_mesh(int numverts, int numfaces)
void add_vertex(float3 P)
void add_triangle(int v0, int v1, int v2, int shader, bool smooth)
static NodeType * add(const char *name, CreateFunc create, Type type=NONE, const NodeType *base=NULL)
virtual void clear(bool preserve_shaders=false) override
static uint hash_string(const char *str)
ccl_device_inline float hash_uint_to_float(uint kx)
CCL_NAMESPACE_BEGIN string string_printf(const char *format,...)
CCL_NAMESPACE_BEGIN NODE_DEFINE(Volume)