pixijs / tilemap

Rectangular tilemap implementation for PixiJS
https://pixijs.io/tilemap/docs/
MIT License
290 stars 55 forks source link

Rendering a hexagon tilemap with offsets #86

Open eranimo opened 4 years ago

eranimo commented 4 years ago

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.

ivanpopelyshev commented 4 years ago

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.

eranimo commented 4 years ago

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?

ivanpopelyshev commented 4 years ago

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 :)

eranimo commented 4 years ago

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

ivanpopelyshev commented 4 years ago

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 :)

eranimo commented 4 years ago

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?

ivanpopelyshev commented 4 years ago

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

eranimo commented 4 years ago

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?

ivanpopelyshev commented 4 years ago

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 commented 4 years ago

Maybe its your time to draw?

eranimo commented 4 years ago

Should every chunk be its own CompositeRectTileLayer instance?

ivanpopelyshev commented 4 years ago

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.

eranimo commented 4 years ago

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?

ivanpopelyshev commented 4 years ago

Show me one chunk

eranimo commented 4 years ago
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!)

ivanpopelyshev commented 4 years ago

Make it the way I shown several comments ago :)

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

eranimo commented 4 years ago

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.

ivanpopelyshev commented 4 years ago

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 commented 4 years ago

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 :)

eranimo commented 4 years ago

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.

ivanpopelyshev commented 4 years ago

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

eranimo commented 4 years ago

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.

ivanpopelyshev commented 4 years ago

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 :)

eranimo commented 4 years ago

Thank you, that's a great help.

ivanpopelyshev commented 4 years ago

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 :)