bin/ltview.pl
author Axel Jacobs <axel@jaloxa.eu>
Sun, 15 Dec 2013 18:04:10 +0000
changeset 44 c8df2d579470
parent 38 a21b69f32c77
child 61 4f3a9f297a6a
permissions -rwxr-xr-x
ltview: working and tested on LINUX and Vista

#!/usr/bin/perl
#
# Make a nice view of a luminaire
# Argument is the Radiance description of a luminaire, incl. distribution
#
# This script is based on Radiance's objview.pl plus
# Rob Guglielmetti's ltview extension to his objview.rb
#
# Axel Jacobs, 25 Dec 2013

use strict;
use warnings;
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 $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).

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;
	} 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/^-\w/) {
		die("objview: Bad option: $_\n");
	} else {
		last;
	}
	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...
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");
	}
}

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";
} 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("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
oconv= -f
AMBF= $ambf
render= $rendopts
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";
}

#EOF