diff --git a/docs/tracks.html b/docs/tracks.html index d93ce10..a72c7d2 100644 --- a/docs/tracks.html +++ b/docs/tracks.html @@ -208,7 +208,7 @@ h1 em { font-style: normal; color: var(--sys); }
-
+

Paingod's Passage

pain

@@ -217,14 +217,14 @@ h1 em { font-style: normal; color: var(--sys); }
Instances
255
Cameras
18
Start boxes
12
-
Extent
1779 × 7228
-
Relief
240
+
Extent
624 × 7223
+
Relief
162
-

244 of 255 placements carry map art; the rest the map screen does not draw either

+

241 of 255 placements are drawn; the rest carry no map art or stand alone off the course

-
+

Blade's Edge

blade

@@ -233,14 +233,14 @@ h1 em { font-style: normal; color: var(--sys); }
Instances
216
Cameras
21
Start boxes
7
-
Extent
1335 × 6791
+
Extent
213 × 6786
Relief
334
-

203 of 216 placements carry map art; the rest the map screen does not draw either

+

202 of 216 placements are drawn; the rest carry no map art or stand alone off the course

-
+

Yip's Yahoorama

yip

@@ -249,14 +249,14 @@ h1 em { font-style: normal; color: var(--sys); }
Instances
127
Cameras
20
Start boxes
17
-
Extent
1540 × 5964
+
Extent
524 × 5961
Relief
432
-

114 of 127 placements carry map art; the rest the map screen does not draw either

+

113 of 127 placements are drawn; the rest carry no map art or stand alone off the course

-
+

Berserker's Bahnzai

otto

@@ -265,14 +265,14 @@ h1 em { font-style: normal; color: var(--sys); }
Instances
203
Cameras
24
Start boxes
16
-
Extent
1329 × 5878
+
Extent
219 × 5873
Relief
442
-

190 of 203 placements carry map art; the rest the map screen does not draw either

+

189 of 203 placements are drawn; the rest carry no map art or stand alone off the course

-
+

Firestorm's Fury

frstrm

@@ -281,14 +281,14 @@ h1 em { font-style: normal; color: var(--sys); }
Instances
325
Cameras
20
Start boxes
15
-
Extent
1329 × 5878
+
Extent
219 × 5873
Relief
382
-

312 of 325 placements carry map art; the rest the map screen does not draw either

+

311 of 325 placements are drawn; the rest carry no map art or stand alone off the course

-
+

Wiseguy's Wake

wise

@@ -297,14 +297,14 @@ h1 em { font-style: normal; color: var(--sys); }
Instances
133
Cameras
16
Start boxes
9
-
Extent
1744 × 5713
-
Relief
386
+
Extent
231 × 5708
+
Relief
90
-

Same footprint and instance count as -- Wiserguy's --

120 of 133 placements carry map art; the rest the map screen does not draw either

+

Same footprint and instance count as -- Wiserguy's --

118 of 133 placements are drawn; the rest carry no map art or stand alone off the course

-
+

Burnt Cookies

burnt

@@ -313,14 +313,14 @@ h1 em { font-style: normal; color: var(--sys); }
Instances
251
Cameras
17
Start boxes
3
-
Extent
1589 × 5447
-
Relief
469
+
Extent
589 × 5444
+
Relief
467
-

240 of 251 placements carry map art; the rest the map screen does not draw either

+

239 of 251 placements are drawn; the rest carry no map art or stand alone off the course

-
+

Brewer's Bane

brewers

@@ -329,14 +329,14 @@ h1 em { font-style: normal; color: var(--sys); }
Instances
607
Cameras
20
Start boxes
20
-
Extent
3160 × 4532
-
Relief
299
+
Extent
3158 × 4529
+
Relief
297
-

595 of 607 placements carry map art; the rest the map screen does not draw either

+

594 of 607 placements are drawn; the rest carry no map art or stand alone off the course

-
+

Lyz's Lane

