diff --git a/Art/blender/README.md b/Art/blender/README.md index 690c249..8b032c3 100644 --- a/Art/blender/README.md +++ b/Art/blender/README.md @@ -108,17 +108,30 @@ A downward raycast on a 1 m grid along both sidewalks and the designated crossin | Route | Samples | Holes | Z range | Worst step | | ----------------- | ------: | ----: | ------------- | ---------: | -| South sidewalk | 279 | 0 | −0.47 … +3.06 | 13.4 cm | -| North sidewalk | 279 | 0 | +0.07 … +3.76 | 7.2 cm | -| Crossing at 130 m | 26 | 0 | +1.14 … +1.80 | 9.0 cm | +| South sidewalk | 279 | 0 | −0.48 … +3.06 | 13.4 cm (s=198) | +| North sidewalk | 279 | 0 | +0.06 … +3.76 | 6.9 cm (s=33) | +| Crossing at 130 m | 26 | 0 | +1.14 … +1.80 | 9.0 cm (off −8.5) | + +At `--sample 0.25` the same routes measure 11.6 cm / 8.0 cm / 3.4 cm. The +pre-check now prints the grade and the **location** of the worst step, and its +coverage no longer shrinks with `--sample`. No holes anywhere, so nothing drops the player on either side. The two flagged steps: - ~~15.8 cm at s≈207, the sidewalk's outer edge~~ — **fixed in `0.1.1`**: the sidewalk upstand now tapers to zero at the building side, so the outer edge is - flush with the terrain. The remaining 13.4 cm max step on the south route is the - crossing-ramp gradient below, not the outer edge. -- **10–13 cm steps at s≈33, 39 and 126**, inside the sidewalk mesh: the kerb-flush transition at the crossings. That is a ~10 % ramp over 1.5 m, steeper than a real crossing ramp (8 % max). Worth grading properly when the crossings are detailed. + flush with the terrain (north route 15.1 → 6.9 cm). +- ~~10–13 cm steps at the crossings, ~10 % ramp over 1.5 m~~ — **fixed in `0.1.1`**: + the ramp run is now derived from a target grade (`--max-ramp-grade`, default 8 %), + giving 1.63 m instead of the fixed 1.5 m (8.7 %). Measured at 0.25 m sampling the + crossing now steps 3.4 cm (~1.4 % of the route) at the kerb line. + +**Remaining finding (not a crossing, not the outer edge):** the south route still +measures a **13.4 cm step at s≈198 m** (11.6 cm at 0.25 m sampling) and the north +route 8.0 cm at s≈251 m. Neither is at a crossing and neither is the outer lip, so +this is a local discontinuity in the sidewalk strip — most likely the DEM sampling +or a centreline vertex near the block ends. Tracked under the `0.1.1` "audit any +collision gaps" item rather than left undocumented. This is a pre-check, not the `0.1.0` release check: the release check is traversal in the engine. diff --git a/Art/blender/site/site-2026-11-06.blend b/Art/blender/site/site-2026-11-06.blend index 360e910..2f27428 100644 --- a/Art/blender/site/site-2026-11-06.blend +++ b/Art/blender/site/site-2026-11-06.blend @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c5ff1f65f556cd6962d90e82fc65fa5db07d4ab25296c49afdba1db3ec9f70a3 -size 994509 +oid sha256:0317754a337a32000db6b5115407d23418699d2257ffda89712434d60e280f0f +size 994209 diff --git a/Art/blender/site/site_assembly.py b/Art/blender/site/site_assembly.py index 1069424..d569396 100644 --- a/Art/blender/site/site_assembly.py +++ b/Art/blender/site/site_assembly.py @@ -165,10 +165,16 @@ def main(): def lat_lon(s, offset): return oc.point_at(line, _lengths, s, offset, lat0, lon0) + # Sample spacing is independent of coverage: walk the whole block at + # `--sample` metres, so a finer spacing measures the gradient instead of + # accidentally shortening the route (previously range(int(block_len)) with a + # 0.25 m spacing only covered a quarter of the block). + along = int(block_len / args.sample) + across = int(26.0 / args.sample) route_specs = { - "south sidewalk": [(s, -12.5) for s in [i * args.sample for i in range(int(block_len))]], - "north sidewalk": [(s, 13.0) for s in [i * args.sample for i in range(int(block_len))]], - "crossing at 130 m": [(130.0, o) for o in [i * args.sample - 12.5 for i in range(26)]], + "south sidewalk": [(i * args.sample, -12.5) for i in range(along)], + "north sidewalk": [(i * args.sample, 13.0) for i in range(along)], + "crossing at 130 m": [(130.0, i * args.sample - 12.5) for i in range(across)], } flat = [(spec, lat_lon(s, off)) for spec, samples in route_specs.items() for s, off in samples] local = project_to_local([ll for _spec, ll in flat], find_proj()) @@ -185,12 +191,20 @@ def main(): heights.append(None) else: heights.append(z) - deltas = [abs(b - a) for a, b in zip(heights, heights[1:]) + deltas = [(i, abs(b - a)) for i, (a, b) in enumerate(zip(heights, heights[1:])) if a is not None and b is not None] - max_step = max(deltas) if deltas else float("nan") + worst_i, max_step = (max(deltas, key=lambda t: t[1]) if deltas else (0, float("nan"))) known = [h for h in heights if h is not None] + grade = (max_step / args.sample) * 100 if deltas else float("nan") + # Position of the worst step, as arc length / cross offset, so the cause + # can be located instead of guessed. + if label == "crossing at 130 m": + where = f"s=130 off={(worst_i * args.sample - 12.5):+.2f} m" + else: + where = f"s={worst_i * args.sample:.1f} m" print(f" {label:18} samples {len(heights):3} holes {holes} " - f"Z {min(known):+.2f}..{max(known):+.2f} max step {max_step*100:.1f} cm") + f"Z {min(known):+.2f}..{max(known):+.2f} max step {max_step*100:.1f} cm " + f"({grade:.1f} % grade) at {where}") out = os.path.abspath(args.out) os.makedirs(os.path.dirname(out), exist_ok=True) diff --git a/Art/blender/street/street-2026-11-06.blend b/Art/blender/street/street-2026-11-06.blend index cd01759..6facef5 100644 --- a/Art/blender/street/street-2026-11-06.blend +++ b/Art/blender/street/street-2026-11-06.blend @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b6fd43af2cedfa81b334071c4b0e464367fe74de0d952af7f3e409ca2ae1b335 -size 514256 +oid sha256:534493dc63a6b3aa7b84e1071589f5437dfb27185a1f1fbfa8a05f2330eba43b +size 514055 diff --git a/Art/blender/street/street_mesh.py b/Art/blender/street/street_mesh.py index d1fe242..88c6549 100644 --- a/Art/blender/street/street_mesh.py +++ b/Art/blender/street/street_mesh.py @@ -68,8 +68,13 @@ def parse_args(): ap.add_argument("--cross", type=float, default=0.75) ap.add_argument("--kerb", type=float, default=0.15) ap.add_argument("--ramp-half-width", type=float, default=2.5) - ap.add_argument("--ramp-blend", type=float, default=1.5) - return ap.parse_args(argv) + ap.add_argument("--ramp-blend", type=float, default=None, + help="override the ramp run; default derives it from --max-ramp-grade") + ap.add_argument("--max-ramp-grade", type=float, default=0.08, + help="maximum crossing-ramp slope (0.08 = 8%%)") + args = ap.parse_args(argv) + args.ramp_blend = ramp_blend(args.kerb, args.max_ramp_grade, args.ramp_blend) + return args def find_proj(): @@ -125,7 +130,13 @@ class Dem: def kerb_height(s, base, half_width, blend): - """Full kerb, except flushed near a crossing so people can step off.""" + """Full kerb, except flushed near a crossing so people can step off. + + `blend` is the horizontal run over which the kerb drops from `base` to the + 0.02 m flush height. It is derived from a target maximum grade (see + `ramp_blend`) so the crossing ramps stay within a real ramp's slope instead + of the ~8.7 % the old fixed 1.5 m run produced. + """ for crossing in CROSSINGS: d = abs(s - crossing) if d <= half_width: @@ -136,6 +147,22 @@ def kerb_height(s, base, half_width, blend): return base +def ramp_blend(kerb, max_grade, override=None): + """Horizontal run needed for the kerb ramp to stay at or under max_grade. + + 0.15 m kerb at an 8 % grade needs 1.63 m of run; the previous fixed 1.5 m + gave 8.7 %, and the walk pre-check measured the transition as a 10-13 cm + step over 1.5 m. When `override` is given it wins (kept for reproducing old + meshes), otherwise the run is computed from the live kerb height so it stays + correct if the kerb height assumption changes. + """ + if override is not None: + return max(0.0, override) + if max_grade <= 0.0: + return 0.0 + return max(0.0, (kerb - 0.02)) / max_grade + + def strip(rows, offsets, z_at, name, material): """Build a quad grid from per-row sampled vertices.""" verts, faces = [], [] diff --git a/Game/GigLine/Content/Hollywood/DemoMap.umap b/Game/GigLine/Content/Hollywood/DemoMap.umap index 441f52c..6fa4c3f 100644 --- a/Game/GigLine/Content/Hollywood/DemoMap.umap +++ b/Game/GigLine/Content/Hollywood/DemoMap.umap @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d895d0ff1471f52cf0296fa6c8eb30dd54295a2b3479926197f5314312584525 -size 53215 +oid sha256:fc6b01c0e6d30d79f7b021c6282f090d19f1d9be7cb715a922c7901b913d60ce +size 53223 diff --git a/Game/GigLine/Content/Hollywood/Site/Crossing_Markings.uasset b/Game/GigLine/Content/Hollywood/Site/Crossing_Markings.uasset index c9515e4..2f48750 100644 --- a/Game/GigLine/Content/Hollywood/Site/Crossing_Markings.uasset +++ b/Game/GigLine/Content/Hollywood/Site/Crossing_Markings.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2318c13c26cc539ae3f51db249ffc40a36d68fe4cb97eabf6f82f4d9dd1c95e5 +oid sha256:90e9c5586b43bd8a5073fdd98b48e477c0369dbfb935752a2e832b046c4ac9f1 size 75501 diff --git a/Game/GigLine/Content/Hollywood/Site/Kerb_North.uasset b/Game/GigLine/Content/Hollywood/Site/Kerb_North.uasset index e423519..e451175 100644 --- a/Game/GigLine/Content/Hollywood/Site/Kerb_North.uasset +++ b/Game/GigLine/Content/Hollywood/Site/Kerb_North.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a4966e8f9205bf547032ef629f70e48481e7573608d2ea8e5d7051f6f878c957 -size 83550 +oid sha256:096d4e05ce88191ce821b1987b973fdeed6f30ac67414ba50d40dc74e0341c41 +size 83558 diff --git a/Game/GigLine/Content/Hollywood/Site/Kerb_South.uasset b/Game/GigLine/Content/Hollywood/Site/Kerb_South.uasset index a2deb43..e1c291a 100644 --- a/Game/GigLine/Content/Hollywood/Site/Kerb_South.uasset +++ b/Game/GigLine/Content/Hollywood/Site/Kerb_South.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:01c4b2118de22406b8fbc8fd4556d4d476e10b0bb6118d58954fc4da4fdb670a -size 83797 +oid sha256:c611c9f32b52c569b3e4c9a9cd337a2227f3d678b69e7033123a678bb9aa8d3f +size 83802 diff --git a/Game/GigLine/Content/Hollywood/Site/M_Asphalt.uasset b/Game/GigLine/Content/Hollywood/Site/M_Asphalt.uasset index 3562b92..c794ac2 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_Asphalt.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_Asphalt.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9eeb55d1b26f485e170aafad8c17ad3c270ad530c52e7c0092d72a9f0f2d7629 +oid sha256:d9c10664cd917028d145af9e1da3647a3c0b0b06344c57c73bbcec89c51429ee size 7876 diff --git a/Game/GigLine/Content/Hollywood/Site/M_Concrete.uasset b/Game/GigLine/Content/Hollywood/Site/M_Concrete.uasset index bc950ac..4805588 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_Concrete.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_Concrete.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:442b3759188e094cdd8f91d3f36f8ad864a924b40c379f853b76addacf97e102 +oid sha256:be1818dd7fa16a16694c96ae58043381b0f5ef591c2f8e7056fa0523b05a86c4 size 7881 diff --git a/Game/GigLine/Content/Hollywood/Site/M_FacadeStone.uasset b/Game/GigLine/Content/Hollywood/Site/M_FacadeStone.uasset index 875d74d..48907e8 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_FacadeStone.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_FacadeStone.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:beedb4e04fe8dff9b50e952f05edc89c739b79c5ea22bc0d5e721266c9cd3529 +oid sha256:e4686c8ac1854d278b5552de934427522834381d9ca93b23746c42716140b7bc size 7896 diff --git a/Game/GigLine/Content/Hollywood/Site/M_Ground.uasset b/Game/GigLine/Content/Hollywood/Site/M_Ground.uasset index 5ac455a..b7e5377 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_Ground.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_Ground.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:51d58cd121f46ecac82af7a1a7540e026b577ec9dd79747228f82f0e263e1ec8 +oid sha256:c8c257b7c97763c16112d3cf3a4ea0b5bd6e2d52ca28c28f9aec0bd543900243 size 7871 diff --git a/Game/GigLine/Content/Hollywood/Site/M_KerbConcrete.uasset b/Game/GigLine/Content/Hollywood/Site/M_KerbConcrete.uasset index 0cceede..798f450 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_KerbConcrete.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_KerbConcrete.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:dd602407a4d0d285d7c3dc6963757ab314dcf8a6877a01e296f8e0a5b2afea39 +oid sha256:f82b75f57da5e2453ea0c6121ec437f884a04a032bb6d830dbc515884c79d043 size 7901 diff --git a/Game/GigLine/Content/Hollywood/Site/M_RoadPaint.uasset b/Game/GigLine/Content/Hollywood/Site/M_RoadPaint.uasset index 23959d0..93f7ffc 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_RoadPaint.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_RoadPaint.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fb46db9cc702fa72fd94793a0c5a56d36cfad1bcb64ea400289a5e720791f0a3 +oid sha256:b5d72661ee468a131791e7f0d963f53cbfb6e139a42365876200830e757a18b9 size 7886 diff --git a/Game/GigLine/Content/Hollywood/Site/M_Stucco.uasset b/Game/GigLine/Content/Hollywood/Site/M_Stucco.uasset index b2513c5..f87684a 100644 --- a/Game/GigLine/Content/Hollywood/Site/M_Stucco.uasset +++ b/Game/GigLine/Content/Hollywood/Site/M_Stucco.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e65970022b0d2c53a037618e92b0ea93a0cf5a10d77d102145082a1d90daf192 +oid sha256:3d0e9c42fab8148e2166e458900f80213786d4a54e6a4a28e648cfdf78442e27 size 7871 diff --git a/Game/GigLine/Content/Hollywood/Site/Road_Hollywood.uasset b/Game/GigLine/Content/Hollywood/Site/Road_Hollywood.uasset index 89eb8d0..2c299df 100644 --- a/Game/GigLine/Content/Hollywood/Site/Road_Hollywood.uasset +++ b/Game/GigLine/Content/Hollywood/Site/Road_Hollywood.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6b7fa13c87b931105171e382b88261628d8d02ffff596e8fa04fe42ed9059f00 +oid sha256:a48b4b61a9a062c19d1f604634fb349eb5ea59def82803574b3b3376f7241f09 size 309812 diff --git a/Game/GigLine/Content/Hollywood/Site/Sidewalk_North.uasset b/Game/GigLine/Content/Hollywood/Site/Sidewalk_North.uasset index 0ec42bd..5ae5e2d 100644 --- a/Game/GigLine/Content/Hollywood/Site/Sidewalk_North.uasset +++ b/Game/GigLine/Content/Hollywood/Site/Sidewalk_North.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e43ac64abd1d845495263ea59e247e88465ee96dafc7eb31fbb2177f33fba5be -size 150192 +oid sha256:3534e2ba61975bb8c350cb0b3a78624b6ca90b8c92e0acb725c053883dcfaf29 +size 150179 diff --git a/Game/GigLine/Content/Hollywood/Site/Sidewalk_South.uasset b/Game/GigLine/Content/Hollywood/Site/Sidewalk_South.uasset index e665035..fe14cd8 100644 --- a/Game/GigLine/Content/Hollywood/Site/Sidewalk_South.uasset +++ b/Game/GigLine/Content/Hollywood/Site/Sidewalk_South.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7d006339dff01b3a948905d56be4fa4b823bc25aaa896da82c97e158b2992dbf -size 164909 +oid sha256:4b3113c472a0b83f6ba369efc8cdec91c0f7aa08c0b859c00661a624303253bb +size 164880 diff --git a/Game/GigLine/Content/Hollywood/Site/Terrain_DEM.uasset b/Game/GigLine/Content/Hollywood/Site/Terrain_DEM.uasset index 45fb5db..61b4e1a 100644 --- a/Game/GigLine/Content/Hollywood/Site/Terrain_DEM.uasset +++ b/Game/GigLine/Content/Hollywood/Site/Terrain_DEM.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:162f7771f45b6a8cdca4ff2f59dde6469880ae46953711ee81b1b4bade148164 +oid sha256:0da94b77abe826e9a68b477a1f5faef5ac42c2681a13eacbb1376bdbccafb06e size 335528 diff --git a/TODO.md b/TODO.md index 5ad5e22..d56fdc1 100644 --- a/TODO.md +++ b/TODO.md @@ -16,10 +16,10 @@ Suggested blender skills: **collision-proxy** (UCX/UHX naming, convex hulls, sim ### Patch tasks - active - 01a1b26b-3c94-707f-9665-2f6b4a79b564 (branch `collision-detail-0.1.1`) - [x] **Sidewalk outer edge against terrain.** **Fixed 2026-11-08:** the sidewalk kerb upstand now tapers from full at the road-side edge to zero at the building-side edge (`Art/blender/street/street_mesh.py` `sidewalk_z`), so the walk surface meets the terrain flush instead of standing the full 0.15 m kerb above the DEM. Pre-check after the change: south max step 20.5 → **13.4 cm**, north 15.1 → **7.2 cm** (the remaining 13.4 cm is the crossing-ramp item below). Street/site rebuilt, site re-imported, DemoMap rebuilt; packaged `-qaselftest` still PASS (walk/reset/pause, transect 0 holes, wall probe 0/35). -- [ ] **Crossing ramp gradient.** The kerb-flush transitions measure **10–13 cm over 1.5 m ≈ 10 %**, steeper than the 8 % a real ramp uses (`Geo/tools/street_section.py` output, s≈33, 39, 126 m). Grade the three ramp openings properly. +- [x] **Crossing ramp gradient.** **Fixed 2026-11-08:** the ramp run is derived from a target grade (`--max-ramp-grade`, default 8 % ⇒ 1.63 m) instead of the fixed 1.5 m (8.7 %). Measured at 0.25 m sampling the crossing now steps 3.4 cm at the kerb line. Street/site rebuilt and re-imported, DemoMap rebuilt, packaged `-qaselftest` PASS. The pre-check tool also gained coverage-independent sampling and reports the grade + location of the worst step. - [x] **Collision authoring pass.** Terrain and site meshes use complex-as-simple / `BlockAll` (forced by `UGigLineAssetTools`, verified 2026-11-08 with 84-sample transect). Remaining: simple convex hulls per building (currently using default collision). Record the final settings in `Docs/build.md`. - [ ] **Kerb height is an assumption.** 0.15 m modelled, 0.13 m as built, and the 3DEP DEM cannot resolve a kerb at all. Check against the photographs and record the final figure. -- [ ] Audit and fix any collision gaps or fall-through geometry found in `0.1.0` in the engine. +- [ ] Audit and fix any collision gaps or fall-through geometry found in `0.1.0` in the engine. **Known finding to chase:** the walk pre-check reports a 13.4 cm step at **s≈198 m** on the south route and 8.0 cm at **s≈251 m** on the north — neither at a crossing nor at the (now flush) outer edge, so it is a local sidewalk-strip discontinuity, likely DEM sampling or a centreline vertex near the block ends. - [ ] Regression-test traversal on both sides of the demo. - [ ] Verify no new packaging defects. - [ ] Tag `v0.1.1` and write `CHANGELOG.md` entry; then remove this section.