#!/usr/bin/ruby # coding: utf-8 # Copyright 2017 Sylvain Sauvage slswww@free.fr # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 3 of # the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . require 'matrix' NEW_MODEL_RE = /^0\s+FILE\s+(.*)/ END_MODEL_RE = /^0\s+NOFILE\s*/ COMMENT_RE = /^\s*0(.*)/ USAGE_RE = /^\s*1\s+(\d+)\s+(([^\s]+\s+){12})(.*)/ OTHER_RE = /^\s*([2-5])\s+(\d+)\s+(.*)/ FLOAT_FMT = '%.5f ' def read_matrix( str ) x, y, z, *r = str.split( /\s+/ ).map { |s| Float( s ) } Matrix[ [ r[0], r[1], r[2], x ], [ r[3], r[4], r[5], y ], [ r[6], r[7], r[8], z ], [ 0, 0, 0, 1 ] ] end def read_vectors( str ) elts = str.split( /\s+/ ).map { |s| Float( s ) } (elts.size / 3).times.map { |v| elts[ (v * 3)..(v * 3 + 2) ] } end def vectors_to_s( vs ) vs.map { |v| ( FLOAT_FMT * 3 ) % v }.join( ' ' ) end class Matrix def to_s ( FLOAT_FMT * 12 ) % [ self[0, 3], self[1, 3], self[2, 3], self[0, 0], self[0, 1], self[0, 2], self[1, 0], self[1, 1], self[1, 2], self[2, 0], self[2, 1], self[2, 2] ] end end Other = Struct.new( :type, :color, :vectors ) Use = Struct.new( :color, :matrix, :file ) Comment = Struct.new( :txt ) Empty = Struct.new( :txt ) Model = Struct.new( :file, :lines ) do def pout( color, matrix, models ) lines.each do |line| case line when Empty puts() when Comment puts( "0 %s\r\n" % line.txt ) when Use actual_color = line.color == 16 ? color : line.color actual_matrix = matrix * line.matrix if models.has_key?( line.file ) puts( "0 // %s in %d at %s\r\n" % [ line.file, line.color, line.matrix ] ) models[line.file].pout( actual_color, actual_matrix, models ) else puts( "1 %d %s %s\r\n" % [ actual_color, actual_matrix, line.file ] ) end else unless line.vectors STDERR.puts( 'E: %s' % line ) end actual_color = line.color == 16 ? color : line.color actual_vectors = line.vectors.map { |v| ( matrix * Vector[ *v, 1 ] )[0..-2] } puts( "%d %d %s\r\n" % [ line.type, actual_color, vectors_to_s( actual_vectors ) ] ) end end end end # read file models = Hash.new first_model = nil cur_model = nil STDIN.each_line do |line| line.chomp! case line when NEW_MODEL_RE # STDERR.puts( '%s >>' % cur_model.file ) if cur_model # STDERR.puts( '<< %s' % $1 ) cur_model = Model.new( $1, [] ) models[ cur_model.file ] = cur_model first_model ||= cur_model when END_MODEL_RE nil when '' cur_model.lines << Empty.new when COMMENT_RE cur_model.lines << Comment.new( $1 ) when USAGE_RE col = $1 mat = $2 fil = $4 # STDERR.puts( 'use %s' % fi ) unless fi[/\.dat/i] cur_model.lines << Use.new( col, read_matrix( mat ), fil ) when OTHER_RE cur_model.lines << Other.new( $1, $2, read_vectors( $3 ) ) else STDERR.puts( 'Eh? ā€œ%sā€' % line ) end end #STDERR.puts( '%s >>' % cur_model.file ) if cur_model STDERR.puts( '# of models read: %d' % models.size ) # output first_model.pout( 16, Matrix.I( 4 ), models )