lyzlane

@@ -345,14 +345,14 @@ h1 em { font-style: normal; color: var(--sys); }
Instances
105
Cameras
12
Start boxes
44
-
Extent
1387 × 4175
+
Extent
251 × 4170
Relief
313
-

94 of 105 placements carry map art; the rest the map screen does not draw either

+

93 of 105 placements are drawn; the rest carry no map art or stand alone off the course

-
+

Freezemoon's Freeway

headoff

@@ -361,14 +361,14 @@ h1 em { font-style: normal; color: var(--sys); }
Instances
264
Cameras
18
Start boxes
5
-
Extent
1589 × 5047
-
Relief
247
+
Extent
589 × 5044
+
Relief
200
-

251 of 264 placements carry map art; the rest the map screen does not draw either

+

250 of 264 placements are drawn; the rest carry no map art or stand alone off the course

-
+

Freezemoon's Freeway (Football)

headmf

@@ -377,14 +377,14 @@ h1 em { font-style: normal; color: var(--sys); }
Instances
274
Cameras
18
Start boxes
5
-
Extent
1589 × 5047
-
Relief
247
+
Extent
589 × 5044
+
Relief
200
-

263 of 274 placements carry map art; the rest the map screen does not draw either

+

262 of 274 placements are drawn; the rest carry no map art or stand alone off the course

-
+

-- Tour De Mars --

tourdemars

@@ -393,14 +393,14 @@ h1 em { font-style: normal; color: var(--sys); }
Instances
607
Cameras
20
Start boxes
20
-
Extent
1387 × 23303
+
Extent
1187 × 23298
Relief
415
-

595 of 607 placements carry map art; the rest the map screen does not draw either

+

594 of 607 placements are drawn; the rest carry no map art or stand alone off the course

-
+

-- Donut --

donut

@@ -409,14 +409,14 @@ h1 em { font-style: normal; color: var(--sys); }
Instances
325
Cameras
20
Start boxes
15
-
Extent
3289 × 9697
-
Relief
129
+
Extent
3289 × 9694
+
Relief
124
-

314 of 325 placements carry map art; the rest the map screen does not draw either

+

313 of 325 placements are drawn; the rest carry no map art or stand alone off the course

-
+

-- Ares' Armpits --

trough

@@ -425,14 +425,14 @@ h1 em { font-style: normal; color: var(--sys); }
Instances
633
Cameras
16
Start boxes
9
-
Extent
1387 × 9219
-
Relief
540
+
Extent
322 × 9217
+
Relief
530
-

582 of 633 placements carry map art; the rest the map screen does not draw either

+

580 of 633 placements are drawn; the rest carry no map art or stand alone off the course

-
+

-- Zaxxis --

rpweekend2014

@@ -441,14 +441,14 @@ h1 em { font-style: normal; color: var(--sys); }
Instances
695
Cameras
40
Start boxes
3
-
Extent
3389 × 5962
+
Extent
3389 × 5959
Relief
266
-

678 of 695 placements carry map art; the rest the map screen does not draw either

+

678 of 695 placements are drawn; the rest carry no map art or stand alone off the course

-
+

-- Wiserguy's --

wiserguys

@@ -457,14 +457,14 @@ h1 em { font-style: normal; color: var(--sys); }
Instances
133
Cameras
16
Start boxes
9
-
Extent
1744 × 5713
-
Relief
435
+
Extent
231 × 5708
+
Relief
138
-

Same footprint and instance count as Wiseguy's Wake

119 of 133 placements carry map art; the rest the map screen does not draw either

+

Same footprint and instance count as Wiseguy's Wake

117 of 133 placements are drawn; the rest carry no map art or stand alone off the course

-
+

-- Arena (Large) --

demoderb

@@ -473,14 +473,14 @@ h1 em { font-style: normal; color: var(--sys); }
Instances
455
Cameras
17
Start boxes
3
-
Extent
2197 × 1997
+
Extent
2000 × 1995
Relief
0
-

