#!/usr/bin/perl ## place_on_mesh ## ## author: D. ElTom ## version: 1.1 ## laste modified: 21. Sep. 2005 ## ## description: ## PERL-Script that reads an include file with ONE mesh description in POVRay mesh2 format ## and will write an POVRay include file with arrays for positions and corresponding normals. ## ## usage: ## [perl] place_on_mesh [options] -i [-o ] ## ## linux: make the script executable and run it. ## window$: you may have to call perl interpreter and pass name of script as 1. argument ## ## parameters: ## -i : specify the name of the file to be parsed ## -o : specify the name of the file to be generated [default = output.inc] ## -s : create seperate files for positions, normals and uv's ## output filename will be used as base name. ## -d : specify density [default = 100] use POSIX; %program_options = ("infile" => "infile.inc", "outfile" => "output.inc", "seperate" => "0", "density" => "100"); # vertex data $vertex_count; @vert_x; @vert_y; @vert_z; # normal data $normal_count; @norm_x; @norm_y; @norm_z; # texture coordinate data $has_texcoord = 0; $texcoord_count; @tex_u; @tex_v; # facette information $face_count; @v1_id; @v2_id; @v3_id; @n1_id; @n2_id; @n3_id; @t1_id; @t2_id; @t3_id; $total_area = 0; @areas; $approx_placements; $total_placements; @pv_x; @pv_y; @pv_z; @pn_x; @pn_y; @pn_z; @puv_u; @puv_v; # greeting (mode) # prints a short message # if mode is 1 then include a short help sub greeting # mode { $verbose = $_[0]; print "PLACE ON MESH (V1.1)\n"; print "--------------------\n\n"; if ($verbose==1) { print "usage:\n"; print "[perl] place_on_mesh [options] -i \n\n"; print "parameters:\n"; print " -i : specify the name of the file to be parsed\n"; print " -o : specify the name of the file to be generated [default = output.inc]\n"; print " -s : create seperate files for positions, normals and uv's\n"; print " output filename will be used as base name.\n"; print " -d : specify density [default = 100]\n"; } } # read_program_arguments # parse the comand line parameters sub read_program_arguments # void { $number_of_arguments = $#ARGV + 1; if ($number_of_arguments == 0) { greeting(1); exit(); } else { greeting(0); $arguments_read = 0; $infile_given = 0; while ($arguments_read < $number_of_arguments) { $argument = $ARGV[$arguments_read]; $arguments_read++; if ($argument =~ m/\A[^-]/) { print " don't know what to do with argument $argument\n"; exit(); } else { if ($argument =~ m/-[iosdIOSD]/g) { $known_argument = substr($argument,1,1); if ($known_argument =~ m/i/g) { # input file name sepcification if (length($argument) > 2) { # assume file name was written without space as seperator $program_options{infile} = substr($argument,2,(length($argument)-2)); } else { # assume file name was written wiht space as seperator $program_options{infile} = $ARGV[$arguments_read]; $arguments_read++; } #print " ... will use $program_options{infile} as input ...\n"; $infile_given = 1; } if ($known_argument =~ m/o/g) { # output file name sepcification if (length($argument) > 2) { # assume file name was written without space as seperator $program_options{outfile} = substr($argument,2,(length($argument)-2)); } else { # assume file name was written wiht space as seperator $program_options{outfile} = $ARGV[$arguments_read]; $arguments_read++; } } if ($known_argument =~ m/d/g) { # density sepcification if (length($argument) > 2) { # assume density was written without space as seperator $program_options{density} = substr($argument,2,(length($argument)-2)); } else { # assume density was written wiht space as seperator $program_options{density} = $ARGV[$arguments_read]; $arguments_read++; } # test if given density is a positiv number if ($program_options{density} =~ m/[^\+0-9\.]/g) { print " density have to be a positive number\n"; exit(); } } if ($known_argument =~ m/s/g) { $program_options{seperate} = 1; } } else { @unknown_argument = $argument =~ m/-\w/g; print " unkown option @unknown_argument\n"; exit(); } } } if ($infile_given == 0) { print " you must specify a valid input file\n"; exit(); } # short summary print " ... using $program_options{infile} as input ...\n"; if ($program_options{seperate} == 0) { print " ... using $program_options{outfile} for output ...\n"; } else { @outputfilename = split(/\./,$program_options{outfile}); $p_filename = $outputfilename[0] . "_p." . $outputfilename[1]; $n_filename = $outputfilename[0] . "_n." . $outputfilename[1]; $uv_filename = $outputfilename[0] . "_uv." . $outputfilename[1]; print " ... using $p_filename, $n_filename and $uv_filename for output ...\n"; } print " ... using a density of $program_options{density} ...\n"; } } # parse_input_file (filename) sub parse_input_file # filename { $filename = $_[0]; print " ... opening $filename for reading ... "; open(INFILE,"<$filename") || die "failed\n"; print "ok\n"; while ($line = ) { if ($line =~ m/vertex_vectors/g) { $line = ; @regex_result = $line =~ m/\d+/g; foreach(@regex_result) { if (length($_) > 0) { $vertex_count = $_; } } print " ... reading $vertex_count vertices ... "; for ($counter = 0; $counter < $vertex_count; $counter++) { $line = ; @regex_result = $line =~ m/-?\d*\.?\d*[eE]?-?\d*/g; $n = 0; foreach(@regex_result) { if (length($_) > 0) { $v_coord[$n] = $_; $n++; } } push(@vert_x, $v_coord[0]); push(@vert_y, $v_coord[1]); push(@vert_z, $v_coord[2]); } print "ok\n"; } if ($line =~ m/normal_vectors/g) { $line = ; @regex_result = $line =~ m/\d+/g; foreach(@regex_result) { if (length($_) > 0) { $normal_count = $_; } } print " ... reading $normal_count normals ... "; for ($counter = 0; $counter < $normal_count; $counter++) { $line = ; @regex_result = $line =~ m/-?\d*\.?\d*[eE]?-?\d*/g; $n = 0; foreach(@regex_result) { if (length($_) > 0) { $n_coord[$n] = $_; $n++; } } push(@norm_x, $n_coord[0]); push(@norm_y, $n_coord[1]); push(@norm_z, $n_coord[2]); } print "ok\n"; } if ($line =~ m/uv_vectors/g) { $has_texcoord = 1; $line = ; @regex_result = $line =~ m/\d+/g; foreach(@regex_result) { if (length($_) > 0) { $texcoord_count = $_; } } print " ... reading $texcoord_count texture coordinates ... "; for ($counter = 0; $counter < $texcoord_count; $counter++) { $line = ; @regex_result = $line =~ m/-?\d*\.?\d*[eE]?-?\d*/g; $n = 0; foreach(@regex_result) { if (length($_) > 0) { $tex_coord[$n] = $_; $n++; } } push(@tex_u, $tex_coord[0]); push(@tex_v, $tex_coord[1]); #print "$tex_coord[0], $tex_coord[1]\n"; } print "ok\n"; } if ($line =~ m/face_indices/g) { $line = ; @regex_result = $line =~ m/\d+/g; foreach(@regex_result) { if (length($_) > 0) { $face_count = $_; } } print " ... reading $face_count face indices ... "; for ($counter = 0; $counter < $face_count; $counter++) { $line = ; @regex_result = $line =~ m/\d+/g; $n = 0; foreach(@regex_result) { if (length($_) > 0) { $f_id[$n] = $_; $n++; } } push(@v1_id, $f_id[0]); push(@v2_id, $f_id[1]); push(@v3_id, $f_id[2]); #print "$f_id[0], $f_id[1], $f_id[2]\n"; } print "ok\n"; } if ($line =~ m/normal_indices/g) { $line = ; @regex_result = $line =~ m/\d+/g; foreach(@regex_result) { if (length($_) > 0) { $face_count = $_; } } print " ... reading $face_count normal indices ... "; for ($counter = 0; $counter < $face_count; $counter++) { $line = ; @regex_result = $line =~ m/\d+/g; $n = 0; foreach(@regex_result) { if (length($_) > 0) { $n_id[$n] = $_; $n++; } } push(@n1_id, $n_id[0]); push(@n2_id, $n_id[1]); push(@n3_id, $n_id[2]); #print "$n_id[0], $n_id[1], $n_id[2]\n"; } print "ok\n"; } if ($line =~ m/uv_indices/g) { $line = ; @regex_result = $line =~ m/\d+/g; foreach(@regex_result) { if (length($_) > 0) { $face_count = $_; } } print " ... reading $face_count texture coordinate indices ... "; for ($counter = 0; $counter < $face_count; $counter++) { $line = ; @regex_result = $line =~ m/\d+/g; $n = 0; foreach(@regex_result) { if (length($_) > 0) { $t_id[$n] = $_; $n++; } } push(@t1_id, $t_id[0]); push(@t2_id, $t_id[1]); push(@t3_id, $t_id[2]); #print "$t_id[0], $t_id[1], $t_id[2]\n"; } print "ok\n"; } } close(INFILE); } # calculate_area() # calculate the area of each facette and total area sub calculate_area # void { print " ... calculating surface area ... "; for($counter = 0; $counter < $face_count; $counter++) { # diference vectors $dv1_x = $vert_x[$v1_id[$counter]] - $vert_x[$v2_id[$counter]]; $dv1_y = $vert_y[$v1_id[$counter]] - $vert_y[$v2_id[$counter]]; $dv1_z = $vert_z[$v1_id[$counter]] - $vert_z[$v2_id[$counter]]; $dv2_x = $vert_x[$v3_id[$counter]] - $vert_x[$v2_id[$counter]]; $dv2_y = $vert_y[$v3_id[$counter]] - $vert_y[$v2_id[$counter]]; $dv2_z = $vert_z[$v3_id[$counter]] - $vert_z[$v2_id[$counter]]; # cross product $cross_x = $dv1_y * $dv2_z - $dv2_y * $dv1_z; $cross_y = $dv2_x * $dv1_z - $dv1_x * $dv2_z; $cross_z = $dv1_x * $dv2_y - $dv2_x * $dv1_y; $area = .5 * sqrt($cross_x*$cross_x + $cross_y*$cross_y + $cross_z*$cross_z); push(@areas,$area); # print " Dreiecksflaeche = $area\n"; $total_area += $area; } print "ok\n"; } sub place { print " ... placing ... "; $total_placements = 0; for($counter=0; $counter < $face_count; $counter++) { $area = $areas[$counter]; $number_of_elements = $area * $approx_placements / $total_area; $place_for_sure = floor($number_of_elements); $place_maybe = $number_of_elements - $place_for_sure; $total_placements += $place_for_sure; $maybe = rand(); # diference vectors $dv1_x = $vert_x[$v1_id[$counter]] - $vert_x[$v2_id[$counter]]; $dv1_y = $vert_y[$v1_id[$counter]] - $vert_y[$v2_id[$counter]]; $dv1_z = $vert_z[$v1_id[$counter]] - $vert_z[$v2_id[$counter]]; $dv2_x = $vert_x[$v3_id[$counter]] - $vert_x[$v2_id[$counter]]; $dv2_y = $vert_y[$v3_id[$counter]] - $vert_y[$v2_id[$counter]]; $dv2_z = $vert_z[$v3_id[$counter]] - $vert_z[$v2_id[$counter]]; for($place_counter=0; $place_counter<$place_for_sure; $place_counter++) { do { $U = rand(); $V = rand(); } while(($U+$V)>1); $p_x = $vert_x[$v2_id[$counter]] + (($dv1_x*$U) + ($dv2_x*$V)); $p_y = $vert_y[$v2_id[$counter]] + (($dv1_y*$U) + ($dv2_y*$V)); $p_z = $vert_z[$v2_id[$counter]] + (($dv1_z*$U) + ($dv2_z*$V)); push(@pv_x, $p_x); push(@pv_y, $p_y); push(@pv_z, $p_z); $n1_x = $norm_x[$n1_id[$counter]]; $n1_y = $norm_y[$n1_id[$counter]]; $n1_z = $norm_z[$n1_id[$counter]]; $n2_x = $norm_x[$n2_id[$counter]]; $n2_y = $norm_y[$n2_id[$counter]]; $n2_z = $norm_z[$n2_id[$counter]]; $n3_x = $norm_x[$n2_id[$counter]]; $n3_y = $norm_y[$n2_id[$counter]]; $n3_z = $norm_z[$n2_id[$counter]]; $nu_x = (1-$U)*$n2_x + $U*$n1_x; $nu_y = (1-$U)*$n2_y + $U*$n1_y; $nu_z = (1-$U)*$n2_z + $U*$n1_z; $nv_x = (1-$V)*$n2_x + $V*$n3_x; $nv_y = (1-$V)*$n2_y + $V*$n3_y; $nv_z = (1-$V)*$n2_z + $V*$n3_z; $n_x = $nu_x + $nv_x; $n_y = $nu_y + $nv_y; $n_z = $nu_z + $nv_z; $nlength = sqrt(($n_x*$n_x)+($n_y*$n_y)+($n_z*$n_z)); $n_x = $n_x / $nlength; $n_y = $n_y / $nlength; $n_z = $n_z / $nlength; push(@pn_x,$n_x); push(@pn_y,$n_y); push(@pn_z,$n_z); if ($has_texcoord == 1) { $duv1_u = $tex_u[$t1_id[$counter]]-$tex_u[$t2_id[$counter]]; $duv1_v = $tex_v[$t1_id[$counter]]-$tex_v[$t2_id[$counter]]; $duv2_u = $tex_u[$t3_id[$counter]]-$tex_u[$t2_id[$counter]]; $duv2_v = $tex_v[$t3_id[$counter]]-$tex_v[$t2_id[$counter]]; $uv_u = $tex_u[$t2_id[$counter]] + $U*$duv1_u + $V*$duv2_u; $uv_v = $tex_v[$t2_id[$counter]] + $U*$duv1_v + $V*$duv2_v; push(@puv_u, $uv_u); push(@puv_v, $uv_v); } } if($maybe <= $place_maybe) { $total_placements++; do { $U = rand(); $V = rand(); } while(($U+$V)>1); $p_x = $vert_x[$v2_id[$counter]] + (($dv1_x*$U) + ($dv2_x*$V)); $p_y = $vert_y[$v2_id[$counter]] + (($dv1_y*$U) + ($dv2_y*$V)); $p_z = $vert_z[$v2_id[$counter]] + (($dv1_z*$U) + ($dv2_z*$V)); push(@pv_x, $p_x); push(@pv_y, $p_y); push(@pv_z, $p_z); $n1_x = $norm_x[$n1_id[$counter]]; $n1_y = $norm_y[$n1_id[$counter]]; $n1_z = $norm_z[$n1_id[$counter]]; $n2_x = $norm_x[$n2_id[$counter]]; $n2_y = $norm_y[$n2_id[$counter]]; $n2_z = $norm_z[$n2_id[$counter]]; $n3_x = $norm_x[$n2_id[$counter]]; $n3_y = $norm_y[$n2_id[$counter]]; $n3_z = $norm_z[$n2_id[$counter]]; $nu_x = (1-$U)*$n2_x + $U*$n1_x; $nu_y = (1-$U)*$n2_y + $U*$n1_y; $nu_z = (1-$U)*$n2_z + $U*$n1_z; $nv_x = (1-$V)*$n2_x + $V*$n3_x; $nv_y = (1-$V)*$n2_y + $V*$n3_y; $nv_z = (1-$V)*$n2_z + $V*$n3_z; $n_x = $nu_x + $nv_x; $n_y = $nu_y + $nv_y; $n_z = $nu_z + $nv_z; $nlength = sqrt(($n_x*$n_x)+($n_y*$n_y)+($n_z*$n_z)); $n_x = $n_x / $nlength; $n_y = $n_y / $nlength; $n_z = $n_z / $nlength; push(@pn_x,$n_x); push(@pn_y,$n_y); push(@pn_z,$n_z); if ($has_texcoord == 1) { $duv1_u = $tex_u[$t1_id[$counter]]-$tex_u[$t2_id[$counter]]; $duv1_v = $tex_v[$t1_id[$counter]]-$tex_v[$t2_id[$counter]]; $duv2_u = $tex_u[$t3_id[$counter]]-$tex_u[$t2_id[$counter]]; $duv2_v = $tex_v[$t3_id[$counter]]-$tex_v[$t2_id[$counter]]; $uv_u = $tex_u[$t2_id[$counter]] + $U*$duv1_u + $V*$duv2_u; $uv_v = $tex_v[$t2_id[$counter]] + $U*$duv1_v + $V*$duv2_v; push(@puv_u, $uv_u); push(@puv_v, $uv_v); } } } print "ok\n"; } sub write_output { @name_parts = split(/\./,$program_options{outfile}); if ($program_options{seperate} == 0) { $outfilename = $program_options{outfile}; } else { $outfilename = $name_parts[0] . "_p." . $name_parts[1]; } print " ... trying to open $outfilename for writing ... "; open (OUTFILE,">$outfilename") || die "failed\n"; print "ok\n"; print " ... writing data ... "; print OUTFILE "#declare pom_placement_count = $total_placements;\n"; print OUTFILE "#declare pom_positions = \n"; print OUTFILE "array[$total_placements]\n{\n"; for($counter=0; $counter < $total_placements; $counter++) { print OUTFILE "< $pv_x[$counter], $pv_y[$counter], $pv_z[$counter]>"; if($counter < ($total_placements-1)) { print OUTFILE ",\n"; } else { print OUTFILE "\n"; } } print OUTFILE "}\n"; if ($program_options{seperate} == 1) { print "ok\n"; close(OUTFILE); $outfilename = $name_parts[0] . "_n." . $name_parts[1]; print " ... trying to open $outfilename for writing ... "; open (OUTFILE,">$outfilename") || die "failed\n"; print "ok\n"; print " ... writing data ... "; print OUTFILE "#declare pom_placement_count = $total_placements;\n"; } print OUTFILE "#declare pom_normals = \n"; print OUTFILE "array[$total_placements]\n{\n"; for($counter=0; $counter < $total_placements; $counter++) { print OUTFILE "< $pn_x[$counter], $pn_y[$counter], $pn_z[$counter]>"; if($counter < ($total_placements-1)) { print OUTFILE ",\n"; } else { print OUTFILE "\n"; } } print OUTFILE "}\n"; if ($has_texcoord == 1) { if ($program_options{seperate} == 1) { print "ok\n"; close(OUTFILE); $outfilename = $name_parts[0] . "_uv." . $name_parts[1]; print " ... trying to open $outfilename for writing ... "; open (OUTFILE,">$outfilename") || die "failed\n"; print "ok\n"; print " ... writing data ... "; print OUTFILE "#declare pom_placement_count = $total_placements;\n"; } print OUTFILE "#declare pom_uvs = \n"; print OUTFILE "array[$total_placements]\n{\n"; for($counter=0; $counter < $total_placements; $counter++) { print OUTFILE "< $puv_u[$counter], $puv_v[$counter]>"; if($counter < ($total_placements-1)) { print OUTFILE ",\n"; } else { print OUTFILE "\n"; } } print OUTFILE "}\n"; } print "ok\n"; close(OUTFILE); } ### # MAIN ### # process program arguments read_program_arguments(); # test if input file exist if (!(-e "$program_options{infile}")) { print " input file ($program_options{infile}) doesn't seems to exist ...\n"; exit(); } # parsing input file parse_input_file($program_options{infile}); # calculate the area of each facette and total area calculate_area(); $approx_placements = floor($program_options{density}*$total_area); print " ... approximately $approx_placements will be placed (density = $program_options{density})\n"; # the essential part place(); write_output(); print " ... good bye.\n";