mourner / icomesh

Fast JavaScript icosphere mesh generation library for WebGL visualizations
https://observablehq.com/@mourner/fast-icosphere-mesh
ISC License
55 stars 4 forks source link

UV mapping #4

Closed mourner closed 5 years ago

mourner commented 5 years ago

Putting a texture over an icosphere is pretty tricky — see https://mft-dev.dk/uv-mapping-sphere for how the naive approach looks and possible workarounds.

It would be cool to explore a proper, performant solution to this — most likely involving passing a uvMapping option to icomesh that generates uv vectors when true, and also duplicates vertices that lie on the 1-0 seam and on the poles to get rid of artifacts.

IvanSanchez commented 5 years ago

...but there are several desireable UV maps. In particular, off the top of my head I can think of:

On the API part, I think this maybe could be done with a map function that would take a vertex array, and return a new attribute array with just the texture coords.

Maybe the zipper artifact can be approached by breaking the topology of the polyhedron; the faces of the polyhedron which intersect the "antimeridian" should be assigned "latitudes" which are outside of the [-180°,+180°] range (out of the [0, 1] range in GL parlance), much like some of Leaflet's approaches at antimeridian artifacts. Then, just set the wrap mode of the texture to repeat.

In particular, I'm thinking about the topology constraints of the algorithm from #5. Since the algorithm needs a set of edges, it should be relatively easy to create a non-topologically-closed icosahedron and mark the faces which need a latitude offset.

mourner commented 5 years ago

There are also zigzag-like icosahedral textures:

image

However, for the sake of simplicity and minimalism, I think we should just do the equirectangular UV — this is by far the most common format for various weather / terrain data.

I think I figured out a scheme for fixing zipper/poles — now I just need to move this over including vertex duplication logic (not many vertices to duplicate so not a big deal): https://observablehq.com/d/41cf6358cc9e5d88 (now the remaining challenge is how to calculate how many vertices should be duplicated)

Re shader — I'd like to avoid that so that icomesh can be a plug in replacement for a standard UV sphere in any WebGL viz (e.g. Three.js), without messing with shader code.

IvanSanchez commented 5 years ago

(now the remaining challenge is how to calculate how many vertices should be duplicated)

I think it's always gonna be 3 * 2^order (or 3 * frequency) - this is how many vertices one needs to cover a 180° arc from pole to pole (3 edges in an icosahedron). Plus 8 to duplicate the pole vertices.

Think of a triangular Manhattan distance - it doesn't matter if the "seam" is made through the icosahedron edges, or through subdivisions of the faces (unless I'm missing something here).

Re number of duplicated vertices - would it be much of a problem if the algorithm from #5 would duplicate all edges? I don't know how worried you are with the overhead of duplicated data.

Also, the idea of calculating 10 sides and then mirroring them (from https://github.com/mourner/icomesh/issues/3#issuecomment-535018993 ) would be interesting - it allows adding an offset to one of the two halves, but creates double the duplicated nodes.

Re shader — I'd like to avoid that so that icomesh can be a plug in replacement for a standard UV sphere in any WebGL viz (e.g. Three.js), without messing with shader code.

Sorry, I misunderstood the technique. My brain inferred that it was about inverting the winding order of the antimeridian triangles and then somehow using the gl_FrontFacing constant.

mourner commented 5 years ago

I think I have this figured out: https://observablehq.com/@mourner/uv-mapping-an-icosphere

mourner commented 5 years ago

Re number of duplicated vertices - would it be much of a problem if the algorithm from #5 would duplicate all edges? I don't know how worried you are with the overhead of duplicated data.

Strictly out of academic interest, I would try to keep the amount of vertices optimal — not more than the minimum.

IvanSanchez commented 5 years ago

Strictly out of academic interest, I would try to keep the amount of vertices optimal — not more than the minimum.

In that case, you want to orientate the starting icosahedron in such a way that the north/south poles at at the "north"/"south" poles - this saves 2 vertices when duplicating the poles. :grin:

(Right now the starting icosahedron has an edge midpoint at each pole)

mourner commented 5 years ago

Only for zero order :) For 1+, we can modify one "pole" and duplicate it only 5 times from each side.

IvanSanchez commented 5 years ago

Only for zero order :) For 1+, we can modify one "pole" and duplicate it only 5 times from each side.

No no no - with poles at the original vertices, there are 5 poles (original and 4 dupes); with poles at midpoints, there are 6 poles (original and 5 dupes) since each face has 3 triangles with that pole as a vertex.

mourner commented 5 years ago

Oh wow, you're right! But that would likely mean rebuilding the UV fixing algorithm from scratch — I think I spent enough time on it to start again :) (Update: also more poles means less precision loss when texturing.)

IvanSanchez commented 5 years ago

Don't worry, I'll be back to my plan to implement topology for #5 plus reorienting the icosahedron :wink: