#!/usr/bin/perl

use strict;
use warnings;
use SDL::App;
use SDL::OpenGL;

my ($done, $frame);
my ($conf, $sdl_app);

START: main();


sub main
{
    init();
    main_loop();
    cleanup();
}

sub init
{
    $| = 1;
    init_conf();
    init_window();
}

sub init_conf
{
    $conf = {
        title  => 'Camel 3D',
        width  => 400,
        height => 400,
        fovy   => 90,
    };
}

sub init_window
{
    my ($title, $w, $h) = @$conf{qw( title width height )};

    $sdl_app = SDL::App->new(-title  => $title,
                             -width  => $w,
                             -height => $h,
                             -gl     => 1,
                            );
    SDL::ShowCursor(0);
}

sub main_loop
{
    while (not $done) {
        $frame++;
        do_frame();
    }
}

sub do_frame
{
    prep_frame();
    draw_frame();
    end_frame();
}

sub prep_frame
{
    glClear(GL_COLOR_BUFFER_BIT |
            GL_DEPTH_BUFFER_BIT );

    glEnable(GL_DEPTH_TEST);
}

sub draw_frame
{
    set_projection_3d();
    set_view_3d();
    draw_view();

    print '.';
    sleep 1;
    $done = 1 if $frame == 5;
}

sub set_projection_3d
{
    my ($fovy, $w, $h) = @$conf{qw( fovy width height )};
    my $aspect = $w / $h;

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity;
    gluPerspective($fovy, $aspect, 1, 1000);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity;
}

sub set_view_3d
{
    # Move the viewpoint so we can see the origin
    glTranslate(0, -2, -10);
}

sub draw_view
{
    draw_axes();

    glColor(1, 1, 1);
    glPushMatrix;
    glTranslate( 0, 0, -4);
    glScale( 2, 2, 2);
    draw_cube();
    glPopMatrix;

    glColor(1, 1, 0);
    glPushMatrix;
    glTranslate( 4, 0, 0);
    glRotate( 40, 0, 0, 1);
    glScale(.2, 1, 2);
    draw_cube();
    glPopMatrix;
}

sub draw_axes
{
    # Lines from origin along positive axes, for orientation
    # X axis = red, Y axis = green, Z axis = blue
    glBegin(GL_LINES);
    glColor(1, 0, 0);
    glVertex(0, 0, 0);
    glVertex(1, 0, 0);

    glColor(0, 1, 0);
    glVertex(0, 0, 0);
    glVertex(0, 1, 0);

    glColor(0, 0, 1);
    glVertex(0, 0, 0);
    glVertex(0, 0, 1);
    glEnd;
}

sub draw_cube
{
    # A simple cube
    my @indices = qw( 4 5 6 7   1 2 6 5   0 1 5 4
                      0 3 2 1   0 4 7 3   2 3 7 6 );
    my @vertices = ([-1, -1, -1], [ 1, -1, -1],
                    [ 1,  1, -1], [-1,  1, -1],
                    [-1, -1,  1], [ 1, -1,  1],
                    [ 1,  1,  1], [-1,  1,  1]);

    glBegin(GL_QUADS);
    foreach my $face (0 .. 5) {
        foreach my $vertex (0 .. 3) {
            my $index  = $indices[4 * $face + $vertex];
            my $coords = $vertices[$index];
            glVertex(@$coords);
        }
    }
    glEnd;
}

sub end_frame
{
    $sdl_app->sync;
}

sub cleanup
{
    print "\nDone.\n"
}
