Blender V4.3
overlay_next_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
9#pragma once
10
11#include "BKE_anim_path.h"
12
13#include "BLI_math_rotation.h"
14
16
18
19namespace blender::draw::overlay {
20
23
24 private:
25 PassSimple ps_ = {"ForceFields"};
26
27 struct CallBuffers {
28 const SelectionType selection_type_;
29
30 ForceFieldsInstanceBuf field_force_buf = {selection_type_, "field_force_buf"};
31 ForceFieldsInstanceBuf field_wind_buf = {selection_type_, "field_wind_buf"};
32 ForceFieldsInstanceBuf field_vortex_buf = {selection_type_, "field_vortex_buf"};
33 ForceFieldsInstanceBuf field_curve_buf = {selection_type_, "field_curve_buf"};
34 ForceFieldsInstanceBuf field_sphere_limit_buf = {selection_type_, "field_sphere_limit_buf"};
35 ForceFieldsInstanceBuf field_tube_limit_buf = {selection_type_, "field_tube_limit_buf"};
36 ForceFieldsInstanceBuf field_cone_limit_buf = {selection_type_, "field_cone_limit_buf"};
37 } call_buffers_;
38
39 public:
40 ForceFields(const SelectionType selection_type) : call_buffers_{selection_type} {}
41
43 {
44 call_buffers_.field_force_buf.clear();
45 call_buffers_.field_wind_buf.clear();
46 call_buffers_.field_vortex_buf.clear();
47 call_buffers_.field_curve_buf.clear();
48 call_buffers_.field_sphere_limit_buf.clear();
49 call_buffers_.field_tube_limit_buf.clear();
50 call_buffers_.field_cone_limit_buf.clear();
51 }
52
53 void object_sync(const ObjectRef &ob_ref, Resources &res, const State &state)
54 {
55 if (!ob_ref.object->pd || !ob_ref.object->pd->forcefield) {
56 return;
57 }
58 const select::ID select_id = res.select_id(ob_ref);
59 const Object *ob = ob_ref.object;
60 PartDeflect *pd = ob->pd;
61 Curve *cu = (ob->type == OB_CURVES_LEGACY) ? static_cast<Curve *>(ob->data) : nullptr;
62
64 ob->object_to_world(), res.object_background_blend_color(ob_ref, state), 1.0f);
65 float4x4 &matrix = data.object_to_world_;
66 float &size_x = matrix[0][3];
67 float &size_y = matrix[1][3];
68 float &size_z = matrix[2][3];
69
70 size_x = size_y = size_z = ob->empty_drawsize;
71
72 switch (pd->forcefield) {
73 case PFIELD_FORCE:
74 call_buffers_.field_force_buf.append(data, select_id);
75 break;
76 case PFIELD_WIND:
77 size_z = pd->f_strength;
78 call_buffers_.field_wind_buf.append(data, select_id);
79 break;
80 case PFIELD_VORTEX:
81 size_y = (pd->f_strength < 0.0f) ? -size_y : size_y;
82 call_buffers_.field_vortex_buf.append(data, select_id);
83 break;
84 case PFIELD_GUIDE:
85 if (cu && (cu->flag & CU_PATH) && ob->runtime->curve_cache->anim_path_accum_length) {
86 size_x = size_y = size_z = pd->f_strength;
87 float4 pos;
88 BKE_where_on_path(ob, 0.0f, pos, nullptr, nullptr, nullptr, nullptr);
89 matrix.location() = ob->object_to_world().location();
90 matrix = math::translate(matrix, pos.xyz());
91 call_buffers_.field_curve_buf.append(data, select_id);
92
93 BKE_where_on_path(ob, 1.0f, pos, nullptr, nullptr, nullptr, nullptr);
94 matrix.location() = ob->object_to_world().location();
95 matrix = math::translate(matrix, pos.xyz());
96 call_buffers_.field_sphere_limit_buf.append(data, select_id);
97 /* Restore */
98 matrix.location() = ob->object_to_world().location();
99 }
100 break;
101 }
102
103 if (pd->falloff == PFIELD_FALL_TUBE) {
104 if (pd->flag & (PFIELD_USEMAX | PFIELD_USEMAXR)) {
105 size_z = (pd->flag & PFIELD_USEMAX) ? pd->maxdist : 0.0f;
106 size_x = (pd->flag & PFIELD_USEMAXR) ? pd->maxrad : 1.0f;
107 size_y = size_x;
108 call_buffers_.field_tube_limit_buf.append(data, select_id);
109 }
110 if (pd->flag & (PFIELD_USEMIN | PFIELD_USEMINR)) {
111 size_z = (pd->flag & PFIELD_USEMIN) ? pd->mindist : 0.0f;
112 size_x = (pd->flag & PFIELD_USEMINR) ? pd->minrad : 1.0f;
113 size_y = size_x;
114 call_buffers_.field_tube_limit_buf.append(data, select_id);
115 }
116 }
117 else if (pd->falloff == PFIELD_FALL_CONE) {
118 if (pd->flag & (PFIELD_USEMAX | PFIELD_USEMAXR)) {
119 float radius = DEG2RADF((pd->flag & PFIELD_USEMAXR) ? pd->maxrad : 1.0f);
120 float distance = (pd->flag & PFIELD_USEMAX) ? pd->maxdist : 0.0f;
121 size_x = distance * sinf(radius);
122 size_z = distance * cosf(radius);
123 size_y = size_x;
124 call_buffers_.field_cone_limit_buf.append(data, select_id);
125 }
126 if (pd->flag & (PFIELD_USEMIN | PFIELD_USEMINR)) {
127 float radius = DEG2RADF((pd->flag & PFIELD_USEMINR) ? pd->minrad : 1.0f);
128 float distance = (pd->flag & PFIELD_USEMIN) ? pd->mindist : 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 }
135 else if (pd->falloff == PFIELD_FALL_SPHERE) {
136 if (pd->flag & PFIELD_USEMAX) {
137 size_x = size_y = size_z = pd->maxdist;
138 call_buffers_.field_sphere_limit_buf.append(data, select_id);
139 }
140 if (pd->flag & PFIELD_USEMIN) {
141 size_x = size_y = size_z = pd->mindist;
142 call_buffers_.field_sphere_limit_buf.append(data, select_id);
143 }
144 }
145 }
146
147 void end_sync(Resources &res, ShapeCache &shapes, const State &state)
148 {
149 ps_.init();
150 res.select_bind(ps_);
152 state.clipping_plane_count);
153 ps_.shader_set(res.shaders.extra_shape.get());
154 ps_.bind_ubo("globalsBlock", &res.globals_buf);
155
156 call_buffers_.field_force_buf.end_sync(ps_, shapes.field_force.get());
157 call_buffers_.field_wind_buf.end_sync(ps_, shapes.field_wind.get());
158 call_buffers_.field_vortex_buf.end_sync(ps_, shapes.field_vortex.get());
159 call_buffers_.field_curve_buf.end_sync(ps_, shapes.field_curve.get());
160 call_buffers_.field_sphere_limit_buf.end_sync(ps_, shapes.field_sphere_limit.get());
161 call_buffers_.field_tube_limit_buf.end_sync(ps_, shapes.field_tube_limit.get());
162 call_buffers_.field_cone_limit_buf.end_sync(ps_, shapes.field_cone_limit.get());
163 }
164
165 void draw(Framebuffer &framebuffer, Manager &manager, View &view)
166 {
167 GPU_framebuffer_bind(framebuffer);
168 manager.submit(ps_, view);
169 }
170};
171
172} // 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
void GPU_framebuffer_bind(GPUFrameBuffer *framebuffer)
void submit(PassSimple &pass, View &view)
void state_set(DRWState state, int clip_plane_count=0)
Definition draw_pass.hh:954
void bind_ubo(const char *name, GPUUniformBuf *buffer)
void shader_set(GPUShader *shader)
Definition draw_pass.hh:971
void draw(Framebuffer &framebuffer, Manager &manager, View &view)
ForceFields(const SelectionType selection_type)
void end_sync(Resources &res, ShapeCache &shapes, const State &state)
void object_sync(const ObjectRef &ob_ref, Resources &res, const State &state)
#define sinf(x)
#define cosf(x)
@ 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
static ulong state[N]
MatBase< T, NumCol, NumRow > translate(const MatBase< T, NumCol, NumRow > &mat, const VectorT &translation)
ObjectRuntimeHandle * runtime
struct PartDeflect * pd
float empty_drawsize
float4 object_background_blend_color(const ObjectRef &ob_ref, const State &state) const
void end_sync(PassSimple::Sub &pass, gpu::Batch *shape)
void append(const InstanceDataT &data, select::ID select_id)
void select_bind(PassSimple &pass)
const ID select_id(const ObjectRef &ob_ref, uint sub_object_id=0)