Cleanup: use struct for GPU the select buffer
GPU_select originally used GL_SELECT which defined the format for storing the selection result. Now this is no longer the case, define our own struct - making the code easier to follow: - Avoid having to deal with arrays in both `uint*` and `uint(*)[4]` multiplying offsets by 4 in some cases & not others. - No magic numbers for the offsets of depth & selection-ID. - No need to allocate unused members to match GL_SELECT (halving the buffer size).
This commit is contained in:
parent
9ccdad8a21
commit
8815f2f116
|
@ -27,6 +27,7 @@
|
|||
struct wmOperatorType;
|
||||
|
||||
struct Base;
|
||||
struct GPUSelectResult;
|
||||
struct Object;
|
||||
struct Scene;
|
||||
struct bContext;
|
||||
|
@ -323,21 +324,21 @@ struct Bone *ED_armature_pick_bone(struct bContext *C,
|
|||
|
||||
struct EditBone *ED_armature_pick_ebone_from_selectbuffer(struct Base **bases,
|
||||
uint bases_len,
|
||||
const uint *buffer,
|
||||
const struct GPUSelectResult *buffer,
|
||||
short hits,
|
||||
bool findunsel,
|
||||
bool do_nearest,
|
||||
struct Base **r_base);
|
||||
struct bPoseChannel *ED_armature_pick_pchan_from_selectbuffer(struct Base **bases,
|
||||
uint bases_len,
|
||||
const uint *buffer,
|
||||
const struct GPUSelectResult *buffer,
|
||||
short hits,
|
||||
bool findunsel,
|
||||
bool do_nearest,
|
||||
struct Base **r_base);
|
||||
struct Bone *ED_armature_pick_bone_from_selectbuffer(struct Base **bases,
|
||||
uint bases_len,
|
||||
const uint *buffer,
|
||||
const struct GPUSelectResult *buffer,
|
||||
short hits,
|
||||
bool findunsel,
|
||||
bool do_nearest,
|
||||
|
|
|
@ -55,6 +55,8 @@
|
|||
|
||||
#include "DEG_depsgraph.h"
|
||||
|
||||
#include "GPU_select.h"
|
||||
|
||||
#include "armature_intern.h"
|
||||
|
||||
/* utility macros for storing a temp int in the bone (selection flag) */
|
||||
|
@ -67,10 +69,10 @@
|
|||
|
||||
Base *ED_armature_base_and_ebone_from_select_buffer(Base **bases,
|
||||
uint bases_len,
|
||||
int hit,
|
||||
const uint select_id,
|
||||
EditBone **r_ebone)
|
||||
{
|
||||
const uint hit_object = hit & 0xFFFF;
|
||||
const uint hit_object = select_id & 0xFFFF;
|
||||
Base *base = NULL;
|
||||
EditBone *ebone = NULL;
|
||||
/* TODO(campbell): optimize, eg: sort & binary search. */
|
||||
|
@ -81,7 +83,7 @@ Base *ED_armature_base_and_ebone_from_select_buffer(Base **bases,
|
|||
}
|
||||
}
|
||||
if (base != NULL) {
|
||||
const uint hit_bone = (hit & ~BONESEL_ANY) >> 16;
|
||||
const uint hit_bone = (select_id & ~BONESEL_ANY) >> 16;
|
||||
bArmature *arm = base->object->data;
|
||||
ebone = BLI_findlink(arm->edbo, hit_bone);
|
||||
}
|
||||
|
@ -91,10 +93,10 @@ Base *ED_armature_base_and_ebone_from_select_buffer(Base **bases,
|
|||
|
||||
Object *ED_armature_object_and_ebone_from_select_buffer(Object **objects,
|
||||
uint objects_len,
|
||||
int hit,
|
||||
const uint select_id,
|
||||
EditBone **r_ebone)
|
||||
{
|
||||
const uint hit_object = hit & 0xFFFF;
|
||||
const uint hit_object = select_id & 0xFFFF;
|
||||
Object *ob = NULL;
|
||||
EditBone *ebone = NULL;
|
||||
/* TODO(campbell): optimize, eg: sort & binary search. */
|
||||
|
@ -105,7 +107,7 @@ Object *ED_armature_object_and_ebone_from_select_buffer(Object **objects,
|
|||
}
|
||||
}
|
||||
if (ob != NULL) {
|
||||
const uint hit_bone = (hit & ~BONESEL_ANY) >> 16;
|
||||
const uint hit_bone = (select_id & ~BONESEL_ANY) >> 16;
|
||||
bArmature *arm = ob->data;
|
||||
ebone = BLI_findlink(arm->edbo, hit_bone);
|
||||
}
|
||||
|
@ -115,10 +117,10 @@ Object *ED_armature_object_and_ebone_from_select_buffer(Object **objects,
|
|||
|
||||
Base *ED_armature_base_and_pchan_from_select_buffer(Base **bases,
|
||||
uint bases_len,
|
||||
int hit,
|
||||
const uint select_id,
|
||||
bPoseChannel **r_pchan)
|
||||
{
|
||||
const uint hit_object = hit & 0xFFFF;
|
||||
const uint hit_object = select_id & 0xFFFF;
|
||||
Base *base = NULL;
|
||||
bPoseChannel *pchan = NULL;
|
||||
/* TODO(campbell): optimize, eg: sort & binary search. */
|
||||
|
@ -130,7 +132,7 @@ Base *ED_armature_base_and_pchan_from_select_buffer(Base **bases,
|
|||
}
|
||||
if (base != NULL) {
|
||||
if (base->object->pose != NULL) {
|
||||
const uint hit_bone = (hit & ~BONESEL_ANY) >> 16;
|
||||
const uint hit_bone = (select_id & ~BONESEL_ANY) >> 16;
|
||||
/* pchan may be NULL. */
|
||||
pchan = BLI_findlink(&base->object->pose->chanbase, hit_bone);
|
||||
}
|
||||
|
@ -141,11 +143,11 @@ Base *ED_armature_base_and_pchan_from_select_buffer(Base **bases,
|
|||
|
||||
Base *ED_armature_base_and_bone_from_select_buffer(Base **bases,
|
||||
uint bases_len,
|
||||
int hit,
|
||||
const uint select_id,
|
||||
Bone **r_bone)
|
||||
{
|
||||
bPoseChannel *pchan = NULL;
|
||||
Base *base = ED_armature_base_and_pchan_from_select_buffer(bases, bases_len, hit, &pchan);
|
||||
Base *base = ED_armature_base_and_pchan_from_select_buffer(bases, bases_len, select_id, &pchan);
|
||||
*r_bone = pchan ? pchan->bone : NULL;
|
||||
return base;
|
||||
}
|
||||
|
@ -166,8 +168,8 @@ Base *ED_armature_base_and_bone_from_select_buffer(Base **bases,
|
|||
static void *ed_armature_pick_bone_from_selectbuffer_impl(const bool is_editmode,
|
||||
Base **bases,
|
||||
uint bases_len,
|
||||
const uint *buffer,
|
||||
short hits,
|
||||
const GPUSelectResult *buffer,
|
||||
const short hits,
|
||||
bool findunsel,
|
||||
bool do_nearest,
|
||||
Base **r_base)
|
||||
|
@ -181,7 +183,7 @@ static void *ed_armature_pick_bone_from_selectbuffer_impl(const bool is_editmode
|
|||
int minsel = 0xffffffff, minunsel = 0xffffffff;
|
||||
|
||||
for (short i = 0; i < hits; i++) {
|
||||
hitresult = buffer[3 + (i * 4)];
|
||||
hitresult = buffer[i].id;
|
||||
|
||||
if (hitresult & BONESEL_ANY) { /* to avoid including objects in selection */
|
||||
Base *base = NULL;
|
||||
|
@ -221,10 +223,10 @@ static void *ed_armature_pick_bone_from_selectbuffer_impl(const bool is_editmode
|
|||
if (data) {
|
||||
if (sel) {
|
||||
if (do_nearest) {
|
||||
if (minsel > buffer[4 * i + 1]) {
|
||||
if (minsel > buffer[i].depth) {
|
||||
firstSel = data;
|
||||
firstSel_base = base;
|
||||
minsel = buffer[4 * i + 1];
|
||||
minsel = buffer[i].depth;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -237,10 +239,10 @@ static void *ed_armature_pick_bone_from_selectbuffer_impl(const bool is_editmode
|
|||
}
|
||||
else {
|
||||
if (do_nearest) {
|
||||
if (minunsel > buffer[4 * i + 1]) {
|
||||
if (minunsel > buffer[i].depth) {
|
||||
firstunSel = data;
|
||||
firstunSel_base = base;
|
||||
minunsel = buffer[4 * i + 1];
|
||||
minunsel = buffer[i].depth;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -268,8 +270,8 @@ static void *ed_armature_pick_bone_from_selectbuffer_impl(const bool is_editmode
|
|||
|
||||
EditBone *ED_armature_pick_ebone_from_selectbuffer(Base **bases,
|
||||
uint bases_len,
|
||||
const uint *buffer,
|
||||
short hits,
|
||||
const GPUSelectResult *buffer,
|
||||
const short hits,
|
||||
bool findunsel,
|
||||
bool do_nearest,
|
||||
Base **r_base)
|
||||
|
@ -281,8 +283,8 @@ EditBone *ED_armature_pick_ebone_from_selectbuffer(Base **bases,
|
|||
|
||||
bPoseChannel *ED_armature_pick_pchan_from_selectbuffer(Base **bases,
|
||||
uint bases_len,
|
||||
const uint *buffer,
|
||||
short hits,
|
||||
const GPUSelectResult *buffer,
|
||||
const short hits,
|
||||
bool findunsel,
|
||||
bool do_nearest,
|
||||
Base **r_base)
|
||||
|
@ -294,8 +296,8 @@ bPoseChannel *ED_armature_pick_pchan_from_selectbuffer(Base **bases,
|
|||
|
||||
Bone *ED_armature_pick_bone_from_selectbuffer(Base **bases,
|
||||
uint bases_len,
|
||||
const uint *buffer,
|
||||
short hits,
|
||||
const GPUSelectResult *buffer,
|
||||
const short hits,
|
||||
bool findunsel,
|
||||
bool do_nearest,
|
||||
Base **r_base)
|
||||
|
@ -327,7 +329,7 @@ static void *ed_armature_pick_bone_impl(
|
|||
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
||||
ViewContext vc;
|
||||
rcti rect;
|
||||
uint buffer[MAXPICKBUF];
|
||||
GPUSelectResult buffer[MAXPICKELEMS];
|
||||
short hits;
|
||||
|
||||
ED_view3d_viewcontext_init(C, &vc, depsgraph);
|
||||
|
@ -340,7 +342,7 @@ static void *ed_armature_pick_bone_impl(
|
|||
|
||||
hits = view3d_opengl_select_with_id_filter(&vc,
|
||||
buffer,
|
||||
MAXPICKBUF,
|
||||
ARRAY_SIZE(buffer),
|
||||
&rect,
|
||||
VIEW3D_SELECT_PICK_NEAREST,
|
||||
VIEW3D_SELECT_FILTER_NOP,
|
||||
|
@ -636,15 +638,15 @@ void ARMATURE_OT_select_linked_pick(wmOperatorType *ot)
|
|||
* \{ */
|
||||
|
||||
/* utility function for get_nearest_editbonepoint */
|
||||
static int selectbuffer_ret_hits_12(uint *UNUSED(buffer), const int hits12)
|
||||
static int selectbuffer_ret_hits_12(GPUSelectResult *UNUSED(buffer), const int hits12)
|
||||
{
|
||||
return hits12;
|
||||
}
|
||||
|
||||
static int selectbuffer_ret_hits_5(uint *buffer, const int hits12, const int hits5)
|
||||
static int selectbuffer_ret_hits_5(GPUSelectResult *buffer, const int hits12, const int hits5)
|
||||
{
|
||||
const int ofs = 4 * hits12;
|
||||
memcpy(buffer, buffer + ofs, 4 * hits5 * sizeof(uint));
|
||||
const int ofs = hits12;
|
||||
memcpy(buffer, buffer + ofs, hits5 * sizeof(*buffer));
|
||||
return hits5;
|
||||
}
|
||||
|
||||
|
@ -653,7 +655,7 @@ static int selectbuffer_ret_hits_5(uint *buffer, const int hits12, const int hit
|
|||
static EditBone *get_nearest_editbonepoint(
|
||||
ViewContext *vc, bool findunsel, bool use_cycle, Base **r_base, int *r_selmask)
|
||||
{
|
||||
uint buffer[MAXPICKBUF];
|
||||
GPUSelectResult buffer[MAXPICKELEMS];
|
||||
struct {
|
||||
uint hitresult;
|
||||
Base *base;
|
||||
|
@ -692,7 +694,7 @@ static EditBone *get_nearest_editbonepoint(
|
|||
rcti rect;
|
||||
BLI_rcti_init_pt_radius(&rect, vc->mval, 12);
|
||||
const int hits12 = view3d_opengl_select_with_id_filter(
|
||||
vc, buffer, MAXPICKBUF, &rect, select_mode, select_filter, select_id_ignore);
|
||||
vc, buffer, ARRAY_SIZE(buffer), &rect, select_mode, select_filter, select_id_ignore);
|
||||
|
||||
if (hits12 == 1) {
|
||||
hits = selectbuffer_ret_hits_12(buffer, hits12);
|
||||
|
@ -701,10 +703,15 @@ static EditBone *get_nearest_editbonepoint(
|
|||
else if (hits12 > 0) {
|
||||
int ofs;
|
||||
|
||||
ofs = 4 * hits12;
|
||||
ofs = hits12;
|
||||
BLI_rcti_init_pt_radius(&rect, vc->mval, 5);
|
||||
const int hits5 = view3d_opengl_select_with_id_filter(
|
||||
vc, buffer + ofs, MAXPICKBUF - ofs, &rect, select_mode, select_filter, select_id_ignore);
|
||||
const int hits5 = view3d_opengl_select_with_id_filter(vc,
|
||||
buffer + ofs,
|
||||
ARRAY_SIZE(buffer) - ofs,
|
||||
&rect,
|
||||
select_mode,
|
||||
select_filter,
|
||||
select_id_ignore);
|
||||
|
||||
if (hits5 == 1) {
|
||||
hits = selectbuffer_ret_hits_5(buffer, hits12, hits5);
|
||||
|
@ -732,7 +739,7 @@ cache_end:
|
|||
/* See if there are any selected bones in this group */
|
||||
if (hits > 0) {
|
||||
if (hits == 1) {
|
||||
result_bias.hitresult = buffer[3];
|
||||
result_bias.hitresult = buffer->id;
|
||||
result_bias.base = ED_armature_base_and_ebone_from_select_buffer(
|
||||
bases, bases_len, result_bias.hitresult, &result_bias.ebone);
|
||||
}
|
||||
|
@ -771,7 +778,7 @@ cache_end:
|
|||
}
|
||||
|
||||
for (int i = 0; i < hits; i++) {
|
||||
const uint hitresult = buffer[3 + (i * 4)];
|
||||
const uint hitresult = buffer[i].id;
|
||||
|
||||
Base *base = NULL;
|
||||
EditBone *ebone;
|
||||
|
|
|
@ -240,8 +240,8 @@ void ED_armature_pose_select_pick_bone(ViewLayer *view_layer,
|
|||
bool ED_armature_pose_select_pick_with_buffer(ViewLayer *view_layer,
|
||||
View3D *v3d,
|
||||
Base *base,
|
||||
const uint *buffer,
|
||||
short hits,
|
||||
const struct GPUSelectResult *buffer,
|
||||
const short hits,
|
||||
bool extend,
|
||||
bool deselect,
|
||||
bool toggle,
|
||||
|
|
|
@ -35,6 +35,7 @@ struct Base;
|
|||
struct Bone;
|
||||
struct Depsgraph;
|
||||
struct EditBone;
|
||||
struct GPUSelectResult;
|
||||
struct ListBase;
|
||||
struct Main;
|
||||
struct Mesh;
|
||||
|
@ -157,22 +158,22 @@ int ED_armature_join_objects_exec(struct bContext *C, struct wmOperator *op);
|
|||
|
||||
struct Base *ED_armature_base_and_ebone_from_select_buffer(struct Base **bases,
|
||||
uint bases_len,
|
||||
int hit,
|
||||
unsigned int select_id,
|
||||
struct EditBone **r_ebone);
|
||||
struct Object *ED_armature_object_and_ebone_from_select_buffer(struct Object **objects,
|
||||
uint objects_len,
|
||||
int hit,
|
||||
unsigned int select_id,
|
||||
struct EditBone **r_ebone);
|
||||
struct Base *ED_armature_base_and_pchan_from_select_buffer(struct Base **bases,
|
||||
uint bases_len,
|
||||
int hit,
|
||||
unsigned int select_id,
|
||||
struct bPoseChannel **r_pchan);
|
||||
/**
|
||||
* For callers that don't need the pose channel.
|
||||
*/
|
||||
struct Base *ED_armature_base_and_bone_from_select_buffer(struct Base **bases,
|
||||
uint bases_len,
|
||||
int hit,
|
||||
unsigned int select_id,
|
||||
struct Bone **r_bone);
|
||||
bool ED_armature_edit_deselect_all(struct Object *obedit);
|
||||
bool ED_armature_edit_deselect_all_visible(struct Object *obedit);
|
||||
|
@ -334,7 +335,7 @@ void ED_armature_pose_select_pick_bone(struct ViewLayer *view_layer,
|
|||
bool ED_armature_pose_select_pick_with_buffer(struct ViewLayer *view_layer,
|
||||
struct View3D *v3d,
|
||||
struct Base *base,
|
||||
const unsigned int *buffer,
|
||||
const struct GPUSelectResult *buffer,
|
||||
short hits,
|
||||
bool extend,
|
||||
bool deselect,
|
||||
|
|
|
@ -41,6 +41,7 @@ struct Camera;
|
|||
struct CustomData_MeshMasks;
|
||||
struct Depsgraph;
|
||||
struct EditBone;
|
||||
struct GPUSelectResult;
|
||||
struct ID;
|
||||
struct MVert;
|
||||
struct Main;
|
||||
|
@ -873,7 +874,6 @@ bool ED_view3d_depth_read_cached_seg(
|
|||
|
||||
/* select */
|
||||
#define MAXPICKELEMS 2500
|
||||
#define MAXPICKBUF (4 * MAXPICKELEMS)
|
||||
|
||||
typedef enum {
|
||||
/* all elements in the region, ignore depth */
|
||||
|
@ -912,21 +912,21 @@ void view3d_opengl_select_cache_end(void);
|
|||
* \note (vc->obedit == NULL) can be set to explicitly skip edit-object selection.
|
||||
*/
|
||||
int view3d_opengl_select_ex(struct ViewContext *vc,
|
||||
unsigned int *buffer,
|
||||
unsigned int bufsize,
|
||||
struct GPUSelectResult *buffer,
|
||||
unsigned int buffer_len,
|
||||
const struct rcti *input,
|
||||
eV3DSelectMode select_mode,
|
||||
eV3DSelectObjectFilter select_filter,
|
||||
bool do_material_slot_selection);
|
||||
int view3d_opengl_select(struct ViewContext *vc,
|
||||
unsigned int *buffer,
|
||||
unsigned int bufsize,
|
||||
struct GPUSelectResult *buffer,
|
||||
unsigned int buffer_len,
|
||||
const struct rcti *input,
|
||||
eV3DSelectMode select_mode,
|
||||
eV3DSelectObjectFilter select_filter);
|
||||
int view3d_opengl_select_with_id_filter(struct ViewContext *vc,
|
||||
unsigned int *buffer,
|
||||
unsigned int bufsize,
|
||||
struct GPUSelectResult *buffer,
|
||||
unsigned int buffer_len,
|
||||
const struct rcti *input,
|
||||
eV3DSelectMode select_mode,
|
||||
eV3DSelectObjectFilter select_filter,
|
||||
|
|
|
@ -20,6 +20,7 @@ set(INC
|
|||
../../blenkernel
|
||||
../../blenlib
|
||||
../../depsgraph
|
||||
../../gpu
|
||||
../../makesdna
|
||||
../../makesrna
|
||||
../../render
|
||||
|
|
|
@ -47,6 +47,8 @@
|
|||
|
||||
#include "DEG_depsgraph.h"
|
||||
|
||||
#include "GPU_select.h"
|
||||
|
||||
#include "ED_mball.h"
|
||||
#include "ED_object.h"
|
||||
#include "ED_screen.h"
|
||||
|
@ -756,15 +758,19 @@ bool ED_mball_select_pick(bContext *C, const int mval[2], bool extend, bool dese
|
|||
static MetaElem *startelem = NULL;
|
||||
ViewContext vc;
|
||||
int a, hits;
|
||||
uint buffer[MAXPICKBUF];
|
||||
GPUSelectResult buffer[MAXPICKELEMS];
|
||||
rcti rect;
|
||||
|
||||
ED_view3d_viewcontext_init(C, &vc, depsgraph);
|
||||
|
||||
BLI_rcti_init_pt_radius(&rect, mval, 12);
|
||||
|
||||
hits = view3d_opengl_select(
|
||||
&vc, buffer, MAXPICKBUF, &rect, VIEW3D_SELECT_PICK_NEAREST, VIEW3D_SELECT_FILTER_NOP);
|
||||
hits = view3d_opengl_select(&vc,
|
||||
buffer,
|
||||
ARRAY_SIZE(buffer),
|
||||
&rect,
|
||||
VIEW3D_SELECT_PICK_NEAREST,
|
||||
VIEW3D_SELECT_FILTER_NOP);
|
||||
|
||||
FOREACH_BASE_IN_EDIT_MODE_BEGIN (vc.view_layer, vc.v3d, base) {
|
||||
ED_view3d_viewcontext_init_object(&vc, base->object);
|
||||
|
@ -789,7 +795,7 @@ bool ED_mball_select_pick(bContext *C, const int mval[2], bool extend, bool dese
|
|||
ml = startelem;
|
||||
while (ml) {
|
||||
for (a = 0; a < hits; a++) {
|
||||
int hitresult = buffer[(4 * a) + 3];
|
||||
const int hitresult = buffer[a].id;
|
||||
if (hitresult == -1) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -99,6 +99,7 @@
|
|||
#include "UI_resources.h"
|
||||
|
||||
#include "GPU_matrix.h"
|
||||
#include "GPU_select.h"
|
||||
|
||||
#include "DEG_depsgraph.h"
|
||||
#include "DEG_depsgraph_query.h"
|
||||
|
@ -1566,8 +1567,8 @@ void VIEW3D_OT_select_menu(wmOperatorType *ot)
|
|||
|
||||
static Base *object_mouse_select_menu(bContext *C,
|
||||
ViewContext *vc,
|
||||
const uint *buffer,
|
||||
int hits,
|
||||
const GPUSelectResult *buffer,
|
||||
const int hits,
|
||||
const int mval[2],
|
||||
bool extend,
|
||||
bool deselect,
|
||||
|
@ -1585,7 +1586,7 @@ static Base *object_mouse_select_menu(bContext *C,
|
|||
if (buffer) {
|
||||
for (int a = 0; a < hits; a++) {
|
||||
/* index was converted */
|
||||
if (base->object->runtime.select_id == (buffer[(4 * a) + 3] & ~0xFFFF0000)) {
|
||||
if (base->object->runtime.select_id == (buffer[a].id & ~0xFFFF0000)) {
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
|
@ -1742,7 +1743,7 @@ void VIEW3D_OT_bone_select_menu(wmOperatorType *ot)
|
|||
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||
}
|
||||
static bool bone_mouse_select_menu(bContext *C,
|
||||
const uint *buffer,
|
||||
const GPUSelectResult *buffer,
|
||||
const int hits,
|
||||
const bool is_editmode,
|
||||
const bool extend,
|
||||
|
@ -1760,7 +1761,7 @@ static bool bone_mouse_select_menu(bContext *C,
|
|||
for (int a = 0; a < hits; a++) {
|
||||
void *bone_ptr = NULL;
|
||||
Base *bone_base = NULL;
|
||||
uint hitresult = buffer[3 + (a * 4)];
|
||||
uint hitresult = buffer[a].id;
|
||||
|
||||
if (!(hitresult & BONESEL_ANY)) {
|
||||
/* To avoid including objects in selection. */
|
||||
|
@ -1874,10 +1875,10 @@ static bool bone_mouse_select_menu(bContext *C,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool selectbuffer_has_bones(const uint *buffer, const uint hits)
|
||||
static bool selectbuffer_has_bones(const GPUSelectResult *buffer, const uint hits)
|
||||
{
|
||||
for (uint i = 0; i < hits; i++) {
|
||||
if (buffer[(4 * i) + 3] & 0xFFFF0000) {
|
||||
if (buffer[i].id & 0xFFFF0000) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1885,25 +1886,25 @@ static bool selectbuffer_has_bones(const uint *buffer, const uint hits)
|
|||
}
|
||||
|
||||
/* utility function for mixed_bones_object_selectbuffer */
|
||||
static int selectbuffer_ret_hits_15(uint *UNUSED(buffer), const int hits15)
|
||||
static int selectbuffer_ret_hits_15(GPUSelectResult *UNUSED(buffer), const int hits15)
|
||||
{
|
||||
return hits15;
|
||||
}
|
||||
|
||||
static int selectbuffer_ret_hits_9(uint *buffer, const int hits15, const int hits9)
|
||||
static int selectbuffer_ret_hits_9(GPUSelectResult *buffer, const int hits15, const int hits9)
|
||||
{
|
||||
const int ofs = 4 * hits15;
|
||||
memcpy(buffer, buffer + ofs, 4 * hits9 * sizeof(uint));
|
||||
const int ofs = hits15;
|
||||
memcpy(buffer, buffer + ofs, hits9 * sizeof(GPUSelectResult));
|
||||
return hits9;
|
||||
}
|
||||
|
||||
static int selectbuffer_ret_hits_5(uint *buffer,
|
||||
static int selectbuffer_ret_hits_5(GPUSelectResult *buffer,
|
||||
const int hits15,
|
||||
const int hits9,
|
||||
const int hits5)
|
||||
{
|
||||
const int ofs = 4 * hits15 + 4 * hits9;
|
||||
memcpy(buffer, buffer + ofs, 4 * hits5 * sizeof(uint));
|
||||
const int ofs = hits15 + hits9;
|
||||
memcpy(buffer, buffer + ofs, hits5 * sizeof(GPUSelectResult));
|
||||
return hits5;
|
||||
}
|
||||
|
||||
|
@ -1916,7 +1917,8 @@ static int selectbuffer_ret_hits_5(uint *buffer,
|
|||
* Needed so we can step to the next, non-active object when it's already selected, see: T76445.
|
||||
*/
|
||||
static int mixed_bones_object_selectbuffer(ViewContext *vc,
|
||||
uint *buffer,
|
||||
GPUSelectResult *buffer,
|
||||
const int buffer_len,
|
||||
const int mval[2],
|
||||
eV3DSelectObjectFilter select_filter,
|
||||
bool do_nearest,
|
||||
|
@ -1941,7 +1943,7 @@ static int mixed_bones_object_selectbuffer(ViewContext *vc,
|
|||
|
||||
BLI_rcti_init_pt_radius(&rect, mval, 14);
|
||||
hits15 = view3d_opengl_select_ex(
|
||||
vc, buffer, MAXPICKBUF, &rect, select_mode, select_filter, do_material_slot_selection);
|
||||
vc, buffer, buffer_len, &rect, select_mode, select_filter, do_material_slot_selection);
|
||||
if (hits15 == 1) {
|
||||
hits = selectbuffer_ret_hits_15(buffer, hits15);
|
||||
goto finally;
|
||||
|
@ -1950,10 +1952,10 @@ static int mixed_bones_object_selectbuffer(ViewContext *vc,
|
|||
int ofs;
|
||||
has_bones15 = selectbuffer_has_bones(buffer, hits15);
|
||||
|
||||
ofs = 4 * hits15;
|
||||
ofs = hits15;
|
||||
BLI_rcti_init_pt_radius(&rect, mval, 9);
|
||||
hits9 = view3d_opengl_select(
|
||||
vc, buffer + ofs, MAXPICKBUF - ofs, &rect, select_mode, select_filter);
|
||||
vc, buffer + ofs, buffer_len - ofs, &rect, select_mode, select_filter);
|
||||
if (hits9 == 1) {
|
||||
hits = selectbuffer_ret_hits_9(buffer, hits15, hits9);
|
||||
goto finally;
|
||||
|
@ -1961,10 +1963,10 @@ static int mixed_bones_object_selectbuffer(ViewContext *vc,
|
|||
else if (hits9 > 0) {
|
||||
has_bones9 = selectbuffer_has_bones(buffer + ofs, hits9);
|
||||
|
||||
ofs += 4 * hits9;
|
||||
ofs += hits9;
|
||||
BLI_rcti_init_pt_radius(&rect, mval, 5);
|
||||
hits5 = view3d_opengl_select(
|
||||
vc, buffer + ofs, MAXPICKBUF - ofs, &rect, select_mode, select_filter);
|
||||
vc, buffer + ofs, buffer_len - ofs, &rect, select_mode, select_filter);
|
||||
if (hits5 == 1) {
|
||||
hits = selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5);
|
||||
goto finally;
|
||||
|
@ -2007,7 +2009,8 @@ finally:
|
|||
}
|
||||
|
||||
static int mixed_bones_object_selectbuffer_extended(ViewContext *vc,
|
||||
uint *buffer,
|
||||
GPUSelectResult *buffer,
|
||||
const int buffer_len,
|
||||
const int mval[2],
|
||||
eV3DSelectObjectFilter select_filter,
|
||||
bool use_cycle,
|
||||
|
@ -2038,7 +2041,7 @@ static int mixed_bones_object_selectbuffer_extended(ViewContext *vc,
|
|||
do_nearest = do_nearest && !enumerate;
|
||||
|
||||
int hits = mixed_bones_object_selectbuffer(
|
||||
vc, buffer, mval, select_filter, do_nearest, true, false);
|
||||
vc, buffer, buffer_len, mval, select_filter, do_nearest, true, false);
|
||||
|
||||
return hits;
|
||||
}
|
||||
|
@ -2051,7 +2054,7 @@ static int mixed_bones_object_selectbuffer_extended(ViewContext *vc,
|
|||
* \return the active base or NULL.
|
||||
*/
|
||||
static Base *mouse_select_eval_buffer(ViewContext *vc,
|
||||
const uint *buffer,
|
||||
const GPUSelectResult *buffer,
|
||||
int hits,
|
||||
Base *startbase,
|
||||
bool has_bones,
|
||||
|
@ -2071,10 +2074,10 @@ static Base *mouse_select_eval_buffer(ViewContext *vc,
|
|||
if (has_bones) {
|
||||
/* we skip non-bone hits */
|
||||
for (a = 0; a < hits; a++) {
|
||||
if (min > buffer[4 * a + 1] && (buffer[4 * a + 3] & 0xFFFF0000)) {
|
||||
min = buffer[4 * a + 1];
|
||||
selcol = buffer[4 * a + 3] & 0xFFFF;
|
||||
sub_selection_id = (buffer[4 * a + 3] & 0xFFFF0000) >> 16;
|
||||
if (min > buffer[a].depth && (buffer[a].id & 0xFFFF0000)) {
|
||||
min = buffer[a].depth;
|
||||
selcol = buffer[a].id & 0xFFFF;
|
||||
sub_selection_id = (buffer[a].id & 0xFFFF0000) >> 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2085,10 +2088,10 @@ static Base *mouse_select_eval_buffer(ViewContext *vc,
|
|||
}
|
||||
|
||||
for (a = 0; a < hits; a++) {
|
||||
if (min > buffer[4 * a + 1] && notcol != (buffer[4 * a + 3] & 0xFFFF)) {
|
||||
min = buffer[4 * a + 1];
|
||||
selcol = buffer[4 * a + 3] & 0xFFFF;
|
||||
sub_selection_id = (buffer[4 * a + 3] & 0xFFFF0000) >> 16;
|
||||
if (min > buffer[a].depth && notcol != (buffer[a].id & 0xFFFF)) {
|
||||
min = buffer[a].depth;
|
||||
selcol = buffer[a].id & 0xFFFF;
|
||||
sub_selection_id = (buffer[a].id & 0xFFFF0000) >> 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2127,14 +2130,14 @@ static Base *mouse_select_eval_buffer(ViewContext *vc,
|
|||
for (a = 0; a < hits; a++) {
|
||||
if (has_bones) {
|
||||
/* skip non-bone objects */
|
||||
if (buffer[4 * a + 3] & 0xFFFF0000) {
|
||||
if (base->object->runtime.select_id == (buffer[(4 * a) + 3] & 0xFFFF)) {
|
||||
if (buffer[a].id & 0xFFFF0000) {
|
||||
if (base->object->runtime.select_id == (buffer[a].id & 0xFFFF)) {
|
||||
basact = base;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (base->object->runtime.select_id == (buffer[(4 * a) + 3] & 0xFFFF)) {
|
||||
if (base->object->runtime.select_id == (buffer[a].id & 0xFFFF)) {
|
||||
basact = base;
|
||||
}
|
||||
}
|
||||
|
@ -2169,7 +2172,7 @@ static Base *ed_view3d_give_base_under_cursor_ex(bContext *C,
|
|||
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
||||
ViewContext vc;
|
||||
Base *basact = NULL;
|
||||
uint buffer[MAXPICKBUF];
|
||||
GPUSelectResult buffer[MAXPICKELEMS];
|
||||
|
||||
/* setup view context for argument to callbacks */
|
||||
view3d_operator_needs_opengl(C);
|
||||
|
@ -2179,8 +2182,14 @@ static Base *ed_view3d_give_base_under_cursor_ex(bContext *C,
|
|||
|
||||
const bool do_nearest = !XRAY_ACTIVE(vc.v3d);
|
||||
const bool do_material_slot_selection = r_material_slot != NULL;
|
||||
const int hits = mixed_bones_object_selectbuffer(
|
||||
&vc, buffer, mval, VIEW3D_SELECT_FILTER_NOP, do_nearest, false, do_material_slot_selection);
|
||||
const int hits = mixed_bones_object_selectbuffer(&vc,
|
||||
buffer,
|
||||
ARRAY_SIZE(buffer),
|
||||
mval,
|
||||
VIEW3D_SELECT_FILTER_NOP,
|
||||
do_nearest,
|
||||
false,
|
||||
do_material_slot_selection);
|
||||
|
||||
if (hits > 0) {
|
||||
const bool has_bones = (r_material_slot == NULL) && selectbuffer_has_bones(buffer, hits);
|
||||
|
@ -2342,7 +2351,7 @@ static bool ed_object_select_pick(bContext *C,
|
|||
}
|
||||
}
|
||||
else {
|
||||
uint buffer[MAXPICKBUF];
|
||||
GPUSelectResult buffer[MAXPICKELEMS];
|
||||
bool do_nearest;
|
||||
|
||||
// TIMEIT_START(select_time);
|
||||
|
@ -2353,7 +2362,7 @@ static bool ed_object_select_pick(bContext *C,
|
|||
vc.obact) :
|
||||
VIEW3D_SELECT_FILTER_NOP);
|
||||
hits = mixed_bones_object_selectbuffer_extended(
|
||||
&vc, buffer, mval, select_filter, true, enumerate, &do_nearest);
|
||||
&vc, buffer, ARRAY_SIZE(buffer), mval, select_filter, true, enumerate, &do_nearest);
|
||||
|
||||
// TIMEIT_END(select_time);
|
||||
|
||||
|
@ -2383,7 +2392,7 @@ static bool ed_object_select_pick(bContext *C,
|
|||
bool changed = false;
|
||||
|
||||
for (int i = 0; i < hits; i++) {
|
||||
int hitresult = buffer[3 + (i * 4)];
|
||||
const int hitresult = buffer[i].id;
|
||||
|
||||
/* if there's bundles in buffer select bundles first,
|
||||
* so non-camera elements should be ignored in buffer */
|
||||
|
@ -2394,7 +2403,7 @@ static bool ed_object_select_pick(bContext *C,
|
|||
/* index of bundle is 1<<16-based. if there's no "bone" index
|
||||
* in height word, this buffer value belongs to camera. not to bundle
|
||||
*/
|
||||
if (buffer[4 * i + 3] & 0xFFFF0000) {
|
||||
if (hitresult & 0xFFFF0000) {
|
||||
MovieTracking *tracking = &clip->tracking;
|
||||
ListBase *tracksbase;
|
||||
MovieTrackingTrack *track;
|
||||
|
@ -2674,9 +2683,15 @@ static int view3d_select_exec(bContext *C, wmOperator *op)
|
|||
ViewContext vc;
|
||||
ED_view3d_viewcontext_init(C, &vc, depsgraph);
|
||||
|
||||
uint buffer[MAXPICKBUF];
|
||||
const int hits = mixed_bones_object_selectbuffer(
|
||||
&vc, buffer, location, VIEW3D_SELECT_FILTER_NOP, false, true, false);
|
||||
GPUSelectResult buffer[MAXPICKELEMS];
|
||||
const int hits = mixed_bones_object_selectbuffer(&vc,
|
||||
buffer,
|
||||
ARRAY_SIZE(buffer),
|
||||
location,
|
||||
VIEW3D_SELECT_FILTER_NOP,
|
||||
false,
|
||||
true,
|
||||
false);
|
||||
retval = bone_mouse_select_menu(C, buffer, hits, true, extend, deselect, toggle);
|
||||
}
|
||||
if (!retval) {
|
||||
|
@ -3256,11 +3271,11 @@ static bool do_meta_box_select(ViewContext *vc, const rcti *rect, const eSelectO
|
|||
int a;
|
||||
bool changed = false;
|
||||
|
||||
uint buffer[MAXPICKBUF];
|
||||
GPUSelectResult buffer[MAXPICKELEMS];
|
||||
int hits;
|
||||
|
||||
hits = view3d_opengl_select(
|
||||
vc, buffer, MAXPICKBUF, rect, VIEW3D_SELECT_ALL, VIEW3D_SELECT_FILTER_NOP);
|
||||
vc, buffer, MAXPICKELEMS, rect, VIEW3D_SELECT_ALL, VIEW3D_SELECT_FILTER_NOP);
|
||||
|
||||
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
|
||||
changed |= BKE_mball_deselect_all(mb);
|
||||
|
@ -3272,7 +3287,7 @@ static bool do_meta_box_select(ViewContext *vc, const rcti *rect, const eSelectO
|
|||
bool is_inside_stiff = false;
|
||||
|
||||
for (a = 0; a < hits; a++) {
|
||||
int hitresult = buffer[(4 * a) + 3];
|
||||
const int hitresult = buffer[a].id;
|
||||
|
||||
if (hitresult == -1) {
|
||||
continue;
|
||||
|
@ -3323,11 +3338,11 @@ static bool do_armature_box_select(ViewContext *vc, const rcti *rect, const eSel
|
|||
bool changed = false;
|
||||
int a;
|
||||
|
||||
uint buffer[MAXPICKBUF];
|
||||
GPUSelectResult buffer[MAXPICKELEMS];
|
||||
int hits;
|
||||
|
||||
hits = view3d_opengl_select(
|
||||
vc, buffer, MAXPICKBUF, rect, VIEW3D_SELECT_ALL, VIEW3D_SELECT_FILTER_NOP);
|
||||
vc, buffer, MAXPICKELEMS, rect, VIEW3D_SELECT_ALL, VIEW3D_SELECT_FILTER_NOP);
|
||||
|
||||
uint bases_len = 0;
|
||||
Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(
|
||||
|
@ -3347,7 +3362,7 @@ static bool do_armature_box_select(ViewContext *vc, const rcti *rect, const eSel
|
|||
|
||||
/* first we only check points inside the border */
|
||||
for (a = 0; a < hits; a++) {
|
||||
int select_id = buffer[(4 * a) + 3];
|
||||
const int select_id = buffer[a].id;
|
||||
if (select_id != -1) {
|
||||
if ((select_id & 0xFFFF0000) == 0) {
|
||||
continue;
|
||||
|
@ -3375,14 +3390,13 @@ static bool do_armature_box_select(ViewContext *vc, const rcti *rect, const eSel
|
|||
}
|
||||
|
||||
/**
|
||||
* Compare result of 'GPU_select': 'uint[4]',
|
||||
* Compare result of 'GPU_select': 'GPUSelectResult',
|
||||
* needed for when we need to align with object draw-order.
|
||||
*/
|
||||
static int opengl_bone_select_buffer_cmp(const void *sel_a_p, const void *sel_b_p)
|
||||
{
|
||||
/* 4th element is select id */
|
||||
uint sel_a = ((uint *)sel_a_p)[3];
|
||||
uint sel_b = ((uint *)sel_b_p)[3];
|
||||
uint sel_a = ((GPUSelectResult *)sel_a_p)->id;
|
||||
uint sel_b = ((GPUSelectResult *)sel_b_p)->id;
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
BLI_endian_switch_uint32(&sel_a);
|
||||
|
@ -3401,14 +3415,15 @@ static int opengl_bone_select_buffer_cmp(const void *sel_a_p, const void *sel_b_
|
|||
static bool do_object_box_select(bContext *C, ViewContext *vc, rcti *rect, const eSelectOp sel_op)
|
||||
{
|
||||
View3D *v3d = vc->v3d;
|
||||
int totobj = MAXPICKBUF; /* XXX solve later */
|
||||
int totobj = MAXPICKELEMS; /* XXX solve later */
|
||||
|
||||
/* selection buffer now has bones potentially too, so we add MAXPICKBUF */
|
||||
uint *vbuffer = MEM_mallocN(4 * (totobj + MAXPICKELEMS) * sizeof(uint[4]), "selection buffer");
|
||||
/* Selection buffer has bones potentially too, so we add #MAXPICKELEMS. */
|
||||
GPUSelectResult *buffer = MEM_mallocN((totobj + MAXPICKELEMS) * sizeof(GPUSelectResult),
|
||||
"selection buffer");
|
||||
const eV3DSelectObjectFilter select_filter = ED_view3d_select_filter_from_mode(vc->scene,
|
||||
vc->obact);
|
||||
const int hits = view3d_opengl_select(
|
||||
vc, vbuffer, 4 * (totobj + MAXPICKELEMS), rect, VIEW3D_SELECT_ALL, select_filter);
|
||||
vc, buffer, (totobj + MAXPICKELEMS), rect, VIEW3D_SELECT_ALL, select_filter);
|
||||
|
||||
LISTBASE_FOREACH (Base *, base, &vc->view_layer->object_bases) {
|
||||
base->object->id.tag &= ~LIB_TAG_DOIT;
|
||||
|
@ -3435,12 +3450,13 @@ static bool do_object_box_select(bContext *C, ViewContext *vc, rcti *rect, const
|
|||
}
|
||||
|
||||
/* The draw order doesn't always match the order we populate the engine, see: T51695. */
|
||||
qsort(vbuffer, hits, sizeof(uint[4]), opengl_bone_select_buffer_cmp);
|
||||
qsort(buffer, hits, sizeof(GPUSelectResult), opengl_bone_select_buffer_cmp);
|
||||
|
||||
for (const uint *col = vbuffer + 3, *col_end = col + (hits * 4); col < col_end; col += 4) {
|
||||
for (const GPUSelectResult *buf_iter = buffer, *buf_end = buf_iter + hits; buf_iter < buf_end;
|
||||
buf_iter++) {
|
||||
bPoseChannel *pchan_dummy;
|
||||
Base *base = ED_armature_base_and_pchan_from_select_buffer(
|
||||
bases, BLI_array_len(bases), *col, &pchan_dummy);
|
||||
bases, BLI_array_len(bases), buf_iter->id, &pchan_dummy);
|
||||
if (base != NULL) {
|
||||
base->object->id.tag |= LIB_TAG_DOIT;
|
||||
}
|
||||
|
@ -3463,7 +3479,7 @@ finally:
|
|||
MEM_freeN(bases);
|
||||
}
|
||||
|
||||
MEM_freeN(vbuffer);
|
||||
MEM_freeN(buffer);
|
||||
|
||||
if (changed) {
|
||||
DEG_id_tag_update(&vc->scene->id, ID_RECALC_SELECT);
|
||||
|
@ -3477,14 +3493,15 @@ static bool do_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, const e
|
|||
uint bases_len;
|
||||
Base **bases = do_pose_tag_select_op_prepare(vc, &bases_len);
|
||||
|
||||
int totobj = MAXPICKBUF; /* XXX solve later */
|
||||
int totobj = MAXPICKELEMS; /* XXX solve later */
|
||||
|
||||
/* selection buffer now has bones potentially too, so we add MAXPICKBUF */
|
||||
uint *vbuffer = MEM_mallocN((totobj + MAXPICKELEMS) * sizeof(uint[4]), "selection buffer");
|
||||
/* Selection buffer has bones potentially too, so add #MAXPICKELEMS. */
|
||||
GPUSelectResult *buffer = MEM_mallocN((totobj + MAXPICKELEMS) * sizeof(GPUSelectResult),
|
||||
"selection buffer");
|
||||
const eV3DSelectObjectFilter select_filter = ED_view3d_select_filter_from_mode(vc->scene,
|
||||
vc->obact);
|
||||
const int hits = view3d_opengl_select(
|
||||
vc, vbuffer, 4 * (totobj + MAXPICKELEMS), rect, VIEW3D_SELECT_ALL, select_filter);
|
||||
vc, buffer, (totobj + MAXPICKELEMS), rect, VIEW3D_SELECT_ALL, select_filter);
|
||||
/*
|
||||
* LOGIC NOTES (theeth):
|
||||
* The buffer and ListBase have the same relative order, which makes the selection
|
||||
|
@ -3498,18 +3515,20 @@ static bool do_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, const e
|
|||
/* no need to loop if there's no hit */
|
||||
|
||||
/* The draw order doesn't always match the order we populate the engine, see: T51695. */
|
||||
qsort(vbuffer, hits, sizeof(uint[4]), opengl_bone_select_buffer_cmp);
|
||||
qsort(buffer, hits, sizeof(GPUSelectResult), opengl_bone_select_buffer_cmp);
|
||||
|
||||
for (const uint *col = vbuffer + 3, *col_end = col + (hits * 4); col < col_end; col += 4) {
|
||||
for (const GPUSelectResult *buf_iter = buffer, *buf_end = buf_iter + hits; buf_iter < buf_end;
|
||||
buf_iter++) {
|
||||
Bone *bone;
|
||||
Base *base = ED_armature_base_and_bone_from_select_buffer(bases, bases_len, *col, &bone);
|
||||
Base *base = ED_armature_base_and_bone_from_select_buffer(
|
||||
bases, bases_len, buf_iter->id, &bone);
|
||||
|
||||
if (base == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Loop over contiguous bone hits for 'base'. */
|
||||
for (; col != col_end; col += 4) {
|
||||
for (; buf_iter != buf_end; buf_iter++) {
|
||||
/* should never fail */
|
||||
if (bone != NULL) {
|
||||
base->object->id.tag |= LIB_TAG_DOIT;
|
||||
|
@ -3517,12 +3536,13 @@ static bool do_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, const e
|
|||
}
|
||||
|
||||
/* Select the next bone if we're not switching bases. */
|
||||
if (col + 4 != col_end) {
|
||||
if ((base->object->runtime.select_id & 0x0000FFFF) != (col[4] & 0x0000FFFF)) {
|
||||
if (buf_iter + 1 != buf_end) {
|
||||
const GPUSelectResult *col_next = buf_iter + 1;
|
||||
if ((base->object->runtime.select_id & 0x0000FFFF) != (col_next->id & 0x0000FFFF)) {
|
||||
break;
|
||||
}
|
||||
if (base->object->pose != NULL) {
|
||||
const uint hit_bone = (col[4] & ~BONESEL_ANY) >> 16;
|
||||
const uint hit_bone = (col_next->id & ~BONESEL_ANY) >> 16;
|
||||
bPoseChannel *pchan = BLI_findlink(&base->object->pose->chanbase, hit_bone);
|
||||
bone = pchan ? pchan->bone : NULL;
|
||||
}
|
||||
|
@ -3543,7 +3563,7 @@ static bool do_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, const e
|
|||
if (bases != NULL) {
|
||||
MEM_freeN(bases);
|
||||
}
|
||||
MEM_freeN(vbuffer);
|
||||
MEM_freeN(buffer);
|
||||
|
||||
return changed_multi;
|
||||
}
|
||||
|
|
|
@ -863,7 +863,7 @@ void view3d_opengl_select_cache_end(void)
|
|||
struct DrawSelectLoopUserData {
|
||||
uint pass;
|
||||
uint hits;
|
||||
uint *buffer;
|
||||
GPUSelectResult *buffer;
|
||||
uint buffer_len;
|
||||
const rcti *rect;
|
||||
eGPUSelectMode gpu_select_mode;
|
||||
|
@ -927,8 +927,8 @@ static bool drw_select_filter_object_mode_lock_for_weight_paint(Object *ob, void
|
|||
}
|
||||
|
||||
int view3d_opengl_select_ex(ViewContext *vc,
|
||||
uint *buffer,
|
||||
uint bufsize,
|
||||
GPUSelectResult *buffer,
|
||||
uint buffer_len,
|
||||
const rcti *input,
|
||||
eV3DSelectMode select_mode,
|
||||
eV3DSelectObjectFilter select_filter,
|
||||
|
@ -1043,7 +1043,7 @@ int view3d_opengl_select_ex(ViewContext *vc,
|
|||
/* Re-use cache (rect must be smaller than the cached)
|
||||
* other context is assumed to be unchanged */
|
||||
if (GPU_select_is_cached()) {
|
||||
GPU_select_begin(buffer, bufsize, &rect, gpu_select_mode, 0);
|
||||
GPU_select_begin(buffer, buffer_len, &rect, gpu_select_mode, 0);
|
||||
GPU_select_cache_load_id();
|
||||
hits = GPU_select_end();
|
||||
goto finally;
|
||||
|
@ -1071,7 +1071,7 @@ int view3d_opengl_select_ex(ViewContext *vc,
|
|||
.pass = 0,
|
||||
.hits = 0,
|
||||
.buffer = buffer,
|
||||
.buffer_len = bufsize,
|
||||
.buffer_len = buffer_len,
|
||||
.rect = &rect,
|
||||
.gpu_select_mode = gpu_select_mode,
|
||||
};
|
||||
|
@ -1101,7 +1101,7 @@ int view3d_opengl_select_ex(ViewContext *vc,
|
|||
.pass = 0,
|
||||
.hits = 0,
|
||||
.buffer = buffer,
|
||||
.buffer_len = bufsize,
|
||||
.buffer_len = buffer_len,
|
||||
.rect = &rect,
|
||||
.gpu_select_mode = gpu_select_mode,
|
||||
};
|
||||
|
@ -1144,24 +1144,24 @@ finally:
|
|||
}
|
||||
|
||||
int view3d_opengl_select(ViewContext *vc,
|
||||
uint *buffer,
|
||||
uint bufsize,
|
||||
GPUSelectResult *buffer,
|
||||
uint buffer_len,
|
||||
const rcti *input,
|
||||
eV3DSelectMode select_mode,
|
||||
eV3DSelectObjectFilter select_filter)
|
||||
{
|
||||
return view3d_opengl_select_ex(vc, buffer, bufsize, input, select_mode, select_filter, false);
|
||||
return view3d_opengl_select_ex(vc, buffer, buffer_len, input, select_mode, select_filter, false);
|
||||
}
|
||||
|
||||
int view3d_opengl_select_with_id_filter(ViewContext *vc,
|
||||
uint *buffer,
|
||||
uint bufsize,
|
||||
GPUSelectResult *buffer,
|
||||
const uint buffer_len,
|
||||
const rcti *input,
|
||||
eV3DSelectMode select_mode,
|
||||
eV3DSelectObjectFilter select_filter,
|
||||
uint select_id)
|
||||
{
|
||||
int hits = view3d_opengl_select(vc, buffer, bufsize, input, select_mode, select_filter);
|
||||
int hits = view3d_opengl_select(vc, buffer, buffer_len, input, select_mode, select_filter);
|
||||
|
||||
/* Selection sometimes uses -1 for an invalid selection ID, remove these as they
|
||||
* interfere with detection of actual number of hits in the selection. */
|
||||
|
|
|
@ -42,11 +42,27 @@ typedef enum eGPUSelectMode {
|
|||
GPU_SELECT_PICK_NEAREST = 5,
|
||||
} eGPUSelectMode;
|
||||
|
||||
/**
|
||||
* The result of calling #GPU_select_begin & #GPU_select_end.
|
||||
*/
|
||||
typedef struct GPUSelectResult {
|
||||
/** The selection identifier matching the value passed in by #GPU_select_load_id. */
|
||||
unsigned int id;
|
||||
/**
|
||||
* The nearest depth.
|
||||
* - Only supported by picking modes (#GPU_SELECT_PICK_ALL and #GPU_SELECT_PICK_NEAREST)
|
||||
* since occlusion quiries don't provide a convenient way of accessing the depth-buffer.
|
||||
* - OpenGL's `GL_SELECT` supported both near and far depths,
|
||||
* this has not been included as Blender doesn't need this however support could be added.
|
||||
*/
|
||||
unsigned int depth;
|
||||
} GPUSelectResult;
|
||||
|
||||
/**
|
||||
* Initialize and provide buffer for results.
|
||||
*/
|
||||
void GPU_select_begin(unsigned int *buffer,
|
||||
unsigned int bufsize,
|
||||
void GPU_select_begin(GPUSelectResult *buffer,
|
||||
unsigned int buffer_len,
|
||||
const struct rcti *input,
|
||||
eGPUSelectMode mode,
|
||||
int oldhits);
|
||||
|
@ -82,8 +98,8 @@ void GPU_select_cache_end(void);
|
|||
*
|
||||
* Note that comparing depth as uint is fine.
|
||||
*/
|
||||
const uint *GPU_select_buffer_near(const uint *buffer, int hits);
|
||||
uint GPU_select_buffer_remove_by_id(uint *buffer, int hits, uint select_id);
|
||||
const GPUSelectResult *GPU_select_buffer_near(const GPUSelectResult *buffer, int hits);
|
||||
uint GPU_select_buffer_remove_by_id(GPUSelectResult *buffer, int hits, uint select_id);
|
||||
/**
|
||||
* Part of the solution copied from `rect_subregion_stride_calc`.
|
||||
*/
|
||||
|
|
|
@ -80,8 +80,11 @@ static GPUSelectState g_select_state = {0};
|
|||
/** \name Public API
|
||||
* \{ */
|
||||
|
||||
void GPU_select_begin(
|
||||
uint *buffer, uint bufsize, const rcti *input, eGPUSelectMode mode, int oldhits)
|
||||
void GPU_select_begin(GPUSelectResult *buffer,
|
||||
const uint buffer_len,
|
||||
const rcti *input,
|
||||
eGPUSelectMode mode,
|
||||
int oldhits)
|
||||
{
|
||||
if (mode == GPU_SELECT_NEAREST_SECOND_PASS) {
|
||||
/* In the case hits was '-1',
|
||||
|
@ -120,12 +123,12 @@ void GPU_select_begin(
|
|||
|
||||
switch (g_select_state.algorithm) {
|
||||
case ALGO_GL_QUERY: {
|
||||
gpu_select_query_begin((uint(*)[4])buffer, bufsize / 4, input, mode, oldhits);
|
||||
gpu_select_query_begin(buffer, buffer_len, input, mode, oldhits);
|
||||
break;
|
||||
}
|
||||
default: /* ALGO_GL_PICK */
|
||||
{
|
||||
gpu_select_pick_begin((uint(*)[4])buffer, bufsize / 4, input, mode);
|
||||
gpu_select_pick_begin(buffer, buffer_len, input, mode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -220,35 +223,35 @@ bool GPU_select_is_cached(void)
|
|||
/** \name Utilities
|
||||
* \{ */
|
||||
|
||||
const uint *GPU_select_buffer_near(const uint *buffer, int hits)
|
||||
const GPUSelectResult *GPU_select_buffer_near(const GPUSelectResult *buffer, int hits)
|
||||
{
|
||||
const uint *buffer_near = NULL;
|
||||
const GPUSelectResult *buffer_near = NULL;
|
||||
uint depth_min = (uint)-1;
|
||||
for (int i = 0; i < hits; i++) {
|
||||
if (buffer[1] < depth_min) {
|
||||
BLI_assert(buffer[3] != -1);
|
||||
depth_min = buffer[1];
|
||||
if (buffer->depth < depth_min) {
|
||||
BLI_assert(buffer->id != -1);
|
||||
depth_min = buffer->depth;
|
||||
buffer_near = buffer;
|
||||
}
|
||||
buffer += 4;
|
||||
buffer++;
|
||||
}
|
||||
return buffer_near;
|
||||
}
|
||||
|
||||
uint GPU_select_buffer_remove_by_id(uint *buffer, int hits, uint select_id)
|
||||
uint GPU_select_buffer_remove_by_id(GPUSelectResult *buffer, int hits, uint select_id)
|
||||
{
|
||||
uint *buffer_src = buffer;
|
||||
uint *buffer_dst = buffer;
|
||||
GPUSelectResult *buffer_src = buffer;
|
||||
GPUSelectResult *buffer_dst = buffer;
|
||||
int hits_final = 0;
|
||||
for (int i = 0; i < hits; i++) {
|
||||
if (buffer_src[3] != select_id) {
|
||||
if (buffer_src->id != select_id) {
|
||||
if (buffer_dst != buffer_src) {
|
||||
memcpy(buffer_dst, buffer_src, sizeof(int[4]));
|
||||
memcpy(buffer_dst, buffer_src, sizeof(GPUSelectResult));
|
||||
}
|
||||
buffer_dst += 4;
|
||||
buffer_dst++;
|
||||
hits_final += 1;
|
||||
}
|
||||
buffer_src += 4;
|
||||
buffer_src++;
|
||||
}
|
||||
return hits_final;
|
||||
}
|
||||
|
|
|
@ -238,10 +238,8 @@ static int depth_cmp(const void *v1, const void *v2)
|
|||
/* depth sorting */
|
||||
typedef struct GPUPickState {
|
||||
/* cache on initialization */
|
||||
uint (*buffer)[4];
|
||||
|
||||
/* Buffer size (stores number of integers, for actual size multiply by sizeof integer). */
|
||||
uint bufsize;
|
||||
GPUSelectResult *buffer;
|
||||
uint buffer_len;
|
||||
/* mode of operation */
|
||||
eGPUSelectMode mode;
|
||||
|
||||
|
@ -303,7 +301,10 @@ typedef struct GPUPickState {
|
|||
|
||||
static GPUPickState g_pick_state = {0};
|
||||
|
||||
void gpu_select_pick_begin(uint (*buffer)[4], uint bufsize, const rcti *input, eGPUSelectMode mode)
|
||||
void gpu_select_pick_begin(GPUSelectResult *buffer,
|
||||
const uint buffer_len,
|
||||
const rcti *input,
|
||||
eGPUSelectMode mode)
|
||||
{
|
||||
GPUPickState *ps = &g_pick_state;
|
||||
|
||||
|
@ -317,8 +318,8 @@ void gpu_select_pick_begin(uint (*buffer)[4], uint bufsize, const rcti *input, e
|
|||
|
||||
GPU_debug_group_begin("Selection Pick");
|
||||
|
||||
ps->bufsize = bufsize;
|
||||
ps->buffer = buffer;
|
||||
ps->buffer_len = buffer_len;
|
||||
ps->mode = mode;
|
||||
|
||||
const uint rect_len = (uint)(BLI_rcti_size_x(input) * BLI_rcti_size_y(input));
|
||||
|
@ -580,7 +581,7 @@ uint gpu_select_pick_end(void)
|
|||
rect_depth_final = ps->gl.rect_depth;
|
||||
}
|
||||
|
||||
uint maxhits = g_pick_state.bufsize;
|
||||
uint maxhits = g_pick_state.buffer_len;
|
||||
DepthID *depth_data;
|
||||
uint depth_data_len = 0;
|
||||
|
||||
|
@ -675,11 +676,8 @@ uint gpu_select_pick_end(void)
|
|||
#ifdef DEBUG_PRINT
|
||||
printf(" hit: %u: depth %u\n", depth_data[i].id, depth_data[i].depth);
|
||||
#endif
|
||||
/* first 3 are dummy values */
|
||||
g_pick_state.buffer[hits][0] = 1;
|
||||
g_pick_state.buffer[hits][1] = depth_data[i].depth;
|
||||
g_pick_state.buffer[hits][2] = 0x0; /* z-far is currently never used. */
|
||||
g_pick_state.buffer[hits][3] = depth_data[i].id;
|
||||
g_pick_state.buffer[hits].depth = depth_data[i].depth;
|
||||
g_pick_state.buffer[hits].id = depth_data[i].id;
|
||||
hits++;
|
||||
}
|
||||
BLI_assert(hits < maxhits);
|
||||
|
|
|
@ -31,8 +31,8 @@ extern "C" {
|
|||
|
||||
/* gpu_select_pick */
|
||||
|
||||
void gpu_select_pick_begin(uint (*buffer)[4],
|
||||
uint bufsize,
|
||||
void gpu_select_pick_begin(GPUSelectResult *buffer,
|
||||
uint buffer_len,
|
||||
const rcti *input,
|
||||
eGPUSelectMode mode);
|
||||
bool gpu_select_pick_load_id(uint id, bool end);
|
||||
|
@ -49,7 +49,7 @@ void gpu_select_pick_cache_load_id(void);
|
|||
/* gpu_select_sample_query */
|
||||
|
||||
void gpu_select_query_begin(
|
||||
uint (*buffer)[4], uint bufsize, const rcti *input, eGPUSelectMode mode, int oldhits);
|
||||
GPUSelectResult *buffer, uint buffer_len, const rcti *input, eGPUSelectMode mode, int oldhits);
|
||||
bool gpu_select_query_load_id(uint id);
|
||||
uint gpu_select_query_end(void);
|
||||
|
||||
|
|
|
@ -55,9 +55,9 @@ struct GPUSelectQueryState {
|
|||
/* Array holding the id corresponding id to each query. */
|
||||
Vector<uint> *ids;
|
||||
/* Cache on initialization. */
|
||||
uint (*buffer)[4];
|
||||
/* Buffer size (stores number of integers, for actual size multiply by `sizeof(int)`). */
|
||||
uint bufsize;
|
||||
GPUSelectResult *buffer;
|
||||
/* The capacity of the `buffer` array. */
|
||||
uint buffer_len;
|
||||
/* Mode of operation. */
|
||||
eGPUSelectMode mode;
|
||||
uint index;
|
||||
|
@ -72,14 +72,17 @@ struct GPUSelectQueryState {
|
|||
|
||||
static GPUSelectQueryState g_query_state = {false};
|
||||
|
||||
void gpu_select_query_begin(
|
||||
uint (*buffer)[4], uint bufsize, const rcti *input, const eGPUSelectMode mode, int oldhits)
|
||||
void gpu_select_query_begin(GPUSelectResult *buffer,
|
||||
uint buffer_len,
|
||||
const rcti *input,
|
||||
const eGPUSelectMode mode,
|
||||
int oldhits)
|
||||
{
|
||||
GPU_debug_group_begin("Selection Queries");
|
||||
|
||||
g_query_state.query_issued = false;
|
||||
g_query_state.bufsize = bufsize;
|
||||
g_query_state.buffer = buffer;
|
||||
g_query_state.buffer_len = buffer_len;
|
||||
g_query_state.mode = mode;
|
||||
g_query_state.index = 0;
|
||||
g_query_state.oldhits = oldhits;
|
||||
|
@ -138,10 +141,11 @@ bool gpu_select_query_load_id(uint id)
|
|||
g_query_state.query_issued = true;
|
||||
|
||||
if (g_query_state.mode == GPU_SELECT_NEAREST_SECOND_PASS) {
|
||||
/* Second pass should never run if first pass fails, can read past 'bufsize' in this case. */
|
||||
/* Second pass should never run if first pass fails,
|
||||
* can read past `buffer_len` in this case. */
|
||||
BLI_assert(g_query_state.oldhits != -1);
|
||||
if (g_query_state.index < g_query_state.oldhits) {
|
||||
if (g_query_state.buffer[g_query_state.index][3] == id) {
|
||||
if (g_query_state.buffer[g_query_state.index].id == id) {
|
||||
g_query_state.index++;
|
||||
return true;
|
||||
}
|
||||
|
@ -154,7 +158,7 @@ bool gpu_select_query_load_id(uint id)
|
|||
uint gpu_select_query_end()
|
||||
{
|
||||
uint hits = 0;
|
||||
const uint maxhits = g_query_state.bufsize;
|
||||
const uint maxhits = g_query_state.buffer_len;
|
||||
|
||||
if (g_query_state.query_issued) {
|
||||
g_query_state.queries->end_query();
|
||||
|
@ -168,10 +172,8 @@ uint gpu_select_query_end()
|
|||
if (result[i] != 0) {
|
||||
if (g_query_state.mode != GPU_SELECT_NEAREST_SECOND_PASS) {
|
||||
if (hits < maxhits) {
|
||||
g_query_state.buffer[hits][0] = 1;
|
||||
g_query_state.buffer[hits][1] = 0xFFFF;
|
||||
g_query_state.buffer[hits][2] = 0xFFFF;
|
||||
g_query_state.buffer[hits][3] = ids[i];
|
||||
g_query_state.buffer[hits].depth = 0xFFFF;
|
||||
g_query_state.buffer[hits].id = ids[i];
|
||||
hits++;
|
||||
}
|
||||
else {
|
||||
|
@ -183,9 +185,8 @@ uint gpu_select_query_end()
|
|||
int j;
|
||||
/* search in buffer and make selected object first */
|
||||
for (j = 0; j < g_query_state.oldhits; j++) {
|
||||
if (g_query_state.buffer[j][3] == ids[i]) {
|
||||
g_query_state.buffer[j][1] = 0;
|
||||
g_query_state.buffer[j][2] = 0;
|
||||
if (g_query_state.buffer[j].id == ids[i]) {
|
||||
g_query_state.buffer[j].depth = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -572,7 +572,7 @@ static int gizmo_find_intersected_3d_intern(wmGizmo **visible_gizmos,
|
|||
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
|
||||
rcti rect;
|
||||
/* Almost certainly overkill, but allow for many custom gizmos. */
|
||||
uint buffer[MAXPICKBUF];
|
||||
GPUSelectResult buffer[MAXPICKELEMS];
|
||||
short hits;
|
||||
|
||||
BLI_rcti_init_pt_radius(&rect, co, hotspot);
|
||||
|
@ -650,14 +650,14 @@ static int gizmo_find_intersected_3d_intern(wmGizmo **visible_gizmos,
|
|||
|
||||
GPU_matrix_unproject_3fv(co_screen, rv3d->viewinv, rv3d->winmat, viewport, co_3d_origin);
|
||||
|
||||
uint *buf_iter = buffer;
|
||||
GPUSelectResult *buf_iter = buffer;
|
||||
float dot_best = FLT_MAX;
|
||||
|
||||
for (int i = 0; i < hits; i++, buf_iter += 4) {
|
||||
BLI_assert(buf_iter[3] != -1);
|
||||
wmGizmo *gz = visible_gizmos[buf_iter[3] >> 8];
|
||||
for (int i = 0; i < hits; i++, buf_iter++) {
|
||||
BLI_assert(buf_iter->id != -1);
|
||||
wmGizmo *gz = visible_gizmos[buf_iter->id >> 8];
|
||||
float co_3d[3];
|
||||
co_screen[2] = int_as_float(buf_iter[1]);
|
||||
co_screen[2] = int_as_float(buf_iter->depth);
|
||||
GPU_matrix_unproject_3fv(co_screen, rv3d->viewinv, rv3d->winmat, viewport, co_3d);
|
||||
float select_bias = gz->select_bias;
|
||||
if ((gz->flag & WM_GIZMO_DRAW_NO_SCALE) == 0) {
|
||||
|
@ -667,14 +667,14 @@ static int gizmo_find_intersected_3d_intern(wmGizmo **visible_gizmos,
|
|||
const float dot_test = dot_v3v3(co_3d, co_direction) - select_bias;
|
||||
if (dot_best > dot_test) {
|
||||
dot_best = dot_test;
|
||||
hit_found = buf_iter[3];
|
||||
hit_found = buf_iter->id;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
const uint *hit_near = GPU_select_buffer_near(buffer, hits);
|
||||
const GPUSelectResult *hit_near = GPU_select_buffer_near(buffer, hits);
|
||||
if (hit_near) {
|
||||
hit_found = hit_near[3];
|
||||
hit_found = hit_near->id;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue