bin/ltview.pl
changeset 61 4f3a9f297a6a
parent 44 c8df2d579470
child 66 7e56c36eb1ae
--- a/bin/ltview.pl	Tue Mar 11 00:29:36 2014 +0000
+++ b/bin/ltview.pl	Tue Mar 11 00:30:15 2014 +0000
@@ -1,78 +1,44 @@
 #!/usr/bin/perl
 #
-# Make a nice view of a luminaire
-# Argument is the Radiance description of a luminaire, incl. distribution
+# 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
 #
-# Axel Jacobs, 25 Dec 2013
+# Written by Axel Jacobs <axel@jaloxa.eu>
 
 use strict;
 use warnings;
+use Math::Trig;
+use File::Copy;
 use File::Temp qw/ tempdir /;
 
-my $td = tempdir( CLEANUP => 1 );
-my $octree = "$td/lt$$.oct";
-my $room = "$td/rm$$.rad";
-my $rif = "$td/lt$$.rif";
-my $lumi = "$td/lt$$.rad";
-my $ambf = "$td/af$$.amb";
-my $raddev = "x11";   # default output device. Overwrite with -o
-my $up = "Z";
-my $vw = "XYZ";    # default view. See 'man rad' for details
-my $bubble = 0;    # Box or bubble?  0..box, 1..bubble
-my $TINY = 0.01;
+my $td     = tempdir( CLEANUP => 1 );
+my $oct    = "$td/ltview.oct";
+my $room   = "$td/room.rad";
+my $rdim;               # Overall room dimensions
+my $rif    = "$td/ltview.rif";
+my $lumi   = "$td/lumi.rad";
+my $ies    = "$td/lumi.ies";
+my $raddev = "x11";     # default output device. Overwrite with -o
+my $is_ies = 0;         # input file is IES photometry, not a Radiance luminaire
 
