Real terrain: DEM elevation under every level
tools/fetch_dem.py pulls the open AWS terrarium elevation tiles for each level's bbox (derived from the OSM geometry itself -- the fetch bboxes were never recorded) and writes an f32 heightmap. The builder bilinear-samples it: roads/footpaths/crossings drape (subdivided to ~8 m so long OSM segments stop chording across curved ground), buildings lift rigidly to the lowest terrain under their footprint with a 2 m foundation skirt, trees/props/planters ride their own base heights, and the flat ground slab becomes a real terrain mesh. Bridges get an explicit deck profile (lerp between end heights plus a hump) instead of draping down into the river, the truss follows the deck, and the Bradfield Highway now genuinely flies over Kemp Place -- the game has an underpass. Kangaroo Point's cliffs are an actual 20 m drop, Edward Street climbs to 55 m at Spring Hill. Junction events bake spawn/convoy heights (osm_junction.py grew a pure-python DEM sampler); the game respects marker heights everywhere it used to hardcode ground=0. Bugs the terrain surfaced, all found by measurement: - Long road segments chorded across curved ground: the car visually sank to its windows mid-block. Fixed by subdividing draped ribbons. - The 9 m terrain grid aliases cliff edges and bulged metres ABOVE the finely draped roads: a car spawning there was inside the terrain sheet and got depenetrated through the floor into the void (y = -710). Fixed by giving roads real collision and carving the terrain grid down wherever a draped road sample lands (11k+ carve samples on Kangaroo Point alone). - The junction validator and tuner drove throttle-only, which cross-slope drift turned into 40-86 m misses; they now hold aim like a player would. - Edward x Elizabeth launched down a 17% grade, went airborne at the crest and wedged off-street: unwinnable geometry, not a bug. Swapped for Elizabeth x George on the flat lower CBD. All 9 junctions validate. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
30d5cfd846
commit
65da434678
@ -2,445 +2,535 @@
|
||||
{
|
||||
"name": "Alice x George",
|
||||
"spawn": {
|
||||
"dx": 0.766833198312044,
|
||||
"dz": -0.641846434878719,
|
||||
"x": -163.586282448655,
|
||||
"z": 162.065991994404
|
||||
"x": -163.58628244865508,
|
||||
"z": 162.06599199440433,
|
||||
"y": 14.0,
|
||||
"dx": 0.7668331983120437,
|
||||
"dz": -0.6418464348787193
|
||||
},
|
||||
"streams": [
|
||||
{
|
||||
"interval": 1.5,
|
||||
"pts": [
|
||||
[
|
||||
-71.6230075670676,
|
||||
85.0918821008208
|
||||
-71.62300756706763,
|
||||
85.0918821008208,
|
||||
15.68
|
||||
],
|
||||
[
|
||||
-72.1027981957511,
|
||||
85.4906175386659
|
||||
-72.10279819575109,
|
||||
85.49061753866586,
|
||||
15.69
|
||||
],
|
||||
[
|
||||
-82.5534519291224,
|
||||
94.8058802983977
|
||||
-82.55345192912239,
|
||||
94.80588029839768,
|
||||
16.5
|
||||
],
|
||||
[
|
||||
-104.449283255202,
|
||||
113.364728030556
|
||||
-104.44928325520195,
|
||||
113.36472803055571,
|
||||
16.93
|
||||
],
|
||||
[
|
||||
-114.552953384248,
|
||||
122.938157884478
|
||||
-114.55295338424757,
|
||||
122.93815788447793,
|
||||
16.38
|
||||
],
|
||||
[
|
||||
-118.635517096346,
|
||||
126.332146888185
|
||||
-118.63551709634598,
|
||||
126.33214688818488,
|
||||
16.11
|
||||
],
|
||||
[
|
||||
-124.179725942706,
|
||||
130.600603993254
|
||||
-124.17972594270637,
|
||||
130.60060399325408,
|
||||
15.66
|
||||
],
|
||||
[
|
||||
-132.412657846607,
|
||||
136.841371982625
|
||||
-132.4126578466066,
|
||||
136.84137198262476,
|
||||
15.15
|
||||
],
|
||||
[
|
||||
-135.426194974764,
|
||||
139.131158627196
|
||||
-135.42619497476394,
|
||||
139.13115862719584,
|
||||
15.05
|
||||
],
|
||||
[
|
||||
-137.017391502614,
|
||||
140.329922425279
|
||||
-137.0173915026139,
|
||||
140.32992242527928,
|
||||
15.02
|
||||
],
|
||||
[
|
||||
-142.2269104628,
|
||||
144.181294358731
|
||||
-142.22691046279974,
|
||||
144.18129435873087,
|
||||
14.99
|
||||
]
|
||||
],
|
||||
"speed": 12.0
|
||||
"speed": 12.0,
|
||||
"interval": 1.5
|
||||
},
|
||||
{
|
||||
"interval": 1.5,
|
||||
"pts": [
|
||||
[
|
||||
-75.361941989609,
|
||||
84.8229236525054
|
||||
84.82292365250544,
|
||||
16.0
|
||||
],
|
||||
[
|
||||
-80.9395388682742,
|
||||
78.6116377012041
|
||||
-80.93953886827424,
|
||||
78.61163770120406,
|
||||
16.61
|
||||
],
|
||||
[
|
||||
-82.5659998940916,
|
||||
76.7348960854059
|
||||
-82.56599989409156,
|
||||
76.7348960854059,
|
||||
16.75
|
||||
],
|
||||
[
|
||||
-115.405581435619,
|
||||
38.7415552213739
|
||||
-115.40558143561937,
|
||||
38.74155522137386,
|
||||
23.41
|
||||
]
|
||||
],
|
||||
"speed": 12.0
|
||||
"speed": 12.0,
|
||||
"interval": 1.5
|
||||
},
|
||||
{
|
||||
"interval": 1.8,
|
||||
"pts": [
|
||||
[
|
||||
-145.437080580831,
|
||||
139.83908204088
|
||||
-145.4370805808313,
|
||||
139.83908204087984,
|
||||
15.0
|
||||
],
|
||||
[
|
||||
-140.236730470549,
|
||||
135.994503574748
|
||||
-140.2367304705485,
|
||||
135.99450357474848,
|
||||
15.01
|
||||
],
|
||||
[
|
||||
-138.687188507682,
|
||||
134.826983772678
|
||||
-138.6871885076824,
|
||||
134.82698377267795,
|
||||
15.02
|
||||
],
|
||||
[
|
||||
-135.676038606364,
|
||||
132.539006817179
|
||||
-135.67603860636424,
|
||||
132.53900681717874,
|
||||
15.1
|
||||
],
|
||||
[
|
||||
-127.454661333638,
|
||||
126.307027606927
|
||||
-127.45466133363814,
|
||||
126.30702760692736,
|
||||
15.64
|
||||
],
|
||||
[
|
||||
-121.996408938187,
|
||||
122.105516312011
|
||||
-121.99640893818653,
|
||||
122.1055163120108,
|
||||
15.97
|
||||
],
|
||||
[
|
||||
-118.197496828121,
|
||||
118.953524515431
|
||||
-118.19749682812089,
|
||||
118.9535245154313,
|
||||
16.16
|
||||
],
|
||||
[
|
||||
-108.01476176314,
|
||||
109.309193169476
|
||||
-108.01476176313997,
|
||||
109.30919316947609,
|
||||
16.87
|
||||
],
|
||||
[
|
||||
-86.0785257896557,
|
||||
90.7151769019407
|
||||
-86.07852578965569,
|
||||
90.71517690194068,
|
||||
16.9
|
||||
],
|
||||
[
|
||||
-75.6896883110217,
|
||||
81.454007661433
|
||||
-75.68968831102165,
|
||||
81.45400766143295,
|
||||
16.16
|
||||
],
|
||||
[
|
||||
-75.0830599635874,
|
||||
80.9460362988959
|
||||
-75.08305996358739,
|
||||
80.94603629889595,
|
||||
16.14
|
||||
]
|
||||
],
|
||||
"speed": 11.0
|
||||
"speed": 11.0,
|
||||
"interval": 1.8
|
||||
},
|
||||
{
|
||||
"interval": 1.8,
|
||||
"pts": [
|
||||
[
|
||||
-111.320181741659,
|
||||
35.2103359785921
|
||||
-111.32018174165945,
|
||||
35.21033597859207,
|
||||
22.71
|
||||
],
|
||||
[
|
||||
-78.4807980853871,
|
||||
73.2034479147318
|
||||
-78.48079808538708,
|
||||
73.20344791473178,
|
||||
16.61
|
||||
],
|
||||
[
|
||||
-76.9072614072839,
|
||||
75.0198778988802
|
||||
75.01987789888024,
|
||||
16.48
|
||||
],
|
||||
[
|
||||
-71.344125541046,
|
||||
81.2149947472113
|
||||
-71.34412554104603,
|
||||
81.2149947472113,
|
||||
15.86
|
||||
]
|
||||
],
|
||||
"speed": 11.0
|
||||
"speed": 11.0,
|
||||
"interval": 1.8
|
||||
},
|
||||
{
|
||||
"interval": 1.5,
|
||||
"pts": [
|
||||
[
|
||||
-72.1166888351082,
|
||||
80.6186568827489
|
||||
-72.11668883510822,
|
||||
80.61865688274891,
|
||||
15.94
|
||||
],
|
||||
[
|
||||
-63.3155168708224,
|
||||
85.2319664647318
|
||||
-63.31551687082244,
|
||||
85.23196646473183,
|
||||
15.12
|
||||
],
|
||||
[
|
||||
-54.5517817587045,
|
||||
95.5382290534301
|
||||
-54.55178175870453,
|
||||
95.53822905343011,
|
||||
14.31
|
||||
],
|
||||
[
|
||||
-39.7832019492811,
|
||||
112.967845683357
|
||||
-39.78320194928109,
|
||||
112.96784568335697,
|
||||
16.67
|
||||
],
|
||||
[
|
||||
-38.2495347293041,
|
||||
114.641424782394
|
||||
-38.24953472930413,
|
||||
114.64142478239386,
|
||||
16.96
|
||||
],
|
||||
[
|
||||
-37.46679081946,
|
||||
115.770892092411
|
||||
-37.466790819459995,
|
||||
115.77089209241056,
|
||||
17.13
|
||||
],
|
||||
[
|
||||
-36.907545471025,
|
||||
116.868308404357
|
||||
-36.90754547102499,
|
||||
116.86830840435711,
|
||||
17.26
|
||||
],
|
||||
[
|
||||
-36.6415428486163,
|
||||
117.9601284403
|
||||
-36.64154284861633,
|
||||
117.96012844030032,
|
||||
17.36
|
||||
],
|
||||
[
|
||||
-36.5496258677079,
|
||||
118.928290187952
|
||||
-36.54962586770791,
|
||||
118.92829018795193,
|
||||
17.43
|
||||
],
|
||||
[
|
||||
-36.5838040309518,
|
||||
120.631630966954
|
||||
-36.58380403095183,
|
||||
120.63163096695364,
|
||||
17.52
|
||||
],
|
||||
[
|
||||
-36.7335166728013,
|
||||
121.773248002537
|
||||
-36.733516672801336,
|
||||
121.77324800253669,
|
||||
17.57
|
||||
],
|
||||
[
|
||||
-36.9496009730767,
|
||||
122.555067847412
|
||||
-36.949600973076684,
|
||||
122.55506784741175,
|
||||
17.58
|
||||
],
|
||||
[
|
||||
-37.3111869258717,
|
||||
123.404225782126
|
||||
-37.31118692587169,
|
||||
123.40422578212599,
|
||||
17.59
|
||||
],
|
||||
[
|
||||
-38.0206496416879,
|
||||
124.385542652475
|
||||
-38.02064964168787,
|
||||
124.38554265247478,
|
||||
17.56
|
||||
],
|
||||
[
|
||||
-39.4579334455589,
|
||||
125.801006946898
|
||||
-39.45793344555888,
|
||||
125.80100694689808,
|
||||
17.47
|
||||
],
|
||||
[
|
||||
-41.9601597793989,
|
||||
127.878176766196
|
||||
-41.96015977939887,
|
||||
127.8781767661959,
|
||||
17.33
|
||||
]
|
||||
],
|
||||
"speed": 12.0
|
||||
"speed": 12.0,
|
||||
"interval": 1.5
|
||||
},
|
||||
{
|
||||
"interval": 1.8,
|
||||
"pts": [
|
||||
[
|
||||
-45.4076787424784,
|
||||
123.721902834029
|
||||
-45.40767874247836,
|
||||
123.72190283402932,
|
||||
16.65
|
||||
],
|
||||
[
|
||||
-43.0308962305509,
|
||||
121.752064253174
|
||||
-43.03089623055088,
|
||||
121.75206425317394,
|
||||
16.81
|
||||
],
|
||||
[
|
||||
-41.9792929338678,
|
||||
120.712785747195
|
||||
120.7127857471952,
|
||||
16.87
|
||||
],
|
||||
[
|
||||
-41.9973981173857,
|
||||
120.721051417958
|
||||
-41.99739811738572,
|
||||
120.72105141795794,
|
||||
16.87
|
||||
],
|
||||
[
|
||||
-42.0626879873161,
|
||||
120.818306152528
|
||||
-42.06268798731611,
|
||||
120.81830615252781,
|
||||
16.87
|
||||
],
|
||||
[
|
||||
-42.0417354235454,
|
||||
120.781878397269
|
||||
-42.041735423545425,
|
||||
120.78187839726885,
|
||||
16.87
|
||||
],
|
||||
[
|
||||
-41.9741642668029,
|
||||
120.309115032842
|
||||
-41.974164266802894,
|
||||
120.30911503284231,
|
||||
16.85
|
||||
],
|
||||
[
|
||||
-41.9490832168424,
|
||||
119.004843012052
|
||||
-41.94908321684239,
|
||||
119.00484301205215,
|
||||
16.78
|
||||
],
|
||||
[
|
||||
-41.975684667957,
|
||||
118.800920359363
|
||||
-41.975684667956976,
|
||||
118.80092035936316,
|
||||
16.76
|
||||
],
|
||||
[
|
||||
-41.9467189152085,
|
||||
118.809115195214
|
||||
-41.94671891520851,
|
||||
118.80911519521383,
|
||||
16.77
|
||||
],
|
||||
[
|
||||
-42.0788310934576,
|
||||
118.579643507368
|
||||
118.57964350736775,
|
||||
16.74
|
||||
],
|
||||
[
|
||||
-42.3825061541171,
|
||||
118.116845217633
|
||||
-42.38250615411705,
|
||||
118.1168452176333,
|
||||
16.67
|
||||
],
|
||||
[
|
||||
-43.8908120639013,
|
||||
116.473204316403
|
||||
-43.89081206390128,
|
||||
116.47320431640294,
|
||||
16.4
|
||||
],
|
||||
[
|
||||
-58.6728283240367,
|
||||
99.0277813465423
|
||||
-58.67282832403665,
|
||||
99.02778134654227,
|
||||
14.55
|
||||
],
|
||||
[
|
||||
-66.8177230511832,
|
||||
89.3422647349603
|
||||
-66.81772305118318,
|
||||
89.3422647349603,
|
||||
15.08
|
||||
],
|
||||
[
|
||||
-74.5893786955468,
|
||||
85.4192615169678
|
||||
85.41926151696784,
|
||||
15.91
|
||||
]
|
||||
],
|
||||
"speed": 11.0
|
||||
"speed": 11.0,
|
||||
"interval": 1.8
|
||||
}
|
||||
],
|
||||
"targets": [
|
||||
26500,
|
||||
29000,
|
||||
46500
|
||||
15000,
|
||||
35000,
|
||||
60000
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Margaret x Edward",
|
||||
"spawn": {
|
||||
"dx": -0.742705793125526,
|
||||
"dz": 0.669617879732749,
|
||||
"x": 274.907915771107,
|
||||
"z": -373.121177827394
|
||||
"x": 274.9079157711072,
|
||||
"z": -373.12117782739404,
|
||||
"y": 13.91,
|
||||
"dx": -0.7427057931255263,
|
||||
"dz": 0.6696178797327494
|
||||
},
|
||||
"streams": [
|
||||
{
|
||||
"interval": 1.5,
|
||||
"pts": [
|
||||
[
|
||||
185.833815296718,
|
||||
-292.812645167915
|
||||
185.8338152967176,
|
||||
-292.8126451679154,
|
||||
14.05
|
||||
],
|
||||
[
|
||||
193.655933950983,
|
||||
-299.882511644341
|
||||
193.65593395098287,
|
||||
-299.88251164434115,
|
||||
14.74
|
||||
],
|
||||
[
|
||||
211.377868675405,
|
||||
-315.230725704805
|
||||
211.37786867540518,
|
||||
-315.2307257048046,
|
||||
15.6
|
||||
],
|
||||
[
|
||||
216.02310568687,
|
||||
-319.254598202675
|
||||
216.02310568686988,
|
||||
-319.25459820267537,
|
||||
16.29
|
||||
],
|
||||
[
|
||||
237.642996194709,
|
||||
-338.582293338578
|
||||
237.6429961947087,
|
||||
-338.58229333857753,
|
||||
18.91
|
||||
],
|
||||
[
|
||||
239.660997181915,
|
||||
-341.288346333546
|
||||
239.66099718191472,
|
||||
-341.2883463335457,
|
||||
19.31
|
||||
]
|
||||
],
|
||||
"speed": 12.0
|
||||
"speed": 12.0,
|
||||
"interval": 1.5
|
||||
},
|
||||
{
|
||||
"interval": 1.5,
|
||||
"pts": [
|
||||
[
|
||||
179.818121576327,
|
||||
-304.166235842252
|
||||
179.81812157632743,
|
||||
-304.16623584225226,
|
||||
14.19
|
||||
],
|
||||
[
|
||||
181.359839275663,
|
||||
-302.406992562087
|
||||
181.35983927566346,
|
||||
-302.4069925620872,
|
||||
14.27
|
||||
],
|
||||
[
|
||||
184.213303452985,
|
||||
-299.144813785439
|
||||
184.2133034529848,
|
||||
-299.1448137854387,
|
||||
14.28
|
||||
],
|
||||
[
|
||||
189.715557971244,
|
||||
-292.541650836584
|
||||
189.71555797124375,
|
||||
-292.5416508365839,
|
||||
14.26
|
||||
],
|
||||
[
|
||||
194.923453137675,
|
||||
-286.336679339567
|
||||
194.9234531376747,
|
||||
-286.3366793395667,
|
||||
14.2
|
||||
],
|
||||
[
|
||||
234.056756167219,
|
||||
-241.131525360219
|
||||
234.05675616721896,
|
||||
-241.1315253602194,
|
||||
16.15
|
||||
],
|
||||
[
|
||||
244.509931259631,
|
||||
-229.329340361402
|
||||
244.50993125963066,
|
||||
-229.32934036140196,
|
||||
14.64
|
||||
]
|
||||
],
|
||||
"speed": 12.0
|
||||
"speed": 12.0,
|
||||
"interval": 1.5
|
||||
},
|
||||
{
|
||||
"interval": 1.8,
|
||||
"pts": [
|
||||
[
|
||||
243.953470490227,
|
||||
-338.011965266358
|
||||
243.95347049022743,
|
||||
-338.01196526635846,
|
||||
16.8
|
||||
],
|
||||
[
|
||||
241.329499501326,
|
||||
-334.636448261753
|
||||
241.32949950132615,
|
||||
-334.63644826175323,
|
||||
16.37
|
||||
],
|
||||
[
|
||||
219.611149514375,
|
||||
-315.219013797425
|
||||
219.61114951437548,
|
||||
-315.21901379742513,
|
||||
15.39
|
||||
],
|
||||
[
|
||||
214.913183354807,
|
||||
-311.14886949499
|
||||
214.91318335480702,
|
||||
-311.1488694949895,
|
||||
15.27
|
||||
],
|
||||
[
|
||||
197.217859554354,
|
||||
-295.823855956056
|
||||
197.21785955435436,
|
||||
-295.8238559560563,
|
||||
14.84
|
||||
],
|
||||
[
|
||||
189.454804209519,
|
||||
-288.806594832065
|
||||
189.45480420951895,
|
||||
-288.8065948320647,
|
||||
14.03
|
||||
]
|
||||
],
|
||||
"speed": 11.0
|
||||
"speed": 11.0,
|
||||
"interval": 1.8
|
||||
},
|
||||
{
|
||||
"interval": 1.8,
|
||||
"pts": [
|
||||
[
|
||||
240.467498400426,
|
||||
-225.74901403845
|
||||
240.4674984004257,
|
||||
-225.74901403845038,
|
||||
13.81
|
||||
],
|
||||
[
|
||||
229.982416914263,
|
||||
-237.587550240129
|
||||
-237.5875502401286,
|
||||
14.69
|
||||
],
|
||||
[
|
||||
190.834294657849,
|
||||
-282.809813460791
|
||||
190.83429465784906,
|
||||
-282.80981346079136,
|
||||
13.75
|
||||
],
|
||||
[
|
||||
185.573061534993,
|
||||
-289.077589163396
|
||||
185.5730615349928,
|
||||
-289.07758916339617,
|
||||
13.81
|
||||
],
|
||||
[
|
||||
180.092607888122,
|
||||
-295.654847014577
|
||||
180.09260788812207,
|
||||
-295.6548470145767,
|
||||
13.73
|
||||
],
|
||||
[
|
||||
177.296693403105,
|
||||
-298.850189837967
|
||||
177.29669340310514,
|
||||
-298.8501898379666,
|
||||
13.58
|
||||
],
|
||||
[
|
||||
175.756931830544,
|
||||
-300.607199758038
|
||||
175.7569318305437,
|
||||
-300.6071997580377,
|
||||
13.51
|
||||
]
|
||||
],
|
||||
"speed": 11.0
|
||||
"speed": 11.0,
|
||||
"interval": 1.8
|
||||
}
|
||||
],
|
||||
"targets": [
|
||||
22500,
|
||||
25000,
|
||||
30000
|
||||
15000,
|
||||
35000,
|
||||
60000
|
||||
]
|
||||
}
|
||||
]
|
||||
Binary file not shown.
@ -3,7 +3,7 @@
|
||||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://dm4gmb5igf0n5"
|
||||
uid="uid://b3e8mqi8lqhx7"
|
||||
path="res://.godot/imported/level.glb-4aa597fe23a02438c7c91aac8329adb8.scn"
|
||||
|
||||
[deps]
|
||||
|
||||
@ -2,149 +2,174 @@
|
||||
{
|
||||
"name": "Cliffs Corner",
|
||||
"spawn": {
|
||||
"dx": 0.711628947630267,
|
||||
"dz": -0.702555507340622,
|
||||
"x": 21.7260085314512,
|
||||
"z": -89.9672382353956
|
||||
"x": 21.72600853145121,
|
||||
"z": -89.96723823539561,
|
||||
"y": 6.96,
|
||||
"dx": 0.7116289476302671,
|
||||
"dz": -0.7025555073406219
|
||||
},
|
||||
"streams": [
|
||||
{
|
||||
"interval": 1.5,
|
||||
"pts": [
|
||||
[
|
||||
63.9261938834286,
|
||||
-109.989375180132
|
||||
63.92619388342862,
|
||||
-109.98937518013152,
|
||||
17.17
|
||||
],
|
||||
[
|
||||
78.3750416498091,
|
||||
-148.834021380346
|
||||
-148.8340213803462,
|
||||
25.6
|
||||
]
|
||||
],
|
||||
"speed": 12.0
|
||||
"speed": 12.0,
|
||||
"interval": 1.5
|
||||
},
|
||||
{
|
||||
"interval": 1.5,
|
||||
"pts": [
|
||||
[
|
||||
106.136602457004,
|
||||
-179.682190508149
|
||||
106.13660245700423,
|
||||
-179.68219050814878,
|
||||
30.64
|
||||
],
|
||||
[
|
||||
105.148984701035,
|
||||
-213.871671308174
|
||||
105.14898470103478,
|
||||
-213.87167130817437,
|
||||
28.03
|
||||
]
|
||||
],
|
||||
"speed": 12.0
|
||||
"speed": 12.0,
|
||||
"interval": 1.5
|
||||
},
|
||||
{
|
||||
"interval": 1.8,
|
||||
"pts": [
|
||||
[
|
||||
83.4362514359038,
|
||||
-146.951428620045
|
||||
83.43625143590378,
|
||||
-146.95142862004474,
|
||||
26.11
|
||||
],
|
||||
[
|
||||
68.9874036695233,
|
||||
-108.10678241983
|
||||
68.98740366952329,
|
||||
-108.10678241983003,
|
||||
17.79
|
||||
]
|
||||
],
|
||||
"speed": 11.0
|
||||
"speed": 11.0,
|
||||
"interval": 1.8
|
||||
},
|
||||
{
|
||||
"interval": 1.8,
|
||||
"pts": [
|
||||
[
|
||||
110.546733134203,
|
||||
-214.027593892259
|
||||
110.54673313420321,
|
||||
-214.02759389225906,
|
||||
27.69
|
||||
],
|
||||
[
|
||||
111.534350890173,
|
||||
-179.838113092233
|
||||
111.53435089017266,
|
||||
-179.83811309223347,
|
||||
30.29
|
||||
]
|
||||
],
|
||||
"speed": 11.0
|
||||
"speed": 11.0,
|
||||
"interval": 1.8
|
||||
},
|
||||
{
|
||||
"interval": 1.5,
|
||||
"pts": [
|
||||
[
|
||||
110.037936896846,
|
||||
-168.495835638497
|
||||
110.03793689684629,
|
||||
-168.49583563849748,
|
||||
31.15
|
||||
],
|
||||
[
|
||||
105.077018158356,
|
||||
-166.641057207958
|
||||
105.07701815835642,
|
||||
-166.64105720795808,
|
||||
31.55
|
||||
],
|
||||
[
|
||||
102.766219089942,
|
||||
-165.688685229298
|
||||
102.76621908994164,
|
||||
-165.6886852292976,
|
||||
31.69
|
||||
],
|
||||
[
|
||||
100.056232383348,
|
||||
-163.762330372999
|
||||
100.0562323833477,
|
||||
-163.76233037299872,
|
||||
31.53
|
||||
],
|
||||
[
|
||||
96.9873892973125,
|
||||
-160.786566032783
|
||||
-160.78656603278262,
|
||||
31.04
|
||||
],
|
||||
[
|
||||
94.5049985015079,
|
||||
-158.034131644146
|
||||
94.50499850150788,
|
||||
-158.03413164414619,
|
||||
30.28
|
||||
],
|
||||
[
|
||||
91.4342291831665,
|
||||
-153.718055174129
|
||||
-153.71805517412884,
|
||||
29.08
|
||||
],
|
||||
[
|
||||
82.7084835068341,
|
||||
-145.882804882052
|
||||
82.70848350683406,
|
||||
-145.88280488205245,
|
||||
25.76
|
||||
]
|
||||
],
|
||||
"speed": 12.0
|
||||
"speed": 12.0,
|
||||
"interval": 1.5
|
||||
},
|
||||
{
|
||||
"interval": 1.8,
|
||||
"pts": [
|
||||
[
|
||||
79.1028095788788,
|
||||
-149.902645118338
|
||||
79.10280957887883,
|
||||
-149.90264511833848,
|
||||
25.94
|
||||
],
|
||||
[
|
||||
87.5616128524851,
|
||||
-157.481410426472
|
||||
87.56161285248508,
|
||||
-157.4814104264721,
|
||||
28.74
|
||||
],
|
||||
[
|
||||
90.2585312272088,
|
||||
-161.369924756482
|
||||
90.25853122720883,
|
||||
-161.369924756482,
|
||||
29.84
|
||||
],
|
||||
[
|
||||
93.1092763097095,
|
||||
-164.544256767181
|
||||
93.10927630970947,
|
||||
-164.5442567671812,
|
||||
30.49
|
||||
],
|
||||
[
|
||||
96.5784627653289,
|
||||
-167.893325227024
|
||||
96.57846276532892,
|
||||
-167.89332522702423,
|
||||
31.01
|
||||
],
|
||||
[
|
||||
100.07071556656,
|
||||
-170.367815571085
|
||||
100.07071556655998,
|
||||
-170.36781557108517,
|
||||
31.29
|
||||
],
|
||||
[
|
||||
103.112804730391,
|
||||
-171.671153192072
|
||||
103.11280473039093,
|
||||
-171.67115319207213,
|
||||
31.36
|
||||
],
|
||||
[
|
||||
108.146577680852,
|
||||
-173.553775961996
|
||||
108.14657768085227,
|
||||
-173.5537759619962,
|
||||
30.96
|
||||
]
|
||||
],
|
||||
"speed": 11.0
|
||||
"speed": 11.0,
|
||||
"interval": 1.8
|
||||
}
|
||||
],
|
||||
"targets": [
|
||||
4000,
|
||||
6500,
|
||||
10500
|
||||
15000,
|
||||
35000,
|
||||
60000
|
||||
]
|
||||
}
|
||||
]
|
||||
Binary file not shown.
@ -3,7 +3,7 @@
|
||||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://dik381ld32een"
|
||||
uid="uid://cr8nyyans2y6h"
|
||||
path="res://.godot/imported/level.glb-30461b4810ef38297351fb89cbe9aa18.scn"
|
||||
|
||||
[deps]
|
||||
|
||||
@ -2,397 +2,432 @@
|
||||
{
|
||||
"name": "Albert x Adelaide",
|
||||
"spawn": {
|
||||
"dx": -0.663386853147646,
|
||||
"dz": -0.748276608662107,
|
||||
"x": 20.6920527258856,
|
||||
"z": -24.7106522816088
|
||||
"x": 20.69205272588558,
|
||||
"z": -24.71065228160878,
|
||||
"y": 29.84,
|
||||
"dx": -0.6633868531476461,
|
||||
"dz": -0.7482766086621067
|
||||
},
|
||||
"streams": [
|
||||
{
|
||||
"interval": 1.5,
|
||||
"pts": [
|
||||
[
|
||||
-58.8461484663001,
|
||||
-114.424174209248
|
||||
-58.84614846630014,
|
||||
-114.42417420924829,
|
||||
11.97
|
||||
],
|
||||
[
|
||||
-53.880474905008,
|
||||
-108.391854739427
|
||||
-108.39185473942744,
|
||||
12.77
|
||||
],
|
||||
[
|
||||
-51.2405150349884,
|
||||
-105.525786544745
|
||||
-51.24051503498836,
|
||||
-105.52578654474546,
|
||||
14.25
|
||||
],
|
||||
[
|
||||
-20.3529842406907,
|
||||
-70.7696216351455
|
||||
-20.352984240690695,
|
||||
-70.76962163514554,
|
||||
23.48
|
||||
]
|
||||
],
|
||||
"speed": 12.0
|
||||
"speed": 12.0,
|
||||
"interval": 1.5
|
||||
},
|
||||
{
|
||||
"interval": 1.5,
|
||||
"pts": [
|
||||
[
|
||||
-86.703252503893,
|
||||
-94.0877138699484
|
||||
-86.70325250389301,
|
||||
-94.08771386994844,
|
||||
22.9
|
||||
],
|
||||
[
|
||||
-77.607019688744,
|
||||
-101.920941690901
|
||||
-77.60701968874399,
|
||||
-101.92094169090129,
|
||||
18.15
|
||||
],
|
||||
[
|
||||
-72.0652250322851,
|
||||
-106.9478629653
|
||||
-72.06522503228508,
|
||||
-106.94786296530025,
|
||||
14.98
|
||||
],
|
||||
[
|
||||
-68.7920906183039,
|
||||
-109.508381296246
|
||||
-68.79209061830386,
|
||||
-109.50838129624599,
|
||||
13.7
|
||||
],
|
||||
[
|
||||
-62.6926613135619,
|
||||
-114.753855415977
|
||||
-62.692661313561906,
|
||||
-114.75385541597699,
|
||||
12.25
|
||||
],
|
||||
[
|
||||
-56.4508191491618,
|
||||
-120.138498306347
|
||||
-56.45081914916183,
|
||||
-120.13849830634709,
|
||||
11.56
|
||||
],
|
||||
[
|
||||
-53.1441813532654,
|
||||
-122.980904904961
|
||||
-53.14418135326541,
|
||||
-122.9809049049611,
|
||||
11.66
|
||||
],
|
||||
[
|
||||
-38.7548693234,
|
||||
-135.567757774861
|
||||
-38.75486932340002,
|
||||
-135.5677577748611,
|
||||
14.48
|
||||
],
|
||||
[
|
||||
-8.13888016446398,
|
||||
-163.054303917178
|
||||
-8.138880164463979,
|
||||
-163.05430391717795,
|
||||
16.8
|
||||
],
|
||||
[
|
||||
7.53742621322278,
|
||||
-176.886292547868
|
||||
7.537426213222782,
|
||||
-176.88629254786764,
|
||||
19.45
|
||||
]
|
||||
],
|
||||
"speed": 12.0
|
||||
"speed": 12.0,
|
||||
"interval": 1.5
|
||||
},
|
||||
{
|
||||
"interval": 1.8,
|
||||
"pts": [
|
||||
[
|
||||
-24.3893890595013,
|
||||
-67.1825007647702
|
||||
-24.38938905950134,
|
||||
-67.18250076477023,
|
||||
24.51
|
||||
],
|
||||
[
|
||||
-55.2720133743741,
|
||||
-101.933152255045
|
||||
-55.272013374374126,
|
||||
-101.93315225504524,
|
||||
15.33
|
||||
],
|
||||
[
|
||||
-57.9853352512913,
|
||||
-104.883276460764
|
||||
-57.98533525129133,
|
||||
-104.88327646076375,
|
||||
14.17
|
||||
],
|
||||
[
|
||||
-63.0150881333189,
|
||||
-110.991982190617
|
||||
-63.01508813331892,
|
||||
-110.99198219061685,
|
||||
12.81
|
||||
]
|
||||
],
|
||||
"speed": 11.0
|
||||
"speed": 11.0,
|
||||
"interval": 1.8
|
||||
},
|
||||
{
|
||||
"interval": 1.8,
|
||||
"pts": [
|
||||
[
|
||||
11.1101677795621,
|
||||
-172.837154651951
|
||||
11.110167779562063,
|
||||
-172.83715465195058,
|
||||
20.06
|
||||
],
|
||||
[
|
||||
-4.54306405533622,
|
||||
-159.025643282508
|
||||
-4.543064055336218,
|
||||
-159.02564328250827,
|
||||
17.14
|
||||
],
|
||||
[
|
||||
-35.1638772092336,
|
||||
-131.534796625037
|
||||
-35.16387720923361,
|
||||
-131.5347966250365,
|
||||
14.59
|
||||
],
|
||||
[
|
||||
-49.5953698809185,
|
||||
-118.910777494948
|
||||
-49.59536988091847,
|
||||
-118.91077749494814,
|
||||
12.53
|
||||
],
|
||||
[
|
||||
-52.9260113021268,
|
||||
-116.047565693668
|
||||
-52.92601130212681,
|
||||
-116.04756569366813,
|
||||
12.11
|
||||
],
|
||||
[
|
||||
-59.1685752860572,
|
||||
-110.662300983888
|
||||
-59.168575286057155,
|
||||
-110.66230098388816,
|
||||
12.46
|
||||
],
|
||||
[
|
||||
-65.3362602521517,
|
||||
-105.359015503696
|
||||
-65.33626025215173,
|
||||
-105.35901550369637,
|
||||
14.71
|
||||
],
|
||||
[
|
||||
-68.5423745958537,
|
||||
-102.855244634386
|
||||
-102.85524463438601,
|
||||
15.97
|
||||
],
|
||||
[
|
||||
-74.0429581637501,
|
||||
-97.8641615087792
|
||||
-97.86416150877923,
|
||||
18.58
|
||||
],
|
||||
[
|
||||
-83.1794893924223,
|
||||
-89.9958813300908
|
||||
-83.17948939242227,
|
||||
-89.9958813300908,
|
||||
23.25
|
||||
]
|
||||
],
|
||||
"speed": 11.0
|
||||
"speed": 11.0,
|
||||
"interval": 1.8
|
||||
},
|
||||
{
|
||||
"interval": 1.5,
|
||||
"pts": [
|
||||
[
|
||||
-63.049013950748,
|
||||
-111.034041203303
|
||||
-63.049013950748005,
|
||||
-111.03404120330288,
|
||||
12.8
|
||||
],
|
||||
[
|
||||
-67.6731119774683,
|
||||
-116.885568358634
|
||||
-67.67311197746825,
|
||||
-116.88556835863362,
|
||||
12.36
|
||||
],
|
||||
[
|
||||
-69.3364043278144,
|
||||
-119.016515361795
|
||||
-69.33640432781439,
|
||||
-119.01651536179543,
|
||||
12.14
|
||||
],
|
||||
[
|
||||
-72.7496535402502,
|
||||
-122.556584617365
|
||||
-72.74965354025018,
|
||||
-122.55658461736515,
|
||||
11.98
|
||||
],
|
||||
[
|
||||
-98.2440886423925,
|
||||
-142.519976823492
|
||||
-98.24408864239251,
|
||||
-142.51997682349207,
|
||||
18.09
|
||||
],
|
||||
[
|
||||
-106.032628822328,
|
||||
-149.462816226915
|
||||
-106.03262882232805,
|
||||
-149.46281622691504,
|
||||
21.13
|
||||
],
|
||||
[
|
||||
-127.254841098403,
|
||||
-167.50831278782
|
||||
-127.2548410984026,
|
||||
-167.5083127878196,
|
||||
27.66
|
||||
]
|
||||
],
|
||||
"speed": 12.0
|
||||
"speed": 12.0,
|
||||
"interval": 1.5
|
||||
},
|
||||
{
|
||||
"interval": 1.8,
|
||||
"pts": [
|
||||
[
|
||||
-123.756786956036,
|
||||
-171.622145212345
|
||||
-123.7567869560363,
|
||||
-171.62214521234466,
|
||||
28.43
|
||||
],
|
||||
[
|
||||
-102.508313753821,
|
||||
-153.554173373131
|
||||
-102.50831375382124,
|
||||
-153.55417337313145,
|
||||
20.4
|
||||
],
|
||||
[
|
||||
-94.8493767077653,
|
||||
-146.719492376612
|
||||
-94.84937670776534,
|
||||
-146.71949237661244,
|
||||
17.28
|
||||
],
|
||||
[
|
||||
-69.3394816295263,
|
||||
-126.743555782696
|
||||
-126.74355578269574,
|
||||
11.23
|
||||
],
|
||||
[
|
||||
-65.3252993333639,
|
||||
-122.631904237628
|
||||
-65.32529933336386,
|
||||
-122.63190423762802,
|
||||
11.48
|
||||
],
|
||||
[
|
||||
-63.4329063916396,
|
||||
-120.229317241236
|
||||
-63.432906391639634,
|
||||
-120.22931724123647,
|
||||
11.7
|
||||
],
|
||||
[
|
||||
-58.8122226488711,
|
||||
-114.382115196562
|
||||
-58.81222264887106,
|
||||
-114.38211519656227,
|
||||
11.97
|
||||
]
|
||||
],
|
||||
"speed": 11.0
|
||||
"speed": 11.0,
|
||||
"interval": 1.8
|
||||
}
|
||||
],
|
||||
"targets": [
|
||||
23000,
|
||||
25500,
|
||||
29500
|
||||
15000,
|
||||
35000,
|
||||
60000
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Edward x Elizabeth",
|
||||
"name": "Elizabeth x George",
|
||||
"spawn": {
|
||||
"dx": 0.688388502507091,
|
||||
"dz": 0.725342174160613,
|
||||
"x": 171.921077302301,
|
||||
"z": -175.651225571771
|
||||
"x": -167.94554211176842,
|
||||
"z": 282.4630938016437,
|
||||
"y": 13.4,
|
||||
"dx": 0.7551073297079488,
|
||||
"dz": -0.6556011902226315
|
||||
},
|
||||
"streams": [
|
||||
{
|
||||
"interval": 1.5,
|
||||
"pts": [
|
||||
[
|
||||
228.742601685131,
|
||||
-123.809388411418
|
||||
-151.6480512074991,
|
||||
261.15863374688365,
|
||||
20.11
|
||||
],
|
||||
[
|
||||
250.487851794393,
|
||||
-101.124186911579
|
||||
-144.0595617023658,
|
||||
254.3334990786212,
|
||||
21.13
|
||||
],
|
||||
[
|
||||
253.191844757795,
|
||||
-98.1321613960494
|
||||
-143.3213169995492,
|
||||
253.69278253341383,
|
||||
21.21
|
||||
],
|
||||
[
|
||||
258.485283289911,
|
||||
-92.2834398309675
|
||||
-91.08224191170491,
|
||||
208.5453042937327,
|
||||
26.1
|
||||
],
|
||||
[
|
||||
-88.11035783744204,
|
||||
205.98090738044175,
|
||||
25.99
|
||||
],
|
||||
[
|
||||
-80.87164084704513,
|
||||
199.7122732897846,
|
||||
25.71
|
||||
]
|
||||
],
|
||||
"speed": 12.0
|
||||
"speed": 12.0,
|
||||
"interval": 1.5
|
||||
},
|
||||
{
|
||||
"interval": 1.5,
|
||||
"pts": [
|
||||
[
|
||||
184.819681990446,
|
||||
-31.5997398360326
|
||||
-118.25454597584726,
|
||||
162.31711832498388,
|
||||
27.58
|
||||
],
|
||||
[
|
||||
200.990172438104,
|
||||
-45.5669611828909
|
||||
],
|
||||
[
|
||||
206.298224766768,
|
||||
-50.115127103271
|
||||
],
|
||||
[
|
||||
208.012771617165,
|
||||
-51.5958506176373
|
||||
],
|
||||
[
|
||||
243.567491578602,
|
||||
-82.5547120764429
|
||||
],
|
||||
[
|
||||
246.131368490435,
|
||||
-84.8446372752634
|
||||
],
|
||||
[
|
||||
254.684705396329,
|
||||
-92.485245640523
|
||||
-141.88997628727992,
|
||||
134.01017432495556,
|
||||
28.01
|
||||
]
|
||||
],
|
||||
"speed": 12.0
|
||||
"speed": 12.0,
|
||||
"interval": 1.5
|
||||
},
|
||||
{
|
||||
"interval": 1.8,
|
||||
"pts": [
|
||||
[
|
||||
254.481581996358,
|
||||
-88.659853768515
|
||||
-77.33660099284295,
|
||||
203.79436751079447,
|
||||
25.77
|
||||
],
|
||||
[
|
||||
249.186979870745,
|
||||
-94.509861403438
|
||||
-84.57742467711269,
|
||||
210.06482501974904,
|
||||
26.02
|
||||
],
|
||||
[
|
||||
246.577198699258,
|
||||
-97.4003726882982
|
||||
-87.55143656981038,
|
||||
212.6310617067039,
|
||||
26.03
|
||||
],
|
||||
[
|
||||
224.844319166858,
|
||||
-120.07262598818
|
||||
-139.79024774732977,
|
||||
257.7783118670535,
|
||||
21.09
|
||||
],
|
||||
[
|
||||
-140.45452335644003,
|
||||
258.3539093219179,
|
||||
21.03
|
||||
],
|
||||
[
|
||||
-148.03695777611765,
|
||||
265.1736062536181,
|
||||
19.8
|
||||
]
|
||||
],
|
||||
"speed": 11.0
|
||||
"speed": 11.0,
|
||||
"interval": 1.8
|
||||
},
|
||||
{
|
||||
"interval": 1.8,
|
||||
"pts": [
|
||||
[
|
||||
258.282159889941,
|
||||
-88.4580479589594
|
||||
-137.74491839162505,
|
||||
130.5491780750776,
|
||||
27.82
|
||||
],
|
||||
[
|
||||
249.72869976276,
|
||||
-80.817329524774
|
||||
],
|
||||
[
|
||||
247.117079187487,
|
||||
-78.4852615230074
|
||||
],
|
||||
[
|
||||
211.558093240145,
|
||||
-47.5226829818001
|
||||
],
|
||||
[
|
||||
209.815723834205,
|
||||
-46.017908496633
|
||||
],
|
||||
[
|
||||
204.515981699117,
|
||||
-41.4768916168623
|
||||
],
|
||||
[
|
||||
188.349489765203,
|
||||
-27.5131205641572
|
||||
-114.10948808019242,
|
||||
158.85612207510593,
|
||||
26.89
|
||||
]
|
||||
],
|
||||
"speed": 11.0
|
||||
"speed": 11.0,
|
||||
"interval": 1.8
|
||||
},
|
||||
{
|
||||
"interval": 1.5,
|
||||
"pts": [
|
||||
[
|
||||
258.480541378725,
|
||||
-92.2886654287672
|
||||
-80.89109247754493,
|
||||
199.7292817019625,
|
||||
25.71
|
||||
],
|
||||
[
|
||||
262.27371225915,
|
||||
-88.1195420122156
|
||||
-74.7953733286614,
|
||||
194.34772839631796,
|
||||
25.24
|
||||
],
|
||||
[
|
||||
266.827379303769,
|
||||
-83.1100839184909
|
||||
],
|
||||
[
|
||||
270.873333747605,
|
||||
-78.6578477713867
|
||||
],
|
||||
[
|
||||
298.089289341555,
|
||||
-47.3042762934113
|
||||
-35.46218143888725,
|
||||
160.46495405823146,
|
||||
21.98
|
||||
]
|
||||
],
|
||||
"speed": 12.0
|
||||
"speed": 12.0,
|
||||
"interval": 1.5
|
||||
},
|
||||
{
|
||||
"interval": 1.5,
|
||||
"pts": [
|
||||
[
|
||||
254.709252094248,
|
||||
-92.5069068273425
|
||||
-81.10769187758535,
|
||||
203.56321084385132,
|
||||
25.83
|
||||
],
|
||||
[
|
||||
259.703037116882,
|
||||
-96.8600914480509
|
||||
-86.41612277054091,
|
||||
197.68669995304248,
|
||||
25.87
|
||||
],
|
||||
[
|
||||
263.665450959975,
|
||||
-100.3447248693
|
||||
-97.11136428582687,
|
||||
185.75737187487675,
|
||||
26.43
|
||||
],
|
||||
[
|
||||
288.615579063857,
|
||||
-122.117679372756
|
||||
-118.18679983484368,
|
||||
162.3951682081065,
|
||||
27.58
|
||||
]
|
||||
],
|
||||
"speed": 12.0
|
||||
"speed": 12.0,
|
||||
"interval": 1.5
|
||||
}
|
||||
],
|
||||
"targets": [
|
||||
22000,
|
||||
24500,
|
||||
28500
|
||||
15000,
|
||||
35000,
|
||||
60000
|
||||
]
|
||||
}
|
||||
]
|
||||
Binary file not shown.
@ -3,7 +3,7 @@
|
||||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://djsujf76tbo3k"
|
||||
uid="uid://do65sk46ogjid"
|
||||
path="res://.godot/imported/level.glb-f093d0a503a60c4e982eefdc88ad879e.scn"
|
||||
|
||||
[deps]
|
||||
|
||||
@ -2,345 +2,407 @@
|
||||
{
|
||||
"name": "Melbourne x Merivale",
|
||||
"spawn": {
|
||||
"dx": 0.852877329272599,
|
||||
"dz": -0.522111349438832,
|
||||
"x": -596.868944790812,
|
||||
"z": -210.352681833747
|
||||
"z": -210.35268183374677,
|
||||
"y": 8.98,
|
||||
"dx": 0.8528773292725991,
|
||||
"dz": -0.5221113494388324
|
||||
},
|
||||
"streams": [
|
||||
{
|
||||
"interval": 1.5,
|
||||
"pts": [
|
||||
[
|
||||
-522.243146999435,
|
||||
-263.291609906853
|
||||
-522.2431469994345,
|
||||
-263.2916099068527,
|
||||
7.69
|
||||
],
|
||||
[
|
||||
-513.298474365917,
|
||||
-268.564620105823
|
||||
-513.2984743659174,
|
||||
-268.5646201058227,
|
||||
7.44
|
||||
],
|
||||
[
|
||||
-505.766456184546,
|
||||
-272.847714331466
|
||||
-505.76645618454586,
|
||||
-272.8477143314658,
|
||||
6.89
|
||||
],
|
||||
[
|
||||
-497.908990415611,
|
||||
-277.262924417905
|
||||
-497.90899041561073,
|
||||
-277.2629244179048,
|
||||
6.23
|
||||
]
|
||||
],
|
||||
"speed": 12.0
|
||||
"speed": 12.0,
|
||||
"interval": 1.5
|
||||
},
|
||||
{
|
||||
"interval": 1.5,
|
||||
"pts": [
|
||||
[
|
||||
-518.331960424561,
|
||||
-316.208166257863
|
||||
-518.3319604245614,
|
||||
-316.20816625786284,
|
||||
9.74
|
||||
],
|
||||
[
|
||||
-502.539989208635,
|
||||
-289.117722143497
|
||||
-502.53998920863535,
|
||||
-289.11772214349674,
|
||||
7.36
|
||||
],
|
||||
[
|
||||
-501.031072012682,
|
||||
-286.533998911906
|
||||
-501.0310720126822,
|
||||
-286.5339989119062,
|
||||
7.03
|
||||
],
|
||||
[
|
||||
-499.307492099731,
|
||||
-283.769724904009
|
||||
-499.3074920997309,
|
||||
-283.76972490400925,
|
||||
6.7
|
||||
],
|
||||
[
|
||||
-498.930545303579,
|
||||
-283.241377841783
|
||||
-498.93054530357944,
|
||||
-283.2413778417831,
|
||||
6.63
|
||||
],
|
||||
[
|
||||
-494.345014474119,
|
||||
-276.414559193545
|
||||
-494.34501447411924,
|
||||
-276.414559193545,
|
||||
6.05
|
||||
]
|
||||
],
|
||||
"speed": 12.0
|
||||
"speed": 12.0,
|
||||
"interval": 1.5
|
||||
},
|
||||
{
|
||||
"interval": 1.8,
|
||||
"pts": [
|
||||
[
|
||||
-495.263684530077,
|
||||
-272.555233182069
|
||||
-495.26368453007734,
|
||||
-272.55523318206934,
|
||||
6.0
|
||||
],
|
||||
[
|
||||
-503.109412344477,
|
||||
-268.146638068316
|
||||
-503.1094123444767,
|
||||
-268.14663806831595,
|
||||
6.51
|
||||
],
|
||||
[
|
||||
-510.589252181608,
|
||||
-263.893419493984
|
||||
-510.58925218160783,
|
||||
-263.8934194939837,
|
||||
6.98
|
||||
],
|
||||
[
|
||||
-519.500789611495,
|
||||
-258.639784893289
|
||||
-519.5007896114952,
|
||||
-258.6397848932893,
|
||||
7.39
|
||||
]
|
||||
],
|
||||
"speed": 11.0
|
||||
"speed": 11.0,
|
||||
"interval": 1.8
|
||||
},
|
||||
{
|
||||
"interval": 1.8,
|
||||
"pts": [
|
||||
[
|
||||
-498.827660471569,
|
||||
-273.403598406429
|
||||
-498.82766047156883,
|
||||
-273.4035984064291,
|
||||
6.2
|
||||
],
|
||||
[
|
||||
-503.407264010886,
|
||||
-280.221611358154
|
||||
-503.4072640108861,
|
||||
-280.2216113581537,
|
||||
6.94
|
||||
],
|
||||
[
|
||||
-503.859919895901,
|
||||
-280.865348695483
|
||||
-503.85991989590116,
|
||||
-280.8653486954825,
|
||||
7.03
|
||||
],
|
||||
[
|
||||
-505.652275149097,
|
||||
-283.740348688276
|
||||
-505.6522751490968,
|
||||
-283.7403486882755,
|
||||
7.41
|
||||
],
|
||||
[
|
||||
-507.204986888727,
|
||||
-286.397833056652
|
||||
-507.20498688872703,
|
||||
-286.3978330566516,
|
||||
7.75
|
||||
],
|
||||
[
|
||||
-522.997174842978,
|
||||
-313.488648942198
|
||||
-313.4886489421985,
|
||||
10.11
|
||||
]
|
||||
],
|
||||
"speed": 11.0
|
||||
"speed": 11.0,
|
||||
"interval": 1.8
|
||||
},
|
||||
{
|
||||
"interval": 1.5,
|
||||
"pts": [
|
||||
[
|
||||
-497.709720982148,
|
||||
-277.364279299137
|
||||
-497.7097209821479,
|
||||
-277.3642792991366,
|
||||
6.22
|
||||
],
|
||||
[
|
||||
-489.265341389724,
|
||||
-281.217004706688
|
||||
-489.2653413897242,
|
||||
-281.21700470668776,
|
||||
6.15
|
||||
],
|
||||
[
|
||||
-470.163954224667,
|
||||
-292.974174195101
|
||||
-470.16395422466655,
|
||||
-292.9741741951012,
|
||||
5.43
|
||||
],
|
||||
[
|
||||
-453.397320014964,
|
||||
-303.36964984342
|
||||
-453.3973200149641,
|
||||
-303.3696498434199,
|
||||
6.15
|
||||
],
|
||||
[
|
||||
-438.717138348101,
|
||||
-313.023771847006
|
||||
-438.7171383481014,
|
||||
-313.0237718470059,
|
||||
8.99
|
||||
],
|
||||
[
|
||||
-428.175689682796,
|
||||
-319.695221818248
|
||||
-428.17568968279613,
|
||||
-319.6952218182481,
|
||||
11.09
|
||||
]
|
||||
],
|
||||
"speed": 12.0
|
||||
"speed": 12.0,
|
||||
"interval": 1.5
|
||||
},
|
||||
{
|
||||
"interval": 1.5,
|
||||
"pts": [
|
||||
[
|
||||
-490.912703075514,
|
||||
-271.24169070377
|
||||
-490.9127030755138,
|
||||
-271.2416907037699,
|
||||
6.0
|
||||
],
|
||||
[
|
||||
-487.079481353019,
|
||||
-265.232181447622
|
||||
-487.07948135301893,
|
||||
-265.2321814476218,
|
||||
6.0
|
||||
],
|
||||
[
|
||||
-460.796114039586,
|
||||
-221.705738945924
|
||||
-460.79611403958603,
|
||||
-221.7057389459239,
|
||||
6.26
|
||||
],
|
||||
[
|
||||
-449.787661487498,
|
||||
-203.621656847663
|
||||
-449.78766148749827,
|
||||
-203.62165684766288,
|
||||
6.74
|
||||
]
|
||||
],
|
||||
"speed": 12.0
|
||||
"speed": 12.0,
|
||||
"interval": 1.5
|
||||
}
|
||||
],
|
||||
"targets": [
|
||||
35500,
|
||||
38000,
|
||||
73000
|
||||
15000,
|
||||
35000,
|
||||
60000
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Grey x Glenelg",
|
||||
"spawn": {
|
||||
"dx": 0.5279471843098,
|
||||
"dz": 0.849277204792024,
|
||||
"x": -137.35790798426,
|
||||
"z": -96.075818860076
|
||||
"x": -137.3579079842604,
|
||||
"z": -96.07581886007603,
|
||||
"y": 13.36,
|
||||
"dx": 0.5279471843098005,
|
||||
"dz": 0.8492772047920241
|
||||
},
|
||||
"streams": [
|
||||
{
|
||||
"interval": 1.5,
|
||||
"pts": [
|
||||
[
|
||||
-66.8941396578206,
|
||||
18.0214549249385
|
||||
18.021454924938546,
|
||||
8.55
|
||||
],
|
||||
[
|
||||
-68.9372122719242,
|
||||
14.7292502722074
|
||||
-68.93721227192415,
|
||||
14.729250272207434,
|
||||
8.67
|
||||
],
|
||||
[
|
||||
-74.0341764510855,
|
||||
5.78813512164328
|
||||
-74.03417645108553,
|
||||
5.788135121643277,
|
||||
9.23
|
||||
],
|
||||
[
|
||||
-78.6658442785157,
|
||||
-1.69267819146961
|
||||
-78.66584427851572,
|
||||
-1.692678191469608,
|
||||
9.75
|
||||
],
|
||||
[
|
||||
-82.8206925318667,
|
||||
-8.34435236597675
|
||||
-82.82069253186671,
|
||||
-8.344352365976752,
|
||||
10.15
|
||||
]
|
||||
],
|
||||
"speed": 12.0
|
||||
"speed": 12.0,
|
||||
"interval": 1.5
|
||||
},
|
||||
{
|
||||
"interval": 1.5,
|
||||
"pts": [
|
||||
[
|
||||
-33.0502081552841,
|
||||
-14.7586201862311
|
||||
-33.05020815528413,
|
||||
-14.758620186231095,
|
||||
8.09
|
||||
],
|
||||
[
|
||||
-35.0675152831888,
|
||||
-14.5994094114893
|
||||
-35.06751528318885,
|
||||
-14.599409411489315,
|
||||
8.2
|
||||
],
|
||||
[
|
||||
-37.270016261863,
|
||||
-13.9961460505448
|
||||
-37.27001626186296,
|
||||
-13.996146050544787,
|
||||
8.29
|
||||
],
|
||||
[
|
||||
-43.3585248193085,
|
||||
-10.7606682738875
|
||||
-43.35852481930847,
|
||||
-10.760668273887504,
|
||||
8.5
|
||||
],
|
||||
[
|
||||
-53.6949181138706,
|
||||
-4.20452046261836
|
||||
-53.694918113870564,
|
||||
-4.204520462618362,
|
||||
8.68
|
||||
],
|
||||
[
|
||||
-56.3314625884028,
|
||||
-2.47024586902805
|
||||
-56.331462588402815,
|
||||
-2.4702458690280507,
|
||||
8.73
|
||||
],
|
||||
[
|
||||
-63.0911519484621,
|
||||
2.2185465904455
|
||||
-63.091151948462084,
|
||||
2.2185465904455017,
|
||||
8.85
|
||||
]
|
||||
],
|
||||
"speed": 12.0
|
||||
"speed": 12.0,
|
||||
"interval": 1.5
|
||||
},
|
||||
{
|
||||
"interval": 1.8,
|
||||
"pts": [
|
||||
[
|
||||
-78.2407420345622,
|
||||
-11.2051308338488
|
||||
-78.24074203456223,
|
||||
-11.205130833848836,
|
||||
10.32
|
||||
],
|
||||
[
|
||||
-74.079811043889,
|
||||
-4.54369540834144
|
||||
-74.07981104388904,
|
||||
-4.543695408341438,
|
||||
9.85
|
||||
],
|
||||
[
|
||||
-69.3883249482344,
|
||||
3.03567007854908
|
||||
-69.38832494823436,
|
||||
3.0356700785490762,
|
||||
9.17
|
||||
],
|
||||
[
|
||||
-64.2732751867703,
|
||||
12.0075429283282
|
||||
-64.27327518677029,
|
||||
12.007542928328153,
|
||||
8.41
|
||||
],
|
||||
[
|
||||
-62.3066015113759,
|
||||
15.1728598756354
|
||||
-62.30660151137585,
|
||||
15.172859875635417,
|
||||
8.28
|
||||
]
|
||||
],
|
||||
"speed": 11.0
|
||||
"speed": 11.0,
|
||||
"interval": 1.8
|
||||
},
|
||||
{
|
||||
"interval": 1.8,
|
||||
"pts": [
|
||||
[
|
||||
-66.1688465571084,
|
||||
-2.2185465904455
|
||||
-2.2185465904455017,
|
||||
9.29
|
||||
],
|
||||
[
|
||||
-59.3783588139033,
|
||||
-6.92854413081255
|
||||
-59.37835881390333,
|
||||
-6.9285441308125515,
|
||||
9.26
|
||||
],
|
||||
[
|
||||
-56.6027334256873,
|
||||
-8.75475233718959
|
||||
-56.602733425687326,
|
||||
-8.754752337189586,
|
||||
9.26
|
||||
],
|
||||
[
|
||||
-46.1200499391949,
|
||||
-15.4011401262142
|
||||
-46.12004993919494,
|
||||
-15.401140126214159,
|
||||
9.08
|
||||
],
|
||||
[
|
||||
-39.5077365181293,
|
||||
-18.9106763490265
|
||||
-39.50773651812935,
|
||||
-18.910676349026538,
|
||||
8.74
|
||||
],
|
||||
[
|
||||
-36.1005431869604,
|
||||
-19.8996785886188
|
||||
-19.899678588618844,
|
||||
8.57
|
||||
],
|
||||
[
|
||||
-33.5155306840827,
|
||||
-20.1385342138149
|
||||
-33.51553068408273,
|
||||
-20.138534213814854,
|
||||
8.43
|
||||
]
|
||||
],
|
||||
"speed": 11.0
|
||||
"speed": 11.0,
|
||||
"interval": 1.8
|
||||
},
|
||||
{
|
||||
"interval": 1.5,
|
||||
"pts": [
|
||||
[
|
||||
-62.4286691941866,
|
||||
-1.5633764655738
|
||||
-62.42866919418658,
|
||||
-1.5633764655737972,
|
||||
9.03
|
||||
],
|
||||
[
|
||||
-56.2253414936718,
|
||||
7.17631569340894
|
||||
-56.22534149367183,
|
||||
7.176315693408943,
|
||||
8.15
|
||||
],
|
||||
[
|
||||
-31.6082945749603,
|
||||
46.3990126063831
|
||||
-31.608294574960304,
|
||||
46.399012606383145,
|
||||
8.71
|
||||
]
|
||||
],
|
||||
"speed": 12.0
|
||||
"speed": 12.0,
|
||||
"interval": 1.5
|
||||
},
|
||||
{
|
||||
"interval": 1.5,
|
||||
"pts": [
|
||||
[
|
||||
-105.444153258371,
|
||||
17.2933813892185
|
||||
-105.44415325837058,
|
||||
17.29338138921854,
|
||||
9.0
|
||||
],
|
||||
[
|
||||
-124.855497585617,
|
||||
29.0280377160981
|
||||
-124.85549758561747,
|
||||
29.02803771609806,
|
||||
10.01
|
||||
],
|
||||
[
|
||||
-145.965198973204,
|
||||
41.6802343084808
|
||||
-145.9651989732041,
|
||||
41.680234308480806,
|
||||
12.4
|
||||
]
|
||||
],
|
||||
"speed": 12.0
|
||||
"speed": 12.0,
|
||||
"interval": 1.5
|
||||
}
|
||||
],
|
||||
"targets": [
|
||||
22500,
|
||||
25000,
|
||||
29000
|
||||
15000,
|
||||
35000,
|
||||
60000
|
||||
]
|
||||
}
|
||||
]
|
||||
Binary file not shown.
@ -3,7 +3,7 @@
|
||||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://dw52qeb8csi30"
|
||||
uid="uid://dxm6gf8nrgrl1"
|
||||
path="res://.godot/imported/level.glb-17af9cdeb05fd15a816097b7ae0fb96c.scn"
|
||||
|
||||
[deps]
|
||||
|
||||
@ -2,185 +2,219 @@
|
||||
{
|
||||
"name": "Bridge Approach",
|
||||
"spawn": {
|
||||
"dx": -0.114095858645717,
|
||||
"dz": -0.993469745407426,
|
||||
"x": 35.5160890575852,
|
||||
"z": -118.596483088614
|
||||
"x": 35.51608905758518,
|
||||
"z": -118.5964830886139,
|
||||
"y": 6.7,
|
||||
"dx": -0.11409585864571734,
|
||||
"dz": -0.9934697454074263
|
||||
},
|
||||
"streams": [
|
||||
{
|
||||
"interval": 1.5,
|
||||
"pts": [
|
||||
[
|
||||
21.8244656781075,
|
||||
-237.813875098783
|
||||
21.82446567810751,
|
||||
-237.81387509878263,
|
||||
37.66
|
||||
],
|
||||
[
|
||||
23.1457200273832,
|
||||
-226.455207706528
|
||||
23.145720027383163,
|
||||
-226.45520770652828,
|
||||
37.76
|
||||
],
|
||||
[
|
||||
24.7882096121438,
|
||||
-213.848153713549
|
||||
24.788209612143817,
|
||||
-213.84815371354867,
|
||||
35.66
|
||||
],
|
||||
[
|
||||
26.1455691749522,
|
||||
-200.297419769933
|
||||
26.145569174952232,
|
||||
-200.29741976993301,
|
||||
31.44
|
||||
]
|
||||
],
|
||||
"speed": 12.0
|
||||
"speed": 12.0,
|
||||
"interval": 1.5
|
||||
},
|
||||
{
|
||||
"interval": 1.5,
|
||||
"pts": [
|
||||
[
|
||||
2.19994158852704,
|
||||
-240.327171190027
|
||||
2.199941588527042,
|
||||
-240.32717119002737,
|
||||
36.31
|
||||
],
|
||||
[
|
||||
-2.52481722237557,
|
||||
-243.919505367749
|
||||
-2.5248172223755736,
|
||||
-243.91950536774928,
|
||||
35.81
|
||||
],
|
||||
[
|
||||
-6.32534953080772,
|
||||
-247.60965512377
|
||||
-6.325349530807717,
|
||||
-247.60965512377,
|
||||
35.17
|
||||
],
|
||||
[
|
||||
-15.1839832375373,
|
||||
-255.261358332787
|
||||
-15.183983237537262,
|
||||
-255.2613583327868,
|
||||
33.26
|
||||
],
|
||||
[
|
||||
-19.8227220865701,
|
||||
-258.67299529667
|
||||
-19.822722086570074,
|
||||
-258.6729952966697,
|
||||
32.36
|
||||
],
|
||||
[
|
||||
-24.2795153329838,
|
||||
-261.703355786389
|
||||
-24.279515332983824,
|
||||
-261.70335578638884,
|
||||
31.56
|
||||
],
|
||||
[
|
||||
-29.0114379744006,
|
||||
-263.890761064968
|
||||
-29.011437974400625,
|
||||
-263.89076106496833,
|
||||
30.9
|
||||
]
|
||||
],
|
||||
"speed": 12.0
|
||||
"speed": 12.0,
|
||||
"interval": 1.5
|
||||
},
|
||||
{
|
||||
"interval": 1.8,
|
||||
"pts": [
|
||||
[
|
||||
20.7724471517801,
|
||||
-199.7593122304
|
||||
20.772447151780117,
|
||||
-199.75931223039953,
|
||||
31.4
|
||||
],
|
||||
[
|
||||
19.4233779811381,
|
||||
-213.232863886751
|
||||
19.423377981138138,
|
||||
-213.23286388675078,
|
||||
35.3
|
||||
],
|
||||
[
|
||||
17.786545159723,
|
||||
-225.792452293243
|
||||
17.78654515972297,
|
||||
-225.7924522932427,
|
||||
37.39
|
||||
],
|
||||
[
|
||||
16.4606356403737,
|
||||
-237.18991410136
|
||||
16.46063564037367,
|
||||
-237.18991410136036,
|
||||
37.31
|
||||
]
|
||||
],
|
||||
"speed": 11.0
|
||||
"speed": 11.0,
|
||||
"interval": 1.8
|
||||
},
|
||||
{
|
||||
"interval": 1.8,
|
||||
"pts": [
|
||||
[
|
||||
-26.7370429025148,
|
||||
-268.788426535065
|
||||
-26.737042902514784,
|
||||
-268.7884265350654,
|
||||
30.16
|
||||
],
|
||||
[
|
||||
-21.6112433779486,
|
||||
-266.398068213575
|
||||
-21.61124337794858,
|
||||
-266.3980682135746,
|
||||
30.89
|
||||
],
|
||||
[
|
||||
-16.704188313209,
|
||||
-263.081481102976
|
||||
-16.704188313209045,
|
||||
-263.0814811029762,
|
||||
31.77
|
||||
],
|
||||
[
|
||||
-11.7617743504717,
|
||||
-259.438496866914
|
||||
-11.761774350471743,
|
||||
-259.43849686691397,
|
||||
32.83
|
||||
],
|
||||
[
|
||||
-2.72241951437748,
|
||||
-251.63195487599
|
||||
-2.7224195143774796,
|
||||
-251.63195487598963,
|
||||
34.86
|
||||
],
|
||||
[
|
||||
0.983930787446262,
|
||||
-248.024220632365
|
||||
0.9839307874462617,
|
||||
-248.02422063236523,
|
||||
35.6
|
||||
],
|
||||
[
|
||||
5.46498065752023,
|
||||
-244.628278010132
|
||||
5.4649806575202335,
|
||||
-244.6282780101317,
|
||||
36.2
|
||||
]
|
||||
],
|
||||
"speed": 11.0
|
||||
"speed": 11.0,
|
||||
"interval": 1.8
|
||||
},
|
||||
{
|
||||
"interval": 1.5,
|
||||
"pts": [
|
||||
[
|
||||
11.2707008429023,
|
||||
-197.847843241665
|
||||
11.27070084290225,
|
||||
-197.84784324166512,
|
||||
31.27
|
||||
],
|
||||
[
|
||||
10.8961758047183,
|
||||
-204.766417702285
|
||||
10.896175804718348,
|
||||
-204.76641770228525,
|
||||
33.12
|
||||
],
|
||||
[
|
||||
10.4764778796752,
|
||||
-211.209757888086
|
||||
10.476477879675205,
|
||||
-211.20975788808624,
|
||||
34.75
|
||||
],
|
||||
[
|
||||
9.92304078347784,
|
||||
-216.207006965937
|
||||
-216.20700696593718,
|
||||
35.63
|
||||
],
|
||||
[
|
||||
8.93295830185362,
|
||||
-221.625317668162
|
||||
8.932958301853615,
|
||||
-221.62531766816238,
|
||||
36.37
|
||||
],
|
||||
[
|
||||
7.50873869919987,
|
||||
-226.865371707994
|
||||
7.508738699199866,
|
||||
-226.8653717079938,
|
||||
36.97
|
||||
]
|
||||
],
|
||||
"speed": 12.0
|
||||
"speed": 12.0,
|
||||
"interval": 1.5
|
||||
},
|
||||
{
|
||||
"interval": 1.5,
|
||||
"pts": [
|
||||
[
|
||||
28.875188928697,
|
||||
-229.492425462448
|
||||
28.875188928696993,
|
||||
-229.49242546244793,
|
||||
38.44
|
||||
],
|
||||
[
|
||||
28.7254802520939,
|
||||
-214.053661592775
|
||||
28.72548025209394,
|
||||
-214.05366159277472,
|
||||
35.92
|
||||
],
|
||||
[
|
||||
28.1508746327618,
|
||||
-209.459560296273
|
||||
28.150874632761848,
|
||||
-209.45956029627345,
|
||||
34.63
|
||||
],
|
||||
[
|
||||
27.2791473530598,
|
||||
-204.781298995536
|
||||
27.279147353059784,
|
||||
-204.7812989955361,
|
||||
32.98
|
||||
],
|
||||
[
|
||||
26.0948795290309,
|
||||
-199.443402630656
|
||||
26.094879529030933,
|
||||
-199.44340263065618,
|
||||
31.15
|
||||
]
|
||||
],
|
||||
"speed": 12.0
|
||||
"speed": 12.0,
|
||||
"interval": 1.5
|
||||
}
|
||||
],
|
||||
"targets": [
|
||||
5000,
|
||||
7500,
|
||||
11500
|
||||
15000,
|
||||
35000,
|
||||
60000
|
||||
]
|
||||
}
|
||||
]
|
||||
Binary file not shown.
@ -3,7 +3,7 @@
|
||||
importer="scene"
|
||||
importer_version=1
|
||||
type="PackedScene"
|
||||
uid="uid://bjd3utm2spgs0"
|
||||
uid="uid://dduudwpqocdxu"
|
||||
path="res://.godot/imported/level.glb-045fc5cf8c0e529ecdc2678ee7acde2a.scn"
|
||||
|
||||
[deps]
|
||||
|
||||
40
shot_bridge_dem.png.import
Normal file
40
shot_bridge_dem.png.import
Normal file
@ -0,0 +1,40 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://cfq88o84umvip"
|
||||
path="res://.godot/imported/shot_bridge_dem.png-75be2353aa1d96cb1fa690daade691e3.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://shot_bridge_dem.png"
|
||||
dest_files=["res://.godot/imported/shot_bridge_dem.png-75be2353aa1d96cb1fa690daade691e3.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
40
shot_kp_dem.png.import
Normal file
40
shot_kp_dem.png.import
Normal file
@ -0,0 +1,40 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://boesb5lcxhlfv"
|
||||
path="res://.godot/imported/shot_kp_dem.png-c9ce5dfc952a5ba8544840830a36b4c0.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://shot_kp_dem.png"
|
||||
dest_files=["res://.godot/imported/shot_kp_dem.png-c9ce5dfc952a5ba8544840830a36b4c0.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
40
shot_kp_top.png.import
Normal file
40
shot_kp_top.png.import
Normal file
@ -0,0 +1,40 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://dv0r0ctfsvyse"
|
||||
path="res://.godot/imported/shot_kp_top.png-9b910b7280f9d3c8de3410ea2430621a.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://shot_kp_top.png"
|
||||
dest_files=["res://.godot/imported/shot_kp_top.png-9b910b7280f9d3c8de3410ea2430621a.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
40
shot_trolleys.png.import
Normal file
40
shot_trolleys.png.import
Normal file
@ -0,0 +1,40 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://w384sbljyqjk"
|
||||
path="res://.godot/imported/shot_trolleys.png-4bc10206031793a54eda76f31a101806.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://shot_trolleys.png"
|
||||
dest_files=["res://.godot/imported/shot_trolleys.png-4bc10206031793a54eda76f31a101806.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
21
src/game.gd
21
src/game.gd
@ -81,6 +81,7 @@ var busts := 0
|
||||
var escapes := 0
|
||||
|
||||
var drag_end: Vector3
|
||||
var drag_end_y := 0.0
|
||||
var drag_len := 0.0
|
||||
var gear := 1
|
||||
var revs := 0.0
|
||||
@ -165,7 +166,7 @@ func _ready() -> void:
|
||||
var sp: Dictionary = junction["spawn"]
|
||||
var jf := Vector3(sp["dx"], 0, sp["dz"]).normalized()
|
||||
car.transform = Transform3D(Basis.looking_at(jf, Vector3.UP),
|
||||
_clear_spawn(Vector3(sp["x"], 0.7, sp["z"]), jf))
|
||||
_clear_spawn(Vector3(sp["x"], float(sp.get("y", 0.0)) + 0.7, sp["z"]), jf))
|
||||
car.hold_wreck = true
|
||||
# The marker test lives in the branch condition, not inside it: as an `elif`
|
||||
# with the test inside, a level without a drag strip (the code-built carpark)
|
||||
@ -174,7 +175,8 @@ func _ready() -> void:
|
||||
elif mode == "drag" and _drag_markers(level).size() == 2:
|
||||
var mk := _drag_markers(level)
|
||||
drag_end = Vector3(mk[1].global_position.x, 0.0, mk[1].global_position.z)
|
||||
var from := Vector3(mk[0].global_position.x, 0.7, mk[0].global_position.z)
|
||||
drag_end_y = mk[1].global_position.y
|
||||
var from := Vector3(mk[0].global_position.x, mk[0].global_position.y + 0.7, mk[0].global_position.z)
|
||||
var dir := (drag_end - Vector3(from.x, 0, from.z)).normalized()
|
||||
drag_len = Vector3(from.x, 0, from.z).distance_to(drag_end)
|
||||
car.transform = Transform3D(Basis.looking_at(dir, Vector3.UP),
|
||||
@ -189,7 +191,8 @@ func _ready() -> void:
|
||||
var f := -t.basis.z
|
||||
f.y = 0.0
|
||||
f = f.normalized() if f.length_squared() > 0.001 else Vector3.FORWARD
|
||||
car.transform = Transform3D(Basis.looking_at(f, Vector3.UP), Vector3(t.origin.x, 0.7, t.origin.z))
|
||||
car.transform = Transform3D(Basis.looking_at(f, Vector3.UP),
|
||||
Vector3(t.origin.x, t.origin.y + 0.7, t.origin.z))
|
||||
else:
|
||||
car.position = Vector3.UP * 0.6
|
||||
add_child(car)
|
||||
@ -244,10 +247,10 @@ func _ready() -> void:
|
||||
var strip := Path3D.new()
|
||||
var sc := Curve3D.new()
|
||||
sc.add_point(car.global_position + lane)
|
||||
sc.add_point(drag_end + Vector3.UP * 0.7 + lane)
|
||||
sc.add_point(drag_end + Vector3.UP * (drag_end_y + 0.7) + lane)
|
||||
# a 2-point curve makes rival.gd's fmod() lookahead wrap to the start once
|
||||
# it nears the end, spinning the car around -- extend past the line instead
|
||||
sc.add_point(drag_end + Vector3.UP * 0.7 + lane + fwd * 120.0)
|
||||
sc.add_point(drag_end + Vector3.UP * (drag_end_y + 0.7) + lane + fwd * 120.0)
|
||||
strip.curve = sc
|
||||
add_child(strip)
|
||||
var pool := Registry.cars().values()
|
||||
@ -296,7 +299,8 @@ func _ready() -> void:
|
||||
var path := Path3D.new()
|
||||
var curve := Curve3D.new()
|
||||
for p in stream["pts"]:
|
||||
curve.add_point(Vector3(p[0], 0, p[1]))
|
||||
# third component (when baked) is terrain height
|
||||
curve.add_point(Vector3(p[0], float(p[2]) if p.size() > 2 else 0.0, p[1]))
|
||||
path.curve = curve
|
||||
add_child(path)
|
||||
var L := curve.get_baked_length()
|
||||
@ -447,7 +451,8 @@ func _spawn_smashables(level: Node) -> void:
|
||||
add_child(b)
|
||||
var t: Transform3D = (m as Node3D).global_transform
|
||||
b.global_transform = Transform3D(
|
||||
Basis(Vector3.UP, t.basis.get_euler().y), Vector3(t.origin.x, 0.75, t.origin.z))
|
||||
Basis(Vector3.UP, t.basis.get_euler().y),
|
||||
Vector3(t.origin.x, t.origin.y + 0.72, t.origin.z))
|
||||
b.sleeping = true
|
||||
n += 1
|
||||
for prefix in SMASHABLE:
|
||||
@ -514,7 +519,7 @@ func _spawn_smashables(level: Node) -> void:
|
||||
var t: Transform3D = (m as Node3D).global_transform
|
||||
b.global_transform = Transform3D(
|
||||
Basis(Vector3.UP, t.basis.get_euler().y),
|
||||
Vector3(t.origin.x, size.y * 0.5 + 0.02, t.origin.z))
|
||||
Vector3(t.origin.x, t.origin.y + size.y * 0.5 + 0.02, t.origin.z))
|
||||
b.sleeping = true
|
||||
n += 1
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@ while IFS='|' read -r id json lat lon specs; do
|
||||
IFS=';' read -ra SPEC <<< "$specs"
|
||||
python3 tools/osm_junction.py "$C/$json" "levels/$id/junctions.json" "$lat" "$lon" "${SPEC[@]}"
|
||||
done <<'EOF'
|
||||
queen_st_mall|brisbane_cbd.json|-27.4699|153.0251|Albert x Adelaide|Albert Street|Adelaide Street;Edward x Elizabeth|Edward Street|Elizabeth Street
|
||||
queen_st_mall|brisbane_cbd.json|-27.4699|153.0251|Albert x Adelaide|Albert Street|Adelaide Street;Elizabeth x George|Elizabeth Street|George Street
|
||||
southbank|southbank.json|-27.4775|153.0215|Melbourne x Merivale|Melbourne Street|Merivale Street;Grey x Glenelg|Grey Street|Glenelg Street
|
||||
albert_parklands|albert_parklands.json|-27.4740|153.0280|Alice x George|Alice Street|George Street;Margaret x Edward|Margaret Street|Edward Street
|
||||
story_bridge|story_bridge.json|-27.4635|153.0355|Bridge Approach|Bradfield Highway|Kemp Place
|
||||
|
||||
@ -41,6 +41,50 @@ TEX = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "assets", "
|
||||
M_LAT = 110574.0
|
||||
M_LON = 111320.0 * math.cos(math.radians(LAT0))
|
||||
|
||||
# ---- real terrain (tools/fetch_dem.py output next to the area json) --------
|
||||
import numpy as _np
|
||||
DEM = None
|
||||
DEM_META = None
|
||||
_dem_base = src[:-5] if src.endswith(".json") else src
|
||||
if os.path.exists(_dem_base + "_dem.f32"):
|
||||
DEM_META = json.load(open(_dem_base + "_dem.json"))
|
||||
DEM = _np.fromfile(_dem_base + "_dem.f32", dtype="<f4").reshape(
|
||||
DEM_META["h"], DEM_META["w"])
|
||||
print("DEM loaded: %dx%d, %.1f..%.1f m" % (DEM_META["w"], DEM_META["h"],
|
||||
float(DEM.min()), float(DEM.max())))
|
||||
|
||||
def H(x, y):
|
||||
"""Terrain height at level-local metres, bilinear. 0 when no DEM."""
|
||||
if DEM is None:
|
||||
return 0.0
|
||||
lon = LON0 + x / M_LON
|
||||
lat = LAT0 + y / M_LAT
|
||||
u = (lon - DEM_META["min_lon"]) / (DEM_META["max_lon"] - DEM_META["min_lon"]) * (DEM_META["w"] - 1)
|
||||
v = (DEM_META["max_lat"] - lat) / (DEM_META["max_lat"] - DEM_META["min_lat"]) * (DEM_META["h"] - 1)
|
||||
u = min(max(u, 0.0), DEM_META["w"] - 1.001)
|
||||
v = min(max(v, 0.0), DEM_META["h"] - 1.001)
|
||||
x0, y0 = int(u), int(v)
|
||||
fx, fy = u - x0, v - y0
|
||||
a = DEM[y0, x0] * (1 - fx) + DEM[y0, x0 + 1] * fx
|
||||
b = DEM[y0 + 1, x0] * (1 - fx) + DEM[y0 + 1, x0 + 1] * fx
|
||||
return float(a * (1 - fy) + b * fy)
|
||||
|
||||
WATER_Z = 0.3 # river surface: above the riverbed's DEM zero, below banks
|
||||
CARVE = [] # (x, y, h) of every draped road/path sample: terrain may not rise above these
|
||||
|
||||
def bridge_profile(pts, named=False):
|
||||
"""Deck heights for a bridge way: lerp between end terrain plus a hump, so
|
||||
the deck spans the river instead of draping down into it."""
|
||||
cum = [0.0]
|
||||
for i in range(1, len(pts)):
|
||||
cum.append(cum[-1] + math.hypot(pts[i][0] - pts[i - 1][0], pts[i][1] - pts[i - 1][1]))
|
||||
T = max(cum[-1], 0.001)
|
||||
hA, hB = H(*pts[0]), H(*pts[-1])
|
||||
hump = 16.0 if named else 3.5
|
||||
return [max(H(*pts[i]),
|
||||
hA + (hB - hA) * (cum[i] / T) + hump * math.sin(math.pi * cum[i] / T))
|
||||
for i in range(len(pts))]
|
||||
|
||||
GROUND_FLOOR = 4.2 # height of the glazed shopfront band
|
||||
AWNING_Z = 3.75 # underside of the street awning
|
||||
AWNING_OUT = 2.3 # how far it cantilevers over the footpath
|
||||
@ -228,10 +272,11 @@ def ring_ccw(pts):
|
||||
for i in range(len(r)))
|
||||
return r if area > 0 else list(reversed(r))
|
||||
|
||||
def poly_bm(pts, z, h=0.0):
|
||||
"""Filled (optionally extruded) polygon bmesh from closed pt list."""
|
||||
def poly_bm(pts, z, h=0.0, drape=False):
|
||||
"""Filled (optionally extruded) polygon bmesh from closed pt list.
|
||||
drape=True adds terrain height per vertex (parks); flat otherwise (water)."""
|
||||
bm = bmesh.new()
|
||||
verts = [bm.verts.new((x, y, z)) for x, y in pts[:-1]]
|
||||
verts = [bm.verts.new((x, y, z + (H(x, y) if drape else 0.0))) for x, y in pts[:-1]]
|
||||
face = bm.faces.new(verts)
|
||||
if h > 0.0:
|
||||
res = bmesh.ops.extrude_face_region(bm, geom=[face])
|
||||
@ -241,9 +286,27 @@ def poly_bm(pts, z, h=0.0):
|
||||
bmesh.ops.triangulate(bm, faces=bm.faces)
|
||||
return bm
|
||||
|
||||
def ribbon(bm, pts, half, z, mat=0, drop=None, offset=0.0):
|
||||
def _subdivide(pts, step=8.0):
|
||||
"""Split long segments so draped ribbons follow the terrain instead of
|
||||
chording across it -- an OSM segment can run 100+ m, and a straight strip
|
||||
over curved ground diverges from the collision mesh by metres. That read
|
||||
in-game as the car sinking to its windows mid-block."""
|
||||
out = [pts[0]]
|
||||
for i in range(1, len(pts)):
|
||||
(x1, y1), (x2, y2) = out[-1], pts[i]
|
||||
L = math.hypot(x2 - x1, y2 - y1)
|
||||
n = max(int(L / step), 1)
|
||||
for k in range(1, n + 1):
|
||||
out.append((x1 + (x2 - x1) * k / n, y1 + (y2 - y1) * k / n))
|
||||
return out
|
||||
|
||||
def ribbon(bm, pts, half, z, mat=0, drop=None, offset=0.0, zs=None):
|
||||
"""Strip of width 2*half along a polyline, shifted sideways by `offset`.
|
||||
`drop` chamfers the edges down to z-PATH_H."""
|
||||
`drop` chamfers the edges down to z-PATH_H. Heights come from the terrain
|
||||
(per segment END, not per corner, so roads don't twist across their width);
|
||||
`zs` overrides with explicit per-point heights (bridge decks)."""
|
||||
if zs is None and DEM is not None:
|
||||
pts = _subdivide(pts)
|
||||
for i in range(len(pts) - 1):
|
||||
(x1, y1), (x2, y2) = pts[i], pts[i + 1]
|
||||
dx, dy = x2 - x1, y2 - y1
|
||||
@ -251,79 +314,88 @@ def ribbon(bm, pts, half, z, mat=0, drop=None, offset=0.0):
|
||||
if L < 0.1:
|
||||
continue
|
||||
nx, ny = -dy / L, dx / L
|
||||
h1 = zs[i] if zs else H(x1, y1)
|
||||
h2 = zs[i + 1] if zs else H(x2, y2)
|
||||
if zs is None:
|
||||
CARVE.append((x1, y1, h1))
|
||||
CARVE.append((x2, y2, h2))
|
||||
if offset:
|
||||
x1, y1 = x1 + nx * offset, y1 + ny * offset
|
||||
x2, y2 = x2 + nx * offset, y2 + ny * offset
|
||||
if drop is None:
|
||||
quad(bm, [(x1 + nx * half, y1 + ny * half, z), (x1 - nx * half, y1 - ny * half, z),
|
||||
(x2 - nx * half, y2 - ny * half, z), (x2 + nx * half, y2 + ny * half, z)], mat)
|
||||
quad(bm, [(x1 + nx * half, y1 + ny * half, z + h1), (x1 - nx * half, y1 - ny * half, z + h1),
|
||||
(x2 - nx * half, y2 - ny * half, z + h2), (x2 + nx * half, y2 + ny * half, z + h2)], mat)
|
||||
else:
|
||||
inner = max(half - PATH_CHAMFER, half * 0.35)
|
||||
for s0, s1, z0, z1 in ((half, inner, z - drop, z), (inner, -inner, z, z),
|
||||
(-inner, -half, z, z - drop)):
|
||||
quad(bm, [(x1 + nx * s0, y1 + ny * s0, z0), (x1 + nx * s1, y1 + ny * s1, z1),
|
||||
(x2 + nx * s1, y2 + ny * s1, z1), (x2 + nx * s0, y2 + ny * s0, z0)], mat)
|
||||
for s0, s1, d0, d1 in ((half, inner, drop, 0.0), (inner, -inner, 0.0, 0.0),
|
||||
(-inner, -half, 0.0, drop)):
|
||||
quad(bm, [(x1 + nx * s0, y1 + ny * s0, z - d0 + h1), (x1 + nx * s1, y1 + ny * s1, z - d1 + h1),
|
||||
(x2 + nx * s1, y2 + ny * s1, z - d1 + h2), (x2 + nx * s0, y2 + ny * s0, z - d0 + h2)], mat)
|
||||
|
||||
# ------------------------------------------------------------------- props
|
||||
|
||||
def add_tree(fol, jac, frond, trunk, x, y, rng):
|
||||
"""Fig (broad layered canopy), jacaranda (same shape, purple), or palm."""
|
||||
z0 = H(x, y)
|
||||
if rng.random() < 0.18:
|
||||
h = rng.uniform(6.5, 9.5)
|
||||
cone(trunk, (x, y, h / 2), 0.22, 0.14, h, 7)
|
||||
cone(trunk, (x, y, z0 + h / 2), 0.22, 0.14, h, 7)
|
||||
for i in range(7):
|
||||
a = i * math.tau / 7 + rng.uniform(-0.25, 0.25)
|
||||
reach = rng.uniform(1.8, 2.5)
|
||||
tip = Vector((x + math.cos(a) * reach, y + math.sin(a) * reach, h - rng.uniform(0.8, 1.6)))
|
||||
beam(frond, Vector((x, y, h)), tip, 0.7, 0.12)
|
||||
tip = Vector((x + math.cos(a) * reach, y + math.sin(a) * reach, z0 + h - rng.uniform(0.8, 1.6)))
|
||||
beam(frond, Vector((x, y, z0 + h)), tip, 0.7, 0.12)
|
||||
else:
|
||||
# canopy well clear of the roof line of a car, and built from three
|
||||
# offset spheres so the silhouette breaks up instead of reading as a ball
|
||||
clear = rng.uniform(3.6, 4.8)
|
||||
r = rng.uniform(1.7, 2.5)
|
||||
cone(trunk, (x, y, (clear + 1.0) / 2), 0.20, 0.13, clear + 1.0, 7)
|
||||
cone(trunk, (x, y, z0 + (clear + 1.0) / 2), 0.20, 0.13, clear + 1.0, 7)
|
||||
target = jac if rng.random() < 0.22 else fol # jacaranda season is eternal here
|
||||
for i in range(3):
|
||||
off = Vector((rng.uniform(-1, 1), rng.uniform(-1, 1), 0)) * r * 0.42
|
||||
blob(target, (x + off.x, y + off.y, clear + r * (0.45 + 0.34 * i)),
|
||||
blob(target, (x + off.x, y + off.y, z0 + clear + r * (0.45 + 0.34 * i)),
|
||||
(r * rng.uniform(0.75, 1.05), r * rng.uniform(0.75, 1.05), r * rng.uniform(0.55, 0.75)),
|
||||
subdiv=2)
|
||||
|
||||
def add_bench(bm, x, y, rng):
|
||||
z0 = H(x, y)
|
||||
a = rng.random() * math.tau
|
||||
d = Vector((math.cos(a), math.sin(a), 0))
|
||||
p = Vector((-d.y, d.x, 0))
|
||||
for s in (-0.75, 0.75):
|
||||
c = Vector((x, y, 0)) + d * s
|
||||
c = Vector((x, y, z0)) + d * s
|
||||
beam(bm, c + Vector((0, 0, 0.02)), c + Vector((0, 0, 0.45)), 0.36, 0.07)
|
||||
a0 = Vector((x, y, 0.47)) - d * 0.95
|
||||
a0 = Vector((x, y, z0 + 0.47)) - d * 0.95
|
||||
slab(bm, [(a0 + p * 0.28).to_tuple(), (a0 - p * 0.28).to_tuple(),
|
||||
(a0 - p * 0.28 + d * 1.9).to_tuple(), (a0 + p * 0.28 + d * 1.9).to_tuple()], 0.08)
|
||||
|
||||
def add_signal(bm, lens, x, y, rng):
|
||||
"""Aussie traffic signal: pole, lantern head, mast arm with a second head.
|
||||
Lenses go in their own bmesh so they can be emissive."""
|
||||
z0 = H(x, y)
|
||||
h = 3.9
|
||||
cone(bm, (x, y, h / 2), 0.10, 0.08, h, 6)
|
||||
cone(bm, (x, y, z0 + h / 2), 0.10, 0.08, h, 6)
|
||||
a = rng.random() * math.tau
|
||||
d = Vector((math.cos(a), math.sin(a), 0))
|
||||
p = Vector((-d.y, d.x, 0))
|
||||
for at, top in ((Vector((x, y, 0)) + p * 0.22, h - 0.15),
|
||||
(Vector((x, y, 0)) + d * 3.6, h + 0.55)):
|
||||
for at, top in ((Vector((x, y, z0)) + p * 0.22, z0 + h - 0.15),
|
||||
(Vector((x, y, z0)) + d * 3.6, z0 + h + 0.55)):
|
||||
# lantern housing + three stacked lenses
|
||||
beam(bm, at + Vector((0, 0, top - 1.0)), at + Vector((0, 0, top)), 0.34, 0.34)
|
||||
for i, m in enumerate((0, 1, 2)):
|
||||
c = at + Vector((0, 0, top - 0.22 - i * 0.32))
|
||||
# must clear beam()'s 0.05 m minimum length or the lens silently vanishes
|
||||
beam(lens, c + d * 0.15, c + d * 0.28, 0.20, 0.20, m)
|
||||
beam(bm, Vector((x, y, h + 0.4)), Vector((x, y, h + 0.4)) + d * 3.6, 0.13, 0.13) # mast arm
|
||||
beam(bm, Vector((x, y, z0 + h + 0.4)), Vector((x, y, z0 + h + 0.4)) + d * 3.6, 0.13, 0.13) # mast arm
|
||||
|
||||
def add_power_pole(bm, wire_bm, x, y, prev, rng):
|
||||
"""Timber power pole with a crossarm; wires sag to the previous pole."""
|
||||
z0 = H(x, y)
|
||||
h = 8.6
|
||||
cone(bm, (x, y, h / 2), 0.19, 0.13, h, 6)
|
||||
beam(bm, (x - 0.95, y, h - 0.5), (x + 0.95, y, h - 0.5), 0.11, 0.11)
|
||||
tops = [Vector((x - 0.8, y, h - 0.38)), Vector((x, y, h - 0.05)), Vector((x + 0.8, y, h - 0.38))]
|
||||
cone(bm, (x, y, z0 + h / 2), 0.19, 0.13, h, 6)
|
||||
beam(bm, (x - 0.95, y, z0 + h - 0.5), (x + 0.95, y, z0 + h - 0.5), 0.11, 0.11)
|
||||
tops = [Vector((x - 0.8, y, z0 + h - 0.38)), Vector((x, y, z0 + h - 0.05)), Vector((x + 0.8, y, z0 + h - 0.38))]
|
||||
if prev is not None:
|
||||
for a, b in zip(prev, tops):
|
||||
mid = (a + b) / 2 - Vector((0, 0, (a - b).length * 0.045)) # catenary sag
|
||||
@ -335,7 +407,7 @@ def add_shelter(bm, glassbm, x, y, rng):
|
||||
a = rng.random() * math.tau
|
||||
d = Vector((math.cos(a), math.sin(a), 0))
|
||||
p = Vector((-d.y, d.x, 0))
|
||||
c = Vector((x, y, 0))
|
||||
c = Vector((x, y, H(x, y)))
|
||||
for sd in (-1.8, 1.8):
|
||||
for sp in (-1.1, 1.1):
|
||||
f = c + d * sd + p * sp
|
||||
@ -460,23 +532,27 @@ for e in d["elements"]:
|
||||
|
||||
bm = bmesh.new()
|
||||
gf = 0.0 if qld else min(GROUND_FLOOR, h * 0.45)
|
||||
# rigid terrain lift: base at the LOWEST terrain under the footprint so
|
||||
# the uphill side cuts into the slope; walls run 2 m below base so no
|
||||
# daylight shows under the downhill edge
|
||||
bz = min(H(x, y) for x, y in ring)
|
||||
for i in range(len(ring)):
|
||||
(x1, y1), (x2, y2) = ring[i], ring[(i + 1) % len(ring)]
|
||||
if gf > 0.0:
|
||||
quad(bm, [(x1, y1, 0), (x2, y2, 0), (x2, y2, gf), (x1, y1, gf)], 2)
|
||||
quad(bm, [(x1, y1, gf), (x2, y2, gf), (x2, y2, h), (x1, y1, h)], 0)
|
||||
quad(bm, [(x1, y1, bz - 2.0), (x2, y2, bz - 2.0), (x2, y2, bz + gf), (x1, y1, bz + gf)], 2)
|
||||
quad(bm, [(x1, y1, bz + gf), (x2, y2, bz + gf), (x2, y2, bz + h), (x1, y1, bz + h)], 0)
|
||||
try:
|
||||
bm.faces.new([bm.verts.new((x, y, h)) for x, y in ring]).material_index = 1
|
||||
bm.faces.new([bm.verts.new((x, y, bz + h)) for x, y in ring]).material_index = 1
|
||||
except ValueError:
|
||||
pass
|
||||
if not qld:
|
||||
for i in range(len(ring)): # parapet caps the roof edge
|
||||
(x1, y1), (x2, y2) = ring[i], ring[(i + 1) % len(ring)]
|
||||
beam(bm, (x1, y1, h + 0.45), (x2, y2, h + 0.45), 0.35, 0.9, 0)
|
||||
beam(bm, (x1, y1, bz + h + 0.45), (x2, y2, bz + h + 0.45), 0.35, 0.9, 0)
|
||||
if h > 26: # rooftop plant room
|
||||
cx = sum(p[0] for p in ring) / len(ring)
|
||||
cy = sum(p[1] for p in ring) / len(ring)
|
||||
beam(bm, (cx - 2.5, cy, h + 1.4), (cx + 2.5, cy, h + 1.4), 4.0, 2.8, 1)
|
||||
beam(bm, (cx - 2.5, cy, bz + h + 1.4), (cx + 2.5, cy, bz + h + 1.4), 4.0, 2.8, 1)
|
||||
bmesh.ops.triangulate(bm, faces=bm.faces)
|
||||
add_obj("bld_%d-col" % e["id"], bm, [fac, M_CORRO if qld else M_ROOF, M_SHOP],
|
||||
{0: 13.0 if not qld else 6.5, 1: 9.0 if not qld else 3.0, 2: 4.6})
|
||||
@ -492,16 +568,16 @@ for e in d["elements"]:
|
||||
mx, my = (ex1 + ex2) / 2, (ey1 + ey2) / 2
|
||||
ux, uy = (ex2 - ex1) / eL, (ey2 - ey1) / eL
|
||||
half = min(4.0, eL * 0.35)
|
||||
a = Vector((mx - ux * half, my - uy * half, h + 2.6))
|
||||
b = Vector((mx + ux * half, my + uy * half, h + 2.6))
|
||||
a = Vector((mx - ux * half, my - uy * half, bz + h + 2.6))
|
||||
b = Vector((mx + ux * half, my + uy * half, bz + h + 2.6))
|
||||
bb = bill_bm[e["id"] % 3]
|
||||
beam(bb, a, b, 0.25, 3.0)
|
||||
beam(bb, Vector((mx, my, h)), Vector((mx, my, h + 1.4)), 0.3, 0.3)
|
||||
beam(bb, Vector((mx, my, bz + h)), Vector((mx, my, bz + h + 1.4)), 0.3, 0.3)
|
||||
|
||||
# street awning over the footpath -- not every shop has one, and a whole
|
||||
# street at one height in one colour reads as a painted stripe
|
||||
if not qld and 6.0 < h < 45.0 and rng.random() < 0.7:
|
||||
az = AWNING_Z + rng.uniform(-0.35, 0.5)
|
||||
az = bz + AWNING_Z + rng.uniform(-0.35, 0.5)
|
||||
amat = e["id"] % 3
|
||||
out = AWNING_OUT * rng.uniform(0.85, 1.1)
|
||||
for i in range(len(ring)):
|
||||
@ -522,7 +598,7 @@ for e in d["elements"]:
|
||||
if not closed:
|
||||
continue
|
||||
try:
|
||||
bm = poly_bm(pts, -0.35)
|
||||
bm = poly_bm(pts, WATER_Z)
|
||||
except Exception:
|
||||
continue
|
||||
# ponytail: water is solid (-col) so cars skim it instead of falling forever
|
||||
@ -534,11 +610,12 @@ for e in d["elements"]:
|
||||
continue
|
||||
ring = ring_ccw(pts)
|
||||
bm = bmesh.new()
|
||||
pz = min(H(x, y) for x, y in ring)
|
||||
for i in range(len(ring)): # raised corten planter box
|
||||
(x1, y1), (x2, y2) = ring[i], ring[(i + 1) % len(ring)]
|
||||
quad(bm, [(x1, y1, 0), (x2, y2, 0), (x2, y2, 0.5), (x1, y1, 0.5)], 0)
|
||||
quad(bm, [(x1, y1, pz), (x2, y2, pz), (x2, y2, pz + 0.5), (x1, y1, pz + 0.5)], 0)
|
||||
try:
|
||||
bm.faces.new([bm.verts.new((x, y, 0.5)) for x, y in ring]).material_index = 1
|
||||
bm.faces.new([bm.verts.new((x, y, pz + 0.5)) for x, y in ring]).material_index = 1
|
||||
except ValueError:
|
||||
bm.free()
|
||||
continue
|
||||
@ -551,7 +628,7 @@ for e in d["elements"]:
|
||||
if not closed:
|
||||
continue
|
||||
try:
|
||||
bm = poly_bm(pts, 0.02)
|
||||
bm = poly_bm(pts, 0.02, drape=True)
|
||||
except Exception:
|
||||
continue
|
||||
add_obj("park_%d" % e["id"], bm, [M_GRASS], 14.0)
|
||||
@ -579,8 +656,8 @@ for e in d["elements"]:
|
||||
elif tags.get("natural") == "cliff":
|
||||
bm = bmesh.new()
|
||||
for i in range(len(pts) - 1):
|
||||
beam(bm, Vector((pts[i][0], pts[i][1], 7.0)),
|
||||
Vector((pts[i + 1][0], pts[i + 1][1], 7.0)), 2.0, 14.0)
|
||||
beam(bm, Vector((pts[i][0], pts[i][1], H(*pts[i]) + 1.0)),
|
||||
Vector((pts[i + 1][0], pts[i + 1][1], H(*pts[i + 1]) + 1.0)), 2.0, 14.0)
|
||||
add_obj("cliff_%d-col" % e["id"], bm, [M_ROCK], 12.0)
|
||||
counts["cliff"] += 1
|
||||
|
||||
@ -608,7 +685,10 @@ for e in d["elements"]:
|
||||
|
||||
wide = ROAD_W.get(hw, 6.0)
|
||||
rkey = "mall" if hw == "pedestrian" else ("bus" if hw == "busway" else "road")
|
||||
ribbon(road_bm[rkey], pts, wide / 2, 0.03)
|
||||
deck = None
|
||||
if tags.get("bridge") in ("yes", "viaduct") or (bridge_name and tags.get("name") == bridge_name):
|
||||
deck = bridge_profile(pts, named=(tags.get("name") == bridge_name))
|
||||
ribbon(road_bm[rkey], pts, wide / 2, 0.03, zs=deck)
|
||||
counts["road"] += 1
|
||||
if hw in ("residential", "unclassified"):
|
||||
# timber power poles down one side with sagging wires -- the single
|
||||
@ -661,8 +741,12 @@ for e in d["elements"]:
|
||||
L = math.hypot(x2 - x1, y2 - y1)
|
||||
for k in range(int(L / 9.0)):
|
||||
t0, t1 = (k * 9.0 + 1.5) / L, (k * 9.0 + 5.0) / L
|
||||
dz = None
|
||||
if deck is not None:
|
||||
dz = [deck[i] + (deck[i + 1] - deck[i]) * t0,
|
||||
deck[i] + (deck[i + 1] - deck[i]) * t1]
|
||||
ribbon(line_bm, [(x1 + (x2 - x1) * t0, y1 + (y2 - y1) * t0),
|
||||
(x1 + (x2 - x1) * t1, y1 + (y2 - y1) * t1)], 0.09, 0.045)
|
||||
(x1 + (x2 - x1) * t1, y1 + (y2 - y1) * t1)], 0.09, 0.045, zs=dz)
|
||||
|
||||
# street trees: OSM maps a fraction of what Brisbane actually has, so line the
|
||||
# kerbs of named streets and the mall edges with our own, deterministically
|
||||
@ -696,9 +780,9 @@ for tx, ty, seed in tree_sites:
|
||||
add_tree(fol_bm, jac_bm, frond_bm, trunk_bm, tx, ty, random.Random(seed))
|
||||
counts["tree"] += 1
|
||||
|
||||
add_obj("roads", road_bm["road"], [M_ROAD], 8.0)
|
||||
add_obj("mall_paving", road_bm["mall"], [M_MALL], 4.0)
|
||||
add_obj("busway", road_bm["bus"], [M_BUSRED], 8.0)
|
||||
add_obj("roads-col", road_bm["road"], [M_ROAD], 8.0)
|
||||
add_obj("mall_paving-col", road_bm["mall"], [M_MALL], 4.0)
|
||||
add_obj("busway-col", road_bm["bus"], [M_BUSRED], 8.0)
|
||||
add_obj("trees_foliage", fol_bm, [M_FOLIAGE], 0.9, smooth=True)
|
||||
add_obj("trees_jacaranda", jac_bm, [M_JAC], 0.9, smooth=True)
|
||||
add_obj("trees_fronds", frond_bm, [M_FOLIAGE], 0.9)
|
||||
@ -736,13 +820,22 @@ if bridge_name:
|
||||
s0, s1 = 0.175 * T, 0.825 * T
|
||||
N = 26
|
||||
bm = bmesh.new()
|
||||
deck_zs = bridge_profile([(pp.x, pp.y) for pp in pts], named=True)
|
||||
def deck_at(sd):
|
||||
for i2 in range(1, len(dists)):
|
||||
if dists[i2] >= sd:
|
||||
f2 = (sd - dists[i2 - 1]) / max(dists[i2] - dists[i2 - 1], 0.001)
|
||||
return deck_zs[i2 - 1] + (deck_zs[i2] - deck_zs[i2 - 1]) * f2
|
||||
return deck_zs[-1]
|
||||
samples = []
|
||||
for i in range(N + 1):
|
||||
t = i / N
|
||||
p = at(s0 + (s1 - s0) * t)
|
||||
sd = s0 + (s1 - s0) * t
|
||||
p = at(sd)
|
||||
p = Vector((p.x, p.y, deck_at(sd))) # truss base rides the deck
|
||||
h = 4.0 + 16.0 * (math.exp(-((t - 0.32) / 0.10) ** 2) + math.exp(-((t - 0.68) / 0.10) ** 2)) \
|
||||
+ 6.0 * math.sin(math.pi * t)
|
||||
fwd = (at(min(s0 + (s1 - s0) * t + 4, T)) - p)
|
||||
fwd = (at(min(sd + 4, T)) - p)
|
||||
fwd.z = 0
|
||||
fwd.normalize()
|
||||
samples.append((p, Vector((-fwd.y, fwd.x, 0)), h))
|
||||
@ -859,15 +952,54 @@ if level_id == "southbank":
|
||||
bpy.context.collection.objects.link(obj_a)
|
||||
print("grand arbour tendrils: %d" % n_t)
|
||||
|
||||
# ground slab sized to content (convex collider: huge trimesh tris break raycasts)
|
||||
# ground: a terrain grid sampled from the DEM (or a flat slab when there is
|
||||
# none). Small triangles are deliberate -- one huge trimesh tri breaks raycasts.
|
||||
xs = [v.co.x for o in bpy.data.objects if o.type == "MESH" for v in o.data.vertices]
|
||||
ys = [v.co.y for o in bpy.data.objects if o.type == "MESH" for v in o.data.vertices]
|
||||
gx, gy = (min(xs) + max(xs)) / 2, (min(ys) + max(ys)) / 2
|
||||
bm = bmesh.new()
|
||||
res = bmesh.ops.create_cube(bm, size=1.0)
|
||||
bmesh.ops.scale(bm, vec=(max(xs) - min(xs) + 100, max(ys) - min(ys) + 100, 1.0), verts=res["verts"])
|
||||
bmesh.ops.translate(bm, vec=(gx, gy, -0.5), verts=res["verts"])
|
||||
add_obj("ground-convcol", bm, [M_GROUND], 18.0)
|
||||
x0g, x1g = min(xs) - 50, max(xs) + 50
|
||||
y0g, y1g = min(ys) - 50, max(ys) + 50
|
||||
if DEM is not None:
|
||||
STEP = 9.0
|
||||
nx = max(int((x1g - x0g) / STEP), 2)
|
||||
ny = max(int((y1g - y0g) / STEP), 2)
|
||||
sx = (x1g - x0g) / nx
|
||||
sy = (y1g - y0g) / ny
|
||||
carve = _np.full((ny + 1, nx + 1), _np.inf, dtype=_np.float64)
|
||||
for cx, cy, ch in CARVE:
|
||||
gi = int(round((cx - x0g) / sx))
|
||||
gj = int(round((cy - y0g) / sy))
|
||||
if 0 <= gi <= nx and 0 <= gj <= ny:
|
||||
carve[gj, gi] = min(carve[gj, gi], ch)
|
||||
# dilate one cell so the clamp covers the whole face a road crosses
|
||||
dil = carve.copy()
|
||||
for dj in (-1, 0, 1):
|
||||
for di in (-1, 0, 1):
|
||||
dil = _np.minimum(dil, _np.roll(_np.roll(carve, dj, axis=0), di, axis=1))
|
||||
bm = bmesh.new()
|
||||
grid = []
|
||||
for j in range(ny + 1):
|
||||
row = []
|
||||
for i in range(nx + 1):
|
||||
gx2 = x0g + i * sx
|
||||
gy2 = y0g + j * sy
|
||||
gz = H(gx2, gy2) - 0.04
|
||||
if dil[j, i] != _np.inf:
|
||||
gz = min(gz, dil[j, i] - 0.22)
|
||||
row.append(bm.verts.new((gx2, gy2, gz)))
|
||||
grid.append(row)
|
||||
for j in range(ny):
|
||||
for i in range(nx):
|
||||
bm.faces.new((grid[j][i], grid[j][i + 1], grid[j + 1][i + 1], grid[j + 1][i]))
|
||||
bmesh.ops.triangulate(bm, faces=bm.faces)
|
||||
add_obj("terrain-col", bm, [M_GROUND], 18.0)
|
||||
print("terrain grid %dx%d (%d carve samples)" % (nx, ny, len(CARVE)))
|
||||
else:
|
||||
gx, gy = (x0g + x1g) / 2, (y0g + y1g) / 2
|
||||
bm = bmesh.new()
|
||||
res = bmesh.ops.create_cube(bm, size=1.0)
|
||||
bmesh.ops.scale(bm, vec=(x1g - x0g, y1g - y0g, 1.0), verts=res["verts"])
|
||||
bmesh.ops.translate(bm, vec=(gx, gy, -0.5), verts=res["verts"])
|
||||
add_obj("ground-convcol", bm, [M_GROUND], 18.0)
|
||||
|
||||
# parked-car / wheelie-bin markers -> empties; game.gd fills them with
|
||||
# shuntable RigidBodies at load (a static GLB can't carry physics bodies)
|
||||
@ -877,7 +1009,7 @@ batches = [("PP", pp_spots, PP_CAP)] + [(k, v, SMASH_CAP[k]) for k, v in smash_s
|
||||
for prefix, spots, cap in batches:
|
||||
for i, (mx, my, yaw) in enumerate(spots[:cap]):
|
||||
emp = bpy.data.objects.new("%s_%03d" % (prefix, i), None)
|
||||
emp.location = (mx, my, 0.05)
|
||||
emp.location = (mx, my, H(mx, my) + 0.05)
|
||||
emp.rotation_euler = (0, 0, yaw)
|
||||
bpy.context.collection.objects.link(emp)
|
||||
counts[prefix.lower()] = min(len(spots), cap)
|
||||
@ -911,7 +1043,7 @@ if best_run and best_run[0] >= 150.0:
|
||||
yaw = math.atan2(p1[1] - p0[1], p1[0] - p0[0])
|
||||
for nm, p in (("DragStart", p0), ("DragEnd", p1)):
|
||||
emp = bpy.data.objects.new(nm, None)
|
||||
emp.location = (p[0], p[1], 0.1)
|
||||
emp.location = (p[0], p[1], H(p[0], p[1]) + 0.1)
|
||||
emp.rotation_euler = (0, 0, yaw)
|
||||
bpy.context.collection.objects.link(emp)
|
||||
counts["drag_m"] = int(run)
|
||||
@ -920,7 +1052,7 @@ if spawn_arg:
|
||||
slat, slon, sbear = [float(v) for v in spawn_arg.split(",")]
|
||||
sx, sy = xy(slat, slon)
|
||||
sp = bpy.data.objects.new("Spawn", None)
|
||||
sp.location = (sx, sy, 0.1)
|
||||
sp.location = (sx, sy, H(sx, sy) + 0.1)
|
||||
sp.rotation_euler = (0, 0, math.radians(-sbear))
|
||||
bpy.context.collection.objects.link(sp)
|
||||
|
||||
@ -931,7 +1063,7 @@ if rp_arg:
|
||||
plat, plon = [float(v) for v in pair.split(",")]
|
||||
px, py = xy(plat, plon)
|
||||
emp = bpy.data.objects.new("RP_%02d" % i, None)
|
||||
emp.location = (px, py, 0.1)
|
||||
emp.location = (px, py, H(px, py) + 0.1)
|
||||
bpy.context.collection.objects.link(emp)
|
||||
emp.parent = rp
|
||||
|
||||
|
||||
101
tools/fetch_dem.py
Normal file
101
tools/fetch_dem.py
Normal file
@ -0,0 +1,101 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Fetch real elevation for a level's OSM area from the AWS terrain tiles.
|
||||
|
||||
Usage: fetch_dem.py <area.json> <out_prefix>
|
||||
|
||||
Reads the area's bounding box straight from its OSM geometry (the original
|
||||
fetch bboxes were never recorded -- same trap as the junction specs), grabs
|
||||
the covering terrarium tiles at z15 (~4.2 m/px at Brisbane's latitude), and
|
||||
writes:
|
||||
<out_prefix>_dem.f32 row-major float32 heights in metres (little-endian)
|
||||
<out_prefix>_dem.json {"w", "h", "min_lat", "min_lon", "max_lat", "max_lon"}
|
||||
|
||||
Terrarium encoding: height = R*256 + G + B/256 - 32768.
|
||||
Tiles: https://s3.amazonaws.com/elevation-tiles-prod/terrarium/{z}/{x}/{y}.png
|
||||
(open data, no key). Data (c) Mapzen/AWS Terrain Tiles contributors.
|
||||
"""
|
||||
import io
|
||||
import json
|
||||
import math
|
||||
import struct
|
||||
import sys
|
||||
import urllib.request
|
||||
|
||||
from PIL import Image
|
||||
|
||||
Z = 15
|
||||
URL = "https://s3.amazonaws.com/elevation-tiles-prod/terrarium/%d/%d/%d.png"
|
||||
|
||||
|
||||
def tile_of(lat, lon, z):
|
||||
n = 2 ** z
|
||||
xt = (lon + 180.0) / 360.0 * n
|
||||
lat_r = math.radians(lat)
|
||||
yt = (1.0 - math.asinh(math.tan(lat_r)) / math.pi) / 2.0 * n
|
||||
return xt, yt
|
||||
|
||||
|
||||
def tile_bounds(xt, yt, z):
|
||||
n = 2 ** z
|
||||
lon0 = xt / n * 360.0 - 180.0
|
||||
lat0 = math.degrees(math.atan(math.sinh(math.pi * (1 - 2 * yt / n))))
|
||||
return lat0, lon0
|
||||
|
||||
|
||||
def main():
|
||||
src, prefix = sys.argv[1], sys.argv[2]
|
||||
d = json.load(open(src))
|
||||
lats, lons = [], []
|
||||
for e in d["elements"]:
|
||||
for g in e.get("geometry") or []:
|
||||
lats.append(g["lat"])
|
||||
lons.append(g["lon"])
|
||||
if e.get("type") == "node" and "lat" in e:
|
||||
lats.append(e["lat"])
|
||||
lons.append(e["lon"])
|
||||
lo_lat, hi_lat = min(lats), max(lats)
|
||||
lo_lon, hi_lon = min(lons), max(lons)
|
||||
|
||||
x0, y1 = tile_of(lo_lat, lo_lon, Z) # south-west -> larger y tile index
|
||||
x1, y0 = tile_of(hi_lat, hi_lon, Z)
|
||||
tx0, tx1 = int(x0), int(x1)
|
||||
ty0, ty1 = int(y0), int(y1)
|
||||
cols = tx1 - tx0 + 1
|
||||
rows = ty1 - ty0 + 1
|
||||
print("bbox lat %.4f..%.4f lon %.4f..%.4f -> %dx%d tiles @z%d"
|
||||
% (lo_lat, hi_lat, lo_lon, hi_lon, cols, rows, Z))
|
||||
|
||||
mosaic = Image.new("RGB", (cols * 256, rows * 256))
|
||||
for ty in range(ty0, ty1 + 1):
|
||||
for tx in range(tx0, tx1 + 1):
|
||||
req = urllib.request.Request(URL % (Z, tx, ty),
|
||||
headers={"User-Agent": "BurnoutShitbox/1.0"})
|
||||
png = urllib.request.urlopen(req, timeout=60).read()
|
||||
mosaic.paste(Image.open(io.BytesIO(png)), ((tx - tx0) * 256, (ty - ty0) * 256))
|
||||
|
||||
# mosaic geographic bounds (tile edges, not the request bbox)
|
||||
m_hi_lat, m_lo_lon = tile_bounds(tx0, ty0, Z)
|
||||
m_lo_lat, m_hi_lon = tile_bounds(tx1 + 1, ty1 + 1, Z)
|
||||
|
||||
w, h = mosaic.size
|
||||
px = mosaic.load()
|
||||
out = open(prefix + "_dem.f32", "wb")
|
||||
lo, hi = 1e9, -1e9
|
||||
for yy in range(h):
|
||||
row = bytearray()
|
||||
for xx in range(w):
|
||||
r, g, b = px[xx, yy]
|
||||
hm = r * 256 + g + b / 256.0 - 32768.0
|
||||
hm = max(hm, 0.0) # clamp bathymetry: the river reads as 0, not -8
|
||||
lo, hi = min(lo, hm), max(hi, hm)
|
||||
row += struct.pack("<f", hm)
|
||||
out.write(row)
|
||||
out.close()
|
||||
json.dump({"w": w, "h": h, "min_lat": m_lo_lat, "max_lat": m_hi_lat,
|
||||
"min_lon": m_lo_lon, "max_lon": m_hi_lon},
|
||||
open(prefix + "_dem.json", "w"))
|
||||
print("wrote %s_dem.f32 (%dx%d, %.1f..%.1f m)" % (prefix, w, h, lo, hi))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@ -16,6 +16,7 @@ are actually crossing when you get there.
|
||||
"""
|
||||
import json
|
||||
import math
|
||||
import os
|
||||
import sys
|
||||
from itertools import zip_longest
|
||||
|
||||
@ -33,6 +34,36 @@ M_LON = 111320.0 * math.cos(math.radians(LAT0))
|
||||
def xz(lat, lon):
|
||||
return ((lon - LON0) * M_LON, -(lat - LAT0) * M_LAT)
|
||||
|
||||
# terrain heights (tools/fetch_dem.py output), pure-python bilinear -- events
|
||||
# bake spawn/convoy heights so the game never has to guess ground level
|
||||
from array import array
|
||||
DEM = None
|
||||
DEM_META = None
|
||||
_base = src[:-5] if src.endswith(".json") else src
|
||||
if os.path.exists(_base + "_dem.f32"):
|
||||
DEM_META = json.load(open(_base + "_dem.json"))
|
||||
DEM = array("f")
|
||||
with open(_base + "_dem.f32", "rb") as f:
|
||||
DEM.fromfile(f, DEM_META["w"] * DEM_META["h"])
|
||||
if sys.byteorder == "big":
|
||||
DEM.byteswap()
|
||||
|
||||
def hgt(x, z):
|
||||
if DEM is None:
|
||||
return 0.0
|
||||
lat = LAT0 - z / M_LAT
|
||||
lon = LON0 + x / M_LON
|
||||
w, h = DEM_META["w"], DEM_META["h"]
|
||||
u = (lon - DEM_META["min_lon"]) / (DEM_META["max_lon"] - DEM_META["min_lon"]) * (w - 1)
|
||||
v = (DEM_META["max_lat"] - lat) / (DEM_META["max_lat"] - DEM_META["min_lat"]) * (h - 1)
|
||||
u = min(max(u, 0.0), w - 1.001)
|
||||
v = min(max(v, 0.0), h - 1.001)
|
||||
x0, y0 = int(u), int(v)
|
||||
fx, fy = u - x0, v - y0
|
||||
a = DEM[y0 * w + x0] * (1 - fx) + DEM[y0 * w + x0 + 1] * fx
|
||||
b = DEM[(y0 + 1) * w + x0] * (1 - fx) + DEM[(y0 + 1) * w + x0 + 1] * fx
|
||||
return a * (1 - fy) + b * fy
|
||||
|
||||
data = json.load(open(src))
|
||||
ways = {}
|
||||
for e in data["elements"]:
|
||||
@ -88,13 +119,14 @@ def launch_point(pts, jpt):
|
||||
dx, dz = jpt[0] - end[0], jpt[1] - end[1]
|
||||
L = math.hypot(dx, dz) or 1.0
|
||||
dx, dz = dx / L, dz / L
|
||||
ey = round(hgt(end[0] - dz * LANE, end[1] + dx * LANE), 2)
|
||||
# Sit in a lane, not on the centreline. Convoys are offset +/-LANE either
|
||||
# side, so a centreline launch threads straight between them -- Grey x
|
||||
# Glenelg passed within 2.9 m of a convoy car and never touched one,
|
||||
# scoring nothing in 12 of 12 tuning runs. Same transform as offset().
|
||||
# sign matters: offsetting the other way moved the launch AWAY from the
|
||||
# convoy lane and widened Grey x Glenelg's closest pass from 2.9 m to 5.5 m
|
||||
return {"x": end[0] - dz * LANE, "z": end[1] + dx * LANE, "dx": dx, "dz": dz}
|
||||
return {"x": end[0] - dz * LANE, "z": end[1] + dx * LANE, "y": ey, "dx": dx, "dz": dz}
|
||||
|
||||
events = []
|
||||
for spec in sys.argv[5:]:
|
||||
@ -141,9 +173,10 @@ for spec in sys.argv[5:]:
|
||||
for i in range(len(near) - 1))
|
||||
if length < MIN_STREAM:
|
||||
continue
|
||||
by_street[street].append({"pts": offset(near, LANE), "speed": 12.0, "interval": 1.5})
|
||||
by_street[street].append({"pts": offset(list(reversed(near)), LANE),
|
||||
"speed": 11.0, "interval": 1.8})
|
||||
fwd_pts = [[px, pz, round(hgt(px, pz), 2)] for px, pz in offset(near, LANE)]
|
||||
rev_pts = [[px, pz, round(hgt(px, pz), 2)] for px, pz in offset(list(reversed(near)), LANE)]
|
||||
by_street[street].append({"pts": fwd_pts, "speed": 12.0, "interval": 1.5})
|
||||
by_street[street].append({"pts": rev_pts, "speed": 11.0, "interval": 1.8})
|
||||
if street == a:
|
||||
# OSM splits a street into many ways; only the one that actually
|
||||
# reaches the junction can define the launch, or we start 40 m
|
||||
|
||||
Loading…
Reference in New Issue
Block a user