Fix T49004 and motion blur of cloth, softbody, etc past the end frame.
Point cache read code contains checks designed to prevent it reading stale data when the relevant simulation code should instead compute the next frame from the previous one. However in some situations like motion blur subframes the simulation can't possibly do it and just exits. This causes completely incorrect motion blur at or after the last cached frame. To fix, add a parameter that tells the cache code whether it should apply the checks and exit, or read what it can even if stale (true means exactly same as old behavior). Doing this in cache rather than clamping the frame number better in the caller lets it handle the case of incomplete cache that stops before the official last frame. Reviewed By: mont29, lukastoenne Maniphest Tasks: T49004 Differential Revision: https://developer.blender.org/D2144
This commit is contained in:
parent
fdc43f993d
commit
1fe9d671cf
Notes:
blender-bot
2023-02-14 07:43:10 +01:00
Referenced by issue #49158, Untranslatable elements in UI Referenced by issue #49161, Blender 2.78 Beta, Choppy color picker and normal node sphere Referenced by issue #49150, New category column in operator search-popup is untranslatable Referenced by issue #49136, Blender closing when f12 for render is pressed Referenced by issue #49111, Automatically add suffix in export alembic(.abc) and collada(.dae) Referenced by issue #49112, The Alembic don't support Chinese path Referenced by issue #49114, Exporting curves to Alembic crashes other software when reading Referenced by issue #49075, Assignment of a keyframed material using the frame_change_pre handler doesn't update the keyframe using the new dependency graph Referenced by issue #49004, Dynamic Paint doesn't update mesh before 'start frame'
|
@ -304,7 +304,7 @@ void BKE_ptcache_mem_pointers_incr(struct PTCacheMem *pm);
|
|||
int BKE_ptcache_mem_pointers_seek(int point_index, struct PTCacheMem *pm);
|
||||
|
||||
/* Main cache reading call. */
|
||||
int BKE_ptcache_read(PTCacheID *pid, float cfra);
|
||||
int BKE_ptcache_read(PTCacheID *pid, float cfra, bool no_extrapolate_old);
|
||||
|
||||
/* Main cache writing call. */
|
||||
int BKE_ptcache_write(PTCacheID *pid, unsigned int cfra);
|
||||
|
|
|
@ -449,9 +449,12 @@ void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, Derived
|
|||
}
|
||||
|
||||
/* try to read from cache */
|
||||
cache_result = BKE_ptcache_read(&pid, (float)framenr+scene->r.subframe);
|
||||
bool can_simulate = (framenr == clmd->clothObject->last_frame+1) && !(cache->flag & PTCACHE_BAKED);
|
||||
|
||||
if (cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED) {
|
||||
cache_result = BKE_ptcache_read(&pid, (float)framenr+scene->r.subframe, can_simulate);
|
||||
|
||||
if (cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED ||
|
||||
(!can_simulate && cache_result == PTCACHE_READ_OLD)) {
|
||||
BKE_cloth_solver_set_positions(clmd);
|
||||
cloth_to_object (ob, clmd, vertexCos);
|
||||
|
||||
|
@ -473,7 +476,7 @@ void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, Derived
|
|||
return;
|
||||
}
|
||||
|
||||
if (framenr!=clmd->clothObject->last_frame+1)
|
||||
if (!can_simulate)
|
||||
return;
|
||||
|
||||
/* if on second frame, write cache for first frame */
|
||||
|
|
|
@ -2015,11 +2015,13 @@ static void dynamicPaint_frameUpdate(DynamicPaintModifierData *pmd, Scene *scene
|
|||
}
|
||||
|
||||
/* try to read from cache */
|
||||
if (BKE_ptcache_read(&pid, (float)scene->r.cfra)) {
|
||||
bool can_simulate = ((int)scene->r.cfra == current_frame) && !(cache->flag & PTCACHE_BAKED);
|
||||
|
||||
if (BKE_ptcache_read(&pid, (float)scene->r.cfra, can_simulate)) {
|
||||
BKE_ptcache_validate(cache, (int)scene->r.cfra);
|
||||
}
|
||||
/* if read failed and we're on surface range do recalculate */
|
||||
else if ((int)scene->r.cfra == current_frame && !(cache->flag & PTCACHE_BAKED)) {
|
||||
else if (can_simulate) {
|
||||
/* calculate surface frame */
|
||||
canvas->flags |= MOD_DPAINT_BAKING;
|
||||
dynamicPaint_calculateFrame(surface, scene, ob, current_frame);
|
||||
|
|
|
@ -3925,7 +3925,7 @@ static void system_step(ParticleSimulationData *sim, float cfra, const bool use_
|
|||
|
||||
/* 2. try to read from the cache */
|
||||
if (pid) {
|
||||
int cache_result = BKE_ptcache_read(pid, cache_cfra);
|
||||
int cache_result = BKE_ptcache_read(pid, cache_cfra, true);
|
||||
|
||||
if (ELEM(cache_result, PTCACHE_READ_EXACT, PTCACHE_READ_INTERPOLATED)) {
|
||||
cached_step(sim, cfra);
|
||||
|
|
|
@ -2632,7 +2632,7 @@ static int ptcache_interpolate(PTCacheID *pid, float cfra, int cfra1, int cfra2)
|
|||
}
|
||||
/* reads cache from disk or memory */
|
||||
/* possible to get old or interpolated result */
|
||||
int BKE_ptcache_read(PTCacheID *pid, float cfra)
|
||||
int BKE_ptcache_read(PTCacheID *pid, float cfra, bool no_extrapolate_old)
|
||||
{
|
||||
int cfrai = (int)floor(cfra), cfra1=0, cfra2=0;
|
||||
int ret = 0;
|
||||
|
@ -2658,10 +2658,17 @@ int BKE_ptcache_read(PTCacheID *pid, float cfra)
|
|||
return 0;
|
||||
|
||||
/* don't read old cache if already simulated past cached frame */
|
||||
if (cfra1 == 0 && cfra2 && cfra2 <= pid->cache->simframe)
|
||||
return 0;
|
||||
if (cfra1 && cfra1 == cfra2)
|
||||
return 0;
|
||||
if (no_extrapolate_old) {
|
||||
if (cfra1 == 0 && cfra2 && cfra2 <= pid->cache->simframe)
|
||||
return 0;
|
||||
if (cfra1 && cfra1 == cfra2)
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
/* avoid calling interpolate between the same frame values */
|
||||
if (cfra1 && cfra1 == cfra2)
|
||||
cfra1 = 0;
|
||||
}
|
||||
|
||||
if (cfra1) {
|
||||
if (pid->file_type == PTCACHE_FILE_OPENVDB && pid->read_openvdb_stream) {
|
||||
|
|
|
@ -1560,14 +1560,16 @@ void BKE_rigidbody_do_simulation(Scene *scene, float ctime)
|
|||
|
||||
/* try to read from cache */
|
||||
// RB_TODO deal with interpolated, old and baked results
|
||||
if (BKE_ptcache_read(&pid, ctime)) {
|
||||
bool can_simulate = (ctime == rbw->ltime + 1) && !(cache->flag & PTCACHE_BAKED);
|
||||
|
||||
if (BKE_ptcache_read(&pid, ctime, can_simulate)) {
|
||||
BKE_ptcache_validate(cache, (int)ctime);
|
||||
rbw->ltime = ctime;
|
||||
return;
|
||||
}
|
||||
|
||||
/* advance simulation, we can only step one frame forward */
|
||||
if (ctime == rbw->ltime + 1 && !(cache->flag & PTCACHE_BAKED)) {
|
||||
if (can_simulate) {
|
||||
/* write cache for first frame when on second frame */
|
||||
if (rbw->ltime == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact == 0)) {
|
||||
BKE_ptcache_write(&pid, startframe);
|
||||
|
|
|
@ -2737,19 +2737,18 @@ static void smokeModifier_process(SmokeModifierData *smd, Scene *scene, Object *
|
|||
return;
|
||||
}
|
||||
|
||||
/* only calculate something when we advanced a single frame */
|
||||
/* don't simulate if viewing start frame, but scene frame is not real start frame */
|
||||
bool can_simulate = (framenr == (int)smd->time + 1) && (framenr == scene->r.cfra);
|
||||
|
||||
/* try to read from cache */
|
||||
if (BKE_ptcache_read(&pid, (float)framenr) == PTCACHE_READ_EXACT) {
|
||||
if (BKE_ptcache_read(&pid, (float)framenr, can_simulate) == PTCACHE_READ_EXACT) {
|
||||
BKE_ptcache_validate(cache, framenr);
|
||||
smd->time = framenr;
|
||||
return;
|
||||
}
|
||||
|
||||
/* only calculate something when we advanced a single frame */
|
||||
if (framenr != (int)smd->time + 1)
|
||||
return;
|
||||
|
||||
/* don't simulate if viewing start frame, but scene frame is not real start frame */
|
||||
if (framenr != scene->r.cfra)
|
||||
if (!can_simulate)
|
||||
return;
|
||||
|
||||
#ifdef DEBUG_TIME
|
||||
|
|
|
@ -3719,9 +3719,12 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i
|
|||
}
|
||||
|
||||
/* try to read from cache */
|
||||
cache_result = BKE_ptcache_read(&pid, (float)framenr+scene->r.subframe);
|
||||
bool can_simulate = (framenr == sb->last_frame+1) && !(cache->flag & PTCACHE_BAKED);
|
||||
|
||||
if (cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED) {
|
||||
cache_result = BKE_ptcache_read(&pid, (float)framenr+scene->r.subframe, can_simulate);
|
||||
|
||||
if (cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED ||
|
||||
(!can_simulate && cache_result == PTCACHE_READ_OLD)) {
|
||||
softbody_to_object(ob, vertexCos, numVerts, sb->local);
|
||||
|
||||
BKE_ptcache_validate(cache, framenr);
|
||||
|
@ -3742,7 +3745,7 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i
|
|||
return;
|
||||
}
|
||||
|
||||
if (framenr!=sb->last_frame+1)
|
||||
if (!can_simulate)
|
||||
return;
|
||||
|
||||
/* if on second frame, write cache for first frame */
|
||||
|
|
Loading…
Reference in New Issue