Files
test2/source/blender/draw/engines/overlay/overlay_force_field.hh
Clément Foucault 5bd572d4fd Cleanup: Overlay: Remove _next in overlay filename
These are not needed anymore since the legacy codebase
is gone.
2025-04-16 20:51:24 +02:00

182 lines
6.8 KiB
C++

/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup overlay
*/
#pragma once
#include "BKE_anim_path.h"
#include "BLI_math_rotation.h"
#include "DNA_object_force_types.h"
#include "overlay_base.hh"
namespace blender::draw::overlay {
/**
* Draw force fields.
* Controlled by (Physics > Force Field)
*/
class ForceFields : Overlay {
using ForceFieldsInstanceBuf = ShapeInstanceBuf<ExtraInstanceData>;
private:
PassSimple ps_ = {"ForceFields"};
struct CallBuffers {
const SelectionType selection_type_;
ForceFieldsInstanceBuf field_force_buf = {selection_type_, "field_force_buf"};
ForceFieldsInstanceBuf field_wind_buf = {selection_type_, "field_wind_buf"};
ForceFieldsInstanceBuf field_vortex_buf = {selection_type_, "field_vortex_buf"};
ForceFieldsInstanceBuf field_curve_buf = {selection_type_, "field_curve_buf"};
ForceFieldsInstanceBuf field_sphere_limit_buf = {selection_type_, "field_sphere_limit_buf"};
ForceFieldsInstanceBuf field_tube_limit_buf = {selection_type_, "field_tube_limit_buf"};
ForceFieldsInstanceBuf field_cone_limit_buf = {selection_type_, "field_cone_limit_buf"};
} call_buffers_;
public:
ForceFields(const SelectionType selection_type) : call_buffers_{selection_type} {}
void begin_sync(Resources & /*res*/, const State & /*state*/) final
{
call_buffers_.field_force_buf.clear();
call_buffers_.field_wind_buf.clear();
call_buffers_.field_vortex_buf.clear();
call_buffers_.field_curve_buf.clear();
call_buffers_.field_sphere_limit_buf.clear();
call_buffers_.field_tube_limit_buf.clear();
call_buffers_.field_cone_limit_buf.clear();
}
void object_sync(Manager & /*manager*/,
const ObjectRef &ob_ref,
Resources &res,
const State &state) final
{
if (!ob_ref.object->pd || !ob_ref.object->pd->forcefield) {
return;
}
const select::ID select_id = res.select_id(ob_ref);
const Object *ob = ob_ref.object;
PartDeflect *pd = ob->pd;
Curve *cu = (ob->type == OB_CURVES_LEGACY) ? &DRW_object_get_data_for_drawing<Curve>(*ob) :
nullptr;
ExtraInstanceData data(
ob->object_to_world(), res.object_background_blend_color(ob_ref, state), 1.0f);
float4x4 &matrix = data.object_to_world;
float &size_x = matrix[0][3];
float &size_y = matrix[1][3];
float &size_z = matrix[2][3];
size_x = size_y = size_z = ob->empty_drawsize;
switch (pd->forcefield) {
case PFIELD_FORCE:
call_buffers_.field_force_buf.append(data, select_id);
break;
case PFIELD_WIND:
size_z = pd->f_strength;
call_buffers_.field_wind_buf.append(data, select_id);
break;
case PFIELD_VORTEX:
size_y = (pd->f_strength < 0.0f) ? -size_y : size_y;
call_buffers_.field_vortex_buf.append(data, select_id);
break;
case PFIELD_GUIDE:
if (cu && (cu->flag & CU_PATH) && ob->runtime->curve_cache->anim_path_accum_length) {
size_x = size_y = size_z = pd->f_strength;
float4 pos;
BKE_where_on_path(ob, 0.0f, pos, nullptr, nullptr, nullptr, nullptr);
matrix.location() = ob->object_to_world().location();
matrix = math::translate(matrix, pos.xyz());
call_buffers_.field_curve_buf.append(data, select_id);
BKE_where_on_path(ob, 1.0f, pos, nullptr, nullptr, nullptr, nullptr);
matrix.location() = ob->object_to_world().location();
matrix = math::translate(matrix, pos.xyz());
call_buffers_.field_sphere_limit_buf.append(data, select_id);
/* Restore */
matrix.location() = ob->object_to_world().location();
}
break;
}
if (pd->falloff == PFIELD_FALL_TUBE) {
if (pd->flag & (PFIELD_USEMAX | PFIELD_USEMAXR)) {
size_z = (pd->flag & PFIELD_USEMAX) ? pd->maxdist : 0.0f;
size_x = (pd->flag & PFIELD_USEMAXR) ? pd->maxrad : 1.0f;
size_y = size_x;
call_buffers_.field_tube_limit_buf.append(data, select_id);
}
if (pd->flag & (PFIELD_USEMIN | PFIELD_USEMINR)) {
size_z = (pd->flag & PFIELD_USEMIN) ? pd->mindist : 0.0f;
size_x = (pd->flag & PFIELD_USEMINR) ? pd->minrad : 1.0f;
size_y = size_x;
call_buffers_.field_tube_limit_buf.append(data, select_id);
}
}
else if (pd->falloff == PFIELD_FALL_CONE) {
if (pd->flag & (PFIELD_USEMAX | PFIELD_USEMAXR)) {
float radius = DEG2RADF((pd->flag & PFIELD_USEMAXR) ? pd->maxrad : 1.0f);
float distance = (pd->flag & PFIELD_USEMAX) ? pd->maxdist : 0.0f;
size_x = distance * sinf(radius);
size_z = distance * cosf(radius);
size_y = size_x;
call_buffers_.field_cone_limit_buf.append(data, select_id);
}
if (pd->flag & (PFIELD_USEMIN | PFIELD_USEMINR)) {
float radius = DEG2RADF((pd->flag & PFIELD_USEMINR) ? pd->minrad : 1.0f);
float distance = (pd->flag & PFIELD_USEMIN) ? pd->mindist : 0.0f;
size_x = distance * sinf(radius);
size_z = distance * cosf(radius);
size_y = size_x;
call_buffers_.field_cone_limit_buf.append(data, select_id);
}
}
else if (pd->falloff == PFIELD_FALL_SPHERE) {
if (pd->flag & PFIELD_USEMAX) {
size_x = size_y = size_z = pd->maxdist;
call_buffers_.field_sphere_limit_buf.append(data, select_id);
}
if (pd->flag & PFIELD_USEMIN) {
size_x = size_y = size_z = pd->mindist;
call_buffers_.field_sphere_limit_buf.append(data, select_id);
}
}
}
void end_sync(Resources &res, const State &state) final
{
ps_.init();
res.select_bind(ps_);
ps_.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL,
state.clipping_plane_count);
ps_.shader_set(res.shaders->extra_shape.get());
ps_.bind_ubo(OVERLAY_GLOBALS_SLOT, &res.globals_buf);
ps_.bind_ubo(DRW_CLIPPING_UBO_SLOT, &res.clip_planes_buf);
call_buffers_.field_force_buf.end_sync(ps_, res.shapes.field_force.get());
call_buffers_.field_wind_buf.end_sync(ps_, res.shapes.field_wind.get());
call_buffers_.field_vortex_buf.end_sync(ps_, res.shapes.field_vortex.get());
call_buffers_.field_curve_buf.end_sync(ps_, res.shapes.field_curve.get());
call_buffers_.field_sphere_limit_buf.end_sync(ps_, res.shapes.field_sphere_limit.get());
call_buffers_.field_tube_limit_buf.end_sync(ps_, res.shapes.field_tube_limit.get());
call_buffers_.field_cone_limit_buf.end_sync(ps_, res.shapes.field_cone_limit.get());
}
void draw_line(Framebuffer &framebuffer, Manager &manager, View &view) final
{
GPU_framebuffer_bind(framebuffer);
manager.submit(ps_, view);
}
};
} // namespace blender::draw::overlay