2011-02-23 10:52:22 +00:00
|
|
|
/*
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software Foundation,
|
2010-02-12 13:34:04 +00:00
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
*/
|
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
* \ingroup bli
|
2011-02-27 20:37:56 +00:00
|
|
|
*/
|
|
|
|
|
2010-08-16 05:46:10 +00:00
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
#include "BLI_utildefines.h"
|
|
|
|
|
2012-02-22 23:57:31 +00:00
|
|
|
#include "BLI_bitmap.h"
|
2009-11-11 10:44:46 +00:00
|
|
|
#include "BLI_math.h"
|
2009-10-27 19:53:34 +00:00
|
|
|
#include "BLI_ghash.h"
|
2016-01-27 12:14:00 +01:00
|
|
|
#include "BLI_task.h"
|
2009-10-27 19:53:34 +00:00
|
|
|
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
#include "DNA_meshdata_types.h"
|
|
|
|
|
2012-12-15 15:59:25 +00:00
|
|
|
#include "BKE_pbvh.h"
|
2012-05-10 20:33:09 +00:00
|
|
|
#include "BKE_ccg.h"
|
2017-09-28 01:38:17 +10:00
|
|
|
#include "BKE_subsurf.h"
|
2009-11-25 13:40:43 +00:00
|
|
|
#include "BKE_DerivedMesh.h"
|
2012-05-05 21:28:12 +00:00
|
|
|
#include "BKE_mesh.h" /* for BKE_mesh_calc_normals */
|
2012-03-14 06:32:25 +00:00
|
|
|
#include "BKE_paint.h"
|
2009-10-27 19:53:34 +00:00
|
|
|
|
2010-07-14 10:46:12 +00:00
|
|
|
#include "GPU_buffers.h"
|
2017-03-02 21:40:13 -05:00
|
|
|
#include "GPU_immediate.h"
|
2009-10-27 19:53:34 +00:00
|
|
|
|
2013-05-30 02:16:22 +00:00
|
|
|
#include "bmesh.h"
|
|
|
|
|
2016-01-27 12:14:00 +01:00
|
|
|
#include "atomic_ops.h"
|
|
|
|
|
2012-12-30 18:25:36 +00:00
|
|
|
#include "pbvh_intern.h"
|
|
|
|
|
2015-07-31 22:52:37 +02:00
|
|
|
#include <limits.h>
|
|
|
|
|
2009-10-27 19:53:34 +00:00
|
|
|
#define LEAF_LIMIT 10000
|
|
|
|
|
|
|
|
//#define PERFCNTRS
|
|
|
|
|
2012-05-11 08:05:47 +00:00
|
|
|
#define STACK_FIXED_DEPTH 100
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
|
2016-01-27 12:14:00 +01:00
|
|
|
#define PBVH_THREADED_LIMIT 4
|
2014-07-28 15:47:32 +06:00
|
|
|
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
typedef struct PBVHStack {
|
|
|
|
PBVHNode *node;
|
2015-11-25 19:49:31 -05:00
|
|
|
bool revisiting;
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
} PBVHStack;
|
|
|
|
|
|
|
|
typedef struct PBVHIter {
|
|
|
|
PBVH *bvh;
|
2012-12-30 18:31:31 +00:00
|
|
|
BKE_pbvh_SearchCallback scb;
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
void *search_data;
|
|
|
|
|
|
|
|
PBVHStack *stack;
|
|
|
|
int stacksize;
|
|
|
|
|
|
|
|
PBVHStack stackfixed[STACK_FIXED_DEPTH];
|
|
|
|
int stackspace;
|
|
|
|
} PBVHIter;
|
2009-10-27 19:53:34 +00:00
|
|
|
|
2012-12-30 18:28:36 +00:00
|
|
|
void BB_reset(BB *bb)
|
2009-10-27 19:53:34 +00:00
|
|
|
{
|
|
|
|
bb->bmin[0] = bb->bmin[1] = bb->bmin[2] = FLT_MAX;
|
|
|
|
bb->bmax[0] = bb->bmax[1] = bb->bmax[2] = -FLT_MAX;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Expand the bounding box to include a new coordinate */
|
2012-12-30 18:28:36 +00:00
|
|
|
void BB_expand(BB *bb, const float co[3])
|
2009-10-27 19:53:34 +00:00
|
|
|
{
|
2015-11-25 19:49:31 -05:00
|
|
|
for (int i = 0; i < 3; ++i) {
|
2012-10-23 13:28:22 +00:00
|
|
|
bb->bmin[i] = min_ff(bb->bmin[i], co[i]);
|
|
|
|
bb->bmax[i] = max_ff(bb->bmax[i], co[i]);
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
}
|
2009-10-27 19:53:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Expand the bounding box to include another bounding box */
|
2012-12-30 18:28:36 +00:00
|
|
|
void BB_expand_with_bb(BB *bb, BB *bb2)
|
2009-10-27 19:53:34 +00:00
|
|
|
{
|
2015-11-25 19:49:31 -05:00
|
|
|
for (int i = 0; i < 3; ++i) {
|
2012-10-23 13:28:22 +00:00
|
|
|
bb->bmin[i] = min_ff(bb->bmin[i], bb2->bmin[i]);
|
|
|
|
bb->bmax[i] = max_ff(bb->bmax[i], bb2->bmax[i]);
|
2009-10-27 19:53:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return 0, 1, or 2 to indicate the widest axis of the bounding box */
|
2012-12-30 18:28:36 +00:00
|
|
|
int BB_widest_axis(const BB *bb)
|
2009-10-27 19:53:34 +00:00
|
|
|
{
|
|
|
|
float dim[3];
|
|
|
|
|
2015-11-25 19:49:31 -05:00
|
|
|
for (int i = 0; i < 3; ++i)
|
2009-10-27 19:53:34 +00:00
|
|
|
dim[i] = bb->bmax[i] - bb->bmin[i];
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (dim[0] > dim[1]) {
|
|
|
|
if (dim[0] > dim[2])
|
2009-10-27 19:53:34 +00:00
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
else {
|
2012-03-24 06:18:31 +00:00
|
|
|
if (dim[1] > dim[2])
|
2009-10-27 19:53:34 +00:00
|
|
|
return 1;
|
|
|
|
else
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-30 18:28:36 +00:00
|
|
|
void BBC_update_centroid(BBC *bbc)
|
2009-10-27 19:53:34 +00:00
|
|
|
{
|
2015-11-25 19:49:31 -05:00
|
|
|
for (int i = 0; i < 3; ++i)
|
2009-10-27 19:53:34 +00:00
|
|
|
bbc->bcentroid[i] = (bbc->bmin[i] + bbc->bmax[i]) * 0.5f;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Not recursive */
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
static void update_node_vb(PBVH *bvh, PBVHNode *node)
|
2009-10-27 19:53:34 +00:00
|
|
|
{
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
BB vb;
|
|
|
|
|
|
|
|
BB_reset(&vb);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (node->flag & PBVH_Leaf) {
|
2009-11-25 13:40:43 +00:00
|
|
|
PBVHVertexIter vd;
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
|
2012-12-30 18:31:31 +00:00
|
|
|
BKE_pbvh_vertex_iter_begin(bvh, node, vd, PBVH_ITER_ALL)
|
2012-05-11 08:05:47 +00:00
|
|
|
{
|
2009-11-25 13:40:43 +00:00
|
|
|
BB_expand(&vb, vd.co);
|
2009-10-27 19:53:34 +00:00
|
|
|
}
|
2012-12-30 18:31:31 +00:00
|
|
|
BKE_pbvh_vertex_iter_end;
|
2009-10-27 19:53:34 +00:00
|
|
|
}
|
|
|
|
else {
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
BB_expand_with_bb(&vb,
|
2012-05-11 08:05:47 +00:00
|
|
|
&bvh->nodes[node->children_offset].vb);
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
BB_expand_with_bb(&vb,
|
2012-05-11 08:05:47 +00:00
|
|
|
&bvh->nodes[node->children_offset + 1].vb);
|
2009-10-27 19:53:34 +00:00
|
|
|
}
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
|
2012-05-11 08:05:47 +00:00
|
|
|
node->vb = vb;
|
2009-10-27 19:53:34 +00:00
|
|
|
}
|
|
|
|
|
2012-12-30 18:31:31 +00:00
|
|
|
//void BKE_pbvh_node_BB_reset(PBVHNode *node)
|
2010-07-14 14:11:03 +00:00
|
|
|
//{
|
|
|
|
// BB_reset(&node->vb);
|
|
|
|
//}
|
|
|
|
//
|
2012-12-30 18:31:31 +00:00
|
|
|
//void BKE_pbvh_node_BB_expand(PBVHNode *node, float co[3])
|
2010-07-14 14:11:03 +00:00
|
|
|
//{
|
|
|
|
// BB_expand(&node->vb, co);
|
|
|
|
//}
|
|
|
|
|
2015-11-25 19:49:31 -05:00
|
|
|
static bool face_materials_match(const MPoly *f1, const MPoly *f2)
|
2012-03-06 02:40:08 +00:00
|
|
|
{
|
|
|
|
return ((f1->flag & ME_SMOOTH) == (f2->flag & ME_SMOOTH) &&
|
2012-05-11 08:05:47 +00:00
|
|
|
(f1->mat_nr == f2->mat_nr));
|
2012-03-06 02:40:08 +00:00
|
|
|
}
|
|
|
|
|
2015-11-25 19:49:31 -05:00
|
|
|
static bool grid_materials_match(const DMFlagMat *f1, const DMFlagMat *f2)
|
2012-03-06 02:40:08 +00:00
|
|
|
{
|
|
|
|
return ((f1->flag & ME_SMOOTH) == (f2->flag & ME_SMOOTH) &&
|
2012-05-11 08:05:47 +00:00
|
|
|
(f1->mat_nr == f2->mat_nr));
|
2012-03-06 02:40:08 +00:00
|
|
|
}
|
2010-07-14 14:11:03 +00:00
|
|
|
|
2009-10-27 19:53:34 +00:00
|
|
|
/* Adapted from BLI_kdopbvh.c */
|
|
|
|
/* Returns the index of the first element on the right of the partition */
|
2009-11-25 13:40:43 +00:00
|
|
|
static int partition_indices(int *prim_indices, int lo, int hi, int axis,
|
2012-05-11 08:05:47 +00:00
|
|
|
float mid, BBC *prim_bbc)
|
2009-10-27 19:53:34 +00:00
|
|
|
{
|
2012-05-11 08:05:47 +00:00
|
|
|
int i = lo, j = hi;
|
|
|
|
for (;; ) {
|
|
|
|
for (; prim_bbc[prim_indices[i]].bcentroid[axis] < mid; i++) ;
|
|
|
|
for (; mid < prim_bbc[prim_indices[j]].bcentroid[axis]; j--) ;
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!(i < j))
|
2009-10-27 19:53:34 +00:00
|
|
|
return i;
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2009-11-25 13:40:43 +00:00
|
|
|
SWAP(int, prim_indices[i], prim_indices[j]);
|
2009-10-27 19:53:34 +00:00
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-06 02:40:08 +00:00
|
|
|
/* Returns the index of the first element on the right of the partition */
|
|
|
|
static int partition_indices_material(PBVH *bvh, int lo, int hi)
|
|
|
|
{
|
2015-07-17 03:36:03 +10:00
|
|
|
const MPoly *mpoly = bvh->mpoly;
|
|
|
|
const MLoopTri *looptri = bvh->looptri;
|
2012-03-06 02:40:08 +00:00
|
|
|
const DMFlagMat *flagmats = bvh->grid_flag_mats;
|
|
|
|
const int *indices = bvh->prim_indices;
|
|
|
|
const void *first;
|
2012-05-11 08:05:47 +00:00
|
|
|
int i = lo, j = hi;
|
2012-03-06 02:40:08 +00:00
|
|
|
|
2015-07-17 03:36:03 +10:00
|
|
|
if (bvh->looptri)
|
2015-07-24 16:28:18 +02:00
|
|
|
first = &mpoly[looptri[bvh->prim_indices[lo]].poly];
|
2012-03-06 02:40:08 +00:00
|
|
|
else
|
|
|
|
first = &flagmats[bvh->prim_indices[lo]];
|
|
|
|
|
2012-05-11 08:05:47 +00:00
|
|
|
for (;; ) {
|
2015-07-17 03:36:03 +10:00
|
|
|
if (bvh->looptri) {
|
|
|
|
for (; face_materials_match(first, &mpoly[looptri[indices[i]].poly]); i++) ;
|
|
|
|
for (; !face_materials_match(first, &mpoly[looptri[indices[j]].poly]); j--) ;
|
2012-03-06 02:40:08 +00:00
|
|
|
}
|
|
|
|
else {
|
2012-05-11 08:05:47 +00:00
|
|
|
for (; grid_materials_match(first, &flagmats[indices[i]]); i++) ;
|
|
|
|
for (; !grid_materials_match(first, &flagmats[indices[j]]); j--) ;
|
2012-03-06 02:40:08 +00:00
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!(i < j))
|
2012-03-06 02:40:08 +00:00
|
|
|
return i;
|
|
|
|
|
|
|
|
SWAP(int, bvh->prim_indices[i], bvh->prim_indices[j]);
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-30 18:28:36 +00:00
|
|
|
void pbvh_grow_nodes(PBVH *bvh, int totnode)
|
2009-10-27 19:53:34 +00:00
|
|
|
{
|
2015-04-14 16:02:38 +10:00
|
|
|
if (UNLIKELY(totnode > bvh->node_mem_count)) {
|
|
|
|
bvh->node_mem_count = bvh->node_mem_count + (bvh->node_mem_count / 3);
|
2012-03-24 06:18:31 +00:00
|
|
|
if (bvh->node_mem_count < totnode)
|
2009-10-27 19:53:34 +00:00
|
|
|
bvh->node_mem_count = totnode;
|
2015-04-14 16:02:38 +10:00
|
|
|
bvh->nodes = MEM_recallocN(bvh->nodes, sizeof(PBVHNode) * bvh->node_mem_count);
|
2009-10-27 19:53:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bvh->totnode = totnode;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Add a vertex to the map, with a positive value for unique vertices and
|
2012-03-03 20:19:11 +00:00
|
|
|
* a negative value for additional vertices */
|
2009-11-06 16:46:35 +00:00
|
|
|
static int map_insert_vert(PBVH *bvh, GHash *map,
|
2012-05-11 08:05:47 +00:00
|
|
|
unsigned int *face_verts,
|
|
|
|
unsigned int *uniq_verts, int vertex)
|
2009-10-27 19:53:34 +00:00
|
|
|
{
|
2013-08-24 15:31:47 +00:00
|
|
|
void *key, **value_p;
|
2009-10-27 19:53:34 +00:00
|
|
|
|
2018-09-19 12:05:58 +10:00
|
|
|
key = POINTER_FROM_INT(vertex);
|
2016-02-13 17:45:41 +11:00
|
|
|
if (!BLI_ghash_ensure_p(map, key, &value_p)) {
|
|
|
|
int value_i;
|
|
|
|
if (BLI_BITMAP_TEST(bvh->vert_bitmap, vertex) == 0) {
|
|
|
|
BLI_BITMAP_ENABLE(bvh->vert_bitmap, vertex);
|
|
|
|
value_i = *uniq_verts;
|
|
|
|
(*uniq_verts)++;
|
2009-10-27 19:53:34 +00:00
|
|
|
}
|
|
|
|
else {
|
2016-02-13 17:45:41 +11:00
|
|
|
value_i = ~(*face_verts);
|
|
|
|
(*face_verts)++;
|
2009-10-27 19:53:34 +00:00
|
|
|
}
|
2018-09-19 12:05:58 +10:00
|
|
|
*value_p = POINTER_FROM_INT(value_i);
|
2016-02-13 17:45:41 +11:00
|
|
|
return value_i;
|
2009-10-27 19:53:34 +00:00
|
|
|
}
|
2013-08-24 15:31:47 +00:00
|
|
|
else {
|
2018-09-19 12:05:58 +10:00
|
|
|
return POINTER_AS_INT(*value_p);
|
2013-08-24 15:31:47 +00:00
|
|
|
}
|
2009-10-27 19:53:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Find vertices used by the faces in this node and update the draw buffers */
|
2009-11-25 13:40:43 +00:00
|
|
|
static void build_mesh_leaf_node(PBVH *bvh, PBVHNode *node)
|
2009-10-27 19:53:34 +00:00
|
|
|
{
|
2014-05-05 22:21:30 +03:00
|
|
|
bool has_visible = false;
|
2009-10-27 19:53:34 +00:00
|
|
|
|
|
|
|
node->uniq_verts = node->face_verts = 0;
|
2015-11-25 19:49:31 -05:00
|
|
|
const int totface = node->totprim;
|
2009-10-27 19:53:34 +00:00
|
|
|
|
2013-08-24 17:33:47 +00:00
|
|
|
/* reserve size is rough guess */
|
2015-11-25 19:49:31 -05:00
|
|
|
GHash *map = BLI_ghash_int_new_ex("build_mesh_leaf_node gh", 2 * totface);
|
2013-08-24 17:33:47 +00:00
|
|
|
|
2016-07-06 19:15:47 +10:00
|
|
|
int (*face_vert_indices)[3] = MEM_mallocN(sizeof(int[3]) * totface,
|
2015-11-25 19:49:31 -05:00
|
|
|
"bvh node face vert indices");
|
2015-07-12 03:49:47 +10:00
|
|
|
|
2016-07-06 19:15:47 +10:00
|
|
|
node->face_vert_indices = (const int (*)[3])face_vert_indices;
|
2009-11-06 16:46:35 +00:00
|
|
|
|
2015-11-25 19:49:31 -05:00
|
|
|
for (int i = 0; i < totface; ++i) {
|
2015-07-17 03:36:03 +10:00
|
|
|
const MLoopTri *lt = &bvh->looptri[node->prim_indices[i]];
|
2016-07-06 19:15:47 +10:00
|
|
|
for (int j = 0; j < 3; ++j) {
|
2015-07-12 03:49:47 +10:00
|
|
|
face_vert_indices[i][j] =
|
2012-05-11 08:05:47 +00:00
|
|
|
map_insert_vert(bvh, map, &node->face_verts,
|
2015-07-17 03:36:03 +10:00
|
|
|
&node->uniq_verts, bvh->mloop[lt->tri[j]].v);
|
2009-10-27 19:53:34 +00:00
|
|
|
}
|
2014-05-05 22:21:30 +03:00
|
|
|
|
2015-07-17 03:36:03 +10:00
|
|
|
if (!paint_is_face_hidden(lt, bvh->verts, bvh->mloop)) {
|
2014-05-05 22:21:30 +03:00
|
|
|
has_visible = true;
|
2015-07-17 03:36:03 +10:00
|
|
|
}
|
2009-10-27 19:53:34 +00:00
|
|
|
}
|
|
|
|
|
2015-11-25 19:49:31 -05:00
|
|
|
int *vert_indices = MEM_callocN(sizeof(int) * (node->uniq_verts + node->face_verts),
|
|
|
|
"bvh node vert indices");
|
2015-07-12 03:49:47 +10:00
|
|
|
node->vert_indices = vert_indices;
|
2009-10-27 19:53:34 +00:00
|
|
|
|
|
|
|
/* Build the vertex list, unique verts first */
|
2015-11-25 19:49:31 -05:00
|
|
|
GHashIterator gh_iter;
|
2015-02-06 15:31:08 +11:00
|
|
|
GHASH_ITER (gh_iter, map) {
|
|
|
|
void *value = BLI_ghashIterator_getValue(&gh_iter);
|
2018-09-19 12:05:58 +10:00
|
|
|
int ndx = POINTER_AS_INT(value);
|
2009-10-27 19:53:34 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (ndx < 0)
|
2009-10-27 19:53:34 +00:00
|
|
|
ndx = -ndx + node->uniq_verts - 1;
|
|
|
|
|
2015-07-12 03:49:47 +10:00
|
|
|
vert_indices[ndx] =
|
2018-09-19 12:05:58 +10:00
|
|
|
POINTER_AS_INT(BLI_ghashIterator_getKey(&gh_iter));
|
2009-10-27 19:53:34 +00:00
|
|
|
}
|
|
|
|
|
2015-11-25 19:49:31 -05:00
|
|
|
for (int i = 0; i < totface; ++i) {
|
2015-07-17 03:36:03 +10:00
|
|
|
const int sides = 3;
|
|
|
|
|
2015-11-25 19:49:31 -05:00
|
|
|
for (int j = 0; j < sides; ++j) {
|
2015-07-12 03:49:47 +10:00
|
|
|
if (face_vert_indices[i][j] < 0)
|
|
|
|
face_vert_indices[i][j] =
|
|
|
|
-face_vert_indices[i][j] +
|
2012-05-11 08:05:47 +00:00
|
|
|
node->uniq_verts - 1;
|
2011-07-31 02:34:53 +00:00
|
|
|
}
|
|
|
|
}
|
2009-11-06 16:46:35 +00:00
|
|
|
|
2014-01-05 04:58:27 +02:00
|
|
|
BKE_pbvh_node_mark_rebuild_draw(node);
|
2009-10-27 19:53:34 +00:00
|
|
|
|
2014-05-05 22:21:30 +03:00
|
|
|
BKE_pbvh_node_fully_hidden_set(node, !has_visible);
|
|
|
|
|
2009-10-27 19:53:34 +00:00
|
|
|
BLI_ghash_free(map, NULL, NULL);
|
|
|
|
}
|
|
|
|
|
2012-03-05 22:24:49 +00:00
|
|
|
static void update_vb(PBVH *bvh, PBVHNode *node, BBC *prim_bbc,
|
2012-05-11 08:05:47 +00:00
|
|
|
int offset, int count)
|
2012-03-05 21:55:53 +00:00
|
|
|
{
|
2012-03-05 22:24:49 +00:00
|
|
|
BB_reset(&node->vb);
|
2015-11-25 19:49:31 -05:00
|
|
|
for (int i = offset + count - 1; i >= offset; --i) {
|
2012-05-11 08:05:47 +00:00
|
|
|
BB_expand_with_bb(&node->vb, (BB *)(&prim_bbc[bvh->prim_indices[i]]));
|
2012-03-05 22:24:49 +00:00
|
|
|
}
|
|
|
|
node->orig_vb = node->vb;
|
|
|
|
}
|
2012-03-05 21:55:53 +00:00
|
|
|
|
2014-05-05 22:21:30 +03:00
|
|
|
/* Returns the number of visible quads in the nodes' grids. */
|
|
|
|
int BKE_pbvh_count_grid_quads(BLI_bitmap **grid_hidden,
|
2014-05-07 06:11:28 +10:00
|
|
|
int *grid_indices, int totgrid,
|
|
|
|
int gridsize)
|
2014-05-05 22:21:30 +03:00
|
|
|
{
|
2015-11-25 19:49:31 -05:00
|
|
|
const int gridarea = (gridsize - 1) * (gridsize - 1);
|
|
|
|
int totquad = 0;
|
2014-05-05 22:21:30 +03:00
|
|
|
|
|
|
|
/* grid hidden layer is present, so have to check each grid for
|
|
|
|
* visibility */
|
|
|
|
|
2015-11-25 19:49:31 -05:00
|
|
|
for (int i = 0; i < totgrid; i++) {
|
2014-05-05 22:21:30 +03:00
|
|
|
const BLI_bitmap *gh = grid_hidden[grid_indices[i]];
|
|
|
|
|
|
|
|
if (gh) {
|
|
|
|
/* grid hidden are present, have to check each element */
|
2015-11-25 19:49:31 -05:00
|
|
|
for (int y = 0; y < gridsize - 1; y++) {
|
|
|
|
for (int x = 0; x < gridsize - 1; x++) {
|
2014-05-05 22:21:30 +03:00
|
|
|
if (!paint_is_grid_face_hidden(gh, gridsize, x, y))
|
|
|
|
totquad++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
totquad += gridarea;
|
|
|
|
}
|
|
|
|
|
|
|
|
return totquad;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void build_grid_leaf_node(PBVH *bvh, PBVHNode *node)
|
|
|
|
{
|
|
|
|
int totquads = BKE_pbvh_count_grid_quads(bvh->grid_hidden, node->prim_indices,
|
2014-05-07 06:11:28 +10:00
|
|
|
node->totprim, bvh->gridkey.grid_size);
|
2014-05-05 22:21:30 +03:00
|
|
|
BKE_pbvh_node_fully_hidden_set(node, (totquads == 0));
|
|
|
|
BKE_pbvh_node_mark_rebuild_draw(node);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-03-05 22:24:49 +00:00
|
|
|
static void build_leaf(PBVH *bvh, int node_index, BBC *prim_bbc,
|
2012-05-11 08:05:47 +00:00
|
|
|
int offset, int count)
|
2012-03-05 22:24:49 +00:00
|
|
|
{
|
2012-03-05 21:55:53 +00:00
|
|
|
bvh->nodes[node_index].flag |= PBVH_Leaf;
|
|
|
|
|
|
|
|
bvh->nodes[node_index].prim_indices = bvh->prim_indices + offset;
|
|
|
|
bvh->nodes[node_index].totprim = count;
|
|
|
|
|
|
|
|
/* Still need vb for searches */
|
2012-03-05 22:24:49 +00:00
|
|
|
update_vb(bvh, &bvh->nodes[node_index], prim_bbc, offset, count);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2015-07-17 03:36:03 +10:00
|
|
|
if (bvh->looptri)
|
2012-03-05 21:55:53 +00:00
|
|
|
build_mesh_leaf_node(bvh, bvh->nodes + node_index);
|
2014-05-05 22:21:30 +03:00
|
|
|
else {
|
|
|
|
build_grid_leaf_node(bvh, bvh->nodes + node_index);
|
|
|
|
}
|
2012-03-05 21:55:53 +00:00
|
|
|
}
|
|
|
|
|
2012-03-06 02:40:08 +00:00
|
|
|
/* Return zero if all primitives in the node can be drawn with the
|
2014-06-09 11:01:51 +10:00
|
|
|
* same material (including flat/smooth shading), non-zero otherwise */
|
2015-11-25 19:49:31 -05:00
|
|
|
static bool leaf_needs_material_split(PBVH *bvh, int offset, int count)
|
2012-03-06 02:40:08 +00:00
|
|
|
{
|
2012-03-24 06:18:31 +00:00
|
|
|
if (count <= 1)
|
2015-11-25 19:49:31 -05:00
|
|
|
return false;
|
2012-03-06 02:40:08 +00:00
|
|
|
|
2015-07-17 03:36:03 +10:00
|
|
|
if (bvh->looptri) {
|
|
|
|
const MLoopTri *first = &bvh->looptri[bvh->prim_indices[offset]];
|
|
|
|
const MPoly *mp = &bvh->mpoly[first->poly];
|
2012-03-06 02:40:08 +00:00
|
|
|
|
2015-11-25 19:49:31 -05:00
|
|
|
for (int i = offset + count - 1; i > offset; --i) {
|
2015-07-17 03:36:03 +10:00
|
|
|
int prim = bvh->prim_indices[i];
|
|
|
|
const MPoly *mp_other = &bvh->mpoly[bvh->looptri[prim].poly];
|
|
|
|
if (!face_materials_match(mp, mp_other)) {
|
2015-11-25 19:49:31 -05:00
|
|
|
return true;
|
2015-07-17 03:36:03 +10:00
|
|
|
}
|
2012-03-06 02:40:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
const DMFlagMat *first = &bvh->grid_flag_mats[bvh->prim_indices[offset]];
|
|
|
|
|
2015-11-25 19:49:31 -05:00
|
|
|
for (int i = offset + count - 1; i > offset; --i) {
|
2015-07-17 03:36:03 +10:00
|
|
|
int prim = bvh->prim_indices[i];
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!grid_materials_match(first, &bvh->grid_flag_mats[prim]))
|
2015-11-25 19:49:31 -05:00
|
|
|
return true;
|
2012-03-06 02:40:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-25 19:49:31 -05:00
|
|
|
return false;
|
2012-03-06 02:40:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-10-27 19:53:34 +00:00
|
|
|
/* Recursively build a node in the tree
|
2012-03-03 20:19:11 +00:00
|
|
|
*
|
|
|
|
* vb is the voxel box around all of the primitives contained in
|
|
|
|
* this node.
|
|
|
|
*
|
|
|
|
* cb is the bounding box around all the centroids of the primitives
|
|
|
|
* contained in this node
|
|
|
|
*
|
|
|
|
* offset and start indicate a range in the array of primitive indices
|
|
|
|
*/
|
2009-10-27 19:53:34 +00:00
|
|
|
|
2011-02-14 17:55:27 +00:00
|
|
|
static void build_sub(PBVH *bvh, int node_index, BB *cb, BBC *prim_bbc,
|
2012-05-11 08:05:47 +00:00
|
|
|
int offset, int count)
|
2009-10-27 19:53:34 +00:00
|
|
|
{
|
2015-11-25 19:49:31 -05:00
|
|
|
int end;
|
2009-10-27 19:53:34 +00:00
|
|
|
BB cb_backing;
|
|
|
|
|
|
|
|
/* Decide whether this is a leaf or not */
|
2015-11-25 19:49:31 -05:00
|
|
|
const bool below_leaf_limit = count <= bvh->leaf_limit;
|
2012-03-24 06:18:31 +00:00
|
|
|
if (below_leaf_limit) {
|
|
|
|
if (!leaf_needs_material_split(bvh, offset, count)) {
|
2012-03-06 02:40:08 +00:00
|
|
|
build_leaf(bvh, node_index, prim_bbc, offset, count);
|
|
|
|
return;
|
|
|
|
}
|
2009-10-27 19:53:34 +00:00
|
|
|
}
|
2012-03-05 21:55:53 +00:00
|
|
|
|
2012-03-05 22:12:50 +00:00
|
|
|
/* Add two child nodes */
|
2012-03-05 21:55:53 +00:00
|
|
|
bvh->nodes[node_index].children_offset = bvh->totnode;
|
2012-12-30 18:28:36 +00:00
|
|
|
pbvh_grow_nodes(bvh, bvh->totnode + 2);
|
2012-03-05 21:55:53 +00:00
|
|
|
|
2012-03-05 22:12:50 +00:00
|
|
|
/* Update parent node bounding box */
|
2012-03-05 22:24:49 +00:00
|
|
|
update_vb(bvh, &bvh->nodes[node_index], prim_bbc, offset, count);
|
2012-03-05 22:12:50 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!below_leaf_limit) {
|
2012-03-06 02:40:08 +00:00
|
|
|
/* Find axis with widest range of primitive centroids */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!cb) {
|
2012-03-06 02:40:08 +00:00
|
|
|
cb = &cb_backing;
|
|
|
|
BB_reset(cb);
|
2015-11-25 19:49:31 -05:00
|
|
|
for (int i = offset + count - 1; i >= offset; --i)
|
2012-03-06 02:40:08 +00:00
|
|
|
BB_expand(cb, prim_bbc[bvh->prim_indices[i]].bcentroid);
|
|
|
|
}
|
2015-11-25 19:49:31 -05:00
|
|
|
const int axis = BB_widest_axis(cb);
|
2012-03-06 02:40:08 +00:00
|
|
|
|
|
|
|
/* Partition primitives along that axis */
|
|
|
|
end = partition_indices(bvh->prim_indices,
|
2012-05-11 08:05:47 +00:00
|
|
|
offset, offset + count - 1,
|
|
|
|
axis,
|
|
|
|
(cb->bmax[axis] + cb->bmin[axis]) * 0.5f,
|
|
|
|
prim_bbc);
|
2012-03-06 02:40:08 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* Partition primitives by material */
|
|
|
|
end = partition_indices_material(bvh, offset, offset + count - 1);
|
2009-10-27 19:53:34 +00:00
|
|
|
}
|
|
|
|
|
2012-03-05 22:12:50 +00:00
|
|
|
/* Build children */
|
2009-10-27 19:53:34 +00:00
|
|
|
build_sub(bvh, bvh->nodes[node_index].children_offset, NULL,
|
2012-05-11 08:05:47 +00:00
|
|
|
prim_bbc, offset, end - offset);
|
2009-10-27 19:53:34 +00:00
|
|
|
build_sub(bvh, bvh->nodes[node_index].children_offset + 1, NULL,
|
2012-05-11 08:05:47 +00:00
|
|
|
prim_bbc, end, offset + count - end);
|
2009-10-27 19:53:34 +00:00
|
|
|
}
|
|
|
|
|
2009-11-25 13:40:43 +00:00
|
|
|
static void pbvh_build(PBVH *bvh, BB *cb, BBC *prim_bbc, int totprim)
|
2009-10-27 19:53:34 +00:00
|
|
|
{
|
2012-03-24 06:18:31 +00:00
|
|
|
if (totprim != bvh->totprim) {
|
2009-11-25 13:40:43 +00:00
|
|
|
bvh->totprim = totprim;
|
2012-03-24 06:18:31 +00:00
|
|
|
if (bvh->nodes) MEM_freeN(bvh->nodes);
|
|
|
|
if (bvh->prim_indices) MEM_freeN(bvh->prim_indices);
|
2016-02-13 17:45:41 +11:00
|
|
|
bvh->prim_indices = MEM_mallocN(sizeof(int) * totprim,
|
2012-05-11 08:05:47 +00:00
|
|
|
"bvh prim indices");
|
2015-11-25 19:49:31 -05:00
|
|
|
for (int i = 0; i < totprim; ++i)
|
2009-11-25 13:40:43 +00:00
|
|
|
bvh->prim_indices[i] = i;
|
2009-10-27 19:53:34 +00:00
|
|
|
bvh->totnode = 0;
|
2012-03-24 06:18:31 +00:00
|
|
|
if (bvh->node_mem_count < 100) {
|
2009-10-27 19:53:34 +00:00
|
|
|
bvh->node_mem_count = 100;
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
bvh->nodes = MEM_callocN(sizeof(PBVHNode) *
|
2012-05-11 08:05:47 +00:00
|
|
|
bvh->node_mem_count,
|
|
|
|
"bvh initial nodes");
|
2009-10-27 19:53:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-11-25 13:40:43 +00:00
|
|
|
bvh->totnode = 1;
|
|
|
|
build_sub(bvh, 0, cb, prim_bbc, 0, totprim);
|
|
|
|
}
|
|
|
|
|
2016-01-04 17:23:39 +01:00
|
|
|
/**
|
|
|
|
* Do a full rebuild with on Mesh data structure.
|
|
|
|
*
|
|
|
|
* \note Unlike mpoly/mloop/verts, looptri is **totally owned** by PBVH (which means it may rewrite it if needed,
|
|
|
|
* see BKE_pbvh_apply_vertCos().
|
|
|
|
*/
|
2015-07-11 04:39:27 +10:00
|
|
|
void BKE_pbvh_build_mesh(
|
2015-07-17 03:36:03 +10:00
|
|
|
PBVH *bvh, const MPoly *mpoly, const MLoop *mloop, MVert *verts,
|
|
|
|
int totvert, struct CustomData *vdata,
|
|
|
|
const MLoopTri *looptri, int looptri_num)
|
2009-11-25 13:40:43 +00:00
|
|
|
{
|
|
|
|
BBC *prim_bbc = NULL;
|
|
|
|
BB cb;
|
|
|
|
|
2012-03-12 23:03:43 +00:00
|
|
|
bvh->type = PBVH_FACES;
|
2015-07-17 03:36:03 +10:00
|
|
|
bvh->mpoly = mpoly;
|
|
|
|
bvh->mloop = mloop;
|
|
|
|
bvh->looptri = looptri;
|
2009-10-27 19:53:34 +00:00
|
|
|
bvh->verts = verts;
|
2012-02-22 23:57:31 +00:00
|
|
|
bvh->vert_bitmap = BLI_BITMAP_NEW(totvert, "bvh->vert_bitmap");
|
2009-11-25 13:40:43 +00:00
|
|
|
bvh->totvert = totvert;
|
|
|
|
bvh->leaf_limit = LEAF_LIMIT;
|
2012-05-10 20:33:36 +00:00
|
|
|
bvh->vdata = vdata;
|
2009-10-27 19:53:34 +00:00
|
|
|
|
|
|
|
BB_reset(&cb);
|
|
|
|
|
|
|
|
/* For each face, store the AABB and the AABB centroid */
|
2015-07-17 03:36:03 +10:00
|
|
|
prim_bbc = MEM_mallocN(sizeof(BBC) * looptri_num, "prim_bbc");
|
2009-10-27 19:53:34 +00:00
|
|
|
|
2015-11-25 19:49:31 -05:00
|
|
|
for (int i = 0; i < looptri_num; ++i) {
|
2015-07-17 03:36:03 +10:00
|
|
|
const MLoopTri *lt = &looptri[i];
|
|
|
|
const int sides = 3;
|
2009-10-27 19:53:34 +00:00
|
|
|
BBC *bbc = prim_bbc + i;
|
|
|
|
|
2012-05-11 08:05:47 +00:00
|
|
|
BB_reset((BB *)bbc);
|
2009-10-27 19:53:34 +00:00
|
|
|
|
2015-11-25 19:49:31 -05:00
|
|
|
for (int j = 0; j < sides; ++j)
|
2015-07-17 03:36:03 +10:00
|
|
|
BB_expand((BB *)bbc, verts[bvh->mloop[lt->tri[j]].v].co);
|
2009-10-27 19:53:34 +00:00
|
|
|
|
|
|
|
BBC_update_centroid(bbc);
|
|
|
|
|
|
|
|
BB_expand(&cb, bbc->bcentroid);
|
|
|
|
}
|
|
|
|
|
2015-07-17 03:36:03 +10:00
|
|
|
if (looptri_num)
|
|
|
|
pbvh_build(bvh, &cb, prim_bbc, looptri_num);
|
2009-10-27 19:53:34 +00:00
|
|
|
|
|
|
|
MEM_freeN(prim_bbc);
|
|
|
|
MEM_freeN(bvh->vert_bitmap);
|
|
|
|
}
|
|
|
|
|
2009-11-25 13:40:43 +00:00
|
|
|
/* Do a full rebuild with on Grids data structure */
|
2015-05-27 19:52:12 +02:00
|
|
|
void BKE_pbvh_build_grids(PBVH *bvh, CCGElem **grids,
|
2013-07-22 23:20:48 +00:00
|
|
|
int totgrid, CCGKey *key, void **gridfaces, DMFlagMat *flagmats, BLI_bitmap **grid_hidden)
|
2009-11-25 13:40:43 +00:00
|
|
|
{
|
2015-11-25 19:49:31 -05:00
|
|
|
const int gridsize = key->grid_size;
|
2009-11-25 13:40:43 +00:00
|
|
|
|
2012-03-12 23:03:43 +00:00
|
|
|
bvh->type = PBVH_GRIDS;
|
2012-05-11 08:05:47 +00:00
|
|
|
bvh->grids = grids;
|
|
|
|
bvh->gridfaces = gridfaces;
|
|
|
|
bvh->grid_flag_mats = flagmats;
|
|
|
|
bvh->totgrid = totgrid;
|
2012-05-10 20:33:09 +00:00
|
|
|
bvh->gridkey = *key;
|
2012-05-11 08:05:47 +00:00
|
|
|
bvh->grid_hidden = grid_hidden;
|
2012-10-23 13:28:22 +00:00
|
|
|
bvh->leaf_limit = max_ii(LEAF_LIMIT / ((gridsize - 1) * (gridsize - 1)), 1);
|
2009-11-25 13:40:43 +00:00
|
|
|
|
2015-11-25 19:49:31 -05:00
|
|
|
BB cb;
|
2009-11-25 13:40:43 +00:00
|
|
|
BB_reset(&cb);
|
|
|
|
|
|
|
|
/* For each grid, store the AABB and the AABB centroid */
|
2015-11-25 19:49:31 -05:00
|
|
|
BBC *prim_bbc = MEM_mallocN(sizeof(BBC) * totgrid, "prim_bbc");
|
2009-11-25 13:40:43 +00:00
|
|
|
|
2015-11-25 19:49:31 -05:00
|
|
|
for (int i = 0; i < totgrid; ++i) {
|
2012-05-11 08:05:47 +00:00
|
|
|
CCGElem *grid = grids[i];
|
2009-11-25 13:40:43 +00:00
|
|
|
BBC *bbc = prim_bbc + i;
|
|
|
|
|
2012-05-11 08:05:47 +00:00
|
|
|
BB_reset((BB *)bbc);
|
2009-11-25 13:40:43 +00:00
|
|
|
|
2015-11-25 19:49:31 -05:00
|
|
|
for (int j = 0; j < gridsize * gridsize; ++j)
|
2012-05-11 08:05:47 +00:00
|
|
|
BB_expand((BB *)bbc, CCG_elem_offset_co(key, grid, j));
|
2009-11-25 13:40:43 +00:00
|
|
|
|
|
|
|
BBC_update_centroid(bbc);
|
|
|
|
|
|
|
|
BB_expand(&cb, bbc->bcentroid);
|
|
|
|
}
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (totgrid)
|
2009-12-18 17:15:58 +00:00
|
|
|
pbvh_build(bvh, &cb, prim_bbc, totgrid);
|
2009-11-25 13:40:43 +00:00
|
|
|
|
|
|
|
MEM_freeN(prim_bbc);
|
|
|
|
}
|
|
|
|
|
2012-12-30 18:31:31 +00:00
|
|
|
PBVH *BKE_pbvh_new(void)
|
2009-10-27 19:53:34 +00:00
|
|
|
{
|
|
|
|
PBVH *bvh = MEM_callocN(sizeof(PBVH), "pbvh");
|
|
|
|
|
|
|
|
return bvh;
|
|
|
|
}
|
|
|
|
|
2012-12-30 18:31:31 +00:00
|
|
|
void BKE_pbvh_free(PBVH *bvh)
|
2009-10-27 19:53:34 +00:00
|
|
|
{
|
2015-11-25 19:49:31 -05:00
|
|
|
for (int i = 0; i < bvh->totnode; ++i) {
|
|
|
|
PBVHNode *node = &bvh->nodes[i];
|
2009-11-25 13:40:43 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (node->flag & PBVH_Leaf) {
|
|
|
|
if (node->draw_buffers)
|
2017-05-11 22:03:50 +10:00
|
|
|
GPU_pbvh_buffers_free(node->draw_buffers);
|
2012-03-24 06:18:31 +00:00
|
|
|
if (node->vert_indices)
|
2015-07-12 03:49:47 +10:00
|
|
|
MEM_freeN((void *)node->vert_indices);
|
2012-03-24 06:18:31 +00:00
|
|
|
if (node->face_vert_indices)
|
2015-07-12 03:49:47 +10:00
|
|
|
MEM_freeN((void *)node->face_vert_indices);
|
2012-12-30 18:31:31 +00:00
|
|
|
BKE_pbvh_node_layer_disp_free(node);
|
2012-12-30 18:28:36 +00:00
|
|
|
|
|
|
|
if (node->bm_faces)
|
2014-04-08 14:45:48 +10:00
|
|
|
BLI_gset_free(node->bm_faces, NULL);
|
2012-12-30 18:28:36 +00:00
|
|
|
if (node->bm_unique_verts)
|
2013-08-25 20:03:45 +00:00
|
|
|
BLI_gset_free(node->bm_unique_verts, NULL);
|
2012-12-30 18:28:36 +00:00
|
|
|
if (node->bm_other_verts)
|
2013-08-25 20:03:45 +00:00
|
|
|
BLI_gset_free(node->bm_other_verts, NULL);
|
2009-10-27 19:53:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-21 20:10:59 +00:00
|
|
|
if (bvh->deformed) {
|
|
|
|
if (bvh->verts) {
|
|
|
|
/* if pbvh was deformed, new memory was allocated for verts/faces -- free it */
|
|
|
|
|
2015-07-11 04:39:27 +10:00
|
|
|
MEM_freeN((void *)bvh->verts);
|
2010-06-21 20:10:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-17 03:36:03 +10:00
|
|
|
if (bvh->looptri) {
|
|
|
|
MEM_freeN((void *)bvh->looptri);
|
|
|
|
}
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (bvh->nodes)
|
2011-11-24 13:39:43 +00:00
|
|
|
MEM_freeN(bvh->nodes);
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (bvh->prim_indices)
|
2011-11-24 13:39:43 +00:00
|
|
|
MEM_freeN(bvh->prim_indices);
|
|
|
|
|
2009-10-27 19:53:34 +00:00
|
|
|
MEM_freeN(bvh);
|
|
|
|
}
|
|
|
|
|
2014-03-07 16:58:56 +02:00
|
|
|
void BKE_pbvh_free_layer_disp(PBVH *bvh)
|
|
|
|
{
|
2015-11-25 19:49:31 -05:00
|
|
|
for (int i = 0; i < bvh->totnode; ++i)
|
2014-03-07 16:58:56 +02:00
|
|
|
BKE_pbvh_node_layer_disp_free(&bvh->nodes[i]);
|
|
|
|
}
|
|
|
|
|
2012-12-30 18:31:31 +00:00
|
|
|
static void pbvh_iter_begin(PBVHIter *iter, PBVH *bvh, BKE_pbvh_SearchCallback scb, void *search_data)
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
{
|
2012-05-11 08:05:47 +00:00
|
|
|
iter->bvh = bvh;
|
|
|
|
iter->scb = scb;
|
|
|
|
iter->search_data = search_data;
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
|
2012-05-11 08:05:47 +00:00
|
|
|
iter->stack = iter->stackfixed;
|
|
|
|
iter->stackspace = STACK_FIXED_DEPTH;
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
|
2012-05-11 08:05:47 +00:00
|
|
|
iter->stack[0].node = bvh->nodes;
|
2015-11-25 19:49:31 -05:00
|
|
|
iter->stack[0].revisiting = false;
|
2012-05-11 08:05:47 +00:00
|
|
|
iter->stacksize = 1;
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void pbvh_iter_end(PBVHIter *iter)
|
|
|
|
{
|
2012-03-24 06:18:31 +00:00
|
|
|
if (iter->stackspace > STACK_FIXED_DEPTH)
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
MEM_freeN(iter->stack);
|
|
|
|
}
|
|
|
|
|
2015-11-25 19:49:31 -05:00
|
|
|
static void pbvh_stack_push(PBVHIter *iter, PBVHNode *node, bool revisiting)
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
{
|
2015-04-14 16:02:38 +10:00
|
|
|
if (UNLIKELY(iter->stacksize == iter->stackspace)) {
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
iter->stackspace *= 2;
|
2016-07-11 17:08:27 +10:00
|
|
|
if (iter->stackspace != (STACK_FIXED_DEPTH * 2)) {
|
2015-04-14 16:02:38 +10:00
|
|
|
iter->stack = MEM_reallocN(iter->stack, sizeof(PBVHStack) * iter->stackspace);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
iter->stack = MEM_mallocN(sizeof(PBVHStack) * iter->stackspace, "PBVHStack");
|
|
|
|
memcpy(iter->stack, iter->stackfixed, sizeof(PBVHStack) * iter->stacksize);
|
|
|
|
}
|
2009-10-27 19:53:34 +00:00
|
|
|
}
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
|
2012-05-11 08:05:47 +00:00
|
|
|
iter->stack[iter->stacksize].node = node;
|
|
|
|
iter->stack[iter->stacksize].revisiting = revisiting;
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
iter->stacksize++;
|
2009-10-27 19:53:34 +00:00
|
|
|
}
|
|
|
|
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
static PBVHNode *pbvh_iter_next(PBVHIter *iter)
|
2009-10-27 19:53:34 +00:00
|
|
|
{
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
/* purpose here is to traverse tree, visiting child nodes before their
|
2012-03-03 20:19:11 +00:00
|
|
|
* parents, this order is necessary for e.g. computing bounding boxes */
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
while (iter->stacksize) {
|
2011-04-21 13:11:51 +00:00
|
|
|
/* pop node */
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
iter->stacksize--;
|
2015-11-25 19:49:31 -05:00
|
|
|
PBVHNode *node = iter->stack[iter->stacksize].node;
|
2010-01-10 10:20:44 +00:00
|
|
|
|
2010-01-10 10:50:11 +00:00
|
|
|
/* on a mesh with no faces this can happen
|
|
|
|
* can remove this check if we know meshes have at least 1 face */
|
2012-05-11 08:05:47 +00:00
|
|
|
if (node == NULL)
|
2010-01-10 10:20:44 +00:00
|
|
|
return NULL;
|
|
|
|
|
2015-11-25 19:49:31 -05:00
|
|
|
bool revisiting = iter->stack[iter->stacksize].revisiting;
|
2009-10-27 19:53:34 +00:00
|
|
|
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
/* revisiting node already checked */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (revisiting)
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
return node;
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (iter->scb && !iter->scb(node, iter->search_data))
|
2012-05-11 08:05:47 +00:00
|
|
|
continue; /* don't traverse, outside of search zone */
|
2009-10-27 19:53:34 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (node->flag & PBVH_Leaf) {
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
/* immediately hit leaf node */
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* come back later when children are done */
|
2015-11-25 19:49:31 -05:00
|
|
|
pbvh_stack_push(iter, node, true);
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
|
|
|
|
/* push two child nodes on the stack */
|
2015-11-25 19:49:31 -05:00
|
|
|
pbvh_stack_push(iter, iter->bvh->nodes + node->children_offset + 1, false);
|
|
|
|
pbvh_stack_push(iter, iter->bvh->nodes + node->children_offset, false);
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-07-14 14:11:03 +00:00
|
|
|
static PBVHNode *pbvh_iter_next_occluded(PBVHIter *iter)
|
|
|
|
{
|
2012-03-24 06:18:31 +00:00
|
|
|
while (iter->stacksize) {
|
2011-04-21 13:11:51 +00:00
|
|
|
/* pop node */
|
|
|
|
iter->stacksize--;
|
2015-11-25 19:49:31 -05:00
|
|
|
PBVHNode *node = iter->stack[iter->stacksize].node;
|
2011-04-21 13:11:51 +00:00
|
|
|
|
|
|
|
/* on a mesh with no faces this can happen
|
|
|
|
* can remove this check if we know meshes have at least 1 face */
|
2012-05-11 08:05:47 +00:00
|
|
|
if (node == NULL) return NULL;
|
2011-04-21 13:11:51 +00:00
|
|
|
|
2012-05-11 08:05:47 +00:00
|
|
|
if (iter->scb && !iter->scb(node, iter->search_data)) continue; /* don't traverse, outside of search zone */
|
2011-04-21 13:11:51 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (node->flag & PBVH_Leaf) {
|
2011-04-21 13:11:51 +00:00
|
|
|
/* immediately hit leaf node */
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
else {
|
2015-11-25 19:49:31 -05:00
|
|
|
pbvh_stack_push(iter, iter->bvh->nodes + node->children_offset + 1, false);
|
|
|
|
pbvh_stack_push(iter, iter->bvh->nodes + node->children_offset, false);
|
2011-04-21 13:11:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
2010-07-14 14:11:03 +00:00
|
|
|
}
|
|
|
|
|
2012-12-30 18:31:31 +00:00
|
|
|
void BKE_pbvh_search_gather(PBVH *bvh,
|
|
|
|
BKE_pbvh_SearchCallback scb, void *search_data,
|
2012-05-11 08:05:47 +00:00
|
|
|
PBVHNode ***r_array, int *r_tot)
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
{
|
|
|
|
PBVHIter iter;
|
2013-08-03 18:05:30 +00:00
|
|
|
PBVHNode **array = NULL, *node;
|
2012-05-11 08:05:47 +00:00
|
|
|
int tot = 0, space = 0;
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
|
|
|
|
pbvh_iter_begin(&iter, bvh, scb, search_data);
|
|
|
|
|
2012-05-11 08:05:47 +00:00
|
|
|
while ((node = pbvh_iter_next(&iter))) {
|
2012-03-24 06:18:31 +00:00
|
|
|
if (node->flag & PBVH_Leaf) {
|
2015-04-14 16:02:38 +10:00
|
|
|
if (UNLIKELY(tot == space)) {
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
/* resize array if needed */
|
2012-05-11 08:05:47 +00:00
|
|
|
space = (tot == 0) ? 32 : space * 2;
|
2013-08-03 18:05:30 +00:00
|
|
|
array = MEM_recallocN_id(array, sizeof(PBVHNode *) * space, __func__);
|
2009-10-27 19:53:34 +00:00
|
|
|
}
|
|
|
|
|
2012-05-11 08:05:47 +00:00
|
|
|
array[tot] = node;
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
tot++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pbvh_iter_end(&iter);
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (tot == 0 && array) {
|
2010-01-05 14:26:38 +00:00
|
|
|
MEM_freeN(array);
|
2012-05-11 08:05:47 +00:00
|
|
|
array = NULL;
|
2010-01-05 14:26:38 +00:00
|
|
|
}
|
|
|
|
|
2012-05-11 08:05:47 +00:00
|
|
|
*r_array = array;
|
|
|
|
*r_tot = tot;
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
}
|
|
|
|
|
2012-12-30 18:31:31 +00:00
|
|
|
void BKE_pbvh_search_callback(PBVH *bvh,
|
|
|
|
BKE_pbvh_SearchCallback scb, void *search_data,
|
|
|
|
BKE_pbvh_HitCallback hcb, void *hit_data)
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
{
|
|
|
|
PBVHIter iter;
|
|
|
|
PBVHNode *node;
|
|
|
|
|
|
|
|
pbvh_iter_begin(&iter, bvh, scb, search_data);
|
|
|
|
|
2012-05-11 08:05:47 +00:00
|
|
|
while ((node = pbvh_iter_next(&iter)))
|
2010-07-14 14:11:03 +00:00
|
|
|
if (node->flag & PBVH_Leaf)
|
2009-11-25 13:40:43 +00:00
|
|
|
hcb(node, hit_data);
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
|
|
|
|
pbvh_iter_end(&iter);
|
|
|
|
}
|
|
|
|
|
2010-07-14 14:11:03 +00:00
|
|
|
typedef struct node_tree {
|
2012-05-11 08:05:47 +00:00
|
|
|
PBVHNode *data;
|
2010-07-14 14:11:03 +00:00
|
|
|
|
2012-05-11 08:05:47 +00:00
|
|
|
struct node_tree *left;
|
|
|
|
struct node_tree *right;
|
2010-07-14 14:11:03 +00:00
|
|
|
} node_tree;
|
|
|
|
|
2012-05-11 08:05:47 +00:00
|
|
|
static void node_tree_insert(node_tree *tree, node_tree *new_node)
|
2010-07-14 14:11:03 +00:00
|
|
|
{
|
2011-04-21 13:11:51 +00:00
|
|
|
if (new_node->data->tmin < tree->data->tmin) {
|
|
|
|
if (tree->left) {
|
|
|
|
node_tree_insert(tree->left, new_node);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
tree->left = new_node;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (tree->right) {
|
|
|
|
node_tree_insert(tree->right, new_node);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
tree->right = new_node;
|
|
|
|
}
|
|
|
|
}
|
2010-07-14 14:11:03 +00:00
|
|
|
}
|
|
|
|
|
2012-12-30 18:31:31 +00:00
|
|
|
static void traverse_tree(node_tree *tree, BKE_pbvh_HitOccludedCallback hcb, void *hit_data, float *tmin)
|
2010-07-14 14:11:03 +00:00
|
|
|
{
|
2011-04-21 13:11:51 +00:00
|
|
|
if (tree->left) traverse_tree(tree->left, hcb, hit_data, tmin);
|
2010-07-14 14:11:03 +00:00
|
|
|
|
2011-04-21 13:11:51 +00:00
|
|
|
hcb(tree->data, hit_data, tmin);
|
2010-07-14 14:11:03 +00:00
|
|
|
|
2011-04-21 13:11:51 +00:00
|
|
|
if (tree->right) traverse_tree(tree->right, hcb, hit_data, tmin);
|
2010-07-14 14:11:03 +00:00
|
|
|
}
|
|
|
|
|
2012-05-11 08:05:47 +00:00
|
|
|
static void free_tree(node_tree *tree)
|
2010-07-14 14:11:03 +00:00
|
|
|
{
|
2011-04-21 13:11:51 +00:00
|
|
|
if (tree->left) {
|
|
|
|
free_tree(tree->left);
|
2013-08-07 03:55:21 +00:00
|
|
|
tree->left = NULL;
|
2011-04-21 13:11:51 +00:00
|
|
|
}
|
2010-07-14 14:11:03 +00:00
|
|
|
|
2011-04-21 13:11:51 +00:00
|
|
|
if (tree->right) {
|
|
|
|
free_tree(tree->right);
|
2013-08-07 03:55:21 +00:00
|
|
|
tree->right = NULL;
|
2011-04-21 13:11:51 +00:00
|
|
|
}
|
2010-07-14 14:11:03 +00:00
|
|
|
|
2011-04-21 13:11:51 +00:00
|
|
|
free(tree);
|
2010-07-14 14:11:03 +00:00
|
|
|
}
|
|
|
|
|
2012-12-30 18:31:31 +00:00
|
|
|
float BKE_pbvh_node_get_tmin(PBVHNode *node)
|
2010-07-14 14:11:03 +00:00
|
|
|
{
|
2011-04-21 13:11:51 +00:00
|
|
|
return node->tmin;
|
2010-07-14 14:11:03 +00:00
|
|
|
}
|
|
|
|
|
2012-12-30 18:31:31 +00:00
|
|
|
static void BKE_pbvh_search_callback_occluded(PBVH *bvh,
|
|
|
|
BKE_pbvh_SearchCallback scb, void *search_data,
|
|
|
|
BKE_pbvh_HitOccludedCallback hcb, void *hit_data)
|
2010-07-14 14:11:03 +00:00
|
|
|
{
|
|
|
|
PBVHIter iter;
|
|
|
|
PBVHNode *node;
|
2013-08-07 03:55:21 +00:00
|
|
|
node_tree *tree = NULL;
|
2010-07-14 14:11:03 +00:00
|
|
|
|
|
|
|
pbvh_iter_begin(&iter, bvh, scb, search_data);
|
|
|
|
|
2012-05-11 08:05:47 +00:00
|
|
|
while ((node = pbvh_iter_next_occluded(&iter))) {
|
2012-03-24 06:18:31 +00:00
|
|
|
if (node->flag & PBVH_Leaf) {
|
2012-05-11 08:05:47 +00:00
|
|
|
node_tree *new_node = malloc(sizeof(node_tree));
|
2010-07-14 14:11:03 +00:00
|
|
|
|
|
|
|
new_node->data = node;
|
|
|
|
|
|
|
|
new_node->left = NULL;
|
|
|
|
new_node->right = NULL;
|
|
|
|
|
|
|
|
if (tree) {
|
|
|
|
node_tree_insert(tree, new_node);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
tree = new_node;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pbvh_iter_end(&iter);
|
|
|
|
|
|
|
|
if (tree) {
|
|
|
|
float tmin = FLT_MAX;
|
|
|
|
traverse_tree(tree, hcb, hit_data, &tmin);
|
|
|
|
free_tree(tree);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-03 18:55:59 +11:00
|
|
|
static bool update_search_cb(PBVHNode *node, void *data_v)
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
{
|
2018-09-19 12:05:58 +10:00
|
|
|
int flag = POINTER_AS_INT(data_v);
|
2009-11-06 16:46:35 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (node->flag & PBVH_Leaf)
|
2014-02-03 18:55:59 +11:00
|
|
|
return (node->flag & flag) != 0;
|
2012-10-22 17:33:53 +00:00
|
|
|
|
2014-12-01 17:11:18 +01:00
|
|
|
return true;
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
}
|
|
|
|
|
2016-01-27 12:14:00 +01:00
|
|
|
typedef struct PBVHUpdateData {
|
|
|
|
PBVH *bvh;
|
|
|
|
PBVHNode **nodes;
|
|
|
|
int totnode;
|
|
|
|
|
|
|
|
float (*fnors)[3];
|
|
|
|
float (*vnors)[3];
|
|
|
|
int flag;
|
|
|
|
} PBVHUpdateData;
|
|
|
|
|
2018-01-10 12:49:51 +01:00
|
|
|
static void pbvh_update_normals_accum_task_cb(
|
|
|
|
void *__restrict userdata,
|
|
|
|
const int n,
|
|
|
|
const ParallelRangeTLS *__restrict UNUSED(tls))
|
2016-01-27 12:14:00 +01:00
|
|
|
{
|
|
|
|
PBVHUpdateData *data = userdata;
|
|
|
|
|
|
|
|
PBVH *bvh = data->bvh;
|
|
|
|
PBVHNode *node = data->nodes[n];
|
|
|
|
float (*fnors)[3] = data->fnors;
|
|
|
|
float (*vnors)[3] = data->vnors;
|
|
|
|
|
|
|
|
if ((node->flag & PBVH_UpdateNormals)) {
|
|
|
|
unsigned int mpoly_prev = UINT_MAX;
|
|
|
|
float fn[3];
|
|
|
|
|
|
|
|
const int *faces = node->prim_indices;
|
|
|
|
const int totface = node->totprim;
|
|
|
|
|
|
|
|
for (int i = 0; i < totface; ++i) {
|
|
|
|
const MLoopTri *lt = &bvh->looptri[faces[i]];
|
|
|
|
const unsigned int vtri[3] = {
|
|
|
|
bvh->mloop[lt->tri[0]].v,
|
|
|
|
bvh->mloop[lt->tri[1]].v,
|
|
|
|
bvh->mloop[lt->tri[2]].v,
|
|
|
|
};
|
|
|
|
const int sides = 3;
|
|
|
|
|
|
|
|
/* Face normal and mask */
|
|
|
|
if (lt->poly != mpoly_prev) {
|
|
|
|
const MPoly *mp = &bvh->mpoly[lt->poly];
|
|
|
|
BKE_mesh_calc_poly_normal(mp, &bvh->mloop[mp->loopstart], bvh->verts, fn);
|
|
|
|
mpoly_prev = lt->poly;
|
|
|
|
|
|
|
|
if (fnors) {
|
|
|
|
/* We can assume a face is only present in one node ever. */
|
|
|
|
copy_v3_v3(fnors[lt->poly], fn);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int j = sides; j--; ) {
|
|
|
|
const int v = vtri[j];
|
|
|
|
|
|
|
|
if (bvh->verts[v].flag & ME_VERT_PBVH_UPDATE) {
|
|
|
|
/* Note: This avoids `lock, add_v3_v3, unlock` and is five to ten times quicker than a spinlock.
|
|
|
|
* Not exact equivalent though, since atomicity is only ensured for one component
|
|
|
|
* of the vector at a time, but here it shall not make any sensible difference. */
|
|
|
|
for (int k = 3; k--; ) {
|
2016-11-15 12:16:26 +01:00
|
|
|
atomic_add_and_fetch_fl(&vnors[v][k], fn[k]);
|
2016-01-27 12:14:00 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-10 12:49:51 +01:00
|
|
|
static void pbvh_update_normals_store_task_cb(
|
|
|
|
void *__restrict userdata,
|
|
|
|
const int n,
|
|
|
|
const ParallelRangeTLS *__restrict UNUSED(tls))
|
2016-01-27 12:14:00 +01:00
|
|
|
{
|
|
|
|
PBVHUpdateData *data = userdata;
|
|
|
|
PBVH *bvh = data->bvh;
|
|
|
|
PBVHNode *node = data->nodes[n];
|
|
|
|
float (*vnors)[3] = data->vnors;
|
|
|
|
|
|
|
|
if (node->flag & PBVH_UpdateNormals) {
|
|
|
|
const int *verts = node->vert_indices;
|
|
|
|
const int totvert = node->uniq_verts;
|
|
|
|
|
|
|
|
for (int i = 0; i < totvert; ++i) {
|
|
|
|
const int v = verts[i];
|
|
|
|
MVert *mvert = &bvh->verts[v];
|
|
|
|
|
|
|
|
/* mvert is shared between nodes, hence between threads. */
|
2017-11-23 16:23:45 +01:00
|
|
|
if (atomic_fetch_and_and_char(&mvert->flag, (char)~ME_VERT_PBVH_UPDATE) & ME_VERT_PBVH_UPDATE) {
|
2016-01-27 12:14:00 +01:00
|
|
|
normalize_v3(vnors[v]);
|
|
|
|
normal_float_to_short_v3(mvert->no, vnors[v]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
node->flag &= ~PBVH_UpdateNormals;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-11-04 20:36:38 +00:00
|
|
|
static void pbvh_update_normals(PBVH *bvh, PBVHNode **nodes,
|
2016-01-27 12:14:00 +01:00
|
|
|
int totnode, float (*fnors)[3])
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
{
|
2016-01-27 12:14:00 +01:00
|
|
|
float (*vnors)[3];
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
|
2012-12-30 18:28:36 +00:00
|
|
|
if (bvh->type == PBVH_BMESH) {
|
2016-01-27 12:14:00 +01:00
|
|
|
BLI_assert(fnors == NULL);
|
2012-12-30 18:28:36 +00:00
|
|
|
pbvh_bmesh_normals_update(nodes, totnode);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-05-29 05:22:44 +03:00
|
|
|
if (bvh->type != PBVH_FACES)
|
2009-11-25 13:40:43 +00:00
|
|
|
return;
|
|
|
|
|
2009-11-04 20:36:38 +00:00
|
|
|
/* could be per node to save some memory, but also means
|
2012-03-03 20:19:11 +00:00
|
|
|
* we have to store for each vertex which node it is in */
|
2016-01-27 12:14:00 +01:00
|
|
|
vnors = MEM_callocN(sizeof(*vnors) * bvh->totvert, __func__);
|
2009-11-04 20:36:38 +00:00
|
|
|
|
2012-05-01 17:51:03 +00:00
|
|
|
/* subtle assumptions:
|
|
|
|
* - We know that for all edited vertices, the nodes with faces
|
|
|
|
* adjacent to these vertices have been marked with PBVH_UpdateNormals.
|
|
|
|
* This is true because if the vertex is inside the brush radius, the
|
|
|
|
* bounding box of it's adjacent faces will be as well.
|
|
|
|
* - However this is only true for the vertices that have actually been
|
|
|
|
* edited, not for all vertices in the nodes marked for update, so we
|
|
|
|
* can only update vertices marked with ME_VERT_PBVH_UPDATE.
|
|
|
|
*/
|
2009-11-04 20:36:38 +00:00
|
|
|
|
2016-01-27 12:14:00 +01:00
|
|
|
PBVHUpdateData data = {
|
|
|
|
.bvh = bvh, .nodes = nodes,
|
2016-01-28 17:23:12 +11:00
|
|
|
.fnors = fnors, .vnors = vnors,
|
2016-01-27 12:14:00 +01:00
|
|
|
};
|
2009-11-04 20:36:38 +00:00
|
|
|
|
2018-01-08 11:35:48 +01:00
|
|
|
ParallelRangeSettings settings;
|
|
|
|
BLI_parallel_range_settings_defaults(&settings);
|
|
|
|
settings.use_threading = (totnode > PBVH_THREADED_LIMIT);
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
|
2018-01-08 11:35:48 +01:00
|
|
|
BLI_task_parallel_range(0, totnode, &data, pbvh_update_normals_accum_task_cb, &settings);
|
|
|
|
|
|
|
|
BLI_task_parallel_range(0, totnode, &data, pbvh_update_normals_store_task_cb, &settings);
|
2009-11-04 20:36:38 +00:00
|
|
|
|
2016-01-27 12:14:00 +01:00
|
|
|
MEM_freeN(vnors);
|
|
|
|
}
|
2009-11-04 20:36:38 +00:00
|
|
|
|
2018-01-10 12:49:51 +01:00
|
|
|
static void pbvh_update_BB_redraw_task_cb(
|
|
|
|
void *__restrict userdata,
|
|
|
|
const int n,
|
|
|
|
const ParallelRangeTLS *__restrict UNUSED(tls))
|
2016-01-27 12:14:00 +01:00
|
|
|
{
|
|
|
|
PBVHUpdateData *data = userdata;
|
|
|
|
PBVH *bvh = data->bvh;
|
|
|
|
PBVHNode *node = data->nodes[n];
|
|
|
|
const int flag = data->flag;
|
2012-05-13 11:05:52 +00:00
|
|
|
|
2016-01-27 12:14:00 +01:00
|
|
|
if ((flag & PBVH_UpdateBB) && (node->flag & PBVH_UpdateBB))
|
|
|
|
/* don't clear flag yet, leave it for flushing later */
|
|
|
|
/* Note that bvh usage is read-only here, so no need to thread-protect it. */
|
|
|
|
update_node_vb(bvh, node);
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
|
2016-01-27 12:14:00 +01:00
|
|
|
if ((flag & PBVH_UpdateOriginalBB) && (node->flag & PBVH_UpdateOriginalBB))
|
|
|
|
node->orig_vb = node->vb;
|
2009-11-04 20:36:38 +00:00
|
|
|
|
2016-01-27 12:14:00 +01:00
|
|
|
if ((flag & PBVH_UpdateRedraw) && (node->flag & PBVH_UpdateRedraw))
|
|
|
|
node->flag &= ~PBVH_UpdateRedraw;
|
2009-11-04 20:36:38 +00:00
|
|
|
}
|
|
|
|
|
2012-12-30 18:28:36 +00:00
|
|
|
void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag)
|
2009-11-04 20:36:38 +00:00
|
|
|
{
|
|
|
|
/* update BB, redraw flag */
|
2016-01-27 12:14:00 +01:00
|
|
|
PBVHUpdateData data = {
|
|
|
|
.bvh = bvh, .nodes = nodes,
|
2016-01-28 17:23:12 +11:00
|
|
|
.flag = flag,
|
2016-01-27 12:14:00 +01:00
|
|
|
};
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
|
2018-01-08 11:35:48 +01:00
|
|
|
ParallelRangeSettings settings;
|
|
|
|
BLI_parallel_range_settings_defaults(&settings);
|
|
|
|
settings.use_threading = (totnode > PBVH_THREADED_LIMIT);
|
|
|
|
BLI_task_parallel_range(0, totnode, &data, pbvh_update_BB_redraw_task_cb, &settings);
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
}
|
2009-10-27 19:53:34 +00:00
|
|
|
|
2018-01-12 17:35:26 +01:00
|
|
|
static int pbvh_get_buffers_update_flags(PBVH *bvh)
|
|
|
|
{
|
|
|
|
int update_flags = 0;
|
2018-01-15 11:38:56 +01:00
|
|
|
update_flags |= bvh->show_mask ? GPU_PBVH_BUFFERS_SHOW_MASK : 0;
|
2018-01-12 17:35:26 +01:00
|
|
|
return update_flags;
|
|
|
|
}
|
|
|
|
|
2012-03-06 02:40:08 +00:00
|
|
|
static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode)
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
{
|
|
|
|
/* can't be done in parallel with OpenGL */
|
2015-11-25 19:49:31 -05:00
|
|
|
for (int n = 0; n < totnode; n++) {
|
|
|
|
PBVHNode *node = nodes[n];
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (node->flag & PBVH_RebuildDrawBuffers) {
|
2017-05-11 22:03:50 +10:00
|
|
|
GPU_pbvh_buffers_free(node->draw_buffers);
|
2012-06-10 16:37:22 +00:00
|
|
|
switch (bvh->type) {
|
|
|
|
case PBVH_GRIDS:
|
|
|
|
node->draw_buffers =
|
2018-09-04 10:21:26 +02:00
|
|
|
GPU_pbvh_grid_buffers_build(
|
|
|
|
node->totprim,
|
2019-02-22 04:00:19 +01:00
|
|
|
bvh->grid_hidden);
|
2012-06-10 16:37:22 +00:00
|
|
|
break;
|
|
|
|
case PBVH_FACES:
|
|
|
|
node->draw_buffers =
|
2018-09-04 10:21:26 +02:00
|
|
|
GPU_pbvh_mesh_buffers_build(
|
|
|
|
node->face_vert_indices,
|
|
|
|
bvh->mpoly, bvh->mloop, bvh->looptri,
|
|
|
|
bvh->verts,
|
|
|
|
node->prim_indices,
|
|
|
|
node->totprim);
|
2012-06-10 16:37:22 +00:00
|
|
|
break;
|
2013-03-02 12:05:25 +00:00
|
|
|
case PBVH_BMESH:
|
2012-12-30 18:28:36 +00:00
|
|
|
node->draw_buffers =
|
2017-05-11 22:03:50 +10:00
|
|
|
GPU_pbvh_bmesh_buffers_build(bvh->flags & PBVH_DYNTOPO_SMOOTH_SHADING);
|
2012-12-30 18:28:36 +00:00
|
|
|
break;
|
2012-03-14 06:32:25 +00:00
|
|
|
}
|
2017-06-12 13:35:00 +10:00
|
|
|
|
2012-03-14 06:32:25 +00:00
|
|
|
node->flag &= ~PBVH_RebuildDrawBuffers;
|
|
|
|
}
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (node->flag & PBVH_UpdateDrawBuffers) {
|
2018-01-12 17:35:26 +01:00
|
|
|
const int update_flags = pbvh_get_buffers_update_flags(bvh);
|
2012-04-28 06:31:57 +00:00
|
|
|
switch (bvh->type) {
|
2012-05-11 08:05:47 +00:00
|
|
|
case PBVH_GRIDS:
|
2017-05-11 22:03:50 +10:00
|
|
|
GPU_pbvh_grid_buffers_update(
|
|
|
|
node->draw_buffers,
|
|
|
|
bvh->grids,
|
|
|
|
bvh->grid_flag_mats,
|
|
|
|
node->prim_indices,
|
|
|
|
node->totprim,
|
|
|
|
&bvh->gridkey,
|
2018-01-12 17:35:26 +01:00
|
|
|
update_flags);
|
2012-05-11 08:05:47 +00:00
|
|
|
break;
|
|
|
|
case PBVH_FACES:
|
2017-05-11 22:03:50 +10:00
|
|
|
GPU_pbvh_mesh_buffers_update(
|
|
|
|
node->draw_buffers,
|
|
|
|
bvh->verts,
|
|
|
|
node->vert_indices,
|
|
|
|
node->uniq_verts +
|
|
|
|
node->face_verts,
|
|
|
|
CustomData_get_layer(bvh->vdata, CD_PAINT_MASK),
|
|
|
|
node->face_vert_indices,
|
2018-01-12 17:35:26 +01:00
|
|
|
update_flags);
|
2012-05-11 08:05:47 +00:00
|
|
|
break;
|
2013-03-02 12:05:25 +00:00
|
|
|
case PBVH_BMESH:
|
2017-05-11 22:03:50 +10:00
|
|
|
GPU_pbvh_bmesh_buffers_update(
|
|
|
|
node->draw_buffers,
|
|
|
|
bvh->bm,
|
|
|
|
node->bm_faces,
|
|
|
|
node->bm_unique_verts,
|
|
|
|
node->bm_other_verts,
|
2018-01-12 17:35:26 +01:00
|
|
|
update_flags);
|
2012-12-30 18:28:36 +00:00
|
|
|
break;
|
2009-11-25 13:40:43 +00:00
|
|
|
}
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
|
|
|
|
node->flag &= ~PBVH_UpdateDrawBuffers;
|
|
|
|
}
|
2009-10-27 19:53:34 +00:00
|
|
|
}
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
}
|
|
|
|
|
2009-11-06 16:46:35 +00:00
|
|
|
static int pbvh_flush_bb(PBVH *bvh, PBVHNode *node, int flag)
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
{
|
2012-05-11 08:05:47 +00:00
|
|
|
int update = 0;
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
|
|
|
|
/* difficult to multithread well, we just do single threaded recursive */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (node->flag & PBVH_Leaf) {
|
|
|
|
if (flag & PBVH_UpdateBB) {
|
2009-11-06 16:46:35 +00:00
|
|
|
update |= (node->flag & PBVH_UpdateBB);
|
|
|
|
node->flag &= ~PBVH_UpdateBB;
|
|
|
|
}
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (flag & PBVH_UpdateOriginalBB) {
|
2009-11-06 16:46:35 +00:00
|
|
|
update |= (node->flag & PBVH_UpdateOriginalBB);
|
|
|
|
node->flag &= ~PBVH_UpdateOriginalBB;
|
|
|
|
}
|
|
|
|
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
return update;
|
|
|
|
}
|
|
|
|
else {
|
2009-11-06 16:46:35 +00:00
|
|
|
update |= pbvh_flush_bb(bvh, bvh->nodes + node->children_offset, flag);
|
|
|
|
update |= pbvh_flush_bb(bvh, bvh->nodes + node->children_offset + 1, flag);
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (update & PBVH_UpdateBB)
|
2009-10-27 19:53:34 +00:00
|
|
|
update_node_vb(bvh, node);
|
2012-03-24 06:18:31 +00:00
|
|
|
if (update & PBVH_UpdateOriginalBB)
|
2012-05-11 08:05:47 +00:00
|
|
|
node->orig_vb = node->vb;
|
2009-10-27 19:53:34 +00:00
|
|
|
}
|
|
|
|
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
return update;
|
2009-10-27 19:53:34 +00:00
|
|
|
}
|
|
|
|
|
2016-01-27 12:14:00 +01:00
|
|
|
void BKE_pbvh_update(PBVH *bvh, int flag, float (*fnors)[3])
|
2009-10-27 19:53:34 +00:00
|
|
|
{
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!bvh->nodes)
|
2011-11-24 13:39:43 +00:00
|
|
|
return;
|
|
|
|
|
2015-11-25 19:49:31 -05:00
|
|
|
PBVHNode **nodes;
|
|
|
|
int totnode;
|
|
|
|
|
2018-09-19 12:05:58 +10:00
|
|
|
BKE_pbvh_search_gather(bvh, update_search_cb, POINTER_FROM_INT(flag),
|
2012-05-11 08:05:47 +00:00
|
|
|
&nodes, &totnode);
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (flag & PBVH_UpdateNormals)
|
2016-01-27 12:14:00 +01:00
|
|
|
pbvh_update_normals(bvh, nodes, totnode, fnors);
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
|
2012-05-11 08:05:47 +00:00
|
|
|
if (flag & (PBVH_UpdateBB | PBVH_UpdateOriginalBB | PBVH_UpdateRedraw))
|
2009-11-04 20:36:38 +00:00
|
|
|
pbvh_update_BB_redraw(bvh, nodes, totnode, flag);
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
|
2012-05-11 08:05:47 +00:00
|
|
|
if (flag & (PBVH_UpdateBB | PBVH_UpdateOriginalBB))
|
2009-11-06 16:46:35 +00:00
|
|
|
pbvh_flush_bb(bvh, bvh->nodes, flag);
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (nodes) MEM_freeN(nodes);
|
2009-10-27 19:53:34 +00:00
|
|
|
}
|
|
|
|
|
2012-12-30 18:31:31 +00:00
|
|
|
void BKE_pbvh_redraw_BB(PBVH *bvh, float bb_min[3], float bb_max[3])
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
{
|
|
|
|
PBVHIter iter;
|
|
|
|
PBVHNode *node;
|
|
|
|
BB bb;
|
|
|
|
|
|
|
|
BB_reset(&bb);
|
|
|
|
|
|
|
|
pbvh_iter_begin(&iter, bvh, NULL, NULL);
|
|
|
|
|
2012-05-11 08:05:47 +00:00
|
|
|
while ((node = pbvh_iter_next(&iter)))
|
2012-03-24 06:18:31 +00:00
|
|
|
if (node->flag & PBVH_UpdateRedraw)
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
BB_expand_with_bb(&bb, &node->vb);
|
|
|
|
|
|
|
|
pbvh_iter_end(&iter);
|
|
|
|
|
2009-11-11 10:44:46 +00:00
|
|
|
copy_v3_v3(bb_min, bb.bmin);
|
|
|
|
copy_v3_v3(bb_max, bb.bmax);
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
}
|
|
|
|
|
2015-11-25 19:49:31 -05:00
|
|
|
void BKE_pbvh_get_grid_updates(PBVH *bvh, bool clear, void ***r_gridfaces, int *r_totface)
|
2009-11-25 13:40:43 +00:00
|
|
|
{
|
2015-11-25 19:49:31 -05:00
|
|
|
GSet *face_set = BLI_gset_ptr_new(__func__);
|
2009-11-25 13:40:43 +00:00
|
|
|
PBVHNode *node;
|
2015-11-25 19:49:31 -05:00
|
|
|
PBVHIter iter;
|
2009-11-25 13:40:43 +00:00
|
|
|
|
|
|
|
pbvh_iter_begin(&iter, bvh, NULL, NULL);
|
|
|
|
|
2012-05-11 08:05:47 +00:00
|
|
|
while ((node = pbvh_iter_next(&iter))) {
|
2012-03-24 06:18:31 +00:00
|
|
|
if (node->flag & PBVH_UpdateNormals) {
|
2015-11-25 19:49:31 -05:00
|
|
|
for (unsigned i = 0; i < node->totprim; ++i) {
|
|
|
|
void *face = bvh->gridfaces[node->prim_indices[i]];
|
2016-02-29 08:48:10 +11:00
|
|
|
BLI_gset_add(face_set, face);
|
2009-11-25 13:40:43 +00:00
|
|
|
}
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (clear)
|
2009-12-09 13:37:19 +00:00
|
|
|
node->flag &= ~PBVH_UpdateNormals;
|
2009-11-25 13:40:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pbvh_iter_end(&iter);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2018-02-15 23:36:11 +11:00
|
|
|
const int tot = BLI_gset_len(face_set);
|
2012-03-24 06:18:31 +00:00
|
|
|
if (tot == 0) {
|
2014-04-22 00:54:36 +10:00
|
|
|
*r_totface = 0;
|
|
|
|
*r_gridfaces = NULL;
|
|
|
|
BLI_gset_free(face_set, NULL);
|
2009-11-25 13:40:43 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-11-25 19:49:31 -05:00
|
|
|
void **faces = MEM_mallocN(sizeof(*faces) * tot, "PBVH Grid Faces");
|
2009-11-25 13:40:43 +00:00
|
|
|
|
2015-11-25 19:49:31 -05:00
|
|
|
GSetIterator gs_iter;
|
2015-11-26 12:35:27 +11:00
|
|
|
int i;
|
2014-04-22 00:54:36 +10:00
|
|
|
GSET_ITER_INDEX (gs_iter, face_set, i) {
|
|
|
|
faces[i] = BLI_gsetIterator_getKey(&gs_iter);
|
2012-04-28 06:31:57 +00:00
|
|
|
}
|
2009-11-25 13:40:43 +00:00
|
|
|
|
2014-04-22 00:54:36 +10:00
|
|
|
BLI_gset_free(face_set, NULL);
|
2009-11-25 13:40:43 +00:00
|
|
|
|
2014-04-22 00:54:36 +10:00
|
|
|
*r_totface = tot;
|
|
|
|
*r_gridfaces = faces;
|
2009-11-25 13:40:43 +00:00
|
|
|
}
|
|
|
|
|
2012-03-12 23:03:43 +00:00
|
|
|
/***************************** PBVH Access ***********************************/
|
|
|
|
|
2012-12-30 18:31:31 +00:00
|
|
|
PBVHType BKE_pbvh_type(const PBVH *bvh)
|
2012-03-12 23:03:43 +00:00
|
|
|
{
|
|
|
|
return bvh->type;
|
|
|
|
}
|
|
|
|
|
2015-04-16 04:14:01 +10:00
|
|
|
bool BKE_pbvh_has_faces(const PBVH *bvh)
|
|
|
|
{
|
|
|
|
if (bvh->type == PBVH_BMESH) {
|
|
|
|
return (bvh->bm->totface != 0);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return (bvh->totprim != 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-20 00:19:57 +00:00
|
|
|
void BKE_pbvh_bounding_box(const PBVH *bvh, float min[3], float max[3])
|
|
|
|
{
|
|
|
|
if (bvh->totnode) {
|
|
|
|
const BB *bb = &bvh->nodes[0].vb;
|
|
|
|
copy_v3_v3(min, bb->bmin);
|
|
|
|
copy_v3_v3(max, bb->bmax);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
zero_v3(min);
|
|
|
|
zero_v3(max);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-22 23:20:48 +00:00
|
|
|
BLI_bitmap **BKE_pbvh_grid_hidden(const PBVH *bvh)
|
2012-03-14 06:32:03 +00:00
|
|
|
{
|
|
|
|
BLI_assert(bvh->type == PBVH_GRIDS);
|
|
|
|
return bvh->grid_hidden;
|
|
|
|
}
|
|
|
|
|
2012-12-30 18:31:31 +00:00
|
|
|
void BKE_pbvh_get_grid_key(const PBVH *bvh, CCGKey *key)
|
2012-05-10 20:33:09 +00:00
|
|
|
{
|
|
|
|
BLI_assert(bvh->type == PBVH_GRIDS);
|
|
|
|
*key = bvh->gridkey;
|
|
|
|
}
|
|
|
|
|
2018-09-15 08:08:43 +10:00
|
|
|
struct CCGElem **BKE_pbvh_get_grids(const PBVH *bvh, int *num_grids)
|
|
|
|
{
|
2018-09-14 10:56:54 +02:00
|
|
|
BLI_assert(bvh->type == PBVH_GRIDS);
|
|
|
|
*num_grids = bvh->totgrid;
|
|
|
|
return bvh->grids;
|
|
|
|
}
|
2017-09-28 01:38:17 +10:00
|
|
|
|
2012-12-30 18:31:31 +00:00
|
|
|
BMesh *BKE_pbvh_get_bmesh(PBVH *bvh)
|
2012-12-30 18:28:36 +00:00
|
|
|
{
|
|
|
|
BLI_assert(bvh->type == PBVH_BMESH);
|
|
|
|
return bvh->bm;
|
|
|
|
}
|
|
|
|
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
/***************************** Node Access ***********************************/
|
|
|
|
|
2012-12-30 18:31:31 +00:00
|
|
|
void BKE_pbvh_node_mark_update(PBVHNode *node)
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
{
|
2012-05-11 08:05:47 +00:00
|
|
|
node->flag |= PBVH_UpdateNormals | PBVH_UpdateBB | PBVH_UpdateOriginalBB | PBVH_UpdateDrawBuffers | PBVH_UpdateRedraw;
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
}
|
|
|
|
|
2012-12-30 18:31:31 +00:00
|
|
|
void BKE_pbvh_node_mark_rebuild_draw(PBVHNode *node)
|
2012-03-14 06:32:25 +00:00
|
|
|
{
|
2012-05-11 08:05:47 +00:00
|
|
|
node->flag |= PBVH_RebuildDrawBuffers | PBVH_UpdateDrawBuffers | PBVH_UpdateRedraw;
|
2012-03-14 06:32:25 +00:00
|
|
|
}
|
|
|
|
|
2013-11-15 23:00:15 +02:00
|
|
|
void BKE_pbvh_node_mark_redraw(PBVHNode *node)
|
|
|
|
{
|
|
|
|
node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateRedraw;
|
|
|
|
}
|
|
|
|
|
2014-05-29 05:22:44 +03:00
|
|
|
void BKE_pbvh_node_mark_normals_update(PBVHNode *node)
|
|
|
|
{
|
|
|
|
node->flag |= PBVH_UpdateNormals;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-12-30 18:31:31 +00:00
|
|
|
void BKE_pbvh_node_fully_hidden_set(PBVHNode *node, int fully_hidden)
|
2012-03-14 06:32:25 +00:00
|
|
|
{
|
|
|
|
BLI_assert(node->flag & PBVH_Leaf);
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (fully_hidden)
|
2012-03-14 06:32:25 +00:00
|
|
|
node->flag |= PBVH_FullyHidden;
|
|
|
|
else
|
|
|
|
node->flag &= ~PBVH_FullyHidden;
|
|
|
|
}
|
|
|
|
|
2015-07-12 03:49:47 +10:00
|
|
|
void BKE_pbvh_node_get_verts(
|
|
|
|
PBVH *bvh, PBVHNode *node,
|
|
|
|
const int **r_vert_indices, MVert **r_verts)
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
{
|
2015-07-12 03:49:47 +10:00
|
|
|
if (r_vert_indices) {
|
|
|
|
*r_vert_indices = node->vert_indices;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (r_verts) {
|
|
|
|
*r_verts = bvh->verts;
|
|
|
|
}
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
}
|
|
|
|
|
2015-07-12 03:49:47 +10:00
|
|
|
void BKE_pbvh_node_num_verts(
|
|
|
|
PBVH *bvh, PBVHNode *node,
|
|
|
|
int *r_uniquevert, int *r_totvert)
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
{
|
2012-03-12 23:03:43 +00:00
|
|
|
int tot;
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2012-04-28 06:31:57 +00:00
|
|
|
switch (bvh->type) {
|
2012-05-11 08:05:47 +00:00
|
|
|
case PBVH_GRIDS:
|
|
|
|
tot = node->totprim * bvh->gridkey.grid_area;
|
2015-07-12 03:49:47 +10:00
|
|
|
if (r_totvert) *r_totvert = tot;
|
|
|
|
if (r_uniquevert) *r_uniquevert = tot;
|
2012-05-11 08:05:47 +00:00
|
|
|
break;
|
|
|
|
case PBVH_FACES:
|
2015-07-12 03:49:47 +10:00
|
|
|
if (r_totvert) *r_totvert = node->uniq_verts + node->face_verts;
|
|
|
|
if (r_uniquevert) *r_uniquevert = node->uniq_verts;
|
2012-05-11 08:05:47 +00:00
|
|
|
break;
|
2012-12-30 18:28:36 +00:00
|
|
|
case PBVH_BMESH:
|
2018-02-15 23:36:11 +11:00
|
|
|
tot = BLI_gset_len(node->bm_unique_verts);
|
|
|
|
if (r_totvert) *r_totvert = tot + BLI_gset_len(node->bm_other_verts);
|
2015-07-12 03:49:47 +10:00
|
|
|
if (r_uniquevert) *r_uniquevert = tot;
|
2012-12-30 18:28:36 +00:00
|
|
|
break;
|
2009-11-25 13:40:43 +00:00
|
|
|
}
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
}
|
|
|
|
|
2015-07-12 03:49:47 +10:00
|
|
|
void BKE_pbvh_node_get_grids(
|
|
|
|
PBVH *bvh, PBVHNode *node,
|
|
|
|
int **r_grid_indices, int *r_totgrid, int *r_maxgrid, int *r_gridsize, CCGElem ***r_griddata)
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
{
|
2012-04-28 06:31:57 +00:00
|
|
|
switch (bvh->type) {
|
2012-05-11 08:05:47 +00:00
|
|
|
case PBVH_GRIDS:
|
2015-07-12 03:49:47 +10:00
|
|
|
if (r_grid_indices) *r_grid_indices = node->prim_indices;
|
|
|
|
if (r_totgrid) *r_totgrid = node->totprim;
|
|
|
|
if (r_maxgrid) *r_maxgrid = bvh->totgrid;
|
|
|
|
if (r_gridsize) *r_gridsize = bvh->gridkey.grid_size;
|
|
|
|
if (r_griddata) *r_griddata = bvh->grids;
|
2012-05-11 08:05:47 +00:00
|
|
|
break;
|
|
|
|
case PBVH_FACES:
|
2012-12-30 18:28:36 +00:00
|
|
|
case PBVH_BMESH:
|
2015-07-12 03:49:47 +10:00
|
|
|
if (r_grid_indices) *r_grid_indices = NULL;
|
|
|
|
if (r_totgrid) *r_totgrid = 0;
|
|
|
|
if (r_maxgrid) *r_maxgrid = 0;
|
|
|
|
if (r_gridsize) *r_gridsize = 0;
|
|
|
|
if (r_griddata) *r_griddata = NULL;
|
2012-05-11 08:05:47 +00:00
|
|
|
break;
|
2009-11-25 13:40:43 +00:00
|
|
|
}
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
}
|
|
|
|
|
2012-12-30 18:31:31 +00:00
|
|
|
void BKE_pbvh_node_get_BB(PBVHNode *node, float bb_min[3], float bb_max[3])
|
2009-11-06 16:46:35 +00:00
|
|
|
{
|
2009-11-11 10:44:46 +00:00
|
|
|
copy_v3_v3(bb_min, node->vb.bmin);
|
|
|
|
copy_v3_v3(bb_max, node->vb.bmax);
|
2009-11-06 16:46:35 +00:00
|
|
|
}
|
|
|
|
|
2012-12-30 18:31:31 +00:00
|
|
|
void BKE_pbvh_node_get_original_BB(PBVHNode *node, float bb_min[3], float bb_max[3])
|
2009-11-06 16:46:35 +00:00
|
|
|
{
|
2009-11-11 10:44:46 +00:00
|
|
|
copy_v3_v3(bb_min, node->orig_vb.bmin);
|
|
|
|
copy_v3_v3(bb_max, node->orig_vb.bmax);
|
2009-11-06 16:46:35 +00:00
|
|
|
}
|
|
|
|
|
2012-12-30 18:31:31 +00:00
|
|
|
void BKE_pbvh_node_get_proxies(PBVHNode *node, PBVHProxyNode **proxies, int *proxy_count)
|
2010-07-14 14:11:03 +00:00
|
|
|
{
|
|
|
|
if (node->proxy_count > 0) {
|
|
|
|
if (proxies) *proxies = node->proxies;
|
|
|
|
if (proxy_count) *proxy_count = node->proxy_count;
|
|
|
|
}
|
|
|
|
else {
|
2013-08-07 03:55:21 +00:00
|
|
|
if (proxies) *proxies = NULL;
|
2010-07-14 14:11:03 +00:00
|
|
|
if (proxy_count) *proxy_count = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-18 04:57:23 +10:00
|
|
|
void BKE_pbvh_node_get_bm_orco_data(
|
|
|
|
PBVHNode *node,
|
|
|
|
int (**r_orco_tris)[3], int *r_orco_tris_num, float (**r_orco_coords)[3])
|
|
|
|
{
|
|
|
|
*r_orco_tris = node->bm_ortri;
|
|
|
|
*r_orco_tris_num = node->bm_tot_ortri;
|
|
|
|
*r_orco_coords = node->bm_orco;
|
|
|
|
}
|
|
|
|
|
2016-02-13 17:58:44 +11:00
|
|
|
/**
|
|
|
|
* \note doing a full search on all vertices here seems expensive,
|
|
|
|
* however this is important to avoid having to recalculate boundbox & sync the buffers to the GPU
|
|
|
|
* (which is far more expensive!) See: T47232.
|
|
|
|
*/
|
|
|
|
bool BKE_pbvh_node_vert_update_check_any(PBVH *bvh, PBVHNode *node)
|
|
|
|
{
|
|
|
|
BLI_assert(bvh->type == PBVH_FACES);
|
|
|
|
const int *verts = node->vert_indices;
|
|
|
|
const int totvert = node->uniq_verts + node->face_verts;
|
|
|
|
|
|
|
|
for (int i = 0; i < totvert; ++i) {
|
|
|
|
const int v = verts[i];
|
|
|
|
const MVert *mvert = &bvh->verts[v];
|
|
|
|
|
|
|
|
if (mvert->flag & ME_VERT_PBVH_UPDATE) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
Sculpt: Multithreading & PBVH Changes
* Sculpting, normal update and bounding box code is now multithreaded
using OpenMP.
* Fix a number of update issues: normals on node boundaries, outdated
bounding boxes, partial redraw, .. . There's probably still a few
left, but should be better now.
* Clicking once now does a single paint instead of two (was also
painting on mouse up event).
* Smooth shading now is enabled for the full mesh when the first face
uses it (so it can be tested at least).
Implementation Notes:
* PBVH search can now be done either using a callback or bt gathering the
nodes in an array. The latter makes multithreading with OpenMP easier.
* Normals update code is now inside PBVH, was doing it per node before but
should do all faces first and only then vertices.
* Instead of using search modes + 1 modified flag, now nodes get 4 flags
to indicate what needs to be updated for them, found that this makes it
easier for me to understand the code and fix update bugs.
* PBVHNode is now exposed as an abstract type, I think this makes it more
clear what is happening than having it's data passed as part of callback
functions.
* Active_verts list was replaced by looping over nodes and the vertices
inside them. However the grab brush still uses the active_verts system,
will fix that later.
* Some micro-optimizations, like avoiding a few multiplications/divisions,
using local variables instead of pointers, or looping over fewer vertices
to update the bounding boxes.
2009-11-02 18:47:03 +00:00
|
|
|
/********************************* Raycast ***********************************/
|
|
|
|
|
2009-10-27 19:53:34 +00:00
|
|
|
typedef struct {
|
2016-01-20 17:00:12 +11:00
|
|
|
struct IsectRayAABB_Precalc ray;
|
2014-10-09 22:39:59 +02:00
|
|
|
bool original;
|
2009-10-27 19:53:34 +00:00
|
|
|
} RaycastData;
|
|
|
|
|
2014-02-03 18:55:59 +11:00
|
|
|
static bool ray_aabb_intersect(PBVHNode *node, void *data_v)
|
2009-10-27 19:53:34 +00:00
|
|
|
{
|
2012-07-05 03:55:55 +00:00
|
|
|
RaycastData *rcd = data_v;
|
2016-07-05 18:55:06 +10:00
|
|
|
const float *bb_min, *bb_max;
|
2009-10-27 19:53:34 +00:00
|
|
|
|
2016-07-05 18:55:06 +10:00
|
|
|
if (rcd->original) {
|
|
|
|
/* BKE_pbvh_node_get_original_BB */
|
|
|
|
bb_min = node->orig_vb.bmin;
|
|
|
|
bb_max = node->orig_vb.bmax;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* BKE_pbvh_node_get_BB */
|
|
|
|
bb_min = node->vb.bmin;
|
|
|
|
bb_max = node->vb.bmax;
|
|
|
|
}
|
2009-10-27 19:53:34 +00:00
|
|
|
|
2016-01-20 17:00:12 +11:00
|
|
|
return isect_ray_aabb_v3(&rcd->ray, bb_min, bb_max, &node->tmin);
|
2009-10-27 19:53:34 +00:00
|
|
|
}
|
|
|
|
|
2014-10-09 22:39:59 +02:00
|
|
|
void BKE_pbvh_raycast(
|
|
|
|
PBVH *bvh, BKE_pbvh_HitOccludedCallback cb, void *data,
|
|
|
|
const float ray_start[3], const float ray_normal[3],
|
|
|
|
bool original)
|
2009-10-27 19:53:34 +00:00
|
|
|
{
|
|
|
|
RaycastData rcd;
|
|
|
|
|
2016-01-20 17:00:12 +11:00
|
|
|
isect_ray_aabb_v3_precalc(&rcd.ray, ray_start, ray_normal);
|
2009-11-06 16:46:35 +00:00
|
|
|
rcd.original = original;
|
2009-10-27 19:53:34 +00:00
|
|
|
|
2012-12-30 18:31:31 +00:00
|
|
|
BKE_pbvh_search_callback_occluded(bvh, ray_aabb_intersect, &rcd, cb, data);
|
2009-10-27 19:53:34 +00:00
|
|
|
}
|
|
|
|
|
2015-07-17 04:15:24 +10:00
|
|
|
bool ray_face_intersection_quad(
|
|
|
|
const float ray_start[3], const float ray_normal[3],
|
|
|
|
const float t0[3], const float t1[3], const float t2[3], const float t3[3],
|
2017-10-05 21:06:04 +11:00
|
|
|
float *depth)
|
2009-11-25 13:40:43 +00:00
|
|
|
{
|
2017-10-05 21:06:04 +11:00
|
|
|
float depth_test;
|
2011-04-21 13:11:51 +00:00
|
|
|
|
2017-10-05 21:06:04 +11:00
|
|
|
if ((isect_ray_tri_epsilon_v3(
|
|
|
|
ray_start, ray_normal, t0, t1, t2, &depth_test, NULL, 0.1f) && (depth_test < *depth)) ||
|
|
|
|
(isect_ray_tri_epsilon_v3(
|
|
|
|
ray_start, ray_normal, t0, t2, t3, &depth_test, NULL, 0.1f) && (depth_test < *depth)))
|
2011-04-21 13:11:51 +00:00
|
|
|
{
|
2017-10-05 21:06:04 +11:00
|
|
|
*depth = depth_test;
|
2015-07-17 04:15:24 +10:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ray_face_intersection_tri(
|
|
|
|
const float ray_start[3], const float ray_normal[3],
|
|
|
|
const float t0[3], const float t1[3], const float t2[3],
|
2017-10-05 21:06:04 +11:00
|
|
|
float *depth)
|
2015-07-17 04:15:24 +10:00
|
|
|
{
|
2017-10-05 21:06:04 +11:00
|
|
|
float depth_test;
|
2015-07-17 04:15:24 +10:00
|
|
|
|
2017-10-05 21:06:04 +11:00
|
|
|
if ((isect_ray_tri_epsilon_v3(
|
|
|
|
ray_start, ray_normal, t0, t1, t2, &depth_test, NULL, 0.1f) && (depth_test < *depth)))
|
|
|
|
{
|
|
|
|
*depth = depth_test;
|
2014-12-01 17:11:18 +01:00
|
|
|
return true;
|
2011-04-21 13:11:51 +00:00
|
|
|
}
|
|
|
|
else {
|
2014-12-01 17:11:18 +01:00
|
|
|
return false;
|
2011-04-21 13:11:51 +00:00
|
|
|
}
|
2009-11-25 13:40:43 +00:00
|
|
|
}
|
|
|
|
|
2017-10-05 21:16:25 +11:00
|
|
|
/* Take advantage of the fact we know this wont be an intersection.
|
|
|
|
* Just handle ray-tri edges. */
|
|
|
|
static float dist_squared_ray_to_tri_v3_fast(
|
|
|
|
const float ray_origin[3], const float ray_direction[3],
|
|
|
|
const float v0[3], const float v1[3], const float v2[3],
|
|
|
|
float r_point[3], float *r_depth)
|
|
|
|
{
|
|
|
|
const float *tri[3] = {v0, v1, v2};
|
|
|
|
float dist_sq_best = FLT_MAX;
|
|
|
|
for (int i = 0, j = 2; i < 3; j = i++) {
|
|
|
|
float point_test[3], depth_test = FLT_MAX;
|
|
|
|
const float dist_sq_test = dist_squared_ray_to_seg_v3(
|
|
|
|
ray_origin, ray_direction, tri[i], tri[j], point_test, &depth_test);
|
|
|
|
if (dist_sq_test < dist_sq_best || i == 0) {
|
|
|
|
copy_v3_v3(r_point, point_test);
|
|
|
|
*r_depth = depth_test;
|
|
|
|
dist_sq_best = dist_sq_test;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return dist_sq_best;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ray_face_nearest_quad(
|
|
|
|
const float ray_start[3], const float ray_normal[3],
|
|
|
|
const float t0[3], const float t1[3], const float t2[3], const float t3[3],
|
|
|
|
float *depth, float *dist_sq)
|
|
|
|
{
|
|
|
|
float dist_sq_test;
|
|
|
|
float co[3], depth_test;
|
|
|
|
|
|
|
|
if (((dist_sq_test = dist_squared_ray_to_tri_v3_fast(
|
|
|
|
ray_start, ray_normal, t0, t1, t2, co, &depth_test)) < *dist_sq))
|
|
|
|
{
|
|
|
|
*dist_sq = dist_sq_test;
|
|
|
|
*depth = depth_test;
|
|
|
|
if (((dist_sq_test = dist_squared_ray_to_tri_v3_fast(
|
|
|
|
ray_start, ray_normal, t0, t2, t3, co, &depth_test)) < *dist_sq))
|
|
|
|
{
|
|
|
|
*dist_sq = dist_sq_test;
|
|
|
|
*depth = depth_test;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ray_face_nearest_tri(
|
|
|
|
const float ray_start[3], const float ray_normal[3],
|
|
|
|
const float t0[3], const float t1[3], const float t2[3],
|
|
|
|
float *depth, float *dist_sq)
|
2015-07-17 04:15:24 +10:00
|
|
|
{
|
2017-10-05 21:16:25 +11:00
|
|
|
float dist_sq_test;
|
|
|
|
float co[3], depth_test;
|
2015-07-17 04:15:24 +10:00
|
|
|
|
2017-10-05 21:16:25 +11:00
|
|
|
if (((dist_sq_test = dist_squared_ray_to_tri_v3_fast(
|
|
|
|
ray_start, ray_normal, t0, t1, t2, co, &depth_test)) < *dist_sq))
|
|
|
|
{
|
|
|
|
*dist_sq = dist_sq_test;
|
|
|
|
*depth = depth_test;
|
2014-12-01 17:11:18 +01:00
|
|
|
return true;
|
2011-04-21 13:11:51 +00:00
|
|
|
}
|
|
|
|
else {
|
2014-12-01 17:11:18 +01:00
|
|
|
return false;
|
2011-04-21 13:11:51 +00:00
|
|
|
}
|
2009-11-25 13:40:43 +00:00
|
|
|
}
|
|
|
|
|
2015-07-17 04:15:24 +10:00
|
|
|
static bool pbvh_faces_node_raycast(
|
|
|
|
PBVH *bvh, const PBVHNode *node,
|
|
|
|
float (*origco)[3],
|
|
|
|
const float ray_start[3], const float ray_normal[3],
|
2017-10-05 21:06:04 +11:00
|
|
|
float *depth)
|
2009-11-25 13:40:43 +00:00
|
|
|
{
|
2012-06-10 16:37:22 +00:00
|
|
|
const MVert *vert = bvh->verts;
|
2015-07-17 03:36:03 +10:00
|
|
|
const MLoop *mloop = bvh->mloop;
|
2012-06-10 16:37:22 +00:00
|
|
|
const int *faces = node->prim_indices;
|
2014-02-03 18:55:59 +11:00
|
|
|
int i, totface = node->totprim;
|
|
|
|
bool hit = false;
|
2012-06-10 16:37:22 +00:00
|
|
|
|
|
|
|
for (i = 0; i < totface; ++i) {
|
2015-07-17 03:36:03 +10:00
|
|
|
const MLoopTri *lt = &bvh->looptri[faces[i]];
|
2012-06-10 16:37:22 +00:00
|
|
|
const int *face_verts = node->face_vert_indices[i];
|
|
|
|
|
2015-07-17 03:36:03 +10:00
|
|
|
if (paint_is_face_hidden(lt, vert, mloop))
|
2012-06-10 16:37:22 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
if (origco) {
|
|
|
|
/* intersect with backuped original coordinates */
|
2015-07-17 04:15:24 +10:00
|
|
|
hit |= ray_face_intersection_tri(
|
|
|
|
ray_start, ray_normal,
|
|
|
|
origco[face_verts[0]],
|
|
|
|
origco[face_verts[1]],
|
|
|
|
origco[face_verts[2]],
|
2017-10-05 21:06:04 +11:00
|
|
|
depth);
|
2012-06-10 16:37:22 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* intersect with current coordinates */
|
2015-07-17 04:15:24 +10:00
|
|
|
hit |= ray_face_intersection_tri(
|
|
|
|
ray_start, ray_normal,
|
|
|
|
vert[mloop[lt->tri[0]].v].co,
|
|
|
|
vert[mloop[lt->tri[1]].v].co,
|
|
|
|
vert[mloop[lt->tri[2]].v].co,
|
2017-10-05 21:06:04 +11:00
|
|
|
depth);
|
2012-06-10 16:37:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return hit;
|
|
|
|
}
|
|
|
|
|
2014-03-24 13:21:58 +11:00
|
|
|
static bool pbvh_grids_node_raycast(
|
|
|
|
PBVH *bvh, PBVHNode *node,
|
|
|
|
float (*origco)[3],
|
|
|
|
const float ray_start[3], const float ray_normal[3],
|
2017-10-05 21:06:04 +11:00
|
|
|
float *depth)
|
2012-06-10 16:37:22 +00:00
|
|
|
{
|
2015-11-25 19:49:31 -05:00
|
|
|
const int totgrid = node->totprim;
|
|
|
|
const int gridsize = bvh->gridkey.grid_size;
|
2014-03-24 13:21:58 +11:00
|
|
|
bool hit = false;
|
2009-11-25 13:40:43 +00:00
|
|
|
|
2015-11-25 19:49:31 -05:00
|
|
|
for (int i = 0; i < totgrid; ++i) {
|
2012-06-10 16:37:22 +00:00
|
|
|
CCGElem *grid = bvh->grids[node->prim_indices[i]];
|
2013-07-22 23:20:48 +00:00
|
|
|
BLI_bitmap *gh;
|
2012-03-14 06:32:25 +00:00
|
|
|
|
2012-06-10 16:37:22 +00:00
|
|
|
if (!grid)
|
|
|
|
continue;
|
2012-03-14 06:32:25 +00:00
|
|
|
|
2012-06-10 16:37:22 +00:00
|
|
|
gh = bvh->grid_hidden[node->prim_indices[i]];
|
2012-05-11 08:05:47 +00:00
|
|
|
|
2015-11-25 19:49:31 -05:00
|
|
|
for (int y = 0; y < gridsize - 1; ++y) {
|
|
|
|
for (int x = 0; x < gridsize - 1; ++x) {
|
2012-06-10 16:37:22 +00:00
|
|
|
/* check if grid face is hidden */
|
|
|
|
if (gh) {
|
|
|
|
if (paint_is_grid_face_hidden(gh, gridsize, x, y))
|
|
|
|
continue;
|
|
|
|
}
|
2012-05-11 08:05:47 +00:00
|
|
|
|
|
|
|
if (origco) {
|
2015-07-17 04:15:24 +10:00
|
|
|
hit |= ray_face_intersection_quad(
|
|
|
|
ray_start, ray_normal,
|
|
|
|
origco[y * gridsize + x],
|
|
|
|
origco[y * gridsize + x + 1],
|
|
|
|
origco[(y + 1) * gridsize + x + 1],
|
|
|
|
origco[(y + 1) * gridsize + x],
|
2017-10-05 21:06:04 +11:00
|
|
|
depth);
|
2012-05-11 08:05:47 +00:00
|
|
|
}
|
|
|
|
else {
|
2015-07-17 04:15:24 +10:00
|
|
|
hit |= ray_face_intersection_quad(
|
|
|
|
ray_start, ray_normal,
|
|
|
|
CCG_grid_elem_co(&bvh->gridkey, grid, x, y),
|
|
|
|
CCG_grid_elem_co(&bvh->gridkey, grid, x + 1, y),
|
|
|
|
CCG_grid_elem_co(&bvh->gridkey, grid, x + 1, y + 1),
|
|
|
|
CCG_grid_elem_co(&bvh->gridkey, grid, x, y + 1),
|
2017-10-05 21:06:04 +11:00
|
|
|
depth);
|
2009-11-25 13:40:43 +00:00
|
|
|
}
|
|
|
|
}
|
2012-06-10 16:37:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (origco)
|
|
|
|
origco += gridsize * gridsize;
|
|
|
|
}
|
|
|
|
|
|
|
|
return hit;
|
|
|
|
}
|
|
|
|
|
2014-03-24 13:21:58 +11:00
|
|
|
bool BKE_pbvh_node_raycast(
|
2015-11-25 19:49:31 -05:00
|
|
|
PBVH *bvh, PBVHNode *node, float (*origco)[3], bool use_origco,
|
2014-03-24 13:21:58 +11:00
|
|
|
const float ray_start[3], const float ray_normal[3],
|
2017-10-05 21:06:04 +11:00
|
|
|
float *depth)
|
2012-06-10 16:37:22 +00:00
|
|
|
{
|
2014-02-03 18:55:59 +11:00
|
|
|
bool hit = false;
|
2012-06-10 16:37:22 +00:00
|
|
|
|
|
|
|
if (node->flag & PBVH_FullyHidden)
|
2015-11-25 19:49:31 -05:00
|
|
|
return false;
|
2012-06-10 16:37:22 +00:00
|
|
|
|
|
|
|
switch (bvh->type) {
|
|
|
|
case PBVH_FACES:
|
2015-07-17 04:15:24 +10:00
|
|
|
hit |= pbvh_faces_node_raycast(
|
|
|
|
bvh, node, origco,
|
2017-10-05 21:06:04 +11:00
|
|
|
ray_start, ray_normal, depth);
|
2012-05-11 08:05:47 +00:00
|
|
|
break;
|
|
|
|
case PBVH_GRIDS:
|
2015-07-17 04:15:24 +10:00
|
|
|
hit |= pbvh_grids_node_raycast(
|
|
|
|
bvh, node, origco,
|
2017-10-05 21:06:04 +11:00
|
|
|
ray_start, ray_normal, depth);
|
2012-05-11 08:05:47 +00:00
|
|
|
break;
|
2012-12-30 18:28:36 +00:00
|
|
|
case PBVH_BMESH:
|
2015-07-17 04:15:24 +10:00
|
|
|
hit = pbvh_bmesh_node_raycast(
|
2017-10-05 21:06:04 +11:00
|
|
|
node, ray_start, ray_normal, depth, use_origco);
|
2012-12-30 18:28:36 +00:00
|
|
|
break;
|
2009-11-25 13:40:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return hit;
|
|
|
|
}
|
|
|
|
|
2015-04-30 08:07:15 +10:00
|
|
|
void BKE_pbvh_raycast_project_ray_root(
|
|
|
|
PBVH *bvh, bool original,
|
|
|
|
float ray_start[3], float ray_end[3], float ray_normal[3])
|
2013-12-18 18:34:02 +02:00
|
|
|
{
|
|
|
|
if (bvh->nodes) {
|
|
|
|
float rootmin_start, rootmin_end;
|
|
|
|
float bb_min_root[3], bb_max_root[3], bb_center[3], bb_diff[3];
|
2016-01-20 17:00:12 +11:00
|
|
|
struct IsectRayAABB_Precalc ray;
|
2013-12-18 18:34:02 +02:00
|
|
|
float ray_normal_inv[3];
|
|
|
|
float offset = 1.0f + 1e-3f;
|
|
|
|
float offset_vec[3] = {1e-3f, 1e-3f, 1e-3f};
|
|
|
|
|
|
|
|
if (original)
|
|
|
|
BKE_pbvh_node_get_original_BB(bvh->nodes, bb_min_root, bb_max_root);
|
|
|
|
else
|
|
|
|
BKE_pbvh_node_get_BB(bvh->nodes, bb_min_root, bb_max_root);
|
|
|
|
|
|
|
|
/* slightly offset min and max in case we have a zero width node (due to a plane mesh for instance),
|
|
|
|
* or faces very close to the bounding box boundary. */
|
|
|
|
mid_v3_v3v3(bb_center, bb_max_root, bb_min_root);
|
|
|
|
/* diff should be same for both min/max since it's calculated from center */
|
|
|
|
sub_v3_v3v3(bb_diff, bb_max_root, bb_center);
|
|
|
|
/* handles case of zero width bb */
|
|
|
|
add_v3_v3(bb_diff, offset_vec);
|
|
|
|
madd_v3_v3v3fl(bb_max_root, bb_center, bb_diff, offset);
|
|
|
|
madd_v3_v3v3fl(bb_min_root, bb_center, bb_diff, -offset);
|
|
|
|
|
|
|
|
/* first project start ray */
|
2016-01-20 17:00:12 +11:00
|
|
|
isect_ray_aabb_v3_precalc(&ray, ray_start, ray_normal);
|
|
|
|
if (!isect_ray_aabb_v3(&ray, bb_min_root, bb_max_root, &rootmin_start))
|
2013-12-18 18:34:02 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
/* then the end ray */
|
|
|
|
mul_v3_v3fl(ray_normal_inv, ray_normal, -1.0);
|
2016-01-20 17:00:12 +11:00
|
|
|
isect_ray_aabb_v3_precalc(&ray, ray_end, ray_normal_inv);
|
2013-12-18 18:34:02 +02:00
|
|
|
/* unlikely to fail exiting if entering succeeded, still keep this here */
|
2016-01-20 17:00:12 +11:00
|
|
|
if (!isect_ray_aabb_v3(&ray, bb_min_root, bb_max_root, &rootmin_end))
|
2013-12-18 18:34:02 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
madd_v3_v3v3fl(ray_start, ray_start, ray_normal, rootmin_start);
|
|
|
|
madd_v3_v3v3fl(ray_end, ray_end, ray_normal_inv, rootmin_end);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-05 21:16:25 +11:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
struct DistRayAABB_Precalc dist_ray_to_aabb_precalc;
|
|
|
|
bool original;
|
|
|
|
} FindNearestRayData;
|
|
|
|
|
|
|
|
static bool nearest_to_ray_aabb_dist_sq(PBVHNode *node, void *data_v)
|
|
|
|
{
|
|
|
|
FindNearestRayData *rcd = data_v;
|
|
|
|
const float *bb_min, *bb_max;
|
|
|
|
|
|
|
|
if (rcd->original) {
|
|
|
|
/* BKE_pbvh_node_get_original_BB */
|
|
|
|
bb_min = node->orig_vb.bmin;
|
|
|
|
bb_max = node->orig_vb.bmax;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* BKE_pbvh_node_get_BB */
|
|
|
|
bb_min = node->vb.bmin;
|
|
|
|
bb_max = node->vb.bmax;
|
|
|
|
}
|
|
|
|
|
|
|
|
float co_dummy[3], depth;
|
2017-10-06 21:05:34 +11:00
|
|
|
node->tmin = dist_squared_ray_to_aabb_v3(&rcd->dist_ray_to_aabb_precalc, bb_min, bb_max, co_dummy, &depth);
|
2017-10-05 21:16:25 +11:00
|
|
|
/* Ideally we would skip distances outside the range. */
|
|
|
|
return depth > 0.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BKE_pbvh_find_nearest_to_ray(
|
|
|
|
PBVH *bvh, BKE_pbvh_SearchNearestCallback cb, void *data,
|
|
|
|
const float ray_start[3], const float ray_normal[3],
|
|
|
|
bool original)
|
|
|
|
{
|
|
|
|
FindNearestRayData ncd;
|
|
|
|
|
2017-10-06 21:05:34 +11:00
|
|
|
dist_squared_ray_to_aabb_v3_precalc(&ncd.dist_ray_to_aabb_precalc, ray_start, ray_normal);
|
2017-10-05 21:16:25 +11:00
|
|
|
ncd.original = original;
|
|
|
|
|
|
|
|
BKE_pbvh_search_callback_occluded(bvh, nearest_to_ray_aabb_dist_sq, &ncd, cb, data);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static bool pbvh_faces_node_nearest_to_ray(
|
|
|
|
PBVH *bvh, const PBVHNode *node,
|
|
|
|
float (*origco)[3],
|
|
|
|
const float ray_start[3], const float ray_normal[3],
|
|
|
|
float *depth, float *dist_sq)
|
|
|
|
{
|
|
|
|
const MVert *vert = bvh->verts;
|
|
|
|
const MLoop *mloop = bvh->mloop;
|
|
|
|
const int *faces = node->prim_indices;
|
|
|
|
int i, totface = node->totprim;
|
|
|
|
bool hit = false;
|
|
|
|
|
|
|
|
for (i = 0; i < totface; ++i) {
|
|
|
|
const MLoopTri *lt = &bvh->looptri[faces[i]];
|
|
|
|
const int *face_verts = node->face_vert_indices[i];
|
|
|
|
|
|
|
|
if (paint_is_face_hidden(lt, vert, mloop))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (origco) {
|
|
|
|
/* intersect with backuped original coordinates */
|
|
|
|
hit |= ray_face_nearest_tri(
|
|
|
|
ray_start, ray_normal,
|
|
|
|
origco[face_verts[0]],
|
|
|
|
origco[face_verts[1]],
|
|
|
|
origco[face_verts[2]],
|
|
|
|
depth, dist_sq);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* intersect with current coordinates */
|
|
|
|
hit |= ray_face_nearest_tri(
|
|
|
|
ray_start, ray_normal,
|
|
|
|
vert[mloop[lt->tri[0]].v].co,
|
|
|
|
vert[mloop[lt->tri[1]].v].co,
|
|
|
|
vert[mloop[lt->tri[2]].v].co,
|
|
|
|
depth, dist_sq);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return hit;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool pbvh_grids_node_nearest_to_ray(
|
|
|
|
PBVH *bvh, PBVHNode *node,
|
|
|
|
float (*origco)[3],
|
|
|
|
const float ray_start[3], const float ray_normal[3],
|
|
|
|
float *depth, float *dist_sq)
|
|
|
|
{
|
|
|
|
const int totgrid = node->totprim;
|
|
|
|
const int gridsize = bvh->gridkey.grid_size;
|
|
|
|
bool hit = false;
|
|
|
|
|
|
|
|
for (int i = 0; i < totgrid; ++i) {
|
|
|
|
CCGElem *grid = bvh->grids[node->prim_indices[i]];
|
|
|
|
BLI_bitmap *gh;
|
|
|
|
|
|
|
|
if (!grid)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
gh = bvh->grid_hidden[node->prim_indices[i]];
|
|
|
|
|
|
|
|
for (int y = 0; y < gridsize - 1; ++y) {
|
|
|
|
for (int x = 0; x < gridsize - 1; ++x) {
|
|
|
|
/* check if grid face is hidden */
|
|
|
|
if (gh) {
|
|
|
|
if (paint_is_grid_face_hidden(gh, gridsize, x, y))
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (origco) {
|
|
|
|
hit |= ray_face_nearest_quad(
|
|
|
|
ray_start, ray_normal,
|
|
|
|
origco[y * gridsize + x],
|
|
|
|
origco[y * gridsize + x + 1],
|
|
|
|
origco[(y + 1) * gridsize + x + 1],
|
|
|
|
origco[(y + 1) * gridsize + x],
|
|
|
|
depth, dist_sq);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
hit |= ray_face_nearest_quad(
|
|
|
|
ray_start, ray_normal,
|
|
|
|
CCG_grid_elem_co(&bvh->gridkey, grid, x, y),
|
|
|
|
CCG_grid_elem_co(&bvh->gridkey, grid, x + 1, y),
|
|
|
|
CCG_grid_elem_co(&bvh->gridkey, grid, x + 1, y + 1),
|
|
|
|
CCG_grid_elem_co(&bvh->gridkey, grid, x, y + 1),
|
|
|
|
depth, dist_sq);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (origco)
|
|
|
|
origco += gridsize * gridsize;
|
|
|
|
}
|
|
|
|
|
|
|
|
return hit;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool BKE_pbvh_node_find_nearest_to_ray(
|
|
|
|
PBVH *bvh, PBVHNode *node, float (*origco)[3], bool use_origco,
|
|
|
|
const float ray_start[3], const float ray_normal[3],
|
|
|
|
float *depth, float *dist_sq)
|
|
|
|
{
|
|
|
|
bool hit = false;
|
|
|
|
|
|
|
|
if (node->flag & PBVH_FullyHidden)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
switch (bvh->type) {
|
|
|
|
case PBVH_FACES:
|
|
|
|
hit |= pbvh_faces_node_nearest_to_ray(
|
|
|
|
bvh, node, origco,
|
|
|
|
ray_start, ray_normal, depth, dist_sq);
|
|
|
|
break;
|
|
|
|
case PBVH_GRIDS:
|
|
|
|
hit |= pbvh_grids_node_nearest_to_ray(
|
|
|
|
bvh, node, origco,
|
|
|
|
ray_start, ray_normal, depth, dist_sq);
|
|
|
|
break;
|
|
|
|
case PBVH_BMESH:
|
|
|
|
hit = pbvh_bmesh_node_nearest_to_ray(
|
|
|
|
node, ray_start, ray_normal, depth, dist_sq, use_origco);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return hit;
|
|
|
|
}
|
|
|
|
|
2012-03-14 06:32:25 +00:00
|
|
|
typedef enum {
|
|
|
|
ISECT_INSIDE,
|
|
|
|
ISECT_OUTSIDE,
|
|
|
|
ISECT_INTERSECT
|
|
|
|
} PlaneAABBIsect;
|
|
|
|
|
2009-11-25 13:40:43 +00:00
|
|
|
/* Adapted from:
|
2012-03-03 20:19:11 +00:00
|
|
|
* http://www.gamedev.net/community/forums/topic.asp?topic_id=512123
|
|
|
|
* Returns true if the AABB is at least partially within the frustum
|
|
|
|
* (ok, not a real frustum), false otherwise.
|
|
|
|
*/
|
2012-03-14 06:32:25 +00:00
|
|
|
static PlaneAABBIsect test_planes_aabb(const float bb_min[3],
|
2012-05-11 08:05:47 +00:00
|
|
|
const float bb_max[3],
|
|
|
|
const float (*planes)[4])
|
2009-11-25 13:40:43 +00:00
|
|
|
{
|
2012-03-14 06:32:25 +00:00
|
|
|
float vmin[3], vmax[3];
|
|
|
|
PlaneAABBIsect ret = ISECT_INSIDE;
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2015-11-25 19:49:31 -05:00
|
|
|
for (int i = 0; i < 4; ++i) {
|
|
|
|
for (int axis = 0; axis < 3; ++axis) {
|
2012-10-21 05:46:41 +00:00
|
|
|
if (planes[i][axis] > 0) {
|
2009-11-25 13:40:43 +00:00
|
|
|
vmin[axis] = bb_min[axis];
|
2012-03-14 06:32:25 +00:00
|
|
|
vmax[axis] = bb_max[axis];
|
2009-11-25 13:40:43 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
vmin[axis] = bb_max[axis];
|
2012-03-14 06:32:25 +00:00
|
|
|
vmax[axis] = bb_min[axis];
|
2009-11-25 13:40:43 +00:00
|
|
|
}
|
|
|
|
}
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (dot_v3v3(planes[i], vmin) + planes[i][3] > 0)
|
2012-03-14 06:32:25 +00:00
|
|
|
return ISECT_OUTSIDE;
|
2012-03-24 06:18:31 +00:00
|
|
|
else if (dot_v3v3(planes[i], vmax) + planes[i][3] >= 0)
|
2012-03-14 06:32:25 +00:00
|
|
|
ret = ISECT_INTERSECT;
|
2012-10-21 05:46:41 +00:00
|
|
|
}
|
2009-11-25 13:40:43 +00:00
|
|
|
|
2012-03-14 06:32:25 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2014-02-03 18:55:59 +11:00
|
|
|
bool BKE_pbvh_node_planes_contain_AABB(PBVHNode *node, void *data)
|
2012-03-14 06:32:25 +00:00
|
|
|
{
|
2016-07-05 18:55:06 +10:00
|
|
|
const float *bb_min, *bb_max;
|
|
|
|
/* BKE_pbvh_node_get_BB */
|
|
|
|
bb_min = node->vb.bmin;
|
|
|
|
bb_max = node->vb.bmax;
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2012-03-14 06:32:25 +00:00
|
|
|
return test_planes_aabb(bb_min, bb_max, data) != ISECT_OUTSIDE;
|
|
|
|
}
|
|
|
|
|
2014-02-03 18:55:59 +11:00
|
|
|
bool BKE_pbvh_node_planes_exclude_AABB(PBVHNode *node, void *data)
|
2012-03-14 06:32:25 +00:00
|
|
|
{
|
2016-07-05 18:55:06 +10:00
|
|
|
const float *bb_min, *bb_max;
|
|
|
|
/* BKE_pbvh_node_get_BB */
|
|
|
|
bb_min = node->vb.bmin;
|
|
|
|
bb_max = node->vb.bmax;
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2012-03-14 06:32:25 +00:00
|
|
|
return test_planes_aabb(bb_min, bb_max, data) != ISECT_INSIDE;
|
2009-11-25 13:40:43 +00:00
|
|
|
}
|
|
|
|
|
2017-05-11 21:21:59 +10:00
|
|
|
struct PBVHNodeDrawCallbackData {
|
2018-07-18 00:12:21 +02:00
|
|
|
void (*draw_fn)(void *user_data, GPUBatch *batch);
|
2017-05-11 21:21:59 +10:00
|
|
|
void *user_data;
|
|
|
|
bool fast;
|
2018-08-24 16:46:42 +02:00
|
|
|
bool only_mask; /* Only draw nodes that have mask data. */
|
2019-02-14 20:24:13 +01:00
|
|
|
bool wires;
|
2017-05-11 21:21:59 +10:00
|
|
|
};
|
|
|
|
|
|
|
|
static void pbvh_node_draw_cb(PBVHNode *node, void *data_v)
|
|
|
|
{
|
|
|
|
struct PBVHNodeDrawCallbackData *data = data_v;
|
|
|
|
|
|
|
|
if (!(node->flag & PBVH_FullyHidden)) {
|
2019-02-14 20:24:13 +01:00
|
|
|
GPUBatch *batch = GPU_pbvh_buffers_batch_get(node->draw_buffers, data->fast, data->wires);
|
2018-08-24 16:46:42 +02:00
|
|
|
bool show_mask = GPU_pbvh_buffers_has_mask(node->draw_buffers);
|
|
|
|
if (!data->only_mask || show_mask) {
|
2019-02-14 20:24:13 +01:00
|
|
|
if (batch != NULL) {
|
|
|
|
data->draw_fn(data->user_data, batch);
|
2018-08-24 16:46:42 +02:00
|
|
|
}
|
2017-05-11 21:21:59 +10:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Version of #BKE_pbvh_draw that runs a callback.
|
|
|
|
*/
|
|
|
|
void BKE_pbvh_draw_cb(
|
2019-02-14 20:24:13 +01:00
|
|
|
PBVH *bvh, float (*planes)[4], float (*fnors)[3], bool fast, bool wires, bool only_mask,
|
2018-07-18 00:12:21 +02:00
|
|
|
void (*draw_fn)(void *user_data, GPUBatch *batch), void *user_data)
|
2017-05-11 21:21:59 +10:00
|
|
|
{
|
|
|
|
struct PBVHNodeDrawCallbackData draw_data = {
|
2018-08-24 16:46:42 +02:00
|
|
|
.only_mask = only_mask,
|
2017-05-11 21:21:59 +10:00
|
|
|
.fast = fast,
|
2019-02-14 20:24:13 +01:00
|
|
|
.wires = wires,
|
2017-05-11 21:21:59 +10:00
|
|
|
.draw_fn = draw_fn,
|
|
|
|
.user_data = user_data,
|
|
|
|
};
|
|
|
|
PBVHNode **nodes;
|
|
|
|
int totnode;
|
|
|
|
|
2018-09-19 12:05:58 +10:00
|
|
|
BKE_pbvh_search_gather(bvh, update_search_cb, POINTER_FROM_INT(PBVH_UpdateNormals | PBVH_UpdateDrawBuffers),
|
2017-05-11 21:21:59 +10:00
|
|
|
&nodes, &totnode);
|
|
|
|
|
|
|
|
pbvh_update_normals(bvh, nodes, totnode, fnors);
|
|
|
|
pbvh_update_draw_buffers(bvh, nodes, totnode);
|
|
|
|
|
|
|
|
if (nodes) MEM_freeN(nodes);
|
|
|
|
|
|
|
|
if (planes) {
|
|
|
|
BKE_pbvh_search_callback(
|
|
|
|
bvh, BKE_pbvh_node_planes_contain_AABB,
|
|
|
|
planes, pbvh_node_draw_cb, &draw_data);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
BKE_pbvh_search_callback(
|
|
|
|
bvh, NULL,
|
|
|
|
NULL, pbvh_node_draw_cb, &draw_data);
|
|
|
|
}
|
|
|
|
#if 0
|
|
|
|
if (G.debug_value == 14)
|
|
|
|
pbvh_draw_BB(bvh);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2015-05-27 19:52:12 +02:00
|
|
|
void BKE_pbvh_grids_update(PBVH *bvh, CCGElem **grids, void **gridfaces,
|
2013-07-22 23:20:48 +00:00
|
|
|
DMFlagMat *flagmats, BLI_bitmap **grid_hidden)
|
2010-06-02 18:04:31 +00:00
|
|
|
{
|
2012-05-11 08:05:47 +00:00
|
|
|
bvh->grids = grids;
|
|
|
|
bvh->gridfaces = gridfaces;
|
2012-11-08 14:22:05 +00:00
|
|
|
|
2012-11-14 08:05:40 +00:00
|
|
|
if (flagmats != bvh->grid_flag_mats || bvh->grid_hidden != grid_hidden) {
|
|
|
|
bvh->grid_flag_mats = flagmats;
|
|
|
|
bvh->grid_hidden = grid_hidden;
|
|
|
|
|
2015-11-25 19:49:31 -05:00
|
|
|
for (int a = 0; a < bvh->totnode; ++a)
|
2012-12-30 18:31:31 +00:00
|
|
|
BKE_pbvh_node_mark_rebuild_draw(&bvh->nodes[a]);
|
2012-11-14 08:05:40 +00:00
|
|
|
}
|
2010-06-02 18:04:31 +00:00
|
|
|
}
|
|
|
|
|
2012-12-30 18:26:11 +00:00
|
|
|
/* Get the node's displacement layer, creating it if necessary */
|
2012-12-30 18:31:31 +00:00
|
|
|
float *BKE_pbvh_node_layer_disp_get(PBVH *bvh, PBVHNode *node)
|
2012-12-30 18:26:11 +00:00
|
|
|
{
|
|
|
|
if (!node->layer_disp) {
|
|
|
|
int totvert = 0;
|
2012-12-30 18:31:31 +00:00
|
|
|
BKE_pbvh_node_num_verts(bvh, node, &totvert, NULL);
|
2012-12-30 18:26:11 +00:00
|
|
|
node->layer_disp = MEM_callocN(sizeof(float) * totvert, "layer disp");
|
|
|
|
}
|
|
|
|
return node->layer_disp;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If the node has a displacement layer, free it and set to null */
|
2012-12-30 18:31:31 +00:00
|
|
|
void BKE_pbvh_node_layer_disp_free(PBVHNode *node)
|
2012-12-30 18:26:11 +00:00
|
|
|
{
|
|
|
|
if (node->layer_disp) {
|
|
|
|
MEM_freeN(node->layer_disp);
|
|
|
|
node->layer_disp = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-26 07:29:01 +00:00
|
|
|
float (*BKE_pbvh_get_vertCos(PBVH *pbvh))[3]
|
2010-06-21 20:10:59 +00:00
|
|
|
{
|
2012-05-11 08:05:47 +00:00
|
|
|
float (*vertCos)[3] = NULL;
|
2010-06-21 20:10:59 +00:00
|
|
|
|
|
|
|
if (pbvh->verts) {
|
2012-05-11 08:05:47 +00:00
|
|
|
MVert *mvert = pbvh->verts;
|
2010-06-21 20:10:59 +00:00
|
|
|
|
2012-12-30 18:31:31 +00:00
|
|
|
vertCos = MEM_callocN(3 * pbvh->totvert * sizeof(float), "BKE_pbvh_get_vertCoords");
|
2015-11-25 19:49:31 -05:00
|
|
|
float *co = (float *)vertCos;
|
2010-06-21 20:10:59 +00:00
|
|
|
|
2015-11-25 19:49:31 -05:00
|
|
|
for (int a = 0; a < pbvh->totvert; a++, mvert++, co += 3) {
|
2010-06-21 20:10:59 +00:00
|
|
|
copy_v3_v3(co, mvert->co);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return vertCos;
|
|
|
|
}
|
|
|
|
|
2018-06-08 15:42:37 +02:00
|
|
|
void BKE_pbvh_apply_vertCos(PBVH *pbvh, float (*vertCos)[3], const int totvert)
|
2010-06-21 20:10:59 +00:00
|
|
|
{
|
2018-06-08 15:42:37 +02:00
|
|
|
if (totvert != pbvh->totvert) {
|
|
|
|
BLI_assert(!"PBVH: Given deforming vcos number does not natch PBVH vertex number!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-06-21 20:10:59 +00:00
|
|
|
if (!pbvh->deformed) {
|
|
|
|
if (pbvh->verts) {
|
|
|
|
/* if pbvh is not already deformed, verts/faces points to the */
|
|
|
|
/* original data and applying new coords to this arrays would lead to */
|
|
|
|
/* unneeded deformation -- duplicate verts/faces to avoid this */
|
|
|
|
|
2015-07-17 03:36:03 +10:00
|
|
|
pbvh->verts = MEM_dupallocN(pbvh->verts);
|
2016-01-04 17:23:39 +01:00
|
|
|
/* No need to dupalloc pbvh->looptri, this one is 'totally owned' by pbvh, it's never some mesh data. */
|
2010-06-21 20:10:59 +00:00
|
|
|
|
2015-11-25 19:49:31 -05:00
|
|
|
pbvh->deformed = true;
|
2010-06-21 20:10:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pbvh->verts) {
|
2012-05-11 08:05:47 +00:00
|
|
|
MVert *mvert = pbvh->verts;
|
2010-06-21 20:10:59 +00:00
|
|
|
/* copy new verts coords */
|
2015-11-25 19:49:31 -05:00
|
|
|
for (int a = 0; a < pbvh->totvert; ++a, ++mvert) {
|
2016-02-13 17:58:44 +11:00
|
|
|
/* no need for float comparison here (memory is exactly equal or not) */
|
|
|
|
if (memcmp(mvert->co, vertCos[a], sizeof(float[3])) != 0) {
|
|
|
|
copy_v3_v3(mvert->co, vertCos[a]);
|
|
|
|
mvert->flag |= ME_VERT_PBVH_UPDATE;
|
|
|
|
}
|
2010-06-21 20:10:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* coordinates are new -- normals should also be updated */
|
2015-07-17 03:36:03 +10:00
|
|
|
BKE_mesh_calc_normals_looptri(
|
|
|
|
pbvh->verts, pbvh->totvert,
|
|
|
|
pbvh->mloop,
|
|
|
|
pbvh->looptri, pbvh->totprim,
|
|
|
|
NULL);
|
2011-01-31 20:02:51 +00:00
|
|
|
|
2015-11-25 19:49:31 -05:00
|
|
|
for (int a = 0; a < pbvh->totnode; ++a)
|
2012-12-30 18:31:31 +00:00
|
|
|
BKE_pbvh_node_mark_update(&pbvh->nodes[a]);
|
2011-01-31 20:02:51 +00:00
|
|
|
|
2012-12-30 18:31:31 +00:00
|
|
|
BKE_pbvh_update(pbvh, PBVH_UpdateBB, NULL);
|
|
|
|
BKE_pbvh_update(pbvh, PBVH_UpdateOriginalBB, NULL);
|
2011-01-31 20:02:51 +00:00
|
|
|
|
2010-06-21 20:10:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-03 18:55:59 +11:00
|
|
|
bool BKE_pbvh_isDeformed(PBVH *pbvh)
|
2010-06-21 20:10:59 +00:00
|
|
|
{
|
|
|
|
return pbvh->deformed;
|
|
|
|
}
|
2010-07-14 14:11:03 +00:00
|
|
|
/* Proxies */
|
|
|
|
|
2012-12-30 18:31:31 +00:00
|
|
|
PBVHProxyNode *BKE_pbvh_node_add_proxy(PBVH *bvh, PBVHNode *node)
|
2010-07-14 14:11:03 +00:00
|
|
|
{
|
|
|
|
int index, totverts;
|
|
|
|
|
2016-01-26 14:30:44 +01:00
|
|
|
index = node->proxy_count;
|
2010-07-14 14:11:03 +00:00
|
|
|
|
2016-01-26 14:30:44 +01:00
|
|
|
node->proxy_count++;
|
2010-07-14 14:11:03 +00:00
|
|
|
|
2016-01-26 14:30:44 +01:00
|
|
|
if (node->proxies)
|
|
|
|
node->proxies = MEM_reallocN(node->proxies, node->proxy_count * sizeof(PBVHProxyNode));
|
|
|
|
else
|
|
|
|
node->proxies = MEM_mallocN(sizeof(PBVHProxyNode), "PBVHNodeProxy");
|
2010-07-14 14:11:03 +00:00
|
|
|
|
2016-01-26 14:30:44 +01:00
|
|
|
BKE_pbvh_node_num_verts(bvh, node, &totverts, NULL);
|
|
|
|
node->proxies[index].co = MEM_callocN(sizeof(float[3]) * totverts, "PBVHNodeProxy.co");
|
2010-07-14 14:11:03 +00:00
|
|
|
|
|
|
|
return node->proxies + index;
|
|
|
|
}
|
|
|
|
|
2012-12-30 18:31:31 +00:00
|
|
|
void BKE_pbvh_node_free_proxies(PBVHNode *node)
|
2010-07-14 14:11:03 +00:00
|
|
|
{
|
2016-01-26 14:30:44 +01:00
|
|
|
for (int p = 0; p < node->proxy_count; p++) {
|
|
|
|
MEM_freeN(node->proxies[p].co);
|
|
|
|
node->proxies[p].co = NULL;
|
|
|
|
}
|
2010-07-14 14:11:03 +00:00
|
|
|
|
2016-01-26 14:30:44 +01:00
|
|
|
MEM_freeN(node->proxies);
|
|
|
|
node->proxies = NULL;
|
2010-07-14 14:11:03 +00:00
|
|
|
|
2016-01-26 14:30:44 +01:00
|
|
|
node->proxy_count = 0;
|
2010-07-14 14:11:03 +00:00
|
|
|
}
|
|
|
|
|
2012-12-30 18:31:31 +00:00
|
|
|
void BKE_pbvh_gather_proxies(PBVH *pbvh, PBVHNode ***r_array, int *r_tot)
|
2010-07-14 14:11:03 +00:00
|
|
|
{
|
2015-11-25 19:49:31 -05:00
|
|
|
PBVHNode **array = NULL;
|
2012-05-11 08:05:47 +00:00
|
|
|
int tot = 0, space = 0;
|
2010-07-14 14:11:03 +00:00
|
|
|
|
2015-11-25 19:49:31 -05:00
|
|
|
for (int n = 0; n < pbvh->totnode; n++) {
|
|
|
|
PBVHNode *node = pbvh->nodes + n;
|
2010-07-14 14:11:03 +00:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (node->proxy_count > 0) {
|
|
|
|
if (tot == space) {
|
2010-07-14 14:11:03 +00:00
|
|
|
/* resize array if needed */
|
2012-05-11 08:05:47 +00:00
|
|
|
space = (tot == 0) ? 32 : space * 2;
|
2013-08-03 18:05:30 +00:00
|
|
|
array = MEM_recallocN_id(array, sizeof(PBVHNode *) * space, __func__);
|
2010-07-14 14:11:03 +00:00
|
|
|
}
|
|
|
|
|
2012-05-11 08:05:47 +00:00
|
|
|
array[tot] = node;
|
2010-07-14 14:11:03 +00:00
|
|
|
tot++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (tot == 0 && array) {
|
2010-07-14 14:11:03 +00:00
|
|
|
MEM_freeN(array);
|
2012-05-11 08:05:47 +00:00
|
|
|
array = NULL;
|
2010-07-14 14:11:03 +00:00
|
|
|
}
|
|
|
|
|
2012-05-11 08:05:47 +00:00
|
|
|
*r_array = array;
|
|
|
|
*r_tot = tot;
|
2010-07-14 14:11:03 +00:00
|
|
|
}
|
2012-02-22 22:37:01 +00:00
|
|
|
|
|
|
|
void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node,
|
2012-05-11 08:05:47 +00:00
|
|
|
PBVHVertexIter *vi, int mode)
|
2012-02-22 22:37:01 +00:00
|
|
|
{
|
2012-05-10 20:33:09 +00:00
|
|
|
struct CCGElem **grids;
|
2012-02-22 22:37:01 +00:00
|
|
|
struct MVert *verts;
|
2015-07-12 03:49:47 +10:00
|
|
|
const int *vert_indices;
|
|
|
|
int *grid_indices;
|
2012-02-22 22:37:01 +00:00
|
|
|
int totgrid, gridsize, uniq_verts, totvert;
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2013-08-07 03:55:21 +00:00
|
|
|
vi->grid = NULL;
|
|
|
|
vi->no = NULL;
|
|
|
|
vi->fno = NULL;
|
|
|
|
vi->mvert = NULL;
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2015-05-27 19:52:12 +02:00
|
|
|
BKE_pbvh_node_get_grids(bvh, node, &grid_indices, &totgrid, NULL, &gridsize, &grids);
|
2012-12-30 18:31:31 +00:00
|
|
|
BKE_pbvh_node_num_verts(bvh, node, &uniq_verts, &totvert);
|
|
|
|
BKE_pbvh_node_get_verts(bvh, node, &vert_indices, &verts);
|
2012-05-10 20:33:09 +00:00
|
|
|
vi->key = &bvh->gridkey;
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2012-05-11 08:05:47 +00:00
|
|
|
vi->grids = grids;
|
|
|
|
vi->grid_indices = grid_indices;
|
|
|
|
vi->totgrid = (grids) ? totgrid : 1;
|
|
|
|
vi->gridsize = gridsize;
|
2018-06-17 17:05:51 +02:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (mode == PBVH_ITER_ALL)
|
2012-02-22 22:37:01 +00:00
|
|
|
vi->totvert = totvert;
|
|
|
|
else
|
2012-05-11 08:05:47 +00:00
|
|
|
vi->totvert = uniq_verts;
|
|
|
|
vi->vert_indices = vert_indices;
|
|
|
|
vi->mverts = verts;
|
2012-03-14 06:32:25 +00:00
|
|
|
|
2012-12-30 18:28:36 +00:00
|
|
|
if (bvh->type == PBVH_BMESH) {
|
2013-08-25 20:03:45 +00:00
|
|
|
BLI_gsetIterator_init(&vi->bm_unique_verts, node->bm_unique_verts);
|
|
|
|
BLI_gsetIterator_init(&vi->bm_other_verts, node->bm_other_verts);
|
2012-12-30 18:28:36 +00:00
|
|
|
vi->bm_vdata = &bvh->bm->vdata;
|
2013-08-27 20:39:08 +00:00
|
|
|
vi->cd_vert_mask_offset = CustomData_get_offset(vi->bm_vdata, CD_PAINT_MASK);
|
2012-12-30 18:28:36 +00:00
|
|
|
}
|
|
|
|
|
2012-05-11 08:05:47 +00:00
|
|
|
vi->gh = NULL;
|
2012-03-24 06:18:31 +00:00
|
|
|
if (vi->grids && mode == PBVH_ITER_UNIQUE)
|
2012-05-11 08:05:47 +00:00
|
|
|
vi->grid_hidden = bvh->grid_hidden;
|
2012-05-10 20:33:45 +00:00
|
|
|
|
2012-05-11 08:05:47 +00:00
|
|
|
vi->mask = NULL;
|
2012-12-30 18:28:36 +00:00
|
|
|
if (bvh->type == PBVH_FACES)
|
2012-05-11 08:05:47 +00:00
|
|
|
vi->vmask = CustomData_get_layer(bvh->vdata, CD_PAINT_MASK);
|
2012-02-22 22:37:01 +00:00
|
|
|
}
|
2012-10-22 17:33:53 +00:00
|
|
|
|
2017-05-12 17:54:14 +02:00
|
|
|
bool pbvh_has_mask(PBVH *bvh)
|
2012-10-22 17:33:53 +00:00
|
|
|
{
|
2014-04-02 17:33:47 +03:00
|
|
|
switch (bvh->type) {
|
|
|
|
case PBVH_GRIDS:
|
2017-05-12 17:54:14 +02:00
|
|
|
return (bvh->gridkey.has_mask != 0);
|
2014-04-02 17:33:47 +03:00
|
|
|
case PBVH_FACES:
|
2017-05-12 17:54:14 +02:00
|
|
|
return (bvh->vdata && CustomData_get_layer(bvh->vdata,
|
|
|
|
CD_PAINT_MASK));
|
2014-04-02 17:33:47 +03:00
|
|
|
case PBVH_BMESH:
|
2017-05-12 17:54:14 +02:00
|
|
|
return (bvh->bm && (CustomData_get_offset(&bvh->bm->vdata, CD_PAINT_MASK) != -1));
|
2014-04-02 17:33:47 +03:00
|
|
|
}
|
|
|
|
|
2017-05-12 17:54:14 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void pbvh_show_diffuse_color_set(PBVH *bvh, bool show_diffuse_color)
|
|
|
|
{
|
|
|
|
bvh->show_diffuse_color = !pbvh_has_mask(bvh) || show_diffuse_color;
|
2012-10-22 17:33:53 +00:00
|
|
|
}
|
2018-01-15 11:38:56 +01:00
|
|
|
|
|
|
|
void pbvh_show_mask_set(PBVH *bvh, bool show_mask)
|
|
|
|
{
|
|
|
|
bvh->show_mask = show_mask;
|
|
|
|
}
|