makepad/libs/model/VEHICLE_API.md
Admin d2130e6550 libs: model, mesh_edit, csg, scene, sim, render, xr
Squash of 25 work commits (Sep 1–12):
  237da90  render: the sprite lane hands the screen draw back the way it found it
  895b9a7  particles: an emitter can ride a body's own frame
  914471f  ai-hub: a feed session whose last socket left ends on its idle timeout; skin: parent, skinned centroid and a nodes-only rig for retargets
  3fcccf3  sim: the whole world is implicitly editable, and one seam says where the ground is
  5692fab  sim: the landform world proves itself — walker through the tunnel included
  f4af6df  sim: terrain knows who changed it — a plan layer over player history
  adbb078  render: a water volume can be physics without a picture
  c17480f  render: a non-rigid body may carry its own orientation
  acad401  sim: an agent with no route holds and retries instead of walking into the wall
  22b2bf9  sim + chat: the composed world surface takes a map floor; the chat gets plan tools
  faf8112  web path: the tessellator's lap timer, the trace span and the fusion cycle timer have no clock on the web
  d3472eb  tsdf: the clock-taking XR helpers are native-only — the browser has no depth camera and no Instant
  4946c9e  sim + render: a repaint is not a world edit — colour and glow restyles never rebake the lightmap
  4317f58  sim + render + chat: walk decks as a surface, the filmed body is no obstruction, the brief never asks
  9791279  render: support rigged models and custom materials across viewers
  3ce2792  sim: use deck geometry for collision and sensing
  c8b79ff  Add portable PBR, rig and soft-body authoring support
  108d423  Add transactional polygon modeling and editable asset documents
  38f4d3b  Refine editable modeling and firm yarn character behavior
  08a2637  sim: add entity-owned lights and vehicle headlights
  00d96a7  render: add clustered lights, local shadows and incremental GI
  cf916af  render: import glTF asset extensions and wire clustered GI
  c6d2cca  model: cut transaction memory and raise capacity limits
  41af47a  raytrace: add a CPU probe-ray BVH budget example
  c963d0a  libs: the game sim splits into makepad-scene and makepad-soft-body; render, model, fab and the asset importer retarget

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-15 13:40:31 +02:00

5.1 KiB

Editable vehicles

Build the actual car geometry and materials with model operations, then bind four separate tire objects. These operations use ordinary transactional model.apply; the source document, undo history and published GLB preserve them.

{"op":"vehicle_wheel","object":"front_left_tire",
 "connection":"wheel_front_left","pivot":[0,0,0],"radius":0.35,"width":0.22}

delete_vehicle_wheel {object} removes a binding without deleting its mesh. vehicle_wheel replaces that object's existing binding. The four distinct connections are wheel_front_left, wheel_front_right, wheel_rear_left, and wheel_rear_right. An object can have one binding, with at most four per document. Ordinary assets with no wheel bindings compile normally; a vehicle with any bindings requires all four before compilation/publication.

Author in metres with Y up, the nose towards +Z, and the driver's left towards +X. Front anchors must be ahead of their rear anchors in Z; left anchors must have larger X than right anchors. The vehicle runtime rotates this model by 180 degrees around Y into its driving direction, engine -Z.

Each wheel's rotation axle is object-local X. The cylinder primitive's axle is Y, so rotate its geometry onto X using a mesh transform before binding. For example, the row-major matrix [[0,-1,0,0],[1,0,0,0],[0,0,1,0],[0,0,0,1]] rotates a cylinder onto X. Place it with object_node translation and optionally parent it to the body. Wheel node world transforms support translation and positive uniform scale; rotated or nonuniform node bases are refused. Use geometry transforms for the axle orientation. Wheel descendants may contain additional rigid rim geometry, but cannot contain another wheel binding.

pivot is the wheel centre in object-local coordinates. Export computes its model-space anchor through the object hierarchy. radius and width are positive model-space metre measurements, at most 10,000; update them after scaling geometry. Pivot edits preserve the anchor. The wheel object must have exported faces. Skin skeletons and driven wheel bindings cannot be combined. Geometry remains editable; tire UVs and material layers use the ordinary paths.

Export writes the runtime contract directly on the wheel's glTF node: extras: {kind:"vehicle_wheel",connection,pivot,anchor,radius,width}. The renderer separates that geometry from the static body stream. Sandbox fits its four suspension probes to the declared anchors/radii, then renders steering, spin, suspension travel and detached wheels through the same binding. A generic named socket is an attachment marker and does not animate a tire.

For headlights, use actual light operations attached to the body. Place them near the +Z nose. A spot emits along its local -Z, so use rotation [0,1,0,0] to aim it towards the car's +Z front. Example:

{"op":"light","name":"headlight_left","attachment":{"object":"body"},
 "transform":{"translation":[0.6,0.15,2.0],"rotation":[0,1,0,0]},
 "kind":"spot","inner":0.12,"outer":0.4,
 "color":[1,0.9,0.7],"intensity":150,"range":30}

Intensity is candela, range metres, cone half-angles radians. The full car instance transform places both mesh and emitters; model scale does not change light intensity or range. Use an emissive material for a visibly glowing lamp surface as well. For a daylight game, start the lens around emissive strength 0.1 and compare its highlights and beam against the sun before increasing it. Keep lens color, metallic and roughness explicit when using surface_material: omitted factors reset to defaults, including emissive RGB zero. Authored lights remain independent of the gameplay command that toggles generic entity headlights. The host automatically suppresses its two generic headlights when the installed exterior has authored emitters; independent script lights remain available.

Publish the finished asset and use its returned reference for the actual car spawn, with explicit chassis dimensions matching the authored exterior length. The chassis remains the physics body; model length determines the common visual/wheel scale. Seats use the existing vehicle seat count/placement. Named seat sockets and door meshes can be authored, but do not automatically replace gameplay seat placement or supply an opening-door interaction.

Visual steering and suspension

vehicle_wheel accepts optional visual:{steer_gain:0.55,steer_max:0.32,compression:0.08,droop:0.10}. All fields are required together: gain 0..1, angle cap 0..1.2 radians, compression/droop 0..5 model metres. Display steering is clamp(physical steering*gain, -cap, cap); display suspension is clamped to -droop..compression. This affects only visible geometry. Turning radius, tire forces, physical suspension, anchors, radii and spin are unchanged. Without visual metadata, existing motion and source serialization remain unchanged.

The authored limits travel with the shared asset and are used by both the game renderer and model.render. Preserve the intended body silhouette, select an appropriate display range, and verify real clearance within that range. Do not grow giant fenders solely to pass the legacy diagnostic pose.