# Spearfish Tender: the user's blueprint measured (exec'd by build_spearfish.py; plain Python, no bpy). # # Source: reference/user_blueprint.webp ("SUBMERSIBLE - ORTHOGRAPHIC RECONSTRUCTION", 1958 x 691 px), sent 2026-10-20 with # "Create this blueprint as subtub tender 3d model in blender using MCP precisely accordingly take your time check as the # referance image". Every number below is a pixel read off the original picture (4x zooms with rulers, reference/z_*.png, # and dark-pixel runs per column). Image x is shared by the TOP, PORT SIDE and UNDERSIDE views (nose tip x 1136, stern # face x 527, stern lugs x 522); TOP centre line at image y 157.5; SIDE view heights are image y (down = larger). # # Scale and axes (the Kazah's: nose to -Y, port +X, Z up, origin 9 cm behind the docking clamp's axis): # S = 0.0155 m per pixel -> 9.50 m from the stern lugs to the nose tip, fin span 3.8 m (fits the moon pool well # 12.3 x 6.3 m with more than the user's 1 m all round). Origin at image x 822, so the clamp axis (y -0.09) sits at # image x 828, the middle of the hull. Height: the hull top (image y 342.5) at z 0.97, low enough that the docking # clamp's claws (lowest point z 1.24) pass 15 cm over the dorsal rails (image y 334.5 -> z 1.094). # # Where the five views disagree (an AI-drawn sheet), the choice made: # * big fins: TOP/UNDERSIDE give the planform, FRONT/REAR show them edge-on as a thick ribbed root, a rod and a round # disc. Built as the planform fin, low on the flank (FRONT: 0.76 of the height down -> image y 415), with a ribbed # actuator at the root (the SIDE view's ribbed "gills") and a small round lamp pod on the outer forward corner. # * antennas: TOP and SIDE show whips raked aft from two small stern pods; FRONT/REAR draw one central mast. The two # pods with whips are built (TOP is the most detailed view). # * canopy lower edge: SIDE says image y 429, UNDERSIDE and FRONT show the glass reaching further under: set at 434. # * stern grille: SIDE shows it under the stern lip, TOP on the aft slope, REAR as a hatch with vents: the end face # carries the hatch and slots, the aft slope a small three-slot vent. S = 0.0155 X0 = 822.0 # image x of the origin Z0 = 405.08 # image y of z = 0 (342.5 -> 0.97) CL_IMG = 828.0 # clamp axis def Yi(x): return (X0 - x) * S def Zi(v): return (Z0 - v) * S def Lp(px): return px * S # ---- hull silhouette: SIDE top (image y), SIDE bottom (image y), TOP half width (px) TOPY = [(527, 367.0), (530, 365.5), (535, 362.0), (545, 358.0), (560, 354.0), (575, 349.5), (590, 346.0), (605, 344.5), (620, 343.5), (640, 343.0), (700, 342.5), (860, 342.5), (875, 343.5), (890, 345.0), (905, 346.2), (920, 347.5), (935, 349.2), (950, 351.0), (965, 353.0), (980, 355.5), (995, 359.0), (1010, 363.0), (1025, 367.5), (1040, 373.0), (1055, 378.5), (1070, 385.0), (1085, 391.5), (1100, 398.5), (1115, 406.5), (1125, 412.5), (1136, 419.0)] BOTY = [(527, 389.0), (530, 393.0), (535, 399.0), (545, 408.0), (560, 420.0), (575, 426.0), (590, 430.0), (605, 433.0), (620, 435.0), (635, 437.0), (650, 438.2), (665, 439.5), (680, 440.8), (710, 442.2), (740, 443.5), (760, 444.0), (920, 444.0), (935, 443.6), (950, 443.0), (965, 442.0), (980, 440.6), (995, 439.0), (1010, 437.0), (1025, 435.0), (1040, 432.5), (1055, 430.0), (1070, 427.0), (1085, 424.5), (1100, 422.3), (1115, 420.5), (1125, 419.7), (1136, 419.0)] WPX = [(527, 24.0), (530, 28.0), (535, 33.0), (540, 37.0), (545, 40.5), (560, 45.5), (575, 51.5), (590, 56.5), (605, 60.0), (620, 62.5), (635, 64.5), (650, 66.5), (665, 68.0), (680, 69.5), (695, 70.5), (710, 71.0), (740, 71.0), (830, 71.0), (845, 70.0), (860, 66.0), (875, 62.5), (890, 61.0), (905, 60.0), (920, 58.0), (935, 54.8), (950, 51.5), (965, 47.5), (980, 43.3), (995, 39.0), (1010, 34.6), (1025, 30.5), (1040, 26.5), (1055, 22.5), (1070, 18.3), (1085, 14.6), (1100, 10.8), (1115, 7.0), (1125, 4.5), (1136, 0.4)] X_TIP, X_STERN = 1136.0, 527.0 # ---- openings, SIDE view outlines (image x, image y), the same on both flanks CANOPY = [(876, 412.0), (879, 404.0), (886, 397.0), (898, 391.0), (914, 387.0), (935, 385.2), (960, 386.0), (985, 389.0), (1010, 394.0), (1040, 400.5), (1065, 407.0), (1083, 413.0), (1097, 418.5), (1090, 421.5), (1070, 426.0), (1040, 430.0), (1000, 433.0), (960, 434.0), (930, 433.0), (905, 429.5), (890, 425.0), (880, 419.0)] MULLIONS = [((933, 384.0), (958, 435.0)), ((1013, 393.0), (983, 434.6)), ((1064, 405.5), (1084, 422.5))] # ---- the user's own canopy, 2026-10-20: "so this tender should be two seater next to each other when two player can seat # each should can see the sea from the window front the glass should be bigger", with the bigger glass drawn in red on two # Blender screenshots (reference/user_canopy_side_2026-10-20.webp, Right Orthographic; _front_2026-10-20.png, Front # Orthographic). Each screenshot was fitted to the hull's silhouette (build/fit_side.py: 417.6 px/m; build/fit_front.py: # 531.8 px/m) and the red lines read in metres (build/canopy_from_drawing.py -> build/canopy_user_2026-10-20.json). The two # drawings agree: the glass's top at 0.63 m (side) and 0.65 m (front). This outline replaces the blueprint's CANOPY above # (kept for the record); the mullions keep the blueprint's places and slants and run across the whole new glass. import json as _json, os as _os _CU = _json.load(open("D:/HADAL - The Descent/models/tender-spearfish/build/canopy_user_2026-10-20.json")) CANOPY_YZ = [tuple(p) for p in _CU["canopy_yz"]] # port side (y, z) in metres: the drawn line; starboard is its mirror CANOPY_INSET = 0.022 # glass edge 22 mm inside the drawn line: the 45 mm frame straddles it SEATS_DRAWN = _CU["seats_drawn_front"] # the drawn seat rectangles (front view): x 0.57..0.82 and -0.87..-0.60 # The red loop round the canard starts at the new glass's aft edge (y -0.82) and runs aft at the canard's height: the canards # move aft out of the glass, 27 px, and 5.7 px out (the hull is wider there, so they keep their span beyond the skin). CANARD_MOVE = (-27.0, 5.7) SIDEWIN = [(689, 394.0), (691, 382.0), (699, 377.5), (740, 376.5), (770, 377.5), (777, 382.0), (778, 389.0), (770, 394.5), (755, 399.0), (740, 404.0), (728, 409.5), (718, 416.0), (710, 423.0), (702, 427.5), (695, 424.0), (690, 413.0)] # ---- fins, TOP view planforms (image x, lateral px from the centre line), port side BIGFIN = [(726.5, 71.5), (720.5, 77.5), (712, 85.5), (707, 95.5), (705, 105.5), (707, 112.5), (712, 116.5), (722, 120.5), (735, 123.0), (748, 122.5), (760, 120.5), (772, 116.5), (783, 110.5), (777, 105.5), (776, 99.5), (779, 93.5), (786, 87.5), (796, 83.5), (806, 80.5), (814, 80.5), (822, 77.5), (822, 71.5)] # (the root's aft corner, blueprint (722, 71.5) and (718, 77.5), moved 4.5 and 2.5 px forward on 2026-10-20: it touched the # side window's frame, whose lower aft corner comes down beside it) BIGFIN_Y = 415.0 # root height (SIDE image y); FRONT: the fins 0.76 of the height down BIGFIN_ANHEDRAL = 8.0 # deg (FRONT: nearly level; SIDE: the root fairing falls aft) CANARD = [(843, 62.5), (843, 70.0), (848, 73.5), (855, 77.5), (865, 81.5), (875, 83.5), (883, 83.5), (902, 81.5), (895, 78.5), (888, 73.5), (884, 67.5), (882, 62.5)] CANARD_Y = 382.0 # SIDE: the "eyebrow" over the canopy, image y 374-387 # fin root fairing (SIDE: the swept blade from aft-low to fore-high) and the ribbed actuator under its fore part STRAKE = [(698, 433.0), (712, 428.5), (728, 421.0), (745, 413.0), (765, 406.0), (790, 401.0), (815, 398.0), (840, 395.5), (866, 393.0)] RIBBED = ((797, 421.0), (880, 401.0)) # ---- dorsal and ventral fittings (TOP / UNDERSIDE: image x, lateral px) RAILS = (676, 860, 33.75, 7.75, 334.5) # x from, x to, centre lateral, half width, top (SIDE image y) HATCH = [(887, 27.0), (927, 19.0)] # trapezoid: aft edge x 887 half width 27, fore edge x 927 half width 19 SCOOP_HUMP = (929, 956, 27.0, 343.0) # aft x, lip x, half width, top (SIDE: rises from 905; starts behind the hatch's fore edge, x 927) SCOOP_RECESS = [(938, 27.0), (945, 22.0), (960, 19.0), (975, 16.0), (993, 11.0)] SCOOP_RAMP = (968, 993, 11.5) NOSE_SENSOR_TOP = [(1065, 8.0), (1080, 7.0), (1098, 4.0)] NOSE_SENSOR_BOT = [(1073, 7.0), (1084, 6.0), (1095, 4.0)] STERN_PODS = (582, 597, 24.5) # x from, x to, lateral ANTENNA_TIP = (543, 44.5, 302.0) # whip tip: image x, lateral px, SIDE image y STERN_VENT_SIDE = [(552, 367.0), (577, 367.0)] # SIDE: dark slot capsule, 10 px high TOP_AFT_VENT = (547, 565, 17.0) STERN_LUGS = (522, 538, 20.0, 379.0) # x from, x to, lateral, SIDE image y STERN_LIP = (520, 371.0) VENTRAL_BLISTER = (833, 912, 11.5, (891, 910)) UNDER_SLOTS = (727, 775, 45.0) UNDER_STERN_VENT = (548, 575, 14.0) SEAMS_X = (565, 619, 655, 768, 843) # transverse panel seams (SIDE and TOP) DECK_SEAM = (600, 860, 45.5) # longitudinal seams on the top, lateral px