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
Add CanvasGeometry #3116
Add CanvasGeometry #3116
Conversation
It is very similar to 2D marching squares (like marching cubes) and it is a common optimization when doing marching cubes/squares to keep track of the previous row to speed up connections. http://en.wikipedia.org/wiki/Marching_squares And then one has extruded this result. I am unsure if this should be in core. But if it is, I'd suggest one algorithm that creates a 2D trimesh of the canvas and then a second part that extrudes it (there is already an extrude geometry in Three.js which you can reuse.) Could you compare your method with that of Marching Squares? Also I'd even suggest adding an intermediary representation where you extract from canvas a 2D array of points and then pass that into your Marching Squares implementation, this way others can use it even if they are not using a canvas. One neat thing you can do with Marching Squares is to retopologize the interior to get rid of unnecessary polygons (first convert to one large concave polygon and then process it separating it into maximally size convex polygons) and you can likely also smooth the outside before doing that to get rid of unnecessary edge pieces. This might be a way of converting rasterized fonts into nice 3D meshes in a general way. |
I am impressed with the speed of this and the quality of the results, although there is a lot of triangles in the results. My concerns in the previous comment are mostly about making its pieces easily reusable. I have found 2D marching square useful in the past and I did generate them from Java Drawing2D Canvases in a similar approach. |
@bhouston I'll check on marching squares but I suspect that the run based approach should be faster. It could also be possible to optimise the model as well, but I opt on letting the quantization on the y axis as it may have interesting application. The contour information is gathered in one array containing pairs of vertex indices, I'll check if that can be exported into something meaningful for other components to use |
@wizgrav Ah, I see. I misunderstood what you meant by runs. It would be faster than marching squares then. It is like marching squares but with arbitrary sized rectangles that vary based on feature size. Very neat actually. I'd still suggest separating the algorithm into a few pieces. The first would create the connected outline, the next would turn it into a solid polygon, another would extrude it. You can reuse the existing ExtrudeGeometry and if you find you can optimize please do! I think there is already code to polygonize an outline in the code base, it was written by @zz85. Thus basically you would provide the canvas to connected outline code. I guess I personally prefer algorithms decomposed into reusable pieces so we can combine them in new forms, rather than having somewhat fixed functionality, which is less useful. Also having decomposed algorithms makes it easier to test and see what is going on even if it can be slightly slower. |
Did some more research on THREE.Path and Shape and I see that producing something generalized will be trickier than I thought. The algorithm keeps track of the contour and could produce lineTo commands for Path. The first issue is that extrude geometry needs array of distinct features(paths) along with the holes definition as distinct paths. There will be some more bookkeeping needed to keep track of the connected components but the algorithm already has that potential. The hole matching could be tricky but feasible as well. Another issue is that THREE.Path.prototype.fromPoints expects points in the order of every feature's contour whereas in CanvasGeometry they're produced on a horizontal scan order for all features. Grouping and reordering these would kill performance without benefit on polygon counts. I'd really appreciate some insight from @zz85 on this |
this seems interesting, it might be useful for extruding pixel art for example. haven't look in detailed into this, but like @bhouston says, seems to be generate a large amount of faces.
|
@zz85 the amount of generated vertices/faces is bound to the y resolution of the image so it can be controlled from that. You can also rotate the canvas to control the direction of the vertex quantization. This comes handy if you'd like to bend or wrap the model around something else. In a sense this is a fast triangulation algorithm that works with an ordered grid as input. Vectors could be rasterised and then triangulated with CanvasGeometry. This may actually be a good choice in HTML. You could load an svg on an img at the resolution you desire(taking advantage of the native path performance), then drawImage and run it to produce a model. Unfortunately this won't work on chrome currently due to a bug that taints the canvas origin flag when loading svgs even those from the same domain http://code.google.com/p/chromium/issues/detail?id=68568 As far as vector extraction is concerned all the vector pairs for the sidewalls are stored along with their 2d normals. The problem is that these are arranged on a row by row basis. The array contains pairs mixed for all the distinct outlines contained in the image. These would have to be grouped and reordered to be useful to a convex polygon triangulator. This step will be very expensive so I'm not sure if it's worth the effort. This method was not really designed to perform tracing |
@mrdoob what would be the most appropriate way to attach custom data on a geometry. I want to export the outline data, should I use a _metadata property on the geometry or is there something more specific? |
|
Updated http://wizgrav.github.com/three.js/runner/ example with options to tweak the canvas before running |
I like userData. We would fine it useful as well. Sent from my phone, sorry for my grammar and terseness.
|
CanvasGeometry extrudes watertight solid meshes from pixels based on transparency(by default). It's based on a technique I'm researching and, so far, call running image triangulation & extrusion. There is still more to be done but it has already started being useful. The base concept comes from a blob tracking algorithm called run based component labeling. It works by recording continuous horizontal lines(separated by transparency) as pairs of vertices, called runs. While it raster scans one row, it interconnects the runs of the previous one, so most of the work gets done fast in one pass. It produces nice models with low polygon counts. You can see a demo here http://wizgrav.github.com/three.js/runner/ and a (preliminary) paper here http://revoxel.com/runner/paper.pdf