Ocean Modifier: Add viewport resolution

Following work done in 2.83, the resolution control is now a real
level-of-detail parameter. It is now useful to be able to set the
resolution for display independently from render. This is true for
both mesh generation and mesh deformation modes.

For compatibility with old scenes, resolution is retained and is the
render resolution. Old modifiers loaded have the value of resolution
also applied to viewport resolution. This allows newer modifiers to
be used in older versions without trouble

Differential Revision: https://developer.blender.org/D8336
This commit is contained in:
Phil Stopford
2020-08-03 10:08:31 -04:00
committed by Hans Goudey
parent 30b52b6a4a
commit a44299ccd1
7 changed files with 64 additions and 25 deletions

View File

@@ -70,8 +70,10 @@ typedef struct OceanCache {
struct Ocean *BKE_ocean_add(void);
void BKE_ocean_free_data(struct Ocean *oc);
void BKE_ocean_free(struct Ocean *oc);
bool BKE_ocean_ensure(struct OceanModifierData *omd);
void BKE_ocean_init_from_modifier(struct Ocean *ocean, struct OceanModifierData const *omd);
bool BKE_ocean_ensure(struct OceanModifierData *omd, const int resolution);
void BKE_ocean_init_from_modifier(struct Ocean *ocean,
struct OceanModifierData const *omd,
const int resolution);
void BKE_ocean_init(struct Ocean *o,
int M,

View File

@@ -753,18 +753,20 @@ struct Ocean *BKE_ocean_add(void)
return oc;
}
bool BKE_ocean_ensure(struct OceanModifierData *omd)
bool BKE_ocean_ensure(struct OceanModifierData *omd, const int resolution)
{
if (omd->ocean) {
return false;
}
omd->ocean = BKE_ocean_add();
BKE_ocean_init_from_modifier(omd->ocean, omd);
BKE_ocean_init_from_modifier(omd->ocean, omd, resolution);
return true;
}
void BKE_ocean_init_from_modifier(struct Ocean *ocean, struct OceanModifierData const *omd)
void BKE_ocean_init_from_modifier(struct Ocean *ocean,
struct OceanModifierData const *omd,
const int resolution)
{
short do_heightfield, do_chop, do_normals, do_jacobian;
@@ -774,9 +776,10 @@ void BKE_ocean_init_from_modifier(struct Ocean *ocean, struct OceanModifierData
do_jacobian = (omd->flag & MOD_OCEAN_GENERATE_FOAM);
BKE_ocean_free_data(ocean);
BKE_ocean_init(ocean,
omd->resolution * omd->resolution,
omd->resolution * omd->resolution,
resolution * resolution,
resolution * resolution,
omd->spatial_size,
omd->spatial_size,
omd->wind_velocity,
@@ -1607,7 +1610,8 @@ void BKE_ocean_bake(struct Ocean *UNUSED(o),
}
void BKE_ocean_init_from_modifier(struct Ocean *UNUSED(ocean),
struct OceanModifierData const *UNUSED(omd))
struct OceanModifierData const *UNUSED(omd),
int UNUSED(resolution))
{
}

View File

@@ -452,5 +452,16 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
cache_file->velocity_unit = CACHEFILE_VELOCITY_UNIT_SECOND;
}
}
if (!DNA_struct_elem_find(fd->filesdna, "OceanModifierData", "int", "viewport_resolution")) {
for (Object *object = bmain->objects.first; object != NULL; object = object->id.next) {
LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
if (md->type == eModifierType_Ocean) {
OceanModifierData *omd = (OceanModifierData *)md;
omd->viewport_resolution = omd->resolution;
}
}
}
}
}
}

View File

@@ -2813,7 +2813,7 @@ static int ocean_bake_exec(bContext *C, wmOperator *op)
/* make a copy of ocean to use for baking - threadsafety */
ocean = BKE_ocean_add();
BKE_ocean_init_from_modifier(ocean, omd);
BKE_ocean_init_from_modifier(ocean, omd, omd->resolution);
#if 0
BKE_ocean_bake(ocean, och);

View File

