#!/usr/bin/perl -w # NAME: showthreejs.pl # AIM: Read and display contents and information on a three.js file # 09/01/2015 geoff mclane http://geoffair.net/mperl use strict; use warnings; use File::Basename; # split path ($name,$dir,$ext) = fileparse($file [, qr/\.[^.]*/] ) use Cwd; use JSON; use Data::Dumper; my $os = $^O; my $perl_dir = '/home/geoff/bin'; my $PATH_SEP = '/'; my $temp_dir = '/tmp'; if ($os =~ /win/i) { $perl_dir = 'C:\GTools\perl'; $temp_dir = $perl_dir; $PATH_SEP = "\\"; } unshift(@INC, $perl_dir); require 'lib_utils.pl' or die "Unable to load 'lib_utils.pl' Check paths in \@INC...\n"; # log file stuff our ($LF); my $pgmname = $0; if ($pgmname =~ /(\\|\/)/) { my @tmpsp = split(/(\\|\/)/,$pgmname); $pgmname = $tmpsp[-1]; } my $outfile = $temp_dir.$PATH_SEP."temp.$pgmname.txt"; open_log($outfile); # user variables my $VERS = "0.0.5 2015-01-09"; my $load_log = 0; my $in_file = ''; my $verbosity = 0; my $out_file = ''; my $write_adjusted = 0; my $show_ints = 0; my @in_files = (); # ### DEBUG ### my $debug_on = 0; ###my $def_file = 'F:\FGx\fgx-aircraft\data\Carreidas\carreidas.js'; my $def_file1 = 'F:\FGx\fgx-aircraft\data\777\777-200.js'; my $def_file2 = 'F:\Projects\aircraft\777\777-200-2.js'; my $def_file3 = 'C:\OSGeo4W\apache\htdocs\map-test2\ac\777-200.js'; my $def_file4 = 'C:\OSGeo4W\apache\htdocs\map-test2\ac'; ### program variables my @warnings = (); my $cwd = cwd(); sub VERB1() { return $verbosity >= 1; } sub VERB2() { return $verbosity >= 2; } sub VERB5() { return $verbosity >= 5; } sub VERB9() { return $verbosity >= 9; } sub show_warnings($) { my ($val) = @_; if (@warnings) { prt( "\nGot ".scalar @warnings." WARNINGS...\n" ); foreach my $itm (@warnings) { prt("$itm\n"); } prt("\n"); } else { prt( "\nNo warnings issued.\n\n" ) if (VERB9()); } } sub pgm_exit($$) { my ($val,$msg) = @_; if (length($msg)) { $msg .= "\n" if (!($msg =~ /\n$/)); prt($msg); } show_warnings($val); close_log($outfile,$load_log); exit($val); } sub prtw($) { my ($tx) = shift; $tx =~ s/\n$//; prt("$tx\n"); push(@warnings,$tx); } sub isBitSet($$) { my ($val, $pos) = @_; return ($val & ( 1 << $pos )) ? 1 : 0; } sub get_decimal6($) { my $n = shift; my $num = sprintf("%.6f",($n+0.0000005)); return $num; } sub key_in_array($$$) { my ($key,$ra,$ri) = @_; my $max = scalar @{$ra}; my ($i,$txt); for ($i = 0; $i < $max; $i++) { $txt = ${$ra}[$i]; if ($key eq $txt) { ${$ri} = $i; return 1; } } return 0; } sub js_head_txt($$$) { my ($max,$max2,$name) = @_; my $txt = < $b); return 0; } sub mycmp_ascend { return 1 if ($a > $b); return -1 if ($a < $b); return 0; } sub process_in_file($) { my ($inf) = @_; if (! open INF, "<$inf") { pgm_exit(1,"ERROR: Unable to open file [$inf]\n"); } my @lines = ; close INF; my ($name,$dir,$ext) = fileparse($inf, qr/\.[^.]*/); my $lncnt = scalar @lines; prt("\nProcessing $lncnt lines, from [$inf]...\n") if (VERB5()); my $line = join("",@lines); my $json = JSON->new->allow_nonref; my $rh = $json->decode( $line ); my ($fa,$va,$tfc,$tvc,$vc,$vc2); my ($i,$bit,$fc,$ioff,$x,$y,$z,$sx,$sy,$sz,$ox,$oy,$oz,$oq); my ($minx,$miny,$minz,$maxx,$maxy,$maxz); my ($ix,$iy,$iz,$key,$ind,$ib,$msg,$i3); my ($isQuad,$hasMaterial,$hasFaceUv,$hasFaceVertexUv,$hasFaceNormal,$hasFaceVertexNormal,$hasFaceColor,$hasFaceVertexColor); my %dxyz = (); my @verts = (); my @faces = (); my %mapped = (); my %indexes = (); my $mvc = 0; my $dodump = 0; my $gotarrays = 0; my $remapcnt = 0; my $facechg = 0; if (defined ${$rh}{faces} && defined ${$rh}{vertices}) { $fa = ${$rh}{faces}; $va = ${$rh}{vertices}; $gotarrays = 1; } elsif (defined ${$rh}{geometries}) { # 'geometries' => [ { # 'data' => { # 'normals' => [ ...,'0.322486194574073','0.446980223599403','0.999241691922136'], # 'vertices' => ['1.89533','-0.684473','-11.1331'], # 'faces' => [48,0,1,2,0,1,2,3,48, my $dra = ${$rh}{geometries}; my $drh = ${$dra}[0]; if (defined ${$drh}{data}) { my $drh2 = ${$drh}{data}; if (defined ${$drh2}{faces} && defined ${$drh2}{vertices}) { $fa = ${$drh2}{faces}; $va = ${$drh2}{vertices}; $gotarrays = 1; } } } if (!$gotarrays) { if (defined ${$rh}{data}) { my $drh2 = ${$rh}{data}; if (defined ${$drh2}{faces} && defined ${$drh2}{vertices}) { $fa = ${$drh2}{faces}; $va = ${$drh2}{vertices}; $gotarrays = 1; } } } if ($gotarrays) { $tfc = scalar @{$fa}; $tvc = scalar @{$va}; $vc = $tvc / 3; $ioff = 0; $x = ${$va}[$ioff + 0]; $y = ${$va}[$ioff + 1]; $z = ${$va}[$ioff + 2]; $minx = $x; $maxx = $x; $miny = $y; $maxy = $y; $minz = $z; $maxz = $z; for ($i = 0; $i < $vc; $i++) { $ioff = $i * 3; $x = ${$va}[$ioff + 0]; $y = ${$va}[$ioff + 1]; $z = ${$va}[$ioff + 2]; $minx = $x if ($x < $minx); $maxx = $x if ($x > $maxx); $miny = $y if ($y < $miny); $maxy = $y if ($y > $maxy); $minz = $z if ($z < $minz); $maxz = $z if ($z > $maxz); $key = "$x|$y|$z"; if (defined $dxyz{$key}) { ###if (key_in_array($key,\@verts,\$ind)) { $ind = $dxyz{$key} - 1; $mapped{$i} = $ind; } else { $dxyz{$key} = $i + 1; push(@verts,$key); } } $vc2 = scalar @verts; $mvc = scalar keys %dxyz; $fc = 0; for ($i = 0; $i < $tfc; $i++) { $bit = ${$fa}[$i]; $isQuad = isBitSet( $bit, 0 ); $hasMaterial = isBitSet( $bit, 1 ); $hasFaceUv = isBitSet( $bit, 2 ); $hasFaceVertexUv = isBitSet( $bit, 3 ); $hasFaceNormal = isBitSet( $bit, 4 ); $hasFaceVertexNormal = isBitSet( $bit, 5 ); $hasFaceColor = isBitSet( $bit, 6 ); $hasFaceVertexColor = isBitSet( $bit, 7 ); $ox = ${$fa}[$i+1]; $oy = ${$fa}[$i+2]; $oz = ${$fa}[$i+3]; if (defined $indexes{$ox}) { $indexes{$ox}++; } else { $indexes{$ox} = 1; } if (defined $indexes{$oy}) { $indexes{$oy}++; } else { $indexes{$oy} = 1; } if (defined $indexes{$oz}) { $indexes{$oz}++; } else { $indexes{$oz} = 1; } $ind = 0; if ($ox && defined $mapped{$ox}) { ${$fa}[$i+1] = $mapped{$ox}; $remapcnt++; $ind++; $ox = $mapped{$ox}; } if ($oy && defined $mapped{$oy}) { ${$fa}[$i+2] = $mapped{$oy}; $remapcnt++; $ind++; $oy = $mapped{$oy}; } if ($oz && defined $mapped{$oz}) { ${$fa}[$i+3] = $mapped{$oz}; $remapcnt++; $ind++; $oz = $mapped{$oz}; } if ($ind) { $facechg++; } push(@faces,$bit); push(@faces,$ox); push(@faces,$oy); push(@faces,$oz); $msg = "Bit $bit $ox,$oy,$oz"; $ib = 3; $i3 = 0; if ($isQuad) { $ib++; $oq = ${$fa}[$i+$ib]; $msg .= ",$oq"; push(@faces,$oq); if (defined $indexes{$oq}) { $indexes{$oq}++; } else { $indexes{$oq} = 1; } } if ($hasMaterial) { $i3++; $oq = ${$fa}[$i+$ib+$i3]; $msg .= ",$oq"; push(@faces,$oq); } if ($hasFaceUv) { $i3++; $oq = ${$fa}[$i+$ib+$i3]; $msg .= ",$oq"; push(@faces,$oq); } if ($hasFaceVertexUv) { $oq = ${$fa}[$i+$ib+$i3+1]; $msg .= ",$oq"; push(@faces,$oq); $oq = ${$fa}[$i+$ib+$i3+2]; $msg .= ",$oq"; push(@faces,$oq); $oq = ${$fa}[$i+$ib+$i3+3]; $msg .= ",$oq"; push(@faces,$oq); if ($isQuad) { $oq = ${$fa}[$i+$ib+$i3+3]; $msg .= ",$oq"; push(@faces,$oq); } $i3 += $ib; } if ($hasFaceNormal) { $i3++; $oq = ${$fa}[$i+$ib+$i3]; $msg .= ",$oq"; push(@faces,$oq); } if ($hasFaceVertexNormal) { $oq = ${$fa}[$i+$ib+$i3+1]; push(@faces,$oq); $msg .= ",$oq"; $oq = ${$fa}[$i+$ib+$i3+2]; push(@faces,$oq); $msg .= ",$oq"; $oq = ${$fa}[$i+$ib+$i3+3]; push(@faces,$oq); $msg .= ",$oq"; if ($isQuad) { $oq = ${$fa}[$i+$ib+$i3+3]; push(@faces,$oq); $msg .= ",$oq"; } $i3 += $ib; } if ($hasFaceColor) { $i3++; $oq = ${$fa}[$i+$ib+$i3]; push(@faces,$oq); $msg .= ",$oq"; } if ($hasFaceVertexColor) { $oq = ${$fa}[$i+$ib+$i3+1]; $msg .= ",$oq"; push(@faces,$oq); $oq = ${$fa}[$i+$ib+$i3+2]; $msg .= ",$oq"; push(@faces,$oq); $oq = ${$fa}[$i+$ib+$i3+3]; $msg .= ",$oq"; push(@faces,$oq); if ($isQuad) { $oq = ${$fa}[$i+$ib+$i3+3]; push(@faces,$oq); $msg .= ",$oq"; } $i3 += $ib; } $i += ($ib + $i3); prt("$msg\n") if (VERB9()); $fc++; } $sx = ($maxx - $minx); $sy = ($maxy - $miny); $sz = ($maxz - $minz); $x = get_decimal6(($maxx + $minx) / 2); $y = get_decimal6(($maxy + $miny) / 2); $z = get_decimal6(($maxz - $minz) / 2); if ($show_ints) { $ix = int(($maxx - $minx) + 0.5); $iy = int(($maxy - $miny) + 0.5); $iz = int(($maxz - $minz) + 0.5); } else { $ix = get_decimal6($maxx - $minx); $iy = get_decimal6($maxy - $miny); $iz = get_decimal6($maxz - $minz); } prt("$name XYZ $ix $iy $iz, Center $x $y $z\n"); if (length($out_file)) { $msg = "[dimensions]\n"; $msg .= "x = $ix\n"; $msg .= "y = $iy\n"; $msg .= "z = $iz\n"; write2file($msg,$out_file); prt("Dimensions written to $out_file\n"); } if (VERB1()) { prt("Found $vc vertices ($tvc), mapped to $mvc diff, and $fc faces...\n"); } if (VERB2()) { prt("Range xyz mins $minx $miny $minz, maxs $maxx $maxy $maxz\n"); ###prt("Span XYZ $sx $sy $sz\n"); } if (VERB5()) { my @arr = sort mycmp_ascend keys(%indexes); $sz = scalar @arr; $sx = $arr[0]; $sy = $arr[$sz-1]; prt("Total $sz indexes, range $sx to $sy, first "); $ioff = $sx * 3; if (($ioff + 2) < $tvc) { $x = ${$va}[$ioff + 0]; $y = ${$va}[$ioff + 1]; $z = ${$va}[$ioff + 2]; prt("($x,$y,$y) "); } else { prt("out-of-range "); } $ioff = $sy * 3; prt("last "); if (($ioff + 2) < $tvc) { $x = ${$va}[$ioff + 0]; $y = ${$va}[$ioff + 1]; $z = ${$va}[$ioff + 2]; prt("($x,$y,$y) "); } else { prt("out-of-range "); } prt("\n"); $msg = "Unused indexes "; $sx = 0; $ioff = 0; for ($sz = 0; $sz < $vc; $sz++) { if (defined $indexes{$sz}) { $sy = $indexes{$sz}; $ioff = $sy if ($sy > $ioff); } else { $msg .= "$sz "; $sx++; } } $msg .= ", cnt $sx, max use $ioff"; prt("$msg\n"); } if ($remapcnt && $write_adjusted) { $line = "$pgmname: version $VERS on ".lu_get_YYYYMMDD_hhmmss(time()); prt("Remapped $remapcnt offsets in $facechg faces...\n"); ###writenewjs(\@verts,$fa,$inf,$line); writenewjs(\@verts,\@faces,$inf,$line); } } else { $msg = 'geometries NOT FOUND'; if (defined ${$rh}{geometries}) { $msg = "got 'geometries' "; my $dra = ${$rh}{geometries}; my $drh = ${$dra}[0]; if (defined ${$drh}{data}) { $msg .= "got 'data' "; my $drh2 = ${$drh}{data}; if (defined ${$drh2}{faces} && defined ${$drh2}{vertices}) { $msg .= "got 'faces' and 'vertices' "; } } prt("TODO: geometries... $msg\n"); } else { $dodump = 1; } } if ($dodump) { prt("'faces' or 'vertices' NOT defined\n"); prt(Dumper($rh)); $load_log = 1; } } sub my_file_type($) { my $file = shift; return 1 if ($file =~ /\.js$/i); return 0; } sub process_in_dir($) { my $dir = shift; if (!opendir(DIR,$dir)) { prtw("WARNING: Failed to open directory $dir!\n"); return; } my @files = readdir(DIR); closedir(DIR); my ($file,$ff); my @dirs = (); ut_fix_directory(\$dir); foreach $file (@files) { next if ($file eq '.'); next if ($file eq '..'); $ff = $dir.$file; if (-f $ff) { process_in_file($ff) if (my_file_type($file)); } elsif (-d $ff) { push(@dirs,$ff); } else { pgm_exit(1,"What is this? $ff ($file)! *** FIX ME ***\n"); } } } sub process_in_files() { foreach $in_file (@in_files) { if (-f $in_file) { process_in_file($in_file); } elsif (-d $in_file) { process_in_dir($in_file); } } } ######################################### ### MAIN ### parse_args(@ARGV); process_in_files(); pgm_exit(0,""); ######################################## sub need_arg { my ($arg,@av) = @_; pgm_exit(1,"ERROR: [$arg] must have a following argument!\n") if (!@av); } sub parse_args { my (@av) = @_; my ($arg,$sarg); my $verb = VERB2(); while (@av) { $arg = $av[0]; if ($arg =~ /^-/) { $sarg = substr($arg,1); $sarg = substr($sarg,1) while ($sarg =~ /^-/); if (($sarg =~ /^h/i)||($sarg eq '?')) { give_help(); pgm_exit(0,"Help exit(0)"); } elsif ($sarg =~ /^v/) { if ($sarg =~ /^v.*(\d+)$/) { $verbosity = $1; } else { while ($sarg =~ /^v/) { $verbosity++; $sarg = substr($sarg,1); } } $verb = VERB2(); prt("Verbosity = $verbosity\n") if ($verb); } elsif ($sarg =~ /^l/) { if ($sarg =~ /^ll/) { $load_log = 2; } else { $load_log = 1; } prt("Set to load log at end. ($load_log)\n") if ($verb); } elsif ($sarg =~ /^o/) { need_arg(@av); shift @av; $sarg = $av[0]; $out_file = $sarg; prt("Set out file to [$out_file].\n") if ($verb); } else { pgm_exit(1,"ERROR: Invalid argument [$arg]! Try -?\n"); } } else { $in_file = $arg; push(@in_files,$in_file); if ( -f $in_file) { prt("Set input file to [$in_file]\n") if ($verb); } elsif ( -d $in_file ) { prt("Set input directory to [$in_file]\n") if ($verb); } else { pgm_exit(1,"ERROR: Unable to find file or directory [$in_file]! Check name, location...\n"); } } shift @av; } if ($debug_on) { prtw("WARNING: DEBUG is ON!\n"); if (length($in_file) == 0) { #$in_file = $def_file1; #push(@in_files,$in_file); #$in_file = $def_file2; #push(@in_files,$in_file); #$in_file = $def_file3; #push(@in_files,$in_file); $in_file = $def_file4; push(@in_files,$in_file); prt("Set DEFAULT input to [$in_file]\n"); # $load_log = 1; } } if (length($in_file) == 0) { pgm_exit(1,"ERROR: No input files found in command!\n"); } #if (! -f $in_file) { # pgm_exit(1,"ERROR: Unable to find in file [$in_file]! Check name, location...\n"); #} } sub give_help { prt("$pgmname: version $VERS\n"); prt("Usage: $pgmname [options] in-file\n"); prt("Options:\n"); prt(" --help (-h or -?) = This help, and exit 0.\n"); prt(" --verb[n] (-v) = Bump [or set] verbosity. def=$verbosity\n"); prt(" --load (-l) = Load LOG at end. ($outfile)\n"); prt(" --out (-o) = Write output to this file.\n"); } # eof - template.pl