|  | @@ -24,7 +24,6 @@ else:
 | 
	
		
			
				|  |  |      import os
 | 
	
		
			
				|  |  |      import base64
 | 
	
		
			
				|  |  |      import numpy as np
 | 
	
		
			
				|  |  | -    from pyquaternion import Quaternion
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      # from . import zs_renderscene as zsrs  # noqa
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -418,6 +417,31 @@ def set_environment(scene_data):
 | 
	
		
			
				|  |  |              print("Group 'NG_Canvas_Background' not found")
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +def calculate_focal_length(fov, film_height):
 | 
	
		
			
				|  |  | +    # Convert FOV from degrees to radians
 | 
	
		
			
				|  |  | +    fov_rad = math.radians(fov)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    # Calculate the focal length
 | 
	
		
			
				|  |  | +    focal_length = (film_height / 2) / math.tan(fov_rad / 2)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    return focal_length
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +def quaternion_multiply(q1, q2):
 | 
	
		
			
				|  |  | +    """
 | 
	
		
			
				|  |  | +    Multiplies two quaternions.
 | 
	
		
			
				|  |  | +    q1 and q2 are arrays or lists of length 4.
 | 
	
		
			
				|  |  | +    Returns the resulting quaternion as a NumPy array.
 | 
	
		
			
				|  |  | +    """
 | 
	
		
			
				|  |  | +    w1, x1, y1, z1 = q1
 | 
	
		
			
				|  |  | +    w2, x2, y2, z2 = q2
 | 
	
		
			
				|  |  | +    w = w1 * w2 - x1 * x2 - y1 * y2 - z1 * z2
 | 
	
		
			
				|  |  | +    x = w1 * x2 + x1 * w2 + y1 * z2 - z1 * y2
 | 
	
		
			
				|  |  | +    y = w1 * y2 - x1 * z2 + y1 * w2 + z1 * x2
 | 
	
		
			
				|  |  | +    z = w1 * z2 + x1 * y2 - y1 * x2 + z1 * w2
 | 
	
		
			
				|  |  | +    return np.array([w, x, y, z])
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  def create_cameras(scene_data):
 | 
	
		
			
				|  |  |      # # Get the 05_Cameras collection, or create it if it doesn't exist
 | 
	
		
			
				|  |  |      collection_name = "05_Cameras"
 | 
	
	
		
			
				|  | @@ -444,18 +468,71 @@ def create_cameras(scene_data):
 | 
	
		
			
				|  |  |          camera.location.z = position[1]
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          # Set the camera's rotation
 | 
	
		
			
				|  |  | -        rotation = camera_data["properties"]["transform"]["rotation"]
 | 
	
		
			
				|  |  | -        rotation_euler = Euler(
 | 
	
		
			
				|  |  | -            (
 | 
	
		
			
				|  |  | -                math.radians(rotation[0]),
 | 
	
		
			
				|  |  | -                math.radians(rotation[2]),
 | 
	
		
			
				|  |  | -                math.radians(rotation[1]),
 | 
	
		
			
				|  |  | -            ),
 | 
	
		
			
				|  |  | -            "XYZ",
 | 
	
		
			
				|  |  | +        # # euler
 | 
	
		
			
				|  |  | +        # rotation_euler = camera_data["properties"]["transform"]["rotation"]
 | 
	
		
			
				|  |  | +        # rotation_euler = Euler(
 | 
	
		
			
				|  |  | +        #     (
 | 
	
		
			
				|  |  | +        #         math.radians(rotation_euler[0] + 90),
 | 
	
		
			
				|  |  | +        #         math.radians(-rotation_euler[2]),
 | 
	
		
			
				|  |  | +        #         math.radians(rotation_euler[1]),
 | 
	
		
			
				|  |  | +        #     ),
 | 
	
		
			
				|  |  | +        #     "XYZ",
 | 
	
		
			
				|  |  | +        # )
 | 
	
		
			
				|  |  | +        # quaternion
 | 
	
		
			
				|  |  | +        rotation_quat_data = camera_data["properties"]["transform"]["rotation"]
 | 
	
		
			
				|  |  | +        # rotation_quat = (
 | 
	
		
			
				|  |  | +        #     rotation_quat[3],
 | 
	
		
			
				|  |  | +        #     rotation_quat[0],
 | 
	
		
			
				|  |  | +        #     rotation_quat[1],
 | 
	
		
			
				|  |  | +        #     rotation_quat[2],
 | 
	
		
			
				|  |  | +        # )
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        # new_quat = Quaternion((2**0.5 / 2, 2**0.5 / 2, 0.0, 0.0))
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        # current_quat = Quaternion(rotation_quat)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        # result_quat = current_quat @ new_quat
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        # rotation_quat = (result_quat.w, result_quat.x, result_quat.y, result_quat.z)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        rotation_quat = [
 | 
	
		
			
				|  |  | +            rotation_quat_data[3],
 | 
	
		
			
				|  |  | +            rotation_quat_data[0],
 | 
	
		
			
				|  |  | +            rotation_quat_data[1],
 | 
	
		
			
				|  |  | +            rotation_quat_data[2],
 | 
	
		
			
				|  |  | +        ]  # Example quaternion
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        # new_quat = [2**0.5 / 2, 2**0.5 / 2, 0.0, 0.0]
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        # result_quat = quaternion_multiply(rotation_quat, new_quat)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        # Example quaternion from GLTF: [x, y, z, w]
 | 
	
		
			
				|  |  | +        gltf_quat = [0.0, 0.707, 0.0, 0.707]
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        # Convert the GLTF quaternion to Blender space (Y-up to Z-up)
 | 
	
		
			
				|  |  | +        converted_quat = Quaternion(
 | 
	
		
			
				|  |  | +            [
 | 
	
		
			
				|  |  | +                rotation_quat_data[3],
 | 
	
		
			
				|  |  | +                rotation_quat_data[0],
 | 
	
		
			
				|  |  | +                rotation_quat_data[1],
 | 
	
		
			
				|  |  | +                rotation_quat_data[2],
 | 
	
		
			
				|  |  | +            ]
 | 
	
		
			
				|  |  |          )
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +        # Define the camera correction quaternion (from GLTF file)
 | 
	
		
			
				|  |  | +        camera_correction = Quaternion((2**0.5 / 2, 2**0.5 / 2, 0.0, 0.0))
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        # Apply the camera correction to the converted quaternion
 | 
	
		
			
				|  |  | +        corrected_quat = camera_correction @ converted_quat
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        # Apply the corrected quaternion to the camera's rotation
 | 
	
		
			
				|  |  | +        camera.rotation_mode = "QUATERNION"
 | 
	
		
			
				|  |  | +        camera.rotation_quaternion = corrected_quat
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        # camera.rotation_mode = "QUATERNION"
 | 
	
		
			
				|  |  | +        # camera.rotation_quaternion = rotation_quat
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          # Apply the local rotation to the camera
 | 
	
		
			
				|  |  | -        camera.rotation_euler = rotation_euler
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          # Set the camera's lens properties
 | 
	
		
			
				|  |  |          lens = camera_data["properties"]["lens"]
 | 
	
	
		
			
				|  | @@ -464,8 +541,11 @@ def create_cameras(scene_data):
 | 
	
		
			
				|  |  |              "ORTHOGRAPHIC": "ORTHO",
 | 
	
		
			
				|  |  |              "PANORAMIC": "PANO",
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        camera.data.lens = lens["focalLength"]
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          camera.data.type = type_mapping.get(lens["type"].upper(), "PERSP")
 | 
	
		
			
				|  |  | -        camera.data.angle = math.radians(lens["fov"])
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          camera.data.clip_start = lens["near"]
 | 
	
		
			
				|  |  |          camera.data.clip_end = lens["far"]
 | 
	
		
			
				|  |  |  
 |