-
Notifications
You must be signed in to change notification settings - Fork 137
avoid sparse indices #1186
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
avoid sparse indices #1186
Conversation
src/boolean3.cpp
Outdated
// Sum up the winding numbers of all vertices. | ||
w03_ = Winding03(inP, p0, s02, false); | ||
w03_ = Winding03(inP, inQ, p0q2, expandP_, true); |
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.
@elalish I'm thinking if it is possible to somehow integrate this winding number computation into Intersect12
, but not sure if that is sound. Will it ever miss anything?
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.
Not sure if you already answered this for yourself, but w03 is calculated for every vertex. It doesn't need to be - I used to only calculate it for the verts of intersected edges and faces - you can flood fill the values to the rest because they're always consistent. I removed that because my flood-filling algorithm was slower than just calculating them all, but I may have just been doing it poorly.
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 think calculating them all is probably good for now, it is pretty fast.
src/boolean3.cpp
Outdated
expandP, | ||
forward ? inP.vertNormal_ : inQ.vertNormal_, | ||
forward}; | ||
F11 f11{forward ? inP.vertPos_ : inQ.vertPos_, |
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 will definitely fix these later, it is just interesting that it works within 30 minutes of trying :)
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #1186 +/- ##
==========================================
+ Coverage 91.62% 92.25% +0.63%
==========================================
Files 32 31 -1
Lines 6067 5902 -165
==========================================
- Hits 5559 5445 -114
+ Misses 508 457 -51 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
to run with different benchmark.csv files
I'm thinking about several things now
And probably need some comments about the code organization. I think for simplicity, we should probably just get rid of those forward parameters in high level functions, as I need to do many conditional to deal with that. |
src/boolean3.cpp
Outdated
// Sum up the winding numbers of all vertices. | ||
w03_ = Winding03(inP, p0, s02, false); | ||
w03_ = Winding03(inP, inQ, p0q2, expandP_, true); |
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.
Not sure if you already answered this for yourself, but w03 is calculated for every vertex. It doesn't need to be - I used to only calculate it for the verts of intersected edges and faces - you can flood fill the values to the rest because they're always consistent. I removed that because my flood-filling algorithm was slower than just calculating them all, but I may have just been doing it poorly.
inline bool Shadows(double p, double q, double dir) { | ||
return p == q ? dir < 0 : p < q; | ||
} | ||
|
||
inline std::pair<int, vec2> Shadow01( | ||
const int p0, const int q1, VecView<const vec3> vertPosP, | ||
VecView<const vec3> vertPosQ, VecView<const Halfedge> halfedgeQ, | ||
const double expandP, VecView<const vec3> normalP, const bool reverse) { | ||
const double expandP, VecView<const vec3> normal, const bool reverse) { |
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.
changed the naming because it is not really for P
, but depends on reverse
. When reverse
is false, it is for P
, but otherwise it is for Q
.
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.
Okay, so this one is weird - I managed to confuse myself a bunch of times, which means my naming is terrible, and part of the problem is I added on this expandP
thing late. At a global level, only P is expanded (or contracted if false), according to its own normals. The normals of Q are never used for anything. This is weird because this function reverses P and Q sometimes, but the normals are always the same. I think I've used them right, but a double-check would be great. As for naming... I don't know.
src/boolean3.cpp
Outdated
VecView<const vec3> vertPosP; | ||
VecView<const vec3> vertPosQ; | ||
VecView<const Halfedge> halfedgeP; | ||
VecView<const Halfedge> halfedgeQ; | ||
const double expandP; | ||
VecView<const vec3> normalP; | ||
const SparseIndices &p1q1; | ||
VecView<const vec3> normal; |
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.
Similarly here.
Vec<int> x12(p1q2.size()); | ||
Vec<vec3> v12(p1q2.size()); | ||
// a: 1 (edge), b: 2 (face) | ||
const Manifold::Impl &a = forward ? inP : inQ; |
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.
Now, instead of swapping inP
and inQ
parameters, I just define new temporaries a and b, depending on forward
. This should hopefully be cleaner now.
* | ||
* @param other A Manifold to overlap with. | ||
*/ | ||
size_t Manifold::NumOverlaps(const Manifold& other) const { |
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 just removed this function because it is not used, and to be honest, I don't think the number of overlaps from the collider result is meaningful.
@@ -1694,3 +1694,272 @@ CondensedMatter64 19 2.30642e-11 1 | |||
-0.06842195833766776 9.6799396338048 | |||
-0.06842195833766818 9.679939633804798 | |||
-0.06842195833766825 9.679939633804798 | |||
DISABLED_Sponge4b 291 5.000000000000000909e-13 27 |
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 weird triangulation failure. It seems that it requires really high precision to reproduce the error.
Sorting the result in boolean3 only adds minor runtime, so we can have determinism there without hurting performance. @elalish I think this is ready for full review, e.g., naming, organization, etc. |
This change removed 413 LoC (excluding the triangulator test case), completely removed some of the logic related to sparse indices. The logic in boolean3 is also a lot more straightforward now. |
}; | ||
|
||
struct Kernel02 { | ||
VecView<int> s; | ||
VecView<double> z; | ||
VecView<const vec3> vertPosP; |
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.
Maybe we should change the name of these P and Q, because we will swap them. Not sure what is the best name here.
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 like your renaming of them to e.g. vertPosA
and halfedgeB
to handle the swapping.
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.
Looking awesome, thanks!
src/collider.h
Outdated
@@ -269,6 +241,16 @@ constexpr inline uint32_t SpreadBits3(uint32_t v) { | |||
/** @ingroup Private */ | |||
class Collider { | |||
public: | |||
template <typename F> | |||
struct SimpleRecorder { | |||
using LocalT = F; |
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 rename something short to something longer? Also, what does LocalT mean?
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.
Oh, it is just some local storage type, I can just rename it to Local.
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 not just leave it as F
or T
? What is special about the type that makes it local?
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 has to be a bit more specific because each thread has its own instance of this value, and the implementation has to deal with this thread local thing. Maybe I should just write a comment about this.
Or put it more simply, this is part of the API interface of recorder for collider, but due to c++ having no interfaces, this is defined implicitly in the collider code...
for (Iter i = range.begin(); i != range.end(); i++) | ||
f(*i); | ||
}); | ||
tbb::this_task_arena::isolate([&]() { |
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.
What does this do?
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.
This prevents the current thread from executing work that is outside this scope. Otherwise, thread local variables can be modified by another thread... See https://uxlfoundation.github.io/oneTBB/main/tbb_userguide/work_isolation.html
@@ -125,7 +125,7 @@ void CheckGeometry(const std::vector<ivec3> &triangles, | |||
} | |||
|
|||
void Dump(const PolygonsIdx &polys, double epsilon) { | |||
std::cout << std::setprecision(16); | |||
std::cout << std::setprecision(19); |
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 just found a bug at work that was sensitive to the least significant bit of a float getting flipped. Argh!
}; | ||
|
||
struct Kernel02 { | ||
VecView<int> s; | ||
VecView<double> z; | ||
VecView<const vec3> vertPosP; |
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 like your renaming of them to e.g. vertPosA
and halfedgeB
to handle the swapping.
inline bool Shadows(double p, double q, double dir) { | ||
return p == q ? dir < 0 : p < q; | ||
} | ||
|
||
inline std::pair<int, vec2> Shadow01( | ||
const int p0, const int q1, VecView<const vec3> vertPosP, | ||
VecView<const vec3> vertPosQ, VecView<const Halfedge> halfedgeQ, | ||
const double expandP, VecView<const vec3> normalP, const bool reverse) { | ||
const double expandP, VecView<const vec3> normal, const bool reverse) { |
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.
Okay, so this one is weird - I managed to confuse myself a bunch of times, which means my naming is terrible, and part of the problem is I added on this expandP
thing late. At a global level, only P is expanded (or contracted if false), according to its own normals. The normals of Q are never used for anything. This is weird because this function reverses P and Q sometimes, but the normals are always the same. I think I've used them right, but a double-check would be great. As for naming... I don't know.
@elalish I changed the naming a bit, but for |
and I will leave it for you to merge it, if you think the naming is fine now |
Hmm, I think I wasn't clear about the naming. Would you mind just reverting the |
This reverts commit 79a2526.
Sure |
Start removing sparse indices usage in
Boolean3.cpp
. This is mainly for discussion about invariants that I am not sure about. Closes #972.The code is really ugly now, but it seems to be working. I will clean it up later. The refactor here is surprisingly simple: just change the binary search to a function call. There is more to be done to make it faster, though.
Performance:
Previously:
Now:
For some numbers:
Not all models are equal in this case, when the sparse indices are relatively small, e.g. for our perfTest where we use high resolution spheres, the speedup is minimal (nTri = 8388608, time = 1.80269 sec).