maps4fs 1.5.7__tar.gz → 1.6.91__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.
- {maps4fs-1.5.7 → maps4fs-1.6.91}/PKG-INFO +45 -8
- {maps4fs-1.5.7 → maps4fs-1.6.91}/README.md +44 -7
- {maps4fs-1.5.7 → maps4fs-1.6.91}/maps4fs/__init__.py +3 -1
- {maps4fs-1.5.7 → maps4fs-1.6.91}/maps4fs/generator/background.py +92 -8
- {maps4fs-1.5.7 → maps4fs-1.6.91}/maps4fs/generator/component.py +24 -1
- {maps4fs-1.5.7 → maps4fs-1.6.91}/maps4fs/generator/dem.py +12 -49
- maps4fs-1.6.91/maps4fs/generator/dtm/__init__.py +0 -0
- {maps4fs-1.5.7/maps4fs/generator → maps4fs-1.6.91/maps4fs/generator/dtm}/dtm.py +59 -71
- maps4fs-1.6.91/maps4fs/generator/dtm/srtm.py +226 -0
- maps4fs-1.6.91/maps4fs/generator/dtm/usgs.py +351 -0
- {maps4fs-1.5.7 → maps4fs-1.6.91}/maps4fs/generator/game.py +1 -1
- {maps4fs-1.5.7 → maps4fs-1.6.91}/maps4fs/generator/grle.py +94 -28
- {maps4fs-1.5.7 → maps4fs-1.6.91}/maps4fs/generator/i3d.py +20 -14
- {maps4fs-1.5.7 → maps4fs-1.6.91}/maps4fs/generator/map.py +22 -2
- {maps4fs-1.5.7 → maps4fs-1.6.91}/maps4fs/generator/satellite.py +1 -1
- {maps4fs-1.5.7 → maps4fs-1.6.91}/maps4fs/generator/settings.py +40 -3
- {maps4fs-1.5.7 → maps4fs-1.6.91}/maps4fs/generator/texture.py +65 -12
- {maps4fs-1.5.7 → maps4fs-1.6.91}/maps4fs.egg-info/PKG-INFO +45 -8
- {maps4fs-1.5.7 → maps4fs-1.6.91}/maps4fs.egg-info/SOURCES.txt +4 -1
- {maps4fs-1.5.7 → maps4fs-1.6.91}/pyproject.toml +1 -1
- {maps4fs-1.5.7 → maps4fs-1.6.91}/tests/test_generator.py +21 -3
- {maps4fs-1.5.7 → maps4fs-1.6.91}/LICENSE.md +0 -0
- {maps4fs-1.5.7 → maps4fs-1.6.91}/maps4fs/generator/__init__.py +0 -0
- {maps4fs-1.5.7 → maps4fs-1.6.91}/maps4fs/generator/config.py +0 -0
- {maps4fs-1.5.7 → maps4fs-1.6.91}/maps4fs/generator/qgis.py +0 -0
- {maps4fs-1.5.7 → maps4fs-1.6.91}/maps4fs/logger.py +0 -0
- {maps4fs-1.5.7 → maps4fs-1.6.91}/maps4fs/toolbox/__init__.py +0 -0
- {maps4fs-1.5.7 → maps4fs-1.6.91}/maps4fs/toolbox/background.py +0 -0
- {maps4fs-1.5.7 → maps4fs-1.6.91}/maps4fs/toolbox/dem.py +0 -0
- {maps4fs-1.5.7 → maps4fs-1.6.91}/maps4fs.egg-info/dependency_links.txt +0 -0
- {maps4fs-1.5.7 → maps4fs-1.6.91}/maps4fs.egg-info/requires.txt +0 -0
- {maps4fs-1.5.7 → maps4fs-1.6.91}/maps4fs.egg-info/top_level.txt +0 -0
- {maps4fs-1.5.7 → maps4fs-1.6.91}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: maps4fs
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.6.91
|
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
|
|
@@ -69,6 +70,7 @@ Requires-Dist: pydantic
|
|
69
70
|
|
70
71
|
🗺️ Supports 2x2, 4x4, 8x8, 16x16 and any custom size maps<br>
|
71
72
|
🔄 Support map rotation 🆕<br>
|
73
|
+
🌐 Supports custom [DTM Providers](#DTM-Providers) 🆕<br>
|
72
74
|
🌾 Automatically generates fields 🆕<br>
|
73
75
|
🌽 Automatically generates farmlands 🆕<br>
|
74
76
|
🌿 Automatically generates decorative foliage 🆕<br>
|
@@ -129,6 +131,7 @@ docker run -d -p 8501:8501 --name maps4fs iwatkot/maps4fs
|
|
129
131
|
```
|
130
132
|
And open [http://localhost:8501](http://localhost:8501) in your browser.<br>
|
131
133
|
If you don't know how to use Docker, navigate to the [Docker version](#option-2-docker-version), it's really simple.<br>
|
134
|
+
Check out the [Docker FAQ](docs/FAQ_docker.md) if you have any questions.<br>
|
132
135
|
|
133
136
|
### 🤯 For developers
|
134
137
|
**Option 3:** Python package. Install the package using the following command:
|
@@ -183,6 +186,7 @@ Using it is easy and doesn't require any guides. Enjoy!
|
|
183
186
|
🗺️ Supported map sizes: 2x2, 4x4, 8x8, 16x16 km and any custom size.
|
184
187
|
⚙️ Advanced settings: enabled.
|
185
188
|
🖼️ Texture dissolving: enabled.
|
189
|
+
Check out the [Docker FAQ](docs/FAQ_docker.md) if you have any questions.<br>
|
186
190
|
You can launch the project with minimalistic UI in your browser using Docker. Follow these steps:
|
187
191
|
|
188
192
|
1. Install [Docker](https://docs.docker.com/get-docker/) for your OS.
|
@@ -251,6 +255,10 @@ The tool now has a Modder Toolbox, which is a set of tools to help you with vari
|
|
251
255
|
|
252
256
|
### Tool Categories
|
253
257
|
Tools are divided into categories, which are listed below.
|
258
|
+
|
259
|
+
#### For custom schemas
|
260
|
+
- **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.
|
261
|
+
|
254
262
|
#### For Textures and DEM
|
255
263
|
- **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
264
|
|
@@ -419,6 +427,7 @@ Let's have a closer look at the fields:
|
|
419
427
|
- `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
428
|
- `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
429
|
- `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).
|
430
|
+
- `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
431
|
|
423
432
|
## Background terrain
|
424
433
|
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 +474,12 @@ List of the important DDS files:
|
|
465
474
|
- `mapsUS/overview.dds` - 4096x4096 pixels, the overview image of the map (in-game map)
|
466
475
|
|
467
476
|
## 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
477
|
|
472
|
-
|
473
|
-
|
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>
|
478
|
+
You can also apply some advanced settings to the map generation process.<br>
|
475
479
|
|
476
480
|
### DEM Advanced settings
|
477
481
|
|
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).
|
482
|
+
- 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
483
|
|
480
484
|
- 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
485
|
|
@@ -491,6 +495,15 @@ You can also apply some advanced settings to the map generation process. Note th
|
|
491
495
|
|
492
496
|
- 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
497
|
|
498
|
+
- 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.
|
499
|
+
|
500
|
+
- Apply decimation - if enabled, the mesh will be simplified to reduce the number of faces.
|
501
|
+
|
502
|
+
- 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.
|
503
|
+
|
504
|
+
- Decimation agression - the aggression of the decimation. The higher the value, the more aggressive the
|
505
|
+
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.
|
506
|
+
|
494
507
|
### GRLE Advanced settings
|
495
508
|
|
496
509
|
- 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 +512,18 @@ You can also apply some advanced settings to the map generation process. Note th
|
|
499
512
|
|
500
513
|
- 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
514
|
|
515
|
+
- Base grass - you can select which plant will be used as a base grass on the map.
|
516
|
+
|
517
|
+
- 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.
|
518
|
+
|
519
|
+
- Plants island maximum size - it's the same as above, but for the maximum size of the island in meters.
|
520
|
+
|
521
|
+
- 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.
|
522
|
+
|
523
|
+
- Plants insland rounding radius - used to round the vertices of the island. The higher the value, the more rounded the island will be.
|
524
|
+
|
525
|
+
- 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.
|
526
|
+
|
502
527
|
### I3D Advanced settings
|
503
528
|
|
504
529
|
- 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 +557,8 @@ The tool also supports the expert settings. Do not use them until you read the d
|
|
532
557
|
|
533
558
|
- 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
559
|
|
560
|
+
- 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.
|
561
|
+
|
535
562
|
## Resources
|
536
563
|
In this section, you'll find a list of the resources that you need to create a map for the Farming Simulator.<br>
|
537
564
|
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 +574,15 @@ To create a basic map, you only need the Giants Editor. But if you want to creat
|
|
547
574
|
➡️ Please, before creating an issue or asking some questions, check the [FAQ](docs/FAQ.md) section.<br>
|
548
575
|
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
576
|
|
577
|
+
## DTM Providers
|
578
|
+
|
579
|
+
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.
|
580
|
+
|
581
|
+
### Supported DTM providers
|
582
|
+
|
583
|
+
- [SRTM 30m](https://dwtkns.com/srtm30m/) - the 30 meters resolution DEM data from the SRTM mission for the whole world.
|
584
|
+
- [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).
|
585
|
+
|
550
586
|
## Special thanks
|
551
587
|
|
552
588
|
Of course, first of all, thanks to the direct [contributors](https://github.com/iwatkot/maps4fs/graphs/contributors) of the project.
|
@@ -562,3 +598,4 @@ But also, I want to thank the people who helped me with the project in some way,
|
|
562
598
|
- [Lucandia](https://github.com/Lucandia) - for the awesome StreamLit [widget to preview STL files](https://github.com/Lucandia/streamlit_stl).
|
563
599
|
- [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
600
|
- [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.
|
601
|
+
- [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
|
|
@@ -43,6 +44,7 @@
|
|
43
44
|
|
44
45
|
🗺️ Supports 2x2, 4x4, 8x8, 16x16 and any custom size maps<br>
|
45
46
|
🔄 Support map rotation 🆕<br>
|
47
|
+
🌐 Supports custom [DTM Providers](#DTM-Providers) 🆕<br>
|
46
48
|
🌾 Automatically generates fields 🆕<br>
|
47
49
|
🌽 Automatically generates farmlands 🆕<br>
|
48
50
|
🌿 Automatically generates decorative foliage 🆕<br>
|
@@ -103,6 +105,7 @@ docker run -d -p 8501:8501 --name maps4fs iwatkot/maps4fs
|
|
103
105
|
```
|
104
106
|
And open [http://localhost:8501](http://localhost:8501) in your browser.<br>
|
105
107
|
If you don't know how to use Docker, navigate to the [Docker version](#option-2-docker-version), it's really simple.<br>
|
108
|
+
Check out the [Docker FAQ](docs/FAQ_docker.md) if you have any questions.<br>
|
106
109
|
|
107
110
|
### 🤯 For developers
|
108
111
|
**Option 3:** Python package. Install the package using the following command:
|
@@ -157,6 +160,7 @@ Using it is easy and doesn't require any guides. Enjoy!
|
|
157
160
|
🗺️ Supported map sizes: 2x2, 4x4, 8x8, 16x16 km and any custom size.
|
158
161
|
⚙️ Advanced settings: enabled.
|
159
162
|
🖼️ Texture dissolving: enabled.
|
163
|
+
Check out the [Docker FAQ](docs/FAQ_docker.md) if you have any questions.<br>
|
160
164
|
You can launch the project with minimalistic UI in your browser using Docker. Follow these steps:
|
161
165
|
|
162
166
|
1. Install [Docker](https://docs.docker.com/get-docker/) for your OS.
|
@@ -225,6 +229,10 @@ The tool now has a Modder Toolbox, which is a set of tools to help you with vari
|
|
225
229
|
|
226
230
|
### Tool Categories
|
227
231
|
Tools are divided into categories, which are listed below.
|
232
|
+
|
233
|
+
#### For custom schemas
|
234
|
+
- **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.
|
235
|
+
|
228
236
|
#### For Textures and DEM
|
229
237
|
- **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
238
|
|
@@ -393,6 +401,7 @@ Let's have a closer look at the fields:
|
|
393
401
|
- `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
402
|
- `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
403
|
- `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).
|
404
|
+
- `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
405
|
|
397
406
|
## Background terrain
|
398
407
|
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 +448,12 @@ List of the important DDS files:
|
|
439
448
|
- `mapsUS/overview.dds` - 4096x4096 pixels, the overview image of the map (in-game map)
|
440
449
|
|
441
450
|
## 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
451
|
|
446
|
-
|
447
|
-
|
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>
|
452
|
+
You can also apply some advanced settings to the map generation process.<br>
|
449
453
|
|
450
454
|
### DEM Advanced settings
|
451
455
|
|
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).
|
456
|
+
- 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
457
|
|
454
458
|
- 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
459
|
|
@@ -465,6 +469,15 @@ You can also apply some advanced settings to the map generation process. Note th
|
|
465
469
|
|
466
470
|
- 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
471
|
|
472
|
+
- 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.
|
473
|
+
|
474
|
+
- Apply decimation - if enabled, the mesh will be simplified to reduce the number of faces.
|
475
|
+
|
476
|
+
- 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.
|
477
|
+
|
478
|
+
- Decimation agression - the aggression of the decimation. The higher the value, the more aggressive the
|
479
|
+
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.
|
480
|
+
|
468
481
|
### GRLE Advanced settings
|
469
482
|
|
470
483
|
- 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 +486,18 @@ You can also apply some advanced settings to the map generation process. Note th
|
|
473
486
|
|
474
487
|
- 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
488
|
|
489
|
+
- Base grass - you can select which plant will be used as a base grass on the map.
|
490
|
+
|
491
|
+
- 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.
|
492
|
+
|
493
|
+
- Plants island maximum size - it's the same as above, but for the maximum size of the island in meters.
|
494
|
+
|
495
|
+
- 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.
|
496
|
+
|
497
|
+
- Plants insland rounding radius - used to round the vertices of the island. The higher the value, the more rounded the island will be.
|
498
|
+
|
499
|
+
- 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.
|
500
|
+
|
476
501
|
### I3D Advanced settings
|
477
502
|
|
478
503
|
- 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 +531,8 @@ The tool also supports the expert settings. Do not use them until you read the d
|
|
506
531
|
|
507
532
|
- 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
533
|
|
534
|
+
- 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.
|
535
|
+
|
509
536
|
## Resources
|
510
537
|
In this section, you'll find a list of the resources that you need to create a map for the Farming Simulator.<br>
|
511
538
|
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 +548,15 @@ To create a basic map, you only need the Giants Editor. But if you want to creat
|
|
521
548
|
➡️ Please, before creating an issue or asking some questions, check the [FAQ](docs/FAQ.md) section.<br>
|
522
549
|
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
550
|
|
551
|
+
## DTM Providers
|
552
|
+
|
553
|
+
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.
|
554
|
+
|
555
|
+
### Supported DTM providers
|
556
|
+
|
557
|
+
- [SRTM 30m](https://dwtkns.com/srtm30m/) - the 30 meters resolution DEM data from the SRTM mission for the whole world.
|
558
|
+
- [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).
|
559
|
+
|
524
560
|
## Special thanks
|
525
561
|
|
526
562
|
Of course, first of all, thanks to the direct [contributors](https://github.com/iwatkot/maps4fs/graphs/contributors) of the project.
|
@@ -536,3 +572,4 @@ But also, I want to thank the people who helped me with the project in some way,
|
|
536
572
|
- [Lucandia](https://github.com/Lucandia) - for the awesome StreamLit [widget to preview STL files](https://github.com/Lucandia/streamlit_stl).
|
537
573
|
- [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
574
|
- [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.
|
575
|
+
- [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
|
-
|
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(
|
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.
|
259
|
+
self.logger.debug("DEM cutout saved: %s", main_dem_path)
|
223
260
|
|
224
261
|
return main_dem_path
|
225
262
|
|
226
|
-
|
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
|
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 =
|
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
|
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.
|
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,
|
@@ -535,3 +535,26 @@ class Component:
|
|
535
535
|
interpolated_polyline.append(polyline[-1])
|
536
536
|
|
537
537
|
return interpolated_polyline
|
538
|
+
|
539
|
+
def get_z_scaling_factor(self) -> float:
|
540
|
+
"""Calculates the scaling factor for the Z axis based on the map settings.
|
541
|
+
|
542
|
+
Returns:
|
543
|
+
float -- The scaling factor for the Z axis.
|
544
|
+
"""
|
545
|
+
|
546
|
+
scaling_factor = 1 / self.map.dem_settings.multiplier
|
547
|
+
self.logger.debug("Z scaling factor including DEM multiplier: %s", scaling_factor)
|
548
|
+
|
549
|
+
if self.map.shared_settings.height_scale_multiplier:
|
550
|
+
scaling_factor *= self.map.shared_settings.height_scale_multiplier
|
551
|
+
self.logger.debug(
|
552
|
+
"Z scaling factor including height scale multiplier: %s", scaling_factor
|
553
|
+
)
|
554
|
+
if self.map.shared_settings.mesh_z_scaling_factor:
|
555
|
+
scaling_factor *= 1 / self.map.shared_settings.mesh_z_scaling_factor
|
556
|
+
self.logger.debug(
|
557
|
+
"Z scaling factor including mesh z scaling factor: %s", scaling_factor
|
558
|
+
)
|
559
|
+
|
560
|
+
return scaling_factor
|
@@ -1,6 +1,7 @@
|
|
1
1
|
"""This module contains DEM class for processing Digital Elevation Model data."""
|
2
2
|
|
3
3
|
import os
|
4
|
+
from typing import Any
|
4
5
|
|
5
6
|
import cv2
|
6
7
|
import numpy as np
|
@@ -9,7 +10,7 @@ import numpy as np
|
|
9
10
|
from pympler import asizeof # type: ignore
|
10
11
|
|
11
12
|
from maps4fs.generator.component import Component
|
12
|
-
from maps4fs.generator.dtm import DTMProvider
|
13
|
+
from maps4fs.generator.dtm.dtm import DTMProvider
|
13
14
|
|
14
15
|
|
15
16
|
# pylint: disable=R0903, R0902
|
@@ -63,6 +64,7 @@ class DEM(Component):
|
|
63
64
|
size=self.map_rotated_size,
|
64
65
|
directory=self.temp_dir,
|
65
66
|
logger=self.logger,
|
67
|
+
map=self.map,
|
66
68
|
)
|
67
69
|
|
68
70
|
@property
|
@@ -281,54 +283,15 @@ class DEM(Component):
|
|
281
283
|
"""
|
282
284
|
return []
|
283
285
|
|
284
|
-
def
|
285
|
-
"""
|
286
|
-
|
286
|
+
def info_sequence(self) -> dict[Any, Any] | None: # type: ignore
|
287
|
+
"""Returns the information sequence for the component. Must be implemented in the child
|
288
|
+
class. If the component does not have an information sequence, an empty dictionary must be
|
289
|
+
returned.
|
287
290
|
|
288
|
-
Arguments:
|
289
|
-
maximum_deviation (int): Maximum deviation in DEM data.
|
290
|
-
|
291
|
-
Returns:
|
292
|
-
float: Scaling factor for DEM data normalization.
|
293
|
-
"""
|
294
|
-
ESTIMATED_MAXIMUM_DEVIATION = 1000 # pylint: disable=C0103
|
295
|
-
scaling_factor = maximum_deviation / ESTIMATED_MAXIMUM_DEVIATION
|
296
|
-
return scaling_factor if scaling_factor < 1 else 1
|
297
|
-
|
298
|
-
def _normalize_dem(self, data: np.ndarray) -> np.ndarray:
|
299
|
-
"""Normalize DEM data to 16-bit unsigned integer using max height from settings.
|
300
|
-
Arguments:
|
301
|
-
data (np.ndarray): DEM data from SRTM file after cropping.
|
302
291
|
Returns:
|
303
|
-
|
292
|
+
dict[Any, Any]: The information sequence for the component.
|
304
293
|
"""
|
305
|
-
self.
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
min_height = data.min()
|
310
|
-
max_dev = max_height - min_height
|
311
|
-
self.logger.debug(
|
312
|
-
"Maximum deviation: %s with maximum at %s and minimum at %s.",
|
313
|
-
max_dev,
|
314
|
-
max_height,
|
315
|
-
min_height,
|
316
|
-
)
|
317
|
-
|
318
|
-
scaling_factor = self._get_scaling_factor(max_dev)
|
319
|
-
adjusted_max_height = int(65535 * scaling_factor)
|
320
|
-
self.logger.debug(
|
321
|
-
"Maximum deviation: %s. Scaling factor: %s. Adjusted max height: %s.",
|
322
|
-
max_dev,
|
323
|
-
scaling_factor,
|
324
|
-
adjusted_max_height,
|
325
|
-
)
|
326
|
-
normalized_data = (
|
327
|
-
(data - data.min()) / (data.max() - data.min()) * adjusted_max_height
|
328
|
-
).astype("uint16")
|
329
|
-
self.logger.debug(
|
330
|
-
"DEM data was normalized to %s - %s.",
|
331
|
-
normalized_data.min(),
|
332
|
-
normalized_data.max(),
|
333
|
-
)
|
334
|
-
return normalized_data
|
294
|
+
provider_info_sequence = self.dtm_provider.info_sequence()
|
295
|
+
if provider_info_sequence is None:
|
296
|
+
return {}
|
297
|
+
return provider_info_sequence
|
File without changes
|