#!/opt/perl/bin/perl use common::sense; use Cwd; use Math::VectorReal; use File::Spec::Functions; $Math::VectorReal::FORMAT = "x=\"%1.3f\" y=\"%1.3f\" z=\"%1.3f\""; sub slurp { open FO, $_[0] or die "Couldn't open $_[0]: $!"; return join '', } sub read_scene_cfg { my ($file) = @_; my $cfg = {}; eval { my $cont = slurp ($file); for (split /\n/, $cont) { if (m/dir\s*=\s*(\d+)\s*-\s*(\d+)/) { for ($1..$2) { push @{$cfg->{dir}}, $_ } } elsif (m/dir\s*=\s*(\d+)/) { push @{$cfg->{dir}}, $1; } elsif (m/replace\s+(\S+)\s+(\S+)/) { push @{$cfg->{replace}}, [$1, $2]; } elsif (m/(\S+)\s*=\s*(.*)/) { $cfg->{$1} = $2; } } }; if ($@) { warn "Couldn't read $file\n" } $cfg->{w} ||= 32; $cfg->{h} ||= 32; $cfg->{height} ||= 100; $cfg->{dir} ||= [5]; return $cfg; } sub add { my ($x, $y, $z, $up, $r, $move_vec) = @_; $move_vec ||= vector (0, 0, 0); my $v = vector ($x, $y, $z); $v = $v + (0.5 * $z * $up); $v = $v + (0.25 * $z * $r); $v = $v + $move_vec; "p $v" } sub new_cam { my ($cont, $dir_n, $cfg, $outfile) = @_; my ($x, $y) = ($cfg->{height} / 2, $cfg->{height} / 2); my ($w, $h) = ($cfg->{w}, $cfg->{h} || $cfg->{w}); my $to = vector (0, 0, 0); my $from = 1 ? vector (0, $cfg->{height}, 0) : vector (0, 0, $cfg->{height}); my $dir = ($from - $to)->norm; my $up; my $r; if ($dir_n == 0 || $dir_n == 1) { #$r = vector (-1, 0, 0)->norm; $up = vector (0, 1, 0)->norm; } elsif ($dir_n == 2) { $up = vector (-1, 1, 0)->norm; } elsif ($dir_n == 3) { $up = vector (-1, 0, 0)->norm; } elsif ($dir_n == 4) { $up = vector (-1, -1, 0)->norm; } elsif ($dir_n == 5) { $up = vector (0, -1, 0)->norm; } elsif ($dir_n == 6) { $up = vector (1, -1, 0)->norm; } elsif ($dir_n == 7) { $up = vector (1, 0, 0)->norm; } elsif ($dir_n == 8) { $up = vector (1, 1, 0)->norm; } $r = ($up x $dir)->norm; my $upv = $up; $up = $from + $up; my $m = vector (0, 0, 0); if ($cfg->{xoffs} || $cfg->{yoffs}) { $m = ($cfg->{xoffs} || 0) * $r + ($cfg->{yoffs} || 0) * $upv; } $cont =~ s/p\s*x="([^"]+)"\s*y="([^"]+)"\s*z="([^"]+)"/add ($1, $2, $3, $upv, $r, $m)/egs; my $light = ($r + vector (0, 0, 0.7) + -$upv)->norm; # x="0" y="1" z="0.5"/> my $backlight = (-$r + vector (0, 0, 0.7) + $upv)->norm; my $cam = < CAM ($cont, $cam) } sub render_dir { my ($cont, $dir, $cfg, $outfile) = @_; my $cam; ($cont, $cam) = new_cam ($cont, $dir, $cfg, $outfile); for (@{$cfg->{replace}}) { $cont =~ s/\Q$_->[0]\E/$_->[1]/egs; } $cont =~ s##$cam."<\/scene>"#es; $cont =~ s###gs; $cont =~ s###gs; $cont =~ s##$cam."<\/scene>"#es; $cont } my $xml = $ARGV[0] or die "render \n"; my $outfile = $xml; $outfile =~ s/\.xml$/\.tga/; my $xmlcont = slurp ($xml); my $cfg = read_scene_cfg ($xml . ".cfg"); my ($vol, $dir, $file) = File::Spec->splitpath($xml); $file =~ m/^(.*?)\.xml/; my $filebase = $1 || $file; for my $d (@{$cfg->{dir}}) { my $ofile = File::Spec->catpath ($vol, $dir, "${filebase}_dir_${d}.tga"); my $oxfile = File::Spec->catpath ($vol, $dir, "${filebase}_rend_${d}.xml"); my $nc = render_dir ($xmlcont, $d, $cfg, "${filebase}_dir_${d}.tga"); open OUT, ">$oxfile" or die "Couldn't write '$nc': $!"; print OUT $nc; close OUT; my $cwd = getcwd; if ($dir) { system ("cd $dir; yafray ${filebase}_rend_${d}.xml > yafray_out.log 2> yafray_out.log"); } else { system ("yafray ${filebase}_rend_${d}.xml > yafray_out.log 2> yafray_out.log"); } unlink $oxfile; if ($cfg->{archname}) { if (@{$cfg->{dir}} > 1) { system ("convert ${filebase}_dir_${d}.tga $cfg->{archname}$d.png"); print "saved arch png to: $cfg->{archname}$d.png\n"; } else { system ("convert ${filebase}_dir_${d}.tga $cfg->{archname}.png"); print "saved arch png to: $cfg->{archname}.png\n"; } } else { system ("convert ${filebase}_dir_${d}.tga ${filebase}_dir_${d}.png"); print "saved arch png to: ${filebase}_dir_${d}.png\n"; } print "rendered $ofile\n"; }