diff options
-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 | ||||
-rw-r--r-- | intern/cycles/kernel/geom/geom_object.h | 15 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_camera.h | 2 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_primitive.h | 22 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_types.h | 3 | ||||
-rw-r--r-- | intern/cycles/render/attribute.cpp | 16 | ||||
-rw-r--r-- | intern/cycles/render/mesh.cpp | 37 | ||||
-rw-r--r-- | intern/cycles/render/object.cpp | 61 | ||||
-rw-r--r-- | intern/cycles/render/object.h | 6 | ||||
-rw-r--r-- | intern/cycles/render/scene.cpp | 4 |
14 files changed, 325 insertions, 115 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; diff --git a/intern/cycles/kernel/geom/geom_object.h b/intern/cycles/kernel/geom/geom_object.h index 3646615b9f6..b1106c25fd7 100644 --- a/intern/cycles/kernel/geom/geom_object.h +++ b/intern/cycles/kernel/geom/geom_object.h @@ -230,6 +230,21 @@ ccl_device_inline float3 object_dupli_uv(KernelGlobals *kg, int object) return make_float3(f.x, f.y, 0.0f); } +ccl_device_inline void object_motion_info(KernelGlobals *kg, int object, int *numsteps, int *numverts, int *numkeys) +{ + int offset = object*OBJECT_SIZE + OBJECT_DUPLI; + + if(numkeys) { + float4 f = kernel_tex_fetch(__objects, offset); + *numkeys = __float_as_int(f.w); + } + + float4 f = kernel_tex_fetch(__objects, offset + 1); + if(numsteps) + *numsteps = __float_as_int(f.z); + if(numverts) + *numverts = __float_as_int(f.w); +} ccl_device int shader_pass_id(KernelGlobals *kg, ShaderData *sd) { diff --git a/intern/cycles/kernel/kernel_camera.h b/intern/cycles/kernel/kernel_camera.h index 887b1afddd4..fe995bbb594 100644 --- a/intern/cycles/kernel/kernel_camera.h +++ b/intern/cycles/kernel/kernel_camera.h @@ -229,7 +229,7 @@ ccl_device void camera_sample(KernelGlobals *kg, int x, int y, float filter_u, f if(kernel_data.cam.shuttertime == -1.0f) ray->time = TIME_INVALID; else - ray->time = 0.5f + 0.5f*(time - 0.5f)*kernel_data.cam.shuttertime; + ray->time = time; #endif /* sample */ diff --git a/intern/cycles/kernel/kernel_primitive.h b/intern/cycles/kernel/kernel_primitive.h index f9efdd2cf56..af5faf37c3f 100644 --- a/intern/cycles/kernel/kernel_primitive.h +++ b/intern/cycles/kernel/kernel_primitive.h @@ -161,14 +161,20 @@ ccl_device float4 primitive_motion_vector(KernelGlobals *kg, ShaderData *sd) float3 motion_pre = sd->P, motion_post = sd->P; /* deformation motion */ - AttributeElement elem_pre, elem_post; - int offset_pre = find_attribute(kg, sd, ATTR_STD_MOTION_PRE, &elem_pre); - int offset_post = find_attribute(kg, sd, ATTR_STD_MOTION_POST, &elem_post); - - if(offset_pre != ATTR_STD_NOT_FOUND) - motion_pre = primitive_attribute_float3(kg, sd, elem_pre, offset_pre, NULL, NULL); - if(offset_post != ATTR_STD_NOT_FOUND) - motion_post = primitive_attribute_float3(kg, sd, elem_post, offset_post, NULL, NULL); + AttributeElement elem; + int offset = find_attribute(kg, sd, ATTR_STD_MOTION_VERTEX_POSITION, &elem); + + if(offset != ATTR_STD_NOT_FOUND) { + /* get motion info */ + int numverts, numkeys; + object_motion_info(kg, sd->object, NULL, &numverts, &numkeys); + + /* lookup attributes */ + int offset_next = (sd->type & PRIMITIVE_ALL_TRIANGLE)? offset + numverts: offset + numkeys; + + motion_pre = primitive_attribute_float3(kg, sd, elem, offset, NULL, NULL); + motion_post = primitive_attribute_float3(kg, sd, elem, offset_next, NULL, NULL); + } /* object motion. note that depending on the mesh having motion vectors, this * transformation was set match the world/object space of motion_pre/post */ diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index b260a3d11ac..f708f019912 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -470,8 +470,7 @@ typedef enum AttributeStandard { ATTR_STD_GENERATED_TRANSFORM, ATTR_STD_POSITION_UNDEFORMED, ATTR_STD_POSITION_UNDISPLACED, - ATTR_STD_MOTION_PRE, - ATTR_STD_MOTION_POST, + ATTR_STD_MOTION_VERTEX_POSITION, ATTR_STD_PARTICLE, ATTR_STD_CURVE_INTERCEPT, ATTR_STD_PTEX_FACE_ID, diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp index bef3295d927..e730cab0c60 100644 --- a/intern/cycles/render/attribute.cpp +++ b/intern/cycles/render/attribute.cpp @@ -163,10 +163,8 @@ const char *Attribute::standard_name(AttributeStandard std) return "undeformed"; else if(std == ATTR_STD_POSITION_UNDISPLACED) return "undisplaced"; - else if(std == ATTR_STD_MOTION_PRE) - return "motion_pre"; - else if(std == ATTR_STD_MOTION_POST) - return "motion_post"; + else if(std == ATTR_STD_MOTION_VERTEX_POSITION) + return "motion_P"; else if(std == ATTR_STD_PARTICLE) return "particle"; else if(std == ATTR_STD_CURVE_INTERCEPT) @@ -272,10 +270,11 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name) case ATTR_STD_GENERATED: case ATTR_STD_POSITION_UNDEFORMED: case ATTR_STD_POSITION_UNDISPLACED: - case ATTR_STD_MOTION_PRE: - case ATTR_STD_MOTION_POST: attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX); break; + case ATTR_STD_MOTION_VERTEX_POSITION: + attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_VERTEX_MOTION); + break; case ATTR_STD_PTEX_FACE_ID: attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_FACE); break; @@ -296,9 +295,8 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name) case ATTR_STD_GENERATED: attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE); break; - case ATTR_STD_MOTION_PRE: - case ATTR_STD_MOTION_POST: - attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE_KEY); + case ATTR_STD_MOTION_VERTEX_POSITION: + attr = add(name, TypeDesc::TypePoint, ATTR_ELEMENT_CURVE_KEY_MOTION); break; case ATTR_STD_CURVE_INTERCEPT: attr = add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_CURVE_KEY); diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index c6ddb00e76b..0d09328119c 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -187,6 +187,24 @@ void Mesh::compute_bounds() for(size_t i = 0; i < curve_keys_size; i++) bnds.grow(float4_to_float3(curve_keys[i]), curve_keys[i].w); + + Attribute *attr = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); + if (attr) { + size_t steps_size = verts.size() * (motion_steps - 1); + float3 *vert_steps = attr->data_float3(); + + for (size_t i = 0; i < steps_size; i++) + bnds.grow(vert_steps[i]); + } + + Attribute *curve_attr = curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); + if (curve_attr) { + size_t steps_size = curve_keys.size() * (motion_steps - 1); + float3 *key_steps = curve_attr->data_float3(); + + for (size_t i = 0; i < steps_size; i++) + bnds.grow(key_steps[i]); + } if(!bnds.valid()) { bnds = BoundBox::empty; @@ -197,6 +215,22 @@ void Mesh::compute_bounds() for(size_t i = 0; i < curve_keys_size; i++) bnds.grow_safe(float4_to_float3(curve_keys[i]), curve_keys[i].w); + + if (attr) { + size_t steps_size = verts.size() * (motion_steps - 1); + float3 *vert_steps = attr->data_float3(); + + for (size_t i = 0; i < steps_size; i++) + bnds.grow_safe(vert_steps[i]); + } + + if (curve_attr) { + size_t steps_size = curve_keys.size() * (motion_steps - 1); + float3 *key_steps = curve_attr->data_float3(); + + for (size_t i = 0; i < steps_size; i++) + bnds.grow_safe(key_steps[i]); + } } } @@ -992,7 +1026,6 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen foreach(Shader *shader, scene->shaders) shader->need_update_attributes = false; - float shuttertime = scene->camera->shuttertime; #ifdef __OBJECT_MOTION__ Scene::MotionType need_motion = scene->need_motion(device->info.advanced_shading); bool motion_blur = need_motion == Scene::MOTION_BLUR; @@ -1001,7 +1034,7 @@ void MeshManager::device_update(Device *device, DeviceScene *dscene, Scene *scen #endif foreach(Object *object, scene->objects) - object->compute_bounds(motion_blur, shuttertime); + object->compute_bounds(motion_blur); if(progress.get_cancel()) return; diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 362b4762b74..e99ca323929 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -55,7 +55,7 @@ Object::~Object() { } -void Object::compute_bounds(bool motion_blur, float shuttertime) +void Object::compute_bounds(bool motion_blur) { BoundBox mbounds = mesh->bounds; @@ -68,10 +68,7 @@ void Object::compute_bounds(bool motion_blur, float shuttertime) /* todo: this is really terrible. according to pbrt there is a better * way to find this iteratively, but did not find implementation yet * or try to implement myself */ - float start_t = 0.5f - shuttertime*0.25f; - float end_t = 0.5f + shuttertime*0.25f; - - for(float t = start_t; t < end_t; t += (1.0f/128.0f)*shuttertime) { + for(float t = 0.0f; t < 1.0f; t += (1.0f/128.0f)) { Transform ttfm; transform_motion_interpolate(&ttfm, &decomp, t); @@ -96,6 +93,15 @@ void Object::apply_transform() for(size_t i = 0; i < mesh->verts.size(); i++) mesh->verts[i] = transform_point(&tfm, mesh->verts[i]); + Attribute *attr = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); + if (attr) { + size_t steps_size = mesh->verts.size() * (mesh->motion_steps - 1); + float3 *vert_steps = attr->data_float3(); + + for (size_t i = 0; i < steps_size; i++) + vert_steps[i] = transform_point(&tfm, vert_steps[i]); + } + /* apply to curve keys */ for(size_t i = 0; i < mesh->curve_keys.size(); i++) { float3 co = transform_point(&tfm, float4_to_float3(mesh->curve_keys[i])); @@ -106,6 +112,15 @@ void Object::apply_transform() mesh->curve_keys[i].w *= radius; } + Attribute *curve_attr = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); + if (curve_attr) { + size_t steps_size = mesh->curve_keys.size() * (mesh->motion_steps - 1); + float3 *vert_steps = curve_attr->data_float3(); + + for (size_t i = 0; i < steps_size; i++) + vert_steps[i] = transform_point(&tfm, vert_steps[i]); + } + /* store matrix to transform later. when accessing these as attributes we * do not want the transform to be applied for consistency between static * and dynamic BVH, so we do it on packing. */ @@ -118,7 +133,7 @@ void Object::apply_transform() if(bounds.valid()) { mesh->compute_bounds(); - compute_bounds(false, 0.0f); + compute_bounds(false); } /* tfm is not reset to identity, all code that uses it needs to check the @@ -144,6 +159,25 @@ void Object::tag_update(Scene *scene) scene->object_manager->need_update = true; } +vector<float> Object::motion_times() +{ + /* compute times at which we sample motion for this object */ + vector<float> times; + int motion_steps = mesh->motion_steps; + + if(!mesh || motion_steps == 1) + return times; + + for(int step = 0; step < motion_steps; step++) { + if(step != motion_steps / 2) { + float time = 2.0f * step / (motion_steps - 1) - 1.0f; + times.push_back(time); + } + } + + return times; +} + /* Object Manager */ ObjectManager::ObjectManager() @@ -239,10 +273,10 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene Transform mtfm_pre = ob->motion.pre; Transform mtfm_post = ob->motion.post; - if(!(mesh->attributes.find(ATTR_STD_MOTION_PRE) || mesh->curve_attributes.find(ATTR_STD_MOTION_PRE))) + if(!mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION)) { mtfm_pre = mtfm_pre * itfm; - if(!(mesh->attributes.find(ATTR_STD_MOTION_POST) || mesh->curve_attributes.find(ATTR_STD_MOTION_POST))) mtfm_post = mtfm_post * itfm; + } memcpy(&objects_vector[i*OBJECT_VECTOR_SIZE+0], &mtfm_pre, sizeof(float4)*3); memcpy(&objects_vector[i*OBJECT_VECTOR_SIZE+3], &mtfm_post, sizeof(float4)*3); @@ -261,9 +295,14 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene } #endif - /* dupli object coords */ - objects[offset+9] = make_float4(ob->dupli_generated[0], ob->dupli_generated[1], ob->dupli_generated[2], 0.0f); - objects[offset+10] = make_float4(ob->dupli_uv[0], ob->dupli_uv[1], 0.0f, 0.0f); + /* dupli object coords and motion info */ + int totalsteps = mesh->motion_steps; + int numsteps = (totalsteps - 1)/2; + int numverts = mesh->verts.size(); + int numkeys = mesh->curve_keys.size(); + + objects[offset+9] = make_float4(ob->dupli_generated[0], ob->dupli_generated[1], ob->dupli_generated[2], __int_as_float(numkeys)); + objects[offset+10] = make_float4(ob->dupli_uv[0], ob->dupli_uv[1], __int_as_float(numsteps), __int_as_float(numverts)); /* object flag */ if(ob->use_holdout) diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h index 31400f3c7f1..f3a019f4d73 100644 --- a/intern/cycles/render/object.h +++ b/intern/cycles/render/object.h @@ -53,14 +53,16 @@ public: ParticleSystem *particle_system; int particle_index; - + Object(); ~Object(); void tag_update(Scene *scene); - void compute_bounds(bool motion_blur, float shuttertime); + void compute_bounds(bool motion_blur); void apply_transform(); + + vector<float> motion_times(); }; /* Object Manager */ diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp index daf22d90978..f7d2f2d0a8e 100644 --- a/intern/cycles/render/scene.cpp +++ b/intern/cycles/render/scene.cpp @@ -226,8 +226,8 @@ bool Scene::need_global_attribute(AttributeStandard std) { if(std == ATTR_STD_UV) return Pass::contains(film->passes, PASS_UV); - if(std == ATTR_STD_MOTION_PRE || std == ATTR_STD_MOTION_POST) - return need_motion() == MOTION_PASS; + if(std == ATTR_STD_MOTION_VERTEX_POSITION) + return need_motion() != MOTION_NONE; return false; } |