#!/usr/bin/perl -w

# This script takes RADIANCE .rad files containing the whole scene
# as created by DesignWorkshop or SiVIEW and creates a seperate file
# for each material.
#
# The -v switch turns on verbosity for debugging.
# The -h and --help switches print the usage. It also comes up when
# no argument is passed on the command line.
#
# The only argument required is the name of the input file.
#
# (c) Axel Jacobs
# Written 16th October 1999
# Revised 20 July 2006

use strict;

my $HASH_COUNT = 10;
my $hash = 1;

my $verbose = 0;

my $now;
my $total_blocks = 0;
my $total_files = 0;

my $file_in;
my $last_file;
my %files;

# Print out usage instructions if no arguments.
if ($#ARGV == "-1") {
	usage();
}

sub usage {
    print <<END_OF_USAGE;
Break up big RADIANCE scene file by material.
Usage: $0 --help
       $0 [-v] file.rad

  -v, --verbose  explain what is being done, useful for debugging
  -h, --help     display this help and exit
END_OF_USAGE
    exit;
}

# Check the arguments
for (my $i=0 ; $i<=$#ARGV ; $i++) {
    $_ = shift @ARGV;
    SWITCH: {
		if ( ( m/-v/ ) || ( m/--verbose/ ) ) {
			$verbose = 1;
			last SWITCH;
		}
		if ( ( m/-h/ ) || ( m/--help/ ) ) {
			usage();
			exit;
		}
		$file_in = $_;
    }
}

# See if the input file exists and if it is a text file
die ("File $file_in doesn't exist. $!")
		unless (-e $file_in);
die ("File $file_in is not a text file. $!")
		unless (-T $file_in);

open (FH_IN, "<$file_in") or
		die ("Cannot open input file $file_in: $!");

sub args_per_line
{
    # Return the number of arguments on the line
    
    my $whole_line = shift;
    # Remove leading whitespaces
    $whole_line =~ s/^s*//;
    # Replace any number of whitespace with exactly one space
    $whole_line =~ s/\s+/ /;
    my @args = split(" ", $whole_line);
    # This is the index of the last element in the array,
    # so we need to increment it by one (0 is the first index)
    my $num = ++$#args;
    return $num;
}

sub set_output_file
{
    # Return a file handler and print some stuff if verbosity is set.
    # The hash %files is a list of all files that were opened already.
    
    my $file_out = shift;
    my $file_name = "${file_out}.rad";

    if ( exists( $files{"$file_name"} ) ) {
		open (FH, ">>$file_name") or
				die ("Cannot append to output file: $file_name. $!");
		if ( "$file_name" eq "$last_file" ) {
			if ( $hash == $HASH_COUNT ) {
				print "#" if $verbose;
					# Autoflush the output buffer
				$| = 1;
				$hash = 1;
			} else {
				++$hash;
			}
		} else {
			print "\nAppending to file: $file_name\n" if $verbose;
			$hash = 1;
		}
    } else {
		open (FH, ">$file_name") or
				die ("Cannot open or create output file $file_name. $!");
		$now = gmtime;
		print FH <<END_OF_HEADER;
# This files contains all primitives with modifier $file_out
# as extracted from file $file_in.
#
# Created with extrad.pl by Axel Jacobs
#
# $now GMT

END_OF_HEADER
		print "\nCreating new file: $file_name\n" if $verbose;
		$files{"$file_name"} = "yes";
		++$total_files;
		$hash = 1;
    }
    $last_file = $file_name;
    return \*FH;
}

# $count runs from 1 to 4 after which it is reset to 0
# and a blank line is written to the file.
my $count = 0;

# $continue is set as long as as the number of line arguments
# is smaller than the number indicated by the first argument.
# This is in case the argument are spread over several lines.
my $continue = 0;

# $nof_args is the actual number of arguments on the line
my $nof_args = 0;

# $no_indicated is the first value in the line and indicates the expected
# number of string, integer, or floating point arguments.
my $no_indicated = 0;

# The number of arguments found and copied so far
my $no_so_far = 0;

my $FH_OUT;

while ( $_ = <FH_IN> ) {
    # Don't copy any blank or comment lines
    if ( (m/^\s*$/) || (m/^#/) ) {
		next;
	}

    if ( ! $count ) {
		# Handle the first line of each section

		m/^\s*(\S+)/;
		# Get the first argument
		$FH_OUT = set_output_file( $1 );
		$count = 1;
    } else {
		# Handle all subsequent lines of the section

		$nof_args = args_per_line( $_ );
		if ( ! $continue ) {
			m/^\s*(\S+)/;
			$no_indicated = $1;
			if ( $no_indicated > $nof_args ) {
				# Arguments are split across several lines
				$continue = 1;
				$no_so_far = --$nof_args;
			} else {
				# All arguments are on the same line
				$count++;
			}
		} else {
			$no_so_far += $nof_args;
			if ( $no_indicated == $no_so_far ) {
				$continue = 0;
				$count++;
			}
		}
    }
    print $FH_OUT "$_";
    if ( $count == 4 ) {
		print $FH_OUT "\n";
		$count = 0;
		++$total_blocks;
    }
}

# Clean up.
close ( FH_IN );

# Write out some statistics
print "\n$total_blocks blocks written to $total_files files.\n";

# EOF

