diff options
Diffstat (limited to 'intern/cycles/blender')
-rw-r--r-- | intern/cycles/blender/blender_camera.cpp | 12 | ||||
-rw-r--r-- | intern/cycles/blender/blender_curves.cpp | 52 | ||||
-rw-r--r-- | intern/cycles/blender/blender_mesh.cpp | 110 | ||||
-rw-r--r-- | intern/cycles/blender/blender_object.cpp | 88 | ||||
-rw-r--r-- | intern/cycles/blender/blender_sync.h | 12 |
5 files changed, 196 insertions, 78 deletions
diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp index 4c6b42a9cbc..6bbd4106a96 100644 --- a/intern/cycles/blender/blender_camera.cpp +++ b/intern/cycles/blender/blender_camera.cpp @@ -386,7 +386,7 @@ void BlenderSync::sync_camera(BL::RenderSettings b_render, BL::Object b_override blender_camera_sync(cam, &bcam, width, height); } -void BlenderSync::sync_camera_motion(BL::Object b_ob, int motion) +void BlenderSync::sync_camera_motion(BL::Object b_ob, float motion_time) { Camera *cam = scene->camera; @@ -394,12 +394,14 @@ void BlenderSync::sync_camera_motion(BL::Object b_ob, int motion) tfm = blender_camera_matrix(tfm, cam->type); if(tfm != cam->matrix) { - if(motion == -1) + if(motion_time == -1.0f) { cam->motion.pre = tfm; - else + cam->use_motion = true; + } + else if(motion_time == 1.0f) { cam->motion.post = tfm; - - cam->use_motion = true; + cam->use_motion = true; + } } } diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp index 4420a306e31..22de7b64273 100644 --- a/intern/cycles/blender/blender_curves.cpp +++ b/intern/cycles/blender/blender_curves.cpp @@ -612,16 +612,23 @@ void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CData) } } -static void ExportCurveSegmentsMotion(Scene *scene, Mesh *mesh, ParticleCurveData *CData, int motion) +static void ExportCurveSegmentsMotion(Scene *scene, Mesh *mesh, ParticleCurveData *CData, int time_index) { + /* find attribute */ + Attribute *attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); + bool new_attribute = false; + + /* add new attribute if it doesn't exist already */ + if(!attr_mP) { + attr_mP = mesh->curve_attributes.add(ATTR_STD_MOTION_VERTEX_POSITION); + new_attribute = true; + } + /* export motion vectors for curve keys */ - AttributeStandard std = (motion == -1)? ATTR_STD_MOTION_PRE: ATTR_STD_MOTION_POST; - Attribute *attr_motion = mesh->curve_attributes.add(std); - float4 *data_motion = attr_motion->data_float4(); - float4 *current_motion = data_motion; - size_t size = mesh->curve_keys.size(); - size_t i = 0; + size_t numkeys = mesh->curve_keys.size(); + float4 *mP = attr_mP->data_float4() + time_index*numkeys; bool have_motion = false; + int i = 0; for(int sys = 0; sys < CData->psys_firstcurve.size(); sys++) { if(CData->psys_curvenum[sys] == 0) @@ -640,16 +647,14 @@ static void ExportCurveSegmentsMotion(Scene *scene, Mesh *mesh, ParticleCurveDat if(CData->psys_closetip[sys] && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)) radius = 0.0f; - *current_motion = float3_to_float4(ickey_loc); - current_motion->w = radius; + mP[i] = float3_to_float4(ickey_loc); + mP[i].w = radius; /* unlike mesh coordinates, these tend to be slightly different * between frames due to particle transforms into/out of object * space, so we use an epsilon to detect actual changes */ - if(len_squared(*current_motion - mesh->curve_keys[i]) > 1e-5f*1e-5f) + if(len_squared(mP[i] - mesh->curve_keys[i]) > 1e-5f*1e-5f) have_motion = true; - - current_motion++; } i++; @@ -657,8 +662,23 @@ static void ExportCurveSegmentsMotion(Scene *scene, Mesh *mesh, ParticleCurveDat } } - if(i != size || !have_motion) - mesh->curve_attributes.remove(std); + /* in case of new attribute, we verify if there really was any motion */ + if(new_attribute) { + if(i != numkeys || !have_motion) { + /* no motion, remove attributes again */ + mesh->curve_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 */ + for(int step = 0; step < time_index; step++) { + float4 *mP = attr_mP->data_float4() + step*numkeys; + + for(int key = 0; key < numkeys; key++) + mP[key] = mesh->curve_keys[key]; + } + } + } } void ExportCurveTriangleUV(Mesh *mesh, ParticleCurveData *CData, int vert_offset, int resol, float3 *uvdata) @@ -804,7 +824,7 @@ void BlenderSync::sync_curve_settings() curve_system_manager->tag_update(scene); } -void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, int motion) +void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool motion, int time_index) { if(!motion) { /* Clear stored curve data */ @@ -859,7 +879,7 @@ void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, int } else { if(motion) - ExportCurveSegmentsMotion(scene, mesh, &CData, motion); + ExportCurveSegmentsMotion(scene, mesh, &CData, time_index); else ExportCurveSegments(scene, mesh, &CData); } 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 diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index 6ffc8c81ce6..f5945a68fc1 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -217,9 +217,11 @@ void BlenderSync::sync_background_light() /* Object */ -Object *BlenderSync::sync_object(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::DupliObject b_dupli_ob, Transform& tfm, uint layer_flag, int motion, bool hide_tris) +Object *BlenderSync::sync_object(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::DupliObject b_dupli_ob, + Transform& tfm, uint layer_flag, float motion_time, bool hide_tris) { BL::Object b_ob = (b_dupli_ob ? b_dupli_ob.object() : b_parent); + bool motion = motion_time != 0.0f; /* light is handled separately */ if(object_is_light(b_ob)) { @@ -243,18 +245,21 @@ Object *BlenderSync::sync_object(BL::Object b_parent, int persistent_id[OBJECT_P object = object_map.find(key); if(object) { + /* object transformation */ if(tfm != object->tfm) { - if(motion == -1) + if(motion_time == -1.0f) { object->motion.pre = tfm; - else + object->use_motion = true; + } + else if(motion_time == 1.0f) { object->motion.post = tfm; - - object->use_motion = true; + object->use_motion = true; + } } - /* mesh deformation blur not supported yet */ - if(!scene->integrator->motion_blur) - sync_mesh_motion(b_ob, object->mesh, motion); + /* mesh deformation */ + if(object->mesh) + sync_mesh_motion(b_ob, object, motion_time); } return object; @@ -314,6 +319,20 @@ Object *BlenderSync::sync_object(BL::Object b_parent, int persistent_id[OBJECT_P object->motion.post = tfm; object->use_motion = false; + /* motion blur */ + if(scene->need_motion() == Scene::MOTION_BLUR && object->mesh) { + Mesh *mesh = object->mesh; + + if(true) { + if(true) + mesh->motion_steps = 3; + + vector<float> times = object->motion_times(); + foreach(float time, times) + motion_times.insert(time); + } + } + /* random number */ object->random_id = hash_string(object->name.c_str()); @@ -412,10 +431,11 @@ static bool object_render_hide_duplis(BL::Object b_ob) /* Object Loop */ -void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion) +void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, float motion_time) { /* layer data */ uint scene_layer = render_layer.scene_layer; + bool motion = motion_time != 0.0f; if(!motion) { /* prepare for sync */ @@ -424,6 +444,7 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion) object_map.pre_sync(); mesh_synced.clear(); particle_system_map.pre_sync(); + motion_times.clear(); } else { mesh_motion_synced.clear(); @@ -468,7 +489,7 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion) BL::Array<int, OBJECT_PERSISTENT_ID_SIZE> persistent_id = b_dup->persistent_id(); /* sync object and mesh or light data */ - Object *object = sync_object(*b_ob, persistent_id.data, *b_dup, tfm, ob_layer, motion, hide_tris); + Object *object = sync_object(*b_ob, persistent_id.data, *b_dup, tfm, ob_layer, motion_time, hide_tris); /* sync possible particle data, note particle_id * starts counting at 1, first is dummy particle */ @@ -488,7 +509,7 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion) if(!object_render_hide(*b_ob, true, true, hide_tris)) { /* object itself */ Transform tfm = get_transform(b_ob->matrix_world()); - sync_object(*b_ob, NULL, PointerRNA_NULL, tfm, ob_layer, motion, hide_tris); + sync_object(*b_ob, NULL, PointerRNA_NULL, tfm, ob_layer, motion_time, hide_tris); } } @@ -528,31 +549,46 @@ void BlenderSync::sync_motion(BL::SpaceView3D b_v3d, BL::Object b_override, void b_cam = b_override; Camera prevcam = *(scene->camera); - - /* go back and forth one frame */ - int frame = b_scene.frame_current(); - for(int motion = -1; motion <= 1; motion += 2) { - /* we need to set the python thread state again because this - * function assumes it is being executed from python and will - * try to save the thread state */ + int frame_center = b_scene.frame_current(); + + /* always sample these times for camera motion */ + motion_times.insert(-1.0f); + motion_times.insert(1.0f); + + /* note iteration over motion_times set happens in sorted order */ + foreach(float relative_time, motion_times) { + /* sync camera, only supports two times at the moment */ + if(relative_time == -1.0f || relative_time == 1.0f) + sync_camera_motion(b_cam, relative_time); + + /* fixed shutter time to get previous and next frame for motion pass */ + float shuttertime; + + if(scene->need_motion() == Scene::MOTION_PASS) + shuttertime = 2.0f; + else + shuttertime = scene->camera->shuttertime; + + /* compute frame and subframe time */ + float time = frame_center + relative_time * shuttertime * 0.5f; + int frame = (int)floorf(time); + float subframe = time - frame; + + /* change frame */ python_thread_state_restore(python_thread_state); - b_scene.frame_set(frame + motion, 0.0f); + b_scene.frame_set(frame, subframe); python_thread_state_save(python_thread_state); - /* camera object */ - if(b_cam) - sync_camera_motion(b_cam, motion); - - /* mesh objects */ - sync_objects(b_v3d, motion); + /* sync object */ + sync_objects(b_v3d, relative_time); } /* we need to set the python thread state again because this * function assumes it is being executed from python and will * try to save the thread state */ python_thread_state_restore(python_thread_state); - b_scene.frame_set(frame, 0.0f); + b_scene.frame_set(frame_center, 0.0f); python_thread_state_save(python_thread_state); /* tag camera for motion update */ diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h index 205761ad302..9c4175ef690 100644 --- a/intern/cycles/blender/blender_sync.h +++ b/intern/cycles/blender/blender_sync.h @@ -71,7 +71,7 @@ private: /* sync */ void sync_lamps(bool update_all); void sync_materials(bool update_all); - void sync_objects(BL::SpaceView3D b_v3d, int motion = 0); + void sync_objects(BL::SpaceView3D b_v3d, float motion_time = 0.0f); void sync_motion(BL::SpaceView3D b_v3d, BL::Object b_override, void **python_thread_state); void sync_film(); void sync_view(); @@ -81,12 +81,13 @@ private: void sync_nodes(Shader *shader, BL::ShaderNodeTree b_ntree); Mesh *sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tris); - void sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, int motion); - Object *sync_object(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::DupliObject b_dupli_object, Transform& tfm, uint layer_flag, int motion, bool hide_tris); + void sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool motion, int time_index = 0); + Object *sync_object(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::DupliObject b_dupli_ob, + Transform& tfm, uint layer_flag, float motion_time, bool hide_tris); void sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::Object b_ob, Transform& tfm); void sync_background_light(); - void sync_mesh_motion(BL::Object b_ob, Mesh *mesh, int motion); - void sync_camera_motion(BL::Object b_ob, int motion); + void sync_mesh_motion(BL::Object b_ob, Object *object, float motion_time); + void sync_camera_motion(BL::Object b_ob, float motion_time); /* particles */ bool sync_dupli_particle(BL::Object b_ob, BL::DupliObject b_dup, Object *object); @@ -109,6 +110,7 @@ private: id_map<ParticleSystemKey, ParticleSystem> particle_system_map; set<Mesh*> mesh_synced; set<Mesh*> mesh_motion_synced; + std::set<float> motion_times; void *world_map; bool world_recalc; |