#!/usr/bin/env perl
use strict;
$^W=1;

use ToyGL ':all';
use ToyGL::GLUT ':all';
use Math::Quaternion;
use Math::Trig;
use Imager;

my $orientation = new Math::Quaternion;
my ($geomx,$geomy,$geomz) = (0,0,-5);
my $nearclip = 0.1;
my $mousescale = 0.01;
my $zoomscale=0.02;
my $midtranslates = 0; # 1 for middle button to translate, 0 for zoom.

my $wsize = 256; # Window size

my %buttonstate = (	GLUT_LEFT_BUTTON,0,
			GLUT_MIDDLE_BUTTON,0,
			GLUT_RIGHT_BUTTON,0);




my ($clickx,$clicky)=(0,0); # Coordinates of last mouse click
my ($screenx,$screeny) = ($wsize,$wsize);
my $sphererad = $screeny*0.5; # Radius of trackball sphere

glutInit;

glutInitWindowSize($screenx,$screeny);
glutInitWindowPosition($wsize,0);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);



my $window = glutCreateWindow("GLUT window");
init_gl();
glutDisplayFunc(\&displayfunc);
glutReshapeFunc( \&reshapefunc);
glutMouseFunc(\&mousefunc);
glutMotionFunc(\&motionfunc);

glutMainLoop;
	
exit 0;

sub init_gl {

	glColorMaterial(GL_FRONT,GL_AMBIENT_AND_DIFFUSE);
	glEnable(GL_COLOR_MATERIAL);

	glClearColor(0.0,0.0,0.0,0.0);

	glDisable(GL_LIGHTING);

	glDisable(GL_DEPTH_TEST);
	glBlendFunc(GL_SRC_ALPHA,GL_ONE);
	glEnable(GL_BLEND);

	glTexParameter(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	glTexParameter(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
        glTexEnv(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
	glEnable(GL_TEXTURE_2D);
	glFrontFace(GL_CCW);

        my $img = Imager->new;

        $img->open(
                file => 'star.png',
                type => 'png',
        ) or die("Could not open image file");

	glTexImage2D(image=>$img);


}

sub reshapefunc {
	my ($w,$h) = @_;

	($screenx,$screeny) = @_;
	$sphererad = $screeny*0.5;

	print "Reshaped to $w x $h\n";
	glViewport(0,0,$w,$h);
}

sub displayfunc{

        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

	# Set up perspective projection
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(60.0,$screenx/$screeny,$nearclip,1024.0 );
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	glTranslate($geomx,$geomy,$geomz);
	my @m = $orientation->matrix4x4;
	glMultMatrix(@m);

	my ($theta,$phi);
	my $dtheta = pi/16;
	my $dphi = 2*pi/12;
	for ($theta=$dtheta;$theta<pi;$theta+=$dtheta) {
		for ($phi=0;$phi<2*pi;$phi+=$dphi) {
			my $r = 5.0;
			my $x = sin($theta)*cos($phi);
			my $y = sin($theta)*sin($phi);
			my $z = cos($theta);
			glColor(
				0.5+0.5*abs($x),
				0.5+0.5*abs($y),
				0.5+0.5*abs($z));
			glPushMatrix;
				glTranslate($r*$x,$r*$y,$r*$z);
				draw_star();
			glPopMatrix;

		}
	}


	glFlush();
	glutSwapBuffers();
}

sub postredisplay {
	glutPostRedisplay();
}

sub mousefunc {
	my ($button,$state,$x,$y) = @_;

	($clickx,$clicky) = ($x,$y);
	$buttonstate{$button} = (GLUT_DOWN == $state) ? 1 : 0;
}

sub motionfunc {
	my ($x,$y) = @_;
	my ($left,$mid,$right) =
	 @buttonstate{GLUT_LEFT_BUTTON, GLUT_MIDDLE_BUTTON, GLUT_RIGHT_BUTTON};

	if ($left) { 
		mouserotatemotion($clickx,$clicky,$x,$y);
		($clickx,$clicky) = ($x,$y);
	} elsif ($mid) {
		if ($midtranslates) {
			mousetransmotion($clickx,$clicky,$x,$y);
		} else {
			mousezoommotion($y-$clicky);
		}
		($clickx,$clicky) = ($x,$y);
	} elsif ($right) {
	}

}

sub mouserotatemotion {
	my ($x0,$y0,$x1,$y1) = @_;

	my $s = $sphererad;
	my $my = $x1-$x0;
	my $mx = $y1-$y0;
	my $m=sqrt($mx*$mx+$my*$my);

	my $theta;

	if (($m>0) && ($m<$s)) {
		$theta = $m/$s;

		$mx /= $m;
		$my /= $m;

		my $rotquat = Math::Quaternion::rotation($theta,$mx,$my,0.0);
		$orientation = $rotquat * $orientation;
	}

	postredisplay;
}

sub mousetransmotion {
	my ($x0,$y0,$x1,$y1) = @_;

	$geomx += $mousescale * ($x1-$x0);
	$geomy += $mousescale * ($y0-$y1);

	postredisplay;
}

sub mousezoommotion {
	my $dz = shift;
	$geomz -= $zoomscale*$dz;
	postredisplay;
}


{
	my $lastidno = 0;
	sub makeid {
		return $lastidno++;
	}
}

sub draw_star {

        my @polydata = (
                [ 0, 1],
                [ 1, 1],
                [ 1, 0],
                [ 0, 0],
        );

	# Grab the modelview matrix into @m
	my @m= glGet(GL_MODELVIEW_MATRIX);
	# Set non-translational part to the identity matrix.
	$m[0] = $m[5] = $m[10] = 1.0;
	$m[1] = $m[2] = $m[4] = $m[6]
	= $m[8] = $m[9] = 0.0;
	# Load this as the new modelview matrix.
	glLoadMatrix(@m);
	# Draw a quad textured with the star.
	glBegin(GL_QUADS);
	for (0..3) {
		my @a = @{$polydata[$_]};
		glTexCoord(@a);
		glVertex(@a);
	}
	glEnd;
}
