maps4fs 1.5.7__tar.gz → 1.7.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of maps4fs might be problematic. Click here for more details.

Files changed (33) hide show
  1. {maps4fs-1.5.7 → maps4fs-1.7.1}/PKG-INFO +58 -16
  2. {maps4fs-1.5.7 → maps4fs-1.7.1}/README.md +56 -14
  3. {maps4fs-1.5.7 → maps4fs-1.7.1}/maps4fs/__init__.py +3 -1
  4. {maps4fs-1.5.7 → maps4fs-1.7.1}/maps4fs/generator/background.py +92 -8
  5. {maps4fs-1.5.7 → maps4fs-1.7.1}/maps4fs/generator/component.py +23 -9
  6. {maps4fs-1.5.7 → maps4fs-1.7.1}/maps4fs/generator/dem.py +12 -49
  7. maps4fs-1.7.1/maps4fs/generator/dtm/__init__.py +0 -0
  8. {maps4fs-1.5.7/maps4fs/generator → maps4fs-1.7.1/maps4fs/generator/dtm}/dtm.py +59 -71
  9. maps4fs-1.7.1/maps4fs/generator/dtm/srtm.py +226 -0
  10. maps4fs-1.7.1/maps4fs/generator/dtm/usgs.py +351 -0
  11. {maps4fs-1.5.7 → maps4fs-1.7.1}/maps4fs/generator/game.py +1 -1
  12. {maps4fs-1.5.7 → maps4fs-1.7.1}/maps4fs/generator/grle.py +94 -28
  13. {maps4fs-1.5.7 → maps4fs-1.7.1}/maps4fs/generator/i3d.py +20 -14
  14. {maps4fs-1.5.7 → maps4fs-1.7.1}/maps4fs/generator/map.py +22 -2
  15. {maps4fs-1.5.7 → maps4fs-1.7.1}/maps4fs/generator/satellite.py +1 -1
  16. {maps4fs-1.5.7 → maps4fs-1.7.1}/maps4fs/generator/settings.py +41 -4
  17. {maps4fs-1.5.7 → maps4fs-1.7.1}/maps4fs/generator/texture.py +107 -59
  18. {maps4fs-1.5.7 → maps4fs-1.7.1}/maps4fs.egg-info/PKG-INFO +58 -16
  19. {maps4fs-1.5.7 → maps4fs-1.7.1}/maps4fs.egg-info/SOURCES.txt +4 -1
  20. {maps4fs-1.5.7 → maps4fs-1.7.1}/pyproject.toml +1 -1
  21. {maps4fs-1.5.7 → maps4fs-1.7.1}/tests/test_generator.py +21 -3
  22. {maps4fs-1.5.7 → maps4fs-1.7.1}/LICENSE.md +0 -0
  23. {maps4fs-1.5.7 → maps4fs-1.7.1}/maps4fs/generator/__init__.py +0 -0
  24. {maps4fs-1.5.7 → maps4fs-1.7.1}/maps4fs/generator/config.py +0 -0
  25. {maps4fs-1.5.7 → maps4fs-1.7.1}/maps4fs/generator/qgis.py +0 -0
  26. {maps4fs-1.5.7 → maps4fs-1.7.1}/maps4fs/logger.py +0 -0
  27. {maps4fs-1.5.7 → maps4fs-1.7.1}/maps4fs/toolbox/__init__.py +0 -0
  28. {maps4fs-1.5.7 → maps4fs-1.7.1}/maps4fs/toolbox/background.py +0 -0
  29. {maps4fs-1.5.7 → maps4fs-1.7.1}/maps4fs/toolbox/dem.py +0 -0
  30. {maps4fs-1.5.7 → maps4fs-1.7.1}/maps4fs.egg-info/dependency_links.txt +0 -0
  31. {maps4fs-1.5.7 → maps4fs-1.7.1}/maps4fs.egg-info/requires.txt +0 -0
  32. {maps4fs-1.5.7 → maps4fs-1.7.1}/maps4fs.egg-info/top_level.txt +0 -0
  33. {maps4fs-1.5.7 → maps4fs-1.7.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: maps4fs
3
- Version: 1.5.7
3
+ Version: 1.7.1
4
4
  Summary: Generate map templates for Farming Simulator from real places.
5
5
  Author-email: iwatkot <iwatkot@gmail.com>
6
6
  License: MIT License
@@ -48,6 +48,7 @@ Requires-Dist: pydantic
48
48
  <a href="#Expert-settings">Expert settings</a> •
49
49
  <a href="#Resources">Resources</a> •
50
50
  <a href="#Bugs-and-feature-requests">Bugs and feature requests</a><br>
51
+ <a href="#DTM-Providers">DTM Providers</a> •
51
52
  <a href="#Special-thanks">Special thanks</a>
52
53
  </p>
53
54
 
@@ -68,15 +69,15 @@ Requires-Dist: pydantic
68
69
  </div>
69
70
 
70
71
  🗺️ Supports 2x2, 4x4, 8x8, 16x16 and any custom size maps<br>
71
- 🔄 Support map rotation 🆕<br>
72
- 🌾 Automatically generates fields 🆕<br>
73
- 🌽 Automatically generates farmlands 🆕<br>
74
- 🌿 Automatically generates decorative foliage 🆕<br>
75
- 🌲 Automatically generates forests 🆕<br>
76
- 🌊 Automatically generates water planes 🆕<br>
72
+ 🔄 Support map rotation<br>
73
+ 🌐 Supports custom [DTM Providers](#DTM-Providers) 🆕<br>
74
+ 🌾 Automatically generates fields<br>
75
+ 🌽 Automatically generates farmlands<br>
76
+ 🌿 Automatically generates decorative foliage<br>
77
+ 🌲 Automatically generates forests<br>
78
+ 🌊 Automatically generates water planes<br>
77
79
  📈 Automatically generates splines 🆕<br>
78
80
  🛰️ Automatically downloads high resolution satellite images 🆕<br>
79
- 🏔️ Allows to use multiple DTM providers for elevation models 🆕<br>
80
81
  🌍 Based on real-world data from OpenStreetMap<br>
81
82
  🗺️ Supports [custom OSM maps](/docs/custom_osm.md)<br>
82
83
  🏞️ Generates height map using SRTM dataset<br>
@@ -97,10 +98,14 @@ Requires-Dist: pydantic
97
98
  🌿 Automatically generates decorative foliage.<br><br>
98
99
  <img src="https://github.com/user-attachments/assets/27a5e541-a9f5-4504-b8d2-64aae9fb3e52"><br>
99
100
  🌲 Automatically generates forests.<br><br>
101
+ <img src="https://github.com/user-attachments/assets/891911d7-081d-431e-a677-b4ae96870286"><br>
102
+ 🌲 Allows to select trees for generation.<br><br>
100
103
  <img src="https://github.com/user-attachments/assets/cce7d4e0-cba2-4dd2-b22d-03137fb2e860"><br>
101
104
  🌊 Automatically generates water planes.<br><br>
102
105
  <img src="https://github.com/user-attachments/assets/0b05b511-a595-48e7-a353-8298081314a4"><br>
103
106
  📈 Automatically generates splines.<br><br>
107
+ <img src="https://github.com/user-attachments/assets/0957db9e-7b95-4951-969c-9d1edd9f073b"><br>
108
+ 🖌️ Allows customization of the texture schema.<br><br>
104
109
  <img src="https://github.com/user-attachments/assets/80e5923c-22c7-4dc0-8906-680902511f3a"><br>
105
110
  🗒️ True-to-life blueprints for fast and precise modding.<br><br>
106
111
  <img width="480" src="https://github.com/user-attachments/assets/1a8802d2-6a3b-4bfa-af2b-7c09478e199b"><br>
@@ -129,6 +134,7 @@ docker run -d -p 8501:8501 --name maps4fs iwatkot/maps4fs
129
134
  ```
130
135
  And open [http://localhost:8501](http://localhost:8501) in your browser.<br>
131
136
  If you don't know how to use Docker, navigate to the [Docker version](#option-2-docker-version), it's really simple.<br>
137
+ Check out the [Docker FAQ](docs/FAQ_docker.md) if you have any questions.<br>
132
138
 
133
139
  ### 🤯 For developers
134
140
  **Option 3:** Python package. Install the package using the following command:
@@ -183,6 +189,7 @@ Using it is easy and doesn't require any guides. Enjoy!
183
189
  🗺️ Supported map sizes: 2x2, 4x4, 8x8, 16x16 km and any custom size.
184
190
  ⚙️ Advanced settings: enabled.
185
191
  🖼️ Texture dissolving: enabled.
192
+ Check out the [Docker FAQ](docs/FAQ_docker.md) if you have any questions.<br>
186
193
  You can launch the project with minimalistic UI in your browser using Docker. Follow these steps:
187
194
 
188
195
  1. Install [Docker](https://docs.docker.com/get-docker/) for your OS.
@@ -251,6 +258,12 @@ The tool now has a Modder Toolbox, which is a set of tools to help you with vari
251
258
 
252
259
  ### Tool Categories
253
260
  Tools are divided into categories, which are listed below.
261
+
262
+ #### For custom schemas
263
+ - **Tree Schema Editor** - allows you to view all the supported trees models and select the ones you need on your map. After it, you should click the Show updated schema button and copy the JSON schema to the clipboard. Then you can use it in the Expert settings to generate the map with the selected trees.
264
+
265
+ - **Texture Schema Editor** - allows you to view all the supported textures and edit their parameters, such as priority, OSM tags and so on. After editing, you should click the Show updated schema button and copy the JSON schema to the clipboard. Then you can use it in the Expert settings to generate the map with the updated textures.
266
+
254
267
  #### For Textures and DEM
255
268
  - **GeoTIFF windowing** - allows you to upload your GeoTIFF file and select the region of interest to extract it from the image. It's useful when you have high-resolution DEM data and want to create a height map using it.
256
269
 
@@ -419,6 +432,7 @@ Let's have a closer look at the fields:
419
432
  - `background` - set it to True for the textures, which should have impact on the Background Terrain, by default it's used to subtract the water depth from the DEM and background terrain.
420
433
  - `info_layer` - if the layer is saving some data in JSON format, this section will describe it's name in the JSON file. Used to find the needed JSON data, for example for fields it will be `fields` and as a value - list of polygon coordinates.
421
434
  - `invisible` - set it to True for the textures, which should not be drawn in the files, but only to save the data in the JSON file (related to the previous field).
435
+ - `procedural` - is a list of corresponding files, that will be used for a procedural generation. For example: `"procedural": ["PG_meadow", "PG_acres"]` - means that the texture will be used for two procedural generation files: `masks/PG_meadow.png` and `masks/PG_acres.png`. Note, that the one procuderal name can be applied to multiple textures, in this case they will be merged into one mask.
422
436
 
423
437
  ## Background terrain
424
438
  The tool now supports the generation of the background terrain. If you don't know what it is, here's a brief explanation. The background terrain is the world around the map. It's important to create it because if you don't, the map will look like it's floating in the void. The background terrain is a simple plane that can (and should) be textured to look fine.<br>
@@ -465,17 +479,12 @@ List of the important DDS files:
465
479
  - `mapsUS/overview.dds` - 4096x4096 pixels, the overview image of the map (in-game map)
466
480
 
467
481
  ## Advanced settings
468
- The tool supports the custom size of the map. To use this feature select `Custom` in the `Map size` dropdown and enter the desired size. The tool will generate a map with the size you entered.<br>
469
-
470
- ⛔️ Do not use this feature, if you don't know what you're doing. In most cases, the Giants Editor will just crash on opening the file, because you need to enter specific values for the map size.<br><br>
471
-
472
- ![Advanced settings](https://github.com/user-attachments/assets/9e8e178a-58d9-4aa6-aefd-4ed53408701d)
473
482
 
474
- You can also apply some advanced settings to the map generation process. Note that they're ADVANCED, so you don't need to use them if you're not sure what they do.<br>
483
+ You can also apply some advanced settings to the map generation process.<br>
475
484
 
476
485
  ### DEM Advanced settings
477
486
 
478
- - Multiplier: the height of the map is multiplied by this value. So the DEM map is just a 16-bit grayscale image, which means that the maximum available value there is 65535, while the actual difference between the deepest and the highest point on Earth is about 20 km. Just note that this setting mostly does not matter, because you can always adjust it in the Giants Editor, learn more about the DEM file and the heightScale parameter in [docs](docs/dem.md). By default, it's set to 1.
487
+ - Multiplier: the height of the map is multiplied by this value. So the DEM map is just a 16-bit grayscale image, which means that the maximum available value there is 65535, while the actual difference between the deepest and the highest point on Earth is about 20 km. Just note that this setting mostly does not matter, because you can always adjust it in the Giants Editor, learn more about the DEM file and the heightScale parameter in [docs](docs/dem.md). To match the in-game heights with SRTM Data provider, the recommended value is 255 (if easy mode is disabled), but depending on the place, you will need to play with both multiplier and the height scale in Giants Editor to find the best values.
479
488
 
480
489
  - Blur radius: the radius of the Gaussian blur filter applied to the DEM map. By default, it's set to 21. This filter just makes the DEM map smoother, so the height transitions will be more natural. You can set it to 1 to disable the filter, but it will result in a Minecraft-like map.
481
490
 
@@ -491,6 +500,15 @@ You can also apply some advanced settings to the map generation process. Note th
491
500
 
492
501
  - Resize factor - the factor by which the background terrain will be resized. It will be used as 1 / resize_factor while generating the models. Which means that the larger the value the more the terrain will be resized. The lowest value is 1, in this case background terrain will not be resized. Note, than low values will lead to long processing and enormous size of the obj files.
493
502
 
503
+ - Remove center - if enabled, the playable region (map terrain) will be removed from the background terrain. Note, that it will require low resize factors, to avoid gaps between the map and the background terrain.
504
+
505
+ - Apply decimation - if enabled, the mesh will be simplified to reduce the number of faces.
506
+
507
+ - Decimation percent - the target percentage of decimation. The higher the value, the more simplified the mesh will be. Note, that high values will break the 3D model entirely.
508
+
509
+ - Decimation agression - the aggression of the decimation. The higher the value, the more aggressive the
510
+ decimation will be, which means the higher it will affect the geometry. It's not recommended to make it higher than the default value, otherwise the background terrain will not match the map terrain.
511
+
494
512
  ### GRLE Advanced settings
495
513
 
496
514
  - Farmlands margin - this value (in meters) will be applied to each farmland, making it bigger. You can use the value to adjust how much the farmland should be bigger than the actual field. By default, it's set to 3.
@@ -499,6 +517,18 @@ You can also apply some advanced settings to the map generation process. Note th
499
517
 
500
518
  - Add Farmyards - if enabled, the tool will create farmlands from the regions that are marked as farmyards in the OSM data. Those farmlands will not have fields and also will not be drawn on textures. By default, it's turned off.
501
519
 
520
+ - Base grass - you can select which plant will be used as a base grass on the map.
521
+
522
+ - Plants island minimum size - when random plants are enabled, the generator will add islands of differents plants to the map and choose the random size of those island between the minimum and maximum values. This one is the minimum size of the island in meters.
523
+
524
+ - Plants island maximum size - it's the same as above, but for the maximum size of the island in meters.
525
+
526
+ - Plants island vertex count - the number of vertices in the island. The higher the value, the more detailed the island will be. Note, that high values will turn the smoothed island into geometric madness.
527
+
528
+ - Plants insland rounding radius - used to round the vertices of the island. The higher the value, the more rounded the island will be.
529
+
530
+ - Plants island percent - defines the relation between the map size and the number of islands of plants. For example, if set to 100% for map size of 2048 will be added 2048 islands of plants.
531
+
502
532
  ### I3D Advanced settings
503
533
 
504
534
  - Forest density - the density of the forest in meters. The lower the value, the lower the distance between the trees, which makes the forest denser. Note, that low values will lead to enormous number of trees, which may cause the Giants Editor to crash or lead to performance issues. By default, it's set to 10.
@@ -532,6 +562,8 @@ The tool also supports the expert settings. Do not use them until you read the d
532
562
 
533
563
  - Show schemas - you'll be able to edit or define your own texture or tree schemas. It's useful if you want to add some custom textures or trees to the map. Refer to the [Texture schema](#texture-schema) section to learn more about the schema structure. Any incorrect value here will lead to the completely broken map.
534
564
 
565
+ - Upload custom background image - if you have an image, which represents the map and background terrain you can use it for generation. Note, that the image should meet the following requirements: 1:1 aspect ratio, size = map size + 2048 * 2, it should be uint16 (unsigned 16-bit integer) grayscale (single channel) image. The image should be in the PNG format. If any of the requirements are not met, the tool raises an error. If you're using rotation, the image should already be rotated.
566
+
535
567
  ## Resources
536
568
  In this section, you'll find a list of the resources that you need to create a map for the Farming Simulator.<br>
537
569
  To create a basic map, you only need the Giants Editor. But if you want to create a background terrain - the world around the map, so it won't look like it's floating in the void - you also need Blender and the Blender Exporter Plugins. To create realistic textures for the background terrain, the QGIS is required to obtain high-resolution satellite images.<br>
@@ -547,6 +579,15 @@ To create a basic map, you only need the Giants Editor. But if you want to creat
547
579
  ➡️ Please, before creating an issue or asking some questions, check the [FAQ](docs/FAQ.md) section.<br>
548
580
  If you find a bug or have an idea for a new feature, please create an issue [here](https://github.com/iwatkot/maps4fs/issues) or contact me directly on [Telegram](https://t.me/iwatkot) or on Discord: `iwatkot`.
549
581
 
582
+ ## DTM Providers
583
+
584
+ The generator supports adding the own DTM providers, please refer to the [DTM Providers](docs/dtm_providers.md) section to learn how to add the custom DTM provider.
585
+
586
+ ### Supported DTM providers
587
+
588
+ - [SRTM 30m](https://dwtkns.com/srtm30m/) - the 30 meters resolution DEM data from the SRTM mission for the whole world.
589
+ - [USGS 1m](https://portal.opentopography.org/raster?opentopoID=OTNED.012021.4269.3) - the 1-meter resolution DEM data from the USGS for the USA. Developed by [ZenJakey](https://github.com/ZenJakey).
590
+
550
591
  ## Special thanks
551
592
 
552
593
  Of course, first of all, thanks to the direct [contributors](https://github.com/iwatkot/maps4fs/graphs/contributors) of the project.
@@ -562,3 +603,4 @@ But also, I want to thank the people who helped me with the project in some way,
562
603
  - [Lucandia](https://github.com/Lucandia) - for the awesome StreamLit [widget to preview STL files](https://github.com/Lucandia/streamlit_stl).
563
604
  - [H4rdB4se](https://github.com/H4rdB4se) - for investigating the issue with custom OSM files and finding a proper way to work with the files in JOSM.
564
605
  - [kbrandwijk](https://github.com/kbrandwijk) - for providing [awesome tool](https://github.com/Paint-a-Farm/satmap_downloader) to download the satellite images from the Google Maps and giving a permission to modify it and create a Python Package.
606
+ - [Maaslandmods](https://github.com/Maaslandmods) - for the awesome idea to edit the tree schema in UI, images and code snippets on how to do it.
@@ -22,6 +22,7 @@
22
22
  <a href="#Expert-settings">Expert settings</a> •
23
23
  <a href="#Resources">Resources</a> •
24
24
  <a href="#Bugs-and-feature-requests">Bugs and feature requests</a><br>
25
+ <a href="#DTM-Providers">DTM Providers</a> •
25
26
  <a href="#Special-thanks">Special thanks</a>
26
27
  </p>
27
28
 
@@ -42,15 +43,15 @@
42
43
  </div>
43
44
 
44
45
  🗺️ Supports 2x2, 4x4, 8x8, 16x16 and any custom size maps<br>
45
- 🔄 Support map rotation 🆕<br>
46
- 🌾 Automatically generates fields 🆕<br>
47
- 🌽 Automatically generates farmlands 🆕<br>
48
- 🌿 Automatically generates decorative foliage 🆕<br>
49
- 🌲 Automatically generates forests 🆕<br>
50
- 🌊 Automatically generates water planes 🆕<br>
46
+ 🔄 Support map rotation<br>
47
+ 🌐 Supports custom [DTM Providers](#DTM-Providers) 🆕<br>
48
+ 🌾 Automatically generates fields<br>
49
+ 🌽 Automatically generates farmlands<br>
50
+ 🌿 Automatically generates decorative foliage<br>
51
+ 🌲 Automatically generates forests<br>
52
+ 🌊 Automatically generates water planes<br>
51
53
  📈 Automatically generates splines 🆕<br>
52
54
  🛰️ Automatically downloads high resolution satellite images 🆕<br>
53
- 🏔️ Allows to use multiple DTM providers for elevation models 🆕<br>
54
55
  🌍 Based on real-world data from OpenStreetMap<br>
55
56
  🗺️ Supports [custom OSM maps](/docs/custom_osm.md)<br>
56
57
  🏞️ Generates height map using SRTM dataset<br>
@@ -71,10 +72,14 @@
71
72
  🌿 Automatically generates decorative foliage.<br><br>
72
73
  <img src="https://github.com/user-attachments/assets/27a5e541-a9f5-4504-b8d2-64aae9fb3e52"><br>
73
74
  🌲 Automatically generates forests.<br><br>
75
+ <img src="https://github.com/user-attachments/assets/891911d7-081d-431e-a677-b4ae96870286"><br>
76
+ 🌲 Allows to select trees for generation.<br><br>
74
77
  <img src="https://github.com/user-attachments/assets/cce7d4e0-cba2-4dd2-b22d-03137fb2e860"><br>
75
78
  🌊 Automatically generates water planes.<br><br>
76
79
  <img src="https://github.com/user-attachments/assets/0b05b511-a595-48e7-a353-8298081314a4"><br>
77
80
  📈 Automatically generates splines.<br><br>
81
+ <img src="https://github.com/user-attachments/assets/0957db9e-7b95-4951-969c-9d1edd9f073b"><br>
82
+ 🖌️ Allows customization of the texture schema.<br><br>
78
83
  <img src="https://github.com/user-attachments/assets/80e5923c-22c7-4dc0-8906-680902511f3a"><br>
79
84
  🗒️ True-to-life blueprints for fast and precise modding.<br><br>
80
85
  <img width="480" src="https://github.com/user-attachments/assets/1a8802d2-6a3b-4bfa-af2b-7c09478e199b"><br>
@@ -103,6 +108,7 @@ docker run -d -p 8501:8501 --name maps4fs iwatkot/maps4fs
103
108
  ```
104
109
  And open [http://localhost:8501](http://localhost:8501) in your browser.<br>
105
110
  If you don't know how to use Docker, navigate to the [Docker version](#option-2-docker-version), it's really simple.<br>
111
+ Check out the [Docker FAQ](docs/FAQ_docker.md) if you have any questions.<br>
106
112
 
107
113
  ### 🤯 For developers
108
114
  **Option 3:** Python package. Install the package using the following command:
@@ -157,6 +163,7 @@ Using it is easy and doesn't require any guides. Enjoy!
157
163
  🗺️ Supported map sizes: 2x2, 4x4, 8x8, 16x16 km and any custom size.
158
164
  ⚙️ Advanced settings: enabled.
159
165
  🖼️ Texture dissolving: enabled.
166
+ Check out the [Docker FAQ](docs/FAQ_docker.md) if you have any questions.<br>
160
167
  You can launch the project with minimalistic UI in your browser using Docker. Follow these steps:
161
168
 
162
169
  1. Install [Docker](https://docs.docker.com/get-docker/) for your OS.
@@ -225,6 +232,12 @@ The tool now has a Modder Toolbox, which is a set of tools to help you with vari
225
232
 
226
233
  ### Tool Categories
227
234
  Tools are divided into categories, which are listed below.
235
+
236
+ #### For custom schemas
237
+ - **Tree Schema Editor** - allows you to view all the supported trees models and select the ones you need on your map. After it, you should click the Show updated schema button and copy the JSON schema to the clipboard. Then you can use it in the Expert settings to generate the map with the selected trees.
238
+
239
+ - **Texture Schema Editor** - allows you to view all the supported textures and edit their parameters, such as priority, OSM tags and so on. After editing, you should click the Show updated schema button and copy the JSON schema to the clipboard. Then you can use it in the Expert settings to generate the map with the updated textures.
240
+
228
241
  #### For Textures and DEM
229
242
  - **GeoTIFF windowing** - allows you to upload your GeoTIFF file and select the region of interest to extract it from the image. It's useful when you have high-resolution DEM data and want to create a height map using it.
230
243
 
@@ -393,6 +406,7 @@ Let's have a closer look at the fields:
393
406
  - `background` - set it to True for the textures, which should have impact on the Background Terrain, by default it's used to subtract the water depth from the DEM and background terrain.
394
407
  - `info_layer` - if the layer is saving some data in JSON format, this section will describe it's name in the JSON file. Used to find the needed JSON data, for example for fields it will be `fields` and as a value - list of polygon coordinates.
395
408
  - `invisible` - set it to True for the textures, which should not be drawn in the files, but only to save the data in the JSON file (related to the previous field).
409
+ - `procedural` - is a list of corresponding files, that will be used for a procedural generation. For example: `"procedural": ["PG_meadow", "PG_acres"]` - means that the texture will be used for two procedural generation files: `masks/PG_meadow.png` and `masks/PG_acres.png`. Note, that the one procuderal name can be applied to multiple textures, in this case they will be merged into one mask.
396
410
 
397
411
  ## Background terrain
398
412
  The tool now supports the generation of the background terrain. If you don't know what it is, here's a brief explanation. The background terrain is the world around the map. It's important to create it because if you don't, the map will look like it's floating in the void. The background terrain is a simple plane that can (and should) be textured to look fine.<br>
@@ -439,17 +453,12 @@ List of the important DDS files:
439
453
  - `mapsUS/overview.dds` - 4096x4096 pixels, the overview image of the map (in-game map)
440
454
 
441
455
  ## Advanced settings
442
- The tool supports the custom size of the map. To use this feature select `Custom` in the `Map size` dropdown and enter the desired size. The tool will generate a map with the size you entered.<br>
443
-
444
- ⛔️ Do not use this feature, if you don't know what you're doing. In most cases, the Giants Editor will just crash on opening the file, because you need to enter specific values for the map size.<br><br>
445
-
446
- ![Advanced settings](https://github.com/user-attachments/assets/9e8e178a-58d9-4aa6-aefd-4ed53408701d)
447
456
 
448
- You can also apply some advanced settings to the map generation process. Note that they're ADVANCED, so you don't need to use them if you're not sure what they do.<br>
457
+ You can also apply some advanced settings to the map generation process.<br>
449
458
 
450
459
  ### DEM Advanced settings
451
460
 
452
- - Multiplier: the height of the map is multiplied by this value. So the DEM map is just a 16-bit grayscale image, which means that the maximum available value there is 65535, while the actual difference between the deepest and the highest point on Earth is about 20 km. Just note that this setting mostly does not matter, because you can always adjust it in the Giants Editor, learn more about the DEM file and the heightScale parameter in [docs](docs/dem.md). By default, it's set to 1.
461
+ - Multiplier: the height of the map is multiplied by this value. So the DEM map is just a 16-bit grayscale image, which means that the maximum available value there is 65535, while the actual difference between the deepest and the highest point on Earth is about 20 km. Just note that this setting mostly does not matter, because you can always adjust it in the Giants Editor, learn more about the DEM file and the heightScale parameter in [docs](docs/dem.md). To match the in-game heights with SRTM Data provider, the recommended value is 255 (if easy mode is disabled), but depending on the place, you will need to play with both multiplier and the height scale in Giants Editor to find the best values.
453
462
 
454
463
  - Blur radius: the radius of the Gaussian blur filter applied to the DEM map. By default, it's set to 21. This filter just makes the DEM map smoother, so the height transitions will be more natural. You can set it to 1 to disable the filter, but it will result in a Minecraft-like map.
455
464
 
@@ -465,6 +474,15 @@ You can also apply some advanced settings to the map generation process. Note th
465
474
 
466
475
  - Resize factor - the factor by which the background terrain will be resized. It will be used as 1 / resize_factor while generating the models. Which means that the larger the value the more the terrain will be resized. The lowest value is 1, in this case background terrain will not be resized. Note, than low values will lead to long processing and enormous size of the obj files.
467
476
 
477
+ - Remove center - if enabled, the playable region (map terrain) will be removed from the background terrain. Note, that it will require low resize factors, to avoid gaps between the map and the background terrain.
478
+
479
+ - Apply decimation - if enabled, the mesh will be simplified to reduce the number of faces.
480
+
481
+ - Decimation percent - the target percentage of decimation. The higher the value, the more simplified the mesh will be. Note, that high values will break the 3D model entirely.
482
+
483
+ - Decimation agression - the aggression of the decimation. The higher the value, the more aggressive the
484
+ decimation will be, which means the higher it will affect the geometry. It's not recommended to make it higher than the default value, otherwise the background terrain will not match the map terrain.
485
+
468
486
  ### GRLE Advanced settings
469
487
 
470
488
  - Farmlands margin - this value (in meters) will be applied to each farmland, making it bigger. You can use the value to adjust how much the farmland should be bigger than the actual field. By default, it's set to 3.
@@ -473,6 +491,18 @@ You can also apply some advanced settings to the map generation process. Note th
473
491
 
474
492
  - Add Farmyards - if enabled, the tool will create farmlands from the regions that are marked as farmyards in the OSM data. Those farmlands will not have fields and also will not be drawn on textures. By default, it's turned off.
475
493
 
494
+ - Base grass - you can select which plant will be used as a base grass on the map.
495
+
496
+ - Plants island minimum size - when random plants are enabled, the generator will add islands of differents plants to the map and choose the random size of those island between the minimum and maximum values. This one is the minimum size of the island in meters.
497
+
498
+ - Plants island maximum size - it's the same as above, but for the maximum size of the island in meters.
499
+
500
+ - Plants island vertex count - the number of vertices in the island. The higher the value, the more detailed the island will be. Note, that high values will turn the smoothed island into geometric madness.
501
+
502
+ - Plants insland rounding radius - used to round the vertices of the island. The higher the value, the more rounded the island will be.
503
+
504
+ - Plants island percent - defines the relation between the map size and the number of islands of plants. For example, if set to 100% for map size of 2048 will be added 2048 islands of plants.
505
+
476
506
  ### I3D Advanced settings
477
507
 
478
508
  - Forest density - the density of the forest in meters. The lower the value, the lower the distance between the trees, which makes the forest denser. Note, that low values will lead to enormous number of trees, which may cause the Giants Editor to crash or lead to performance issues. By default, it's set to 10.
@@ -506,6 +536,8 @@ The tool also supports the expert settings. Do not use them until you read the d
506
536
 
507
537
  - Show schemas - you'll be able to edit or define your own texture or tree schemas. It's useful if you want to add some custom textures or trees to the map. Refer to the [Texture schema](#texture-schema) section to learn more about the schema structure. Any incorrect value here will lead to the completely broken map.
508
538
 
539
+ - Upload custom background image - if you have an image, which represents the map and background terrain you can use it for generation. Note, that the image should meet the following requirements: 1:1 aspect ratio, size = map size + 2048 * 2, it should be uint16 (unsigned 16-bit integer) grayscale (single channel) image. The image should be in the PNG format. If any of the requirements are not met, the tool raises an error. If you're using rotation, the image should already be rotated.
540
+
509
541
  ## Resources
510
542
  In this section, you'll find a list of the resources that you need to create a map for the Farming Simulator.<br>
511
543
  To create a basic map, you only need the Giants Editor. But if you want to create a background terrain - the world around the map, so it won't look like it's floating in the void - you also need Blender and the Blender Exporter Plugins. To create realistic textures for the background terrain, the QGIS is required to obtain high-resolution satellite images.<br>
@@ -521,6 +553,15 @@ To create a basic map, you only need the Giants Editor. But if you want to creat
521
553
  ➡️ Please, before creating an issue or asking some questions, check the [FAQ](docs/FAQ.md) section.<br>
522
554
  If you find a bug or have an idea for a new feature, please create an issue [here](https://github.com/iwatkot/maps4fs/issues) or contact me directly on [Telegram](https://t.me/iwatkot) or on Discord: `iwatkot`.
523
555
 
556
+ ## DTM Providers
557
+
558
+ The generator supports adding the own DTM providers, please refer to the [DTM Providers](docs/dtm_providers.md) section to learn how to add the custom DTM provider.
559
+
560
+ ### Supported DTM providers
561
+
562
+ - [SRTM 30m](https://dwtkns.com/srtm30m/) - the 30 meters resolution DEM data from the SRTM mission for the whole world.
563
+ - [USGS 1m](https://portal.opentopography.org/raster?opentopoID=OTNED.012021.4269.3) - the 1-meter resolution DEM data from the USGS for the USA. Developed by [ZenJakey](https://github.com/ZenJakey).
564
+
524
565
  ## Special thanks
525
566
 
526
567
  Of course, first of all, thanks to the direct [contributors](https://github.com/iwatkot/maps4fs/graphs/contributors) of the project.
@@ -536,3 +577,4 @@ But also, I want to thank the people who helped me with the project in some way,
536
577
  - [Lucandia](https://github.com/Lucandia) - for the awesome StreamLit [widget to preview STL files](https://github.com/Lucandia/streamlit_stl).
537
578
  - [H4rdB4se](https://github.com/H4rdB4se) - for investigating the issue with custom OSM files and finding a proper way to work with the files in JOSM.
538
579
  - [kbrandwijk](https://github.com/kbrandwijk) - for providing [awesome tool](https://github.com/Paint-a-Farm/satmap_downloader) to download the satellite images from the Google Maps and giving a permission to modify it and create a Python Package.
580
+ - [Maaslandmods](https://github.com/Maaslandmods) - for the awesome idea to edit the tree schema in UI, images and code snippets on how to do it.
@@ -1,5 +1,7 @@
1
1
  # pylint: disable=missing-module-docstring
2
- from maps4fs.generator.dtm import DTMProvider
2
+ from maps4fs.generator.dtm.dtm import DTMProvider
3
+ from maps4fs.generator.dtm.srtm import SRTM30Provider
4
+ from maps4fs.generator.dtm.usgs import USGSProvider
3
5
  from maps4fs.generator.game import Game
4
6
  from maps4fs.generator.map import Map
5
7
  from maps4fs.generator.settings import (
@@ -58,6 +58,10 @@ class Background(Component):
58
58
  os.makedirs(self.water_directory, exist_ok=True)
59
59
 
60
60
  self.output_path = os.path.join(self.background_directory, f"{FULL_NAME}.png")
61
+ if self.map.custom_background_path:
62
+ self.check_custom_background(self.map.custom_background_path)
63
+ shutil.copyfile(self.map.custom_background_path, self.output_path)
64
+
61
65
  self.not_substracted_path = os.path.join(self.background_directory, "not_substracted.png")
62
66
  self.not_resized_path = os.path.join(self.background_directory, "not_resized.png")
63
67
 
@@ -75,6 +79,28 @@ class Background(Component):
75
79
  self.dem.set_output_resolution((self.rotated_size, self.rotated_size))
76
80
  self.dem.set_dem_path(self.output_path)
77
81
 
82
+ def check_custom_background(self, image_path: str) -> None:
83
+ """Checks if the custom background image meets the requirements.
84
+
85
+ Arguments:
86
+ image_path (str): The path to the custom background image.
87
+
88
+ Raises:
89
+ ValueError: If the custom background image does not meet the requirements.
90
+ """
91
+ image = cv2.imread(image_path, cv2.IMREAD_UNCHANGED) # pylint: disable=no-member
92
+ if image.shape[0] != image.shape[1]:
93
+ raise ValueError("The custom background image must be a square.")
94
+
95
+ if image.shape[0] != self.map_size + DEFAULT_DISTANCE * 2:
96
+ raise ValueError("The custom background image must have the size of the map + 4096.")
97
+
98
+ if len(image.shape) != 2:
99
+ raise ValueError("The custom background image must be a grayscale image.")
100
+
101
+ if image.dtype != np.uint16:
102
+ raise ValueError("The custom background image must be a 16-bit grayscale image.")
103
+
78
104
  def is_preview(self, name: str) -> bool:
79
105
  """Checks if the DEM is a preview.
80
106
 
@@ -91,7 +117,9 @@ class Background(Component):
91
117
  as a result the DEM files will be saved, then based on them the obj files will be
92
118
  generated."""
93
119
  self.create_background_textures()
94
- self.dem.process()
120
+
121
+ if not self.map.custom_background_path:
122
+ self.dem.process()
95
123
 
96
124
  shutil.copyfile(self.dem.dem_path, self.not_substracted_path)
97
125
  self.cutout(self.dem.dem_path, save_path=self.not_resized_path)
@@ -148,6 +176,9 @@ class Background(Component):
148
176
  "east": east,
149
177
  "west": west,
150
178
  }
179
+
180
+ dem_info_sequence = self.dem.info_sequence()
181
+ data["DEM"] = dem_info_sequence
151
182
  return data # type: ignore
152
183
 
153
184
  def qgis_sequence(self) -> None:
@@ -176,7 +207,13 @@ class Background(Component):
176
207
  self.logger.debug("Generating obj file in path: %s", save_path)
177
208
 
178
209
  dem_data = cv2.imread(self.dem.dem_path, cv2.IMREAD_UNCHANGED) # pylint: disable=no-member
179
- self.plane_from_np(dem_data, save_path) # type: ignore
210
+ self.plane_from_np(
211
+ dem_data,
212
+ save_path,
213
+ create_preview=True,
214
+ remove_center=self.map.background_settings.remove_center,
215
+ include_zeros=False,
216
+ ) # type: ignore
180
217
 
181
218
  # pylint: disable=too-many-locals
182
219
  def cutout(self, dem_path: str, save_path: str | None = None) -> str:
@@ -219,16 +256,37 @@ class Background(Component):
219
256
  )
220
257
 
221
258
  cv2.imwrite(main_dem_path, resized_dem_data) # pylint: disable=no-member
222
- self.logger.info("DEM cutout saved: %s", main_dem_path)
259
+ self.logger.debug("DEM cutout saved: %s", main_dem_path)
223
260
 
224
261
  return main_dem_path
225
262
 
226
- # pylint: disable=too-many-locals
263
+ def remove_center(self, dem_data: np.ndarray, resize_factor: float) -> np.ndarray:
264
+ """Removes the center part of the DEM data.
265
+
266
+ Arguments:
267
+ dem_data (np.ndarray) -- The DEM data as a numpy array.
268
+ resize_factor (float) -- The resize factor of the DEM data.
269
+
270
+ Returns:
271
+ np.ndarray -- The DEM data with the center part removed.
272
+ """
273
+ center = (dem_data.shape[0] // 2, dem_data.shape[1] // 2)
274
+ half_size = int(self.map_size // 2 * resize_factor)
275
+ x1 = center[0] - half_size
276
+ x2 = center[0] + half_size
277
+ y1 = center[1] - half_size
278
+ y2 = center[1] + half_size
279
+ dem_data[x1:x2, y1:y2] = 0
280
+ return dem_data
281
+
282
+ # pylint: disable=R0913, R0917, R0915
227
283
  def plane_from_np(
228
284
  self,
229
285
  dem_data: np.ndarray,
230
286
  save_path: str,
231
287
  include_zeros: bool = True,
288
+ create_preview: bool = False,
289
+ remove_center: bool = False,
232
290
  ) -> None:
233
291
  """Generates a 3D obj file based on DEM data.
234
292
 
@@ -236,11 +294,18 @@ class Background(Component):
236
294
  dem_data (np.ndarray) -- The DEM data as a numpy array.
237
295
  save_path (str) -- The path where the obj file will be saved.
238
296
  include_zeros (bool, optional) -- If True, the mesh will include the zero height values.
297
+ create_preview (bool, optional) -- If True, a simplified mesh will be saved as an STL.
298
+ remove_center (bool, optional) -- If True, the center of the mesh will be removed.
299
+ This setting is used for a Background Terrain, where the center part where the
300
+ playable area is will be cut out.
239
301
  """
240
302
  resize_factor = 1 / self.map.background_settings.resize_factor
241
303
  dem_data = cv2.resize( # pylint: disable=no-member
242
304
  dem_data, (0, 0), fx=resize_factor, fy=resize_factor
243
305
  )
306
+ if remove_center:
307
+ dem_data = self.remove_center(dem_data, resize_factor)
308
+ self.logger.debug("Center removed from DEM data.")
244
309
  self.logger.debug(
245
310
  "DEM data resized to shape: %s with factor: %s", dem_data.shape, resize_factor
246
311
  )
@@ -275,7 +340,10 @@ class Background(Component):
275
340
  bottom_left = top_left + cols
276
341
  bottom_right = bottom_left + 1
277
342
 
278
- if ground in [z[i, j], z[i, j + 1], z[i + 1, j], z[i + 1, j + 1]]:
343
+ if (
344
+ ground in [z[i, j], z[i, j + 1], z[i + 1, j], z[i + 1, j + 1]]
345
+ and not include_zeros
346
+ ):
279
347
  skipped += 1
280
348
  continue
281
349
 
@@ -294,16 +362,32 @@ class Background(Component):
294
362
  mesh.apply_transform(rotation_matrix_z)
295
363
 
296
364
  # if not include_zeros:
297
- z_scaling_factor = 1 / self.map.dem_settings.multiplier
365
+ z_scaling_factor = self.get_z_scaling_factor()
298
366
  self.logger.debug("Z scaling factor: %s", z_scaling_factor)
299
367
  mesh.apply_scale([1 / resize_factor, 1 / resize_factor, z_scaling_factor])
300
368
 
369
+ old_faces = len(mesh.faces)
370
+ self.logger.debug("Mesh generated with %s faces.", old_faces)
371
+
372
+ if self.map.background_settings.apply_decimation:
373
+ percent = self.map.background_settings.decimation_percent / 100
374
+ mesh = mesh.simplify_quadric_decimation(
375
+ percent=percent, aggression=self.map.background_settings.decimation_agression
376
+ )
377
+
378
+ new_faces = len(mesh.faces)
379
+ decimation_percent = (old_faces - new_faces) / old_faces * 100
380
+
381
+ self.logger.debug(
382
+ "Mesh simplified to %s faces. Decimation percent: %s", new_faces, decimation_percent
383
+ )
384
+
301
385
  mesh.export(save_path)
302
386
  self.logger.debug("Obj file saved: %s", save_path)
303
387
 
304
- if include_zeros:
388
+ if create_preview:
305
389
  # Simplify the preview mesh to reduce the size of the file.
306
- mesh = mesh.simplify_quadric_decimation(face_count=len(mesh.faces) // 2**7)
390
+ # mesh = mesh.simplify_quadric_decimation(face_count=len(mesh.faces) // 2**7)
307
391
 
308
392
  # Apply scale to make the preview mesh smaller in the UI.
309
393
  mesh.apply_scale([0.5, 0.5, 0.5])
@@ -58,7 +58,7 @@ class Component:
58
58
  self.logger = logger
59
59
  self.kwargs = kwargs
60
60
 
61
- self.logger.info(
61
+ self.logger.debug(
62
62
  "Component %s initialized. Map size: %s, map rotated size: %s", # type: ignore
63
63
  self.__class__.__name__,
64
64
  self.map_size,
@@ -188,8 +188,7 @@ class Component:
188
188
  self,
189
189
  coordinates: tuple[float, float] | None = None,
190
190
  distance: int | None = None,
191
- project_utm: bool = False,
192
- ) -> tuple[int, int, int, int]:
191
+ ) -> tuple[float, float, float, float]:
193
192
  """Calculates the bounding box of the map from the coordinates and the height and
194
193
  width of the map.
195
194
  If coordinates and distance are not provided, the instance variables are used.
@@ -199,24 +198,23 @@ class Component:
199
198
  of the map. Defaults to None.
200
199
  distance (int, optional): The distance from the center of the map to the edge of the
201
200
  map in all directions. Defaults to None.
202
- project_utm (bool, optional): Whether to project the bounding box to UTM.
203
201
 
204
202
  Returns:
205
- tuple[int, int, int, int]: The bounding box of the map.
203
+ tuple[float, float, float, float]: The bounding box of the map.
206
204
  """
207
205
  coordinates = coordinates or self.coordinates
208
206
  distance = distance or int(self.map_rotated_size / 2)
209
207
 
210
208
  west, south, east, north = ox.utils_geo.bbox_from_point( # type: ignore
211
- coordinates, dist=distance, project_utm=project_utm
209
+ coordinates,
210
+ dist=distance,
212
211
  )
213
212
 
214
213
  bbox = north, south, east, west
215
214
  self.logger.debug(
216
- "Calculated bounding box for component: %s: %s, project_utm: %s, distance: %s",
215
+ "Calculated bounding box for component: %s: %s, distance: %s",
217
216
  self.__class__.__name__,
218
217
  bbox,
219
- project_utm,
220
218
  distance,
221
219
  )
222
220
  return bbox
@@ -225,7 +223,7 @@ class Component:
225
223
  """Saves the bounding box of the map to the component instance from the coordinates and the
226
224
  height and width of the map.
227
225
  """
228
- self.bbox = self.get_bbox(project_utm=False)
226
+ self.bbox = self.get_bbox()
229
227
  self.logger.debug("Saved bounding box: %s", self.bbox)
230
228
 
231
229
  @property
@@ -535,3 +533,19 @@ class Component:
535
533
  interpolated_polyline.append(polyline[-1])
536
534
 
537
535
  return interpolated_polyline
536
+
537
+ def get_z_scaling_factor(self) -> float:
538
+ """Calculates the scaling factor for the Z axis based on the map settings.
539
+
540
+ Returns:
541
+ float -- The scaling factor for the Z axis.
542
+ """
543
+
544
+ scaling_factor = 1 / self.map.dem_settings.multiplier
545
+
546
+ if self.map.shared_settings.height_scale_multiplier:
547
+ scaling_factor *= self.map.shared_settings.height_scale_multiplier
548
+ if self.map.shared_settings.mesh_z_scaling_factor:
549
+ scaling_factor *= 1 / self.map.shared_settings.mesh_z_scaling_factor
550
+
551
+ return scaling_factor