/usr/local/CPAN/Wx-GLCanvas/Wx/DemoModules/wxGLCanvas.pm
#############################################################################
## Name: lib/Wx/DemoModules/wxGLCanvas.pm
## Purpose: wxPerl demo helper for Wx::GLCanvas
## Author: Mattia Barbon
## Modified by:
## Created: 26/07/2003
## RCS-ID: $Id: wxGLCanvas.pm 2489 2008-10-27 19:50:51Z mbarbon $
## Copyright: (c) 2000, 2006, 2008 Mattia Barbon
## Licence: This program is free software; you can redistribute it and/or
## modify it under the same terms as Perl itself
#############################################################################
package Wx::DemoModules::wxGLCanvas;
use strict;
use Wx::Event qw(EVT_PAINT EVT_SIZE EVT_ERASE_BACKGROUND EVT_IDLE EVT_TIMER);
# must load OpenGL *before* Wx::GLCanvas
use OpenGL qw(:glconstants :glfunctions);
use base qw(Wx::GLCanvas Class::Accessor::Fast);
use Wx::GLCanvas qw(:all);
__PACKAGE__->mk_accessors( qw(timer x_rot y_rot dirty init) );
sub new {
my( $class, $parent ) = @_;
my $self = $class->SUPER::new( $parent );
# my $self = $class->SUPER::new( $parent, -1, [-1, -1], [-1, -1], 0,
# "GLCanvas",
# [WX_GL_RGBA, WX_GL_DOUBLEBUFFER, 0] );
my $timer = $self->timer( Wx::Timer->new( $self ) );
$timer->Start( 50 );
$self->x_rot( 0 );
$self->y_rot( 0 );
EVT_PAINT( $self,
sub {
my $dc = Wx::PaintDC->new( $self );
$self->Render( $dc );
} );
EVT_SIZE( $self, sub { $self->dirty( 1 ) } );
EVT_IDLE( $self, sub {
return unless $self->dirty;
$self->Resize( $self->GetSizeWH );
$self->Refresh;
} );
EVT_TIMER( $self, -1, sub {
my( $self, $e ) = @_;
$self->x_rot( $self->x_rot - 1 );
$self->y_rot( $self->y_rot + 2 );
$self->dirty( 1 );
Wx::WakeUpIdle;
} );
return $self;
}
sub GetContext {
my( $self ) = @_;
if( Wx::wxVERSION >= 2.009 ) {
return $self->{context} ||= Wx::GLContext->new( $self );
} else {
return $self->SUPER::GetContext;
}
}
sub SetCurrent {
my( $self, $context ) = @_;
if( Wx::wxVERSION >= 2.009 ) {
return $self->SUPER::SetCurrent( $context );
} else {
return $self->SUPER::SetCurrent;
}
}
sub Resize {
my( $self, $x, $y ) = @_;
return unless $self->GetContext;
$self->dirty( 0 );
$self->SetCurrent( $self->GetContext );
glViewport( 0, 0, $x, $y );
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
my_gluPerspective( 45, $x/$y, .5, 100 );
glMatrixMode(GL_MODELVIEW);
}
use Math::Trig;
sub my_gluPerspective {
my( $fov, $ratio, $near, $far ) = @_;
my $top = tan(deg2rad($fov)*0.5) * $near;
my $bottom = -$top;
my $left = $ratio * $bottom;
my $right = $ratio * $top;
glFrustum( $left, $right, $bottom, $top, $near, $far );
}
sub DESTROY {
my( $self ) = @_;
$self->timer->Stop;
$self->timer( undef );
}
sub tags { [ 'windows/glcanvas' => 'wxGLCanvas' ] }
package Wx::DemoModules::wxGLCanvas::Cube;
use strict;
# must load OpenGL *before* Wx::GLCanvas
use OpenGL qw(:glconstants :glfunctions);
use base qw(Wx::DemoModules::wxGLCanvas);
sub cube {
my( @v ) = ( [ 1, 1, 1 ], [ -1, 1, 1 ],
[ -1, -1, 1 ], [ 1, -1, 1 ],
[ 1, 1, -1 ], [ -1, 1, -1 ],
[ -1, -1, -1 ], [ 1, -1, -1 ] );
my( @c ) = ( [ 1, 1, 0 ], [ 1, 0, 1 ],
[ 0, 1, 1 ], [ 1, 1, 1 ],
[ 0, 0, 1 ], [ 0, 1, 0 ],
[ 1, 0, 1 ], [ 1, 1, 0 ] );
my( @s ) = ( [ 0, 1, 2, 3 ], [ 4, 5, 6, 7 ],
[ 0, 1, 5, 4 ], [ 2, 3, 7, 6 ],
[ 1, 2, 6, 5 ], [ 0, 3, 7, 4 ] );
for my $i ( 0 .. 5 ) {
my $s = $s[$i];
glBegin(GL_QUADS);
foreach my $j ( @$s ) {
glColor3f( @{$c[$j]} );
glVertex3f( @{$v[$j]} );
}
glEnd();
}
}
sub InitGL {
my $self = shift;
return if $self->init;
return unless $self->GetContext;
$self->init( 1 );
glDisable( GL_LIGHTING );
glDepthFunc( GL_LESS );
glEnable( GL_DEPTH_TEST );
}
sub Render {
my( $self, $dc ) = @_;
return unless $self->GetContext;
$self->SetCurrent( $self->GetContext );
$self->InitGL;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glTranslatef( 0, 0, -5 );
glRotatef( $self->x_rot, 1, 0, 0 );
glRotatef( $self->y_rot, 0, 0, 1 );
cube();
glPopMatrix();
glFlush();
$self->SwapBuffers();
}
sub add_to_tags { qw(windows/glcanvas) }
sub title { 'Cube' }
sub file { __FILE__ }
package Wx::DemoModules::wxGLCanvas::Light;
use strict;
# must load OpenGL *before* Wx::GLCanvas
use OpenGL qw(:glconstants :glfunctions);
use base qw(Wx::DemoModules::wxGLCanvas);
sub plane_mat {
glMaterialfv_p( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, 0.2, 0.1, 0.8, 0.5 );
glMaterialfv_p( GL_FRONT, GL_SPECULAR, 1, 1, 1, 1 );
glMaterialfv_p( GL_FRONT, GL_SHININESS, 4 );
}
sub plane {
my( $x, $y, $step ) = ( -2, -2, .5 );
for my $i ( 0 .. 7 ) {
$x += $step;
$y = -2;
for my $j ( 0 .. 7 ) {
$y += $step;
glBegin(GL_QUADS);
glNormal3f( 0, 1, 0 );
glVertex3f( $x, -1, $y );
glVertex3f( $x, -1, $y + $step );
glVertex3f( $x + $step, -1, $y + $step );
glVertex3f( $x + $step, -1, $y );
glEnd();
}
}
}
sub icosaedron_mat {
glMaterialfv_p( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, 0.1, 0.4, 0.7, 1 );
glMaterialfv_p( GL_FRONT, GL_SPECULAR, 1, 0, 0, 1 );
glMaterialfv_p( GL_FRONT, GL_SHININESS, 5 );
glMaterialfv_p( GL_FRONT, GL_EMISSION, 0.1, 0.2, 0.7, 0 );
}
sub icosahedron{
# from the 'light' demo in OpenGL-0.54
# from OpenGL Programming Guide page 56
my $x = 0.525731112119133606;
my $z = 0.850650808352039932;
my $v=[
[-$x, 0, $z],
[ $x, 0, $z],
[-$x, 0, -$z],
[ $x, 0, -$z],
[ 0, $z, $x],
[ 0, $z, -$x],
[ 0, -$z, $x],
[ 0, -$z, -$x],
[ $z, $x, 0],
[-$z, $x, 0],
[ $z, -$x, 0],
[-$z, -$x, 0],
];
my $t=[
[0,4,1], [0, 9, 4],
[9, 5, 4], [4, 5, 8],
[4, 8, 1], [8, 10, 1],
[8, 3, 10], [5, 3, 8],
[5, 2, 3], [2, 7, 3],
[7, 10, 3], [7, 6, 10],
[7, 11, 6], [11, 0, 6],
[0, 1, 6], [6, 1, 10],
[9, 0, 11], [9, 11, 2],
[9, 2, 5], [7, 2, 11],
];
for(my $i=0;$i<20;$i++) {
glBegin(GL_POLYGON);
for(my $j=0;$j<3;$j++) {
glNormal3f( $v->[$t->[$i][$j]][0],
$v->[$t->[$i][$j]][1],
$v->[$t->[$i][$j]][2]);
glVertex3f( $v->[$t->[$i][$j]][0],
$v->[$t->[$i][$j]][1],
$v->[$t->[$i][$j]][2]);
}
glEnd();
}
}
sub InitGL {
my $self = shift;
return if $self->init;
return unless $self->GetContext;
$self->init( 1 );
glLightfv_p( GL_LIGHT0, GL_AMBIENT, .5,.5,.5,1 );
glLightfv_p( GL_LIGHT0, GL_DIFFUSE, .2,.2,.2,1 );
glLightfv_p( GL_LIGHT0, GL_SPECULAR, 1,.5,.5,1 );
glLightfv_p( GL_LIGHT0, GL_POSITION, -3, 3, -4, 1);
glLightfv_p( GL_LIGHT1, GL_SPECULAR, 0, 1, 1, 1 );
glLightfv_p( GL_LIGHT1, GL_POSITION, 0, 0, -6, 1 );
glLightfv_p( GL_LIGHT2, GL_SPECULAR, 1, 1, 1, 1 );
glLightfv_p( GL_LIGHT2, GL_POSITION, 2, -0.5, -4, 1 );
glEnable( GL_LIGHTING );
glEnable( GL_LIGHT0 );
glEnable( GL_LIGHT1 );
glEnable( GL_LIGHT2 );
glDepthFunc( GL_LESS );
glEnable( GL_DEPTH_TEST );
}
sub Render {
my( $self, $dc ) = @_;
return unless $self->GetContext;
$self->SetCurrent( $self->GetContext );
$self->InitGL;
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glPushMatrix();
glTranslatef( 0, 0, -5 );
plane_mat();
plane();
glRotatef( $self->x_rot, 1, 0, 0 );
glRotatef( $self->y_rot, 0, 0, 1 );
icosaedron_mat();
icosahedron();
glPopMatrix();
glFlush();
$self->SwapBuffers();
}
sub add_to_tags { qw(windows/glcanvas) }
sub title { 'Light' }
sub file { __FILE__ }
1;