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 } |