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
diff options
context:
space:
mode:
-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;
}