| 1 | 
#!/usr/bin/perl | 
| 2 | 
# | 
| 3 | 
# Make an interactive preview of a luminaire | 
| 4 | 
# | 
| 5 | 
# This script is based on Radiance's objview.pl plus | 
| 6 | 
# Rob Guglielmetti's ltview extension to his objview.rb | 
| 7 | 
# | 
| 8 | 
# Written by Axel Jacobs <[email protected]> | 
| 9 | 
 | 
| 10 | 
use strict; | 
| 11 | 
use warnings; | 
| 12 | 
use Math::Trig; | 
| 13 | 
use File::Temp qw/ tempdir /; | 
| 14 | 
 | 
| 15 | 
my $td   = tempdir( CLEANUP => 1 ); | 
| 16 | 
my $oct  = "$td/ltview.oct"; | 
| 17 | 
my $room = "$td/room.rad"; | 
| 18 | 
my $box;    # Overall box dimensions | 
| 19 | 
my $rif  = "$td/ltview.rif"; | 
| 20 | 
my $lumi   = "$td/lumi.rad";     # Fitting as given on cmd line, or generated by ies2rad | 
| 21 | 
my $lumi2  = "$td/lumi2.rad";    # Fitting centred at origin | 
| 22 | 
my $raddev = "x11";              # Default output device. Overwrite with -o | 
| 23 | 
my $is_ies = 0;    # Input file is IES photometry, not a Radiance luminaire | 
| 24 | 
 | 
| 25 | 
while (@ARGV) { | 
| 26 | 
    $_ = $ARGV[0]; | 
| 27 | 
    if (m/-i/) { | 
| 28 | 
        $is_ies = 1; | 
| 29 | 
    } elsif (m/-o/) {    # output device (rvu -devices) | 
| 30 | 
        $raddev = $ARGV[1]; | 
| 31 | 
        shift @ARGV; | 
| 32 | 
    } elsif (m/-b/) { | 
| 33 | 
        $box = $ARGV[1];    # Box dimensions | 
| 34 | 
        shift @ARGV; | 
| 35 | 
    } elsif (m/^-\w/) { | 
| 36 | 
        die("ltview: Bad option: '$_'\n"); | 
| 37 | 
    } else { | 
| 38 | 
        last; | 
| 39 | 
    } | 
| 40 | 
    shift @ARGV; | 
| 41 | 
} | 
| 42 | 
 | 
| 43 | 
# We need exactly one Radiance luminaires or IES file | 
| 44 | 
if ( !$#ARGV == 0 ) { | 
| 45 | 
    die("ltview: Need one Radiance luminaire or IES file.\n"); | 
| 46 | 
} elsif ( $is_ies == 0 ) { | 
| 47 | 
 | 
| 48 | 
    # Input file is a Radiance luminaire | 
| 49 | 
    $lumi = $ARGV[0]; | 
| 50 | 
} else { | 
| 51 | 
 | 
| 52 | 
    # Input file is IES photometry | 
| 53 | 
    system qq[ ies2rad -p $td -o lumi "$ARGV[0]" ]; | 
| 54 | 
} | 
| 55 | 
 | 
| 56 | 
# Work out centre of luminaire | 
| 57 | 
my $dimstr = `getbbox -h "$lumi"`; | 
| 58 | 
chomp $dimstr; | 
| 59 | 
 | 
| 60 | 
# Values returned by getbbox are indented and delimited with multiple spaces. | 
| 61 | 
$dimstr =~ s/^\s+//;    # remove leading spaces | 
| 62 | 
my @dims = split( /\s+/, $dimstr );    # convert to array | 
| 63 | 
 | 
| 64 | 
# Find largest axes-aligned luminaire dimension | 
| 65 | 
# The box will be ten times as large, unless overwritten with -b option. | 
| 66 | 
my @diffs = reverse sort { $a <=> $b } | 
| 67 | 
  ( $dims[1] - $dims[0], $dims[3] - $dims[2], $dims[5] - $dims[4] ); | 
| 68 | 
my $lsize = $diffs[0]; | 
| 69 | 
 | 
| 70 | 
# Centre fitting at origin | 
| 71 | 
my $xtrans = -1.0 * ( $dims[0] + $dims[1] ) / 2; | 
| 72 | 
my $ytrans = -1.0 * ( $dims[2] + $dims[3] ) / 2; | 
| 73 | 
my $ztrans = -1.0 * ( $dims[4] + $dims[5] ) / 2; | 
| 74 | 
system qq[ xform -t $xtrans $ytrans $ztrans "$lumi" > $lumi2 ]; | 
| 75 | 
 | 
