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

时间:2022-02-21 15:08:02

I'm trying to convert my .obj file to a .h header file, but i'm getting "Can't use 'defined(@array)' (Maybe you should just omit the defined()?)" warning and no .h files has created.

我试图将我的.obj文件转换成.h头文件,但是我得到了“不能使用”定义的(@array)(也许您应该省略已定义的()?)“警告和no .h文件已经创建了。”

I've tried replacing @center to $center or omintting defined() but it creates .exe file!
I've read somewhere that it may be a perl version problem, mine is 5.22 and I couldn't find higher versions to try.

我已经尝试将@center替换为$center或omintting定义(),但它创建.exe文件!我在某个地方读到过,它可能是perl版本的问题,我的是5.22,我找不到更高版本的尝试。

Update1:
I've put the "obj2opengl.pl " and "myobject.obj" in the same folder. and trying to convert it with this code in console(win10): c:\obj2openglfolder>obj2opengl.pl myobject.obj

Update1:我把“obj2opengl”放在了这里。pl”和“myobject。obj在同一个文件夹中。并且试图用控制台的代码转换它(win10): c:\obj2openglfolder>obj2opengl。pl myobject.obj

Update2:
This is the line154 code that cause the problem:

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

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

Update3:
this is the whole code:

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 个解决方案

#1


4  

That's because an array doesn't have an 'undefined' state. It just has an 'empty' state.

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

If you do:

如果你做的事:

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

use Data::Dumper;

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

Then what you get is:

然后你得到的是:

$VAR1 = [
          undef
        ];

Which is an array with a single (undefined) element.

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

But you can test if an array is empty, trivially - because in a scalar context, @array returns a number of elements:

但是,如果数组是空的,则可以进行测试——因为在标量上下文中,@array返回了一些元素:

print scalar @list;

As long as you force a scalar context, then you'll get a numeric value out.

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

Usefully for an 'empty' array, this is zero, and thus works just fine in an 'if' to test if there's values in the array.

对于一个“空”数组,这是零,因此如果要测试数组中是否有值,那么在“if”中可以很好地工作。

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

#2


3  

defined(@array) used to return whether the array was empty or not. This was a bug.

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

defined(@array) should always return true (since the number of element in an array is always defined).

定义(@array)应该总是返回true(因为数组中元素的数量总是被定义的)。

Rather than fixing the bug (causing code to silently malfunction), that particular (and useless) use of defined now lets the user know they are doing something wrong and how to fix it.

而不是修复bug(导致代码悄无声息地故障),这一特定的(和无用的)使用定义现在让用户知道他们正在做错误的事情以及如何修复它。

As the error message suggests, simply use if (@array) to check if the array is empty.

正如错误消息建议的那样,只要使用if (@array)来检查数组是否为空。

#3


1  

From perldoc:

从perldoc:

Use of defined on aggregates (hashes and arrays) is deprecated. It used to report whether memory for that aggregate had ever been allocated. This behavior may disappear in future versions of Perl. You should instead use a simple test for size:

使用定义的聚合(散列和数组)是不赞成的。它用于报告是否已经分配了该聚合的内存。在Perl的未来版本中,这种行为可能会消失。相反,您应该使用一个简单的大小测试:

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

#4


0  

Just replace

只是替换

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

to

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

#1


4  

That's because an array doesn't have an 'undefined' state. It just has an 'empty' state.

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

If you do:

如果你做的事:

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

use Data::Dumper;

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

Then what you get is:

然后你得到的是:

$VAR1 = [
          undef
        ];

Which is an array with a single (undefined) element.

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

But you can test if an array is empty, trivially - because in a scalar context, @array returns a number of elements:

但是,如果数组是空的,则可以进行测试——因为在标量上下文中,@array返回了一些元素:

print scalar @list;

As long as you force a scalar context, then you'll get a numeric value out.

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

Usefully for an 'empty' array, this is zero, and thus works just fine in an 'if' to test if there's values in the array.

对于一个“空”数组,这是零,因此如果要测试数组中是否有值,那么在“if”中可以很好地工作。

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

#2


3  

defined(@array) used to return whether the array was empty or not. This was a bug.

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

defined(@array) should always return true (since the number of element in an array is always defined).

定义(@array)应该总是返回true(因为数组中元素的数量总是被定义的)。

Rather than fixing the bug (causing code to silently malfunction), that particular (and useless) use of defined now lets the user know they are doing something wrong and how to fix it.

而不是修复bug(导致代码悄无声息地故障),这一特定的(和无用的)使用定义现在让用户知道他们正在做错误的事情以及如何修复它。

As the error message suggests, simply use if (@array) to check if the array is empty.

正如错误消息建议的那样,只要使用if (@array)来检查数组是否为空。

#3


1  

From perldoc:

从perldoc:

Use of defined on aggregates (hashes and arrays) is deprecated. It used to report whether memory for that aggregate had ever been allocated. This behavior may disappear in future versions of Perl. You should instead use a simple test for size:

使用定义的聚合(散列和数组)是不赞成的。它用于报告是否已经分配了该聚合的内存。在Perl的未来版本中,这种行为可能会消失。相反,您应该使用一个简单的大小测试:

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

#4


0  

Just replace

只是替换

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

to

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