在将.obj转换为.h时不能使用'defined(@array)'警告

时间:2017-02-01 13:16:38

标签: perl opengl header-files .obj

我正在尝试将我的.obj文件转换为.h头文件,但我得到“无法使用”定义(@array)'(也许你应该省略已定义的()?)“警告并没有创建.h文件。

我已尝试将@center替换为$center或省略defined(),但会创建.exe文件!
我在某处看过它可能是一个perl版本的问题,我的是5.22,我找不到更高版本的尝试。

UPDATE1:
我把“obj2opengl.pl”和“myobject.obj”放在同一个文件夹中。并尝试在控制台(win10)中使用此代码转换它: c:\obj2openglfolder>obj2opengl.pl myobject.obj

UPDATE2:
这是导致问题的line154代码:

if(defined(@center)) {
    $xcen = $center[0];
    $ycen = $center[1];
    $zcen = $center[2];
}

UPDATE3:
这是整个代码:

# -----------------------------------------------------------------

# Main Program

# -----------------------------------------------------------------

handleArguments();
# derive center coords and scale factor if neither provided nor disabled

unless(defined($scalefac) && defined($xcen)) {
calcSizeAndCenter();

}


if($verbose) {
printInputAndOptions();

}


# TODO check integrity: Does every referenced vertex, normal and coord 
exist?

loadData();

normalizeNormals();


if($verbose) {
printStatistics();

}


writeOutput();


# -----------------------------------------------------------------

# Sub Routines

# -----------------------------------------------------------------


sub handleArguments() {
my $help = 0;
my $man = 0;
my $noscale = 0;
my $nomove = 0;
$verbose = 1;
$errorInOptions = !GetOptions (
    "help" => \$help,
    "man"  => \$man,
    "noScale" => \$noscale,
    "scale=f" => \$scalefac,
    "noMove" => \$nomove,
    "center=f{3}" => \@center,
    "outputFilename=s" => \$outFilename,
    "nameOfObject=s" => \$object,
    "verbose!" => \$verbose,
    );

if($noscale) {
    $scalefac = 1;
}

if($nomove) {
    @center = (0, 0, 0);
}

if(@center) {
    $xcen = $center[0];
    $ycen = $center[1];
    $zcen = $center[2];
}

if($#ARGV == 0) {
    my ($file, $dir, $ext) = fileparse($ARGV[0], qr/\.[^.]*/);
    $inFilename = $dir . $file . $ext;
} else {
    $errorInOptions = true;
}

# (optional) derive output filename from input filename
unless($errorInOptions || defined($outFilename)) {
    my ($file, $dir, $ext) = fileparse($inFilename, qr/\.[^.]*/);
    $outFilename = $dir . $file . ".h";
}

# (optional) define object name from output filename
unless($errorInOptions || defined($object)) {
    my ($file, $dir, $ext) = fileparse($outFilename, qr/\.[^.]*/);
    $object = $file;
}

($inFilename ne $outFilename) or
    die ("Input filename must not be the same as output filename")
    unless($errorInOptions);

if($errorInOptions || $man || $help) {
    pod2usage(-verbose => 2) if $man;
    pod2usage(-verbose => 1) if $help;
    pod2usage(); 
}

# check wheter file exists
open ( INFILE, "<$inFilename" ) 
  || die "Can't find file '$inFilename' ...exiting \n";
close(INFILE);

}


# Stores center of object in $xcen, $ycen, $zcen

# and calculates scaling factor $scalefac to limit max

#   side of object to 1.0 units

