Ocean modifier: Expose eigenvectors for use as map

The eigenvectors in the ocean modifier (plus and minus) can be useful,
but are not exposed. Assuming the particle system was capable, the
eigenvectors could be used to drive spray emission velocities.

This exposes the controls to allow a map to be generated from these
eigenvectors. Currently, the values are mapped into a 0-255 range
similar to foam.

Differential Revision: https://developer.blender.org/D7182
This commit is contained in:
Phil Stopford 2020-07-02 11:49:15 -04:00 committed by Hans Goudey
parent 35481fde40
commit 17b89f6dac
3 changed files with 83 additions and 2 deletions

View File

@ -1302,6 +1302,7 @@ typedef struct OceanModifierData {
char cachepath[1024];
/** MAX_CUSTOMDATA_LAYER_NAME. */
char foamlayername[64];
char spraylayername[64];
char cached;
char geometry_mode;
@ -1336,6 +1337,8 @@ enum {
enum {
MOD_OCEAN_GENERATE_FOAM = (1 << 0),
MOD_OCEAN_GENERATE_NORMALS = (1 << 1),
MOD_OCEAN_GENERATE_SPRAY = (1 << 2),
MOD_OCEAN_INVERT_SPRAY = (1 << 3),
};
typedef struct WarpModifierData {

View File

@ -5587,6 +5587,24 @@ static void rna_def_modifier_ocean(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Generate Foam", "Generate foam mask as a vertex color channel");
RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
prop = RNA_def_property(srna, "use_spray", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_OCEAN_GENERATE_SPRAY);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(
prop, "Generate Spray Map", "Generate map of spray direction as a vertex color channel");
RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
prop = RNA_def_property(srna, "invert_spray", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_OCEAN_INVERT_SPRAY);
RNA_def_property_ui_text(prop, "Invert Spray", "Invert the spray direction map");
RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
prop = RNA_def_property(srna, "spray_layer_name", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "spraylayername");
RNA_def_property_ui_text(
prop, "Spray Map", "Name of the vertex color layer used for the spray direction map");
RNA_def_property_update(prop, 0, "rna_OceanModifier_init_update");
prop = RNA_def_property(srna, "resolution", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "resolution");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);

View File

@ -122,7 +122,8 @@ static void initData(ModifierData *md)
omd->bakeend = 250;
omd->oceancache = NULL;
omd->foam_fade = 0.98;
omd->foamlayername[0] = '\0'; /* layer name empty by default */
omd->foamlayername[0] = '\0'; /* layer name empty by default */
omd->spraylayername[0] = '\0'; /* layer name empty by default */
omd->ocean = BKE_ocean_add();
BKE_ocean_init_from_modifier(omd->ocean, omd);
@ -420,6 +421,12 @@ static Mesh *doOcean(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mes
MLoopCol *mloopcols = CustomData_add_layer_named(
&result->ldata, CD_MLOOPCOL, CD_CALLOC, NULL, num_loops, omd->foamlayername);
MLoopCol *mloopcols_spray = NULL;
if (omd->flag & MOD_OCEAN_GENERATE_SPRAY) {
mloopcols_spray = CustomData_add_layer_named(
&result->ldata, CD_MLOOPCOL, CD_CALLOC, NULL, num_loops, omd->spraylayername);
}
if (mloopcols) { /* unlikely to fail */
MPoly *mpolys = result->mpoly;
MPoly *mp;
@ -428,6 +435,11 @@ static Mesh *doOcean(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mes
MLoop *ml = &mloops[mp->loopstart];
MLoopCol *mlcol = &mloopcols[mp->loopstart];
MLoopCol *mlcolspray = NULL;
if (omd->flag & MOD_OCEAN_GENERATE_SPRAY) {
mlcolspray = &mloopcols_spray[mp->loopstart];
}
for (j = mp->totloop; j--; ml++, mlcol++) {
const float *vco = mverts[ml->v].co;
const float u = OCEAN_CO(size_co_inv, vco[0]);
@ -447,6 +459,23 @@ static Mesh *doOcean(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mes
mlcol->r = mlcol->g = mlcol->b = (char)(foam * 255);
/* This needs to be set (render engine uses) */
mlcol->a = 255;
if (omd->flag & MOD_OCEAN_GENERATE_SPRAY) {
if (omd->flag & MOD_OCEAN_INVERT_SPRAY) {
mlcolspray->r = ocr.Eminus[0] * 255;
}
else {
mlcolspray->r = ocr.Eplus[0] * 255;
}
mlcolspray->g = 0;
if (omd->flag & MOD_OCEAN_INVERT_SPRAY) {
mlcolspray->b = ocr.Eminus[2] * 255;
}
else {
mlcolspray->b = ocr.Eplus[2] * 255;
}
mlcolspray->a = 255;
}
}
}
}
@ -607,6 +636,35 @@ static void foam_panel_draw(const bContext *C, Panel *panel)
uiItemR(col, &ptr, "foam_layer_name", 0, IFACE_("Data Layer"), ICON_NONE);
}
static void spray_panel_draw_header(const bContext *C, Panel *panel)
{
uiLayout *layout = panel->layout;
PointerRNA ptr;
modifier_panel_get_property_pointers(C, panel, NULL, &ptr);
uiItemR(layout, &ptr, "use_spray", 0, IFACE_("Spray"), ICON_NONE);
}
static void spray_panel_draw(const bContext *C, Panel *panel)
{
uiLayout *col;
uiLayout *layout = panel->layout;
PointerRNA ptr;
modifier_panel_get_property_pointers(C, panel, NULL, &ptr);
bool use_foam = RNA_boolean_get(&ptr, "use_foam");
bool use_spray = RNA_boolean_get(&ptr, "use_spray") && use_foam;
uiLayoutSetPropSep(layout, true);
col = uiLayoutColumn(layout, false);
uiLayoutSetActive(col, use_foam && use_spray);
uiItemR(col, &ptr, "spray_layer_name", 0, IFACE_("Data Layer"), ICON_NONE);
uiItemR(col, &ptr, "invert_spray", 0, IFACE_("Invert"), ICON_NONE);
}
static void spectrum_panel_draw(const bContext *C, Panel *panel)
{
uiLayout *col;
@ -674,8 +732,10 @@ static void panelRegister(ARegionType *region_type)
PanelType *panel_type = modifier_panel_register(region_type, eModifierType_Ocean, panel_draw);
#ifdef WITH_OCEANSIM
modifier_subpanel_register(region_type, "waves", "Waves", NULL, waves_panel_draw, panel_type);
modifier_subpanel_register(
PanelType *foam_panel = modifier_subpanel_register(
region_type, "foam", "", foam_panel_draw_header, foam_panel_draw, panel_type);
modifier_subpanel_register(
region_type, "spray", "", spray_panel_draw_header, spray_panel_draw, foam_panel);
modifier_subpanel_register(
region_type, "spectrum", "Spectrum", NULL, spectrum_panel_draw, panel_type);
modifier_subpanel_register(region_type, "bake", "Bake", NULL, bake_panel_draw, panel_type);