#!/usr/bin/perl use OpenGL ':all'; use Math::Trig; use Data::Dumper; use strict; my $Window = undef; my $Width = 500.0; my $Height = 500.0; my %config; my $pos = 0; sub Resize() { glViewport(0, 0, $Width, $Height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0,1.0,0.1,500.0); glMatrixMode(GL_MODELVIEW); } my ($x_rot, $y_rot, $zoom) = (0, 0, -80); sub render() { my ($section_name, $section, $vertices, $triangles, $positions, $strips, $item, $colors); glLoadIdentity(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glTranslatef( 0.0, -5.0, $zoom ); glRotatef( $x_rot, 1.0, 0.0, 0.0 ); glRotatef( $y_rot, 0.0, 1.0, 0.0 ); for $section_name (keys %config) { $section = $config{$section_name}; next unless $$section{SectionType} eq 'FRAGMENT'; $vertices = $$section{VERTICES}; $triangles = $$section{TRIANGLES}; $strips = $$section{STRIP}; $positions = $$section{POSITIONS}; $colors = $$section{COLOURS}; glPushMatrix(); glTranslatef($$section{POS}[0], $$section{POS}[1], $$section{POS}[2]); my $col=0; for $item ( @$strips ) { glBegin( GL_TRIANGLE_STRIP ); for( my $i = 0; $i <= $#$item; ++$i ) { $col += 0.1; glColor3f( sin($col), cos($col), 0.5 ); glVertex3f( $$positions[$$vertices[$$item[$i]][0]][0], $$positions[$$vertices[$$item[$i]][0]][1], $$positions[$$vertices[$$item[$i]][0]][2], ); } glEnd(); } $col = 0; for $item (@$triangles) { glPushMatrix(); glBegin(GL_TRIANGLES); $col += 0.1; glColor3f( cos($col), 0.5, 0 ); glVertex3f( $$positions[$$vertices[$$item[0]][0]][0], $$positions[$$vertices[$$item[0]][0]][1], $$positions[$$vertices[$$item[0]][0]][2] ); $col += 0.1; glColor3f( 0, cos($col), 0.5 ); glVertex3f( $$positions[$$vertices[$$item[1]][0]][0], $$positions[$$vertices[$$item[1]][0]][1], $$positions[$$vertices[$$item[1]][0]][2] ); $col += 0.1; glColor3f( 0.5, 0, cos($col) ); glVertex3f( $$positions[$$vertices[$$item[2]][0]][0], $$positions[$$vertices[$$item[2]][0]][1], $$positions[$$vertices[$$item[2]][0]][2] ); glEnd(); glPopMatrix(); } glPopMatrix(); } glutSwapBuffers(); } sub KeyPressed() { my ($key) = uc( chr( shift( ) ) ); if( $key eq 'A' ) { $y_rot += 10.0 } elsif ($key eq 'D') { $y_rot -= 10.0 } elsif( $key eq 'W' ) { $x_rot += 10.0 } elsif( $key eq 'S' ) { $x_rot -= 10.0 } elsif( $key eq 'Q' ) { $zoom -= 10.0 } elsif( $key eq 'Z' ) { $zoom += 10.0 } } %config = %{&parse_file($ARGV[0])}; glutInit(); glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH ); glutInitWindowSize( $Width, $Height ); glutInitWindowPosition( $Width/2, $Height/2 ); $Window = glutCreateWindow("Darwinia Shapefile Viewer"); glutDisplayFunc( \&render ); glutIdleFunc( \&render ); glutReshapeFunc( \&Resize ); glutKeyboardFunc(\&KeyPressed); # GL glClearColor( 0.0, 0.0, 0.0, 0.0 ); glClearDepth( 1000.0 ); glDepthFunc( GL_LESS ); glShadeModel( GL_SMOOTH ); glEnable( GL_DEPTH_TEST ); glDisable( GL_CULL_FACE ); Resize(); glutMainLoop(); sub read_line( ) { local $_; $_ = ''; my $file_h = shift; while( $_ eq '' ) { $_ = <$file_h> or return undef; chomp(); tr/,/ /; s/\s+/ /g; s/#.*$//g; s/(^\s)|(\s$)//g; s/(\s:)|(:\s)/:/g; } return uc($_); } sub parse_file( ) { my $file = shift(); my ( %config, $setting, $value, $subsetting, $subvalue, $sub2setting, $sub2value, $cur_section ); local $_; open( my $file_h, "<$file" ) || die $! ; for( ;; ) { ($setting, $value) = split( /:/, &read_line( $file_h ) ) or last; for( $setting ) { #These set current data context ( /^Fragment$/i || /^Marker$/i ) && do { $cur_section = $value; $config{$cur_section}{SectionType} = $setting; last; }; #These terminiate current data context ( /^EndMarker$/i ) && do { $cur_section = ''; last; }; #Space-separated single-line arrays ( /^Up$/i || /^Front$/i || /^Pos$/i ) && do { $config{$cur_section}{$setting} = [ split(/ /, $value) ]; last; }; # Strips gives count of #r strips # each strip gives count of vertices # vertices are space-separated and # may span multiple lines. ( /^Strips/i ) && do { for( 1 .. $value ) { ($subsetting, $subvalue) = split( /:/, &read_line( $file_h ) ); $sub2setting = ''; while( $sub2setting ne 'VERTS' ) { ($sub2setting, $sub2value) = split( /:/, &read_line( $file_h ) ); } $config{$cur_section}{$subsetting}[$subvalue] = []; while( $#{$config{$cur_section}{$subsetting}[$subvalue]} < $sub2value-1 ) { my $line = &read_line( $file_h ); $line =~ s/v//gi; push @{$config{$cur_section}{$subsetting}[$subvalue]}, split( / /, $line ); } } last; }; ( /^Colours$/i || /^Vertices$/i || /^Positions$/i ) && do { for( 1..$value ) { ($subsetting, $subvalue) = split( /:/, &read_line( $file_h ) ); $config{$cur_section}{$setting}[$subsetting] = [ split(/ /, $subvalue) ]; } last; }; ( /^Triangles$/i ) && do { $config{$cur_section}{$setting} = []; for( 1 .. $value ) { push @{$config{$cur_section}{$setting}}, [ split( / /, &read_line( $file_h ) ) ]; } last; }; # If nothing else matches it, then just throw it in the hash if( $cur_section eq '') { $config{$setting} = $value; } else { $config{$cur_section}{$setting} = $value; } } } close( $file_h ); #print Dumper( \%config ); #die(); return \%config; }