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
Features in geometry tree tailored for clash detection. See #4278. #4282
Conversation
This considers only protruding clashes. It does not consider touching nor encroaching clashes and does not consider protrusion direction in the protrusion distance.
…ults. Add cache for points that have already been checked. Separate out new add_triangulated function with new kwarg add_element(should_triangulate=True) so that you can still have the old geom tree using aabb only if you want, also because add() is used in boolean_utils. Tolerance is now a kwarg. I misunderstood the OBB dimension and should *2 not /2 which now makes it much slower since there's more triangles to check.
… optimal OBBs, check OBB first for points_in_b prior to doing raycast (much faster now), and return the surface point of the protrusion too for convenience.
…rotrusion) This should be equivalent to select(element) but faster and with an allow_touching toggle.
I think this is now ready for a discussion (but not for merging) :) You'll notice this PR is mostly lines added, not removed because I didn't want to touch existing functionality. Things not yet implemented:
|
…nor cleanup to use vert/normal maps.
…eed, verts now use gp_Pnt instead of BVH_Vec3d, and optimise add_triangulated.
Super awesome! I see a couple of follow up tasks:
plicated, to save some mem I don't think I'm going to touch any of the geometric predicates. It sounds rather thought through. In some cases I'd have different preferences (like I conceptually don't really like how the distinction between piercing and protruding happens based on loose edges/verts as opposed to topology, but don't see a quick way out of resolving that without a more proper triangle mesh datastructure) I can work on these follow up tasks if you want, but then we need to agree on some "handover time" so that we're loosing time on conflicts. |
I'm not sure how to do this. The BVH tree is created from a triangle_set, and a triangle_set is created from a shape list, and a shape list is a list of TopoDS_Face, not triangles. I'm guessing somehow under the hood it reuses the triangulation data from incremental mesh, but I don't know how to get at the triangles until after the BVH is actually created. |
…rse than when we used unordered maps.
A small benchmark regarding the vertex indices indirection on a 40MB data set clashing all 6400 elements against each other using a intersection check (without early returns). I'm measuring this portion of the code: for element in sorted(all_els, key=lambda e: e.Name):
clashes = tree.clash_intersection(element, tolerance=0.002, check_all=True)
Note: negligible time difference in the tree adding portion of the code. |
… test instead of intersection which is much faster.
OK I think I've done what I can. The remaining unchecked boxes I either don't know how to do properly or probably need a bigger architectural decision (also probably worth thinking what signatures to use for many-many clashes). I'll be pens down for the rest of today if you want to write code :) |
Current benchmarks :) Notice the growing majority of time in opening, building the tree, and the crazy high memory use. All times in seconds. Memory in MB. All elements are clashed against all other elements.
Note that tree.select(e, extend=x) is not measured (equivalent to Clr) because it's simply too slow (gave up measuring after 5 minutes).
|
The latest commit introduces many-many variants of the clash functions: Do you see any reason to keep the 1:N functions or can / should I delete them? |
…is divided by num_threads equally.
I had a shot at implementing multithreading. I attempted to try to do something similar to IfcOpenShell/src/ifcgeom/IfcGeomIteratorImplementation.h Lines 326 to 362 in c66cf0a
I've got no idea if there is a better way to do it, but I've just updated the results table again and I'm very impressed with the results. I think I've run out of tricks I can think of to further optimise the clash portion of the code. I reckon it's now time to move on to optimising opening / tree creation. |
Multi-threading on IO bound tasks like this likely has very little effect. It may even make things worse because of all the locking that has to be put in place. |
Hmm, I'm looking to crush the 140 seconds of save/load time mentioned here. I did a couple of measurements: 108 seconds to convert to H5 via Python (89 seconds for geom iteration + ~19 seconds for H5 processing). 29 seconds to load a chunked H5 into Blender. (26 seconds of H5 loading / processing, and ~3 seconds of creating Blender objects) I was hoping that merely using C++ / multithreading would be enough to crush either the 19 or 26 seconds. |
The good news is that with my attempt at porting the loading code to C++, the 29 seconds it took to load a H5 into Blender has now dropped to 6.6 seconds. Woohoo! (half the time loading the H5, and the other half creating Blender objects). No multithreading was used. I found a crazy behaviour in H5 where getting a subgroup name was very, very slow. Maybe that explains why the Python code I also found that the casting from SWIG wrapped vector to Python list was very slow too. I got around this by implementing The bad news is that I've gone past the point of knowing what I'm doing and I have absolutely no idea how this now compiles (I manually copied over numpy.i and the numpy include .h directory, and manually included something in CMakeLists that obviously only works on my machine. So there's a huge amount of cleanup to do ... but hey I'm still really excited about the numbers! :) |
Given there's a week left before the release, here's the coordination usecase wishlist I'd ideally like covered by then.
|
I tested with saving to H5 via C++ and it seems as though the 108 seconds have also dropped down to 89 seconds for saving a H5. I guess all the overhead in the past was in passing big lists to Python and handling those lists there. (Note I originally measured 108 seconds but when remeasuring with my own compiled version of IfcOpenShell it went down to 101 seconds, I wonder is there is some -March native optimisation compared to IfcOpenBot, or if the latest OCCT 7.7 is faster somehow) I did a few measurements:
I wonder if this means that there could be a benefit in serving TriangulationElement geometry verts/edges/faces as numpy arrays (such as for general geometry iteration that everybody uses). I didn't look in detail as to how that's managed in SWIG but |
It's now possible to chunk directly from an IFC (instead of first having to save out a H5). This means that users can press a button in Blender and immediately load and see an IFC with a fast FPS. Something that would previously take almost 5 minutes and have them browse around with 3 FPS would now take 83 seconds and at 30 FPS. And this should work for multiple models too! (Once I build the operator for it) Users would also be able to headlessly run it in the background and save out a Blend file and auto-link that blend file to the scene (and then memory used for ifcopenshell.open() should be freed I think). So in a single session they can load in many models and federate them conveniently. (BTW you've probably noticed the code getting worse and worse, I'd love to clean it up but I need your guidance, and there's a lot of magic around SWIG which escapes me. I've definitely gone overscope in this and starting working on #4279 which is related but perhaps should be in a separate PR) |
…lend generation) is now possible
… balance RAM (instancing) vs speed (chunking)
- Only affects non-chunked instances (where verts are higher so the impact will be greater) - Things far away or not in view of the camera will be rendered as bounds
Next steps:
|
Definitely do not merge :)
First attempt at implementation of intersection clash checks. See #4278.
This considers only protruding clashes. It does not consider touching nor encroaching clashes and does not consider protrusion direction in the protrusion distance.
Still a lot to move around and tweak so it's also not yet ready for a detailed review and you can see lots of random prints and probably horrifically incorrect usage of pointers and structs and what not but at least something is committed to a branch for now ...