diff options
author | Sergey Sharybin <sergey.vfx@gmail.com> | 2018-11-23 16:41:21 +0300 |
---|---|---|
committer | Sergey Sharybin <sergey.vfx@gmail.com> | 2018-11-23 16:41:21 +0300 |
commit | d891c8f1f802f91629ca63c149f126fd19f9a5d9 (patch) | |
tree | c44f6886e1bf9b494409499699c69a39a1b3d441 /intern/cycles/blender | |
parent | 859d5e56994a8ec274e701a3b6ffae57d848b5c8 (diff) | |
parent | 874f12480f465374e53ee1870cf108828172fe17 (diff) |
Merge branch 'master' into blender2.8
Diffstat (limited to 'intern/cycles/blender')
-rw-r--r-- | intern/cycles/blender/blender_curves.cpp | 89 |
1 files changed, 67 insertions, 22 deletions
diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp index 5e4522af6e1..f32e1db505c 100644 --- a/intern/cycles/blender/blender_curves.cpp +++ b/intern/cycles/blender/blender_curves.cpp @@ -619,6 +619,41 @@ static void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CDa } } +static float4 CurveSegmentMotionCV(ParticleCurveData *CData, int sys, int curve, int curvekey) +{ + float3 ickey_loc = CData->curvekey_co[curvekey]; + float time = CData->curvekey_time[curvekey]/CData->curve_length[curve]; + float radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time); + + if(CData->psys_closetip[sys] && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)) + radius = 0.0f; + + /* curve motion keys store both position and radius in float4 */ + float4 mP = float3_to_float4(ickey_loc); + mP.w = radius; + return mP; +} + +static float4 LerpCurveSegmentMotionCV(ParticleCurveData *CData, int sys, int curve, float step) +{ + step = clamp(step, 0.0f, 1.0f); + float curve_key_f = step * (CData->curve_keynum[curve] - 1); + int curvekey = (int)floorf(curve_key_f); + float remainder = curve_key_f - curvekey; + if(remainder == 0.0f) { + return CurveSegmentMotionCV(CData, sys, curve, curvekey); + } + int curvekey2 = curvekey + 1; + if(curvekey2 >= (CData->curve_keynum[curve] - 1)) { + curvekey2 = (CData->curve_keynum[curve] - 1); + curvekey = curvekey2 - 1; + } + + float4 mP = CurveSegmentMotionCV(CData, sys, curve, curvekey); + float4 mP2 = CurveSegmentMotionCV(CData, sys, curve, curvekey2); + return lerp(mP, mP2, remainder); +} + static void ExportCurveSegmentsMotion(Mesh *mesh, ParticleCurveData *CData, int motion_step) { VLOG(1) << "Exporting curve motion segments for mesh " << mesh->name @@ -640,6 +675,7 @@ static void ExportCurveSegmentsMotion(Mesh *mesh, ParticleCurveData *CData, int float4 *mP = attr_mP->data_float4() + motion_step*numkeys; bool have_motion = false; int i = 0; + int num_curves = 0; for(int sys = 0; sys < CData->psys_firstcurve.size(); sys++) { if(CData->psys_curvenum[sys] == 0) @@ -649,30 +685,39 @@ static void ExportCurveSegmentsMotion(Mesh *mesh, ParticleCurveData *CData, int if(CData->curve_keynum[curve] <= 1 || CData->curve_length[curve] == 0.0f) continue; - for(int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve]; curvekey++) { - if(i < mesh->curve_keys.size()) { - float3 ickey_loc = CData->curvekey_co[curvekey]; - float time = CData->curvekey_time[curvekey]/CData->curve_length[curve]; - float radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time); - - if(CData->psys_closetip[sys] && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)) - radius = 0.0f; - - /* curve motion keys store both position and radius in float4 */ - 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 */ - float4 curve_key = float3_to_float4(mesh->curve_keys[i]); - curve_key.w = mesh->curve_radius[i]; - if(len_squared(mP[i] - curve_key) > 1e-5f*1e-5f) - have_motion = true; + /* Curve lengths may not match! Curves can be clipped. */ + int curve_key_end = (num_curves+1 < (int)mesh->curve_first_key.size() ? mesh->curve_first_key[num_curves+1] : (int)mesh->curve_keys.size()); + int center_curve_len = curve_key_end - mesh->curve_first_key[num_curves]; + int diff = CData->curve_keynum[curve] - center_curve_len; + + if(diff == 0) { + for(int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve]; curvekey++) { + if(i < mesh->curve_keys.size()) { + mP[i] = CurveSegmentMotionCV(CData, sys, curve, curvekey); + if(!have_motion) { + /* 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 */ + float4 curve_key = float3_to_float4(mesh->curve_keys[i]); + curve_key.w = mesh->curve_radius[i]; + if(len_squared(mP[i] - curve_key) > 1e-5f*1e-5f) + have_motion = true; + } + } + i++; } - - i++; } + else { + /* Number of keys has changed. Genereate an interpolated version to preserve motion blur. */ + float step = 0; + float step_size = 1.0f / (center_curve_len-1); + for(; i < curve_key_end; i++) { + mP[i] = LerpCurveSegmentMotionCV(CData, sys, curve, step); + step = i * step_size; + } + have_motion = true; + } + num_curves++; } } |