public static TileSet makeTileset(Texture texture, bool collisions)
    {
        BitMap original_bitmap = null;
        BitMap bitmap          = null;

        if (collisions)
        {
            var image = texture.GetData();
            original_bitmap = new BitMap();
            original_bitmap.CreateFromImageAlpha(image, .001f);

            // bitmap with borders is needed to shrink mask later
            bitmap = new BitMap();
            bitmap.Create(new Vector2((TILE_WIDTH + 2) * TILESET_WIDTH, (TILE_HEIGHT + 2) * TILESET_HEIGHT));
            bitmap.SetBitRect(new Rect2(new Vector2(0, 0), bitmap.GetSize()), true);
        }

        var ts = new TileSet();

        int i = 0;

        for (int y = 0; y < TILESET_HEIGHT; y++)
        {
            for (int x = 0; x < TILESET_WIDTH; x++)
            {
                ts.CreateTile(i);
                ts.TileSetTexture(i, texture);
                var region = new Rect2(x * TILE_WIDTH, y * TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT);
                ts.TileSetRegion(i, region);

                if (collisions)
                {
                    for (int m = 0; m < TILE_WIDTH; m++)
                    {
                        for (int n = 0; n < TILE_HEIGHT; n++)
                        {
                            bitmap.SetBit(new Vector2(x * (TILE_WIDTH + 2) + m + 1, y * (TILE_HEIGHT + 2) + n + 1),
                                          original_bitmap.GetBit(new Vector2(x * TILE_WIDTH + m, y * TILE_HEIGHT + n)));
                        }
                    }

                    var bitmap_region = new Rect2(x * (TILE_WIDTH + 2) + 1, y * (TILE_HEIGHT + 2) + 1, TILE_WIDTH, TILE_HEIGHT);
                    var polygons      = tilePolygons(bitmap, bitmap_region);
                    int c             = 0;

                    foreach (Vector2[] polygon in polygons)
                    {
                        if (isConvex(polygon))
                        {
                            var collision = new ConvexPolygonShape2D();
                            collision.SetPointCloud(polygon);
                            ts.TileSetShape(i, c++, collision);
                        }
                        else
                        {
                            int[] triangles = Geometry.TriangulatePolygon(polygon);
                            for (int t = 0; t < triangles.Length; t += 3)
                            {
                                Vector2[] triangle  = { polygon[triangles[t]], polygon[triangles[t + 1]], polygon[triangles[t + 2]] };
                                var       collision = new ConvexPolygonShape2D();
                                collision.SetPointCloud(triangle);
                                ts.TileSetShape(i, c++, collision);
                            }
                        }
                    }
                }
                i++;
            }
        }
        return(ts);
    }