Ocean Modifier: refactored the delayed-refresh approach

The approach of setting 'refresh' flags on the modifier, and performing
the associated actions when the modifier is being evaluated, is a bad
one. Instead, we use the separation of the original and the evaluated
copy to 'refresh' certain things (because they simply aren't set at all
on the original). Other actions are now done directly with BKE_ocean_xxx
functions on the original data, intead of during evaluation.
This commit is contained in:
Sybren A. Stüvel
2018-07-05 16:23:35 +02:00
parent b9bef10d19
commit de55ae56ae
7 changed files with 38 additions and 59 deletions

View File

@@ -31,6 +31,8 @@
extern "C" {
#endif
struct OceanModifierData;
typedef struct OceanResult {
float disp[3];
float normal[3];
@@ -99,6 +101,8 @@ void BKE_ocean_cache_eval_uv(struct OceanCache *och, struct OceanResult *ocr, in
void BKE_ocean_cache_eval_ij(struct OceanCache *och, struct OceanResult *ocr, int f, int i, int j);
void BKE_ocean_free_cache(struct OceanCache *och);
void BKE_ocean_free_modifier_cache(struct OceanModifierData *omd);
#ifdef __cplusplus
}
#endif

View File

@@ -36,6 +36,7 @@
#include "MEM_guardedalloc.h"
#include "DNA_modifier_types.h"
#include "DNA_scene_types.h"
#include "BLI_math.h"
@@ -1512,3 +1513,10 @@ void BKE_ocean_bake(struct Ocean *UNUSED(o), struct OceanCache *UNUSED(och),
(void)update_cb;
}
#endif /* WITH_OCEANSIM */
void BKE_ocean_free_modifier_cache(struct OceanModifierData *omd)
{
BKE_ocean_free_cache(omd->oceancache);
omd->oceancache = NULL;
omd->cached = false;
}

View File

@@ -5225,8 +5225,7 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
else if (md->type == eModifierType_Ocean) {
OceanModifierData *omd = (OceanModifierData *)md;
omd->oceancache = NULL;
omd->ocean = BKE_ocean_add();
omd->refresh = MOD_OCEAN_REFRESH_RESET;
omd->ocean = NULL;
}
else if (md->type == eModifierType_Warp) {
WarpModifierData *tmd = (WarpModifierData *)md;

View File

@@ -2083,7 +2083,7 @@ static void init_ocean_modifier_bake(struct Ocean *oc, struct OceanModifierData
typedef struct OceanBakeJob {
/* from wmJob */
void *owner;
struct Object *owner;
short *stop, *do_update;
float *progress;
int current_frame;
@@ -2149,6 +2149,9 @@ static void oceanbake_endjob(void *customdata)
oj->omd->oceancache = oj->och;
oj->omd->cached = true;
Object *ob = oj->owner;
DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE);
}
static int ocean_bake_exec(bContext *C, wmOperator *op)
@@ -2169,8 +2172,8 @@ static int ocean_bake_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
if (free) {
omd->refresh |= MOD_OCEAN_REFRESH_CLEAR_CACHE;
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
BKE_ocean_free_modifier_cache(omd);
DEG_id_tag_update(&ob->id, OB_RECALC_DATA | DEG_TAG_COPY_ON_WRITE);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
return OPERATOR_FINISHED;
}
@@ -2232,6 +2235,7 @@ static int ocean_bake_exec(bContext *C, wmOperator *op)
wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Ocean Simulation",
WM_JOB_PROGRESS, WM_JOB_TYPE_OBJECT_SIM_OCEAN);
oj = MEM_callocN(sizeof(OceanBakeJob), "ocean bake job");
oj->owner = ob;
oj->ocean = ocean;
oj->och = och;
oj->omd = omd;

View File

@@ -997,7 +997,7 @@ typedef struct OceanModifierData {
char geometry_mode;
char flag;
char refresh;
char pad2;
short repeat_x;
short repeat_y;
@@ -1017,13 +1017,6 @@ enum {
MOD_OCEAN_GEOM_SIM_ONLY = 2,
};
enum {
MOD_OCEAN_REFRESH_RESET = (1 << 0),
/* MOD_OCEAN_REFRESH_SIM = (1 << 1), */
/* MOD_OCEAN_REFRESH_ADD = (1 << 2), */
MOD_OCEAN_REFRESH_CLEAR_CACHE = (1 << 3),
/* MOD_OCEAN_REFRESH_TOPOLOGY = (1 << 4), */
};
enum {
MOD_OCEAN_GENERATE_FOAM = (1 << 0),

View File

@@ -50,6 +50,7 @@
#include "BKE_mesh_mapping.h"
#include "BKE_mesh_remap.h"
#include "BKE_multires.h"
#include "BKE_ocean.h"
#include "BKE_smoke.h" /* For smokeModifier_free & smokeModifier_createType */
#include "RNA_access.h"
@@ -739,8 +740,7 @@ static void rna_OceanModifier_init_update(Main *bmain, Scene *scene, PointerRNA
{
OceanModifierData *omd = (OceanModifierData *)ptr->data;
omd->refresh |= MOD_OCEAN_REFRESH_RESET | MOD_OCEAN_REFRESH_CLEAR_CACHE;
BKE_ocean_free_modifier_cache(omd);
rna_Modifier_update(bmain, scene, ptr);
}
@@ -754,8 +754,7 @@ static void rna_OceanModifier_ocean_chop_set(PointerRNA *ptr, float value)
if ((old_value == 0.0f && value > 0.0f) ||
(old_value > 0.0f && value == 0.0f))
{
omd->refresh |= MOD_OCEAN_REFRESH_RESET;
omd->refresh |= MOD_OCEAN_REFRESH_CLEAR_CACHE;
BKE_ocean_free_modifier_cache(omd);
}
}

View File

@@ -61,13 +61,6 @@ static void init_cache_data(Object *ob, struct OceanModifierData *omd)
omd->chop_amount, omd->foam_coverage, omd->foam_fade, omd->resolution);
}
static void clear_cache_data(struct OceanModifierData *omd)
{
BKE_ocean_free_cache(omd->oceancache);
omd->oceancache = NULL;
omd->cached = false;
}
/* keep in sync with init_ocean_modifier_bake(), object_modifier.c */
static void init_ocean_modifier(struct OceanModifierData *omd)
{
@@ -91,8 +84,6 @@ static void init_ocean_modifier(struct OceanModifierData *omd)
static void simulate_ocean_modifier(struct OceanModifierData *omd)
{
if (!omd || !omd->ocean) return;
BKE_ocean_simulate(omd->ocean, omd->time, omd->wave_scale, omd->chop_amount);
}
#endif /* WITH_OCEANSIM */
@@ -126,8 +117,6 @@ static void initData(ModifierData *md)
omd->seed = 0;
omd->time = 1.0;
omd->refresh = 0;
omd->size = 1.0;
omd->repeat_x = 1;
omd->repeat_y = 1;
@@ -174,10 +163,8 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla
modifier_copyData_generic(md, target, flag);
tomd->refresh = 0;
/* XXX todo: copy cache runtime too */
tomd->cached = 0;
/* The oceancache object will be recreated for this copy
* automatically when cached=true */
tomd->oceancache = NULL;
tomd->ocean = BKE_ocean_add();
@@ -409,19 +396,18 @@ static Mesh *generate_ocean_geometry(OceanModifierData *omd)
return result;
}
static Mesh *doOcean(
ModifierData *md, Scene *scene, Object *ob,
Mesh *mesh,
int UNUSED(useRenderParams))
static Mesh *doOcean(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
{
OceanModifierData *omd = (OceanModifierData *) md;
int cfra_scene = (int)DEG_get_ctime(ctx->depsgraph);
Object *ob = ctx->object;
Mesh *result = NULL;
OceanResult ocr;
MVert *mverts;
int cfra;
int cfra_for_cache;
int i, j;
/* use cached & inverted value for speed
@@ -437,21 +423,12 @@ static Mesh *doOcean(
return mesh;
}
/* update modifier */
if (omd->refresh & MOD_OCEAN_REFRESH_RESET) {
init_ocean_modifier(omd);
}
if (omd->refresh & MOD_OCEAN_REFRESH_CLEAR_CACHE) {
clear_cache_data(omd);
}
omd->refresh = 0;
/* do ocean simulation */
if (omd->cached == true) {
if (!omd->oceancache) {
init_cache_data(ob, omd);
}
BKE_ocean_simulate_cache(omd->oceancache, scene->r.cfra);
BKE_ocean_simulate_cache(omd->oceancache, cfra_scene);
}
else {
simulate_ocean_modifier(omd);
@@ -470,9 +447,9 @@ static Mesh *doOcean(
false);
}
cfra = scene->r.cfra;
CLAMP(cfra, omd->bakestart, omd->bakeend);
cfra -= omd->bakestart; /* shift to 0 based */
cfra_for_cache = cfra_scene;
CLAMP(cfra_for_cache, omd->bakestart, omd->bakeend);
cfra_for_cache -= omd->bakestart; /* shift to 0 based */
mverts = result->mvert;
@@ -501,7 +478,7 @@ static Mesh *doOcean(
float foam;
if (omd->oceancache && omd->cached == true) {
BKE_ocean_cache_eval_uv(omd->oceancache, &ocr, cfra, u, v);
BKE_ocean_cache_eval_uv(omd->oceancache, &ocr, cfra_for_cache, u, v);
foam = ocr.foam;
CLAMP(foam, 0.0f, 1.0f);
}
@@ -532,7 +509,7 @@ static Mesh *doOcean(
const float v = OCEAN_CO(size_co_inv, vco[1]);
if (omd->oceancache && omd->cached == true) {
BKE_ocean_cache_eval_uv(omd->oceancache, &ocr, cfra, u, v);
BKE_ocean_cache_eval_uv(omd->oceancache, &ocr, cfra_for_cache, u, v);
}
else {
BKE_ocean_eval_uv(omd->ocean, &ocr, u, v);
@@ -552,10 +529,7 @@ static Mesh *doOcean(
return result;
}
#else /* WITH_OCEANSIM */
static Mesh *doOcean(
ModifierData *UNUSED(md), Scene *UNUSED(scene), Object *UNUSED(ob),
Mesh *mesh,
int UNUSED(useRenderParams))
static Mesh *doOcean(ModifierData *UNUSED(md), const ModifierEvalContext *UNUSED(ctx), Mesh *mesh)
{
return mesh;
}
@@ -566,10 +540,8 @@ static Mesh *applyModifier(
Mesh *mesh)
{
Mesh *result;
Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph);
result = doOcean(md, scene, ctx->object, mesh, 0);
result = doOcean(md, ctx, mesh);
if (result != mesh)
result->runtime.cd_dirty_vert |= CD_MASK_NORMAL;