#!/usr/bin/env python3

import bpy
import os,sys,math
import numpy as np

"""
Rendering script for translating a blender scene into a full sky HDR image.
This script takes a series of screenshots at different camera angles, and outputs them to a directory

In this setup, the camera is adjusted to have a 50 degree field of view (so that the renders overlap slightly) and a square image output (equal aspect ratio)
"""

#X and Z camera angles for 50 degree fov screenshots to form a full-sky panorama
xorient = np.arange(-90,90,15)
zorient = np.arange(0,360,15)

#Unfortunately, this must be an absolute path in blender on Linux
# Output directory for which to output a series of screenshots
outdir = "/absolute/path/to/your/outdir"

def orient_camera(x,y,z):
    """_
        orient_camera(x,y,z)
        x,y,z - camera angles in degrees.
        Called from within blender to orient the camera, assumed to be named "Camera"
    """
    camera = bpy.data.objects["Camera"]
    camera.rotation_mode = 'XYZ'
    camera.rotation_euler[0] = x
    camera.rotation_euler[1] = y
    camera.rotation_euler[2] = z
    
    #update scene to apply changes
    bpy.context.view_layer.update()
    
    return

def render(outdir = outdir, fname="tmp.png"):
    """
    render(outdir, fname)
        outdir - the output directory in which to place the rendered image
        fname - the output filename for the rendered image

        Called from within blender to render a still image at the given location
    """


    fname = os.path.join(outdir,fname)
    
    camera = bpy.data.objects["Camera"]
    
    scene = bpy.context.scene
    
    scene.render.filepath = fname
    
    bpy.ops.render.render(write_still=True)
    
    return



def main1():
    """
        The main script.
        Rotates the camera around and saves a series of named outputs
        output names are scene_{x_angle_in_degrees}_{z_angle_in_degrees}
    """

    for I in range(0,len(xorient)):
        for J in range(0,len(zorient)):
            
            xx = np.floor(xorient[I])
            zz = np.floor(zorient[J])
            
            fnout = "scene_{:d}_{:d}.png".format(int(xx),int(zz))
            
            orient_camera((xorient[I]+90)*np.pi/180,0,zorient[J]*np.pi/180)
            render(outdir=outdir,fname=fnout)

main1()