@@ -1277,7 +1277,11 @@ typedef struct OceanModifierData {
struct Ocean *ocean;
struct OceanCache *oceancache;
/** Render resolution. */
int resolution;
/** Viewport resolution for the non-render case. */
int viewport_resolution;
int spatial_size;
float wind_velocity;
@@ -1294,8 +1298,6 @@ typedef struct OceanModifierData {
float foam_coverage;
float time;
char _pad1[4];
/* Spectrum being used. */
int spectrum;

View File

@@ -113,7 +113,7 @@ const EnumPropertyItem rna_enum_object_modifier_type_items[] = {
{0, "", 0, N_("Generate"), ""},
{eModifierType_Array,
"ARRAY",
ICON_MOD_ARRAY,
ICON_MOD_ARRAY,
"Array",
"Create copies of the shape with offsets"},
{eModifierType_Bevel,
@@ -5712,7 +5712,17 @@ static void rna_def_modifier_ocean(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_range(prop, 1, 1024);
RNA_def_property_ui_range(prop, 1, 32, 1, -1);
RNA_def_property_ui_text(prop, "Resolution", "Resolution of the generated surface");
RNA_def_property_ui_text(
prop, "Render Resolution", "Resolution of the generated surface for rendering and baking");
RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
prop = RNA_def_property(srna, "viewport_resolution", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "viewport_resolution");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_range(prop, 1, 1024);
RNA_def_property_ui_range(prop, 1, 32, 1, -1);
RNA_def_property_ui_text(
prop, "Viewport Resolution", "Viewport resolution of the generated surface");
RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
prop = RNA_def_property(srna, "spatial_size", PROP_INT, PROP_NONE);

View File

@@ -59,7 +59,7 @@
#include "MOD_ui_common.h"
#ifdef WITH_OCEANSIM
static void init_cache_data(Object *ob, struct OceanModifierData *omd)
static void init_cache_data(Object *ob, struct OceanModifierData *omd, const int resolution)
{
const char *relbase = BKE_modifier_path_relbase_from_global(ob);
@@ -71,7 +71,7 @@ static void init_cache_data(Object *ob, struct OceanModifierData *omd)
omd->chop_amount,
omd->foam_coverage,
omd->foam_fade,
omd->resolution);
resolution);
}
static void simulate_ocean_modifier(struct OceanModifierData *omd)
@@ -87,7 +87,11 @@ static void initData(ModifierData *md)
#ifdef WITH_OCEANSIM
OceanModifierData *omd = (OceanModifierData *)md;
/* Render resolution */
omd->resolution = 7;
/* Display resolution for the non-render case */
omd->viewport_resolution = 7;
omd->spatial_size = 50;
omd->wave_alignment = 0.0;
@@ -126,7 +130,7 @@ static void initData(ModifierData *md)
omd->spraylayername[0] = '\0'; /* layer name empty by default */
omd->ocean = BKE_ocean_add();
BKE_ocean_init_from_modifier(omd->ocean, omd);
BKE_ocean_init_from_modifier(omd->ocean, omd, omd->viewport_resolution);
simulate_ocean_modifier(omd);
#else /* WITH_OCEANSIM */
/* unused */
@@ -164,7 +168,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla
tomd->oceancache = NULL;
tomd->ocean = BKE_ocean_add();
BKE_ocean_init_from_modifier(tomd->ocean, tomd);
BKE_ocean_init_from_modifier(tomd->ocean, tomd, tomd->viewport_resolution);
simulate_ocean_modifier(tomd);
#else /* WITH_OCEANSIM */
/* unused */
@@ -288,7 +292,7 @@ static void generate_ocean_geometry_uvs(void *__restrict userdata,
}
}
static Mesh *generate_ocean_geometry(OceanModifierData *omd, Mesh *mesh_orig)
static Mesh *generate_ocean_geometry(OceanModifierData *omd, Mesh *mesh_orig, const int resolution)
{
Mesh *result;
@@ -297,10 +301,10 @@ static Mesh *generate_ocean_geometry(OceanModifierData *omd, Mesh *mesh_orig)
int num_verts;
int num_polys;
const bool use_threading = omd->resolution > 4;
const bool use_threading = resolution > 4;
gogd.rx = omd->resolution * omd->resolution;
gogd.ry = omd->resolution * omd->resolution;
gogd.rx = resolution * resolution;
gogd.ry = resolution * resolution;
gogd.res_x = gogd.rx * omd->repeat_x;
gogd.res_y = gogd.ry * omd->repeat_y;
@@ -362,6 +366,9 @@ static Mesh *doOcean(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mes
Mesh *result = NULL;
OceanResult ocr;
const int resolution = (ctx->flag & MOD_APPLY_RENDER) ? omd->resolution :
omd->viewport_resolution;
MVert *mverts;
int cfra_for_cache;
@@ -383,7 +390,7 @@ static Mesh *doOcean(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mes
/* do ocean simulation */
if (omd->cached == true) {
if (!omd->oceancache) {
init_cache_data(ob, omd);
init_cache_data(ob, omd, resolution);
}
BKE_ocean_simulate_cache(omd->oceancache, cfra_scene);
}
@@ -393,12 +400,12 @@ static Mesh *doOcean(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mes
* This function is only called on an original object when applying the modifier
* using the 'Apply Modifier' button, and thus it is not called frequently for
* simulation. */
allocated_ocean |= BKE_ocean_ensure(omd);
allocated_ocean |= BKE_ocean_ensure(omd, resolution);
simulate_ocean_modifier(omd);
}
if (omd->geometry_mode == MOD_OCEAN_GEOM_GENERATE) {
result = generate_ocean_geometry(omd, mesh);
result = generate_ocean_geometry(omd, mesh, resolution);
BKE_mesh_ensure_normals(result);
}
else if (omd->geometry_mode == MOD_OCEAN_GEOM_DISPLACE) {
@@ -558,7 +565,10 @@ static void panel_draw(const bContext *C, Panel *panel)
uiItemR(sub, &ptr, "repeat_x", 0, IFACE_("Repeat X"), ICON_NONE);
uiItemR(sub, &ptr, "repeat_y", 0, IFACE_("Y"), ICON_NONE);
}
uiItemR(col, &ptr, "resolution", 0, NULL, ICON_NONE);
sub = uiLayoutColumn(col, true);
uiItemR(sub, &ptr, "viewport_resolution", 0, IFACE_("Resolution Viewport"), ICON_NONE);
uiItemR(sub, &ptr, "resolution", 0, IFACE_("Render"), ICON_NONE);
uiItemR(col, &ptr, "time", 0, NULL, ICON_NONE);