-my $opts = "";        # Options common to rad and glrad
-my $rendopts = "-ab 1 -ds .15 -av 0 0 0";    # For render= line in rif file
-my $usegl = 0;        # Run glrad instead of rad (Boolean).
-my $radopt = 0;       # An option specific to rad was passed (Boolean).
-my $glradopt = 0;     # An option specific to glrad was passed (Boolean).
+my $maxscale = 1;       # Maximum luminiare dimension after scaling
+my $opts     = "";      # Options common to rad and glrad
+my $render   = "-ab 1 -ds .15 -av 0 0 0";    # render= line in rif file
+my $radopt   = 0;       # An option specific to rad was passed (Boolean).
 
 while (@ARGV) {
 	$_ = $ARGV[0];
-	if (m/-g/) {   # OpenGL output
-		if ( $^O =~ /MSWin32/ ) {
-			# No meaningful error messages under Windows. Just ignore...
-			#die("OpenGL view is not available under Windows.\n");
-		} else {
-			$usegl = 1;
-		}
-	} elsif (m/-u/) {   # up direction
-		$up = $ARGV[1];
-		shift @ARGV;
-	} elsif ((m/-s/) or (m/-w/)) {   # silent, no warnings
-		$opts .= " $_";
-	} elsif (m/-b/) {   # back face visibility
-		$rendopts .= ' -bv';
-	} elsif (m/-v/) {   # standard view "[Xx]?[Yy]?[Zz]?[vlcahs]?"
-		# Prepend view with '+' for custom view away from the luminaire, not at it.
-		# This is not defined by rad's default views.
-		$vw = $ARGV[1];
-		shift @ARGV;
-	} elsif (m/-N/) {   # No. of parallel processes
-		if ( $^O =~ /MSWin32/ ) {
-			# Silently ignore this under Windoze
-			#die("Multi-processor support is not available under Windows.\n");
-		} else {
-			$opts .= ' -N ' . $ARGV[1];
-		}
-		$radopt = 1;
-		shift @ARGV;
+	if (m/-i/) {
+		$is_ies = 1;
 	} elsif (m/-o/) {   # output device (rvu -devices)
 		$raddev = $ARGV[1];
 		$radopt = 1;
 		shift @ARGV;
-	} elsif ((m/-V/) or (m/-e/)) {   # print view, explicate variables
-		# Think of those two as '-verbose'.
-		$opts .= " $_";
-		$radopt = 1;
-	} elsif (m/-S/) {   # full-screen stereo
-		$opts .= " $_";
-		$glradopt = 1;
-	} elsif (m/-r/) {    # spherical room rather than box
-		$bubble = 1;
+	} elsif (m/-r/) {
+		$rdim = $ARGV[1];    # Room dimensions
+		shift @ARGV;
 	} elsif (m/^-\w/) {
 		die("objview: Bad option: $_\n");
 	} else {
@@ -81,143 +47,85 @@
 	shift @ARGV;
 }
 
-# We need exactly one input file: a Radiance luminaires description
-#TODO: this could be expanded to handle Radiance .dat files and IES photometry files...
+# We need one Radiance luminaires description, or an IES file
 if (! $#ARGV == 0) {
-	die("ltview: Need one Radiance luminaire.\n");
-}
-
-# Make sure we don't confuse glrad and rad options.
-if ($usegl) {
-	if ($radopt) {
-		die("objview: glrad output requested, but rad option passed.\n");
-	}
-} else {
-	if ($glradopt) {
-		die("objview: rad output requested, but glrad option passed.\n");
-	}
+	die("ltview: Need one Radiance luminaire or IES file.\n");
 }
 
 open(FH, ">$room") or
 		die("ltview: Can't write to temporary file $room\n");
 print FH "void plastic wall_mat  0  0  5 .2 .2 .2 0 0\n";
 
-if ($bubble == 1) {
-	# Room is a bubble, not a box
-	my $radius = sprintf "%.6f", 1.1*5 * 3**(1/3);
-	print FH "wall_mat sphere orb  0  0  4 0 0 0 $radius\n";
+my $r;
+if (defined $rdim) {
+	# Room dimensions are giving explicitly.  Don't touch the fitting.
+	$r = $rdim;
+
+	copy ($ARGV[0], $lumi);
 } else {
-	print FH <<EndOfRoom;
-# Don't rely on genbox here (named genrbox under Debian/Ubuntu)
-wall_mat polygon box.1540  0  0  12  5 -5 -5  5 -5 5  -5 -5 5  -5 -5 -5
-wall_mat polygon box.4620  0  0  12  -5 -5 5  -5 5 5  -5 5 -5  -5 -5 -5
-wall_mat polygon box.2310  0  0  12  -5 5 -5  5 5 -5  5 -5 -5  -5 -5 -5
-wall_mat polygon box.3267  0  0  12  5 5 -5  -5 5 -5  -5 5 5  5 5 5
-wall_mat polygon box.5137  0  0  12  5 -5 5  5 -5 -5  5 5 -5  5 5 5
-wall_mat polygon box.6457  0  0  12  -5 5 5  -5 -5 5  5 -5 5  5 5 5
-EndOfRoom
-}
-close(FH);
+	# Scale fitting so it fits nicely into our default test room.
+	$r = 5;    # Default room dimension
+
+	# Work out how large the luminaire is and scale so that the longest
+	# axis-align dimension is $maxscale
+	my $dimstr = `getbbox -h $ARGV[0]`;
+	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
 
-# Work out how large the luminaire is and scale so that the longest
-# axis-align dimension is one unit
-my $dimstr = `getbbox -h $ARGV[0]`;
-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 dimension
+	my @diffs = ($dims[1]-$dims[0], $dims[3]-$dims[2], $dims[5]-$dims[4]);
+	@diffs = reverse sort { $a <=> $b } @diffs;
+	my $size = $diffs[0];
+
+	# Move objects so centre is 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;
+	# Scale so that largest object dimension is $maxscale
+	my $scale = $maxscale / $size;
 
-# Find largest axes-aligned dimension
-my @diffs = ($dims[1]-$dims[0], $dims[3]-$dims[2], $dims[5]-$dims[4]);
-@diffs = reverse sort { $a <=> $b } @diffs;
-my $size = $diffs[0];
+	system "xform -t $xtrans $ytrans $ztrans -s $scale $ARGV[0] > $lumi";
+}
 
-# Move objects so centre is 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;
-# Scale so that largest object dimension is unity
-my $scale = 1 / $size;
-
-my $cmd = "xform -t $xtrans $ytrans $ztrans -s $scale $ARGV[0] > $lumi";
-system "$cmd";
+print FH <<EndOfRoom;
+# Don't generate -y face so we can look into the box (could use clipping)
+#wall_mat polygon box.1540  0  0  12  $r -$r -$r  $r -$r $r  -$r -$r $r  -$r -$r -$r
+wall_mat polygon box.4620  0  0  12  -$r -$r $r  -$r $r $r  -$r $r -$r  -$r -$r -$r
+wall_mat polygon box.2310  0  0  12  -$r $r -$r  $r $r -$r  $r -$r -$r  -$r -$r -$r
+wall_mat polygon box.3267  0  0  12  $r $r -$r  -$r $r -$r  -$r $r $r  $r $r $r
+wall_mat polygon box.5137  0  0  12  $r -$r $r  $r -$r -$r  $r $r -$r  $r $r $r
+wall_mat polygon box.6457  0  0  12  -$r $r $r  -$r -$r $r  $r -$r $r  $r $r $r
+EndOfRoom
+close(FH);
 
 my $scene = "$room $lumi";
 # Make this work under Windoze
 if ( $^O =~ /MSWin32/ ) {
 	$scene =~ s{\\}{/}g;
-	$octree =~ s{\\}{/}g;
-	$ambf =~ s{\\}{/}g;
+	$oct =~ s{\\}{/}g;
 	$raddev = "qt";
 }
 
-my $custom_vw = $vw;
-$vw =~ s/^\+//;
+# Tweak 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 * $r * ( 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
 EXPOSURE= 2
-ZONE= Interior -5 5  -5 5  -5 5
-UP= $up
-view= $vw
-OCTREE= $octree
+ZONE= Interior -$zone $zone  -$zone $zone  -$zone $zone
+UP= Z
+view= y
+OCTREE= $oct
 oconv= -f
-AMBF= $ambf
-render= $rendopts
+render= $render
 EndOfRif
 close(FH);
 
-# Custom view: look away from the luminaire, not at it.  This is indicated
-# by a leading '+' in front of the view (-v argument, default: XYZ)
-if ($custom_vw =~ m/^\+/) {
-	# Get rad to spit out the -v* options for the default view requested
-	my $view = `rad -V -n -s $rif`;
-	$view =~ s/\n//;
-	$view =~ s/^VIEW= //;
-
-	my $x = 0;
-	my $y = 0;
-	my $z = 0;
-	if ($vw =~ m/X/) {
-		$x = $dims[0] - $TINY;
-	} elsif ($vw =~ m/x/) {
-		$x = $dims[1] + $TINY;
-	}
-	if ($vw =~ m/Y/) {
-		$y = $dims[2] - $TINY;
-	} elsif ($vw =~ m/y/) {
-		$y = $dims[3] + $TINY;
-	}
-	if ($vw =~ m/Z/) {
-		$z = $dims[4] - $TINY;
-	} elsif ($vw =~ m/z/) {
-		$z = $dims[5] + $TINY;
-	}
-	
-	# Keep rad-generated standard view, but modify -vp
-	$vw = "nice $view -vp $x $y $z";
-
-	open(FH, ">$rif") or
-			die("ltview: Can't write to temporary file $rif\n");
-	print FH <<EndOfRif2;
-scene= $scene
-EXPOSURE= 2
-ZONE= Interior -5 5  -5 5  -5 5
-UP= $up
-view= $vw
-OCTREE= $octree
-oconv= -f
-AMBF= $ambf
-render= $rendopts
-EndOfRif2
-	close(FH);
-}
-
-if ($usegl) {
-	system "glrad $opts $rif";
-} else {
-	system "rad -o $raddev $opts $rif";
-}
+system "rad -o $raddev $opts $rif";
 
 #EOF