#!/usr/bin/perl
#
# Make an interactive preview of a luminaire
#
# This script is based on Radiance's objview.pl plus
# Rob Guglielmetti's ltview extension to his objview.rb
#
# Written by Axel Jacobs <axel@jaloxa.eu>

use strict;
use warnings;
use Math::Trig;
use File::Temp qw/ tempdir /;

my $td   = tempdir( CLEANUP => 1 );
my $oct  = "$td/ltview.oct";
my $room = "$td/room.rad";
my $box;    # Overall box dimensions
my $rif  = "$td/ltview.rif";
my $lumi   = "$td/lumi.rad";     # Fitting as given on cmd line, or generated by ies2rad
my $lumi2  = "$td/lumi2.rad";    # Fitting centred at origin
my $raddev = "x11";              # Default output device. Overwrite with -o
my $is_ies = 0;    # Input file is IES photometry, not a Radiance luminaire

while (@ARGV) {
    $_ = $ARGV[0];
    if (m/-i/) {
        $is_ies = 1;
    } elsif (m/-o/) {    # output device (rvu -devices)
        $raddev = $ARGV[1];
        shift @ARGV;
    } elsif (m/-b/) {
        $box = $ARGV[1];    # Box dimensions
        shift @ARGV;
    } elsif (m/^-\w/) {
        die("ltview: Bad option: '$_'\n");
    } else {
        last;
    }
    shift @ARGV;
}

# We need exactly one Radiance luminaires or IES file
if ( !$#ARGV == 0 ) {
    die("ltview: Need one Radiance luminaire or IES file.\n");
} elsif ( $is_ies == 0 ) {

    # Input file is a Radiance luminaire
    $lumi = $ARGV[0];
} else {

    # Input file is IES photometry
    system qq[ ies2rad -p $td -o lumi "$ARGV[0]" ];
}

# Work out centre of luminaire
my $dimstr = `getbbox -h "$lumi"`;
chomp $dimstr;

# Values returned by getbbox are indented and delimited with multiple spaces.
$dimstr =~ s/^\s+//;    # remove leading spaces
my @dims = split( /\s+/, $dimstr );    # convert to array

# Find largest axes-aligned luminaire dimension
# The box will be ten times as large, unless overwritten with -b option.
my @diffs = reverse sort { $a <=> $b }
  ( $dims[1] - $dims[0], $dims[3] - $dims[2], $dims[5] - $dims[4] );
my $lsize = $diffs[0];

# Centre fitting at origin
my $xtrans = -1.0 * ( $dims[0] + $dims[1] ) / 2;
my $ytrans = -1.0 * ( $dims[2] + $dims[3] ) / 2;
my $ztrans = -1.0 * ( $dims[4] + $dims[5] ) / 2;
system qq[ xform -t $xtrans $ytrans $ztrans "$lumi" > $lumi2 ];

# Make the enclosing box
my $b2;
if ( defined $box ) {

    # Room dimensions are giving explicitly.
    $b2 = $box / 2;
} else {

    # Box dimensions are ten times largest luminaire bbox dimensions.
    $b2 = $lsize * 10.0 / 2.0;
}

open( FH, ">$room" )
  or die("ltview: Can't write to temporary file '$room'\n");
print FH <<EndOfRoom;
void plastic wall_mat  0  0  5 .2 .2 .2 0 0

# Don't generate -y face so we can look into the box
#wall_mat polygon box.1540  0  0  12  $b2 -$b2 -$b2  $b2 -$b2 $b2  -$b2 -$b2 $b2  -$b2 -$b2 -$b2
wall_mat polygon box.4620  0  0  12  -$b2 -$b2 $b2  -$b2 $b2 $b2  -$b2 $b2 -$b2  -$b2 -$b2 -$b2
wall_mat polygon box.2310  0  0  12  -$b2 $b2 -$b2  $b2 $b2 -$b2  $b2 -$b2 -$b2  -$b2 -$b2 -$b2
wall_mat polygon box.3267  0  0  12  $b2 $b2 -$b2  -$b2 $b2 -$b2  -$b2 $b2 $b2  $b2 $b2 $b2
wall_mat polygon box.5137  0  0  12  $b2 -$b2 $b2  $b2 -$b2 -$b2  $b2 $b2 -$b2  $b2 $b2 $b2
wall_mat polygon box.6457  0  0  12  -$b2 $b2 $b2  -$b2 -$b2 $b2  $b2 -$b2 $b2  $b2 $b2 $b2
EndOfRoom
close(FH);

my $scene = "$room $lumi2";

# Make this work under Windoze
if ( $^O =~ /MSWin32/ ) {
    $scene =~ s{\\}{/}g;
    $oct =~ s{\\}{/}g;
    $raddev = "qt";
}

# Tweak scene bounding box so we get a nice view covering all of the box, without
# having a wasteful black border around it.  Must work for arbitrary box dims.
my $zone = 1.1 * $b2 * ( 1 + 1 / tan( 22.5 * pi / 180 ) );

open( FH, ">$rif" )
  or die("ltview: Can't write to temporary file '$rif'\n");
print FH <<EndOfRif;
scene= $scene
ZONE= Interior -$zone $zone  -$zone $zone  -$zone $zone
UP= Z
view= y
OCTREE= $oct
oconv= -f
render= -av 0 0 0
INDIRECT= 0
QUALITY= Med
DETAIL= Low
VARIABILITY= Med
EndOfRif
close(FH);

exec "rad -o $raddev $rif";

#EOF
