diff options
author | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2020-03-08 16:21:29 +0300 |
---|---|---|
committer | Brecht Van Lommel <brecht@blender.org> | 2020-03-11 22:45:39 +0300 |
commit | 6cf4861c3ac09fd65a765e8f8e3584713cc5303b (patch) | |
tree | b2b104fbda65b67c56dd2a39ad812c89bc5b1ee2 /intern/cycles/blender/blender_volume.cpp | |
parent | d8aa613d94caf6a3d82a8f4e9e90b9b8f5c61a7d (diff) |
Cleanup: refactor image loading to use abstract ImageLoader base class
Rather than passing around void pointers, various Blender image sources now
subclass this. OIIO is also just another type of image loader.
Also fixes T67718: Cycles viewport render crash editing point density settings
Diffstat (limited to 'intern/cycles/blender/blender_volume.cpp')
-rw-r--r-- | intern/cycles/blender/blender_volume.cpp | 155 |
1 files changed, 150 insertions, 5 deletions
diff --git a/intern/cycles/blender/blender_volume.cpp b/intern/cycles/blender/blender_volume.cpp index e11cc4ab18f..60ef4c5ed87 100644 --- a/intern/cycles/blender/blender_volume.cpp +++ b/intern/cycles/blender/blender_volume.cpp @@ -23,6 +23,152 @@ CCL_NAMESPACE_BEGIN +/* TODO: verify this is not loading unnecessary attributes. */ +class BlenderSmokeLoader : public ImageLoader { + public: + BlenderSmokeLoader(const BL::Object &b_ob, AttributeStandard attribute) + : b_ob(b_ob), attribute(attribute) + { + } + + bool load_metadata(ImageMetaData &metadata) override + { + BL::FluidDomainSettings b_domain = object_fluid_gas_domain_find(b_ob); + + if (!b_domain) { + return false; + } + + if (attribute == ATTR_STD_VOLUME_DENSITY || attribute == ATTR_STD_VOLUME_FLAME || + attribute == ATTR_STD_VOLUME_HEAT || attribute == ATTR_STD_VOLUME_TEMPERATURE) { + metadata.type = IMAGE_DATA_TYPE_FLOAT; + metadata.channels = 1; + } + else if (attribute == ATTR_STD_VOLUME_COLOR) { + metadata.type = IMAGE_DATA_TYPE_FLOAT4; + metadata.channels = 4; + } + else if (attribute == ATTR_STD_VOLUME_VELOCITY) { + metadata.type = IMAGE_DATA_TYPE_FLOAT4; + metadata.channels = 3; + } + else { + return false; + } + + int3 resolution = get_int3(b_domain.domain_resolution()); + int amplify = (b_domain.use_noise()) ? b_domain.noise_scale() : 1; + + /* Velocity and heat data is always low-resolution. */ + if (attribute == ATTR_STD_VOLUME_VELOCITY || attribute == ATTR_STD_VOLUME_HEAT) { + amplify = 1; + } + + metadata.width = resolution.x * amplify; + metadata.height = resolution.y * amplify; + metadata.depth = resolution.z * amplify; + + return true; + } + + bool load_pixels(const ImageMetaData &, void *pixels, const size_t, const bool) override + { + /* smoke volume data */ + BL::FluidDomainSettings b_domain = object_fluid_gas_domain_find(b_ob); + + if (!b_domain) { + return false; + } +#ifdef WITH_FLUID + int3 resolution = get_int3(b_domain.domain_resolution()); + int length, amplify = (b_domain.use_noise()) ? b_domain.noise_scale() : 1; + + /* Velocity and heat data is always low-resolution. */ + if (attribute == ATTR_STD_VOLUME_VELOCITY || attribute == ATTR_STD_VOLUME_HEAT) { + amplify = 1; + } + + const int width = resolution.x * amplify; + const int height = resolution.y * amplify; + const int depth = resolution.z * amplify; + const size_t num_pixels = ((size_t)width) * height * depth; + + float *fpixels = (float *)pixels; + + if (attribute == ATTR_STD_VOLUME_DENSITY) { + FluidDomainSettings_density_grid_get_length(&b_domain.ptr, &length); + if (length == num_pixels) { + FluidDomainSettings_density_grid_get(&b_domain.ptr, fpixels); + return true; + } + } + else if (attribute == ATTR_STD_VOLUME_FLAME) { + /* this is in range 0..1, and interpreted by the OpenGL smoke viewer + * as 1500..3000 K with the first part faded to zero density */ + FluidDomainSettings_flame_grid_get_length(&b_domain.ptr, &length); + if (length == num_pixels) { + FluidDomainSettings_flame_grid_get(&b_domain.ptr, fpixels); + return true; + } + } + else if (attribute == ATTR_STD_VOLUME_COLOR) { + /* the RGB is "premultiplied" by density for better interpolation results */ + FluidDomainSettings_color_grid_get_length(&b_domain.ptr, &length); + if (length == num_pixels * 4) { + FluidDomainSettings_color_grid_get(&b_domain.ptr, fpixels); + return true; + } + } + else if (attribute == ATTR_STD_VOLUME_VELOCITY) { + FluidDomainSettings_velocity_grid_get_length(&b_domain.ptr, &length); + if (length == num_pixels * 3) { + FluidDomainSettings_velocity_grid_get(&b_domain.ptr, fpixels); + return true; + } + } + else if (attribute == ATTR_STD_VOLUME_HEAT) { + FluidDomainSettings_heat_grid_get_length(&b_domain.ptr, &length); + if (length == num_pixels) { + FluidDomainSettings_heat_grid_get(&b_domain.ptr, fpixels); + return true; + } + } + else if (attribute == ATTR_STD_VOLUME_TEMPERATURE) { + FluidDomainSettings_temperature_grid_get_length(&b_domain.ptr, &length); + if (length == num_pixels) { + FluidDomainSettings_temperature_grid_get(&b_domain.ptr, fpixels); + return true; + } + } + else { + fprintf(stderr, + "Cycles error: unknown volume attribute %s, skipping\n", + Attribute::standard_name(attribute)); + fpixels[0] = 0.0f; + return false; + } +#else + (void)pixels; +#endif + fprintf(stderr, "Cycles error: unexpected smoke volume resolution, skipping\n"); + return false; + } + + string name() const override + { + return Attribute::standard_name(attribute); + } + + bool equals(const ImageLoader &other) const override + { + const BlenderSmokeLoader &other_loader = (const BlenderSmokeLoader &)other; + return b_ob == other_loader.b_ob && attribute == other_loader.attribute; + } + + BL::Object b_ob; + AttributeStandard attribute; +}; + static void sync_smoke_volume(Scene *scene, BL::Object &b_ob, Mesh *mesh, float frame) { BL::FluidDomainSettings b_domain = object_fluid_gas_domain_find(b_ob); @@ -30,7 +176,6 @@ static void sync_smoke_volume(Scene *scene, BL::Object &b_ob, Mesh *mesh, float return; } - ImageManager *image_manager = scene->image_manager; AttributeStandard attributes[] = {ATTR_STD_VOLUME_DENSITY, ATTR_STD_VOLUME_COLOR, ATTR_STD_VOLUME_FLAME, @@ -49,11 +194,11 @@ static void sync_smoke_volume(Scene *scene, BL::Object &b_ob, Mesh *mesh, float Attribute *attr = mesh->attributes.add(std); - ImageKey key; - key.filename = Attribute::standard_name(std); - key.builtin_data = b_ob.ptr.data; + ImageLoader *loader = new BlenderSmokeLoader(b_ob, std); + ImageParams params; + params.frame = frame; - attr->add(image_manager->add_image(key, frame)); + attr->data_voxel() = scene->image_manager->add_image(loader, params); } /* Create a matrix to transform from object space to mesh texture space. |