| 1 |
greg |
2.1 |
#!/usr/bin/perl
|
| 2 |
|
|
|
| 3 |
|
|
# Make a four-view picture of the photometry of a luminaire
|
| 4 |
|
|
#
|
| 5 |
|
|
# This is inspired by objpict.pl that renders four-view
|
| 6 |
|
|
# images of objects that are not light sources.
|
| 7 |
|
|
#
|
| 8 |
|
|
# Written by Axel Jacobs <[email protected]>
|
| 9 |
|
|
|
| 10 |
|
|
use strict;
|
| 11 |
|
|
use warnings;
|
| 12 |
|
|
|
| 13 |
|
|
use File::Temp qw/ tempdir /;
|
| 14 |
|
|
my $td = tempdir( CLEANUP => 1 );
|
| 15 |
|
|
|
| 16 |
greg |
2.2 |
my $res = 1024; # Default output image dimensions. Same as objpict.
|
| 17 |
greg |
2.1 |
my $tiny = 0.01;
|
| 18 |
greg |
2.2 |
my $maxsize = 0.001; # max luminaire size after scaling
|
| 19 |
greg |
2.1 |
my $is_ies = 0;
|
| 20 |
|
|
|
| 21 |
|
|
my $ies = "$td/dist.ies";
|
| 22 |
greg |
2.2 |
my $lumi = "$td/lumi.rad"; # Fitting given on cmd line, or generated by ies2rad
|
| 23 |
|
|
my $lumi2 = "$td/lumi2.rad"; # Fitting scaled to size
|
| 24 |
greg |
2.1 |
my $mat = "$td/lt.mat";
|
| 25 |
|
|
my $room1 = "$td/room1.rad";
|
| 26 |
|
|
my $room2 = "$td/room2.rad";
|
| 27 |
|
|
my $room3 = "$td/room3.rad";
|
| 28 |
|
|
my $room4 = "$td/room4.rad";
|
| 29 |
|
|
my $oct1 = "$td/lt1.oct";
|
| 30 |
|
|
my $oct2 = "$td/lt2.oct";
|
| 31 |
|
|
my $oct3 = "$td/lt3.oct";
|
| 32 |
|
|
my $oct4 = "$td/lt4.oct";
|
| 33 |
|
|
|
| 34 |
|
|
# Parse command line arguments
|
| 35 |
|
|
while (@ARGV) {
|
| 36 |
greg |
2.2 |
$_ = $ARGV[0];
|
| 37 |
|
|
if (m/-i/) { # File is an IES file, not a Radiance luminaire
|
| 38 |
|
|
$is_ies = 1;
|
| 39 |
|
|
} elsif (m/-d/) { # Resolution of the output HDR image
|
| 40 |
|
|
$res = $ARGV[1];
|
| 41 |
|
|
shift @ARGV;
|
| 42 |
|
|
} elsif (m/^-\w/) { # Oops! Illegal option
|
| 43 |
greg |
2.1 |
die("ltpict: bad option '$_'\n");
|
| 44 |
|
|
} else {
|
| 45 |
greg |
2.2 |
last; # No more options. What's left is the actual file name.
|
| 46 |
|
|
}
|
| 47 |
greg |
2.1 |
shift @ARGV;
|
| 48 |
|
|
}
|
| 49 |
|
|
|
| 50 |
greg |
2.2 |
# We need exactly one Radiance luminaires or IES file
|
| 51 |
|
|
if ( !$#ARGV == 0 ) {
|
| 52 |
|
|
die("ltpict: Need one Radiance luminaire or IES file.\n");
|
| 53 |
|
|
} elsif ( $is_ies == 0 ) {
|
| 54 |
|
|
|
| 55 |
|
|
# Input file is a Radiance luminaire
|
| 56 |
|
|
$lumi = $ARGV[0];
|
| 57 |
greg |
2.1 |
} else {
|
| 58 |
greg |
2.2 |
|
| 59 |
|
|
# Input file is IES photometry
|
| 60 |
|
|
system qq[ ies2rad -p $td -o lumi "$ARGV[0]" ];
|
| 61 |
greg |
2.1 |
}
|
| 62 |
|
|
|
| 63 |
|
|
my $res2 = $res / 2; # Each rendering is half the size of final composite
|
| 64 |
|
|
|
| 65 |
|
|
# Scale luminaire and center at origin
|
| 66 |
greg |
2.2 |
my $dimstr = `getbbox -h "$lumi"`;
|
| 67 |
greg |
2.1 |
chomp $dimstr;
|
| 68 |
greg |
2.2 |
|
| 69 |
greg |
2.1 |
# Values returned by getbbox are indented and delimited with multiple spaces.
|
| 70 |
greg |
2.2 |
$dimstr =~ s/^\s+//; # remove leading spaces
|
| 71 |
|
|
my @dims = split( /\s+/, $dimstr ); # convert to array
|
| 72 |
greg |
2.1 |
|
| 73 |
|
|
# Find largest axes-aligned dimension
|
| 74 |
greg |
2.2 |
my @diffs = ( $dims[1] - $dims[0], $dims[3] - $dims[2], $dims[5] - $dims[4] );
|
| 75 |
greg |
2.1 |
@diffs = reverse sort { $a <=> $b } @diffs;
|
| 76 |
|
|
my $size = $diffs[0];
|
| 77 |
|
|
|
| 78 |
|
|
# Move luminaire so centre is at origin, and scale
|
| 79 |
greg |
2.2 |
my $xtrans = -1.0 * ( $dims[0] + $dims[1] ) / 2;
|
| 80 |
|
|
my $ytrans = -1.0 * ( $dims[2] + $dims[3] ) / 2;
|
| 81 |
|
|
my $ztrans = -1.0 * ( $dims[4] + $dims[5] ) / 2;
|
| 82 |
|
|
my $scale = $maxsize / $size;
|
| 83 |
|
|
system qq[ xform -t $xtrans $ytrans $ztrans "$lumi" > $lumi2 ];
|
| 84 |
greg |
2.1 |
|
| 85 |
|
|
# Material for the room
|
| 86 |
greg |
2.2 |
open( FH, ">$mat" )
|
| 87 |
|
|
or die("ltpict: Cannot write to temporary file $mat");
|
| 88 |
greg |
2.1 |
print FH "void plastic wall_mat 0 0 5 .5 .5 .5 0 0";
|
| 89 |
|
|
close FH;
|
| 90 |
|
|
|
| 91 |
|
|
# Different 'room' geometry for different views
|
| 92 |
greg |
2.2 |
my $o = 0.1; # Offset
|
| 93 |
greg |
2.1 |
|
| 94 |
|
|
# C0-C180
|
| 95 |
greg |
2.2 |
open( FH, ">$room1" )
|
| 96 |
|
|
or die("ltpict: Cannot write to temporary file $room1");
|
| 97 |
|
|
print FH
|
| 98 |
|
|
"wall_mat polygon box.4620 0 0 12 -$o -5 5 -$o 5 5 -$o 5 -5 -$o -5 -5";
|
| 99 |
greg |
2.1 |
close(FH);
|
| 100 |
|
|
|
| 101 |
|
|
# C90-C270
|
| 102 |
greg |
2.2 |
open( FH, ">$room2" )
|
| 103 |
|
|
or die("ltpict: Cannot write to temporary file $room2");
|
| 104 |
|
|
print FH
|
| 105 |
|
|
"wall_mat polygon box.1540 0 0 12 5 $o -5 5 $o 5 -5 $o 5 -5 $o -5";
|
| 106 |
greg |
2.1 |
close(FH);
|
| 107 |
|
|
|
| 108 |
|
|
# Lower hemisphere
|
| 109 |
greg |
2.2 |
open( FH, ">$room3" )
|
| 110 |
|
|
or die("ltpict: Cannot write to temporary file $room3");
|
| 111 |
greg |
2.1 |
print FH "wall_mat bubble lower 0 0 4 0 0 $dims[4] 5";
|
| 112 |
|
|
close(FH);
|
| 113 |
|
|
|
| 114 |
|
|
# Upper hemisphere
|
| 115 |
greg |
2.2 |
open( FH, ">$room4" )
|
| 116 |
|
|
or die("ltpict: Cannot write to temporary file $room4");
|
| 117 |
greg |
2.1 |
print FH "wall_mat bubble upper 0 0 4 0 0 $dims[5] 5";
|
| 118 |
|
|
close(FH);
|
| 119 |
|
|
|
| 120 |
|
|
# Call bbox again, for the translated and scaled luminaire.
|
| 121 |
|
|
$dimstr = `getbbox -h $lumi2`;
|
| 122 |
|
|
chomp $dimstr;
|
| 123 |
greg |
2.2 |
|
| 124 |
greg |
2.1 |
# Values returned by getbbox are indented and delimited with multiple spaces.
|
| 125 |
greg |
2.2 |
$dimstr =~ s/^\s+//; # remove leading spaces
|
| 126 |
|
|
@dims = split( /\s+/, $dimstr ); # convert to array
|
| 127 |
greg |
2.1 |
|
| 128 |
|
|
# Define the four views
|
| 129 |
greg |
2.2 |
my $vw1 = "-vtl -vp 4.5 0 0 -vd -1 0 0 -vh 10 -vv 10";
|
| 130 |
|
|
my $vw2 = "-vtl -vp 0 -4.5 0 -vd 0 1 0 -vh 10 -vv 10";
|
| 131 |
greg |
2.1 |
my $zcent3 = $dims[4] - $tiny;
|
| 132 |
greg |
2.2 |
my $vw3 = "-vta -vp 0 0 $zcent3 -vd 0 0 -1 -vu 0 1 0 -vh 180 -vv 180";
|
| 133 |
greg |
2.1 |
my $zcent4 = $dims[5] + $tiny;
|
| 134 |
greg |
2.2 |
my $vw4 = "-vta -vp 0 0 $zcent4 -vd 0 0 1 -vu 0 1 0 -vh 180 -vv 180";
|
| 135 |
greg |
2.1 |
|
| 136 |
greg |
2.2 |
# Compile octrees
|
| 137 |
greg |
2.1 |
system "oconv $mat $room1 $lumi2 > $oct1";
|
| 138 |
|
|
system "oconv $mat $room2 $lumi2 > $oct2";
|
| 139 |
|
|
system "oconv $mat $room3 $lumi2 > $oct3";
|
| 140 |
|
|
system "oconv $mat $room4 $lumi2 > $oct4";
|
| 141 |
|
|
|
| 142 |
|
|
# Render four different views of the objects
|
| 143 |
|
|
my $rpict_cmd = "rpict -ab 0 -ds 0 -dv -av 0 0 0 -x $res2 -y $res2";
|
| 144 |
|
|
system "$rpict_cmd $vw1 $oct1 > $td/right.hdr";
|
| 145 |
|
|
system "$rpict_cmd $vw2 $oct2 > $td/front.hdr";
|
| 146 |
|
|
system "$rpict_cmd $vw3 $oct3 > $td/down.hdr";
|
| 147 |
|
|
system "$rpict_cmd $vw4 $oct4 > $td/up.hdr";
|
| 148 |
|
|
|
| 149 |
|
|
# Compose the four views into one image
|
| 150 |
greg |
2.2 |
my $vtl = "$td/vtl.hdr"; # The two parallel views
|
| 151 |
|
|
my $vta = "$td/vta.hdr"; # The two fisheye views
|
| 152 |
greg |
2.1 |
|
| 153 |
|
|
# Auto-expose right/front and down/up pairs separately
|
| 154 |
|
|
my $pcond_cmd = "pcond -l";
|
| 155 |
|
|
system "pcompos -a 2 $td/right.hdr $td/front.hdr > $td/rf.hdr";
|
| 156 |
|
|
system "$pcond_cmd $td/rf.hdr > $vtl";
|
| 157 |
|
|
system "pcompos -a 2 $td/down.hdr $td/up.hdr > $td/du.hdr";
|
| 158 |
|
|
system "$pcond_cmd $td/du.hdr > $vta";
|
| 159 |
|
|
|
| 160 |
|
|
# Combine top two images with bottom row. Output HDR.
|
| 161 |
|
|
exec "pcompos -a 1 $vtl $vta";
|
| 162 |
|
|
|
| 163 |
|
|
#EOF
|