bin/ltview.pl
changeset 44 c8df2d579470
parent 38 a21b69f32c77
child 61 4f3a9f297a6a
equal deleted inserted replaced
43:417e2adf19bf 44:c8df2d579470
     1 #!/usr/bin/perl
     1 #!/usr/bin/perl
     2 #
     2 #
     3 # Make a nice view of an object
     3 # Make a nice view of a luminaire
     4 # Arguments are scene input files
     4 # Argument is the Radiance description of a luminaire, incl. distribution
     5 #
     5 #
     6 # This is a re-write of Greg's original objview.csh.
     6 # This script is based on Radiance's objview.pl plus
     7 # The only extra functionality is that we accept a scene on STDIN
     7 # Rob Guglielmetti's ltview extension to his objview.rb
     8 # if no file name is given.
       
     9 #
     8 #
    10 # Axel, Nov 2013
     9 # Axel Jacobs, 25 Dec 2013
    11 
    10 
    12 use strict;
    11 use strict;
    13 use warnings;
    12 use warnings;
    14 use File::Temp qw/ tempdir /;
    13 use File::Temp qw/ tempdir /;
    15 
    14 
    16 #my $td = tempdir( CLEANUP => 1 );
    15 my $td = tempdir( CLEANUP => 1 );
    17 my $td = "tmp";
    16 my $octree = "$td/lt$$.oct";
    18 my $octree = "$td/ov$$.oct";
       
    19 my $room = "$td/rm$$.rad";
    17 my $room = "$td/rm$$.rad";
    20 my $rif = "$td/ov$$.rif";
    18 my $rif = "$td/lt$$.rif";
       
    19 my $lumi = "$td/lt$$.rad";
    21 my $ambf = "$td/af$$.amb";
    20 my $ambf = "$td/af$$.amb";
    22 my $raddev = "x11";   # default output device. Overwrite with -o
    21 my $raddev = "x11";   # default output device. Overwrite with -o
    23 my $up = "Z";
    22 my $up = "Z";
    24 my $vw = "XYZ";
    23 my $vw = "XYZ";    # default view. See 'man rad' for details
    25 my $rsize = 1;    # room size in metres
    24 my $bubble = 0;    # Box or bubble?  0..box, 1..bubble
       
    25 my $TINY = 0.01;
    26 
    26 
    27 my $opts = "";        # Options common to rad and glrad
    27 my $opts = "";        # Options common to rad and glrad
    28 my $rendopts = "-ab 1 -ds .15";    # For render= line in rif file
    28 my $rendopts = "-ab 1 -ds .15 -av 0 0 0";    # For render= line in rif file
    29 my $usegl = 0;        # Run glrad instead of rad (Boolean).
    29 my $usegl = 0;        # Run glrad instead of rad (Boolean).
    30 my $radopt = 0;       # An option specific to rad was passed (Boolean).
    30 my $radopt = 0;       # An option specific to rad was passed (Boolean).
    31 my $glradopt = 0;     # An option specific to glrad was passed (Boolean).
    31 my $glradopt = 0;     # An option specific to glrad was passed (Boolean).
    32 
    32 
    33 while (@ARGV) {
    33 while (@ARGV) {
    34 	$_ = $ARGV[0];
    34 	$_ = $ARGV[0];
    35 	if (m/-g/) {   # OpenGL output
    35 	if (m/-g/) {   # OpenGL output
    36 		if ( $^O =~ /MSWin32/ ) {
    36 		if ( $^O =~ /MSWin32/ ) {
    37 			die("OpenGL view is not available under Windows.\n");
    37 			# No meaningful error messages under Windows. Just ignore...
       
    38 			#die("OpenGL view is not available under Windows.\n");
       
    39 		} else {
       
    40 			$usegl = 1;
    38 		}
    41 		}
    39 		$usegl = 1;
       
    40 	} elsif (m/-u/) {   # up direction
    42 	} elsif (m/-u/) {   # up direction
    41 		$up = $ARGV[1];
    43 		$up = $ARGV[1];
    42 		shift @ARGV;
    44 		shift @ARGV;
    43 	} elsif ((m/-s/) or (m/-w/)) {   # silent, no warnings
    45 	} elsif ((m/-s/) or (m/-w/)) {   # silent, no warnings
    44 		$opts .= " $_";
    46 		$opts .= " $_";
    45 	} elsif (m/-b/) {   # back face visibility
    47 	} elsif (m/-b/) {   # back face visibility
    46 		$rendopts .= ' -bv';
    48 		$rendopts .= ' -bv';
    47 	} elsif (m/-v/) {   # standard view "[Xx]?[Yy]?[Zz]?[vlcahs]?"
    49 	} elsif (m/-v/) {   # standard view "[Xx]?[Yy]?[Zz]?[vlcahs]?"
    48 		# Let rad do any error handling...
    50 		# Prepend view with '+' for custom view away from the luminaire, not at it.
       
    51 		# This is not defined by rad's default views.
    49 		$vw = $ARGV[1];
    52 		$vw = $ARGV[1];
    50 		shift @ARGV;
    53 		shift @ARGV;
    51 	} elsif (m/-N/) {   # No. of parallel processes
    54 	} elsif (m/-N/) {   # No. of parallel processes
    52 		$opts .= ' -N ' . $ARGV[1];
    55 		if ( $^O =~ /MSWin32/ ) {
       
    56 			# Silently ignore this under Windoze
       
    57 			#die("Multi-processor support is not available under Windows.\n");
       
    58 		} else {
       
    59 			$opts .= ' -N ' . $ARGV[1];
       
    60 		}
    53 		$radopt = 1;
    61 		$radopt = 1;
    54 		shift @ARGV;
    62 		shift @ARGV;
    55 	} elsif (m/-o/) {   # output device (rvu -devices)
    63 	} elsif (m/-o/) {   # output device (rvu -devices)
    56 		$raddev = $ARGV[1];
    64 		$raddev = $ARGV[1];
    57 		$radopt = 1;
    65 		$radopt = 1;
    61 		$opts .= " $_";
    69 		$opts .= " $_";
    62 		$radopt = 1;
    70 		$radopt = 1;
    63 	} elsif (m/-S/) {   # full-screen stereo
    71 	} elsif (m/-S/) {   # full-screen stereo
    64 		$opts .= " $_";
    72 		$opts .= " $_";
    65 		$glradopt = 1;
    73 		$glradopt = 1;
    66 	} elsif (m/-r/) {    # room size
    74 	} elsif (m/-r/) {    # spherical room rather than box
    67 		$rsize = $ARGV[1];
    75 		$bubble = 1;
    68 		shift @ARGV;
       
    69 	} elsif (m/^-\w/) {
    76 	} elsif (m/^-\w/) {
    70 		die("objview: Bad option: $_\n");
    77 		die("objview: Bad option: $_\n");
    71 	} else {
    78 	} else {
    72 		last;
    79 		last;
    73 	}
    80 	}
    74 	shift @ARGV;
    81 	shift @ARGV;
    75 }
    82 }
    76 
    83 
    77 # We need one IES file
    84 # We need exactly one input file: a Radiance luminaires description
       
    85 #TODO: this could be expanded to handle Radiance .dat files and IES photometry files...
    78 if (! $#ARGV == 0) {
    86 if (! $#ARGV == 0) {
    79 	die("ltview: Need one IES photometry file\n");
    87 	die("ltview: Need one Radiance luminaire.\n");
    80 }
    88 }
    81 my $scene = $ARGV[0];
       
    82 
    89 
    83 # Make sure we don't confuse glrad and rad options.
    90 # Make sure we don't confuse glrad and rad options.
    84 if ($usegl) {
    91 if ($usegl) {
    85 	if ($radopt) {
    92 	if ($radopt) {
    86 		die("objview: glrad output requested, but rad option passed.\n");
    93 		die("objview: glrad output requested, but rad option passed.\n");
    91 	}
    98 	}
    92 }
    99 }
    93 
   100 
    94 open(FH, ">$room") or
   101 open(FH, ">$room") or
    95 		die("ltview: Can't write to temporary file $room\n");
   102 		die("ltview: Can't write to temporary file $room\n");
    96 print FH <<EndOfRoom;
   103 print FH "void plastic wall_mat  0  0  5 .2 .2 .2 0 0\n";
    97 void plastic surf  0  0  5  .2 .2 .2 0 0
   104 
    98 !genbox -i surf room $rsize $rsize $rsize |xform -t -$rsize/2 -$rsize/2 -$rsize/2
   105 if ($bubble == 1) {
       
   106 	# Room is a bubble, not a box
       
   107 	my $radius = sprintf "%.6f", 1.1*5 * 3**(1/3);
       
   108 	print FH "wall_mat sphere orb  0  0  4 0 0 0 $radius\n";
       
   109 } else {
       
   110 	print FH <<EndOfRoom;
       
   111 # Don't rely on genbox here (named genrbox under Debian/Ubuntu)
       
   112 wall_mat polygon box.1540  0  0  12  5 -5 -5  5 -5 5  -5 -5 5  -5 -5 -5
       
   113 wall_mat polygon box.4620  0  0  12  -5 -5 5  -5 5 5  -5 5 -5  -5 -5 -5
       
   114 wall_mat polygon box.2310  0  0  12  -5 5 -5  5 5 -5  5 -5 -5  -5 -5 -5
       
   115 wall_mat polygon box.3267  0  0  12  5 5 -5  -5 5 -5  -5 5 5  5 5 5
       
   116 wall_mat polygon box.5137  0  0  12  5 -5 5  5 -5 -5  5 5 -5  5 5 5
       
   117 wall_mat polygon box.6457  0  0  12  -5 5 5  -5 -5 5  5 -5 5  5 5 5
    99 EndOfRoom
   118 EndOfRoom
       
   119 }
   100 close(FH);
   120 close(FH);
   101 
   121 
       
   122 # Work out how large the luminaire is and scale so that the longest
       
   123 # axis-align dimension is one unit
       
   124 my $dimstr = `getbbox -h $ARGV[0]`;
       
   125 chomp $dimstr;
       
   126 # Values returned by getbbox are indented and delimited with multiple spaces.
       
   127 $dimstr =~ s/^\s+//;   # remove leading spaces
       
   128 my @dims = split(/\s+/, $dimstr);   # convert to array
       
   129 
       
   130 # Find largest axes-aligned dimension
       
   131 my @diffs = ($dims[1]-$dims[0], $dims[3]-$dims[2], $dims[5]-$dims[4]);
       
   132 @diffs = reverse sort { $a <=> $b } @diffs;
       
   133 my $size = $diffs[0];
       
   134 
       
   135 # Move objects so centre is at origin
       
   136 my $xtrans = -1.0 * ($dims[0] + $dims[1]) / 2;
       
   137 my $ytrans = -1.0 * ($dims[2] + $dims[3]) / 2;
       
   138 my $ztrans = -1.0 * ($dims[4] + $dims[5]) / 2;
       
   139 # Scale so that largest object dimension is unity
       
   140 my $scale = 1 / $size;
       
   141 
       
   142 my $cmd = "xform -t $xtrans $ytrans $ztrans -s $scale $ARGV[0] > $lumi";
       
   143 system "$cmd";
       
   144 
       
   145 my $scene = "$room $lumi";
   102 # Make this work under Windoze
   146 # Make this work under Windoze
   103 if ( $^O =~ /MSWin32/ ) {
   147 if ( $^O =~ /MSWin32/ ) {
   104 	$scene =~ s{\\}{/}g;
   148 	$scene =~ s{\\}{/}g;
   105 	$octree =~ s{\\}{/}g;
   149 	$octree =~ s{\\}{/}g;
       
   150 	$ambf =~ s{\\}{/}g;
   106 	$raddev = "qt";
   151 	$raddev = "qt";
   107 }
   152 }
   108 
   153 
       
   154 my $custom_vw = $vw;
       
   155 $vw =~ s/^\+//;
   109 open(FH, ">$rif") or
   156 open(FH, ">$rif") or
   110 		die("objview: Can't write to temporary file $rif\n");
   157 		die("ltview: Can't write to temporary file $rif\n");
   111 print FH <<EndOfRif;
   158 print FH <<EndOfRif;
   112 scene= $scene
   159 scene= $scene
   113 EXPOSURE= .5
   160 EXPOSURE= 2
       
   161 ZONE= Interior -5 5  -5 5  -5 5
   114 UP= $up
   162 UP= $up
   115 view= $vw
   163 view= $vw
   116 OCTREE= $octree
   164 OCTREE= $octree
   117 oconv= -f
   165 oconv= -f
   118 AMBF= $ambf
   166 AMBF= $ambf
   119 render= $rendopts
   167 render= $rendopts
   120 EndOfRif
   168 EndOfRif
   121 close(FH);
   169 close(FH);
   122 
   170 
       
   171 # Custom view: look away from the luminaire, not at it.  This is indicated
       
   172 # by a leading '+' in front of the view (-v argument, default: XYZ)
       
   173 if ($custom_vw =~ m/^\+/) {
       
   174 	# Get rad to spit out the -v* options for the default view requested
       
   175 	my $view = `rad -V -n -s $rif`;
       
   176 	$view =~ s/\n//;
       
   177 	$view =~ s/^VIEW= //;
       
   178 
       
   179 	my $x = 0;
       
   180 	my $y = 0;
       
   181 	my $z = 0;
       
   182 	if ($vw =~ m/X/) {
       
   183 		$x = $dims[0] - $TINY;
       
   184 	} elsif ($vw =~ m/x/) {
       
   185 		$x = $dims[1] + $TINY;
       
   186 	}
       
   187 	if ($vw =~ m/Y/) {
       
   188 		$y = $dims[2] - $TINY;
       
   189 	} elsif ($vw =~ m/y/) {
       
   190 		$y = $dims[3] + $TINY;
       
   191 	}
       
   192 	if ($vw =~ m/Z/) {
       
   193 		$z = $dims[4] - $TINY;
       
   194 	} elsif ($vw =~ m/z/) {
       
   195 		$z = $dims[5] + $TINY;
       
   196 	}
       
   197 	
       
   198 	# Keep rad-generated standard view, but modify -vp
       
   199 	$vw = "nice $view -vp $x $y $z";
       
   200 
       
   201 	open(FH, ">$rif") or
       
   202 			die("ltview: Can't write to temporary file $rif\n");
       
   203 	print FH <<EndOfRif2;
       
   204 scene= $scene
       
   205 EXPOSURE= 2
       
   206 ZONE= Interior -5 5  -5 5  -5 5
       
   207 UP= $up
       
   208 view= $vw
       
   209 OCTREE= $octree
       
   210 oconv= -f
       
   211 AMBF= $ambf
       
   212 render= $rendopts
       
   213 EndOfRif2
       
   214 	close(FH);
       
   215 }
       
   216 
   123 if ($usegl) {
   217 if ($usegl) {
   124 	system "glrad $opts $rif";
   218 	system "glrad $opts $rif";
   125 } else {
   219 } else {
   126 	system "rad -o $raddev $opts $rif";
   220 	system "rad -o $raddev $opts $rif";
   127 }
   221 }