# Nutrition vat, game-ready A standing pod after the user's picture (2026-10-21, `reference/ref_user.jpg`; the user: *"Create 3d model for nutrition vat in blender. build exactly as the image"*). The picture shows one pod from three sides (front three-quarter, right side with hoses, an elevated right side). The model: a pale sage shell; a two-chamber glass tank of dark teal liquid with bright bubbles at the front, a glowing disc under its lid, a mid band and a bottom bezel with cyan light rings; a C-frame round the tank whose lower part steps forward; a raised middle panel, a rear column with two pills, a vertical rod in the C-groove; hex knobs in round bezels, a grille, a slot, a keypad; six ribbed ports on the head; a U handle at the head's front left corner and a rail round the lower housing's front left corner; a cyan strip along the lower housing's front; a C-shaped arm with five windows behind the pod that sweeps down into the plinth; a cartridge at each rear corner in two clamp rings. **Pipes (2026-10-22, the user's change):** *"replace those cables with pipes from arm models (those transparant ones) the size would be not like cables size should be exactly like in the reference picture(red colored drawing) also max 3 pipes. so the other holes should be without cables or pipes. pipes should be going to the ceiling instead floor"*, with a red drawing of a pipe as wide as a port. The picture's cable bundle is gone. Three of the six ports (right rear, left rear, front; 120° apart) carry the docking arm's clear ore duct (`models/docking-arm`, "Ore hose": clear film, a grey spiral rib, steel clamp bands), as wide as the port: the film slides over the port's rim under a clamp band, bends 22° to vertical and runs straight up to a steel coupling in the ceiling (default ceiling 3.46 m, the ship's corridor ceiling). The other three ports stay open. The coupling is where the ship's main line will connect: biomass from the Tenders' cargo comes down these pipes into the vat, as ore goes (the user: *"later on this will be modular when player places vat anywhere in the ship"*). The ducts are empty. The cable version is kept in `versions/v01_cables/`. Built **headless** by script (`build/`), nothing in anyone's open Blender. Nothing is a boolean. ## Files - `NutritionVat.blend` (Blender 5.2): collections `NutritionVat` → `NV | static` (body), `NV | movable` (liquid, the two cartridges), `NV | pipes` (three fittings, runs and ceiling couplings), `NV | collision` (UCX hulls, excluded from the view layer); `Studio` (floor, a camera-only ceiling at 3.46 m, lights, camera; not exported). All parented to the empty `NutritionVat_Root`. - `fbx/SM_NutritionVat_.fbx`: one file per mesh at its own pivot, with its `UCX_` hulls (body 17, cartridge 1, each pipe piece 1). The three pipes share three meshes, each exported once; `SM_NutritionVat_PipeRun` is a 1 m piece. `fbx/NutritionVat_Assembled.fbx`: everything as placed. `fbx/verify_report.json`: the re-import check. - `NutritionVat_layout.json`: pivots, the cartridges' and the pipes' placements, the run-length rule, the open ports' mouths, materials, the liquid's fill heights, in Unreal units. - `textures/`: `T_NV_Masks.png` (4096, baked: R occlusion, G edges, B crevices), `T_NV_Decals.png` (side label, warning sticker, keypad digits), `T_NV_CanLabel.png` (the cartridge's wrap), `T_NV_Bubbles.png` (the liquid), `T_NV_Perforation.png` (the grille); drawn by `build/nv_textures.py`. Read in place by relative path (**keep the .blend here**): the Season 2 pack's tiling sets from `../vessel-interior/textures/ModSci_Engineer/Textures`, and the docking arm's duct maps `../docking-arm/textures/T_DockArm_Duct_BaseColor.png` (opacity in its alpha), `_Roughness.png`, `_Normal.png`. - `previews/`: Cycles pictures `NutritionVat_v02_*` (pipes and side: floor to ceiling; hero = front right, front_left, rear, tank, top, ceiling) and `wire_*` (topology). `previews/compare/v02.png`: for each of the picture's three views, the picture left and the model right, rendered from a camera fitted to that view (`_overlay` adds the model's outline); `v02_pipes_sheet.png`, `v02_couplings.png`: the pipes. `previews/cycles/` holds the fitted renders. - `reference/`: the picture and its ruler crops `z_*.png` (`build/zoom.py`). - `build/`: `nv_lib.py` (geometry: rounded polygons with offset rings, slabs, Coons caps relaxed into a Tutte grid, lathes, tubes, cell solids, decals), `nv_build.py` (the parts and the pipes; measured numbers in its docstring), `nv_textures.py`, `nv_surfaces.py`, `nv_check.py`, `nv_export.py`, `nv_verify_fbx.py`, `nv_render.py`, `nv_wire.py`, `nv_compare.py`; `nv_fit.py` fits a camera to each of the picture's views from landmarks (`cams.json`), `nv_preview.py` makes quick Workbench looks from those cameras. `run_all.sh` runs the chain in order (one Blender at a time). - `versions/v01_cables/`: the first delivery (the picture's cable bundle), its scripts, FBX files and pictures. ## Scale, axes, size Measured in pixels of the picture's middle (side) view; **1 px = 4.62 mm**, chosen so the head's top stands **2.00 m** over the floor (the picture has no person; the knobs, keypad, handles and ports all read right at that size). The width (110 px, 50.8 cm) is from the front three-quarter view. 1 unit = 1 m, Z up, the tank faces −Y, the picture's visible side (label, knobs, grille) is +X. **The origin is on the floor under the body's middle.** In Unreal: **ue_cm = (x, −y, z) × 100** (the project's FBX pair; the data is turned −90° about Z on export); an instance turned φ about Z in Blender takes Unreal yaw −φ. | | | |---|---| | height | 200 cm to the head's top, 214 cm with the ports; the pipes reach the ceiling (346 cm by default) | | width | 50.8 cm body, 66.4 cm at the plinth and handles | | depth | 118.7 cm from the front rail to the plinth's back | | tank | glass r 20.3 cm, two chambers 33 and 68 cm tall, liquid from 58 to 163 cm above the floor | | pipes | 20.7 cm across the film (the port's width), clamp bands 23.5 cm; the vertical part stands 7.2 cm out from its port | ## Parts and pivots | Mesh | Pivot | Note | |---|---|---| | `SM_NutritionVat_Body` | origin | everything static, glass and decals included (glass and decals are their own material slots) | | `SM_NutritionVat_Fluid` | the bottom of the liquid on the tank's axis | static; for the fill level cut it in the material by world height (58.0 cm empty, 162.9 cm full above the origin). Scaling it would push its rounded bottom through the glass | | `SM_NutritionVat_Canister` | its foot on its axis | one mesh, placed twice: right corner as built, left corner turned 180° (`NutritionVat_Canister_L`), label out on both | | `SM_NutritionVat_PipeFitting` | the port's foot on the head's top, x out from the vat's middle | film over the port's rim, a clamp band there, the 22° bend, a band at its top that also holds the run's end. Placed three times (`NutritionVat_PipeFitting_A/B/C`) | | `SM_NutritionVat_PipeRun` | its bottom on the duct's axis | a straight **1 m** piece of film, stretched along Z to the length: **length = ceiling − 8.3 cm − 233.3 cm** (it starts 233.3 cm over the floor and ends 8.3 cm under the ceiling); 104.4 cm at the default ceiling | | `SM_NutritionVat_PipeCeiling` | on the ceiling's plane on the duct's axis | flange with six bolts, collar, the spigot the film slides over and its clamp band: **the socket for the ship's main line** | The layout file lists each pipe's three placements. No rig: nothing moves. ## Checked `build/nv_check.py` tests every pair of separate meshes for triangle overlap: **no clash** between the body, the liquid, the two cartridges and the three pipes, nor between the pipes. The pieces of one pipe meet by design (the bands clamp the film; the film slides over the ceiling spigot) and are listed apart. Smallest gaps: liquid to glass 2.1 mm, cartridges to the body (their clamp rings) 4.6 mm, pipe fittings to the ports 4.6 mm (the film clears the port's rim by 1 px, the band by 0.6 px). The C-frame's lower part wraps the glass (its inner side follows the tank's cylinder 2.8 mm off it) instead of cutting into it. Topology: body 18,997 quads and **4 triangles** (two corners where a bevelled edge meets an unbevelled one), no n-gons, no non-manifold edges, no zero-area faces; liquid, cartridges and pipe pieces all quads. Open edges are where parts sit on each other (their contact faces are left out) and the ducts' film ends. The FBX files re-import at scale 1 on their pivots with both UV layers, their materials and hulls (`fbx/verify_report.json`). Wireframes: `previews/wire_*`. ## Surfaces Two UV layers on every mesh: `UVMap` (UV0: a unique unwrap into the mask atlas; decals take their atlas, the cartridge's glass its wrap, the liquid a cylinder, the ducts' film round 0..1 and along in texture repeats of 0.69 m like the docking arm's) and `UV_Tile` (UV1, metres, box-projected, for the tiling sets). Clean, low wear. | Material | What it is | Set | |---|---|---| | `M_NV_Shell` | the pale sage paint (body, arm, plinth) | ScratchedMetal under the tint, faint | | `M_NV_ShellDark` | the plinth's toe | ScratchedMetal | | `M_NV_Gap` | port bores, the lid's dark ring, the couplings' bores | — | | `M_NV_Glass` | the tank's two chambers: clear, thin walls | Glass_DirtRough as smudges | | `M_NV_Fluid` | dark teal liquid, bubbles emissive | `T_NV_Bubbles` | | `M_NV_Glow` | the lid's disc, the light rings, the front strip (emissive cyan) | — | | `M_NV_Rubber` | ports, cartridge caps | ScratchedMetal | | `M_NV_PipeFilm` | the ducts' clear film: the docking arm's `M_DockArm_OreHose` shader (Fresnel reflections, opaque spiral rib, dust), two-sided | the arm's `T_DockArm_Duct_*` (normal map OpenGL: flip green for Unreal) | | `M_NV_PipeBand` | clamp bands and ceiling couplings: the arm's band steel | StainedSteel + scratch normal | | `M_NV_Chrome`, `M_NV_Brass` | handles, rod, cartridge clamp rings; the valve lever | BrushedMetal + scratch normal | | `M_NV_Keypad`, `M_NV_Grille` | the keypad's panel; the grille (holes every 4 mm) | `T_NV_Perforation` | | `M_NV_Decal` | label, warning sticker, keypad digits (alpha), 0.25 mm off the surface | `T_NV_Decals` | | `M_NV_CanGlass` | the cartridge's glass with its label | `T_NV_CanLabel` | In Unreal the film can be the docking arm's own ore-hose material (same textures): one material for every cargo duct. ## Collision Body: 17 `UCX_SM_NutritionVat_Body_NN` hulls (head, lip, tank, body, lower housing, plinth, rear block, the ports' crown, the arm in seven pieces, the two handles). Cartridge: one 12-sided prism. Each pipe piece: one hull round it (the run's is the 1 m piece's, so it stretches with it). Liquid: none. ## Triangles Body 38.0k, liquid 3.7k, cartridge 1.6k (×2), pipe fitting 0.8k, run 32 and ceiling coupling 1.6k (×3 each): **52.5k**. ## Against the picture - The three views are not one pod in every detail: the front three-quarter view has no arm, no hoses, no second cartridge and a shorter base. The model follows the side and elevated views there (where views disagree the side view rules). - The middle view's cable bundle was replaced by the three pipes at the user's word (2026-10-22). - The second cartridge (left rear corner) is placed from the elevated view, where only its cap shows above the arm. - The picture's lettering "medpod", the "gen:LOCK" logo and the artist's watermark are not on the model (no names in textures); the side label reads **"nutrivat"** (my word, in `nv_textures.py`, `LABEL_WORD`). The warning sticker and the cartridge label are generic. - The picture is concept art for the series gen:LOCK (its watermarks name the artist, Ian Llanas). The model follows its design closely; whether a game that ships may use it that way is the user's call. - The left side (−X) is not in the picture: its plates mirror the right side; knobs, grille, label and slot are on +X only. ## Not done / open - Unreal: not imported. `NutritionVat_layout.json` has what the import and a vat actor need. - The modular pipe system (the vat placed anywhere, its pipes joined to the ship's main line) is later work: here are the pieces, the socket on the ceiling and the run-length rule. The ducts are empty: no biomass moves in them yet. - The run's rib stretches with the run (its UV0 V runs along it); a world-height V in the Unreal material keeps the pitch. - The liquid's level and the bubbles' rise are material work in Unreal (a height cut and a panning UV); the textures are here. ## Rebuild `sh build/run_all.sh [TAG]` (Git Bash) runs the whole chain headless, one Blender at a time, all threads (the user allows full CPU since 2026-10-19); the GPU (HIP) does the bake and the renders. About two minutes. `nv_build.py` rewrites `NutritionVat.blend` from scratch, so run the rest of the chain after it. `nv_fit.py` (the cameras for the comparison) is not in the chain: re-run it only if the landmarks in it change. The default ceiling is `CEIL_Z` in `nv_build.py` (and `PIPE_CEIL` in `nv_export.py`, the studio's ceiling in `nv_render.py`).