git clone https://git.lucas.co/hou-control.git
hc: implement precise framing logic for Perspective and Ortho projections
python3.11libs/hc/hccam.py | 44 ++++++++++++++++++++++++++++++++++++++++----
1 file changed, 40 insertions(+), 4 deletions(-)
diff --git a/python3.11libs/hc/hccam.py b/python3.11libs/hc/hccam.py
index 899778a..1fcc8ef 100644
--- a/python3.11libs/hc/hccam.py
+++ b/python3.11libs/hc/hccam.py
@@ -42,12 +42,48 @@ class HCCam:
self.p = hou.Vector3(centroid)
def frame(self):
+ import math
geo = self.geo()
- centroid = geo.boundingBox().center() if geo else hou.Vector3(0, 0, 0)
- self.t = hou.Vector3(centroid)
+ if not geo:
+ return
+
+ bbox = geo.boundingBox()
+ centroid = bbox.center()
+ size = bbox.sizevec()
+
+ # Set pivot and basic target position to centroid
self.p = hou.Vector3(centroid)
- # self.ow = 10
- self.setZoom(10)
+ self.t = hou.Vector3(centroid)
+
+ margin = 1.2
+
+ if self.projection == 'perspective':
+ # Calculate FOV from camera parameters
+ # Horizontal FOV: 2 * atan(aperture / (2 * focal))
+ # Vertical FOV: 2 * atan((aperture/aspect) / (2 * focal))
+ aperture = self.cam_node.parm('aperture').eval()
+ focal = self.cam_node.parm('focal').eval()
+ aspect = self.aspect_ratio
+
+ fov_h = 2.0 * math.atan(aperture / (2.0 * focal))
+ fov_v = 2.0 * math.atan((aperture / aspect) / (2.0 * focal))
+
+ # Use the bounding sphere radius for a safe framing from any angle
+ radius = size.length() * 0.5
+
+ # Required distance to fit the sphere in both H and V FOV
+ dist_h = (radius * margin) / math.sin(fov_h * 0.5)
+ dist_v = (radius * margin) / math.sin(fov_v * 0.5)
+
+ dist = max(dist_h, dist_v)
+ self.setZoom(dist)
+
+ else:
+ # Orthographic framing
+ # We need to fit the bounding box into the orthowidth
+ # ow = max(width, height * aspect)
+ width = max(size[0], size[1], size[2])
+ self.ow = width * margin * 1.5 # Extra buffer for ortho
def home(self):
geo = self.geo()