# TRAIN_ASSET_PACK

Low-poly, PS1/PS2-style post-Soviet passenger train with its interior, props, railway kit and outdoor sets.
Everything is generated procedurally in Blender (Python), at real metric scale, and is ready for game engines.

* **470 assets** in 33 categories, plus **9 prefabs** (assembled scenes).
* **396 assets have LOD0/LOD1/LOD2**. Small props only have LOD0 (or LOD0/LOD1).
* Every asset has simple collision (`UCX_` convex boxes and hulls).
* **90 PBR texture sets** plus 3 atlases (Labels, Grime, Prints).

The full list, with triangle counts, is in **ASSET_LIST.md**.

## Folder layout

```
TRAIN_ASSET_PACK.blend         master file (collections below, materials linked to TEXTURES/)
TEXTURES/Materials/<Set>/      T_<Set>_BaseColor / _Normal / _Roughness / _Metallic / _AO / _ORM .png
TEXTURES/Atlases/<Atlas>/      Labels (signs, numbers, posters), Grime (decals), Prints (packaging)
TEXTURES/atlases.json          atlas regions: UV rectangle, pixel size, real size in metres
TEXTURES/materials_textures.json   resolution (512/1024/2048) and tiling (metres per texture repeat) of each set
EXPORTS/FBX/<CATEGORY>/<Asset>.fbx    LOD0 + LOD1 + LOD2 + UCX colliders + SOCKET empties, in one file
EXPORTS/GLTF/<Asset>.gltf             LOD0 + colliders (Godot "-convcolonly" naming)
EXPORTS/GLTF/<Asset>_LOD1/_LOD2.gltf  separate LOD files
EXPORTS/GLTF/textures/                textures used by the glTF files
EXPORTS/FBX/PREFABS, GLTF/PF_*        prefab scenes
EXPORTS/manifest.json                 machine-readable list: files, LODs, triangle counts, collider counts
PREVIEWS/                             contact sheets of every asset, one per category
```

Keep the folder structure as it is. FBX files point to `TEXTURES/` with relative paths.

## Blender collections

```
TRAIN_ASSET_PACK
├─ TRAIN       LOCOMOTIVE, PASSENGER_WAGONS, WHEELS, BOGIES, COUPLERS, EXTERIOR
├─ INTERIOR    SEATS, TABLES, LUGGAGE_RACKS, HANDRAILS, WINDOWS, DOORS, LIGHTS, VENTILATION, KITCHEN
├─ PROPS       LUGGAGE, FURNITURE, TRASH, FOOD, SMALL_PROPS, OUTDOOR_INDUSTRIAL, OUTDOOR_RURAL, OUTDOOR_ABANDONED
├─ TECHNICAL   ELECTRICAL, PIPES, CABLES, MACHINERY, EMERGENCY
├─ RAILWAY     RAILS, SLEEPERS, SIGNALS, SIGNS, RAILWAY_TECHNICAL
├─ MATERIALS   material preview spheres
├─ TEXTURES    atlas preview planes
├─ COLLISION   all UCX collider objects (parented to their asset; hidden by default)
├─ LODS        LOD1/LOD2 objects
└─ PREFABS     assembled train, wagons, railway section, crossing, industrial yard, rural halt, abandoned siding
```

Each asset is an empty named `SM_<Name>` placed at the asset origin. Its children are:

* `SM_<Name>_LOD0`, `_LOD1`, `_LOD2`: meshes. Transforms are applied and shading is flat or smooth with sharp edges.
* `UCX_SM_<Name>_NN`: convex colliders (Unreal naming; the Unity and Godot notes are below).
* `SOCKET_SM_<Name>_<Socket>`: attachment points (`Next`, `Start`, `End_Straight`, `Door`, `Pivot`, `Contact_Wire`, and so on).

## Conventions

* **Units:** metres, Z up in Blender. FBX/glTF use Y up, −Z forward, and scale 1.
* **Origins:** at ground level (z = 0), at the centre of the asset or at its logical attachment point.
  * Fences and walls start at the origin and run along +X, with a `Next` socket at the far end.
  * Doors and hatches are pivoted at their hinge.
