fix: cinematic camera accounts for output aspect ratio

For 16:9 (1280x720), vertical FOV is narrower than horizontal —
products could be clipped top/bottom. Now applies an aspect ratio
correction factor to camera distance: wider formats push camera
further back proportionally.

Still render (_blender_camera.py) already handled this via
min(fov_h, fov_v); cinematic now has equivalent correction.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-16 08:15:10 +01:00
parent 81eb1f9eae
commit 02669c395c
+11 -3
View File
@@ -321,14 +321,21 @@ def _get_segment_params(frame: int, bsphere_radius: float):
return azimuth, elevation, distance, lens, use_dof return azimuth, elevation, distance, lens, use_dof
def _setup_cinematic_camera(parts, bbox_center, bsphere_radius, total_frames): def _setup_cinematic_camera(parts, bbox_center, bsphere_radius, total_frames, width=1920, height=1080):
"""Create camera and keyframe the cinematic 4-segment animation. """Create camera and keyframe the cinematic animation.
Takes aspect ratio into account — wider formats push the camera
further back so the product isn't clipped vertically.
Returns the camera object. Returns the camera object.
""" """
# Starting azimuth: offset so segment 1 starts from a good angle (40deg) # Starting azimuth: offset so segment 1 starts from a good angle (40deg)
base_azimuth = 40.0 base_azimuth = 40.0
# Aspect ratio correction: for wide formats (16:9), vertical FOV is tighter
# so we need more distance. For square/portrait, no correction needed.
aspect_correction = max(1.0, (width / height) * 0.7) if height > 0 else 1.0
# Create camera # Create camera
start_az, start_el, start_dist, start_lens, _ = _get_segment_params(1, bsphere_radius) start_az, start_el, start_dist, start_lens, _ = _get_segment_params(1, bsphere_radius)
start_pos = _spherical_to_xyz(base_azimuth + start_az, start_el, start_dist, bbox_center) start_pos = _spherical_to_xyz(base_azimuth + start_az, start_el, start_dist, bbox_center)
@@ -354,6 +361,7 @@ def _setup_cinematic_camera(parts, bbox_center, bsphere_radius, total_frames):
bpy.context.scene.frame_set(frame) bpy.context.scene.frame_set(frame)
azimuth, elevation, distance, lens, use_dof = _get_segment_params(frame, bsphere_radius) azimuth, elevation, distance, lens, use_dof = _get_segment_params(frame, bsphere_radius)
distance *= aspect_correction # scale for aspect ratio
azimuth += base_azimuth # offset from base viewing angle azimuth += base_azimuth # offset from base viewing angle
# Camera position from spherical coordinates # Camera position from spherical coordinates
@@ -746,7 +754,7 @@ def main():
scene.frame_start = 1 scene.frame_start = 1
scene.frame_end = frame_count scene.frame_end = frame_count
camera = _setup_cinematic_camera(parts, bbox_center, bsphere_radius, frame_count) camera = _setup_cinematic_camera(parts, bbox_center, bsphere_radius, frame_count, width, height)
# ── Colour management ──────────────────────────────────────────────────── # ── Colour management ────────────────────────────────────────────────────
if not use_template: if not use_template: