tilemap icon indicating copy to clipboard operation
tilemap copied to clipboard

Rendering a hexagon tilemap with offsets

Open eranimo opened this issue 4 years ago • 25 comments

Does pixi-tilemap support tilemaps with an offset? I have a tileset that is 32x48 but renders into a hexagon grid of 32*32 with a 2px offset.

Rendering an entire tilemap works, but as soon as I try to update a single tile, it renders it above its neighbor tiles, showing the offsetted parts of the tilemap tile.

Essentially, I need layer sort ordering.

eranimo avatar Jun 02 '20 23:06 eranimo

tilemap is made for "clear & refill" approach. Usually map is separated to many chunks, each of those are completely recalculated once something was changed inside.

You tried to redraw tile above itself, it doesnt actually delete its previous instance.

ivanpopelyshev avatar Jun 02 '20 23:06 ivanpopelyshev

The problem I'm currently facing is that since I'm using a hexagon tilemap, and tiles can overlap their neighbors slightly, the hexes on the edge of chunks overlap. How do I support that?

eranimo avatar Jun 03 '20 14:06 eranimo

Its about math and algorithms, not a low-level solution :)

You use diamond tiles in isometry, right? Make your chunks also diamonds, and follow the same order you usually fill the map.

You can even figure out extra trick of how to cut geometry using 45 degree rotations of texture: https://pixijs.io/examples/#/textures/texture-rotate.js , without actually modifying your textures.

Those things require you to actually think, write something on paper. I'm ashamed that there are no articles about it, but I cant make one right now because there are 10 more pixi plugins on me.

If you dont figure out that stuff after a few hours of thinking, then i can help :)

ivanpopelyshev avatar Jun 03 '20 14:06 ivanpopelyshev

What does texture rotation have to do with this? Why does the chunk have to be diamond shaped (and not rectangular?)

eranimo avatar Jun 03 '20 14:06 eranimo

Order i which tiles are drawn is important. If you make correct order inside chunks and order of chunks inside map, you'll get your overlaps correct. To make that order you need diamond chunks. For square chunks, "tooth" at the edge wont have correct top-to-bottom overlap.

If you cant imagine what order of tiles in map will give that to you - sorry, there's no way to do that in any renderer, whether its canvas2d , webgl-based or whatever.

Texture rotation is extra trick to cut half of geometry, dont bother with it yet :)

ivanpopelyshev avatar Jun 03 '20 15:06 ivanpopelyshev

Given that I have a rectangular map, I don't think diamond shaped chunks would work. Also, I have flat-topped hexagons. Is that a problem here?

eranimo avatar Jun 03 '20 15:06 eranimo

oh, hexagons.. sorry :)

so you cant make them square because of same reason - at the left and right sides it has "tooth". but you can make parallelograms or hexes.

First try to refill whole visible culled part of map, then make chunks. Difficulty depends on your coordinate system.

image

ivanpopelyshev avatar Jun 03 '20 15:06 ivanpopelyshev

Thank you for the visualization and answering questions, it's been a great help. I still don't quite understand how having the chunks in this shape changes anything. It seems that the problem is still that the chunk has a single layer, but each hex on the chunk edge needs to "interweave" (or "tooth" as you put it) with hexes in the other chunks (since I have flat topped hexagons the top left, top, and top right of each hexagon can overlap onto the hexes above it)

I have a feeling that chunked rendering with flat-topped hexes is just impossible because of the above reason. If I had pointy-top hexes, there would only be direction of overlap. Does that sound correct?

eranimo avatar Jun 03 '20 16:06 eranimo

look around one hex.If you draw naively, top hexes and left hex are drawn under it.

If you use chunks like I drawn, that invariant wont be broken, there's no teeth.

ivanpopelyshev avatar Jun 03 '20 18:06 ivanpopelyshev

Maybe its your time to draw?

ivanpopelyshev avatar Jun 03 '20 18:06 ivanpopelyshev

Should every chunk be its own CompositeRectTileLayer instance?

eranimo avatar Jun 03 '20 20:06 eranimo

yes, that's the point. You can clear & refill them independently. Each one means one webgl drawcall (every frame), one vertex buffer upload (when its changed).

Refill is just double-For that can also check for autotiles if you have them.

