【问题标题】:Can't use 'defined(@array)' warning in converting .obj to .h在将 .obj 转换为 .h 时不能使用“已定义(@array)”警告
【发布时间】:2017-06-18 06:14:27
【问题描述】:

我正在尝试将我的 .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:
这是导致问题的第 154 行代码:

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 =~ /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;

}

【问题讨论】:

  • 你的代码在哪里?
  • 在C目录的“obj2openglfolder”文件夹中
  • 请阅读并提供minimal reproducible example
  • 在最近的 Perl 版本中,defined(@array) 已被弃用。删除defined
  • 我已经尝试过这个,这种情况下警告会过去,但仍然没有创建 .h 文件。它只是创建一个 .exe 文件,我不需要它。还是谢谢

标签: perl opengl header-files .obj


【解决方案1】:

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

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

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

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

【讨论】:

    【解决方案2】:

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

    如果你这样做:

    #!/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";
    }
    

    【讨论】:

    • 谢谢。那我到底应该怎么做呢?我对 perl 不熟悉
    • 聘请 perl 程序员可能吗?我的意思是,你已经给了我们 4 行 perl 来查看,我们可以告诉你它有什么问题 - 但我们不能告诉你如何修复它,因为我们无法告诉你代码的其余部分是什么正在做。
    【解决方案3】:

    来自perldoc

    已弃用在聚合(散列和数组)上定义的用法。它用于报告该聚合的内存是否已分配。这种行为可能会在 Perl 的未来版本中消失。您应该改为使用简单的大小测试:

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

    【讨论】:

    • 这是正确的。但是,我想知道上述代码中“定义”测试的目的。我的意思是,它是否测试数组 exists 或它是否具有值? defined 表示前者,但代码会执行后者。
    • 我已经尝试过这个,这种情况下警告会过去,但仍然没有创建 .h 文件。它只是创建一个 .exe 文件,我不需要它。还是谢谢
    【解决方案4】:

    只需替换

    `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];
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-25
      • 1970-01-01
      相关资源
      最近更新 更多