Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/cycles/blender/blender_volume.cpp')
-rw-r--r--intern/cycles/blender/blender_volume.cpp180
1 files changed, 168 insertions, 12 deletions
diff --git a/intern/cycles/blender/blender_volume.cpp b/intern/cycles/blender/blender_volume.cpp
index 47259d4945c..237c5d061e8 100644
--- a/intern/cycles/blender/blender_volume.cpp
+++ b/intern/cycles/blender/blender_volume.cpp
@@ -1,4 +1,3 @@
-
/*
* Copyright 2011-2013 Blender Foundation
*
@@ -24,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);
@@ -31,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,15 +193,12 @@ static void sync_smoke_volume(Scene *scene, BL::Object &b_ob, Mesh *mesh, float
mesh->volume_isovalue = b_domain.clipping();
Attribute *attr = mesh->attributes.add(std);
- VoxelAttribute *volume_data = attr->data_voxel();
- ImageMetaData metadata;
- 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;
- volume_data->manager = image_manager;
- volume_data->slot = image_manager->add_image(key, frame, metadata);
+ attr->data_voxel() = scene->image_manager->add_image(loader, params);
}
/* Create a matrix to transform from object space to mesh texture space.
@@ -75,18 +216,33 @@ static void sync_smoke_volume(Scene *scene, BL::Object &b_ob, Mesh *mesh, float
}
}
+/* 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, Mesh *mesh, const vector<Shader *> &used_shaders)
{
- bool old_has_voxel_attributes = mesh->has_voxel_attributes();
+ vector<int> old_voxel_slots = get_voxel_image_slots(mesh);
mesh->clear();
mesh->used_shaders = used_shaders;
/* Smoke domain. */
- sync_smoke_volume(scene, b_ob, mesh, b_scene.frame_current());
+ if (view_layer.use_volumes) {
+ sync_smoke_volume(scene, b_ob, mesh, b_scene.frame_current());
+ }
/* Tag update. */
- bool rebuild = (old_has_voxel_attributes != mesh->has_voxel_attributes());
+ bool rebuild = (old_voxel_slots != get_voxel_image_slots(mesh));
mesh->tag_update(scene, rebuild);
}