-
Notifications
You must be signed in to change notification settings - Fork 1.5k
PMP: Accelerate isotropic remeshing #5507
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
I also replaced some |
@janetournois when I simplify (that is a target edge length larger than the average edge length) iphigenia.off, we spend 16% of the time in an exact collinearity test. Is that by accident or by construction? I think there is a flaw. For the first |
@janetournois can we avoid this |
Intersections_3/include/CGAL/Intersections_3/internal/Bbox_3_Sphere_3_do_intersect.h
Outdated
Show resolved
Hide resolved
@@ -265,6 +264,7 @@ class Do_intersect_3 | |||
if (double_tmp_result < -eps) | |||
return true; | |||
else { | |||
// return true; // AF: just to test conservative approach |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lrineau Maybe you have an idea for the following problem: We use this sphere/bbox test in the AABB tree for finding the closest triangle. While vtuning code I noticed that there are filter failures that is we do the test with exact arithmetic. I could well live with a true
(that is overlap) in case of uncertainly. The question is, if we have to add such a functor to the kernel, or if we can add somehow a parameter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That would be a sort of "possibly intersect" instead of "do intersect".
CGAL::internal::Static_filters_predicates::Do_intersect_3
could have a third template parameter (a non-type template argument, I suggest a dedicated enum, to avoid the curve of a Boolean parameter), with a default-value.
Then we can add a new functor name in the Kernel concept, and it would be implemented using either Do_intersect_3
or CGAL::internal::Static_filters_predicates::Do_intersect_3
with the special value as third template argument.
I might actually be more efficient to implement that possibly_intersect(sphere, bbox)
by do_overlap(sphere.bbox(), bbox)
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that I also mentioned the tag this morning with #4654 in mind where we also brought the tag onto the table to allow/forbid degenerate input.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To use the bbox of the sphere makes it 25% slower.
@@ -1,6 +1,7 @@ | |||
#define EARLY |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be removed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No longer needed. It was for an #ifdef EARLY
which I had in the code.
std::cout << "Read: " << t.time() << " sec" << std::endl; | ||
t.reset(); | ||
|
||
double target_edge_length = (argc > 2) ? std::stod(std::string(argv[2])) : 1.0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason to change the previous default?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By accident.
for(halfedge_descriptor h : halfedges(mesh_)) | ||
{ | ||
vertex_descriptor t = target(h, mesh_); | ||
put(degree, t, get(degree,t)+1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@janetournois shall the degree depend only on the selected edges? This matters only for vertices on the boundary of a selection.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The degree of a vertex that stands on the boundary of the selection (i.e. on a PATCH_BORDER
) should count only internal edges.
Here all edges are counted, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that in your code, IRC you were using degree()
so Andreas' code does the same thing the original (to be checked)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But in the original code we call the degree()
function for the vertex which does not distinguish either.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right.
valence(v)
and target_valence(v)
(which is 4 on borders and 6 elsewhere) both take into account only the "real" borders, not the patch borders.
It's not wrong, but maybe we can improve that, when a vertex stands at the limit between a patch to be remeshed and a patched to be left as is.
We can keep it this way for now.
@@ -859,6 +875,12 @@ namespace internal { | |||
vvb -= 1; | |||
vvc += 1; | |||
vvd += 1; | |||
#ifdef VALE |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you want to keep that ? you observe no gain when activating it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In fact THAT is the code we must take.
@@ -1879,8 +1913,10 @@ namespace internal { | |||
bool check_normals(const HalfedgeRange& hedges) const | |||
{ | |||
std::size_t nb_patches = patch_id_to_index_map.size(); | |||
//std::vector<boost::optional<Vector_3> > normal_per_patch(nb_patches,boost::none); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. I later replaced it with two vectors. By the way I am not sure if vector<bool>
is a good idea, and if it should not be vector<int>
instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why would it be bad?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because it is more time consuming to change a bit inside an int.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but you checked with optional and vector<bool>
was faster? I agree with int since nb_patches is not expected to be very large
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did not really see a difference in vtune but sticked to the second solution. I don''t agree on what you say on nb_patches
. If it is the number of patches of the data set and not only the patches incident to the vertex it may be arbitrarily big.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it is the total number of surface patches indeed, but still it's likely not to be arbitrarily big. A hundred would already be a strong data set...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because it is more time consuming to change a bit inside an int.
That is very cheap, comparable to a memory load or a memory store from L1 cache. Both are about 3-4 CPU cycles. As soon as you have L1 caches misses, the memory load/stores are at more costly that that operation (setting a bit in a word).
That should be benched, but I doubt you will see any penalty for using std::vector<bool>
instead of std::vector<int>
I made quite a few experiments with this branch, and all the results are good/similar to About timings, the computation time (displayed by the demo) is on average 10 times faster than |
I have not planned to do more work on this. Note also that some improvements are not in the PMP package, so even other packages will profit from this PR. |
I think the next step with this function should be #805. The improvement is very nice! Congrats. |
But in an independent PR I would suggest, so that we have this one quickly in the master branch. |
Of course ! |
out.precision(17); | ||
//out << mesh << std::endl; | ||
out.close(); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@MaelRL just spotted this. @janetournois shall we write a mesh or shall we just go back to the original file and also kick out the timer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since it is the "main" example for isotropic remeshing, visible in the user manual, I would remove this and the timer too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you look at the other examples it seems that those who somehow modify the mesh or produce a mesh (union), at the end write the mesh to a file. We might unify. I also do not like the prefix or suffix example
in the file names.
@maxGimeno Both Sébastien and Mael approved this PR. It can be tested now. |
…g-GF PMP: Accelerate isotropic remeshing
successfully tested in https://cgal.geometryfactory.com/CGAL/testsuite/results-5.3-Ic-98.shtml |
Summary of Changes
vtuning in order to find small improvements to make.
Todo
Release Management