diff options
-rw-r--r-- | intern/cycles/blender/blender_mesh.cpp | 36 | ||||
-rw-r--r-- | intern/cycles/blender/blender_session.cpp | 165 | ||||
-rw-r--r-- | intern/cycles/blender/blender_util.h | 21 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_types.h | 5 | ||||
-rw-r--r-- | intern/cycles/render/attribute.cpp | 21 |
5 files changed, 206 insertions, 42 deletions
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index 8c9734283ea..fb667d1ba2f 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -206,6 +206,40 @@ static void mikk_compute_tangents(BL::Mesh b_mesh, BL::MeshTextureFaceLayer b_la } } +/* Create Volume Attribute */ + +static void create_mesh_volume_attribute(BL::Object b_ob, Mesh *mesh, ImageManager *image_manager, AttributeStandard std) +{ + BL::SmokeDomainSettings b_domain = object_smoke_domain_find(b_ob); + + if(!b_domain) + return; + + Attribute *attr = mesh->attributes.add(std); + VoxelAttribute *volume_data = attr->data_voxel(); + bool is_float, is_linear; + bool animated = false; + + volume_data->manager = image_manager; + volume_data->slot = image_manager->add_image(Attribute::standard_name(std), + b_ob.ptr.data, animated, is_float, is_linear, INTERPOLATION_LINEAR); +} + +static void create_mesh_volume_attributes(Scene *scene, BL::Object b_ob, Mesh *mesh) +{ + /* for smoke volume rendering */ + if(mesh->need_attribute(scene, ATTR_STD_VOLUME_DENSITY)) + create_mesh_volume_attribute(b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_DENSITY); + if(mesh->need_attribute(scene, ATTR_STD_VOLUME_COLOR)) + create_mesh_volume_attribute(b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_COLOR); + if(mesh->need_attribute(scene, ATTR_STD_VOLUME_FLAME)) + create_mesh_volume_attribute(b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_FLAME); + if(mesh->need_attribute(scene, ATTR_STD_VOLUME_HEAT)) + create_mesh_volume_attribute(b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_HEAT); + if(mesh->need_attribute(scene, ATTR_STD_VOLUME_VELOCITY)) + create_mesh_volume_attribute(b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_VELOCITY); +} + /* Create Mesh */ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<uint>& used_shaders) @@ -501,6 +535,8 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tri create_subd_mesh(scene, mesh, b_mesh, &cmesh, used_shaders); else create_mesh(scene, mesh, b_mesh, used_shaders); + + create_mesh_volume_attributes(scene, b_ob, mesh); } if(render_layer.use_hair) diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 82434712ca7..f5e696bc582 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -726,85 +726,121 @@ int BlenderSession::builtin_image_frame(const string &builtin_name) void BlenderSession::builtin_image_info(const string &builtin_name, void *builtin_data, bool &is_float, int &width, int &height, int &depth, int &channels) { + /* empty image */ + is_float = false; + width = 0; + height = 0; + depth = 0; + channels = 0; + + if(!builtin_data) + return; + + /* recover ID pointer */ PointerRNA ptr; RNA_id_pointer_create((ID*)builtin_data, &ptr); - BL::Image b_image(ptr); + BL::ID b_id(ptr); + + if(b_id.is_a(&RNA_Image)) { + /* image data */ + BL::Image b_image(b_id); - if(b_image) { is_float = b_image.is_float(); width = b_image.size()[0]; height = b_image.size()[1]; depth = 1; channels = b_image.channels(); } - else { - is_float = false; - width = 0; - height = 0; - depth = 0; - channels = 0; + else if(b_id.is_a(&RNA_Object)) { + /* smoke volume data */ + BL::Object b_ob(b_id); + BL::SmokeDomainSettings b_domain = object_smoke_domain_find(b_ob); + + if(!b_domain) + return; + + if(builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_DENSITY) || + builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_FLAME)) + channels = 1; + else if(builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_COLOR)) + channels = 4; + else + return; + + int3 resolution = get_int3(b_domain.domain_resolution()); + int amplify = (b_domain.use_high_resolution())? b_domain.amplify() + 1: 1; + + width = resolution.x * amplify; + height = resolution.y * amplify; + depth = resolution.z * amplify; + + is_float = true; } } bool BlenderSession::builtin_image_pixels(const string &builtin_name, void *builtin_data, unsigned char *pixels) { + if(!builtin_data) + return false; + int frame = builtin_image_frame(builtin_name); PointerRNA ptr; RNA_id_pointer_create((ID*)builtin_data, &ptr); BL::Image b_image(ptr); - if(b_image) { - int width = b_image.size()[0]; - int height = b_image.size()[1]; - int channels = b_image.channels(); + int width = b_image.size()[0]; + int height = b_image.size()[1]; + int channels = b_image.channels(); - unsigned char *image_pixels; - image_pixels = image_get_pixels_for_frame(b_image, frame); + unsigned char *image_pixels; + image_pixels = image_get_pixels_for_frame(b_image, frame); - if(image_pixels) { - memcpy(pixels, image_pixels, width * height * channels * sizeof(unsigned char)); - MEM_freeN(image_pixels); + if(image_pixels) { + memcpy(pixels, image_pixels, width * height * channels * sizeof(unsigned char)); + MEM_freeN(image_pixels); + } + else { + if(channels == 1) { + memset(pixels, 0, width * height * sizeof(unsigned char)); } else { - if(channels == 1) { - memset(pixels, 0, width * height * sizeof(unsigned char)); - } - else { - unsigned char *cp = pixels; - for(int i = 0; i < width * height; i++, cp += channels) { - cp[0] = 255; - cp[1] = 0; - cp[2] = 255; - if(channels == 4) - cp[3] = 255; - } + unsigned char *cp = pixels; + for(int i = 0; i < width * height; i++, cp += channels) { + cp[0] = 255; + cp[1] = 0; + cp[2] = 255; + if(channels == 4) + cp[3] = 255; } } + } - /* premultiply, byte images are always straight for blender */ - unsigned char *cp = pixels; - for(int i = 0; i < width * height; i++, cp += channels) { - cp[0] = (cp[0] * cp[3]) >> 8; - cp[1] = (cp[1] * cp[3]) >> 8; - cp[2] = (cp[2] * cp[3]) >> 8; - } - - return true; + /* premultiply, byte images are always straight for blender */ + unsigned char *cp = pixels; + for(int i = 0; i < width * height; i++, cp += channels) { + cp[0] = (cp[0] * cp[3]) >> 8; + cp[1] = (cp[1] * cp[3]) >> 8; + cp[2] = (cp[2] * cp[3]) >> 8; } - return false; + return true; } bool BlenderSession::builtin_image_float_pixels(const string &builtin_name, void *builtin_data, float *pixels) { - int frame = builtin_image_frame(builtin_name); + if(!builtin_data) + return false; PointerRNA ptr; RNA_id_pointer_create((ID*)builtin_data, &ptr); - BL::Image b_image(ptr); + BL::ID b_id(ptr); + + if(b_id.is_a(&RNA_Image)) { + /* image data */ + BL::Image b_image(b_id); + int frame = builtin_image_frame(builtin_name); - if(b_image) { int width = b_image.size()[0]; int height = b_image.size()[1]; int channels = b_image.channels(); @@ -834,6 +870,51 @@ bool BlenderSession::builtin_image_float_pixels(const string &builtin_name, void return true; } + else if(b_id.is_a(&RNA_Object)) { + /* smoke volume data */ + BL::Object b_ob(b_id); + BL::SmokeDomainSettings b_domain = object_smoke_domain_find(b_ob); + + if(!b_domain) + return false; + + int3 resolution = get_int3(b_domain.domain_resolution()); + int length, amplify = (b_domain.use_high_resolution())? b_domain.amplify() + 1: 1; + + int width = resolution.x * amplify; + int height = resolution.y * amplify; + int depth = resolution.z * amplify; + + if(builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_DENSITY)) { + SmokeDomainSettings_density_grid_get_length(&b_domain.ptr, &length); + + if(length == width*height*depth) { + SmokeDomainSettings_density_grid_get(&b_domain.ptr, pixels); + return true; + } + } + else if(builtin_name == Attribute::standard_name(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 */ + SmokeDomainSettings_flame_grid_get_length(&b_domain.ptr, &length); + + if(length == width*height*depth) { + SmokeDomainSettings_flame_grid_get(&b_domain.ptr, pixels); + return true; + } + } + else if(builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_COLOR)) { + /* the RGB is "premultiplied" by density for better interpolation results */ + SmokeDomainSettings_color_grid_get_length(&b_domain.ptr, &length); + + if(length == width*height*depth*4) { + SmokeDomainSettings_color_grid_get(&b_domain.ptr, pixels); + return true; + } + } + + fprintf(stderr, "Cycles error: unexpected smoke volume resolution, skipping\n"); + } return false; } diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h index bea5ee49bf4..45ca0e17550 100644 --- a/intern/cycles/blender/blender_util.h +++ b/intern/cycles/blender/blender_util.h @@ -168,6 +168,11 @@ static inline float4 get_float4(BL::Array<float, 4> array) return make_float4(array[0], array[1], array[2], array[3]); } +static inline int3 get_int3(BL::Array<int, 3> array) +{ + return make_int3(array[0], array[1], array[2]); +} + static inline int4 get_int4(BL::Array<int, 4> array) { return make_int4(array[0], array[1], array[2], array[3]); @@ -371,6 +376,22 @@ static inline bool object_use_deform_motion(BL::Object b_ob) return use_deform_motion; } +static inline BL::SmokeDomainSettings object_smoke_domain_find(BL::Object b_ob) +{ + BL::Object::modifiers_iterator b_mod; + + for(b_ob.modifiers.begin(b_mod); b_mod != b_ob.modifiers.end(); ++b_mod) { + if (b_mod->is_a(&RNA_SmokeModifier)) { + BL::SmokeModifier b_smd(*b_mod); + + if(b_smd.smoke_type() == BL::SmokeModifier::smoke_type_DOMAIN) + return b_smd.domain_settings(); + } + } + + return BL::SmokeDomainSettings(PointerRNA_NULL); +} + /* ID Map * * Utility class to keep in sync with blender data. diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index f7aebd29bbe..f01b173269c 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -480,6 +480,11 @@ typedef enum AttributeStandard { ATTR_STD_CURVE_INTERCEPT, ATTR_STD_PTEX_FACE_ID, ATTR_STD_PTEX_UV, + ATTR_STD_VOLUME_DENSITY, + ATTR_STD_VOLUME_COLOR, + ATTR_STD_VOLUME_FLAME, + ATTR_STD_VOLUME_HEAT, + ATTR_STD_VOLUME_VELOCITY, ATTR_STD_NUM, ATTR_STD_NOT_FOUND = ~0 diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp index cd81c33a28f..e5b1ee7b95e 100644 --- a/intern/cycles/render/attribute.cpp +++ b/intern/cycles/render/attribute.cpp @@ -202,6 +202,16 @@ const char *Attribute::standard_name(AttributeStandard std) return "ptex_face_id"; case ATTR_STD_PTEX_UV: return "ptex_uv"; + case ATTR_STD_VOLUME_DENSITY: + return "density"; + case ATTR_STD_VOLUME_COLOR: + return "color"; + case ATTR_STD_VOLUME_FLAME: + return "flame"; + case ATTR_STD_VOLUME_HEAT: + return "heat"; + case ATTR_STD_VOLUME_VELOCITY: + return "velocity"; case ATTR_STD_NOT_FOUND: case ATTR_STD_NONE: case ATTR_STD_NUM: @@ -328,6 +338,17 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name) case ATTR_STD_GENERATED_TRANSFORM: attr = add(name, TypeDesc::TypeMatrix, ATTR_ELEMENT_MESH); break; + case ATTR_STD_VOLUME_DENSITY: + case ATTR_STD_VOLUME_FLAME: + case ATTR_STD_VOLUME_HEAT: + attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_VOXEL); + break; + case ATTR_STD_VOLUME_COLOR: + attr = add(name, TypeDesc::TypeColor, ATTR_ELEMENT_VOXEL); + break; + case ATTR_STD_VOLUME_VELOCITY: + attr = add(name, TypeDesc::TypeVector, ATTR_ELEMENT_VOXEL); + break; default: assert(0); break; |