Blender V4.3
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
9#include "BLI_utildefines.h"
10
11#include "BLI_task.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
29#include "UI_interface.hh"
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 {
143 blender::MutableSpan<int> face_offsets;
144 blender::MutableSpan<int> corner_verts;
145 float (*mloopuvs)[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->mloopuvs[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);
247 BKE_mesh_copy_parameters_for_eval(result, mesh_orig);
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
263 blender::bke::mesh_calc_edges(*result, false, false);
264
265 /* add uvs */
266 if (CustomData_number_of_layers(&result->corner_data, CD_PROP_FLOAT2) < MAX_MTFACE) {
267 gogd.mloopuvs = 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.mloopuvs) { /* 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 uiLayoutSetPropSep(layout, true);
478
479 col = uiLayoutColumn(layout, false);
480 uiItemR(col, ptr, "geometry_mode", UI_ITEM_NONE, nullptr, ICON_NONE);
481 if (RNA_enum_get(ptr, "geometry_mode") == MOD_OCEAN_GEOM_GENERATE) {
482 sub = uiLayoutColumn(col, true);
483 uiItemR(sub, ptr, "repeat_x", UI_ITEM_NONE, IFACE_("Repeat X"), ICON_NONE);
484 uiItemR(sub, ptr, "repeat_y", UI_ITEM_NONE, IFACE_("Y"), ICON_NONE);
485 }
486
487 sub = uiLayoutColumn(col, true);
488 uiItemR(sub, ptr, "viewport_resolution", UI_ITEM_NONE, IFACE_("Resolution Viewport"), ICON_NONE);
489 uiItemR(sub, ptr, "resolution", UI_ITEM_NONE, IFACE_("Render"), ICON_NONE);
490
491 uiItemR(col, ptr, "time", UI_ITEM_NONE, nullptr, ICON_NONE);
492
493 uiItemR(col, ptr, "depth", UI_ITEM_NONE, nullptr, ICON_NONE);
494 uiItemR(col, ptr, "size", UI_ITEM_NONE, nullptr, ICON_NONE);
495 uiItemR(col, ptr, "spatial_size", UI_ITEM_NONE, nullptr, ICON_NONE);
496
497 uiItemR(col, ptr, "random_seed", UI_ITEM_NONE, nullptr, ICON_NONE);
498
499 uiItemR(col, ptr, "use_normals", UI_ITEM_NONE, nullptr, ICON_NONE);
500
501 modifier_panel_end(layout, ptr);
502
503#else /* WITH_OCEANSIM */
504 uiItemL(layout, 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 uiLayoutSetPropSep(layout, true);
517
518 col = uiLayoutColumn(layout, false);
519 uiItemR(col, ptr, "wave_scale", UI_ITEM_NONE, IFACE_("Scale"), ICON_NONE);
520 uiItemR(col, ptr, "wave_scale_min", UI_ITEM_NONE, nullptr, ICON_NONE);
521 uiItemR(col, ptr, "choppiness", UI_ITEM_NONE, nullptr, ICON_NONE);
522 uiItemR(col, ptr, "wind_velocity", UI_ITEM_NONE, nullptr, ICON_NONE);
523
524 uiItemS(layout);
525
526 col = uiLayoutColumn(layout, false);
527 uiItemR(col, ptr, "wave_alignment", UI_ITEM_R_SLIDER, IFACE_("Alignment"), ICON_NONE);
528 sub = uiLayoutColumn(col, false);
529 uiLayoutSetActive(sub, RNA_float_get(ptr, "wave_alignment") > 0.0f);
530 uiItemR(sub, ptr, "wave_direction", UI_ITEM_NONE, IFACE_("Direction"), ICON_NONE);
531 uiItemR(sub, ptr, "damping", UI_ITEM_NONE, nullptr, ICON_NONE);
532}
533
534static void foam_panel_draw_header(const bContext * /*C*/, Panel *panel)
535{
536 uiLayout *layout = panel->layout;
537
539
540 uiItemR(layout, 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 uiLayoutSetPropSep(layout, true);
553
554 col = uiLayoutColumn(layout, false);
555 uiLayoutSetActive(col, use_foam);
556 uiItemR(col, ptr, "foam_layer_name", UI_ITEM_NONE, IFACE_("Data Layer"), ICON_NONE);
557 uiItemR(col, 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 = uiLayoutRow(layout, false);
570 uiLayoutSetActive(row, use_foam);
571 uiItemR(row,
572 ptr,
573 "use_spray",
576 ICON_NONE);
577}
578
579static void spray_panel_draw(const bContext * /*C*/, Panel *panel)
580{
581 uiLayout *col;
582 uiLayout *layout = panel->layout;
583
585
586 bool use_foam = RNA_boolean_get(ptr, "use_foam");
587 bool use_spray = RNA_boolean_get(ptr, "use_spray");
588
589 uiLayoutSetPropSep(layout, true);
590
591 col = uiLayoutColumn(layout, false);
592 uiLayoutSetActive(col, use_foam && use_spray);
593 uiItemR(col, ptr, "spray_layer_name", UI_ITEM_NONE, IFACE_("Data Layer"), ICON_NONE);
594 uiItemR(col, ptr, "invert_spray", UI_ITEM_NONE, IFACE_("Invert"), ICON_NONE);
595}
596
597static void spectrum_panel_draw(const bContext * /*C*/, Panel *panel)
598{
599 uiLayout *col;
600 uiLayout *layout = panel->layout;
601
603
604 int spectrum = RNA_enum_get(ptr, "spectrum");
605
606 uiLayoutSetPropSep(layout, true);
607
608 col = uiLayoutColumn(layout, false);
609 uiItemR(col, ptr, "spectrum", UI_ITEM_NONE, nullptr, ICON_NONE);
611 uiItemR(col, ptr, "sharpen_peak_jonswap", UI_ITEM_R_SLIDER, nullptr, ICON_NONE);
612 uiItemR(col, ptr, "fetch_jonswap", UI_ITEM_NONE, nullptr, ICON_NONE);
613 }
614}
615
616static void bake_panel_draw(const bContext * /*C*/, Panel *panel)
617{
618 uiLayout *col;
619 uiLayout *layout = panel->layout;
620
622
623 uiLayoutSetPropSep(layout, true);
624
625 bool is_cached = RNA_boolean_get(ptr, "is_cached");
626 bool use_foam = RNA_boolean_get(ptr, "use_foam");
627
628 if (is_cached) {
629 PointerRNA op_ptr;
630 uiItemFullO(layout,
631 "OBJECT_OT_ocean_bake",
632 IFACE_("Delete Bake"),
633 ICON_NONE,
634 nullptr,
637 &op_ptr);
638 RNA_boolean_set(&op_ptr, "free", true);
639 }
640 else {
641 PointerRNA op_ptr;
642 uiItemFullO(layout,
643 "OBJECT_OT_ocean_bake",
644 IFACE_("Bake"),
645 ICON_NONE,
646 nullptr,
649 &op_ptr);
650 RNA_boolean_set(&op_ptr, "free", false);
651 }
652
653 uiItemR(layout, ptr, "filepath", UI_ITEM_NONE, nullptr, ICON_NONE);
654
655 col = uiLayoutColumn(layout, true);
656 uiLayoutSetEnabled(col, !is_cached);
657 uiItemR(col, ptr, "frame_start", UI_ITEM_NONE, IFACE_("Frame Start"), ICON_NONE);
658 uiItemR(col, ptr, "frame_end", UI_ITEM_NONE, IFACE_("End"), ICON_NONE);
659
660 col = uiLayoutColumn(layout, false);
661 uiLayoutSetActive(col, use_foam);
662 uiItemR(col, ptr, "bake_foam_fade", UI_ITEM_NONE, nullptr, ICON_NONE);
663}
664#endif /* WITH_OCEANSIM */
665
666static void panel_register(ARegionType *region_type)
667{
669#ifdef WITH_OCEANSIM
670 modifier_subpanel_register(region_type, "waves", "Waves", nullptr, waves_panel_draw, panel_type);
672 region_type, "foam", "", foam_panel_draw_header, foam_panel_draw, panel_type);
674 region_type, "spray", "", spray_panel_draw_header, spray_panel_draw, foam_panel);
676 region_type, "spectrum", "Spectrum", nullptr, spectrum_panel_draw, panel_type);
677 modifier_subpanel_register(region_type, "bake", "Bake", nullptr, bake_panel_draw, panel_type);
678#else
679 UNUSED_VARS(panel_type);
680#endif /* WITH_OCEANSIM */
681}
682
683static void blend_read(BlendDataReader * /*reader*/, ModifierData *md)
684{
686 omd->oceancache = nullptr;
687 omd->ocean = nullptr;
688}
689
691 /*idname*/ "Ocean",
692 /*name*/ N_("Ocean"),
693 /*struct_name*/ "OceanModifierData",
694 /*struct_size*/ sizeof(OceanModifierData),
695 /*srna*/ &RNA_OceanModifier,
699 /*icon*/ ICON_MOD_OCEAN,
700
701 /*copy_data*/ copy_data,
702 /*deform_verts*/ nullptr,
703
704 /*deform_matrices*/ nullptr,
705 /*deform_verts_EM*/ nullptr,
706 /*deform_matrices_EM*/ nullptr,
707 /*modify_mesh*/ modify_mesh,
708 /*modify_geometry_set*/ nullptr,
709
710 /*init_data*/ init_data,
711 /*required_data_mask*/ required_data_mask,
712 /*free_data*/ free_data,
713 /*is_disabled*/ nullptr,
714 /*update_depsgraph*/ nullptr,
715 /*depends_on_time*/ nullptr,
716 /*depends_on_normals*/ nullptr,
717 /*foreach_ID_link*/ nullptr,
718 /*foreach_tex_link*/ nullptr,
719 /*free_runtime_data*/ nullptr,
720 /*panel_register*/ panel_register,
721 /*blend_write*/ nullptr,
722 /*blend_read*/ blend_read,
723 /*foreach_cache*/ nullptr,
724};
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)
@ LIB_ID_COPY_LOCALIZE
ID * BKE_id_copy_ex(Main *bmain, const ID *id, ID **new_id_p, int flag)
Definition lib_id.cc:760
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:1577
void BKE_ocean_cache_eval_uv(struct OceanCache *och, struct OceanResult *ocr, int f, float u, float v)
Definition ocean.cc:1631
void BKE_ocean_simulate(struct Ocean *o, float t, float scale, float chop_amount)
Definition ocean.cc:1575
float BKE_ocean_jminus_to_foam(float jminus, float coverage)
Definition ocean.cc:1559
bool BKE_ocean_ensure(struct OceanModifierData *omd, int resolution)
void BKE_ocean_free_cache(struct OceanCache *och)
Definition ocean.cc:1622
void BKE_ocean_simulate_cache(struct OceanCache *och, int frame)
Definition ocean.cc:1656
void BKE_ocean_eval_uv(struct Ocean *oc, struct OceanResult *ocr, float u, float v)
Definition ocean.cc:1564
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:1612
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:1641
#define BLI_assert(a)
Definition BLI_assert.h:50
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:230
#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_GEOM_GENERATE
@ MOD_OCEAN_GEOM_DISPLACE
@ MOD_OCEAN_GENERATE_FOAM
@ MOD_OCEAN_INVERT_SPRAY
@ MOD_OCEAN_GENERATE_SPRAY
@ eModifierType_Ocean
struct OceanModifierData OceanModifierData
@ 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)
Definition MOD_ocean.cc:65
static void panel_register(ARegionType *region_type)
Definition MOD_ocean.cc:666
static void blend_read(BlendDataReader *, ModifierData *md)
Definition MOD_ocean.cc:683
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:690
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)
void modifier_panel_end(uiLayout *layout, PointerRNA *ptr)
PanelType * modifier_panel_register(ARegionType *region_type, ModifierType type, PanelDrawFn draw)
PointerRNA * modifier_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ptr)
void uiLayoutSetActive(uiLayout *layout, bool active)
void uiLayoutSetEnabled(uiLayout *layout, bool enabled)
void uiItemL(uiLayout *layout, const char *name, int icon)
void uiItemFullO(uiLayout *layout, const char *opname, const char *name, int icon, IDProperty *properties, wmOperatorCallContext context, eUI_Item_Flag flag, PointerRNA *r_opptr)
uiLayout * uiLayoutRow(uiLayout *layout, bool align)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
void uiItemS(uiLayout *layout)
#define UI_ITEM_NONE
uiLayout * uiLayoutColumn(uiLayout *layout, bool align)
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
@ UI_ITEM_R_SLIDER
@ WM_OP_INVOKE_DEFAULT
Definition WM_types.hh:218
ATTR_WARN_UNUSED_RESULT const BMVert * v
constexpr int64_t size() const
Definition BLI_span.hh:253
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
uint col
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:28
float Eminus[3]
Definition BKE_ocean.h:27
float disp[3]
Definition BKE_ocean.h:20
float Jminus
Definition BKE_ocean.h:25
float foam
Definition BKE_ocean.h:22
struct uiLayout * layout
#define N_(msgid)
PointerRNA * ptr
Definition wm_files.cc:4126
uint8_t flag
Definition wm_window.cc:138