Overlay-Next: Initial implementation #107045

Closed
Clément Foucault wants to merge 28 commits from fclem/blender:overlay-next into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
7 changed files with 66 additions and 48 deletions
Showing only changes of commit 68a0f9e01c - Show all commits

View File

@ -58,7 +58,6 @@ template<typename SelectEngineT> class Empties {
ExtraInstanceData data( ExtraInstanceData data(
float4x4(ob_ref.object->object_to_world), color, ob_ref.object->empty_drawsize); float4x4(ob_ref.object->object_to_world), color, ob_ref.object->empty_drawsize);
/* TODO(fclem): Get selection ID from the selection engine. */
const SelectID select_id = res.select_id(ob_ref); const SelectID select_id = res.select_id(ob_ref);
switch (ob_ref.object->empty_drawtype) { switch (ob_ref.object->empty_drawtype) {

View File

@ -122,7 +122,7 @@ template<typename T> void Instance<T>::object_sync(ObjectRef &ob_ref)
template<typename T> void Instance<T>::end_sync() template<typename T> void Instance<T>::end_sync()
{ {
metaballs.end_sync(resources, state); metaballs.end_sync(resources, shapes, state);
empties.end_sync(resources, shapes, state); empties.end_sync(resources, shapes, state);
} }
@ -190,3 +190,18 @@ template void Instance<>::end_sync();
template void Instance<>::draw(Manager &manager); template void Instance<>::draw(Manager &manager);
} // namespace blender::draw::overlay } // namespace blender::draw::overlay
/* TODO(fclem): Move elsewhere. */
BoneInstanceData::BoneInstanceData(Object *ob,
const float *pos,
const float radius,
const float color[4])
{
/* TODO(fclem): Use C++ math API. */
mul_v3_v3fl(this->mat[0], ob->object_to_world[0], radius);
mul_v3_v3fl(this->mat[1], ob->object_to_world[1], radius);
mul_v3_v3fl(this->mat[2], ob->object_to_world[2], radius);
mul_v3_m4v3(this->mat[3], ob->object_to_world, pos);
/* WATCH: Reminder, alpha is wire-size. */
OVERLAY_bone_instance_data_set_color(this, color);
}

View File

@ -7,8 +7,8 @@
#pragma once #pragma once
#include "DEG_depsgraph_query.h" #include "DEG_depsgraph_query.h"
#include "DNA_camera_types.h"
#include "DNA_space_types.h" #include "DNA_space_types.h"
#include "ED_mball.h"
#include "ED_view3d.h" #include "ED_view3d.h"
#include "UI_resources.h" #include "UI_resources.h"
@ -20,14 +20,16 @@
namespace blender::draw::overlay { namespace blender::draw::overlay {
template<typename SelectEngineT> class Metaballs { template<typename SelectEngineT> class Metaballs {
using SelectID = typename SelectEngineT::ID;
using ResourcesT = Resources<SelectEngineT>; using ResourcesT = Resources<SelectEngineT>;
using SphereOutlineInstanceBuf = ShapeInstanceBuf<SelectEngineT, BoneInstanceData>;
private: private:
PassSimple metaball_ps_ = {"MetaBalls"}; PassSimple metaball_ps_ = {"MetaBalls"};
PassSimple metaball_in_front_ps_ = {"MetaBalls_In_front"}; PassSimple metaball_in_front_ps_ = {"MetaBalls_In_front"};
ArmatureSphereBuf data_buf_ = {"metaball_data_buf"}; SphereOutlineInstanceBuf data_buf_ = {"metaball_data_buf"};
ArmatureSphereBuf data_in_front_buf_ = {"metaball_data_buf"}; SphereOutlineInstanceBuf data_in_front_buf_ = {"metaball_data_buf"};
public: public:
void begin_sync() void begin_sync()
@ -36,26 +38,11 @@ template<typename SelectEngineT> class Metaballs {
data_in_front_buf_.clear(); data_in_front_buf_.clear();
} }
void metaball_instance_data_set(BoneInstanceData *data, void edit_object_sync(const ObjectRef &ob_ref, ResourcesT &res)
Object *ob,
const float *pos,
const float radius,
const float color[4])
{ {
/* Bone point radius is 0.05. Compensate for that. */ SphereOutlineInstanceBuf &data_buf = (ob_ref.object->dtx & OB_DRAW_IN_FRONT) != 0 ?
mul_v3_v3fl(data->mat[0], ob->object_to_world[0], radius / 0.05f); data_in_front_buf_ :
mul_v3_v3fl(data->mat[1], ob->object_to_world[1], radius / 0.05f); data_buf_;
mul_v3_v3fl(data->mat[2], ob->object_to_world[2], radius / 0.05f);
mul_v3_m4v3(data->mat[3], ob->object_to_world, pos);
/* WATCH: Reminder, alpha is wire-size. */
OVERLAY_bone_instance_data_set_color(data, color);
}
void edit_object_sync(const ObjectRef &ob_ref, const ResourcesT &res)
{
ArmatureSphereBuf &data_buf = (ob_ref.object->dtx & OB_DRAW_IN_FRONT) != 0 ?
data_in_front_buf_ :
data_buf_;
MetaBall *mb = static_cast<MetaBall *>(ob_ref.object->data); MetaBall *mb = static_cast<MetaBall *>(ob_ref.object->data);
const float *color; const float *color;
@ -68,47 +55,43 @@ template<typename SelectEngineT> class Metaballs {
const bool is_selected = (ml->flag & SELECT) != 0; const bool is_selected = (ml->flag & SELECT) != 0;
const bool is_scale_radius = (ml->flag & MB_SCALE_RAD) != 0; const bool is_scale_radius = (ml->flag & MB_SCALE_RAD) != 0;
float stiffness_radius = ml->rad * atanf(ml->s) / float(M_PI_2); float stiffness_radius = ml->rad * atanf(ml->s) / float(M_PI_2);
BoneInstanceData instdata;
const SelectID radius_id = res.select_id(ob_ref, MBALLSEL_RADIUS);
color = (is_selected && is_scale_radius) ? col_radius_select : col_radius; color = (is_selected && is_scale_radius) ? col_radius_select : col_radius;
metaball_instance_data_set(&instdata, ob_ref.object, &ml->x, ml->rad, color); data_buf.append({ob_ref.object, &ml->x, ml->rad, color}, radius_id);
data_buf.append(*reinterpret_cast<float4x4 *>(&instdata));
const SelectID stiff_id = res.select_id(ob_ref, MBALLSEL_STIFF);
color = (is_selected && !is_scale_radius) ? col_stiffness_select : col_stiffness; color = (is_selected && !is_scale_radius) ? col_stiffness_select : col_stiffness;
metaball_instance_data_set(&instdata, ob_ref.object, &ml->x, stiffness_radius, color); data_buf.append({ob_ref.object, &ml->x, stiffness_radius, color}, stiff_id);
data_buf.append(*reinterpret_cast<float4x4 *>(&instdata));
} }
} }
void object_sync(const ObjectRef &ob_ref, const ResourcesT &res, const State &state) void object_sync(const ObjectRef &ob_ref, ResourcesT &res, const State &state)
{ {
ArmatureSphereBuf &data_buf = (ob_ref.object->dtx & OB_DRAW_IN_FRONT) != 0 ? SphereOutlineInstanceBuf &data_buf = (ob_ref.object->dtx & OB_DRAW_IN_FRONT) != 0 ?
data_in_front_buf_ : data_in_front_buf_ :
data_buf_; data_buf_;
MetaBall *mb = static_cast<MetaBall *>(ob_ref.object->data); MetaBall *mb = static_cast<MetaBall *>(ob_ref.object->data);
const float4 &color = res.object_wire_color(ob_ref, state); const float4 &color = res.object_wire_color(ob_ref, state);
const SelectID select_id = res.select_id(ob_ref);
LISTBASE_FOREACH (MetaElem *, ml, &mb->elems) { LISTBASE_FOREACH (MetaElem *, ml, &mb->elems) {
/* Draw radius only. */ /* Draw radius only. */
BoneInstanceData instdata; data_buf.append({ob_ref.object, &ml->x, ml->rad, color}, select_id);
metaball_instance_data_set(&instdata, ob_ref.object, &ml->x, ml->rad, color);
data_buf.append(*reinterpret_cast<float4x4 *>(&instdata));
} }
} }
void end_sync(ResourcesT &res, const State &state) void end_sync(ResourcesT &res, ShapeCache &shapes, const State &state)
{ {
auto init_pass = [&](PassSimple &pass, ArmatureSphereBuf &data_buf) { auto init_pass = [&](PassSimple &pass, SphereOutlineInstanceBuf &call_buf) {
data_buf.push_update();
pass.init(); pass.init();
pass.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | pass.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL |
state.clipping_state); state.clipping_state);
pass.shader_set(OVERLAY_shader_armature_sphere(true)); pass.shader_set(OVERLAY_shader_armature_sphere(true));
pass.bind_ubo("globalsBlock", &res.globals_buf); pass.bind_ubo("globalsBlock", &res.globals_buf);
pass.bind_ssbo("data_buf", &data_buf);
pass.draw(DRW_cache_bone_point_wire_outline_get(), data_buf.size()); call_buf.end_sync(pass, shapes.metaball_wire_circle);
}; };
init_pass(metaball_ps_, data_buf_); init_pass(metaball_ps_, data_buf_);
init_pass(metaball_in_front_ps_, data_in_front_buf_); init_pass(metaball_in_front_ps_, data_in_front_buf_);

View File

@ -62,7 +62,6 @@ using blender::draw::StorageVectorBuffer;
using blender::draw::Texture; using blender::draw::Texture;
using blender::draw::TextureFromPool; using blender::draw::TextureFromPool;
using blender::draw::TextureRef; using blender::draw::TextureRef;
using ArmatureSphereBuf = StorageVectorBuffer<float4x4>;
template<typename SelectEngineT> struct Resources : public SelectEngineT::SelectMap { template<typename SelectEngineT> struct Resources : public SelectEngineT::SelectMap {
Framebuffer overlay_fb = {"overlay_fb"}; Framebuffer overlay_fb = {"overlay_fb"};
@ -587,7 +586,7 @@ typedef struct OVERLAY_DupliData {
short base_flag; short base_flag;
} OVERLAY_DupliData; } OVERLAY_DupliData;
typedef struct BoneInstanceData { struct BoneInstanceData {
/* Keep sync with bone instance vertex format (OVERLAY_InstanceFormats) */ /* Keep sync with bone instance vertex format (OVERLAY_InstanceFormats) */
union { union {
float mat[4][4]; float mat[4][4];
@ -604,7 +603,12 @@ typedef struct BoneInstanceData {
float _pad03[3], amax_b; float _pad03[3], amax_b;
}; };
}; };
} BoneInstanceData;
BoneInstanceData() = default;
/* Constructor used by metaball overlays and expected to be used for drawing
* metaball_wire_sphere with armature wire shader that produces wide-lines. */
BoneInstanceData(Object *ob, const float *pos, const float radius, const float color[4]);
};
typedef struct OVERLAY_InstanceFormats { typedef struct OVERLAY_InstanceFormats {
struct GPUVertFormat *instance_pos; struct GPUVertFormat *instance_pos;

View File

@ -360,6 +360,21 @@ class ShapeCache {
return GPU_batch_create_ex( return GPU_batch_create_ex(
GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO); GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO);
}(); }();
AutoFreeGPUBatch metaball_wire_circle = [this]() {
/* A single ring of vertices. */
constexpr int resolution = 64;
constexpr float radius = 1.0f;
Vector<float2> ring = ring_vertices(radius, resolution);
Vector<Vertex> verts;
for (int i : IndexRange(resolution + 1)) {
float2 cv = ring[i % resolution];
verts.append({{cv[0], cv[1], 0.0f}, VCLASS_SCREENALIGNED});
}
return GPU_batch_create_ex(
GPU_PRIM_LINE_STRIP, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO);
}();
}; };
} // namespace blender::draw::overlay } // namespace blender::draw::overlay

View File

@ -24,7 +24,7 @@ struct EngineEmpty {
}; };
struct SelectMap { struct SelectMap {
[[nodiscard]] constexpr ID select_id(const ObjectRef &) [[nodiscard]] const ID select_id(const ObjectRef &, uint = 0)
{ {
return {}; return {};
} }

View File

@ -52,10 +52,12 @@ struct EngineObject {
uint next_id = 0; uint next_id = 0;
Map<uint, ObjectRef> map; Map<uint, ObjectRef> map;
[[nodiscard]] const ID select_id(const ObjectRef &) /* TODO(fclem): The sub_object_id id should eventually become some enum or take a sub-object
* reference directly. */
[[nodiscard]] const ID select_id(const ObjectRef &, uint sub_object_id = 0)
{ {
/* TODO Insert Ref into the map. */ /* TODO Insert Ref into the map. */
return {next_id++}; return {sub_object_id | next_id++};
} }
}; };
}; };