Blender V5.0
MOD_ocean.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "BLI_math_base.h"
10#include "BLI_task.h"
11#include "BLI_utildefines.h"
12
13#include "BLT_translation.hh"
14
16#include "DNA_defaults.h"
17#include "DNA_mesh_types.h"
18#include "DNA_meshdata_types.h"
19#include "DNA_modifier_types.h"
20#include "DNA_object_types.h"
21#include "DNA_screen_types.h"
22
23#include "BKE_customdata.hh"
24#include "BKE_lib_id.hh"
25#include "BKE_mesh.hh"
26#include "BKE_modifier.hh"
27#include "BKE_ocean.h"
28
30#include "UI_resources.hh"
31
32#include "RNA_access.hh"
33#include "RNA_prototypes.hh"
34
35#include "WM_types.hh" /* For UI free bake operator. */
36
38
39#include "MOD_ui_common.hh"
40
41#ifdef WITH_OCEANSIM
42static void init_cache_data(Object *ob, OceanModifierData *omd, const int resolution)
43{
44 const char *relbase = BKE_modifier_path_relbase_from_global(ob);
45
47 relbase,
48 omd->bakestart,
49 omd->bakeend,
50 omd->wave_scale,
51 omd->chop_amount,
52 omd->foam_coverage,
53 omd->foam_fade,
54 resolution);
55}
56
57static void simulate_ocean_modifier(OceanModifierData *omd)
58{
59 BKE_ocean_simulate(omd->ocean, omd->time, omd->wave_scale, omd->chop_amount);
60}
61#endif /* WITH_OCEANSIM */
62
63/* Modifier Code */
64
65static void init_data(ModifierData *md)
66{
67#ifdef WITH_OCEANSIM
69
71
73
74 BKE_modifier_path_init(omd->cachepath, sizeof(omd->cachepath), "cache_ocean");
75
76 omd->ocean = BKE_ocean_add();
78 simulate_ocean_modifier(omd);
79 }
80#else /* WITH_OCEANSIM */
81 UNUSED_VARS(md);
82#endif /* WITH_OCEANSIM */
83}
84
85static void free_data(ModifierData *md)
86{
87#ifdef WITH_OCEANSIM
89
91 if (omd->oceancache) {
93 }
94#else /* WITH_OCEANSIM */
95 /* unused */
96 (void)md;
97#endif /* WITH_OCEANSIM */
98}
99
100static void copy_data(const ModifierData *md, ModifierData *target, const int flag)
101{
102#ifdef WITH_OCEANSIM
103# if 0
104 const OceanModifierData *omd = (const OceanModifierData *)md;
105# endif
106 OceanModifierData *tomd = (OceanModifierData *)target;
107
109
110 /* The oceancache object will be recreated for this copy
111 * automatically when cached=true */
112 tomd->oceancache = nullptr;
113
114 tomd->ocean = BKE_ocean_add();
116 simulate_ocean_modifier(tomd);
117 }
118#else /* WITH_OCEANSIM */
119 /* unused */
120 (void)md;
121 (void)target;
122 (void)flag;
123#endif /* WITH_OCEANSIM */
124}
125
126#ifdef WITH_OCEANSIM
127static void required_data_mask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks)
128{
130
131 if (omd->flag & MOD_OCEAN_GENERATE_FOAM) {
132 r_cddata_masks->fmask |= CD_MASK_MCOL; /* XXX Should be loop cddata I guess? */
133 }
134}
135#else /* WITH_OCEANSIM */
136static void required_data_mask(ModifierData * /*md*/, CustomData_MeshMasks * /*r_cddata_masks*/) {}
137#endif /* WITH_OCEANSIM */
138
139#ifdef WITH_OCEANSIM
140
141struct GenerateOceanGeometryData {
142 blender::MutableSpan<blender::float3> vert_positions;
143 blender::MutableSpan<int> face_offsets;
144 blender::MutableSpan<int> corner_verts;
145 float (*uv_map)[2];
146
147 int res_x, res_y;
148 int rx, ry;
149 float ox, oy;
150 float sx, sy;
151 float ix, iy;
152};
153
154static void generate_ocean_geometry_verts(void *__restrict userdata,
155 const int y,
156 const TaskParallelTLS *__restrict /*tls*/)
157{
158 GenerateOceanGeometryData *gogd = static_cast<GenerateOceanGeometryData *>(userdata);
159 int x;
160
161 for (x = 0; x <= gogd->res_x; x++) {
162 const int i = y * (gogd->res_x + 1) + x;
163 float *co = gogd->vert_positions[i];
164 co[0] = gogd->ox + (x * gogd->sx);
165 co[1] = gogd->oy + (y * gogd->sy);
166 co[2] = 0.0f;
167 }
168}
169
170static void generate_ocean_geometry_faces(void *__restrict userdata,
171 const int y,
172 const TaskParallelTLS *__restrict /*tls*/)
173{
174 GenerateOceanGeometryData *gogd = static_cast<GenerateOceanGeometryData *>(userdata);
175 int x;
176
177 for (x = 0; x < gogd->res_x; x++) {
178 const int fi = y * gogd->res_x + x;
179 const int vi = y * (gogd->res_x + 1) + x;
180
181 gogd->corner_verts[fi * 4 + 0] = vi;
182 gogd->corner_verts[fi * 4 + 1] = vi + 1;
183 gogd->corner_verts[fi * 4 + 2] = vi + 1 + gogd->res_x + 1;
184 gogd->corner_verts[fi * 4 + 3] = vi + gogd->res_x + 1;
185
186 gogd->face_offsets[fi] = fi * 4;
187 }
188}
189
190static void generate_ocean_geometry_uvs(void *__restrict userdata,
191 const int y,
192 const TaskParallelTLS *__restrict /*tls*/)
193{
194 GenerateOceanGeometryData *gogd = static_cast<GenerateOceanGeometryData *>(userdata);
195 int x;
196
197 for (x = 0; x < gogd->res_x; x++) {
198 const int i = y * gogd->res_x + x;
199 float (*luv)[2] = &gogd->uv_map[i * 4];
200
201 (*luv)[0] = x * gogd->ix;
202 (*luv)[1] = y * gogd->iy;
203 luv++;
204
205 (*luv)[0] = (x + 1) * gogd->ix;
206 (*luv)[1] = y * gogd->iy;
207 luv++;
208
209 (*luv)[0] = (x + 1) * gogd->ix;
210 (*luv)[1] = (y + 1) * gogd->iy;
211 luv++;
212
213 (*luv)[0] = x * gogd->ix;
214 (*luv)[1] = (y + 1) * gogd->iy;
215 luv++;
216 }
217}
218
219static Mesh *generate_ocean_geometry(OceanModifierData *omd, Mesh *mesh_orig, const int resolution)
220{
221 Mesh *result;
222
223 GenerateOceanGeometryData gogd;
224
225 int verts_num;
226 int faces_num;
227
228 const bool use_threading = resolution > 4;
229
230 gogd.rx = resolution * resolution;
231 gogd.ry = resolution * resolution;
232 gogd.res_x = gogd.rx * omd->repeat_x;
233 gogd.res_y = gogd.ry * omd->repeat_y;
234
235 verts_num = (gogd.res_x + 1) * (gogd.res_y + 1);
236 faces_num = gogd.res_x * gogd.res_y;
237
238 gogd.sx = omd->size * omd->spatial_size;
239 gogd.sy = omd->size * omd->spatial_size;
240 gogd.ox = -gogd.sx / 2.0f;
241 gogd.oy = -gogd.sy / 2.0f;
242
243 gogd.sx /= gogd.rx;
244 gogd.sy /= gogd.ry;
245
246 result = BKE_mesh_new_nomain(verts_num, 0, faces_num, faces_num * 4);
248
249 gogd.vert_positions = result->vert_positions_for_write();
250 gogd.face_offsets = result->face_offsets_for_write();
251 gogd.corner_verts = result->corner_verts_for_write();
252
253 TaskParallelSettings settings;
255 settings.use_threading = use_threading;
256
257 /* create vertices */
258 BLI_task_parallel_range(0, gogd.res_y + 1, &gogd, generate_ocean_geometry_verts, &settings);
259
260 /* create faces */
261 BLI_task_parallel_range(0, gogd.res_y, &gogd, generate_ocean_geometry_faces, &settings);
262
264
265 /* add uvs */
267 gogd.uv_map = static_cast<float (*)[2]>(CustomData_add_layer_named(
268 &result->corner_data, CD_PROP_FLOAT2, CD_SET_DEFAULT, faces_num * 4, "UVMap"));
269
270 if (gogd.uv_map) { /* unlikely to fail */
271 gogd.ix = 1.0 / gogd.rx;
272 gogd.iy = 1.0 / gogd.ry;
273
274 BLI_task_parallel_range(0, gogd.res_y, &gogd, generate_ocean_geometry_uvs, &settings);
275 }
276 }
277
278 return result;
279}
280
281static Mesh *doOcean(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
282{
284 if (omd->ocean && !BKE_ocean_is_valid(omd->ocean)) {
285 BKE_modifier_set_error(ctx->object, md, "Failed to allocate memory");
286 return mesh;
287 }
288 int cfra_scene = int(DEG_get_ctime(ctx->depsgraph));
289 Object *ob = ctx->object;
290 bool allocated_ocean = false;
291
292 Mesh *result = nullptr;
293 OceanResult ocr;
294
295 const int resolution = (ctx->flag & MOD_APPLY_RENDER) ? omd->resolution :
296 omd->viewport_resolution;
297
298 int cfra_for_cache;
299 int i, j;
300
301 /* use cached & inverted value for speed
302 * expanded this would read...
303 *
304 * (axis / (omd->size * omd->spatial_size)) + 0.5f) */
305# define OCEAN_CO(_size_co_inv, _v) ((_v * _size_co_inv) + 0.5f)
306
307 const float size_co_inv = 1.0f / (omd->size * omd->spatial_size);
308
309 /* can happen in when size is small, avoid bad array lookups later and quit now */
310 if (!isfinite(size_co_inv)) {
311 return mesh;
312 }
313
314 /* do ocean simulation */
315 if (omd->cached) {
316 if (!omd->oceancache) {
317 init_cache_data(ob, omd, resolution);
318 }
319 BKE_ocean_simulate_cache(omd->oceancache, cfra_scene);
320 }
321 else {
322 /* omd->ocean is nullptr on an original object (in contrast to an evaluated one).
323 * We can create a new one, but we have to free it as well once we're done.
324 * This function is only called on an original object when applying the modifier
325 * using the 'Apply Modifier' button, and thus it is not called frequently for
326 * simulation. */
327 allocated_ocean |= BKE_ocean_ensure(omd, resolution);
328 simulate_ocean_modifier(omd);
329 }
330
332 result = generate_ocean_geometry(omd, mesh, resolution);
333 }
334 else if (omd->geometry_mode == MOD_OCEAN_GEOM_DISPLACE) {
335 result = (Mesh *)BKE_id_copy_ex(nullptr, &mesh->id, nullptr, LIB_ID_COPY_LOCALIZE);
336 }
337
338 cfra_for_cache = cfra_scene;
339 CLAMP(cfra_for_cache, omd->bakestart, omd->bakeend);
340 cfra_for_cache -= omd->bakestart; /* shift to 0 based */
341
342 blender::MutableSpan<blender::float3> positions = result->vert_positions_for_write();
343 const blender::OffsetIndices faces = result->faces();
344
345 /* Add vertex-colors before displacement: allows lookup based on position. */
346
347 if (omd->flag & MOD_OCEAN_GENERATE_FOAM) {
348 const blender::Span<int> corner_verts = result->corner_verts();
349 MLoopCol *mloopcols = static_cast<MLoopCol *>(CustomData_add_layer_named(&result->corner_data,
352 corner_verts.size(),
353 omd->foamlayername));
354
355 MLoopCol *mloopcols_spray = nullptr;
356 if (omd->flag & MOD_OCEAN_GENERATE_SPRAY) {
357 mloopcols_spray = static_cast<MLoopCol *>(CustomData_add_layer_named(&result->corner_data,
360 corner_verts.size(),
361 omd->spraylayername));
362 }
363
364 if (mloopcols) { /* unlikely to fail */
365
366 for (const int i : faces.index_range()) {
367 const blender::IndexRange face = faces[i];
368 const int *corner_vert = &corner_verts[face.start()];
369 MLoopCol *mlcol = &mloopcols[face.start()];
370
371 MLoopCol *mlcolspray = nullptr;
372 if (omd->flag & MOD_OCEAN_GENERATE_SPRAY) {
373 mlcolspray = &mloopcols_spray[face.start()];
374 }
375
376 for (j = face.size(); j--; corner_vert++, mlcol++) {
377 const float *vco = positions[*corner_vert];
378 const float u = OCEAN_CO(size_co_inv, vco[0]);
379 const float v = OCEAN_CO(size_co_inv, vco[1]);
380 float foam;
381
382 if (omd->oceancache && omd->cached) {
383 BKE_ocean_cache_eval_uv(omd->oceancache, &ocr, cfra_for_cache, u, v);
384 foam = ocr.foam;
385 CLAMP(foam, 0.0f, 1.0f);
386 }
387 else {
388 BKE_ocean_eval_uv(omd->ocean, &ocr, u, v);
390 }
391
392 mlcol->r = mlcol->g = mlcol->b = char(foam * 255);
393 /* This needs to be set (render engine uses) */
394 mlcol->a = 255;
395
396 if (omd->flag & MOD_OCEAN_GENERATE_SPRAY) {
397 if (omd->flag & MOD_OCEAN_INVERT_SPRAY) {
398 mlcolspray->r = ocr.Eminus[0] * 255;
399 }
400 else {
401 mlcolspray->r = ocr.Eplus[0] * 255;
402 }
403 mlcolspray->g = 0;
404 if (omd->flag & MOD_OCEAN_INVERT_SPRAY) {
405 mlcolspray->b = ocr.Eminus[2] * 255;
406 }
407 else {
408 mlcolspray->b = ocr.Eplus[2] * 255;
409 }
410 mlcolspray->a = 255;
411 }
412 }
413 }
414 }
415 }
416
417 /* displace the geometry */
418
419 /* NOTE: tried to parallelized that one and previous foam loop,
420 * but gives 20% slower results... odd. */
421 {
422 const int verts_num = result->verts_num;
423
424 for (i = 0; i < verts_num; i++) {
425 float *vco = positions[i];
426 const float u = OCEAN_CO(size_co_inv, vco[0]);
427 const float v = OCEAN_CO(size_co_inv, vco[1]);
428
429 if (omd->oceancache && omd->cached) {
430 BKE_ocean_cache_eval_uv(omd->oceancache, &ocr, cfra_for_cache, u, v);
431 }
432 else {
433 BKE_ocean_eval_uv(omd->ocean, &ocr, u, v);
434 }
435
436 vco[2] += ocr.disp[1];
437
438 if (omd->chop_amount > 0.0f) {
439 vco[0] += ocr.disp[0];
440 vco[1] += ocr.disp[2];
441 }
442 }
443 }
444
445 result->tag_positions_changed();
446
447 if (allocated_ocean) {
448 BKE_ocean_free(omd->ocean);
449 omd->ocean = nullptr;
450 }
451
452# undef OCEAN_CO
453
454 return result;
455}
456#else /* WITH_OCEANSIM */
457static Mesh *doOcean(ModifierData * /*md*/, const ModifierEvalContext * /*ctx*/, Mesh *mesh)
458{
459 return mesh;
460}
461#endif /* WITH_OCEANSIM */
462
463static Mesh *modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
464{
465 return doOcean(md, ctx, mesh);
466}
467// #define WITH_OCEANSIM
468static void panel_draw(const bContext * /*C*/, Panel *panel)
469{
470 uiLayout *layout = panel->layout;
471#ifdef WITH_OCEANSIM
472 uiLayout *col, *sub;
473
474 PointerRNA ob_ptr;
476
477 layout->use_property_split_set(true);
478
479 col = &layout->column(false);
480 col->prop(ptr, "geometry_mode", UI_ITEM_NONE, std::nullopt, ICON_NONE);
481 if (RNA_enum_get(ptr, "geometry_mode") == MOD_OCEAN_GEOM_GENERATE) {
482 sub = &col->column(true);
483 sub->prop(ptr, "repeat_x", UI_ITEM_NONE, IFACE_("Repeat X"), ICON_NONE);
484 sub->prop(ptr, "repeat_y", UI_ITEM_NONE, IFACE_("Y"), ICON_NONE);
485 }
486
487 sub = &col->column(true);
488 sub->prop(ptr, "viewport_resolution", UI_ITEM_NONE, IFACE_("Resolution Viewport"), ICON_NONE);
489 sub->prop(ptr, "resolution", UI_ITEM_NONE, IFACE_("Render"), ICON_NONE);
490
491 col->prop(ptr, "time", UI_ITEM_NONE, std::nullopt, ICON_NONE);
492
493 col->prop(ptr, "depth", UI_ITEM_NONE, std::nullopt, ICON_NONE);
494 col->prop(ptr, "size", UI_ITEM_NONE, std::nullopt, ICON_NONE);
495 col->prop(ptr, "spatial_size", UI_ITEM_NONE, std::nullopt, ICON_NONE);
496
497 col->prop(ptr, "random_seed", UI_ITEM_NONE, std::nullopt, ICON_NONE);
498
499 col->prop(ptr, "use_normals", UI_ITEM_NONE, std::nullopt, ICON_NONE);
500
502
503#else /* WITH_OCEANSIM */
504 layout->label(RPT_("Built without Ocean modifier"), ICON_NONE);
505#endif /* WITH_OCEANSIM */
506}
507
508#ifdef WITH_OCEANSIM
509static void waves_panel_draw(const bContext * /*C*/, Panel *panel)
510{
511 uiLayout *col, *sub;
512 uiLayout *layout = panel->layout;
513
515
516 layout->use_property_split_set(true);
517
518 col = &layout->column(false);
519 col->prop(ptr, "wave_scale", UI_ITEM_NONE, IFACE_("Scale"), ICON_NONE);
520 col->prop(ptr, "wave_scale_min", UI_ITEM_NONE, std::nullopt, ICON_NONE);
521 col->prop(ptr, "choppiness", UI_ITEM_NONE, std::nullopt, ICON_NONE);
522 col->prop(ptr, "wind_velocity", UI_ITEM_NONE, std::nullopt, ICON_NONE);
523
524 layout->separator();
525
526 col = &layout->column(false);
527 col->prop(ptr, "wave_alignment", UI_ITEM_R_SLIDER, IFACE_("Alignment"), ICON_NONE);
528 sub = &col->column(false);
529 sub->active_set(RNA_float_get(ptr, "wave_alignment") > 0.0f);
530 sub->prop(ptr, "wave_direction", UI_ITEM_NONE, IFACE_("Direction"), ICON_NONE);
531 sub->prop(ptr, "damping", UI_ITEM_NONE, std::nullopt, ICON_NONE);
532}
533
534static void foam_panel_draw_header(const bContext * /*C*/, Panel *panel)
535{
536 uiLayout *layout = panel->layout;
537
539
540 layout->prop(ptr, "use_foam", UI_ITEM_NONE, IFACE_("Foam"), ICON_NONE);
541}
542
543static void foam_panel_draw(const bContext * /*C*/, Panel *panel)
544{
545 uiLayout *col;
546 uiLayout *layout = panel->layout;
547
549
550 bool use_foam = RNA_boolean_get(ptr, "use_foam");
551
552 layout->use_property_split_set(true);
553
554 col = &layout->column(false);
555 col->active_set(use_foam);
556 col->prop(ptr, "foam_layer_name", UI_ITEM_NONE, IFACE_("Data Layer"), ICON_NONE);
557 col->prop(ptr, "foam_coverage", UI_ITEM_NONE, IFACE_("Coverage"), ICON_NONE);
558}
559
560static void spray_panel_draw_header(const bContext * /*C*/, Panel *panel)
561{
562 uiLayout *row;
563 uiLayout *layout = panel->layout;
564
566
567 bool use_foam = RNA_boolean_get(ptr, "use_foam");
568
569 row = &layout->row(false);
570 row->active_set(use_foam);
571 row->prop(
572 ptr, "use_spray", UI_ITEM_NONE, CTX_IFACE_(BLT_I18NCONTEXT_ID_MESH, "Spray"), ICON_NONE);
573}
574
575static void spray_panel_draw(const bContext * /*C*/, Panel *panel)
576{
577 uiLayout *col;
578 uiLayout *layout = panel->layout;
579
581
582 bool use_foam = RNA_boolean_get(ptr, "use_foam");
583 bool use_spray = RNA_boolean_get(ptr, "use_spray");
584
585 layout->use_property_split_set(true);
586
587 col = &layout->column(false);
588 col->active_set(use_foam && use_spray);
589 col->prop(ptr, "spray_layer_name", UI_ITEM_NONE, IFACE_("Data Layer"), ICON_NONE);
590 col->prop(ptr, "invert_spray", UI_ITEM_NONE, IFACE_("Invert"), ICON_NONE);
591}
592
593static void spectrum_panel_draw(const bContext * /*C*/, Panel *panel)
594{
595 uiLayout *col;
596 uiLayout *layout = panel->layout;
597
599
600 int spectrum = RNA_enum_get(ptr, "spectrum");
601
602 layout->use_property_split_set(true);
603
604 col = &layout->column(false);
605 col->prop(ptr, "spectrum", UI_ITEM_NONE, std::nullopt, ICON_NONE);
607 col->prop(ptr, "sharpen_peak_jonswap", UI_ITEM_R_SLIDER, std::nullopt, ICON_NONE);
608 col->prop(ptr, "fetch_jonswap", UI_ITEM_NONE, std::nullopt, ICON_NONE);
609 }
610}
611
612static void bake_panel_draw(const bContext * /*C*/, Panel *panel)
613{
614 uiLayout *col;
615 uiLayout *layout = panel->layout;
616
618
619 layout->use_property_split_set(true);
620
621 bool is_cached = RNA_boolean_get(ptr, "is_cached");
622 bool use_foam = RNA_boolean_get(ptr, "use_foam");
623
624 if (is_cached) {
625 PointerRNA op_ptr = layout->op("OBJECT_OT_ocean_bake",
626 IFACE_("Delete Bake"),
627 ICON_NONE,
630 RNA_boolean_set(&op_ptr, "free", true);
631 }
632 else {
633 PointerRNA op_ptr = layout->op("OBJECT_OT_ocean_bake",
634 IFACE_("Bake"),
635 ICON_NONE,
638 RNA_boolean_set(&op_ptr, "free", false);
639 }
640
641 layout->prop(ptr, "filepath", UI_ITEM_NONE, std::nullopt, ICON_NONE);
642
643 col = &layout->column(true);
644 col->enabled_set(!is_cached);
645 col->prop(ptr, "frame_start", UI_ITEM_NONE, IFACE_("Frame Start"), ICON_NONE);
646 col->prop(ptr, "frame_end", UI_ITEM_NONE, IFACE_("End"), ICON_NONE);
647
648 col = &layout->column(false);
649 col->active_set(use_foam);
650 col->prop(ptr, "bake_foam_fade", UI_ITEM_NONE, std::nullopt, ICON_NONE);
651}
652#endif /* WITH_OCEANSIM */
653
654static void panel_register(ARegionType *region_type)
655{
657#ifdef WITH_OCEANSIM
658 modifier_subpanel_register(region_type, "waves", "Waves", nullptr, waves_panel_draw, panel_type);
660 region_type, "foam", "", foam_panel_draw_header, foam_panel_draw, panel_type);
662 region_type, "spray", "", spray_panel_draw_header, spray_panel_draw, foam_panel);
664 region_type, "spectrum", "Spectrum", nullptr, spectrum_panel_draw, panel_type);
665 modifier_subpanel_register(region_type, "bake", "Bake", nullptr, bake_panel_draw, panel_type);
666#else
667 UNUSED_VARS(panel_type);
668#endif /* WITH_OCEANSIM */
669}
670
671static void blend_read(BlendDataReader * /*reader*/, ModifierData *md)
672{
674 omd->oceancache = nullptr;
675 omd->ocean = nullptr;
676}
677
679 /*idname*/ "Ocean",
680 /*name*/ N_("Ocean"),
681 /*struct_name*/ "OceanModifierData",
682 /*struct_size*/ sizeof(OceanModifierData),
683 /*srna*/ &RNA_OceanModifier,
687 /*icon*/ ICON_MOD_OCEAN,
688
689 /*copy_data*/ copy_data,
690 /*deform_verts*/ nullptr,
691
692 /*deform_matrices*/ nullptr,
693 /*deform_verts_EM*/ nullptr,
694 /*deform_matrices_EM*/ nullptr,
695 /*modify_mesh*/ modify_mesh,
696 /*modify_geometry_set*/ nullptr,
697
698 /*init_data*/ init_data,
699 /*required_data_mask*/ required_data_mask,
700 /*free_data*/ free_data,
701 /*is_disabled*/ nullptr,
702 /*update_depsgraph*/ nullptr,
703 /*depends_on_time*/ nullptr,
704 /*depends_on_normals*/ nullptr,
705 /*foreach_ID_link*/ nullptr,
706 /*foreach_tex_link*/ nullptr,
707 /*free_runtime_data*/ nullptr,
708 /*panel_register*/ panel_register,
709 /*blend_write*/ nullptr,
710 /*blend_read*/ blend_read,
711 /*foreach_cache*/ nullptr,
712 /*foreach_working_space_color*/ nullptr,
713};
CustomData interface, see also DNA_customdata_types.h.
@ CD_SET_DEFAULT
void * CustomData_add_layer_named(CustomData *data, eCustomDataType type, eCDAllocType alloctype, int totelem, blender::StringRef name)
int CustomData_number_of_layers(const CustomData *data, eCustomDataType type)
ID * BKE_id_copy_ex(Main *bmain, const ID *id, ID **new_id_p, int flag)
Definition lib_id.cc:777
@ LIB_ID_COPY_LOCALIZE
void BKE_mesh_copy_parameters_for_eval(Mesh *me_dst, const Mesh *me_src)
Mesh * BKE_mesh_new_nomain(int verts_num, int edges_num, int faces_num, int corners_num)
void BKE_modifier_path_init(char *path, int path_maxncpy, const char *name)
void BKE_modifier_copydata_generic(const ModifierData *md, ModifierData *md_dst, int flag)
@ eModifierTypeFlag_EnableInEditmode
@ eModifierTypeFlag_SupportsEditmode
@ eModifierTypeFlag_AcceptsMesh
const char * BKE_modifier_path_relbase_from_global(Object *ob)
void BKE_modifier_set_error(const Object *ob, ModifierData *md, const char *format,...) ATTR_PRINTF_FORMAT(3
@ MOD_APPLY_RENDER
struct Ocean * BKE_ocean_add(void)
Definition ocean.cc:1571
void BKE_ocean_cache_eval_uv(struct OceanCache *och, struct OceanResult *ocr, int f, float u, float v)
Definition ocean.cc:1625
void BKE_ocean_simulate(struct Ocean *o, float t, float scale, float chop_amount)
Definition ocean.cc:1569
float BKE_ocean_jminus_to_foam(float jminus, float coverage)
Definition ocean.cc:1553
bool BKE_ocean_ensure(struct OceanModifierData *omd, int resolution)
void BKE_ocean_free_cache(struct OceanCache *och)
Definition ocean.cc:1616
void BKE_ocean_simulate_cache(struct OceanCache *och, int frame)
Definition ocean.cc:1650
void BKE_ocean_eval_uv(struct Ocean *oc, struct OceanResult *ocr, float u, float v)
Definition ocean.cc:1558
bool BKE_ocean_init_from_modifier(struct Ocean *ocean, struct OceanModifierData const *omd, int resolution)
void BKE_ocean_free(struct Ocean *oc)
Definition ocean.cc:1606
bool BKE_ocean_is_valid(const struct Ocean *o)
struct OceanCache * BKE_ocean_init_cache(const char *bakepath, const char *relbase, int start, int end, float wave_scale, float chop_amount, float foam_coverage, float foam_fade, int resolution)
Definition ocean.cc:1635
#define BLI_assert(a)
Definition BLI_assert.h:46
void BLI_task_parallel_range(int start, int stop, void *userdata, TaskParallelRangeFunc func, const TaskParallelSettings *settings)
Definition task_range.cc:99
BLI_INLINE void BLI_parallel_range_settings_defaults(TaskParallelSettings *settings)
Definition BLI_task.h:221
#define CLAMP(a, b, c)
#define UNUSED_VARS(...)
#define ELEM(...)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#define RPT_(msgid)
#define CTX_IFACE_(context, msgid)
#define IFACE_(msgid)
#define BLT_I18NCONTEXT_ID_MESH
float DEG_get_ctime(const Depsgraph *graph)
#define CD_MASK_MCOL
@ CD_PROP_BYTE_COLOR
@ CD_PROP_FLOAT2
#define MAX_MTFACE
#define DNA_struct_default_get(struct_name)
@ MOD_OCEAN_GENERATE_FOAM
@ MOD_OCEAN_INVERT_SPRAY
@ MOD_OCEAN_GENERATE_SPRAY
@ MOD_OCEAN_GEOM_GENERATE
@ MOD_OCEAN_GEOM_DISPLACE
@ eModifierType_Ocean
@ MOD_OCEAN_SPECTRUM_TEXEL_MARSEN_ARSLOE
@ MOD_OCEAN_SPECTRUM_JONSWAP
Object is a sort of wrapper for general info.
static void init_data(ModifierData *md)
static void panel_register(ARegionType *region_type)
static void required_data_mask(ModifierData *, CustomData_MeshMasks *r_cddata_masks)
static void blend_read(BlendDataReader *, ModifierData *md)
static void panel_draw(const bContext *, Panel *panel)
static void copy_data(const ModifierData *md, ModifierData *target, const int flag)
static Mesh * modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
Definition MOD_array.cc:862
static void free_data(ModifierData *md)
Definition MOD_bevel.cc:272
static void init_data(ModifierData *md)
Definition MOD_ocean.cc:65
static void panel_register(ARegionType *region_type)
Definition MOD_ocean.cc:654
static void blend_read(BlendDataReader *, ModifierData *md)
Definition MOD_ocean.cc:671
static Mesh * modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
Definition MOD_ocean.cc:463
static void free_data(ModifierData *md)
Definition MOD_ocean.cc:85
ModifierTypeInfo modifierType_Ocean
Definition MOD_ocean.cc:678
static void required_data_mask(ModifierData *, CustomData_MeshMasks *)
Definition MOD_ocean.cc:136
static Mesh * doOcean(ModifierData *, const ModifierEvalContext *, Mesh *mesh)
Definition MOD_ocean.cc:457
static void panel_draw(const bContext *, Panel *panel)
Definition MOD_ocean.cc:468
static void copy_data(const ModifierData *md, ModifierData *target, const int flag)
Definition MOD_ocean.cc:100
PanelType * modifier_subpanel_register(ARegionType *region_type, const char *name, const char *label, PanelDrawFn draw_header, PanelDrawFn draw, PanelType *parent)
PanelType * modifier_panel_register(ARegionType *region_type, ModifierType type, PanelDrawFn draw)
PointerRNA * modifier_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ptr)
void modifier_error_message_draw(uiLayout *layout, PointerRNA *ptr)
@ UI_ITEM_R_SLIDER
#define UI_ITEM_NONE
ATTR_WARN_UNUSED_RESULT const BMVert * v
constexpr int64_t size() const
constexpr int64_t start() const
constexpr int64_t size() const
Definition BLI_span.hh:252
nullptr float
uint col
static char faces[256]
void mesh_calc_edges(Mesh &mesh, bool keep_existing_edges, bool select_new_edges)
void RNA_boolean_set(PointerRNA *ptr, const char *name, bool value)
float RNA_float_get(PointerRNA *ptr, const char *name)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
int RNA_enum_get(PointerRNA *ptr, const char *name)
unsigned char a
unsigned char b
unsigned char r
unsigned char g
ModifierApplyFlag flag
struct OceanCache * oceancache
float Eplus[3]
Definition BKE_ocean.h:24
float Eminus[3]
Definition BKE_ocean.h:23
float disp[3]
Definition BKE_ocean.h:16
float Jminus
Definition BKE_ocean.h:21
float foam
Definition BKE_ocean.h:18
struct uiLayout * layout
void label(blender::StringRef name, int icon)
uiLayout & column(bool align)
void active_set(bool active)
void separator(float factor=1.0f, LayoutSeparatorType type=LayoutSeparatorType::Auto)
uiLayout & row(bool align)
PointerRNA op(wmOperatorType *ot, std::optional< blender::StringRef > name, int icon, blender::wm::OpCallContext context, eUI_Item_Flag flag)
void use_property_split_set(bool value)
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)
i
Definition text_draw.cc:230
#define N_(msgid)
PointerRNA * ptr
Definition wm_files.cc:4238
uint8_t flag
Definition wm_window.cc:145