Fish Tales¶
Complete VPW rebuild from scratch featuring playfield alignment from accurate scans, full Blender Toolkit implementation, wire ramp physics, and comprehensive VR room. Development spanned 3+ years (Dec 2020 - Feb 2024) with extensive team collaboration.
Build Notes¶
Playfield Alignment Workflow¶
Major realignment project using accurate playfield scan as truth source:
- Get accurate playfield scan
- Bord imports to Blender at correct dimensions
- Use Blender to align all posts/pegs/slings to screw holes visible in scan
- Group objects into collections (posts, pegs, rubbers, etc.)
- Export guide pins and aligned objects back to VPX
- Rebuild/resize metal guides and plastics to match new positions
Critical lesson: Manual blueprints are NOT accurate - use scan + drill holes as truth. The Fish Tales manual blueprint was completely inaccurate and didn't match real playfield at all.
Starting Fresh vs. Mod-of-Mod¶
When existing table versions are built on bad playfield scans with wrong object placement/dimensions, better to start from near-scratch. Keep only: base ROM code, complex mech code (like reel/toy mechanisms), and core table functionality.
Standard WPC playfield dimensions: 20.25" wide × 46" tall. Fish Tales measured playfield: 51.5cm × 118cm (approximately 20.3" × 46.5"), confirming standard width.
Low-Poly Wire Ramps for Physics¶
VPX native ramps don't model wire ramps well. Solution: Use low-poly primitive meshes for wire ramp physics tracks. Proven to work in RCT and AC/DC (by nFozzy).
Process: Take visual wire ramp from Blender, decimate if needed to keep poly count low, export as collidable primitive. Benefits: More accurate ball behavior on wire ramps without major performance hit.
Blender Toolkit Blueprint Export for Physics Alignment¶
Blender Toolkit can export "blueprints" showing physics layout: Turn on visibility of desired collections (posts, rubbers, guides, switches, ramps), hit blueprint render button, find output in Image Viewer.
Benefits: Can overlay blueprint on playfield image in Photoshop at 50% opacity to verify alignment. Useful for VPX physics builders to see exactly where Blender assets are positioned before importing.
Captive Ball Post Angle Alignment¶
Captive ball posts are NOT vertical - they're mounted on mini-playfield (boat) which is angled at ~12.5 degrees. If posts were vertical, incoming ball would hit captive ball from underneath and launch it upward.
When building in Blender: All objects attached to mini-playfield must match its angle.
Scripting¶
VPinMame 3.6 PWM Implementation¶
VPinMame 3.6 introduced new PWM system (UseVPMModSol=2). Changes:
- Remove InitPWM sub entirely
- Update GI callbacks for new physics output format
- Update FlashXX subs for modulated output
- Set all light fader models to "None" (fading now handled by VPM based on ROM signal and bulb model)
VPinMame calculates fading curve based on bulb type, so no additional VPX-side fader needed. Requires latest VPM 3.6 AND VPX 10.8.0 RC1.
Fishing Reel Multiball Mech - Ball Rotation Code¶
Fish Tales reel mechanism rotates balls in a circle without destroying them. Implementation uses coordinate-based ball control similar to Judge Dredd's Deadworld and Cyclone's ferris wheel.
Critical: Reel positions and heights must be finalized first - code manually controls balls and moves them through 3D space using specific coordinates. Requires measurements of radius, height, and rotation angle.
Ball Shadow Code Improvements¶
Improved ball shadow positioning code that reduces the shadow offset at table edges:
BallShadow(b).X = BOT(b).X - (TableWidth/2 - BOT(b).X)/20
BallShadow(b).Y = BOT(b).Y + 10
If BOT(b).Z > 22 and BOT(b).Z < 35 Then
BallShadow(b).visible = 1
Else
BallShadow(b).visible = 0
End If
The key improvement is the X calculation: dividing by 20 instead of 7 reduces the lateral shadow offset at the table edges.
Material Assignment for Physics Collections¶
Table stripping/prep workflow for toolkit:
- All posts should be hit threshold 0.5
- Walls in "Rubbers" collection = hit threshold 2
- Set all collidable objects to correct collections (dposts, dSleeves, Rubbers)
- Bumpers, slingshots, gates: use values from nFozzy physics doc
- Gravity factor = 0.97 (not 0.95)
- Set all GI to Z-height +25 for ray-traced ball shadows
- Enable ball shadow checkbox only on GI split lights
3D & Art¶
Playfield Scan Cleanup - Generative Fill vs Vector Redraw¶
Brad1X's vector redraw benefits: Perfect solid colors (like new screenprint), fixes damage, all text/details recreated cleanly.
Process: Trace black outlines first in Illustrator, then color fill (takes twice as long as outlines). For Fish Tales, redraw provided cleaner inserts that were too dark/damaged in scan to extract properly.
Font Identification for Inserts¶
Fish Tales uses Helvetica Black (or very close variant like LinikSans-Black or HelveticaNowText-Black).
For insert text recreation: Use font to regenerate text cleanly rather than extracting from degraded scan. Requires manual kerning adjustments - characters like "C", "R", "M", and "U" often need per-character spacing.
Photoshop Object Selection Tool for Insert Cutouts¶
Photoshop's "Object Selection Tool" is a gamechanger for cutting out inserts from playfield scans. After selection, use "Select and Mask" window for edge refinement tools.
High resolution scans (13k pixels wide) help antialiasing be less noticeable. For tiny detailed inserts, manual path tracing still required.
EXR Compression and File Size Optimization¶
Blender exports lightmap EXRs using DWAA compression (lossy) with compression level ~20-45.
CRITICAL WARNING: Don't over-compress - EXRs carry HDR color/brightness data essential for light reflections. Tests showed compressed versions lost bright highlight detail. When images stack additively in VPX, lost detail compounds.
Plastic Tracing Workflow in Blender via Reference Image¶
Technique for creating accurate plastic meshes:
- Layout all plastic scans in a single image at consistent DPI (e.g., 300 PPI at 35"x35")
- In Blender, set the reference image to the same dimensions as the source image
- Trace plastic outlines in Blender using the scans as background reference
- Create a big square outline (same size as reference image) and merge with all traced shapes
- Project UV to bounds - the UV of traced shapes aligns exactly with the reference image
- Apply plastic modifiers, then split shapes apart
Result: Plastics are perfectly to scale with accurate UV mapping in a single operation.
Nestmap Resolution and Playfield Width¶
Detailed debate on optimal playfield render resolution in Blender Toolkit. Key findings:
- Each object is rendered separately at its configured resolution, then packed into nestmap images (max 8K per nestmap)
- Increasing one object's resolution doesn't enlarge other objects - it just generates more nestmaps
- The playfield render height is independently configurable from camera renders
- Effective playfield width in nestmaps often falls below 2160px (4K monitor width)
- AI upscaling (chaiNNer with models like realesrgan-x4plus-anime) can improve nestmap quality post-render with no FPS impact
Troubleshooting¶
GI Lightmaps Not Working - Missing Leading Zero¶
GI lightmaps weren't responding to ROM. Problem: Light name typo - "gitop19" instead of "gitop019" (missing leading zero).
All GI lights on same string need exact same VPX name. In Blender: Set lights to "Split" mode and assign same "VPX name" field - this makes toolkit merge lightmaps automatically.
Playfield Alpha Channel Not Working¶
Playfield alpha channel (holes for inserts) not rendering correctly.
Solution: All lightmaps in UnderPF collection need depth bias > 0. Workaround: Uncheck "Opaque" for UnderPF collection in Blender, set UnderPF to depth bias 500, export to VPX, then manually re-check "Static" render for BM_UnderPF primitive in VPX after export.
Ball Stuck on Ramp - Apex Height Fix¶
Ball getting stuck on ramp curve was caused by the ramp apex not matching the physical high point.
Fix: Set the apex of the hill at the apex of the corner (height 95), with the drop toward the crossroads going down to 90. Theory: when elevation and table slope cancel out, you get a flat section where the ball loses momentum and stops.
Ramp Height Transition Issues¶
Ball slowdown at ramp exits is often caused by the ball slamming into a steep incline at ramp-to-playfield transitions.
Fix approaches: - Smooth out the transition (ramp bottom shouldn't be at height -1 if playfield is at 0) - Use a second ramp to create a gradual bridge - Export to Blender to visualize physics geometry in 3D
VPX 10.8 Script API - Render Probe Control¶
VPX 10.8.0 RC1 added script API for render probes. Can now assign probes with/without roughness via script, or remove probes entirely.
Allows creating table option for users to disable probes based on their GPU. Use try/catch to handle error gracefully for users on older VPX versions.
Render Probe Performance Varies by Session¶
Inconsistent behavior: Sometimes table runs smooth with all probes/roughness enabled, other times must disable probe roughness for good performance.
Possible causes: Windows background processes, GPU state, thermal throttling, driver state. Recommendation: Provide user option to disable probes for consistency.
Game Knowledge¶
Fish Tales Captive Ball Physics Behavior¶
On real Fish Tales, clean shot to captive ball should kill momentum significantly - ball doesn't rocket back like in VPX. Only rockets back when hitting posts, not on clean captive ball contact.
Physics principle: Equal mass elastic collision should transfer ALL momentum to captive ball. Captive ball held above playfield by sleeves = non-perpendicular collision point.
Insert Colors and Types¶
Fish Tales inserts: Most are standard arrows and circles. Specific types: Diamond inserts (not starburst) used in certain locations - verify against manual. Some inserts share location with flashers (L67 insert + F18 flasher in same hole).
VPinMame ROM Patches¶
Fish Tales L-5 text size patch fixes display issues on real machines. Requires TWO ROM files in roms folder: ft_l5.zip (base ROM) and ft_l5p.zip (patch). VPinMame loads necessary files from both zips for complete set.
Reference: https://pinside.com/pinball/forum/topic/fish-tales-display-issue
Resources¶
Real Table Measurements¶
Post and Sleeve Measurements (from real Fish Tales): - Post height: 1.00" (25.4mm) - Sleeve height (used): 0.83" (21.1mm) - Sleeve outer diameter: 0.71" (18mm) - Sleeve inner diameter/post diameter: 0.44" (11.2mm)
New unused sleeve is slightly longer (0.87"/22mm) and thicker from less compression.
VR Room¶
Night fishing setting with animated water. 75MB total (including cab and topper artwork), down from ~150MB original. Dardog created animation loops, Rawd baked room lighting AND water lighting. Used nFozzy frame timer code for smooth animation.
Project Timeline¶
- Dec 2020: Started as Skitso mod
- 2021: G5k contributed premium scans/assets but life intervened
- 2021-2022: Multiple realignment attempts (fluffhead learning Blender)
- Mid-2022: Put on hold
- Mid-2023: Benji picked up Blender work with Brad1X playfield redraw
- Dec 2023: Rothbauerw took physics lead
- Dec 2023-Jan 2024: VR room by Rawd/Dardog
- Feb 2024: Released
3+ years, many handoffs, ultimately successful premium release.
Development Team¶
- Blender Toolkit: benji084, tomate80
- Physics/Scripting: rothbauerw, TastyWasps, fluffhead35
- Artwork: Brad1X, redbone615, benji084
- VR Room: rawd, dardog81
- Assets: g5k (scans), clarkkent (stitching), kev_v (real table measurements)
- Testing: PinStratsDan, kev_v, bietekwiet, passion4pins