[Bf-blender-cvs] [1fe9d67] master: Fix T49004 and motion blur of cloth, softbody, etc past the end frame.

Alexander Gavrilov noreply at git.blender.org
Thu Aug 11 12:37:25 CEST 2016


Commit: 1fe9d671cf19f339917a78cb3ab0b6148ab1ceff
Author: Alexander Gavrilov
Date:   Thu Aug 11 13:36:29 2016 +0300
Branches: master
https://developer.blender.org/rB1fe9d671cf19f339917a78cb3ab0b6148ab1ceff

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

===================================================================

M	source/blender/blenkernel/BKE_pointcache.h
M	source/blender/blenkernel/intern/cloth.c
M	source/blender/blenkernel/intern/dynamicpaint.c
M	source/blender/blenkernel/intern/particle_system.c
M	source/blender/blenkernel/intern/pointcache.c
M	source/blender/blenkernel/intern/rigidbody.c
M	source/blender/blenkernel/intern/smoke.c
M	source/blender/blenkernel/intern/softbody.c

===================================================================

diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h
index 8238ea6..02f6c43 100644
--- a/source/blender/blenkernel/BKE_pointcache.h
+++ b/source/blender/blenkernel/BKE_pointcache.h
@@ -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);
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index 681b931..445be52 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -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 */
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index d35de6f..2442572 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -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);
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 0728fef..b4e951c 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -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);
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index 69a98c0..d08814e 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -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) {
diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c
index 0f1f9b4..c3ae573 100644
--- a/source/blender/blenkernel/intern/rigidbody.c
+++ b/source/blender/blenkernel/intern/rigidbody.c
@@ -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);
diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c
index 43569f9..3fc7262 100644
--- a/source/blender/blenkernel/intern/smoke.c
+++ b/source/blender/blenkernel/intern/smoke.c
@@ -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
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index 901926d..03cf330 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -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 */




More information about the Bf-blender-cvs mailing list