Editable GPU meshes — engine v13 Check getGPUCapabilities().gpuMeshEditing. Refresh Game after deployment. All commands return Promises; await dependencies. These are geometry tools, not an elastic-material solver. No automatic Rigidbody/collider changes. Create a subdivided mesh whose vertices can be edited on the GPU. await createGPUMesh("sheet", "grid", { size: {x: 6, y: 1, z: 4}, origin: {x: 0, y: 3, z: 0}, resolution: 32 }); Shapes: grid (XZ plane), sphere (ellipsoid), box (six subdivided faces). size means full dimensions; grid ignores size.y. Resolution2..64. World-space positions. Source buffers: positions/restPositions/normals/restNormals (xyz), uv (xy), weights (one scalar per vertex), triangles (u32 triples), faceStarts/ faceLinks (fixed adjacency). Remove with removeGPUProgram("sheet"). Uses the existing four-program/128MiB typed-buffer budget. Copy one static mesh from a loaded CS object or scenery object. var info = await importGPUMesh("editable", "objectname", {meshIndex: 0, submesh: 0}); info.vertices; info.triangleCount; info.pivot; Select one MeshFilter and triangle submesh; readable source required. Limit65536 source vertices/131072 triangles. World transform, selected UVs and base color are copied/snapshotted. The selected base texture is referenced; keep its source asset resident. Original object, renderer and collider remain unchanged; hide the original explicitly if wanted. Does not import skinned animation, arbitrary shader graphs, all material channels, or all submeshes. Nonzero negative scale is supported; winding is corrected. Source movement after import does not move the snapshot. Reimport deliberately when a new copy is needed. Mesh positions use Unity world coordinates. Legacy CS object.pos.x uses the opposite X sign; account for that when aligning a GPU mesh with a CS object. Stretch, twist, bend, inflate or ripple from the original shape. await deformGPUMesh("sheet", "stretch", 1.5, {axis: "x"}); await deformGPUMesh("sheet", "twist", 0.6, {axis: "x"}); await deformGPUMesh("sheet", "bend", 0.3, {axis: "x"}); await deformGPUMesh("sheet", "inflate", 0.5); await deformGPUMesh("sheet", "wave", 0.5, {axis: "x", wavelength: 3, phase: 0}); Stretch amount is a positive scale factor. Twist is radians per world unit along axis; bend is curvature (1/world-unit), bending toward the next cyclic axis (x toward y, y toward z, z toward x). Inflate and wave amplitudes are world units along REST normals. Wavelength in world units, phase in radians. Default axis y; pivot defaults to imported/generated world bounds center. Optional pivot:{x,y,z} overrides it. Each call replaces the previous deformation from rest, not a cumulative modifier stack. Normals refresh after deformation. Large bends can self-intersect; this tool does not resolve contacts or volume loss. Limit a deformation to a local region, or pin that region while editing the rest. await maskGPUMesh("sheet", {x: 0, y: 3, z: 0}, 2, {feather: 0.5}); await maskGPUMesh("sheet", {x: 0, y: 3, z: 0}, 2, {feather: 0.5, invert: true}); Mask uses rest positions. Weight1 receives full deformation;0 stays at rest. Feather0 gives a hard boundary;1 feathers from center to radius. After changing a mask, call the deformation again. Restore all weights with: await fillGPUBuffer("sheet", "weights", 1); Control lit surface appearance and a mesh/grid overlay. await showGPUMesh("sheet", { tint: {x: 0.1, y: 0.65, z: 0.8}, metallic: 0, smoothness: 0.4, checker: 8, grid: false, extent: 100, autoNormals: true }); Tint multiplies copied base color/texture. Checker0 disables procedural UV checks. Metallic/smoothness in0..1. Uses URP lighting/ambient/reflections and received main light shadows; does not cast shadows. Open/double-sided opaque rendering; imported alpha masks/transparency are not reproduced. extent is a conservative world box half-size about origin; include every deformed position. Set all desired style options together: omitted options return to defaults, not a partial patch. Refresh lighting after a custom runtime kernel edits positions. await refreshGPUMeshNormals("sheet"); Area-weighted normals from fixed per-vertex adjacent faces. UV/material seams keep separate vertex normals. Degenerate triangles fall back to rest normals. By default normals update every frame for live WGSL edits; autoNormals:false is more efficient for static meshes or custom kernels that supply their own normals. Do not edit triangles/faceStarts/faceLinks: dynamic topology is not supported. Return to the original mesh without reimporting it. await pauseGPUProgram("sheet"); await resetGPUMesh("sheet"); Reset positions/normals; preserve mask, style and topology. Pause any running kernel first or it will overwrite the reset. Reset is not a simulation time/RNG checkpoint. Runtime WGSL uses the same buffers and ordinary compileGPUProgram/runGPUProgram. Bindings named by the caller can reference positions/restPositions/weights etc. A runtime deformation should read restPositions and write positions; avoid copying vertices through JavaScript each frame. Save source/setup code to rebuild a demo; a live deformed buffer is not automatically serialized into a movie-set manifest. The complete GPU Mesh demos are in catalog/examples/gpu-mesh-*.js.