package SDL::Tutorial::3DWorld::Actor::MaterialSampler;

=pod

=head1 NAME

SDL::Tutorial::3DWorld::Actor::MaterialSampler - A demonstrator for MTL files

=head1 DESCRIPTION

A B<MaterialSampler> is a grid of shapes designed to show off the properties
of different materials.

=cut

use 5.008;
use strict;
use warnings;
use OpenGL::List                       ();
use SDL::Tutorial::3DWorld::OpenGL     ();
use SDL::Tutorial::3DWorld::Actor      ();
use SDL::Tutorial::3DWorld::MTL ();
use SDL::Tutorial::3DWorld::Bound      ();

our $VERSION = '0.33';
our @ISA     = 'SDL::Tutorial::3DWorld::Actor';

sub new {
	my $self = shift->SUPER::new(@_);

	# Were we passed a MTL filename
	unless ( -f $self->file ) {
		die "Did not provide a MTL file";
	}

	# Material samples might contain transparent materials that need blending
	# $self->{blending} = 1;

	# Scaling and rotation are not supported
	if ( $self->{scale} ) {
		die "MaterialSampler actors do not support scaling";
	}
	if ( $self->{orient} ) {
		die "MaterialSampler actors do not support rotation";
	}

	return $self;
}

sub file {
	$_[0]->{file};
}





######################################################################
# Engine Interface

sub init {
	my $self = shift;

	# Load the material file
	$self->{mtl} = SDL::Tutorial::3DWorld::MTL->new(
		file => $self->{file},
	) or die "Failed to load MTL file";

	# Initialise the material file
	$self->{mtl}->init;

	# Fully initialise all materials and set up positions
	# for their material spheres.
	my $i = 0;
	$self->{mtlpos} = { };
	foreach my $name ( $self->{mtl}->names ) {
		$self->{mtl}->material($name)->init;
		$self->{mtlpos}->{$name} = [
			$self->{position}->[0] + ($i++ * 2),
			$self->{position}->[1],
			$self->{position}->[2],
		];
	}

	# Define the boundary box if the object is static
	unless ( $self->{velocity} ) {
		my $L = 2 * (scalar $self->{mtl}->names - 1);
		$self->{bound} = SDL::Tutorial::3DWorld::Bound->box(
			-0.5,      -0.5, -0.5,
			 0.5 + $L,  0.5,  0.5,
		);
	}

	return 1;
}

sub display {
	my $self = shift;

	# Calculate the order we'll render the spheres.
	# This ensures that anything transparent is blended properly.
	my @names = $self->{mtl}->names;
	my @order = SDL::Tutorial::3DWorld->current->camera->distance_isort(
		map { $self->{mtlpos}->{$_} } @names
	);

	# Iterate over the materials
	foreach my $i ( @order ) {
		my $name = $names[$i];
		$self->{mtl}->material($name)->display;
		OpenGL::glPushMatrix();
		OpenGL::glTranslatef( @{$self->{mtlpos}->{$name}} );
		OpenGL::glutSolidSphere( 0.5, 50, 50 );
		OpenGL::glPopMatrix();
	}

	return 1;
}

1;

=pod

=head1 SUPPORT

Bugs should be reported via the CPAN bug tracker at

L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=SDL-Tutorial-3DWorld>

=head1 AUTHOR

Adam Kennedy E<lt>adamk@cpan.orgE<gt>

=head1 SEE ALSO

L<SDL>, L<OpenGL>

=head1 COPYRIGHT

Copyright 2010 Adam Kennedy.

This program is free software; you can redistribute
it and/or modify it under the same terms as Perl itself.

The full text of the license can be found in the
LICENSE file included with this module.

=cut