| 76 | 
# Make the enclosing box | 
| 77 | 
my $b2; | 
| 78 | 
if ( defined $box ) { | 
| 79 | 
 | 
| 80 | 
    # Room dimensions are giving explicitly. | 
| 81 | 
    $b2 = $box / 2; | 
| 82 | 
} else { | 
| 83 | 
 | 
| 84 | 
    # Box dimensions are ten times largest luminaire bbox dimensions. | 
| 85 | 
    $b2 = $lsize * 10.0 / 2.0; | 
| 86 | 
} | 
| 87 | 
 | 
| 88 | 
open( FH, ">$room" ) | 
| 89 | 
  or die("ltview: Can't write to temporary file '$room'\n"); | 
| 90 | 
print FH <<EndOfRoom; | 
| 91 | 
void plastic wall_mat  0  0  5 .2 .2 .2 0 0 | 
| 92 | 
 | 
| 93 | 
# Don't generate -y face so we can look into the box | 
| 94 | 
#wall_mat polygon box.1540  0  0  12  $b2 -$b2 -$b2  $b2 -$b2 $b2  -$b2 -$b2 $b2  -$b2 -$b2 -$b2 | 
| 95 | 
wall_mat polygon box.4620  0  0  12  -$b2 -$b2 $b2  -$b2 $b2 $b2  -$b2 $b2 -$b2  -$b2 -$b2 -$b2 | 
| 96 | 
wall_mat polygon box.2310  0  0  12  -$b2 $b2 -$b2  $b2 $b2 -$b2  $b2 -$b2 -$b2  -$b2 -$b2 -$b2 | 
| 97 | 
wall_mat polygon box.3267  0  0  12  $b2 $b2 -$b2  -$b2 $b2 -$b2  -$b2 $b2 $b2  $b2 $b2 $b2 | 
| 98 | 
wall_mat polygon box.5137  0  0  12  $b2 -$b2 $b2  $b2 -$b2 -$b2  $b2 $b2 -$b2  $b2 $b2 $b2 | 
| 99 | 
wall_mat polygon box.6457  0  0  12  -$b2 $b2 $b2  -$b2 -$b2 $b2  $b2 -$b2 $b2  $b2 $b2 $b2 | 
| 100 | 
EndOfRoom | 
| 101 | 
close(FH); | 
| 102 | 
 | 
| 103 | 
my $scene = "$room $lumi2"; | 
| 104 | 
 | 
| 105 | 
# Make this work under Windoze | 
| 106 | 
if ( $^O =~ /MSWin32/ ) { | 
| 107 | 
    $scene =~ s{\\}{/}g; | 
| 108 | 
    $oct =~ s{\\}{/}g; | 
| 109 | 
    $raddev = "qt"; | 
| 110 | 
} | 
| 111 | 
 | 
| 112 | 
# Tweak scene bounding box so we get a nice view covering all of the box, without | 
| 113 | 
# having a wasteful black border around it.  Must work for arbitrary box dims. | 
| 114 | 
my $zone = 1.1 * $b2 * ( 1 + 1 / tan( 22.5 * pi / 180 ) ); | 
| 115 | 
 | 
| 116 | 
open( FH, ">$rif" ) | 
| 117 | 
  or die("ltview: Can't write to temporary file '$rif'\n"); | 
| 118 | 
print FH <<EndOfRif; | 
| 119 | 
scene= $scene | 
| 120 | 
ZONE= Interior -$zone $zone  -$zone $zone  -$zone $zone | 
| 121 | 
UP= Z | 
| 122 | 
view= y | 
| 123 | 
OCTREE= $oct | 
| 124 | 
oconv= -f | 
| 125 | 
render= -av 0 0 0 | 
| 126 | 
INDIRECT= 0 | 
| 127 | 
QUALITY= Med | 
| 128 | 
DETAIL= Low | 
| 129 | 
VARIABILITY= Med | 
| 130 | 
EndOfRif | 
| 131 | 
close(FH); | 
| 132 | 
 | 
| 133 | 
exec "rad -o $raddev $rif"; | 
| 134 | 
 | 
| 135 | 
#EOF |