Blender V5.0
overlay_force_field.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2024 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#pragma once
10
11#include "BKE_anim_path.h"
12
13#include "BLI_math_rotation.h"
14
16
17#include "overlay_base.hh"
18
19namespace blender::draw::overlay {
20
26 using ForceFieldsInstanceBuf = ShapeInstanceBuf<ExtraInstanceData>;
27
28 private:
29 PassSimple ps_ = {"ForceFields"};
30
31 struct CallBuffers {
32 const SelectionType selection_type_;
33
34 ForceFieldsInstanceBuf field_force_buf = {selection_type_, "field_force_buf"};
35 ForceFieldsInstanceBuf field_wind_buf = {selection_type_, "field_wind_buf"};
36 ForceFieldsInstanceBuf field_vortex_buf = {selection_type_, "field_vortex_buf"};
37 ForceFieldsInstanceBuf field_curve_buf = {selection_type_, "field_curve_buf"};
38 ForceFieldsInstanceBuf field_sphere_limit_buf = {selection_type_, "field_sphere_limit_buf"};
39 ForceFieldsInstanceBuf field_tube_limit_buf = {selection_type_, "field_tube_limit_buf"};
40 ForceFieldsInstanceBuf field_cone_limit_buf = {selection_type_, "field_cone_limit_buf"};
41 } call_buffers_;
42
43 public:
44 ForceFields(const SelectionType selection_type) : call_buffers_{selection_type} {}
45
46 void begin_sync(Resources & /*res*/, const State & /*state*/) final
47 {
48 call_buffers_.field_force_buf.clear();
49 call_buffers_.field_wind_buf.clear();
50 call_buffers_.field_vortex_buf.clear();
51 call_buffers_.field_curve_buf.clear();
52 call_buffers_.field_sphere_limit_buf.clear();
53 call_buffers_.field_tube_limit_buf.clear();
54 call_buffers_.field_cone_limit_buf.clear();
55 }
56
57 void object_sync(Manager & /*manager*/,
58 const ObjectRef &ob_ref,
59 Resources &res,
60 const State &state) final
61 {
62 if (!ob_ref.object->pd || !ob_ref.object->pd->forcefield) {
63 return;
64 }
65 const select::ID select_id = res.select_id(ob_ref);
66 const Object *ob = ob_ref.object;
67 PartDeflect *pd = ob->pd;
69 nullptr;
70
72 ob->object_to_world(), res.object_background_blend_color(ob_ref, state), 1.0f);
73 float4x4 &matrix = data.object_to_world;
74 float &size_x = matrix[0][3];
75 float &size_y = matrix[1][3];
76 float &size_z = matrix[2][3];
77
78 size_x = size_y = size_z = ob->empty_drawsize;
79
80 switch (pd->forcefield) {
81 case PFIELD_FORCE:
82 call_buffers_.field_force_buf.append(data, select_id);
83 break;
84 case PFIELD_WIND:
85 size_z = pd->f_strength;
86 call_buffers_.field_wind_buf.append(data, select_id);
87 break;
88 case PFIELD_VORTEX:
89 size_y = (pd->f_strength < 0.0f) ? -size_y : size_y;
90 call_buffers_.field_vortex_buf.append(data, select_id);
91 break;
92 case PFIELD_GUIDE:
93 if (cu && (cu->flag & CU_PATH) && ob->runtime->curve_cache->anim_path_accum_length) {
94 size_x = size_y = size_z = pd->f_strength;
95 float4 pos;
96 BKE_where_on_path(ob, 0.0f, pos, nullptr, nullptr, nullptr, nullptr);
97 matrix.location() = ob->object_to_world().location();
98 matrix = math::translate(matrix, pos.xyz());
99 call_buffers_.field_curve_buf.append(data, select_id);
100
101 BKE_where_on_path(ob, 1.0f, pos, nullptr, nullptr, nullptr, nullptr);
102 matrix.location() = ob->object_to_world().location();
103 matrix = math::translate(matrix, pos.xyz());
104 call_buffers_.field_sphere_limit_buf.append(data, select_id);
105 /* Restore */
106 matrix.location() = ob->object_to_world().location();
107 }
108 break;
109 }
110
111 if (pd->falloff == PFIELD_FALL_TUBE) {
112 if (pd->flag & (PFIELD_USEMAX | PFIELD_USEMAXR)) {
113 size_z = (pd->flag & PFIELD_USEMAX) ? pd->maxdist : 0.0f;
114 size_x = (pd->flag & PFIELD_USEMAXR) ? pd->maxrad : 1.0f;
115 size_y = size_x;
116 call_buffers_.field_tube_limit_buf.append(data, select_id);
117 }
118 if (pd->flag & (PFIELD_USEMIN | PFIELD_USEMINR)) {
119 size_z = (pd->flag & PFIELD_USEMIN) ? pd->mindist : 0.0f;
120 size_x = (pd->flag & PFIELD_USEMINR) ? pd->minrad : 1.0f;
121 size_y = size_x;
122 call_buffers_.field_tube_limit_buf.append(data, select_id);
123 }
124 }
125 else if (pd->falloff == PFIELD_FALL_CONE) {
126 if (pd->flag & (PFIELD_USEMAX | PFIELD_USEMAXR)) {
127 float radius = DEG2RADF((pd->flag & PFIELD_USEMAXR) ? pd->maxrad : 1.0f);
128 float distance = (pd->flag & PFIELD_USEMAX) ? pd->maxdist : 0.0f;
129 size_x = distance * sinf(radius);
130 size_z = distance * cosf(radius);
131 size_y = size_x;
132 call_buffers_.field_cone_limit_buf.append(data, select_id);
133 }
134 if (pd->flag & (PFIELD_USEMIN | PFIELD_USEMINR)) {
135 float radius = DEG2RADF((pd->flag & PFIELD_USEMINR) ? pd->minrad : 1.0f);
136 float distance = (pd->flag & PFIELD_USEMIN) ? pd->mindist : 0.0f;
137 size_x = distance * sinf(radius);
138 size_z = distance * cosf(radius);
139 size_y = size_x;
140 call_buffers_.field_cone_limit_buf.append(data, select_id);
141 }
142 }
143 else if (pd->falloff == PFIELD_FALL_SPHERE) {
144 if (pd->flag & PFIELD_USEMAX) {
145 size_x = size_y = size_z = pd->maxdist;
146 call_buffers_.field_sphere_limit_buf.append(data, select_id);
147 }
148 if (pd->flag & PFIELD_USEMIN) {
149 size_x = size_y = size_z = pd->mindist;
150 call_buffers_.field_sphere_limit_buf.append(data, select_id);
151 }
152 }
153 }
154
155 void end_sync(Resources &res, const State &state) final
156 {
157 ps_.init();
158 res.select_bind(ps_);
160 state.clipping_plane_count);
161 ps_.shader_set(res.shaders->extra_shape.get());
162 ps_.bind_ubo(OVERLAY_GLOBALS_SLOT, &res.globals_buf);
163 ps_.bind_ubo(DRW_CLIPPING_UBO_SLOT, &res.clip_planes_buf);
164
165 call_buffers_.field_force_buf.end_sync(ps_, res.shapes.field_force.get());
166 call_buffers_.field_wind_buf.end_sync(ps_, res.shapes.field_wind.get());
167 call_buffers_.field_vortex_buf.end_sync(ps_, res.shapes.field_vortex.get());
168 call_buffers_.field_curve_buf.end_sync(ps_, res.shapes.field_curve.get());
169 call_buffers_.field_sphere_limit_buf.end_sync(ps_, res.shapes.field_sphere_limit.get());
170 call_buffers_.field_tube_limit_buf.end_sync(ps_, res.shapes.field_tube_limit.get());
171 call_buffers_.field_cone_limit_buf.end_sync(ps_, res.shapes.field_cone_limit.get());
172 }
173
174 void draw_line(Framebuffer &framebuffer, Manager &manager, View &view) final
175 {
176 GPU_framebuffer_bind(framebuffer);
177 manager.submit(ps_, view);
178 }
179};
180
181} // namespace blender::draw::overlay
bool BKE_where_on_path(const struct Object *ob, float ctime, float r_vec[4], float r_dir[3], float r_quat[4], float *r_radius, float *r_weight)
#define DEG2RADF(_deg)
@ CU_PATH
@ PFIELD_FALL_SPHERE
@ OB_CURVES_LEGACY
T & DRW_object_get_data_for_drawing(const Object &object)
static AppView * view
void GPU_framebuffer_bind(blender::gpu::FrameBuffer *fb)
BMesh const char void * data
void object_sync(Manager &, const ObjectRef &ob_ref, Resources &res, const State &state) final
void end_sync(Resources &res, const State &state) final
void draw_line(Framebuffer &framebuffer, Manager &manager, View &view) final
void begin_sync(Resources &, const State &) final
ForceFields(const SelectionType selection_type)
#define DRW_CLIPPING_UBO_SLOT
#define OVERLAY_GLOBALS_SLOT
@ DRW_STATE_WRITE_DEPTH
Definition draw_state.hh:29
@ DRW_STATE_WRITE_COLOR
Definition draw_state.hh:30
@ DRW_STATE_DEPTH_LESS_EQUAL
Definition draw_state.hh:38
uint pos
static ulong state[N]
select::SelectionType SelectionType
detail::Pass< command::DrawCommandBuf > PassSimple
T distance(const T &a, const T &b)
MatBase< T, NumCol, NumRow > translate(const MatBase< T, NumCol, NumRow > &mat, const VectorT &translation)
MatBase< float, 4, 4 > float4x4
VecBase< float, 4 > float4
#define sinf
#define cosf
ObjectRuntimeHandle * runtime
struct PartDeflect * pd
float empty_drawsize