sub calcSizeAndCenter() {
open ( INFILE, "<$inFilename" ) 
  || die "Can't find file $inFilename...exiting \n";

$numVerts = 0;

my (
    $xsum, $ysum, $zsum, 
    $xmin, $ymin, $zmin,
    $xmax, $ymax, $zmax,
    );

while ( $line = <INFILE> ) 
{
  chop $line;

  if ($line =~ /v\s+.*/)
  {

    $numVerts++;
    @tokens = split(' ', $line);

    $xsum += $tokens[1];
    $ysum += $tokens[2];
    $zsum += $tokens[3];

    if ( $numVerts == 1 )
    {
      $xmin = $tokens[1];
      $xmax = $tokens[1];
      $ymin = $tokens[2];
      $ymax = $tokens[2];
      $zmin = $tokens[3];
      $zmax = $tokens[3];
    }
    else
    {   
        if ($tokens[1] < $xmin)
      {
        $xmin = $tokens[1];
      }
      elsif ($tokens[1] > $xmax)
      {
        $xmax = $tokens[1];
      }

      if ($tokens[2] < $ymin) 
      {
        $ymin = $tokens[2];
      }
      elsif ($tokens[2] > $ymax) 
      {
        $ymax = $tokens[2];
      }

      if ($tokens[3] < $zmin) 
      {
        $zmin = $tokens[3];
      }
      elsif ($tokens[3] > $zmax) 
      {
        $zmax = $tokens[3];
      }

    }

  }

}
close INFILE;

#  Calculate the center
unless(defined($xcen)) {
    $xcen = $xsum / $numVerts;
    $ycen = $ysum / $numVerts;
    $zcen = $zsum / $numVerts;
}

#  Calculate the scale factor
unless(defined($scalefac)) {
    my $xdiff = ($xmax - $xmin);
    my $ydiff = ($ymax - $ymin);
    my $zdiff = ($zmax - $zmin);

    if ( ( $xdiff >= $ydiff ) && ( $xdiff >= $zdiff ) ) 
    {
      $scalefac = $xdiff;
    }
    elsif ( ( $ydiff >= $xdiff ) && ( $ydiff >= $zdiff ) ) 
    {
      $scalefac = $ydiff;
    }
    else 
    {
      $scalefac = $zdiff;
    }
    $scalefac = 1.0 / $scalefac;
}

}


sub printInputAndOptions() {
print "Input file     : $inFilename\n";
print "Output file    : $outFilename\n";
print "Object name    : $object\n";
print "Center         : <$xcen, $ycen, $zcen>\n";
print "Scale by       : $scalefac\n";

}


sub printStatistics() {
print "----------------\n";
print "Vertices       : $numVerts\n";
print "Faces          : $numFaces\n";
print "Texture Coords : $numTexture\n";
print "Normals        : $numNormals\n";

}


# reads vertices into $xcoords[], $ycoords[], $zcoords[]

#   where coordinates are moved and scaled according to

#   $xcen, $ycen, $zcen and $scalefac

# reads texture coords into $tx[], $ty[] 

#   where y coordinate is mirrowed

# reads normals into $nx[], $ny[], $nz[]

#   but does not normalize, see normalizeNormals()

# reads faces and establishes lookup data where

#   va_idx[], vb_idx[], vc_idx[] for vertices

#   ta_idx[], tb_idx[], tc_idx[] for texture coords

#   na_idx[], nb_idx[], nc_idx[] for normals

#   store indizes for the former arrays respectively

#   also, $face_line[] store actual face string

