bin/ltview.pl
changeset 44 c8df2d579470
parent 38 a21b69f32c77
child 61 4f3a9f297a6a
--- a/bin/ltview.pl	Sun Dec 15 18:03:49 2013 +0000
+++ b/bin/ltview.pl	Sun Dec 15 18:04:10 2013 +0000
@@ -1,31 +1,31 @@
 #!/usr/bin/perl
 #
-# Make a nice view of an object
-# Arguments are scene input files
+# Make a nice view of a luminaire
+# Argument is the Radiance description of a luminaire, incl. distribution
 #
-# This is a re-write of Greg's original objview.csh.
-# The only extra functionality is that we accept a scene on STDIN
-# if no file name is given.
+# This script is based on Radiance's objview.pl plus
+# Rob Guglielmetti's ltview extension to his objview.rb
 #
-# Axel, Nov 2013
+# Axel Jacobs, 25 Dec 2013
 
 use strict;
 use warnings;
 use File::Temp qw/ tempdir /;
 
-#my $td = tempdir( CLEANUP => 1 );
-my $td = "tmp";
-my $octree = "$td/ov$$.oct";
+my $td = tempdir( CLEANUP => 1 );
+my $octree = "$td/lt$$.oct";
 my $room = "$td/rm$$.rad";
-my $rif = "$td/ov$$.rif";
+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";
-my $rsize = 1;    # room size in metres
+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 $opts = "";        # Options common to rad and glrad
-my $rendopts = "-ab 1 -ds .15";    # For render= line in rif file
+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).
@@ -34,9 +34,11 @@
 	$_ = $ARGV[0];
 	if (m/-g/) {   # OpenGL output
 		if ( $^O =~ /MSWin32/ ) {
-			die("OpenGL view is not available under Windows.\n");
+			# No meaningful error messages under Windows. Just ignore...
+			#die("OpenGL view is not available under Windows.\n");
+		} else {
+			$usegl = 1;
 		}
-		$usegl = 1;
 	} elsif (m/-u/) {   # up direction
 		$up = $ARGV[1];
 		shift @ARGV;
@@ -45,11 +47,17 @@
 	} elsif (m/-b/) {   # back face visibility
 		$rendopts .= ' -bv';
 	} elsif (m/-v/) {   # standard view "[Xx]?[Yy]?[Zz]?[vlcahs]?"
-		# Let rad do any error handling...
+		# 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
-		$opts .= ' -N ' . $ARGV[1];
+		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;
 	} elsif (m/-o/) {   # output device (rvu -devices)
@@ -63,9 +71,8 @@
 	} elsif (m/-S/) {   # full-screen stereo
 		$opts .= " $_";
 		$glradopt = 1;
-	} elsif (m/-r/) {    # room size
-		$rsize = $ARGV[1];
-		shift @ARGV;
+	} elsif (m/-r/) {    # spherical room rather than box
+		$bubble = 1;
 	} elsif (m/^-\w/) {
 		die("objview: Bad option: $_\n");
 	} else {
@@ -74,11 +81,11 @@
 	shift @ARGV;
 }
 
-# We need one IES file
+# We need exactly one input file: a Radiance luminaires description
+#TODO: this could be expanded to handle Radiance .dat files and IES photometry files...
 if (! $#ARGV == 0) {
-	die("ltview: Need one IES photometry file\n");
+	die("ltview: Need one Radiance luminaire.\n");
 }
-my $scene = $ARGV[0];
 
 # Make sure we don't confuse glrad and rad options.
 if ($usegl) {
@@ -93,24 +100,65 @@
 
 open(FH, ">$room") or
 		die("ltview: Can't write to temporary file $room\n");
-print FH <<EndOfRoom;
-void plastic surf  0  0  5  .2 .2 .2 0 0
-!genbox -i surf room $rsize $rsize $rsize |xform -t -$rsize/2 -$rsize/2 -$rsize/2
+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";
+} 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);
 
+# 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 unity
+my $scale = 1 / $size;
+
+my $cmd = "xform -t $xtrans $ytrans $ztrans -s $scale $ARGV[0] > $lumi";
+system "$cmd";
+
+my $scene = "$room $lumi";
 # Make this work under Windoze
 if ( $^O =~ /MSWin32/ ) {
 	$scene =~ s{\\}{/}g;
 	$octree =~ s{\\}{/}g;
+	$ambf =~ s{\\}{/}g;
 	$raddev = "qt";
 }
 
+my $custom_vw = $vw;
+$vw =~ s/^\+//;
 open(FH, ">$rif") or
-		die("objview: Can't write to temporary file $rif\n");
+		die("ltview: Can't write to temporary file $rif\n");
 print FH <<EndOfRif;
 scene= $scene
-EXPOSURE= .5
+EXPOSURE= 2
+ZONE= Interior -5 5  -5 5  -5 5
 UP= $up
 view= $vw
 OCTREE= $octree
@@ -120,6 +168,52 @@
 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 {