diff options
author | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2014-03-29 16:03:46 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2014-03-29 16:03:46 +0400 |
commit | 99f59930885ed69890967f8864a3aa0626249d86 (patch) | |
tree | b6f8dcc40c294077d585639e701f7fdf9b6c0dcb /intern/cycles/render | |
parent | 934767cf7f51ae82224138de2ffcafe7bae2b8fa (diff) |
Cycles code refactor: improve vertex motion attribute storage and export.
This now supports multiple steps and subframe sampling of motion.
There is one difference for object and camera transform motion blur. It still
only supports two steps there, but the transforms are now sampled at subframe
times instead of the previous and next frame and then interpolated/extrapolated.
This will give different render results in some cases but it's more accurate.
Part of the code is from the summer of code project by Gavin Howard, but it has
been significantly rewritten and extended.
Diffstat (limited to 'intern/cycles/render')
-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 |
5 files changed, 98 insertions, 26 deletions
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; } |