Closed mariuszhermansdorfer closed 2 years ago
Some quick notes/research:
Array.Sort()
. Pretty sure C# uses quick sort under the hood, but if the sorting ends up being slow a bucket or radix sort might be potentially quicker as the sorting process mirrors what we intend to use the data structure for. Ad 1. I have just uploaded a branch where I doodled a bit with displaying contour lines as part of the vertex shader. It is fast, but visually quite disappointing... https://youtu.be/kjxylCEvV5M
We're probably better off looking into drawing actual polylines...
And btw. we need some better-looking gradients soon! My eyes hurt each time I see these ultra-saturated rainbow on the screen :)
From the middle of this video one can see the difference, proper curves make. It's worlds apart. Obviously, we'd need to internalize the logic. Having it run through an external component is way too slow.
We can cut the time to 40% using mesh¦plane intersection instead of the Mesh.CreateContourCurves()
22k faces
30k faces
57k faces
It seems to compute at 38-40% of the time.
Awesome @BarusXXX ! We should definitely use this as an immediate improvement.
Mid-term I'd like us to have a more interactive logic, though. I've found this post with a nice description of how the algorithm works. To answer your questions, @BarusXXX, instead of creating isocurves from the mesh, we use the elevation array from the sensor and work directly on its values.
For every pixel, we check the elevation delta to each neighbor and mark it with a dot. The placement of these dots is linearly interpolated -> difference between elevation values for neighboring pixels is '5', we place 4 dots at the corresponding edge and space them by edgeLength/5
Then it's just a matter of connecting the right dots (corresponding to the contour interval setting).
OK, I took a stab at implementing the logic from the above post. Preliminary results are not too sexy yet, but I'll try to optimize it for one more day to see how feasible this approach is.
I like the fact, that we can decide on the density of the sampling grid for contour lines separately to the mesh. Here, I added a slider to define how coarse we want the analysis to be:
I haven't figured out a proper way of connecting these lines yet and didn't optimize the code at all, but already now it is the fastest we've ever had.
@philipbelesky, @BarusXXX do you have an idea on how to connect the lines?
Right now, it's just a bunch of loose lines, and ideally we'd have one polyline per contour line.
Fixed some bugs in the contour lines logic - it looks like we can use this for fast & coarse interactive contour display, and let users generate more detailed contours once the mesh is baked.
Still some work to be done on this front but looks potentially promising. The biggest issue right now, is that relatively small elevation differences between points are not identified at all. Color ramp vs. contour lines comparison visualizes this quite well:
Getting there:
@philipbelesky, @BarusXXX, I think we've got it! Displaying all contour lines through the display pipeline (DrawViewportWires) rather than outputting them through the component speeds things up tremendously! Now, we really have an interactive model which is super fun to work with!
There might be value in having a dedicated contour lines output, though. Therefore, I added the following hybrid logic:
contours
output parameter, SandWorm switches to displaying real geometry, which is slower but potentially more fliexible:
I'm using the same trick for water surface
rendering - the moment something is connected to the corresponding output, its display is turned off in the main component. We can't really use the typical GH approach of disabling the preview of the entire component, since it would force us to output contours as geometry as well and slow things down significantly.
When nothing is connected to the water surface
output, we get the typical GH preview:
After connecting the Custom Preview
component, we only see the downstream geometry:
Code ported to work with Kinect for Windows as well. It is super smooth and a joy to work with:
Made contour lines adapt to Rhino's drawing units.
As you mentioned, this is a joy to use! The lack of overhead in the component-preview mode is also great to see.
Regarding the geometric output, I assume the latency is coming from the sheer amount of Line
objects that are being output? In which case it might be worth trying to use GH_Line
rather than Line
to see if type conversions can be avoided. The other trick is that changing the output parameter to be Generic
rather than Curve
can often route around conversion issues.
Another option might be to test if the overhead of joining the lines together might be similar/less to the overhead of outputting so many lines individually. As a bonus, it could open up some nice opportunities in the component to bridge some of the transient 'gaps' between lines as well as making downstream operations (e.g. further smoothing or contour 'matching') easier.
I've slightly run out of time today just reading/testing the new code but would be happy to have a go at some of the above options.
Definitely, way too many lines to output for Grasshopper to remain interactive. I took a stab at creating Polyline
object rather than lines using two linked Dictionary<Point3d, Polyline>
. One for start points, the other for end points. I got to a point, that roughly half of the lines were connected, couldn't figure out how to solve the issue, got annoyed and deleted the code :)
Would be great if you could test the proposed solutions, I might also revisit my idea another day with a fresh brain.
Did some testing today:
pManager.AddCurveParameter + Rhino.Geometry.Line:
pManager.AddGenericParameter + Rhino.Geometry.Line:
pManager.AddGenericParameter + Grasshopper.Kernel.Types.GH_Line:
pManager.AddCurveParameter + Grasshopper.Kernel.Types.GH_Line:
Generic parameters force a cast in downstream components, which we can do faster internally. Decided to go with 4
as it's the fastest and cleanest overall.
Drawing fewer contours yields acceptable results in terms of time:
Ah, thanks for trying that out. Should we close this issue and could come back to joining/linking as a separate issue?
Drawing actual curves to display contour lines is computationally expensive. Let's try adding these in the shader instead. Simply change the vertex color value to black at a given interval in the Z direction.