不能在将 .obj 转换为 .h 时使用"已定义(@array)"警告



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

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

更新1:
我把"obj2opengl.pl"和"myobject.obj"放在同一个文件夹中。并尝试在控制台(win10)中使用此代码对其进行转换: c:obj2openglfolder>obj2opengl.pl myobject.obj

更新2:
这是导致问题的 line154 代码:

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

更新3:
这是整个代码:

# -----------------------------------------------------------------
# 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 =~ /vs+.*/)
  {
    $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     : $inFilenamen";
print "Output file    : $outFilenamen";
print "Object name    : $objectn";
print "Center         : <$xcen, $ycen, $zcen>n";
print "Scale by       : $scalefacn";
}

sub printStatistics() {
print "----------------n";
print "Vertices       : $numVertsn";
print "Faces          : $numFacesn";
print "Texture Coords : $numTexturen";
print "Normals        : $numNormalsn";
}

# 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 =~ /vs+.*/)
  {
    @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 =~ /vts+.*/)
  {
    @tokens= split(' ', $line);
    $x = $tokens[1];
    $y = 1 - $tokens[2];
    $tx[$numTexture] = $x;
    $ty[$numTexture] = $y;
    $numTexture++;
  }
  #normals
  if ($line =~ /vns+.*/)
  {
    @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 =~ /fs+([^ ]+)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 ... exitingn";
print OUTFILE "/*n";
print OUTFILE "created with obj2opengl.plnn";
# some statistics
print OUTFILE "source file    : $inFilenamen";
print OUTFILE "vertices       : $numVertsn";
print OUTFILE "faces          : $numFacesn";
print OUTFILE "normals        : $numNormalsn";
print OUTFILE "texture coords : $numTexturen";
print OUTFILE "nn";
# example usage
print OUTFILE "// include generated arraysn";
print OUTFILE "#import "".$outFilename.""n";
print OUTFILE "n";
print OUTFILE "// set input data to arraysn";
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 datan";
print OUTFILE "glDrawArrays(GL_TRIANGLES, 0, ".$object."NumVerts);n";
print OUTFILE "*/nn";
# needed constant for glDrawArrays
print OUTFILE "unsigned int ".$object."NumVerts = ".($numFaces * 3).";nn";
# 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 "};nn";
# 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 "};nn";
}
# 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 "};nn";
}
close OUTFILE;
}

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

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

现在,对

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

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

这是因为数组没有"未定义"状态。它只有一个"空"状态。

如果您这样做:

#!/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, " entriesn";
}
else { 
    print "Array is empty.n";
}

来自 perldoc:

推荐使用在聚合(哈希和数组)上定义的。它用于报告是否曾经分配过该聚合的内存。这种行为可能会在未来的 Perl 版本中消失。您应该改用一个简单的大小测试:

    if (@an_array) { print "has array elementsn" }
    if (%a_hash)   { print "has hash membersn"   }

只需替换

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

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

最新更新