ivanpopelyshev avatar Jun 03 '20 20:06 ivanpopelyshev

Got it. So I've tried with square chunks (I have a rectangular map, not sure how to have any other shape) Map size is 150x100, with 10x10 chunks. I'm rendering the chunks in top-left order (hexes as well).

This is what the edges of the chunks look like:

Screen Shot 2020-06-03 at 5 39 10 PM Right below the black edge you can see brown, that's not supposed to be cut off. The top sides of the hexes do overlap correctly.

For reference, this is the tileset: (black edges aren't supposed to be rendered) Screen Shot 2020-06-03 at 5 39 27 PM

How does diamond shaped chunks solve anything? Wouldn't I still have overlapping issues, just no longer in this pattern?

eranimo avatar Jun 03 '20 21:06 eranimo

Show me one chunk

ivanpopelyshev avatar Jun 03 '20 22:06 ivanpopelyshev

Screen Shot 2020-06-03 at 6 36 02 PM

I guess I could do triangular chunks, would that work better?

(Thanks again for helping me!)

eranimo avatar Jun 03 '20 22:06 eranimo

Make it the way I shown several comments ago :)

Yes you'll have a bit of a problem depending on your coordinate system.

ivanpopelyshev avatar Jun 03 '20 22:06 ivanpopelyshev

How do I decide what zIndex to put each chunk? I don't quite understand why rectangular chunks are an issue, given that I'm having a problem with the side that isn't "tooth" shaped. I can explore a parallelogram shape but I'll need irregular chunk shapes to make the map square again, which would have the same issue with overlap.

eranimo avatar Jun 03 '20 23:06 eranimo

I love those kind of problems. Abstract ones. When you just have to meditate on words or draw some shapes to understand and solve them :)

I dont know which coord system you use, and I dont want to talk about system I use because that's not important in the case.

Imagine you have a map. You separate it into chunks: for every tile you specify number of chunk it belongs. Whether its formulae or its precalculated and stored in two-dimensional array is not important.

Your goal is to separate large map to medium-sized chunks and order those chunks that way if tile A covered tile B in big map, it still covers it in chunked map.

If you use figure I shown - it should work. Parallelogram chunk covers chunk at the right of it and at the bottom.

In your chunk , two tiles at the right side, one below another - one should cover next chunk and another should be under it - that's why its not working.

I tried to draw it in Paint.net but with my mad skillz at 2:55AM its just not possible.

ivanpopelyshev avatar Jun 03 '20 23:06 ivanpopelyshev

I will be happy to help my fellow major of CS tomorrow, probably make a demo out of generated textures to show both your and mine version of chunks.

We all have blind spots from time to time :)

ivanpopelyshev avatar Jun 04 '20 00:06 ivanpopelyshev

I just tried with parallelogram chunks and it has the same issue with the right-side overlapping. Like I said, I think the issue is how I'm determining the zIndex of the chunk. Yes, a hexagon tilemap example would be great for others benefit as well.

eranimo avatar Jun 04 '20 15:06 eranimo

you have to determine zIndex of chunk the same way you determined it for individual tiles, then it should work.

ivanpopelyshev avatar Jun 04 '20 15:06 ivanpopelyshev

I'm ordering hexes by their y coordinates (using the odd-q coordinate system), and I'm ordering chunks the same way. I've also tried layering chunks by the lowest and highest hexes in the chunk, nothing has worked.

I've also tried using axial coordinates and ordering by the r-coordinate, same effect.

eranimo avatar Jun 04 '20 16:06 eranimo

Here it is.

https://www.pixiplayground.com/#/edit/qPQyCCuYWy7LGyYdB4uyj

Do you see artifacts at the right side?

Make a proper chunkW and chunkH that bounds are almost squares - and you'll get a good base to make culling of. Yeah, we have to add getBounds() in CompositeRectTileLayer :)

ivanpopelyshev avatar Jun 04 '20 18:06 ivanpopelyshev

Thank you, that's a great help.

eranimo avatar Jun 04 '20 18:06 eranimo

I made it for you to believe in math again! after all those angular projects. I know they produce jelly out of brains :) Honestly, I'm glad to have R&D as my primary job and not a hobby :)

ivanpopelyshev avatar Jun 04 '20 18:06 ivanpopelyshev