438 of 455 placements carry map art; the rest the map screen does not draw either

+

437 of 455 placements are drawn; the rest carry no map art or stand alone off the course

-
+

-- Arena (Small) --

arena

@@ -489,10 +489,10 @@ h1 em { font-style: normal; color: var(--sys); }
Instances
695
Cameras
17
Start boxes
3
-
Extent
1844 × 1855
+
Extent
1844 × 1850
Relief
55
-

678 of 695 placements carry map art; the rest the map screen does not draw either

+

678 of 695 placements are drawn; the rest carry no map art or stand alone off the course

@@ -505,6 +505,17 @@ h1 em { font-style: normal; color: var(--sys); } rotated and positioned. A placement whose model has no gauge image is skipped here exactly as the map screen skips it, which is why a card can say fewer placements carry map art than the track contains.

+

Two things are drawn plainer than the pod draws them, so the plan reads + as an outline. Nearly every track is one model repeated — cn3, a + wall bar whose gauge image is two closed 25×5 rectangles. Five metres of wall + thickness is finer than the plan can resolve, so each bar is collapsed to the + centreline between its short edges: one stroke for one wall, instead of two parallel + lines and two end caps several hundred times over. Walls stacked to build height land + on each other seen from above, and are drawn once. Placements standing alone more than + 200 units from any other are dropped — fourteen tracks park a single bar at + (1200, 0, 0) far off the course, and one stray placement stretches the frame + to twelve times the width of the track. A real branch keeps its neighbours and stays: + Paingod's second canyon is sixty bars out at x = -400.

