Overlay-Next: Armature
Functional Changes: - Custom shapes using empties now supports line width. - Line width is supported on MacOS. - Fixed Stick bone drawing on MacOS. Some shaders are duplicated and ported to the new primitive expansion API. The legacy code inside `overlay_armature.cc` have been guarded behind `NO_LEGACY_OVERLAY` which can be enabled to make sure no legacy code is used unnoticed. This allows for spotting more easily code that needs to be ported. Moreover, it is easier to remove this legacy code when the time comes. Rel #102179 Pull Request: https://projects.blender.org/blender/blender/pulls/126474
This commit is contained in:
committed by
Clément Foucault
parent
5ec49b61e9
commit
508b39661d
@@ -641,10 +641,12 @@ set(GLSL_SRC
|
||||
engines/overlay/shaders/overlay_armature_envelope_solid_frag.glsl
|
||||
engines/overlay/shaders/overlay_armature_envelope_solid_vert.glsl
|
||||
engines/overlay/shaders/overlay_armature_shape_outline_geom.glsl
|
||||
engines/overlay/shaders/overlay_armature_shape_outline_next_vert.glsl
|
||||
engines/overlay/shaders/overlay_armature_shape_outline_vert.glsl
|
||||
engines/overlay/shaders/overlay_armature_shape_outline_vert_no_geom.glsl
|
||||
engines/overlay/shaders/overlay_armature_shape_solid_frag.glsl
|
||||
engines/overlay/shaders/overlay_armature_shape_solid_vert.glsl
|
||||
engines/overlay/shaders/overlay_armature_shape_wire_next_vert.glsl
|
||||
engines/overlay/shaders/overlay_armature_shape_wire_vert.glsl
|
||||
engines/overlay/shaders/overlay_armature_shape_wire_vert_no_geom.glsl
|
||||
engines/overlay/shaders/overlay_armature_shape_wire_frag.glsl
|
||||
|
||||
@@ -45,65 +45,14 @@
|
||||
#include "draw_common_c.hh"
|
||||
#include "draw_manager_text.hh"
|
||||
|
||||
#include "overlay_next_armature.hh"
|
||||
#include "overlay_private.hh"
|
||||
|
||||
#include "draw_cache_impl.hh"
|
||||
|
||||
#define PT_DEFAULT_RAD 0.05f /* radius of the point batch. */
|
||||
|
||||
using namespace blender;
|
||||
|
||||
enum eArmatureDrawMode {
|
||||
ARM_DRAW_MODE_OBJECT,
|
||||
ARM_DRAW_MODE_POSE,
|
||||
ARM_DRAW_MODE_EDIT,
|
||||
};
|
||||
|
||||
struct ArmatureDrawContext {
|
||||
/* Current armature object */
|
||||
Object *ob;
|
||||
// bArmature *arm; /* TODO. */
|
||||
eArmatureDrawMode draw_mode;
|
||||
eArmature_Drawtype drawtype;
|
||||
|
||||
union {
|
||||
struct {
|
||||
DRWCallBuffer *outline;
|
||||
DRWCallBuffer *solid;
|
||||
DRWCallBuffer *wire;
|
||||
};
|
||||
struct {
|
||||
DRWCallBuffer *envelope_outline;
|
||||
DRWCallBuffer *envelope_solid;
|
||||
DRWCallBuffer *envelope_distance;
|
||||
};
|
||||
struct {
|
||||
DRWCallBuffer *stick;
|
||||
};
|
||||
};
|
||||
|
||||
DRWCallBuffer *dof_lines;
|
||||
DRWCallBuffer *dof_sphere;
|
||||
DRWCallBuffer *point_solid;
|
||||
DRWCallBuffer *point_outline;
|
||||
DRWShadingGroup *custom_solid;
|
||||
DRWShadingGroup *custom_outline;
|
||||
DRWShadingGroup *custom_wire;
|
||||
GHash *custom_shapes_ghash;
|
||||
|
||||
OVERLAY_ExtraCallBuffers *extras;
|
||||
|
||||
/* not a theme, this is an override */
|
||||
const float *const_color;
|
||||
float const_wire;
|
||||
|
||||
bool do_relations;
|
||||
bool transparent;
|
||||
bool show_relations;
|
||||
bool draw_relation_from_head;
|
||||
|
||||
const ThemeWireColor *bcolor; /* pchan color */
|
||||
};
|
||||
using namespace blender::draw::overlay;
|
||||
|
||||
/**
|
||||
* Container for either an #EditBone or a #bPoseChannel.
|
||||
@@ -260,12 +209,12 @@ class ArmatureBoneDrawStrategy {
|
||||
const Object *ob,
|
||||
const bPoseChannel *pchan) const = 0;
|
||||
|
||||
virtual void draw_context_setup(ArmatureDrawContext *ctx,
|
||||
virtual void draw_context_setup(Armatures::DrawContext *ctx,
|
||||
const OVERLAY_ArmatureCallBuffersInner *cb,
|
||||
const bool is_filled,
|
||||
const bool do_envelope_dist) const = 0;
|
||||
|
||||
virtual void draw_bone(const ArmatureDrawContext *ctx,
|
||||
virtual void draw_bone(const Armatures::DrawContext *ctx,
|
||||
const UnifiedBonePtr bone,
|
||||
const eBone_Flag boneflag,
|
||||
const int select_id) const = 0;
|
||||
@@ -614,6 +563,17 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata)
|
||||
}
|
||||
}
|
||||
|
||||
// #define NO_LEGACY_OVERLAY
|
||||
|
||||
/* Allows to check that all legacy API usage are guarded behind this flag.
|
||||
* Checks that all code have been ported to new API. */
|
||||
#ifdef NO_LEGACY_OVERLAY
|
||||
# define DRW_buffer_add_entry_struct POISON
|
||||
# define DRW_select_load_id POISON
|
||||
# define OVERLAY_empty_shape POISON
|
||||
# define OVERLAY_extra_line_dashed POISON
|
||||
#endif
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Shader Groups (DRW_shgroup)
|
||||
* \{ */
|
||||
@@ -652,8 +612,10 @@ void OVERLAY_bone_instance_data_set_color(BoneInstanceData *data, const float bo
|
||||
data->color_b = encode_2f_to_float(bone_color[2], bone_color[3]);
|
||||
}
|
||||
|
||||
#ifndef NO_LEGACY_OVERLAY
|
||||
|
||||
/* Octahedral */
|
||||
static void drw_shgroup_bone_octahedral(const ArmatureDrawContext *ctx,
|
||||
static void drw_shgroup_bone_octahedral(const Armatures::DrawContext *ctx,
|
||||
const float (*bone_mat)[4],
|
||||
const float bone_color[4],
|
||||
const float hint_color[4],
|
||||
@@ -673,7 +635,7 @@ static void drw_shgroup_bone_octahedral(const ArmatureDrawContext *ctx,
|
||||
}
|
||||
|
||||
/* Box / B-Bone */
|
||||
static void drw_shgroup_bone_box(const ArmatureDrawContext *ctx,
|
||||
static void drw_shgroup_bone_box(const Armatures::DrawContext *ctx,
|
||||
const float (*bone_mat)[4],
|
||||
const float bone_color[4],
|
||||
const float hint_color[4],
|
||||
@@ -691,45 +653,47 @@ static void drw_shgroup_bone_box(const ArmatureDrawContext *ctx,
|
||||
DRW_buffer_add_entry_struct(ctx->outline, &inst_data);
|
||||
}
|
||||
}
|
||||
|
||||
/* Wire */
|
||||
static void drw_shgroup_bone_wire(const ArmatureDrawContext *ctx,
|
||||
const float (*bone_mat)[4],
|
||||
const float color[4])
|
||||
{
|
||||
float head[3], tail[3];
|
||||
mul_v3_m4v3(head, ctx->ob->object_to_world().ptr(), bone_mat[3]);
|
||||
add_v3_v3v3(tail, bone_mat[3], bone_mat[1]);
|
||||
mul_m4_v3(ctx->ob->object_to_world().ptr(), tail);
|
||||
|
||||
DRW_buffer_add_entry(ctx->wire, head, color);
|
||||
DRW_buffer_add_entry(ctx->wire, tail, color);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Stick */
|
||||
static void drw_shgroup_bone_stick(const ArmatureDrawContext *ctx,
|
||||
static void drw_shgroup_bone_stick(const Armatures::DrawContext *ctx,
|
||||
const float (*bone_mat)[4],
|
||||
const float col_wire[4],
|
||||
const float col_bone[4],
|
||||
const float col_head[4],
|
||||
const float col_tail[4])
|
||||
const float col_tail[4],
|
||||
const int select_id)
|
||||
{
|
||||
float head[3], tail[3];
|
||||
mul_v3_m4v3(head, ctx->ob->object_to_world().ptr(), bone_mat[3]);
|
||||
add_v3_v3v3(tail, bone_mat[3], bone_mat[1]);
|
||||
mul_m4_v3(ctx->ob->object_to_world().ptr(), tail);
|
||||
float4x4 bmat = float4x4(bone_mat);
|
||||
float3 head = math::transform_point(ctx->ob->object_to_world(), bmat.location());
|
||||
float3 tail = math::transform_point(ctx->ob->object_to_world(), bmat.location() + bmat.y_axis());
|
||||
|
||||
DRW_buffer_add_entry(ctx->stick, head, tail, col_wire, col_bone, col_head, col_tail);
|
||||
if (ctx->is_overlay_next()) {
|
||||
auto sel_id = ctx->res->select_id(*ctx->ob_ref, select_id);
|
||||
|
||||
ctx->bone_buf->stick_buf.append({head,
|
||||
tail,
|
||||
*(float4 *)col_wire,
|
||||
*(float4 *)col_bone,
|
||||
*(float4 *)col_head,
|
||||
*(float4 *)col_tail},
|
||||
sel_id);
|
||||
}
|
||||
#ifndef NO_LEGACY_OVERLAY
|
||||
else {
|
||||
DRW_buffer_add_entry(ctx->stick, head, tail, col_wire, col_bone, col_head, col_tail);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Envelope */
|
||||
static void drw_shgroup_bone_envelope_distance(const ArmatureDrawContext *ctx,
|
||||
static void drw_shgroup_bone_envelope_distance(const Armatures::DrawContext *ctx,
|
||||
const float (*bone_mat)[4],
|
||||
const float *radius_head,
|
||||
const float *radius_tail,
|
||||
const float *distance)
|
||||
{
|
||||
if (ctx->envelope_distance) {
|
||||
if (ctx->draw_envelope_distance) {
|
||||
float head_sph[4] = {0.0f, 0.0f, 0.0f, 1.0f}, tail_sph[4] = {0.0f, 1.0f, 0.0f, 1.0f};
|
||||
float xaxis[4] = {1.0f, 0.0f, 0.0f, 1.0f};
|
||||
/* Still less operation than m4 multiplication. */
|
||||
@@ -745,17 +709,28 @@ static void drw_shgroup_bone_envelope_distance(const ArmatureDrawContext *ctx,
|
||||
head_sph[3] += *distance * obscale;
|
||||
tail_sph[3] = *radius_tail * obscale;
|
||||
tail_sph[3] += *distance * obscale;
|
||||
DRW_buffer_add_entry(ctx->envelope_distance, head_sph, tail_sph, xaxis);
|
||||
if (ctx->is_overlay_next()) {
|
||||
/* TODO(fclem): Cleanup these casts when Overlay Next is shipped. */
|
||||
ctx->bone_buf->envelope_distance_buf.append(
|
||||
{*(float4 *)head_sph, *(float4 *)tail_sph, *(float3 *)xaxis},
|
||||
draw::select::SelectMap::select_invalid_id());
|
||||
}
|
||||
#ifndef NO_LEGACY_OVERLAY
|
||||
else if (ctx->envelope_distance) {
|
||||
DRW_buffer_add_entry(ctx->envelope_distance, head_sph, tail_sph, xaxis);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static void drw_shgroup_bone_envelope(const ArmatureDrawContext *ctx,
|
||||
static void drw_shgroup_bone_envelope(const Armatures::DrawContext *ctx,
|
||||
const float (*bone_mat)[4],
|
||||
const float bone_col[4],
|
||||
const float hint_col[4],
|
||||
const float outline_col[4],
|
||||
const float *radius_head,
|
||||
const float *radius_tail)
|
||||
const float *radius_tail,
|
||||
const int select_id)
|
||||
{
|
||||
float head_sph[4] = {0.0f, 0.0f, 0.0f, 1.0f}, tail_sph[4] = {0.0f, 1.0f, 0.0f, 1.0f};
|
||||
float xaxis[4] = {1.0f, 0.0f, 0.0f, 1.0f};
|
||||
@@ -770,6 +745,9 @@ static void drw_shgroup_bone_envelope(const ArmatureDrawContext *ctx,
|
||||
head_sph[3] = *radius_head * obscale;
|
||||
tail_sph[3] = *radius_tail * obscale;
|
||||
|
||||
auto sel_id = (ctx->bone_buf) ? ctx->res->select_id(*ctx->ob_ref, select_id) :
|
||||
draw::select::SelectMap::select_invalid_id();
|
||||
|
||||
if (head_sph[3] < 0.0f || tail_sph[3] < 0.0f) {
|
||||
BoneInstanceData inst_data;
|
||||
if (head_sph[3] < 0.0f) {
|
||||
@@ -783,15 +761,27 @@ static void drw_shgroup_bone_envelope(const ArmatureDrawContext *ctx,
|
||||
copy_v3_v3(inst_data.mat[3], head_sph);
|
||||
}
|
||||
|
||||
if (ctx->point_solid) {
|
||||
OVERLAY_bone_instance_data_set_color(&inst_data, bone_col);
|
||||
OVERLAY_bone_instance_data_set_color_hint(&inst_data, hint_col);
|
||||
DRW_buffer_add_entry_struct(ctx->point_solid, &inst_data);
|
||||
if (ctx->is_overlay_next()) {
|
||||
if (ctx->is_filled) {
|
||||
ctx->bone_buf->sphere_fill_buf.append({inst_data.mat44, bone_col, hint_col}, sel_id);
|
||||
}
|
||||
if (outline_col[3] > 0.0f) {
|
||||
ctx->bone_buf->sphere_outline_buf.append({inst_data.mat44, outline_col}, sel_id);
|
||||
}
|
||||
}
|
||||
if (outline_col[3] > 0.0f) {
|
||||
OVERLAY_bone_instance_data_set_color(&inst_data, outline_col);
|
||||
DRW_buffer_add_entry_struct(ctx->point_outline, &inst_data);
|
||||
#ifndef NO_LEGACY_OVERLAY
|
||||
else {
|
||||
if (ctx->point_solid) {
|
||||
OVERLAY_bone_instance_data_set_color(&inst_data, bone_col);
|
||||
OVERLAY_bone_instance_data_set_color_hint(&inst_data, hint_col);
|
||||
DRW_buffer_add_entry_struct(ctx->point_solid, &inst_data);
|
||||
}
|
||||
if (outline_col[3] > 0.0f) {
|
||||
OVERLAY_bone_instance_data_set_color(&inst_data, outline_col);
|
||||
DRW_buffer_add_entry_struct(ctx->point_outline, &inst_data);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
/* Draw Body */
|
||||
@@ -804,12 +794,33 @@ static void drw_shgroup_bone_envelope(const ArmatureDrawContext *ctx,
|
||||
copy_v4_v4(tmp_sph, head_sph);
|
||||
interp_v4_v4v4(head_sph, tail_sph, head_sph, fac_head);
|
||||
interp_v4_v4v4(tail_sph, tmp_sph, tail_sph, fac_tail);
|
||||
if (ctx->envelope_solid) {
|
||||
DRW_buffer_add_entry(ctx->envelope_solid, head_sph, tail_sph, bone_col, hint_col, xaxis);
|
||||
|
||||
if (ctx->is_overlay_next()) {
|
||||
if (ctx->is_filled) {
|
||||
/* TODO(fclem): Cleanup these casts when Overlay Next is shipped. */
|
||||
ctx->bone_buf->envelope_fill_buf.append({*(float4 *)head_sph,
|
||||
*(float4 *)tail_sph,
|
||||
*(float3 *)bone_col,
|
||||
*(float3 *)hint_col,
|
||||
*(float3 *)xaxis},
|
||||
sel_id);
|
||||
}
|
||||
if (outline_col[3] > 0.0f) {
|
||||
ctx->bone_buf->envelope_outline_buf.append(
|
||||
{*(float4 *)head_sph, *(float4 *)tail_sph, *(float4 *)outline_col, *(float3 *)xaxis},
|
||||
sel_id);
|
||||
}
|
||||
}
|
||||
if (outline_col[3] > 0.0f) {
|
||||
DRW_buffer_add_entry(ctx->envelope_outline, head_sph, tail_sph, outline_col, xaxis);
|
||||
#ifndef NO_LEGACY_OVERLAY
|
||||
else {
|
||||
if (ctx->envelope_solid) {
|
||||
DRW_buffer_add_entry(ctx->envelope_solid, head_sph, tail_sph, bone_col, hint_col, xaxis);
|
||||
}
|
||||
if (outline_col[3] > 0.0f) {
|
||||
DRW_buffer_add_entry(ctx->envelope_outline, head_sph, tail_sph, outline_col, xaxis);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
/* Distance between endpoints is too small for a capsule. Draw a Sphere instead. */
|
||||
@@ -819,22 +830,36 @@ static void drw_shgroup_bone_envelope(const ArmatureDrawContext *ctx,
|
||||
BoneInstanceData inst_data;
|
||||
scale_m4_fl(inst_data.mat, tmp_sph[3] / PT_DEFAULT_RAD);
|
||||
copy_v3_v3(inst_data.mat[3], tmp_sph);
|
||||
if (ctx->point_solid) {
|
||||
OVERLAY_bone_instance_data_set_color(&inst_data, bone_col);
|
||||
OVERLAY_bone_instance_data_set_color_hint(&inst_data, hint_col);
|
||||
DRW_buffer_add_entry_struct(ctx->point_solid, &inst_data);
|
||||
|
||||
if (ctx->is_overlay_next()) {
|
||||
if (ctx->is_filled) {
|
||||
ctx->bone_buf->sphere_fill_buf.append({inst_data.mat44, bone_col, hint_col}, sel_id);
|
||||
}
|
||||
if (outline_col[3] > 0.0f) {
|
||||
ctx->bone_buf->sphere_outline_buf.append({inst_data.mat44, outline_col}, sel_id);
|
||||
}
|
||||
}
|
||||
if (outline_col[3] > 0.0f) {
|
||||
OVERLAY_bone_instance_data_set_color(&inst_data, outline_col);
|
||||
DRW_buffer_add_entry_struct(ctx->point_outline, &inst_data);
|
||||
#ifndef NO_LEGACY_OVERLAY
|
||||
else {
|
||||
if (ctx->point_solid) {
|
||||
OVERLAY_bone_instance_data_set_color(&inst_data, bone_col);
|
||||
OVERLAY_bone_instance_data_set_color_hint(&inst_data, hint_col);
|
||||
DRW_buffer_add_entry_struct(ctx->point_solid, &inst_data);
|
||||
}
|
||||
if (outline_col[3] > 0.0f) {
|
||||
OVERLAY_bone_instance_data_set_color(&inst_data, outline_col);
|
||||
DRW_buffer_add_entry_struct(ctx->point_outline, &inst_data);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Custom (geometry) */
|
||||
|
||||
BLI_INLINE DRWCallBuffer *custom_bone_instance_shgroup(const ArmatureDrawContext *ctx,
|
||||
#ifndef NO_LEGACY_OVERLAY
|
||||
BLI_INLINE DRWCallBuffer *custom_bone_instance_shgroup(const Armatures::DrawContext *ctx,
|
||||
DRWShadingGroup *grp,
|
||||
blender::gpu::Batch *custom_geom)
|
||||
{
|
||||
@@ -847,17 +872,20 @@ BLI_INLINE DRWCallBuffer *custom_bone_instance_shgroup(const ArmatureDrawContext
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void drw_shgroup_bone_custom_solid_mesh(const ArmatureDrawContext *ctx,
|
||||
static void drw_shgroup_bone_custom_solid_mesh(const Armatures::DrawContext *ctx,
|
||||
Mesh &mesh,
|
||||
const float (*bone_mat)[4],
|
||||
const float bone_color[4],
|
||||
const float hint_color[4],
|
||||
const float outline_color[4],
|
||||
const float wire_width,
|
||||
const draw::select::ID select_id,
|
||||
Object &custom)
|
||||
{
|
||||
using namespace blender::draw;
|
||||
using BoneInstanceBuf = ShapeInstanceBuf<BoneInstanceData>;
|
||||
/* TODO(fclem): arg... less than ideal but we never iter on this object
|
||||
* to assure batch cache is valid. */
|
||||
DRW_mesh_batch_cache_validate(custom, mesh);
|
||||
@@ -869,69 +897,100 @@ static void drw_shgroup_bone_custom_solid_mesh(const ArmatureDrawContext *ctx,
|
||||
DRWCallBuffer *buf;
|
||||
|
||||
if (surf || edges || loose_edges) {
|
||||
mul_m4_m4m4(inst_data.mat, ctx->ob->object_to_world().ptr(), bone_mat);
|
||||
inst_data.mat44 = ctx->ob->object_to_world() * float4x4(bone_mat);
|
||||
}
|
||||
|
||||
if (surf && ctx->custom_solid) {
|
||||
buf = custom_bone_instance_shgroup(ctx, ctx->custom_solid, surf);
|
||||
OVERLAY_bone_instance_data_set_color_hint(&inst_data, hint_color);
|
||||
OVERLAY_bone_instance_data_set_color(&inst_data, bone_color);
|
||||
DRW_buffer_add_entry_struct(buf, inst_data.mat);
|
||||
if (surf) {
|
||||
inst_data.set_hint_color(hint_color);
|
||||
inst_data.set_color(bone_color);
|
||||
if (ctx->is_overlay_next() && ctx->is_filled) {
|
||||
ctx->bone_buf->custom_shape_fill_get_buffer(surf).append(inst_data, select_id);
|
||||
}
|
||||
#ifndef NO_LEGACY_OVERLAY
|
||||
else if (ctx->custom_solid) {
|
||||
buf = custom_bone_instance_shgroup(ctx, ctx->custom_solid, surf);
|
||||
DRW_buffer_add_entry_struct(buf, inst_data.mat);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (edges && ctx->custom_outline) {
|
||||
buf = custom_bone_instance_shgroup(ctx, ctx->custom_outline, edges);
|
||||
OVERLAY_bone_instance_data_set_color(&inst_data, outline_color);
|
||||
DRW_buffer_add_entry_struct(buf, inst_data.mat);
|
||||
if (edges) {
|
||||
inst_data.set_color(outline_color);
|
||||
if (ctx->is_overlay_next()) {
|
||||
ctx->bone_buf->custom_shape_outline_get_buffer(edges).append(inst_data, select_id);
|
||||
}
|
||||
#ifndef NO_LEGACY_OVERLAY
|
||||
else if (ctx->custom_outline) {
|
||||
buf = custom_bone_instance_shgroup(ctx, ctx->custom_outline, edges);
|
||||
DRW_buffer_add_entry_struct(buf, inst_data.mat);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (loose_edges) {
|
||||
buf = custom_bone_instance_shgroup(ctx, ctx->custom_wire, loose_edges);
|
||||
OVERLAY_bone_instance_data_set_color_hint(&inst_data, outline_color);
|
||||
inst_data.color_a = encode_2f_to_float(outline_color[0], outline_color[1]);
|
||||
inst_data.color_b = encode_2f_to_float(outline_color[2], wire_width / WIRE_WIDTH_COMPRESSION);
|
||||
DRW_buffer_add_entry_struct(buf, inst_data.mat);
|
||||
inst_data.set_hint_color(outline_color);
|
||||
inst_data.set_color(float4(UNPACK3(outline_color), wire_width / WIRE_WIDTH_COMPRESSION));
|
||||
if (ctx->is_overlay_next()) {
|
||||
ctx->bone_buf->custom_shape_wire_get_buffer(loose_edges).append(inst_data, select_id);
|
||||
}
|
||||
#ifndef NO_LEGACY_OVERLAY
|
||||
else {
|
||||
buf = custom_bone_instance_shgroup(ctx, ctx->custom_wire, loose_edges);
|
||||
DRW_buffer_add_entry_struct(buf, inst_data.mat);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* TODO(fclem): needs to be moved elsewhere. */
|
||||
drw_batch_cache_generate_requested_delayed(&custom);
|
||||
}
|
||||
|
||||
static void drw_shgroup_bone_custom_mesh_wire(const ArmatureDrawContext *ctx,
|
||||
static void drw_shgroup_bone_custom_mesh_wire(const Armatures::DrawContext *ctx,
|
||||
Mesh &mesh,
|
||||
const float (*bone_mat)[4],
|
||||
const float color[4],
|
||||
const float wire_width,
|
||||
const draw::select::ID select_id,
|
||||
Object &custom)
|
||||
{
|
||||
using namespace blender::draw;
|
||||
using BoneInstanceBuf = ShapeInstanceBuf<BoneInstanceData>;
|
||||
/* TODO(fclem): arg... less than ideal but we never iter on this object
|
||||
* to assure batch cache is valid. */
|
||||
DRW_mesh_batch_cache_validate(custom, mesh);
|
||||
|
||||
blender::gpu::Batch *geom = DRW_mesh_batch_cache_get_all_edges(mesh);
|
||||
if (geom) {
|
||||
DRWCallBuffer *buf = custom_bone_instance_shgroup(ctx, ctx->custom_wire, geom);
|
||||
BoneInstanceData inst_data;
|
||||
mul_m4_m4m4(inst_data.mat, ctx->ob->object_to_world().ptr(), bone_mat);
|
||||
OVERLAY_bone_instance_data_set_color_hint(&inst_data, color);
|
||||
inst_data.color_a = encode_2f_to_float(color[0], color[1]);
|
||||
inst_data.color_b = encode_2f_to_float(color[2], wire_width / WIRE_WIDTH_COMPRESSION);
|
||||
DRW_buffer_add_entry_struct(buf, inst_data.mat);
|
||||
inst_data.mat44 = ctx->ob->object_to_world() * float4x4(bone_mat);
|
||||
inst_data.set_hint_color(color);
|
||||
inst_data.set_color(float4(UNPACK3(color), wire_width / WIRE_WIDTH_COMPRESSION));
|
||||
|
||||
if (ctx->is_overlay_next()) {
|
||||
ctx->bone_buf->custom_shape_wire_get_buffer(geom).append(inst_data, select_id);
|
||||
}
|
||||
#ifndef NO_LEGACY_OVERLAY
|
||||
else {
|
||||
DRWCallBuffer *buf = custom_bone_instance_shgroup(ctx, ctx->custom_wire, geom);
|
||||
DRW_buffer_add_entry_struct(buf, inst_data.mat);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* TODO(fclem): needs to be moved elsewhere. */
|
||||
drw_batch_cache_generate_requested_delayed(&custom);
|
||||
}
|
||||
|
||||
static void drw_shgroup_custom_bone_curve(const ArmatureDrawContext *ctx,
|
||||
static void drw_shgroup_custom_bone_curve(const Armatures::DrawContext *ctx,
|
||||
Curve *curve,
|
||||
const float (*bone_mat)[4],
|
||||
const float outline_color[4],
|
||||
const float wire_width,
|
||||
const draw::select::ID select_id,
|
||||
Object *custom)
|
||||
{
|
||||
using namespace blender::draw;
|
||||
using BoneInstanceBuf = ShapeInstanceBuf<BoneInstanceData>;
|
||||
/* TODO(fclem): arg... less than ideal but we never iter on this object
|
||||
* to assure batch cache is valid. */
|
||||
DRW_curve_batch_cache_validate(curve);
|
||||
@@ -948,25 +1007,32 @@ static void drw_shgroup_custom_bone_curve(const ArmatureDrawContext *ctx,
|
||||
|
||||
if (loose_edges) {
|
||||
BoneInstanceData inst_data;
|
||||
mul_m4_m4m4(inst_data.mat, ctx->ob->object_to_world().ptr(), bone_mat);
|
||||
inst_data.mat44 = ctx->ob->object_to_world() * float4x4(bone_mat);
|
||||
inst_data.set_hint_color(outline_color);
|
||||
inst_data.set_color(float4(UNPACK3(outline_color), wire_width / WIRE_WIDTH_COMPRESSION));
|
||||
|
||||
DRWCallBuffer *buf = custom_bone_instance_shgroup(ctx, ctx->custom_wire, loose_edges);
|
||||
OVERLAY_bone_instance_data_set_color_hint(&inst_data, outline_color);
|
||||
inst_data.color_a = encode_2f_to_float(outline_color[0], outline_color[1]);
|
||||
inst_data.color_b = encode_2f_to_float(outline_color[2], wire_width / WIRE_WIDTH_COMPRESSION);
|
||||
DRW_buffer_add_entry_struct(buf, inst_data.mat);
|
||||
if (ctx->is_overlay_next()) {
|
||||
ctx->bone_buf->custom_shape_wire_get_buffer(loose_edges).append(inst_data, select_id);
|
||||
}
|
||||
#ifndef NO_LEGACY_OVERLAY
|
||||
else {
|
||||
DRWCallBuffer *buf = custom_bone_instance_shgroup(ctx, ctx->custom_wire, loose_edges);
|
||||
DRW_buffer_add_entry_struct(buf, inst_data.mat);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* TODO(fclem): needs to be moved elsewhere. */
|
||||
drw_batch_cache_generate_requested_delayed(custom);
|
||||
}
|
||||
|
||||
static void drw_shgroup_bone_custom_solid(const ArmatureDrawContext *ctx,
|
||||
static void drw_shgroup_bone_custom_solid(const Armatures::DrawContext *ctx,
|
||||
const float (*bone_mat)[4],
|
||||
const float bone_color[4],
|
||||
const float hint_color[4],
|
||||
const float outline_color[4],
|
||||
const float wire_width,
|
||||
const draw::select::ID select_id,
|
||||
Object *custom)
|
||||
{
|
||||
/* The custom object is not an evaluated object, so its object->data field hasn't been replaced
|
||||
@@ -975,44 +1041,103 @@ static void drw_shgroup_bone_custom_solid(const ArmatureDrawContext *ctx,
|
||||
* larger refactor of this area. */
|
||||
Mesh *mesh = BKE_object_get_evaluated_mesh_no_subsurf_unchecked(custom);
|
||||
if (mesh != nullptr) {
|
||||
drw_shgroup_bone_custom_solid_mesh(
|
||||
ctx, *mesh, bone_mat, bone_color, hint_color, outline_color, wire_width, *custom);
|
||||
drw_shgroup_bone_custom_solid_mesh(ctx,
|
||||
*mesh,
|
||||
bone_mat,
|
||||
bone_color,
|
||||
hint_color,
|
||||
outline_color,
|
||||
wire_width,
|
||||
select_id,
|
||||
*custom);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ELEM(custom->type, OB_CURVES_LEGACY, OB_FONT, OB_SURF)) {
|
||||
drw_shgroup_custom_bone_curve(
|
||||
ctx, static_cast<Curve *>(custom->data), bone_mat, outline_color, wire_width, custom);
|
||||
drw_shgroup_custom_bone_curve(ctx,
|
||||
static_cast<Curve *>(custom->data),
|
||||
bone_mat,
|
||||
outline_color,
|
||||
wire_width,
|
||||
select_id,
|
||||
custom);
|
||||
}
|
||||
}
|
||||
|
||||
static void drw_shgroup_bone_custom_wire(const ArmatureDrawContext *ctx,
|
||||
static void drw_shgroup_bone_custom_wire(const Armatures::DrawContext *ctx,
|
||||
const float (*bone_mat)[4],
|
||||
const float color[4],
|
||||
const float wire_width,
|
||||
const draw::select::ID select_id,
|
||||
Object *custom)
|
||||
{
|
||||
/* See comments in #drw_shgroup_bone_custom_solid. */
|
||||
Mesh *mesh = BKE_object_get_evaluated_mesh_no_subsurf_unchecked(custom);
|
||||
if (mesh != nullptr) {
|
||||
drw_shgroup_bone_custom_mesh_wire(ctx, *mesh, bone_mat, color, wire_width, *custom);
|
||||
drw_shgroup_bone_custom_mesh_wire(ctx, *mesh, bone_mat, color, wire_width, select_id, *custom);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ELEM(custom->type, OB_CURVES_LEGACY, OB_FONT, OB_SURF)) {
|
||||
drw_shgroup_custom_bone_curve(
|
||||
ctx, static_cast<Curve *>(custom->data), bone_mat, color, wire_width, custom);
|
||||
ctx, static_cast<Curve *>(custom->data), bone_mat, color, wire_width, select_id, custom);
|
||||
}
|
||||
}
|
||||
|
||||
static void drw_shgroup_bone_custom_empty(const ArmatureDrawContext *ctx,
|
||||
static void drw_shgroup_bone_custom_empty(const Armatures::DrawContext *ctx,
|
||||
const float (*bone_mat)[4],
|
||||
const float color[4],
|
||||
const float wire_width,
|
||||
const draw::select::ID select_id,
|
||||
Object *custom)
|
||||
{
|
||||
const float final_color[4] = {color[0], color[1], color[2], 1.0f};
|
||||
float mat[4][4];
|
||||
mul_m4_m4m4(mat, ctx->ob->object_to_world().ptr(), bone_mat);
|
||||
using namespace blender::draw;
|
||||
using BoneInstanceBuf = ShapeInstanceBuf<BoneInstanceData>;
|
||||
|
||||
if (ctx->is_overlay_next()) {
|
||||
gpu::Batch *geom = nullptr;
|
||||
switch (custom->empty_drawtype) {
|
||||
case OB_PLAINAXES:
|
||||
geom = ctx->shapes->plain_axes.get();
|
||||
break;
|
||||
case OB_SINGLE_ARROW:
|
||||
geom = ctx->shapes->single_arrow.get();
|
||||
break;
|
||||
case OB_CUBE:
|
||||
geom = ctx->shapes->cube.get();
|
||||
break;
|
||||
case OB_CIRCLE:
|
||||
geom = ctx->shapes->circle.get();
|
||||
break;
|
||||
case OB_EMPTY_SPHERE:
|
||||
geom = ctx->shapes->empty_sphere.get();
|
||||
break;
|
||||
case OB_EMPTY_CONE:
|
||||
geom = ctx->shapes->empty_cone.get();
|
||||
break;
|
||||
case OB_ARROWS:
|
||||
geom = ctx->shapes->arrows.get();
|
||||
break;
|
||||
case OB_EMPTY_IMAGE:
|
||||
/* Not supported. */
|
||||
return;
|
||||
}
|
||||
BLI_assert(geom);
|
||||
|
||||
const float4 final_color(UNPACK3(color), 1.0f);
|
||||
|
||||
BoneInstanceData inst_data;
|
||||
inst_data.mat44 = ctx->ob->object_to_world() * float4x4(bone_mat);
|
||||
inst_data.set_hint_color(final_color);
|
||||
inst_data.set_color(float4(UNPACK3(final_color), wire_width / WIRE_WIDTH_COMPRESSION));
|
||||
|
||||
ctx->bone_buf->custom_shape_wire_get_buffer(geom).append(inst_data, select_id);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef NO_LEGACY_OVERLAY
|
||||
const float4 final_color(UNPACK3(color), 1.0f);
|
||||
const float4x4 mat = ctx->ob->object_to_world() * float4x4(bone_mat);
|
||||
|
||||
switch (custom->empty_drawtype) {
|
||||
case OB_PLAINAXES:
|
||||
@@ -1023,22 +1148,40 @@ static void drw_shgroup_bone_custom_empty(const ArmatureDrawContext *ctx,
|
||||
case OB_EMPTY_CONE:
|
||||
case OB_ARROWS:
|
||||
OVERLAY_empty_shape(
|
||||
ctx->extras, mat, custom->empty_drawsize, custom->empty_drawtype, final_color);
|
||||
ctx->extras, mat.ptr(), custom->empty_drawsize, custom->empty_drawtype, final_color);
|
||||
break;
|
||||
case OB_EMPTY_IMAGE:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Head and tail sphere */
|
||||
static void drw_shgroup_bone_point(const ArmatureDrawContext *ctx,
|
||||
const float (*bone_mat)[4],
|
||||
const float bone_color[4],
|
||||
const float hint_color[4],
|
||||
const float outline_color[4])
|
||||
static void drw_shgroup_bone_sphere(const Armatures::DrawContext *ctx,
|
||||
const float (*bone_mat)[4],
|
||||
const float bone_color[4],
|
||||
const float hint_color[4],
|
||||
const float outline_color[4],
|
||||
const int select_id)
|
||||
{
|
||||
auto sel_id = (ctx->bone_buf) ? ctx->res->select_id(*ctx->ob_ref, select_id) :
|
||||
draw::select::SelectMap::select_invalid_id();
|
||||
float4x4 mat = ctx->ob->object_to_world() * float4x4(bone_mat);
|
||||
|
||||
if (ctx->is_overlay_next()) {
|
||||
if (ctx->is_filled) {
|
||||
ctx->bone_buf->sphere_fill_buf.append({mat, bone_color, hint_color}, sel_id);
|
||||
}
|
||||
if (outline_color[3] > 0.0f) {
|
||||
ctx->bone_buf->sphere_outline_buf.append({mat, outline_color}, sel_id);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef NO_LEGACY_OVERLAY
|
||||
BoneInstanceData inst_data;
|
||||
mul_m4_m4m4(inst_data.mat, ctx->ob->object_to_world().ptr(), bone_mat);
|
||||
inst_data.mat44 = mat;
|
||||
|
||||
if (ctx->point_solid) {
|
||||
OVERLAY_bone_instance_data_set_color(&inst_data, bone_color);
|
||||
OVERLAY_bone_instance_data_set_color_hint(&inst_data, hint_color);
|
||||
@@ -1048,48 +1191,65 @@ static void drw_shgroup_bone_point(const ArmatureDrawContext *ctx,
|
||||
OVERLAY_bone_instance_data_set_color(&inst_data, outline_color);
|
||||
DRW_buffer_add_entry_struct(ctx->point_outline, &inst_data);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Axes */
|
||||
static void drw_shgroup_bone_axes(const ArmatureDrawContext *ctx,
|
||||
static void drw_shgroup_bone_axes(const Armatures::DrawContext *ctx,
|
||||
const float (*bone_mat)[4],
|
||||
const float color[4])
|
||||
{
|
||||
float mat[4][4];
|
||||
mul_m4_m4m4(mat, ctx->ob->object_to_world().ptr(), bone_mat);
|
||||
float4x4 mat = ctx->ob->object_to_world() * float4x4(bone_mat);
|
||||
/* Move to bone tail. */
|
||||
add_v3_v3(mat[3], mat[1]);
|
||||
OVERLAY_empty_shape(ctx->extras, mat, 0.25f, OB_ARROWS, color);
|
||||
mat[3] += mat[1];
|
||||
if (ctx->is_overlay_next()) {
|
||||
ExtraInstanceData data(mat, color, 0.25f);
|
||||
/* NOTE: Axes are not drawn in bone selection (pose or edit mode).
|
||||
* They are only drawn and selectable in object mode. So only load the object select ID. */
|
||||
ctx->bone_buf->arrows_buf.append(data, ctx->res->select_id(*ctx->ob_ref));
|
||||
return;
|
||||
}
|
||||
#ifndef NO_LEGACY_OVERLAY
|
||||
OVERLAY_empty_shape(ctx->extras, mat.ptr(), 0.25f, OB_ARROWS, color);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Relationship lines */
|
||||
static void drw_shgroup_bone_relationship_lines_ex(const ArmatureDrawContext *ctx,
|
||||
static void drw_shgroup_bone_relationship_lines_ex(const Armatures::DrawContext *ctx,
|
||||
const float start[3],
|
||||
const float end[3],
|
||||
const float color[4])
|
||||
{
|
||||
float s[3], e[3];
|
||||
mul_v3_m4v3(s, ctx->ob->object_to_world().ptr(), start);
|
||||
mul_v3_m4v3(e, ctx->ob->object_to_world().ptr(), end);
|
||||
/* reverse order to have less stipple overlap */
|
||||
OVERLAY_extra_line_dashed(ctx->extras, s, e, color);
|
||||
float3 start_pt = math::transform_point(ctx->ob->object_to_world(), float3(start));
|
||||
float3 end_pt = math::transform_point(ctx->ob->object_to_world(), float3(end));
|
||||
|
||||
if (ctx->is_overlay_next()) {
|
||||
/* reverse order to have less stipple overlap */
|
||||
ctx->bone_buf->relations_buf.append(start_pt, end_pt, float4(color));
|
||||
}
|
||||
#ifndef NO_LEGACY_OVERLAY
|
||||
else {
|
||||
/* reverse order to have less stipple overlap */
|
||||
OVERLAY_extra_line_dashed(ctx->extras, start_pt, end_pt, color);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void drw_shgroup_bone_relationship_lines(const ArmatureDrawContext *ctx,
|
||||
static void drw_shgroup_bone_relationship_lines(const Armatures::DrawContext *ctx,
|
||||
const float start[3],
|
||||
const float end[3])
|
||||
{
|
||||
drw_shgroup_bone_relationship_lines_ex(ctx, start, end, G_draw.block.color_wire);
|
||||
}
|
||||
|
||||
static void drw_shgroup_bone_ik_lines(const ArmatureDrawContext *ctx,
|
||||
static void drw_shgroup_bone_ik_lines(const Armatures::DrawContext *ctx,
|
||||
const float start[3],
|
||||
const float end[3])
|
||||
{
|
||||
drw_shgroup_bone_relationship_lines_ex(ctx, start, end, G_draw.block.color_bone_ik_line);
|
||||
}
|
||||
|
||||
static void drw_shgroup_bone_ik_no_target_lines(const ArmatureDrawContext *ctx,
|
||||
static void drw_shgroup_bone_ik_no_target_lines(const Armatures::DrawContext *ctx,
|
||||
const float start[3],
|
||||
const float end[3])
|
||||
{
|
||||
@@ -1097,7 +1257,7 @@ static void drw_shgroup_bone_ik_no_target_lines(const ArmatureDrawContext *ctx,
|
||||
ctx, start, end, G_draw.block.color_bone_ik_line_no_target);
|
||||
}
|
||||
|
||||
static void drw_shgroup_bone_ik_spline_lines(const ArmatureDrawContext *ctx,
|
||||
static void drw_shgroup_bone_ik_spline_lines(const Armatures::DrawContext *ctx,
|
||||
const float start[3],
|
||||
const float end[3])
|
||||
{
|
||||
@@ -1114,7 +1274,7 @@ static void drw_shgroup_bone_ik_spline_lines(const ArmatureDrawContext *ctx,
|
||||
* \{ */
|
||||
|
||||
/* This function sets the color-set for coloring a certain bone */
|
||||
static void set_ctx_bcolor(ArmatureDrawContext *ctx, const UnifiedBonePtr bone)
|
||||
static void set_ctx_bcolor(Armatures::DrawContext *ctx, const UnifiedBonePtr bone)
|
||||
{
|
||||
bArmature *arm = static_cast<bArmature *>(ctx->ob->data);
|
||||
|
||||
@@ -1265,7 +1425,8 @@ static void bone_locked_color_shade(float color[4])
|
||||
interp_v3_v3v3(color, color, locked_color, locked_color[3]);
|
||||
}
|
||||
|
||||
static const float *get_bone_solid_color(const ArmatureDrawContext *ctx, const eBone_Flag boneflag)
|
||||
static const float *get_bone_solid_color(const Armatures::DrawContext *ctx,
|
||||
const eBone_Flag boneflag)
|
||||
{
|
||||
if (ctx->const_color) {
|
||||
return G_draw.block.color_bone_solid;
|
||||
@@ -1281,7 +1442,7 @@ static const float *get_bone_solid_color(const ArmatureDrawContext *ctx, const e
|
||||
return disp_color;
|
||||
}
|
||||
|
||||
static const float *get_bone_solid_with_consts_color(const ArmatureDrawContext *ctx,
|
||||
static const float *get_bone_solid_with_consts_color(const Armatures::DrawContext *ctx,
|
||||
const UnifiedBonePtr bone,
|
||||
const eBone_Flag boneflag)
|
||||
{
|
||||
@@ -1300,7 +1461,7 @@ static const float *get_bone_solid_with_consts_color(const ArmatureDrawContext *
|
||||
return consts_color;
|
||||
}
|
||||
|
||||
static float get_bone_wire_thickness(const ArmatureDrawContext *ctx, int boneflag)
|
||||
static float get_bone_wire_thickness(const Armatures::DrawContext *ctx, int boneflag)
|
||||
{
|
||||
if (ctx->const_color) {
|
||||
return ctx->const_wire;
|
||||
@@ -1312,7 +1473,8 @@ static float get_bone_wire_thickness(const ArmatureDrawContext *ctx, int bonefla
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
static const float *get_bone_wire_color(const ArmatureDrawContext *ctx, const eBone_Flag boneflag)
|
||||
static const float *get_bone_wire_color(const Armatures::DrawContext *ctx,
|
||||
const eBone_Flag boneflag)
|
||||
{
|
||||
static float disp_color[4];
|
||||
|
||||
@@ -1351,7 +1513,8 @@ static void bone_hint_color_shade(float hint_color[4], const float color[4])
|
||||
hint_color[3] = 1.0f;
|
||||
}
|
||||
|
||||
static const float *get_bone_hint_color(const ArmatureDrawContext *ctx, const eBone_Flag boneflag)
|
||||
static const float *get_bone_hint_color(const Armatures::DrawContext *ctx,
|
||||
const eBone_Flag boneflag)
|
||||
{
|
||||
static float hint_color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
|
||||
|
||||
@@ -1621,7 +1784,7 @@ static void draw_bone_update_disp_matrix_bbone(UnifiedBonePtr bone)
|
||||
draw_bone_update_disp_matrix_default(bone);
|
||||
}
|
||||
|
||||
static void draw_axes(const ArmatureDrawContext *ctx,
|
||||
static void draw_axes(const Armatures::DrawContext *ctx,
|
||||
const UnifiedBonePtr bone,
|
||||
const bArmature *arm)
|
||||
{
|
||||
@@ -1654,7 +1817,7 @@ static void draw_axes(const ArmatureDrawContext *ctx,
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_points(const ArmatureDrawContext *ctx,
|
||||
static void draw_points(const Armatures::DrawContext *ctx,
|
||||
const UnifiedBonePtr bone,
|
||||
const eBone_Flag boneflag,
|
||||
const float col_solid[4],
|
||||
@@ -1699,9 +1862,11 @@ static void draw_points(const ArmatureDrawContext *ctx,
|
||||
/* Draw root point if we are not connected to our parent */
|
||||
|
||||
if (!(bone.has_parent() && (boneflag & BONE_CONNECTED))) {
|
||||
if (select_id != -1) {
|
||||
#ifndef NO_LEGACY_OVERLAY
|
||||
if (!ctx->is_overlay_next() && select_id != -1) {
|
||||
DRW_select_load_id(select_id | BONESEL_ROOT);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (is_envelope_draw) {
|
||||
drw_shgroup_bone_envelope(ctx,
|
||||
@@ -1710,17 +1875,21 @@ static void draw_points(const ArmatureDrawContext *ctx,
|
||||
col_hint_root,
|
||||
col_wire_root,
|
||||
&bone.rad_head(),
|
||||
&envelope_ignore);
|
||||
&envelope_ignore,
|
||||
select_id | BONESEL_ROOT);
|
||||
}
|
||||
else {
|
||||
drw_shgroup_bone_point(ctx, bone.disp_mat(), col_solid, col_hint_root, col_wire_root);
|
||||
drw_shgroup_bone_sphere(
|
||||
ctx, bone.disp_mat(), col_solid, col_hint_root, col_wire_root, select_id | BONESEL_ROOT);
|
||||
}
|
||||
}
|
||||
|
||||
/* Draw tip point */
|
||||
if (select_id != -1) {
|
||||
#ifndef NO_LEGACY_OVERLAY
|
||||
if (!ctx->is_overlay_next() && select_id != -1) {
|
||||
DRW_select_load_id(select_id | BONESEL_TIP);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (is_envelope_draw) {
|
||||
drw_shgroup_bone_envelope(ctx,
|
||||
@@ -1729,15 +1898,23 @@ static void draw_points(const ArmatureDrawContext *ctx,
|
||||
col_hint_tail,
|
||||
col_wire_tail,
|
||||
&envelope_ignore,
|
||||
&bone.rad_tail());
|
||||
&bone.rad_tail(),
|
||||
select_id | BONESEL_TIP);
|
||||
}
|
||||
else {
|
||||
drw_shgroup_bone_point(ctx, bone.disp_tail_mat(), col_solid, col_hint_tail, col_wire_tail);
|
||||
drw_shgroup_bone_sphere(ctx,
|
||||
bone.disp_tail_mat(),
|
||||
col_solid,
|
||||
col_hint_tail,
|
||||
col_wire_tail,
|
||||
select_id | BONESEL_TIP);
|
||||
}
|
||||
|
||||
if (select_id != -1) {
|
||||
#ifndef NO_LEGACY_OVERLAY
|
||||
if (!ctx->is_overlay_next() && select_id != -1) {
|
||||
DRW_select_load_id(-1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/** \} */
|
||||
@@ -1746,17 +1923,14 @@ static void draw_points(const ArmatureDrawContext *ctx,
|
||||
/** \name Draw Degrees of Freedom
|
||||
* \{ */
|
||||
|
||||
static void draw_bone_degrees_of_freedom(const ArmatureDrawContext *ctx, const bPoseChannel *pchan)
|
||||
static void draw_bone_degrees_of_freedom(const Armatures::DrawContext *ctx,
|
||||
const bPoseChannel *pchan)
|
||||
{
|
||||
BoneInstanceData inst_data;
|
||||
float tmp[4][4], posetrans[4][4];
|
||||
float xminmax[2], zminmax[2];
|
||||
float color[4];
|
||||
|
||||
if (ctx->dof_sphere == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* *0.5f here comes from M_PI/360.0f when rotations were still in degrees */
|
||||
xminmax[0] = sinf(pchan->limitmin[0] * 0.5f);
|
||||
xminmax[1] = sinf(pchan->limitmax[0] * 0.5f);
|
||||
@@ -1780,27 +1954,59 @@ static void draw_bone_degrees_of_freedom(const ArmatureDrawContext *ctx, const b
|
||||
mul_m4_m4m4(posetrans, posetrans, tmp);
|
||||
|
||||
/* into world space. */
|
||||
mul_m4_m4m4(inst_data.mat, ctx->ob->object_to_world().ptr(), posetrans);
|
||||
inst_data.mat44 = ctx->ob->object_to_world() * float4x4(posetrans);
|
||||
|
||||
/* Not selectable. */
|
||||
auto sel_id = draw::select::SelectMap::select_invalid_id();
|
||||
|
||||
if ((pchan->ikflag & BONE_IK_XLIMIT) && (pchan->ikflag & BONE_IK_ZLIMIT)) {
|
||||
bone_instance_data_set_angle_minmax(
|
||||
&inst_data, xminmax[0], zminmax[0], xminmax[1], zminmax[1]);
|
||||
if (ctx->is_overlay_next()) {
|
||||
ExtraInstanceData data(
|
||||
inst_data.mat44, float4(0.25f), xminmax[0], zminmax[0], xminmax[1], zminmax[1]);
|
||||
|
||||
copy_v4_fl4(color, 0.25f, 0.25f, 0.25f, 0.25f);
|
||||
DRW_buffer_add_entry(ctx->dof_sphere, color, &inst_data);
|
||||
ctx->bone_buf->degrees_of_freedom_fill_buf.append(data, sel_id);
|
||||
ctx->bone_buf->degrees_of_freedom_wire_buf.append(data.with_color({0.0f, 0.0f, 0.0f, 1.0f}),
|
||||
sel_id);
|
||||
}
|
||||
#ifndef NO_LEGACY_OVERLAY
|
||||
else if (ctx->dof_sphere) {
|
||||
bone_instance_data_set_angle_minmax(
|
||||
&inst_data, xminmax[0], zminmax[0], xminmax[1], zminmax[1]);
|
||||
copy_v4_fl4(color, 0.25f, 0.25f, 0.25f, 0.25f);
|
||||
DRW_buffer_add_entry(ctx->dof_sphere, color, &inst_data);
|
||||
|
||||
copy_v4_fl4(color, 0.0f, 0.0f, 0.0f, 1.0f);
|
||||
DRW_buffer_add_entry(ctx->dof_lines, color, &inst_data);
|
||||
copy_v4_fl4(color, 0.0f, 0.0f, 0.0f, 1.0f);
|
||||
DRW_buffer_add_entry(ctx->dof_lines, color, &inst_data);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (pchan->ikflag & BONE_IK_XLIMIT) {
|
||||
bone_instance_data_set_angle_minmax(&inst_data, xminmax[0], 0.0f, xminmax[1], 0.0f);
|
||||
copy_v4_fl4(color, 1.0f, 0.0f, 0.0f, 1.0f);
|
||||
DRW_buffer_add_entry(ctx->dof_lines, color, &inst_data);
|
||||
if (ctx->is_overlay_next()) {
|
||||
ExtraInstanceData data(
|
||||
inst_data.mat44, float4(1.0f, 0.0f, 0.0f, 1.0f), xminmax[0], 0.0f, xminmax[1], 0.0f);
|
||||
ctx->bone_buf->degrees_of_freedom_wire_buf.append(data, sel_id);
|
||||
}
|
||||
#ifndef NO_LEGACY_OVERLAY
|
||||
else if (ctx->dof_sphere) {
|
||||
bone_instance_data_set_angle_minmax(&inst_data, xminmax[0], 0.0f, xminmax[1], 0.0f);
|
||||
copy_v4_fl4(color, 1.0f, 0.0f, 0.0f, 1.0f);
|
||||
DRW_buffer_add_entry(ctx->dof_lines, color, &inst_data);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (pchan->ikflag & BONE_IK_ZLIMIT) {
|
||||
bone_instance_data_set_angle_minmax(&inst_data, 0.0f, zminmax[0], 0.0f, zminmax[1]);
|
||||
copy_v4_fl4(color, 0.0f, 0.0f, 1.0f, 1.0f);
|
||||
DRW_buffer_add_entry(ctx->dof_lines, color, &inst_data);
|
||||
if (ctx->is_overlay_next()) {
|
||||
ExtraInstanceData data(
|
||||
inst_data.mat44, float4(0.0f, 0.0f, 1.0f, 1.0f), 0.0f, zminmax[0], 0.0f, zminmax[1]);
|
||||
ctx->bone_buf->degrees_of_freedom_wire_buf.append(data, sel_id);
|
||||
}
|
||||
#ifndef NO_LEGACY_OVERLAY
|
||||
else if (ctx->dof_sphere) {
|
||||
bone_instance_data_set_angle_minmax(&inst_data, 0.0f, zminmax[0], 0.0f, zminmax[1]);
|
||||
copy_v4_fl4(color, 0.0f, 0.0f, 1.0f, 1.0f);
|
||||
DRW_buffer_add_entry(ctx->dof_lines, color, &inst_data);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1810,7 +2016,7 @@ static void draw_bone_degrees_of_freedom(const ArmatureDrawContext *ctx, const b
|
||||
/** \name Draw Relationships
|
||||
* \{ */
|
||||
|
||||
static void pchan_draw_ik_lines(const ArmatureDrawContext *ctx,
|
||||
static void pchan_draw_ik_lines(const Armatures::DrawContext *ctx,
|
||||
const bPoseChannel *pchan,
|
||||
const bool only_temp)
|
||||
{
|
||||
@@ -1890,7 +2096,7 @@ static void pchan_draw_ik_lines(const ArmatureDrawContext *ctx,
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_bone_bone_relationship_line(const ArmatureDrawContext *ctx,
|
||||
static void draw_bone_bone_relationship_line(const Armatures::DrawContext *ctx,
|
||||
const float bone_head[3],
|
||||
const float parent_head[3],
|
||||
const float parent_tail[3])
|
||||
@@ -1903,7 +2109,7 @@ static void draw_bone_bone_relationship_line(const ArmatureDrawContext *ctx,
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_bone_relations(const ArmatureDrawContext *ctx,
|
||||
static void draw_bone_relations(const Armatures::DrawContext *ctx,
|
||||
const ArmatureBoneDrawStrategy &draw_strategy,
|
||||
const UnifiedBonePtr bone,
|
||||
const eBone_Flag boneflag)
|
||||
@@ -1937,7 +2143,7 @@ static void draw_bone_relations(const ArmatureDrawContext *ctx,
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_bone_name(const ArmatureDrawContext *ctx,
|
||||
static void draw_bone_name(const Armatures::DrawContext *ctx,
|
||||
const UnifiedBonePtr bone,
|
||||
const eBone_Flag boneflag)
|
||||
{
|
||||
@@ -2048,14 +2254,14 @@ class ArmatureBoneDrawStrategyEmpty : public ArmatureBoneDrawStrategy {
|
||||
return false;
|
||||
}
|
||||
|
||||
void draw_context_setup(ArmatureDrawContext * /*ctx*/,
|
||||
void draw_context_setup(Armatures::DrawContext * /*ctx*/,
|
||||
const OVERLAY_ArmatureCallBuffersInner * /*cb*/,
|
||||
const bool /*is_filled*/,
|
||||
const bool /*do_envelope_dist*/) const override
|
||||
{
|
||||
}
|
||||
|
||||
void draw_bone(const ArmatureDrawContext * /*ctx*/,
|
||||
void draw_bone(const Armatures::DrawContext * /*ctx*/,
|
||||
const UnifiedBonePtr /*bone*/,
|
||||
const eBone_Flag /*boneflag*/,
|
||||
const int /*select_id*/) const override
|
||||
@@ -2106,14 +2312,14 @@ class ArmatureBoneDrawStrategyCustomShape : public ArmatureBoneDrawStrategy {
|
||||
return pchan_culling_test_simple(view, ob, pchan);
|
||||
}
|
||||
|
||||
void draw_context_setup(ArmatureDrawContext * /*ctx*/,
|
||||
void draw_context_setup(Armatures::DrawContext * /*ctx*/,
|
||||
const OVERLAY_ArmatureCallBuffersInner * /*cb*/,
|
||||
const bool /*is_filled*/,
|
||||
const bool /*do_envelope_dist*/) const override
|
||||
{
|
||||
}
|
||||
|
||||
void draw_bone(const ArmatureDrawContext *ctx,
|
||||
void draw_bone(const Armatures::DrawContext *ctx,
|
||||
const UnifiedBonePtr bone,
|
||||
const eBone_Flag boneflag,
|
||||
const int select_id) const override
|
||||
@@ -2123,6 +2329,39 @@ class ArmatureBoneDrawStrategyCustomShape : public ArmatureBoneDrawStrategy {
|
||||
const float *col_hint = get_bone_hint_color(ctx, boneflag);
|
||||
const float(*disp_mat)[4] = bone.disp_mat();
|
||||
|
||||
if (ctx->is_overlay_next()) {
|
||||
/* TODO(fclem): Code after this scope should be removed when we remove the legacy code. */
|
||||
auto sel_id = ctx->res->select_id(*ctx->ob_ref, select_id | BONESEL_BONE);
|
||||
|
||||
/* Custom bone shapes are only supported in pose mode for now. */
|
||||
const bPoseChannel *pchan = bone.as_posebone();
|
||||
Object *custom_shape_ob = pchan->custom;
|
||||
|
||||
if (custom_shape_ob->type == OB_EMPTY) {
|
||||
if (custom_shape_ob->empty_drawtype != OB_EMPTY_IMAGE) {
|
||||
drw_shgroup_bone_custom_empty(
|
||||
ctx, disp_mat, col_wire, pchan->custom_shape_wire_width, sel_id, pchan->custom);
|
||||
}
|
||||
}
|
||||
else if (boneflag & (BONE_DRAWWIRE | BONE_DRAW_LOCKED_WEIGHT)) {
|
||||
drw_shgroup_bone_custom_wire(
|
||||
ctx, disp_mat, col_wire, pchan->custom_shape_wire_width, sel_id, pchan->custom);
|
||||
}
|
||||
else {
|
||||
drw_shgroup_bone_custom_solid(ctx,
|
||||
disp_mat,
|
||||
col_solid,
|
||||
col_hint,
|
||||
col_wire,
|
||||
pchan->custom_shape_wire_width,
|
||||
sel_id,
|
||||
pchan->custom);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef NO_LEGACY_OVERLAY
|
||||
if (select_id != -1) {
|
||||
DRW_select_load_id(select_id | BONESEL_BONE);
|
||||
}
|
||||
@@ -2133,7 +2372,13 @@ class ArmatureBoneDrawStrategyCustomShape : public ArmatureBoneDrawStrategy {
|
||||
if (pchan->custom->type == OB_EMPTY) {
|
||||
Object *ob = pchan->custom;
|
||||
if (ob->empty_drawtype != OB_EMPTY_IMAGE) {
|
||||
drw_shgroup_bone_custom_empty(ctx, disp_mat, col_wire, pchan->custom);
|
||||
drw_shgroup_bone_custom_empty(ctx,
|
||||
disp_mat,
|
||||
col_wire,
|
||||
pchan->custom_shape_wire_width,
|
||||
/* Dummy values for legacy pipeline. */
|
||||
draw::select::SelectMap::select_invalid_id(),
|
||||
pchan->custom);
|
||||
}
|
||||
}
|
||||
if ((boneflag & BONE_DRAWWIRE) == 0 && (boneflag & BONE_DRAW_LOCKED_WEIGHT) == 0) {
|
||||
@@ -2143,16 +2388,24 @@ class ArmatureBoneDrawStrategyCustomShape : public ArmatureBoneDrawStrategy {
|
||||
col_hint,
|
||||
col_wire,
|
||||
pchan->custom_shape_wire_width,
|
||||
/* Dummy values for legacy pipeline. */
|
||||
draw::select::SelectMap::select_invalid_id(),
|
||||
pchan->custom);
|
||||
}
|
||||
else {
|
||||
drw_shgroup_bone_custom_wire(
|
||||
ctx, disp_mat, col_wire, pchan->custom_shape_wire_width, pchan->custom);
|
||||
drw_shgroup_bone_custom_wire(ctx,
|
||||
disp_mat,
|
||||
col_wire,
|
||||
pchan->custom_shape_wire_width,
|
||||
/* Dummy values for legacy pipeline. */
|
||||
draw::select::SelectMap::select_invalid_id(),
|
||||
pchan->custom);
|
||||
}
|
||||
|
||||
if (select_id != -1) {
|
||||
DRW_select_load_id(-1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2174,7 +2427,7 @@ class ArmatureBoneDrawStrategyOcta : public ArmatureBoneDrawStrategy {
|
||||
return pchan_culling_test_with_radius_scale(view, ob, pchan, scale);
|
||||
}
|
||||
|
||||
void draw_context_setup(ArmatureDrawContext *ctx,
|
||||
void draw_context_setup(Armatures::DrawContext *ctx,
|
||||
const OVERLAY_ArmatureCallBuffersInner *cb,
|
||||
const bool is_filled,
|
||||
const bool /*do_envelope_dist*/) const override
|
||||
@@ -2183,7 +2436,7 @@ class ArmatureBoneDrawStrategyOcta : public ArmatureBoneDrawStrategy {
|
||||
ctx->solid = (is_filled) ? cb->octa_fill : nullptr;
|
||||
}
|
||||
|
||||
void draw_bone(const ArmatureDrawContext *ctx,
|
||||
void draw_bone(const Armatures::DrawContext *ctx,
|
||||
const UnifiedBonePtr bone,
|
||||
const eBone_Flag boneflag,
|
||||
const int select_id) const override
|
||||
@@ -2192,6 +2445,23 @@ class ArmatureBoneDrawStrategyOcta : public ArmatureBoneDrawStrategy {
|
||||
const float *col_wire = get_bone_wire_color(ctx, boneflag);
|
||||
const float *col_hint = get_bone_hint_color(ctx, boneflag);
|
||||
|
||||
if (ctx->is_overlay_next()) {
|
||||
/* TODO(fclem): Code after this scope should be removed when we remove the legacy code. */
|
||||
auto sel_id = ctx->res->select_id(*ctx->ob_ref, select_id | BONESEL_BONE);
|
||||
float4x4 bone_mat = ctx->ob->object_to_world() * float4x4(bone.disp_mat());
|
||||
|
||||
if (ctx->is_filled) {
|
||||
ctx->bone_buf->octahedral_fill_buf.append({bone_mat, col_solid, col_hint}, sel_id);
|
||||
}
|
||||
if (col_wire[3] > 0.0f) {
|
||||
ctx->bone_buf->octahedral_outline_buf.append({bone_mat, col_wire}, sel_id);
|
||||
}
|
||||
|
||||
draw_points(ctx, bone, boneflag, col_solid, select_id);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef NO_LEGACY_OVERLAY
|
||||
if (select_id != -1) {
|
||||
DRW_select_load_id(select_id | BONESEL_BONE);
|
||||
}
|
||||
@@ -2203,6 +2473,7 @@ class ArmatureBoneDrawStrategyOcta : public ArmatureBoneDrawStrategy {
|
||||
}
|
||||
|
||||
draw_points(ctx, bone, boneflag, col_solid, select_id);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2225,7 +2496,7 @@ class ArmatureBoneDrawStrategyLine : public ArmatureBoneDrawStrategy {
|
||||
return pchan_culling_test_with_radius_scale(view, ob, pchan, scale);
|
||||
}
|
||||
|
||||
void draw_context_setup(ArmatureDrawContext *ctx,
|
||||
void draw_context_setup(Armatures::DrawContext *ctx,
|
||||
const OVERLAY_ArmatureCallBuffersInner *cb,
|
||||
const bool /*is_filled*/,
|
||||
const bool /*do_envelope_dist*/) const override
|
||||
@@ -2233,7 +2504,7 @@ class ArmatureBoneDrawStrategyLine : public ArmatureBoneDrawStrategy {
|
||||
ctx->stick = cb->stick;
|
||||
}
|
||||
|
||||
void draw_bone(const ArmatureDrawContext *ctx,
|
||||
void draw_bone(const Armatures::DrawContext *ctx,
|
||||
const UnifiedBonePtr bone,
|
||||
const eBone_Flag boneflag,
|
||||
const int select_id) const override
|
||||
@@ -2266,23 +2537,58 @@ class ArmatureBoneDrawStrategyLine : public ArmatureBoneDrawStrategy {
|
||||
}
|
||||
|
||||
if (select_id == -1) {
|
||||
/* Not in selection mode, draw everything at once. */
|
||||
drw_shgroup_bone_stick(ctx, bone.disp_mat(), col_wire, col_bone, col_head, col_tail);
|
||||
/* Not in bone selection mode (can still be object select mode), draw everything at once. */
|
||||
drw_shgroup_bone_stick(
|
||||
ctx, bone.disp_mat(), col_wire, col_bone, col_head, col_tail, select_id);
|
||||
}
|
||||
else {
|
||||
/* In selection mode, draw bone, root and tip separately. */
|
||||
DRW_select_load_id(select_id | BONESEL_BONE);
|
||||
drw_shgroup_bone_stick(ctx, bone.disp_mat(), col_wire, col_bone, no_display, no_display);
|
||||
#ifndef NO_LEGACY_OVERLAY
|
||||
if (!ctx->is_overlay_next()) {
|
||||
DRW_select_load_id(select_id | BONESEL_BONE);
|
||||
}
|
||||
#endif
|
||||
drw_shgroup_bone_stick(ctx,
|
||||
bone.disp_mat(),
|
||||
col_wire,
|
||||
col_bone,
|
||||
no_display,
|
||||
no_display,
|
||||
select_id | BONESEL_BONE);
|
||||
|
||||
if (col_head[3] > 0.0f) {
|
||||
DRW_select_load_id(select_id | BONESEL_ROOT);
|
||||
drw_shgroup_bone_stick(ctx, bone.disp_mat(), col_wire, no_display, col_head, no_display);
|
||||
#ifndef NO_LEGACY_OVERLAY
|
||||
if (!ctx->is_overlay_next()) {
|
||||
DRW_select_load_id(select_id | BONESEL_ROOT);
|
||||
}
|
||||
#endif
|
||||
drw_shgroup_bone_stick(ctx,
|
||||
bone.disp_mat(),
|
||||
col_wire,
|
||||
no_display,
|
||||
col_head,
|
||||
no_display,
|
||||
select_id | BONESEL_ROOT);
|
||||
}
|
||||
|
||||
DRW_select_load_id(select_id | BONESEL_TIP);
|
||||
drw_shgroup_bone_stick(ctx, bone.disp_mat(), col_wire, no_display, no_display, col_tail);
|
||||
#ifndef NO_LEGACY_OVERLAY
|
||||
if (!ctx->is_overlay_next()) {
|
||||
DRW_select_load_id(select_id | BONESEL_TIP);
|
||||
}
|
||||
#endif
|
||||
drw_shgroup_bone_stick(ctx,
|
||||
bone.disp_mat(),
|
||||
col_wire,
|
||||
no_display,
|
||||
no_display,
|
||||
col_tail,
|
||||
select_id | BONESEL_TIP);
|
||||
|
||||
DRW_select_load_id(-1);
|
||||
#ifndef NO_LEGACY_OVERLAY
|
||||
if (!ctx->is_overlay_next()) {
|
||||
DRW_select_load_id(-1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -2317,7 +2623,7 @@ class ArmatureBoneDrawStrategyBBone : public ArmatureBoneDrawStrategy {
|
||||
return false;
|
||||
}
|
||||
|
||||
void draw_context_setup(ArmatureDrawContext *ctx,
|
||||
void draw_context_setup(Armatures::DrawContext *ctx,
|
||||
const OVERLAY_ArmatureCallBuffersInner *cb,
|
||||
const bool is_filled,
|
||||
const bool /*do_envelope_dist*/) const override
|
||||
@@ -2326,7 +2632,7 @@ class ArmatureBoneDrawStrategyBBone : public ArmatureBoneDrawStrategy {
|
||||
ctx->solid = (is_filled) ? cb->box_fill : nullptr;
|
||||
}
|
||||
|
||||
void draw_bone(const ArmatureDrawContext *ctx,
|
||||
void draw_bone(const Armatures::DrawContext *ctx,
|
||||
const UnifiedBonePtr bone,
|
||||
const eBone_Flag boneflag,
|
||||
const int select_id) const override
|
||||
@@ -2335,6 +2641,41 @@ class ArmatureBoneDrawStrategyBBone : public ArmatureBoneDrawStrategy {
|
||||
const float *col_wire = get_bone_wire_color(ctx, boneflag);
|
||||
const float *col_hint = get_bone_hint_color(ctx, boneflag);
|
||||
|
||||
if (ctx->is_overlay_next()) {
|
||||
/* TODO(fclem): Code after this scope should be removed when we remove the legacy code. */
|
||||
|
||||
/* NOTE: Cannot reinterpret as float4x4 because of alignment requirement of float4x4.
|
||||
* This would require a deeper refactor. */
|
||||
Span<Mat4> bbone_matrices;
|
||||
if (bone.is_posebone()) {
|
||||
bbone_matrices = {(Mat4 *)bone.as_posebone()->draw_data->bbone_matrix,
|
||||
bone.as_posebone()->bone->segments};
|
||||
}
|
||||
else {
|
||||
bbone_matrices = {(Mat4 *)bone.as_editbone()->disp_bbone_mat,
|
||||
bone.as_editbone()->segments};
|
||||
}
|
||||
|
||||
auto sel_id = ctx->res->select_id(*ctx->ob_ref, select_id | BONESEL_BONE);
|
||||
|
||||
for (const Mat4 &in_bone_mat : bbone_matrices) {
|
||||
float4x4 bone_mat = ctx->ob->object_to_world() * float4x4(in_bone_mat.mat);
|
||||
|
||||
if (ctx->is_filled) {
|
||||
ctx->bone_buf->bbones_fill_buf.append({bone_mat, col_solid, col_hint}, sel_id);
|
||||
}
|
||||
if (col_wire[3] > 0.0f) {
|
||||
ctx->bone_buf->bbones_outline_buf.append({bone_mat, col_wire}, sel_id);
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->draw_mode == ARM_DRAW_MODE_EDIT) {
|
||||
draw_points(ctx, bone, boneflag, col_solid, select_id);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef NO_LEGACY_OVERLAY
|
||||
if (select_id != -1) {
|
||||
DRW_select_load_id(select_id | BONESEL_BONE);
|
||||
}
|
||||
@@ -2362,6 +2703,7 @@ class ArmatureBoneDrawStrategyBBone : public ArmatureBoneDrawStrategy {
|
||||
if (bone.is_editbone()) {
|
||||
draw_points(ctx, bone, boneflag, col_solid, select_id);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2388,7 +2730,7 @@ class ArmatureBoneDrawStrategyEnvelope : public ArmatureBoneDrawStrategy {
|
||||
return DRW_culling_sphere_test(view, &bsphere);
|
||||
}
|
||||
|
||||
void draw_context_setup(ArmatureDrawContext *ctx,
|
||||
void draw_context_setup(Armatures::DrawContext *ctx,
|
||||
const OVERLAY_ArmatureCallBuffersInner *cb,
|
||||
const bool is_filled,
|
||||
const bool do_envelope_dist) const override
|
||||
@@ -2398,7 +2740,7 @@ class ArmatureBoneDrawStrategyEnvelope : public ArmatureBoneDrawStrategy {
|
||||
ctx->envelope_distance = (do_envelope_dist) ? cb->envelope_distance : nullptr;
|
||||
}
|
||||
|
||||
void draw_bone(const ArmatureDrawContext *ctx,
|
||||
void draw_bone(const Armatures::DrawContext *ctx,
|
||||
const UnifiedBonePtr bone,
|
||||
const eBone_Flag boneflag,
|
||||
const int select_id) const override
|
||||
@@ -2430,16 +2772,26 @@ class ArmatureBoneDrawStrategyEnvelope : public ArmatureBoneDrawStrategy {
|
||||
drw_shgroup_bone_envelope_distance(ctx, bone.disp_mat(), rad_head, rad_tail, distance);
|
||||
}
|
||||
|
||||
#ifndef NO_LEGACY_OVERLAY
|
||||
if (select_id != -1) {
|
||||
DRW_select_load_id(select_id | BONESEL_BONE);
|
||||
}
|
||||
#endif
|
||||
|
||||
drw_shgroup_bone_envelope(
|
||||
ctx, bone.disp_mat(), col_solid, col_hint, col_wire, rad_head, rad_tail);
|
||||
drw_shgroup_bone_envelope(ctx,
|
||||
bone.disp_mat(),
|
||||
col_solid,
|
||||
col_hint,
|
||||
col_wire,
|
||||
rad_head,
|
||||
rad_tail,
|
||||
select_id | BONESEL_BONE);
|
||||
|
||||
#ifndef NO_LEGACY_OVERLAY
|
||||
if (select_id != -1) {
|
||||
DRW_select_load_id(-1);
|
||||
}
|
||||
#endif
|
||||
|
||||
draw_points(ctx, bone, boneflag, col_solid, select_id);
|
||||
}
|
||||
@@ -2461,7 +2813,7 @@ class ArmatureBoneDrawStrategyWire : public ArmatureBoneDrawStrategy {
|
||||
return pchan_culling_test_simple(view, ob, pchan);
|
||||
}
|
||||
|
||||
void draw_context_setup(ArmatureDrawContext *ctx,
|
||||
void draw_context_setup(Armatures::DrawContext *ctx,
|
||||
const OVERLAY_ArmatureCallBuffersInner *cb,
|
||||
const bool /*is_filled*/,
|
||||
const bool /*do_envelope_dist*/) const override
|
||||
@@ -2470,36 +2822,54 @@ class ArmatureBoneDrawStrategyWire : public ArmatureBoneDrawStrategy {
|
||||
ctx->const_wire = 1.5f;
|
||||
}
|
||||
|
||||
void draw_bone(const ArmatureDrawContext *ctx,
|
||||
void draw_bone(const Armatures::DrawContext *ctx,
|
||||
const UnifiedBonePtr bone,
|
||||
const eBone_Flag boneflag,
|
||||
const int select_id) const override
|
||||
{
|
||||
using namespace blender::math;
|
||||
|
||||
const float *col_wire = get_bone_wire_color(ctx, boneflag);
|
||||
|
||||
if (select_id != -1) {
|
||||
#ifndef NO_LEGACY_OVERLAY
|
||||
if (!ctx->is_overlay_next() && select_id != -1) {
|
||||
DRW_select_load_id(select_id | BONESEL_BONE);
|
||||
}
|
||||
#endif
|
||||
|
||||
auto sel_id = (ctx->bone_buf) ? ctx->res->select_id(*ctx->ob_ref, select_id | BONESEL_BONE) :
|
||||
draw::select::SelectMap::select_invalid_id();
|
||||
|
||||
/* NOTE: Cannot reinterpret as float4x4 because of alignment requirement of float4x4.
|
||||
* This would require a deeper refactor. */
|
||||
Span<Mat4> bbone_matrices;
|
||||
if (bone.is_posebone()) {
|
||||
const bPoseChannel *pchan = bone.as_posebone();
|
||||
Mat4 *bbones_mat = (Mat4 *)pchan->draw_data->bbone_matrix;
|
||||
BLI_assert(bbones_mat != nullptr);
|
||||
|
||||
for (int i = pchan->bone->segments; i--; bbones_mat++) {
|
||||
drw_shgroup_bone_wire(ctx, bbones_mat->mat, col_wire);
|
||||
}
|
||||
bbone_matrices = {(Mat4 *)bone.as_posebone()->draw_data->bbone_matrix,
|
||||
bone.as_posebone()->bone->segments};
|
||||
}
|
||||
else {
|
||||
const EditBone *eBone = bone.as_editbone();
|
||||
for (int i = 0; i < eBone->segments; i++) {
|
||||
drw_shgroup_bone_wire(ctx, eBone->disp_bbone_mat[i], col_wire);
|
||||
bbone_matrices = {(Mat4 *)bone.as_editbone()->disp_bbone_mat, bone.as_editbone()->segments};
|
||||
}
|
||||
|
||||
for (const Mat4 &in_bone_mat : bbone_matrices) {
|
||||
float4x4 bmat = float4x4(in_bone_mat.mat);
|
||||
float3 head = transform_point(ctx->ob->object_to_world(), bmat.location());
|
||||
float3 tail = transform_point(ctx->ob->object_to_world(), bmat.location() + bmat.y_axis());
|
||||
|
||||
if (ctx->is_overlay_next()) {
|
||||
ctx->bone_buf->wire_buf.append(head, tail, float4(col_wire), sel_id);
|
||||
}
|
||||
else {
|
||||
DRW_buffer_add_entry(ctx->wire, head, col_wire);
|
||||
DRW_buffer_add_entry(ctx->wire, tail, col_wire);
|
||||
}
|
||||
}
|
||||
|
||||
if (select_id != -1) {
|
||||
#ifndef NO_LEGACY_OVERLAY
|
||||
if (!ctx->is_overlay_next() && select_id != -1) {
|
||||
DRW_select_load_id(-1);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (bone.is_editbone()) {
|
||||
const float *col_solid = get_bone_solid_with_consts_color(ctx, bone, boneflag);
|
||||
@@ -2556,7 +2926,7 @@ static ArmatureBoneDrawStrategy &strategy_for_armature_drawtype(const eArmature_
|
||||
/** \name Main Draw Loops
|
||||
* \{ */
|
||||
|
||||
static void draw_armature_edit(ArmatureDrawContext *ctx)
|
||||
void Armatures::draw_armature_edit(Armatures::DrawContext *ctx)
|
||||
{
|
||||
Object *ob = ctx->ob;
|
||||
EditBone *eBone;
|
||||
@@ -2577,7 +2947,9 @@ static void draw_armature_edit(ArmatureDrawContext *ctx)
|
||||
const ArmatureBoneDrawStrategy &draw_strat = strategy_for_armature_drawtype(
|
||||
eArmature_Drawtype(arm->drawtype));
|
||||
|
||||
for (eBone = static_cast<EditBone *>(arm->edbo->first), index = ob_orig->runtime->select_id;
|
||||
for (eBone = static_cast<EditBone *>(arm->edbo->first),
|
||||
/* Note: Selection Next handles the object id merging later. */
|
||||
index = ctx->bone_buf ? 0x0 : ob_orig->runtime->select_id;
|
||||
eBone;
|
||||
eBone = eBone->next, index += 0x10000)
|
||||
{
|
||||
@@ -2624,7 +2996,7 @@ static void draw_armature_edit(ArmatureDrawContext *ctx)
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_armature_pose(ArmatureDrawContext *ctx)
|
||||
void Armatures::draw_armature_pose(Armatures::DrawContext *ctx)
|
||||
{
|
||||
Object *ob = ctx->ob;
|
||||
const DRWContextState *draw_ctx = DRW_context_state_get();
|
||||
@@ -2667,7 +3039,8 @@ static void draw_armature_pose(ArmatureDrawContext *ctx)
|
||||
|
||||
if (is_pose_select) {
|
||||
const Object *ob_orig = DEG_get_original_object(ob);
|
||||
index = ob_orig->runtime->select_id;
|
||||
/* Note: Selection Next handles the object id merging later. */
|
||||
index = ctx->bone_buf ? 0x0 : ob_orig->runtime->select_id;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2698,6 +3071,9 @@ static void draw_armature_pose(ArmatureDrawContext *ctx)
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO(fclem): Remove global access. This is only used for culling in selection mode.
|
||||
* This is just a workaround for slow selection queries. Selection-next will not have this issue.
|
||||
*/
|
||||
const DRWView *view = is_pose_select ? DRW_view_default_get() : nullptr;
|
||||
|
||||
const ArmatureBoneDrawStrategy &draw_strat_normal = strategy_for_armature_drawtype(
|
||||
@@ -2768,13 +3144,14 @@ static void draw_armature_pose(ArmatureDrawContext *ctx)
|
||||
}
|
||||
}
|
||||
|
||||
static void armature_context_setup(ArmatureDrawContext *ctx,
|
||||
static void armature_context_setup(Armatures::DrawContext *ctx,
|
||||
OVERLAY_PrivateData *pd,
|
||||
Object *ob,
|
||||
const eArmatureDrawMode draw_mode,
|
||||
const float *const_color)
|
||||
{
|
||||
BLI_assert(BLI_memory_is_zero(ctx, sizeof(*ctx)));
|
||||
/* Not true anymore. */
|
||||
// BLI_assert(BLI_memory_is_zero(ctx, sizeof(*ctx)));
|
||||
const bool is_edit_or_pose_mode = draw_mode != ARM_DRAW_MODE_OBJECT;
|
||||
const bool is_xray = (ob->dtx & OB_DRAW_IN_FRONT) != 0 ||
|
||||
(pd->armature.do_pose_xray && draw_mode == ARM_DRAW_MODE_POSE);
|
||||
@@ -2805,6 +3182,7 @@ static void armature_context_setup(ArmatureDrawContext *ctx,
|
||||
ctx->const_wire = ((ob->base_flag & BASE_SELECTED) && (pd->v3d_flag & V3D_SELECT_OUTLINE) ?
|
||||
1.5f :
|
||||
((!is_filled || is_transparent) ? 1.0f : 0.0f));
|
||||
ctx->draw_envelope_distance = is_edit_or_pose_mode;
|
||||
ctx->draw_relation_from_head = (arm->flag & ARM_DRAW_RELATION_FROM_HEAD);
|
||||
|
||||
/* Call the draw strategy after setting the generic context properties, so
|
||||
@@ -2818,24 +3196,24 @@ static void armature_context_setup(ArmatureDrawContext *ctx,
|
||||
void OVERLAY_edit_armature_cache_populate(OVERLAY_Data *vedata, Object *ob)
|
||||
{
|
||||
OVERLAY_PrivateData *pd = vedata->stl->pd;
|
||||
ArmatureDrawContext arm_ctx = {nullptr};
|
||||
Armatures::DrawContext arm_ctx = {};
|
||||
armature_context_setup(&arm_ctx, pd, ob, ARM_DRAW_MODE_EDIT, nullptr);
|
||||
draw_armature_edit(&arm_ctx);
|
||||
Armatures::draw_armature_edit(&arm_ctx);
|
||||
}
|
||||
|
||||
void OVERLAY_pose_armature_cache_populate(OVERLAY_Data *vedata, Object *ob)
|
||||
{
|
||||
OVERLAY_PrivateData *pd = vedata->stl->pd;
|
||||
ArmatureDrawContext arm_ctx = {nullptr};
|
||||
Armatures::DrawContext arm_ctx = {};
|
||||
armature_context_setup(&arm_ctx, pd, ob, ARM_DRAW_MODE_POSE, nullptr);
|
||||
draw_armature_pose(&arm_ctx);
|
||||
Armatures::draw_armature_pose(&arm_ctx);
|
||||
}
|
||||
|
||||
void OVERLAY_armature_cache_populate(OVERLAY_Data *vedata, Object *ob)
|
||||
{
|
||||
const DRWContextState *draw_ctx = DRW_context_state_get();
|
||||
OVERLAY_PrivateData *pd = vedata->stl->pd;
|
||||
ArmatureDrawContext arm_ctx = {nullptr};
|
||||
Armatures::DrawContext arm_ctx = {};
|
||||
float *color;
|
||||
|
||||
if (ob->dt == OB_BOUNDBOX) {
|
||||
@@ -2844,7 +3222,7 @@ void OVERLAY_armature_cache_populate(OVERLAY_Data *vedata, Object *ob)
|
||||
|
||||
DRW_object_wire_theme_get(ob, draw_ctx->view_layer, &color);
|
||||
armature_context_setup(&arm_ctx, pd, ob, ARM_DRAW_MODE_OBJECT, color);
|
||||
draw_armature_pose(&arm_ctx);
|
||||
Armatures::draw_armature_pose(&arm_ctx);
|
||||
}
|
||||
|
||||
static bool POSE_is_driven_by_active_armature(Object *ob)
|
||||
|
||||
661
source/blender/draw/engines/overlay/overlay_next_armature.hh
Normal file
661
source/blender/draw/engines/overlay/overlay_next_armature.hh
Normal file
@@ -0,0 +1,661 @@
|
||||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup overlay
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ED_view3d.hh"
|
||||
|
||||
#include "overlay_next_private.hh"
|
||||
#include "overlay_shader_shared.h"
|
||||
|
||||
namespace blender::draw::overlay {
|
||||
using namespace blender;
|
||||
|
||||
enum eArmatureDrawMode {
|
||||
ARM_DRAW_MODE_OBJECT,
|
||||
ARM_DRAW_MODE_POSE,
|
||||
ARM_DRAW_MODE_EDIT,
|
||||
};
|
||||
|
||||
class Armatures {
|
||||
using EmptyInstanceBuf = ShapeInstanceBuf<ExtraInstanceData>;
|
||||
using BoneInstanceBuf = ShapeInstanceBuf<BoneInstanceData>;
|
||||
using BoneEnvelopeBuf = ShapeInstanceBuf<BoneEnvelopeData>;
|
||||
using BoneStickBuf = ShapeInstanceBuf<BoneStickData>;
|
||||
using DegreesOfFreedomBuf = ShapeInstanceBuf<ExtraInstanceData>;
|
||||
|
||||
private:
|
||||
const SelectionType selection_type_;
|
||||
|
||||
PassSimple armature_ps_ = {"Armature"};
|
||||
|
||||
/* Force transparent drawing in Xray mode. */
|
||||
bool draw_transparent = false;
|
||||
/* Force disable drawing relation is relations are off in viewport. */
|
||||
bool show_relations = false;
|
||||
/* Show selection state. */
|
||||
bool show_outline = false;
|
||||
|
||||
struct BoneBuffers {
|
||||
const SelectionType selection_type_;
|
||||
|
||||
/* Bone end points (joints). */
|
||||
PassSimple::Sub *sphere_fill = nullptr;
|
||||
PassSimple::Sub *sphere_outline = nullptr;
|
||||
/* Bone shapes. */
|
||||
PassSimple::Sub *shape_fill = nullptr;
|
||||
PassSimple::Sub *shape_outline = nullptr;
|
||||
/* Custom bone wire-frame. */
|
||||
PassSimple::Sub *shape_wire = nullptr;
|
||||
/* Envelopes. */
|
||||
PassSimple::Sub *envelope_fill = nullptr;
|
||||
PassSimple::Sub *envelope_outline = nullptr;
|
||||
PassSimple::Sub *envelope_distance = nullptr;
|
||||
/* Stick bones. */
|
||||
PassSimple::Sub *stick = nullptr;
|
||||
/* Wire bones. */
|
||||
PassSimple::Sub *wire = nullptr;
|
||||
|
||||
/* Bone axes. */
|
||||
PassSimple::Sub *arrows = nullptr;
|
||||
/* Degrees of freedom. */
|
||||
PassSimple::Sub *degrees_of_freedom_fill = nullptr;
|
||||
PassSimple::Sub *degrees_of_freedom_wire = nullptr;
|
||||
/* Relations. */
|
||||
PassSimple::Sub *relations = nullptr;
|
||||
|
||||
BoneInstanceBuf bbones_fill_buf = {selection_type_, "bbones_fill_buf"};
|
||||
BoneInstanceBuf bbones_outline_buf = {selection_type_, "bbones_outline_buf"};
|
||||
|
||||
BoneInstanceBuf octahedral_fill_buf = {selection_type_, "octahedral_fill_buf"};
|
||||
BoneInstanceBuf octahedral_outline_buf = {selection_type_, "octahedral_outline_buf"};
|
||||
|
||||
BoneInstanceBuf sphere_fill_buf = {selection_type_, "sphere_fill_buf"};
|
||||
BoneInstanceBuf sphere_outline_buf = {selection_type_, "sphere_outline_buf"};
|
||||
|
||||
BoneEnvelopeBuf envelope_fill_buf = {selection_type_, "envelope_fill_buf"};
|
||||
BoneEnvelopeBuf envelope_outline_buf = {selection_type_, "envelope_outline_buf"};
|
||||
BoneEnvelopeBuf envelope_distance_buf = {selection_type_, "envelope_distance_buf"};
|
||||
|
||||
BoneStickBuf stick_buf = {selection_type_, "stick_buf"};
|
||||
|
||||
LinePrimitiveBuf wire_buf = {selection_type_, "wire_buf"};
|
||||
|
||||
EmptyInstanceBuf arrows_buf = {selection_type_, "arrows_buf"};
|
||||
|
||||
DegreesOfFreedomBuf degrees_of_freedom_fill_buf = {SelectionType::DISABLED,
|
||||
"degrees_of_freedom_buf"};
|
||||
DegreesOfFreedomBuf degrees_of_freedom_wire_buf = {SelectionType::DISABLED,
|
||||
"degrees_of_freedom_buf"};
|
||||
|
||||
LinePrimitiveBuf relations_buf = {SelectionType::DISABLED, "relations_buf"};
|
||||
|
||||
Map<gpu::Batch *, std::unique_ptr<BoneInstanceBuf>> custom_shape_fill;
|
||||
Map<gpu::Batch *, std::unique_ptr<BoneInstanceBuf>> custom_shape_outline;
|
||||
Map<gpu::Batch *, std::unique_ptr<BoneInstanceBuf>> custom_shape_wire;
|
||||
|
||||
BoneInstanceBuf &custom_shape_fill_get_buffer(gpu::Batch *geom)
|
||||
{
|
||||
return *custom_shape_fill.lookup_or_add_cb(geom, [this]() {
|
||||
return std::make_unique<BoneInstanceBuf>(this->selection_type_, "CustomBoneSolid");
|
||||
});
|
||||
}
|
||||
|
||||
BoneInstanceBuf &custom_shape_outline_get_buffer(gpu::Batch *geom)
|
||||
{
|
||||
return *custom_shape_outline.lookup_or_add_cb(geom, [this]() {
|
||||
return std::make_unique<BoneInstanceBuf>(this->selection_type_, "CustomBoneOutline");
|
||||
});
|
||||
}
|
||||
|
||||
BoneInstanceBuf &custom_shape_wire_get_buffer(gpu::Batch *geom)
|
||||
{
|
||||
return *custom_shape_wire.lookup_or_add_cb(geom, [this]() {
|
||||
return std::make_unique<BoneInstanceBuf>(this->selection_type_, "CustomBoneWire");
|
||||
});
|
||||
}
|
||||
|
||||
BoneBuffers(const SelectionType selection_type) : selection_type_(selection_type){};
|
||||
};
|
||||
|
||||
BoneBuffers opaque_ = {selection_type_};
|
||||
BoneBuffers transparent_ = {selection_type_};
|
||||
|
||||
bool enabled_ = false;
|
||||
|
||||
public:
|
||||
Armatures(const SelectionType selection_type) : selection_type_(selection_type){};
|
||||
|
||||
void begin_sync(Resources &res, const State &state)
|
||||
{
|
||||
enabled_ = !(state.overlay.flag & V3D_OVERLAY_HIDE_BONES);
|
||||
|
||||
if (!enabled_) {
|
||||
return;
|
||||
}
|
||||
|
||||
const bool is_select_mode = (selection_type_ != SelectionType::DISABLED);
|
||||
|
||||
draw_transparent = (state.v3d->shading.type == OB_WIRE) || XRAY_FLAG_ENABLED(state.v3d);
|
||||
show_relations = !((state.v3d->flag & V3D_HIDE_HELPLINES) || is_select_mode);
|
||||
show_outline = (state.v3d->flag & V3D_SELECT_OUTLINE);
|
||||
|
||||
const bool do_smooth_wire = U.gpu_flag & USER_GPU_FLAG_OVERLAY_SMOOTH_WIRE;
|
||||
const float wire_alpha = state.overlay.bone_wire_alpha;
|
||||
/* Draw bone outlines and custom shape wire with a specific alpha. */
|
||||
const bool use_wire_alpha = (wire_alpha < 1.0f);
|
||||
|
||||
GPUTexture **depth_tex = (state.xray_enabled) ? &res.depth_tx : &res.dummy_depth_tx;
|
||||
|
||||
armature_ps_.init();
|
||||
res.select_bind(armature_ps_);
|
||||
|
||||
/* Envelope distances and degrees of freedom need to be drawn first as they use additive
|
||||
* transparent blending. */
|
||||
{
|
||||
DRWState transparent_state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL |
|
||||
DRW_STATE_BLEND_ADD;
|
||||
{
|
||||
auto &sub = armature_ps_.sub("opaque.envelope_distance");
|
||||
sub.state_set(transparent_state | DRW_STATE_CULL_FRONT, state.clipping_plane_count);
|
||||
sub.shader_set(res.shaders.armature_envelope_fill.get());
|
||||
sub.push_constant("alpha", 1.0f);
|
||||
sub.push_constant("isDistance", true);
|
||||
opaque_.envelope_distance = ⊂
|
||||
}
|
||||
if (use_wire_alpha) {
|
||||
auto &sub = armature_ps_.sub("transparent.envelope_distance");
|
||||
sub.state_set(transparent_state | DRW_STATE_CULL_FRONT, state.clipping_plane_count);
|
||||
sub.shader_set(res.shaders.armature_envelope_fill.get());
|
||||
sub.push_constant("alpha", wire_alpha);
|
||||
sub.push_constant("isDistance", true);
|
||||
transparent_.envelope_distance = ⊂
|
||||
}
|
||||
else {
|
||||
transparent_.envelope_distance = opaque_.envelope_distance;
|
||||
}
|
||||
|
||||
{
|
||||
auto &sub = armature_ps_.sub("opaque.degrees_of_freedom_fill");
|
||||
sub.state_set(transparent_state, state.clipping_plane_count);
|
||||
sub.shader_set(res.shaders.armature_degrees_of_freedom.get());
|
||||
sub.push_constant("alpha", 1.0f);
|
||||
sub.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
opaque_.degrees_of_freedom_fill = ⊂
|
||||
}
|
||||
if (use_wire_alpha) {
|
||||
auto &sub = armature_ps_.sub("transparent.degrees_of_freedom_fill");
|
||||
sub.state_set(transparent_state, state.clipping_plane_count);
|
||||
sub.shader_set(res.shaders.armature_degrees_of_freedom.get());
|
||||
sub.push_constant("alpha", wire_alpha);
|
||||
sub.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
transparent_.degrees_of_freedom_fill = ⊂
|
||||
}
|
||||
else {
|
||||
transparent_.degrees_of_freedom_fill = opaque_.degrees_of_freedom_fill;
|
||||
}
|
||||
}
|
||||
|
||||
DRWState default_state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL |
|
||||
DRW_STATE_WRITE_DEPTH;
|
||||
|
||||
/* Bone Shapes (Octahedral, Box, Custom Shapes, Spheres). */
|
||||
{
|
||||
{
|
||||
auto &sub = armature_ps_.sub("opaque.sphere_fill");
|
||||
sub.state_set(default_state, state.clipping_plane_count);
|
||||
sub.shader_set(res.shaders.armature_sphere_fill.get());
|
||||
sub.push_constant("alpha", 1.0f);
|
||||
opaque_.sphere_fill = ⊂
|
||||
}
|
||||
{
|
||||
auto &sub = armature_ps_.sub("transparent.sphere_fill");
|
||||
sub.state_set((default_state & ~DRW_STATE_WRITE_DEPTH) | DRW_STATE_BLEND_ALPHA,
|
||||
state.clipping_plane_count);
|
||||
sub.shader_set(res.shaders.armature_sphere_fill.get());
|
||||
sub.push_constant("alpha", wire_alpha * 0.4f);
|
||||
transparent_.sphere_fill = ⊂
|
||||
}
|
||||
|
||||
{
|
||||
auto &sub = armature_ps_.sub("opaque.shape_fill");
|
||||
sub.state_set(default_state, state.clipping_plane_count);
|
||||
sub.shader_set(res.shaders.armature_shape_fill.get());
|
||||
sub.push_constant("alpha", 1.0f);
|
||||
opaque_.shape_fill = ⊂
|
||||
}
|
||||
{
|
||||
auto &sub = armature_ps_.sub("transparent.shape_fill");
|
||||
sub.state_set((default_state & ~DRW_STATE_WRITE_DEPTH) | DRW_STATE_BLEND_ALPHA,
|
||||
state.clipping_plane_count);
|
||||
sub.shader_set(res.shaders.armature_shape_fill.get());
|
||||
sub.push_constant("alpha", wire_alpha * 0.6f);
|
||||
transparent_.shape_fill = ⊂
|
||||
}
|
||||
|
||||
{
|
||||
auto &sub = armature_ps_.sub("opaque.sphere_outline");
|
||||
sub.state_set(default_state, state.clipping_plane_count);
|
||||
sub.shader_set(res.shaders.armature_sphere_outline.get());
|
||||
sub.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
sub.push_constant("alpha", 1.0f);
|
||||
opaque_.sphere_outline = ⊂
|
||||
}
|
||||
if (use_wire_alpha) {
|
||||
auto &sub = armature_ps_.sub("transparent.sphere_outline");
|
||||
sub.state_set(default_state | DRW_STATE_BLEND_ALPHA, state.clipping_plane_count);
|
||||
sub.shader_set(res.shaders.armature_sphere_outline.get());
|
||||
sub.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
sub.push_constant("alpha", wire_alpha);
|
||||
transparent_.sphere_outline = ⊂
|
||||
}
|
||||
else {
|
||||
transparent_.sphere_outline = opaque_.sphere_outline;
|
||||
}
|
||||
|
||||
{
|
||||
auto &sub = armature_ps_.sub("opaque.shape_outline");
|
||||
sub.state_set(default_state, state.clipping_plane_count);
|
||||
sub.shader_set(res.shaders.armature_shape_outline.get());
|
||||
sub.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
sub.push_constant("alpha", 1.0f);
|
||||
opaque_.shape_outline = ⊂
|
||||
}
|
||||
if (use_wire_alpha) {
|
||||
auto &sub = armature_ps_.sub("transparent.shape_outline");
|
||||
sub.state_set(default_state | DRW_STATE_BLEND_ALPHA, state.clipping_plane_count);
|
||||
sub.shader_set(res.shaders.armature_shape_outline.get());
|
||||
sub.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
sub.bind_texture("depthTex", depth_tex);
|
||||
sub.push_constant("alpha", wire_alpha * 0.6f);
|
||||
sub.push_constant("do_smooth_wire", do_smooth_wire);
|
||||
transparent_.shape_outline = ⊂
|
||||
}
|
||||
else {
|
||||
transparent_.shape_outline = opaque_.shape_outline;
|
||||
}
|
||||
|
||||
{
|
||||
auto &sub = armature_ps_.sub("opaque.shape_wire");
|
||||
sub.state_set(default_state, state.clipping_plane_count);
|
||||
sub.shader_set(res.shaders.armature_shape_wire.get());
|
||||
sub.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
sub.push_constant("alpha", 1.0f);
|
||||
opaque_.shape_wire = ⊂
|
||||
}
|
||||
if (use_wire_alpha) {
|
||||
auto &sub = armature_ps_.sub("transparent.shape_wire");
|
||||
sub.state_set(default_state | DRW_STATE_BLEND_ALPHA, state.clipping_plane_count);
|
||||
sub.shader_set(res.shaders.armature_shape_wire.get());
|
||||
sub.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
sub.bind_texture("depthTex", depth_tex);
|
||||
sub.push_constant("alpha", wire_alpha * 0.6f);
|
||||
sub.push_constant("do_smooth_wire", do_smooth_wire);
|
||||
transparent_.shape_wire = ⊂
|
||||
}
|
||||
else {
|
||||
transparent_.shape_wire = opaque_.shape_wire;
|
||||
}
|
||||
}
|
||||
/* Degrees of freedom. */
|
||||
{
|
||||
{
|
||||
auto &sub = armature_ps_.sub("opaque.degrees_of_freedom_wire");
|
||||
sub.shader_set(res.shaders.armature_degrees_of_freedom.get());
|
||||
sub.push_constant("alpha", 1.0f);
|
||||
sub.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
opaque_.degrees_of_freedom_wire = ⊂
|
||||
}
|
||||
if (use_wire_alpha) {
|
||||
auto &sub = armature_ps_.sub("transparent.degrees_of_freedom_wire");
|
||||
sub.shader_set(res.shaders.armature_degrees_of_freedom.get());
|
||||
sub.push_constant("alpha", wire_alpha);
|
||||
sub.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
transparent_.degrees_of_freedom_wire = ⊂
|
||||
}
|
||||
else {
|
||||
transparent_.degrees_of_freedom_wire = opaque_.degrees_of_freedom_wire;
|
||||
}
|
||||
}
|
||||
/* Stick bones. */
|
||||
{
|
||||
{
|
||||
auto &sub = armature_ps_.sub("opaque.stick");
|
||||
sub.shader_set(res.shaders.armature_stick.get());
|
||||
sub.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
sub.push_constant("alpha", 1.0f);
|
||||
opaque_.stick = ⊂
|
||||
}
|
||||
if (use_wire_alpha) {
|
||||
auto &sub = armature_ps_.sub("transparent.stick");
|
||||
sub.state_set(default_state | DRW_STATE_BLEND_ALPHA, state.clipping_plane_count);
|
||||
sub.shader_set(res.shaders.armature_stick.get());
|
||||
sub.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
sub.push_constant("alpha", wire_alpha);
|
||||
transparent_.stick = ⊂
|
||||
}
|
||||
else {
|
||||
transparent_.stick = opaque_.stick;
|
||||
}
|
||||
}
|
||||
/* Envelopes. */
|
||||
{
|
||||
{
|
||||
auto &sub = armature_ps_.sub("opaque.envelope_fill");
|
||||
sub.state_set(default_state | DRW_STATE_CULL_BACK, state.clipping_plane_count);
|
||||
sub.shader_set(res.shaders.armature_envelope_fill.get());
|
||||
sub.push_constant("isDistance", false);
|
||||
sub.push_constant("alpha", 1.0f);
|
||||
opaque_.envelope_fill = ⊂
|
||||
}
|
||||
{
|
||||
auto &sub = armature_ps_.sub("transparent.envelope_fill");
|
||||
sub.state_set((default_state & ~DRW_STATE_WRITE_DEPTH) |
|
||||
(DRW_STATE_BLEND_ALPHA | DRW_STATE_CULL_BACK),
|
||||
state.clipping_plane_count);
|
||||
sub.shader_set(res.shaders.armature_envelope_fill.get());
|
||||
sub.push_constant("alpha", wire_alpha * 0.6f);
|
||||
transparent_.envelope_fill = ⊂
|
||||
}
|
||||
|
||||
{
|
||||
auto &sub = armature_ps_.sub("opaque.envelope_outline");
|
||||
sub.state_set(default_state | DRW_STATE_CULL_BACK, state.clipping_plane_count);
|
||||
sub.shader_set(res.shaders.armature_envelope_outline.get());
|
||||
sub.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
sub.push_constant("alpha", 1.0f);
|
||||
opaque_.envelope_outline = ⊂
|
||||
}
|
||||
if (use_wire_alpha) {
|
||||
auto &sub = armature_ps_.sub("transparent.envelope_outline");
|
||||
sub.state_set((default_state & ~DRW_STATE_WRITE_DEPTH) |
|
||||
(DRW_STATE_BLEND_ALPHA | DRW_STATE_CULL_BACK),
|
||||
state.clipping_plane_count);
|
||||
sub.shader_set(res.shaders.armature_envelope_outline.get());
|
||||
sub.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
sub.push_constant("alpha", wire_alpha);
|
||||
transparent_.envelope_outline = ⊂
|
||||
}
|
||||
else {
|
||||
transparent_.envelope_outline = opaque_.envelope_outline;
|
||||
}
|
||||
}
|
||||
{
|
||||
{
|
||||
auto &sub = armature_ps_.sub("opaque.wire");
|
||||
sub.shader_set(res.shaders.armature_wire.get());
|
||||
sub.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
sub.push_constant("alpha", 1.0f);
|
||||
opaque_.wire = ⊂
|
||||
}
|
||||
if (use_wire_alpha) {
|
||||
auto &sub = armature_ps_.sub("transparent.wire");
|
||||
sub.state_set(default_state | DRW_STATE_BLEND_ALPHA, state.clipping_plane_count);
|
||||
sub.shader_set(res.shaders.armature_wire.get());
|
||||
sub.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
sub.push_constant("alpha", wire_alpha);
|
||||
transparent_.wire = ⊂
|
||||
}
|
||||
else {
|
||||
transparent_.wire = opaque_.wire;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
auto &sub = armature_ps_.sub("opaque.arrow");
|
||||
sub.shader_set(res.shaders.extra_shape.get());
|
||||
sub.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
opaque_.arrows = ⊂
|
||||
transparent_.arrows = opaque_.arrows;
|
||||
}
|
||||
|
||||
{
|
||||
auto &sub = armature_ps_.sub("opaque.relations");
|
||||
sub.shader_set(res.shaders.extra_wire.get());
|
||||
sub.bind_ubo("globalsBlock", &res.globals_buf);
|
||||
opaque_.relations = ⊂
|
||||
transparent_.relations = opaque_.relations;
|
||||
}
|
||||
|
||||
auto shape_instance_bufs_begin_sync = [](BoneBuffers &bb) {
|
||||
bb.envelope_fill_buf.clear();
|
||||
bb.envelope_outline_buf.clear();
|
||||
bb.envelope_distance_buf.clear();
|
||||
bb.bbones_fill_buf.clear();
|
||||
bb.bbones_outline_buf.clear();
|
||||
bb.octahedral_fill_buf.clear();
|
||||
bb.octahedral_outline_buf.clear();
|
||||
bb.sphere_fill_buf.clear();
|
||||
bb.sphere_outline_buf.clear();
|
||||
bb.stick_buf.clear();
|
||||
bb.wire_buf.clear();
|
||||
bb.arrows_buf.clear();
|
||||
bb.degrees_of_freedom_fill_buf.clear();
|
||||
bb.degrees_of_freedom_wire_buf.clear();
|
||||
bb.relations_buf.clear();
|
||||
/* TODO(fclem): Potentially expensive operation recreating a lot of gpu buffers.
|
||||
* Prefer a pruning strategy. */
|
||||
bb.custom_shape_fill.clear();
|
||||
bb.custom_shape_outline.clear();
|
||||
bb.custom_shape_wire.clear();
|
||||
};
|
||||
|
||||
shape_instance_bufs_begin_sync(transparent_);
|
||||
shape_instance_bufs_begin_sync(opaque_);
|
||||
}
|
||||
|
||||
struct DrawContext {
|
||||
/* Current armature object */
|
||||
Object *ob = nullptr;
|
||||
const ObjectRef *ob_ref = nullptr;
|
||||
|
||||
/* Note: can be mutated inside `draw_armature_pose()`. */
|
||||
eArmatureDrawMode draw_mode = ARM_DRAW_MODE_OBJECT;
|
||||
eArmature_Drawtype drawtype = ARM_OCTA;
|
||||
|
||||
Armatures::BoneBuffers *bone_buf = nullptr;
|
||||
Resources *res = nullptr;
|
||||
const ShapeCache *shapes = nullptr;
|
||||
|
||||
/* TODO: Legacy structures to be removed after overlay next is shipped. */
|
||||
DRWCallBuffer *outline = nullptr;
|
||||
DRWCallBuffer *solid = nullptr;
|
||||
DRWCallBuffer *wire = nullptr;
|
||||
DRWCallBuffer *envelope_outline = nullptr;
|
||||
DRWCallBuffer *envelope_solid = nullptr;
|
||||
DRWCallBuffer *envelope_distance = nullptr;
|
||||
DRWCallBuffer *stick = nullptr;
|
||||
DRWCallBuffer *dof_lines = nullptr;
|
||||
DRWCallBuffer *dof_sphere = nullptr;
|
||||
DRWCallBuffer *point_solid = nullptr;
|
||||
DRWCallBuffer *point_outline = nullptr;
|
||||
DRWShadingGroup *custom_solid = nullptr;
|
||||
DRWShadingGroup *custom_outline = nullptr;
|
||||
DRWShadingGroup *custom_wire = nullptr;
|
||||
GHash *custom_shapes_ghash = nullptr;
|
||||
OVERLAY_ExtraCallBuffers *extras = nullptr;
|
||||
|
||||
/* Not a theme, this is an override. */
|
||||
const float *const_color = nullptr;
|
||||
/* Wire thickness. */
|
||||
float const_wire = 0.0f;
|
||||
|
||||
bool do_relations = false;
|
||||
bool transparent = false;
|
||||
bool show_relations = false;
|
||||
bool draw_envelope_distance = false;
|
||||
bool draw_relation_from_head = false;
|
||||
/* Draw the inner part of the bones, otherwise render just outlines. */
|
||||
bool is_filled = false;
|
||||
|
||||
const ThemeWireColor *bcolor = nullptr; /* pchan color */
|
||||
|
||||
DrawContext() = default;
|
||||
|
||||
/* Runtime switch between legacy and new overlay codebase.
|
||||
* Should be removed once the legacy code is removed. */
|
||||
bool is_overlay_next() const
|
||||
{
|
||||
return this->bone_buf != nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
DrawContext create_draw_context(const ObjectRef &ob_ref,
|
||||
Resources &res,
|
||||
const ShapeCache &shapes,
|
||||
const State &state,
|
||||
eArmatureDrawMode draw_mode)
|
||||
{
|
||||
bArmature *arm = static_cast<bArmature *>(ob_ref.object->data);
|
||||
|
||||
DrawContext ctx;
|
||||
ctx.ob = ob_ref.object;
|
||||
ctx.ob_ref = &ob_ref;
|
||||
ctx.res = &res;
|
||||
ctx.shapes = &shapes;
|
||||
ctx.draw_mode = draw_mode;
|
||||
ctx.drawtype = eArmature_Drawtype(arm->drawtype);
|
||||
|
||||
const bool is_edit_or_pose_mode = draw_mode != ARM_DRAW_MODE_OBJECT;
|
||||
const bool draw_as_wire = (ctx.ob->dt < OB_SOLID);
|
||||
const bool is_transparent = draw_transparent || (draw_as_wire && is_edit_or_pose_mode);
|
||||
|
||||
ctx.bone_buf = is_transparent ? &transparent_ : &opaque_;
|
||||
|
||||
ctx.is_filled = (!draw_transparent && !draw_as_wire) || is_edit_or_pose_mode;
|
||||
ctx.show_relations = show_relations;
|
||||
ctx.do_relations = show_relations && is_edit_or_pose_mode;
|
||||
ctx.draw_envelope_distance = is_edit_or_pose_mode;
|
||||
ctx.draw_relation_from_head = (arm->flag & ARM_DRAW_RELATION_FROM_HEAD);
|
||||
ctx.const_color = is_edit_or_pose_mode ? nullptr : &res.object_wire_color(ob_ref, state)[0];
|
||||
ctx.const_wire = (!ctx.is_filled || is_transparent) ? 1.0f : 0.0f;
|
||||
if ((ctx.ob->base_flag & BASE_SELECTED) && show_outline) {
|
||||
ctx.const_wire = 1.5f;
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void edit_object_sync(const ObjectRef &ob_ref,
|
||||
Resources &res,
|
||||
ShapeCache &shapes,
|
||||
const State &state)
|
||||
{
|
||||
if (!enabled_) {
|
||||
return;
|
||||
}
|
||||
|
||||
DrawContext ctx = create_draw_context(ob_ref, res, shapes, state, ARM_DRAW_MODE_EDIT);
|
||||
draw_armature_edit(&ctx);
|
||||
}
|
||||
|
||||
void object_sync(const ObjectRef &ob_ref,
|
||||
Resources &res,
|
||||
const ShapeCache &shapes,
|
||||
const State &state)
|
||||
{
|
||||
if (!enabled_ || ob_ref.object->dt == OB_BOUNDBOX) {
|
||||
return;
|
||||
}
|
||||
|
||||
eArmatureDrawMode draw_mode = is_pose_mode(ob_ref.object, state) ? ARM_DRAW_MODE_POSE :
|
||||
ARM_DRAW_MODE_OBJECT;
|
||||
|
||||
DrawContext ctx = create_draw_context(ob_ref, res, shapes, state, draw_mode);
|
||||
draw_armature_pose(&ctx);
|
||||
}
|
||||
|
||||
void end_sync(Resources & /*res*/, const ShapeCache &shapes, const State & /*state*/)
|
||||
{
|
||||
if (!enabled_) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto end_sync = [&](BoneBuffers &bb) {
|
||||
bb.sphere_fill_buf.end_sync(*bb.sphere_fill, shapes.bone_sphere.get());
|
||||
bb.sphere_outline_buf.end_sync(*bb.sphere_outline, shapes.bone_sphere_wire.get());
|
||||
|
||||
bb.octahedral_fill_buf.end_sync(*bb.shape_fill, shapes.bone_octahedron.get());
|
||||
bb.octahedral_outline_buf.end_sync(
|
||||
*bb.shape_outline, shapes.bone_octahedron_wire.get(), GPU_PRIM_LINES, 1);
|
||||
|
||||
bb.bbones_fill_buf.end_sync(*bb.shape_fill, shapes.bone_box.get());
|
||||
bb.bbones_outline_buf.end_sync(
|
||||
*bb.shape_outline, shapes.bone_box_wire.get(), GPU_PRIM_LINES, 1);
|
||||
|
||||
bb.envelope_fill_buf.end_sync(*bb.envelope_fill, shapes.bone_envelope.get());
|
||||
bb.envelope_outline_buf.end_sync(*bb.envelope_outline, shapes.bone_envelope_wire.get());
|
||||
bb.envelope_distance_buf.end_sync(*bb.envelope_distance, shapes.bone_envelope.get());
|
||||
|
||||
bb.stick_buf.end_sync(*bb.stick, shapes.bone_stick.get());
|
||||
|
||||
bb.wire_buf.end_sync(*bb.wire);
|
||||
|
||||
bb.arrows_buf.end_sync(*bb.arrows, shapes.arrows.get());
|
||||
|
||||
bb.degrees_of_freedom_fill_buf.end_sync(*bb.degrees_of_freedom_fill,
|
||||
shapes.bone_degrees_of_freedom.get());
|
||||
bb.degrees_of_freedom_wire_buf.end_sync(*bb.degrees_of_freedom_wire,
|
||||
shapes.bone_degrees_of_freedom_wire.get());
|
||||
|
||||
bb.relations_buf.end_sync(*bb.relations);
|
||||
|
||||
using CustomShapeBuf = MutableMapItem<gpu::Batch *, std::unique_ptr<BoneInstanceBuf>>;
|
||||
|
||||
for (CustomShapeBuf item : bb.custom_shape_fill.items()) {
|
||||
item.value->end_sync(*bb.shape_fill, item.key);
|
||||
}
|
||||
for (CustomShapeBuf item : bb.custom_shape_outline.items()) {
|
||||
item.value->end_sync(*bb.shape_outline, item.key, GPU_PRIM_LINES, 1);
|
||||
}
|
||||
for (CustomShapeBuf item : bb.custom_shape_wire.items()) {
|
||||
item.value->end_sync(*bb.shape_wire, item.key, GPU_PRIM_TRIS, 2);
|
||||
}
|
||||
};
|
||||
|
||||
end_sync(transparent_);
|
||||
end_sync(opaque_);
|
||||
}
|
||||
|
||||
void draw(Framebuffer &framebuffer, Manager &manager, View &view)
|
||||
{
|
||||
if (!enabled_) {
|
||||
return;
|
||||
}
|
||||
|
||||
GPU_framebuffer_bind(framebuffer);
|
||||
manager.submit(armature_ps_, view);
|
||||
}
|
||||
|
||||
/* Public for the time of the Overlay Next port to avoid duplicated logic. */
|
||||
public:
|
||||
static void draw_armature_pose(Armatures::DrawContext *ctx);
|
||||
static void draw_armature_edit(Armatures::DrawContext *ctx);
|
||||
|
||||
static bool is_pose_mode(const Object *armature_ob, const State &state)
|
||||
{
|
||||
Object *active_ob = state.active_base->object;
|
||||
|
||||
/* Armature is in pose mode. */
|
||||
if (((armature_ob == active_ob) || (armature_ob->mode & OB_MODE_POSE)) &&
|
||||
((state.object_mode & OB_MODE_POSE) != 0))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Active object is in weight paint and the associated armature is in pose mode. */
|
||||
if ((active_ob != nullptr) && (state.object_mode & OB_MODE_ALL_WEIGHT_PAINT)) {
|
||||
if (armature_ob == BKE_object_pose_armature_get(active_ob)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace blender::draw::overlay
|
||||
@@ -65,6 +65,10 @@ void Instance::init()
|
||||
state.overlay.wireframe_threshold = state.v3d->overlay.wireframe_threshold;
|
||||
state.overlay.wireframe_opacity = state.v3d->overlay.wireframe_opacity;
|
||||
}
|
||||
|
||||
state.do_pose_xray = (state.overlay.flag & V3D_OVERLAY_BONE_SELECT);
|
||||
state.do_pose_fade_geom = state.do_pose_xray && !(state.object_mode & OB_MODE_WEIGHT_PAINT) &&
|
||||
ctx->object_pose != nullptr;
|
||||
}
|
||||
|
||||
/* TODO(fclem): Remove DRW global usage. */
|
||||
@@ -73,10 +77,9 @@ void Instance::init()
|
||||
resources.weight_ramp_tx.wrap(G_draw.weight_ramp);
|
||||
{
|
||||
eGPUTextureUsage usage = GPU_TEXTURE_USAGE_SHADER_READ;
|
||||
if (resources.dummy_depth_tx.ensure_2d(GPU_DEPTH24_STENCIL8, int2(1, 1), usage)) {
|
||||
uint32_t data = 0;
|
||||
GPU_texture_update_sub(
|
||||
resources.dummy_depth_tx, GPU_DATA_UINT_24_8, &data, 0, 0, 0, 1, 1, 1);
|
||||
if (resources.dummy_depth_tx.ensure_2d(GPU_DEPTH_COMPONENT32F, int2(1, 1), usage)) {
|
||||
float data = 1.0f;
|
||||
GPU_texture_update_sub(resources.dummy_depth_tx, GPU_DATA_FLOAT, &data, 0, 0, 0, 1, 1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -95,6 +98,7 @@ void Instance::begin_sync()
|
||||
outline.begin_sync(resources, state);
|
||||
|
||||
auto begin_sync_layer = [&](OverlayLayer &layer) {
|
||||
layer.armatures.begin_sync(resources, state);
|
||||
layer.bounds.begin_sync();
|
||||
layer.cameras.begin_sync(resources, state, view);
|
||||
layer.curves.begin_sync(resources, state, view);
|
||||
@@ -131,8 +135,7 @@ void Instance::object_sync(ObjectRef &ob_ref, Manager &manager)
|
||||
ob_ref, in_edit_mode, in_paint_mode, in_sculpt_mode);
|
||||
const bool needs_prepass = !state.xray_enabled; /* TODO */
|
||||
|
||||
OverlayLayer &layer = (state.use_in_front && ob_ref.object->dtx & OB_DRAW_IN_FRONT) ? infront :
|
||||
regular;
|
||||
OverlayLayer &layer = object_is_in_front(ob_ref.object, state) ? infront : regular;
|
||||
|
||||
if (needs_prepass) {
|
||||
layer.prepass.object_sync(manager, ob_ref, resources);
|
||||
@@ -144,6 +147,7 @@ void Instance::object_sync(ObjectRef &ob_ref, Manager &manager)
|
||||
layer.meshes.edit_object_sync(manager, ob_ref, resources);
|
||||
break;
|
||||
case OB_ARMATURE:
|
||||
layer.armatures.edit_object_sync(ob_ref, resources, shapes, state);
|
||||
break;
|
||||
case OB_CURVES_LEGACY:
|
||||
layer.curves.edit_object_sync_legacy(manager, ob_ref, resources);
|
||||
@@ -177,6 +181,9 @@ void Instance::object_sync(ObjectRef &ob_ref, Manager &manager)
|
||||
layer.cameras.object_sync(ob_ref, shapes, manager, resources, state);
|
||||
break;
|
||||
case OB_ARMATURE:
|
||||
if (!in_edit_mode) {
|
||||
layer.armatures.object_sync(ob_ref, resources, shapes, state);
|
||||
}
|
||||
break;
|
||||
case OB_LATTICE:
|
||||
if (!in_edit_mode) {
|
||||
@@ -218,6 +225,7 @@ void Instance::end_sync()
|
||||
resources.end_sync();
|
||||
|
||||
auto end_sync_layer = [&](OverlayLayer &layer) {
|
||||
layer.armatures.end_sync(resources, shapes, state);
|
||||
layer.bounds.end_sync(resources, shapes, state);
|
||||
layer.cameras.end_sync(resources, shapes, state);
|
||||
layer.empties.end_sync(resources, shapes, state);
|
||||
@@ -364,6 +372,7 @@ void Instance::draw(Manager &manager)
|
||||
layer.relations.draw(framebuffer, manager, view);
|
||||
layer.fluids.draw(framebuffer, manager, view);
|
||||
layer.particles.draw(framebuffer, manager, view);
|
||||
layer.armatures.draw(framebuffer, manager, view);
|
||||
layer.meshes.draw(framebuffer, manager, view);
|
||||
};
|
||||
|
||||
@@ -484,21 +493,24 @@ bool Instance::object_is_edit_mode(const Object *object)
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace blender::draw::overlay
|
||||
|
||||
#include "overlay_private.hh"
|
||||
|
||||
/* TODO(fclem): Move elsewhere. */
|
||||
BoneInstanceData::BoneInstanceData(Object *ob,
|
||||
const float *pos,
|
||||
const float radius,
|
||||
const float color[4])
|
||||
bool Instance::object_is_in_front(const Object *object, const State &state)
|
||||
{
|
||||
/* TODO(fclem): Use C++ math API. */
|
||||
mul_v3_v3fl(this->mat[0], ob->object_to_world().ptr()[0], radius);
|
||||
mul_v3_v3fl(this->mat[1], ob->object_to_world().ptr()[1], radius);
|
||||
mul_v3_v3fl(this->mat[2], ob->object_to_world().ptr()[2], radius);
|
||||
mul_v3_m4v3(this->mat[3], ob->object_to_world().ptr(), pos);
|
||||
/* WATCH: Reminder, alpha is wire-size. */
|
||||
OVERLAY_bone_instance_data_set_color(this, color);
|
||||
switch (object->type) {
|
||||
case OB_ARMATURE:
|
||||
return (object->dtx & OB_DRAW_IN_FRONT) ||
|
||||
(state.do_pose_xray && Armatures::is_pose_mode(object, state));
|
||||
case OB_MESH:
|
||||
case OB_CURVES_LEGACY:
|
||||
case OB_SURF:
|
||||
case OB_LATTICE:
|
||||
case OB_MBALL:
|
||||
case OB_FONT:
|
||||
case OB_CURVES:
|
||||
case OB_POINTCLOUD:
|
||||
case OB_VOLUME:
|
||||
return state.use_in_front && (object->dtx & OB_DRAW_IN_FRONT);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace blender::draw::overlay
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "overlay_next_private.hh"
|
||||
|
||||
#include "overlay_next_antialiasing.hh"
|
||||
#include "overlay_next_armature.hh"
|
||||
#include "overlay_next_background.hh"
|
||||
#include "overlay_next_bounds.hh"
|
||||
#include "overlay_next_camera.hh"
|
||||
@@ -62,6 +63,7 @@ class Instance {
|
||||
struct OverlayLayer {
|
||||
const SelectionType selection_type_;
|
||||
|
||||
Armatures armatures = {selection_type_};
|
||||
Bounds bounds = {selection_type_};
|
||||
Cameras cameras = {selection_type_};
|
||||
Curves curves;
|
||||
@@ -119,6 +121,7 @@ class Instance {
|
||||
bool in_edit_mode,
|
||||
bool in_paint_mode,
|
||||
bool in_sculpt_mode);
|
||||
bool object_is_in_front(const Object *object, const State &state);
|
||||
};
|
||||
|
||||
} // namespace blender::draw::overlay
|
||||
|
||||
@@ -35,7 +35,8 @@ class Metaballs {
|
||||
|
||||
void edit_object_sync(const ObjectRef &ob_ref, Resources &res)
|
||||
{
|
||||
MetaBall *mb = static_cast<MetaBall *>(ob_ref.object->data);
|
||||
const Object *ob = ob_ref.object;
|
||||
const MetaBall *mb = static_cast<MetaBall *>(ob->data);
|
||||
|
||||
const float *color;
|
||||
const float *col_radius = res.theme_settings.color_mball_radius;
|
||||
@@ -48,28 +49,31 @@ class Metaballs {
|
||||
const bool is_selected = (ml->flag & SELECT) != 0;
|
||||
const bool is_scale_radius = (ml->flag & MB_SCALE_RAD) != 0;
|
||||
const float stiffness_radius = ml->rad * atanf(ml->s) * 2.0f / math::numbers::pi;
|
||||
const float3 position = float3(&ml->x);
|
||||
|
||||
const select::ID radius_id = res.select_id(ob_ref, MBALLSEL_RADIUS | elem_num);
|
||||
color = (is_selected && is_scale_radius) ? col_radius_select : col_radius;
|
||||
circle_buf_.append({ob_ref.object, &ml->x, ml->rad, color}, radius_id);
|
||||
circle_buf_.append({ob->object_to_world(), position, ml->rad, color}, radius_id);
|
||||
|
||||
const select::ID stiff_id = res.select_id(ob_ref, MBALLSEL_STIFF | elem_num);
|
||||
color = (is_selected && !is_scale_radius) ? col_stiffness_select : col_stiffness;
|
||||
circle_buf_.append({ob_ref.object, &ml->x, stiffness_radius, color}, stiff_id);
|
||||
circle_buf_.append({ob->object_to_world(), position, stiffness_radius, color}, stiff_id);
|
||||
elem_num += 1 << 16;
|
||||
}
|
||||
}
|
||||
|
||||
void object_sync(const ObjectRef &ob_ref, Resources &res, const State &state)
|
||||
{
|
||||
MetaBall *mb = static_cast<MetaBall *>(ob_ref.object->data);
|
||||
const Object *ob = ob_ref.object;
|
||||
const MetaBall *mb = static_cast<MetaBall *>(ob->data);
|
||||
|
||||
const float4 &color = res.object_wire_color(ob_ref, state);
|
||||
const select::ID select_id = res.select_id(ob_ref);
|
||||
|
||||
LISTBASE_FOREACH (MetaElem *, ml, &mb->elems) {
|
||||
const float3 position = float3(&ml->x);
|
||||
/* Draw radius only. */
|
||||
circle_buf_.append({ob_ref.object, &ml->x, ml->rad, color}, select_id);
|
||||
circle_buf_.append({ob->object_to_world(), position, ml->rad, color}, select_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -55,6 +55,10 @@ struct State {
|
||||
bool hide_overlays;
|
||||
bool xray_enabled;
|
||||
bool xray_enabled_and_not_wire;
|
||||
/* Brings the active pose armature in front of all objects. */
|
||||
bool do_pose_xray;
|
||||
/* Add a veil on top of all surfaces to make the active pose armature pop out. */
|
||||
bool do_pose_fade_geom;
|
||||
float xray_opacity;
|
||||
short v3d_flag; /* TODO: move to #View3DOverlay. */
|
||||
short v3d_gridflag; /* TODO: move to #View3DOverlay. */
|
||||
@@ -95,6 +99,19 @@ class ShapeCache {
|
||||
using BatchPtr = std::unique_ptr<gpu::Batch, BatchDeleter>;
|
||||
|
||||
public:
|
||||
BatchPtr bone_box;
|
||||
BatchPtr bone_box_wire;
|
||||
BatchPtr bone_envelope;
|
||||
BatchPtr bone_envelope_wire;
|
||||
BatchPtr bone_octahedron;
|
||||
BatchPtr bone_octahedron_wire;
|
||||
BatchPtr bone_sphere;
|
||||
BatchPtr bone_sphere_wire;
|
||||
BatchPtr bone_stick;
|
||||
|
||||
BatchPtr bone_degrees_of_freedom;
|
||||
BatchPtr bone_degrees_of_freedom_wire;
|
||||
|
||||
BatchPtr quad_wire;
|
||||
BatchPtr quad_solid;
|
||||
BatchPtr plain_axes;
|
||||
@@ -172,6 +189,7 @@ class ShaderModule {
|
||||
public:
|
||||
/** Shaders */
|
||||
ShaderPtr anti_aliasing = shader("overlay_antialiasing");
|
||||
ShaderPtr armature_degrees_of_freedom;
|
||||
ShaderPtr background_fill = shader("overlay_background");
|
||||
ShaderPtr background_clip_bound = shader("overlay_clipbound");
|
||||
ShaderPtr curve_edit_points;
|
||||
@@ -201,7 +219,15 @@ class ShaderModule {
|
||||
ShaderPtr xray_fade;
|
||||
|
||||
/** Selectable Shaders */
|
||||
ShaderPtr armature_envelope_fill;
|
||||
ShaderPtr armature_envelope_outline;
|
||||
ShaderPtr armature_shape_outline;
|
||||
ShaderPtr armature_shape_fill;
|
||||
ShaderPtr armature_shape_wire;
|
||||
ShaderPtr armature_sphere_outline;
|
||||
ShaderPtr armature_sphere_fill;
|
||||
ShaderPtr armature_stick;
|
||||
ShaderPtr armature_wire;
|
||||
ShaderPtr depth_mesh;
|
||||
ShaderPtr extra_grid;
|
||||
ShaderPtr extra_shape;
|
||||
@@ -447,6 +473,21 @@ template<typename InstanceDataT> struct ShapeInstanceBuf : private select::Selec
|
||||
pass.bind_ssbo("data_buf", &data_buf);
|
||||
pass.draw(shape, data_buf.size());
|
||||
}
|
||||
|
||||
void end_sync(PassSimple::Sub &pass,
|
||||
gpu::Batch *shape,
|
||||
GPUPrimType primitive_type,
|
||||
uint primitive_len)
|
||||
{
|
||||
if (data_buf.is_empty()) {
|
||||
return;
|
||||
}
|
||||
this->select_bind(pass);
|
||||
data_buf.push_update();
|
||||
pass.bind_ssbo("data_buf", &data_buf);
|
||||
pass.draw_expand(
|
||||
shape, primitive_type, primitive_len, data_buf.size(), ResourceHandle(0), uint(0));
|
||||
}
|
||||
};
|
||||
|
||||
struct VertexPrimitiveBuf {
|
||||
|
||||
@@ -116,6 +116,15 @@ ShaderModule::ShaderModule(const SelectionType selection_type, const bool clippi
|
||||
{
|
||||
/** Shaders */
|
||||
|
||||
armature_degrees_of_freedom = shader(
|
||||
"overlay_armature_dof", [](gpu::shader::ShaderCreateInfo &info) {
|
||||
info.storage_buf(0, Qualifier::READ, "ExtraInstanceData", "data_buf[]");
|
||||
info.define("inst_obmat", "data_buf[gl_InstanceID].object_to_world_");
|
||||
info.define("color", "data_buf[gl_InstanceID].color_");
|
||||
info.vertex_inputs_.pop_last();
|
||||
info.vertex_inputs_.pop_last();
|
||||
});
|
||||
|
||||
curve_edit_points = shader(
|
||||
"overlay_edit_particle_point",
|
||||
[](gpu::shader::ShaderCreateInfo &info) { shader_patch_common(info); });
|
||||
@@ -225,12 +234,100 @@ ShaderModule::ShaderModule(const SelectionType selection_type, const bool clippi
|
||||
|
||||
/** Selectable Shaders */
|
||||
|
||||
armature_envelope_fill = selectable_shader(
|
||||
"overlay_armature_envelope_solid", [](gpu::shader::ShaderCreateInfo &info) {
|
||||
info.storage_buf(0, Qualifier::READ, "BoneEnvelopeData", "data_buf[]");
|
||||
info.define("headSphere", "data_buf[gl_InstanceID].head_sphere");
|
||||
info.define("tailSphere", "data_buf[gl_InstanceID].tail_sphere");
|
||||
info.define("xAxis", "data_buf[gl_InstanceID].x_axis.xyz");
|
||||
info.define("stateColor", "data_buf[gl_InstanceID].state_color.xyz");
|
||||
info.define("boneColor", "data_buf[gl_InstanceID].bone_color_and_wire_width.xyz");
|
||||
info.vertex_inputs_.pop_last();
|
||||
info.vertex_inputs_.pop_last();
|
||||
info.vertex_inputs_.pop_last();
|
||||
info.vertex_inputs_.pop_last();
|
||||
info.vertex_inputs_.pop_last();
|
||||
});
|
||||
|
||||
armature_envelope_outline = selectable_shader(
|
||||
"overlay_armature_envelope_outline", [](gpu::shader::ShaderCreateInfo &info) {
|
||||
info.storage_buf(0, Qualifier::READ, "BoneEnvelopeData", "data_buf[]");
|
||||
info.define("headSphere", "data_buf[gl_InstanceID].head_sphere");
|
||||
info.define("tailSphere", "data_buf[gl_InstanceID].tail_sphere");
|
||||
info.define("outlineColorSize", "data_buf[gl_InstanceID].bone_color_and_wire_width");
|
||||
info.define("xAxis", "data_buf[gl_InstanceID].x_axis.xyz");
|
||||
info.vertex_inputs_.pop_last();
|
||||
info.vertex_inputs_.pop_last();
|
||||
info.vertex_inputs_.pop_last();
|
||||
info.vertex_inputs_.pop_last();
|
||||
});
|
||||
|
||||
armature_shape_outline = selectable_shader("overlay_armature_shape_outline_next",
|
||||
[](gpu::shader::ShaderCreateInfo & /*info*/) {});
|
||||
|
||||
armature_shape_fill = selectable_shader(
|
||||
"overlay_armature_shape_solid", [](gpu::shader::ShaderCreateInfo &info) {
|
||||
info.storage_buf(0, Qualifier::READ, "mat4", "data_buf[]");
|
||||
info.define("inst_obmat", "data_buf[gl_InstanceID]");
|
||||
info.vertex_inputs_.pop_last();
|
||||
});
|
||||
|
||||
armature_shape_wire = selectable_shader("overlay_armature_shape_wire_next",
|
||||
[](gpu::shader::ShaderCreateInfo & /*info*/) {});
|
||||
|
||||
armature_sphere_outline = selectable_shader(
|
||||
"overlay_armature_sphere_outline", [](gpu::shader::ShaderCreateInfo &info) {
|
||||
info.storage_buf(0, Qualifier::READ, "mat4", "data_buf[]");
|
||||
info.define("inst_obmat", "data_buf[gl_InstanceID]");
|
||||
info.vertex_inputs_.pop_last();
|
||||
});
|
||||
armature_sphere_fill = selectable_shader(
|
||||
"overlay_armature_sphere_solid", [](gpu::shader::ShaderCreateInfo &info) {
|
||||
info.storage_buf(0, Qualifier::READ, "mat4", "data_buf[]");
|
||||
info.define("inst_obmat", "data_buf[gl_InstanceID]");
|
||||
info.vertex_inputs_.pop_last();
|
||||
});
|
||||
|
||||
armature_stick = selectable_shader(
|
||||
"overlay_armature_stick", [](gpu::shader::ShaderCreateInfo &info) {
|
||||
info.additional_infos_.clear();
|
||||
info.additional_info("overlay_frag_output",
|
||||
"overlay_armature_common",
|
||||
"draw_resource_handle_new",
|
||||
"draw_modelmat_new",
|
||||
"draw_globals");
|
||||
info.storage_buf(0, Qualifier::READ, "BoneStickData", "data_buf[]");
|
||||
info.define("boneStart", "data_buf[gl_InstanceID].bone_start.xyz");
|
||||
info.define("boneEnd", "data_buf[gl_InstanceID].bone_end.xyz");
|
||||
info.define("wireColor", "data_buf[gl_InstanceID].wire_color");
|
||||
info.define("boneColor", "data_buf[gl_InstanceID].bone_color");
|
||||
info.define("headColor", "data_buf[gl_InstanceID].head_color");
|
||||
info.define("tailColor", "data_buf[gl_InstanceID].tail_color");
|
||||
info.vertex_inputs_.pop_last();
|
||||
info.vertex_inputs_.pop_last();
|
||||
info.vertex_inputs_.pop_last();
|
||||
info.vertex_inputs_.pop_last();
|
||||
info.vertex_inputs_.pop_last();
|
||||
info.vertex_inputs_.pop_last();
|
||||
info.vertex_inputs_.pop_last();
|
||||
info.vertex_in(1, gpu::shader::Type::INT, "vclass");
|
||||
info.define("flag", "vclass");
|
||||
});
|
||||
|
||||
armature_wire = selectable_shader(
|
||||
"overlay_armature_wire", [](gpu::shader::ShaderCreateInfo &info) {
|
||||
info.additional_infos_.clear();
|
||||
info.additional_info("draw_view",
|
||||
"overlay_frag_output",
|
||||
"draw_resource_handle_new",
|
||||
"draw_modelmat_new",
|
||||
"draw_globals");
|
||||
info.storage_buf(0, Qualifier::READ, "VertexData", "data_buf[]");
|
||||
info.define("pos", "data_buf[gl_VertexID].pos_.xyz");
|
||||
info.define("color", "data_buf[gl_VertexID].color_");
|
||||
info.vertex_inputs_.pop_last();
|
||||
info.vertex_inputs_.pop_last();
|
||||
});
|
||||
|
||||
depth_mesh = selectable_shader("overlay_depth_only", [](gpu::shader::ShaderCreateInfo &info) {
|
||||
info.additional_infos_.clear();
|
||||
|
||||
@@ -22,6 +22,13 @@ struct VertShaded {
|
||||
float3 nor;
|
||||
};
|
||||
|
||||
/* TODO(fclem): Might be good to remove for simplicity. */
|
||||
struct VertexTriple {
|
||||
float2 pos0;
|
||||
float2 pos1;
|
||||
float2 pos2;
|
||||
};
|
||||
|
||||
/* Caller gets ownership of the #gpu::VertBuf. */
|
||||
static gpu::VertBuf *vbo_from_vector(const Vector<Vertex> &vector)
|
||||
{
|
||||
@@ -52,6 +59,21 @@ static gpu::VertBuf *vbo_from_vector(Vector<VertShaded> &vector)
|
||||
return vbo;
|
||||
}
|
||||
|
||||
static gpu::VertBuf *vbo_from_vector(Vector<VertexTriple> &vector)
|
||||
{
|
||||
static GPUVertFormat format = {0};
|
||||
if (format.attr_len == 0) {
|
||||
GPU_vertformat_attr_add(&format, "pos0", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
||||
GPU_vertformat_attr_add(&format, "pos1", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
||||
GPU_vertformat_attr_add(&format, "pos2", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
||||
}
|
||||
|
||||
gpu::VertBuf *vbo = GPU_vertbuf_create_with_format(format);
|
||||
GPU_vertbuf_data_alloc(*vbo, vector.size());
|
||||
vbo->data<VertexTriple>().copy_from(vector);
|
||||
return vbo;
|
||||
}
|
||||
|
||||
enum VertexClass {
|
||||
VCLASS_NONE = 0,
|
||||
|
||||
@@ -91,7 +113,7 @@ static constexpr float bone_box_verts[8][3] = {
|
||||
{-1.0f, 1.0f, 1.0f},
|
||||
};
|
||||
|
||||
static constexpr std::array<uint, 24> bone_box_wire = {
|
||||
static constexpr std::array<uint, 24> bone_box_wire_lines = {
|
||||
0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7,
|
||||
};
|
||||
|
||||
@@ -115,6 +137,135 @@ static const std::array<uint3, 12> bone_box_solid_tris{
|
||||
{4, 6, 7},
|
||||
};
|
||||
|
||||
/**
|
||||
* Store indices of generated verts from bone_box_solid_tris to define adjacency infos.
|
||||
* See bone_octahedral_solid_tris for more infos.
|
||||
*/
|
||||
static const std::array<uint4, 12> bone_box_wire_lines_adjacency = {
|
||||
uint4{4, 2, 0, 11},
|
||||
{0, 1, 2, 8},
|
||||
{2, 4, 1, 14},
|
||||
{1, 0, 4, 20}, /* bottom */
|
||||
{0, 8, 11, 14},
|
||||
{2, 14, 8, 20},
|
||||
{1, 20, 14, 11},
|
||||
{4, 11, 20, 8}, /* top */
|
||||
{20, 0, 11, 2},
|
||||
{11, 2, 8, 1},
|
||||
{8, 1, 14, 4},
|
||||
{14, 4, 20, 0}, /* sides */
|
||||
};
|
||||
|
||||
/* aligned with bone_box_solid_tris */
|
||||
static const std::array<float3, 12> bone_box_solid_normals = {
|
||||
float3{0.0f, -1.0f, 0.0f},
|
||||
{0.0f, -1.0f, 0.0f},
|
||||
|
||||
{1.0f, 0.0f, 0.0f},
|
||||
{1.0f, 0.0f, 0.0f},
|
||||
|
||||
{0.0f, 0.0f, -1.0f},
|
||||
{0.0f, 0.0f, -1.0f},
|
||||
|
||||
{-1.0f, 0.0f, 0.0f},
|
||||
{-1.0f, 0.0f, 0.0f},
|
||||
|
||||
{0.0f, 0.0f, 1.0f},
|
||||
{0.0f, 0.0f, 1.0f},
|
||||
|
||||
{0.0f, 1.0f, 0.0f},
|
||||
{0.0f, 1.0f, 0.0f},
|
||||
};
|
||||
|
||||
static const std::array<float3, 6> bone_octahedral_verts{
|
||||
float3{0.0f, 0.0f, 0.0f},
|
||||
{0.1f, 0.1f, 0.1f},
|
||||
{0.1f, 0.1f, -0.1f},
|
||||
{-0.1f, 0.1f, -0.1f},
|
||||
{-0.1f, 0.1f, 0.1f},
|
||||
{0.0f, 1.0f, 0.0f},
|
||||
};
|
||||
|
||||
/**
|
||||
* NOTE: This is not the correct normals.
|
||||
* The correct smooth normals for the equator vertices should be
|
||||
* {+-0.943608f * M_SQRT1_2, -0.331048f, +-0.943608f * M_SQRT1_2}
|
||||
* but it creates problems for outlines when bones are scaled.
|
||||
*/
|
||||
static const std::array<float3, 6> bone_octahedral_smooth_normals{
|
||||
float3{0.0f, -1.0f, 0.0f},
|
||||
{float(M_SQRT1_2), 0.0f, float(M_SQRT1_2)},
|
||||
{float(M_SQRT1_2), 0.0f, -float(M_SQRT1_2)},
|
||||
{-float(M_SQRT1_2), 0.0f, -float(M_SQRT1_2)},
|
||||
{-float(M_SQRT1_2), 0.0f, float(M_SQRT1_2)},
|
||||
{0.0f, 1.0f, 0.0f},
|
||||
};
|
||||
|
||||
static const std::array<uint2, 12> bone_octahedral_wire_lines = {
|
||||
uint2{0, 1},
|
||||
{1, 5},
|
||||
{5, 3},
|
||||
{3, 0},
|
||||
{0, 4},
|
||||
{4, 5},
|
||||
{5, 2},
|
||||
{2, 0},
|
||||
{1, 2},
|
||||
{2, 3},
|
||||
{3, 4},
|
||||
{4, 1},
|
||||
};
|
||||
|
||||
static const std::array<uint3, 8> bone_octahedral_solid_tris = {
|
||||
uint3{2, 1, 0}, /* bottom */
|
||||
{3, 2, 0},
|
||||
{4, 3, 0},
|
||||
{1, 4, 0},
|
||||
|
||||
{5, 1, 2}, /* top */
|
||||
{5, 2, 3},
|
||||
{5, 3, 4},
|
||||
{5, 4, 1},
|
||||
};
|
||||
|
||||
/**
|
||||
* Store indices of generated verts from bone_octahedral_solid_tris to define adjacency infos.
|
||||
* Example: triangle {2, 1, 0} is adjacent to {3, 2, 0}, {1, 4, 0} and {5, 1, 2}.
|
||||
* {2, 1, 0} becomes {0, 1, 2}
|
||||
* {3, 2, 0} becomes {3, 4, 5}
|
||||
* {1, 4, 0} becomes {9, 10, 11}
|
||||
* {5, 1, 2} becomes {12, 13, 14}
|
||||
* According to opengl specification it becomes (starting from
|
||||
* the first vertex of the first face aka. vertex 2):
|
||||
* {0, 12, 1, 10, 2, 3}
|
||||
*/
|
||||
static const std::array<uint4, 12> bone_octahedral_wire_lines_adjacency = {
|
||||
uint4{0, 1, 2, 6},
|
||||
{0, 12, 1, 6},
|
||||
{0, 3, 12, 6},
|
||||
{0, 2, 3, 6},
|
||||
{1, 6, 2, 3},
|
||||
{1, 12, 6, 3},
|
||||
{1, 0, 12, 3},
|
||||
{1, 2, 0, 3},
|
||||
{2, 0, 1, 12},
|
||||
{2, 3, 0, 12},
|
||||
{2, 6, 3, 12},
|
||||
{2, 1, 6, 12},
|
||||
};
|
||||
|
||||
/* aligned with bone_octahedral_solid_tris */
|
||||
static const float bone_octahedral_solid_normals[8][3] = {
|
||||
{M_SQRT1_2, -M_SQRT1_2, 0.00000000f},
|
||||
{-0.00000000f, -M_SQRT1_2, -M_SQRT1_2},
|
||||
{-M_SQRT1_2, -M_SQRT1_2, 0.00000000f},
|
||||
{0.00000000f, -M_SQRT1_2, M_SQRT1_2},
|
||||
{0.99388373f, 0.11043154f, -0.00000000f},
|
||||
{0.00000000f, 0.11043154f, -0.99388373f},
|
||||
{-0.99388373f, 0.11043154f, 0.00000000f},
|
||||
{0.00000000f, 0.11043154f, 0.99388373f},
|
||||
};
|
||||
|
||||
static void append_line_loop(
|
||||
Vector<Vertex> &dest, Span<float2> verts, float z, int flag, bool dashed = false)
|
||||
{
|
||||
@@ -261,6 +412,223 @@ static void append_sphere(Vector<VertShaded> &dest, const eDRWLevelOfDetail leve
|
||||
|
||||
ShapeCache::ShapeCache()
|
||||
{
|
||||
UNUSED_VARS(bone_octahedral_wire_lines);
|
||||
|
||||
/* Armature Octahedron. */
|
||||
{
|
||||
Vector<VertShaded> verts;
|
||||
for (int tri = 0; tri < 8; tri++) {
|
||||
for (int v = 0; v < 3; v++) {
|
||||
verts.append({bone_octahedral_verts[bone_octahedral_solid_tris[tri][v]],
|
||||
VCLASS_NONE,
|
||||
bone_octahedral_solid_normals[tri]});
|
||||
}
|
||||
}
|
||||
bone_octahedron = BatchPtr(
|
||||
GPU_batch_create_ex(GPU_PRIM_TRIS, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
|
||||
}
|
||||
{
|
||||
GPUIndexBufBuilder elb;
|
||||
GPU_indexbuf_init(&elb, GPU_PRIM_LINES_ADJ, 12, 24);
|
||||
|
||||
for (auto line : bone_octahedral_wire_lines_adjacency) {
|
||||
GPU_indexbuf_add_line_adj_verts(&elb, line[0], line[1], line[2], line[3]);
|
||||
}
|
||||
gpu::IndexBuf *ibo = GPU_indexbuf_build(&elb);
|
||||
|
||||
/* NOTE: Reuses the same VBO as bone_octahedron. Thus has the same vertex format. */
|
||||
bone_octahedron_wire = BatchPtr(GPU_batch_create_ex(
|
||||
GPU_PRIM_LINES_ADJ, bone_octahedron.get()->verts[0], ibo, GPU_BATCH_OWNS_INDEX));
|
||||
}
|
||||
|
||||
/* Armature Sphere. */
|
||||
{
|
||||
constexpr int resolution = 64;
|
||||
Vector<float2> ring = ring_vertices(0.05f, resolution);
|
||||
|
||||
Vector<Vertex> verts;
|
||||
for (int a : IndexRange(resolution + 1)) {
|
||||
float2 cv = ring[a % resolution];
|
||||
verts.append({{cv.x, cv.y, 0.0f}, VCLASS_EMPTY_SCALED});
|
||||
}
|
||||
|
||||
bone_sphere = BatchPtr(GPU_batch_create_ex(
|
||||
GPU_PRIM_TRI_FAN, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
|
||||
}
|
||||
{
|
||||
bone_sphere_wire = BatchPtr(
|
||||
GPU_batch_create(GPU_PRIM_LINE_STRIP, bone_sphere.get()->verts[0], nullptr));
|
||||
}
|
||||
|
||||
/* Armature Stick. */
|
||||
{
|
||||
/* Gather as a strip and add to main buffer as a list of triangles. */
|
||||
Vector<Vertex> vert_strip;
|
||||
vert_strip.append({{0.0f, 1.0f, 0.0f}, COL_BONE | POS_BONE | POS_HEAD | COL_HEAD | COL_WIRE});
|
||||
vert_strip.append({{0.0f, 1.0f, 0.0f}, COL_BONE | POS_BONE | POS_TAIL | COL_TAIL | COL_WIRE});
|
||||
vert_strip.append({{0.0f, 0.0f, 0.0f}, COL_BONE | POS_BONE | POS_HEAD | COL_HEAD});
|
||||
vert_strip.append({{0.0f, 0.0f, 0.0f}, COL_BONE | POS_BONE | POS_TAIL | COL_TAIL});
|
||||
vert_strip.append({{0.0f, -1.0f, 0.0f}, COL_BONE | POS_BONE | POS_HEAD | COL_HEAD | COL_WIRE});
|
||||
vert_strip.append({{0.0f, -1.0f, 0.0f}, COL_BONE | POS_BONE | POS_TAIL | COL_TAIL | COL_WIRE});
|
||||
|
||||
Vector<Vertex> verts;
|
||||
/* Bone rectangle */
|
||||
for (int t : IndexRange(vert_strip.size() - 2)) {
|
||||
/* NOTE: Don't care about winding.
|
||||
* Theses triangles are facing the camera and should not be backface culled. */
|
||||
verts.append(vert_strip[t]);
|
||||
verts.append(vert_strip[t + 1]);
|
||||
verts.append(vert_strip[t + 2]);
|
||||
}
|
||||
|
||||
constexpr int resolution = 12;
|
||||
Vector<float2> ring = ring_vertices(2.0f, resolution);
|
||||
for (int a : IndexRange(resolution)) {
|
||||
float2 cv1 = ring[a % resolution];
|
||||
float2 cv2 = ring[(a + 1) % resolution];
|
||||
/* Head point. */
|
||||
verts.append({{0.0f, 0.0f, 0.0f}, int(POS_HEAD | COL_HEAD)});
|
||||
verts.append({{cv1.x, cv1.y, 0.0f}, int(POS_HEAD | COL_HEAD | COL_WIRE)});
|
||||
verts.append({{cv2.x, cv2.y, 0.0f}, int(POS_HEAD | COL_HEAD | COL_WIRE)});
|
||||
/* Tail point. */
|
||||
verts.append({{0.0f, 0.0f, 0.0f}, int(POS_TAIL | COL_TAIL)});
|
||||
verts.append({{cv1.x, cv1.y, 0.0f}, int(POS_TAIL | COL_TAIL | COL_WIRE)});
|
||||
verts.append({{cv2.x, cv2.y, 0.0f}, int(POS_TAIL | COL_TAIL | COL_WIRE)});
|
||||
}
|
||||
|
||||
bone_stick = BatchPtr(
|
||||
GPU_batch_create_ex(GPU_PRIM_TRIS, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
|
||||
}
|
||||
|
||||
/* Armature BBones. */
|
||||
{
|
||||
Vector<VertShaded> verts;
|
||||
for (int tri = 0; tri < 12; tri++) {
|
||||
for (int v = 0; v < 3; v++) {
|
||||
verts.append({bone_box_verts[bone_box_solid_tris[tri][v]],
|
||||
VCLASS_NONE,
|
||||
bone_box_solid_normals[tri]});
|
||||
}
|
||||
}
|
||||
bone_box = BatchPtr(
|
||||
GPU_batch_create_ex(GPU_PRIM_TRIS, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
|
||||
}
|
||||
{
|
||||
GPUIndexBufBuilder elb;
|
||||
GPU_indexbuf_init(&elb, GPU_PRIM_LINES_ADJ, 12, 36);
|
||||
|
||||
for (auto line : bone_box_wire_lines_adjacency) {
|
||||
GPU_indexbuf_add_line_adj_verts(&elb, line[0], line[1], line[2], line[3]);
|
||||
}
|
||||
gpu::IndexBuf *ibo = GPU_indexbuf_build(&elb);
|
||||
|
||||
/* NOTE: Reuses the same VBO as bone_box. Thus has the same vertex format. */
|
||||
bone_box_wire = BatchPtr(GPU_batch_create_ex(
|
||||
GPU_PRIM_LINES_ADJ, bone_box.get()->verts[0], ibo, GPU_BATCH_OWNS_INDEX));
|
||||
}
|
||||
|
||||
/* Armature Envelope. */
|
||||
{
|
||||
constexpr int lon_res = 24;
|
||||
constexpr int lat_res = 24;
|
||||
constexpr float lon_inc = 2.0f * M_PI / lon_res;
|
||||
constexpr float lat_inc = M_PI / lat_res;
|
||||
|
||||
auto lat_lon_to_co = [](const float lat, const float lon) {
|
||||
return float3(sinf(lat) * cosf(lon), sinf(lat) * sinf(lon), cosf(lat));
|
||||
};
|
||||
|
||||
Vector<Vertex> verts;
|
||||
float lon = 0.0f;
|
||||
for (int i = 0; i < lon_res; i++, lon += lon_inc) {
|
||||
float lat = 0.0f;
|
||||
/* NOTE: the poles are duplicated on purpose, to restart the strip. */
|
||||
for (int j = 0; j < lat_res; j++, lat += lat_inc) {
|
||||
verts.append({lat_lon_to_co(lat, lon), VCLASS_NONE});
|
||||
verts.append({lat_lon_to_co(lat, lon + lon_inc), VCLASS_NONE});
|
||||
}
|
||||
/* Closing the loop */
|
||||
verts.append({lat_lon_to_co(M_PI, lon), VCLASS_NONE});
|
||||
verts.append({lat_lon_to_co(M_PI, lon + lon_inc), VCLASS_NONE});
|
||||
}
|
||||
|
||||
bone_envelope = BatchPtr(GPU_batch_create_ex(
|
||||
GPU_PRIM_TRI_STRIP, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
|
||||
}
|
||||
{
|
||||
constexpr int circle_resolution = 64;
|
||||
float2 v0, v1, v2;
|
||||
|
||||
auto circle_pt = [](const float angle) { return float2(sinf(angle), cosf(angle)); };
|
||||
|
||||
Vector<VertexTriple> verts;
|
||||
/* Output 3 verts for each position. See shader for explanation. */
|
||||
v0 = circle_pt((2.0f * M_PI * -2) / float(circle_resolution));
|
||||
v1 = circle_pt((2.0f * M_PI * -1) / float(circle_resolution));
|
||||
for (int a = 0; a <= circle_resolution; a++, v0 = v1, v1 = v2) {
|
||||
v2 = circle_pt((2.0f * M_PI * a) / float(circle_resolution));
|
||||
verts.append({v0, v1, v2});
|
||||
}
|
||||
|
||||
bone_envelope_wire = BatchPtr(GPU_batch_create_ex(
|
||||
GPU_PRIM_LINE_STRIP, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
|
||||
}
|
||||
|
||||
/* Degrees of freedom. */
|
||||
{
|
||||
constexpr int resolution = 16;
|
||||
|
||||
Vector<Vertex> verts;
|
||||
auto set_vert = [&](const float x, const float y, const int quarter) {
|
||||
verts.append({{(quarter % 2 == 0) ? -x : x, (quarter < 2) ? -y : y, 0.0f}, VCLASS_NONE});
|
||||
};
|
||||
|
||||
for (int quarter : IndexRange(4)) {
|
||||
float prev_z = 0.0f;
|
||||
for (int i : IndexRange(1, resolution - 1)) {
|
||||
float z = sinf(M_PI_2 * i / float(resolution - 1));
|
||||
float prev_x = 0.0f;
|
||||
for (int j : IndexRange(1, resolution - i)) {
|
||||
float x = sinf(M_PI_2 * j / float(resolution - 1));
|
||||
if (j == resolution - i) {
|
||||
/* Pole triangle. */
|
||||
set_vert(prev_x, z, quarter);
|
||||
set_vert(prev_x, prev_z, quarter);
|
||||
set_vert(x, prev_z, quarter);
|
||||
}
|
||||
else {
|
||||
/* Quad. */
|
||||
set_vert(x, z, quarter);
|
||||
set_vert(x, prev_z, quarter);
|
||||
set_vert(prev_x, z, quarter);
|
||||
|
||||
set_vert(x, prev_z, quarter);
|
||||
set_vert(prev_x, prev_z, quarter);
|
||||
set_vert(prev_x, z, quarter);
|
||||
}
|
||||
prev_x = x;
|
||||
}
|
||||
prev_z = z;
|
||||
}
|
||||
}
|
||||
|
||||
bone_degrees_of_freedom = BatchPtr(
|
||||
GPU_batch_create_ex(GPU_PRIM_TRIS, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
|
||||
}
|
||||
{
|
||||
constexpr int resolution = 16 * 4;
|
||||
Vector<float2> ring = ring_vertices(1.0f, resolution);
|
||||
|
||||
Vector<Vertex> verts;
|
||||
for (int a : IndexRange(resolution + 1)) {
|
||||
float2 cv = ring[a % resolution];
|
||||
verts.append({{cv.x, cv.y, 0.0f}, VCLASS_NONE});
|
||||
}
|
||||
|
||||
bone_degrees_of_freedom_wire = BatchPtr(GPU_batch_create_ex(
|
||||
GPU_PRIM_LINE_STRIP, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
|
||||
}
|
||||
|
||||
/* quad_wire */
|
||||
{
|
||||
Vector<Vertex> verts;
|
||||
@@ -332,7 +700,7 @@ ShapeCache::ShapeCache()
|
||||
/* cube */
|
||||
{
|
||||
Vector<Vertex> verts;
|
||||
for (auto index : bone_box_wire) {
|
||||
for (auto index : bone_box_wire_lines) {
|
||||
float x = bone_box_verts[index][0];
|
||||
float y = bone_box_verts[index][1] * 2.0 - 1.0f;
|
||||
float z = bone_box_verts[index][2];
|
||||
@@ -349,12 +717,14 @@ ShapeCache::ShapeCache()
|
||||
|
||||
Vector<Vertex> verts;
|
||||
for (int a : IndexRange(resolution + 1)) {
|
||||
float2 cv = ring[a % resolution];
|
||||
verts.append({{cv.x, 0.0f, cv.y}, VCLASS_EMPTY_SCALED});
|
||||
float2 cv1 = ring[(a + 0) % resolution];
|
||||
float2 cv2 = ring[(a + 1) % resolution];
|
||||
verts.append({{cv1.x, 0.0f, cv1.y}, VCLASS_EMPTY_SCALED});
|
||||
verts.append({{cv2.x, 0.0f, cv2.y}, VCLASS_EMPTY_SCALED});
|
||||
}
|
||||
|
||||
circle = BatchPtr(GPU_batch_create_ex(
|
||||
GPU_PRIM_LINE_STRIP, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
|
||||
circle = BatchPtr(
|
||||
GPU_batch_create_ex(GPU_PRIM_LINES, vbo_from_vector(verts), nullptr, GPU_BATCH_OWNS_VBO));
|
||||
}
|
||||
/* empty_spehere */
|
||||
{
|
||||
@@ -626,8 +996,8 @@ ShapeCache::ShapeCache()
|
||||
}
|
||||
/* camera volume wire */
|
||||
{
|
||||
Vector<Vertex> verts(bone_box_wire.size());
|
||||
for (int i : bone_box_wire) {
|
||||
Vector<Vertex> verts(bone_box_wire_lines.size());
|
||||
for (int i : bone_box_wire_lines) {
|
||||
const float x = bone_box_verts[i][2];
|
||||
const float y = bone_box_verts[i][0];
|
||||
const float z = bone_box_verts[i][1];
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
|
||||
#include "BKE_global.hh"
|
||||
|
||||
#include "BLI_math_matrix.hh"
|
||||
|
||||
#include "DRW_gpu_wrapper.hh"
|
||||
#include "DRW_render.hh"
|
||||
|
||||
@@ -465,6 +467,7 @@ struct OVERLAY_DupliData {
|
||||
struct BoneInstanceData {
|
||||
/* Keep sync with bone instance vertex format (OVERLAY_InstanceFormats) */
|
||||
union {
|
||||
float4x4 mat44;
|
||||
float mat[4][4];
|
||||
struct {
|
||||
float _pad0[3], color_hint_a;
|
||||
@@ -481,9 +484,55 @@ struct 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]);
|
||||
* metaball edit circles with armature wire shader that produces wide-lines. */
|
||||
BoneInstanceData(const float4x4 &ob_mat,
|
||||
const float3 &pos,
|
||||
const float radius,
|
||||
const float color[4])
|
||||
|
||||
{
|
||||
mat44[0] = ob_mat[0] * radius;
|
||||
mat44[1] = ob_mat[1] * radius;
|
||||
mat44[2] = ob_mat[2] * radius;
|
||||
mat44[3] = float4(blender::math::transform_point(ob_mat, pos));
|
||||
set_color(color);
|
||||
}
|
||||
|
||||
BoneInstanceData(const float4x4 &bone_mat, const float4 &bone_color, const float4 &hint_color)
|
||||
: mat44(bone_mat)
|
||||
{
|
||||
set_color(bone_color);
|
||||
set_hint_color(hint_color);
|
||||
};
|
||||
|
||||
BoneInstanceData(const float4x4 &bone_mat, const float4 &bone_color) : mat44(bone_mat)
|
||||
{
|
||||
set_color(bone_color);
|
||||
};
|
||||
|
||||
void set_color(const float4 &bone_color)
|
||||
{
|
||||
/* Encoded color into 2 floats to be able to use the matrix to color the custom bones. */
|
||||
color_a = encode_2f_to_float(bone_color[0], bone_color[1]);
|
||||
color_b = encode_2f_to_float(bone_color[2], bone_color[3]);
|
||||
}
|
||||
|
||||
void set_hint_color(const float4 &hint_color)
|
||||
{
|
||||
/* Encoded color into 2 floats to be able to use the matrix to color the custom bones. */
|
||||
color_hint_a = encode_2f_to_float(hint_color[0], hint_color[1]);
|
||||
color_hint_b = encode_2f_to_float(hint_color[2], hint_color[3]);
|
||||
}
|
||||
|
||||
private:
|
||||
/* Encode 2 units float with byte precision into a float. */
|
||||
float encode_2f_to_float(float a, float b) const
|
||||
{
|
||||
/* NOTE: `b` can go up to 2. Needed to encode wire size. */
|
||||
return float(int(clamp_f(a, 0.0f, 1.0f) * 255) | (int(clamp_f(b, 0.0f, 2.0f) * 255) << 8));
|
||||
}
|
||||
};
|
||||
|
||||
struct OVERLAY_InstanceFormats {
|
||||
|
||||
@@ -279,8 +279,8 @@ GPUShader *OVERLAY_shader_armature_degrees_of_freedom_wire()
|
||||
OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
|
||||
if (!sh_data->armature_dof_wire) {
|
||||
sh_data->armature_dof_wire = GPU_shader_create_from_info_name(
|
||||
(draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) ? "overlay_armature_dof_wire_clipped" :
|
||||
"overlay_armature_dof_wire");
|
||||
(draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) ? "overlay_armature_dof_clipped" :
|
||||
"overlay_armature_dof");
|
||||
}
|
||||
return sh_data->armature_dof_wire;
|
||||
}
|
||||
@@ -291,8 +291,8 @@ GPUShader *OVERLAY_shader_armature_degrees_of_freedom_solid()
|
||||
OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
|
||||
if (!sh_data->armature_dof_solid) {
|
||||
sh_data->armature_dof_solid = GPU_shader_create_from_info_name(
|
||||
(draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) ? "overlay_armature_dof_solid_clipped" :
|
||||
"overlay_armature_dof_solid");
|
||||
(draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) ? "overlay_armature_dof_clipped" :
|
||||
"overlay_armature_dof");
|
||||
}
|
||||
return sh_data->armature_dof_solid;
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ ENUM_OPERATORS(OVERLAY_GridBits, CUSTOM_GRID)
|
||||
#define OVERLAY_GRID_STEPS_LEN 8
|
||||
|
||||
/* Due to the encoding clamping the passed in floats, the wire width needs to be scaled down. */
|
||||
#define WIRE_WIDTH_COMPRESSION 16
|
||||
#define WIRE_WIDTH_COMPRESSION 16.0
|
||||
|
||||
struct OVERLAY_GridData {
|
||||
float4 steps[OVERLAY_GRID_STEPS_LEN]; /* float arrays are padded to float4 in std130. */
|
||||
@@ -228,6 +228,21 @@ struct ExtraInstanceData {
|
||||
return copy;
|
||||
}
|
||||
|
||||
/* For degrees of freedom. */
|
||||
ExtraInstanceData(const float4x4 &object_to_world,
|
||||
const float4 &color,
|
||||
float angle_min_x,
|
||||
float angle_min_z,
|
||||
float angle_max_x,
|
||||
float angle_max_z)
|
||||
{
|
||||
this->color_ = color;
|
||||
this->object_to_world_ = object_to_world;
|
||||
this->object_to_world_[0][3] = angle_min_x;
|
||||
this->object_to_world_[1][3] = angle_min_z;
|
||||
this->object_to_world_[2][3] = angle_max_x;
|
||||
this->object_to_world_[3][3] = angle_max_z;
|
||||
};
|
||||
#endif
|
||||
};
|
||||
BLI_STATIC_ASSERT_ALIGN(ExtraInstanceData, 16)
|
||||
@@ -256,6 +271,84 @@ struct ParticlePointData {
|
||||
};
|
||||
BLI_STATIC_ASSERT_ALIGN(ParticlePointData, 16)
|
||||
|
||||
struct BoneEnvelopeData {
|
||||
float4 head_sphere;
|
||||
float4 tail_sphere;
|
||||
float4 bone_color_and_wire_width;
|
||||
float4 state_color;
|
||||
float4 x_axis;
|
||||
|
||||
#ifndef GPU_SHADER
|
||||
BoneEnvelopeData() = default;
|
||||
|
||||
/* For bone fills. */
|
||||
BoneEnvelopeData(float4 &head_sphere,
|
||||
float4 &tail_sphere,
|
||||
float3 &bone_color,
|
||||
float3 &state_color,
|
||||
float3 &x_axis)
|
||||
: head_sphere(head_sphere),
|
||||
tail_sphere(tail_sphere),
|
||||
bone_color_and_wire_width(bone_color),
|
||||
state_color(state_color),
|
||||
x_axis(x_axis){};
|
||||
|
||||
/* For bone outlines. */
|
||||
BoneEnvelopeData(float4 &head_sphere,
|
||||
float4 &tail_sphere,
|
||||
float4 &color_and_wire_width,
|
||||
float3 &x_axis)
|
||||
: head_sphere(head_sphere),
|
||||
tail_sphere(tail_sphere),
|
||||
bone_color_and_wire_width(color_and_wire_width),
|
||||
x_axis(x_axis){};
|
||||
|
||||
/* For bone distance volumes. */
|
||||
BoneEnvelopeData(float4 &head_sphere, float4 &tail_sphere, float3 &x_axis)
|
||||
: head_sphere(head_sphere), tail_sphere(tail_sphere), x_axis(x_axis){};
|
||||
#endif
|
||||
};
|
||||
BLI_STATIC_ASSERT_ALIGN(BoneEnvelopeData, 16)
|
||||
|
||||
/* Keep in sync with armature_stick_vert.glsl. */
|
||||
enum StickBoneFlag {
|
||||
COL_WIRE = (1u << 0u),
|
||||
COL_HEAD = (1u << 1u),
|
||||
COL_TAIL = (1u << 2u),
|
||||
COL_BONE = (1u << 3u),
|
||||
POS_HEAD = (1u << 4u),
|
||||
POS_TAIL = (1u << 5u),
|
||||
POS_BONE = (1u << 6u),
|
||||
};
|
||||
|
||||
struct BoneStickData {
|
||||
float4 bone_start;
|
||||
float4 bone_end;
|
||||
float4 wire_color;
|
||||
float4 bone_color;
|
||||
float4 head_color;
|
||||
float4 tail_color;
|
||||
|
||||
#ifndef GPU_SHADER
|
||||
BoneStickData() = default;
|
||||
|
||||
/* For bone fills. */
|
||||
BoneStickData(float3 &bone_start,
|
||||
float3 &bone_end,
|
||||
float4 &wire_color,
|
||||
float4 &bone_color,
|
||||
float4 &head_color,
|
||||
float4 &tail_color)
|
||||
: bone_start(bone_start),
|
||||
bone_end(bone_end),
|
||||
wire_color(wire_color),
|
||||
bone_color(bone_color),
|
||||
head_color(head_color),
|
||||
tail_color(tail_color){};
|
||||
#endif
|
||||
};
|
||||
BLI_STATIC_ASSERT_ALIGN(BoneStickData, 16)
|
||||
|
||||
#ifndef GPU_SHADER
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -68,7 +68,6 @@ GPU_SHADER_INTERFACE_INFO(overlay_armature_shape_outline_iface, "geom_in")
|
||||
.smooth(Type::VEC4, "pPos")
|
||||
.smooth(Type::VEC3, "vPos")
|
||||
.smooth(Type::VEC2, "ssPos")
|
||||
.smooth(Type::VEC2, "ssNor")
|
||||
.smooth(Type::VEC4, "vColSize");
|
||||
GPU_SHADER_INTERFACE_INFO(overlay_armature_shape_outline_flat_iface, "geom_flat_in")
|
||||
.flat(Type::INT, "inverted");
|
||||
@@ -81,9 +80,7 @@ GPU_SHADER_INTERFACE_INFO(overlay_armature_shape_outline_no_geom_iface, "")
|
||||
GPU_SHADER_CREATE_INFO(overlay_armature_shape_outline)
|
||||
.do_static_compilation(true)
|
||||
.vertex_in(0, Type::VEC3, "pos")
|
||||
.vertex_in(1, Type::VEC3, "snor")
|
||||
/* Per instance. */
|
||||
.vertex_in(2, Type::VEC4, "color")
|
||||
.vertex_in(3, Type::MAT4, "inst_obmat")
|
||||
.vertex_out(overlay_armature_shape_outline_iface)
|
||||
.vertex_out(overlay_armature_shape_outline_flat_iface)
|
||||
@@ -98,15 +95,26 @@ GPU_SHADER_CREATE_INFO(overlay_armature_shape_outline_no_geom)
|
||||
.metal_backend_only(true)
|
||||
.do_static_compilation(true)
|
||||
.vertex_in(0, Type::VEC3, "pos")
|
||||
.vertex_in(1, Type::VEC3, "snor")
|
||||
/* Per instance. */
|
||||
.vertex_in(2, Type::VEC4, "color")
|
||||
.vertex_in(3, Type::MAT4, "inst_obmat")
|
||||
.vertex_out(overlay_armature_shape_outline_no_geom_iface)
|
||||
.vertex_source("overlay_armature_shape_outline_vert_no_geom.glsl")
|
||||
.fragment_source("overlay_armature_wire_frag.glsl")
|
||||
.additional_info("overlay_frag_output", "overlay_armature_common", "draw_globals");
|
||||
|
||||
GPU_SHADER_CREATE_INFO(overlay_armature_shape_outline_next)
|
||||
.do_static_compilation(true)
|
||||
.storage_buf(0, Qualifier::READ, "float", "pos[]", Frequency::GEOMETRY)
|
||||
.storage_buf(1, Qualifier::READ, "mat4", "data_buf[]")
|
||||
.push_constant(Type::IVEC2, "gpu_attr_0")
|
||||
.vertex_out(overlay_armature_shape_outline_no_geom_iface)
|
||||
.vertex_source("overlay_armature_shape_outline_next_vert.glsl")
|
||||
.fragment_source("overlay_armature_wire_frag.glsl")
|
||||
.additional_info("overlay_frag_output",
|
||||
"overlay_armature_common",
|
||||
"gpu_index_load",
|
||||
"draw_globals");
|
||||
|
||||
GPU_SHADER_CREATE_INFO(overlay_armature_shape_outline_clipped)
|
||||
.do_static_compilation(true)
|
||||
.additional_info("overlay_armature_shape_outline", "drw_clipped");
|
||||
@@ -136,6 +144,11 @@ GPU_SHADER_CREATE_INFO(overlay_armature_shape_solid_clipped)
|
||||
.do_static_compilation(true)
|
||||
.additional_info("overlay_armature_shape_solid", "drw_clipped");
|
||||
|
||||
GPU_SHADER_INTERFACE_INFO(overlay_armature_shape_wire_next_iface, "")
|
||||
.flat(Type::VEC4, "finalColor")
|
||||
.flat(Type::FLOAT, "wire_width")
|
||||
.no_perspective(Type::FLOAT, "edgeCoord");
|
||||
|
||||
GPU_SHADER_INTERFACE_INFO(overlay_armature_shape_wire_iface, "geometry_in")
|
||||
.flat(Type::VEC4, "finalColor")
|
||||
.flat(Type::FLOAT, "wire_width");
|
||||
@@ -182,6 +195,23 @@ GPU_SHADER_CREATE_INFO(overlay_armature_shape_wire_no_geom)
|
||||
.additional_info("overlay_frag_output", "overlay_armature_common", "draw_globals");
|
||||
#endif
|
||||
|
||||
GPU_SHADER_CREATE_INFO(overlay_armature_shape_wire_next)
|
||||
.do_static_compilation(true)
|
||||
.define("NO_GEOM")
|
||||
.push_constant(Type::BOOL, "do_smooth_wire")
|
||||
.storage_buf(0, Qualifier::READ, "float", "pos[]", Frequency::GEOMETRY)
|
||||
.storage_buf(1, Qualifier::READ, "mat4", "data_buf[]")
|
||||
.push_constant(Type::IVEC2, "gpu_attr_0")
|
||||
.define("inst_obmat", "data_buf[gl_InstanceID]")
|
||||
.vertex_out(overlay_armature_shape_wire_next_iface)
|
||||
.vertex_source("overlay_armature_shape_wire_next_vert.glsl")
|
||||
.fragment_source("overlay_armature_shape_wire_frag.glsl")
|
||||
.typedef_source("overlay_shader_shared.h")
|
||||
.additional_info("overlay_frag_output",
|
||||
"overlay_armature_common",
|
||||
"gpu_index_load",
|
||||
"draw_globals");
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
@@ -190,6 +220,7 @@ GPU_SHADER_CREATE_INFO(overlay_armature_shape_wire_no_geom)
|
||||
|
||||
GPU_SHADER_CREATE_INFO(overlay_armature_envelope_outline)
|
||||
.do_static_compilation(true)
|
||||
.typedef_source("overlay_shader_shared.h")
|
||||
.vertex_in(0, Type::VEC2, "pos0")
|
||||
.vertex_in(1, Type::VEC2, "pos1")
|
||||
.vertex_in(2, Type::VEC2, "pos2")
|
||||
@@ -214,6 +245,7 @@ GPU_SHADER_INTERFACE_INFO(overlay_armature_envelope_solid_iface, "")
|
||||
|
||||
GPU_SHADER_CREATE_INFO(overlay_armature_envelope_solid)
|
||||
.do_static_compilation(true)
|
||||
.typedef_source("overlay_shader_shared.h")
|
||||
.vertex_in(0, Type::VEC3, "pos")
|
||||
/* Per instance. Assumed to be in world coordinate already. */
|
||||
.vertex_in(1, Type::VEC4, "headSphere")
|
||||
@@ -244,6 +276,7 @@ GPU_SHADER_INTERFACE_INFO(overlay_armature_stick_iface, "")
|
||||
|
||||
GPU_SHADER_CREATE_INFO(overlay_armature_stick)
|
||||
.do_static_compilation(true)
|
||||
.typedef_source("overlay_shader_shared.h")
|
||||
/* Bone aligned screen space. */
|
||||
.vertex_in(0, Type::VEC2, "pos")
|
||||
.vertex_in(1, Type::UINT, "flag")
|
||||
@@ -272,31 +305,20 @@ GPU_SHADER_CREATE_INFO(overlay_armature_stick_clipped)
|
||||
* \{ */
|
||||
|
||||
GPU_SHADER_CREATE_INFO(overlay_armature_dof)
|
||||
.do_static_compilation(true)
|
||||
.typedef_source("overlay_shader_shared.h")
|
||||
.vertex_in(0, Type::VEC2, "pos")
|
||||
/* Per instance. Assumed to be in world coordinate already. */
|
||||
.vertex_in(1, Type::VEC4, "color")
|
||||
.vertex_in(2, Type::MAT4, "inst_obmat")
|
||||
.vertex_out(overlay_armature_wire_iface)
|
||||
.vertex_source("overlay_armature_dof_vert.glsl")
|
||||
.fragment_source("overlay_armature_dof_solid_frag.glsl")
|
||||
.additional_info("overlay_frag_output", "overlay_armature_common", "draw_globals");
|
||||
|
||||
GPU_SHADER_CREATE_INFO(overlay_armature_dof_wire)
|
||||
GPU_SHADER_CREATE_INFO(overlay_armature_dof_lipped)
|
||||
.do_static_compilation(true)
|
||||
.fragment_source("overlay_armature_dof_solid_frag.glsl")
|
||||
.additional_info("overlay_armature_dof");
|
||||
|
||||
GPU_SHADER_CREATE_INFO(overlay_armature_dof_wire_clipped)
|
||||
.do_static_compilation(true)
|
||||
.additional_info("overlay_armature_dof_wire", "drw_clipped");
|
||||
|
||||
GPU_SHADER_CREATE_INFO(overlay_armature_dof_solid)
|
||||
.do_static_compilation(true)
|
||||
.fragment_source("overlay_armature_dof_solid_frag.glsl")
|
||||
.additional_info("overlay_armature_dof");
|
||||
|
||||
GPU_SHADER_CREATE_INFO(overlay_armature_dof_solid_clipped)
|
||||
.do_static_compilation(true)
|
||||
.additional_info("overlay_armature_dof_solid", "drw_clipped");
|
||||
.additional_info("overlay_armature_dof", "drw_clipped");
|
||||
|
||||
/** \} */
|
||||
|
||||
@@ -306,6 +328,7 @@ GPU_SHADER_CREATE_INFO(overlay_armature_dof_solid_clipped)
|
||||
|
||||
GPU_SHADER_CREATE_INFO(overlay_armature_wire)
|
||||
.do_static_compilation(true)
|
||||
.typedef_source("overlay_shader_shared.h")
|
||||
.vertex_in(0, Type::VEC3, "pos")
|
||||
.vertex_in(1, Type::VEC4, "color")
|
||||
.push_constant(Type::FLOAT, "alpha")
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(select_lib.glsl)
|
||||
|
||||
/* project to screen space */
|
||||
vec2 proj(vec4 pos)
|
||||
@@ -91,6 +92,8 @@ vec3 get_outline_point(vec2 pos,
|
||||
|
||||
void main()
|
||||
{
|
||||
select_id_set(in_select_buf[gl_InstanceID]);
|
||||
|
||||
float dst_head = distance(headSphere.xyz, drw_view.viewinv[3].xyz);
|
||||
float dst_tail = distance(tailSphere.xyz, drw_view.viewinv[3].xyz);
|
||||
// float dst_head = -dot(headSphere.xyz, drw_view.viewmat[2].xyz);
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma BLENDER_REQUIRE(select_lib.glsl)
|
||||
|
||||
void main()
|
||||
{
|
||||
float n = normalize(normalView).z;
|
||||
@@ -17,4 +19,6 @@ void main()
|
||||
fragColor.a = alpha;
|
||||
}
|
||||
lineOutput = vec4(0.0);
|
||||
|
||||
select_id_output(select_id);
|
||||
}
|
||||
|
||||
@@ -4,9 +4,12 @@
|
||||
|
||||
#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(select_lib.glsl)
|
||||
|
||||
void main()
|
||||
{
|
||||
select_id_set(in_select_buf[gl_InstanceID]);
|
||||
|
||||
vec3 bone_vec = tailSphere.xyz - headSphere.xyz;
|
||||
float bone_len = max(1e-8, sqrt(dot(bone_vec, bone_vec)));
|
||||
float bone_lenrcp = 1.0 / bone_len;
|
||||
|
||||
@@ -0,0 +1,198 @@
|
||||
/* SPDX-FileCopyrightText: 2018-2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(draw_view_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(gpu_shader_utildefines_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(gpu_shader_index_load_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(gpu_shader_attribute_load_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(gpu_shader_math_matrix_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(select_lib.glsl)
|
||||
|
||||
struct VertIn {
|
||||
vec3 ls_P;
|
||||
mat4 inst_matrix;
|
||||
};
|
||||
|
||||
VertIn input_assembly(uint in_vertex_id, mat4x4 inst_matrix)
|
||||
{
|
||||
uint v_i = gpu_index_load(in_vertex_id);
|
||||
|
||||
VertIn vert_in;
|
||||
vert_in.ls_P = gpu_attr_load_float3(pos, gpu_attr_0, v_i);
|
||||
vert_in.inst_matrix = inst_matrix;
|
||||
return vert_in;
|
||||
}
|
||||
|
||||
struct VertOut {
|
||||
vec3 vs_P;
|
||||
vec3 ws_P;
|
||||
vec4 hs_P;
|
||||
vec2 ss_P;
|
||||
vec4 color_size;
|
||||
int inverted;
|
||||
};
|
||||
|
||||
VertOut vertex_main(VertIn v_in)
|
||||
{
|
||||
vec4 bone_color, state_color;
|
||||
mat4 model_mat = extract_matrix_packed_data(v_in.inst_matrix, state_color, bone_color);
|
||||
|
||||
VertOut v_out;
|
||||
v_out.ws_P = transform_point(model_mat, v_in.ls_P);
|
||||
v_out.vs_P = drw_point_world_to_view(v_out.ws_P);
|
||||
v_out.hs_P = drw_point_view_to_homogenous(v_out.vs_P);
|
||||
v_out.ss_P = drw_perspective_divide(v_out.hs_P).xy * sizeViewport;
|
||||
v_out.inverted = int(dot(cross(model_mat[0].xyz, model_mat[1].xyz), model_mat[2].xyz) < 0.0);
|
||||
v_out.color_size = bone_color;
|
||||
|
||||
return v_out;
|
||||
}
|
||||
|
||||
void emit_vertex(const uint strip_index,
|
||||
uint out_vertex_id,
|
||||
uint out_primitive_id,
|
||||
vec4 color,
|
||||
vec4 hs_P,
|
||||
vec3 ws_P,
|
||||
vec2 offset,
|
||||
bool is_persp)
|
||||
{
|
||||
bool is_odd_primitive = (out_primitive_id & 1u) != 0u;
|
||||
/* Maps triangle list primitives to triangle strip indices. */
|
||||
uint out_strip_index = (is_odd_primitive ? (2u - out_vertex_id) : out_vertex_id) +
|
||||
out_primitive_id;
|
||||
|
||||
if (out_strip_index != strip_index) {
|
||||
return;
|
||||
}
|
||||
|
||||
finalColor = color;
|
||||
|
||||
gl_Position = hs_P;
|
||||
/* Offset away from the center to avoid overlap with solid shape. */
|
||||
gl_Position.xy += offset * sizeViewportInv * gl_Position.w;
|
||||
/* Improve AA bleeding inside bone silhouette. */
|
||||
gl_Position.z -= (is_persp) ? 1e-4 : 1e-6;
|
||||
|
||||
edgeStart = edgePos = ((gl_Position.xy / gl_Position.w) * 0.5 + 0.5) * sizeViewport;
|
||||
|
||||
view_clipping_distances(ws_P);
|
||||
}
|
||||
|
||||
void geometry_main(VertOut geom_in[4],
|
||||
uint out_vertex_id,
|
||||
uint out_primitive_id,
|
||||
uint out_invocation_id)
|
||||
{
|
||||
bool is_persp = (drw_view.winmat[3][3] == 0.0);
|
||||
|
||||
vec3 view_vec = (is_persp) ? normalize(geom_in[1].vs_P) : vec3(0.0, 0.0, -1.0);
|
||||
vec3 v10 = geom_in[0].vs_P - geom_in[1].vs_P;
|
||||
vec3 v12 = geom_in[2].vs_P - geom_in[1].vs_P;
|
||||
vec3 v13 = geom_in[3].vs_P - geom_in[1].vs_P;
|
||||
|
||||
vec3 n0 = cross(v12, v10);
|
||||
vec3 n3 = cross(v13, v12);
|
||||
|
||||
float fac0 = dot(view_vec, n0);
|
||||
float fac3 = dot(view_vec, n3);
|
||||
|
||||
/* If one of the face is perpendicular to the view,
|
||||
* consider it and outline edge. */
|
||||
if (abs(fac0) > 1e-5 && abs(fac3) > 1e-5) {
|
||||
/* If both adjacent verts are facing the camera the same way,
|
||||
* then it isn't an outline edge. */
|
||||
if (sign(fac0) == sign(fac3)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
n0 = (geom_in[0].inverted == 1) ? -n0 : n0;
|
||||
/* Don't outline if concave edge. */
|
||||
if (dot(n0, v13) > 0.0001) {
|
||||
return;
|
||||
}
|
||||
|
||||
vec2 perp = normalize(geom_in[2].ss_P - geom_in[1].ss_P);
|
||||
vec2 edge_dir = vec2(-perp.y, perp.x);
|
||||
|
||||
vec2 hidden_point;
|
||||
/* Take the farthest point to compute edge direction
|
||||
* (avoid problems with point behind near plane).
|
||||
* If the chosen point is parallel to the edge in screen space,
|
||||
* choose the other point anyway.
|
||||
* This fixes some issue with cubes in orthographic views. */
|
||||
if (geom_in[0].vs_P.z < geom_in[3].vs_P.z) {
|
||||
hidden_point = (abs(fac0) > 1e-5) ? geom_in[0].ss_P : geom_in[3].ss_P;
|
||||
}
|
||||
else {
|
||||
hidden_point = (abs(fac3) > 1e-5) ? geom_in[3].ss_P : geom_in[0].ss_P;
|
||||
}
|
||||
vec2 hidden_dir = normalize(hidden_point - geom_in[1].ss_P);
|
||||
|
||||
float fac = dot(-hidden_dir, edge_dir);
|
||||
edge_dir *= (fac < 0.0) ? -1.0 : 1.0;
|
||||
|
||||
emit_vertex(0,
|
||||
out_vertex_id,
|
||||
out_primitive_id,
|
||||
vec4(geom_in[0].color_size.rgb, 1.0),
|
||||
geom_in[1].hs_P,
|
||||
geom_in[1].ws_P,
|
||||
edge_dir - perp,
|
||||
is_persp);
|
||||
|
||||
emit_vertex(1,
|
||||
out_vertex_id,
|
||||
out_primitive_id,
|
||||
vec4(geom_in[0].color_size.rgb, 1.0),
|
||||
geom_in[2].hs_P,
|
||||
geom_in[2].ws_P,
|
||||
edge_dir + perp,
|
||||
is_persp);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
select_id_set(in_select_buf[gl_InstanceID]);
|
||||
|
||||
/* Line Adjacency primitive. */
|
||||
const uint input_primitive_vertex_count = 4u;
|
||||
/* Line list primitive. */
|
||||
const uint ouput_primitive_vertex_count = 2u;
|
||||
const uint ouput_primitive_count = 1u;
|
||||
const uint ouput_invocation_count = 1u;
|
||||
const uint output_vertex_count_per_invocation = ouput_primitive_count *
|
||||
ouput_primitive_vertex_count;
|
||||
const uint output_vertex_count_per_input_primitive = output_vertex_count_per_invocation *
|
||||
ouput_invocation_count;
|
||||
|
||||
uint in_primitive_id = uint(gl_VertexID) / output_vertex_count_per_input_primitive;
|
||||
uint in_primitive_first_vertex = in_primitive_id * input_primitive_vertex_count;
|
||||
|
||||
uint out_vertex_id = uint(gl_VertexID) % ouput_primitive_vertex_count;
|
||||
uint out_primitive_id = (uint(gl_VertexID) / ouput_primitive_vertex_count) %
|
||||
ouput_primitive_count;
|
||||
uint out_invocation_id = (uint(gl_VertexID) / output_vertex_count_per_invocation) %
|
||||
ouput_invocation_count;
|
||||
|
||||
mat4x4 inst_matrix = data_buf[gl_InstanceID];
|
||||
|
||||
VertIn vert_in[input_primitive_vertex_count];
|
||||
vert_in[0] = input_assembly(in_primitive_first_vertex + 0u, inst_matrix);
|
||||
vert_in[1] = input_assembly(in_primitive_first_vertex + 1u, inst_matrix);
|
||||
vert_in[2] = input_assembly(in_primitive_first_vertex + 2u, inst_matrix);
|
||||
vert_in[3] = input_assembly(in_primitive_first_vertex + 3u, inst_matrix);
|
||||
|
||||
VertOut vert_out[input_primitive_vertex_count];
|
||||
vert_out[0] = vertex_main(vert_in[0]);
|
||||
vert_out[1] = vertex_main(vert_in[1]);
|
||||
vert_out[2] = vertex_main(vert_in[2]);
|
||||
vert_out[3] = vertex_main(vert_in[3]);
|
||||
|
||||
/* Discard by default. */
|
||||
gl_Position = vec4(NAN_FLT);
|
||||
geometry_main(vert_out, out_vertex_id, out_primitive_id, out_invocation_id);
|
||||
}
|
||||
@@ -11,31 +11,65 @@ vec2 proj(vec4 pos)
|
||||
return (0.5 * (pos.xy / pos.w) + 0.5) * sizeViewport.xy;
|
||||
}
|
||||
|
||||
void main()
|
||||
struct VertIn {
|
||||
vec3 l_P;
|
||||
mat4 inst_matrix;
|
||||
};
|
||||
|
||||
struct VertOut {
|
||||
vec3 vPos;
|
||||
vec4 pPos;
|
||||
vec2 ssPos;
|
||||
vec4 vColSize;
|
||||
int inverted;
|
||||
};
|
||||
|
||||
VertOut vertex_main(VertIn v_in)
|
||||
{
|
||||
vec4 bone_color, state_color;
|
||||
mat4 model_mat = extract_matrix_packed_data(inst_obmat, state_color, bone_color);
|
||||
mat4 model_mat = extract_matrix_packed_data(v_in.inst_matrix, state_color, bone_color);
|
||||
|
||||
vec4 world_pos = model_mat * vec4(pos, 1.0);
|
||||
vec4 world_pos = model_mat * vec4(v_in.l_P, 1.0);
|
||||
vec4 view_pos = drw_view.viewmat * world_pos;
|
||||
|
||||
geom_in.vPos = view_pos.xyz;
|
||||
geom_in.pPos = drw_view.winmat * view_pos;
|
||||
|
||||
geom_flat_in.inverted = int(dot(cross(model_mat[0].xyz, model_mat[1].xyz), model_mat[2].xyz) <
|
||||
0.0);
|
||||
|
||||
/* This is slow and run per vertex, but it's still faster than
|
||||
* doing it per instance on CPU and sending it on via instance attribute. */
|
||||
mat3 normal_mat = transpose(inverse(mat3(model_mat)));
|
||||
/* TODO: FIX: there is still a problem with this vector
|
||||
* when the bone is scaled or in perspective mode.
|
||||
* But it's barely visible at the outline corners. */
|
||||
geom_in.ssNor = normalize(normal_world_to_view(normal_mat * snor).xy);
|
||||
|
||||
geom_in.ssPos = proj(geom_in.pPos);
|
||||
|
||||
geom_in.vColSize = bone_color;
|
||||
VertOut v_out;
|
||||
v_out.vPos = view_pos.xyz;
|
||||
v_out.pPos = drw_view.winmat * view_pos;
|
||||
v_out.inverted = int(dot(cross(model_mat[0].xyz, model_mat[1].xyz), model_mat[2].xyz) < 0.0);
|
||||
v_out.ssPos = proj(v_out.pPos);
|
||||
v_out.vColSize = bone_color;
|
||||
|
||||
view_clipping_distances(world_pos.xyz);
|
||||
|
||||
return v_out;
|
||||
}
|
||||
|
||||
#ifndef NO_GEOM
|
||||
/* Legacy Path */
|
||||
void main()
|
||||
{
|
||||
VertIn v_in;
|
||||
v_in.l_P = pos;
|
||||
v_in.inst_matrix = inst_obmat;
|
||||
|
||||
VertOut v_out = vertex_main(v_in);
|
||||
|
||||
geom_in.vPos = v_out.vPos;
|
||||
geom_in.pPos = v_out.pPos;
|
||||
geom_in.ssPos = v_out.ssPos;
|
||||
geom_in.vColSize = v_out.vColSize;
|
||||
geom_flat_in.inverted = v_out.inverted;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void main()
|
||||
{
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -19,11 +19,9 @@ vec2 proj(vec4 pos)
|
||||
|
||||
void do_vertex_shader(mat4 in_inst_obmat,
|
||||
vec3 in_pos,
|
||||
vec3 in_snor,
|
||||
out vec4 out_pPos,
|
||||
out vec3 out_vPos,
|
||||
out vec2 out_ssPos,
|
||||
out vec2 out_ssNor,
|
||||
out vec4 out_vColSize,
|
||||
out int out_inverted,
|
||||
out vec4 out_wpos)
|
||||
@@ -42,10 +40,6 @@ void do_vertex_shader(mat4 in_inst_obmat,
|
||||
/* This is slow and run per vertex, but it's still faster than
|
||||
* doing it per instance on CPU and sending it on via instance attribute. */
|
||||
mat3 normal_mat = transpose(inverse(mat3(model_mat)));
|
||||
/* TODO FIX: there is still a problem with this vector
|
||||
* when the bone is scaled or in persp mode. But it's
|
||||
* barely visible at the outline corners. */
|
||||
out_ssNor = normalize(normal_world_to_view(normal_mat * in_snor).xy);
|
||||
|
||||
out_ssPos = proj(out_pPos);
|
||||
|
||||
@@ -73,37 +67,19 @@ void main()
|
||||
in_pos[2] = vertex_fetch_attribute_raw(vertex_id_from_index_id(4 * line_prim_id + 2), pos, vec3);
|
||||
in_pos[3] = vertex_fetch_attribute_raw(vertex_id_from_index_id(4 * line_prim_id + 3), pos, vec3);
|
||||
|
||||
vec3 in_snor[4];
|
||||
in_snor[0] = vertex_fetch_attribute_raw(vertex_id_from_index_id(4 * line_prim_id), snor, vec3);
|
||||
in_snor[1] = vertex_fetch_attribute_raw(
|
||||
vertex_id_from_index_id(4 * line_prim_id + 1), snor, vec3);
|
||||
in_snor[2] = vertex_fetch_attribute_raw(
|
||||
vertex_id_from_index_id(4 * line_prim_id + 2), snor, vec3);
|
||||
in_snor[3] = vertex_fetch_attribute_raw(
|
||||
vertex_id_from_index_id(4 * line_prim_id + 3), snor, vec3);
|
||||
|
||||
mat4 in_inst_obmat = vertex_fetch_attribute(gl_VertexID, inst_obmat, mat4);
|
||||
|
||||
/* Run original GL vertex shader implementation per vertex in adjacency list. */
|
||||
vec4 pPos[4];
|
||||
vec3 vPos[4];
|
||||
vec2 ssPos[4];
|
||||
vec2 ssNor[4];
|
||||
vec4 vColSize[4];
|
||||
int inverted[4];
|
||||
vec4 wPos[4];
|
||||
|
||||
for (int v = 0; v < 4; v++) {
|
||||
do_vertex_shader(in_inst_obmat,
|
||||
in_pos[v],
|
||||
in_snor[v],
|
||||
pPos[v],
|
||||
vPos[v],
|
||||
ssPos[v],
|
||||
ssNor[v],
|
||||
vColSize[v],
|
||||
inverted[v],
|
||||
wPos[v]);
|
||||
do_vertex_shader(
|
||||
in_inst_obmat, in_pos[v], pPos[v], vPos[v], ssPos[v], vColSize[v], inverted[v], wPos[v]);
|
||||
}
|
||||
|
||||
/* Geometry Shader equivalent to calculate vertex output position. */
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma BLENDER_REQUIRE(select_lib.glsl)
|
||||
|
||||
void main()
|
||||
{
|
||||
/* Manual back-face culling. Not ideal for performance
|
||||
@@ -9,7 +11,9 @@ void main()
|
||||
* for inverted bone matrices. */
|
||||
if ((inverted == 1) == gl_FrontFacing) {
|
||||
discard;
|
||||
return;
|
||||
}
|
||||
fragColor = vec4(finalColor.rgb, alpha);
|
||||
lineOutput = vec4(0.0);
|
||||
select_id_output(select_id);
|
||||
}
|
||||
|
||||
@@ -4,9 +4,12 @@
|
||||
|
||||
#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(select_lib.glsl)
|
||||
|
||||
void main()
|
||||
{
|
||||
select_id_set(in_select_buf[gl_InstanceID]);
|
||||
|
||||
vec4 bone_color, state_color;
|
||||
mat4 model_mat = extract_matrix_packed_data(inst_obmat, state_color, bone_color);
|
||||
|
||||
|
||||
@@ -31,18 +31,20 @@ float edge_step(float dist)
|
||||
|
||||
void main()
|
||||
{
|
||||
#ifndef NO_GEOM
|
||||
float wire_width = geometry_out.wire_width;
|
||||
if (do_smooth_wire) {
|
||||
wire_width -= 0.5;
|
||||
}
|
||||
float4 finalColor = geometry_out.finalColor;
|
||||
float edgeCoord = geometry_noperspective_out.edgeCoord;
|
||||
#endif
|
||||
|
||||
float half_size = wire_width / 2.0;
|
||||
float half_size = (do_smooth_wire ? wire_width - 0.5 : wire_width) / 2.0;
|
||||
|
||||
float dist = abs(geometry_noperspective_out.edgeCoord) - half_size;
|
||||
float dist = abs(edgeCoord) - half_size;
|
||||
const float mix_w = clamp(edge_step(dist), 0.0, 1.0);
|
||||
|
||||
fragColor = mix(vec4(geometry_out.finalColor.rgb, alpha), vec4(0), mix_w);
|
||||
fragColor = mix(vec4(finalColor.rgb, alpha), vec4(0), mix_w);
|
||||
fragColor.a *= 1.0 - mix_w;
|
||||
select_id_output(select_id);
|
||||
lineOutput = vec4(0);
|
||||
|
||||
select_id_output(select_id);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,193 @@
|
||||
/* SPDX-FileCopyrightText: 2019-2022 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(gpu_shader_utildefines_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(gpu_shader_index_load_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(gpu_shader_attribute_load_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(select_lib.glsl)
|
||||
|
||||
struct VertIn {
|
||||
vec3 lP;
|
||||
mat4 inst_matrix;
|
||||
};
|
||||
|
||||
VertIn input_assembly(uint in_vertex_id, mat4x4 inst_matrix)
|
||||
{
|
||||
uint v_i = gpu_index_load(in_vertex_id);
|
||||
|
||||
VertIn vert_in;
|
||||
vert_in.lP = gpu_attr_load_float3(pos, gpu_attr_0, v_i);
|
||||
vert_in.inst_matrix = inst_matrix;
|
||||
return vert_in;
|
||||
}
|
||||
|
||||
struct VertOut {
|
||||
vec4 gpu_position;
|
||||
vec4 finalColor;
|
||||
vec3 world_pos;
|
||||
float wire_width;
|
||||
};
|
||||
|
||||
VertOut vertex_main(VertIn v_in)
|
||||
{
|
||||
vec4 bone_color, state_color;
|
||||
mat4 model_mat = extract_matrix_packed_data(v_in.inst_matrix, state_color, bone_color);
|
||||
|
||||
VertOut v_out;
|
||||
v_out.world_pos = (model_mat * vec4(v_in.lP, 1.0)).xyz;
|
||||
v_out.gpu_position = point_world_to_ndc(v_out.world_pos);
|
||||
|
||||
v_out.finalColor.rgb = mix(state_color.rgb, bone_color.rgb, 0.5);
|
||||
v_out.finalColor.a = 1.0;
|
||||
/* Because the packing clamps the value, the wire width is passed in compressed. */
|
||||
v_out.wire_width = bone_color.a * WIRE_WIDTH_COMPRESSION;
|
||||
|
||||
return v_out;
|
||||
}
|
||||
|
||||
void do_vertex(const uint strip_index,
|
||||
uint out_vertex_id,
|
||||
uint out_primitive_id,
|
||||
vec4 color,
|
||||
vec4 hs_P,
|
||||
vec3 ws_P,
|
||||
float coord,
|
||||
vec2 offset)
|
||||
{
|
||||
bool is_odd_primitive = (out_primitive_id & 1u) != 0u;
|
||||
/* Maps triangle list primitives to triangle strip indices. */
|
||||
uint out_strip_index = (is_odd_primitive ? (2u - out_vertex_id) : out_vertex_id) +
|
||||
out_primitive_id;
|
||||
|
||||
if (out_strip_index != strip_index) {
|
||||
return;
|
||||
}
|
||||
|
||||
finalColor = color;
|
||||
edgeCoord = coord;
|
||||
gl_Position = hs_P;
|
||||
/* Multiply offset by 2 because gl_Position range is [-1..1]. */
|
||||
gl_Position.xy += offset * 2.0 * hs_P.w;
|
||||
|
||||
view_clipping_distances(ws_P);
|
||||
}
|
||||
|
||||
void geometry_main(VertOut geom_in[2],
|
||||
uint out_vertex_id,
|
||||
uint out_primitive_id,
|
||||
uint out_invocation_id)
|
||||
{
|
||||
/* Clip line against near plane to avoid deformed lines. */
|
||||
vec4 pos0 = geom_in[0].gpu_position;
|
||||
vec4 pos1 = geom_in[1].gpu_position;
|
||||
vec2 pz_ndc = vec2(pos0.z / pos0.w, pos1.z / pos1.w);
|
||||
bvec2 clipped = lessThan(pz_ndc, vec2(-1.0));
|
||||
if (all(clipped)) {
|
||||
/* Totally clipped. */
|
||||
return;
|
||||
}
|
||||
|
||||
vec4 pos01 = pos0 - pos1;
|
||||
float ofs = abs((pz_ndc.y + 1.0) / (pz_ndc.x - pz_ndc.y));
|
||||
if (clipped.y) {
|
||||
pos1 += pos01 * ofs;
|
||||
}
|
||||
else if (clipped.x) {
|
||||
pos0 -= pos01 * (1.0 - ofs);
|
||||
}
|
||||
|
||||
vec2 screen_space_pos[2];
|
||||
screen_space_pos[0] = pos0.xy / pos0.w;
|
||||
screen_space_pos[1] = pos1.xy / pos1.w;
|
||||
|
||||
/* `sizeEdge` is defined as the distance from the center to the outer edge. As such to get the
|
||||
total width it needs to be doubled. */
|
||||
wire_width = geom_in[0].wire_width * (sizeEdge * 2);
|
||||
float half_size = max(wire_width / 2.0, 0.5);
|
||||
|
||||
if (do_smooth_wire) {
|
||||
/* Add 1px for AA */
|
||||
half_size += 0.5;
|
||||
}
|
||||
|
||||
vec2 line = (screen_space_pos[0] - screen_space_pos[1]) * sizeViewport.xy;
|
||||
vec2 line_norm = normalize(vec2(line[1], -line[0]));
|
||||
vec2 edge_ofs = (half_size * line_norm) * sizeViewportInv;
|
||||
|
||||
vec4 final_color = geom_in[0].finalColor;
|
||||
do_vertex(0,
|
||||
out_vertex_id,
|
||||
out_primitive_id,
|
||||
final_color,
|
||||
pos0,
|
||||
geom_in[0].world_pos,
|
||||
half_size,
|
||||
edge_ofs);
|
||||
do_vertex(1,
|
||||
out_vertex_id,
|
||||
out_primitive_id,
|
||||
final_color,
|
||||
pos0,
|
||||
geom_in[0].world_pos,
|
||||
-half_size,
|
||||
-edge_ofs);
|
||||
|
||||
do_vertex(2,
|
||||
out_vertex_id,
|
||||
out_primitive_id,
|
||||
final_color,
|
||||
pos1,
|
||||
geom_in[1].world_pos,
|
||||
half_size,
|
||||
edge_ofs);
|
||||
do_vertex(3,
|
||||
out_vertex_id,
|
||||
out_primitive_id,
|
||||
final_color,
|
||||
pos1,
|
||||
geom_in[1].world_pos,
|
||||
-half_size,
|
||||
-edge_ofs);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
select_id_set(in_select_buf[gl_InstanceID]);
|
||||
|
||||
/* Line primitive. */
|
||||
const uint input_primitive_vertex_count = 2u;
|
||||
/* Triangle list primitive. */
|
||||
const uint ouput_primitive_vertex_count = 3u;
|
||||
const uint ouput_primitive_count = 2u;
|
||||
const uint ouput_invocation_count = 1u;
|
||||
const uint output_vertex_count_per_invocation = ouput_primitive_count *
|
||||
ouput_primitive_vertex_count;
|
||||
const uint output_vertex_count_per_input_primitive = output_vertex_count_per_invocation *
|
||||
ouput_invocation_count;
|
||||
|
||||
uint in_primitive_id = uint(gl_VertexID) / output_vertex_count_per_input_primitive;
|
||||
uint in_primitive_first_vertex = in_primitive_id * input_primitive_vertex_count;
|
||||
|
||||
uint out_vertex_id = uint(gl_VertexID) % ouput_primitive_vertex_count;
|
||||
uint out_primitive_id = (uint(gl_VertexID) / ouput_primitive_vertex_count) %
|
||||
ouput_primitive_count;
|
||||
uint out_invocation_id = (uint(gl_VertexID) / output_vertex_count_per_invocation) %
|
||||
ouput_invocation_count;
|
||||
|
||||
mat4x4 inst_matrix = inst_obmat;
|
||||
|
||||
VertIn vert_in[input_primitive_vertex_count];
|
||||
vert_in[0] = input_assembly(in_primitive_first_vertex + 0u, inst_matrix);
|
||||
vert_in[1] = input_assembly(in_primitive_first_vertex + 1u, inst_matrix);
|
||||
|
||||
VertOut vert_out[input_primitive_vertex_count];
|
||||
vert_out[0] = vertex_main(vert_in[0]);
|
||||
vert_out[1] = vertex_main(vert_in[1]);
|
||||
|
||||
/* Discard by default. */
|
||||
gl_Position = vec4(NAN_FLT);
|
||||
geometry_main(vert_out, out_vertex_id, out_primitive_id, out_invocation_id);
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(select_lib.glsl)
|
||||
|
||||
void main()
|
||||
{
|
||||
@@ -51,5 +52,9 @@ void main()
|
||||
lineOutput = vec4(0.0);
|
||||
|
||||
t /= ray_len;
|
||||
|
||||
#ifndef SELECT_ENABLE
|
||||
gl_FragDepth = get_depth_from_view_z(ray_dir_view.z * t + ray_ori_view.z);
|
||||
#endif
|
||||
select_id_output(select_id);
|
||||
}
|
||||
|
||||
@@ -2,10 +2,13 @@
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma BLENDER_REQUIRE(select_lib.glsl)
|
||||
|
||||
void main()
|
||||
{
|
||||
float fac = smoothstep(1.0, 0.2, colorFac);
|
||||
fragColor.rgb = mix(finalInnerColor.rgb, finalWireColor.rgb, fac);
|
||||
fragColor.a = alpha;
|
||||
lineOutput = vec4(0.0);
|
||||
select_id_output(select_id);
|
||||
}
|
||||
|
||||
@@ -2,35 +2,26 @@
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma BLENDER_REQUIRE(gpu_shader_utildefines_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
|
||||
|
||||
/* TODO(@fclem): Share definition with C code. */
|
||||
#define COL_WIRE 1u /* (1 << 0) */
|
||||
#define COL_HEAD 2u /* (1 << 1) */
|
||||
#define COL_TAIL 4u /* (1 << 2) */
|
||||
#define COL_BONE 8u /* (1 << 3) */
|
||||
|
||||
#define POS_HEAD 16u /* (1 << 4) */
|
||||
#define POS_TAIL 32u /* (1 << 5) */ /* UNUSED */
|
||||
#define POS_BONE 64u /* (1 << 6) */
|
||||
|
||||
#define is_head bool(flag & POS_HEAD)
|
||||
#define is_bone bool(flag & POS_BONE)
|
||||
#pragma BLENDER_REQUIRE(select_lib.glsl)
|
||||
|
||||
/* project to screen space */
|
||||
vec2 proj(vec4 pos)
|
||||
vec2 proj(vec4 hs_P)
|
||||
{
|
||||
return (0.5 * (pos.xy / pos.w) + 0.5) * sizeViewport.xy;
|
||||
return (0.5 * (hs_P.xy / hs_P.w) + 0.5) * sizeViewport.xy;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
finalInnerColor = ((flag & COL_HEAD) != 0u) ? headColor : tailColor;
|
||||
finalInnerColor = ((flag & COL_BONE) != 0u) ? boneColor : finalInnerColor;
|
||||
select_id_set(in_select_buf[gl_InstanceID]);
|
||||
|
||||
StickBoneFlag bone_flag = StickBoneFlag(flag);
|
||||
finalInnerColor = flag_test(bone_flag, COL_HEAD) ? headColor : tailColor;
|
||||
finalInnerColor = flag_test(bone_flag, COL_BONE) ? boneColor : finalInnerColor;
|
||||
finalWireColor = (do_wire) ? wireColor : finalInnerColor;
|
||||
/* Make the color */
|
||||
colorFac = ((flag & COL_WIRE) == 0u) ? ((flag & COL_BONE) != 0u) ? 1.0 : 2.0 : 0.0;
|
||||
colorFac = flag_test(bone_flag, COL_WIRE) ? 0.0 : (flag_test(bone_flag, COL_BONE) ? 1.0 : 2.0);
|
||||
|
||||
vec4 boneStart_4d = vec4(boneStart, 1.0);
|
||||
vec4 boneEnd_4d = vec4(boneEnd, 1.0);
|
||||
@@ -54,6 +45,9 @@ void main()
|
||||
vec4 p0 = drw_view.winmat * v0;
|
||||
vec4 p1 = drw_view.winmat * v1;
|
||||
|
||||
bool is_head = flag_test(bone_flag, POS_HEAD);
|
||||
bool is_bone = flag_test(bone_flag, POS_BONE);
|
||||
|
||||
float h = (is_head) ? p0.w : p1.w;
|
||||
|
||||
vec2 x_screen_vec = normalize(proj(p1) - proj(p0) + 1e-8);
|
||||
|
||||
@@ -4,13 +4,16 @@
|
||||
|
||||
#pragma BLENDER_REQUIRE(common_view_clipping_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(select_lib.glsl)
|
||||
|
||||
void main()
|
||||
{
|
||||
select_id_set(in_select_buf[gl_VertexID / 2]);
|
||||
|
||||
finalColor.rgb = color.rgb;
|
||||
finalColor.a = 1.0;
|
||||
|
||||
vec3 world_pos = point_object_to_world(pos);
|
||||
vec3 world_pos = pos;
|
||||
gl_Position = point_world_to_ndc(world_pos);
|
||||
|
||||
edgeStart = edgePos = ((gl_Position.xy / gl_Position.w) * 0.5 + 0.5) * sizeViewport.xy;
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
|
||||
namespace blender::draw::select {
|
||||
|
||||
// #define DEBUG_PRINT
|
||||
|
||||
enum class SelectionType { DISABLED = 0, ENABLED = 1 };
|
||||
|
||||
class ID {
|
||||
@@ -99,7 +101,7 @@ struct SelectMap {
|
||||
/** Uniform buffer to bind to all passes to pass information about the selection state. */
|
||||
UniformBuffer<SelectInfoData> info_buf;
|
||||
/** Will remove the depth test state from any pass drawing objects with select id. */
|
||||
bool disable_depth_test;
|
||||
bool disable_depth_test = false;
|
||||
|
||||
SelectMap(const SelectionType selection_type) : selection_type(selection_type){};
|
||||
|
||||
@@ -111,8 +113,26 @@ struct SelectMap {
|
||||
return {0};
|
||||
}
|
||||
|
||||
if (sub_object_id == uint(-1)) {
|
||||
/* WORKAROUND: Armature code set the sub_object_id to -1 when individual bones are not
|
||||
* selectable (i.e. in object mode). */
|
||||
sub_object_id = 0;
|
||||
}
|
||||
|
||||
uint object_id = ob_ref.object->runtime->select_id;
|
||||
uint id = select_id_map.append_and_get_index(object_id | sub_object_id);
|
||||
|
||||
#ifdef DEBUG_PRINT
|
||||
/* Print mapping from object name, select id and the mapping to internal select id.
|
||||
* If something is wrong at this stage, it indicates an error in the caller code. */
|
||||
printf("%s : %u | %u = %u -> %u\n",
|
||||
ob_ref.object->id.name,
|
||||
object_id,
|
||||
sub_object_id,
|
||||
object_id | sub_object_id,
|
||||
id);
|
||||
#endif
|
||||
|
||||
#ifndef NDEBUG
|
||||
map_names.append(ob_ref.object->id.name);
|
||||
#endif
|
||||
@@ -120,7 +140,7 @@ struct SelectMap {
|
||||
}
|
||||
|
||||
/* Load an invalid index that will not write to the output (not selectable). */
|
||||
[[nodiscard]] const ID select_invalid_id()
|
||||
[[nodiscard]] static const ID select_invalid_id()
|
||||
{
|
||||
return {uint32_t(-1)};
|
||||
}
|
||||
@@ -266,6 +286,13 @@ struct SelectMap {
|
||||
}
|
||||
break;
|
||||
}
|
||||
#ifdef DEBUG_PRINT
|
||||
for (auto &hit : hit_results) {
|
||||
/* Print hit results right out of the GPU selection buffer.
|
||||
* If something is wrong at this stage, it indicates an error in the selection shaders. */
|
||||
printf(" hit: %u: depth %u\n", hit_result.id, hit_result.depth);
|
||||
}
|
||||
#endif
|
||||
|
||||
gpu_select_next_set_result(hit_results.data(), hit_results.size());
|
||||
}
|
||||
|
||||
@@ -2080,12 +2080,11 @@ blender::gpu::Batch *DRW_cache_bone_octahedral_get()
|
||||
|
||||
static GPUVertFormat format = {0};
|
||||
static struct {
|
||||
uint pos, nor, snor;
|
||||
uint pos, nor;
|
||||
} attr_id;
|
||||
if (format.attr_len == 0) {
|
||||
attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
||||
attr_id.nor = GPU_vertformat_attr_add(&format, "nor", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
||||
attr_id.snor = GPU_vertformat_attr_add(&format, "snor", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
||||
}
|
||||
|
||||
/* Vertices */
|
||||
@@ -2095,10 +2094,6 @@ blender::gpu::Batch *DRW_cache_bone_octahedral_get()
|
||||
for (int i = 0; i < 8; i++) {
|
||||
for (int j = 0; j < 3; j++) {
|
||||
GPU_vertbuf_attr_set(vbo, attr_id.nor, v_idx, bone_octahedral_solid_normals[i]);
|
||||
GPU_vertbuf_attr_set(vbo,
|
||||
attr_id.snor,
|
||||
v_idx,
|
||||
bone_octahedral_smooth_normals[bone_octahedral_solid_tris[i][j]]);
|
||||
GPU_vertbuf_attr_set(
|
||||
vbo, attr_id.pos, v_idx++, bone_octahedral_verts[bone_octahedral_solid_tris[i][j]]);
|
||||
}
|
||||
@@ -2141,12 +2136,11 @@ blender::gpu::Batch *DRW_cache_bone_box_get()
|
||||
|
||||
static GPUVertFormat format = {0};
|
||||
static struct {
|
||||
uint pos, nor, snor;
|
||||
uint pos, nor;
|
||||
} attr_id;
|
||||
if (format.attr_len == 0) {
|
||||
attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
||||
attr_id.nor = GPU_vertformat_attr_add(&format, "nor", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
||||
attr_id.snor = GPU_vertformat_attr_add(&format, "snor", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
||||
}
|
||||
|
||||
/* Vertices */
|
||||
@@ -2156,8 +2150,6 @@ blender::gpu::Batch *DRW_cache_bone_box_get()
|
||||
for (int i = 0; i < 12; i++) {
|
||||
for (int j = 0; j < 3; j++) {
|
||||
GPU_vertbuf_attr_set(vbo, attr_id.nor, v_idx, bone_box_solid_normals[i]);
|
||||
GPU_vertbuf_attr_set(
|
||||
vbo, attr_id.snor, v_idx, bone_box_smooth_normals[bone_box_solid_tris[i][j]]);
|
||||
GPU_vertbuf_attr_set(vbo, attr_id.pos, v_idx++, bone_box_verts[bone_box_solid_tris[i][j]]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,6 +177,11 @@ void Draw::execute(RecordingState &state) const
|
||||
IndexRange expanded_range = {vert_range.start() * expand_prim_len,
|
||||
vert_range.size() * expand_prim_len};
|
||||
|
||||
if (expanded_range.is_empty()) {
|
||||
/* Nothing to draw, and can lead to asserts in GPU_batch_bind_as_resources. */
|
||||
return;
|
||||
}
|
||||
|
||||
GPU_batch_bind_as_resources(batch, state.shader);
|
||||
|
||||
gpu::Batch *gpu_batch = procedural_batch_get(GPUPrimType(expand_prim_type));
|
||||
|
||||
Reference in New Issue
Block a user