b3d-city
A city to drive around, built from a seed: roads, blocks of buildings, street lights, parked cars, traffic and lit windows. The plan is city-layout; this dresses it with a kit, Kenney's city kits unless you give it another, at 12 m a cell. Street lights come on at dusk, each a spot pointing down from its pole (the few that matter most to your view are real lights), a few of them failing and flickering; a car you drive turns its headlights on.
Demo
import { b3d, b3dCar, b3dCity, cityStart, b3dLibrary, b3dLight, b3dSkybox, b3dSun, inputFocus, slider3d, assetUrl } from 'tosijs-3d'
import { tosi } from 'tosijs'
const { cityDemo } = tosi({ cityDemo: { time: 19.5, speed: 120 } })
const sky = b3dSkybox({ timeOfDay: cityDemo.time, realtimeScale: cityDemo.speed })
const plan = { width: 24, depth: 24, seed: 3 }
const start = cityStart(plan)
preview.append(
b3d(
{
style: 'width: 100%; height: 100%',
gamepad: 'left_stick,right_stick,left_trigger,right_trigger,right_bumper,A,X',
panelTitle: 'City',
scenePanel: () => [
slider3d({ label: 'time of day', value: cityDemo.time, min: 0, max: 24, step: 0.1 }),
slider3d({ label: 'time speed', value: cityDemo.speed, min: 0, max: 600, step: 10 }),
],
},
b3dSun({ shadowTextureSize: 2048 }),
b3dLight({ intensity: 0.5, nightIntensity: 0.06, groundColor: '#4b4d52' }),
sky,
b3dLibrary({ url: assetUrl('kenney/libraries/car-kit.glb'), type: 'cars' }),
b3dCity(plan),
inputFocus(
b3dCar({ library: 'cars', meshName: 'sedan-sports', scale: 1.7, player: true, ...start })
)
)
)
.preview { height: 100%; }
You start in the middle of the city, driving: the right trigger or W goes, the left trigger, the right bumper or S brakes and reverses, the left stick or A and D steer. Time runs at 120×, so night falls in a few minutes; the owl's panel sets the hour and the speed.
Attributes
| Attribute | Default | Description |
|---|---|---|
width, depth |
24 |
The grid, cells |
seed |
1 |
Same seed, same city |
cell |
12 |
Metres a cell (Kenney's road is 0.8 of a tile: 9.6 m kerb to kerb, a lane each way and a parked car) |
blockMin, blockMax |
3, 6 |
Block sizes, cells (see city-layout) |
downtown |
0.45 |
How far out from the middle the tall buildings go, 0 to 1 |
lightEvery |
2 |
A street light every this many road cells |
lampAngle |
80 |
A street light's cone, degrees; it reaches twice its height |
flicker |
0.08 |
The share of street lights that are failing and flicker |
parked |
0.2 |
The chance of a parked car on a stretch of road |
chunk |
0 |
Cells a side of a chunk. Each chunk draws its own copies, so the ones out of view are skipped; smaller chunks cull more and cost more draws. 0 draws the whole city as one, the default: measured in City Drive, 16-cell chunks doubled the draws and saved 3% of the triangles (a building is cheap; the trees are not) |
sound |
'on' |
Positional sound: the nearest traffic's engines and horns (a driver you block honks), the hum of the nearest street lights, a sputter from the failing ones. 'off' for silence |
traffic |
24 |
The car budget: this many cars drive round near you (they stop for yours, and are knocked about by it; lamps at night). Cars far away or out of view go, and come back out of view, driving toward you |
The city is centred on its x, y, z. kit (a property, not an
attribute) is the manifest: which library model is each road piece, building,
street light and car, how a model is turned and how big it is in cells. See
KENNEY_CITY for the shape; another kit on another grid needs only another
manifest. layout is the plan it built, lamps how many street lights it has.
cityStart(options) says where to put a car in the middle of the city.