PS1 Asset Optimizer
The PS1 Asset Optimizer creates a lower-poly runtime copy of a static OBJ or FBX while preserving the project source and a reproducible import recipe. It is intended for modern assets whose silhouette is useful but whose topology is too dense for a PlayStation 1 production budget.
The optimizer is a constrained simplifier, not a one-click art replacement. It stops before a requested target when reaching it would violate the enabled topology, UV, material, symmetry, normal, or vertex-displacement constraints.
Open the Optimizer
- Import an OBJ or static FBX into
Assets/Models/. - Select the source in the Project panel.
- In the Model Inspector, click Open PS1 Asset Optimizer.
- Choose the closest Asset Role.
- Start from Use Recommended Target, then adjust the logarithmic triangle slider if the asset needs a different trade-off.
- Inspect the source preview, compatibility report, and comparison counts in the same optimizer window, then click Generate Optimized Output.
- Keep the window open while generation runs. Compare Source and Generated with the shared preview controls, then adjust and generate another pass if needed.
The optimizer is a modeless, movable, and resizable workspace. It does not hide or lock the Inspector behind it, and it can always be closed with its title-bar X, Close Window, or Escape. Wide windows show preview/status and recipe side by side; compact windows switch them into tabs so controls are not clipped.
Generation runs as a background import. The optimizer keeps its action footer visible and shows progress plus a Cancel action; cancellation stops before a partial candidate is published. You may close the optimizer while the job continues. Other asset edits and imports wait for the model transaction, preventing two jobs from overwriting the asset database concurrently.
The Inspector automatically offers the optimizer for especially dense static
models. Imported files chosen outside the project are copied into
Assets/Models/ before processing. The source is never rewritten; only the
generated .msh under Library/ is replaced.
Recommendations and Asset Roles
The recommendation combines the model role with the project's configured per-mesh triangle budget.
| Role | Intended content | Default guidance |
|---|---|---|
| Auto | Unknown or mixed content | Uses source triangle count and project budget |
| Hero | Close-up focal object | Up to about 2,000 triangles |
| Character | Readable animated-style silhouette, imported as static | Up to about 1,800 triangles |
| Prop | Common world object | Up to about 800 triangles |
| Environment | Modular level section | Uses the project per-mesh soft limit, capped at 2,048 |
These values are recommendations, not new hardware limits. Scene triangle count, material changes, texture pages, overdraw, ordering-table behavior, and CPU work still determine whether the asset is appropriate.
Quality and Preservation Controls
The optimizer uses deterministic quadric-error edge collapse on the OpenMesh topology kernel with explicit Polygon Engine constraints. OpenMesh is bundled under its BSD license and listed in the product's third-party notices.
| Control | Effect |
|---|---|
| Quality | Selects edge sensitivity plus conservative, balanced, or aggressive normal/error defaults |
| Symmetry | Auto-detects or explicitly preserves an X, Y, or Z mirror plane |
| Preserve Boundaries | Prevents open borders from being collapsed away |
| Preserve UV Seams | Protects incompatible UV islands and rejects surviving UV triangles that collapse, flip, or exceed the allowed area-ratio change |
| Preserve Hard Edges | Protects sharp normal discontinuities |
| Preserve Material Boundaries | Keeps material regions separated |
| Max Normal Deviation | Stops collapses that rotate surfaces too far |
| Max Vertex Displacement | Caps accumulated collapsed-vertex displacement as a percentage of the source bounds diagonal |
Auto symmetry enables paired collapses only when the source has a reliable mirrored vertex and face correspondence. An explicit symmetry axis fails closed if that correspondence cannot be guaranteed. Center-plane vertices remain on the plane.
The optimizer always preserves the number of connected components. When Preserve Boundary Loops is enabled, it also preserves the number of boundary-loop components. In that mode, “no new holes” means an accepted result does not create or remove those loop components. A non-manifold or invalid source is rejected with an actionable message instead of being guessed at.
Preview and Result
The optimizer window keeps the asset path, source/generated/recommended counts,
complete PS1 compatibility report, import errors, preservation controls, and
preview together. When no valid generated candidate exists, the first optimizer
view selects Source automatically instead of showing an empty generated
preview. After generation, switch between Source and Generated with the
same orbit and display mode. Very dense sources are sampled deterministically to
keep the comparison responsive. The sampled source preview is cached under
Library/model_previews/, so the comparison remains available after restarting
the editor and is regenerated whenever the model is reimported. Use:
- Textured + Wireframe for topology over the final material;
- Wireframe for density and long triangles;
- Silhouette for the outer contour;
- UV Density for relative UV coverage differences; magenta marks a degenerate geometric or UV triangle;
- PS1 Quantized for the runtime-oriented vertex appearance.
The visible result status and stored metadata record whether the target was reached, detected symmetry, source/output vertices and triangles, the accumulated vertex-displacement bound, and a stop reason. If the target was not reached, lower the preservation constraints only after checking why the protected feature matters.
Source and Runtime Limits
The import working mesh uses 32-bit indices so a source above 65,535 vertices
can be parsed and simplified. The generated PS1 .msh still uses 16-bit
indices. Generation fails before replacing the prior output if the optimized
mesh remains above 65,535 vertices or contains invalid indices.
The generated mesh is also capped at the runtime's 2,048 sortable triangles. This is a hard output contract even if a project raises its authoring soft limit. T-junction repair is accounted for after simplification; if repair raises the final count above the requested target, the result is marked as the best valid result, and a result above 2,048 is rejected.
T-junction repair and detailed PS1 topology diagnostics run after simplification. Extremely dense candidates may skip expensive diagnostics and report that decision rather than freezing the editor.
Reimport and Recipes
Optimization is part of the model import recipe. The following choices are stored in source metadata and included in the importer settings hash:
- enabled state and requested triangle target;
- role and quality;
- symmetry mode;
- boundary, UV seam, hard-edge, and material-boundary preservation;
- normal-deviation and vertex-displacement limits.
Reimporting the source reproduces the recipe. Changing one of these settings invalidates the generated result. Mesh, optional new material, skeletal output, asset database, and metadata are published as a rollback-backed transaction. An invalid conversion or persistence failure keeps the previous generated set instead of mixing old and new artifacts.
Current Scope
- Static triangle meshes only.
- OBJ and static FBX sources supported by the normal model importer.
- Existing positions, normals, UVs, and material regions are considered.
- Sources with multiple material slots must keep Single Material enabled; material regions are protected during reduction, then collapsed to the one material currently published by the model importer.
- Skinned FBX optimization is blocked because topology reduction would also require deliberate bone-weight and animation remapping.
- The feature does not create UVs, retopologize arbitrary non-manifold input, optimize collision separately, or prove final draw ordering on hardware.
For animated content, reduce the mesh in the DCC and follow Skeletal Animation. For the runtime budget context, see PS1 Hardware Constraints & Budgets.
Troubleshooting
Target not reached
Read the stop reason. A protected boundary, material seam, UV seam, hard edge, symmetry pair, normal limit, or vertex-displacement limit may make the requested target unsafe. Raise the triangle target first. Disable a constraint only when you have inspected the relevant preview.
Symmetry cannot be preserved
Use Auto to let an asymmetric source proceed without symmetry, or correct the model's mirrored topology in the DCC. Explicit X/Y/Z modes intentionally reject an unreliable pair mapping.
Source is non-manifold or invalid
Remove degenerate faces, duplicate faces, non-manifold edges, invalid indices, and non-finite vertex data in the DCC, then reimport. The optimizer does not silently patch ambiguous topology.
The output is valid but looks wrong on PS1
Check long triangles, material count, texture filtering and palettes, UV islands, coplanar overlap, near-plane crossings, and ordering-table behavior. Use the PS1 Budget dashboard, a packaged DuckStation build, and representative real hardware before shipping.
Production Checklist
- preserve the original source under
Assets/Models/; - begin with the recommended target and review the stop reason;
- inspect wireframe, silhouette, UV density, and PS1-quantized previews;
- compare source/output counts and confirm material assignment;
- re-check collision if it was authored from visual geometry;
- review the full scene in the PS1 Budget dashboard;
- validate packaged output in DuckStation and on intended hardware.