├── .gitignore
├── Assets
├── Default_1mx1m.png
├── Default_1mx1m.png.import
├── Image_12.jpg
├── Image_12.jpg.import
├── Image_13.png
├── Image_13.png.import
├── Image_15.jpg
├── Image_15.jpg.import
├── Image_16.png
├── Image_16.png.import
├── Image_18.png
├── Image_18.png.import
├── Image_19.png
├── Image_19.png.import
├── Image_2.jpg
├── Image_2.jpg.import
├── Image_21.jpg
├── Image_21.jpg.import
├── Image_22.png
├── Image_22.png.import
├── Image_24.jpg
├── Image_24.jpg.import
├── Image_25.png
├── Image_25.png.import
├── Image_27.jpg
├── Image_27.jpg.import
├── Image_28.png
├── Image_28.png.import
├── Image_30.jpg
├── Image_30.jpg.import
├── Image_31.png
├── Image_31.png.import
├── Image_33.jpg
├── Image_33.jpg.import
├── Image_34.png
├── Image_34.png.import
├── Image_37.jpg
├── Image_37.jpg.import
├── Image_38.png
├── Image_38.png.import
├── Image_39.jpg
├── Image_39.jpg.import
├── Image_40.png
├── Image_40.png.import
├── Image_49.png
├── Image_49.png.import
├── Image_50.png
├── Image_50.png.import
├── Image_66.jpg
├── Image_66.jpg.import
├── Image_67.png
├── Image_67.png.import
├── Image_75.jpg
├── Image_75.jpg.import
├── Image_76.png
├── Image_76.png.import
├── asphalt_01_diff_4k.jpg
├── asphalt_01_diff_4k.jpg.import
├── grass.jpg
├── grass.jpg.import
├── gravel-ballast-roof-2500-mm-architextures.png
└── gravel-ballast-roof-2500-mm-architextures.png.import
├── CameraEnvironment.tres
├── GUIMaterials
├── PressedButton.tres
└── SelectedTensorField.tres
├── LICENSE
├── Materials
├── BuildingMaterial1.tres
├── BuildingMaterial10.tres
├── BuildingMaterial11.tres
├── BuildingMaterial2.tres
├── BuildingMaterial3.tres
├── BuildingMaterial4.tres
├── BuildingMaterial5.tres
├── BuildingMaterial6.tres
├── BuildingMaterial7.tres
├── BuildingMaterial8.tres
├── BuildingMaterial9.tres
├── BuildingRoofMaterial1.tres
├── FloorMaterial.tres
├── RoadMaterial1.tres
└── SidewalkMaterial1.tres
├── Prefabs
└── tensorFieldPoint.tscn
├── ProceduralCityGenerator.csproj
├── ProceduralCityGenerator.csproj.old
├── ProceduralCityGenerator.sln
├── ProceduralCityGenerator.sln.DotSettings.user
├── README.md
├── Scenes
└── Main.tscn
├── Scripts
├── CameraController.cs
├── DataStructure
│ ├── Field.cs
│ ├── Grid.cs
│ ├── GridStorage.cs
│ ├── IPointDrawImmediate.cs
│ ├── Integrator.cs
│ ├── Intersection.cs
│ ├── PolygonGenerator.cs
│ ├── Radial.cs
│ ├── Segment.cs
│ ├── StreamLineIntegration.cs
│ ├── StreamLines.cs
│ ├── StreamLinesParams.cs
│ ├── Tensor.cs
│ └── TensorField.cs
├── GUI
│ ├── GuiController.cs
│ └── PropertiesPointsEdit.cs
├── LineDrawer3D.cs
├── MainBuildings3D.cs
├── MainRoads3D.cs
├── MainScript.cs
├── MainSidewalk3D.cs
├── PointDrawer3D.cs
├── RayCast3D.cs
└── Roads.cs
├── default_env.tres
├── icon.png
├── icon.png.import
└── project.godot
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by https://www.toptal.com/developers/gitignore/api/latex,godot,rider,visualstudiocode
2 | # Edit at https://www.toptal.com/developers/gitignore?templates=latex,godot,rider,visualstudiocode
3 |
4 | ### Godot ###
5 | # Godot 4+ specific ignores
6 | .godot/
7 | .idea/
8 |
9 | # Godot-specific ignores
10 | .import/
11 | export.cfg
12 | export_presets.cfg
13 |
14 | # Imported translations (automatically generated from CSV files)
15 | *.translation
16 |
17 | # Mono-specific ignores
18 | .mono/
19 | data_*/
20 | mono_crash.*.json
21 |
22 | ### LaTeX ###
23 | ## Core latex/pdflatex auxiliary files:
24 | *.aux
25 | *.lof
26 | *.log
27 | *.lot
28 | *.fls
29 | *.out
30 | *.toc
31 | *.fmt
32 | *.fot
33 | *.cb
34 | *.cb2
35 | .*.lb
36 |
37 | ## Intermediate documents:
38 | *.dvi
39 | *.xdv
40 | *-converted-to.*
41 | # these rules might exclude image files for figures etc.
42 | # *.ps
43 | # *.eps
44 | # *.pdf
45 |
46 | ## Generated if empty string is given at "Please type another file name for output:"
47 | .pdf
48 |
49 | ## Bibliography auxiliary files (bibtex/biblatex/biber):
50 | *.bbl
51 | *.bcf
52 | *.blg
53 | *-blx.aux
54 | *-blx.bib
55 | *.run.xml
56 |
57 | ## Build tool auxiliary files:
58 | *.fdb_latexmk
59 | *.synctex
60 | *.synctex(busy)
61 | *.synctex.gz
62 | *.synctex.gz(busy)
63 | *.pdfsync
64 |
65 | ## Build tool directories for auxiliary files
66 | # latexrun
67 | latex.out/
68 |
69 | ## Auxiliary and intermediate files from other packages:
70 | # algorithms
71 | *.alg
72 | *.loa
73 |
74 | # achemso
75 | acs-*.bib
76 |
77 | # amsthm
78 | *.thm
79 |
80 | # beamer
81 | *.nav
82 | *.pre
83 | *.snm
84 | *.vrb
85 |
86 | # changes
87 | *.soc
88 |
89 | # comment
90 | *.cut
91 |
92 | # cprotect
93 | *.cpt
94 |
95 | # elsarticle (documentclass of Elsevier journals)
96 | *.spl
97 |
98 | # endnotes
99 | *.ent
100 |
101 | # fixme
102 | *.lox
103 |
104 | # feynmf/feynmp
105 | *.mf
106 | *.mp
107 | *.t[1-9]
108 | *.t[1-9][0-9]
109 | *.tfm
110 |
111 | #(r)(e)ledmac/(r)(e)ledpar
112 | *.end
113 | *.?end
114 | *.[1-9]
115 | *.[1-9][0-9]
116 | *.[1-9][0-9][0-9]
117 | *.[1-9]R
118 | *.[1-9][0-9]R
119 | *.[1-9][0-9][0-9]R
120 | *.eledsec[1-9]
121 | *.eledsec[1-9]R
122 | *.eledsec[1-9][0-9]
123 | *.eledsec[1-9][0-9]R
124 | *.eledsec[1-9][0-9][0-9]
125 | *.eledsec[1-9][0-9][0-9]R
126 |
127 | # glossaries
128 | *.acn
129 | *.acr
130 | *.glg
131 | *.glo
132 | *.gls
133 | *.glsdefs
134 | *.lzo
135 | *.lzs
136 | *.slg
137 | *.slo
138 | *.sls
139 |
140 | # uncomment this for glossaries-extra (will ignore makeindex's style files!)
141 | # *.ist
142 |
143 | # gnuplot
144 | *.gnuplot
145 | *.table
146 |
147 | # gnuplottex
148 | *-gnuplottex-*
149 |
150 | # gregoriotex
151 | *.gaux
152 | *.glog
153 | *.gtex
154 |
155 | # htlatex
156 | *.4ct
157 | *.4tc
158 | *.idv
159 | *.lg
160 | *.trc
161 | *.xref
162 |
163 | # hyperref
164 | *.brf
165 |
166 | # knitr
167 | *-concordance.tex
168 | # TODO Uncomment the next line if you use knitr and want to ignore its generated tikz files
169 | # *.tikz
170 | *-tikzDictionary
171 |
172 | # listings
173 | *.lol
174 |
175 | # luatexja-ruby
176 | *.ltjruby
177 |
178 | # makeidx
179 | *.idx
180 | *.ilg
181 | *.ind
182 |
183 | # minitoc
184 | *.maf
185 | *.mlf
186 | *.mlt
187 | *.mtc[0-9]*
188 | *.slf[0-9]*
189 | *.slt[0-9]*
190 | *.stc[0-9]*
191 |
192 | # minted
193 | _minted*
194 | *.pyg
195 |
196 | # morewrites
197 | *.mw
198 |
199 | # newpax
200 | *.newpax
201 |
202 | # nomencl
203 | *.nlg
204 | *.nlo
205 | *.nls
206 |
207 | # pax
208 | *.pax
209 |
210 | # pdfpcnotes
211 | *.pdfpc
212 |
213 | # sagetex
214 | *.sagetex.sage
215 | *.sagetex.py
216 | *.sagetex.scmd
217 |
218 | # scrwfile
219 | *.wrt
220 |
221 | # svg
222 | svg-inkscape/
223 |
224 | # sympy
225 | *.sout
226 | *.sympy
227 | sympy-plots-for-*.tex/
228 |
229 | # pdfcomment
230 | *.upa
231 | *.upb
232 |
233 | # pythontex
234 | *.pytxcode
235 | pythontex-files-*/
236 |
237 | # tcolorbox
238 | *.listing
239 |
240 | # thmtools
241 | *.loe
242 |
243 | # TikZ & PGF
244 | *.dpth
245 | *.md5
246 | *.auxlock
247 |
248 | # titletoc
249 | *.ptc
250 |
251 | # todonotes
252 | *.tdo
253 |
254 | # vhistory
255 | *.hst
256 | *.ver
257 |
258 | # easy-todo
259 | *.lod
260 |
261 | # xcolor
262 | *.xcp
263 |
264 | # xmpincl
265 | *.xmpi
266 |
267 | # xindy
268 | *.xdy
269 |
270 | # xypic precompiled matrices and outlines
271 | *.xyc
272 | *.xyd
273 |
274 | # endfloat
275 | *.ttt
276 | *.fff
277 |
278 | # Latexian
279 | TSWLatexianTemp*
280 |
281 | ## Editors:
282 | # WinEdt
283 | *.bak
284 | *.sav
285 |
286 | # Texpad
287 | .texpadtmp
288 |
289 | # LyX
290 | *.lyx~
291 |
292 | # Kile
293 | *.backup
294 |
295 | # gummi
296 | .*.swp
297 |
298 | # KBibTeX
299 | *~[0-9]*
300 |
301 | # TeXnicCenter
302 | *.tps
303 |
304 | # auto folder when using emacs and auctex
305 | ./auto/*
306 | *.el
307 |
308 | # expex forward references with \gathertags
309 | *-tags.tex
310 |
311 | # standalone packages
312 | *.sta
313 |
314 | # Makeindex log files
315 | *.lpz
316 |
317 | # xwatermark package
318 | *.xwm
319 |
320 | # REVTeX puts footnotes in the bibliography by default, unless the nofootinbib
321 | # option is specified. Footnotes are the stored in a file with suffix Notes.bib.
322 | # Uncomment the next line to have this generated file ignored.
323 | #*Notes.bib
324 |
325 | ### LaTeX Patch ###
326 | # LIPIcs / OASIcs
327 | *.vtc
328 |
329 | # glossaries
330 | *.glstex
331 |
332 | ### Rider ###
333 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
334 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
335 |
336 | # User-specific stuff
337 | .idea/**/workspace.xml
338 | .idea/**/tasks.xml
339 | .idea/**/usage.statistics.xml
340 | .idea/**/dictionaries
341 | .idea/**/shelf
342 |
343 | # AWS User-specific
344 | .idea/**/aws.xml
345 |
346 | # Generated files
347 | .idea/**/contentModel.xml
348 |
349 | # Sensitive or high-churn files
350 | .idea/**/dataSources/
351 | .idea/**/dataSources.ids
352 | .idea/**/dataSources.local.xml
353 | .idea/**/sqlDataSources.xml
354 | .idea/**/dynamic.xml
355 | .idea/**/uiDesigner.xml
356 | .idea/**/dbnavigator.xml
357 |
358 | # Gradle
359 | .idea/**/gradle.xml
360 | .idea/**/libraries
361 |
362 | # Gradle and Maven with auto-import
363 | # When using Gradle or Maven with auto-import, you should exclude module files,
364 | # since they will be recreated, and may cause churn. Uncomment if using
365 | # auto-import.
366 | # .idea/artifacts
367 | # .idea/compiler.xml
368 | # .idea/jarRepositories.xml
369 | # .idea/modules.xml
370 | # .idea/*.iml
371 | # .idea/modules
372 | # *.iml
373 | # *.ipr
374 |
375 | # CMake
376 | cmake-build-*/
377 |
378 | # Mongo Explorer plugin
379 | .idea/**/mongoSettings.xml
380 |
381 | # File-based project format
382 | *.iws
383 |
384 | # IntelliJ
385 | out/
386 |
387 | # mpeltonen/sbt-idea plugin
388 | .idea_modules/
389 |
390 | # JIRA plugin
391 | atlassian-ide-plugin.xml
392 |
393 | # Cursive Clojure plugin
394 | .idea/replstate.xml
395 |
396 | # SonarLint plugin
397 | .idea/sonarlint/
398 |
399 | # Crashlytics plugin (for Android Studio and IntelliJ)
400 | com_crashlytics_export_strings.xml
401 | crashlytics.properties
402 | crashlytics-build.properties
403 | fabric.properties
404 |
405 | # Editor-based Rest Client
406 | .idea/httpRequests
407 |
408 | # Android studio 3.1+ serialized cache file
409 | .idea/caches/build_file_checksums.ser
410 |
411 | ### VisualStudioCode ###
412 | .vscode/*
413 | !.vscode/settings.json
414 | !.vscode/tasks.json
415 | !.vscode/launch.json
416 | !.vscode/extensions.json
417 | !.vscode/*.code-snippets
418 |
419 | # Local History for Visual Studio Code
420 | .history/
421 |
422 | # Built Visual Studio Code Extensions
423 | *.vsix
424 |
425 | ### VisualStudioCode Patch ###
426 | # Ignore all local history of files
427 | .history
428 | .ionide
429 |
430 | .directory
431 |
432 | # End of https://www.toptal.com/developers/gitignore/api/latex,godot,rider,visualstudiocode
433 |
434 |
--------------------------------------------------------------------------------
/Assets/Default_1mx1m.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Carl0sCheca/Procedural-City-Generator-Godot/176277e88729c8fad332bb9432f70ba87ab45598/Assets/Default_1mx1m.png
--------------------------------------------------------------------------------
/Assets/Default_1mx1m.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://dlaaf5sxco1rv"
6 | path.s3tc="res://.godot/imported/Default_1mx1m.png-08571233490fe6dab753208cba39c918.s3tc.ctex"
7 | metadata={
8 | "imported_formats": ["s3tc_bptc"],
9 | "vram_texture": true
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://Assets/Default_1mx1m.png"
15 | dest_files=["res://.godot/imported/Default_1mx1m.png-08571233490fe6dab753208cba39c918.s3tc.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=2
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=0
24 | compress/channel_pack=0
25 | mipmaps/generate=true
26 | mipmaps/limit=-1
27 | roughness/mode=0
28 | roughness/src_normal=""
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=0
36 |
--------------------------------------------------------------------------------
/Assets/Image_12.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Carl0sCheca/Procedural-City-Generator-Godot/176277e88729c8fad332bb9432f70ba87ab45598/Assets/Image_12.jpg
--------------------------------------------------------------------------------
/Assets/Image_12.jpg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://dlr1xsa17w7mm"
6 | path.s3tc="res://.godot/imported/Image_12.jpg-3394c66cba0a001614ae414fb6f31ca8.s3tc.ctex"
7 | metadata={
8 | "imported_formats": ["s3tc_bptc"],
9 | "vram_texture": true
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://Assets/Image_12.jpg"
15 | dest_files=["res://.godot/imported/Image_12.jpg-3394c66cba0a001614ae414fb6f31ca8.s3tc.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=2
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=0
24 | compress/channel_pack=0
25 | mipmaps/generate=true
26 | mipmaps/limit=-1
27 | roughness/mode=0
28 | roughness/src_normal=""
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=0
36 |
--------------------------------------------------------------------------------
/Assets/Image_13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Carl0sCheca/Procedural-City-Generator-Godot/176277e88729c8fad332bb9432f70ba87ab45598/Assets/Image_13.png
--------------------------------------------------------------------------------
/Assets/Image_13.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://cefjkxahm2dqn"
6 | path.s3tc="res://.godot/imported/Image_13.png-5c7c3884f3b30ae12c3f764c7f327de1.s3tc.ctex"
7 | metadata={
8 | "imported_formats": ["s3tc_bptc"],
9 | "vram_texture": true
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://Assets/Image_13.png"
15 | dest_files=["res://.godot/imported/Image_13.png-5c7c3884f3b30ae12c3f764c7f327de1.s3tc.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=2
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=1
24 | compress/channel_pack=0
25 | mipmaps/generate=true
26 | mipmaps/limit=-1
27 | roughness/mode=1
28 | roughness/src_normal="res://Assets/Image_13.png"
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=0
36 |
--------------------------------------------------------------------------------
/Assets/Image_15.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Carl0sCheca/Procedural-City-Generator-Godot/176277e88729c8fad332bb9432f70ba87ab45598/Assets/Image_15.jpg
--------------------------------------------------------------------------------
/Assets/Image_15.jpg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://dw7h7q8f5emdx"
6 | path.s3tc="res://.godot/imported/Image_15.jpg-302b22144e7b610a0c193d9fbef9231b.s3tc.ctex"
7 | metadata={
8 | "imported_formats": ["s3tc_bptc"],
9 | "vram_texture": true
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://Assets/Image_15.jpg"
15 | dest_files=["res://.godot/imported/Image_15.jpg-302b22144e7b610a0c193d9fbef9231b.s3tc.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=2
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=0
24 | compress/channel_pack=0
25 | mipmaps/generate=true
26 | mipmaps/limit=-1
27 | roughness/mode=0
28 | roughness/src_normal=""
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=0
36 |
--------------------------------------------------------------------------------
/Assets/Image_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Carl0sCheca/Procedural-City-Generator-Godot/176277e88729c8fad332bb9432f70ba87ab45598/Assets/Image_16.png
--------------------------------------------------------------------------------
/Assets/Image_16.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://b4qx2qwwlt0yl"
6 | path.s3tc="res://.godot/imported/Image_16.png-ee89cc02e05d1135431961911a70966f.s3tc.ctex"
7 | metadata={
8 | "imported_formats": ["s3tc_bptc"],
9 | "vram_texture": true
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://Assets/Image_16.png"
15 | dest_files=["res://.godot/imported/Image_16.png-ee89cc02e05d1135431961911a70966f.s3tc.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=2
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=1
24 | compress/channel_pack=0
25 | mipmaps/generate=true
26 | mipmaps/limit=-1
27 | roughness/mode=1
28 | roughness/src_normal="res://Assets/Image_16.png"
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=0
36 |
--------------------------------------------------------------------------------
/Assets/Image_18.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Carl0sCheca/Procedural-City-Generator-Godot/176277e88729c8fad332bb9432f70ba87ab45598/Assets/Image_18.png
--------------------------------------------------------------------------------
/Assets/Image_18.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://cy2fo3gqj6xxs"
6 | path.s3tc="res://.godot/imported/Image_18.png-d6e983d72d9c6fcfaacb8b3a4285e47f.s3tc.ctex"
7 | metadata={
8 | "imported_formats": ["s3tc_bptc"],
9 | "vram_texture": true
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://Assets/Image_18.png"
15 | dest_files=["res://.godot/imported/Image_18.png-d6e983d72d9c6fcfaacb8b3a4285e47f.s3tc.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=2
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=0
24 | compress/channel_pack=0
25 | mipmaps/generate=true
26 | mipmaps/limit=-1
27 | roughness/mode=0
28 | roughness/src_normal=""
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=0
36 |
--------------------------------------------------------------------------------
/Assets/Image_19.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Carl0sCheca/Procedural-City-Generator-Godot/176277e88729c8fad332bb9432f70ba87ab45598/Assets/Image_19.png
--------------------------------------------------------------------------------
/Assets/Image_19.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://bhyll7idn30gw"
6 | path.s3tc="res://.godot/imported/Image_19.png-d6227919b829e88eb60dd469557c93da.s3tc.ctex"
7 | metadata={
8 | "imported_formats": ["s3tc_bptc"],
9 | "vram_texture": true
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://Assets/Image_19.png"
15 | dest_files=["res://.godot/imported/Image_19.png-d6227919b829e88eb60dd469557c93da.s3tc.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=2
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=1
24 | compress/channel_pack=0
25 | mipmaps/generate=true
26 | mipmaps/limit=-1
27 | roughness/mode=1
28 | roughness/src_normal="res://Assets/Image_19.png"
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=0
36 |
--------------------------------------------------------------------------------
/Assets/Image_2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Carl0sCheca/Procedural-City-Generator-Godot/176277e88729c8fad332bb9432f70ba87ab45598/Assets/Image_2.jpg
--------------------------------------------------------------------------------
/Assets/Image_2.jpg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://crohtkl2ogb3t"
6 | path.s3tc="res://.godot/imported/Image_2.jpg-dcc35e2d8ad35228526c226ec9473e78.s3tc.ctex"
7 | metadata={
8 | "imported_formats": ["s3tc_bptc"],
9 | "vram_texture": true
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://Assets/Image_2.jpg"
15 | dest_files=["res://.godot/imported/Image_2.jpg-dcc35e2d8ad35228526c226ec9473e78.s3tc.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=2
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=0
24 | compress/channel_pack=0
25 | mipmaps/generate=true
26 | mipmaps/limit=-1
27 | roughness/mode=0
28 | roughness/src_normal=""
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=0
36 |
--------------------------------------------------------------------------------
/Assets/Image_21.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Carl0sCheca/Procedural-City-Generator-Godot/176277e88729c8fad332bb9432f70ba87ab45598/Assets/Image_21.jpg
--------------------------------------------------------------------------------
/Assets/Image_21.jpg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://dbyb2qf6lrmog"
6 | path.s3tc="res://.godot/imported/Image_21.jpg-6ef58dcde23e8955497cd0c1b45add79.s3tc.ctex"
7 | metadata={
8 | "imported_formats": ["s3tc_bptc"],
9 | "vram_texture": true
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://Assets/Image_21.jpg"
15 | dest_files=["res://.godot/imported/Image_21.jpg-6ef58dcde23e8955497cd0c1b45add79.s3tc.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=2
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=0
24 | compress/channel_pack=0
25 | mipmaps/generate=true
26 | mipmaps/limit=-1
27 | roughness/mode=0
28 | roughness/src_normal=""
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=0
36 |
--------------------------------------------------------------------------------
/Assets/Image_22.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Carl0sCheca/Procedural-City-Generator-Godot/176277e88729c8fad332bb9432f70ba87ab45598/Assets/Image_22.png
--------------------------------------------------------------------------------
/Assets/Image_22.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://bge1yem0n6xue"
6 | path.s3tc="res://.godot/imported/Image_22.png-21de3775cf8271eb8f4fc72bf788f60e.s3tc.ctex"
7 | metadata={
8 | "imported_formats": ["s3tc_bptc"],
9 | "vram_texture": true
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://Assets/Image_22.png"
15 | dest_files=["res://.godot/imported/Image_22.png-21de3775cf8271eb8f4fc72bf788f60e.s3tc.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=2
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=1
24 | compress/channel_pack=0
25 | mipmaps/generate=true
26 | mipmaps/limit=-1
27 | roughness/mode=0
28 | roughness/src_normal=""
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=0
36 |
--------------------------------------------------------------------------------
/Assets/Image_24.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Carl0sCheca/Procedural-City-Generator-Godot/176277e88729c8fad332bb9432f70ba87ab45598/Assets/Image_24.jpg
--------------------------------------------------------------------------------
/Assets/Image_24.jpg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://bdqvjxtybdc7j"
6 | path.s3tc="res://.godot/imported/Image_24.jpg-3c3037fd6d7ddced0b29bdcd85519974.s3tc.ctex"
7 | metadata={
8 | "imported_formats": ["s3tc_bptc"],
9 | "vram_texture": true
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://Assets/Image_24.jpg"
15 | dest_files=["res://.godot/imported/Image_24.jpg-3c3037fd6d7ddced0b29bdcd85519974.s3tc.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=2
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=0
24 | compress/channel_pack=0
25 | mipmaps/generate=true
26 | mipmaps/limit=-1
27 | roughness/mode=0
28 | roughness/src_normal=""
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=0
36 |
--------------------------------------------------------------------------------
/Assets/Image_25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Carl0sCheca/Procedural-City-Generator-Godot/176277e88729c8fad332bb9432f70ba87ab45598/Assets/Image_25.png
--------------------------------------------------------------------------------
/Assets/Image_25.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://dr7qt8s3tjanf"
6 | path.s3tc="res://.godot/imported/Image_25.png-d73b92c919fab1cb393df01527454794.s3tc.ctex"
7 | metadata={
8 | "imported_formats": ["s3tc_bptc"],
9 | "vram_texture": true
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://Assets/Image_25.png"
15 | dest_files=["res://.godot/imported/Image_25.png-d73b92c919fab1cb393df01527454794.s3tc.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=2
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=1
24 | compress/channel_pack=0
25 | mipmaps/generate=true
26 | mipmaps/limit=-1
27 | roughness/mode=1
28 | roughness/src_normal="res://Assets/Image_25.png"
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=0
36 |
--------------------------------------------------------------------------------
/Assets/Image_27.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Carl0sCheca/Procedural-City-Generator-Godot/176277e88729c8fad332bb9432f70ba87ab45598/Assets/Image_27.jpg
--------------------------------------------------------------------------------
/Assets/Image_27.jpg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://e76xhy7kdb6n"
6 | path.s3tc="res://.godot/imported/Image_27.jpg-1df22abbada51efeb4e7954ed50006ac.s3tc.ctex"
7 | metadata={
8 | "imported_formats": ["s3tc_bptc"],
9 | "vram_texture": true
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://Assets/Image_27.jpg"
15 | dest_files=["res://.godot/imported/Image_27.jpg-1df22abbada51efeb4e7954ed50006ac.s3tc.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=2
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=0
24 | compress/channel_pack=0
25 | mipmaps/generate=true
26 | mipmaps/limit=-1
27 | roughness/mode=0
28 | roughness/src_normal=""
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=0
36 |
--------------------------------------------------------------------------------
/Assets/Image_28.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Carl0sCheca/Procedural-City-Generator-Godot/176277e88729c8fad332bb9432f70ba87ab45598/Assets/Image_28.png
--------------------------------------------------------------------------------
/Assets/Image_28.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://blamqi6hfwsn8"
6 | path.s3tc="res://.godot/imported/Image_28.png-f29b715eb86537648b9a5e71bdf56efd.s3tc.ctex"
7 | metadata={
8 | "imported_formats": ["s3tc_bptc"],
9 | "vram_texture": true
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://Assets/Image_28.png"
15 | dest_files=["res://.godot/imported/Image_28.png-f29b715eb86537648b9a5e71bdf56efd.s3tc.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=2
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=1
24 | compress/channel_pack=0
25 | mipmaps/generate=true
26 | mipmaps/limit=-1
27 | roughness/mode=1
28 | roughness/src_normal="res://Assets/Image_28.png"
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=0
36 |
--------------------------------------------------------------------------------
/Assets/Image_30.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Carl0sCheca/Procedural-City-Generator-Godot/176277e88729c8fad332bb9432f70ba87ab45598/Assets/Image_30.jpg
--------------------------------------------------------------------------------
/Assets/Image_30.jpg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://cxkpy86hriclc"
6 | path.s3tc="res://.godot/imported/Image_30.jpg-7738c2e489a74e4cd21ed531e550b18c.s3tc.ctex"
7 | metadata={
8 | "imported_formats": ["s3tc_bptc"],
9 | "vram_texture": true
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://Assets/Image_30.jpg"
15 | dest_files=["res://.godot/imported/Image_30.jpg-7738c2e489a74e4cd21ed531e550b18c.s3tc.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=2
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=0
24 | compress/channel_pack=0
25 | mipmaps/generate=true
26 | mipmaps/limit=-1
27 | roughness/mode=0
28 | roughness/src_normal=""
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=0
36 |
--------------------------------------------------------------------------------
/Assets/Image_31.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Carl0sCheca/Procedural-City-Generator-Godot/176277e88729c8fad332bb9432f70ba87ab45598/Assets/Image_31.png
--------------------------------------------------------------------------------
/Assets/Image_31.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://b266paove0s0r"
6 | path.s3tc="res://.godot/imported/Image_31.png-ed3cf00432eac89b80519c837f0ddf51.s3tc.ctex"
7 | metadata={
8 | "imported_formats": ["s3tc_bptc"],
9 | "vram_texture": true
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://Assets/Image_31.png"
15 | dest_files=["res://.godot/imported/Image_31.png-ed3cf00432eac89b80519c837f0ddf51.s3tc.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=2
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=1
24 | compress/channel_pack=0
25 | mipmaps/generate=true
26 | mipmaps/limit=-1
27 | roughness/mode=1
28 | roughness/src_normal="res://Assets/Image_31.png"
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=0
36 |
--------------------------------------------------------------------------------
/Assets/Image_33.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Carl0sCheca/Procedural-City-Generator-Godot/176277e88729c8fad332bb9432f70ba87ab45598/Assets/Image_33.jpg
--------------------------------------------------------------------------------
/Assets/Image_33.jpg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://b3ls7cf1wj7yl"
6 | path.s3tc="res://.godot/imported/Image_33.jpg-2c72f29f3c16118ef47fe06b179f60b3.s3tc.ctex"
7 | metadata={
8 | "imported_formats": ["s3tc_bptc"],
9 | "vram_texture": true
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://Assets/Image_33.jpg"
15 | dest_files=["res://.godot/imported/Image_33.jpg-2c72f29f3c16118ef47fe06b179f60b3.s3tc.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=2
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=0
24 | compress/channel_pack=0
25 | mipmaps/generate=true
26 | mipmaps/limit=-1
27 | roughness/mode=0
28 | roughness/src_normal=""
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=0
36 |
--------------------------------------------------------------------------------
/Assets/Image_34.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Carl0sCheca/Procedural-City-Generator-Godot/176277e88729c8fad332bb9432f70ba87ab45598/Assets/Image_34.png
--------------------------------------------------------------------------------
/Assets/Image_34.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://dkse7h6mt8f4o"
6 | path.s3tc="res://.godot/imported/Image_34.png-472f0d4fd1e86be25bef9382b7ed8e19.s3tc.ctex"
7 | metadata={
8 | "imported_formats": ["s3tc_bptc"],
9 | "vram_texture": true
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://Assets/Image_34.png"
15 | dest_files=["res://.godot/imported/Image_34.png-472f0d4fd1e86be25bef9382b7ed8e19.s3tc.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=2
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=1
24 | compress/channel_pack=0
25 | mipmaps/generate=true
26 | mipmaps/limit=-1
27 | roughness/mode=1
28 | roughness/src_normal="res://Assets/Image_34.png"
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=0
36 |
--------------------------------------------------------------------------------
/Assets/Image_37.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Carl0sCheca/Procedural-City-Generator-Godot/176277e88729c8fad332bb9432f70ba87ab45598/Assets/Image_37.jpg
--------------------------------------------------------------------------------
/Assets/Image_37.jpg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://cvaiir664f3no"
6 | path.s3tc="res://.godot/imported/Image_37.jpg-33b19aece053f499264d5b313a72ab69.s3tc.ctex"
7 | metadata={
8 | "imported_formats": ["s3tc_bptc"],
9 | "vram_texture": true
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://Assets/Image_37.jpg"
15 | dest_files=["res://.godot/imported/Image_37.jpg-33b19aece053f499264d5b313a72ab69.s3tc.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=2
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=0
24 | compress/channel_pack=0
25 | mipmaps/generate=true
26 | mipmaps/limit=-1
27 | roughness/mode=0
28 | roughness/src_normal=""
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=0
36 |
--------------------------------------------------------------------------------
/Assets/Image_38.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Carl0sCheca/Procedural-City-Generator-Godot/176277e88729c8fad332bb9432f70ba87ab45598/Assets/Image_38.png
--------------------------------------------------------------------------------
/Assets/Image_38.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://bgbma1mouwl4w"
6 | path.s3tc="res://.godot/imported/Image_38.png-a5f72e9c84b9c0c9f286f9d100e41f4e.s3tc.ctex"
7 | metadata={
8 | "imported_formats": ["s3tc_bptc"],
9 | "vram_texture": true
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://Assets/Image_38.png"
15 | dest_files=["res://.godot/imported/Image_38.png-a5f72e9c84b9c0c9f286f9d100e41f4e.s3tc.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=2
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=1
24 | compress/channel_pack=0
25 | mipmaps/generate=true
26 | mipmaps/limit=-1
27 | roughness/mode=1
28 | roughness/src_normal="res://Assets/Image_38.png"
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=0
36 |
--------------------------------------------------------------------------------
/Assets/Image_39.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Carl0sCheca/Procedural-City-Generator-Godot/176277e88729c8fad332bb9432f70ba87ab45598/Assets/Image_39.jpg
--------------------------------------------------------------------------------
/Assets/Image_39.jpg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://c6jsm27bkpne0"
6 | path.s3tc="res://.godot/imported/Image_39.jpg-083066ced67afa4f6c242333f400d2c8.s3tc.ctex"
7 | metadata={
8 | "imported_formats": ["s3tc_bptc"],
9 | "vram_texture": true
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://Assets/Image_39.jpg"
15 | dest_files=["res://.godot/imported/Image_39.jpg-083066ced67afa4f6c242333f400d2c8.s3tc.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=2
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=0
24 | compress/channel_pack=0
25 | mipmaps/generate=true
26 | mipmaps/limit=-1
27 | roughness/mode=0
28 | roughness/src_normal=""
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=0
36 |
--------------------------------------------------------------------------------
/Assets/Image_40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Carl0sCheca/Procedural-City-Generator-Godot/176277e88729c8fad332bb9432f70ba87ab45598/Assets/Image_40.png
--------------------------------------------------------------------------------
/Assets/Image_40.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://dnccvrcak1a7b"
6 | path.s3tc="res://.godot/imported/Image_40.png-bcdde4d2e5870daff2934ee4165c882c.s3tc.ctex"
7 | metadata={
8 | "imported_formats": ["s3tc_bptc"],
9 | "vram_texture": true
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://Assets/Image_40.png"
15 | dest_files=["res://.godot/imported/Image_40.png-bcdde4d2e5870daff2934ee4165c882c.s3tc.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=2
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=1
24 | compress/channel_pack=0
25 | mipmaps/generate=true
26 | mipmaps/limit=-1
27 | roughness/mode=1
28 | roughness/src_normal="res://Assets/Image_40.png"
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=0
36 |
--------------------------------------------------------------------------------
/Assets/Image_49.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Carl0sCheca/Procedural-City-Generator-Godot/176277e88729c8fad332bb9432f70ba87ab45598/Assets/Image_49.png
--------------------------------------------------------------------------------
/Assets/Image_49.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://bhgo1ocdgu58d"
6 | path.s3tc="res://.godot/imported/Image_49.png-7a65d831ee4691c39ffc426d75771fcf.s3tc.ctex"
7 | metadata={
8 | "imported_formats": ["s3tc_bptc"],
9 | "vram_texture": true
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://Assets/Image_49.png"
15 | dest_files=["res://.godot/imported/Image_49.png-7a65d831ee4691c39ffc426d75771fcf.s3tc.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=2
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=0
24 | compress/channel_pack=0
25 | mipmaps/generate=true
26 | mipmaps/limit=-1
27 | roughness/mode=0
28 | roughness/src_normal=""
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=0
36 |
--------------------------------------------------------------------------------
/Assets/Image_50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Carl0sCheca/Procedural-City-Generator-Godot/176277e88729c8fad332bb9432f70ba87ab45598/Assets/Image_50.png
--------------------------------------------------------------------------------
/Assets/Image_50.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://cu00hhhpe6r1c"
6 | path="res://.godot/imported/Image_50.png-bb238a2a7b8f1086475a94f5152853fe.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://Assets/Image_50.png"
14 | dest_files=["res://.godot/imported/Image_50.png-bb238a2a7b8f1086475a94f5152853fe.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/hdr_compression=1
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 |
--------------------------------------------------------------------------------
/Assets/Image_66.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Carl0sCheca/Procedural-City-Generator-Godot/176277e88729c8fad332bb9432f70ba87ab45598/Assets/Image_66.jpg
--------------------------------------------------------------------------------
/Assets/Image_66.jpg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://xpc42yi268y2"
6 | path.s3tc="res://.godot/imported/Image_66.jpg-4d1140a7aba3191d9008ef9f15cb4b4c.s3tc.ctex"
7 | metadata={
8 | "imported_formats": ["s3tc_bptc"],
9 | "vram_texture": true
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://Assets/Image_66.jpg"
15 | dest_files=["res://.godot/imported/Image_66.jpg-4d1140a7aba3191d9008ef9f15cb4b4c.s3tc.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=2
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=0
24 | compress/channel_pack=0
25 | mipmaps/generate=true
26 | mipmaps/limit=-1
27 | roughness/mode=0
28 | roughness/src_normal=""
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=0
36 |
--------------------------------------------------------------------------------
/Assets/Image_67.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Carl0sCheca/Procedural-City-Generator-Godot/176277e88729c8fad332bb9432f70ba87ab45598/Assets/Image_67.png
--------------------------------------------------------------------------------
/Assets/Image_67.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://csc3a12il6mxm"
6 | path.s3tc="res://.godot/imported/Image_67.png-091c4a8ea2d68f140cf26b8caa4c3ee8.s3tc.ctex"
7 | metadata={
8 | "imported_formats": ["s3tc_bptc"],
9 | "vram_texture": true
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://Assets/Image_67.png"
15 | dest_files=["res://.godot/imported/Image_67.png-091c4a8ea2d68f140cf26b8caa4c3ee8.s3tc.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=2
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=1
24 | compress/channel_pack=0
25 | mipmaps/generate=true
26 | mipmaps/limit=-1
27 | roughness/mode=1
28 | roughness/src_normal="res://Assets/Image_67.png"
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=0
36 |
--------------------------------------------------------------------------------
/Assets/Image_75.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Carl0sCheca/Procedural-City-Generator-Godot/176277e88729c8fad332bb9432f70ba87ab45598/Assets/Image_75.jpg
--------------------------------------------------------------------------------
/Assets/Image_75.jpg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://828yxtcifo2k"
6 | path.s3tc="res://.godot/imported/Image_75.jpg-d4754d8fb7865d0b2d39599dee616ce8.s3tc.ctex"
7 | metadata={
8 | "imported_formats": ["s3tc_bptc"],
9 | "vram_texture": true
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://Assets/Image_75.jpg"
15 | dest_files=["res://.godot/imported/Image_75.jpg-d4754d8fb7865d0b2d39599dee616ce8.s3tc.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=2
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=0
24 | compress/channel_pack=0
25 | mipmaps/generate=true
26 | mipmaps/limit=-1
27 | roughness/mode=0
28 | roughness/src_normal=""
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=0
36 |
--------------------------------------------------------------------------------
/Assets/Image_76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Carl0sCheca/Procedural-City-Generator-Godot/176277e88729c8fad332bb9432f70ba87ab45598/Assets/Image_76.png
--------------------------------------------------------------------------------
/Assets/Image_76.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://cdjik05nthfl4"
6 | path.s3tc="res://.godot/imported/Image_76.png-befd6311a8f0f3dcd9aebdfd5d984466.s3tc.ctex"
7 | metadata={
8 | "imported_formats": ["s3tc_bptc"],
9 | "vram_texture": true
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://Assets/Image_76.png"
15 | dest_files=["res://.godot/imported/Image_76.png-befd6311a8f0f3dcd9aebdfd5d984466.s3tc.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=2
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=1
24 | compress/channel_pack=0
25 | mipmaps/generate=true
26 | mipmaps/limit=-1
27 | roughness/mode=1
28 | roughness/src_normal="res://Assets/Image_76.png"
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=0
36 |
--------------------------------------------------------------------------------
/Assets/asphalt_01_diff_4k.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Carl0sCheca/Procedural-City-Generator-Godot/176277e88729c8fad332bb9432f70ba87ab45598/Assets/asphalt_01_diff_4k.jpg
--------------------------------------------------------------------------------
/Assets/asphalt_01_diff_4k.jpg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://demk5w3bmixwx"
6 | path.s3tc="res://.godot/imported/asphalt_01_diff_4k.jpg-ff95bc701e80208ec2b23d6c05989254.s3tc.ctex"
7 | metadata={
8 | "imported_formats": ["s3tc_bptc"],
9 | "vram_texture": true
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://Assets/asphalt_01_diff_4k.jpg"
15 | dest_files=["res://.godot/imported/asphalt_01_diff_4k.jpg-ff95bc701e80208ec2b23d6c05989254.s3tc.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=2
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=0
24 | compress/channel_pack=0
25 | mipmaps/generate=true
26 | mipmaps/limit=-1
27 | roughness/mode=0
28 | roughness/src_normal=""
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=0
36 |
--------------------------------------------------------------------------------
/Assets/grass.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Carl0sCheca/Procedural-City-Generator-Godot/176277e88729c8fad332bb9432f70ba87ab45598/Assets/grass.jpg
--------------------------------------------------------------------------------
/Assets/grass.jpg.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://b6x4orqnfp2q6"
6 | path.s3tc="res://.godot/imported/grass.jpg-a807c661017f5cb8ef8de151216c8350.s3tc.ctex"
7 | metadata={
8 | "imported_formats": ["s3tc_bptc"],
9 | "vram_texture": true
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://Assets/grass.jpg"
15 | dest_files=["res://.godot/imported/grass.jpg-a807c661017f5cb8ef8de151216c8350.s3tc.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=2
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=0
24 | compress/channel_pack=0
25 | mipmaps/generate=true
26 | mipmaps/limit=-1
27 | roughness/mode=0
28 | roughness/src_normal=""
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=0
36 |
--------------------------------------------------------------------------------
/Assets/gravel-ballast-roof-2500-mm-architextures.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Carl0sCheca/Procedural-City-Generator-Godot/176277e88729c8fad332bb9432f70ba87ab45598/Assets/gravel-ballast-roof-2500-mm-architextures.png
--------------------------------------------------------------------------------
/Assets/gravel-ballast-roof-2500-mm-architextures.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://c76iuhm3exgdf"
6 | path.s3tc="res://.godot/imported/gravel-ballast-roof-2500-mm-architextures.png-6ab1251242678878951030f21b428b05.s3tc.ctex"
7 | metadata={
8 | "imported_formats": ["s3tc_bptc"],
9 | "vram_texture": true
10 | }
11 |
12 | [deps]
13 |
14 | source_file="res://Assets/gravel-ballast-roof-2500-mm-architextures.png"
15 | dest_files=["res://.godot/imported/gravel-ballast-roof-2500-mm-architextures.png-6ab1251242678878951030f21b428b05.s3tc.ctex"]
16 |
17 | [params]
18 |
19 | compress/mode=2
20 | compress/high_quality=false
21 | compress/lossy_quality=0.7
22 | compress/hdr_compression=1
23 | compress/normal_map=0
24 | compress/channel_pack=0
25 | mipmaps/generate=true
26 | mipmaps/limit=-1
27 | roughness/mode=0
28 | roughness/src_normal=""
29 | process/fix_alpha_border=true
30 | process/premult_alpha=false
31 | process/normal_map_invert_y=false
32 | process/hdr_as_srgb=false
33 | process/hdr_clamp_exposure=false
34 | process/size_limit=0
35 | detect_3d/compress_to=0
36 |
--------------------------------------------------------------------------------
/CameraEnvironment.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Environment" load_steps=3 format=3 uid="uid://6fklvphu014u"]
2 |
3 | [sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_bto4x"]
4 |
5 | [sub_resource type="Sky" id="Sky_ge24j"]
6 | sky_material = SubResource("ProceduralSkyMaterial_bto4x")
7 |
8 | [resource]
9 | background_mode = 2
10 | background_energy_multiplier = 1.2
11 | sky = SubResource("Sky_ge24j")
12 | ambient_light_source = 3
13 | ambient_light_color = Color(0, 0.501961, 0.952941, 1)
14 | ssao_horizon = 0.79
15 | ssil_enabled = true
16 | sdfgi_enabled = true
17 | sdfgi_use_occlusion = true
18 | fog_light_color = Color(0.172549, 0.576471, 0.870588, 1)
19 | fog_density = 0.005
20 | volumetric_fog_enabled = true
21 | volumetric_fog_density = 0.02
22 |
--------------------------------------------------------------------------------
/GUIMaterials/PressedButton.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="StyleBoxFlat" format=3 uid="uid://d385yneucsjb5"]
2 |
3 | [resource]
4 | bg_color = Color(0.117647, 0.619608, 1, 1)
5 | border_width_left = 4
6 | border_width_top = 4
7 | border_width_right = 4
8 | border_width_bottom = 4
9 |
--------------------------------------------------------------------------------
/GUIMaterials/SelectedTensorField.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="StyleBoxFlat" format=3 uid="uid://khqvj7h7agu1"]
2 |
3 | [resource]
4 | bg_color = Color(0.317647, 0.694118, 0.392157, 1)
5 | border_width_left = 4
6 | border_width_top = 4
7 | border_width_right = 4
8 | border_width_bottom = 4
9 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 | Preamble
9 |
10 | The GNU General Public License is a free, copyleft license for
11 | software and other kinds of works.
12 |
13 | The licenses for most software and other practical works are designed
14 | to take away your freedom to share and change the works. By contrast,
15 | the GNU General Public License is intended to guarantee your freedom to
16 | share and change all versions of a program--to make sure it remains free
17 | software for all its users. We, the Free Software Foundation, use the
18 | GNU General Public License for most of our software; it applies also to
19 | any other work released this way by its authors. You can apply it to
20 | your programs, too.
21 |
22 | When we speak of free software, we are referring to freedom, not
23 | price. Our General Public Licenses are designed to make sure that you
24 | have the freedom to distribute copies of free software (and charge for
25 | them if you wish), that you receive source code or can get it if you
26 | want it, that you can change the software or use pieces of it in new
27 | free programs, and that you know you can do these things.
28 |
29 | To protect your rights, we need to prevent others from denying you
30 | these rights or asking you to surrender the rights. Therefore, you have
31 | certain responsibilities if you distribute copies of the software, or if
32 | you modify it: responsibilities to respect the freedom of others.
33 |
34 | For example, if you distribute copies of such a program, whether
35 | gratis or for a fee, you must pass on to the recipients the same
36 | freedoms that you received. You must make sure that they, too, receive
37 | or can get the source code. And you must show them these terms so they
38 | know their rights.
39 |
40 | Developers that use the GNU GPL protect your rights with two steps:
41 | (1) assert copyright on the software, and (2) offer you this License
42 | giving you legal permission to copy, distribute and/or modify it.
43 |
44 | For the developers' and authors' protection, the GPL clearly explains
45 | that there is no warranty for this free software. For both users' and
46 | authors' sake, the GPL requires that modified versions be marked as
47 | changed, so that their problems will not be attributed erroneously to
48 | authors of previous versions.
49 |
50 | Some devices are designed to deny users access to install or run
51 | modified versions of the software inside them, although the manufacturer
52 | can do so. This is fundamentally incompatible with the aim of
53 | protecting users' freedom to change the software. The systematic
54 | pattern of such abuse occurs in the area of products for individuals to
55 | use, which is precisely where it is most unacceptable. Therefore, we
56 | have designed this version of the GPL to prohibit the practice for those
57 | products. If such problems arise substantially in other domains, we
58 | stand ready to extend this provision to those domains in future versions
59 | of the GPL, as needed to protect the freedom of users.
60 |
61 | Finally, every program is threatened constantly by software patents.
62 | States should not allow patents to restrict development and use of
63 | software on general-purpose computers, but in those that do, we wish to
64 | avoid the special danger that patents applied to a free program could
65 | make it effectively proprietary. To prevent this, the GPL assures that
66 | patents cannot be used to render the program non-free.
67 |
68 | The precise terms and conditions for copying, distribution and
69 | modification follow.
70 |
71 | TERMS AND CONDITIONS
72 |
73 | 0. Definitions.
74 |
75 | "This License" refers to version 3 of the GNU General Public License.
76 |
77 | "Copyright" also means copyright-like laws that apply to other kinds of
78 | works, such as semiconductor masks.
79 |
80 | "The Program" refers to any copyrightable work licensed under this
81 | License. Each licensee is addressed as "you". "Licensees" and
82 | "recipients" may be individuals or organizations.
83 |
84 | To "modify" a work means to copy from or adapt all or part of the work
85 | in a fashion requiring copyright permission, other than the making of an
86 | exact copy. The resulting work is called a "modified version" of the
87 | earlier work or a work "based on" the earlier work.
88 |
89 | A "covered work" means either the unmodified Program or a work based
90 | on the Program.
91 |
92 | To "propagate" a work means to do anything with it that, without
93 | permission, would make you directly or secondarily liable for
94 | infringement under applicable copyright law, except executing it on a
95 | computer or modifying a private copy. Propagation includes copying,
96 | distribution (with or without modification), making available to the
97 | public, and in some countries other activities as well.
98 |
99 | To "convey" a work means any kind of propagation that enables other
100 | parties to make or receive copies. Mere interaction with a user through
101 | a computer network, with no transfer of a copy, is not conveying.
102 |
103 | An interactive user interface displays "Appropriate Legal Notices"
104 | to the extent that it includes a convenient and prominently visible
105 | feature that (1) displays an appropriate copyright notice, and (2)
106 | tells the user that there is no warranty for the work (except to the
107 | extent that warranties are provided), that licensees may convey the
108 | work under this License, and how to view a copy of this License. If
109 | the interface presents a list of user commands or options, such as a
110 | menu, a prominent item in the list meets this criterion.
111 |
112 | 1. Source Code.
113 |
114 | The "source code" for a work means the preferred form of the work
115 | for making modifications to it. "Object code" means any non-source
116 | form of a work.
117 |
118 | A "Standard Interface" means an interface that either is an official
119 | standard defined by a recognized standards body, or, in the case of
120 | interfaces specified for a particular programming language, one that
121 | is widely used among developers working in that language.
122 |
123 | The "System Libraries" of an executable work include anything, other
124 | than the work as a whole, that (a) is included in the normal form of
125 | packaging a Major Component, but which is not part of that Major
126 | Component, and (b) serves only to enable use of the work with that
127 | Major Component, or to implement a Standard Interface for which an
128 | implementation is available to the public in source code form. A
129 | "Major Component", in this context, means a major essential component
130 | (kernel, window system, and so on) of the specific operating system
131 | (if any) on which the executable work runs, or a compiler used to
132 | produce the work, or an object code interpreter used to run it.
133 |
134 | The "Corresponding Source" for a work in object code form means all
135 | the source code needed to generate, install, and (for an executable
136 | work) run the object code and to modify the work, including scripts to
137 | control those activities. However, it does not include the work's
138 | System Libraries, or general-purpose tools or generally available free
139 | programs which are used unmodified in performing those activities but
140 | which are not part of the work. For example, Corresponding Source
141 | includes interface definition files associated with source files for
142 | the work, and the source code for shared libraries and dynamically
143 | linked subprograms that the work is specifically designed to require,
144 | such as by intimate data communication or control flow between those
145 | subprograms and other parts of the work.
146 |
147 | The Corresponding Source need not include anything that users
148 | can regenerate automatically from other parts of the Corresponding
149 | Source.
150 |
151 | The Corresponding Source for a work in source code form is that
152 | same work.
153 |
154 | 2. Basic Permissions.
155 |
156 | All rights granted under this License are granted for the term of
157 | copyright on the Program, and are irrevocable provided the stated
158 | conditions are met. This License explicitly affirms your unlimited
159 | permission to run the unmodified Program. The output from running a
160 | covered work is covered by this License only if the output, given its
161 | content, constitutes a covered work. This License acknowledges your
162 | rights of fair use or other equivalent, as provided by copyright law.
163 |
164 | You may make, run and propagate covered works that you do not
165 | convey, without conditions so long as your license otherwise remains
166 | in force. You may convey covered works to others for the sole purpose
167 | of having them make modifications exclusively for you, or provide you
168 | with facilities for running those works, provided that you comply with
169 | the terms of this License in conveying all material for which you do
170 | not control copyright. Those thus making or running the covered works
171 | for you must do so exclusively on your behalf, under your direction
172 | and control, on terms that prohibit them from making any copies of
173 | your copyrighted material outside their relationship with you.
174 |
175 | Conveying under any other circumstances is permitted solely under
176 | the conditions stated below. Sublicensing is not allowed; section 10
177 | makes it unnecessary.
178 |
179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180 |
181 | No covered work shall be deemed part of an effective technological
182 | measure under any applicable law fulfilling obligations under article
183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184 | similar laws prohibiting or restricting circumvention of such
185 | measures.
186 |
187 | When you convey a covered work, you waive any legal power to forbid
188 | circumvention of technological measures to the extent such circumvention
189 | is effected by exercising rights under this License with respect to
190 | the covered work, and you disclaim any intention to limit operation or
191 | modification of the work as a means of enforcing, against the work's
192 | users, your or third parties' legal rights to forbid circumvention of
193 | technological measures.
194 |
195 | 4. Conveying Verbatim Copies.
196 |
197 | You may convey verbatim copies of the Program's source code as you
198 | receive it, in any medium, provided that you conspicuously and
199 | appropriately publish on each copy an appropriate copyright notice;
200 | keep intact all notices stating that this License and any
201 | non-permissive terms added in accord with section 7 apply to the code;
202 | keep intact all notices of the absence of any warranty; and give all
203 | recipients a copy of this License along with the Program.
204 |
205 | You may charge any price or no price for each copy that you convey,
206 | and you may offer support or warranty protection for a fee.
207 |
208 | 5. Conveying Modified Source Versions.
209 |
210 | You may convey a work based on the Program, or the modifications to
211 | produce it from the Program, in the form of source code under the
212 | terms of section 4, provided that you also meet all of these conditions:
213 |
214 | a) The work must carry prominent notices stating that you modified
215 | it, and giving a relevant date.
216 |
217 | b) The work must carry prominent notices stating that it is
218 | released under this License and any conditions added under section
219 | 7. This requirement modifies the requirement in section 4 to
220 | "keep intact all notices".
221 |
222 | c) You must license the entire work, as a whole, under this
223 | License to anyone who comes into possession of a copy. This
224 | License will therefore apply, along with any applicable section 7
225 | additional terms, to the whole of the work, and all its parts,
226 | regardless of how they are packaged. This License gives no
227 | permission to license the work in any other way, but it does not
228 | invalidate such permission if you have separately received it.
229 |
230 | d) If the work has interactive user interfaces, each must display
231 | Appropriate Legal Notices; however, if the Program has interactive
232 | interfaces that do not display Appropriate Legal Notices, your
233 | work need not make them do so.
234 |
235 | A compilation of a covered work with other separate and independent
236 | works, which are not by their nature extensions of the covered work,
237 | and which are not combined with it such as to form a larger program,
238 | in or on a volume of a storage or distribution medium, is called an
239 | "aggregate" if the compilation and its resulting copyright are not
240 | used to limit the access or legal rights of the compilation's users
241 | beyond what the individual works permit. Inclusion of a covered work
242 | in an aggregate does not cause this License to apply to the other
243 | parts of the aggregate.
244 |
245 | 6. Conveying Non-Source Forms.
246 |
247 | You may convey a covered work in object code form under the terms
248 | of sections 4 and 5, provided that you also convey the
249 | machine-readable Corresponding Source under the terms of this License,
250 | in one of these ways:
251 |
252 | a) Convey the object code in, or embodied in, a physical product
253 | (including a physical distribution medium), accompanied by the
254 | Corresponding Source fixed on a durable physical medium
255 | customarily used for software interchange.
256 |
257 | b) Convey the object code in, or embodied in, a physical product
258 | (including a physical distribution medium), accompanied by a
259 | written offer, valid for at least three years and valid for as
260 | long as you offer spare parts or customer support for that product
261 | model, to give anyone who possesses the object code either (1) a
262 | copy of the Corresponding Source for all the software in the
263 | product that is covered by this License, on a durable physical
264 | medium customarily used for software interchange, for a price no
265 | more than your reasonable cost of physically performing this
266 | conveying of source, or (2) access to copy the
267 | Corresponding Source from a network server at no charge.
268 |
269 | c) Convey individual copies of the object code with a copy of the
270 | written offer to provide the Corresponding Source. This
271 | alternative is allowed only occasionally and noncommercially, and
272 | only if you received the object code with such an offer, in accord
273 | with subsection 6b.
274 |
275 | d) Convey the object code by offering access from a designated
276 | place (gratis or for a charge), and offer equivalent access to the
277 | Corresponding Source in the same way through the same place at no
278 | further charge. You need not require recipients to copy the
279 | Corresponding Source along with the object code. If the place to
280 | copy the object code is a network server, the Corresponding Source
281 | may be on a different server (operated by you or a third party)
282 | that supports equivalent copying facilities, provided you maintain
283 | clear directions next to the object code saying where to find the
284 | Corresponding Source. Regardless of what server hosts the
285 | Corresponding Source, you remain obligated to ensure that it is
286 | available for as long as needed to satisfy these requirements.
287 |
288 | e) Convey the object code using peer-to-peer transmission, provided
289 | you inform other peers where the object code and Corresponding
290 | Source of the work are being offered to the general public at no
291 | charge under subsection 6d.
292 |
293 | A separable portion of the object code, whose source code is excluded
294 | from the Corresponding Source as a System Library, need not be
295 | included in conveying the object code work.
296 |
297 | A "User Product" is either (1) a "consumer product", which means any
298 | tangible personal property which is normally used for personal, family,
299 | or household purposes, or (2) anything designed or sold for incorporation
300 | into a dwelling. In determining whether a product is a consumer product,
301 | doubtful cases shall be resolved in favor of coverage. For a particular
302 | product received by a particular user, "normally used" refers to a
303 | typical or common use of that class of product, regardless of the status
304 | of the particular user or of the way in which the particular user
305 | actually uses, or expects or is expected to use, the product. A product
306 | is a consumer product regardless of whether the product has substantial
307 | commercial, industrial or non-consumer uses, unless such uses represent
308 | the only significant mode of use of the product.
309 |
310 | "Installation Information" for a User Product means any methods,
311 | procedures, authorization keys, or other information required to install
312 | and execute modified versions of a covered work in that User Product from
313 | a modified version of its Corresponding Source. The information must
314 | suffice to ensure that the continued functioning of the modified object
315 | code is in no case prevented or interfered with solely because
316 | modification has been made.
317 |
318 | If you convey an object code work under this section in, or with, or
319 | specifically for use in, a User Product, and the conveying occurs as
320 | part of a transaction in which the right of possession and use of the
321 | User Product is transferred to the recipient in perpetuity or for a
322 | fixed term (regardless of how the transaction is characterized), the
323 | Corresponding Source conveyed under this section must be accompanied
324 | by the Installation Information. But this requirement does not apply
325 | if neither you nor any third party retains the ability to install
326 | modified object code on the User Product (for example, the work has
327 | been installed in ROM).
328 |
329 | The requirement to provide Installation Information does not include a
330 | requirement to continue to provide support service, warranty, or updates
331 | for a work that has been modified or installed by the recipient, or for
332 | the User Product in which it has been modified or installed. Access to a
333 | network may be denied when the modification itself materially and
334 | adversely affects the operation of the network or violates the rules and
335 | protocols for communication across the network.
336 |
337 | Corresponding Source conveyed, and Installation Information provided,
338 | in accord with this section must be in a format that is publicly
339 | documented (and with an implementation available to the public in
340 | source code form), and must require no special password or key for
341 | unpacking, reading or copying.
342 |
343 | 7. Additional Terms.
344 |
345 | "Additional permissions" are terms that supplement the terms of this
346 | License by making exceptions from one or more of its conditions.
347 | Additional permissions that are applicable to the entire Program shall
348 | be treated as though they were included in this License, to the extent
349 | that they are valid under applicable law. If additional permissions
350 | apply only to part of the Program, that part may be used separately
351 | under those permissions, but the entire Program remains governed by
352 | this License without regard to the additional permissions.
353 |
354 | When you convey a copy of a covered work, you may at your option
355 | remove any additional permissions from that copy, or from any part of
356 | it. (Additional permissions may be written to require their own
357 | removal in certain cases when you modify the work.) You may place
358 | additional permissions on material, added by you to a covered work,
359 | for which you have or can give appropriate copyright permission.
360 |
361 | Notwithstanding any other provision of this License, for material you
362 | add to a covered work, you may (if authorized by the copyright holders of
363 | that material) supplement the terms of this License with terms:
364 |
365 | a) Disclaiming warranty or limiting liability differently from the
366 | terms of sections 15 and 16 of this License; or
367 |
368 | b) Requiring preservation of specified reasonable legal notices or
369 | author attributions in that material or in the Appropriate Legal
370 | Notices displayed by works containing it; or
371 |
372 | c) Prohibiting misrepresentation of the origin of that material, or
373 | requiring that modified versions of such material be marked in
374 | reasonable ways as different from the original version; or
375 |
376 | d) Limiting the use for publicity purposes of names of licensors or
377 | authors of the material; or
378 |
379 | e) Declining to grant rights under trademark law for use of some
380 | trade names, trademarks, or service marks; or
381 |
382 | f) Requiring indemnification of licensors and authors of that
383 | material by anyone who conveys the material (or modified versions of
384 | it) with contractual assumptions of liability to the recipient, for
385 | any liability that these contractual assumptions directly impose on
386 | those licensors and authors.
387 |
388 | All other non-permissive additional terms are considered "further
389 | restrictions" within the meaning of section 10. If the Program as you
390 | received it, or any part of it, contains a notice stating that it is
391 | governed by this License along with a term that is a further
392 | restriction, you may remove that term. If a license document contains
393 | a further restriction but permits relicensing or conveying under this
394 | License, you may add to a covered work material governed by the terms
395 | of that license document, provided that the further restriction does
396 | not survive such relicensing or conveying.
397 |
398 | If you add terms to a covered work in accord with this section, you
399 | must place, in the relevant source files, a statement of the
400 | additional terms that apply to those files, or a notice indicating
401 | where to find the applicable terms.
402 |
403 | Additional terms, permissive or non-permissive, may be stated in the
404 | form of a separately written license, or stated as exceptions;
405 | the above requirements apply either way.
406 |
407 | 8. Termination.
408 |
409 | You may not propagate or modify a covered work except as expressly
410 | provided under this License. Any attempt otherwise to propagate or
411 | modify it is void, and will automatically terminate your rights under
412 | this License (including any patent licenses granted under the third
413 | paragraph of section 11).
414 |
415 | However, if you cease all violation of this License, then your
416 | license from a particular copyright holder is reinstated (a)
417 | provisionally, unless and until the copyright holder explicitly and
418 | finally terminates your license, and (b) permanently, if the copyright
419 | holder fails to notify you of the violation by some reasonable means
420 | prior to 60 days after the cessation.
421 |
422 | Moreover, your license from a particular copyright holder is
423 | reinstated permanently if the copyright holder notifies you of the
424 | violation by some reasonable means, this is the first time you have
425 | received notice of violation of this License (for any work) from that
426 | copyright holder, and you cure the violation prior to 30 days after
427 | your receipt of the notice.
428 |
429 | Termination of your rights under this section does not terminate the
430 | licenses of parties who have received copies or rights from you under
431 | this License. If your rights have been terminated and not permanently
432 | reinstated, you do not qualify to receive new licenses for the same
433 | material under section 10.
434 |
435 | 9. Acceptance Not Required for Having Copies.
436 |
437 | You are not required to accept this License in order to receive or
438 | run a copy of the Program. Ancillary propagation of a covered work
439 | occurring solely as a consequence of using peer-to-peer transmission
440 | to receive a copy likewise does not require acceptance. However,
441 | nothing other than this License grants you permission to propagate or
442 | modify any covered work. These actions infringe copyright if you do
443 | not accept this License. Therefore, by modifying or propagating a
444 | covered work, you indicate your acceptance of this License to do so.
445 |
446 | 10. Automatic Licensing of Downstream Recipients.
447 |
448 | Each time you convey a covered work, the recipient automatically
449 | receives a license from the original licensors, to run, modify and
450 | propagate that work, subject to this License. You are not responsible
451 | for enforcing compliance by third parties with this License.
452 |
453 | An "entity transaction" is a transaction transferring control of an
454 | organization, or substantially all assets of one, or subdividing an
455 | organization, or merging organizations. If propagation of a covered
456 | work results from an entity transaction, each party to that
457 | transaction who receives a copy of the work also receives whatever
458 | licenses to the work the party's predecessor in interest had or could
459 | give under the previous paragraph, plus a right to possession of the
460 | Corresponding Source of the work from the predecessor in interest, if
461 | the predecessor has it or can get it with reasonable efforts.
462 |
463 | You may not impose any further restrictions on the exercise of the
464 | rights granted or affirmed under this License. For example, you may
465 | not impose a license fee, royalty, or other charge for exercise of
466 | rights granted under this License, and you may not initiate litigation
467 | (including a cross-claim or counterclaim in a lawsuit) alleging that
468 | any patent claim is infringed by making, using, selling, offering for
469 | sale, or importing the Program or any portion of it.
470 |
471 | 11. Patents.
472 |
473 | A "contributor" is a copyright holder who authorizes use under this
474 | License of the Program or a work on which the Program is based. The
475 | work thus licensed is called the contributor's "contributor version".
476 |
477 | A contributor's "essential patent claims" are all patent claims
478 | owned or controlled by the contributor, whether already acquired or
479 | hereafter acquired, that would be infringed by some manner, permitted
480 | by this License, of making, using, or selling its contributor version,
481 | but do not include claims that would be infringed only as a
482 | consequence of further modification of the contributor version. For
483 | purposes of this definition, "control" includes the right to grant
484 | patent sublicenses in a manner consistent with the requirements of
485 | this License.
486 |
487 | Each contributor grants you a non-exclusive, worldwide, royalty-free
488 | patent license under the contributor's essential patent claims, to
489 | make, use, sell, offer for sale, import and otherwise run, modify and
490 | propagate the contents of its contributor version.
491 |
492 | In the following three paragraphs, a "patent license" is any express
493 | agreement or commitment, however denominated, not to enforce a patent
494 | (such as an express permission to practice a patent or covenant not to
495 | sue for patent infringement). To "grant" such a patent license to a
496 | party means to make such an agreement or commitment not to enforce a
497 | patent against the party.
498 |
499 | If you convey a covered work, knowingly relying on a patent license,
500 | and the Corresponding Source of the work is not available for anyone
501 | to copy, free of charge and under the terms of this License, through a
502 | publicly available network server or other readily accessible means,
503 | then you must either (1) cause the Corresponding Source to be so
504 | available, or (2) arrange to deprive yourself of the benefit of the
505 | patent license for this particular work, or (3) arrange, in a manner
506 | consistent with the requirements of this License, to extend the patent
507 | license to downstream recipients. "Knowingly relying" means you have
508 | actual knowledge that, but for the patent license, your conveying the
509 | covered work in a country, or your recipient's use of the covered work
510 | in a country, would infringe one or more identifiable patents in that
511 | country that you have reason to believe are valid.
512 |
513 | If, pursuant to or in connection with a single transaction or
514 | arrangement, you convey, or propagate by procuring conveyance of, a
515 | covered work, and grant a patent license to some of the parties
516 | receiving the covered work authorizing them to use, propagate, modify
517 | or convey a specific copy of the covered work, then the patent license
518 | you grant is automatically extended to all recipients of the covered
519 | work and works based on it.
520 |
521 | A patent license is "discriminatory" if it does not include within
522 | the scope of its coverage, prohibits the exercise of, or is
523 | conditioned on the non-exercise of one or more of the rights that are
524 | specifically granted under this License. You may not convey a covered
525 | work if you are a party to an arrangement with a third party that is
526 | in the business of distributing software, under which you make payment
527 | to the third party based on the extent of your activity of conveying
528 | the work, and under which the third party grants, to any of the
529 | parties who would receive the covered work from you, a discriminatory
530 | patent license (a) in connection with copies of the covered work
531 | conveyed by you (or copies made from those copies), or (b) primarily
532 | for and in connection with specific products or compilations that
533 | contain the covered work, unless you entered into that arrangement,
534 | or that patent license was granted, prior to 28 March 2007.
535 |
536 | Nothing in this License shall be construed as excluding or limiting
537 | any implied license or other defenses to infringement that may
538 | otherwise be available to you under applicable patent law.
539 |
540 | 12. No Surrender of Others' Freedom.
541 |
542 | If conditions are imposed on you (whether by court order, agreement or
543 | otherwise) that contradict the conditions of this License, they do not
544 | excuse you from the conditions of this License. If you cannot convey a
545 | covered work so as to satisfy simultaneously your obligations under this
546 | License and any other pertinent obligations, then as a consequence you may
547 | not convey it at all. For example, if you agree to terms that obligate you
548 | to collect a royalty for further conveying from those to whom you convey
549 | the Program, the only way you could satisfy both those terms and this
550 | License would be to refrain entirely from conveying the Program.
551 |
552 | 13. Use with the GNU Affero General Public License.
553 |
554 | Notwithstanding any other provision of this License, you have
555 | permission to link or combine any covered work with a work licensed
556 | under version 3 of the GNU Affero General Public License into a single
557 | combined work, and to convey the resulting work. The terms of this
558 | License will continue to apply to the part which is the covered work,
559 | but the special requirements of the GNU Affero General Public License,
560 | section 13, concerning interaction through a network will apply to the
561 | combination as such.
562 |
563 | 14. Revised Versions of this License.
564 |
565 | The Free Software Foundation may publish revised and/or new versions of
566 | the GNU General Public License from time to time. Such new versions will
567 | be similar in spirit to the present version, but may differ in detail to
568 | address new problems or concerns.
569 |
570 | Each version is given a distinguishing version number. If the
571 | Program specifies that a certain numbered version of the GNU General
572 | Public License "or any later version" applies to it, you have the
573 | option of following the terms and conditions either of that numbered
574 | version or of any later version published by the Free Software
575 | Foundation. If the Program does not specify a version number of the
576 | GNU General Public License, you may choose any version ever published
577 | by the Free Software Foundation.
578 |
579 | If the Program specifies that a proxy can decide which future
580 | versions of the GNU General Public License can be used, that proxy's
581 | public statement of acceptance of a version permanently authorizes you
582 | to choose that version for the Program.
583 |
584 | Later license versions may give you additional or different
585 | permissions. However, no additional obligations are imposed on any
586 | author or copyright holder as a result of your choosing to follow a
587 | later version.
588 |
589 | 15. Disclaimer of Warranty.
590 |
591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599 |
600 | 16. Limitation of Liability.
601 |
602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610 | SUCH DAMAGES.
611 |
612 | 17. Interpretation of Sections 15 and 16.
613 |
614 | If the disclaimer of warranty and limitation of liability provided
615 | above cannot be given local legal effect according to their terms,
616 | reviewing courts shall apply local law that most closely approximates
617 | an absolute waiver of all civil liability in connection with the
618 | Program, unless a warranty or assumption of liability accompanies a
619 | copy of the Program in return for a fee.
620 |
621 | END OF TERMS AND CONDITIONS
622 |
623 | How to Apply These Terms to Your New Programs
624 |
625 | If you develop a new program, and you want it to be of the greatest
626 | possible use to the public, the best way to achieve this is to make it
627 | free software which everyone can redistribute and change under these terms.
628 |
629 | To do so, attach the following notices to the program. It is safest
630 | to attach them to the start of each source file to most effectively
631 | state the exclusion of warranty; and each file should have at least
632 | the "copyright" line and a pointer to where the full notice is found.
633 |
634 |
635 | Copyright (C)
636 |
637 | This program is free software: you can redistribute it and/or modify
638 | it under the terms of the GNU General Public License as published by
639 | the Free Software Foundation, either version 3 of the License, or
640 | (at your option) any later version.
641 |
642 | This program is distributed in the hope that it will be useful,
643 | but WITHOUT ANY WARRANTY; without even the implied warranty of
644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645 | GNU General Public License for more details.
646 |
647 | You should have received a copy of the GNU General Public License
648 | along with this program. If not, see .
649 |
650 | Also add information on how to contact you by electronic and paper mail.
651 |
652 | If the program does terminal interaction, make it output a short
653 | notice like this when it starts in an interactive mode:
654 |
655 | Copyright (C)
656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657 | This is free software, and you are welcome to redistribute it
658 | under certain conditions; type `show c' for details.
659 |
660 | The hypothetical commands `show w' and `show c' should show the appropriate
661 | parts of the General Public License. Of course, your program's commands
662 | might be different; for a GUI interface, you would use an "about box".
663 |
664 | You should also get your employer (if you work as a programmer) or school,
665 | if any, to sign a "copyright disclaimer" for the program, if necessary.
666 | For more information on this, and how to apply and follow the GNU GPL, see
667 | .
668 |
669 | The GNU General Public License does not permit incorporating your program
670 | into proprietary programs. If your program is a subroutine library, you
671 | may consider it more useful to permit linking proprietary applications with
672 | the library. If this is what you want to do, use the GNU Lesser General
673 | Public License instead of this License. But first, please read
674 | .
675 |
--------------------------------------------------------------------------------
/Materials/BuildingMaterial1.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="StandardMaterial3D" load_steps=3 format=3 uid="uid://dlpsns3f767fm"]
2 |
3 | [ext_resource type="Texture2D" uid="uid://cxkpy86hriclc" path="res://Assets/Image_30.jpg" id="1_fvxkf"]
4 | [ext_resource type="Texture2D" uid="uid://b266paove0s0r" path="res://Assets/Image_31.png" id="2_mk312"]
5 |
6 | [resource]
7 | albedo_texture = ExtResource("1_fvxkf")
8 | metallic_specular = 0.0
9 | normal_enabled = true
10 | normal_texture = ExtResource("2_mk312")
11 | uv1_scale = Vector3(1.5, 6, 1)
12 |
--------------------------------------------------------------------------------
/Materials/BuildingMaterial10.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="StandardMaterial3D" load_steps=3 format=3 uid="uid://by6d738i8uuhc"]
2 |
3 | [ext_resource type="Texture2D" uid="uid://xpc42yi268y2" path="res://Assets/Image_66.jpg" id="1_fjewj"]
4 | [ext_resource type="Texture2D" uid="uid://csc3a12il6mxm" path="res://Assets/Image_67.png" id="2_8u0e1"]
5 |
6 | [resource]
7 | albedo_texture = ExtResource("1_fjewj")
8 | metallic_specular = 0.0
9 | normal_enabled = true
10 | normal_texture = ExtResource("2_8u0e1")
11 | uv1_scale = Vector3(2, 7, 1)
12 |
--------------------------------------------------------------------------------
/Materials/BuildingMaterial11.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="StandardMaterial3D" load_steps=3 format=3 uid="uid://byevgk7f5k71v"]
2 |
3 | [ext_resource type="Texture2D" uid="uid://828yxtcifo2k" path="res://Assets/Image_75.jpg" id="1_qor1q"]
4 | [ext_resource type="Texture2D" uid="uid://cdjik05nthfl4" path="res://Assets/Image_76.png" id="2_i0xip"]
5 |
6 | [resource]
7 | albedo_texture = ExtResource("1_qor1q")
8 | metallic_specular = 0.0
9 | normal_enabled = true
10 | normal_texture = ExtResource("2_i0xip")
11 | uv1_scale = Vector3(2, 7, 1)
12 |
--------------------------------------------------------------------------------
/Materials/BuildingMaterial2.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="StandardMaterial3D" load_steps=3 format=3 uid="uid://io6h7j2xgfql"]
2 |
3 | [ext_resource type="Texture2D" uid="uid://b3ls7cf1wj7yl" path="res://Assets/Image_33.jpg" id="1_4a687"]
4 | [ext_resource type="Texture2D" uid="uid://dkse7h6mt8f4o" path="res://Assets/Image_34.png" id="2_sua56"]
5 |
6 | [resource]
7 | albedo_texture = ExtResource("1_4a687")
8 | metallic_specular = 0.0
9 | normal_enabled = true
10 | normal_texture = ExtResource("2_sua56")
11 | uv1_scale = Vector3(3, 7, 1)
12 |
--------------------------------------------------------------------------------
/Materials/BuildingMaterial3.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="StandardMaterial3D" load_steps=3 format=3 uid="uid://qyefq5uofu1b"]
2 |
3 | [ext_resource type="Texture2D" uid="uid://c6jsm27bkpne0" path="res://Assets/Image_39.jpg" id="1_gc3ft"]
4 | [ext_resource type="Texture2D" uid="uid://dnccvrcak1a7b" path="res://Assets/Image_40.png" id="2_1lyto"]
5 |
6 | [resource]
7 | albedo_texture = ExtResource("1_gc3ft")
8 | metallic_specular = 0.0
9 | normal_enabled = true
10 | normal_texture = ExtResource("2_1lyto")
11 | uv1_scale = Vector3(2, 8, 1)
12 |
--------------------------------------------------------------------------------
/Materials/BuildingMaterial4.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="StandardMaterial3D" load_steps=3 format=3 uid="uid://bcatyh4wyy4qv"]
2 |
3 | [ext_resource type="Texture2D" uid="uid://dlr1xsa17w7mm" path="res://Assets/Image_12.jpg" id="1_jw0s2"]
4 | [ext_resource type="Texture2D" uid="uid://cefjkxahm2dqn" path="res://Assets/Image_13.png" id="2_0crm6"]
5 |
6 | [resource]
7 | albedo_texture = ExtResource("1_jw0s2")
8 | metallic_specular = 0.0
9 | normal_enabled = true
10 | normal_texture = ExtResource("2_0crm6")
11 | uv1_scale = Vector3(2, 12, 1)
12 |
--------------------------------------------------------------------------------
/Materials/BuildingMaterial5.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="StandardMaterial3D" load_steps=3 format=3 uid="uid://d1cf36ct3xc3b"]
2 |
3 | [ext_resource type="Texture2D" uid="uid://dw7h7q8f5emdx" path="res://Assets/Image_15.jpg" id="1_egisv"]
4 | [ext_resource type="Texture2D" uid="uid://b4qx2qwwlt0yl" path="res://Assets/Image_16.png" id="2_4jhrl"]
5 |
6 | [resource]
7 | albedo_texture = ExtResource("1_egisv")
8 | metallic_specular = 0.0
9 | normal_enabled = true
10 | normal_texture = ExtResource("2_4jhrl")
11 | uv1_scale = Vector3(2, 7, 1)
12 |
--------------------------------------------------------------------------------
/Materials/BuildingMaterial6.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="StandardMaterial3D" load_steps=3 format=3 uid="uid://c7ni8ykuhulic"]
2 |
3 | [ext_resource type="Texture2D" uid="uid://cy2fo3gqj6xxs" path="res://Assets/Image_18.png" id="1_hqxsj"]
4 | [ext_resource type="Texture2D" uid="uid://bhyll7idn30gw" path="res://Assets/Image_19.png" id="2_wgmis"]
5 |
6 | [resource]
7 | albedo_texture = ExtResource("1_hqxsj")
8 | metallic_specular = 0.0
9 | normal_enabled = true
10 | normal_texture = ExtResource("2_wgmis")
11 | uv1_scale = Vector3(2, 8, 1)
12 |
--------------------------------------------------------------------------------
/Materials/BuildingMaterial7.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="StandardMaterial3D" load_steps=3 format=3 uid="uid://b6nn5mgt5rph4"]
2 |
3 | [ext_resource type="Texture2D" uid="uid://dbyb2qf6lrmog" path="res://Assets/Image_21.jpg" id="1_3r5at"]
4 | [ext_resource type="Texture2D" uid="uid://bge1yem0n6xue" path="res://Assets/Image_22.png" id="2_rrmev"]
5 |
6 | [resource]
7 | albedo_texture = ExtResource("1_3r5at")
8 | normal_enabled = true
9 | normal_texture = ExtResource("2_rrmev")
10 | uv1_scale = Vector3(2.5, 7, 1)
11 |
--------------------------------------------------------------------------------
/Materials/BuildingMaterial8.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="StandardMaterial3D" load_steps=3 format=3 uid="uid://b226obygdsjg4"]
2 |
3 | [ext_resource type="Texture2D" uid="uid://bdqvjxtybdc7j" path="res://Assets/Image_24.jpg" id="1_p2pyk"]
4 | [ext_resource type="Texture2D" uid="uid://dr7qt8s3tjanf" path="res://Assets/Image_25.png" id="2_4by32"]
5 |
6 | [resource]
7 | albedo_texture = ExtResource("1_p2pyk")
8 | metallic_specular = 0.0
9 | normal_enabled = true
10 | normal_texture = ExtResource("2_4by32")
11 | uv1_scale = Vector3(2, 5, 1)
12 |
--------------------------------------------------------------------------------
/Materials/BuildingMaterial9.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="StandardMaterial3D" load_steps=3 format=3 uid="uid://cdphh522k3dwd"]
2 |
3 | [ext_resource type="Texture2D" uid="uid://e76xhy7kdb6n" path="res://Assets/Image_27.jpg" id="1_tp6mk"]
4 | [ext_resource type="Texture2D" uid="uid://blamqi6hfwsn8" path="res://Assets/Image_28.png" id="2_yfden"]
5 |
6 | [resource]
7 | albedo_texture = ExtResource("1_tp6mk")
8 | metallic_specular = 0.0
9 | normal_enabled = true
10 | normal_texture = ExtResource("2_yfden")
11 | uv1_scale = Vector3(2, 7, 1)
12 |
--------------------------------------------------------------------------------
/Materials/BuildingRoofMaterial1.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="StandardMaterial3D" load_steps=2 format=3 uid="uid://bhurd24vqoyu5"]
2 |
3 | [ext_resource type="Texture2D" uid="uid://c76iuhm3exgdf" path="res://Assets/gravel-ballast-roof-2500-mm-architextures.png" id="1_wogmt"]
4 |
5 | [resource]
6 | albedo_texture = ExtResource("1_wogmt")
7 | uv1_scale = Vector3(10, 10, 1)
8 |
--------------------------------------------------------------------------------
/Materials/FloorMaterial.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="StandardMaterial3D" load_steps=2 format=3 uid="uid://dop7fuh6lrt1o"]
2 |
3 | [ext_resource type="Texture2D" uid="uid://b6x4orqnfp2q6" path="res://Assets/grass.jpg" id="1_ebr5b"]
4 |
5 | [resource]
6 | albedo_color = Color(0, 0.678431, 0.215686, 1)
7 | albedo_texture = ExtResource("1_ebr5b")
8 | metallic_specular = 0.0
9 | uv1_scale = Vector3(20, 20, 1)
10 |
--------------------------------------------------------------------------------
/Materials/RoadMaterial1.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="StandardMaterial3D" load_steps=2 format=3 uid="uid://dj4mb4w8fyjx6"]
2 |
3 | [ext_resource type="Texture2D" uid="uid://demk5w3bmixwx" path="res://Assets/asphalt_01_diff_4k.jpg" id="1_mlgm3"]
4 |
5 | [resource]
6 | albedo_texture = ExtResource("1_mlgm3")
7 | metallic_specular = 0.0
8 | texture_filter = 1
9 |
--------------------------------------------------------------------------------
/Materials/SidewalkMaterial1.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="StandardMaterial3D" load_steps=3 format=3 uid="uid://c8yleok4yc5fy"]
2 |
3 | [ext_resource type="Texture2D" uid="uid://cvaiir664f3no" path="res://Assets/Image_37.jpg" id="1_lieoa"]
4 | [ext_resource type="Texture2D" uid="uid://bgbma1mouwl4w" path="res://Assets/Image_38.png" id="2_vev34"]
5 |
6 | [resource]
7 | albedo_texture = ExtResource("1_lieoa")
8 | normal_enabled = true
9 | normal_texture = ExtResource("2_vev34")
10 | uv1_scale = Vector3(10, 10, 1)
11 |
--------------------------------------------------------------------------------
/Prefabs/tensorFieldPoint.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=4 format=3 uid="uid://c34d65rdo2d2f"]
2 |
3 | [ext_resource type="Script" path="res://Scripts/GUI/PropertiesPointsEdit.cs" id="1_4f8lx"]
4 | [ext_resource type="StyleBox" uid="uid://d385yneucsjb5" path="res://GUIMaterials/PressedButton.tres" id="2_c6q1d"]
5 | [ext_resource type="StyleBox" uid="uid://khqvj7h7agu1" path="res://GUIMaterials/SelectedTensorField.tres" id="3_xobsu"]
6 |
7 | [node name="Point" type="VBoxContainer" node_paths=PackedStringArray("pointButton", "removeButton", "tensorPropertiesContainer", "sliderSize", "textEditSize", "angleEditContainer", "sliderAngle", "textEditAngle", "sliderDecay", "textEditDecay")]
8 | offset_right = 49.0
9 | offset_bottom = 31.0
10 | size_flags_horizontal = 3
11 | script = ExtResource("1_4f8lx")
12 | _selectedStyle = ExtResource("3_xobsu")
13 | _unselectedStyle = ExtResource("2_c6q1d")
14 | pointButton = NodePath("HBoxContainer/PointButton")
15 | removeButton = NodePath("HBoxContainer/Remove")
16 | tensorPropertiesContainer = NodePath("Properties")
17 | sliderSize = NodePath("Properties/SizeContainerProperties/HBoxContainer/HSlider")
18 | textEditSize = NodePath("Properties/SizeContainerProperties/HBoxContainer/LineEdit")
19 | angleEditContainer = NodePath("Properties/AngleContainerProperties")
20 | sliderAngle = NodePath("Properties/AngleContainerProperties/HBoxContainer2/HSlider")
21 | textEditAngle = NodePath("Properties/AngleContainerProperties/HBoxContainer2/LineEdit")
22 | sliderDecay = NodePath("Properties/DecayContainerProperties/HBoxContainer3/HSlider")
23 | textEditDecay = NodePath("Properties/DecayContainerProperties/HBoxContainer3/LineEdit")
24 |
25 | [node name="HBoxContainer" type="HBoxContainer" parent="."]
26 | layout_mode = 2
27 |
28 | [node name="PointButton" type="Button" parent="HBoxContainer"]
29 | layout_mode = 2
30 | size_flags_horizontal = 3
31 | focus_mode = 0
32 | theme_override_styles/pressed = ExtResource("2_c6q1d")
33 | toggle_mode = true
34 | text = "Point"
35 |
36 | [node name="Remove" type="Button" parent="HBoxContainer"]
37 | visible = false
38 | layout_mode = 2
39 | focus_mode = 0
40 | text = "Remove"
41 |
42 | [node name="Properties" type="VBoxContainer" parent="."]
43 | visible = false
44 | layout_mode = 2
45 |
46 | [node name="SizeContainerProperties" type="VBoxContainer" parent="Properties"]
47 | layout_mode = 2
48 |
49 | [node name="Label2" type="Label" parent="Properties/SizeContainerProperties"]
50 | layout_mode = 2
51 | theme_override_font_sizes/font_size = 14
52 | text = "Size"
53 | vertical_alignment = 2
54 |
55 | [node name="HBoxContainer" type="HBoxContainer" parent="Properties/SizeContainerProperties"]
56 | layout_mode = 2
57 |
58 | [node name="LineEdit" type="LineEdit" parent="Properties/SizeContainerProperties/HBoxContainer"]
59 | layout_mode = 2
60 | focus_mode = 1
61 | theme_override_constants/minimum_character_width = 3
62 | text = "5"
63 | max_length = 4
64 | caret_blink = true
65 |
66 | [node name="HSlider" type="HSlider" parent="Properties/SizeContainerProperties/HBoxContainer"]
67 | custom_minimum_size = Vector2(100, 0)
68 | layout_mode = 2
69 | size_flags_horizontal = 3
70 | size_flags_vertical = 4
71 | focus_mode = 0
72 | max_value = 20.0
73 | step = 0.5
74 | value = 5.0
75 |
76 | [node name="AngleContainerProperties" type="VBoxContainer" parent="Properties"]
77 | layout_mode = 2
78 |
79 | [node name="Label3" type="Label" parent="Properties/AngleContainerProperties"]
80 | layout_mode = 2
81 | theme_override_font_sizes/font_size = 14
82 | text = "Angle"
83 | vertical_alignment = 2
84 |
85 | [node name="HBoxContainer2" type="HBoxContainer" parent="Properties/AngleContainerProperties"]
86 | layout_mode = 2
87 |
88 | [node name="LineEdit" type="LineEdit" parent="Properties/AngleContainerProperties/HBoxContainer2"]
89 | layout_mode = 2
90 | focus_mode = 1
91 | theme_override_constants/minimum_character_width = 3
92 | text = "45"
93 | max_length = 3
94 | caret_blink = true
95 |
96 | [node name="HSlider" type="HSlider" parent="Properties/AngleContainerProperties/HBoxContainer2"]
97 | custom_minimum_size = Vector2(100, 0)
98 | layout_mode = 2
99 | size_flags_horizontal = 3
100 | size_flags_vertical = 4
101 | focus_mode = 0
102 | max_value = 360.0
103 | step = 0.5
104 | value = 45.0
105 |
106 | [node name="DecayContainerProperties" type="VBoxContainer" parent="Properties"]
107 | layout_mode = 2
108 |
109 | [node name="Label4" type="Label" parent="Properties/DecayContainerProperties"]
110 | layout_mode = 2
111 | theme_override_font_sizes/font_size = 14
112 | text = "Decay"
113 | vertical_alignment = 2
114 |
115 | [node name="HBoxContainer3" type="HBoxContainer" parent="Properties/DecayContainerProperties"]
116 | layout_mode = 2
117 |
118 | [node name="LineEdit" type="LineEdit" parent="Properties/DecayContainerProperties/HBoxContainer3"]
119 | layout_mode = 2
120 | focus_mode = 1
121 | theme_override_constants/minimum_character_width = 3
122 | text = "2"
123 | max_length = 4
124 | caret_blink = true
125 |
126 | [node name="HSlider" type="HSlider" parent="Properties/DecayContainerProperties/HBoxContainer3"]
127 | custom_minimum_size = Vector2(100, 0)
128 | layout_mode = 2
129 | size_flags_horizontal = 3
130 | size_flags_vertical = 4
131 | focus_mode = 0
132 | min_value = -1.0
133 | max_value = 25.0
134 | value = 2.0
135 |
--------------------------------------------------------------------------------
/ProceduralCityGenerator.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net6.0
4 | true
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/ProceduralCityGenerator.csproj.old:
--------------------------------------------------------------------------------
1 |
2 |
3 | net6.0
4 | true
5 |
6 |
--------------------------------------------------------------------------------
/ProceduralCityGenerator.sln:
--------------------------------------------------------------------------------
1 | Microsoft Visual Studio Solution File, Format Version 12.00
2 | # Visual Studio 2012
3 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProceduralCityGenerator", "ProceduralCityGenerator.csproj", "{38E7DFD8-1E42-49A2-861F-BABAD9384DE5}"
4 | EndProject
5 | Global
6 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
7 | Debug|Any CPU = Debug|Any CPU
8 | ExportDebug|Any CPU = ExportDebug|Any CPU
9 | ExportRelease|Any CPU = ExportRelease|Any CPU
10 | EndGlobalSection
11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
12 | {38E7DFD8-1E42-49A2-861F-BABAD9384DE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
13 | {38E7DFD8-1E42-49A2-861F-BABAD9384DE5}.Debug|Any CPU.Build.0 = Debug|Any CPU
14 | {38E7DFD8-1E42-49A2-861F-BABAD9384DE5}.ExportDebug|Any CPU.ActiveCfg = ExportDebug|Any CPU
15 | {38E7DFD8-1E42-49A2-861F-BABAD9384DE5}.ExportDebug|Any CPU.Build.0 = ExportDebug|Any CPU
16 | {38E7DFD8-1E42-49A2-861F-BABAD9384DE5}.ExportRelease|Any CPU.ActiveCfg = ExportRelease|Any CPU
17 | {38E7DFD8-1E42-49A2-861F-BABAD9384DE5}.ExportRelease|Any CPU.Build.0 = ExportRelease|Any CPU
18 | EndGlobalSection
19 | EndGlobal
20 |
--------------------------------------------------------------------------------
/ProceduralCityGenerator.sln.DotSettings.user:
--------------------------------------------------------------------------------
1 |
2 | <AssemblyExplorer>
3 | <Assembly Path="/home/carl0scheca/.local/share/godot/mono/GodotNuGetFallbackFolder/godotsharp/4.0.0/lib/net6.0/GodotSharp.dll" />
4 | </AssemblyExplorer>
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Procedural City Generator
2 |
3 | Demo https://www.youtube.com/watch?v=61dwd36fJaE
4 |
5 | This project was developed using Godot. The most recent version of the code has been tested and verified to function properly with Godot Mono 4.2.1.
6 |
7 | This project was developed as part of my Bachelor's Degree Final Project. It was inspired by https://probabletrain.itch.io/city-generator and is based on Chen, Guoning & Esch, Gregory & Wonka, Peter & Müller, Pascal & Zhang, Eugene. (2008). Interactive Procedural Street Modeling. ACM Trans. Graph.. 27. 10.1145/1399504.1360702.
8 |
9 | You can download and try it from the [releases page](https://github.com/Carl0sCheca/Procedural-City-Generator-Godot/releases/tag/v1.0).
10 |
11 | Feel free to fork the repository and make improvements as you see fit.
12 |
--------------------------------------------------------------------------------
/Scenes/Main.tscn:
--------------------------------------------------------------------------------
1 | [gd_scene load_steps=12 format=3 uid="uid://cm8a07k34k065"]
2 |
3 | [ext_resource type="Environment" uid="uid://6fklvphu014u" path="res://CameraEnvironment.tres" id="1_m02sb"]
4 | [ext_resource type="Script" path="res://Scripts/CameraController.cs" id="1_tgwq1"]
5 | [ext_resource type="StyleBox" uid="uid://d385yneucsjb5" path="res://GUIMaterials/PressedButton.tres" id="2_pw8xn"]
6 | [ext_resource type="Script" path="res://Scripts/LineDrawer3D.cs" id="3_jelu0"]
7 | [ext_resource type="PackedScene" uid="uid://c34d65rdo2d2f" path="res://Prefabs/tensorFieldPoint.tscn" id="4_3wj43"]
8 | [ext_resource type="Script" path="res://Scripts/PointDrawer3D.cs" id="4_rx5bt"]
9 | [ext_resource type="Script" path="res://Scripts/MainScript.cs" id="4_sxoga"]
10 | [ext_resource type="Environment" uid="uid://dknc6bkcyjc43" path="res://default_env.tres" id="6_lt8wb"]
11 | [ext_resource type="Script" path="res://Scripts/GUI/GuiController.cs" id="7_kas2y"]
12 | [ext_resource type="Material" uid="uid://dop7fuh6lrt1o" path="res://Materials/FloorMaterial.tres" id="7_l5vx1"]
13 |
14 | [sub_resource type="PlaneMesh" id="1"]
15 |
16 | [node name="Root" type="Node3D"]
17 |
18 | [node name="GUI" type="Control" parent="." node_paths=PackedStringArray("_mainScript", "addAllRoads", "addFieldButton", "addMainRoads", "addMajorRoads", "addMinorRoads", "angleEditContainer", "generateBuildings", "generateCity", "hideMenuButton", "listTensorPointsContainer", "mainMenuPanel", "regenerateBuildings", "regenerateTrees", "saveModelButton", "selectGridButton", "selectRadialButton", "showMenuButton", "sliderAngle", "sliderDecay", "sliderSize", "tabBar", "tabContainer1", "tabContainer2", "tensorPropertiesContainer", "textEditAngle", "textEditDecay", "textEditSize")]
19 | layout_mode = 3
20 | anchors_preset = 9
21 | anchor_bottom = 1.0
22 | offset_bottom = 2.0
23 | grow_vertical = 2
24 | mouse_filter = 1
25 | script = ExtResource("7_kas2y")
26 | _mainScript = NodePath("../MainScript")
27 | addAllRoads = NodePath("MainMenu/MenuVBoxContainer/TabMenu/All roads")
28 | addFieldButton = NodePath("MainMenu/MenuVBoxContainer/TabMenu2/ScrollContainer/PointContainer/TensorProperties/AddField")
29 | addMainRoads = NodePath("MainMenu/MenuVBoxContainer/TabMenu/Main roads")
30 | addMajorRoads = NodePath("MainMenu/MenuVBoxContainer/TabMenu/Major roads")
31 | addMinorRoads = NodePath("MainMenu/MenuVBoxContainer/TabMenu/Minor roads")
32 | angleEditContainer = NodePath("MainMenu/MenuVBoxContainer/TabMenu2/ScrollContainer/PointContainer/TensorProperties/AngleContainerProperties")
33 | generateBuildings = NodePath("MainMenu/MenuVBoxContainer/TabMenu/Generate buildings")
34 | generateCity = NodePath("MainMenu/MenuVBoxContainer/TabMenu/Generate city 3D")
35 | hideMenuButton = NodePath("MainMenu/MenuVBoxContainer/TabMenu/Hide menu")
36 | listTensorPointsContainer = NodePath("MainMenu/MenuVBoxContainer/TabMenu2/ScrollContainer/PointContainer/ScrollContainer/Tensorfield points")
37 | mainMenuPanel = NodePath("MainMenu")
38 | regenerateBuildings = NodePath("MainMenu/MenuVBoxContainer/TabMenu/Regenerate buildings")
39 | regenerateTrees = NodePath("MainMenu/MenuVBoxContainer/TabMenu/Regenerate trees")
40 | saveModelButton = NodePath("MainMenu/MenuVBoxContainer/TabMenu/Export model")
41 | selectGridButton = NodePath("MainMenu/MenuVBoxContainer/TabMenu2/ScrollContainer/PointContainer/SelectGrid")
42 | selectRadialButton = NodePath("MainMenu/MenuVBoxContainer/TabMenu2/ScrollContainer/PointContainer/SelectRadial")
43 | showMenuButton = NodePath("Show menu")
44 | sliderAngle = NodePath("MainMenu/MenuVBoxContainer/TabMenu2/ScrollContainer/PointContainer/TensorProperties/AngleContainerProperties/HBoxContainer2/HSlider")
45 | sliderDecay = NodePath("MainMenu/MenuVBoxContainer/TabMenu2/ScrollContainer/PointContainer/TensorProperties/DecayContainerProperties/HBoxContainer3/HSlider")
46 | sliderSize = NodePath("MainMenu/MenuVBoxContainer/TabMenu2/ScrollContainer/PointContainer/TensorProperties/SizeContainerProperties/HBoxContainer/HSlider")
47 | tabBar = NodePath("MainMenu/MenuVBoxContainer/TabBar")
48 | tabContainer1 = NodePath("MainMenu/MenuVBoxContainer/TabMenu")
49 | tabContainer2 = NodePath("MainMenu/MenuVBoxContainer/TabMenu2")
50 | tensorPointPrefab = ExtResource("4_3wj43")
51 | tensorPropertiesContainer = NodePath("MainMenu/MenuVBoxContainer/TabMenu2/ScrollContainer/PointContainer/TensorProperties")
52 | textEditAngle = NodePath("MainMenu/MenuVBoxContainer/TabMenu2/ScrollContainer/PointContainer/TensorProperties/AngleContainerProperties/HBoxContainer2/LineEdit")
53 | textEditDecay = NodePath("MainMenu/MenuVBoxContainer/TabMenu2/ScrollContainer/PointContainer/TensorProperties/DecayContainerProperties/HBoxContainer3/LineEdit")
54 | textEditSize = NodePath("MainMenu/MenuVBoxContainer/TabMenu2/ScrollContainer/PointContainer/TensorProperties/SizeContainerProperties/HBoxContainer/LineEdit")
55 |
56 | [node name="Show menu" type="Button" parent="GUI"]
57 | layout_mode = 2
58 | offset_right = 99.0
59 | offset_bottom = 31.0
60 | focus_mode = 0
61 | text = "Show menu (ESC)"
62 |
63 | [node name="MainMenu" type="PanelContainer" parent="GUI"]
64 | layout_mode = 1
65 | anchors_preset = 1
66 | anchor_left = 1.0
67 | anchor_right = 1.0
68 | offset_left = -200.0
69 | offset_bottom = 650.0
70 | grow_horizontal = 0
71 |
72 | [node name="MenuVBoxContainer" type="VBoxContainer" parent="GUI/MainMenu"]
73 | layout_mode = 2
74 |
75 | [node name="TabBar" type="TabBar" parent="GUI/MainMenu/MenuVBoxContainer"]
76 | clip_contents = true
77 | layout_mode = 2
78 | tab_count = 2
79 | tab_alignment = 1
80 | clip_tabs = false
81 | max_tab_width = 150
82 | tab_0/title = "Roads"
83 | tab_1/title = "Tensor fields"
84 |
85 | [node name="TabMenu" type="VBoxContainer" parent="GUI/MainMenu/MenuVBoxContainer"]
86 | layout_mode = 2
87 |
88 | [node name="Hide menu" type="Button" parent="GUI/MainMenu/MenuVBoxContainer/TabMenu"]
89 | layout_mode = 2
90 | focus_mode = 0
91 | text = "Hide menu (ESC)"
92 |
93 | [node name="Main roads" type="Button" parent="GUI/MainMenu/MenuVBoxContainer/TabMenu"]
94 | layout_mode = 2
95 | focus_mode = 0
96 | text = "Main roads"
97 |
98 | [node name="Major roads" type="Button" parent="GUI/MainMenu/MenuVBoxContainer/TabMenu"]
99 | layout_mode = 2
100 | focus_mode = 0
101 | text = "Major roads"
102 |
103 | [node name="Minor roads" type="Button" parent="GUI/MainMenu/MenuVBoxContainer/TabMenu"]
104 | layout_mode = 2
105 | focus_mode = 0
106 | text = "Minor roads"
107 |
108 | [node name="All roads" type="Button" parent="GUI/MainMenu/MenuVBoxContainer/TabMenu"]
109 | layout_mode = 2
110 | tooltip_text = "Generate all roads at once"
111 | focus_mode = 0
112 | text = "All roads"
113 |
114 | [node name="Generate buildings" type="Button" parent="GUI/MainMenu/MenuVBoxContainer/TabMenu"]
115 | layout_mode = 2
116 | tooltip_text = "Generate buildings.
117 | You need to generate at least one road first"
118 | focus_mode = 0
119 | text = "Generate buildings"
120 |
121 | [node name="Generate city 3D" type="Button" parent="GUI/MainMenu/MenuVBoxContainer/TabMenu"]
122 | layout_mode = 2
123 | focus_mode = 0
124 | text = "Generate city 3D"
125 |
126 | [node name="Regenerate buildings" type="Button" parent="GUI/MainMenu/MenuVBoxContainer/TabMenu"]
127 | layout_mode = 2
128 | tooltip_text = "Change building height distribution"
129 | focus_mode = 0
130 | text = "Regenerate 3D buildings"
131 |
132 | [node name="Regenerate trees" type="Button" parent="GUI/MainMenu/MenuVBoxContainer/TabMenu"]
133 | layout_mode = 2
134 | tooltip_text = "Change building tree distribution"
135 | focus_mode = 0
136 | text = "Regenerate trees"
137 |
138 | [node name="Export model" type="Button" parent="GUI/MainMenu/MenuVBoxContainer/TabMenu"]
139 | layout_mode = 2
140 | focus_mode = 0
141 | text = "Export 3D model"
142 |
143 | [node name="TabMenu2" type="VBoxContainer" parent="GUI/MainMenu/MenuVBoxContainer"]
144 | visible = false
145 | layout_mode = 2
146 | size_flags_vertical = 3
147 |
148 | [node name="ScrollContainer" type="ScrollContainer" parent="GUI/MainMenu/MenuVBoxContainer/TabMenu2"]
149 | clip_contents = false
150 | custom_minimum_size = Vector2(150, 500)
151 | layout_mode = 2
152 | size_flags_vertical = 3
153 | horizontal_scroll_mode = 0
154 |
155 | [node name="PointContainer" type="VBoxContainer" parent="GUI/MainMenu/MenuVBoxContainer/TabMenu2/ScrollContainer"]
156 | clip_contents = true
157 | layout_mode = 2
158 | size_flags_horizontal = 3
159 | size_flags_vertical = 3
160 |
161 | [node name="Label5" type="Label" parent="GUI/MainMenu/MenuVBoxContainer/TabMenu2/ScrollContainer/PointContainer"]
162 | layout_mode = 2
163 | text = "Tensor field type"
164 | horizontal_alignment = 1
165 |
166 | [node name="SelectRadial" type="Button" parent="GUI/MainMenu/MenuVBoxContainer/TabMenu2/ScrollContainer/PointContainer"]
167 | layout_mode = 2
168 | focus_mode = 0
169 | theme_override_styles/pressed = ExtResource("2_pw8xn")
170 | toggle_mode = true
171 | text = "Radial
172 | "
173 |
174 | [node name="SelectGrid" type="Button" parent="GUI/MainMenu/MenuVBoxContainer/TabMenu2/ScrollContainer/PointContainer"]
175 | layout_mode = 2
176 | focus_mode = 0
177 | theme_override_styles/pressed = ExtResource("2_pw8xn")
178 | toggle_mode = true
179 | text = "Grid"
180 |
181 | [node name="TensorProperties" type="VBoxContainer" parent="GUI/MainMenu/MenuVBoxContainer/TabMenu2/ScrollContainer/PointContainer"]
182 | visible = false
183 | layout_mode = 2
184 |
185 | [node name="Label" type="Label" parent="GUI/MainMenu/MenuVBoxContainer/TabMenu2/ScrollContainer/PointContainer/TensorProperties"]
186 | layout_mode = 2
187 | text = "Properties"
188 | horizontal_alignment = 1
189 | vertical_alignment = 2
190 |
191 | [node name="SizeContainerProperties" type="VBoxContainer" parent="GUI/MainMenu/MenuVBoxContainer/TabMenu2/ScrollContainer/PointContainer/TensorProperties"]
192 | layout_mode = 2
193 |
194 | [node name="Label2" type="Label" parent="GUI/MainMenu/MenuVBoxContainer/TabMenu2/ScrollContainer/PointContainer/TensorProperties/SizeContainerProperties"]
195 | layout_mode = 2
196 | theme_override_font_sizes/font_size = 14
197 | text = "Size"
198 | vertical_alignment = 2
199 |
200 | [node name="HBoxContainer" type="HBoxContainer" parent="GUI/MainMenu/MenuVBoxContainer/TabMenu2/ScrollContainer/PointContainer/TensorProperties/SizeContainerProperties"]
201 | layout_mode = 2
202 |
203 | [node name="LineEdit" type="LineEdit" parent="GUI/MainMenu/MenuVBoxContainer/TabMenu2/ScrollContainer/PointContainer/TensorProperties/SizeContainerProperties/HBoxContainer"]
204 | layout_mode = 2
205 | focus_mode = 1
206 | theme_override_constants/minimum_character_width = 3
207 | text = "5"
208 | max_length = 4
209 | caret_blink = true
210 |
211 | [node name="HSlider" type="HSlider" parent="GUI/MainMenu/MenuVBoxContainer/TabMenu2/ScrollContainer/PointContainer/TensorProperties/SizeContainerProperties/HBoxContainer"]
212 | custom_minimum_size = Vector2(100, 0)
213 | layout_mode = 2
214 | size_flags_horizontal = 3
215 | size_flags_vertical = 4
216 | focus_mode = 0
217 | max_value = 20.0
218 | step = 0.5
219 | value = 5.0
220 |
221 | [node name="AngleContainerProperties" type="VBoxContainer" parent="GUI/MainMenu/MenuVBoxContainer/TabMenu2/ScrollContainer/PointContainer/TensorProperties"]
222 | layout_mode = 2
223 |
224 | [node name="Label3" type="Label" parent="GUI/MainMenu/MenuVBoxContainer/TabMenu2/ScrollContainer/PointContainer/TensorProperties/AngleContainerProperties"]
225 | layout_mode = 2
226 | theme_override_font_sizes/font_size = 14
227 | text = "Angle"
228 | vertical_alignment = 2
229 |
230 | [node name="HBoxContainer2" type="HBoxContainer" parent="GUI/MainMenu/MenuVBoxContainer/TabMenu2/ScrollContainer/PointContainer/TensorProperties/AngleContainerProperties"]
231 | layout_mode = 2
232 |
233 | [node name="LineEdit" type="LineEdit" parent="GUI/MainMenu/MenuVBoxContainer/TabMenu2/ScrollContainer/PointContainer/TensorProperties/AngleContainerProperties/HBoxContainer2"]
234 | layout_mode = 2
235 | focus_mode = 1
236 | theme_override_constants/minimum_character_width = 3
237 | text = "45"
238 | max_length = 3
239 | caret_blink = true
240 |
241 | [node name="HSlider" type="HSlider" parent="GUI/MainMenu/MenuVBoxContainer/TabMenu2/ScrollContainer/PointContainer/TensorProperties/AngleContainerProperties/HBoxContainer2"]
242 | custom_minimum_size = Vector2(100, 0)
243 | layout_mode = 2
244 | size_flags_horizontal = 3
245 | size_flags_vertical = 4
246 | focus_mode = 0
247 | max_value = 360.0
248 | step = 0.5
249 | value = 45.0
250 |
251 | [node name="DecayContainerProperties" type="VBoxContainer" parent="GUI/MainMenu/MenuVBoxContainer/TabMenu2/ScrollContainer/PointContainer/TensorProperties"]
252 | layout_mode = 2
253 |
254 | [node name="Label4" type="Label" parent="GUI/MainMenu/MenuVBoxContainer/TabMenu2/ScrollContainer/PointContainer/TensorProperties/DecayContainerProperties"]
255 | layout_mode = 2
256 | theme_override_font_sizes/font_size = 14
257 | text = "Decay"
258 | vertical_alignment = 2
259 |
260 | [node name="HBoxContainer3" type="HBoxContainer" parent="GUI/MainMenu/MenuVBoxContainer/TabMenu2/ScrollContainer/PointContainer/TensorProperties/DecayContainerProperties"]
261 | layout_mode = 2
262 |
263 | [node name="LineEdit" type="LineEdit" parent="GUI/MainMenu/MenuVBoxContainer/TabMenu2/ScrollContainer/PointContainer/TensorProperties/DecayContainerProperties/HBoxContainer3"]
264 | layout_mode = 2
265 | focus_mode = 1
266 | theme_override_constants/minimum_character_width = 3
267 | text = "2"
268 | max_length = 4
269 | caret_blink = true
270 |
271 | [node name="HSlider" type="HSlider" parent="GUI/MainMenu/MenuVBoxContainer/TabMenu2/ScrollContainer/PointContainer/TensorProperties/DecayContainerProperties/HBoxContainer3"]
272 | custom_minimum_size = Vector2(100, 0)
273 | layout_mode = 2
274 | size_flags_horizontal = 3
275 | size_flags_vertical = 4
276 | focus_mode = 0
277 | min_value = -1.0
278 | max_value = 25.0
279 | value = 2.0
280 |
281 | [node name="AddField" type="Button" parent="GUI/MainMenu/MenuVBoxContainer/TabMenu2/ScrollContainer/PointContainer/TensorProperties"]
282 | layout_mode = 2
283 | focus_mode = 0
284 | text = "Add tensor field"
285 |
286 | [node name="HSeparator" type="HSeparator" parent="GUI/MainMenu/MenuVBoxContainer/TabMenu2/ScrollContainer/PointContainer"]
287 | layout_mode = 2
288 |
289 | [node name="ScrollContainer" type="ScrollContainer" parent="GUI/MainMenu/MenuVBoxContainer/TabMenu2/ScrollContainer/PointContainer"]
290 | layout_mode = 2
291 | size_flags_vertical = 3
292 | horizontal_scroll_mode = 0
293 |
294 | [node name="Tensorfield points" type="VBoxContainer" parent="GUI/MainMenu/MenuVBoxContainer/TabMenu2/ScrollContainer/PointContainer/ScrollContainer"]
295 | layout_mode = 2
296 | size_flags_horizontal = 3
297 | size_flags_vertical = 3
298 |
299 | [node name="MainScript" type="Node" parent="." node_paths=PackedStringArray("_guiController")]
300 | script = ExtResource("4_sxoga")
301 | _cameraEnvironment = ExtResource("1_m02sb")
302 | _defaultEnvironment = ExtResource("6_lt8wb")
303 | _guiController = NodePath("../GUI")
304 |
305 | [node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
306 | transform = Transform3D(0.0906328, -0.96195, -0.257754, 0, -0.258819, 0.965926, -0.995884, -0.0875446, -0.0234575, 0, 4.77529, 0)
307 | shadow_enabled = true
308 |
309 | [node name="Camera3D" type="Camera3D" parent="."]
310 | transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 20, 10, -20)
311 | visible = false
312 | environment = ExtResource("6_lt8wb")
313 | projection = 1
314 | size = 2.0
315 | script = ExtResource("1_tgwq1")
316 |
317 | [node name="Points" type="MeshInstance3D" parent="."]
318 | transform = Transform3D(1, 0, 0, 0, 1.19249e-08, 1, 0, -1, 1.19249e-08, 0, 0, 0)
319 | skeleton = NodePath("../Camera3D")
320 | script = ExtResource("4_rx5bt")
321 |
322 | [node name="Lines" type="MeshInstance3D" parent="."]
323 | transform = Transform3D(1, 0, 0, 0, 1.19249e-08, 1, 0, -1, 1.19249e-08, 0, 0, 0)
324 | skeleton = NodePath("../Camera3D")
325 | script = ExtResource("3_jelu0")
326 |
327 | [node name="Lines2" type="MeshInstance3D" parent="."]
328 | transform = Transform3D(1, 0, 0, 0, -1, 2.38498e-08, 0, -2.38498e-08, -1, 0, 0, 0)
329 | skeleton = NodePath("../Camera3D")
330 | script = ExtResource("3_jelu0")
331 |
332 | [node name="TensorFieldPoints" type="MeshInstance3D" parent="."]
333 | transform = Transform3D(1, 0, 0, 0, 1.19249e-08, 1, 0, -1, 1.19249e-08, 0, 0, 0)
334 | sorting_offset = 1.0
335 | skeleton = NodePath("../Camera3D")
336 | script = ExtResource("4_rx5bt")
337 |
338 | [node name="RoadModel" type="Node3D" parent="."]
339 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 20, 0, -20)
340 |
341 | [node name="Roads" type="CSGCombiner3D" parent="RoadModel"]
342 | use_collision = true
343 |
344 | [node name="BuildingsModel" type="Node3D" parent="."]
345 | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 10, 0, -10)
346 |
347 | [node name="Buildings" type="CSGCombiner3D" parent="BuildingsModel"]
348 | transform = Transform3D(1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, -10, 0, 10)
349 | use_collision = true
350 |
351 | [node name="RoadsBuildings" type="CSGCombiner3D" parent="BuildingsModel"]
352 | transform = Transform3D(1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, -10, 0, 10)
353 | use_collision = true
354 |
355 | [node name="Floor" type="CSGMesh3D" parent="."]
356 | transform = Transform3D(20, 0, 0, 0, 1, 0, 0, 0, 20, 20, 0, -20)
357 | visible = false
358 | use_collision = true
359 | mesh = SubResource("1")
360 | material = ExtResource("7_l5vx1")
361 |
362 | [node name="Trees" type="Node3D" parent="."]
363 |
364 | [node name="Control" type="Control" parent="."]
365 | layout_mode = 3
366 | anchors_preset = 0
367 | offset_right = 40.0
368 | offset_bottom = 40.0
369 |
--------------------------------------------------------------------------------
/Scripts/CameraController.cs:
--------------------------------------------------------------------------------
1 | using Godot;
2 |
3 | namespace ProceduralCityGenerator.Scripts;
4 |
5 | public partial class CameraController : Camera3D
6 | {
7 | private const float MouseSensitivity = 0.1f;
8 | private readonly Vector2 _draggingSensitivity = new(200f, 200f);
9 | private Vector2 _actualMousePosition;
10 |
11 | private CameraMovement _cameraMovement;
12 | private Vector3 _cameraSpeed = Vector3.One;
13 | private bool _dragging;
14 | private Vector2 _mouseMovement;
15 | private float _pitch;
16 | private Vector2 _startPoint;
17 | private float _yaw;
18 |
19 | public Vector2 centerScreen;
20 |
21 | public bool mouseCapture;
22 |
23 | public override void _Ready()
24 | {
25 | _startPoint = Vector2.Zero;
26 | _actualMousePosition = Vector2.Zero;
27 | Size = 4;
28 | }
29 |
30 | public override void _Process(double delta)
31 | {
32 | centerScreen = new Vector2(Position.X, Position.Z);
33 |
34 | switch (Projection)
35 | {
36 | case ProjectionType.Orthogonal:
37 | _ProcessOrthogonal();
38 | break;
39 | case ProjectionType.Perspective:
40 | _ProcessProjection(delta);
41 | break;
42 | }
43 | }
44 |
45 | private void _ProcessOrthogonal()
46 | {
47 | Input.MouseMode = Input.MouseModeEnum.Visible;
48 |
49 | if (!_dragging) return;
50 |
51 | var newPosition = new Vector3(
52 | Position.X + (_startPoint.X - _actualMousePosition.X) / _draggingSensitivity.X,
53 | Position.Y,
54 | Position.Z + (_startPoint.Y - _actualMousePosition.Y) / _draggingSensitivity.Y
55 | );
56 | Position = newPosition;
57 | _startPoint = _actualMousePosition;
58 | }
59 |
60 | private void _ProcessProjection(double delta)
61 | {
62 | Input.MouseMode = mouseCapture ? Input.MouseModeEnum.Captured : Input.MouseModeEnum.Visible;
63 | _yaw = (_yaw - _mouseMovement.X * MouseSensitivity) % 360;
64 | _pitch = Mathf.Max(Mathf.Min(_pitch - _mouseMovement.Y * MouseSensitivity, 90), -90);
65 | Rotation = new Vector3(Mathf.DegToRad(_pitch), Mathf.DegToRad(_yaw), 0);
66 | if (_cameraMovement.forward)
67 | Position -= GlobalTransform.Basis.Z * _cameraSpeed * (float)delta;
68 | else if (_cameraMovement.backward) Position += GlobalTransform.Basis.Z * _cameraSpeed * (float)delta;
69 | if (_cameraMovement.left)
70 | Position -= GlobalTransform.Basis.X * _cameraSpeed * (float)delta;
71 | else if (_cameraMovement.right) Position += GlobalTransform.Basis.X * _cameraSpeed * (float)delta;
72 | if (_cameraMovement.up)
73 | Position += Vector3.Up * _cameraSpeed * (float)delta;
74 | else if (_cameraMovement.down) Position -= Vector3.Up * _cameraSpeed * (float)delta;
75 | _mouseMovement = Vector2.Zero;
76 | }
77 |
78 | public override void _Input(InputEvent @event)
79 | {
80 | if (@event.IsActionReleased("mouseMiddle"))
81 | _dragging = false;
82 | else if (@event.IsActionPressed("mouseMiddle")) _dragging = true;
83 |
84 | switch (Projection)
85 | {
86 | case ProjectionType.Orthogonal:
87 | _InputOrthogonal(@event);
88 | break;
89 | case ProjectionType.Perspective:
90 | _InputProjection(@event);
91 | break;
92 | }
93 | }
94 |
95 | private void _InputOrthogonal(InputEvent @event)
96 | {
97 | if (@event is InputEventMouseMotion eventMouseMotion)
98 | if (_dragging)
99 | _actualMousePosition = eventMouseMotion.Position;
100 |
101 | if (@event is InputEventMouseButton eventMouseButton)
102 | {
103 | if (@event.IsActionPressed("mouseMiddle"))
104 | {
105 | _startPoint = eventMouseButton.Position;
106 | _actualMousePosition = eventMouseButton.Position;
107 | }
108 |
109 | // Scroll up
110 | if (eventMouseButton.ButtonIndex is MouseButton.WheelUp)
111 | {
112 | if (Size - 1 <= 0)
113 | Size = 1;
114 | else
115 | Size -= 1;
116 | }
117 | // Scroll down
118 | else if (eventMouseButton.ButtonIndex is MouseButton.WheelDown)
119 | {
120 | Size += 1;
121 | }
122 |
123 | // var width = Size * (GetViewport().GetVisibleRect().Size.X / GetViewport().GetVisibleRect().Size.Y);
124 | // GD.Print("Position: ", Position.X - width / 2, ", ", Position.Z - Size / 2);
125 | }
126 | }
127 |
128 | private void _InputProjection(InputEvent @event)
129 | {
130 | if (!mouseCapture) return;
131 |
132 | if (@event is InputEventMouseMotion eventMouseMotion) _mouseMovement = eventMouseMotion.Relative;
133 |
134 | if (@event is InputEventKey inputEventKey)
135 | {
136 | if (inputEventKey.IsPressed() && inputEventKey.Keycode == Key.W)
137 | {
138 | _cameraMovement.forward = true;
139 | }
140 | else if (inputEventKey.IsPressed() && inputEventKey.Keycode == Key.S)
141 | {
142 | _cameraMovement.backward = true;
143 | }
144 | else if (inputEventKey.Keycode is Key.W or Key.S)
145 | {
146 | _cameraMovement.forward = false;
147 | _cameraMovement.backward = false;
148 | }
149 |
150 | if (inputEventKey.IsPressed() && inputEventKey.Keycode == Key.A)
151 | {
152 | _cameraMovement.left = true;
153 | }
154 | else if (inputEventKey.IsPressed() && inputEventKey.Keycode == Key.D)
155 | {
156 | _cameraMovement.right = true;
157 | }
158 | else if (inputEventKey.Keycode is Key.A or Key.D)
159 | {
160 | _cameraMovement.left = false;
161 | _cameraMovement.right = false;
162 | }
163 |
164 | if (inputEventKey.IsPressed() && inputEventKey.Keycode == Key.E)
165 | {
166 | _cameraMovement.up = true;
167 | }
168 | else if (inputEventKey.IsPressed() && inputEventKey.Keycode == Key.Q)
169 | {
170 | _cameraMovement.down = true;
171 | }
172 | else if (inputEventKey.Keycode is Key.Q or Key.E)
173 | {
174 | _cameraMovement.up = false;
175 | _cameraMovement.down = false;
176 | }
177 |
178 | if (inputEventKey.IsPressed() && inputEventKey.Keycode == Key.Shift)
179 | _cameraSpeed = Vector3.One * 4f;
180 | else if (!inputEventKey.IsPressed() && inputEventKey.Keycode == Key.Shift) _cameraSpeed = Vector3.One;
181 | }
182 | }
183 |
184 | private struct CameraMovement
185 | {
186 | public bool forward;
187 | public bool backward;
188 | public bool left;
189 | public bool right;
190 | public bool up;
191 | public bool down;
192 | }
193 | }
--------------------------------------------------------------------------------
/Scripts/DataStructure/Field.cs:
--------------------------------------------------------------------------------
1 | using Godot;
2 |
3 | namespace ProceduralCityGenerator.Scripts.DataStructure;
4 |
5 | public abstract class Field
6 | {
7 | public Vector2 center;
8 | public float decay;
9 | public float size;
10 |
11 | protected Field(Vector2 center, float size, float decay)
12 | {
13 | this.center = center;
14 | this.size = size;
15 | this.decay = decay;
16 | }
17 |
18 | public Tensor GetWeightedTensor(Vector2 point)
19 | {
20 | var tensor = GetTensor(point);
21 | tensor.r *= GetTensorWeight(point);
22 | tensor.oldth = true;
23 |
24 | return tensor;
25 | }
26 |
27 | private float GetTensorWeight(Vector2 point)
28 | {
29 | var normDistanceToCenter = (point - center).Length() / size;
30 |
31 | if (decay == 0 && normDistanceToCenter >= 1) return 0;
32 |
33 | return Mathf.Pow(Mathf.Max(0, 1 - normDistanceToCenter), decay);
34 | }
35 |
36 | protected abstract Tensor GetTensor(Vector2 point);
37 | }
--------------------------------------------------------------------------------
/Scripts/DataStructure/Grid.cs:
--------------------------------------------------------------------------------
1 | using Godot;
2 |
3 | namespace ProceduralCityGenerator.Scripts.DataStructure;
4 |
5 | public class Grid : Field
6 | {
7 | public float theta;
8 |
9 | public Grid(Vector2 center, float size, float decay, float theta) : base(center, size, decay)
10 | {
11 | this.theta = theta;
12 | }
13 |
14 | protected override Tensor GetTensor(Vector2 point)
15 | {
16 | return new Tensor(1, new[] { Mathf.Cos(2 * theta), Mathf.Sin(2 * theta) });
17 | }
18 | }
--------------------------------------------------------------------------------
/Scripts/DataStructure/GridStorage.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using Godot;
3 |
4 | namespace ProceduralCityGenerator.Scripts.DataStructure;
5 |
6 | public class GridStorage
7 | {
8 | private readonly List>> _grid;
9 | private readonly Vector2 _gridDimensions;
10 | private readonly Vector2 _origin;
11 | private readonly float _sep;
12 | private readonly Vector2 _worldDimensions;
13 |
14 | public GridStorage(Vector2 worldDimensions, Vector2 origin, float sep)
15 | {
16 | _grid = new List>>();
17 | _origin = origin;
18 | _sep = sep;
19 | _worldDimensions = worldDimensions;
20 | _gridDimensions = _worldDimensions / _sep;
21 |
22 | for (var i = 0; i < _gridDimensions.X; i++)
23 | {
24 | _grid.Add(new List>());
25 | for (var j = 0; j < _gridDimensions.Y; j++) _grid[i].Add(new List());
26 | }
27 | }
28 |
29 | public void AddAll(GridStorage gridStorage)
30 | {
31 | foreach (var row in gridStorage._grid)
32 | foreach (var cell in row)
33 | foreach (var sample in cell)
34 | AddSample(sample);
35 | }
36 |
37 | public List GetNearbyPoints(Vector2 v, float distance)
38 | {
39 | var radius = (int)Mathf.Ceil(distance / _sep - 0.5f);
40 | var coords = GetSampleCoords(v);
41 | var outVectors = new List();
42 |
43 | for (var i = -1 * radius; i <= 1 * radius; i++)
44 | for (var j = -1 * radius; j <= 1 * radius; j++)
45 | {
46 | var cell = coords + new Vector2(i, j);
47 | if (!VectorOutOfBounds(cell, _gridDimensions))
48 | foreach (var v2 in _grid[(int)cell.X][(int)cell.Y])
49 | outVectors.Add(v2);
50 | }
51 |
52 | return outVectors;
53 | }
54 |
55 | public void AddSample(Vector2 v)
56 | {
57 | var coords = GetSampleCoords(v);
58 |
59 | AddSample(v, coords);
60 | }
61 |
62 | private void AddSample(Vector2 v, Vector2 coords)
63 | {
64 | _grid[(int)coords.X][(int)coords.Y].Add(v);
65 | }
66 |
67 | private Vector2 GetSampleCoords(Vector2 worldV)
68 | {
69 | var v = worldV - _origin;
70 |
71 | if (VectorOutOfBounds(v, _worldDimensions)) return Vector2.Zero;
72 |
73 | return new Vector2(Mathf.Floor(v.X / _sep), Mathf.Floor(v.Y / _sep));
74 | }
75 |
76 | public bool IsValidSample(Vector2 v, float dSq)
77 | {
78 | var coords = GetSampleCoords(v);
79 |
80 | for (var i = -1; i <= 1; i++)
81 | for (var j = -1; j <= 1; j++)
82 | {
83 | var cell = coords + new Vector2(i, j);
84 |
85 | if (!VectorOutOfBounds(cell, _gridDimensions))
86 | if (!VectorFarFromVectors(v, _grid[(int)cell.X][(int)cell.Y], dSq))
87 | return false;
88 | }
89 |
90 | return true;
91 | }
92 |
93 | private static bool VectorFarFromVectors(Vector2 v, List vectors, float dSq)
94 | {
95 | foreach (var sample in vectors)
96 | if (!sample.Equals(v))
97 | {
98 | var distanceSq = sample.DistanceSquaredTo(v);
99 |
100 | if (distanceSq < dSq) return false;
101 | }
102 |
103 | return true;
104 | }
105 |
106 | private static bool VectorOutOfBounds(Vector2 gridV, Vector2 bounds)
107 | {
108 | return gridV.X < 0 || gridV.Y < 0 ||
109 | gridV.X >= bounds.X || gridV.Y >= bounds.Y;
110 | }
111 |
112 | public void AddPolyline(List line)
113 | {
114 | foreach (var v in line) AddSample(v);
115 | }
116 | }
--------------------------------------------------------------------------------
/Scripts/DataStructure/IPointDrawImmediate.cs:
--------------------------------------------------------------------------------
1 | using Godot;
2 |
3 | namespace ProceduralCityGenerator.Scripts.DataStructure;
4 |
5 | public interface IPointDrawImmediate
6 | {
7 | internal struct Point
8 | {
9 | internal Vector3 point;
10 | internal Color color;
11 | }
12 | }
--------------------------------------------------------------------------------
/Scripts/DataStructure/Integrator.cs:
--------------------------------------------------------------------------------
1 | using Godot;
2 |
3 | namespace ProceduralCityGenerator.Scripts.DataStructure;
4 |
5 | public class Integrator
6 | {
7 | private readonly float _step;
8 | private readonly TensorField _tensorField;
9 |
10 | public Integrator(TensorField tensorField, float step)
11 | {
12 | _tensorField = tensorField;
13 | _step = step;
14 | }
15 |
16 | private Vector2 SampleFieldVector(Vector2 point, bool major)
17 | {
18 | var tensor = _tensorField.GetPoint(point);
19 |
20 | return major ? tensor.Major : tensor.Minor;
21 | }
22 |
23 | public Vector2 Integrate(Vector2 point, bool major)
24 | {
25 | var k1 = SampleFieldVector(point, major);
26 | var k23 = SampleFieldVector(point + new Vector2(_step / 2f, _step / 2f), major);
27 | var k4 = SampleFieldVector(point + new Vector2(_step, _step), major);
28 |
29 | return (k1 + 4 * k23 + k4) * (_step / 6f);
30 | }
31 | }
--------------------------------------------------------------------------------
/Scripts/DataStructure/Intersection.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using Godot;
3 |
4 | namespace ProceduralCityGenerator.Scripts.DataStructure;
5 |
6 | public struct Intersection
7 | {
8 | public Vector2 point;
9 | public HashSet neighbours;
10 | public List segments;
11 | }
--------------------------------------------------------------------------------
/Scripts/DataStructure/PolygonGenerator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using Godot;
5 | using NetTopologySuite;
6 | using NetTopologySuite.Geometries;
7 |
8 | namespace ProceduralCityGenerator.Scripts.DataStructure;
9 |
10 | public static class PolygonGenerator
11 | {
12 | private const int MaxLength = 20;
13 | private static readonly GeometryFactory Gf = NtsGeometryServices.Instance.CreateGeometryFactory();
14 |
15 | public static List> GeneratePolygons(List intersections)
16 | {
17 | var polygons = new List>();
18 |
19 | foreach (var p in intersections)
20 | if (p.neighbours.Count >= 2)
21 | foreach (var nextPoint in p.neighbours.ToList())
22 | {
23 | var polygon = GetPolygons(new List { p, nextPoint });
24 |
25 | if (polygon is { Count: < MaxLength })
26 | {
27 | RemovePolygonAdjacency(polygon);
28 | polygons.Add(polygon);
29 | polygon.Add(polygon[0]);
30 | }
31 | }
32 |
33 | return polygons;
34 | }
35 |
36 | private static void RemovePolygonAdjacency(IReadOnlyList polygon)
37 | {
38 | for (var i = 0; i < polygon.Count; i++)
39 | {
40 | var current = polygon[i];
41 | var next = polygon[(i + 1) % polygon.Count];
42 |
43 | if (current.neighbours.Contains(next)) current.neighbours.Remove(next);
44 | }
45 | }
46 |
47 | private static List GetPolygons(List visited, int count = 0)
48 | {
49 | List output = null;
50 | var continueLoop = true;
51 | while (continueLoop)
52 | if (count >= MaxLength)
53 | {
54 | continueLoop = false;
55 | }
56 | else
57 | {
58 | var nextIntersection = GetRightMostIntersection(visited[^2], visited[^1]);
59 | if (!nextIntersection.HasValue)
60 | {
61 | continueLoop = false;
62 | }
63 | else
64 | {
65 | var visitedIndex = visited.IndexOf(nextIntersection.Value);
66 | if (visitedIndex >= 0)
67 | {
68 | output = visited.GetRange(visitedIndex, visited.Count - visitedIndex);
69 | continueLoop = false;
70 | }
71 | else
72 | {
73 | visited.Add(nextIntersection.Value);
74 | count++;
75 | }
76 | }
77 | }
78 |
79 | return output;
80 | }
81 |
82 | private static Intersection? GetRightMostIntersection(Intersection intersectionFrom, Intersection intersectionTo)
83 | {
84 | if (intersectionTo.neighbours.Count == 0) return null;
85 |
86 | var backwardsDifferenceVector = intersectionFrom.point - intersectionTo.point;
87 | var transformAngle = Mathf.Atan2(backwardsDifferenceVector.Y, backwardsDifferenceVector.X);
88 |
89 | Intersection? rightMostIntersection = null;
90 | var smallestTheta = Mathf.Tau;
91 |
92 | foreach (var nextIntersection in intersectionTo.neighbours)
93 | {
94 | if (nextIntersection.Equals(intersectionFrom))
95 | continue;
96 |
97 | var nextVector = nextIntersection.point - intersectionTo.point;
98 | var nextAngle = Mathf.Atan2(nextVector.Y, nextVector.X) - transformAngle;
99 |
100 | if (nextAngle < 0) nextAngle += Mathf.Tau;
101 |
102 | if (nextAngle < smallestTheta)
103 | {
104 | smallestTheta = nextAngle;
105 | rightMostIntersection = nextIntersection;
106 | }
107 | }
108 |
109 | return rightMostIntersection;
110 | }
111 |
112 | public static (List>, List>, List>, List) GeneratePlots(
113 | List> polygons)
114 | {
115 | var shrunkPolygons = new List>();
116 | var sidewalkPolygons = new List>();
117 | var sidewalkFloorPolygons = new List>();
118 | var centroidPolygon = new List();
119 |
120 | var random = new Random();
121 |
122 | foreach (var polygon in polygons)
123 | {
124 | if (random.Next(0, 1001) - 1 < 5) continue;
125 |
126 | if (polygon.Count <= 2) continue;
127 |
128 | var poly = Gf.CreatePolygon(
129 | Gf.CreateLinearRing(polygon.Select(x => new Coordinate(x.point.X, x.point.Y))
130 | .ToArray())
131 | );
132 |
133 | var plotBuilding = poly.Buffer(GD.RandRange(-0.4d, -0.8d));
134 |
135 |
136 | if (!plotBuilding.IsSimple || plotBuilding.Area < 1d || plotBuilding.Area > 100d) continue;
137 |
138 | var plotSidewalk = poly.Buffer(-0.25d);
139 | var plotSidewalkRounded = plotSidewalk.Buffer(-0.1d).Buffer(0.1d);
140 |
141 | shrunkPolygons.Add(
142 | plotBuilding.Coordinates.Select(c => new Vector2((float)c.X, (float)c.Y)).ToList()
143 | );
144 | sidewalkPolygons.Add(
145 | plotSidewalk.Coordinates.Select(c => new Vector2((float)c.X, (float)c.Y)).ToList()
146 | );
147 | sidewalkFloorPolygons.Add(
148 | plotSidewalkRounded.Coordinates.Select(c => new Vector2((float)c.X, (float)c.Y)).ToList()
149 | );
150 | centroidPolygon.Add(new Vector2((float)plotBuilding.Centroid.X, (float)plotBuilding.Centroid.Y));
151 | }
152 |
153 | return (shrunkPolygons, sidewalkPolygons, sidewalkFloorPolygons, centroidPolygon);
154 | }
155 | }
--------------------------------------------------------------------------------
/Scripts/DataStructure/Radial.cs:
--------------------------------------------------------------------------------
1 | using Godot;
2 |
3 | namespace ProceduralCityGenerator.Scripts.DataStructure;
4 |
5 | public class Radial : Field
6 | {
7 | public Radial(Vector2 center, float size, float decay) : base(center, size, decay)
8 | {
9 | }
10 |
11 | protected override Tensor GetTensor(Vector2 point)
12 | {
13 | var t = point - center;
14 | var t1 = Mathf.Pow(t.Y, 2) - Mathf.Pow(t.X, 2);
15 | var t2 = -2 * t.X * t.Y;
16 |
17 | return new Tensor(1, new[] { t1, t2 });
18 | }
19 | }
--------------------------------------------------------------------------------
/Scripts/DataStructure/Segment.cs:
--------------------------------------------------------------------------------
1 | namespace ProceduralCityGenerator.Scripts.DataStructure;
2 |
3 | public struct Segment
4 | {
5 | public int indexA;
6 | public int indexB;
7 | public int indexStreamline;
8 | }
--------------------------------------------------------------------------------
/Scripts/DataStructure/StreamLineIntegration.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using Godot;
3 |
4 | namespace ProceduralCityGenerator.Scripts.DataStructure;
5 |
6 | public struct StreamLineIntegration
7 | {
8 | public Vector2 seed;
9 | public Vector2 originalDir;
10 | public List streamline;
11 | public Vector2 previousDirection;
12 | public Vector2 previousPoint;
13 | public bool valid;
14 | }
--------------------------------------------------------------------------------
/Scripts/DataStructure/StreamLines.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using Godot;
4 | using Simplify.NET;
5 |
6 | namespace ProceduralCityGenerator.Scripts.DataStructure;
7 |
8 | public class StreamLines
9 | {
10 | private readonly List> _allStreamlines = new();
11 |
12 | private readonly Integrator _integrator;
13 |
14 | private readonly GridStorage _major;
15 | private readonly GridStorage _minor;
16 | private readonly Vector2 _origin;
17 | private readonly StreamLinesParams _parameters;
18 | private readonly List> _streamlinesMajor = new();
19 | private readonly List> _streamlinesMinor = new();
20 | private readonly Vector2 _worldDimensions;
21 | private StreamLinesParams _parametersSq;
22 | public List> allStreamlinesSimple = new();
23 |
24 | public StreamLines(Integrator integrator, Vector2 worldDimensions, Vector2 origin, StreamLinesParams parameters)
25 | {
26 | _integrator = integrator;
27 | _worldDimensions = worldDimensions;
28 | _origin = origin;
29 | _parameters = parameters;
30 |
31 | if (_parameters.step > _parameters.sep)
32 | GD.PrintErr("Distancia de la muestra de linea de flujo más grande que dsep");
33 |
34 | _parameters.test = Mathf.Min(_parameters.test, _parameters.sep);
35 |
36 | _major = new GridStorage(_worldDimensions, _origin, _parameters.sep);
37 | _minor = new GridStorage(_worldDimensions, _origin, _parameters.sep);
38 |
39 | SetParametersSq();
40 | }
41 |
42 | private void SetParametersSq()
43 | {
44 | _parametersSq = new StreamLinesParams
45 | {
46 | sep = _parameters.sep * _parameters.sep,
47 | test = _parameters.test * _parameters.test,
48 | step = _parameters.step * _parameters.step,
49 | lookahead = _parameters.lookahead * _parameters.lookahead,
50 | circleJoin = _parameters.circleJoin * _parameters.circleJoin,
51 | joinAngle = _parameters.joinAngle * _parameters.joinAngle,
52 | pathIterations = _parameters.pathIterations * _parameters.pathIterations,
53 | seedTries = _parameters.seedTries * _parameters.seedTries,
54 | simplifyTolerance = _parameters.simplifyTolerance * _parameters.simplifyTolerance,
55 | colliderEarly = _parameters.colliderEarly * _parameters.colliderEarly
56 | };
57 | }
58 |
59 | public void AddExistingStreamlines(StreamLines streamLines)
60 | {
61 | _major.AddAll(streamLines._major);
62 | _minor.AddAll(streamLines._minor);
63 | }
64 |
65 | public void CreateAllStreamLines()
66 | {
67 | var major = true;
68 | while (CreateStreamLine(major)) major = !major;
69 |
70 | JoinDanglingStreamlines();
71 | }
72 |
73 | private Vector2? GetBestNextPoint(Vector2 point, Vector2 previousPoint)
74 | {
75 | var nearbyPoints = _major.GetNearbyPoints(point, _parameters.lookahead);
76 | nearbyPoints.AddRange(_minor.GetNearbyPoints(point, _parameters.lookahead));
77 | var direction = point - previousPoint;
78 |
79 | Vector2? closestSample = null;
80 | var closestDistance = float.PositiveInfinity;
81 |
82 | foreach (var sample in nearbyPoints)
83 | if (!sample.Equals(point) && !sample.Equals(previousPoint))
84 | {
85 | var differenceVector = sample - point;
86 | var dotDifferenceVector = differenceVector.Dot(direction);
87 | if (dotDifferenceVector < 0)
88 | continue;
89 |
90 | var distanceToSample = point.DistanceSquaredTo(sample);
91 | if (distanceToSample < closestDistance && distanceToSample < 2 * 0.01f * 0.01f)
92 | {
93 | closestDistance = distanceToSample;
94 | closestSample = sample;
95 | continue;
96 | }
97 |
98 | var angleBetween = MathF.Abs(direction.AngleTo(differenceVector));
99 |
100 | if (angleBetween < _parameters.joinAngle && distanceToSample < closestDistance)
101 | {
102 | closestDistance = distanceToSample;
103 | closestSample = sample;
104 | }
105 | }
106 |
107 | if (closestSample.HasValue) closestSample += direction.Normalized() * _parameters.simplifyTolerance * 4;
108 |
109 | return closestSample;
110 | }
111 |
112 | private void JoinDanglingStreamlines()
113 | {
114 | var dstep = 0.01f;
115 | foreach (var major in new[] { true, false })
116 | foreach (var streamline in Streamlines(major))
117 | {
118 | if (streamline[0].Equals(streamline[^1])) continue;
119 |
120 | var newStart = GetBestNextPoint(streamline[0], streamline[4]);
121 |
122 | if (newStart.HasValue)
123 | foreach (var p in PointsBetween(streamline[0], newStart.Value, dstep))
124 | {
125 | streamline.Insert(0, p);
126 | Grid(major).AddSample(p);
127 | }
128 |
129 | var newEnd = GetBestNextPoint(streamline[^1], streamline[^4]);
130 |
131 | if (newEnd.HasValue)
132 | foreach (var p in PointsBetween(streamline[^1], newEnd.Value, dstep))
133 | {
134 | streamline.Add(p);
135 | Grid(major).AddSample(p);
136 | }
137 | }
138 |
139 | allStreamlinesSimple = new List>();
140 | foreach (var s in _allStreamlines) allStreamlinesSimple.Add(SimplifyStreamline(s));
141 | }
142 |
143 | private List PointsBetween(Vector2 v1, Vector2 v2, float step)
144 | {
145 | var d = v1.DistanceTo(v2);
146 | var nPoints = Mathf.Floor(d / step);
147 |
148 | if (nPoints == 0) return new List();
149 |
150 | var stepVector = v2 - v1;
151 |
152 | var outVectors = new List();
153 |
154 | var i = 1;
155 | var next = v1 + stepVector * (i / nPoints);
156 |
157 | for (i = 1; i <= nPoints; i++)
158 | {
159 | if (_integrator.Integrate(next, true).LengthSquared() > 0.001f)
160 | outVectors.Add(next);
161 | else
162 | return outVectors;
163 |
164 | next = v1 + stepVector * (i / nPoints);
165 | }
166 |
167 | return outVectors;
168 | }
169 |
170 | private List> Streamlines(bool major)
171 | {
172 | return major ? _streamlinesMajor : _streamlinesMinor;
173 | }
174 |
175 | private GridStorage Grid(bool major)
176 | {
177 | return major ? _major : _minor;
178 | }
179 |
180 | private Vector2 SamplePoint()
181 | {
182 | return new Vector2(GD.Randf() * _worldDimensions.X, GD.Randf() * _worldDimensions.Y) + _origin;
183 | }
184 |
185 | private Vector2? GetSeed(bool major)
186 | {
187 | var seed = SamplePoint();
188 | var i = 0;
189 |
190 | while (!IsValidSample(major, seed, _parametersSq.sep))
191 | {
192 | if (i >= _parameters.seedTries) return null;
193 |
194 | seed = SamplePoint();
195 | i++;
196 | }
197 |
198 | return seed;
199 | }
200 |
201 | private bool IsValidSample(bool major, Vector2 point, float dSq, bool bothGrids = false)
202 | {
203 | var gridValid = Grid(major).IsValidSample(point, dSq);
204 |
205 | if (bothGrids) gridValid = gridValid && Grid(!major).IsValidSample(point, dSq);
206 |
207 | return gridValid;
208 | }
209 |
210 | private bool CreateStreamLine(bool major)
211 | {
212 | var seed = GetSeed(major);
213 | var isValid = false;
214 | if (seed.HasValue)
215 | {
216 | var streamline = _IntegrateStreamline(seed.Value, major);
217 | if (ValidStreamline(streamline))
218 | {
219 | Grid(major).AddPolyline(streamline);
220 | Streamlines(major).Add(streamline);
221 | _allStreamlines.Add(streamline);
222 | allStreamlinesSimple.Add(SimplifyStreamline(streamline));
223 | }
224 |
225 | isValid = true;
226 | }
227 |
228 | return isValid;
229 | }
230 |
231 | private List SimplifyStreamline(List streamline)
232 | {
233 | var simplified = new List();
234 |
235 | foreach (var point in SimplifyNet.Simplify(Vector2ToPoint(streamline), _parameters.simplifyTolerance))
236 | simplified.Add(new Vector2((float)point.X, (float)point.Y));
237 |
238 | return simplified;
239 | }
240 |
241 | private static List Vector2ToPoint(List vector)
242 | {
243 | var points = new List();
244 | foreach (var point in vector) points.Add(new Point(point.X, point.Y));
245 |
246 | return points;
247 | }
248 |
249 | private bool ValidStreamline(List streamline)
250 | {
251 | return streamline.Count > 5;
252 | }
253 |
254 | private List _IntegrateStreamline(Vector2 seed, bool major)
255 | {
256 | var count = 0;
257 | var pointsEscaped = false;
258 |
259 | var collideBoth = GD.Randf() < _parameters.colliderEarly;
260 |
261 | var d = _integrator.Integrate(seed, major);
262 |
263 | var forwardParameters = new StreamLineIntegration
264 | {
265 | seed = seed,
266 | originalDir = d,
267 | streamline = new List { seed },
268 | previousDirection = d,
269 | previousPoint = seed + d,
270 | valid = true
271 | };
272 |
273 | forwardParameters.valid = PointInBounds(forwardParameters.previousPoint);
274 |
275 | var negD = -d;
276 | var backwardParameters = new StreamLineIntegration
277 | {
278 | seed = seed,
279 | originalDir = negD,
280 | streamline = new List(),
281 | previousDirection = negD,
282 | previousPoint = seed + negD,
283 | valid = true
284 | };
285 |
286 | backwardParameters.valid = PointInBounds(backwardParameters.previousPoint);
287 |
288 | var finished = false;
289 | while (!finished && count < _parameters.pathIterations && (forwardParameters.valid || backwardParameters.valid))
290 | {
291 | StreamLineIntegrationStep(ref forwardParameters, major, collideBoth);
292 | StreamLineIntegrationStep(ref backwardParameters, major, collideBoth);
293 |
294 | var sqDistanceBetweenPoints =
295 | forwardParameters.previousPoint
296 | .DistanceSquaredTo(backwardParameters.previousPoint);
297 |
298 | if (!pointsEscaped && sqDistanceBetweenPoints > _parametersSq.circleJoin) pointsEscaped = true;
299 |
300 | if (pointsEscaped && sqDistanceBetweenPoints <= _parametersSq.circleJoin)
301 | {
302 | forwardParameters.streamline.Add(forwardParameters.previousPoint);
303 | forwardParameters.streamline.Add(backwardParameters.previousPoint);
304 | backwardParameters.streamline.Add(backwardParameters.previousPoint);
305 | finished = true;
306 | }
307 |
308 | count++;
309 | }
310 |
311 | backwardParameters.streamline.Reverse();
312 | backwardParameters.streamline.AddRange(forwardParameters.streamline);
313 | return backwardParameters.streamline;
314 | }
315 |
316 | private void StreamLineIntegrationStep(ref StreamLineIntegration parameters, bool major, bool collideBoth)
317 | {
318 | if (!parameters.valid) return;
319 |
320 | parameters.streamline.Add(parameters.previousPoint);
321 | var nextDirection = _integrator.Integrate(parameters.previousPoint, major);
322 |
323 | if (nextDirection.LengthSquared() < 0.01f)
324 | {
325 | parameters.valid = false;
326 | return;
327 | }
328 |
329 | if (nextDirection.Dot(parameters.previousDirection) < 0) nextDirection *= -1;
330 |
331 | var nextPoint = parameters.previousPoint + nextDirection;
332 |
333 | if (PointInBounds(nextPoint)
334 | && IsValidSample(major, nextPoint, _parametersSq.test, collideBoth)
335 | && !StreamlineTurned(parameters.seed, parameters.originalDir, nextPoint, nextDirection))
336 | {
337 | parameters.previousPoint = nextPoint;
338 | parameters.previousDirection = nextDirection;
339 | }
340 | else
341 | {
342 | parameters.streamline.Add(nextPoint);
343 | parameters.valid = false;
344 | }
345 | }
346 |
347 | private static bool StreamlineTurned(Vector2 seed, Vector2 originalDir, Vector2 point, Vector2 direction)
348 | {
349 | if (!(originalDir.Dot(direction) < 0))
350 | return false;
351 |
352 | var perpendicularVector = new Vector2(originalDir.Y, -originalDir.X);
353 | var isLeft = (point - seed).Dot(perpendicularVector) < 0;
354 | var directionUp = direction.Dot(perpendicularVector) > 0;
355 |
356 | return isLeft == directionUp;
357 | }
358 |
359 | private bool PointInBounds(Vector2 v)
360 | {
361 | return v.X >= _origin.X
362 | && v.Y >= _origin.Y
363 | && v.X < _worldDimensions.X + _origin.X
364 | && v.Y < _worldDimensions.Y + _origin.Y;
365 | }
366 | }
--------------------------------------------------------------------------------
/Scripts/DataStructure/StreamLinesParams.cs:
--------------------------------------------------------------------------------
1 | namespace ProceduralCityGenerator.Scripts.DataStructure;
2 |
3 | public struct StreamLinesParams
4 | {
5 | public StreamLinesParams SetSep(float sep)
6 | {
7 | this.sep = sep;
8 | return this;
9 | }
10 |
11 | public StreamLinesParams SetLookahead(float lookahead)
12 | {
13 | this.lookahead = lookahead;
14 | return this;
15 | }
16 |
17 | public static StreamLinesParams Default => new()
18 | {
19 | sep = 100f,
20 | test = 50f,
21 | step = 1,
22 | lookahead = 500,
23 | circleJoin = 5000,
24 | joinAngle = 0.1f,
25 | pathIterations = 500,
26 | seedTries = 300,
27 | simplifyTolerance = 0.0125f,
28 | colliderEarly = 0
29 | };
30 |
31 | public float sep;
32 | public float test;
33 | public float step;
34 | public float lookahead;
35 | public float circleJoin;
36 | public float joinAngle;
37 | public float pathIterations;
38 | public float seedTries;
39 | public float simplifyTolerance;
40 | public float colliderEarly;
41 | }
--------------------------------------------------------------------------------
/Scripts/DataStructure/Tensor.cs:
--------------------------------------------------------------------------------
1 | using Godot;
2 |
3 | namespace ProceduralCityGenerator.Scripts.DataStructure;
4 |
5 | public class Tensor
6 | {
7 | private readonly float[] _m;
8 | private float _theta;
9 | public bool oldth;
10 |
11 | public float r;
12 |
13 | public Tensor(float r, float[] m)
14 | {
15 | this.r = r;
16 | _m = m;
17 | oldth = false;
18 | Theta = CalculateTheta();
19 | }
20 |
21 | private float Theta
22 | {
23 | get
24 | {
25 | if (oldth)
26 | {
27 | _theta = CalculateTheta();
28 | oldth = false;
29 | }
30 |
31 | return _theta;
32 | }
33 | init => _theta = value;
34 | }
35 |
36 | public static Tensor Zero
37 | {
38 | get { return new Tensor(0, new float[] { 0, 0 }); }
39 | }
40 |
41 | public Vector2 Major
42 | {
43 | get
44 | {
45 | var vector = Vector2.Zero;
46 | if (r != 0) vector = new Vector2(Mathf.Cos(Theta), Mathf.Sin(Theta));
47 |
48 | return vector;
49 | }
50 | }
51 |
52 | public Vector2 Minor
53 | {
54 | get
55 | {
56 | var vector = Vector2.Zero;
57 | if (r != 0)
58 | {
59 | var angle = Theta + Mathf.Pi / 2;
60 | vector = new Vector2(Mathf.Cos(angle), Mathf.Sin(angle));
61 | }
62 |
63 | return vector;
64 | }
65 | }
66 |
67 | private float CalculateTheta()
68 | {
69 | var theta = 0.0f;
70 | if (r != 0) theta = Mathf.Atan2(_m[1] / r, _m[0] / r) / 2;
71 |
72 | return theta;
73 | }
74 |
75 | public void Add(Tensor tensor)
76 | {
77 | for (var i = 0; i < _m.Length; i++) _m[i] = _m[i] * r + tensor._m[i] * tensor.r;
78 |
79 | r = 2;
80 | oldth = true;
81 | }
82 | }
--------------------------------------------------------------------------------
/Scripts/DataStructure/TensorField.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using Godot;
3 |
4 | namespace ProceduralCityGenerator.Scripts.DataStructure;
5 |
6 | public class TensorField
7 | {
8 | private readonly float _diameter;
9 | public readonly List points;
10 |
11 | public TensorField(Vector2 worldDimensions, Vector2 origin)
12 | {
13 | _diameter = 0.1f;
14 | var n = new Vector2(Mathf.Ceil(worldDimensions.X / _diameter) + 1,
15 | Mathf.Ceil(worldDimensions.Y / _diameter) + 1);
16 |
17 | Fields = new List();
18 |
19 | // Puntos en la rejilla
20 | points = new List();
21 | for (var i = 1; i < n.X - 1; i++)
22 | for (var j = 1; j < n.Y - 1; j++)
23 | points.Add(new Vector2(origin.X + i * _diameter * 2, origin.Y + j * _diameter * 2));
24 | }
25 |
26 | public List Fields { get; }
27 |
28 | public Tensor GetPoint(Vector2 p)
29 | {
30 | if (Fields.Count == 0) return new Tensor(1, new float[] { 0, 0 });
31 |
32 | var tensorAcc = Tensor.Zero;
33 |
34 | foreach (var f in Fields) tensorAcc.Add(f.GetWeightedTensor(p));
35 |
36 | return tensorAcc;
37 | }
38 |
39 | public List GetTensorLine(Vector2 point, Vector2 tensor)
40 | {
41 | var diff = tensor * _diameter;
42 | var start = point - diff;
43 | var end = point + diff;
44 |
45 | return new List { start, end };
46 | }
47 |
48 | public void AddRadial(Vector2 center, float size, float decay)
49 | {
50 | AddField(new Radial(center, size, decay));
51 | }
52 |
53 | public void AddGrid(Vector2 center, float size, float decay, float theta)
54 | {
55 | AddField(new Grid(center, size, decay, theta));
56 | }
57 |
58 | private void AddField(Field field)
59 | {
60 | Fields.Add(field);
61 | }
62 | }
--------------------------------------------------------------------------------
/Scripts/GUI/GuiController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Globalization;
3 | using Godot;
4 |
5 | namespace ProceduralCityGenerator.Scripts.GUI;
6 |
7 | public partial class GuiController : Control
8 | {
9 | private bool _angleEdit;
10 | private bool _decayEdit;
11 |
12 | [Export] private MainScript _mainScript;
13 | private bool _sizeEdit;
14 | [Export] public Button addAllRoads;
15 | [Export] public Button addFieldButton;
16 |
17 | [Export] public Button addMainRoads;
18 | [Export] public Button addMajorRoads;
19 | [Export] public Button addMinorRoads;
20 | [Export] public VBoxContainer angleEditContainer;
21 | [Export] public Button generateBuildings;
22 | [Export] public Button generateCity;
23 | [Export] public Button hideMenuButton;
24 |
25 | [Export] public VBoxContainer listTensorPointsContainer;
26 |
27 | [Export] public PanelContainer mainMenuPanel;
28 | [Export] public Button regenerateBuildings;
29 | [Export] public Button regenerateTrees;
30 | [Export] public Button saveModelButton;
31 | [Export] public Button selectGridButton;
32 |
33 | [Export] public Button selectRadialButton;
34 | public bool showMenu;
35 |
36 | [Export] public Button showMenuButton;
37 | [Export] public HSlider sliderAngle;
38 | [Export] public HSlider sliderDecay;
39 | [Export] public HSlider sliderSize;
40 |
41 | [Export] public TabBar tabBar;
42 | [Export] public VBoxContainer tabContainer1;
43 | [Export] public VBoxContainer tabContainer2;
44 | [Export] public PackedScene tensorPointPrefab;
45 | [Export] public VBoxContainer tensorPropertiesContainer;
46 | [Export] public LineEdit textEditAngle;
47 | [Export] public LineEdit textEditDecay;
48 | [Export] public LineEdit textEditSize;
49 |
50 | public override void _Ready()
51 | {
52 | regenerateTrees.Pressed += () => _mainScript.GenerateTrees();
53 |
54 | regenerateBuildings.Pressed += async () =>
55 | {
56 | _mainScript.GenerateBuildings3D();
57 |
58 | await ToSignal(GetTree(), "process_frame");
59 | _mainScript.GenerateTrees();
60 | };
61 |
62 | generateCity.Pressed += async () =>
63 | {
64 | _mainScript.GenerateBuildings3D();
65 | _mainScript.GenerateRoads3D();
66 |
67 | await ToSignal(GetTree(), "process_frame");
68 | _mainScript.GenerateTrees();
69 | };
70 |
71 | generateBuildings.Pressed += () =>
72 | {
73 | _mainScript.GenerateIntersections();
74 | _mainScript.GeneratePolygons();
75 | };
76 |
77 | textEditDecay.TextChanged += text =>
78 | {
79 | try
80 | {
81 | sliderDecay.Value = float.Parse(text);
82 | }
83 | catch (FormatException)
84 | {
85 | // ignored
86 | }
87 | };
88 | sliderDecay.DragEnded += _ => { _decayEdit = false; };
89 | sliderDecay.DragStarted += () => { _decayEdit = true; };
90 |
91 | textEditAngle.TextChanged += text =>
92 | {
93 | try
94 | {
95 | sliderAngle.Value = float.Parse(text);
96 | }
97 | catch (FormatException)
98 | {
99 | // ignored
100 | }
101 | };
102 | sliderAngle.DragEnded += _ => { _angleEdit = false; };
103 | sliderAngle.DragStarted += () => { _angleEdit = true; };
104 |
105 | textEditSize.TextChanged += text =>
106 | {
107 | try
108 | {
109 | sliderSize.Value = float.Parse(text);
110 | }
111 | catch (FormatException)
112 | {
113 | // ignored
114 | }
115 | };
116 | sliderSize.DragEnded += _ => { _sizeEdit = false; };
117 | sliderSize.DragStarted += () => { _sizeEdit = true; };
118 |
119 | tabBar.TabChanged += index =>
120 | {
121 | switch (index)
122 | {
123 | case 0:
124 | tabContainer1.Visible = true;
125 | tabContainer2.Visible = false;
126 | _mainScript.state = MainScript.DrawState.Roads;
127 | break;
128 | case 1:
129 | tabContainer1.Visible = false;
130 | tabContainer2.Visible = true;
131 | _mainScript.SetTensorFieldState();
132 | break;
133 | }
134 |
135 | MainScript.Redraw();
136 | };
137 |
138 | addAllRoads.Pressed += () =>
139 | {
140 | _mainScript.GenerateRoads(_mainScript.mainRoads);
141 | _mainScript.GenerateRoads(_mainScript.majorRoads);
142 | _mainScript.GenerateRoads(_mainScript.minorRoads);
143 | };
144 |
145 | addMainRoads.Pressed += () =>
146 | {
147 | if (_mainScript.majorRoads.Streamlines != null) _mainScript.majorRoads.Streamlines = null;
148 |
149 | if (_mainScript.minorRoads.Streamlines != null) _mainScript.minorRoads.Streamlines = null;
150 |
151 | _mainScript.GenerateRoads(_mainScript.mainRoads);
152 | };
153 |
154 | addMajorRoads.Pressed += () =>
155 | {
156 | if (_mainScript.minorRoads.Streamlines != null) _mainScript.minorRoads.Streamlines = null;
157 |
158 | _mainScript.GenerateRoads(_mainScript.majorRoads);
159 | };
160 |
161 | addMinorRoads.Pressed += () => { _mainScript.GenerateRoads(_mainScript.minorRoads); };
162 |
163 | addFieldButton.Pressed += () =>
164 | {
165 | var position = _mainScript.cameraController.centerScreen;
166 |
167 | if (selectGridButton.ButtonPressed)
168 | MainScript.tensorField.AddGrid(new Vector2(position.X, -position.Y), (float)sliderSize.Value,
169 | (float)sliderDecay.Value, Mathf.DegToRad((float)sliderAngle.Value));
170 | else if (selectRadialButton.ButtonPressed)
171 | MainScript.tensorField.AddRadial(new Vector2(position.X, -position.Y), (float)sliderSize.Value,
172 | (float)sliderDecay.Value);
173 |
174 | var tensor = tensorPointPrefab.Instantiate();
175 | tensor.AddField(MainScript.tensorField.Fields[^1]);
176 | listTensorPointsContainer.AddChild(tensor);
177 |
178 | _mainScript.DrawReload();
179 | };
180 |
181 | selectGridButton.Pressed += () =>
182 | {
183 | selectRadialButton.ButtonPressed = false;
184 | angleEditContainer.Visible = true;
185 |
186 | tensorPropertiesContainer.Visible = selectGridButton.ButtonPressed;
187 | };
188 |
189 | selectRadialButton.Pressed += () =>
190 | {
191 | selectGridButton.ButtonPressed = false;
192 | angleEditContainer.Visible = false;
193 |
194 | tensorPropertiesContainer.Visible = selectRadialButton.ButtonPressed;
195 | };
196 |
197 | hideMenuButton.Pressed += HideMenu;
198 |
199 | showMenuButton.Pressed += ShowMenu;
200 |
201 | saveModelButton.Pressed += () =>
202 | {
203 | var gl = new GltfDocument();
204 | var state = new GltfState();
205 | var fileDialog = new FileDialog();
206 | fileDialog.Access = FileDialog.AccessEnum.Filesystem;
207 | fileDialog.InitialPosition = Window.WindowInitialPosition.CenterMainWindowScreen;
208 | fileDialog.Size = new Vector2I(930, 440);
209 | fileDialog.AddFilter("*.gltf");
210 | GetNode("/root/Root/GUI").AddChild(fileDialog);
211 | fileDialog.Visible = true;
212 |
213 | fileDialog.FileSelected += path =>
214 | {
215 | gl.AppendFromScene(GetTree().CurrentScene, state);
216 |
217 | var err = gl.WriteToFilesystem(state, path);
218 |
219 | if (err == Error.Failed) GD.PrintErr("Ha ocurrido un error");
220 | };
221 | };
222 | }
223 |
224 | public async void ShowMenu()
225 | {
226 | if (showMenu) return;
227 |
228 | showMenu = true;
229 |
230 | showMenuButton.Visible = false;
231 |
232 | var tween = GetTree().CreateTween();
233 | tween.SetTrans(Tween.TransitionType.Expo);
234 | tween.SetEase(Tween.EaseType.Out);
235 |
236 | mainMenuPanel.Visible = true;
237 | tween.TweenProperty(mainMenuPanel, "position", -mainMenuPanel.Position, 0.5f).AsRelative();
238 | await ToSignal(tween, Tween.SignalName.Finished);
239 | }
240 |
241 | public async void HideMenu()
242 | {
243 | if (!showMenu) return;
244 |
245 | var tween = GetTree().CreateTween();
246 | tween.SetTrans(Tween.TransitionType.Expo);
247 | tween.SetEase(Tween.EaseType.Out);
248 |
249 | tween.TweenProperty(mainMenuPanel, "position", new Vector2(-mainMenuPanel.Size.X, mainMenuPanel.Position.Y),
250 | 0.5f).AsRelative();
251 | showMenuButton.Visible = true;
252 | await ToSignal(tween, Tween.SignalName.Finished);
253 | mainMenuPanel.Visible = false;
254 | showMenu = false;
255 | }
256 |
257 | public override void _Process(double delta)
258 | {
259 | if (_sizeEdit) textEditSize.Text = sliderSize.Value.ToString(CultureInfo.InvariantCulture);
260 |
261 | if (_angleEdit) textEditAngle.Text = sliderAngle.Value.ToString(CultureInfo.InvariantCulture);
262 |
263 | if (_decayEdit) textEditDecay.Text = sliderDecay.Value.ToString(CultureInfo.InvariantCulture);
264 | }
265 | }
--------------------------------------------------------------------------------
/Scripts/GUI/PropertiesPointsEdit.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Globalization;
3 | using Godot;
4 | using ProceduralCityGenerator.Scripts.DataStructure;
5 |
6 | namespace ProceduralCityGenerator.Scripts.GUI;
7 |
8 | public partial class PropertiesPointsEdit : VBoxContainer
9 | {
10 | private bool _angleEdit;
11 | private bool _decayEdit;
12 |
13 | private Field _field;
14 | [Export] private StyleBoxFlat _selectedStyle;
15 | private bool _sizeEdit;
16 | [Export] private StyleBoxFlat _unselectedStyle;
17 | [Export] public VBoxContainer angleEditContainer;
18 | [Export] public Button pointButton;
19 | [Export] public Button removeButton;
20 | [Export] public HSlider sliderAngle;
21 | [Export] public HSlider sliderDecay;
22 | [Export] public HSlider sliderSize;
23 | [Export] public VBoxContainer tensorPropertiesContainer;
24 | [Export] public LineEdit textEditAngle;
25 | [Export] public LineEdit textEditDecay;
26 | [Export] public LineEdit textEditSize;
27 |
28 | public override void _Ready()
29 | {
30 | removeButton.Pressed += () =>
31 | {
32 | MainScript.tensorField.Fields.Remove(_field);
33 | MainScript.Redraw();
34 | QueueFree();
35 | };
36 |
37 | pointButton.Pressed += () =>
38 | {
39 | tensorPropertiesContainer.Visible = !tensorPropertiesContainer.Visible;
40 | removeButton.Visible = !removeButton.Visible;
41 | };
42 |
43 | textEditDecay.TextChanged += text =>
44 | {
45 | try
46 | {
47 | sliderDecay.Value = float.Parse(text);
48 | }
49 | catch (FormatException)
50 | {
51 | // ignored
52 | }
53 |
54 | if (_field != null)
55 | {
56 | _field.decay = (float)sliderDecay.Value;
57 | MainScript.Redraw();
58 | }
59 | };
60 | sliderDecay.DragEnded += _ => { _decayEdit = false; };
61 | sliderDecay.DragStarted += () => { _decayEdit = true; };
62 |
63 | textEditAngle.TextChanged += text =>
64 | {
65 | try
66 | {
67 | sliderAngle.Value = float.Parse(text);
68 | }
69 | catch (FormatException)
70 | {
71 | // ignored
72 | }
73 |
74 | if (_field is Grid grid)
75 | {
76 | grid.theta = (float)Mathf.DegToRad(sliderAngle.Value);
77 | MainScript.Redraw();
78 | }
79 | };
80 | sliderAngle.DragEnded += _ => { _angleEdit = false; };
81 | sliderAngle.DragStarted += () => { _angleEdit = true; };
82 |
83 | textEditSize.TextChanged += text =>
84 | {
85 | try
86 | {
87 | sliderSize.Value = float.Parse(text);
88 | }
89 | catch (FormatException)
90 | {
91 | // ignored
92 | }
93 |
94 | if (_field != null)
95 | {
96 | _field.size = (float)sliderSize.Value;
97 | MainScript.Redraw();
98 | }
99 | };
100 | sliderSize.DragEnded += _ => { _sizeEdit = false; };
101 | sliderSize.DragStarted += () => { _sizeEdit = true; };
102 | }
103 |
104 | public override void _Process(double delta)
105 | {
106 | if (_sizeEdit)
107 | {
108 | textEditSize.Text = sliderSize.Value.ToString(CultureInfo.InvariantCulture);
109 |
110 | if (_field != null)
111 | {
112 | _field.size = (float)sliderSize.Value;
113 | MainScript.Redraw();
114 | }
115 | }
116 |
117 | if (_angleEdit)
118 | {
119 | textEditAngle.Text = sliderAngle.Value.ToString(CultureInfo.InvariantCulture);
120 |
121 | if (_field is Grid grid)
122 | {
123 | grid.theta = (float)Mathf.DegToRad(sliderAngle.Value);
124 | MainScript.Redraw();
125 | }
126 | }
127 |
128 | if (_decayEdit)
129 | {
130 | textEditDecay.Text = sliderDecay.Value.ToString(CultureInfo.InvariantCulture);
131 |
132 | if (_field != null)
133 | {
134 | _field.decay = (float)sliderDecay.Value;
135 | MainScript.Redraw();
136 | }
137 | }
138 |
139 | if (_field != null && MainScript.selectedField != null && MainScript.selectedField.Equals(_field))
140 | {
141 | tensorPropertiesContainer.Visible = true;
142 | removeButton.Visible = true;
143 | pointButton.ButtonPressed = true;
144 |
145 | pointButton.Set("theme_override_styles/pressed", _selectedStyle);
146 | }
147 | else
148 | {
149 | pointButton.Set("theme_override_styles/pressed", _unselectedStyle);
150 | }
151 | }
152 |
153 | public void AddField(Field tensorField)
154 | {
155 | _field = tensorField;
156 | SetValuesInit();
157 | }
158 |
159 | private void SetValuesInit()
160 | {
161 | if (_field is Grid grid)
162 | {
163 | textEditAngle.Text = Mathf.RadToDeg(grid.theta).ToString(CultureInfo.InvariantCulture);
164 | sliderAngle.Value = Mathf.RadToDeg(grid.theta);
165 | pointButton.Text = "Grid point";
166 | }
167 | else
168 | {
169 | pointButton.Text = "Radial point";
170 | angleEditContainer.Visible = false;
171 | }
172 |
173 | textEditDecay.Text = _field.decay.ToString(CultureInfo.InvariantCulture);
174 | sliderDecay.Value = _field.decay;
175 | textEditSize.Text = _field.size.ToString(CultureInfo.InvariantCulture);
176 | sliderSize.Value = _field.size;
177 | }
178 | }
--------------------------------------------------------------------------------
/Scripts/LineDrawer3D.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using Godot;
3 | using ProceduralCityGenerator.Scripts.DataStructure;
4 |
5 | public partial class LineDrawer3D : MeshInstance3D, IPointDrawImmediate
6 | {
7 | private readonly List _points = new();
8 | private ImmediateMesh _mesh = new();
9 |
10 | public void AddLine(Vector3 p1, Vector3 p2, Color color)
11 | {
12 | _points.Add(new IPointDrawImmediate.Point { point = p1, color = color });
13 | _points.Add(new IPointDrawImmediate.Point { point = p2, color = color });
14 | }
15 |
16 | public void AddLine(Vector3 p1, Vector3 p2)
17 | {
18 | AddLine(p1, p2, Colors.Red);
19 | }
20 |
21 | public void AddLines(List line)
22 | {
23 | AddLines(line, Colors.Red);
24 | }
25 |
26 | public void AddLines(List line, Color color)
27 | {
28 | if (line.Count < 2) return;
29 |
30 | foreach (var point in line)
31 | _points.Add(new IPointDrawImmediate.Point { point = new Vector3(point.X, point.Y, 0), color = color });
32 | }
33 |
34 | public override void _Ready()
35 | {
36 | var m = new StandardMaterial3D();
37 | m.NoDepthTest = true;
38 | m.ShadingMode = BaseMaterial3D.ShadingModeEnum.Unshaded;
39 | m.VertexColorUseAsAlbedo = true;
40 | m.Transparency = BaseMaterial3D.TransparencyEnum.Alpha;
41 | MaterialOverride = m;
42 | }
43 |
44 | public void Clear()
45 | {
46 | _mesh.ClearSurfaces();
47 | _points.Clear();
48 | }
49 |
50 | public override void _Process(double delta)
51 | {
52 | if (_points.Count == 0) return;
53 |
54 | _mesh.ClearSurfaces();
55 | _mesh.SurfaceBegin(Mesh.PrimitiveType.Lines);
56 | foreach (var t in _points)
57 | {
58 | _mesh.SurfaceSetColor(t.color);
59 | _mesh.SurfaceAddVertex(t.point);
60 | }
61 |
62 | _mesh.SurfaceEnd();
63 |
64 | Mesh = _mesh;
65 | }
66 | }
--------------------------------------------------------------------------------
/Scripts/MainBuildings3D.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using Godot;
4 |
5 | namespace ProceduralCityGenerator.Scripts;
6 |
7 | public partial class MainBuildings3D : CsgPolygon3D
8 | {
9 | private MainBuildings3D()
10 | {
11 | }
12 |
13 | public MainBuildings3D(IEnumerable polygon, float height)
14 | {
15 | Mode = ModeEnum.Depth;
16 | Name = "Building";
17 | Polygon = polygon.Select(v => new Vector2(v.X, -v.Y)).ToArray();
18 | Scale = new Vector3(Scale.X, Scale.Y, height);
19 | }
20 |
21 | public static MainBuildings3D SetTop(MainBuildings3D building)
22 | {
23 | var top = new MainBuildings3D();
24 | top.Mode = ModeEnum.Depth;
25 | top.Polygon = building.Polygon.ToArray();
26 | top.Name = "Building Top";
27 | top.Scale = new Vector3(building.Scale.X, building.Scale.Y, 0.005f);
28 | top.Position = new Vector3(building.Position.X, building.Position.Y, -building.Scale.Z);
29 | top.Material = (Material)ResourceLoader.Load("res://Materials/BuildingRoofMaterial1.tres");
30 | return top;
31 | }
32 | }
--------------------------------------------------------------------------------
/Scripts/MainRoads3D.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using Godot;
3 |
4 | public partial class MainRoads3D : CsgPolygon3D
5 | {
6 | public override void _Ready()
7 | {
8 | const float width = 0.5f;
9 | const float height = 0.0125f;
10 | const float halfWidth = width * 0.5f;
11 | const float halfHeight = height * 0.5f;
12 | Polygon = new Vector2[]
13 | {
14 | new(-halfWidth, -halfHeight),
15 | new(-halfWidth, height - halfHeight),
16 | new(width - halfWidth, height - halfHeight),
17 | new(width - halfWidth, -halfHeight)
18 | };
19 | Mode = ModeEnum.Path;
20 | Name = "Road";
21 | Material = (Material)ResourceLoader.Load("res://Materials/RoadMaterial1.tres");
22 | PathIntervalType = PathIntervalTypeEnum.Subdivide;
23 | PathInterval = 0.1f;
24 | }
25 |
26 | public void AddPath(List points)
27 | {
28 | var path3d = new Path3D();
29 | path3d.Name = "Path";
30 | path3d.Curve = new Curve3D();
31 |
32 | foreach (var point in points) path3d.Curve.AddPoint(point);
33 |
34 | AddChild(path3d);
35 | PathNode = path3d.GetPath();
36 | }
37 | }
--------------------------------------------------------------------------------
/Scripts/MainScript.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using Advanced.Algorithms.Geometry;
5 | using Godot;
6 | using ProceduralCityGenerator.Scripts.DataStructure;
7 | using ProceduralCityGenerator.Scripts.GUI;
8 | using Environment = Godot.Environment;
9 | using Noise = SimplexNoise.Noise;
10 |
11 | namespace ProceduralCityGenerator.Scripts;
12 |
13 | public partial class MainScript : Node
14 | {
15 | public enum DrawState
16 | {
17 | TensorFields,
18 | Roads,
19 | Intersections,
20 | Polygons,
21 | Roads3D
22 | }
23 |
24 | public static TensorField tensorField;
25 |
26 | private static bool _redraw;
27 |
28 | public static Field selectedField;
29 | private readonly Vector2 _origin = Vector2.Zero;
30 |
31 | private readonly Vector2 _worldDimension = Vector2.One * 40;
32 | [Export] private Environment _cameraEnvironment;
33 | [Export] private Environment _defaultEnvironment;
34 |
35 | [Export] private GuiController _guiController;
36 |
37 | private List _intersections;
38 | private LineDrawer3D _line;
39 | private PointDrawer3D _point;
40 | private List> _polygons;
41 | private List _polygonsCentroid;
42 | private List> _polygonsShrunk;
43 | private List> _polygonsSidewalk;
44 | private List> _polygonsSidewalkRounded;
45 | private PointDrawer3D _tensorPoints;
46 |
47 | public CameraController cameraController;
48 |
49 | public Roads mainRoads;
50 | public Roads majorRoads;
51 | public Roads minorRoads;
52 |
53 | public DrawState state;
54 |
55 | public override void _Ready()
56 | {
57 | tensorField = new TensorField(_worldDimension * 0.5f, _origin);
58 | var integrator = new Integrator(tensorField, 1f);
59 |
60 | mainRoads = new Roads(StreamLinesParams.Default, integrator, _worldDimension, _origin);
61 | majorRoads = new Roads(StreamLinesParams.Default.SetSep(5f).SetLookahead(500f), integrator,
62 | _worldDimension,
63 | _origin);
64 | minorRoads = new Roads(StreamLinesParams.Default.SetSep(2.5f).SetLookahead(500f), integrator,
65 | _worldDimension,
66 | _origin);
67 |
68 | minorRoads.SetExistingStreamlines(new List { mainRoads, majorRoads });
69 | majorRoads.SetExistingStreamlines(new List { mainRoads });
70 | state = DrawState.TensorFields;
71 |
72 |
73 | cameraController = GetTree().Root.GetNode("Root").GetNode("Camera3D");
74 | _line = GetTree().Root.GetNode("Root").GetNode("Lines");
75 | _point = GetTree().Root.GetNode("Root").GetNode("Points");
76 | _tensorPoints = GetTree().Root.GetNode("Root").GetNode("TensorFieldPoints");
77 |
78 | DrawReload();
79 | }
80 |
81 | public override void _Input(InputEvent @event)
82 | {
83 | if (@event is InputEventKey inputEventKey)
84 | {
85 | // Ver las intersecciones y las uniones (DEBUG)
86 | if (inputEventKey.IsPressed() && inputEventKey.Keycode == Key.I && minorRoads.Streamlines != null &&
87 | majorRoads.Streamlines != null && mainRoads.Streamlines != null)
88 | GenerateIntersections(true);
89 |
90 | if (inputEventKey.IsPressed() && inputEventKey.Keycode == Key.Escape)
91 | {
92 | if (_guiController.showMenu)
93 | {
94 | _guiController.HideMenu();
95 | cameraController.mouseCapture = true;
96 | }
97 | else
98 | {
99 | _guiController.ShowMenu();
100 | cameraController.mouseCapture = false;
101 | }
102 | }
103 | }
104 |
105 |
106 | if (@event is InputEventMouseButton eventMouseButton)
107 | {
108 | var position = cameraController.ProjectPosition(eventMouseButton.Position, 0);
109 |
110 | if (eventMouseButton.Pressed && eventMouseButton.ButtonIndex == MouseButton.Left)
111 | {
112 | foreach (var field in tensorField.Fields)
113 | {
114 | var v1 = field.center;
115 | var v2 = new Vector2(position.X, -position.Z);
116 | const float width = 0.1f;
117 |
118 | if (v2.X >= v1.X - width && v2.X <= v1.X + width && v2.Y >= v1.Y - width && v2.Y <= v1.Y + width)
119 | {
120 | selectedField = field;
121 | break;
122 | }
123 |
124 | selectedField = null;
125 | }
126 |
127 | DrawReload();
128 | }
129 | }
130 |
131 | if (@event is InputEventMouseMotion eventMouseMotion)
132 | {
133 | var position = cameraController.ProjectPosition(eventMouseMotion.Position, 0);
134 |
135 | if (Input.IsActionPressed("mouseLeft") && selectedField != null)
136 | {
137 | selectedField.center = new Vector2(position.X, -position.Z);
138 | DrawReload();
139 | }
140 | }
141 | }
142 |
143 | public void GeneratePolygons(bool redraw = true)
144 | {
145 | state = DrawState.Polygons;
146 | while (true)
147 | {
148 | var polygonsGenerated = PolygonGenerator.GeneratePolygons(_intersections);
149 |
150 | if (polygonsGenerated.Count == 0) break;
151 |
152 | _polygons.AddRange(polygonsGenerated);
153 | }
154 |
155 | (_polygonsShrunk, _polygonsSidewalk, _polygonsSidewalkRounded, _polygonsCentroid) =
156 | PolygonGenerator.GeneratePlots(_polygons);
157 |
158 | if (redraw) DrawReload();
159 | }
160 |
161 | public void GenerateIntersections(bool redraw = false)
162 | {
163 | state = DrawState.Intersections;
164 |
165 | var allStreamlines = new List>();
166 |
167 | if (minorRoads.Streamlines != null) allStreamlines.AddRange(minorRoads.Streamlines.allStreamlinesSimple);
168 |
169 | if (mainRoads.Streamlines != null) allStreamlines.AddRange(mainRoads.Streamlines.allStreamlinesSimple);
170 |
171 | if (majorRoads.Streamlines != null) allStreamlines.AddRange(majorRoads.Streamlines.allStreamlinesSimple);
172 |
173 | _intersections = new List();
174 | _polygons = new List>();
175 |
176 | // Intersección entre todas las streamlines
177 | for (var m = 0; m < allStreamlines.Count - 1; m++)
178 | for (var i = 0; i < allStreamlines[m].Count - 1; i++)
179 | for (var j = i + 1; j < allStreamlines[m].Count; j++)
180 | {
181 | for (var k = m + 1; k < allStreamlines.Count; k++)
182 | for (var l = 0; l < allStreamlines[k].Count - 1; l++)
183 | {
184 | var line1 = new Line(
185 | new Point(
186 | _worldDimension.X + allStreamlines[m][i].X,
187 | _worldDimension.Y + allStreamlines[m][i].Y
188 | ), new Point(
189 | _worldDimension.X + allStreamlines[m][j].X,
190 | _worldDimension.Y + allStreamlines[m][j].Y)
191 | );
192 |
193 | var line2 = new Line(
194 | new Point(
195 | _worldDimension.X + allStreamlines[k][l].X,
196 | _worldDimension.Y + allStreamlines[k][l].Y
197 | ), new Point(
198 | _worldDimension.X + allStreamlines[k][l + 1].X,
199 | _worldDimension.Y + allStreamlines[k][l + 1].Y)
200 | );
201 |
202 | var actualIntersections = LineIntersection.Find(line1, line2);
203 | if (actualIntersections != null)
204 | _intersections.Add(new Intersection
205 | {
206 | point = new Vector2((float)actualIntersections.X,
207 | (float)actualIntersections.Y) -
208 | _worldDimension,
209 | neighbours = new HashSet(),
210 | segments = new List
211 | {
212 | new()
213 | {
214 | indexA = i,
215 | indexB = j,
216 | indexStreamline = m
217 | },
218 | new()
219 | {
220 | indexA = l,
221 | indexB = l + 1,
222 | indexStreamline = k
223 | }
224 | }
225 | });
226 | }
227 |
228 | i++;
229 | }
230 |
231 | for (var i = 0; i < allStreamlines.Count; i++)
232 | for (var j = 0; j < allStreamlines[i].Count - 2; j++)
233 | {
234 | var line1 = new Line(
235 | new Point(
236 | _worldDimension.X + allStreamlines[i][j].X,
237 | _worldDimension.Y + allStreamlines[i][j].Y
238 | ), new Point(
239 | _worldDimension.X + allStreamlines[i][j + 1].X,
240 | _worldDimension.Y + allStreamlines[i][j + 1].Y)
241 | );
242 |
243 | var line2 = new Line(
244 | new Point(
245 | _worldDimension.X + allStreamlines[i][j + 1].X,
246 | _worldDimension.Y + allStreamlines[i][j + 1].Y
247 | ), new Point(
248 | _worldDimension.X + allStreamlines[i][j + 2].X,
249 | _worldDimension.Y + allStreamlines[i][j + 2].Y)
250 | );
251 |
252 | var actualIntersections = LineIntersection.Find(line1, line2);
253 | if (actualIntersections != null)
254 | _intersections.Add(new Intersection
255 | {
256 | point = new Vector2((float)actualIntersections.X,
257 | (float)actualIntersections.Y) -
258 | _worldDimension,
259 | neighbours = new HashSet(),
260 | segments = new List
261 | {
262 | new()
263 | {
264 | indexA = j,
265 | indexB = j + 1,
266 | indexStreamline = i
267 | },
268 | new()
269 | {
270 | indexA = j + 1,
271 | indexB = j + 2,
272 | indexStreamline = i
273 | }
274 | }
275 | });
276 | }
277 |
278 | // Eliminar líneas que acaban sin ninguna intersección
279 | var usedStreamlines = new HashSet();
280 | foreach (var intersection in _intersections)
281 | foreach (var segment in intersection.segments)
282 | {
283 | var selectedStreamlineIndex = segment.indexStreamline;
284 | if (usedStreamlines.Contains(selectedStreamlineIndex)) continue;
285 | usedStreamlines.Add(selectedStreamlineIndex);
286 |
287 | // Buscar todos las intersecciones que se encuentren en esa streamline
288 | var selectedIntersectionsFromStreamline = new List();
289 | for (var i = 0; i < _intersections.Count; i++)
290 | for (var j = 0; j < _intersections[i].segments.Count; j++)
291 | if (_intersections[i].segments[j].indexStreamline == selectedStreamlineIndex)
292 | selectedIntersectionsFromStreamline.Add(_intersections[i]);
293 |
294 | // Si hay más de 2 intersecciones en esa streamline, buscar cuál es el la más cercana al primer
295 | // punto de la streamline y al último [0] y [^1]
296 | if (selectedIntersectionsFromStreamline.Count >= 2)
297 | {
298 | var distanceA = float.MaxValue;
299 | var distanceB = float.MaxValue;
300 |
301 | var indexPointA = -1;
302 | var indexPointB = -1;
303 |
304 | for (var i = 0; i < selectedIntersectionsFromStreamline.Count; i++)
305 | {
306 | var p = selectedIntersectionsFromStreamline[i].point;
307 |
308 | if (allStreamlines[selectedStreamlineIndex][0].DistanceSquaredTo(p) <= distanceA)
309 | {
310 | indexPointA = i;
311 | distanceA = allStreamlines[selectedStreamlineIndex][0].DistanceSquaredTo(p);
312 | }
313 |
314 | if (allStreamlines[selectedStreamlineIndex][^1].DistanceSquaredTo(p) <= distanceB)
315 | {
316 | indexPointB = i;
317 | distanceB = allStreamlines[selectedStreamlineIndex][^1].DistanceSquaredTo(p);
318 | }
319 | }
320 |
321 | if (indexPointA == indexPointB) continue;
322 | if (indexPointA != -1)
323 | allStreamlines[selectedStreamlineIndex][0] = new Vector2(
324 | selectedIntersectionsFromStreamline[indexPointA].point.X,
325 | selectedIntersectionsFromStreamline[indexPointA].point.Y);
326 |
327 | if (indexPointB != -1)
328 | allStreamlines[selectedStreamlineIndex][^1] = new Vector2(
329 | selectedIntersectionsFromStreamline[indexPointB].point.X,
330 | selectedIntersectionsFromStreamline[indexPointB].point.Y);
331 | }
332 | }
333 |
334 | // Añadir vecinos a cada intersección
335 | foreach (var intersection in _intersections)
336 | foreach (var segment in intersection.segments)
337 | {
338 | var selectedStreamlineIndex = segment.indexStreamline;
339 | var selectedIntersectionsFromStreamline = new List();
340 | for (var i = 0; i < _intersections.Count; i++)
341 | for (var j = 0; j < _intersections[i].segments.Count; j++)
342 | if (_intersections[i].segments[j].indexStreamline == selectedStreamlineIndex)
343 | selectedIntersectionsFromStreamline.Add(_intersections[i]);
344 | var streamlinesSegments = new Dictionary<(int, int), List>();
345 | for (var i = 0; i < selectedIntersectionsFromStreamline.Count; i++)
346 | foreach (var s in selectedIntersectionsFromStreamline[i].segments
347 | .Where(s => s.indexStreamline == selectedStreamlineIndex))
348 | if (streamlinesSegments.ContainsKey((s.indexA, s.indexB)))
349 | streamlinesSegments[(s.indexA, s.indexB)]
350 | .Add(selectedIntersectionsFromStreamline[i]);
351 | else
352 | streamlinesSegments.Add((s.indexA, s.indexB),
353 | new List { selectedIntersectionsFromStreamline[i] });
354 |
355 | foreach (var kv in streamlinesSegments)
356 | {
357 | var firstPoint = allStreamlines[selectedStreamlineIndex][kv.Key.Item1];
358 | streamlinesSegments[kv.Key] =
359 | kv.Value.OrderBy(item => item.point.DistanceSquaredTo(firstPoint)).ToList();
360 | }
361 |
362 | var sortedDict = streamlinesSegments.Keys.OrderBy(item => item.Item1).ToList();
363 |
364 | var finish = false;
365 | for (var i = 0; i < sortedDict.Count && !finish; i++)
366 | for (var j = 0; j < streamlinesSegments[sortedDict[i]].Count && !finish; j++)
367 | if (streamlinesSegments[sortedDict[i]][j].point == intersection.point)
368 | {
369 | if (j - 1 >= 0)
370 | intersection.neighbours.Add(streamlinesSegments[sortedDict[i]][j - 1]);
371 | else if (i - 1 >= 0) intersection.neighbours.Add(streamlinesSegments[sortedDict[i - 1]][^1]);
372 |
373 | if (j + 1 < streamlinesSegments[sortedDict[i]].Count)
374 | intersection.neighbours.Add(streamlinesSegments[sortedDict[i]][j + 1]);
375 | else if (i + 1 < sortedDict.Count)
376 | intersection.neighbours.Add(streamlinesSegments[sortedDict[i + 1]][0]);
377 | finish = true;
378 | }
379 | }
380 |
381 | foreach (var intersection in _intersections)
382 | foreach (var neighbour in intersection.neighbours)
383 | neighbour.neighbours.Add(intersection);
384 |
385 | if (redraw)
386 | DrawReload();
387 | }
388 |
389 | public void GenerateRoads(Roads roads, bool redraw = true)
390 | {
391 | roads.GenerateRoads();
392 | state = DrawState.Roads;
393 | if (redraw)
394 | DrawReload();
395 | }
396 |
397 | public void DrawReload()
398 | {
399 | _line.Clear();
400 | _point.Clear();
401 | _tensorPoints.Clear();
402 |
403 | switch (state)
404 | {
405 | case DrawState.TensorFields:
406 | foreach (var p in tensorField.points)
407 | {
408 | var tensor = tensorField.GetPoint(p);
409 | _line.AddLines(tensorField.GetTensorLine(p, tensor.Major));
410 | _line.AddLines(tensorField.GetTensorLine(p, tensor.Minor));
411 | }
412 |
413 | foreach (var field in tensorField.Fields)
414 | if (selectedField != null && selectedField.Equals(field))
415 | _tensorPoints.AddPoint(new Vector3(field.center.X, field.center.Y, 0), Colors.GreenYellow);
416 | else
417 | _tensorPoints.AddPoint(new Vector3(field.center.X, field.center.Y, 0), Colors.Yellow);
418 |
419 | break;
420 | case DrawState.Roads:
421 | // Orden de dibujado: MINOR -> MAJOR -> MAIN
422 | // Orden de creación: MAIN -> MAJOR -> MINOR
423 |
424 | minorRoads.DrawLineRoads(_line, Colors.Red);
425 | majorRoads.DrawLineRoads(_line, Colors.Green);
426 | mainRoads.DrawLineRoads(_line, Colors.Blue);
427 |
428 | break;
429 | case DrawState.Intersections:
430 | if (_intersections != null)
431 | foreach (var p in _intersections)
432 | {
433 | _point.AddPoint(new Vector3(p.point.X, p.point.Y, 0), Colors.Red);
434 |
435 | foreach (var neighbour in p.neighbours)
436 | {
437 | var vector1 = new Vector3(p.point.X, p.point.Y, 0);
438 | var vector2 = new Vector3(neighbour.point.X, neighbour.point.Y, 0);
439 | _line.AddLine(vector1, vector2, Colors.Black);
440 | }
441 | }
442 |
443 | break;
444 | case DrawState.Polygons:
445 | if (_intersections != null)
446 | foreach (var p in _intersections)
447 | _point.AddPoint(new Vector3(p.point.X, p.point.Y, 0));
448 |
449 | if (_polygonsShrunk != null)
450 | {
451 | minorRoads.DrawLineRoads(_line, Colors.Red);
452 | majorRoads.DrawLineRoads(_line, Colors.Green);
453 | mainRoads.DrawLineRoads(_line, Colors.Blue);
454 |
455 | foreach (var plist in _polygonsShrunk)
456 | for (var i = 0; i < plist.Count - 1; i++)
457 | {
458 | var vector1 = new Vector3(plist[i].X, plist[i].Y, 0);
459 | var vector2 = new Vector3(plist[i + 1].X, plist[i + 1].Y, 0);
460 |
461 | _line.AddLine(vector1, vector2, Colors.Chocolate);
462 | }
463 | }
464 |
465 | break;
466 | case DrawState.Roads3D:
467 | var floorNode = GetNode("/root/Root/Floor");
468 | if (!floorNode.IsVisibleInTree()) floorNode.Visible = true;
469 |
470 | break;
471 | }
472 | }
473 |
474 | public override void _Process(double delta)
475 | {
476 | if (!_redraw) return;
477 |
478 | DrawReload();
479 | _redraw = false;
480 | }
481 |
482 | public static void Redraw()
483 | {
484 | _redraw = true;
485 | }
486 |
487 | public void GenerateRoads3D()
488 | {
489 | var roadsNode = GetNode("/root/Root/RoadModel/Roads");
490 | foreach (var child in roadsNode.GetChildren()) child.Free();
491 |
492 | if (minorRoads.Streamlines != null)
493 | foreach (var plist in minorRoads.Streamlines.allStreamlinesSimple)
494 | {
495 | var roadPolygon = new MainRoads3D();
496 | roadsNode.AddChild(roadPolygon);
497 | roadPolygon.AddPath(plist
498 | .Select(p =>
499 | new Vector3(p.X - _worldDimension.X, 0, p.Y - _worldDimension.Y).Rotated(Vector3.Right,
500 | Mathf.Pi))
501 | .ToList());
502 | }
503 |
504 | if (majorRoads.Streamlines != null)
505 | foreach (var plist in majorRoads.Streamlines.allStreamlinesSimple)
506 | {
507 | var roadPolygon = new MainRoads3D();
508 | roadsNode.AddChild(roadPolygon);
509 | roadPolygon.AddPath(plist
510 | .Select(p =>
511 | new Vector3(p.X - _worldDimension.X, 0, p.Y - _worldDimension.Y).Rotated(Vector3.Right,
512 | Mathf.Pi))
513 | .ToList());
514 | }
515 |
516 | if (mainRoads.Streamlines != null)
517 | foreach (var plist in mainRoads.Streamlines.allStreamlinesSimple)
518 | {
519 | var roadPolygon = new MainRoads3D();
520 | roadsNode.AddChild(roadPolygon);
521 | roadPolygon.AddPath(plist
522 | .Select(p =>
523 | new Vector3(p.X - _worldDimension.X, 0, p.Y - _worldDimension.Y).Rotated(Vector3.Right,
524 | Mathf.Pi))
525 | .ToList());
526 | }
527 |
528 | ChangeCameraToPerspective();
529 | DrawReload();
530 | }
531 |
532 | private void ChangeCameraToPerspective()
533 | {
534 | state = DrawState.Roads3D;
535 | cameraController.Projection = Camera3D.ProjectionType.Perspective;
536 | cameraController.Environment = _cameraEnvironment;
537 | }
538 |
539 | public void GenerateBuildings3D()
540 | {
541 | var buildingsNode = GetNode("/root/Root/BuildingsModel/Buildings");
542 | var roadsNode = GetNode("/root/Root/BuildingsModel/RoadsBuildings");
543 | foreach (var child in buildingsNode.GetChildren()) child.Free();
544 | foreach (var child in roadsNode.GetChildren()) child.Free();
545 |
546 | Noise.Seed = GD.RandRange(0, 100000);
547 | var noiseValues = Noise.Calc2D((int)_worldDimension.X, (int)_worldDimension.Y, 0.01f);
548 |
549 | for (var i = 0; i < _polygonsShrunk.Count; i++)
550 | {
551 | var buildingsPolygon = new MainBuildings3D(_polygonsShrunk[i],
552 | noiseValues[(int)_polygonsCentroid[i].X, (int)_polygonsCentroid[i].Y] / 255 *
553 | (float)GD.RandRange(1f, 10f));
554 |
555 | var index = GD.RandRange(1, 11);
556 | buildingsPolygon.Material =
557 | (Material)ResourceLoader
558 | .Load($"res://Materials/BuildingMaterial{index}.tres");
559 |
560 | buildingsNode.AddChild(buildingsPolygon);
561 | buildingsNode.AddChild(MainBuildings3D.SetTop(buildingsPolygon));
562 | }
563 |
564 | foreach (var plist in _polygonsSidewalkRounded)
565 | {
566 | var sidewalkPolygon = new MainSidewalk3D(plist);
567 |
568 | buildingsNode.AddChild(sidewalkPolygon);
569 | }
570 |
571 | foreach (var plist in _polygonsSidewalk)
572 | {
573 | var sidewalkPolygon = MainSidewalk3D.Bottom(plist);
574 |
575 | roadsNode.AddChild(sidewalkPolygon);
576 | }
577 |
578 | ChangeCameraToPerspective();
579 | DrawReload();
580 | }
581 |
582 | public void GenerateTrees()
583 | {
584 | var raycasts = new List();
585 | foreach (var child in GetTree().Root.GetNode("Root/Trees").GetChildren()) child.Free();
586 |
587 | for (var i = 0; i < _worldDimension.X; i++)
588 | for (var j = 0; j < _worldDimension.Y; j++)
589 | {
590 | var raycast = new RayCast3D(new Vector3(i, 12, -j));
591 | GetTree().Root.AddChild(raycast);
592 | raycast.ForceRaycastUpdate();
593 | if (((Node)raycast.GetCollider()).Name.Equals("Floor")) raycasts.Add(raycast.GetCollisionPoint());
594 | raycast.Free();
595 | }
596 |
597 | var random = new Random();
598 | foreach (var raycast in raycasts)
599 | if (random.Next(0, 101) - 1 <= 30)
600 | {
601 | var tree = new Sprite3D();
602 | tree.Texture = (Texture2D)ResourceLoader.Load("res://Assets/Image_49.png");
603 | tree.Position = new Vector3(raycast.X, 0.635f, raycast.Z);
604 | tree.Scale = Vector3.One * 0.25f;
605 | tree.Shaded = true;
606 | tree.RotateY((float)GD.RandRange(0, Mathf.Tau));
607 | var tree2 = tree.Duplicate();
608 | ((Node3D)tree2).RotateY(Mathf.Pi * 0.5f);
609 | GetTree().Root.GetNode("Root/Trees").AddChild(tree);
610 | GetTree().Root.GetNode("Root/Trees").AddChild(tree2);
611 | }
612 | }
613 |
614 | public void SetTensorFieldState()
615 | {
616 | state = DrawState.TensorFields;
617 | cameraController.Projection = Camera3D.ProjectionType.Orthogonal;
618 |
619 | cameraController.Position = new Vector3(cameraController.Position.X, 10, cameraController.Position.Z);
620 | cameraController.RotationDegrees = new Vector3(-90, 0, 0);
621 |
622 | cameraController.Environment = _defaultEnvironment;
623 |
624 | var buildingsNode = GetNode("/root/Root/BuildingsModel/Buildings");
625 | foreach (var child in buildingsNode.GetChildren()) child.Free();
626 |
627 | var sidewalks = GetNode("/root/Root/BuildingsModel/RoadsBuildings");
628 | foreach (var child in sidewalks.GetChildren()) child.Free();
629 |
630 | var roadsNode = GetNode("/root/Root/RoadModel/Roads");
631 | foreach (var child in roadsNode.GetChildren()) child.Free();
632 |
633 | var treesNode = GetNode("/root/Root/Trees");
634 | foreach (var child in treesNode.GetChildren()) child.Free();
635 |
636 | DrawReload();
637 | var floorNode = GetNode("/root/Root/Floor");
638 | floorNode.Visible = false;
639 | }
640 | }
--------------------------------------------------------------------------------
/Scripts/MainSidewalk3D.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using Godot;
4 |
5 | namespace ProceduralCityGenerator.Scripts;
6 |
7 | public partial class MainSidewalk3D : CsgPolygon3D
8 | {
9 | public MainSidewalk3D(IEnumerable polygon)
10 | {
11 | Mode = ModeEnum.Depth;
12 | Name = "Sidewalk";
13 | Polygon = polygon.Select(v => new Vector2(v.X, -v.Y)).ToArray();
14 | Scale = new Vector3(Scale.X, Scale.Y, 0.015f);
15 | Material = (Material)ResourceLoader.Load("res://Materials/SidewalkMaterial1.tres");
16 | }
17 |
18 | public static MainSidewalk3D Bottom(List polygons)
19 | {
20 | var sidewalk = new MainSidewalk3D(polygons);
21 | sidewalk.Scale = new Vector3(sidewalk.Scale.X, sidewalk.Scale.Y, 0.005f);
22 | sidewalk.Material = (Material)ResourceLoader.Load("res://Materials/RoadMaterial1.tres");
23 | return sidewalk;
24 | }
25 | }
--------------------------------------------------------------------------------
/Scripts/PointDrawer3D.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using Godot;
3 | using ProceduralCityGenerator.Scripts.DataStructure;
4 |
5 | public partial class PointDrawer3D : MeshInstance3D, IPointDrawImmediate
6 | {
7 | private readonly List _points = new();
8 | private ImmediateMesh _mesh = new();
9 |
10 | public void AddPoint(Vector3 p)
11 | {
12 | AddPoint(p, Colors.Green);
13 | }
14 |
15 | public void AddPoint(Vector3 p, Color color)
16 | {
17 | _points.Add(new IPointDrawImmediate.Point
18 | {
19 | point = p,
20 | color = color
21 | });
22 | }
23 |
24 | public void Clear()
25 | {
26 | _mesh.ClearSurfaces();
27 | _points.Clear();
28 | }
29 |
30 | public override void _Ready()
31 | {
32 | var m = new StandardMaterial3D();
33 | m.NoDepthTest = true;
34 | m.ShadingMode = BaseMaterial3D.ShadingModeEnum.Unshaded;
35 | m.VertexColorUseAsAlbedo = true;
36 | m.Transparency = BaseMaterial3D.TransparencyEnum.Alpha;
37 | MaterialOverride = m;
38 | }
39 |
40 | public override void _Process(double delta)
41 | {
42 | if (_points.Count == 0) return;
43 |
44 | _mesh.ClearSurfaces();
45 | _mesh.SurfaceBegin(Mesh.PrimitiveType.Triangles);
46 |
47 | var width = 0.1f;
48 | foreach (var t in _points)
49 | {
50 | _mesh.SurfaceSetColor(t.color);
51 | _mesh.SurfaceAddVertex(t.point + new Vector3(-1 * width, 1 * width, 0));
52 | _mesh.SurfaceAddVertex(t.point + new Vector3(1 * width, -1 * width, 0));
53 | _mesh.SurfaceAddVertex(t.point + new Vector3(-1 * width, -1 * width, 0));
54 |
55 | _mesh.SurfaceAddVertex(t.point + new Vector3(-1 * width, 1 * width, 0));
56 | _mesh.SurfaceAddVertex(t.point + new Vector3(1 * width, 1 * width, 0));
57 | _mesh.SurfaceAddVertex(t.point + new Vector3(1 * width, -1 * width, 0));
58 | }
59 |
60 | _mesh.SurfaceEnd();
61 |
62 | Mesh = _mesh;
63 | }
64 | }
--------------------------------------------------------------------------------
/Scripts/RayCast3D.cs:
--------------------------------------------------------------------------------
1 | using Godot;
2 |
3 | namespace ProceduralCityGenerator.Scripts;
4 |
5 | public partial class RayCast3D : Godot.RayCast3D
6 | {
7 | public RayCast3D(Vector3 position)
8 | {
9 | Enabled = true;
10 | Position = position;
11 | CollideWithBodies = true;
12 | TargetPosition = new Vector3(0, -13, 0);
13 | }
14 | }
--------------------------------------------------------------------------------
/Scripts/Roads.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using Godot;
3 | using ProceduralCityGenerator.Scripts.DataStructure;
4 |
5 | namespace ProceduralCityGenerator.Scripts;
6 |
7 | public class Roads
8 | {
9 | private readonly Integrator _integrator;
10 | private readonly Vector2 _origin;
11 | private readonly Vector2 _worldDimension;
12 |
13 | private List _existingStreamlines;
14 |
15 | public Roads(StreamLinesParams streamLinesParams, Integrator integrator, Vector2 worldDimension, Vector2 origin)
16 | {
17 | StreamLinesParams = streamLinesParams;
18 | _integrator = integrator;
19 | _worldDimension = worldDimension;
20 | _origin = origin;
21 | _existingStreamlines = new List();
22 | }
23 |
24 | private StreamLinesParams StreamLinesParams { get; }
25 | public StreamLines Streamlines { get; set; }
26 |
27 | public void GenerateRoads()
28 | {
29 | Streamlines = new StreamLines(_integrator, _worldDimension, _origin, StreamLinesParams);
30 |
31 | foreach (var road in _existingStreamlines)
32 | if (road.Streamlines != null)
33 | Streamlines.AddExistingStreamlines(road.Streamlines);
34 |
35 | Streamlines.CreateAllStreamLines();
36 | }
37 |
38 | public void SetExistingStreamlines(List roadsList)
39 | {
40 | _existingStreamlines = roadsList;
41 | }
42 |
43 | public void DrawLineRoads(LineDrawer3D line, Color color)
44 | {
45 | if (Streamlines == null)
46 | return;
47 |
48 | foreach (var plist in Streamlines.allStreamlinesSimple)
49 | for (var i = 0; i < plist.Count - 1; i++)
50 | {
51 | var vector1 = new Vector3(plist[i].X, plist[i].Y, 0);
52 | var vector2 = new Vector3(plist[i + 1].X, plist[i + 1].Y, 0);
53 | line.AddLine(vector1, vector2, color);
54 | }
55 | }
56 | }
--------------------------------------------------------------------------------
/default_env.tres:
--------------------------------------------------------------------------------
1 | [gd_resource type="Environment" format=3 uid="uid://dknc6bkcyjc43"]
2 |
3 | [resource]
4 | background_mode = 1
5 |
--------------------------------------------------------------------------------
/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Carl0sCheca/Procedural-City-Generator-Godot/176277e88729c8fad332bb9432f70ba87ab45598/icon.png
--------------------------------------------------------------------------------
/icon.png.import:
--------------------------------------------------------------------------------
1 | [remap]
2 |
3 | importer="texture"
4 | type="CompressedTexture2D"
5 | uid="uid://cxiy2vv8psm85"
6 | path="res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.ctex"
7 | metadata={
8 | "vram_texture": false
9 | }
10 |
11 | [deps]
12 |
13 | source_file="res://icon.png"
14 | dest_files=["res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.ctex"]
15 |
16 | [params]
17 |
18 | compress/mode=0
19 | compress/high_quality=false
20 | compress/lossy_quality=0.7
21 | compress/hdr_compression=1
22 | compress/normal_map=0
23 | compress/channel_pack=0
24 | mipmaps/generate=false
25 | mipmaps/limit=-1
26 | roughness/mode=0
27 | roughness/src_normal=""
28 | process/fix_alpha_border=true
29 | process/premult_alpha=false
30 | process/normal_map_invert_y=false
31 | process/hdr_as_srgb=false
32 | process/hdr_clamp_exposure=false
33 | process/size_limit=0
34 | detect_3d/compress_to=1
35 |
--------------------------------------------------------------------------------
/project.godot:
--------------------------------------------------------------------------------
1 | ; Engine configuration file.
2 | ; It's best edited using the editor UI and not directly,
3 | ; since the parameters that go here are not all obvious.
4 | ;
5 | ; Format:
6 | ; [section] ; section goes between []
7 | ; param=value ; assign values to parameters
8 |
9 | config_version=5
10 |
11 | [application]
12 |
13 | config/name="ProceduralCityGenerator"
14 | run/main_scene="res://Scenes/Main.tscn"
15 | config/features=PackedStringArray("4.2", "C#")
16 | boot_splash/show_image=false
17 | config/icon="res://icon.png"
18 |
19 | [display]
20 |
21 | window/subwindows/embed_subwindows=false
22 |
23 | [dotnet]
24 |
25 | project/assembly_name="ProceduralCityGenerator"
26 |
27 | [gui]
28 |
29 | common/drop_mouse_on_gui_input_disabled=true
30 |
31 | [input]
32 |
33 | mouseMiddle={
34 | "deadzone": 0.5,
35 | "events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":3,"canceled":false,"pressed":false,"double_click":false,"script":null)
36 | ]
37 | }
38 | mouseLeft={
39 | "deadzone": 0.5,
40 | "events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":1,"canceled":false,"pressed":false,"double_click":false,"script":null)
41 | ]
42 | }
43 |
44 | [mono]
45 |
46 | project/assembly_name="ProceduralCityGenerator"
47 |
48 | [physics]
49 |
50 | common/enable_pause_aware_picking=true
51 |
52 | [rendering]
53 |
54 | environment/defaults/default_environment="res://default_env.tres"
55 |
--------------------------------------------------------------------------------