California gets roads, traffic, and a car to follow
This commit is contained in:
+61
-6
@@ -73,6 +73,20 @@ interface Box {
|
||||
commercial: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* A named building's claim on the anonymous city scatter, in scene units.
|
||||
*
|
||||
* Circles are deliberately conservative. Anonymous buildings rotate with
|
||||
* their districts and named glyphs rotate with their streets; a circle is the
|
||||
* one cheap overlap test that cannot leave a corner poking through, and there
|
||||
* are only a handful of reservations to test.
|
||||
*/
|
||||
export interface BuildingReservation {
|
||||
x: number;
|
||||
z: number;
|
||||
radius: number;
|
||||
}
|
||||
|
||||
function polygonBounds(poly: [number, number][]) {
|
||||
let minLat = Infinity;
|
||||
let maxLat = -Infinity;
|
||||
@@ -87,7 +101,10 @@ function polygonBounds(poly: [number, number][]) {
|
||||
return { minLat, maxLat, minLng, maxLng };
|
||||
}
|
||||
|
||||
export function createBlocks(world: World): THREE.InstancedMesh {
|
||||
export function createBlocks(
|
||||
world: World,
|
||||
reservations: readonly BuildingReservation[] = [],
|
||||
): THREE.InstancedMesh {
|
||||
const boxes: Box[] = [];
|
||||
let seedBase = 1337;
|
||||
|
||||
@@ -165,15 +182,40 @@ export function createBlocks(world: World): THREE.InstancedMesh {
|
||||
// towers assemble their sites, and Salesforce Tower is about 5:1.
|
||||
const fill = isTower ? 1.5 + rand() * 0.7 : 0.78 + rand() * 0.18;
|
||||
|
||||
const width = LOT * fill;
|
||||
const depth = LOT * fill * (0.85 + rand() * 0.3);
|
||||
const rotation = angle + (rand() - 0.5) * 0.03;
|
||||
const color = new THREE.Color(
|
||||
palette[Math.floor(rand() * palette.length)] ?? 0xd9d3c6,
|
||||
);
|
||||
|
||||
/**
|
||||
* Keep a named building legible instead of drawing it inside a random
|
||||
* one at the same address.
|
||||
*
|
||||
* Every random property is drawn before this test. The sequence is
|
||||
* load-bearing: skipping those calls for one reserved lot would
|
||||
* reshuffle every anonymous building after it and turn a local change
|
||||
* into a whole new skyline.
|
||||
*/
|
||||
const radius = Math.hypot(width, depth) / 2;
|
||||
if (
|
||||
reservations.some(
|
||||
(reserved) => Math.hypot(x - reserved.x, z - reserved.z) < radius + reserved.radius,
|
||||
)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
boxes.push({
|
||||
x,
|
||||
z,
|
||||
y: world.groundAt(lat, lng),
|
||||
w: LOT * fill,
|
||||
d: LOT * fill * (0.85 + rand() * 0.3),
|
||||
w: width,
|
||||
d: depth,
|
||||
h: world.metres(heightM),
|
||||
rot: angle + (rand() - 0.5) * 0.03,
|
||||
color: new THREE.Color(palette[Math.floor(rand() * palette.length)] ?? 0xd9d3c6),
|
||||
rot: rotation,
|
||||
color,
|
||||
// A tower is an office whatever district it landed in.
|
||||
commercial: Math.min(1, commercial + (isTower ? 0.4 : 0)),
|
||||
});
|
||||
@@ -230,12 +272,25 @@ export function createBlocks(world: World): THREE.InstancedMesh {
|
||||
* specific silhouettes — a pyramid at Montgomery, a white finger on Telegraph
|
||||
* Hill, the red tripod on the ridge — and a box would not do.
|
||||
*/
|
||||
export function createLandmarks(world: World): THREE.Group {
|
||||
export function createLandmarks(
|
||||
world: World,
|
||||
reservations: readonly BuildingReservation[] = [],
|
||||
): THREE.Group {
|
||||
const group = new THREE.Group();
|
||||
group.name = "landmarks";
|
||||
|
||||
for (const lm of world.city.landmarks) {
|
||||
const [x, z] = world.project(lm.lat, lm.lng);
|
||||
// A richer stable glyph at this address supersedes the coarse landmark
|
||||
// primitive. Drawing both would hide the glyph inside the old mesh and
|
||||
// leave two different sources claiming the same real building.
|
||||
if (
|
||||
reservations.some(
|
||||
(reserved) => Math.hypot(x - reserved.x, z - reserved.z) < reserved.radius,
|
||||
)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
const base = world.groundAt(lm.lat, lm.lng);
|
||||
const h = world.metres(lm.height);
|
||||
const w = lm.footprint * world.lngScale * 2;
|
||||
|
||||
Reference in New Issue
Block a user