Can't use 'defined(@array)' warning in converting .obj to .h

心已入冬 提交于 2019-12-25 18:41:40

问题


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.

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.

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

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

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

Update3:
this is the whole code:

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

# 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;

}

回答1:


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:

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 ( @array ) { 
    print "Array has ", scalar @array, " entries\n";
}
else { 
    print "Array is empty.\n";
}



回答2:


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

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

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.

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




回答3:


From 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:

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



回答4:


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


来源:https://stackoverflow.com/questions/41980796/cant-use-definedarray-warning-in-converting-obj-to-h

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!