2023-05-31 16:19:06 +02:00
|
|
|
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
|
|
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
2021-02-21 17:57:03 -05:00
|
|
|
|
2023-11-13 10:42:29 +01:00
|
|
|
#include <iostream>
|
|
|
|
|
|
2022-08-31 09:09:01 -05:00
|
|
|
#include "BKE_attribute.hh"
|
2023-11-16 11:41:55 +01:00
|
|
|
#include "BKE_customdata.hh"
|
2024-04-18 13:52:20 +02:00
|
|
|
#include "BKE_lib_id.hh"
|
2023-03-12 22:29:15 +01:00
|
|
|
#include "BKE_mesh.hh"
|
2021-02-21 17:57:03 -05:00
|
|
|
|
|
|
|
|
#include "BLI_alloca.h"
|
2021-04-02 00:16:01 -05:00
|
|
|
#include "BLI_array.hh"
|
Cleanup: reduce amount of math-related includes
Using ClangBuildAnalyzer on the whole Blender build, it was pointing
out that BLI_math.h is the heaviest "header hub" (i.e. non tiny file
that is included a lot).
However, there's very little (actually zero) source files in Blender
that need "all the math" (base, colors, vectors, matrices,
quaternions, intersection, interpolation, statistics, solvers and
time). A common use case is source files needing just vectors, or
just vectors & matrices, or just colors etc. Actually, 181 files
were including the whole math thing without needing it at all.
This change removes BLI_math.h completely, and instead in all the
places that need it, includes BLI_math_vector.h or BLI_math_color.h
and so on.
Change from that:
- BLI_math_color.h was included 1399 times -> now 408 (took 114.0sec
to parse -> now 36.3sec)
- BLI_simd.h 1403 -> 418 (109.7sec -> 34.9sec).
Full rebuild of Blender (Apple M1, Xcode, RelWithDebInfo) is not
affected much (342sec -> 334sec). Most of benefit would be when
someone's changing BLI_simd.h or BLI_math_color.h or similar files,
that now there's 3x fewer files result in a recompile.
Pull Request #110944
2023-08-09 11:39:20 +03:00
|
|
|
#include "BLI_math_geom.h"
|
|
|
|
|
#include "BLI_math_matrix.h"
|
2023-02-06 21:25:45 +01:00
|
|
|
#include "BLI_math_matrix.hh"
|
Cleanup: reduce amount of math-related includes
Using ClangBuildAnalyzer on the whole Blender build, it was pointing
out that BLI_math.h is the heaviest "header hub" (i.e. non tiny file
that is included a lot).
However, there's very little (actually zero) source files in Blender
that need "all the math" (base, colors, vectors, matrices,
quaternions, intersection, interpolation, statistics, solvers and
time). A common use case is source files needing just vectors, or
just vectors & matrices, or just colors etc. Actually, 181 files
were including the whole math thing without needing it at all.
This change removes BLI_math.h completely, and instead in all the
places that need it, includes BLI_math_vector.h or BLI_math_color.h
and so on.
Change from that:
- BLI_math_color.h was included 1399 times -> now 408 (took 114.0sec
to parse -> now 36.3sec)
- BLI_simd.h 1403 -> 418 (109.7sec -> 34.9sec).
Full rebuild of Blender (Apple M1, Xcode, RelWithDebInfo) is not
affected much (342sec -> 334sec). Most of benefit would be when
someone's changing BLI_simd.h or BLI_math_color.h or similar files,
that now there's 3x fewer files result in a recompile.
Pull Request #110944
2023-08-09 11:39:20 +03:00
|
|
|
#include "BLI_math_vector.h"
|
2021-02-21 17:57:03 -05:00
|
|
|
#include "BLI_mesh_boolean.hh"
|
|
|
|
|
#include "BLI_mesh_intersect.hh"
|
|
|
|
|
#include "BLI_span.hh"
|
2023-09-01 21:37:11 +02:00
|
|
|
#include "BLI_string.h"
|
2021-07-05 18:09:36 -04:00
|
|
|
#include "BLI_task.hh"
|
2022-08-31 09:09:01 -05:00
|
|
|
#include "BLI_virtual_array.hh"
|
2021-02-21 17:57:03 -05:00
|
|
|
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
#include "DNA_node_types.h"
|
|
|
|
|
|
2024-03-12 07:00:33 -04:00
|
|
|
#include "GEO_mesh_boolean.hh"
|
2024-03-11 18:17:57 +01:00
|
|
|
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
#include "bmesh.hh"
|
|
|
|
|
#include "bmesh_tools.hh"
|
|
|
|
|
#include "tools/bmesh_boolean.hh"
|
|
|
|
|
#include "tools/bmesh_intersect.hh"
|
|
|
|
|
|
|
|
|
|
namespace blender::geometry::boolean {
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Mesh Arrangements (Old Exact Boolean)
|
|
|
|
|
* \{ */
|
2021-02-21 17:57:03 -05:00
|
|
|
|
|
|
|
|
#ifdef WITH_GMP
|
|
|
|
|
|
|
|
|
|
constexpr int estimated_max_facelen = 100; /* Used for initial size of some Vectors. */
|
|
|
|
|
|
|
|
|
|
/* Snap entries that are near 0 or 1 or -1 to those values.
|
|
|
|
|
* Sometimes Blender's rotation matrices for multiples of 90 degrees have
|
|
|
|
|
* tiny numbers where there should be zeros. That messes makes some things
|
|
|
|
|
* every so slightly non-coplanar when users expect coplanarity,
|
|
|
|
|
* so this is a hack to clean up such matrices.
|
|
|
|
|
* Would be better to change the transformation code itself.
|
|
|
|
|
*/
|
2022-04-27 18:52:56 -05:00
|
|
|
static float4x4 clean_transform(const float4x4 &mat)
|
2021-02-21 17:57:03 -05:00
|
|
|
{
|
Geometry Nodes: Improve speed of boolean node, use multi-input socket
This commit improves the performance of the node by up to 40% in some
cases when there are only two input meshes, mainly by skipping the
conversion to and from BMesh.
When there are more than two input meshes (note the distinction from
"Geometries", a geometry set can have many mesh instances), the
performance is actually worse, since boolean currently always does
self intersection in that case. Theoretically this could be improved
in the boolean code, or another option is automatically realizing
instances for each input geometry set.
Another improvement is using multi-input sockets for the inputs, which
removes the need to have a separate boolean node for every operation,
which can hopefully simplify some node trees.
The changes necessary for transforms in `mesh_boolean_convert.cc` are
somewhat subtle; they come from the fact that the collecting the
geometry set instances already gives transforms in the local space
of the modifier object. There is also a very small amount of cleanup
to those lines, using `float4x4::identity()`.
This commit also fixes T87078, where overlapping difference meshes
makes the operation not work, though I haven't investigated why.
Differential Revision: https://developer.blender.org/D10599
2021-04-01 15:00:47 -05:00
|
|
|
float4x4 cleaned;
|
2021-02-21 17:57:03 -05:00
|
|
|
const float fuzz = 1e-6f;
|
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
|
|
|
for (int j = 0; j < 4; j++) {
|
2023-02-06 21:25:45 +01:00
|
|
|
float f = mat[i][j];
|
2021-02-21 17:57:03 -05:00
|
|
|
if (fabsf(f) <= fuzz) {
|
|
|
|
|
f = 0.0f;
|
|
|
|
|
}
|
|
|
|
|
else if (fabsf(f - 1.0f) <= fuzz) {
|
|
|
|
|
f = 1.0f;
|
|
|
|
|
}
|
|
|
|
|
else if (fabsf(f + 1.0f) <= fuzz) {
|
|
|
|
|
f = -1.0f;
|
|
|
|
|
}
|
2023-02-06 21:25:45 +01:00
|
|
|
cleaned[i][j] = f;
|
2021-02-21 17:57:03 -05:00
|
|
|
}
|
|
|
|
|
}
|
Geometry Nodes: Improve speed of boolean node, use multi-input socket
This commit improves the performance of the node by up to 40% in some
cases when there are only two input meshes, mainly by skipping the
conversion to and from BMesh.
When there are more than two input meshes (note the distinction from
"Geometries", a geometry set can have many mesh instances), the
performance is actually worse, since boolean currently always does
self intersection in that case. Theoretically this could be improved
in the boolean code, or another option is automatically realizing
instances for each input geometry set.
Another improvement is using multi-input sockets for the inputs, which
removes the need to have a separate boolean node for every operation,
which can hopefully simplify some node trees.
The changes necessary for transforms in `mesh_boolean_convert.cc` are
somewhat subtle; they come from the fact that the collecting the
geometry set instances already gives transforms in the local space
of the modifier object. There is also a very small amount of cleanup
to those lines, using `float4x4::identity()`.
This commit also fixes T87078, where overlapping difference meshes
makes the operation not work, though I haven't investigated why.
Differential Revision: https://developer.blender.org/D10599
2021-04-01 15:00:47 -05:00
|
|
|
return cleaned;
|
2021-02-21 17:57:03 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* `MeshesToIMeshInfo` keeps track of information used when combining a number
|
|
|
|
|
* of `Mesh`es into a single `IMesh` for doing boolean on.
|
|
|
|
|
* Mostly this means keeping track of the index offsets for various mesh elements. */
|
|
|
|
|
class MeshesToIMeshInfo {
|
|
|
|
|
public:
|
|
|
|
|
/* The input meshes, */
|
|
|
|
|
Span<const Mesh *> meshes;
|
|
|
|
|
/* Numbering the vertices of the meshes in order of meshes,
|
|
|
|
|
* at what offset does the vertex range for mesh[i] start? */
|
|
|
|
|
Array<int> mesh_vert_offset;
|
|
|
|
|
/* Similarly for edges of meshes. */
|
|
|
|
|
Array<int> mesh_edge_offset;
|
2023-07-24 22:06:55 +02:00
|
|
|
/* Similarly for faces of meshes. */
|
|
|
|
|
Array<int> mesh_face_offset;
|
2021-02-21 17:57:03 -05:00
|
|
|
/* For each Mesh vertex in all the meshes (with concatenated indexing),
|
2021-02-24 15:53:03 +11:00
|
|
|
* what is the IMesh Vert* allocated for it in the input IMesh? */
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
Array<const meshintersect::Vert *> mesh_to_imesh_vert;
|
2023-07-24 22:06:55 +02:00
|
|
|
/* Similarly for each Mesh face. */
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
Array<meshintersect::Face *> mesh_to_imesh_face;
|
2021-02-21 17:57:03 -05:00
|
|
|
/* Transformation matrix to transform a coordinate in the corresponding
|
|
|
|
|
* Mesh to the local space of the first Mesh. */
|
Geometry Nodes: Improve speed of boolean node, use multi-input socket
This commit improves the performance of the node by up to 40% in some
cases when there are only two input meshes, mainly by skipping the
conversion to and from BMesh.
When there are more than two input meshes (note the distinction from
"Geometries", a geometry set can have many mesh instances), the
performance is actually worse, since boolean currently always does
self intersection in that case. Theoretically this could be improved
in the boolean code, or another option is automatically realizing
instances for each input geometry set.
Another improvement is using multi-input sockets for the inputs, which
removes the need to have a separate boolean node for every operation,
which can hopefully simplify some node trees.
The changes necessary for transforms in `mesh_boolean_convert.cc` are
somewhat subtle; they come from the fact that the collecting the
geometry set instances already gives transforms in the local space
of the modifier object. There is also a very small amount of cleanup
to those lines, using `float4x4::identity()`.
This commit also fixes T87078, where overlapping difference meshes
makes the operation not work, though I haven't investigated why.
Differential Revision: https://developer.blender.org/D10599
2021-04-01 15:00:47 -05:00
|
|
|
Array<float4x4> to_target_transform;
|
2021-07-25 13:29:45 -04:00
|
|
|
/* For each input mesh, whether or not their transform is negative. */
|
|
|
|
|
Array<bool> has_negative_transform;
|
2021-03-14 11:39:56 -04:00
|
|
|
/* For each input mesh, how to remap the material slot numbers to
|
|
|
|
|
* the material slots in the first mesh. */
|
2021-04-02 00:16:01 -05:00
|
|
|
Span<Array<short>> material_remaps;
|
2021-02-21 17:57:03 -05:00
|
|
|
/* Total number of input mesh vertices. */
|
|
|
|
|
int tot_meshes_verts;
|
|
|
|
|
/* Total number of input mesh edges. */
|
|
|
|
|
int tot_meshes_edges;
|
|
|
|
|
/* Total number of input mesh polys. */
|
|
|
|
|
int tot_meshes_polys;
|
|
|
|
|
|
|
|
|
|
int input_mesh_for_imesh_vert(int imesh_v) const;
|
|
|
|
|
int input_mesh_for_imesh_edge(int imesh_e) const;
|
|
|
|
|
int input_mesh_for_imesh_face(int imesh_f) const;
|
2023-07-24 22:06:55 +02:00
|
|
|
const IndexRange input_face_for_orig_index(int orig_index,
|
|
|
|
|
const Mesh **r_orig_mesh,
|
|
|
|
|
int *r_orig_mesh_index,
|
|
|
|
|
int *r_index_in_orig_mesh) const;
|
Mesh: Move positions to a generic attribute
**Changes**
As described in T93602, this patch removes all use of the `MVert`
struct, replacing it with a generic named attribute with the name
`"position"`, consistent with other geometry types.
Variable names have been changed from `verts` to `positions`, to align
with the attribute name and the more generic design (positions are not
vertices, they are just an attribute stored on the point domain).
This change is made possible by previous commits that moved all other
data out of `MVert` to runtime data or other generic attributes. What
remains is mostly a simple type change. Though, the type still shows up
859 times, so the patch is quite large.
One compromise is that now `CD_MASK_BAREMESH` now contains
`CD_PROP_FLOAT3`. With the general move towards generic attributes
over custom data types, we are removing use of these type masks anyway.
**Benefits**
The most obvious benefit is reduced memory usage and the benefits
that brings in memory-bound situations. `float3` is only 3 bytes, in
comparison to `MVert` which was 4. When there are millions of vertices
this starts to matter more.
The other benefits come from using a more generic type. Instead of
writing algorithms specifically for `MVert`, code can just use arrays
of vectors. This will allow eliminating many temporary arrays or
wrappers used to extract positions.
Many possible improvements aren't implemented in this patch, though
I did switch simplify or remove the process of creating temporary
position arrays in a few places.
The design clarity that "positions are just another attribute" brings
allows removing explicit copying of vertices in some procedural
operations-- they are just processed like most other attributes.
**Performance**
This touches so many areas that it's hard to benchmark exhaustively,
but I observed some areas as examples.
* The mesh line node with 4 million count was 1.5x (8ms to 12ms) faster.
* The Spring splash screen went from ~4.3 to ~4.5 fps.
* The subdivision surface modifier/node was slightly faster
RNA access through Python may be slightly slower, since now we need
a name lookup instead of just a custom data type lookup for each index.
**Future Improvements**
* Remove uses of "vert_coords" functions:
* `BKE_mesh_vert_coords_alloc`
* `BKE_mesh_vert_coords_get`
* `BKE_mesh_vert_coords_apply{_with_mat4}`
* Remove more hidden copying of positions
* General simplification now possible in many areas
* Convert more code to C++ to use `float3` instead of `float[3]`
* Currently `reinterpret_cast` is used for those C-API functions
Differential Revision: https://developer.blender.org/D15982
2023-01-10 00:10:43 -05:00
|
|
|
void input_mvert_for_orig_index(int orig_index,
|
|
|
|
|
const Mesh **r_orig_mesh,
|
|
|
|
|
int *r_index_in_orig_mesh) const;
|
2023-03-01 14:13:05 +01:00
|
|
|
void input_medge_for_orig_index(int orig_index,
|
|
|
|
|
const Mesh **r_orig_mesh,
|
|
|
|
|
int *r_index_in_orig_mesh) const;
|
2021-02-21 17:57:03 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* Given an index `imesh_v` in the `IMesh`, return the index of the
|
Mesh: Move positions to a generic attribute
**Changes**
As described in T93602, this patch removes all use of the `MVert`
struct, replacing it with a generic named attribute with the name
`"position"`, consistent with other geometry types.
Variable names have been changed from `verts` to `positions`, to align
with the attribute name and the more generic design (positions are not
vertices, they are just an attribute stored on the point domain).
This change is made possible by previous commits that moved all other
data out of `MVert` to runtime data or other generic attributes. What
remains is mostly a simple type change. Though, the type still shows up
859 times, so the patch is quite large.
One compromise is that now `CD_MASK_BAREMESH` now contains
`CD_PROP_FLOAT3`. With the general move towards generic attributes
over custom data types, we are removing use of these type masks anyway.
**Benefits**
The most obvious benefit is reduced memory usage and the benefits
that brings in memory-bound situations. `float3` is only 3 bytes, in
comparison to `MVert` which was 4. When there are millions of vertices
this starts to matter more.
The other benefits come from using a more generic type. Instead of
writing algorithms specifically for `MVert`, code can just use arrays
of vectors. This will allow eliminating many temporary arrays or
wrappers used to extract positions.
Many possible improvements aren't implemented in this patch, though
I did switch simplify or remove the process of creating temporary
position arrays in a few places.
The design clarity that "positions are just another attribute" brings
allows removing explicit copying of vertices in some procedural
operations-- they are just processed like most other attributes.
**Performance**
This touches so many areas that it's hard to benchmark exhaustively,
but I observed some areas as examples.
* The mesh line node with 4 million count was 1.5x (8ms to 12ms) faster.
* The Spring splash screen went from ~4.3 to ~4.5 fps.
* The subdivision surface modifier/node was slightly faster
RNA access through Python may be slightly slower, since now we need
a name lookup instead of just a custom data type lookup for each index.
**Future Improvements**
* Remove uses of "vert_coords" functions:
* `BKE_mesh_vert_coords_alloc`
* `BKE_mesh_vert_coords_get`
* `BKE_mesh_vert_coords_apply{_with_mat4}`
* Remove more hidden copying of positions
* General simplification now possible in many areas
* Convert more code to C++ to use `float3` instead of `float[3]`
* Currently `reinterpret_cast` is used for those C-API functions
Differential Revision: https://developer.blender.org/D15982
2023-01-10 00:10:43 -05:00
|
|
|
* input `Mesh` that contained the vertex that it came from. */
|
2021-02-21 17:57:03 -05:00
|
|
|
int MeshesToIMeshInfo::input_mesh_for_imesh_vert(int imesh_v) const
|
|
|
|
|
{
|
2022-09-25 18:30:50 +10:00
|
|
|
int n = int(mesh_vert_offset.size());
|
2021-02-21 17:57:03 -05:00
|
|
|
for (int i = 0; i < n - 1; ++i) {
|
|
|
|
|
if (imesh_v < mesh_vert_offset[i + 1]) {
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return n - 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Given an index `imesh_e` used as an original index in the `IMesh`,
|
Mesh: Move positions to a generic attribute
**Changes**
As described in T93602, this patch removes all use of the `MVert`
struct, replacing it with a generic named attribute with the name
`"position"`, consistent with other geometry types.
Variable names have been changed from `verts` to `positions`, to align
with the attribute name and the more generic design (positions are not
vertices, they are just an attribute stored on the point domain).
This change is made possible by previous commits that moved all other
data out of `MVert` to runtime data or other generic attributes. What
remains is mostly a simple type change. Though, the type still shows up
859 times, so the patch is quite large.
One compromise is that now `CD_MASK_BAREMESH` now contains
`CD_PROP_FLOAT3`. With the general move towards generic attributes
over custom data types, we are removing use of these type masks anyway.
**Benefits**
The most obvious benefit is reduced memory usage and the benefits
that brings in memory-bound situations. `float3` is only 3 bytes, in
comparison to `MVert` which was 4. When there are millions of vertices
this starts to matter more.
The other benefits come from using a more generic type. Instead of
writing algorithms specifically for `MVert`, code can just use arrays
of vectors. This will allow eliminating many temporary arrays or
wrappers used to extract positions.
Many possible improvements aren't implemented in this patch, though
I did switch simplify or remove the process of creating temporary
position arrays in a few places.
The design clarity that "positions are just another attribute" brings
allows removing explicit copying of vertices in some procedural
operations-- they are just processed like most other attributes.
**Performance**
This touches so many areas that it's hard to benchmark exhaustively,
but I observed some areas as examples.
* The mesh line node with 4 million count was 1.5x (8ms to 12ms) faster.
* The Spring splash screen went from ~4.3 to ~4.5 fps.
* The subdivision surface modifier/node was slightly faster
RNA access through Python may be slightly slower, since now we need
a name lookup instead of just a custom data type lookup for each index.
**Future Improvements**
* Remove uses of "vert_coords" functions:
* `BKE_mesh_vert_coords_alloc`
* `BKE_mesh_vert_coords_get`
* `BKE_mesh_vert_coords_apply{_with_mat4}`
* Remove more hidden copying of positions
* General simplification now possible in many areas
* Convert more code to C++ to use `float3` instead of `float[3]`
* Currently `reinterpret_cast` is used for those C-API functions
Differential Revision: https://developer.blender.org/D15982
2023-01-10 00:10:43 -05:00
|
|
|
* return the index of the input `Mesh` that contained the vertex that it came from. */
|
2021-02-21 17:57:03 -05:00
|
|
|
int MeshesToIMeshInfo::input_mesh_for_imesh_edge(int imesh_e) const
|
|
|
|
|
{
|
2022-09-25 18:30:50 +10:00
|
|
|
int n = int(mesh_edge_offset.size());
|
2021-02-21 17:57:03 -05:00
|
|
|
for (int i = 0; i < n - 1; ++i) {
|
|
|
|
|
if (imesh_e < mesh_edge_offset[i + 1]) {
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return n - 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Given an index `imesh_f` in the `IMesh`, return the index of the
|
2023-07-24 22:06:55 +02:00
|
|
|
* input `Mesh` that contained the face that it came from. */
|
2021-02-21 17:57:03 -05:00
|
|
|
int MeshesToIMeshInfo::input_mesh_for_imesh_face(int imesh_f) const
|
|
|
|
|
{
|
2023-07-24 22:06:55 +02:00
|
|
|
int n = int(mesh_face_offset.size());
|
2021-02-21 17:57:03 -05:00
|
|
|
for (int i = 0; i < n - 1; ++i) {
|
2023-07-24 22:06:55 +02:00
|
|
|
if (imesh_f < mesh_face_offset[i + 1]) {
|
2021-02-21 17:57:03 -05:00
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return n - 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Given an index of an original face in the `IMesh`, find out the input
|
|
|
|
|
* `Mesh` that it came from and return it in `*r_orig_mesh`,
|
|
|
|
|
* and also return the index of that `Mesh` in `*r_orig_mesh_index`.
|
2023-07-24 22:06:55 +02:00
|
|
|
* Finally, return the index of the corresponding face in that `Mesh`
|
2021-02-21 17:57:03 -05:00
|
|
|
* in `*r_index_in_orig_mesh`. */
|
2023-07-24 22:06:55 +02:00
|
|
|
const IndexRange MeshesToIMeshInfo::input_face_for_orig_index(int orig_index,
|
|
|
|
|
const Mesh **r_orig_mesh,
|
|
|
|
|
int *r_orig_mesh_index,
|
|
|
|
|
int *r_index_in_orig_mesh) const
|
2021-02-21 17:57:03 -05:00
|
|
|
{
|
|
|
|
|
int orig_mesh_index = input_mesh_for_imesh_face(orig_index);
|
|
|
|
|
BLI_assert(0 <= orig_mesh_index && orig_mesh_index < meshes.size());
|
2023-12-08 16:40:06 -05:00
|
|
|
const Mesh *mesh = meshes[orig_mesh_index];
|
|
|
|
|
const OffsetIndices faces = mesh->faces();
|
2023-07-24 22:06:55 +02:00
|
|
|
int index_in_mesh = orig_index - mesh_face_offset[orig_mesh_index];
|
2023-12-08 16:40:06 -05:00
|
|
|
BLI_assert(0 <= index_in_mesh && index_in_mesh < mesh->faces_num);
|
2023-07-24 22:06:55 +02:00
|
|
|
const IndexRange face = faces[index_in_mesh];
|
2021-02-21 17:57:03 -05:00
|
|
|
if (r_orig_mesh) {
|
2023-12-08 16:40:06 -05:00
|
|
|
*r_orig_mesh = mesh;
|
2021-02-21 17:57:03 -05:00
|
|
|
}
|
|
|
|
|
if (r_orig_mesh_index) {
|
|
|
|
|
*r_orig_mesh_index = orig_mesh_index;
|
|
|
|
|
}
|
|
|
|
|
if (r_index_in_orig_mesh) {
|
|
|
|
|
*r_index_in_orig_mesh = index_in_mesh;
|
|
|
|
|
}
|
2023-07-24 22:06:55 +02:00
|
|
|
return face;
|
2021-02-21 17:57:03 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Given an index of an original vertex in the `IMesh`, find out the input
|
|
|
|
|
* `Mesh` that it came from and return it in `*r_orig_mesh`.
|
Mesh: Move positions to a generic attribute
**Changes**
As described in T93602, this patch removes all use of the `MVert`
struct, replacing it with a generic named attribute with the name
`"position"`, consistent with other geometry types.
Variable names have been changed from `verts` to `positions`, to align
with the attribute name and the more generic design (positions are not
vertices, they are just an attribute stored on the point domain).
This change is made possible by previous commits that moved all other
data out of `MVert` to runtime data or other generic attributes. What
remains is mostly a simple type change. Though, the type still shows up
859 times, so the patch is quite large.
One compromise is that now `CD_MASK_BAREMESH` now contains
`CD_PROP_FLOAT3`. With the general move towards generic attributes
over custom data types, we are removing use of these type masks anyway.
**Benefits**
The most obvious benefit is reduced memory usage and the benefits
that brings in memory-bound situations. `float3` is only 3 bytes, in
comparison to `MVert` which was 4. When there are millions of vertices
this starts to matter more.
The other benefits come from using a more generic type. Instead of
writing algorithms specifically for `MVert`, code can just use arrays
of vectors. This will allow eliminating many temporary arrays or
wrappers used to extract positions.
Many possible improvements aren't implemented in this patch, though
I did switch simplify or remove the process of creating temporary
position arrays in a few places.
The design clarity that "positions are just another attribute" brings
allows removing explicit copying of vertices in some procedural
operations-- they are just processed like most other attributes.
**Performance**
This touches so many areas that it's hard to benchmark exhaustively,
but I observed some areas as examples.
* The mesh line node with 4 million count was 1.5x (8ms to 12ms) faster.
* The Spring splash screen went from ~4.3 to ~4.5 fps.
* The subdivision surface modifier/node was slightly faster
RNA access through Python may be slightly slower, since now we need
a name lookup instead of just a custom data type lookup for each index.
**Future Improvements**
* Remove uses of "vert_coords" functions:
* `BKE_mesh_vert_coords_alloc`
* `BKE_mesh_vert_coords_get`
* `BKE_mesh_vert_coords_apply{_with_mat4}`
* Remove more hidden copying of positions
* General simplification now possible in many areas
* Convert more code to C++ to use `float3` instead of `float[3]`
* Currently `reinterpret_cast` is used for those C-API functions
Differential Revision: https://developer.blender.org/D15982
2023-01-10 00:10:43 -05:00
|
|
|
* Also find the index of the vertex in that `Mesh` and return it in
|
2021-02-21 17:57:03 -05:00
|
|
|
* `*r_index_in_orig_mesh`. */
|
Mesh: Move positions to a generic attribute
**Changes**
As described in T93602, this patch removes all use of the `MVert`
struct, replacing it with a generic named attribute with the name
`"position"`, consistent with other geometry types.
Variable names have been changed from `verts` to `positions`, to align
with the attribute name and the more generic design (positions are not
vertices, they are just an attribute stored on the point domain).
This change is made possible by previous commits that moved all other
data out of `MVert` to runtime data or other generic attributes. What
remains is mostly a simple type change. Though, the type still shows up
859 times, so the patch is quite large.
One compromise is that now `CD_MASK_BAREMESH` now contains
`CD_PROP_FLOAT3`. With the general move towards generic attributes
over custom data types, we are removing use of these type masks anyway.
**Benefits**
The most obvious benefit is reduced memory usage and the benefits
that brings in memory-bound situations. `float3` is only 3 bytes, in
comparison to `MVert` which was 4. When there are millions of vertices
this starts to matter more.
The other benefits come from using a more generic type. Instead of
writing algorithms specifically for `MVert`, code can just use arrays
of vectors. This will allow eliminating many temporary arrays or
wrappers used to extract positions.
Many possible improvements aren't implemented in this patch, though
I did switch simplify or remove the process of creating temporary
position arrays in a few places.
The design clarity that "positions are just another attribute" brings
allows removing explicit copying of vertices in some procedural
operations-- they are just processed like most other attributes.
**Performance**
This touches so many areas that it's hard to benchmark exhaustively,
but I observed some areas as examples.
* The mesh line node with 4 million count was 1.5x (8ms to 12ms) faster.
* The Spring splash screen went from ~4.3 to ~4.5 fps.
* The subdivision surface modifier/node was slightly faster
RNA access through Python may be slightly slower, since now we need
a name lookup instead of just a custom data type lookup for each index.
**Future Improvements**
* Remove uses of "vert_coords" functions:
* `BKE_mesh_vert_coords_alloc`
* `BKE_mesh_vert_coords_get`
* `BKE_mesh_vert_coords_apply{_with_mat4}`
* Remove more hidden copying of positions
* General simplification now possible in many areas
* Convert more code to C++ to use `float3` instead of `float[3]`
* Currently `reinterpret_cast` is used for those C-API functions
Differential Revision: https://developer.blender.org/D15982
2023-01-10 00:10:43 -05:00
|
|
|
void MeshesToIMeshInfo::input_mvert_for_orig_index(int orig_index,
|
|
|
|
|
const Mesh **r_orig_mesh,
|
|
|
|
|
int *r_index_in_orig_mesh) const
|
2021-02-21 17:57:03 -05:00
|
|
|
{
|
|
|
|
|
int orig_mesh_index = input_mesh_for_imesh_vert(orig_index);
|
|
|
|
|
BLI_assert(0 <= orig_mesh_index && orig_mesh_index < meshes.size());
|
2023-12-08 16:40:06 -05:00
|
|
|
const Mesh *mesh = meshes[orig_mesh_index];
|
2021-02-21 17:57:03 -05:00
|
|
|
int index_in_mesh = orig_index - mesh_vert_offset[orig_mesh_index];
|
2023-12-20 02:21:48 +01:00
|
|
|
BLI_assert(0 <= index_in_mesh && index_in_mesh < mesh->verts_num);
|
2021-02-21 17:57:03 -05:00
|
|
|
if (r_orig_mesh) {
|
2023-12-08 16:40:06 -05:00
|
|
|
*r_orig_mesh = mesh;
|
2021-02-21 17:57:03 -05:00
|
|
|
}
|
|
|
|
|
if (r_index_in_orig_mesh) {
|
|
|
|
|
*r_index_in_orig_mesh = index_in_mesh;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Similarly for edges. */
|
2023-03-01 14:13:05 +01:00
|
|
|
void MeshesToIMeshInfo::input_medge_for_orig_index(int orig_index,
|
|
|
|
|
const Mesh **r_orig_mesh,
|
|
|
|
|
int *r_index_in_orig_mesh) const
|
2021-02-21 17:57:03 -05:00
|
|
|
{
|
|
|
|
|
int orig_mesh_index = input_mesh_for_imesh_edge(orig_index);
|
|
|
|
|
BLI_assert(0 <= orig_mesh_index && orig_mesh_index < meshes.size());
|
2023-12-08 16:40:06 -05:00
|
|
|
const Mesh *mesh = meshes[orig_mesh_index];
|
2021-02-21 17:57:03 -05:00
|
|
|
int index_in_mesh = orig_index - mesh_edge_offset[orig_mesh_index];
|
2023-12-20 02:21:48 +01:00
|
|
|
BLI_assert(0 <= index_in_mesh && index_in_mesh < mesh->edges_num);
|
2021-02-21 17:57:03 -05:00
|
|
|
if (r_orig_mesh) {
|
2023-12-08 16:40:06 -05:00
|
|
|
*r_orig_mesh = mesh;
|
2021-02-21 17:57:03 -05:00
|
|
|
}
|
|
|
|
|
if (r_index_in_orig_mesh) {
|
|
|
|
|
*r_index_in_orig_mesh = index_in_mesh;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-09 18:47:10 +10:00
|
|
|
/**
|
|
|
|
|
* Convert all of the meshes in `meshes` to an `IMesh` and return that.
|
2021-02-21 17:57:03 -05:00
|
|
|
* All of the coordinates are transformed into the local space of the
|
|
|
|
|
* first Mesh. To do this transformation, we also need the transformation
|
|
|
|
|
* obmats corresponding to the Meshes, so they are in the `obmats` argument.
|
|
|
|
|
* The 'original' indexes in the IMesh are the indexes you get by
|
2023-07-24 22:06:55 +02:00
|
|
|
* a scheme that offsets each vertex, edge, and face index by the sum of the
|
2021-02-21 17:57:03 -05:00
|
|
|
* vertices, edges, and polys in the preceding Meshes in the mesh span.
|
|
|
|
|
* The `*r_info class` is filled in with information needed to make the
|
|
|
|
|
* correspondence between the Mesh MVerts/MPolys and the IMesh Verts/Faces.
|
|
|
|
|
* All allocation of memory for the IMesh comes from `arena`.
|
|
|
|
|
*/
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
static meshintersect::IMesh meshes_to_imesh(Span<const Mesh *> meshes,
|
|
|
|
|
Span<float4x4> obmats,
|
|
|
|
|
Span<Array<short>> material_remaps,
|
|
|
|
|
const float4x4 &target_transform,
|
|
|
|
|
meshintersect::IMeshArena &arena,
|
|
|
|
|
MeshesToIMeshInfo *r_info)
|
2021-02-21 17:57:03 -05:00
|
|
|
{
|
|
|
|
|
int nmeshes = meshes.size();
|
|
|
|
|
BLI_assert(nmeshes > 0);
|
|
|
|
|
r_info->meshes = meshes;
|
|
|
|
|
r_info->tot_meshes_verts = 0;
|
|
|
|
|
r_info->tot_meshes_polys = 0;
|
|
|
|
|
int &totvert = r_info->tot_meshes_verts;
|
|
|
|
|
int &totedge = r_info->tot_meshes_edges;
|
2023-07-24 22:06:55 +02:00
|
|
|
int &faces_num = r_info->tot_meshes_polys;
|
2023-12-08 16:40:06 -05:00
|
|
|
for (const Mesh *mesh : meshes) {
|
2023-12-20 02:21:48 +01:00
|
|
|
totvert += mesh->verts_num;
|
|
|
|
|
totedge += mesh->edges_num;
|
2023-12-08 16:40:06 -05:00
|
|
|
faces_num += mesh->faces_num;
|
2021-02-21 17:57:03 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Estimate the number of vertices and faces in the boolean output,
|
|
|
|
|
* so that the memory arena can reserve some space. It is OK if these
|
|
|
|
|
* estimates are wrong. */
|
|
|
|
|
const int estimate_num_outv = 3 * totvert;
|
2023-07-24 22:06:55 +02:00
|
|
|
const int estimate_num_outf = 4 * faces_num;
|
2021-02-21 17:57:03 -05:00
|
|
|
arena.reserve(estimate_num_outv, estimate_num_outf);
|
2022-04-27 18:52:56 -05:00
|
|
|
r_info->mesh_to_imesh_vert.reinitialize(totvert);
|
2023-07-24 22:06:55 +02:00
|
|
|
r_info->mesh_to_imesh_face.reinitialize(faces_num);
|
2022-04-27 18:52:56 -05:00
|
|
|
r_info->mesh_vert_offset.reinitialize(nmeshes);
|
|
|
|
|
r_info->mesh_edge_offset.reinitialize(nmeshes);
|
2023-07-24 22:06:55 +02:00
|
|
|
r_info->mesh_face_offset.reinitialize(nmeshes);
|
2022-04-27 18:52:56 -05:00
|
|
|
r_info->to_target_transform.reinitialize(nmeshes);
|
|
|
|
|
r_info->has_negative_transform.reinitialize(nmeshes);
|
2021-04-02 00:16:01 -05:00
|
|
|
r_info->material_remaps = material_remaps;
|
2021-02-21 17:57:03 -05:00
|
|
|
int v = 0;
|
|
|
|
|
int e = 0;
|
|
|
|
|
int f = 0;
|
|
|
|
|
|
|
|
|
|
/* Put these Vectors here, with a size unlikely to need resizing,
|
|
|
|
|
* so that the loop to make new Faces will likely not need to allocate
|
|
|
|
|
* over and over. */
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
Vector<const meshintersect::Vert *, estimated_max_facelen> face_vert;
|
2021-02-21 17:57:03 -05:00
|
|
|
Vector<int, estimated_max_facelen> face_edge_orig;
|
|
|
|
|
|
2022-04-27 18:52:56 -05:00
|
|
|
/* To convert the coordinates of meshes 1, 2, etc. into the local space
|
|
|
|
|
* of the target, multiply each transform by the inverse of the
|
Geometry Nodes: Improve speed of boolean node, use multi-input socket
This commit improves the performance of the node by up to 40% in some
cases when there are only two input meshes, mainly by skipping the
conversion to and from BMesh.
When there are more than two input meshes (note the distinction from
"Geometries", a geometry set can have many mesh instances), the
performance is actually worse, since boolean currently always does
self intersection in that case. Theoretically this could be improved
in the boolean code, or another option is automatically realizing
instances for each input geometry set.
Another improvement is using multi-input sockets for the inputs, which
removes the need to have a separate boolean node for every operation,
which can hopefully simplify some node trees.
The changes necessary for transforms in `mesh_boolean_convert.cc` are
somewhat subtle; they come from the fact that the collecting the
geometry set instances already gives transforms in the local space
of the modifier object. There is also a very small amount of cleanup
to those lines, using `float4x4::identity()`.
This commit also fixes T87078, where overlapping difference meshes
makes the operation not work, though I haven't investigated why.
Differential Revision: https://developer.blender.org/D10599
2021-04-01 15:00:47 -05:00
|
|
|
* target matrix. Exact Boolean works better if these matrices are 'cleaned'
|
2022-04-27 18:52:56 -05:00
|
|
|
* -- see the comment for the `clean_transform` function, above. */
|
2023-02-06 21:25:45 +01:00
|
|
|
const float4x4 inv_target_mat = math::invert(clean_transform(target_transform));
|
2021-02-21 17:57:03 -05:00
|
|
|
|
|
|
|
|
/* For each input `Mesh`, make `Vert`s and `Face`s for the corresponding
|
Mesh: Replace MPoly struct with offset indices
Implements #95967.
Currently the `MPoly` struct is 12 bytes, and stores the index of a
face's first corner and the number of corners/verts/edges. Polygons
and corners are always created in order by Blender, meaning each
face's corners will be after the previous face's corners. We can take
advantage of this fact and eliminate the redundancy in mesh face
storage by only storing a single integer corner offset for each face.
The size of the face is then encoded by the offset of the next face.
The size of a single integer is 4 bytes, so this reduces memory
usage by 3 times.
The same method is used for `CurvesGeometry`, so Blender already has
an abstraction to simplify using these offsets called `OffsetIndices`.
This class is used to easily retrieve a range of corner indices for
each face. This also gives the opportunity for sharing some logic with
curves.
Another benefit of the change is that the offsets and sizes stored in
`MPoly` can no longer disagree with each other. Storing faces in the
order of their corners can simplify some code too.
Face/polygon variables now use the `IndexRange` type, which comes with
quite a few utilities that can simplify code.
Some:
- The offset integer array has to be one longer than the face count to
avoid a branch for every face, which means the data is no longer part
of the mesh's `CustomData`.
- We lose the ability to "reference" an original mesh's offset array
until more reusable CoW from #104478 is committed. That will be added
in a separate commit.
- Since they aren't part of `CustomData`, poly offsets often have to be
copied manually.
- To simplify using `OffsetIndices` in many places, some functions and
structs in headers were moved to only compile in C++.
- All meshes created by Blender use the same order for faces and face
corners, but just in case, meshes with mismatched order are fixed by
versioning code.
- `MeshPolygon.totloop` is no longer editable in RNA. This API break is
necessary here unfortunately. It should be worth it in 3.6, since
that's the best way to allow loading meshes from 4.0, which is
important for an LTS version.
Pull Request: https://projects.blender.org/blender/blender/pulls/105938
2023-04-04 20:39:28 +02:00
|
|
|
* vertices and polygons, and keep track of the original indices (using the
|
2021-02-21 17:57:03 -05:00
|
|
|
* concatenating offset scheme) inside the `Vert`s and `Face`s.
|
Mesh: Move edges to a generic attribute
Implements #95966, as the final step of #95965.
This commit changes the storage of mesh edge vertex indices from the
`MEdge` type to the generic `int2` attribute type. This follows the
general design for geometry and the attribute system, where the data
storage type and the usage semantics are separated.
The main benefit of the change is reduced memory usage-- the
requirements of storing mesh edges is reduced by 1/3. For example,
this saves 8MB on a 1 million vertex grid. This also gives performance
benefits to any memory-bound mesh processing algorithm that uses edges.
Another benefit is that all of the edge's vertex indices are
contiguous. In a few cases, it's helpful to process all of them as
`Span<int>` rather than `Span<int2>`. Similarly, the type is more
likely to match a generic format used by a library, or code that
shouldn't know about specific Blender `Mesh` types.
Various Notes:
- The `.edge_verts` name is used to reflect a mapping between domains,
similar to `.corner_verts`, etc. The period means that it the data
shouldn't change arbitrarily by the user or procedural operations.
- `edge[0]` is now used instead of `edge.v1`
- Signed integers are used instead of unsigned to reduce the mixing
of signed-ness, which can be error prone.
- All of the previously used core mesh data types (`MVert`, `MEdge`,
`MLoop`, `MPoly` are now deprecated. Only generic types are used).
- The `vec2i` DNA type is used in the few C files where necessary.
Pull Request: https://projects.blender.org/blender/blender/pulls/106638
2023-04-17 13:47:41 +02:00
|
|
|
* When making `Face`s, we also put in the original indices for edges that
|
Mesh: Replace MPoly struct with offset indices
Implements #95967.
Currently the `MPoly` struct is 12 bytes, and stores the index of a
face's first corner and the number of corners/verts/edges. Polygons
and corners are always created in order by Blender, meaning each
face's corners will be after the previous face's corners. We can take
advantage of this fact and eliminate the redundancy in mesh face
storage by only storing a single integer corner offset for each face.
The size of the face is then encoded by the offset of the next face.
The size of a single integer is 4 bytes, so this reduces memory
usage by 3 times.
The same method is used for `CurvesGeometry`, so Blender already has
an abstraction to simplify using these offsets called `OffsetIndices`.
This class is used to easily retrieve a range of corner indices for
each face. This also gives the opportunity for sharing some logic with
curves.
Another benefit of the change is that the offsets and sizes stored in
`MPoly` can no longer disagree with each other. Storing faces in the
order of their corners can simplify some code too.
Face/polygon variables now use the `IndexRange` type, which comes with
quite a few utilities that can simplify code.
Some:
- The offset integer array has to be one longer than the face count to
avoid a branch for every face, which means the data is no longer part
of the mesh's `CustomData`.
- We lose the ability to "reference" an original mesh's offset array
until more reusable CoW from #104478 is committed. That will be added
in a separate commit.
- Since they aren't part of `CustomData`, poly offsets often have to be
copied manually.
- To simplify using `OffsetIndices` in many places, some functions and
structs in headers were moved to only compile in C++.
- All meshes created by Blender use the same order for faces and face
corners, but just in case, meshes with mismatched order are fixed by
versioning code.
- `MeshPolygon.totloop` is no longer editable in RNA. This API break is
necessary here unfortunately. It should be worth it in 3.6, since
that's the best way to allow loading meshes from 4.0, which is
important for an LTS version.
Pull Request: https://projects.blender.org/blender/blender/pulls/105938
2023-04-04 20:39:28 +02:00
|
|
|
* make up the polygons using the same scheme. */
|
2021-02-21 17:57:03 -05:00
|
|
|
for (int mi : meshes.index_range()) {
|
2023-12-08 16:40:06 -05:00
|
|
|
const Mesh *mesh = meshes[mi];
|
Geometry Nodes: Improve speed of boolean node, use multi-input socket
This commit improves the performance of the node by up to 40% in some
cases when there are only two input meshes, mainly by skipping the
conversion to and from BMesh.
When there are more than two input meshes (note the distinction from
"Geometries", a geometry set can have many mesh instances), the
performance is actually worse, since boolean currently always does
self intersection in that case. Theoretically this could be improved
in the boolean code, or another option is automatically realizing
instances for each input geometry set.
Another improvement is using multi-input sockets for the inputs, which
removes the need to have a separate boolean node for every operation,
which can hopefully simplify some node trees.
The changes necessary for transforms in `mesh_boolean_convert.cc` are
somewhat subtle; they come from the fact that the collecting the
geometry set instances already gives transforms in the local space
of the modifier object. There is also a very small amount of cleanup
to those lines, using `float4x4::identity()`.
This commit also fixes T87078, where overlapping difference meshes
makes the operation not work, though I haven't investigated why.
Differential Revision: https://developer.blender.org/D10599
2021-04-01 15:00:47 -05:00
|
|
|
r_info->mesh_vert_offset[mi] = v;
|
|
|
|
|
r_info->mesh_edge_offset[mi] = e;
|
2023-07-24 22:06:55 +02:00
|
|
|
r_info->mesh_face_offset[mi] = f;
|
2022-04-27 18:52:56 -05:00
|
|
|
/* Get matrix that transforms a coordinate in meshes[mi]'s local space
|
2022-02-23 18:24:08 +11:00
|
|
|
* to the target space. */
|
2023-11-03 09:27:59 +01:00
|
|
|
const float4x4 objn_mat = obmats.is_empty() ? float4x4::identity() :
|
|
|
|
|
clean_transform(obmats[mi]);
|
Geometry Nodes: Improve speed of boolean node, use multi-input socket
This commit improves the performance of the node by up to 40% in some
cases when there are only two input meshes, mainly by skipping the
conversion to and from BMesh.
When there are more than two input meshes (note the distinction from
"Geometries", a geometry set can have many mesh instances), the
performance is actually worse, since boolean currently always does
self intersection in that case. Theoretically this could be improved
in the boolean code, or another option is automatically realizing
instances for each input geometry set.
Another improvement is using multi-input sockets for the inputs, which
removes the need to have a separate boolean node for every operation,
which can hopefully simplify some node trees.
The changes necessary for transforms in `mesh_boolean_convert.cc` are
somewhat subtle; they come from the fact that the collecting the
geometry set instances already gives transforms in the local space
of the modifier object. There is also a very small amount of cleanup
to those lines, using `float4x4::identity()`.
This commit also fixes T87078, where overlapping difference meshes
makes the operation not work, though I haven't investigated why.
Differential Revision: https://developer.blender.org/D10599
2021-04-01 15:00:47 -05:00
|
|
|
r_info->to_target_transform[mi] = inv_target_mat * objn_mat;
|
2023-02-06 21:25:45 +01:00
|
|
|
r_info->has_negative_transform[mi] = math::is_negative(objn_mat);
|
2021-07-25 13:29:45 -04:00
|
|
|
|
|
|
|
|
/* All meshes 1 and up will be transformed into the local space of operand 0.
|
|
|
|
|
* Historical behavior of the modifier has been to flip the faces of any meshes
|
|
|
|
|
* that would have a negative transform if you do that. */
|
|
|
|
|
bool need_face_flip = r_info->has_negative_transform[mi] != r_info->has_negative_transform[0];
|
Geometry Nodes: Improve speed of boolean node, use multi-input socket
This commit improves the performance of the node by up to 40% in some
cases when there are only two input meshes, mainly by skipping the
conversion to and from BMesh.
When there are more than two input meshes (note the distinction from
"Geometries", a geometry set can have many mesh instances), the
performance is actually worse, since boolean currently always does
self intersection in that case. Theoretically this could be improved
in the boolean code, or another option is automatically realizing
instances for each input geometry set.
Another improvement is using multi-input sockets for the inputs, which
removes the need to have a separate boolean node for every operation,
which can hopefully simplify some node trees.
The changes necessary for transforms in `mesh_boolean_convert.cc` are
somewhat subtle; they come from the fact that the collecting the
geometry set instances already gives transforms in the local space
of the modifier object. There is also a very small amount of cleanup
to those lines, using `float4x4::identity()`.
This commit also fixes T87078, where overlapping difference meshes
makes the operation not work, though I haven't investigated why.
Differential Revision: https://developer.blender.org/D10599
2021-04-01 15:00:47 -05:00
|
|
|
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
Vector<meshintersect::Vert *> verts(mesh->verts_num);
|
2023-12-08 16:40:06 -05:00
|
|
|
const Span<float3> vert_positions = mesh->vert_positions();
|
|
|
|
|
const OffsetIndices faces = mesh->faces();
|
|
|
|
|
const Span<int> corner_verts = mesh->corner_verts();
|
|
|
|
|
const Span<int> corner_edges = mesh->corner_edges();
|
2021-07-05 18:09:36 -04:00
|
|
|
|
|
|
|
|
/* Allocate verts
|
|
|
|
|
* Skip the matrix multiplication for each point when there is no transform for a mesh,
|
|
|
|
|
* for example when the first mesh is already in the target space. (Note the logic
|
2023-12-04 02:03:10 +01:00
|
|
|
* directly above, which uses an identity matrix with an empty input transform). */
|
|
|
|
|
if (obmats.is_empty() || r_info->to_target_transform[mi] == float4x4::identity()) {
|
Mesh: Move positions to a generic attribute
**Changes**
As described in T93602, this patch removes all use of the `MVert`
struct, replacing it with a generic named attribute with the name
`"position"`, consistent with other geometry types.
Variable names have been changed from `verts` to `positions`, to align
with the attribute name and the more generic design (positions are not
vertices, they are just an attribute stored on the point domain).
This change is made possible by previous commits that moved all other
data out of `MVert` to runtime data or other generic attributes. What
remains is mostly a simple type change. Though, the type still shows up
859 times, so the patch is quite large.
One compromise is that now `CD_MASK_BAREMESH` now contains
`CD_PROP_FLOAT3`. With the general move towards generic attributes
over custom data types, we are removing use of these type masks anyway.
**Benefits**
The most obvious benefit is reduced memory usage and the benefits
that brings in memory-bound situations. `float3` is only 3 bytes, in
comparison to `MVert` which was 4. When there are millions of vertices
this starts to matter more.
The other benefits come from using a more generic type. Instead of
writing algorithms specifically for `MVert`, code can just use arrays
of vectors. This will allow eliminating many temporary arrays or
wrappers used to extract positions.
Many possible improvements aren't implemented in this patch, though
I did switch simplify or remove the process of creating temporary
position arrays in a few places.
The design clarity that "positions are just another attribute" brings
allows removing explicit copying of vertices in some procedural
operations-- they are just processed like most other attributes.
**Performance**
This touches so many areas that it's hard to benchmark exhaustively,
but I observed some areas as examples.
* The mesh line node with 4 million count was 1.5x (8ms to 12ms) faster.
* The Spring splash screen went from ~4.3 to ~4.5 fps.
* The subdivision surface modifier/node was slightly faster
RNA access through Python may be slightly slower, since now we need
a name lookup instead of just a custom data type lookup for each index.
**Future Improvements**
* Remove uses of "vert_coords" functions:
* `BKE_mesh_vert_coords_alloc`
* `BKE_mesh_vert_coords_get`
* `BKE_mesh_vert_coords_apply{_with_mat4}`
* Remove more hidden copying of positions
* General simplification now possible in many areas
* Convert more code to C++ to use `float3` instead of `float[3]`
* Currently `reinterpret_cast` is used for those C-API functions
Differential Revision: https://developer.blender.org/D15982
2023-01-10 00:10:43 -05:00
|
|
|
threading::parallel_for(vert_positions.index_range(), 2048, [&](IndexRange range) {
|
2021-07-05 18:09:36 -04:00
|
|
|
for (int i : range) {
|
Mesh: Move positions to a generic attribute
**Changes**
As described in T93602, this patch removes all use of the `MVert`
struct, replacing it with a generic named attribute with the name
`"position"`, consistent with other geometry types.
Variable names have been changed from `verts` to `positions`, to align
with the attribute name and the more generic design (positions are not
vertices, they are just an attribute stored on the point domain).
This change is made possible by previous commits that moved all other
data out of `MVert` to runtime data or other generic attributes. What
remains is mostly a simple type change. Though, the type still shows up
859 times, so the patch is quite large.
One compromise is that now `CD_MASK_BAREMESH` now contains
`CD_PROP_FLOAT3`. With the general move towards generic attributes
over custom data types, we are removing use of these type masks anyway.
**Benefits**
The most obvious benefit is reduced memory usage and the benefits
that brings in memory-bound situations. `float3` is only 3 bytes, in
comparison to `MVert` which was 4. When there are millions of vertices
this starts to matter more.
The other benefits come from using a more generic type. Instead of
writing algorithms specifically for `MVert`, code can just use arrays
of vectors. This will allow eliminating many temporary arrays or
wrappers used to extract positions.
Many possible improvements aren't implemented in this patch, though
I did switch simplify or remove the process of creating temporary
position arrays in a few places.
The design clarity that "positions are just another attribute" brings
allows removing explicit copying of vertices in some procedural
operations-- they are just processed like most other attributes.
**Performance**
This touches so many areas that it's hard to benchmark exhaustively,
but I observed some areas as examples.
* The mesh line node with 4 million count was 1.5x (8ms to 12ms) faster.
* The Spring splash screen went from ~4.3 to ~4.5 fps.
* The subdivision surface modifier/node was slightly faster
RNA access through Python may be slightly slower, since now we need
a name lookup instead of just a custom data type lookup for each index.
**Future Improvements**
* Remove uses of "vert_coords" functions:
* `BKE_mesh_vert_coords_alloc`
* `BKE_mesh_vert_coords_get`
* `BKE_mesh_vert_coords_apply{_with_mat4}`
* Remove more hidden copying of positions
* General simplification now possible in many areas
* Convert more code to C++ to use `float3` instead of `float[3]`
* Currently `reinterpret_cast` is used for those C-API functions
Differential Revision: https://developer.blender.org/D15982
2023-01-10 00:10:43 -05:00
|
|
|
float3 co = vert_positions[i];
|
2021-07-05 18:09:36 -04:00
|
|
|
mpq3 mco = mpq3(co.x, co.y, co.z);
|
|
|
|
|
double3 dco(mco[0].get_d(), mco[1].get_d(), mco[2].get_d());
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
verts[i] = new meshintersect::Vert(mco, dco, meshintersect::NO_INDEX, i);
|
2021-07-05 18:09:36 -04:00
|
|
|
}
|
|
|
|
|
});
|
2021-02-21 17:57:03 -05:00
|
|
|
}
|
Geometry Nodes: Improve speed of boolean node, use multi-input socket
This commit improves the performance of the node by up to 40% in some
cases when there are only two input meshes, mainly by skipping the
conversion to and from BMesh.
When there are more than two input meshes (note the distinction from
"Geometries", a geometry set can have many mesh instances), the
performance is actually worse, since boolean currently always does
self intersection in that case. Theoretically this could be improved
in the boolean code, or another option is automatically realizing
instances for each input geometry set.
Another improvement is using multi-input sockets for the inputs, which
removes the need to have a separate boolean node for every operation,
which can hopefully simplify some node trees.
The changes necessary for transforms in `mesh_boolean_convert.cc` are
somewhat subtle; they come from the fact that the collecting the
geometry set instances already gives transforms in the local space
of the modifier object. There is also a very small amount of cleanup
to those lines, using `float4x4::identity()`.
This commit also fixes T87078, where overlapping difference meshes
makes the operation not work, though I haven't investigated why.
Differential Revision: https://developer.blender.org/D10599
2021-04-01 15:00:47 -05:00
|
|
|
else {
|
Mesh: Move positions to a generic attribute
**Changes**
As described in T93602, this patch removes all use of the `MVert`
struct, replacing it with a generic named attribute with the name
`"position"`, consistent with other geometry types.
Variable names have been changed from `verts` to `positions`, to align
with the attribute name and the more generic design (positions are not
vertices, they are just an attribute stored on the point domain).
This change is made possible by previous commits that moved all other
data out of `MVert` to runtime data or other generic attributes. What
remains is mostly a simple type change. Though, the type still shows up
859 times, so the patch is quite large.
One compromise is that now `CD_MASK_BAREMESH` now contains
`CD_PROP_FLOAT3`. With the general move towards generic attributes
over custom data types, we are removing use of these type masks anyway.
**Benefits**
The most obvious benefit is reduced memory usage and the benefits
that brings in memory-bound situations. `float3` is only 3 bytes, in
comparison to `MVert` which was 4. When there are millions of vertices
this starts to matter more.
The other benefits come from using a more generic type. Instead of
writing algorithms specifically for `MVert`, code can just use arrays
of vectors. This will allow eliminating many temporary arrays or
wrappers used to extract positions.
Many possible improvements aren't implemented in this patch, though
I did switch simplify or remove the process of creating temporary
position arrays in a few places.
The design clarity that "positions are just another attribute" brings
allows removing explicit copying of vertices in some procedural
operations-- they are just processed like most other attributes.
**Performance**
This touches so many areas that it's hard to benchmark exhaustively,
but I observed some areas as examples.
* The mesh line node with 4 million count was 1.5x (8ms to 12ms) faster.
* The Spring splash screen went from ~4.3 to ~4.5 fps.
* The subdivision surface modifier/node was slightly faster
RNA access through Python may be slightly slower, since now we need
a name lookup instead of just a custom data type lookup for each index.
**Future Improvements**
* Remove uses of "vert_coords" functions:
* `BKE_mesh_vert_coords_alloc`
* `BKE_mesh_vert_coords_get`
* `BKE_mesh_vert_coords_apply{_with_mat4}`
* Remove more hidden copying of positions
* General simplification now possible in many areas
* Convert more code to C++ to use `float3` instead of `float[3]`
* Currently `reinterpret_cast` is used for those C-API functions
Differential Revision: https://developer.blender.org/D15982
2023-01-10 00:10:43 -05:00
|
|
|
threading::parallel_for(vert_positions.index_range(), 2048, [&](IndexRange range) {
|
2021-07-05 18:09:36 -04:00
|
|
|
for (int i : range) {
|
2023-02-06 21:25:45 +01:00
|
|
|
float3 co = math::transform_point(r_info->to_target_transform[mi], vert_positions[i]);
|
2021-07-05 18:09:36 -04:00
|
|
|
mpq3 mco = mpq3(co.x, co.y, co.z);
|
|
|
|
|
double3 dco(mco[0].get_d(), mco[1].get_d(), mco[2].get_d());
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
verts[i] = new meshintersect::Vert(mco, dco, meshintersect::NO_INDEX, i);
|
2021-07-05 18:09:36 -04:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
Mesh: Move positions to a generic attribute
**Changes**
As described in T93602, this patch removes all use of the `MVert`
struct, replacing it with a generic named attribute with the name
`"position"`, consistent with other geometry types.
Variable names have been changed from `verts` to `positions`, to align
with the attribute name and the more generic design (positions are not
vertices, they are just an attribute stored on the point domain).
This change is made possible by previous commits that moved all other
data out of `MVert` to runtime data or other generic attributes. What
remains is mostly a simple type change. Though, the type still shows up
859 times, so the patch is quite large.
One compromise is that now `CD_MASK_BAREMESH` now contains
`CD_PROP_FLOAT3`. With the general move towards generic attributes
over custom data types, we are removing use of these type masks anyway.
**Benefits**
The most obvious benefit is reduced memory usage and the benefits
that brings in memory-bound situations. `float3` is only 3 bytes, in
comparison to `MVert` which was 4. When there are millions of vertices
this starts to matter more.
The other benefits come from using a more generic type. Instead of
writing algorithms specifically for `MVert`, code can just use arrays
of vectors. This will allow eliminating many temporary arrays or
wrappers used to extract positions.
Many possible improvements aren't implemented in this patch, though
I did switch simplify or remove the process of creating temporary
position arrays in a few places.
The design clarity that "positions are just another attribute" brings
allows removing explicit copying of vertices in some procedural
operations-- they are just processed like most other attributes.
**Performance**
This touches so many areas that it's hard to benchmark exhaustively,
but I observed some areas as examples.
* The mesh line node with 4 million count was 1.5x (8ms to 12ms) faster.
* The Spring splash screen went from ~4.3 to ~4.5 fps.
* The subdivision surface modifier/node was slightly faster
RNA access through Python may be slightly slower, since now we need
a name lookup instead of just a custom data type lookup for each index.
**Future Improvements**
* Remove uses of "vert_coords" functions:
* `BKE_mesh_vert_coords_alloc`
* `BKE_mesh_vert_coords_get`
* `BKE_mesh_vert_coords_apply{_with_mat4}`
* Remove more hidden copying of positions
* General simplification now possible in many areas
* Convert more code to C++ to use `float3` instead of `float[3]`
* Currently `reinterpret_cast` is used for those C-API functions
Differential Revision: https://developer.blender.org/D15982
2023-01-10 00:10:43 -05:00
|
|
|
for (int i : vert_positions.index_range()) {
|
2021-07-05 18:09:36 -04:00
|
|
|
r_info->mesh_to_imesh_vert[v] = arena.add_or_find_vert(verts[i]);
|
|
|
|
|
++v;
|
2021-02-21 17:57:03 -05:00
|
|
|
}
|
Geometry Nodes: Improve speed of boolean node, use multi-input socket
This commit improves the performance of the node by up to 40% in some
cases when there are only two input meshes, mainly by skipping the
conversion to and from BMesh.
When there are more than two input meshes (note the distinction from
"Geometries", a geometry set can have many mesh instances), the
performance is actually worse, since boolean currently always does
self intersection in that case. Theoretically this could be improved
in the boolean code, or another option is automatically realizing
instances for each input geometry set.
Another improvement is using multi-input sockets for the inputs, which
removes the need to have a separate boolean node for every operation,
which can hopefully simplify some node trees.
The changes necessary for transforms in `mesh_boolean_convert.cc` are
somewhat subtle; they come from the fact that the collecting the
geometry set instances already gives transforms in the local space
of the modifier object. There is also a very small amount of cleanup
to those lines, using `float4x4::identity()`.
This commit also fixes T87078, where overlapping difference meshes
makes the operation not work, though I haven't investigated why.
Differential Revision: https://developer.blender.org/D10599
2021-04-01 15:00:47 -05:00
|
|
|
|
2023-07-24 22:06:55 +02:00
|
|
|
for (const int face_i : faces.index_range()) {
|
|
|
|
|
const IndexRange face = faces[face_i];
|
|
|
|
|
int flen = face.size();
|
2021-07-25 13:29:45 -04:00
|
|
|
face_vert.resize(flen);
|
|
|
|
|
face_edge_orig.resize(flen);
|
2021-02-21 17:57:03 -05:00
|
|
|
for (int i = 0; i < flen; ++i) {
|
2023-07-24 22:06:55 +02:00
|
|
|
const int corner_i = face[i];
|
Mesh: Replace MLoop struct with generic attributes
Implements #102359.
Split the `MLoop` struct into two separate integer arrays called
`corner_verts` and `corner_edges`, referring to the vertex each corner
is attached to and the next edge around the face at each corner. These
arrays can be sliced to give access to the edges or vertices in a face.
Then they are often referred to as "poly_verts" or "poly_edges".
The main benefits are halving the necessary memory bandwidth when only
one array is used and simplifications from using regular integer indices
instead of a special-purpose struct.
The commit also starts a renaming from "loop" to "corner" in mesh code.
Like the other mesh struct of array refactors, forward compatibility is
kept by writing files with the older format. This will be done until 4.0
to ease the transition process.
Looking at a small portion of the patch should give a good impression
for the rest of the changes. I tried to make the changes as small as
possible so it's easy to tell the correctness from the diff. Though I
found Blender developers have been very inventive over the last decade
when finding different ways to loop over the corners in a face.
For performance, nearly every piece of code that deals with `Mesh` is
slightly impacted. Any algorithm that is memory bottle-necked should
see an improvement. For example, here is a comparison of interpolating
a vertex float attribute to face corners (Ryzen 3700x):
**Before** (Average: 3.7 ms, Min: 3.4 ms)
```
threading::parallel_for(loops.index_range(), 4096, [&](IndexRange range) {
for (const int64_t i : range) {
dst[i] = src[loops[i].v];
}
});
```
**After** (Average: 2.9 ms, Min: 2.6 ms)
```
array_utils::gather(src, corner_verts, dst);
```
That's an improvement of 28% to the average timings, and it's also a
simplification, since an index-based routine can be used instead.
For more examples using the new arrays, see the design task.
Pull Request: https://projects.blender.org/blender/blender/pulls/104424
2023-03-20 15:55:13 +01:00
|
|
|
int mverti = r_info->mesh_vert_offset[mi] + corner_verts[corner_i];
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
const meshintersect::Vert *fv = r_info->mesh_to_imesh_vert[mverti];
|
2021-07-25 13:29:45 -04:00
|
|
|
if (need_face_flip) {
|
|
|
|
|
face_vert[flen - i - 1] = fv;
|
|
|
|
|
int iedge = i < flen - 1 ? flen - i - 2 : flen - 1;
|
Mesh: Replace MLoop struct with generic attributes
Implements #102359.
Split the `MLoop` struct into two separate integer arrays called
`corner_verts` and `corner_edges`, referring to the vertex each corner
is attached to and the next edge around the face at each corner. These
arrays can be sliced to give access to the edges or vertices in a face.
Then they are often referred to as "poly_verts" or "poly_edges".
The main benefits are halving the necessary memory bandwidth when only
one array is used and simplifications from using regular integer indices
instead of a special-purpose struct.
The commit also starts a renaming from "loop" to "corner" in mesh code.
Like the other mesh struct of array refactors, forward compatibility is
kept by writing files with the older format. This will be done until 4.0
to ease the transition process.
Looking at a small portion of the patch should give a good impression
for the rest of the changes. I tried to make the changes as small as
possible so it's easy to tell the correctness from the diff. Though I
found Blender developers have been very inventive over the last decade
when finding different ways to loop over the corners in a face.
For performance, nearly every piece of code that deals with `Mesh` is
slightly impacted. Any algorithm that is memory bottle-necked should
see an improvement. For example, here is a comparison of interpolating
a vertex float attribute to face corners (Ryzen 3700x):
**Before** (Average: 3.7 ms, Min: 3.4 ms)
```
threading::parallel_for(loops.index_range(), 4096, [&](IndexRange range) {
for (const int64_t i : range) {
dst[i] = src[loops[i].v];
}
});
```
**After** (Average: 2.9 ms, Min: 2.6 ms)
```
array_utils::gather(src, corner_verts, dst);
```
That's an improvement of 28% to the average timings, and it's also a
simplification, since an index-based routine can be used instead.
For more examples using the new arrays, see the design task.
Pull Request: https://projects.blender.org/blender/blender/pulls/104424
2023-03-20 15:55:13 +01:00
|
|
|
face_edge_orig[iedge] = e + corner_edges[corner_i];
|
2021-07-25 13:29:45 -04:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
face_vert[i] = fv;
|
Mesh: Replace MLoop struct with generic attributes
Implements #102359.
Split the `MLoop` struct into two separate integer arrays called
`corner_verts` and `corner_edges`, referring to the vertex each corner
is attached to and the next edge around the face at each corner. These
arrays can be sliced to give access to the edges or vertices in a face.
Then they are often referred to as "poly_verts" or "poly_edges".
The main benefits are halving the necessary memory bandwidth when only
one array is used and simplifications from using regular integer indices
instead of a special-purpose struct.
The commit also starts a renaming from "loop" to "corner" in mesh code.
Like the other mesh struct of array refactors, forward compatibility is
kept by writing files with the older format. This will be done until 4.0
to ease the transition process.
Looking at a small portion of the patch should give a good impression
for the rest of the changes. I tried to make the changes as small as
possible so it's easy to tell the correctness from the diff. Though I
found Blender developers have been very inventive over the last decade
when finding different ways to loop over the corners in a face.
For performance, nearly every piece of code that deals with `Mesh` is
slightly impacted. Any algorithm that is memory bottle-necked should
see an improvement. For example, here is a comparison of interpolating
a vertex float attribute to face corners (Ryzen 3700x):
**Before** (Average: 3.7 ms, Min: 3.4 ms)
```
threading::parallel_for(loops.index_range(), 4096, [&](IndexRange range) {
for (const int64_t i : range) {
dst[i] = src[loops[i].v];
}
});
```
**After** (Average: 2.9 ms, Min: 2.6 ms)
```
array_utils::gather(src, corner_verts, dst);
```
That's an improvement of 28% to the average timings, and it's also a
simplification, since an index-based routine can be used instead.
For more examples using the new arrays, see the design task.
Pull Request: https://projects.blender.org/blender/blender/pulls/104424
2023-03-20 15:55:13 +01:00
|
|
|
face_edge_orig[i] = e + corner_edges[corner_i];
|
2021-07-25 13:29:45 -04:00
|
|
|
}
|
2021-02-21 17:57:03 -05:00
|
|
|
}
|
|
|
|
|
r_info->mesh_to_imesh_face[f] = arena.add_face(face_vert, f, face_edge_orig);
|
|
|
|
|
++f;
|
|
|
|
|
}
|
2023-12-20 02:21:48 +01:00
|
|
|
e += mesh->edges_num;
|
2021-02-21 17:57:03 -05:00
|
|
|
}
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
return meshintersect::IMesh(r_info->mesh_to_imesh_face);
|
2021-02-21 17:57:03 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Copy vertex attributes, including customdata, from `orig_mv` to `mv`.
|
|
|
|
|
* `mv` is in `dest_mesh` with index `mv_index`.
|
|
|
|
|
* The `orig_mv` vertex came from Mesh `orig_me` and had index `index_in_orig_me` there. */
|
|
|
|
|
static void copy_vert_attributes(Mesh *dest_mesh,
|
|
|
|
|
const Mesh *orig_me,
|
|
|
|
|
int mv_index,
|
|
|
|
|
int index_in_orig_me)
|
|
|
|
|
{
|
|
|
|
|
/* For all layers in the orig mesh, copy the layer information. */
|
2023-07-25 21:15:52 +02:00
|
|
|
CustomData *target_cd = &dest_mesh->vert_data;
|
|
|
|
|
const CustomData *source_cd = &orig_me->vert_data;
|
2021-02-21 17:57:03 -05:00
|
|
|
for (int source_layer_i = 0; source_layer_i < source_cd->totlayer; ++source_layer_i) {
|
2023-03-29 17:10:49 +02:00
|
|
|
const eCustomDataType ty = eCustomDataType(source_cd->layers[source_layer_i].type);
|
Mesh: Move positions to a generic attribute
**Changes**
As described in T93602, this patch removes all use of the `MVert`
struct, replacing it with a generic named attribute with the name
`"position"`, consistent with other geometry types.
Variable names have been changed from `verts` to `positions`, to align
with the attribute name and the more generic design (positions are not
vertices, they are just an attribute stored on the point domain).
This change is made possible by previous commits that moved all other
data out of `MVert` to runtime data or other generic attributes. What
remains is mostly a simple type change. Though, the type still shows up
859 times, so the patch is quite large.
One compromise is that now `CD_MASK_BAREMESH` now contains
`CD_PROP_FLOAT3`. With the general move towards generic attributes
over custom data types, we are removing use of these type masks anyway.
**Benefits**
The most obvious benefit is reduced memory usage and the benefits
that brings in memory-bound situations. `float3` is only 3 bytes, in
comparison to `MVert` which was 4. When there are millions of vertices
this starts to matter more.
The other benefits come from using a more generic type. Instead of
writing algorithms specifically for `MVert`, code can just use arrays
of vectors. This will allow eliminating many temporary arrays or
wrappers used to extract positions.
Many possible improvements aren't implemented in this patch, though
I did switch simplify or remove the process of creating temporary
position arrays in a few places.
The design clarity that "positions are just another attribute" brings
allows removing explicit copying of vertices in some procedural
operations-- they are just processed like most other attributes.
**Performance**
This touches so many areas that it's hard to benchmark exhaustively,
but I observed some areas as examples.
* The mesh line node with 4 million count was 1.5x (8ms to 12ms) faster.
* The Spring splash screen went from ~4.3 to ~4.5 fps.
* The subdivision surface modifier/node was slightly faster
RNA access through Python may be slightly slower, since now we need
a name lookup instead of just a custom data type lookup for each index.
**Future Improvements**
* Remove uses of "vert_coords" functions:
* `BKE_mesh_vert_coords_alloc`
* `BKE_mesh_vert_coords_get`
* `BKE_mesh_vert_coords_apply{_with_mat4}`
* Remove more hidden copying of positions
* General simplification now possible in many areas
* Convert more code to C++ to use `float3` instead of `float[3]`
* Currently `reinterpret_cast` is used for those C-API functions
Differential Revision: https://developer.blender.org/D15982
2023-01-10 00:10:43 -05:00
|
|
|
if (StringRef(source_cd->layers->name) == "position") {
|
2021-02-21 17:57:03 -05:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
const char *name = source_cd->layers[source_layer_i].name;
|
|
|
|
|
int target_layer_i = CustomData_get_named_layer_index(target_cd, ty, name);
|
|
|
|
|
/* Not all layers were merged in target: some are marked CD_FLAG_NOCOPY
|
|
|
|
|
* and some are not in the CD_MASK_MESH.vdata. */
|
|
|
|
|
if (target_layer_i != -1) {
|
|
|
|
|
CustomData_copy_data_layer(
|
|
|
|
|
source_cd, target_cd, source_layer_i, target_layer_i, index_in_orig_me, mv_index, 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-24 22:06:55 +02:00
|
|
|
/* Similar to copy_vert_attributes but for face attributes. */
|
|
|
|
|
static void copy_face_attributes(Mesh *dest_mesh,
|
2021-02-21 17:57:03 -05:00
|
|
|
const Mesh *orig_me,
|
2023-07-24 22:06:55 +02:00
|
|
|
int face_index,
|
2021-03-14 11:39:56 -04:00
|
|
|
int index_in_orig_me,
|
2022-08-31 09:09:01 -05:00
|
|
|
Span<short> material_remap,
|
|
|
|
|
MutableSpan<int> dst_material_indices)
|
2021-02-21 17:57:03 -05:00
|
|
|
{
|
2023-07-25 21:15:52 +02:00
|
|
|
CustomData *target_cd = &dest_mesh->face_data;
|
|
|
|
|
const CustomData *source_cd = &orig_me->face_data;
|
2021-02-21 17:57:03 -05:00
|
|
|
for (int source_layer_i = 0; source_layer_i < source_cd->totlayer; ++source_layer_i) {
|
2023-03-29 17:10:49 +02:00
|
|
|
const eCustomDataType ty = eCustomDataType(source_cd->layers[source_layer_i].type);
|
2021-02-21 17:57:03 -05:00
|
|
|
const char *name = source_cd->layers[source_layer_i].name;
|
|
|
|
|
int target_layer_i = CustomData_get_named_layer_index(target_cd, ty, name);
|
|
|
|
|
if (target_layer_i != -1) {
|
|
|
|
|
CustomData_copy_data_layer(
|
2023-07-24 22:06:55 +02:00
|
|
|
source_cd, target_cd, source_layer_i, target_layer_i, index_in_orig_me, face_index, 1);
|
2021-02-21 17:57:03 -05:00
|
|
|
}
|
|
|
|
|
}
|
2022-11-21 15:49:18 -06:00
|
|
|
|
|
|
|
|
/* Fix material indices after they have been transferred as a generic attribute. */
|
2023-04-19 11:21:06 +02:00
|
|
|
const VArray<int> src_material_indices = *orig_me->attributes().lookup_or_default<int>(
|
2023-12-20 13:13:16 -05:00
|
|
|
"material_index", bke::AttrDomain::Face, 0);
|
2022-11-21 15:49:18 -06:00
|
|
|
const int src_index = src_material_indices[index_in_orig_me];
|
Fix T99592: Exact Boolean: Skip empty materials, add index-based option
**Empty Slot Fix**
Currently the boolean modifier transfers the default material from
meshes with no materials and empty material slots to the faces on the
base mesh. I added this in a2d59b2dac9e for the sake of consistency,
but the behavior is actually not useful at all. The default empty
material isn't chosen by users, it just signifies "nothing," so when
it replaces a material chosen by users, it feels like a bug.
This commit corrects that behavior by only transferring materials from
non-empty material slots. The implementation is now consistent between
exact mode of the boolean modifier and the geometry node.
**Index-Based Option**
"Index-based" is the new default material method for the boolean
modifier, to access the old behavior from before the breaking commit.
a2d59b2dac9e actually broke some Boolean workflows fundamentally, since
it was important to set up matching slot indices on each operand. That
isn't the cleanest workflow, and it breaks when materials change
procedurally, but historically that hasn't been a problem. The
"transfer" behavior transfers all materials except for empty slots,
but the fundamental problem is that there isn't a good way to specify
the result materials besides using the slot indices.
Even then, the transfer option is a bit more intuitive and useful for
some simpler situations, and it allows accessing the behavior that has
been in 3.2 and 3.3 for a long time, so it's also left in as an option.
The geometry node doesn't get this new option, in the hope that we'll
find a better solution in the future.
Differential Revision: https://developer.blender.org/D16187
2022-11-28 12:42:08 -06:00
|
|
|
if (material_remap.index_range().contains(src_index)) {
|
|
|
|
|
const int remapped_index = material_remap[src_index];
|
2023-07-24 22:06:55 +02:00
|
|
|
dst_material_indices[face_index] = remapped_index >= 0 ? remapped_index : src_index;
|
2022-11-21 15:49:18 -06:00
|
|
|
}
|
|
|
|
|
else {
|
2023-07-24 22:06:55 +02:00
|
|
|
dst_material_indices[face_index] = src_index;
|
2022-11-21 15:49:18 -06:00
|
|
|
}
|
2023-07-24 22:06:55 +02:00
|
|
|
BLI_assert(dst_material_indices[face_index] >= 0);
|
2021-02-21 17:57:03 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Similar to copy_vert_attributes but for edge attributes. */
|
|
|
|
|
static void copy_edge_attributes(Mesh *dest_mesh,
|
|
|
|
|
const Mesh *orig_me,
|
|
|
|
|
int medge_index,
|
|
|
|
|
int index_in_orig_me)
|
|
|
|
|
{
|
2023-07-25 21:15:52 +02:00
|
|
|
CustomData *target_cd = &dest_mesh->edge_data;
|
|
|
|
|
const CustomData *source_cd = &orig_me->edge_data;
|
2021-02-21 17:57:03 -05:00
|
|
|
for (int source_layer_i = 0; source_layer_i < source_cd->totlayer; ++source_layer_i) {
|
2023-03-29 17:10:49 +02:00
|
|
|
const eCustomDataType ty = eCustomDataType(source_cd->layers[source_layer_i].type);
|
Mesh: Move edges to a generic attribute
Implements #95966, as the final step of #95965.
This commit changes the storage of mesh edge vertex indices from the
`MEdge` type to the generic `int2` attribute type. This follows the
general design for geometry and the attribute system, where the data
storage type and the usage semantics are separated.
The main benefit of the change is reduced memory usage-- the
requirements of storing mesh edges is reduced by 1/3. For example,
this saves 8MB on a 1 million vertex grid. This also gives performance
benefits to any memory-bound mesh processing algorithm that uses edges.
Another benefit is that all of the edge's vertex indices are
contiguous. In a few cases, it's helpful to process all of them as
`Span<int>` rather than `Span<int2>`. Similarly, the type is more
likely to match a generic format used by a library, or code that
shouldn't know about specific Blender `Mesh` types.
Various Notes:
- The `.edge_verts` name is used to reflect a mapping between domains,
similar to `.corner_verts`, etc. The period means that it the data
shouldn't change arbitrarily by the user or procedural operations.
- `edge[0]` is now used instead of `edge.v1`
- Signed integers are used instead of unsigned to reduce the mixing
of signed-ness, which can be error prone.
- All of the previously used core mesh data types (`MVert`, `MEdge`,
`MLoop`, `MPoly` are now deprecated. Only generic types are used).
- The `vec2i` DNA type is used in the few C files where necessary.
Pull Request: https://projects.blender.org/blender/blender/pulls/106638
2023-04-17 13:47:41 +02:00
|
|
|
if (ty == CD_PROP_INT32_2D) {
|
|
|
|
|
if (STREQ(source_cd->layers[source_layer_i].name, ".edge_verts")) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2021-02-21 17:57:03 -05:00
|
|
|
}
|
|
|
|
|
const char *name = source_cd->layers[source_layer_i].name;
|
|
|
|
|
int target_layer_i = CustomData_get_named_layer_index(target_cd, ty, name);
|
|
|
|
|
if (target_layer_i != -1) {
|
|
|
|
|
CustomData_copy_data_layer(
|
|
|
|
|
source_cd, target_cd, source_layer_i, target_layer_i, index_in_orig_me, medge_index, 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-25 16:34:27 +11:00
|
|
|
/**
|
2023-07-24 22:06:55 +02:00
|
|
|
* For #IMesh face `f`, with corresponding output Mesh face `face`,
|
|
|
|
|
* where the original Mesh face is `orig_face`, coming from the Mesh
|
2021-02-21 17:57:03 -05:00
|
|
|
* `orig_me`, which has index `orig_me_index` in `mim`:
|
|
|
|
|
* fill in the `orig_loops` Array with corresponding indices of MLoops from `orig_me`
|
|
|
|
|
* where they have the same start and end vertices; for cases where that is
|
|
|
|
|
* not true, put -1 in the `orig_loops` slot.
|
2023-07-24 22:06:55 +02:00
|
|
|
* For now, we only try to do this if `face` and `orig_face` have the same size.
|
2021-02-21 17:57:03 -05:00
|
|
|
* Return the number of non-null MLoops filled in.
|
|
|
|
|
*/
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
static int fill_orig_loops(const meshintersect::Face *f,
|
2023-07-24 22:06:55 +02:00
|
|
|
const IndexRange orig_face,
|
2021-02-21 17:57:03 -05:00
|
|
|
const Mesh *orig_me,
|
|
|
|
|
int orig_me_index,
|
|
|
|
|
MeshesToIMeshInfo &mim,
|
Mesh: Remove redundant custom data pointers
For copy-on-write, we want to share attribute arrays between meshes
where possible. Mutable pointers like `Mesh.mvert` make that difficult
by making ownership vague. They also make code more complex by adding
redundancy.
The simplest solution is just removing them and retrieving layers from
`CustomData` as needed. Similar changes have already been applied to
curves and point clouds (e9f82d3dc7ee, 410a6efb747f). Removing use of
the pointers generally makes code more obvious and more reusable.
Mesh data is now accessed with a C++ API (`Mesh::edges()` or
`Mesh::edges_for_write()`), and a C API (`BKE_mesh_edges(mesh)`).
The CoW changes this commit makes possible are described in T95845
and T95842, and started in D14139 and D14140. The change also simplifies
the ongoing mesh struct-of-array refactors from T95965.
**RNA/Python Access Performance**
Theoretically, accessing mesh elements with the RNA API may become
slower, since the layer needs to be found on every random access.
However, overhead is already high enough that this doesn't make a
noticible differenc, and performance is actually improved in some
cases. Random access can be up to 10% faster, but other situations
might be a bit slower. Generally using `foreach_get/set` are the best
way to improve performance. See the differential revision for more
discussion about Python performance.
Cycles has been updated to use raw pointers and the internal Blender
mesh types, mostly because there is no sense in having this overhead
when it's already compiled with Blender. In my tests this roughly
halves the Cycles mesh creation time (0.19s to 0.10s for a 1 million
face grid).
Differential Revision: https://developer.blender.org/D15488
2022-09-05 11:56:34 -05:00
|
|
|
MutableSpan<int> r_orig_loops)
|
2021-02-21 17:57:03 -05:00
|
|
|
{
|
Mesh: Remove redundant custom data pointers
For copy-on-write, we want to share attribute arrays between meshes
where possible. Mutable pointers like `Mesh.mvert` make that difficult
by making ownership vague. They also make code more complex by adding
redundancy.
The simplest solution is just removing them and retrieving layers from
`CustomData` as needed. Similar changes have already been applied to
curves and point clouds (e9f82d3dc7ee, 410a6efb747f). Removing use of
the pointers generally makes code more obvious and more reusable.
Mesh data is now accessed with a C++ API (`Mesh::edges()` or
`Mesh::edges_for_write()`), and a C API (`BKE_mesh_edges(mesh)`).
The CoW changes this commit makes possible are described in T95845
and T95842, and started in D14139 and D14140. The change also simplifies
the ongoing mesh struct-of-array refactors from T95965.
**RNA/Python Access Performance**
Theoretically, accessing mesh elements with the RNA API may become
slower, since the layer needs to be found on every random access.
However, overhead is already high enough that this doesn't make a
noticible differenc, and performance is actually improved in some
cases. Random access can be up to 10% faster, but other situations
might be a bit slower. Generally using `foreach_get/set` are the best
way to improve performance. See the differential revision for more
discussion about Python performance.
Cycles has been updated to use raw pointers and the internal Blender
mesh types, mostly because there is no sense in having this overhead
when it's already compiled with Blender. In my tests this roughly
halves the Cycles mesh creation time (0.19s to 0.10s for a 1 million
face grid).
Differential Revision: https://developer.blender.org/D15488
2022-09-05 11:56:34 -05:00
|
|
|
r_orig_loops.fill(-1);
|
Mesh: Replace MLoop struct with generic attributes
Implements #102359.
Split the `MLoop` struct into two separate integer arrays called
`corner_verts` and `corner_edges`, referring to the vertex each corner
is attached to and the next edge around the face at each corner. These
arrays can be sliced to give access to the edges or vertices in a face.
Then they are often referred to as "poly_verts" or "poly_edges".
The main benefits are halving the necessary memory bandwidth when only
one array is used and simplifications from using regular integer indices
instead of a special-purpose struct.
The commit also starts a renaming from "loop" to "corner" in mesh code.
Like the other mesh struct of array refactors, forward compatibility is
kept by writing files with the older format. This will be done until 4.0
to ease the transition process.
Looking at a small portion of the patch should give a good impression
for the rest of the changes. I tried to make the changes as small as
possible so it's easy to tell the correctness from the diff. Though I
found Blender developers have been very inventive over the last decade
when finding different ways to loop over the corners in a face.
For performance, nearly every piece of code that deals with `Mesh` is
slightly impacted. Any algorithm that is memory bottle-necked should
see an improvement. For example, here is a comparison of interpolating
a vertex float attribute to face corners (Ryzen 3700x):
**Before** (Average: 3.7 ms, Min: 3.4 ms)
```
threading::parallel_for(loops.index_range(), 4096, [&](IndexRange range) {
for (const int64_t i : range) {
dst[i] = src[loops[i].v];
}
});
```
**After** (Average: 2.9 ms, Min: 2.6 ms)
```
array_utils::gather(src, corner_verts, dst);
```
That's an improvement of 28% to the average timings, and it's also a
simplification, since an index-based routine can be used instead.
For more examples using the new arrays, see the design task.
Pull Request: https://projects.blender.org/blender/blender/pulls/104424
2023-03-20 15:55:13 +01:00
|
|
|
const Span<int> orig_corner_verts = orig_me->corner_verts();
|
Mesh: Remove redundant custom data pointers
For copy-on-write, we want to share attribute arrays between meshes
where possible. Mutable pointers like `Mesh.mvert` make that difficult
by making ownership vague. They also make code more complex by adding
redundancy.
The simplest solution is just removing them and retrieving layers from
`CustomData` as needed. Similar changes have already been applied to
curves and point clouds (e9f82d3dc7ee, 410a6efb747f). Removing use of
the pointers generally makes code more obvious and more reusable.
Mesh data is now accessed with a C++ API (`Mesh::edges()` or
`Mesh::edges_for_write()`), and a C API (`BKE_mesh_edges(mesh)`).
The CoW changes this commit makes possible are described in T95845
and T95842, and started in D14139 and D14140. The change also simplifies
the ongoing mesh struct-of-array refactors from T95965.
**RNA/Python Access Performance**
Theoretically, accessing mesh elements with the RNA API may become
slower, since the layer needs to be found on every random access.
However, overhead is already high enough that this doesn't make a
noticible differenc, and performance is actually improved in some
cases. Random access can be up to 10% faster, but other situations
might be a bit slower. Generally using `foreach_get/set` are the best
way to improve performance. See the differential revision for more
discussion about Python performance.
Cycles has been updated to use raw pointers and the internal Blender
mesh types, mostly because there is no sense in having this overhead
when it's already compiled with Blender. In my tests this roughly
halves the Cycles mesh creation time (0.19s to 0.10s for a 1 million
face grid).
Differential Revision: https://developer.blender.org/D15488
2022-09-05 11:56:34 -05:00
|
|
|
|
2023-07-24 22:06:55 +02:00
|
|
|
int orig_mplen = orig_face.size();
|
2021-02-21 17:57:03 -05:00
|
|
|
if (f->size() != orig_mplen) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
Mesh: Remove redundant custom data pointers
For copy-on-write, we want to share attribute arrays between meshes
where possible. Mutable pointers like `Mesh.mvert` make that difficult
by making ownership vague. They also make code more complex by adding
redundancy.
The simplest solution is just removing them and retrieving layers from
`CustomData` as needed. Similar changes have already been applied to
curves and point clouds (e9f82d3dc7ee, 410a6efb747f). Removing use of
the pointers generally makes code more obvious and more reusable.
Mesh data is now accessed with a C++ API (`Mesh::edges()` or
`Mesh::edges_for_write()`), and a C API (`BKE_mesh_edges(mesh)`).
The CoW changes this commit makes possible are described in T95845
and T95842, and started in D14139 and D14140. The change also simplifies
the ongoing mesh struct-of-array refactors from T95965.
**RNA/Python Access Performance**
Theoretically, accessing mesh elements with the RNA API may become
slower, since the layer needs to be found on every random access.
However, overhead is already high enough that this doesn't make a
noticible differenc, and performance is actually improved in some
cases. Random access can be up to 10% faster, but other situations
might be a bit slower. Generally using `foreach_get/set` are the best
way to improve performance. See the differential revision for more
discussion about Python performance.
Cycles has been updated to use raw pointers and the internal Blender
mesh types, mostly because there is no sense in having this overhead
when it's already compiled with Blender. In my tests this roughly
halves the Cycles mesh creation time (0.19s to 0.10s for a 1 million
face grid).
Differential Revision: https://developer.blender.org/D15488
2022-09-05 11:56:34 -05:00
|
|
|
BLI_assert(r_orig_loops.size() == orig_mplen);
|
2021-02-21 17:57:03 -05:00
|
|
|
/* We'll look for the case where the first vertex in f has an original vertex
|
|
|
|
|
* that is the same as one in orig_me (after correcting for offset in mim meshes).
|
|
|
|
|
* Then see that loop and any subsequent ones have the same start and end vertex.
|
|
|
|
|
* This may miss some cases of partial alignment, but that's OK since discovering
|
2021-02-25 16:34:27 +11:00
|
|
|
* aligned loops is only an optimization to avoid some re-interpolation.
|
2021-02-21 17:57:03 -05:00
|
|
|
*/
|
|
|
|
|
int first_orig_v = f->vert[0]->orig;
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
if (first_orig_v == meshintersect::NO_INDEX) {
|
2021-02-21 17:57:03 -05:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
/* It is possible that the original vert was merged with another in another mesh. */
|
|
|
|
|
if (orig_me_index != mim.input_mesh_for_imesh_vert(first_orig_v)) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
int orig_me_vert_offset = mim.mesh_vert_offset[orig_me_index];
|
|
|
|
|
int first_orig_v_in_orig_me = first_orig_v - orig_me_vert_offset;
|
2023-12-20 02:21:48 +01:00
|
|
|
BLI_assert(0 <= first_orig_v_in_orig_me && first_orig_v_in_orig_me < orig_me->verts_num);
|
2023-07-26 15:23:26 +10:00
|
|
|
/* Assume all vertices in each face is unique. */
|
2021-02-21 17:57:03 -05:00
|
|
|
int offset = -1;
|
|
|
|
|
for (int i = 0; i < orig_mplen; ++i) {
|
2023-07-24 22:06:55 +02:00
|
|
|
int loop_i = i + orig_face.start();
|
Mesh: Replace MLoop struct with generic attributes
Implements #102359.
Split the `MLoop` struct into two separate integer arrays called
`corner_verts` and `corner_edges`, referring to the vertex each corner
is attached to and the next edge around the face at each corner. These
arrays can be sliced to give access to the edges or vertices in a face.
Then they are often referred to as "poly_verts" or "poly_edges".
The main benefits are halving the necessary memory bandwidth when only
one array is used and simplifications from using regular integer indices
instead of a special-purpose struct.
The commit also starts a renaming from "loop" to "corner" in mesh code.
Like the other mesh struct of array refactors, forward compatibility is
kept by writing files with the older format. This will be done until 4.0
to ease the transition process.
Looking at a small portion of the patch should give a good impression
for the rest of the changes. I tried to make the changes as small as
possible so it's easy to tell the correctness from the diff. Though I
found Blender developers have been very inventive over the last decade
when finding different ways to loop over the corners in a face.
For performance, nearly every piece of code that deals with `Mesh` is
slightly impacted. Any algorithm that is memory bottle-necked should
see an improvement. For example, here is a comparison of interpolating
a vertex float attribute to face corners (Ryzen 3700x):
**Before** (Average: 3.7 ms, Min: 3.4 ms)
```
threading::parallel_for(loops.index_range(), 4096, [&](IndexRange range) {
for (const int64_t i : range) {
dst[i] = src[loops[i].v];
}
});
```
**After** (Average: 2.9 ms, Min: 2.6 ms)
```
array_utils::gather(src, corner_verts, dst);
```
That's an improvement of 28% to the average timings, and it's also a
simplification, since an index-based routine can be used instead.
For more examples using the new arrays, see the design task.
Pull Request: https://projects.blender.org/blender/blender/pulls/104424
2023-03-20 15:55:13 +01:00
|
|
|
if (orig_corner_verts[loop_i] == first_orig_v_in_orig_me) {
|
2021-02-21 17:57:03 -05:00
|
|
|
offset = i;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (offset == -1) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
int num_orig_loops_found = 0;
|
|
|
|
|
for (int mp_loop_index = 0; mp_loop_index < orig_mplen; ++mp_loop_index) {
|
|
|
|
|
int orig_mp_loop_index = (mp_loop_index + offset) % orig_mplen;
|
2023-07-24 22:06:55 +02:00
|
|
|
const int vert_i = orig_corner_verts[orig_face.start() + orig_mp_loop_index];
|
2021-02-21 17:57:03 -05:00
|
|
|
int fv_orig = f->vert[mp_loop_index]->orig;
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
if (fv_orig != meshintersect::NO_INDEX) {
|
2021-02-21 17:57:03 -05:00
|
|
|
fv_orig -= orig_me_vert_offset;
|
2023-12-20 02:21:48 +01:00
|
|
|
if (fv_orig < 0 || fv_orig >= orig_me->verts_num) {
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
fv_orig = meshintersect::NO_INDEX;
|
2021-02-21 17:57:03 -05:00
|
|
|
}
|
|
|
|
|
}
|
Mesh: Replace MLoop struct with generic attributes
Implements #102359.
Split the `MLoop` struct into two separate integer arrays called
`corner_verts` and `corner_edges`, referring to the vertex each corner
is attached to and the next edge around the face at each corner. These
arrays can be sliced to give access to the edges or vertices in a face.
Then they are often referred to as "poly_verts" or "poly_edges".
The main benefits are halving the necessary memory bandwidth when only
one array is used and simplifications from using regular integer indices
instead of a special-purpose struct.
The commit also starts a renaming from "loop" to "corner" in mesh code.
Like the other mesh struct of array refactors, forward compatibility is
kept by writing files with the older format. This will be done until 4.0
to ease the transition process.
Looking at a small portion of the patch should give a good impression
for the rest of the changes. I tried to make the changes as small as
possible so it's easy to tell the correctness from the diff. Though I
found Blender developers have been very inventive over the last decade
when finding different ways to loop over the corners in a face.
For performance, nearly every piece of code that deals with `Mesh` is
slightly impacted. Any algorithm that is memory bottle-necked should
see an improvement. For example, here is a comparison of interpolating
a vertex float attribute to face corners (Ryzen 3700x):
**Before** (Average: 3.7 ms, Min: 3.4 ms)
```
threading::parallel_for(loops.index_range(), 4096, [&](IndexRange range) {
for (const int64_t i : range) {
dst[i] = src[loops[i].v];
}
});
```
**After** (Average: 2.9 ms, Min: 2.6 ms)
```
array_utils::gather(src, corner_verts, dst);
```
That's an improvement of 28% to the average timings, and it's also a
simplification, since an index-based routine can be used instead.
For more examples using the new arrays, see the design task.
Pull Request: https://projects.blender.org/blender/blender/pulls/104424
2023-03-20 15:55:13 +01:00
|
|
|
if (vert_i == fv_orig) {
|
|
|
|
|
const int vert_next =
|
2023-07-24 22:06:55 +02:00
|
|
|
orig_corner_verts[orig_face.start() + ((orig_mp_loop_index + 1) % orig_mplen)];
|
2021-02-21 17:57:03 -05:00
|
|
|
int fvnext_orig = f->vert[(mp_loop_index + 1) % orig_mplen]->orig;
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
if (fvnext_orig != meshintersect::NO_INDEX) {
|
2021-02-21 17:57:03 -05:00
|
|
|
fvnext_orig -= orig_me_vert_offset;
|
2023-12-20 02:21:48 +01:00
|
|
|
if (fvnext_orig < 0 || fvnext_orig >= orig_me->verts_num) {
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
fvnext_orig = meshintersect::NO_INDEX;
|
2021-02-21 17:57:03 -05:00
|
|
|
}
|
|
|
|
|
}
|
Mesh: Replace MLoop struct with generic attributes
Implements #102359.
Split the `MLoop` struct into two separate integer arrays called
`corner_verts` and `corner_edges`, referring to the vertex each corner
is attached to and the next edge around the face at each corner. These
arrays can be sliced to give access to the edges or vertices in a face.
Then they are often referred to as "poly_verts" or "poly_edges".
The main benefits are halving the necessary memory bandwidth when only
one array is used and simplifications from using regular integer indices
instead of a special-purpose struct.
The commit also starts a renaming from "loop" to "corner" in mesh code.
Like the other mesh struct of array refactors, forward compatibility is
kept by writing files with the older format. This will be done until 4.0
to ease the transition process.
Looking at a small portion of the patch should give a good impression
for the rest of the changes. I tried to make the changes as small as
possible so it's easy to tell the correctness from the diff. Though I
found Blender developers have been very inventive over the last decade
when finding different ways to loop over the corners in a face.
For performance, nearly every piece of code that deals with `Mesh` is
slightly impacted. Any algorithm that is memory bottle-necked should
see an improvement. For example, here is a comparison of interpolating
a vertex float attribute to face corners (Ryzen 3700x):
**Before** (Average: 3.7 ms, Min: 3.4 ms)
```
threading::parallel_for(loops.index_range(), 4096, [&](IndexRange range) {
for (const int64_t i : range) {
dst[i] = src[loops[i].v];
}
});
```
**After** (Average: 2.9 ms, Min: 2.6 ms)
```
array_utils::gather(src, corner_verts, dst);
```
That's an improvement of 28% to the average timings, and it's also a
simplification, since an index-based routine can be used instead.
For more examples using the new arrays, see the design task.
Pull Request: https://projects.blender.org/blender/blender/pulls/104424
2023-03-20 15:55:13 +01:00
|
|
|
if (vert_next == fvnext_orig) {
|
2023-07-24 22:06:55 +02:00
|
|
|
r_orig_loops[mp_loop_index] = orig_face.start() + orig_mp_loop_index;
|
2021-02-21 17:57:03 -05:00
|
|
|
++num_orig_loops_found;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return num_orig_loops_found;
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-24 22:06:55 +02:00
|
|
|
/* Fill `cos_2d` with the 2d coordinates found by projection face `face` along
|
2021-02-21 17:57:03 -05:00
|
|
|
* its normal. Also fill in r_axis_mat with the matrix that does that projection.
|
|
|
|
|
* But before projecting, also transform the 3d coordinate by multiplying by trans_mat.
|
2023-07-24 22:06:55 +02:00
|
|
|
* `cos_2d` should have room for `face.size()` entries. */
|
2023-12-08 16:40:06 -05:00
|
|
|
static void get_poly2d_cos(const Mesh *mesh,
|
2023-07-24 22:06:55 +02:00
|
|
|
const IndexRange face,
|
2021-02-21 17:57:03 -05:00
|
|
|
float (*cos_2d)[2],
|
2021-03-02 20:58:05 -06:00
|
|
|
const float4x4 &trans_mat,
|
2021-02-21 17:57:03 -05:00
|
|
|
float r_axis_mat[3][3])
|
|
|
|
|
{
|
2023-12-08 16:40:06 -05:00
|
|
|
const Span<float3> positions = mesh->vert_positions();
|
|
|
|
|
const Span<int> corner_verts = mesh->corner_verts();
|
2023-07-24 22:06:55 +02:00
|
|
|
const Span<int> face_verts = corner_verts.slice(face);
|
2021-02-21 17:57:03 -05:00
|
|
|
|
|
|
|
|
/* Project coordinates to 2d in cos_2d, using normal as projection axis. */
|
2023-07-24 22:06:55 +02:00
|
|
|
const float3 axis_dominant = bke::mesh::face_normal_calc(positions, face_verts);
|
2021-02-21 17:57:03 -05:00
|
|
|
axis_dominant_v3_to_m3(r_axis_mat, axis_dominant);
|
2023-07-24 22:06:55 +02:00
|
|
|
for (const int i : face_verts.index_range()) {
|
|
|
|
|
float3 co = positions[face_verts[i]];
|
2023-02-06 21:25:45 +01:00
|
|
|
co = math::transform_point(trans_mat, co);
|
|
|
|
|
*reinterpret_cast<float2 *>(&cos_2d[i]) = (float3x3(r_axis_mat) * co).xy();
|
2021-02-21 17:57:03 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-24 22:06:55 +02:00
|
|
|
/* For the loops of `face`, see if the face is unchanged from `orig_face`, and if so,
|
2021-02-21 17:57:03 -05:00
|
|
|
* copy the Loop attributes from corresponding loops to corresponding loops.
|
2023-07-24 22:06:55 +02:00
|
|
|
* Otherwise, interpolate the Loop attributes in the face `orig_face`. */
|
2021-02-21 17:57:03 -05:00
|
|
|
static void copy_or_interp_loop_attributes(Mesh *dest_mesh,
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
const meshintersect::Face *f,
|
2023-07-24 22:06:55 +02:00
|
|
|
const IndexRange face,
|
|
|
|
|
const IndexRange orig_face,
|
2021-02-21 17:57:03 -05:00
|
|
|
const Mesh *orig_me,
|
|
|
|
|
int orig_me_index,
|
|
|
|
|
MeshesToIMeshInfo &mim)
|
|
|
|
|
{
|
2023-07-24 22:06:55 +02:00
|
|
|
Array<int> orig_loops(face.size());
|
|
|
|
|
int norig = fill_orig_loops(f, orig_face, orig_me, orig_me_index, mim, orig_loops);
|
2021-02-21 17:57:03 -05:00
|
|
|
/* We may need these arrays if we have to interpolate Loop attributes rather than just copy.
|
|
|
|
|
* Right now, trying Array<float[2]> complains, so declare cos_2d a different way. */
|
|
|
|
|
float(*cos_2d)[2];
|
|
|
|
|
Array<float> weights;
|
|
|
|
|
Array<const void *> src_blocks_ofs;
|
|
|
|
|
float axis_mat[3][3];
|
2023-07-24 22:06:55 +02:00
|
|
|
if (norig != face.size()) {
|
|
|
|
|
/* We will need to interpolate. Make `cos_2d` hold 2d-projected coordinates of `orig_face`,
|
2021-02-21 17:57:03 -05:00
|
|
|
* which are transformed into object 0's local space before projecting.
|
|
|
|
|
* At this point we cannot yet calculate the interpolation weights, as they depend on
|
|
|
|
|
* the coordinate where interpolation is to happen, but we can allocate the needed arrays,
|
|
|
|
|
* so they don't have to be allocated per-layer. */
|
2023-07-24 22:06:55 +02:00
|
|
|
cos_2d = (float(*)[2])BLI_array_alloca(cos_2d, orig_face.size());
|
|
|
|
|
weights = Array<float>(orig_face.size());
|
|
|
|
|
src_blocks_ofs = Array<const void *>(orig_face.size());
|
|
|
|
|
get_poly2d_cos(orig_me, orig_face, cos_2d, mim.to_target_transform[orig_me_index], axis_mat);
|
2021-02-21 17:57:03 -05:00
|
|
|
}
|
2023-12-19 20:38:59 -05:00
|
|
|
CustomData *target_cd = &dest_mesh->corner_data;
|
Mesh: Move positions to a generic attribute
**Changes**
As described in T93602, this patch removes all use of the `MVert`
struct, replacing it with a generic named attribute with the name
`"position"`, consistent with other geometry types.
Variable names have been changed from `verts` to `positions`, to align
with the attribute name and the more generic design (positions are not
vertices, they are just an attribute stored on the point domain).
This change is made possible by previous commits that moved all other
data out of `MVert` to runtime data or other generic attributes. What
remains is mostly a simple type change. Though, the type still shows up
859 times, so the patch is quite large.
One compromise is that now `CD_MASK_BAREMESH` now contains
`CD_PROP_FLOAT3`. With the general move towards generic attributes
over custom data types, we are removing use of these type masks anyway.
**Benefits**
The most obvious benefit is reduced memory usage and the benefits
that brings in memory-bound situations. `float3` is only 3 bytes, in
comparison to `MVert` which was 4. When there are millions of vertices
this starts to matter more.
The other benefits come from using a more generic type. Instead of
writing algorithms specifically for `MVert`, code can just use arrays
of vectors. This will allow eliminating many temporary arrays or
wrappers used to extract positions.
Many possible improvements aren't implemented in this patch, though
I did switch simplify or remove the process of creating temporary
position arrays in a few places.
The design clarity that "positions are just another attribute" brings
allows removing explicit copying of vertices in some procedural
operations-- they are just processed like most other attributes.
**Performance**
This touches so many areas that it's hard to benchmark exhaustively,
but I observed some areas as examples.
* The mesh line node with 4 million count was 1.5x (8ms to 12ms) faster.
* The Spring splash screen went from ~4.3 to ~4.5 fps.
* The subdivision surface modifier/node was slightly faster
RNA access through Python may be slightly slower, since now we need
a name lookup instead of just a custom data type lookup for each index.
**Future Improvements**
* Remove uses of "vert_coords" functions:
* `BKE_mesh_vert_coords_alloc`
* `BKE_mesh_vert_coords_get`
* `BKE_mesh_vert_coords_apply{_with_mat4}`
* Remove more hidden copying of positions
* General simplification now possible in many areas
* Convert more code to C++ to use `float3` instead of `float[3]`
* Currently `reinterpret_cast` is used for those C-API functions
Differential Revision: https://developer.blender.org/D15982
2023-01-10 00:10:43 -05:00
|
|
|
const Span<float3> dst_positions = dest_mesh->vert_positions();
|
Mesh: Replace MLoop struct with generic attributes
Implements #102359.
Split the `MLoop` struct into two separate integer arrays called
`corner_verts` and `corner_edges`, referring to the vertex each corner
is attached to and the next edge around the face at each corner. These
arrays can be sliced to give access to the edges or vertices in a face.
Then they are often referred to as "poly_verts" or "poly_edges".
The main benefits are halving the necessary memory bandwidth when only
one array is used and simplifications from using regular integer indices
instead of a special-purpose struct.
The commit also starts a renaming from "loop" to "corner" in mesh code.
Like the other mesh struct of array refactors, forward compatibility is
kept by writing files with the older format. This will be done until 4.0
to ease the transition process.
Looking at a small portion of the patch should give a good impression
for the rest of the changes. I tried to make the changes as small as
possible so it's easy to tell the correctness from the diff. Though I
found Blender developers have been very inventive over the last decade
when finding different ways to loop over the corners in a face.
For performance, nearly every piece of code that deals with `Mesh` is
slightly impacted. Any algorithm that is memory bottle-necked should
see an improvement. For example, here is a comparison of interpolating
a vertex float attribute to face corners (Ryzen 3700x):
**Before** (Average: 3.7 ms, Min: 3.4 ms)
```
threading::parallel_for(loops.index_range(), 4096, [&](IndexRange range) {
for (const int64_t i : range) {
dst[i] = src[loops[i].v];
}
});
```
**After** (Average: 2.9 ms, Min: 2.6 ms)
```
array_utils::gather(src, corner_verts, dst);
```
That's an improvement of 28% to the average timings, and it's also a
simplification, since an index-based routine can be used instead.
For more examples using the new arrays, see the design task.
Pull Request: https://projects.blender.org/blender/blender/pulls/104424
2023-03-20 15:55:13 +01:00
|
|
|
const Span<int> dst_corner_verts = dest_mesh->corner_verts();
|
2023-07-24 22:06:55 +02:00
|
|
|
for (int i = 0; i < face.size(); ++i) {
|
|
|
|
|
int loop_index = face[i];
|
2021-02-21 17:57:03 -05:00
|
|
|
int orig_loop_index = norig > 0 ? orig_loops[i] : -1;
|
2023-12-19 20:38:59 -05:00
|
|
|
const CustomData *source_cd = &orig_me->corner_data;
|
2021-02-21 17:57:03 -05:00
|
|
|
if (orig_loop_index == -1) {
|
|
|
|
|
/* Will need interpolation weights for this loop's vertex's coordinates.
|
2023-07-24 22:06:55 +02:00
|
|
|
* The coordinate needs to be projected into 2d, just like the interpolating face's
|
2021-02-21 17:57:03 -05:00
|
|
|
* coordinates were. The `dest_mesh` coordinates are already in object 0 local space. */
|
|
|
|
|
float co[2];
|
Mesh: Replace MLoop struct with generic attributes
Implements #102359.
Split the `MLoop` struct into two separate integer arrays called
`corner_verts` and `corner_edges`, referring to the vertex each corner
is attached to and the next edge around the face at each corner. These
arrays can be sliced to give access to the edges or vertices in a face.
Then they are often referred to as "poly_verts" or "poly_edges".
The main benefits are halving the necessary memory bandwidth when only
one array is used and simplifications from using regular integer indices
instead of a special-purpose struct.
The commit also starts a renaming from "loop" to "corner" in mesh code.
Like the other mesh struct of array refactors, forward compatibility is
kept by writing files with the older format. This will be done until 4.0
to ease the transition process.
Looking at a small portion of the patch should give a good impression
for the rest of the changes. I tried to make the changes as small as
possible so it's easy to tell the correctness from the diff. Though I
found Blender developers have been very inventive over the last decade
when finding different ways to loop over the corners in a face.
For performance, nearly every piece of code that deals with `Mesh` is
slightly impacted. Any algorithm that is memory bottle-necked should
see an improvement. For example, here is a comparison of interpolating
a vertex float attribute to face corners (Ryzen 3700x):
**Before** (Average: 3.7 ms, Min: 3.4 ms)
```
threading::parallel_for(loops.index_range(), 4096, [&](IndexRange range) {
for (const int64_t i : range) {
dst[i] = src[loops[i].v];
}
});
```
**After** (Average: 2.9 ms, Min: 2.6 ms)
```
array_utils::gather(src, corner_verts, dst);
```
That's an improvement of 28% to the average timings, and it's also a
simplification, since an index-based routine can be used instead.
For more examples using the new arrays, see the design task.
Pull Request: https://projects.blender.org/blender/blender/pulls/104424
2023-03-20 15:55:13 +01:00
|
|
|
mul_v2_m3v3(co, axis_mat, dst_positions[dst_corner_verts[loop_index]]);
|
2023-07-24 22:06:55 +02:00
|
|
|
interp_weights_poly_v2(weights.data(), cos_2d, orig_face.size(), co);
|
2021-02-21 17:57:03 -05:00
|
|
|
}
|
|
|
|
|
for (int source_layer_i = 0; source_layer_i < source_cd->totlayer; ++source_layer_i) {
|
2023-03-29 17:10:49 +02:00
|
|
|
const eCustomDataType ty = eCustomDataType(source_cd->layers[source_layer_i].type);
|
2023-03-21 19:46:13 +11:00
|
|
|
if (STR_ELEM(source_cd->layers[source_layer_i].name, ".corner_vert", ".corner_edge")) {
|
2021-02-21 17:57:03 -05:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
const char *name = source_cd->layers[source_layer_i].name;
|
|
|
|
|
int target_layer_i = CustomData_get_named_layer_index(target_cd, ty, name);
|
|
|
|
|
if (target_layer_i == -1) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (orig_loop_index != -1) {
|
|
|
|
|
CustomData_copy_data_layer(
|
|
|
|
|
source_cd, target_cd, source_layer_i, target_layer_i, orig_loop_index, loop_index, 1);
|
|
|
|
|
}
|
|
|
|
|
else {
|
2021-07-03 23:08:40 +10:00
|
|
|
/* NOTE: although CustomData_bmesh_interp_n function has bmesh in its name, nothing about
|
2021-02-21 17:57:03 -05:00
|
|
|
* it is BMesh-specific. We can't use CustomData_interp because it assumes that
|
|
|
|
|
* all source layers exist in the dest.
|
|
|
|
|
* A non bmesh version could have the benefit of not copying data into src_blocks_ofs -
|
|
|
|
|
* using the contiguous data instead. TODO: add to the custom data API. */
|
|
|
|
|
int target_layer_type_index = CustomData_get_named_layer(target_cd, ty, name);
|
2021-03-06 09:05:55 -05:00
|
|
|
if (!CustomData_layer_has_interp(source_cd, source_layer_i)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2021-02-21 17:57:03 -05:00
|
|
|
int source_layer_type_index = source_layer_i - source_cd->typemap[ty];
|
|
|
|
|
BLI_assert(target_layer_type_index != -1 && source_layer_type_index >= 0);
|
2023-01-13 17:21:20 -06:00
|
|
|
const int size = CustomData_sizeof(ty);
|
2023-07-24 22:06:55 +02:00
|
|
|
for (int j = 0; j < orig_face.size(); ++j) {
|
2023-01-13 17:21:20 -06:00
|
|
|
const void *layer = CustomData_get_layer_n(source_cd, ty, source_layer_type_index);
|
2023-07-24 22:06:55 +02:00
|
|
|
src_blocks_ofs[j] = POINTER_OFFSET(layer, size * (orig_face[j]));
|
2021-02-21 17:57:03 -05:00
|
|
|
}
|
2023-01-13 17:21:20 -06:00
|
|
|
void *dst_layer = CustomData_get_layer_n_for_write(
|
2023-12-20 02:21:48 +01:00
|
|
|
target_cd, ty, target_layer_type_index, dest_mesh->corners_num);
|
2023-01-13 17:21:20 -06:00
|
|
|
void *dst_block_ofs = POINTER_OFFSET(dst_layer, size * loop_index);
|
2021-02-21 17:57:03 -05:00
|
|
|
CustomData_bmesh_interp_n(target_cd,
|
|
|
|
|
src_blocks_ofs.data(),
|
|
|
|
|
weights.data(),
|
|
|
|
|
nullptr,
|
2023-07-24 22:06:55 +02:00
|
|
|
orig_face.size(),
|
2021-02-21 17:57:03 -05:00
|
|
|
dst_block_ofs,
|
|
|
|
|
target_layer_i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-09 18:47:10 +10:00
|
|
|
/**
|
|
|
|
|
* Make sure that there are custom data layers in the target mesh
|
2021-02-21 17:57:03 -05:00
|
|
|
* corresponding to all target layers in all of the operands after the first.
|
|
|
|
|
* (The target should already have layers for those in the first operand mesh).
|
|
|
|
|
* Edges done separately -- will have to be done later, after edges are made.
|
|
|
|
|
*/
|
2023-07-24 22:06:55 +02:00
|
|
|
static void merge_vertex_loop_face_customdata_layers(Mesh *target, MeshesToIMeshInfo &mim)
|
2021-02-21 17:57:03 -05:00
|
|
|
{
|
|
|
|
|
for (int mesh_index = 1; mesh_index < mim.meshes.size(); ++mesh_index) {
|
2023-12-08 16:40:06 -05:00
|
|
|
const Mesh *mesh = mim.meshes[mesh_index];
|
2023-12-20 02:21:48 +01:00
|
|
|
if (mesh->verts_num) {
|
2023-12-08 16:40:06 -05:00
|
|
|
CustomData_merge_layout(&mesh->vert_data,
|
|
|
|
|
&target->vert_data,
|
|
|
|
|
CD_MASK_MESH.vmask,
|
|
|
|
|
CD_SET_DEFAULT,
|
2023-12-20 02:21:48 +01:00
|
|
|
target->verts_num);
|
2021-02-21 17:57:03 -05:00
|
|
|
}
|
2023-12-20 02:21:48 +01:00
|
|
|
if (mesh->corners_num) {
|
2023-12-19 20:38:59 -05:00
|
|
|
CustomData_merge_layout(&mesh->corner_data,
|
|
|
|
|
&target->corner_data,
|
2023-12-08 16:40:06 -05:00
|
|
|
CD_MASK_MESH.lmask,
|
|
|
|
|
CD_SET_DEFAULT,
|
2023-12-20 02:21:48 +01:00
|
|
|
target->corners_num);
|
2021-02-21 17:57:03 -05:00
|
|
|
}
|
2023-12-08 16:40:06 -05:00
|
|
|
if (mesh->faces_num) {
|
|
|
|
|
CustomData_merge_layout(&mesh->face_data,
|
2023-07-25 15:23:56 -04:00
|
|
|
&target->face_data,
|
|
|
|
|
CD_MASK_MESH.pmask,
|
|
|
|
|
CD_SET_DEFAULT,
|
|
|
|
|
target->faces_num);
|
2021-02-21 17:57:03 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void merge_edge_customdata_layers(Mesh *target, MeshesToIMeshInfo &mim)
|
|
|
|
|
{
|
2022-12-26 14:43:32 -05:00
|
|
|
for (int mesh_index = 0; mesh_index < mim.meshes.size(); ++mesh_index) {
|
2023-12-08 16:40:06 -05:00
|
|
|
const Mesh *mesh = mim.meshes[mesh_index];
|
2023-12-20 02:21:48 +01:00
|
|
|
if (mesh->edges_num) {
|
2023-12-08 16:40:06 -05:00
|
|
|
CustomData_merge_layout(&mesh->edge_data,
|
|
|
|
|
&target->edge_data,
|
|
|
|
|
CD_MASK_MESH.emask,
|
|
|
|
|
CD_SET_DEFAULT,
|
2023-12-20 02:21:48 +01:00
|
|
|
target->edges_num);
|
2021-02-21 17:57:03 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-09 18:47:10 +10:00
|
|
|
/**
|
|
|
|
|
* Convert the output IMesh im to a Blender Mesh,
|
2021-02-21 17:57:03 -05:00
|
|
|
* using the information in mim to get all the attributes right.
|
|
|
|
|
*/
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
static Mesh *imesh_to_mesh(meshintersect::IMesh *im, MeshesToIMeshInfo &mim)
|
2021-02-21 17:57:03 -05:00
|
|
|
{
|
|
|
|
|
constexpr int dbg_level = 0;
|
|
|
|
|
|
|
|
|
|
im->populate_vert();
|
|
|
|
|
int out_totvert = im->vert_size();
|
2023-07-24 22:06:55 +02:00
|
|
|
int out_faces_num = im->face_size();
|
2021-02-21 17:57:03 -05:00
|
|
|
int out_totloop = 0;
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
for (const meshintersect::Face *f : im->faces()) {
|
2021-02-21 17:57:03 -05:00
|
|
|
out_totloop += f->size();
|
|
|
|
|
}
|
|
|
|
|
/* Will calculate edges later. */
|
|
|
|
|
Mesh *result = BKE_mesh_new_nomain_from_template(
|
2023-07-24 22:06:55 +02:00
|
|
|
mim.meshes[0], out_totvert, 0, out_faces_num, out_totloop);
|
2021-02-21 17:57:03 -05:00
|
|
|
|
2023-07-24 22:06:55 +02:00
|
|
|
merge_vertex_loop_face_customdata_layers(result, mim);
|
2021-02-21 17:57:03 -05:00
|
|
|
/* Set the vertex coordinate values and other data. */
|
Mesh: Move positions to a generic attribute
**Changes**
As described in T93602, this patch removes all use of the `MVert`
struct, replacing it with a generic named attribute with the name
`"position"`, consistent with other geometry types.
Variable names have been changed from `verts` to `positions`, to align
with the attribute name and the more generic design (positions are not
vertices, they are just an attribute stored on the point domain).
This change is made possible by previous commits that moved all other
data out of `MVert` to runtime data or other generic attributes. What
remains is mostly a simple type change. Though, the type still shows up
859 times, so the patch is quite large.
One compromise is that now `CD_MASK_BAREMESH` now contains
`CD_PROP_FLOAT3`. With the general move towards generic attributes
over custom data types, we are removing use of these type masks anyway.
**Benefits**
The most obvious benefit is reduced memory usage and the benefits
that brings in memory-bound situations. `float3` is only 3 bytes, in
comparison to `MVert` which was 4. When there are millions of vertices
this starts to matter more.
The other benefits come from using a more generic type. Instead of
writing algorithms specifically for `MVert`, code can just use arrays
of vectors. This will allow eliminating many temporary arrays or
wrappers used to extract positions.
Many possible improvements aren't implemented in this patch, though
I did switch simplify or remove the process of creating temporary
position arrays in a few places.
The design clarity that "positions are just another attribute" brings
allows removing explicit copying of vertices in some procedural
operations-- they are just processed like most other attributes.
**Performance**
This touches so many areas that it's hard to benchmark exhaustively,
but I observed some areas as examples.
* The mesh line node with 4 million count was 1.5x (8ms to 12ms) faster.
* The Spring splash screen went from ~4.3 to ~4.5 fps.
* The subdivision surface modifier/node was slightly faster
RNA access through Python may be slightly slower, since now we need
a name lookup instead of just a custom data type lookup for each index.
**Future Improvements**
* Remove uses of "vert_coords" functions:
* `BKE_mesh_vert_coords_alloc`
* `BKE_mesh_vert_coords_get`
* `BKE_mesh_vert_coords_apply{_with_mat4}`
* Remove more hidden copying of positions
* General simplification now possible in many areas
* Convert more code to C++ to use `float3` instead of `float[3]`
* Currently `reinterpret_cast` is used for those C-API functions
Differential Revision: https://developer.blender.org/D15982
2023-01-10 00:10:43 -05:00
|
|
|
MutableSpan<float3> positions = result->vert_positions_for_write();
|
2021-02-21 17:57:03 -05:00
|
|
|
for (int vi : im->vert_index_range()) {
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
const meshintersect::Vert *v = im->vert(vi);
|
|
|
|
|
if (v->orig != meshintersect::NO_INDEX) {
|
2021-02-21 17:57:03 -05:00
|
|
|
const Mesh *orig_me;
|
|
|
|
|
int index_in_orig_me;
|
Mesh: Move selection flags to generic attributes
Using the attribute name semantics from T97452, this patch moves the
selection status of mesh elements from the `SELECT` of vertices, and
edges, and the `ME_FACE_SEL` of faces to generic boolean attribute
Storing this data as generic attributes can significantly simplify and
improve code, as described in T95965.
The attributes are called `.select_vert`, `.select_edge`, and
`.select_poly`. The `.` prefix means they are "UI attributes",so they
still contain original data edited by users, but they aren't meant to
be accessed procedurally by the user in arbitrary situations. They are
also be hidden in the spreadsheet and the attribute list.
Until 4.0, the attributes are still written to and read from the mesh
in the old way, so neither forward nor backward compatibility are
affected. This means memory requirements will be increased by one byte
per element when selection is used. When the flags are removed
completely, requirements will decrease.
Further notes:
* The `MVert` flag is empty at runtime now, so it can be ignored.
* `BMesh` is unchanged, otherwise the change would be much larger.
* Many tests have slightly different results, since the selection
attribute uses more generic propagation. Previously you couldn't
really rely on edit mode selections being propagated procedurally.
Now it mostly works as expected.
Similar to 2480b55f216c
Ref T95965
Differential Revision: https://developer.blender.org/D15795
2022-09-23 09:38:37 -05:00
|
|
|
mim.input_mvert_for_orig_index(v->orig, &orig_me, &index_in_orig_me);
|
|
|
|
|
copy_vert_attributes(result, orig_me, vi, index_in_orig_me);
|
2021-02-21 17:57:03 -05:00
|
|
|
}
|
Mesh: Move positions to a generic attribute
**Changes**
As described in T93602, this patch removes all use of the `MVert`
struct, replacing it with a generic named attribute with the name
`"position"`, consistent with other geometry types.
Variable names have been changed from `verts` to `positions`, to align
with the attribute name and the more generic design (positions are not
vertices, they are just an attribute stored on the point domain).
This change is made possible by previous commits that moved all other
data out of `MVert` to runtime data or other generic attributes. What
remains is mostly a simple type change. Though, the type still shows up
859 times, so the patch is quite large.
One compromise is that now `CD_MASK_BAREMESH` now contains
`CD_PROP_FLOAT3`. With the general move towards generic attributes
over custom data types, we are removing use of these type masks anyway.
**Benefits**
The most obvious benefit is reduced memory usage and the benefits
that brings in memory-bound situations. `float3` is only 3 bytes, in
comparison to `MVert` which was 4. When there are millions of vertices
this starts to matter more.
The other benefits come from using a more generic type. Instead of
writing algorithms specifically for `MVert`, code can just use arrays
of vectors. This will allow eliminating many temporary arrays or
wrappers used to extract positions.
Many possible improvements aren't implemented in this patch, though
I did switch simplify or remove the process of creating temporary
position arrays in a few places.
The design clarity that "positions are just another attribute" brings
allows removing explicit copying of vertices in some procedural
operations-- they are just processed like most other attributes.
**Performance**
This touches so many areas that it's hard to benchmark exhaustively,
but I observed some areas as examples.
* The mesh line node with 4 million count was 1.5x (8ms to 12ms) faster.
* The Spring splash screen went from ~4.3 to ~4.5 fps.
* The subdivision surface modifier/node was slightly faster
RNA access through Python may be slightly slower, since now we need
a name lookup instead of just a custom data type lookup for each index.
**Future Improvements**
* Remove uses of "vert_coords" functions:
* `BKE_mesh_vert_coords_alloc`
* `BKE_mesh_vert_coords_get`
* `BKE_mesh_vert_coords_apply{_with_mat4}`
* Remove more hidden copying of positions
* General simplification now possible in many areas
* Convert more code to C++ to use `float3` instead of `float[3]`
* Currently `reinterpret_cast` is used for those C-API functions
Differential Revision: https://developer.blender.org/D15982
2023-01-10 00:10:43 -05:00
|
|
|
copy_v3fl_v3db(positions[vi], v->co);
|
2021-02-21 17:57:03 -05:00
|
|
|
}
|
|
|
|
|
|
2023-07-24 22:06:55 +02:00
|
|
|
/* Set the loop-start and total-loops for each output face,
|
2021-02-21 17:57:03 -05:00
|
|
|
* and set the vertices in the appropriate loops. */
|
2022-08-31 09:09:01 -05:00
|
|
|
bke::SpanAttributeWriter<int> dst_material_indices =
|
2022-09-07 21:41:39 -05:00
|
|
|
result->attributes_for_write().lookup_or_add_for_write_only_span<int>("material_index",
|
2023-12-20 13:13:16 -05:00
|
|
|
bke::AttrDomain::Face);
|
2021-02-21 17:57:03 -05:00
|
|
|
int cur_loop_index = 0;
|
Mesh: Replace MLoop struct with generic attributes
Implements #102359.
Split the `MLoop` struct into two separate integer arrays called
`corner_verts` and `corner_edges`, referring to the vertex each corner
is attached to and the next edge around the face at each corner. These
arrays can be sliced to give access to the edges or vertices in a face.
Then they are often referred to as "poly_verts" or "poly_edges".
The main benefits are halving the necessary memory bandwidth when only
one array is used and simplifications from using regular integer indices
instead of a special-purpose struct.
The commit also starts a renaming from "loop" to "corner" in mesh code.
Like the other mesh struct of array refactors, forward compatibility is
kept by writing files with the older format. This will be done until 4.0
to ease the transition process.
Looking at a small portion of the patch should give a good impression
for the rest of the changes. I tried to make the changes as small as
possible so it's easy to tell the correctness from the diff. Though I
found Blender developers have been very inventive over the last decade
when finding different ways to loop over the corners in a face.
For performance, nearly every piece of code that deals with `Mesh` is
slightly impacted. Any algorithm that is memory bottle-necked should
see an improvement. For example, here is a comparison of interpolating
a vertex float attribute to face corners (Ryzen 3700x):
**Before** (Average: 3.7 ms, Min: 3.4 ms)
```
threading::parallel_for(loops.index_range(), 4096, [&](IndexRange range) {
for (const int64_t i : range) {
dst[i] = src[loops[i].v];
}
});
```
**After** (Average: 2.9 ms, Min: 2.6 ms)
```
array_utils::gather(src, corner_verts, dst);
```
That's an improvement of 28% to the average timings, and it's also a
simplification, since an index-based routine can be used instead.
For more examples using the new arrays, see the design task.
Pull Request: https://projects.blender.org/blender/blender/pulls/104424
2023-03-20 15:55:13 +01:00
|
|
|
MutableSpan<int> dst_corner_verts = result->corner_verts_for_write();
|
2023-07-24 22:06:55 +02:00
|
|
|
MutableSpan<int> dst_face_offsets = result->face_offsets_for_write();
|
2021-02-21 17:57:03 -05:00
|
|
|
for (int fi : im->face_index_range()) {
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
const meshintersect::Face *f = im->face(fi);
|
2021-02-21 17:57:03 -05:00
|
|
|
const Mesh *orig_me;
|
|
|
|
|
int index_in_orig_me;
|
|
|
|
|
int orig_me_index;
|
2023-07-24 22:06:55 +02:00
|
|
|
const IndexRange orig_face = mim.input_face_for_orig_index(
|
2021-02-21 17:57:03 -05:00
|
|
|
f->orig, &orig_me, &orig_me_index, &index_in_orig_me);
|
2023-07-24 22:06:55 +02:00
|
|
|
dst_face_offsets[fi] = cur_loop_index;
|
2021-02-21 17:57:03 -05:00
|
|
|
for (int j : f->index_range()) {
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
const meshintersect::Vert *vf = f->vert[j];
|
2021-02-21 17:57:03 -05:00
|
|
|
const int vfi = im->lookup_vert(vf);
|
Mesh: Replace MLoop struct with generic attributes
Implements #102359.
Split the `MLoop` struct into two separate integer arrays called
`corner_verts` and `corner_edges`, referring to the vertex each corner
is attached to and the next edge around the face at each corner. These
arrays can be sliced to give access to the edges or vertices in a face.
Then they are often referred to as "poly_verts" or "poly_edges".
The main benefits are halving the necessary memory bandwidth when only
one array is used and simplifications from using regular integer indices
instead of a special-purpose struct.
The commit also starts a renaming from "loop" to "corner" in mesh code.
Like the other mesh struct of array refactors, forward compatibility is
kept by writing files with the older format. This will be done until 4.0
to ease the transition process.
Looking at a small portion of the patch should give a good impression
for the rest of the changes. I tried to make the changes as small as
possible so it's easy to tell the correctness from the diff. Though I
found Blender developers have been very inventive over the last decade
when finding different ways to loop over the corners in a face.
For performance, nearly every piece of code that deals with `Mesh` is
slightly impacted. Any algorithm that is memory bottle-necked should
see an improvement. For example, here is a comparison of interpolating
a vertex float attribute to face corners (Ryzen 3700x):
**Before** (Average: 3.7 ms, Min: 3.4 ms)
```
threading::parallel_for(loops.index_range(), 4096, [&](IndexRange range) {
for (const int64_t i : range) {
dst[i] = src[loops[i].v];
}
});
```
**After** (Average: 2.9 ms, Min: 2.6 ms)
```
array_utils::gather(src, corner_verts, dst);
```
That's an improvement of 28% to the average timings, and it's also a
simplification, since an index-based routine can be used instead.
For more examples using the new arrays, see the design task.
Pull Request: https://projects.blender.org/blender/blender/pulls/104424
2023-03-20 15:55:13 +01:00
|
|
|
dst_corner_verts[cur_loop_index] = vfi;
|
2021-02-21 17:57:03 -05:00
|
|
|
++cur_loop_index;
|
|
|
|
|
}
|
2021-03-14 11:39:56 -04:00
|
|
|
|
2023-07-24 22:06:55 +02:00
|
|
|
copy_face_attributes(result,
|
2021-04-02 00:16:01 -05:00
|
|
|
orig_me,
|
|
|
|
|
fi,
|
|
|
|
|
index_in_orig_me,
|
|
|
|
|
(mim.material_remaps.size() > 0) ?
|
|
|
|
|
mim.material_remaps[orig_me_index].as_span() :
|
2022-08-31 09:09:01 -05:00
|
|
|
Span<short>(),
|
|
|
|
|
dst_material_indices.span);
|
Mesh: Replace MPoly struct with offset indices
Implements #95967.
Currently the `MPoly` struct is 12 bytes, and stores the index of a
face's first corner and the number of corners/verts/edges. Polygons
and corners are always created in order by Blender, meaning each
face's corners will be after the previous face's corners. We can take
advantage of this fact and eliminate the redundancy in mesh face
storage by only storing a single integer corner offset for each face.
The size of the face is then encoded by the offset of the next face.
The size of a single integer is 4 bytes, so this reduces memory
usage by 3 times.
The same method is used for `CurvesGeometry`, so Blender already has
an abstraction to simplify using these offsets called `OffsetIndices`.
This class is used to easily retrieve a range of corner indices for
each face. This also gives the opportunity for sharing some logic with
curves.
Another benefit of the change is that the offsets and sizes stored in
`MPoly` can no longer disagree with each other. Storing faces in the
order of their corners can simplify some code too.
Face/polygon variables now use the `IndexRange` type, which comes with
quite a few utilities that can simplify code.
Some:
- The offset integer array has to be one longer than the face count to
avoid a branch for every face, which means the data is no longer part
of the mesh's `CustomData`.
- We lose the ability to "reference" an original mesh's offset array
until more reusable CoW from #104478 is committed. That will be added
in a separate commit.
- Since they aren't part of `CustomData`, poly offsets often have to be
copied manually.
- To simplify using `OffsetIndices` in many places, some functions and
structs in headers were moved to only compile in C++.
- All meshes created by Blender use the same order for faces and face
corners, but just in case, meshes with mismatched order are fixed by
versioning code.
- `MeshPolygon.totloop` is no longer editable in RNA. This API break is
necessary here unfortunately. It should be worth it in 3.6, since
that's the best way to allow loading meshes from 4.0, which is
important for an LTS version.
Pull Request: https://projects.blender.org/blender/blender/pulls/105938
2023-04-04 20:39:28 +02:00
|
|
|
copy_or_interp_loop_attributes(result,
|
|
|
|
|
f,
|
2023-07-24 22:06:55 +02:00
|
|
|
IndexRange(dst_face_offsets[fi], f->size()),
|
|
|
|
|
orig_face,
|
Mesh: Replace MPoly struct with offset indices
Implements #95967.
Currently the `MPoly` struct is 12 bytes, and stores the index of a
face's first corner and the number of corners/verts/edges. Polygons
and corners are always created in order by Blender, meaning each
face's corners will be after the previous face's corners. We can take
advantage of this fact and eliminate the redundancy in mesh face
storage by only storing a single integer corner offset for each face.
The size of the face is then encoded by the offset of the next face.
The size of a single integer is 4 bytes, so this reduces memory
usage by 3 times.
The same method is used for `CurvesGeometry`, so Blender already has
an abstraction to simplify using these offsets called `OffsetIndices`.
This class is used to easily retrieve a range of corner indices for
each face. This also gives the opportunity for sharing some logic with
curves.
Another benefit of the change is that the offsets and sizes stored in
`MPoly` can no longer disagree with each other. Storing faces in the
order of their corners can simplify some code too.
Face/polygon variables now use the `IndexRange` type, which comes with
quite a few utilities that can simplify code.
Some:
- The offset integer array has to be one longer than the face count to
avoid a branch for every face, which means the data is no longer part
of the mesh's `CustomData`.
- We lose the ability to "reference" an original mesh's offset array
until more reusable CoW from #104478 is committed. That will be added
in a separate commit.
- Since they aren't part of `CustomData`, poly offsets often have to be
copied manually.
- To simplify using `OffsetIndices` in many places, some functions and
structs in headers were moved to only compile in C++.
- All meshes created by Blender use the same order for faces and face
corners, but just in case, meshes with mismatched order are fixed by
versioning code.
- `MeshPolygon.totloop` is no longer editable in RNA. This API break is
necessary here unfortunately. It should be worth it in 3.6, since
that's the best way to allow loading meshes from 4.0, which is
important for an LTS version.
Pull Request: https://projects.blender.org/blender/blender/pulls/105938
2023-04-04 20:39:28 +02:00
|
|
|
orig_me,
|
|
|
|
|
orig_me_index,
|
|
|
|
|
mim);
|
2021-02-21 17:57:03 -05:00
|
|
|
}
|
2022-08-31 09:09:01 -05:00
|
|
|
dst_material_indices.finish();
|
2021-02-21 17:57:03 -05:00
|
|
|
|
2023-12-20 17:47:10 -05:00
|
|
|
bke::mesh_calc_edges(*result, false, false);
|
2021-02-21 17:57:03 -05:00
|
|
|
merge_edge_customdata_layers(result, mim);
|
|
|
|
|
|
|
|
|
|
/* Now that the MEdges are populated, we can copy over the required attributes and custom layers.
|
|
|
|
|
*/
|
2023-07-24 22:06:55 +02:00
|
|
|
const OffsetIndices dst_polys = result->faces();
|
Mesh: Replace MLoop struct with generic attributes
Implements #102359.
Split the `MLoop` struct into two separate integer arrays called
`corner_verts` and `corner_edges`, referring to the vertex each corner
is attached to and the next edge around the face at each corner. These
arrays can be sliced to give access to the edges or vertices in a face.
Then they are often referred to as "poly_verts" or "poly_edges".
The main benefits are halving the necessary memory bandwidth when only
one array is used and simplifications from using regular integer indices
instead of a special-purpose struct.
The commit also starts a renaming from "loop" to "corner" in mesh code.
Like the other mesh struct of array refactors, forward compatibility is
kept by writing files with the older format. This will be done until 4.0
to ease the transition process.
Looking at a small portion of the patch should give a good impression
for the rest of the changes. I tried to make the changes as small as
possible so it's easy to tell the correctness from the diff. Though I
found Blender developers have been very inventive over the last decade
when finding different ways to loop over the corners in a face.
For performance, nearly every piece of code that deals with `Mesh` is
slightly impacted. Any algorithm that is memory bottle-necked should
see an improvement. For example, here is a comparison of interpolating
a vertex float attribute to face corners (Ryzen 3700x):
**Before** (Average: 3.7 ms, Min: 3.4 ms)
```
threading::parallel_for(loops.index_range(), 4096, [&](IndexRange range) {
for (const int64_t i : range) {
dst[i] = src[loops[i].v];
}
});
```
**After** (Average: 2.9 ms, Min: 2.6 ms)
```
array_utils::gather(src, corner_verts, dst);
```
That's an improvement of 28% to the average timings, and it's also a
simplification, since an index-based routine can be used instead.
For more examples using the new arrays, see the design task.
Pull Request: https://projects.blender.org/blender/blender/pulls/104424
2023-03-20 15:55:13 +01:00
|
|
|
const Span<int> dst_corner_edges = result->corner_edges();
|
2021-02-21 17:57:03 -05:00
|
|
|
for (int fi : im->face_index_range()) {
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
const meshintersect::Face *f = im->face(fi);
|
2023-07-24 22:06:55 +02:00
|
|
|
const IndexRange face = dst_polys[fi];
|
2021-02-21 17:57:03 -05:00
|
|
|
for (int j : f->index_range()) {
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
if (f->edge_orig[j] != meshintersect::NO_INDEX) {
|
2021-02-21 17:57:03 -05:00
|
|
|
const Mesh *orig_me;
|
|
|
|
|
int index_in_orig_me;
|
2023-03-01 14:13:05 +01:00
|
|
|
mim.input_medge_for_orig_index(f->edge_orig[j], &orig_me, &index_in_orig_me);
|
2023-07-24 22:06:55 +02:00
|
|
|
int e_index = dst_corner_edges[face[j]];
|
2023-03-01 14:13:05 +01:00
|
|
|
copy_edge_attributes(result, orig_me, e_index, index_in_orig_me);
|
2021-02-21 17:57:03 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dbg_level > 0) {
|
|
|
|
|
BKE_mesh_validate(result, true, true);
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-14 17:24:22 -04:00
|
|
|
static meshintersect::BoolOpType operation_to_mesh_arr_mode(const Operation operation)
|
|
|
|
|
{
|
|
|
|
|
switch (operation) {
|
|
|
|
|
case Operation::Intersect:
|
|
|
|
|
return meshintersect::BoolOpType::Intersect;
|
|
|
|
|
case Operation::Union:
|
|
|
|
|
return meshintersect::BoolOpType::Union;
|
|
|
|
|
case Operation::Difference:
|
|
|
|
|
return meshintersect::BoolOpType::Difference;
|
|
|
|
|
}
|
|
|
|
|
BLI_assert_unreachable();
|
|
|
|
|
return meshintersect::BoolOpType::None;
|
|
|
|
|
}
|
|
|
|
|
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
static Mesh *mesh_boolean_mesh_arr(Span<const Mesh *> meshes,
|
|
|
|
|
Span<float4x4> transforms,
|
|
|
|
|
const float4x4 &target_transform,
|
|
|
|
|
Span<Array<short>> material_remaps,
|
|
|
|
|
const bool use_self,
|
|
|
|
|
const bool hole_tolerant,
|
2024-03-14 17:24:22 -04:00
|
|
|
const meshintersect::BoolOpType boolean_mode,
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
Vector<int> *r_intersecting_edges)
|
2021-02-21 17:57:03 -05:00
|
|
|
{
|
2023-05-18 15:08:53 -04:00
|
|
|
BLI_assert(transforms.is_empty() || meshes.size() == transforms.size());
|
2023-12-11 13:54:57 -05:00
|
|
|
BLI_assert(material_remaps.is_empty() || material_remaps.size() == meshes.size());
|
2021-04-02 00:16:01 -05:00
|
|
|
if (meshes.size() <= 0) {
|
2021-02-21 17:57:03 -05:00
|
|
|
return nullptr;
|
|
|
|
|
}
|
2021-04-02 00:16:01 -05:00
|
|
|
|
|
|
|
|
const int dbg_level = 0;
|
2021-02-21 17:57:03 -05:00
|
|
|
if (dbg_level > 0) {
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
std::cout << "\nOLD_MESH_INTERSECT, nmeshes = " << meshes.size() << "\n";
|
2021-02-21 17:57:03 -05:00
|
|
|
}
|
|
|
|
|
MeshesToIMeshInfo mim;
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
meshintersect::IMeshArena arena;
|
|
|
|
|
meshintersect::IMesh m_in = meshes_to_imesh(
|
|
|
|
|
meshes, transforms, material_remaps, target_transform, arena, &mim);
|
2021-02-21 17:57:03 -05:00
|
|
|
std::function<int(int)> shape_fn = [&mim](int f) {
|
2023-07-24 22:06:55 +02:00
|
|
|
for (int mi = 0; mi < mim.mesh_face_offset.size() - 1; ++mi) {
|
|
|
|
|
if (f < mim.mesh_face_offset[mi + 1]) {
|
2021-02-21 17:57:03 -05:00
|
|
|
return mi;
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-07-24 22:06:55 +02:00
|
|
|
return int(mim.mesh_face_offset.size()) - 1;
|
2021-02-21 17:57:03 -05:00
|
|
|
};
|
2024-03-14 17:24:22 -04:00
|
|
|
meshintersect::IMesh m_out = boolean_mesh(
|
|
|
|
|
m_in, boolean_mode, meshes.size(), shape_fn, use_self, hole_tolerant, nullptr, &arena);
|
2021-04-02 00:16:01 -05:00
|
|
|
if (dbg_level > 0) {
|
2021-02-21 17:57:03 -05:00
|
|
|
std::cout << m_out;
|
|
|
|
|
write_obj_mesh(m_out, "m_out");
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-04 12:26:50 +02:00
|
|
|
Mesh *result = imesh_to_mesh(&m_out, mim);
|
|
|
|
|
|
|
|
|
|
/* Store intersecting edge indices. */
|
|
|
|
|
if (r_intersecting_edges != nullptr) {
|
2023-07-24 22:06:55 +02:00
|
|
|
const OffsetIndices faces = result->faces();
|
Mesh: Replace MLoop struct with generic attributes
Implements #102359.
Split the `MLoop` struct into two separate integer arrays called
`corner_verts` and `corner_edges`, referring to the vertex each corner
is attached to and the next edge around the face at each corner. These
arrays can be sliced to give access to the edges or vertices in a face.
Then they are often referred to as "poly_verts" or "poly_edges".
The main benefits are halving the necessary memory bandwidth when only
one array is used and simplifications from using regular integer indices
instead of a special-purpose struct.
The commit also starts a renaming from "loop" to "corner" in mesh code.
Like the other mesh struct of array refactors, forward compatibility is
kept by writing files with the older format. This will be done until 4.0
to ease the transition process.
Looking at a small portion of the patch should give a good impression
for the rest of the changes. I tried to make the changes as small as
possible so it's easy to tell the correctness from the diff. Though I
found Blender developers have been very inventive over the last decade
when finding different ways to loop over the corners in a face.
For performance, nearly every piece of code that deals with `Mesh` is
slightly impacted. Any algorithm that is memory bottle-necked should
see an improvement. For example, here is a comparison of interpolating
a vertex float attribute to face corners (Ryzen 3700x):
**Before** (Average: 3.7 ms, Min: 3.4 ms)
```
threading::parallel_for(loops.index_range(), 4096, [&](IndexRange range) {
for (const int64_t i : range) {
dst[i] = src[loops[i].v];
}
});
```
**After** (Average: 2.9 ms, Min: 2.6 ms)
```
array_utils::gather(src, corner_verts, dst);
```
That's an improvement of 28% to the average timings, and it's also a
simplification, since an index-based routine can be used instead.
For more examples using the new arrays, see the design task.
Pull Request: https://projects.blender.org/blender/blender/pulls/104424
2023-03-20 15:55:13 +01:00
|
|
|
const Span<int> corner_edges = result->corner_edges();
|
2022-04-04 12:26:50 +02:00
|
|
|
for (int fi : m_out.face_index_range()) {
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
const meshintersect::Face &face = *m_out.face(fi);
|
2023-07-24 22:06:55 +02:00
|
|
|
const IndexRange mesh_face = faces[fi];
|
Mesh: Replace MPoly struct with offset indices
Implements #95967.
Currently the `MPoly` struct is 12 bytes, and stores the index of a
face's first corner and the number of corners/verts/edges. Polygons
and corners are always created in order by Blender, meaning each
face's corners will be after the previous face's corners. We can take
advantage of this fact and eliminate the redundancy in mesh face
storage by only storing a single integer corner offset for each face.
The size of the face is then encoded by the offset of the next face.
The size of a single integer is 4 bytes, so this reduces memory
usage by 3 times.
The same method is used for `CurvesGeometry`, so Blender already has
an abstraction to simplify using these offsets called `OffsetIndices`.
This class is used to easily retrieve a range of corner indices for
each face. This also gives the opportunity for sharing some logic with
curves.
Another benefit of the change is that the offsets and sizes stored in
`MPoly` can no longer disagree with each other. Storing faces in the
order of their corners can simplify some code too.
Face/polygon variables now use the `IndexRange` type, which comes with
quite a few utilities that can simplify code.
Some:
- The offset integer array has to be one longer than the face count to
avoid a branch for every face, which means the data is no longer part
of the mesh's `CustomData`.
- We lose the ability to "reference" an original mesh's offset array
until more reusable CoW from #104478 is committed. That will be added
in a separate commit.
- Since they aren't part of `CustomData`, poly offsets often have to be
copied manually.
- To simplify using `OffsetIndices` in many places, some functions and
structs in headers were moved to only compile in C++.
- All meshes created by Blender use the same order for faces and face
corners, but just in case, meshes with mismatched order are fixed by
versioning code.
- `MeshPolygon.totloop` is no longer editable in RNA. This API break is
necessary here unfortunately. It should be worth it in 3.6, since
that's the best way to allow loading meshes from 4.0, which is
important for an LTS version.
Pull Request: https://projects.blender.org/blender/blender/pulls/105938
2023-04-04 20:39:28 +02:00
|
|
|
for (int i : face.index_range()) {
|
|
|
|
|
if (face.is_intersect[i]) {
|
2023-07-24 22:06:55 +02:00
|
|
|
int e_index = corner_edges[mesh_face[i]];
|
2022-04-04 12:26:50 +02:00
|
|
|
r_intersecting_edges->append(e_index);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
2021-02-21 17:57:03 -05:00
|
|
|
}
|
|
|
|
|
|
2024-03-14 18:50:19 -04:00
|
|
|
#endif // WITH_GMP
|
|
|
|
|
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
|
/** \name Float Boolean
|
|
|
|
|
* \{ */
|
|
|
|
|
|
|
|
|
|
/* has no meaning for faces, do this so we can tell which face is which */
|
|
|
|
|
#define BM_FACE_TAG BM_ELEM_DRAW
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Function use to say what operand a face is part of, based on the `BM_FACE_TAG`,`
|
|
|
|
|
* which is set in `bm_mesh_create`.
|
|
|
|
|
*/
|
|
|
|
|
static int face_boolean_operand(BMFace *f, void * /*user_data*/)
|
|
|
|
|
{
|
|
|
|
|
return BM_elem_flag_test(f, BM_FACE_TAG) ? 0 : 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Create a BMesh that is the concatenation of the given meshes.
|
|
|
|
|
* The corresponding mesh-to-world transformations are also given,
|
|
|
|
|
* as well as a target_tranform.
|
|
|
|
|
* A triangulation is also calculated and returned in the last two
|
|
|
|
|
* parameters.
|
|
|
|
|
* The faces of the first mesh are tagged with BM_FACE_TAG so that the
|
|
|
|
|
* face_boolean_operand() function can distinguish those faces from the
|
|
|
|
|
* rest.
|
|
|
|
|
* The caller is responsible for using `BM_mesh_free` on the returned
|
|
|
|
|
* BMesh, and calling `MEM_freeN` on the returned looptris.
|
|
|
|
|
*
|
|
|
|
|
* TODO: maybe figure out how to use the join_geometries() function
|
|
|
|
|
* to join all the meshes into one mesh first, and then convert
|
|
|
|
|
* that single mesh to BMesh. Issues with that include needing
|
|
|
|
|
* to apply the transforms and material remaps.
|
|
|
|
|
*/
|
|
|
|
|
static BMesh *mesh_bm_concat(Span<const Mesh *> meshes,
|
|
|
|
|
Span<float4x4> transforms,
|
|
|
|
|
const float4x4 &target_transform,
|
|
|
|
|
Span<Array<short>> material_remaps,
|
2024-03-23 17:43:38 +01:00
|
|
|
Array<std::array<BMLoop *, 3>> &r_looptris)
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
{
|
|
|
|
|
const int meshes_num = meshes.size();
|
|
|
|
|
BLI_assert(meshes_num >= 1);
|
|
|
|
|
bool ok;
|
|
|
|
|
float4x4 inv_target_mat = math::invert(target_transform, ok);
|
|
|
|
|
if (!ok) {
|
|
|
|
|
BLI_assert_unreachable();
|
|
|
|
|
inv_target_mat = float4x4::identity();
|
|
|
|
|
}
|
|
|
|
|
Array<float4x4> to_target(meshes_num);
|
|
|
|
|
Array<bool> is_negative_transform(meshes_num);
|
|
|
|
|
Array<bool> is_flip(meshes_num);
|
|
|
|
|
const int tsize = transforms.size();
|
|
|
|
|
for (const int i : IndexRange(meshes_num)) {
|
|
|
|
|
if (tsize > i) {
|
|
|
|
|
to_target[i] = inv_target_mat * transforms[i];
|
|
|
|
|
is_negative_transform[i] = math::is_negative(transforms[i]);
|
|
|
|
|
is_flip[i] = is_negative_transform[i] != is_negative_transform[0];
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
to_target[i] = inv_target_mat;
|
|
|
|
|
is_negative_transform[i] = false;
|
|
|
|
|
is_flip[i] = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Make a BMesh that will be a concatenation of the elements of all the meshes */
|
|
|
|
|
BMAllocTemplate allocsize;
|
|
|
|
|
allocsize.totvert = 0;
|
|
|
|
|
allocsize.totedge = 0;
|
|
|
|
|
allocsize.totloop = 0;
|
|
|
|
|
allocsize.totface = 0;
|
|
|
|
|
for (const int i : meshes.index_range()) {
|
|
|
|
|
allocsize.totvert += meshes[i]->verts_num;
|
|
|
|
|
allocsize.totedge += meshes[i]->edges_num;
|
|
|
|
|
allocsize.totloop += meshes[i]->corners_num;
|
|
|
|
|
allocsize.totface += meshes[i]->faces_num;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BMeshCreateParams bmesh_create_params{};
|
|
|
|
|
BMesh *bm = BM_mesh_create(&allocsize, &bmesh_create_params);
|
|
|
|
|
|
|
|
|
|
BM_mesh_copy_init_customdata_from_mesh_array(
|
|
|
|
|
bm, const_cast<const Mesh **>(meshes.begin()), meshes_num, &allocsize);
|
|
|
|
|
|
|
|
|
|
BMeshFromMeshParams bmesh_from_mesh_params{};
|
|
|
|
|
bmesh_from_mesh_params.calc_face_normal = true;
|
|
|
|
|
bmesh_from_mesh_params.calc_vert_normal = true;
|
|
|
|
|
|
|
|
|
|
Array<int> verts_end(meshes_num);
|
|
|
|
|
Array<int> faces_end(meshes_num);
|
|
|
|
|
verts_end[0] = meshes[0]->verts_num;
|
|
|
|
|
faces_end[0] = meshes[0]->faces_num;
|
|
|
|
|
for (const int i : meshes.index_range()) {
|
|
|
|
|
/* Append meshes[i] elements and data to bm. */
|
|
|
|
|
BM_mesh_bm_from_me(bm, meshes[i], &bmesh_from_mesh_params);
|
|
|
|
|
if (i > 0) {
|
|
|
|
|
verts_end[i] = verts_end[i - 1] + meshes[i]->verts_num;
|
|
|
|
|
faces_end[i] = faces_end[i - 1] + meshes[i]->faces_num;
|
|
|
|
|
if (is_flip[i]) {
|
|
|
|
|
/* Need to flip face normals to match that of mesh[0]. */
|
|
|
|
|
const int cd_loop_mdisp_offset = CustomData_get_offset(&bm->ldata, CD_MDISPS);
|
|
|
|
|
BM_mesh_elem_table_ensure(bm, BM_FACE);
|
|
|
|
|
for (int j = faces_end[i - 1]; j < faces_end[i]; j++) {
|
|
|
|
|
BMFace *efa = bm->ftable[j];
|
|
|
|
|
BM_face_normal_flip_ex(bm, efa, cd_loop_mdisp_offset, true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Make a triangulation of all polys before transforming vertices
|
|
|
|
|
* so we can use the original normals. */
|
|
|
|
|
const int looptris_tot = poly_to_tri_count(bm->totface, bm->totloop);
|
2024-03-23 17:43:38 +01:00
|
|
|
r_looptris.reinitialize(looptris_tot);
|
|
|
|
|
BM_mesh_calc_tessellation_beauty(bm, r_looptris);
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
|
2024-03-21 10:01:43 +11:00
|
|
|
/* Transform the vertices that into the desired target_transform space. */
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
BMIter iter;
|
|
|
|
|
BMVert *eve;
|
|
|
|
|
int i = 0;
|
|
|
|
|
int mesh_index = 0;
|
|
|
|
|
BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
|
|
|
|
|
copy_v3_v3(eve->co, math::transform_point(to_target[mesh_index], float3(eve->co)));
|
|
|
|
|
++i;
|
|
|
|
|
if (i == verts_end[mesh_index]) {
|
|
|
|
|
mesh_index++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Transform face normals and tag the first-operand faces.
|
|
|
|
|
* Also, apply material remaps. */
|
|
|
|
|
BMFace *efa;
|
|
|
|
|
i = 0;
|
|
|
|
|
mesh_index = 0;
|
|
|
|
|
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
|
|
|
|
|
copy_v3_v3(efa->no, math::transform_direction(to_target[mesh_index], float3(efa->no)));
|
|
|
|
|
if (is_negative_transform[mesh_index]) {
|
|
|
|
|
negate_v3(efa->no);
|
|
|
|
|
}
|
|
|
|
|
normalize_v3(efa->no);
|
|
|
|
|
|
|
|
|
|
/* Temp tag used in `face_boolean_operand()` to test for operand 0. */
|
|
|
|
|
if (i < faces_end[0]) {
|
|
|
|
|
BM_elem_flag_enable(efa, BM_FACE_TAG);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Remap material. */
|
|
|
|
|
int cur_mat = efa->mat_nr;
|
|
|
|
|
if (cur_mat < material_remaps[mesh_index].size()) {
|
|
|
|
|
int new_mat = material_remaps[mesh_index][cur_mat];
|
|
|
|
|
if (new_mat >= 0) {
|
|
|
|
|
efa->mat_nr = material_remaps[mesh_index][cur_mat];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
++i;
|
|
|
|
|
if (i == faces_end[mesh_index]) {
|
|
|
|
|
mesh_index++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return bm;
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-14 17:24:22 -04:00
|
|
|
static int operation_to_float_mode(const Operation operation)
|
|
|
|
|
{
|
|
|
|
|
switch (operation) {
|
|
|
|
|
case Operation::Intersect:
|
|
|
|
|
return BMESH_ISECT_BOOLEAN_ISECT;
|
|
|
|
|
case Operation::Union:
|
|
|
|
|
return BMESH_ISECT_BOOLEAN_UNION;
|
|
|
|
|
case Operation::Difference:
|
|
|
|
|
return BMESH_ISECT_BOOLEAN_DIFFERENCE;
|
|
|
|
|
}
|
|
|
|
|
BLI_assert_unreachable();
|
|
|
|
|
return BMESH_ISECT_BOOLEAN_NONE;
|
|
|
|
|
}
|
|
|
|
|
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
static Mesh *mesh_boolean_float(Span<const Mesh *> meshes,
|
|
|
|
|
Span<float4x4> transforms,
|
|
|
|
|
const float4x4 &target_transform,
|
|
|
|
|
Span<Array<short>> material_remaps,
|
2024-03-14 17:24:22 -04:00
|
|
|
const int boolean_mode,
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
Vector<int> * /*r_intersecting_edges*/)
|
|
|
|
|
{
|
|
|
|
|
BLI_assert(meshes.size() == transforms.size() || transforms.size() == 0);
|
|
|
|
|
BLI_assert(material_remaps.size() == 0 || material_remaps.size() == meshes.size());
|
|
|
|
|
if (meshes.is_empty()) {
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (meshes.size() == 1) {
|
|
|
|
|
/* The float solver doesn't do self union. Just return nullptr, which will
|
|
|
|
|
* cause geometry nodes to leave the input as is. */
|
2024-05-20 13:18:24 -04:00
|
|
|
return BKE_mesh_copy_for_eval(*meshes[0]);
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
}
|
|
|
|
|
|
2024-03-23 17:43:38 +01:00
|
|
|
Array<std::array<BMLoop *, 3>> looptris;
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
if (meshes.size() == 2) {
|
2024-03-23 17:43:38 +01:00
|
|
|
BMesh *bm = mesh_bm_concat(meshes, transforms, target_transform, material_remaps, looptris);
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
BM_mesh_intersect(bm,
|
|
|
|
|
looptris,
|
|
|
|
|
face_boolean_operand,
|
|
|
|
|
nullptr,
|
|
|
|
|
false,
|
|
|
|
|
false,
|
|
|
|
|
true,
|
|
|
|
|
true,
|
|
|
|
|
false,
|
|
|
|
|
false,
|
|
|
|
|
boolean_mode,
|
|
|
|
|
1e-6f);
|
|
|
|
|
Mesh *result = BKE_mesh_from_bmesh_for_eval_nomain(bm, nullptr, meshes[0]);
|
|
|
|
|
BM_mesh_free(bm);
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Iteratively operate with each operand. */
|
|
|
|
|
Array<const Mesh *> two_meshes = {meshes[0], meshes[1]};
|
|
|
|
|
Array<float4x4> two_transforms = {transforms[0], transforms[1]};
|
|
|
|
|
Array<Array<short>> two_remaps = {material_remaps[0], material_remaps[1]};
|
|
|
|
|
Mesh *prev_result_mesh = nullptr;
|
|
|
|
|
for (const int i : meshes.index_range().drop_back(1)) {
|
|
|
|
|
BMesh *bm = mesh_bm_concat(
|
2024-03-23 17:43:38 +01:00
|
|
|
two_meshes, two_transforms, float4x4::identity(), two_remaps, looptris);
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
BM_mesh_intersect(bm,
|
|
|
|
|
looptris,
|
|
|
|
|
face_boolean_operand,
|
|
|
|
|
nullptr,
|
|
|
|
|
false,
|
|
|
|
|
false,
|
|
|
|
|
true,
|
|
|
|
|
true,
|
|
|
|
|
false,
|
|
|
|
|
false,
|
|
|
|
|
boolean_mode,
|
|
|
|
|
1e-6f);
|
|
|
|
|
Mesh *result_i_mesh = BKE_mesh_from_bmesh_for_eval_nomain(bm, nullptr, meshes[0]);
|
|
|
|
|
BM_mesh_free(bm);
|
|
|
|
|
if (prev_result_mesh != nullptr) {
|
|
|
|
|
/* Except in the first iteration, two_meshes[0] holds the intermediate
|
2024-03-21 10:01:43 +11:00
|
|
|
* mesh result from the previous iteration. */
|
2024-04-18 13:52:20 +02:00
|
|
|
BKE_id_free(nullptr, prev_result_mesh);
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
}
|
|
|
|
|
if (i < meshes.size() - 2) {
|
|
|
|
|
two_meshes[0] = result_i_mesh;
|
|
|
|
|
two_meshes[1] = meshes[i + 2];
|
|
|
|
|
two_transforms[0] = float4x4::identity();
|
|
|
|
|
two_transforms[1] = transforms[i + 2];
|
|
|
|
|
two_remaps[0] = {};
|
|
|
|
|
two_remaps[1] = material_remaps[i + 2];
|
|
|
|
|
prev_result_mesh = result_i_mesh;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
return result_i_mesh;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BLI_assert_unreachable();
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** \} */
|
|
|
|
|
|
|
|
|
|
Mesh *mesh_boolean(Span<const Mesh *> meshes,
|
|
|
|
|
Span<float4x4> transforms,
|
|
|
|
|
const float4x4 &target_transform,
|
|
|
|
|
Span<Array<short>> material_remaps,
|
|
|
|
|
BooleanOpParameters op_params,
|
|
|
|
|
Solver solver,
|
|
|
|
|
Vector<int> *r_intersecting_edges)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
switch (solver) {
|
|
|
|
|
case Solver::Float:
|
|
|
|
|
return mesh_boolean_float(meshes,
|
|
|
|
|
transforms,
|
|
|
|
|
target_transform,
|
|
|
|
|
material_remaps,
|
2024-03-14 17:24:22 -04:00
|
|
|
operation_to_float_mode(op_params.boolean_mode),
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
r_intersecting_edges);
|
|
|
|
|
case Solver::MeshArr:
|
2024-03-14 18:50:19 -04:00
|
|
|
#ifdef WITH_GMP
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
return mesh_boolean_mesh_arr(meshes,
|
|
|
|
|
transforms,
|
|
|
|
|
target_transform,
|
|
|
|
|
material_remaps,
|
|
|
|
|
!op_params.no_self_intersections,
|
|
|
|
|
!op_params.watertight,
|
2024-03-14 17:24:22 -04:00
|
|
|
operation_to_mesh_arr_mode(op_params.boolean_mode),
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
r_intersecting_edges);
|
2024-03-14 18:50:19 -04:00
|
|
|
#else
|
|
|
|
|
return nullptr;
|
|
|
|
|
#endif
|
Geometry Nodes: Add float solver to mesh boolean node
This adds a "Solver" option to the geo boolean node, with the options
Exact and Float.
The current geo boolean node only uses the Exact solver.
This adds the ability to use the faster original floating point boolean solver.
The float solver has issues with coplanar and other coincident geometry,
but is generally much faster than the Exact solver, and users have asked
for this option (which is available in the Boolean Modifier and edit mode
boolean tool).
Like the modifier, the Float solver needs to convert the Mesh to BMesh,
do the operation, and then convert back to Mesh. It also has to do it
iteratively if more than two operands are supplied.
This is the first of a planned series of commits that will add a
new exact boolean solver, based on the Ember paper, as a solver option.
Ember will be much faster than the current exact solver, but may still not
be as fast as float, and also will not handle some non-volume-enclosing
inputs as well as Float, so it is likely that the Float solver will always remain.
We may eventually retire the old Exact Solver, however.
This commit also prepares for more sensible code in the future by
changing the internal enum names for the solvers to better reflect the
algorithms used: Fast -> Float, and Exact -> Mesh_Arr (which means
"Mesh Arrangments, the name of the paper upon which the current
exact solver is based).
Co-authored-by: Howard Trickey <trickey@google.com>
Co-authored-by: Hans Goudey <hans@blender.org>
Pull Request: https://projects.blender.org/blender/blender/pulls/119294
2024-03-14 20:49:57 +01:00
|
|
|
default:
|
|
|
|
|
BLI_assert_unreachable();
|
|
|
|
|
}
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace blender::geometry::boolean
|