The SystemViewport class provides visualization and user interaction capabilities for the physics simulation. It bridges the simulation state (positions, velocities, muscle activations) with 2D rendering on an HTML canvas, manages camera tracking, and enables interactive manipulation of vertices through drag-and-drop.
For details on the underlying 2D graphics library, see mm2d Graphics Library. For camera tracking behavior, see Camera Tracking and User Interaction.
SystemViewport serves as the primary interface between the System simulation engine and the visual representation. Its core responsibilities include:
| Responsibility | Implementation |
|---|---|
| Rendering orchestration | Manages mm2d.Renderer, mm2d.Scene, mm2d.Camera, and mm2d.Mesh instances algovivo/render/SystemViewport.js56-68 |
| State synchronization | Converts System state (vertex positions, muscle activations) to renderable mesh data algovivo/render/SystemViewport.js205-218 |
| Visual customization | Configures colors, shaders, backgrounds, and grid appearance algovivo/render/SystemViewport.js41-122 |
| User interaction | Enables vertex dragging via DragBehavior with DOM event handling algovivo/render/SystemViewport.js136-169 |
| Camera control | Automatically tracks mesh movement using Tracker algovivo/render/SystemViewport.js171-215 |
Sources: algovivo/render/SystemViewport.js27-172 algovivo/render/SystemViewport.js205-218
The following diagram shows how SystemViewport coordinates its internal components:
SystemViewport Component Hierarchy
Sources: algovivo/render/SystemViewport.js27-172 algovivo/render/Tracker.js1-80 algovivo/render/mm2d/ui/DragBehavior.js3-69
The SystemViewport constructor accepts a configuration object with extensive customization options:
| Parameter | Type | Default | Description |
|---|---|---|---|
width | number | 400 | Canvas width in pixels algovivo/render/SystemViewport.js60 |
height | number | 400 | Canvas height in pixels algovivo/render/SystemViewport.js61 |
borderColor | string | "black" | Color for vertex borders and edges algovivo/render/SystemViewport.js41 |
fillColor | string | "white" | Color for vertex and triangle fills algovivo/render/SystemViewport.js43 |
gridColor | string | "#acadad" | Color for background grid lines algovivo/render/SystemViewport.js44 |
backgroundColor | string | null | Uniform background color (overrides gradient) algovivo/render/SystemViewport.js80 |
backgroundCenterColor | string | "#fcfcfc" | Gradient center color algovivo/render/SystemViewport.js84 |
backgroundOuterColor | string | "#d7d8d8" | Gradient outer color algovivo/render/SystemViewport.js85 |
activeMuscleColor | string/array | [255, 0, 0] | Color for activated muscles algovivo/render/SystemViewport.js70 |
inactiveMuscleColor | string/array | [250, 190, 190] | Color for relaxed muscles algovivo/render/SystemViewport.js71 |
| Parameter | Type | Default | Description |
|---|---|---|---|
sortedVertexIds | array | null | Vertex drawing order (back-to-front) algovivo/render/SystemViewport.js33-34 |
vertexDepths | array | null | Depth values to compute sortedVertexIds algovivo/render/SystemViewport.js35-37 |
renderVertexIds | boolean | false | Display vertex ID labels algovivo/render/SystemViewport.js48 |
draggable | boolean | true | Enable vertex dragging algovivo/render/SystemViewport.js135 |
headless | boolean | false | Run without DOM attachment algovivo/render/SystemViewport.js39 |
Sources: algovivo/render/SystemViewport.js28-172
The constructor accepts colors as either hex strings or RGB arrays. Hex strings are converted using the hexToRgb helper algovivo/render/SystemViewport.js13-25
Sources: algovivo/render/SystemViewport.js13-25 algovivo/render/SystemViewport.js70-77
The following diagram illustrates the data flow from System state to renderable mesh geometry:
Data Flow: System to Mesh
Sources: algovivo/render/SystemViewport.js194-195 algovivo/render/SystemViewport.js220-275 algovivo/render/SystemViewport.js277-317
Mesh updates are split into two phases:
_updateMesh): Called when mesh structure changes. Rebuilds mesh.triangles, mesh.lines from system data, computes edge lists, and creates mappings for muscle visualization algovivo/render/SystemViewport.js220-275_updateFromSystem): Called every frame. Updates mesh.pos from the system's position tensor and updates muscleIntensity attributes from muscle activations algovivo/render/SystemViewport.js277-317The needsMeshUpdate flag triggers topology updates only when necessary algovivo/render/SystemViewport.js192-198
The viewport uses a hash-based approach to map line segments to muscle IDs via the hashSimplex function algovivo/render/SystemViewport.js8-11 This enables identifying line segments that correspond to muscles for dynamic coloring during rendering.
The render() method orchestrates the complete rendering pipeline:
SystemViewport Render Cycle
Sources: algovivo/render/SystemViewport.js191-218 algovivo/render/Tracker.js13-79
The viewport configures custom shader functions during construction:
| Shader | Implementation | Purpose |
|---|---|---|
mesh.pointShader.renderPoint | VertexRenderer.renderVertex | Draws circles for vertices with borders algovivo/render/SystemViewport.js124 |
mesh.lineShader.renderLine | LineRenderer.makeLineShaderFunction | Draws edges with muscle activation coloring algovivo/render/SystemViewport.js129-133 |
mesh.triangleShader.renderTriangle | TriangleRenderer.renderTriangle | Fills triangles with solid color algovivo/render/SystemViewport.js126-127 |
Sources: algovivo/render/VertexRenderer.js26-52 algovivo/render/SystemViewport.js124-133
When draggable: true, the viewport enables interactive vertex manipulation via mm2d.ui.DragBehavior algovivo/render/SystemViewport.js135-169
Interaction Logic
Sources: algovivo/render/SystemViewport.js137-164 algovivo/render/mm2d/ui/DragBehavior.js41-68
| Method | Parameters | Description |
|---|---|---|
hitTestVertex(p, hitTestRadius) | p: world coordinates, hitTestRadius: threshold | Returns vertex ID if found within radius algovivo/render/VertexRenderer.js64-80 |
setVertexPos(i, p) | i: vertex ID, p: [x, y] position | Updates vertex position in system state algovivo/render/VertexRenderer.js82-89 |
setVertexVel(i, v) | i: vertex ID, v: [vx, vy] velocity | Updates vertex velocity in system state algovivo/render/VertexRenderer.js91-97 |
fixVertex(vertexId) | vertexId: ID to fix | Pins vertex position, zeros velocity algovivo/render/SystemViewport.js331-338 |
freeVertex() | none | Releases currently fixed vertex algovivo/render/SystemViewport.js340-343 |
Sources: algovivo/render/VertexRenderer.js64-97 algovivo/render/SystemViewport.js331-343
The Tracker component provides automatic camera following by calculating the mesh center and smoothly interpolating the camera's horizontal position algovivo/render/Tracker.js13-40
Tracker Step Logic
Sources: algovivo/render/Tracker.js13-79
| Property | Default | Description |
|---|---|---|
visibleWorldWidth | 3.8 | Width of visible area in world units algovivo/render/Tracker.js6 |
targetCenterY | 1 | Fixed vertical center position algovivo/render/Tracker.js7 |
offsetX | 0 | Horizontal offset from mesh center algovivo/render/Tracker.js8 |
centeringSpeedFactor | 0.5 | Interpolation speed (0=static, 1=instant) algovivo/render/Tracker.js10 |
Sources: algovivo/render/Tracker.js1-11
The viewport supports depth-based rendering order. The setSortedVertexIdsFromVertexDepths method sorts vertices by depth (descending) and extracts indices to determine the drawing order algovivo/render/SystemViewport.js174-182
Sources: algovivo/render/SystemViewport.js33-37 algovivo/render/SystemViewport.js174-182
Setting headless: true creates a viewport without DOM attachment, useful for server-side rendering or testing. In this mode, DragBehavior is not linked to DOM events algovivo/render/SystemViewport.js39-168
Sources: algovivo/render/SystemViewport.js39-56 algovivo/render/SystemViewport.js165-168
Refresh this wiki