Cycles: add "density", "flame" and "color" attributes for smoke domains.
[blender.git] / intern / cycles / blender / blender_mesh.cpp
index 9e11cc1ae0b44a68efeab84ba0c026d9cb6a4489..fb667d1ba2f9535d0fb34650b6bcad028eb4c708 100644 (file)
@@ -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)
@@ -559,6 +595,9 @@ void BlenderSync::sync_mesh_motion(BL::Object b_ob, Object *object, float motion
        int time_index = 0;
 
        if(scene->need_motion() == Scene::MOTION_BLUR) {
+               if(!mesh->use_motion_blur)
+                       return;
+               
                /* see if this mesh needs motion data at this time */
                vector<float> object_times = object->motion_times();
                bool found = false;
@@ -601,37 +640,50 @@ void BlenderSync::sync_mesh_motion(BL::Object b_ob, Object *object, float motion
        if(numverts) {
                /* find attributes */
                Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+               Attribute *attr_mN = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_NORMAL);
+               Attribute *attr_N = mesh->attributes.find(ATTR_STD_VERTEX_NORMAL);
                bool new_attribute = false;
 
                /* add new attributes if they don't exist already */
                if(!attr_mP) {
                        attr_mP = mesh->attributes.add(ATTR_STD_MOTION_VERTEX_POSITION);
+                       if(attr_N)
+                               attr_mN = mesh->attributes.add(ATTR_STD_MOTION_VERTEX_NORMAL);
 
                        new_attribute = true;
                }
 
                /* load vertex data from mesh */
                float3 *mP = attr_mP->data_float3() + time_index*numverts;
+               float3 *mN = (attr_mN)? attr_mN->data_float3() + time_index*numverts: NULL;
 
                BL::Mesh::vertices_iterator v;
                int i = 0;
 
-               for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end() && i < numverts; ++v, ++i)
+               for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end() && i < numverts; ++v, ++i) {
                        mP[i] = get_float3(v->co());
+                       if(mN)
+                               mN[i] = get_float3(v->normal());
+               }
 
                /* in case of new attribute, we verify if there really was any motion */
                if(new_attribute) {
                        if(i != numverts || memcmp(mP, &mesh->verts[0], sizeof(float3)*numverts) == 0) {
                                /* no motion, remove attributes again */
                                mesh->attributes.remove(ATTR_STD_MOTION_VERTEX_POSITION);
+                               if(attr_mN)
+                                       mesh->attributes.remove(ATTR_STD_MOTION_VERTEX_NORMAL);
                        }
                        else if(time_index > 0) {
                                /* motion, fill up previous steps that we might have skipped because
                                 * they had no motion, but we need them anyway now */
                                float3 *P = &mesh->verts[0];
+                               float3 *N = (attr_N)? attr_N->data_float3(): NULL;
 
-                               for(int step = 0; step < time_index; step++)
+                               for(int step = 0; step < time_index; step++) {
                                        memcpy(attr_mP->data_float3() + step*numverts, P, sizeof(float3)*numverts);
+                                       memcpy(attr_mN->data_float3() + step*numverts, N, sizeof(float3)*numverts);
+                               }
                        }
                }
        }