* **Railway:** z = 0 is the top of the rail and the track centre is y = 0. Gauge is 1520 mm.
  * The ground and the bottom of the ballast are at z = −0.68. Track pieces start at the origin and run along +X.
  * Turnouts (`SM_Rail_Switch_1_9_*`) are 1:9 with R200, 33 m long, and have Start, End_Straight and End_Diverging sockets.
  * `SM_Rail_Switch_Return_*` is modelled in the turnout's own axes. Place it at the turnout's End_Diverging position with **no rotation**. It then ends parallel to the main line, 4.10 m away (the standard track spacing).
  * High platforms (`SM_Rur_Platform_10m`) go at y = +1.92 from the track centre. The deck is 1.10 m above the rail.
* **Train:** the passenger wagon floor is at 1.30 m above the rail and the body is 3.10 m wide. `PF_Train_Full` shows the coupling spacing between the locomotive and the wagons.
  * The passenger car is walkable: floor, walls and furniture have colliders, and the aisle, doors and gangways are left open.
* **Names:** `SM_` static mesh, `M_` material, `T_` texture, `PF_` prefab, `UCX_` collider, `SOCKET_` socket.
  * Outdoor sets use `SM_Ind_` (industrial), `SM_Rur_` (rural) and `SM_Abn_` (abandoned).

## Materials and textures

* Metal/roughness PBR. Each set has BaseColor (sRGB), Normal (**OpenGL**, Y+), Roughness, Metallic and AO.
  * **ORM** packs AO in R, Roughness in G and Metallic in B, for Unreal, Godot and glTF.
  * For Unity HDRP, build a mask map from Metallic and AO, plus smoothness = 1 − Roughness.
  * For DirectX-normal engines (Unreal, Unity), flip the green channel of the Normal maps. Unreal does this automatically on import if you tick "Flip Green Channel".
* Resolutions are 512, 1024 and 2048 px, depending on the material (see materials_textures.json). The textures tile, and UVs use real-world size, so texel density is consistent.
* Weathering (rust streaks, dirt, scratches, posters, numbers, signs) uses alpha-blended decal quads mapped into the **Labels / Grime / Prints atlases**. That keeps draw calls low and lets you remove the dirt layer by hiding one material (`M_Decal_Grime`).
* Coloured variants (for example ochre plaster, grey bark, coloured enamel) have their own baked BaseColor sets. They share the Normal and ORM maps of their base set.
* Emissive materials (lamps, signal lenses, floodlights) have an Emissive map. Their strength is set on the material.

## Engine notes

* **Unreal:** import the FBX with "Combine Meshes" off. `UCX_` colliders are picked up automatically, and LODs come from the `_LOD1`/`_LOD2` meshes (or import the LOD files separately). Sockets come in as `SOCKET_` empties.
* **Unity:** import the FBX and add an LOD Group using LOD0/1/2 (screen heights of roughly 0.5 / 0.2 / 0.05 work well). For each `UCX_` mesh, disable its renderer and add a Mesh Collider with Convex ticked. An AssetPostprocessor script can do this by name prefix.
* **Godot 4:** import the `.gltf`. Nodes ending in `-convcolonly` become convex collision shapes automatically. Add the `_LOD1`/`_LOD2` files as visibility ranges, or let Godot generate LODs.
* All assets use the same metric scale, so prefabs can be rebuilt in an engine from the socket and origin conventions above.

## LOD guidelines

* LOD1 has roughly 50–60 % of LOD0's triangles. Bevels are removed, cylinders use fewer segments and small details are dropped.
* LOD2 has roughly 20–35 %. It keeps the silhouette only, and decals and most small parts are removed.

## Regenerating

The `.blend` file was built by Python scripts. If you have the source, `blender -b -P build.py` rebuilds the whole pack, and the textures are regenerated by `gen_materials.py`.