So the walls are the canyon walls and the chambers are real chambers, but there is still no driving surface: the map draws what lines the route, never the tarmac. Extent and relief are the span of the drawn outlines in world units, so a diff --git a/tools/pages/build_tracks.py b/tools/pages/build_tracks.py index 197fe8c..1b0e8af 100644 --- a/tools/pages/build_tracks.py +++ b/tools/pages/build_tracks.py @@ -86,7 +86,7 @@ def era(key): GAUGE_IDS = {rid for rid, r in TABLE.items() if r['desc'].endswith(': GaugeImage')} -def plan_view(segs, box=900): +def plan_view(segs, box=520): """The track's own outlines, straight down, as an alpha mask.""" pts = [p for seg in segs for p in seg] xs = [p[0] for p in pts] @@ -171,9 +171,9 @@ for key in ORDER: kin = [k for k in twins.get(sig, []) if k != key] twin = ('

Same footprint and instance count as ' + ', '.join(tracks[k]['name'] for k in kin) + '

') if kin else '' - short = ('

%d of %d placements carry map art; the rest the ' - 'map screen does not draw either

' % (t['drawn'], t['instances']) - ) if t['skipped'] else '' + short = ('

%d of %d placements are drawn; the rest carry no ' + 'map art or stand alone off the course

' + % (t['drawn'], t['instances'])) if t['skipped'] else '' art = ('' % (html.escape(t['name']), t['art'], t['aw'], t['ah'])) if t['art'] else '' diff --git a/tools/pages/navmap.py b/tools/pages/navmap.py index f36124a..2fa3d7f 100644 --- a/tools/pages/navmap.py +++ b/tools/pages/navmap.py @@ -100,6 +100,29 @@ def instances(res, addr, size, count, gauge_ids): return out +def spine(seg): + """A track is built almost entirely from one model, cn3: a wall bar + drawn as two closed 25x5 rectangles. Five metres of wall thickness is + below the map's own resolution, so drawing the rectangle puts two + parallel lines and two end caps where the wall is one line - and a few + hundred bars of that is the hatching that swamps the plan. Collapse a + thin closed quad to the centreline joining its two short edges: the + same wall, drawn as the single stroke it reads as.""" + p = seg[:-1] if len(seg) >= 5 and seg[0] == seg[-1] else None + if not p or len(p) != 4: + return [seg] + import math + edge = [math.hypot(p[(i + 1) % 4][0] - p[i][0], + p[(i + 1) % 4][2] - p[i][2]) for i in range(4)] + if max(edge) == 0 or min(edge) / max(edge) > 0.5: + return [seg] # not a bar - leave it alone + lo = min(range(4), key=lambda i: edge[i]) + a, b = p[lo], p[(lo + 1) % 4] + c, d = p[(lo + 2) % 4], p[(lo + 3) % 4] + mid = lambda u, v: tuple((u[k] + v[k]) / 2 for k in range(3)) + return [[mid(a, b), mid(c, d)]] + + def rotate(q, p): """Quaternion (x,y,z,w) applied to a point.""" qx, qy, qz, qw = q @@ -120,10 +143,29 @@ def track_lines(res, table, map_addr, map_size, map_count): gauge[rid] = r segs = [] drawn = skipped = 0 - for gid, pos, q in instances(res, map_addr, map_size, map_count, set(gauge)): + placed = instances(res, map_addr, map_size, map_count, set(gauge)) + + # Fourteen of the eighteen tracks carry a single bar parked at exactly + # (1200, 0, 0), well off the course; the four that don't are the four + # that always framed correctly. One stray placement drags the bounding + # box out to twelve times the width of the course and squeezes the + # track into a sliver, so drop placements that stand alone. A real + # branch - Paingod's second canyon is sixty bars out at x=-400 - has + # neighbours and stays. + def isolated(i): + x, _, z = placed[i][1] + for j, (g, p, _) in enumerate(placed): + if j != i and g is not None and (p[0] - x) ** 2 + (p[2] - z) ** 2 < 200 ** 2: + return False + return True + + for i, (gid, pos, q) in enumerate(placed): if gid is None: skipped += 1 continue + if isolated(i): + skipped += 1 + continue r = gauge[gid] img = read_gauge_image(res, r['addr'], r['size']) if img is None: @@ -138,5 +180,14 @@ def track_lines(res, table, map_addr, map_size, map_count): wx, wy, wz = rotate(q, verts[k]) pts.append((wx + pos[0], wy + pos[1], wz + pos[2])) if len(pts) > 1: - segs.append(pts) - return segs, drawn, skipped + segs.extend(spine(pts)) + + # Walls are stacked to build height. Seen from above those copies land + # on each other exactly, so draw each distinct wall once. + seen, out = set(), [] + for s in segs: + key = tuple(round(v, 1) for p in s for v in (p[0], p[2])) + if key not in seen: + seen.add(key) + out.append(s) + return out, drawn, skipped diff --git a/tools/pages/tracks.tpl b/tools/pages/tracks.tpl index 438fbb8..1498ccf 100644 --- a/tools/pages/tracks.tpl +++ b/tools/pages/tracks.tpl @@ -50,6 +50,17 @@ rotated and positioned. A placement whose model has no gauge image is skipped here exactly as the map screen skips it, which is why a card can say fewer placements carry map art than the track contains.

+

Two things are drawn plainer than the pod draws them, so the plan reads + as an outline. Nearly every track is one model repeated — cn3, a + wall bar whose gauge image is two closed 25×5 rectangles. Five metres of wall + thickness is finer than the plan can resolve, so each bar is collapsed to the + centreline between its short edges: one stroke for one wall, instead of two parallel + lines and two end caps several hundred times over. Walls stacked to build height land + on each other seen from above, and are drawn once. Placements standing alone more than + 200 units from any other are dropped — fourteen tracks park a single bar at + (1200, 0, 0) far off the course, and one stray placement stretches the frame + to twelve times the width of the track. A real branch keeps its neighbours and stays: + Paingod's second canyon is sixty bars out at x = -400.

So the walls are the canyon walls and the chambers are real chambers, but there is still no driving surface: the map draws what lines the route, never the tarmac. Extent and relief are the span of the drawn outlines in world units, so a