diff options
author | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2014-03-29 16:03:46 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2014-03-29 16:03:46 +0400 |
commit | 99f59930885ed69890967f8864a3aa0626249d86 (patch) | |
tree | b6f8dcc40c294077d585639e701f7fdf9b6c0dcb /intern/cycles/blender/blender_mesh.cpp | |
parent | 934767cf7f51ae82224138de2ffcafe7bae2b8fa (diff) |
Cycles code refactor: improve vertex motion attribute storage and export.
This now supports multiple steps and subframe sampling of motion.
There is one difference for object and camera transform motion blur. It still
only supports two steps there, but the transforms are now sampled at subframe
times instead of the previous and next frame and then interpolated/extrapolated.
This will give different render results in some cases but it's more accurate.
Part of the code is from the summer of code project by Gavin Howard, but it has
been significantly rewritten and extended.
Diffstat (limited to 'intern/cycles/blender/blender_mesh.cpp')
-rw-r--r-- | intern/cycles/blender/blender_mesh.cpp | 110 |
1 files changed, 84 insertions, 26 deletions
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index b356537e971..9e11cc1ae0b 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -449,6 +449,7 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tri Mesh *mesh; if(!mesh_map.sync(&mesh, key)) { + /* if transform was applied to mesh, need full update */ if(object_updated && mesh->transform_applied); /* test if shaders changed, these can be object level so mesh @@ -503,7 +504,7 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tri } if(render_layer.use_hair) - sync_curves(mesh, b_mesh, b_ob, 0); + sync_curves(mesh, b_mesh, b_ob, false); /* free derived mesh */ b_data.meshes.remove(b_mesh); @@ -544,46 +545,103 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tri return mesh; } -void BlenderSync::sync_mesh_motion(BL::Object b_ob, Mesh *mesh, int motion) +void BlenderSync::sync_mesh_motion(BL::Object b_ob, Object *object, float motion_time) { - /* todo: displacement, subdivision */ - size_t size = mesh->verts.size(); - - /* skip objects without deforming modifiers. this is not a totally reliable, - * would need a more extensive check to see which objects are animated */ - if(!size || !ccl::BKE_object_is_deform_modified(b_ob, b_scene, preview)) - return; - /* ensure we only sync instanced meshes once */ + Mesh *mesh = object->mesh; + if(mesh_motion_synced.find(mesh) != mesh_motion_synced.end()) return; mesh_motion_synced.insert(mesh); + /* for motion pass always compute, for motion blur it can be disabled */ + int time_index = 0; + + if(scene->need_motion() == Scene::MOTION_BLUR) { + /* see if this mesh needs motion data at this time */ + vector<float> object_times = object->motion_times(); + bool found = false; + + foreach(float object_time, object_times) { + if(motion_time == object_time) { + found = true; + break; + } + else + time_index++; + } + + if(!found) + return; + } + else { + if(motion_time == -1.0f) + time_index = 0; + else if(motion_time == 1.0f) + time_index = 1; + else + return; + } + + /* skip objects without deforming modifiers. this is not totally reliable, + * would need a more extensive check to see which objects are animated */ + size_t numverts = mesh->verts.size(); + size_t numkeys = mesh->curve_keys.size(); + + if((!numverts && !numkeys) || !ccl::BKE_object_is_deform_modified(b_ob, b_scene, preview)) + return; + /* get derived mesh */ BL::Mesh b_mesh = object_to_mesh(b_data, b_ob, b_scene, true, !preview, false); - if(b_mesh) { - BL::Mesh::vertices_iterator v; - AttributeStandard std = (motion == -1)? ATTR_STD_MOTION_PRE: ATTR_STD_MOTION_POST; - Attribute *attr_M = mesh->attributes.add(std); - float3 *M = attr_M->data_float3(), *cur_M; - size_t i = 0; + if(!b_mesh) + return; + + if(numverts) { + /* find attributes */ + Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); + 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); + + new_attribute = true; + } + + /* load vertex data from mesh */ + float3 *mP = attr_mP->data_float3() + time_index*numverts; - for(b_mesh.vertices.begin(v), cur_M = M; v != b_mesh.vertices.end() && i < size; ++v, cur_M++, i++) - *cur_M = get_float3(v->co()); + BL::Mesh::vertices_iterator v; + int i = 0; - /* if number of vertices changed, or if coordinates stayed the same, drop it */ - if(i != size || memcmp(M, &mesh->verts[0], sizeof(float3)*size) == 0) - mesh->attributes.remove(std); + for(b_mesh.vertices.begin(v); v != b_mesh.vertices.end() && i < numverts; ++v, ++i) + mP[i] = get_float3(v->co()); - /* hair motion */ - if(render_layer.use_hair) - sync_curves(mesh, b_mesh, b_ob, motion); + /* 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); + } + 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]; - /* free derived mesh */ - b_data.meshes.remove(b_mesh); + for(int step = 0; step < time_index; step++) + memcpy(attr_mP->data_float3() + step*numverts, P, sizeof(float3)*numverts); + } + } } + + /* hair motion */ + if(numkeys) + sync_curves(mesh, b_mesh, b_ob, true, time_index); + + /* free derived mesh */ + b_data.meshes.remove(b_mesh); } CCL_NAMESPACE_END |