sub loadData {
$numVerts = 0;
$numFaces = 0;
$numTexture = 0;
$numNormals = 0;

open ( INFILE, "<$inFilename" )
  || die "Can't find file $inFilename...exiting \n";

while ($line = <INFILE>) 
{
  chop $line;

  # vertices
  if ($line =~ /v\s+.*/)
  {
    @tokens= split(' ', $line);
    $x = ( $tokens[1] - $xcen ) * $scalefac;
    $y = ( $tokens[2] - $ycen ) * $scalefac;
    $z = ( $tokens[3] - $zcen ) * $scalefac;    
    $xcoords[$numVerts] = $x; 
    $ycoords[$numVerts] = $y;
    $zcoords[$numVerts] = $z;

    $numVerts++;
  }

  # texture coords
  if ($line =~ /vt\s+.*/)
  {
    @tokens= split(' ', $line);
    $x = $tokens[1];
    $y = 1 - $tokens[2];
    $tx[$numTexture] = $x;
    $ty[$numTexture] = $y;

    $numTexture++;
  }

  #normals
  if ($line =~ /vn\s+.*/)
  {
    @tokens= split(' ', $line);
    $x = $tokens[1];
    $y = $tokens[2];
    $z = $tokens[3];
    $nx[$numNormals] = $x; 
    $ny[$numNormals] = $y;
    $nz[$numNormals] = $z;

    $numNormals++;
  }

  # faces
  if ($line =~ /f\s+([^ ]+)\s+([^ ]+)\s+([^ ]+)(\s+([^ ]+))?/) 
  {
    @a = split('/', $1);
    @b = split('/', $2);
    @c = split('/', $3);
    $va_idx[$numFaces] = $a[0]-1;
    $ta_idx[$numFaces] = $a[1]-1;
    $na_idx[$numFaces] = $a[2]-1;

    $vb_idx[$numFaces] = $b[0]-1;
    $tb_idx[$numFaces] = $b[1]-1;
    $nb_idx[$numFaces] = $b[2]-1;

    $vc_idx[$numFaces] = $c[0]-1;
    $tc_idx[$numFaces] = $c[1]-1;
    $nc_idx[$numFaces] = $c[2]-1;

    $face_line[$numFaces] = $line;

    $numFaces++;

    # ractangle => second triangle
    if($5 != "")
    {
        @d = split('/', $5);
        $va_idx[$numFaces] = $a[0]-1;
        $ta_idx[$numFaces] = $a[1]-1;
        $na_idx[$numFaces] = $a[2]-1;

        $vb_idx[$numFaces] = $d[0]-1;
        $tb_idx[$numFaces] = $d[1]-1;
        $nb_idx[$numFaces] = $d[2]-1;

        $vc_idx[$numFaces] = $c[0]-1;
        $tc_idx[$numFaces] = $c[1]-1;
        $nc_idx[$numFaces] = $c[2]-1;

        $face_line[$numFaces] = $line;

        $numFaces++;
    }

  }  
}

close INFILE;

}


sub normalizeNormals {
for ( $j = 0; $j < $numNormals; ++$j) 
{
 $d = sqrt ( $nx[$j]*$nx[$j] + $ny[$j]*$ny[$j] + $nz[$j]*$nz[$j] );

  if ( $d == 0 )
  {
    $nx[$j] = 1;
    $ny[$j] = 0;
    $nz[$j] = 0;
  }
  else
  {
    $nx[$j] = $nx[$j] / $d;
    $ny[$j] = $ny[$j] / $d;
    $nz[$j] = $nz[$j] / $d;
  }

}

}


sub fixedIndex {
local $idx = $_[0];
local $num = $_[1];
if($idx >= 0)
{
    $idx;
} else {
    $num + $idx + 1;
}

}


