artificial-terrains 0.1.0__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.
Files changed (40) hide show
  1. artificial_terrains-0.1.0/LICENCE.md +9 -0
  2. artificial_terrains-0.1.0/PKG-INFO +364 -0
  3. artificial_terrains-0.1.0/README.md +348 -0
  4. artificial_terrains-0.1.0/artificial_terrains/__init__.py +103 -0
  5. artificial_terrains-0.1.0/artificial_terrains/generate_terrain.py +125 -0
  6. artificial_terrains-0.1.0/artificial_terrains/modules/__init__.py +1 -0
  7. artificial_terrains-0.1.0/artificial_terrains/modules/blender.py +541 -0
  8. artificial_terrains-0.1.0/artificial_terrains/modules/combining.py +232 -0
  9. artificial_terrains-0.1.0/artificial_terrains/modules/data.py +665 -0
  10. artificial_terrains-0.1.0/artificial_terrains/modules/generating.py +229 -0
  11. artificial_terrains-0.1.0/artificial_terrains/modules/generating_function.py +202 -0
  12. artificial_terrains-0.1.0/artificial_terrains/modules/las.py +106 -0
  13. artificial_terrains-0.1.0/artificial_terrains/modules/loop.py +205 -0
  14. artificial_terrains-0.1.0/artificial_terrains/modules/modifiers.py +278 -0
  15. artificial_terrains-0.1.0/artificial_terrains/modules/modules.py +83 -0
  16. artificial_terrains-0.1.0/artificial_terrains/modules/other.py +862 -0
  17. artificial_terrains-0.1.0/artificial_terrains/modules/pipes.py +130 -0
  18. artificial_terrains-0.1.0/artificial_terrains/modules/terrain.py +429 -0
  19. artificial_terrains-0.1.0/artificial_terrains/print_installed_packages.py +35 -0
  20. artificial_terrains-0.1.0/artificial_terrains/tests/test4.py +51 -0
  21. artificial_terrains-0.1.0/artificial_terrains/tests/test5.py +54 -0
  22. artificial_terrains-0.1.0/artificial_terrains/utils/Blender.py +1089 -0
  23. artificial_terrains-0.1.0/artificial_terrains/utils/artificial_shapes.py +275 -0
  24. artificial_terrains-0.1.0/artificial_terrains/utils/debug.py +20 -0
  25. artificial_terrains-0.1.0/artificial_terrains/utils/examples.py +268 -0
  26. artificial_terrains-0.1.0/artificial_terrains/utils/interpolator.py +76 -0
  27. artificial_terrains-0.1.0/artificial_terrains/utils/logging_utils.py +75 -0
  28. artificial_terrains-0.1.0/artificial_terrains/utils/noise.py +114 -0
  29. artificial_terrains-0.1.0/artificial_terrains/utils/obstacles.py +261 -0
  30. artificial_terrains-0.1.0/artificial_terrains/utils/parse_utils.py +369 -0
  31. artificial_terrains-0.1.0/artificial_terrains/utils/plots.py +579 -0
  32. artificial_terrains-0.1.0/artificial_terrains/utils/terrains.py +294 -0
  33. artificial_terrains-0.1.0/artificial_terrains/utils/utils.py +611 -0
  34. artificial_terrains-0.1.0/artificial_terrains.egg-info/PKG-INFO +364 -0
  35. artificial_terrains-0.1.0/artificial_terrains.egg-info/SOURCES.txt +38 -0
  36. artificial_terrains-0.1.0/artificial_terrains.egg-info/dependency_links.txt +1 -0
  37. artificial_terrains-0.1.0/artificial_terrains.egg-info/requires.txt +5 -0
  38. artificial_terrains-0.1.0/artificial_terrains.egg-info/top_level.txt +1 -0
  39. artificial_terrains-0.1.0/pyproject.toml +28 -0
  40. artificial_terrains-0.1.0/setup.cfg +4 -0
