-
Notifications
You must be signed in to change notification settings - Fork 121
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
BVH for ray-triangle intersection tests #379
Conversation
testing yet, plus needs optimization
memory requirements. Bound of a whole group of triangles is now computed when needed. Use the existing mesh collision data to compute triangle centroids. Will need the collision data anyway to compute ray intersections later. Remove max depth parameter Fix incorrect deletes Verified correctness with more mesh
This looks really awesome! I'm very excited about this, and I'm hoping to give this a hands-on spin a little later! :D Here's a few notes just from reading over the code, hopefully this doesn't come across as picky.
|
Not at all, it's your code base :) I tried to match the style and constructs I saw, but can probably fix most of the things you mention.
Okay, that should be doable. Is the reason for this choice so you can easily interface to C, without having to build another API layer?
I might need a bit more info on which to use for what, having not looked closely into those memory routines (nor did I see comments ;-)). For example, how would you go about allocating an array of structs where each element would normally get initialized by the default constructor?
Yes, I looked at that, and similar for extending vec3 for the indexing by axis stuff. The latter is a bit tricky to do efficiently without changing the underlying data to a 3-array instead of an x,y,z struct. So I would prefer more to further optimize the boundingbox struct specifically for BVH usage, and possibly use a local float3 or something, as that will ensure we can keep up performance. Although, all in all, it's a bit hard to judge any performance impact without testing. I guess there's also a bit of personal bias there as well as I'm mostly interested in using this on large (1M+ triangles) meshes, where performance will matter :)
One reason to keep the current methods around (just for now) is for easy checks on correctness of the BVH stuff. The intersection results should match, as a BVH is purely a method for speeding up the queries.
Right, but for that I need to work on the C# layer and I need to check how easy it is to build SK from source under visual studio. I think I've only done that once so far. Anything specific to watch out for in that process? |
PODPOD types have the advantage of being a lot more clear about what's happening! You can be guaranteed there's no hidden vtable pointers, nothing weird happening on creation or copy, I also have at the back of my mind that it might be nice to make StereoKit properly just C rather than the C/C++ hybrid that it is, but that may just be wishful thinking. MemoryIf you're sticking to POD, then it's a little easier to avoid quat* rots = sk_malloc_t(quat, 10);
for (int32_t i=0; i<10; i++)
rots[i] = quat_identity;
free(rots); SK's memory functions are basically the same as normal C stuff, just with some macro wrappers to make it a little easier. The StereoKitCTestSo there is actually a C++ equivalent of StereoKitTest, no C# involved! It has a similar sort of structure to it, where you can have a demo_topic.h/cpp per subject. Only difference is no reflection, so you still have to register the demo over in main.cpp manually, which is easy enough :) It's not a 1:1 match with the C# test project, and the samples there tend to be a lot less polished. I use it a fair bit for testing out APIs before I commit to something and write up the C# side of it, faster to iterate with! And then it's also already hooked up to the cmake file too. MiscI am totally down with a |
and intersection working, but can be optimized a bit
ray can be rejected early based on mesh bbox
Added mesh_gen_cone(), as used by BVH example
results are not correct. This is the case for both the BVH-based intersection, but also the existing model_ray_intersect(). Need to figure out why. Improve coloring of ray elements in BVH example
@maluoi I've done some more work on this, including adding an example in StereoKitCTest.
|
is in model-space coordinates and so needs to be transformed to world-space
Awesome! Suuuuper exciting! :D I'm doing MR Dev Days stuff all day today, but I'll take a good look tomorrow :) |
Show options UI with BVH toggle and intersection time Added time_get_raw() to API
model_ray_intersect_bvh_detailed() to get to the necessary triangle information, similar to what already was available for mesh intersection. Added reset pose button
Alright, I've added a few more things in the StereoKitCTest example, including highlighting the intersected triangle (needed to add a
|
with Visual Studio. Need to verify this doesn't break the build on Linux
Just tried this out on a model with 1.6 million tris, and it really takes it like a champ! That is slick, really excellent work! :) I'm also noticing that this code does intersect with backfaces, which on further inspection, even my own code did backface intersection as well! That might actually be something we want to either avoid, or make optional. |
Fix compilation with new mesh_.h setup
I fixed the use of Regarding the intersection test currently ignoring facing, it depends a bit on the usage if that's preferred, so I'd definitely want to keep the option to always intersect regardless of facing. E.g. my current interest in this code is intersection testing for teleporting, and I'm mostly using photogrammetry models that are not nicely closed surfaces. So I render them without back-face culling and would want to allow intersection testing on both faces. But maybe in the general case having the optimization to ignore back-facing triangles is a good default. |
By the way, I've been trying to get a VS build to work for this code, but it just keeps erroring on me (seemingly unrelated to my code). In general, I'm a bit confused as to how the SK build system is organized, especially in relation to CMake usage and things like the physics code. I read somewhere that the react library would be cloned and built automatically once, but that's one of the things that keeps going wrong in my builds (and I definitely have cmake installed and on PATH). And are the VS project files supposed to be managed by hand? As I noticed the BVH-related files being listed in the StereoKitC_UWP project, but I definitely did not place them there myself. Or is there some VS project generation done based on the CMake files? Is there a description somewhere of the build system with a bit of detail? |
Yeah, this all sounds pretty sensible. Thinking about this a little more specifically, it might be good to have the option be the Personally, when I think about photogrammetry, I worry about the user getting stuck outside of the mesh, or getting inside the mesh in the first place! Which is why I kinda prefer ignoring backfaces :D So, definitely a range of valid perspectives here. With respect to the VS build, there's something funky in there recently that I've been hunting down! I haven't managed to smooth it over, but it's related to reactphysics3d again. Since Visual Studio has no dependency management tools for git repositories, I've kinda had to replicate some of that "clone and build" pipeline with powershell :( In Visual Studio, the powershell invocation happens in the "pre-build events". Normally this works relatively well, but I'm not a build expert and writing all that via powershell has been an issue prone adventure. You could try deleting the I'm still looking for a better option for doing this. I've been looking a bit at vcpkg, or possibly moving C# and the Windows dev experience over to pure cmake, but nothing is really looking like a silver bullet. |
Fix use of sprintf()
I'd like to use
or this
I prefer the latter, as I assume the culling option to be used more than the output indices one. But it seems in |
I'd prefer the first signature for SK, for compatibility reasons! The second one I'd consider to be a breaking change, even if I also do like it a little more. I'd recommend adding a TODO comment mentioning parameter reordering for v0.4 so it gets reconsidered next time we introduce breaking changes :) In C# we can safely add an overload in the second order, which is not a breaking change there! And yeah, feel free to shift |
I guess the culling is one of the last things I needed to add. |
into a POD struct
Okay, I managed to finally get StereoKitCTest compiling on the win10 system that has our XR-3 attached. This allowed some more interactive testing of the BVH intersection with larger models. All intersections (including the different cull modes) seem to be correct and indeed quite fast even for large models. So I guess that completes this particular pull request. We can always revisit/optimize stuff later on :) |
Okay perfect! I'll take this for a spin later this evening and get it merged! Thanks a lot for this feature, I'm really excited about using it :D I guess I'll also noodle around and see about the public C# API. It's pretty likely that I'll replace the |
* Have some form of BVH construction working. No intersection testing yet, plus needs optimization * Use smaller BVH node structure (32 bytes) * Get rid of precomputed triangle bboxes, to lower memory requirements. Bound of a whole group of triangles is now computed when needed. Use the existing mesh collision data to compute triangle centroids. Will need the collision data anyway to compute ray intersections later. Remove max depth parameter Fix incorrect deletes Verified correctness with more mesh * Cleanups * Initial bvh intersection code added, but not fully correct yet. * Corrections to bvh intersection * Added model_ray_intersect_bvh() but not getting the results I'd expect yet * Cleanups * Debug printf tweak * First pass of turning classes into POD. BVH construction and intersection working, but can be optimized a bit * WIP cleanup and optimization * Gather BVH statistics in a separate optional pass * Always build BVH in mesh_ray_intersect_bvh(), even if ray can be rejected early based on mesh bbox * Ident spaces to tabs * Added BVH example to StereoKitCTest Added mesh_gen_cone(), as used by BVH example * Incorporate model pose in intersection test, but the results are not correct. This is the case for both the BVH-based intersection, but also the existing model_ray_intersect(). Need to figure out why. Improve coloring of ray elements in BVH example * Added newline at EOF * Plugged brain back in and realized that the returned intersection is in model-space coordinates and so needs to be transformed to world-space * Scale model to unit size Show options UI with BVH toggle and intersection time Added time_get_raw() to API * Only scale down large models in BVH sample * Highlight intersected triangle. Needed to add model_ray_intersect_bvh_detailed() to get to the necessary triangle information, similar to what already was available for mesh intersection. Added reset pose button * Disable some debug prints * Comment fix * Fixed issue with intersected triangle not matching up with intersection point. The mesh transform also needs to be applied, so is now returned by model_ray_intersect_bvh_detailed() as well * Indent with tabs instead of spaces in some files * Fixed some issues that propped up when attempting to build with Visual Studio. Need to verify this doesn't break the build on Linux * Revert some of the VS fixed, will revisit at some point * Get rid of <algorithm>, std::max and std::swap usage Fix compilation with new mesh_.h setup * Comment * Add bvh source to VS project files Fix use of sprintf() * Add cull_mode parameter to filter triangle intersections based on facing * Turn boundingbox class used for BVH construction into a POD struct * Correctly initialize model pose, some optimizations Co-authored-by: Paul Melis <paul.melis@surf.nl>
Here's an initial implementation (C++ parts only, and 3 lines of C#) of using a bounding-volume hierarchy for ray-triangle intersection testing. This is based on existing BVH code I had laying around, plus some inspiration from Jacco Bikker's blog series on BVH construction (see bvh.cpp comments). It contains a fair amount of tracing printf()s, as a code such as this is challenging to debug otherwise, so for now those are best to leave in (I'm sure we'll find bugs ;-)).
I also added a small standalone C++ test for checking with different models and rays, but it's mostly for debugging right now. The next step would be to add the C# layer for easier testing, i.e. interactive ray casting in 3D, possibly as part of StereoKitTest.
This has only been tested with a few 3D models, but ranging from small ones to complex ones (up to 500k triangles, and even a 24M triangle model). Construction seems fairly quick, given that it's not very optimized (models of up to 50k triangles in less than 50ms).
Construction has had more testing than intersection testing, as the latter can be better done interactively (as mentioned above).One thing I haven't figured out is why the addedmodel_ray_intersect_bvh()
does not return the same results as usingmesh_ray_intersect()
on each of the submeshes and taking the closest hit. In most models I tested the subparts do not have a non-identity transform, so that should not influence the outcome, yet it does.