sub writeOutput {
open ( OUTFILE, ">$outFilename" ) 
  || die "Can't create file $outFilename ... exiting\n";

print OUTFILE "/*\n";
print OUTFILE "created with obj2opengl.pl\n\n";

# some statistics
print OUTFILE "source file    : $inFilename\n";
print OUTFILE "vertices       : $numVerts\n";
print OUTFILE "faces          : $numFaces\n";
print OUTFILE "normals        : $numNormals\n";
print OUTFILE "texture coords : $numTexture\n";
print OUTFILE "\n\n";

# example usage
print OUTFILE "// include generated arrays\n";
print OUTFILE "#import \"".$outFilename."\"\n";
print OUTFILE "\n";
print OUTFILE "// set input data to arrays\n";
print OUTFILE "glVertexPointer(3, GL_FLOAT, 0, ".$object."Verts);\n";
print OUTFILE "glNormalPointer(GL_FLOAT, 0, ".$object."Normals);\n"
    if $numNormals > 0;
print OUTFILE "glTexCoordPointer(2, GL_FLOAT, 0, ".$object."TexCoords);\n"
    if $numTexture > 0;
print OUTFILE "\n";
print OUTFILE "// draw data\n";
print OUTFILE "glDrawArrays(GL_TRIANGLES, 0, ".$object."NumVerts);\n";
print OUTFILE "*/\n\n";

# needed constant for glDrawArrays
print OUTFILE "unsigned int ".$object."NumVerts = ".($numFaces * 3).";\n\n";

# write verts
print OUTFILE "float ".$object."Verts \[\] = {\n"; 
for( $j = 0; $j < $numFaces; $j++)
{
    $ia = fixedIndex($va_idx[$j], $numVerts);
    $ib = fixedIndex($vb_idx[$j], $numVerts);
    $ic = fixedIndex($vc_idx[$j], $numVerts);
    print OUTFILE "  // $face_line[$j]\n";
    print OUTFILE "  $xcoords[$ia], $ycoords[$ia], $zcoords[$ia],\n";
    print OUTFILE "  $xcoords[$ib], $ycoords[$ib], $zcoords[$ib],\n";
    print OUTFILE "  $xcoords[$ic], $ycoords[$ic], $zcoords[$ic],\n";
}
print OUTFILE "};\n\n";

# write normals
if($numNormals > 0) {
    print OUTFILE "float ".$object."Normals \[\] = {\n"; 
    for( $j = 0; $j < $numFaces; $j++) {
        $ia = fixedIndex($na_idx[$j], $numNormals);
        $ib = fixedIndex($nb_idx[$j], $numNormals);
        $ic = fixedIndex($nc_idx[$j], $numNormals);
        print OUTFILE "  // $face_line[$j]\n";
        print OUTFILE "  $nx[$ia], $ny[$ia], $nz[$ia],\n";
        print OUTFILE "  $nx[$ib], $ny[$ib], $nz[$ib],\n";
        print OUTFILE "  $nx[$ic], $ny[$ic], $nz[$ic],\n";
    }

    print OUTFILE "};\n\n";
}

# write texture coords
if($numTexture) {
    print OUTFILE "float ".$object."TexCoords \[\] = {\n"; 
    for( $j = 0; $j < $numFaces; $j++) {
        $ia = fixedIndex($ta_idx[$j], $numTexture);
        $ib = fixedIndex($tb_idx[$j], $numTexture);
        $ic = fixedIndex($tc_idx[$j], $numTexture);
        print OUTFILE "  // $face_line[$j]\n";
        print OUTFILE "  $tx[$ia], $ty[$ia],\n";
        print OUTFILE "  $tx[$ib], $ty[$ib],\n";
        print OUTFILE "  $tx[$ic], $ty[$ic],\n";
    }

    print OUTFILE "};\n\n";
}

close OUTFILE;

}

4 个答案:

答案 0 :(得分:5)

那是因为数组没有'undefined'状态。它只是一个'空'状态。

如果你这样做:

#!/usr/bin/env perl
use strict;
use warnings;

use Data::Dumper;

my @array = undef;   
print Dumper \@array ;

然后你得到的是:

$VAR1 = [
          undef
        ];

这是一个包含单个(未定义)元素的数组。

但是你可以测试一个数组是否为空,非常简单 - 因为在标量上下文中,@array返回了许多元素:

print scalar @list;

只要强制使用标量上下文,就会得到一个数值。

对于'空'数组有用,这是零,因此在'if'中可以正常工作,以测试数组中是否有值。

if ( @array ) { 
    print "Array has ", scalar @array, " entries\n";
}
else { 
    print "Array is empty.\n";
}

答案 1 :(得分:4)

defined(@array)用于返回数组是否为空。这是一个错误。

defined(@array)应始终返回true(因为始终定义数组中的元素数)。

而不是修复错误(导致代码无声地出现故障),defined的特定(和无用)使用现在让用户知道他们做错了什么以及如何修复它。

如错误消息所示,只需使用if (@array)检查数组是否为空。

答案 2 :(得分:1)

来自perldoc

  

不推荐在聚合(哈希和数组)上使用已定义的内容。它曾用于报告是否已分配该聚合的内存。在将来的Perl版本中,此行为可能会消失。您应该使用简单的大小测试:

    if (@an_array) { print "has array elements\n" }
    if (%a_hash)   { print "has hash members\n"   }

答案 3 :(得分:0)

只需替换

`if(defined(@center)) {
        $xcen = $center[0];
        $ycen = $center[1];
        $zcen = $center[2];
    }`

if ( @center ) { 
    print "Array has ", scalar @array, " entries\n";
    $xcen = $center[0];
    $ycen = $center[1];
    $zcen = $center[2];
}