Blender V4.3
overlay_next_bounds.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_mball.hh"
12
13#include "BLI_bounds_types.hh"
14#include "BLI_utildefines.h"
15
16#include "DNA_rigidbody_types.h"
17
19
20namespace blender::draw::overlay {
21class Bounds {
23
24 private:
25 PassSimple ps_ = {"Bounds"};
26
27 struct CallBuffers {
28 const SelectionType selection_type_;
29
30 BoundsInstanceBuf box = {selection_type_, "bound_box"};
31 BoundsInstanceBuf sphere = {selection_type_, "bound_sphere"};
32 BoundsInstanceBuf cylinder = {selection_type_, "bound_cylinder"};
33 BoundsInstanceBuf cone = {selection_type_, "bound_cone"};
34 BoundsInstanceBuf capsule_body = {selection_type_, "bound_capsule_body"};
35 BoundsInstanceBuf capsule_cap = {selection_type_, "bound_capsule_cap"};
36 } call_buffers_;
37
38 public:
39 Bounds(const SelectionType selection_type) : call_buffers_{selection_type} {}
40
42 {
43 call_buffers_.box.clear();
44 call_buffers_.sphere.clear();
45 call_buffers_.cylinder.clear();
46 call_buffers_.cone.clear();
47 call_buffers_.capsule_body.clear();
48 call_buffers_.capsule_cap.clear();
49 }
50
51 void object_sync(const ObjectRef &ob_ref, Resources &res, const State &state)
52 {
53 const Object *ob = ob_ref.object;
54 const bool from_dupli = (ob->base_flag & (BASE_FROM_SET | BASE_FROM_DUPLI)) != 0;
55 const bool has_bounds = !ELEM(
57 const bool draw_bounds = has_bounds && ((ob->dt == OB_BOUNDBOX) ||
58 ((ob->dtx & OB_DRAWBOUNDOX) && !from_dupli));
59 const float4 color = res.object_wire_color(ob_ref, state);
60
61 auto add_bounds = [&](const bool around_origin, const char bound_type) {
62 if (ob->type == OB_MBALL && !BKE_mball_is_basis(ob)) {
63 return;
64 }
65 const float4x4 object_mat{ob->object_to_world().ptr()};
66 const blender::Bounds<float3> bounds = BKE_object_boundbox_get(ob).value_or(
67 blender::Bounds(float3(-1.0f), float3(1.0f)));
68 const float3 size = (bounds.max - bounds.min) * 0.5f;
69 const float3 center = around_origin ? float3(0) : math::midpoint(bounds.min, bounds.max);
70 const select::ID select_id = res.select_id(ob_ref);
71
72 switch (bound_type) {
73 case OB_BOUND_BOX: {
75 scale.location() = center;
76 ExtraInstanceData data(object_mat * scale, color, 1.0f);
77 call_buffers_.box.append(data, select_id);
78 break;
79 }
80 case OB_BOUND_SPHERE: {
82 scale.location() = center;
83 ExtraInstanceData data(object_mat * scale, color, 1.0f);
84 call_buffers_.sphere.append(data, select_id);
85 break;
86 }
87 case OB_BOUND_CYLINDER: {
89 float3(float2(math::max(size.x, size.y)), size.z));
90 scale.location() = center;
91 ExtraInstanceData data(object_mat * scale, color, 1.0f);
92 call_buffers_.cylinder.append(data, select_id);
93 break;
94 }
95 case OB_BOUND_CONE: {
97 float3(float2(math::max(size.x, size.y)), size.z));
98 mat.location() = center;
99 /* Cone batch has base at 0 and is pointing towards +Y. */
100 std::swap(mat[1], mat[2]);
101 mat.location().z -= size.z;
102 ExtraInstanceData data(object_mat * mat, color, 1.0f);
103 call_buffers_.cone.append(data, select_id);
104 break;
105 }
106 case OB_BOUND_CAPSULE: {
107 float4x4 mat = math::from_scale<float4x4>(float3(math::max(size.x, size.y)));
108 mat.location() = center;
109 mat.location().z = center.z + std::max(0.0f, size.z - size.x);
110 ExtraInstanceData data(object_mat * mat, color, 1.0f);
111 call_buffers_.capsule_cap.append(data, select_id);
112 mat.z_axis() *= -1;
113 mat.location().z = center.z - std::max(0.0f, size.z - size.x);
114 data.object_to_world_ = object_mat * mat;
115 call_buffers_.capsule_cap.append(data, select_id);
116 mat.z_axis().z = std::max(0.0f, size.z * 2.0f - size.x * 2.0f);
117 data.object_to_world_ = object_mat * mat;
118 call_buffers_.capsule_body.append(data, select_id);
119 break;
120 }
121 }
122 };
123
124 if (draw_bounds) {
125 add_bounds(false, ob->boundtype);
126 }
127 if (!from_dupli && ob->rigidbody_object != nullptr) {
128 switch (ob->rigidbody_object->shape) {
129 case RB_SHAPE_BOX:
130 add_bounds(true, OB_BOUND_BOX);
131 break;
132 case RB_SHAPE_SPHERE:
133 add_bounds(true, OB_BOUND_SPHERE);
134 break;
135 case RB_SHAPE_CONE:
136 add_bounds(true, OB_BOUND_CONE);
137 break;
139 add_bounds(true, OB_BOUND_CYLINDER);
140 break;
141 case RB_SHAPE_CAPSULE:
142 add_bounds(true, OB_BOUND_CAPSULE);
143 break;
144 };
145 }
146 }
147
148 void end_sync(Resources &res, ShapeCache &shapes, const State &state)
149 {
150 ps_.init();
152 state.clipping_plane_count);
153 ps_.shader_set(res.shaders.extra_shape.get());
154 ps_.bind_ubo("globalsBlock", &res.globals_buf);
155 res.select_bind(ps_);
156
157 call_buffers_.box.end_sync(ps_, shapes.cube.get());
158 call_buffers_.sphere.end_sync(ps_, shapes.empty_sphere.get());
159 call_buffers_.cylinder.end_sync(ps_, shapes.cylinder.get());
160 call_buffers_.cone.end_sync(ps_, shapes.empty_cone.get());
161 call_buffers_.capsule_body.end_sync(ps_, shapes.capsule_body.get());
162 call_buffers_.capsule_cap.end_sync(ps_, shapes.capsule_cap.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} // namespace blender::draw::overlay
bool BKE_mball_is_basis(const Object *ob)
Definition mball.cc:230
std::optional< blender::Bounds< blender::float3 > > BKE_object_boundbox_get(const Object *ob)
#define ELEM(...)
@ BASE_FROM_DUPLI
@ BASE_FROM_SET
@ OB_BOUNDBOX
@ OB_SPEAKER
@ OB_MBALL
@ OB_EMPTY
@ OB_CAMERA
@ OB_LAMP
@ OB_LIGHTPROBE
@ OB_DRAWBOUNDOX
@ OB_BOUND_CAPSULE
@ OB_BOUND_SPHERE
@ OB_BOUND_CONE
@ OB_BOUND_BOX
@ OB_BOUND_CYLINDER
Types and defines for representing Rigid Body entities.
@ RB_SHAPE_CAPSULE
@ RB_SHAPE_BOX
@ RB_SHAPE_SPHERE
@ RB_SHAPE_CYLINDER
@ RB_SHAPE_CONE
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 object_sync(const ObjectRef &ob_ref, Resources &res, const State &state)
Bounds(const SelectionType selection_type)
void end_sync(Resources &res, ShapeCache &shapes, const State &state)
void draw(Framebuffer &framebuffer, Manager &manager, View &view)
@ 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]
T reduce_max(const VecBase< T, Size > &a)
T midpoint(const T &a, const T &b)
MatT from_scale(const VecBase< typename MatT::base_type, ScaleDim > &scale)
T max(const T &a, const T &b)
VecBase< float, 2 > float2
VecBase< float, 3 > float3
short base_flag
struct RigidBodyOb * rigidbody_object
T center() const
const float4 & object_wire_color(const ObjectRef &ob_ref, ThemeColorID theme_id) 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)