Fix T82516: Cycles crash updateding animated volumes after NanoVDB

Two issues:
* Automatic deduplication of OpenVDB grid data was failing when Cycles had
  already cleared the OpenVDB grid, causing an empty grid. Instead rely on
  Blender return the same OpenVDB grid pointer when deduplication is possible.
* The volume bounds mesh was not properly cleared when the OpenVDB grid was
  empty, causing a mismatch between mesh and voxel data.
This commit is contained in:
Brecht Van Lommel 2020-11-11 18:40:46 +01:00
parent f17dfd575c
commit 5c01ecd2bf
Notes: blender-bot 2023-02-14 05:04:52 +01:00
Referenced by issue #82516, Volume Object crash is back... this time with NanoVDB
2 changed files with 33 additions and 52 deletions

View File

@ -242,13 +242,6 @@ class BlenderVolumeLoader : public VDBImageLoader {
#endif
}
bool equals(const ImageLoader &other) const override
{
/* TODO: detect multiple volume datablocks with the same filepath. */
const BlenderVolumeLoader &other_loader = (const BlenderVolumeLoader &)other;
return b_volume == other_loader.b_volume && grid_name == other_loader.grid_name;
}
BL::Volume b_volume;
};
@ -307,25 +300,10 @@ static void sync_volume_object(BL::BlendData &b_data,
}
}
/* If the voxel attributes change, we need to rebuild the bounding mesh. */
static vector<int> get_voxel_image_slots(Mesh *mesh)
{
vector<int> slots;
for (const Attribute &attr : mesh->attributes.attributes) {
if (attr.element == ATTR_ELEMENT_VOXEL) {
slots.push_back(attr.data_voxel().svm_slot());
}
}
return slots;
}
void BlenderSync::sync_volume(BL::Object &b_ob,
Volume *volume,
const vector<Shader *> &used_shaders)
{
vector<int> old_voxel_slots = get_voxel_image_slots(volume);
volume->clear();
volume->used_shaders = used_shaders;
@ -342,8 +320,7 @@ void BlenderSync::sync_volume(BL::Object &b_ob,
}
/* Tag update. */
bool rebuild = (old_voxel_slots != get_voxel_image_slots(volume));
volume->tag_update(scene, rebuild);
volume->tag_update(scene, true);
}
CCL_NAMESPACE_END

View File

@ -495,6 +495,37 @@ void GeometryManager::create_volume_mesh(Volume *volume, Progress &progress)
string msg = string_printf("Computing Volume Mesh %s", volume->name.c_str());
progress.set_status("Updating Mesh", msg);
/* Find shader and compute padding based on volume shader interpolation settings. */
Shader *volume_shader = NULL;
int pad_size = 0;
foreach (Shader *shader, volume->used_shaders) {
if (!shader->has_volume) {
continue;
}
volume_shader = shader;
if (shader->volume_interpolation_method == VOLUME_INTERPOLATION_LINEAR) {
pad_size = max(1, pad_size);
}
else if (shader->volume_interpolation_method == VOLUME_INTERPOLATION_CUBIC) {
pad_size = max(2, pad_size);
}
break;
}
/* Clear existing volume mesh, done here in case we early out due to
* empty grid or missing volume shader. */
volume->clear();
volume->need_update_rebuild = true;
if (!volume_shader) {
return;
}
/* Create volume mesh builder. */
VolumeMeshBuilder builder;
#ifdef WITH_OPENVDB
@ -541,35 +572,11 @@ void GeometryManager::create_volume_mesh(Volume *volume, Progress &progress)
}
#endif
/* If nothing to build, early out. */
if (builder.empty_grid()) {
return;
}
/* Compute padding. */
Shader *volume_shader = NULL;
int pad_size = 0;
foreach (Shader *shader, volume->used_shaders) {
if (!shader->has_volume) {
continue;
}
volume_shader = shader;
if (shader->volume_interpolation_method == VOLUME_INTERPOLATION_LINEAR) {
pad_size = max(1, pad_size);
}
else if (shader->volume_interpolation_method == VOLUME_INTERPOLATION_CUBIC) {
pad_size = max(2, pad_size);
}
break;
}
if (!volume_shader) {
return;
}
builder.add_padding(pad_size);
/* Slightly offset vertex coordinates to avoid overlapping faces with other
@ -585,11 +592,8 @@ void GeometryManager::create_volume_mesh(Volume *volume, Progress &progress)
vector<float3> face_normals;
builder.create_mesh(vertices, indices, face_normals, face_overlap_avoidance);
volume->clear();
volume->reserve_mesh(vertices.size(), indices.size() / 3);
volume->used_shaders.push_back(volume_shader);
volume->need_update = true;
volume->need_update_rebuild = true;
for (size_t i = 0; i < vertices.size(); ++i) {
volume->add_vertex(vertices[i]);