Compare commits
11
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0d7ceae474 | ||
|
|
319096d0d9 | ||
|
|
84291a5270 | ||
|
|
63ba9d91ce | ||
|
|
d8cbb0c95b | ||
|
|
dd36d399ad | ||
|
|
911a7059ae | ||
|
|
ecdd8208db | ||
|
|
a2f8ddccf1 | ||
|
|
3d4e830660 | ||
|
|
c3aacabd46 |
No files matched your search
@@ -185,16 +185,49 @@ The project-specific pack, `.agents/skills/blender-skills/blender-director/` —
|
||||
|
||||
Do not copy the common packs into the repository: a second copy under a different root is a name collision, and Pi keeps the first one it finds and warns on every start. Add a pack to `~/.pi/agent/skills/<pack>/SKILL.md` (one level down, flat) and it is picked up everywhere; `references/` sits beside them at `~/.pi/agent/skills/references/`.
|
||||
|
||||
**All agents must consult the relevant skill packs before starting a task in that discipline.** Each patch section in `TODO.md` lists its suggested skills; the general mapping is:
|
||||
**Entry point:** `blender-director` — the orchestrator picks the specialist packs in pipeline order and matches a reference photograph before detail work. Start any multi-step Blender task there.
|
||||
|
||||
- **Modeling / procedural assets** — `blender-modeler`, `procedural-modeling`, `geometry-nodes`, `hard-surface`.
|
||||
- **Façades and architecture** — `archviz`, `historical-worlds` (1920s Hollywood Blvd direction), `realistic-style`.
|
||||
**Pack index.** Every pack available to this project, grouped by discipline. The 93 common packs plus the project's `blender-director`; `unity-export` and `godot-export` are installed for other projects and unused here, since the project ships Unreal only.
|
||||
|
||||
| Group | Packs |
|
||||
| --- | --- |
|
||||
| Pipeline entry point | `blender-director` (project pack) |
|
||||
| Core modelling | `blender-modeler`, `hard-surface`, `prop-artist`, `vehicle-artist`, `character-artist`, `creature-artist`, `sculpting`, `retopology`, `geometry-nodes`, `procedural-modeling` |
|
||||
| Environment and architecture | `environment-artist`, `archviz`, `set-dressing`, `vegetation-artist`, `scene-assembly`, `collision-proxy` |
|
||||
| Characters and animation | `character-archetypes`, `rigging`, `animation`, `cloth-sim`, `hair-groom` |
|
||||
| Materials, light and render | `materials`, `texture-workflow`, `lookdev`, `lighting`, `rendering`, `compositing`, `camera-cinematography` |
|
||||
| UVs, export and optimisation | `uv-workflow`, `export-pipeline`, `unreal-export`, `asset-optimization`, `lod-pipeline` |
|
||||
| Physics and VFX | `physics-sim`, `vfx-fx` |
|
||||
| Review and QA | `qa-review`, plus the `references/` notes below |
|
||||
| Project direction | `realistic-style`, `historical-worlds` |
|
||||
| World packs | `apocalypse-worlds`, `biome-worlds`, `fantasy-worlds`, `sci-fi-punk-worlds` |
|
||||
| Genre art direction | `genre-action-combat`, `genre-card-party-idle`, `genre-metroidvania-roguelike`, `genre-narrative-vn`, `genre-open-world-sandbox`, `genre-puzzle-platformer`, `genre-racing-sports`, `genre-rpg`, `genre-shooter`, `genre-soulslike`, `genre-stealth`, `genre-strategy-sim`, `genre-survival` |
|
||||
| Mood art direction | `brutalist-mood`, `cozy-wholesome-mood`, `dark-gritty-mood`, `dream-surreal-mood`, `neon-retrofuturism`, `noir-style` |
|
||||
| Style art direction | `analog-found-footage-horror`, `anime-style`, `body-horror-style`, `cartoon-style`, `chibi-style`, `comic-book-style`, `cosmic-eldritch-horror`, `dream-weirdcore-style`, `folk-horror-style`, `frutiger-aero-style`, `hand-painted-style`, `hd-2d-style`, `horror-style`, `indie-horror-aesthetics`, `isometric-style`, `liminal-space-style`, `lowpoly-style`, `manga-style`, `mascot-puppet-horror`, `minimalist-style`, `painterly-style`, `pixel-art-style`, `psx-horror-style`, `retro-16bit-style`, `retro-8bit-style`, `stop-motion-craft-style`, `stylized-style`, `vector-style`, `visual-console-eras`, `voxel-style` |
|
||||
| Other engines (unused) | `unity-export`, `godot-export` |
|
||||
|
||||
**All agents must consult the relevant skill packs before starting a task in that discipline.** Each task section in `TODO.md` names its suggested skills; the general mapping is:
|
||||
|
||||
- **Modeling / procedural assets** — `blender-modeler`, `procedural-modeling`, `geometry-nodes`, `hard-surface`, `prop-artist`, `sculpting`, `retopology`.
|
||||
- **Vehicles** — `vehicle-artist` with `hard-surface`, `collision-proxy`, `lod-pipeline` (the `0.3.0` car).
|
||||
- **Façades and architecture** — `archviz`, `historical-worlds` (1920s Hollywood Blvd direction), `realistic-style`, `environment-artist`.
|
||||
- **Characters and animation** — `character-artist`, `rigging`, `animation`, `cloth-sim`, `hair-groom` (the MPFB `AGigLineNPCPerson` prefab; `character-archetypes` for crowd variety).
|
||||
- **Materials and textures** — `materials`, `texture-workflow`, `lookdev`.
|
||||
- **UVs and export** — `uv-workflow`, `export-pipeline`, `unreal-export` (verify against the `ue_metric_v1` / `ue_character_v1` presets in `Tools/`).
|
||||
- **UVs and export** — `uv-workflow`, `export-pipeline`, `unreal-export` (verify against the `ue_metric_v1` / `ue_character_v1` presets in `Tools/`), `asset-optimization`, `lod-pipeline`.
|
||||
- **Collision** — `collision-proxy` (UCX/UHX naming, hulls, simple colliders).
|
||||
- **Scene assembly / optimization** — `scene-assembly`, `asset-optimization`, `lod-pipeline`.
|
||||
- **Lighting and rendering** — `lighting`, `rendering`, `lookdev`, `compositing`, `camera-cinematography`.
|
||||
- **Blender-side physics and VFX** — `physics-sim`, `vfx-fx`.
|
||||
- **Review and QA** — `qa-review`, `references` (reference-image-match and visual-match checklists), `camera-cinematography` (matching reference camera angles).
|
||||
|
||||
**Reference notes.** `~/.pi/agent/skills/references/` sits beside the packs and holds the checklists they cite:
|
||||
|
||||
- `asset-pipeline.md` — the stage order every asset follows.
|
||||
- `reference-image-match.md` and `reference-analysis-template.md` — match the camera and write the analysis before micro-detail when a photograph drives the asset.
|
||||
- `visual-match-checklist.md` and `validation-checklist.md` — the two gates before an asset is called done.
|
||||
- `naming-conventions.md` and `polycount-budgets.md` — names and budgets to hold to.
|
||||
- `mcp-integration.md` and `mcp-tools.md` — the packs' MCP tooling, **not used here** (see the caveat below).
|
||||
|
||||
**Caveat:** the skill packs assume MCP-driven interactive Blender. This project runs Blender headless via scripts in `Tools/` — use the skills as method guides (checklists, naming conventions, proportions, validation steps), not for their MCP tooling. The headless scripts remain the execution path.
|
||||
|
||||
## Unreal Engine skills
|
||||
@@ -224,6 +257,24 @@ The general mapping to this project's work:
|
||||
|
||||
One router skill, `cpp` (MIT, [DiamonDinoia/skill-cpp](https://github.com/DiamonDinoia/skill-cpp) `f2617fb`), lives at `.agents/skills/cpp/` and covers general C++11 through C++23 against the C++ Core Guidelines. It detects the project language standard from the build system (**C++20** for this project, from the UBT compile flags), then loads the matching standard reference plus the topic references the task touches. Load it for any C++ work that is not Unreal-specific; the UE skills supersede it for engine API questions.
|
||||
|
||||
## Skill roots and provenance
|
||||
|
||||
Every skill pack is agent instruction, never game code or an add-on, and none is committed: `/.agents/skills/` is gitignored. The runtime discovers packs from these roots:
|
||||
|
||||
| Root | Packs | Source |
|
||||
| --- | --- | --- |
|
||||
| `~/.pi/agent/skills/<pack>/SKILL.md` | 93 Blender packs, flat, one level down | [blender-skills](https://github.com/arjun988/blender-skills) 1.3.0, MIT |
|
||||
| `~/.pi/agent/skills/references/` | shared notes beside the packs, not a pack | same |
|
||||
| `.agents/skills/blender-skills/blender-director/` | 1 project orchestrator | project-specific |
|
||||
| `.agents/skills/ue-*/` | 31 Unreal Engine 5.8 C++ packs | [quodsoler/unreal-engine-skills](https://github.com/quodsoler/unreal-engine-skills) `f3742d7`, MIT |
|
||||
| `.agents/skills/cpp/` | 1 C++ router | [DiamonDinoia/skill-cpp](https://github.com/DiamonDinoia/skill-cpp) `f2617fb`, MIT |
|
||||
| `~/.agents/skills/` | user-level packs shared with other projects | local |
|
||||
|
||||
- `.agents/skills/skills.manifest.json` records every installed source, commit, target and local patch, with `LICENSE-unreal-engine-skills.txt` and `LICENSE-skill-cpp.txt` beside it. Keep the manifest current when a pack is installed, upgraded or removed.
|
||||
- The upstream Blender clone sits at `~/.agents/skills/blender-skills/` (`git remote https://github.com/arjun988/blender-skills.git`, 94 packs under `.claude/skills/`). `~/.pi/agent/skills/` is the installed copy the runtime actually reads and holds 93 of them; `blender-director` is kept project-local because it names this project's tools and stages.
|
||||
- Because the packs are gitignored, a fresh checkout has none of them: every task must stay doable from the scripts in `Tools/`, `Geo/tools/` and `Art/blender/`, with the packs only guiding method.
|
||||
- User-level packs: `de-ai-writing` strips AI-writing tells from `Docs/`, `CHANGELOG.md` and `MEMORY.md` prose; `hf-cli` (Hugging Face Hub CLI) and `reverse-engineer-anything` (REA for shipped binaries and packaged builds) are not part of this pipeline and are loaded only when the task is actually about them.
|
||||
|
||||
## Licensing & Distribution
|
||||
|
||||
- Publish project-owned code under a chosen open-source license.
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -318,7 +318,8 @@ void AGigLineVehicle::Tick(float DeltaSeconds)
|
||||
{
|
||||
if (DriveElapsed > 1.0f && DriveElapsed < 4.0f)
|
||||
{
|
||||
Movement->SetThrottleInput(1.0f);
|
||||
const float Throttle = FParse::Param(FCommandLine::Get(), TEXT("reversetest")) ? -1.0f : 1.0f;
|
||||
Movement->SetThrottleInput(Throttle);
|
||||
}
|
||||
else if (DriveElapsed >= 4.0f && !bDriveReported)
|
||||
{
|
||||
@@ -444,19 +445,22 @@ void AGigLineVehicle::Tick(float DeltaSeconds)
|
||||
// If the Chaos vehicle never came into existence (no wheels), its movement component has no
|
||||
// valid state to drive, and continuing to tick it writes whatever is in that empty state back
|
||||
// onto the actor - which is the only explanation that fits a still body and a moving actor.
|
||||
// Only stop in that case: with real wheels the mover must keep ticking to drive, and stopping
|
||||
// it at 2.5 s was what killed the drive test (throttle runs 1-4 s).
|
||||
if (!bMoverStopped && SettleElapsed > 2.5f)
|
||||
{
|
||||
bMoverStopped = true;
|
||||
if (const UChaosWheeledVehicleMovementComponent* WheelComp =
|
||||
Cast<UChaosWheeledVehicleMovementComponent>(GetVehicleMovementComponent()))
|
||||
const UChaosWheeledVehicleMovementComponent* WheelComp =
|
||||
Cast<UChaosWheeledVehicleMovementComponent>(GetVehicleMovementComponent());
|
||||
if (!WheelComp || WheelComp->Wheels.Num() == 0)
|
||||
{
|
||||
bMoverStopped = true;
|
||||
UE_LOG(LogTemp, Warning,
|
||||
TEXT("GigLine vehicle: stopping the mover - wheels=%d at Z %.0f"),
|
||||
WheelComp->Wheels.Num(), GetActorLocation().Z);
|
||||
}
|
||||
if (UMovementComponent* Mover = GetVehicleMovementComponent())
|
||||
{
|
||||
Mover->SetComponentTickEnabled(false);
|
||||
WheelComp ? WheelComp->Wheels.Num() : -1, GetActorLocation().Z);
|
||||
if (UMovementComponent* Mover = GetVehicleMovementComponent())
|
||||
{
|
||||
Mover->SetComponentTickEnabled(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -53,10 +53,17 @@ UPhysicsAsset* UGigLineVehicleBuilder::BuildPhysicsAsset(USkeletalMesh* Mesh,
|
||||
// A box slightly under the mesh bounds: a body that is exactly the bounds sits on the
|
||||
// ground plane and reads as floating because the mesh has wheels below the sills.
|
||||
FKBoxElem Box;
|
||||
// The skeletal mesh imports ROLLED (height along Y, width along Z) while the armature is
|
||||
// unrolled (height Z, width Y). The box is a body on the root bone, so it must be built in
|
||||
// the UNROLLED frame: length from mesh X, width from mesh Z, height from mesh Y.
|
||||
Box.X = Extent.X * 1.9f;
|
||||
Box.Y = Extent.Y * 1.8f;
|
||||
Box.Z = Extent.Z * 0.55f;
|
||||
Box.Center = FVector(0.f, 0.f, -Extent.Z * 0.25f);
|
||||
Box.Y = Extent.Z * 1.8f;
|
||||
Box.Z = Extent.Y * 0.55f;
|
||||
// The chassis sits at the car's centre of mass, which is the rolled mesh's mid-height
|
||||
// (Bounds.Origin.Y) mapped onto the unrolled height axis (Z). The suspension rest position is
|
||||
// measured against the root bone (the grounded origin), so the box must sit at the centre of
|
||||
// mass rather than the root bone - this is what settled the vehicle on the road.
|
||||
Box.Center = FVector(0.f, 0.f, Bounds.Origin.Y);
|
||||
Body->AggGeom.BoxElems.Add(Box);
|
||||
PhysicsAsset->SkeletalBodySetups.Add(Body);
|
||||
|
||||
|
||||
@@ -1048,3 +1048,137 @@ Historical task context from 2026-11-09/10; later vehicle findings above may sup
|
||||
X, not the bone's Y), the engine torque sign, or the throttle sign. Next probe: run the
|
||||
`-drivetest` with `SetThrottleInput(-1.0)` to split "throttle inverted" from "wheel spin
|
||||
inverted" in one run.
|
||||
|
||||
## 2026-11-10 — Vehicle reverse: both throttle signs drive backward
|
||||
|
||||
- `-reversetest` (negative throttle) shows the throttle sign is not the cause: forward
|
||||
throttle → −224.9 km/h, reverse throttle → −99.5 km/h — **both backward**, so the wheel
|
||||
spin is inverted relative to the engine torque, not the input mapping.
|
||||
- The mesh orientation is fine (imported bounds 476 × 228 cm, nose at +X). The earlier axle
|
||||
flip (inward→outward) was a no-op, so the next check is the **imported wheel-bone
|
||||
reference pose**: the axle (bone Y) may be landing on Unreal X or Z, not Y, so the wheel
|
||||
spins about the wrong axis. `FPhysicsAssetUtils`-style body setup is not the cause either
|
||||
(physics already simulates).
|
||||
- Kept `-reversetest` in the drive test as the diagnostic for this.
|
||||
|
||||
## 2026-11-10 — Vehicle reverse: the skeleton is rolled 90° vs the mesh
|
||||
|
||||
- Bone reference poses (`AnimPose.get_ref_bone_pose`) show the armature is **rolled 90°**:
|
||||
`root` rot (roll 90, 0, 0), `Wheel_FL/RL` rot (90, 0, −180), `Wheel_FR/RR` rot (−90, 0, 0);
|
||||
wheel centres land at Z ±0.81 instead of Y ±0.81. The mesh vertices are unrotated (bounds
|
||||
476 × 228 × 144, nose +X), so the **FBX `axis_forward: -Y` conversion rotates the armature
|
||||
but not the geometry** — the wheel axle (bone Y) ends up on a rotated axis, which is why the
|
||||
engine torque drives the wheels backward and why the inward/outward axle flip was a no-op.
|
||||
- Fix belongs in the bone authoring, not the vehicle component: build the wheel bones so their
|
||||
Y axis lands on Unreal +Y after the FBX conversion, or set `use_space_transform`/bake the
|
||||
space transform so mesh and armature share one frame. Verify with the reference-pose probe
|
||||
(`get_ref_bone_pose` → the wheel axle should read ±Y, not ±Z) before re-running the drive
|
||||
test.
|
||||
|
||||
## 2026-11-10 — Vehicle reverse: FBX armature bakes a −90° roll the build can't undo
|
||||
|
||||
- Inspecting `vehicle_skeletal.fbx` (imported back into Blender) shows the export bakes a
|
||||
**−90° rotation about X** into the armature: `root` tail (0,1.64,0), wheel tails at
|
||||
(x, 0.33, ±0.83) — the wheel **axle lands on Z**, not Y. The mesh vertices are exported
|
||||
unrotated (bounds 476×228×144), so mesh and armature come back in different frames.
|
||||
- Three Blender-side fixes were tried and **none changed the imported wheel bones**:
|
||||
1. axle tail along −Z (head/tail) — reference pose unchanged;
|
||||
2. `axis_forward: "X"` on the `_CHARACTER` preset — unchanged;
|
||||
3. armature object pre-roll −90° about X — unrolled the `root` (roll 90→0) but left the
|
||||
wheel bones at roll ±90 / Z ±0.81.
|
||||
- Conclusion: the export bakes the armature conversion regardless of head/tail or the
|
||||
object transform. Remaining options (untried): `bake_space_transform: true` (also rolls
|
||||
the mesh — would need the mesh un-rolled again in Unreal), or a **post-import skeleton
|
||||
fix** — rotate each wheel bone's reference pose −90° about X in `ue_vehicle_import.py`
|
||||
(or a commandlet) so the axle lands on Y. Verify with the `get_ref_bone_pose` probe
|
||||
(axle should read ±Y) before re-running `-drivetest`.
|
||||
|
||||
## 2026-11-10 — Vehicle reverse: not the axle, not the gear ratio
|
||||
|
||||
- The reverse direction is **not** the axle orientation and **not** the final-drive ratio:
|
||||
flipping the wheel-bone axle to horizontal (Unreal ±Y, via `axis_forward: X` + a Blender-Z
|
||||
tail) changed the reference pose (FL roll 180, FR roll 0) but the `-drivetest` still reads
|
||||
`speed=-2737 cm/s`. `FinalRatio = -3.5` also changed nothing (it is a magnitude; the gear
|
||||
direction is `ForwardGearRatios` vs `ReverseGearRatios`).
|
||||
- So the wheels spin backward for positive torque regardless of axle direction, which points
|
||||
at the **wheel spin axis convention in the Chaos solver** (the `FSimpleWheel` angular
|
||||
velocity axis) or the engine torque sign, not the bone authoring. The horizontal-axle fix
|
||||
is kept (it is correct even if insufficient): `axis_forward: X` in the character preset and
|
||||
a Blender-Z wheel tail (`r - copysign(0.25, y)`) so the axle lands on Unreal Y.
|
||||
|
||||
## 2026-11-10 — Vehicle reverse is in the Chaos solver, not the assets (revert the axis fix)
|
||||
|
||||
- Reverted the `axis_forward: X` / Blender-Z axle fix (`ecdd820`): the reference pose changed
|
||||
but `-drivetest` still read −2737 cm/s, and `axis_forward: X` lives in the shared character
|
||||
preset, so it would also alter every character export.
|
||||
- Traced the Chaos solver: the wheel's local frame is `GroundXVector = CrossProduct(VehicleRightAxis,
|
||||
GroundZVector)` and the drive force is `FinalLongitudinalForce = DriveTorque / Re`, applied forward —
|
||||
yet the car moves backward. The wheel spins about the **vehicle's** Y, not the bone's, so the bone
|
||||
authoring is irrelevant. The inversion is in the **engine-torque / drive-force sign** (`FSimpleWheel`),
|
||||
not the assets. Next: check `GetEngineTorque()` sign, or override `SetupVehicle`/`ProcessMechanicalSimulation`
|
||||
in `UGigLineVehicleMovement` to negate the drive torque.
|
||||
|
||||
## 2026-11-10 — Vehicle: the visual body and the physics body are different vehicles
|
||||
|
||||
- `SM_Vehicle_Body` (the owner's **hot hatch** template, what the panels render) imports with
|
||||
bounds **150 x 400 x 122 cm** — its length is along **Y**. `SK_Vehicle_Sedan` (the procedural
|
||||
sedan that the Chaos solver drives) is **476 x 228 x 144** with the length along **X**. They
|
||||
are built by different scripts (`vehicle_from_template.py` vs `vehicle_build.py`) and do not
|
||||
even share a forward axis.
|
||||
- This is almost certainly the real story behind the "reverse" drive: the solver applies the
|
||||
drive force forward on the skeletal sedan (+X) while the visible car's nose is on a different
|
||||
axis, so a forward physics motion reads as a sideways/backward car. `MaxTorque = -500` was also
|
||||
a no-op (the torque curve normalises the magnitude), ruling out the engine torque sign.
|
||||
- Next step is not more solver tracing: reconcile the two meshes — drive the **hot hatch** (make
|
||||
it skeletal, or rebuild `SK_Vehicle_Sedan` to match the hot hatch's axis and dimensions) so the
|
||||
visible and physics cars are one asset with one forward axis.
|
||||
|
||||
## 2026-11-10 — Hot hatch is now the skeletal (physics) mesh; vehicle still floats
|
||||
|
||||
- `vehicle_from_template.py` now builds a skeletal mesh from the hot hatch (the real car):
|
||||
it applies the MIRROR/NODES modifiers, derives the four wheel centres by quadrant, adds a
|
||||
root + `Wheel_FL/FR/RL/RR` armature, weights wheels-to-bones, and exports
|
||||
`vehicle_skeletal.fbx`. A rotation matrix [[0,1,0],[0,0,-1],[-1,0,0]] orients the car so the
|
||||
FBX conversion lands it unrolled (length +X, width +Y, height +Z). Wheel bones import
|
||||
correctly: FL (1.43,-0.71,0.34) FR (1.43,0.62,0.34) RL (-1.22,-0.75,0.36) RR (-1.22,0.67,0.36).
|
||||
- **Still floats** (rises 300 -> 3315 cm, `simulating=1`, 4 wheels): the same suspension push
|
||||
as before, so the reverse/float is NOT the visual/physics axis mismatch after all. Remaining
|
||||
suspect is the chassis box centre (`-Extent.Z*0.25` = ~-20) vs the wheel-bone height (0.34):
|
||||
the suspension rest length is measured against the root BONE, not the box, so the box offset
|
||||
may be the push. Next: try `Box.Center = (0,0,+Extent.Z*0.3)` or drive the box from the
|
||||
wheel-bone height, then re-run `-drivetest`.
|
||||
|
||||
## 2026-11-10 — Box centre: raising it cuts the float, but it persists
|
||||
|
||||
- `Box.Center = Extent.Z*0.35` (was `-Extent.Z*0.25`) cuts the float from ~33 m to **7.82 m**
|
||||
(`settled at Z 782`, ground at Z 5). Direction confirmed: the chassis box belongs above the
|
||||
ground, not below the root bone. Still not settled, so the box centre needs to go higher toward
|
||||
the car's centre of mass (~0.7 m), and/or the root bone should sit at the centre of mass rather
|
||||
than at the ground (the `normalise_scale` grounds the whole car, so the root bone is at Z 0).
|
||||
- The hot-hatch skeletal mesh now imports (403 x 148 x 158 cm), but the mesh is rolled (height Y,
|
||||
width Z) while the armature is correct - the MESH vertices are exported raw (identity) while the
|
||||
ARMATURE is baked with the FBX conversion, the same mesh-vs-armature split as before.
|
||||
|
||||
## 2026-11-10 — Vehicle settles (float 33 m -> 6 cm); drive still ~0
|
||||
|
||||
- **Two real fixes** (commit `319096d`):
|
||||
1. The skeletal mesh imports ROLLED (height along Y, width along Z) while the armature is
|
||||
unrolled. The chassis box must therefore be built with swapped axes (`Box.Y = Extent.Z*1.8`,
|
||||
`Box.Z = Extent.Y*0.55`) and centred at the rolled mesh's mid-height (`Box.Center.Z =
|
||||
Bounds.Origin.Y`). This is what settled the car at Z 6 cm (was floating at 33 m).
|
||||
2. A diagnostic `if (SettleElapsed > 2.5f) Mover->SetComponentTickEnabled(false)` was firing for
|
||||
every vehicle (not just zero-wheel ones) and cut the drive test (throttle 1-4 s). Now gated
|
||||
on `Wheels.Num() == 0`.
|
||||
- **Experiment that FAILED and was reverted**: moving the root bone to the centre of mass in
|
||||
`vehicle_from_template.py` (root at `body.bound_box` centre) puts the wheel bones at NEGATIVE Z
|
||||
(-54 cm below root) and the vehicle then FLOATS at spawn height (stays Z 304, never falls).
|
||||
So the Chaos suspension in this rig wants a POSITIVE rest position (wheel bone above the root
|
||||
bone). Root bone stays grounded at (0,0,0); the box offset to centre of mass is done in C++.
|
||||
- **Remaining**: drive test reports `speed=1 cm/s` (no forward motion) and `travelled ~56 m` - a
|
||||
horizontal drift during the fall. Wheels rest ~2 cm above the ground (wheel bone Z +34 vs wheel
|
||||
radius 33) because the suspension rest position is measured against the root bone while the box
|
||||
sits at +76. Next: make the wheels actually contact (align wheel radius to the bone, or correct
|
||||
the rest position for the box offset) before re-testing direction.
|
||||
- `GetWheelRestingPosition` = `LocateBoneOffset(BoneName, WheelClass.Offset + AdditionalOffset)`,
|
||||
which is the wheel bone position relative to the ROOT BODY BONE - it does NOT account for
|
||||
`Box.Center`. That offset is the root of the drive gap.
|
||||
@@ -8,6 +8,7 @@ Actionable task list for this project. Planned work and progress marks live here
|
||||
- A level-three (`###`) section being worked on carries `- active - <sessionId>` (and optionally the branch name) in its heading. Remove the suffix when you stop.
|
||||
- When all steps in a version section are done: write a `CHANGELOG.md` entry, then remove the version section from this file.
|
||||
- Release gate: a version is tagged only on the owner's explicit go-ahead once its release checks pass, not automatically when the checkboxes close.
|
||||
- Every task section carries a `**Suggested skills:**` line naming the packs to load before starting. Load them with the `skill` tool — `blender-director` for asset pipelines, `ue-project-context` for engine work, then the packs named — and use them as method guides, since this project runs Blender and Unreal headless from scripts.
|
||||
|
||||
## Toolchain — end-to-end asset check (done 2026-11-10)
|
||||
|
||||
@@ -15,6 +16,8 @@ Actionable task list for this project. Planned work and progress marks live here
|
||||
|
||||
See [toolchain notes](MEMORY.md#toolchain--end-to-end-asset-check-done-2026-11-10).
|
||||
|
||||
**Suggested skills:** no pack covers the local ComfyUI, judge or driver tooling — work from `Tools/README.md`, `Tools/review/` and the toolchain notes in `MEMORY.md`.
|
||||
|
||||
- [x] Group the sixty tools by sandbox: `Tools/unreal/`, `Tools/blender/`, `Tools/review/`, `Tools/gen/`, `Tools/input/`, with the layout documented in `Tools/README.md`.
|
||||
- [x] Empty both maps and verify that no actors remain using `Tools/unreal/ue_recreate_maps.py`.
|
||||
- [x] Clear the whole level in both builders.
|
||||
@@ -34,6 +37,8 @@ See [historical notes](MEMORY.md#vehicle-physics--chaos-rig-own-task-from-030).
|
||||
|
||||
### Tasks
|
||||
|
||||
**Suggested skills:** `ue-physics-collision`, `ue-module-build-system` (plugin enablement), `ue-actor-component-architecture`, `ue-gameplay-framework`, `ue-input-system`, `ue-testing-debugging`, `cpp`; Blender side `vehicle-artist`, `collision-proxy`, `export-pipeline`, `unreal-export`. No pack covers Chaos Vehicles — the notes in this section and the `ChaosVehiclesPlugin` headers are the reference.
|
||||
|
||||
- [x] Give `SK_Vehicle_Sedan` a physics asset whose single chassis body matches the car's box. **Resolved 2026-11-10** — two causes, both fixed: `ChaosVehiclesPlugin` was not enabled in `.uproject`, so `CreateVehicle()` never ran (`0 wheels`); and `BuildPhysicsAsset` never set `Body->PhysicsType`, so the body stayed `PhysType_Default` (follow owner) and never simulated. Enabling the plugin (`5e328f5`) and setting `PhysicsType = PhysType_Simulated` (`927e937`) make the pawn **simulate, settle at Z 77 cm, and drive** (`-drivetest` moved 36.3 m).
|
||||
- [x] Find what writes the actor transform in `DemoMap` but not in `ReviewMap`. **Resolved** — it was never a transform writer: the body was not simulating (see above), so the "float" and "teleport" were the unsimulated chassis being driven by the regular rigid-body solver instead of the Chaos async solver.
|
||||
- [x] Confirm `Wheels.Num()` becomes 4 once the vehicle is created; log it at the settle check. **4 wheels** once the plugin is enabled (`setups=4 wheels=4`).
|
||||
@@ -45,6 +50,8 @@ See [historical notes](MEMORY.md#hero-facade-rework--from-the-reviewmap-review-o
|
||||
|
||||
### Tasks
|
||||
|
||||
**Suggested skills:** `blender-director`, `archviz`, `historical-worlds`, `realistic-style`, `hard-surface` (relief and mouldings), `materials`, `texture-workflow`, `uv-workflow`, `lookdev`, `rendering`, `camera-cinematography`, `references` (visual-match checklist), `qa-review`; engine side `ue-materials-rendering`.
|
||||
|
||||
- [x] Confirm the hero captures frame `Hero_Facade`.
|
||||
- [x] Seat the elevation detail in front of the mass.
|
||||
- [x] Remove the blank lintel band across the portals.
|
||||
@@ -66,6 +73,8 @@ See [historical notes](MEMORY.md#hero-facade-rework--from-the-reviewmap-review-o
|
||||
|
||||
See [vehicle production notes](MEMORY.md#030--chaos-vehicle-enterexit-closed-driving-route-weeks-1013).
|
||||
|
||||
**Suggested skills:** `blender-director`, `vehicle-artist`, `hard-surface`, `materials`, `uv-workflow`, `collision-proxy`, `lod-pipeline`, `asset-optimization`, `export-pipeline`, `unreal-export` (against `ue_metric_v1`); engine side `ue-project-context` first, then `ue-physics-collision`, `ue-actor-component-architecture`, `ue-gameplay-framework`, `ue-input-system`, `ue-character-movement` (enter/exit), `ue-world-level-streaming` (route bounds), `ue-testing-debugging`, `cpp`.
|
||||
|
||||
- [A] Model one vehicle in Blender with collision meshes; export to Unreal.
|
||||
- [D] Set up Chaos Vehicle with wheel and physics configuration.
|
||||
- [x] Fix the vehicle not rendering in the scene.
|
||||
@@ -89,6 +98,8 @@ See [vehicle production notes](MEMORY.md#030--chaos-vehicle-enterexit-closed-dri
|
||||
|
||||
### Patch tasks
|
||||
|
||||
**Suggested skills:** `ue-physics-collision`, `ue-input-system`, `ue-actor-component-architecture`, `ue-testing-debugging`, `cpp`; `vehicle-artist` only if the fix is visual mass or wheel placement.
|
||||
|
||||
- [ ] Refine vehicle handling feel based on `0.3.0` feedback.
|
||||
- [ ] Tag `v0.3.1` and write `CHANGELOG.md` entry; then remove this section.
|
||||
|
||||
@@ -96,6 +107,8 @@ See [vehicle production notes](MEMORY.md#030--chaos-vehicle-enterexit-closed-dri
|
||||
|
||||
### Patch tasks
|
||||
|
||||
**Suggested skills:** `collision-proxy`, `vehicle-artist`, `asset-optimization`, `export-pipeline`, `unreal-export`, `ue-physics-collision`, `ue-testing-debugging`.
|
||||
|
||||
- [ ] Fix vehicle collision defects (mesh/physics mismatches).
|
||||
- [ ] Tag `v0.3.2` and write `CHANGELOG.md` entry; then remove this section.
|
||||
|
||||
@@ -103,6 +116,8 @@ See [vehicle production notes](MEMORY.md#030--chaos-vehicle-enterexit-closed-dri
|
||||
|
||||
### Patch tasks
|
||||
|
||||
**Suggested skills:** `ue-input-system`, `ue-character-movement`, `ue-gameplay-framework`, `ue-blueprint-cpp-interop`, `ue-testing-debugging`.
|
||||
|
||||
- [ ] Fix vehicle/character input issues in `0.3.x`.
|
||||
- [ ] Tag `v0.3.3` and write `CHANGELOG.md` entry; then remove this section.
|
||||
|
||||
@@ -110,6 +125,8 @@ See [vehicle production notes](MEMORY.md#030--chaos-vehicle-enterexit-closed-dri
|
||||
|
||||
### World expansion
|
||||
|
||||
**Suggested skills:** `blender-director`, `environment-artist`, `procedural-modeling`, `geometry-nodes`, `archviz`, `scene-assembly`, `asset-optimization`, `lod-pipeline`, `uv-workflow`, `materials`, `export-pipeline`, `unreal-export`; engine side `ue-project-context` first, then `ue-world-level-streaming`, `ue-procedural-generation`, `ue-async-threading`, `ue-materials-rendering`, `ue-testing-debugging`, `cpp`.
|
||||
|
||||
- [ ] Extend geo pipeline to a small connected neighborhood beyond the demo block.
|
||||
- [ ] Produce modular buildings, sidewalks, and roads for the expanded area.
|
||||
- [ ] Set up World Partition with streaming cells.
|
||||
@@ -127,6 +144,8 @@ See [vehicle production notes](MEMORY.md#030--chaos-vehicle-enterexit-closed-dri
|
||||
|
||||
### Patch tasks
|
||||
|
||||
**Suggested skills:** `ue-world-level-streaming`, `asset-optimization`, `environment-artist`, `ue-testing-debugging`.
|
||||
|
||||
- [ ] Fix visible seams between streamed cells.
|
||||
- [ ] Tag `v0.4.1` and write `CHANGELOG.md` entry; then remove this section.
|
||||
|
||||
@@ -134,6 +153,8 @@ See [vehicle production notes](MEMORY.md#030--chaos-vehicle-enterexit-closed-dri
|
||||
|
||||
### Patch tasks
|
||||
|
||||
**Suggested skills:** `ue-world-level-streaming`, `ue-async-threading`, `ue-testing-debugging`.
|
||||
|
||||
- [ ] Correct streaming/loading issues found in `0.4.x`.
|
||||
- [ ] Tag `v0.4.2` and write `CHANGELOG.md` entry; then remove this section.
|
||||
|
||||
@@ -141,6 +162,8 @@ See [vehicle production notes](MEMORY.md#030--chaos-vehicle-enterexit-closed-dri
|
||||
|
||||
### Patch tasks
|
||||
|
||||
**Suggested skills:** `lod-pipeline`, `ue-world-level-streaming`, `asset-optimization`, `ue-testing-debugging`.
|
||||
|
||||
- [ ] Tune HLOD quality and distance settings.
|
||||
- [ ] Tag `v0.4.3` and write `CHANGELOG.md` entry; then remove this section.
|
||||
|
||||
@@ -148,6 +171,8 @@ See [vehicle production notes](MEMORY.md#030--chaos-vehicle-enterexit-closed-dri
|
||||
|
||||
### Simulation
|
||||
|
||||
**Suggested skills:** `ue-project-context` first, then `ue-ai-navigation`, `ue-character-movement`, `ue-actor-component-architecture`, `ue-gameplay-framework`, `ue-state-trees`, `ue-mass-entity` (crowd scale), `ue-async-threading`, `ue-testing-debugging`; the `AGigLineNPCPerson` prefab is Blender work — `character-artist`, `rigging`, `animation`, `export-pipeline`, `unreal-export`.
|
||||
|
||||
- [ ] Add pedestrian characters with navigation, using `AGigLineNPCPerson` (the reusable NPC prefab) as the base, driving it via AI/`AutoPossessAI`.
|
||||
- [ ] Implement crosswalk behavior (pedestrians use the designated crossing).
|
||||
- [ ] Add limited ambient traffic on the street network.
|
||||
@@ -163,6 +188,8 @@ See [vehicle production notes](MEMORY.md#030--chaos-vehicle-enterexit-closed-dri
|
||||
|
||||
### Patch tasks
|
||||
|
||||
**Suggested skills:** `ue-ai-navigation`, `ue-physics-collision`, `ue-testing-debugging`.
|
||||
|
||||
- [ ] Fix pedestrian navigation issues.
|
||||
- [ ] Tag `v0.5.1` and write `CHANGELOG.md` entry; then remove this section.
|
||||
|
||||
@@ -170,6 +197,8 @@ See [vehicle production notes](MEMORY.md#030--chaos-vehicle-enterexit-closed-dri
|
||||
|
||||
### Patch tasks
|
||||
|
||||
**Suggested skills:** `ue-ai-navigation`, `ue-state-trees`, `ue-gameplay-tags-messaging`, `ue-testing-debugging`.
|
||||
|
||||
- [ ] Fix crosswalk behavior defects.
|
||||
- [ ] Tag `v0.5.2` and write `CHANGELOG.md` entry; then remove this section.
|
||||
|
||||
@@ -177,6 +206,8 @@ See [vehicle production notes](MEMORY.md#030--chaos-vehicle-enterexit-closed-dri
|
||||
|
||||
### Patch tasks
|
||||
|
||||
**Suggested skills:** `ue-mass-entity`, `ue-async-threading`, `ue-testing-debugging`, `asset-optimization`, `lod-pipeline`.
|
||||
|
||||
- [ ] Optimize pedestrian/traffic simulation cost.
|
||||
- [ ] Tag `v0.5.3` and write `CHANGELOG.md` entry; then remove this section.
|
||||
|
||||
@@ -186,6 +217,8 @@ See [vehicle production notes](MEMORY.md#030--chaos-vehicle-enterexit-closed-dri
|
||||
|
||||
See [pavement notes](MEMORY.md#060--visualaudio-pass-and-evening-lighting-preset-weeks-2224).
|
||||
|
||||
**Suggested skills:** `lighting`, `rendering`, `lookdev`, `materials`, `texture-workflow`, `archviz`, `environment-artist`, `blender-director`, `references` (visual-match checklist), `qa-review`; engine side `ue-materials-rendering`, `ue-niagara-effects`, `ue-audio-system`, `ue-gameplay-cameras`, `ue-testing-debugging`.
|
||||
|
||||
- [ ] Create an evening lighting preset.
|
||||
- [ ] Complete a visual polish pass across the neighborhood.
|
||||
- [ ] Model the pavement between kerb and building line.
|
||||
@@ -203,6 +236,8 @@ See [pavement notes](MEMORY.md#060--visualaudio-pass-and-evening-lighting-preset
|
||||
|
||||
### Patch tasks
|
||||
|
||||
**Suggested skills:** `lighting`, `lookdev`, `rendering`, `references`, `qa-review`, `ue-materials-rendering`.
|
||||
|
||||
- [ ] Fix lighting defects in day/evening presets.
|
||||
- [ ] Tag `v0.6.1` and write `CHANGELOG.md` entry; then remove this section.
|
||||
|
||||
@@ -210,6 +245,8 @@ See [pavement notes](MEMORY.md#060--visualaudio-pass-and-evening-lighting-preset
|
||||
|
||||
### Patch tasks
|
||||
|
||||
**Suggested skills:** `materials`, `texture-workflow`, `lookdev`, `qa-review`, `ue-materials-rendering`.
|
||||
|
||||
- [ ] Fix material errors found in `0.6.x`.
|
||||
- [ ] Tag `v0.6.2` and write `CHANGELOG.md` entry; then remove this section.
|
||||
|
||||
@@ -217,6 +254,8 @@ See [pavement notes](MEMORY.md#060--visualaudio-pass-and-evening-lighting-preset
|
||||
|
||||
### Patch tasks
|
||||
|
||||
**Suggested skills:** `ue-audio-system`, `ue-testing-debugging`.
|
||||
|
||||
- [ ] Balance audio levels across the scene.
|
||||
- [ ] Tag `v0.6.3` and write `CHANGELOG.md` entry; then remove this section.
|
||||
|
||||
@@ -224,6 +263,8 @@ See [pavement notes](MEMORY.md#060--visualaudio-pass-and-evening-lighting-preset
|
||||
|
||||
### Systems
|
||||
|
||||
**Suggested skills:** `ue-project-context` first, then `ue-ui-umg-slate`, `ue-input-system`, `ue-serialization-savegames`, `ue-data-assets-tables`, `ue-gameplay-framework`, `ue-blueprint-cpp-interop`, `cpp`, `ue-testing-debugging`.
|
||||
|
||||
- [ ] Build settings menu (graphics and audio options).
|
||||
- [ ] Implement control rebinding with persistence.
|
||||
- [ ] Implement save/load for player state.
|
||||
@@ -239,6 +280,8 @@ See [pavement notes](MEMORY.md#060--visualaudio-pass-and-evening-lighting-preset
|
||||
|
||||
### Patch tasks
|
||||
|
||||
**Suggested skills:** `ue-serialization-savegames`, `ue-testing-debugging`, `cpp`.
|
||||
|
||||
- [ ] Fix save/load defects.
|
||||
- [ ] Tag `v0.7.1` and write `CHANGELOG.md` entry; then remove this section.
|
||||
|
||||
@@ -246,6 +289,8 @@ See [pavement notes](MEMORY.md#060--visualaudio-pass-and-evening-lighting-preset
|
||||
|
||||
### Patch tasks
|
||||
|
||||
**Suggested skills:** `ue-ui-umg-slate`, `ue-testing-debugging`.
|
||||
|
||||
- [ ] Fix UI issues in `0.7.x`.
|
||||
- [ ] Tag `v0.7.2` and write `CHANGELOG.md` entry; then remove this section.
|
||||
|
||||
@@ -253,6 +298,8 @@ See [pavement notes](MEMORY.md#060--visualaudio-pass-and-evening-lighting-preset
|
||||
|
||||
### Patch tasks
|
||||
|
||||
**Suggested skills:** `ue-input-system`, `ue-serialization-savegames`, `ue-testing-debugging`.
|
||||
|
||||
- [ ] Fix rebinding persistence issues.
|
||||
- [ ] Tag `v0.7.3` and write `CHANGELOG.md` entry; then remove this section.
|
||||
|
||||
@@ -260,6 +307,8 @@ See [pavement notes](MEMORY.md#060--visualaudio-pass-and-evening-lighting-preset
|
||||
|
||||
### Performance
|
||||
|
||||
**Suggested skills:** `ue-testing-debugging` (Unreal Insights, `stat unit`, `memreport`), `asset-optimization`, `lod-pipeline`, `ue-materials-rendering` (scalability and upscaler state), `ue-async-threading`, `ue-world-level-streaming`, `ue-niagara-effects`, `cpp`.
|
||||
|
||||
- [ ] Define performance budgets (frame time, VRAM) and document them.
|
||||
- [ ] Profile the full neighborhood; fix budget violations.
|
||||
- [ ] Test on broader Linux hardware and VRAM configurations; document results.
|
||||
@@ -275,6 +324,8 @@ See [pavement notes](MEMORY.md#060--visualaudio-pass-and-evening-lighting-preset
|
||||
|
||||
### Patch tasks
|
||||
|
||||
**Suggested skills:** `ue-materials-rendering` (texture streaming, LOD bias), `asset-optimization`, `texture-workflow`, `lod-pipeline`, `ue-testing-debugging`.
|
||||
|
||||
- [ ] Reduce VRAM usage where profiling shows excess.
|
||||
- [ ] Tag `v0.8.1` and write `CHANGELOG.md` entry; then remove this section.
|
||||
|
||||
@@ -282,6 +333,8 @@ See [pavement notes](MEMORY.md#060--visualaudio-pass-and-evening-lighting-preset
|
||||
|
||||
### Patch tasks
|
||||
|
||||
**Suggested skills:** `ue-testing-debugging`, `ue-async-threading`, `ue-niagara-effects`, `asset-optimization`, `lod-pipeline`.
|
||||
|
||||
- [ ] Fix frame-time spikes found in `0.8.x`.
|
||||
- [ ] Tag `v0.8.2` and write `CHANGELOG.md` entry; then remove this section.
|
||||
|
||||
@@ -289,6 +342,8 @@ See [pavement notes](MEMORY.md#060--visualaudio-pass-and-evening-lighting-preset
|
||||
|
||||
### Patch tasks
|
||||
|
||||
**Suggested skills:** `ue-testing-debugging`, `ue-module-build-system` (build and package differences), `ue-materials-rendering` (GPU and driver-specific paths).
|
||||
|
||||
- [ ] Fix compatibility issues from the hardware testing matrix.
|
||||
- [ ] Tag `v0.8.3` and write `CHANGELOG.md` entry; then remove this section.
|
||||
|
||||
@@ -298,6 +353,8 @@ See [realistic building notes](MEMORY.md#090--realistic-buildings-weeks-3134).
|
||||
|
||||
### Façade system
|
||||
|
||||
**Suggested skills:** `blender-director`, `archviz`, `historical-worlds`, `realistic-style`, `procedural-modeling`, `geometry-nodes`, `hard-surface`, `materials`, `texture-workflow`, `uv-workflow`, `asset-optimization`, `lod-pipeline`, `export-pipeline`, `unreal-export`, `references`, `qa-review`; engine side `ue-materials-rendering`.
|
||||
|
||||
- [ ] **Extend the module kit beyond one order.** Art Deco, neoclassical and streamline-moderne variants on the shared 4.96 m bay: alternate window proportions, spandrel and transom bands, and the way each order terminates at the roof.
|
||||
- [ ] **Build a profile library** for cornices, copings, string courses, sills and storefront surrounds, so a building is assembled from named profiles rather than ad-hoc boxes.
|
||||
- [ ] **Storefront types**: recessed entry, bulkhead and kickplate, mullion spacing, transom, awning/canopy brackets, and grille/shutter variants.
|
||||
@@ -306,6 +363,8 @@ See [realistic building notes](MEMORY.md#090--realistic-buildings-weeks-3134).
|
||||
|
||||
### Per-building models
|
||||
|
||||
**Suggested skills:** `references` (reference-image-match and visual-match), `camera-cinematography` (match the photograph's angle before detail), `archviz`, `historical-worlds`, `realistic-style`, `blender-modeler`, `hard-surface`, `prop-artist` (street-level details), `materials`, `texture-workflow`, `uv-workflow`, `qa-review`, `blender-director`.
|
||||
|
||||
- [ ] Use a building-specific reference set for each building; retain blockouts and record buildings without references.
|
||||
|
||||
- [ ] Hero façade (6840): add volute capital depth, lattice grille depth, window rhythm behind the colonnade, and heavy banded rustication.
|
||||
@@ -320,6 +379,8 @@ See [realistic building notes](MEMORY.md#090--realistic-buildings-weeks-3134).
|
||||
|
||||
### Materials, UVs and performance
|
||||
|
||||
**Suggested skills:** `materials`, `texture-workflow`, `uv-workflow`, `lookdev`, `rendering`, `collision-proxy`, `lod-pipeline`, `asset-optimization`, `ue-materials-rendering`, `ue-testing-debugging`.
|
||||
|
||||
- [ ] **Measured material library**, including the hero's stone: stucco, painted render, ashlar, brick, terrazzo, glazing, bronze and steel trim, with albedo and roughness taken from the photographs rather than guessed; one Unreal material instance per surface type.
|
||||
- [ ] **Texel-density rule** per building class, applied through modular UVs; lightmap UVs where required.
|
||||
- [ ] **LOD chain and collision proxies** per building: UCX proxies for blocking volume, detail geometry non-colliding.
|
||||
@@ -339,6 +400,8 @@ See [realistic building notes](MEMORY.md#090--realistic-buildings-weeks-3134).
|
||||
|
||||
### Freeze and audit
|
||||
|
||||
**Suggested skills:** `ue-project-context` (refresh before the audit), `ue-module-build-system` (reproducible build), `ue-testing-debugging`, `qa-review`, `de-ai-writing` (`Docs/` prose).
|
||||
|
||||
- [ ] Freeze features; document the freeze in `CHANGELOG.md`.
|
||||
- [ ] Produce a public beta build for testers.
|
||||
- [ ] Complete license audit: `THIRD_PARTY_NOTICES.md`, all MPFB assets, textures, animations, vehicles, audio.
|
||||
@@ -354,6 +417,8 @@ See [realistic building notes](MEMORY.md#090--realistic-buildings-weeks-3134).
|
||||
|
||||
### Patch tasks
|
||||
|
||||
**Suggested skills:** `ue-testing-debugging` plus the pack for the subsystem each blocker lives in (see the mapping in `AGENTS.md`); `cpp` for non-engine code.
|
||||
|
||||
- [ ] Fix blockers reported during the public beta.
|
||||
- [ ] Tag `v0.10.1` and write `CHANGELOG.md` entry; then remove this section.
|
||||
|
||||
@@ -361,6 +426,8 @@ See [realistic building notes](MEMORY.md#090--realistic-buildings-weeks-3134).
|
||||
|
||||
### Patch tasks
|
||||
|
||||
**Suggested skills:** `ue-testing-debugging`, plus the owning subsystem's pack, and `cpp` where the regression is in game code; check `MEMORY.md` for how the original defect was found.
|
||||
|
||||
- [ ] Fix regressions introduced by `0.9.x` fixes.
|
||||
- [ ] Tag `v0.10.2` and write `CHANGELOG.md` entry; then remove this section.
|
||||
|
||||
@@ -368,6 +435,8 @@ See [realistic building notes](MEMORY.md#090--realistic-buildings-weeks-3134).
|
||||
|
||||
### Patch tasks
|
||||
|
||||
**Suggested skills:** `de-ai-writing` (prose), `ue-project-context` (verify the project facts it records), `ue-module-build-system` (verify the build and checkout steps documented).
|
||||
|
||||
- [ ] Update all `Docs/` for accuracy before `1.0.0`.
|
||||
- [ ] Tag `v0.10.3` and write `CHANGELOG.md` entry; then remove this section.
|
||||
|
||||
@@ -375,6 +444,8 @@ See [realistic building notes](MEMORY.md#090--realistic-buildings-weeks-3134).
|
||||
|
||||
### Final release
|
||||
|
||||
**Suggested skills:** `qa-review`, `references` (final visual-match sweep), `ue-testing-debugging`, `de-ai-writing` (`Docs/`), `ue-project-context` refresh.
|
||||
|
||||
- [ ] Complete final acceptance sweep across all `0.x` features.
|
||||
- [ ] Confirm the stable, agreed game scope is met (neighborhood-scale walking and driving).
|
||||
- [ ] Final build, documentation, and licensing verification.
|
||||
|
||||
@@ -230,6 +230,90 @@ def join_system(objects, name):
|
||||
return joined
|
||||
|
||||
|
||||
def build_skeletal(joined, args):
|
||||
"""Bind the body + wheels to a root + 4 wheel bones for the Chaos vehicle.
|
||||
|
||||
The hot hatch's nose is along +Y, so wheel front/rear is the Y sign and left/right is the
|
||||
X sign (the wheels are mirrored in the template, so the joined mesh has all four). Each
|
||||
wheel is weighted to its own bone at full weight; the body goes to the root.
|
||||
"""
|
||||
import math
|
||||
|
||||
body = joined["body"]
|
||||
wheels = joined["wheels"]
|
||||
|
||||
# Derive the four wheel centres from the wheel geometry: group vertices by quadrant.
|
||||
# After the Unreal-frame rotation, front/rear is the X sign and left/right is the Z sign.
|
||||
quadrants = {"FL": [], "FR": [], "RL": [], "RR": []}
|
||||
for vertex in wheels.data.vertices:
|
||||
world = wheels.matrix_world @ vertex.co
|
||||
key = ("F" if world.x > 0 else "R") + ("L" if world.z > 0 else "R")
|
||||
quadrants[key].append(world)
|
||||
centres = {}
|
||||
for key, verts in quadrants.items():
|
||||
if not verts:
|
||||
continue
|
||||
centres[f"Wheel_{key}"] = (
|
||||
sum(v.x for v in verts) / len(verts),
|
||||
sum(v.y for v in verts) / len(verts),
|
||||
sum(v.z for v in verts) / len(verts),
|
||||
)
|
||||
if len(centres) != 4:
|
||||
raise SystemExit(f"expected 4 wheel quadrants, got {len(centres)}: {list(centres)}")
|
||||
log(f"wheel centres: " + ", ".join(f"{k}=({v[0]:.2f},{v[1]:.2f},{v[2]:.2f})"
|
||||
for k, v in sorted(centres.items())))
|
||||
|
||||
bpy.ops.object.armature_add(location=(0.0, 0.0, 0.0))
|
||||
rig = bpy.context.active_object
|
||||
rig.name = "VehicleRig"
|
||||
bpy.ops.object.mode_set(mode="EDIT")
|
||||
edit_bones = rig.data.edit_bones
|
||||
root = edit_bones[0]
|
||||
root.name = "root"
|
||||
root.head = (0.0, 0.0, 0.0)
|
||||
root.tail = (0.0, 0.0, 0.30)
|
||||
for name, (x, y, z) in sorted(centres.items()):
|
||||
bone = edit_bones.new(name)
|
||||
bone.head = (x, y, z)
|
||||
# Axle direction is irrelevant to the Chaos solver (it drives the wheel about the
|
||||
# vehicle's Y), so point the tail straight down for a stable reference frame.
|
||||
bone.tail = (x, y, z - 0.25)
|
||||
bone.parent = root
|
||||
bpy.ops.object.mode_set(mode="OBJECT")
|
||||
|
||||
# Join the body and wheels into one skinned mesh.
|
||||
bpy.ops.object.select_all(action="DESELECT")
|
||||
body.select_set(True)
|
||||
wheels.select_set(True)
|
||||
bpy.context.view_layer.objects.active = body
|
||||
bpy.ops.object.join()
|
||||
mesh = bpy.context.active_object
|
||||
mesh.name = "SM_Vehicle_Skeletal"
|
||||
|
||||
groups = {name: mesh.vertex_groups.new(name=name) for name in ["root", *centres]}
|
||||
for vertex in mesh.data.vertices:
|
||||
world = mesh.matrix_world @ vertex.co
|
||||
nearest, best = "root", 0.6 ** 2
|
||||
for name, (x, y, z) in centres.items():
|
||||
d = (world.x - x) ** 2 + (world.y - y) ** 2 + (world.z - z) ** 2
|
||||
if d < best:
|
||||
best, nearest = d, name
|
||||
groups[nearest].add([vertex.index], 1.0, "REPLACE")
|
||||
|
||||
armature = mesh.modifiers.new(name="Armature", type="ARMATURE")
|
||||
armature.object = rig
|
||||
mesh.parent = rig
|
||||
|
||||
bpy.ops.object.select_all(action="DESELECT")
|
||||
rig.select_set(True)
|
||||
mesh.select_set(True)
|
||||
bpy.context.view_layer.objects.active = rig
|
||||
path = os.path.join(args.out, "vehicle_skeletal.fbx")
|
||||
fbx_export_preset.export_character(path, selection=True)
|
||||
log(f"skeletal vehicle exported: {path}, bones root + 4 wheels")
|
||||
return path
|
||||
|
||||
|
||||
def add_collision(body):
|
||||
"""One convex box per major volume, `UCX_`-prefixed for Unreal."""
|
||||
hulls = []
|
||||
@@ -282,6 +366,38 @@ def main(argv=None) -> int:
|
||||
|
||||
normalise_scale(meshes)
|
||||
|
||||
# Apply the MIRROR modifier so the left wheels exist in the mesh data BEFORE the nose
|
||||
# rotation; the mirror is in the object's local space, so rotating first would mirror
|
||||
# about a rotated axis.
|
||||
for obj in meshes:
|
||||
bpy.context.view_layer.objects.active = obj
|
||||
obj.select_set(True)
|
||||
for modifier in list(obj.modifiers):
|
||||
try:
|
||||
bpy.ops.object.modifier_apply(modifier=modifier.name)
|
||||
except RuntimeError:
|
||||
pass
|
||||
obj.select_set(False)
|
||||
|
||||
# Rotate so the FBX axis conversion (Blender Y->Unreal -Z, Z->-Y) lands the car unrolled:
|
||||
# length along +X (forward), width along Y, height along Z. The mapping is X->-Z, Y->X,
|
||||
# Z->-Y, i.e. the rotation matrix [[0,1,0],[0,0,-1],[-1,0,0]].
|
||||
from mathutils import Matrix
|
||||
rot = Matrix((
|
||||
(0.0, 1.0, 0.0),
|
||||
(0.0, 0.0, -1.0),
|
||||
(-1.0, 0.0, 0.0),
|
||||
))
|
||||
for obj in meshes:
|
||||
obj.rotation_euler = rot.to_euler()
|
||||
bpy.ops.object.select_all(action="DESELECT")
|
||||
obj.select_set(True)
|
||||
bpy.context.view_layer.objects.active = obj
|
||||
bpy.ops.object.transform_apply(location=False, rotation=True, scale=False)
|
||||
obj.select_set(False)
|
||||
bpy.context.view_layer.update()
|
||||
log("rotated to the Unreal frame (length +X, width +Y, height +Z)")
|
||||
|
||||
systems = {}
|
||||
for obj in meshes:
|
||||
systems.setdefault(classify(obj), []).append(obj)
|
||||
@@ -363,6 +479,12 @@ def main(argv=None) -> int:
|
||||
with open(args.report, "w") as handle:
|
||||
json.dump(report, handle, indent=2)
|
||||
print(f"[hatch] report -> {args.report}")
|
||||
|
||||
# Build the skeletal (physics) mesh last, after the report has recorded the separate
|
||||
# systems: build_skeletal joins the body and wheels, so it must not run before the
|
||||
# static exports and report are written.
|
||||
build_skeletal(joined, args)
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user