@@ -0,0 +1,9 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Erik Wallin
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,364 @@
1
+ Metadata-Version: 2.4
2
+ Name: artificial-terrains
3
+ Version: 0.1.0
4
+ Summary: Modular, extensible terrain generation library
5
+ Author-email: Erik Wallin <erik.wallin@umu.se>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/erikwallin86/artificial_terrains
8
+ Description-Content-Type: text/markdown
9
+ License-File: LICENCE.md
10
+ Requires-Dist: numpy
11
+ Requires-Dist: matplotlib
12
+ Requires-Dist: scipy
13
+ Requires-Dist: colorcet
14
+ Requires-Dist: opensimplex
15
+ Dynamic: license-file
16
+
17
+ # artificial_terrain
18
+
19
+ A library and script for creating artificial terrains.
20
+ The library is described in more detail in the following arXiv preprint: [arXiv abstract](https://arxiv.org/abs/2506.19751), [PDF download](https://arxiv.org/pdf/2506.19751).
21
+ The paper also includes more up-to-date and relevant examples.
22
+ For now, the README has only been cleaned to remove outdated or incorrect information; further updates are planned.
23
+
24
+ The script executes an ordered list of specified 'modules', to create and combine terrain buidling blocks to (more or less) realistic terrains.
25
+
26
+ ## Use as libary
27
+ To use as library (temporary solution until properly published/released on pypi) (only tested in linux)
28
+ 1. Clone this repo
29
+ 2. Navigate the the main folder, and run `pip install .`
30
+ Example of how to construct a simple terrain:
31
+ ```
32
+ import artificial_terrains as at
33
+
34
+
35
+ settings = [
36
+ ('Size', 100),
37
+ ('Basic', {}),
38
+ ('WeightedSum', {}),
39
+ ('Print', {}),
40
+ ('Plot', {}),
41
+ ('Save', {}),
42
+ ]
43
+
44
+ at.run(settings, verbose=True)
45
+ terrain = at.get_terrain()
46
+ print(f"terrain:{terrain}")
47
+ ```
48
+
49
+
50
+
51
+ ## Getting started
52
+ The following command creates a terrain with an overall ground-shape generated from a `WeightedSum` of different simplex noise `Octaves`. `Holes` and `Rocks` of different scale are generated and combined with a `Min` and `Max` operation respectivly. The resultant ground, holes, and rocks are `Combined` with a default Add operation, and the result is `Save`d and `Plot`ted in the folder Result.
53
+ ```
54
+ python generate_terrain.py --modules Holes Combine:Min Octaves WeightedSum Rocks Combine:Max Combine Save:Result Plot:Result --save-dir Terrains/test_001a/
55
+ ```
56
+
57
+ Alternativly, the same command can be run by
58
+ ```
59
+ python generate_terrain.py --settings-file settings.yml
60
+ ```
61
+ with settings specified in a yaml file,
62
+ ```yaml
63
+ save-dir: runs/data_001a
64
+ modules:
65
+ - Holes
66
+ - [Combine, Min]
67
+ - Octaves
68
+ - WeightedSum
69
+ - Rocks
70
+ - [Combine, Max]
71
+ - Combine
72
+ - [Save, Result]
73
+ - [Plot, Result]
74
+ ```
75
+ In all runs, a copy of the used settings is saved in `settings.yml`, and commands and prints are appended to `logger.txt`.
76
+
77
+ ## Modules
78
+ The overall setup for creating a terrain is to create 'terrain elements', and combine them in different ways.
79
+
80
+ We can split the modules in some main categories. Two fundamental such is 'generating' and 'combining'. The 'generating' generate 'terrain elements', and the 'combining' combine these elements into more complex terrains. Some modules alter the general 'settings' (e.g. extent and resolution), and some do 'input/output' (e.g. save terrains and plot).
81
+
82
+ ### Pipes
83
+ Modules are called in order, and the output of one module is passed as input to the next, as if connected along a 'pipe'. This makes it possible to generate a multitude of terrain of different types and complexities using basic building blocks.
84
+
85
+ It is also possible to run multiple pipes to generate a number of terrains.
86
+
87
+ ### 'Primary' and 'temporary' terrain lists
88
+ In order to combine basic building blocks to more complex results, and in turn combine these and so on, we utilize two lists for storing sub-results, 'primary' and 'temporary'.
89
+ Generated terrain elements are placed in the `temporary` list.
90
+ If a 'combining' module is run, it primarily operates on the content of the 'temporary' list, with the result appended to the 'primary' list.
91
+ If the 'temporary' list is empty, the 'combining' module operates on the 'primary' list instead.
92
+
93
+ ### Generating from noise
94
+ | Technique | Description | Input arguments| Output |
95
+ |-----------|-------------|-------|-------|
96
+ | **Octaves** | Generate a list of 'terrain elements' (default=10) from random noise with increasing scale factor. Additionally passes a `weights` list which can be used by `WeightedSum` to combine the 'terrain elements' to a more complex terrain. | `num_octaves=10` <br /> `start=128` <br /> `persistance=0.6` <br /> `amplitude_start=10` <br /> `random_amp=0.5` | <img src="readme/images/octaves_fixed.png" height="75"> <br /> `weights=amplitude_list` |
97
+ | **Basic** | Generate a list of 3 'terrain elements' with a large, medium, small scale factor from random noise. | | <img src="readme/images/basic_fixed.png" height="75"> |
98
+ | **Rocks** | Generate a list of 'terrain elements' (default=4) representing rocks from random noise. | `rock_size=[0.5,1,2,4]` <br /> `rock_heights=None` <br /> `fraction=0.8` | <img src="readme/images/rocks_fixed.png" height="75"> |
99
+ | **Holes** | Generate a list of 'terrain elements' (default=4) representing holes from random noise. | `size_list=[0.5,1,2,4]` <br /> `fraction=0.8` | <img src="readme/images/holes_fixed.png" height="75"> |
100
+
101
+ ### Combining
102
+ | Technique | Description | Input arguments | Example input| Output |
103
+ |-----------|-------------|----------------|---------------|--------|
104
+ |**Combine**| Combines the (entire by default) content of the 'temporary' list (primarily) or the 'primary' list (secondarily) using a mathematical operation e.g. (add, min, max, prod). | `operation='add'` <br /> `last=None` | <img src="readme/images/trio_fixed.png" height="75"> | `Combine:add` <img src="readme/images/add.png" height="75"> <br /> `Combine:max` <img src="readme/images/max.png" height="75"> <br /> `Combine:min`<img src="readme/images/min.png" height="75"> <br /> `Combine:prod`<img src="readme/images/prod.png" height="75">
105
+ |**CombineLast**| As Combine, but only work on the last 2 terrains in the 'temporary' or primary lists. (note that this is a shortcut, and the option `last=X` can be passed to `Combine` for the more general case of combining the last X terrains) | `operation='add'` | |
106
+ |**WeightedSum**| Add the content of the 'temporary' list as a weighted sum. The input `weights` must match the length of the 'temporary' list.| `weights=[5,8,0.1]` | <img src="readme/images/octaves_fixed.png" height="75"> | <img src="readme/images/octaves_sum_fixed.png" height="75"> |
107
+
108
+
109
+
110
+
111
+ ### Other?
112
+ | Technique | Description | Image |
113
+ |-----------|-------------|-------|
114
+ | **Extent** | Set the coordinate bounds of the terrain as [x_min, x_max, y_min, y_max]. Determines the physical area covered. | |
115
+ | **Location** | Shifts the terrain’s position in space. Applied as an offset to the Extent. | |
116
+ | **Size** | Set the physical size of the terrain | |
117
+ | **Resolution** | 'resolution', in points per meter. Used to infer the grid-size, if that is not explicitly given | |
118
+ | **GridSize** | Set the 'grid_size', the number of values in each dimension. Overrides the `resolution` if given. | |
119
+ | **Seed** | Set random seed | |
120
+ | **Folder** | Set folder, affects eg. 'Save' and 'Plot' and other modules where a 'folder' is given as input | |
121
+ | **Set** | Set parameter value as `Set:parameter=value` | |
122
+ | **SetDistribution** | Set distribution as `SetDistribution:parameter=distribution[*args]`. Both square and rounded parenthesis can be used. In bash, rounded parameter must either be 'escaped' (as `SetDistribution:parameter=distribution\(*args\)`), or placed within quotation marks (as `SetDistribution:'parameter=distribution(*args)'` | |
123
+
124
+
125
+
126
+ ### Obstacles?
127
+ | Technique | Description | Input | Example 1 | Example 2 | Example 3 | Example 4 |
128
+ |-----------|-------------|-------|-------|-------|-------|-------|
129
+ | **LoadObstacles** | LoadObstacles | | |
130
+ | **SaveObstacles** | SaveObstacles | | |
131
+ | **Random** | Random | `number_of_values` <br /> `position_distribution` <br /> `height_distribution` <br /> `yaw_deg_distribution` <br /> `width_distribution` <br /> `aspect_distribution` <br /> `pitch_deg_distribution` <br /> `position_distribution_2d` | `Random:10` <br /> <img src="readme/images/random_10.png" height="75"> | `Random:position` <br /> <img src="readme/images/random_2.png" height="75"> | `Random:[position,yaw_deg]` <br /> <img src="readme/images/random_5.png" height="75"> |`Set:number_of_values=10 Random:[position,yaw_deg]` <br /> <img src="readme/images/random_6.png" height="75"> |
132
+
133
+
134
+ ### Generating from functions
135
+ | Technique | Description | Input | Basic output | Combined output |
136
+ |-----------|-------------|-------|---|----|
137
+ | **Gaussian** | Gaussian | `position` <br /> `height` <br /> `yaw_deg` <br /> `width` <br /> `aspect` <br /> ~~`pitch_deg`~~ | `Gaussian` <br /> <img src="readme/images/gaussian_fixed.png" height="75"> | `Random:10 Gaussian Combine:Max` <br /> <img src="readme/images/combined_gaussian_fixed.png" height="75"> |
138
+ | **Step** | Step| `position` <br /> `height` <br /> `yaw_deg` <br /> ~~`width`~~ <br /> ~~`aspect`~~ <br /> ~~`pitch_deg`~~ | `Step` <br /> <img src="readme/images/step_fixed.png" height="75"> | `Random:10 Step Combine:Max` <br /> <img src="readme/images/combined_step_fixed.png" height="75"> |
139
+ | **Donut** | Donut| `position` <br /> `height` <br /> `yaw_deg` <br /> `width` <br /> `aspect` <br /> ~~`pitch_deg`~~ | `Donut` <br /> <img src="readme/images/donut_fixed.png" height="75"> | `Random:10 Donut Combine:Max` <br /> <img src="readme/images/combined_donut_fixed.png" height="75"> |
140
+ | **Plane** | Plane| ~~`position`~~ <br /> ~~`height`~~ <br /> `yaw_deg` <br /> ~~`width`~~ <br /> `aspect` <br /> `pitch_deg` | `Plane` <br /> <img src="readme/images/plane_fixed.png" height="75"> | `Random:10 Plane Combine:Max` <br /> <img src="readme/images/combined_plane_fixed.png" height="75"> |
141
+ | **Sphere** | Sphere| `position` <br /> `height` <br /> `yaw_deg` <br /> `width` <br /> `aspect` <br /> ~~`pitch_deg`~~ | `Sphere` <br /> <img src="readme/images/sphere_fixed.png" height="75"> | `Random:10 Sphere Combine:Max` <br /> <img src="readme/images/combined_sphere_fixed.png" height="75"> |
142
+ | **Cube** | Cube| `position` <br /> `height` <br /> `yaw_deg` <br /> `width` <br /> `aspect` <br /> ~~`pitch_deg`~~ | `Cube` <br /> <img src="readme/images/cube_fixed.png" height="75"> | `Random:10 Cube Combine:Max` <br /> <img src="readme/images/combined_cube_fixed.png" height="75"> |
143
+ | **SmoothStep** | SmoothStep| | `SmoothStep` <br /> <img src="readme/images/smoothstep_fixed.png" height="75"> | `Random:10 SmoothStep Combine:Max` <br /> <img src="readme/images/combined_smoothstep_fixed.png" height="75"> |
144
+ | **Sine** | Sine| ~~`position`~~ <br /> `height` <br /> `yaw_deg` <br /> `width` <br /> ~~`aspect`~~ <br /> ~~`pitch_deg`~~ | `Sine` <br /> <img src="readme/images/sine_fixed.png" height="75"> | `Random:10 Sine Combine:Max` <br /> <img src="readme/images/combined_sine_fixed.png" height="75"> |
145
+
146
+
147
+ ### Modifiers
148
+ | Technique | Description | Image |
149
+ |-----------|-------------|-------|
150
+ |**Negate**| Negate ||
151
+ |**Scale**| Scale ||
152
+ |**Add**| Add ||
153
+ |**Absolute**| Absolute ||
154
+ |**Clip**| Clip ||
155
+ |**Around**| Around ||
156
+ |**Smooth**| Smooth ||
157
+ |**AsProbability**| AsProbability ||
158
+ |**AsLookupFor**| AsLookupFor ||
159
+ |**AsFactor**| AsFactor ||
160
+
161
+
162
+ ### Settings
163
+
164
+
165
+ ### Input/output
166
+ | Technique | Description | Input |
167
+ |-----------|-------------|-------|
168
+ | Save | Save terrains | `folder='Save'` (default) <br /> `filename='terrain.npz'` |
169
+ | Plot | Plot terrains | |
170
+
171
+
172
+ ### Other
173
+ | Technique | Description | Input |
174
+ |-----------|-------------|-------|
175
+ | **Exit** | Exit early | | |
176
+ | **Print** | Print information of pipe | | |
177
+
178
+
179
+
180
+ ### Examples
181
+ Examples of different combinations of modules and the resultant terrains. Only the relevant modules are listed in the table, and not the full command to generate the terrain/rendered images. However, these commands can be found below the table. In some cases, alternative (equivalent or almost equivalent) formatting are shown. Most of the terrains/images are generated by a single command, but some might require two or more.
182
+
183
+ | #| Description | Modules | Output |
184
+ |-|------------|-------|-------|
185
+ | 1 | Sloped plane with grooves. Adding an angled plane to a sine plane | `Set:width=10 Sine Random:1 Plane Combine` **or** <br /> `Sine:"dict(width=10)" Plane:"dict(pitch_deg=10)" Combine:Add` | <img src="readme/images/02_angled_sine_plane_fixed.png" > |
186
+ | 2| Walls along the perimiter. Negating a large cube. | `Set:width=45 Cube Negate` **or** <br /> `Cube:"dict(width=45)" Negate`| <img src="readme/images/01_wall_fixed.png"> |
187
+ | 3 | Moon landscape. Combine multiple 'donuts' using a pointwise max, and adding to a large sphere | `Random:20 Donut Combine:Max Set:width=500 Sphere ToPrimary Combine:Add` | <img src="readme/images/03_moon_landcape_fixed.png"> |
188
+ |4 | Stone circle. Interpret a large donut as a positional probability, and setup a constant width-distribution. Draw 30 random samples to generate cube-terrains in the temporary list, and combine using pointwise max. | `Donut:"dict(width=35)" AsProbability SetDistribution:width=uniform[2,2] Random:30 Cube Combine:Max` | <img src="readme/images/04_stone_circle_fixed.png" > |
189
+ | 5| Stone circle with obj-file stones. Increase resolution to 10 points-per-meter. Make a flat terrain, and use to make a blender-ground. Sample points along a circle as above, and use to add rocks in blender. Generate Depth image and save. | `Resolution:10 Plane Ground Donut:"dict(width=35)" AsProbability SetDistribution:width=uniform[2,2] Random:30 AddRocks Depth Save` | <img src="readme/images/05_stone_circle2b_fixed.png"> |
190
+ | 6 | Terrain from noise, combined with step function | `Octaves WeightedSum Random:2 Step Combine:Max Combine:Add` | <img src="readme/images/06_terrain_with_step_fixed.png" > |
191
+ | 7 | Load from saved 'octaves' and combine using random weights | `Resolution:10 Octaves Save:Octaves` **then** `Load:runs/data_030/Octaves Random:weights WeightedSum` | <img src="readme/images/07_generate_and_load_fixed.png" > |
192
+ | 8 | Load from saved octaves, and add unevenly spaced rocks. We use the combination of some 'Basic' terrains to get a 2d position probability, and add 10 obj-file rocks in blender. | (Assumes first step from 7) `Load:runs/data_030/Octaves Random:weights WeightedSum Ground Basic Combine:Add AsProbability Random:10 AddRocks Depth Save` | <img src="readme/images/08_unevenly_spaced_rocksb_fixed.png" > |
193
+
194
+
195
+ #### Full commands to make terrains, plot, and save as numpy npz files
196
+ ```
197
+ # 1
198
+ python generate_terrain.py --save-dir runs/data_030 --settings overwrite:True --modules Sine:"dict(width=10)" Plane:"dict(pitch_deg=10)" Combine:Add Folder:02_angled_sine_plane Plot Save
199
+ # 2
200
+ python generate_terrain.py --save-dir runs/data_030 --settings overwrite:True --modules Set:width=45 Cube Negate Folder:01_wall Plot Save
201
+
202
+ # 6
203
+ python generate_terrain.py --save-dir runs/data_030 --settings overwrite:True --modules Octaves WeightedSum Random:2 Step Combine:Max Combine:Add Folder:06_terrain_with_step Plot Save
204
+ # 7
205
+ python generate_terrain.py --save-dir runs/data_030 --settings overwrite:True --modules Resolution:10 Octaves Save:Octaves
206
+ python generate_terrain.py --save-dir runs/data_030 --settings overwrite:True --modules Load:runs/data_030/Octaves Random:weights WeightedSum Folder:07_generate_and_load Plot Save
207
+ # 8
208
+ blender --python generate_terrain.py -- --save-dir runs/data_030 --settings overwrite:True --modules Load:runs/data_030/Octaves Random:weights WeightedSum Ground Basic Combine:Add AsProbability Random:10 AddRocks Folder:08_unevenly_spaced_rocks Resolution:10 Camera:top Depth Save
209
+ ```
210
+
211
+
212
+ #### Full commands to make the above rendered images
213
+ ```
214
+ # 1
215
+ blender --python generate_terrain.py -- --save-dir runs/data_030 --settings overwrite:True --modules Sine:"dict(width=10)" Plane:"dict(pitch_deg=10)" Combine:Add Folder:02_angled_sine_plane Plot Save Ground ColorMap:dimgray Camera:angled Holdout Render Exit
216
+ # 2
217
+ blender --python generate_terrain.py -- --save-dir runs/data_030 --settings overwrite:True --modules Set:width=45 Cube Negate Folder:01_wall Plot Save Ground ColorMap:dimgray Camera:angled Holdout Render Exit
218
+
219
+ # 6
220
+ blender --python generate_terrain.py -- --save-dir runs/data_030 --settings overwrite:True --modules Octaves WeightedSum Random:2 Step Combine:Max Combine:Add Folder:06_terrain_with_step Plot Save Ground ColorMap:dimgray Camera:angled Holdout Render
221
+ # 7
222
+ python generate_terrain.py --save-dir runs/data_030 --settings overwrite:True --modules Resolution:10 Octaves Save:Octaves
223
+ blender --python generate_terrain.py -- --save-dir runs/data_030 --settings overwrite:True --modules Load:runs/data_030/Octaves Random:weights WeightedSum Folder:07_generate_and_load Plot Save Ground ColorMap:dimgray Camera:angled Holdout Render
224
+ # 8
225
+ blender --python generate_terrain.py -- --save-dir runs/data_030 --settings overwrite:True --modules Load:runs/data_030/Octaves Random:weights WeightedSum Ground Basic Combine:Add AsProbability Random:10 AddRocks Folder:08_unevenly_spaced_rocks Resolution:10 Camera:top Depth Save
226
+ blender --python generate_terrain.py -- --save-dir runs/data_030 --settings overwrite:True --modules Load:runs/data_030/08_unevenly_spaced_rocks/terrain_00000.npz Ground Folder:08_unevenly_spaced_rocksb Plot Save Ground ColorMap:dimgray Camera:angled Holdout Render
227
+ ```
228
+
229
+
230
+
231
+
232
+ ### Blender
233
+ The script `generate_terrain.py` enables using blender via its python interface. All the above modules work, in additionally a number of specific modules, listed below.
234
+ To run the blender script, the following command is used in place of `python generate_terrain.py`: `blender --python generate_terrain.py --`. Note the final `--`, which states that any following arguments are passed to the script `generate_terrain.py` (and not the actual blender software). An example run, producing an angled plane with sine grooves:
235
+ ```
236
+ blender --python generate_terrain.py -- --save-dir runs/data_001/ --modules Sine Random Plane Combine Ground
237
+ ```
238
+
239
+ | Technique | Description | Input | Output |
240
+ |-----------|-------------|-------|-------|
241
+ | **Ground** | Create grid, using either a terrain from a specified file, or the latest terrain in the primary or temporary heaps | `filename=None` | `Ground` <br /> <img src="readme/images/ground_fixed.png" height="75"> |
242
+ | **ColorMap** | Color heightfield using colormap | ~~`cmap='viridis'`~~ | `Ground ColorMap` <br /> <img src="readme/images/colormap_fixed.png" height="75"> |
243
+ | **AddRocks** | Add rocks to scene. | `position` <br /> ~~`height`~~ <br /> `yaw_deg` <br /> `width` <br /> ~~`aspect`~~ <br /> `pitch_deg` | `Ground Random:10 AddRocks` <br /> <img src="readme/images/addrocks_fixed.png" height="75"> |
244
+ | **ImageTexture** | Color heightfield using image texture file | `filename=None` | `Ground ImageTexture:image_texture.png` <br /> <img src="readme/images/imagetexture_fixed.png" height="75"> |
245
+ | **Render** | | | `Ground Random:10 AddRocks Render` <br /> <img src="readme/images/addrocks_fixed.png" height="75"> |
246
+ | **RenderSegmentation** | | | `Ground Random:10 AddRocks RenderSegmentation` <br /> <img src="readme/images/render_segmentation_fixed.png" height="75"> |
247
+ | **Depth** | Generate depth image. This also returns a 'terrain', but this will only be resonable together with the `Camera:top` command, see below. | | `Ground Random:10 AddRocks Depth` <br /> <img src="readme/images/depth_fixed.png" height="75"> |
248
+ | **Camera** | Setup camera. Takes either 'angled' or 'top' as input | | `... Depth:top` <br /> <img src="readme/images/depth_top.png" height="75"> |
249
+ | **GenericCamera** | | | |
250
+ | **Holdout** | Add a large 'holdout plane' at height -100 m, which gives a transparent background in generated images. | | |
251
+ | **BasicSetup** | Clean and setup basic blender scene. NOTE: Runs by default as the first module. | | |
252
+
253
+
254
+
255
+
256
+
257
+
258
+
259
+ ## Dependencies
260
+ In order to be able to run, the following python packages should be installed.
261
+ ```
262
+ python -m pip install numpy
263
+ python -m pip install matplotlib
264
+ python -m pip install opensimplex
265
+ python -m pip install colorcet
266
+ python -m pip install PyYaml
267
+ python -m pip install scipy
268
+ ```
269
+
270
+
271
+ ## Settings file
272
+ The options in the settings can be specified with different formatting. The `modules` is a list of 2-tuples/lists `(module-name, options)`. The following contains 4 examples of equivalent formatting.
273
+ ```yaml
274
+ modules
275
+ # Version 1, default formatting
276
+ - - Donut
277
+ - position:
278
+ - 10
279
+ - 10
280
+ height: 5
281
+
282
+ # Version 2, position list on one line
283
+ - - Donut
284
+ - position: [10, 10]
285
+ height: 5
286
+
287
+ # Version 3, options as a one line dict
288
+ - - Donut
289
+ - {position: [10, 10], height: 5}
290
+
291
+ # Version 4, [name, options] on one line
292
+ - [Donut, {position: [10, 10], height: 5}]
293
+ ```
294
+ In each run, the used settings are saved to `<save_dir>/settings.yml`.
295
+
296
+
297
+ ## Extending
298
+ The setup is modular and new 'modules' can easiliy be added, as e.g.
299
+ ```
300
+ class NewModule(Module):
301
+ ''' A new module '''
302
+ @debug_decorator
303
+ def __call__(self, terrain=None,
304
+ default=None,
305
+ overwrite=False,
306
+ **_):
307
+ ```
308
+ This inherits from the `Module` base class, which sets up e.g. logging and `self.save_dir`. The new module is setup by defining the `__call__` method. As a module is run, this method is executed, with the `pipe` given as keyword arguments. The `default` argument is special. If a single value/string is passed as options for the module, e.g. `Random:10` or `Load:folder/terrain.npz`, then this is passed as the 'default' value.
309
+ Otherwise the keyword arguments are given py the pipe, or by specifying a dict input to the module, as e.g. `Gaussian:"dict(position=[10,10],height=3,width=10)"`
310
+
311
+ The above example takes a `terrain` keyword as input, with the idea of this being passed in the 'pipe' from a previous module, e.g. `Load` or some 'generating' module. Anything can be passed between modules in this way, and the names are arbitrary. Some special are the following,
312
+ [Note that these are the current names and this might/will change after some clean up]
313
+ | Name | Description |
314
+ |-----------|-------------|
315
+ | `terrain_prim` | The primary list |
316
+ | `terrain_temp` | The temporary list |
317
+ | `position`, `height`, `yaw_deg`, `width`, `aspect`, `pitch_deg` | Parameterisation of generation functions, obstacles etc. in a common interface |
318
+ | `extent`, `resolution` | Parameterisation of the terrain extent and resolution. |
319
+ | `weights` | A list of weights, which is currently used by `WeightedSum` to combine different basics to a terrain |
320
+
321
+ The `return` from a module is collected, in order to allow passing information between modules. The typical return type is a `dict`. It is used to update the pipe, after which any `None` type values are removed from the pipe.
322
+
323
+
324
+ ## Ubuntu
325
+ Install blender, and clone the repo.
326
+ Use a virtual environment for python.
327
+ If the virtual environment uses the same version of python as blender does, life will be easier.
328
+ (otherwise the blender script will give some ModuleNotFoundError)
329
+ Install the following python packages
330
+ ```
331
+ python -m pip install numpy
332
+ python -m pip install matplotlib
333
+ python -m pip install opensimplex
334
+ python -m pip install colorcet
335
+ python -m pip install PyYaml
336
+ python -m pip install scipy
337
+ ```
338
+
339
+
340
+ ## Windows
341
+ Install git for Windows, install python, and install blender. Clone the repo.
342
+
343
+ When running blender scripts, this uses a separate python, and the dependencies must be installed there as well.
344
+ This worked by running the following in git-bash in Windows:
345
+ ```
346
+ C:\\Program\ Files\\Blender\ Foundation\\Blender\ 4.1\\4.1\\python\\bin\\python.exe -m pip install matplotlib
347
+ C:\\Program\ Files\\Blender\ Foundation\\Blender\ 4.1\\4.1\\python\\bin\\python.exe -m pip install opensimplex
348
+ C:\\Program\ Files\\Blender\ Foundation\\Blender\ 4.1\\4.1\\python\\bin\\python.exe -m pip install colorcet
349
+ C:\\Program\ Files\\Blender\ Foundation\\Blender\ 4.1\\4.1\\python\\bin\\python.exe -m pip install PyYaml
350
+ C:\\Program\ Files\\Blender\ Foundation\\Blender\ 4.1\\4.1\\python\\bin\\python.exe -m pip install scipy
351
+ ```
352
+ (There where some problems with scipy though, for unknown reasons)
353
+
354
+
355
+ ## If things don't work
356
+ There is a script, `print_installed_packages.py`, which can be used to debug the python environment.
357
+ Running it with blender can show the installed packages, and help to understand which python is run (e.g. blender python, system python, or some python environment?).
358
+ ```
359
+ blender --python print_installed_packages.py --background
360
+ ```
361
+ This can be compared to running python
362
+ ```
363
+ python print_installed_packages.py
364
+ ```