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(
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);
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()
{
metaballs.end_sync(resources, state);
metaballs.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);
} // 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
#include "DEG_depsgraph_query.h"
#include "DNA_camera_types.h"
#include "DNA_space_types.h"
#include "ED_mball.h"
#include "ED_view3d.h"
#include "UI_resources.h"
@ -20,14 +20,16 @@
namespace blender::draw::overlay {
template<typename SelectEngineT> class Metaballs {
using SelectID = typename SelectEngineT::ID;
using ResourcesT = Resources<SelectEngineT>;
using SphereOutlineInstanceBuf = ShapeInstanceBuf<SelectEngineT, BoneInstanceData>;
private:
PassSimple metaball_ps_ = {"MetaBalls"};
PassSimple metaball_in_front_ps_ = {"MetaBalls_In_front"};
ArmatureSphereBuf data_buf_ = {"metaball_data_buf"};
ArmatureSphereBuf data_in_front_buf_ = {"metaball_data_buf"};
SphereOutlineInstanceBuf data_buf_ = {"metaball_data_buf"};
SphereOutlineInstanceBuf data_in_front_buf_ = {"metaball_data_buf"};
public:
void begin_sync()
@ -36,26 +38,11 @@ template<typename SelectEngineT> class Metaballs {
data_in_front_buf_.clear();
}
void metaball_instance_data_set(BoneInstanceData *data,
Object *ob,
const float *pos,
const float radius,
const float color[4])
void edit_object_sync(const ObjectRef &ob_ref, ResourcesT &res)
{
/* Bone point radius is 0.05. Compensate for that. */
mul_v3_v3fl(data->mat[0], ob->object_to_world[0], radius / 0.05f);
mul_v3_v3fl(data->mat[1], ob->object_to_world[1], radius / 0.05f);
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_;
SphereOutlineInstanceBuf &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);
const float *color;
@ -68,47 +55,43 @@ template<typename SelectEngineT> class Metaballs {
const bool is_selected = (ml->flag & SELECT) != 0;
const bool is_scale_radius = (ml->flag & MB_SCALE_RAD) != 0;
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;
metaball_instance_data_set(&instdata, ob_ref.object, &ml->x, ml->rad, color);
data_buf.append(*reinterpret_cast<float4x4 *>(&instdata));
data_buf.append({ob_ref.object, &ml->x, ml->rad, color}, radius_id);
const SelectID stiff_id = res.select_id(ob_ref, MBALLSEL_STIFF);
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(*reinterpret_cast<float4x4 *>(&instdata));
data_buf.append({ob_ref.object, &ml->x, stiffness_radius, color}, stiff_id);
}
}
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 ?
data_in_front_buf_ :
data_buf_;
SphereOutlineInstanceBuf &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);
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) {
/* Draw radius only. */
BoneInstanceData instdata;
metaball_instance_data_set(&instdata, ob_ref.object, &ml->x, ml->rad, color);
data_buf.append(*reinterpret_cast<float4x4 *>(&instdata));
data_buf.append({ob_ref.object, &ml->x, ml->rad, color}, select_id);
}
}
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) {
data_buf.push_update();
auto init_pass = [&](PassSimple &pass, SphereOutlineInstanceBuf &call_buf) {
pass.init();
pass.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL |
state.clipping_state);
pass.shader_set(OVERLAY_shader_armature_sphere(true));
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_in_front_ps_, data_in_front_buf_);

View File

@ -62,7 +62,6 @@ using blender::draw::StorageVectorBuffer;
using blender::draw::Texture;
using blender::draw::TextureFromPool;
using blender::draw::TextureRef;
using ArmatureSphereBuf = StorageVectorBuffer<float4x4>;
template<typename SelectEngineT> struct Resources : public SelectEngineT::SelectMap {
Framebuffer overlay_fb = {"overlay_fb"};
@ -587,7 +586,7 @@ typedef struct OVERLAY_DupliData {
short base_flag;
} OVERLAY_DupliData;
typedef struct BoneInstanceData {
struct BoneInstanceData {
/* Keep sync with bone instance vertex format (OVERLAY_InstanceFormats) */
union {
float mat[4][4];
@ -604,7 +603,12 @@ typedef struct BoneInstanceData {
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 {
struct GPUVertFormat *instance_pos;

View File

@ -360,6 +360,21 @@ class ShapeCache {
return GPU_batch_create_ex(
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

View File

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

View File

@ -52,10 +52,12 @@ struct EngineObject {
uint next_id = 0;
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. */
return {next_id++};
return {sub_object_id | next_id++};
}
};
};