Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/intern
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@gmail.com>2014-03-29 16:03:46 +0400
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2014-03-29 16:03:46 +0400
commit99f59930885ed69890967f8864a3aa0626249d86 (patch)
treeb6f8dcc40c294077d585639e701f7fdf9b6c0dcb /intern
parent934767cf7f51ae82224138de2ffcafe7bae2b8fa (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')
-rw-r--r--intern/cycles/blender/blender_camera.cpp12
-rw-r--r--intern/cycles/blender/blender_curves.cpp52
-rw-r--r--intern/cycles/blender/blender_mesh.cpp110
-rw-r--r--intern/cycles/blender/blender_object.cpp88
-rw-r--r--intern/cycles/blender/blender_sync.h12
-rw-r--r--intern/cycles/kernel/geom/geom_object.h15
-rw-r--r--intern/cycles/kernel/kernel_camera.h2
-rw-r--r--intern/cycles/kernel/kernel_primitive.h22
-rw-r--r--intern/cycles/kernel/kernel_types.h3
-rw-r--r--intern/cycles/render/attribute.cpp16
-rw-r--r--intern/cycles/render/mesh.cpp37
-rw-r--r--intern/cycles/render/object.cpp61
-rw-r--r--intern/cycles/render/object.h6
-rw-r--r--intern/cycles/render/scene.cpp4
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;
}