Help: Plug in bug
-
I'm not a programmer and I need some help fixing a ruby plug-in. The author wrote it largely as an educational exercise (it seemed to work as he now has a job with a cad company) and he is no longer available to deal with this problem. It's a simple export to game format plug-in with one flaw: it doesn't export the correct position of a manually moved texture when the poly displaying that texture is in a component. If the poly is not in a component, any adjustment to the textures position exports properly.
I'd would be very grateful if someone here was willing to take a look at the code and see if the problem jumps out / is easilly corrected.
WRT copyright: Any suggested fix will be returned to the author (on the chance he wants it). I'll edit my own copy for my own use.
###====================================================== # Copyright © 2006-2008. All rights reserved. # version 1.0 24th June 2006. # version 1.3 29/2/2008 - adjusted for polymaster ###====================================================== # THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. #----------------------------------------------------------------------------- require "3dmath.rb" ##################################################### # Single class instance class SFile attr_accessor ;name, ;fileName, ;newFolder, ;fh , ;specular, ;message # scan the model groups for geometry def scanModel1(startEnt,parentSeg,dlevel,trans,lay) showFaces=true # if component instance, set grp to be the definition grp=startEnt if(grp.kind_of? Sketchup;;ComponentInstance) then # matrix id id=parentSeg trans=Geom;;Transformation.new() if not trans trans = trans * grp.transformation # get component definition grp = grp.definition else # grp could be a group or a model # # @lastMatrixid is nil for first LOD, 0+ for later passes if @lastMatrixid then id=@lastMatrixid oMatrix=@matrices[id] @lastMatrixid+=1 else oMatrix=Matrix.new() oMatrix.polys=0 if(grp.kind_of? Sketchup;;Model) then oMatrix.name = "main" else oMatrix.name=grp.name.tr(" ","_") end oMatrix.name="default" if oMatrix.name.length==0 oMatrix.name = "x" + oMatrix.name if oMatrix.name =~ /^\d/ if parentSeg>=0 then # get the transform matrix oMatrix.setFromSU startEnt.transformation.to_a end # count faces id=@matrices.length @matrices.push oMatrix end # if group lod if id>0 then showFaces=(dlevel==0 or grp.lod==0 or grp.lod >= lay) end @distance_levels[dlevel].hierarchy.push parentSeg end # scan faces if showFaces then for ent in grp.entities if(ent.kind_of? Sketchup;;Face) then if dlevel==0 or ent.lod==0 or ent.lod >= lay then scanVerts ent,id,startEnt,dlevel,trans end end end end # recursive call to sub groups for ent in grp.entities # scan sub groups if(ent.kind_of? Sketchup;;Group) scanModel1 ent, id,dlevel,trans,lay # don't show instances if group is disabled elsif( ent.kind_of? Sketchup;;ComponentInstance and showFaces ) # ignore component if it'd LOD is not visible if dlevel==0 or ent.lod==0 or ent.lod >= lay then scanModel1 ent, id,dlevel,trans,lay end elsif( ent.kind_of? Sketchup;;ComponentDefinition ) scanModel1 ent, id,dlevel,trans,lay end end end # save the vertices for a face def scanVerts(o,id,ent,dlevel,trans) # o is a face # ent - original entity mf=o.material mb=o.back_material scaleu,scalev,shade1,shade2=nil,nil,nil,nil polys=0 # get the instance material if definition material is nil if not mf mf=ent.material if ent.kind_of? Sketchup;;ComponentInstance if mf and mf.texture then scaleu=mf.texture.width.inch scalev=mf.texture.height.inch end end mat,matb=nil,nil uvhelp=o.get_UVHelper(true, true, @tw) subobj1=@distance_levels[dlevel].sub_objects.at(0) subobj2=subobj1 mesh = o.mesh 7 p1,p2,p3 = 0 pr2,fNormal2,shade2,pstat2,vst2,lmc2,vset2,nx2=nil,nil,nil,nil,nil,nil,nil,nil pr1,fNormal1,shade1,pstat1,vst1,lmc1,vset1,nx1=nil,nil,nil,nil,nil,nil,nil,nil if mf or not mb fNormal1=findItem(o.normal,@normals) # use front face material mat = findTexture(mf) shade1=findShader(mf) lmc1=findLightCnf(shade1) vst1=findVState(mf,id,lmc1) # calc prim_state ps=SPState.new() ps.shader=shade1 ps.lightCfg=lmc1 ps.vState=vst1 ps.tex_idxs.push mat if mat # gloss if @light_model_cfgs.at(lmc1)==2 then img=@images.index("env_map.ace") # compare image properties ps.tex_idxs.push @textures.index(img) end # no material alpha is for solid/transparent # alpha of 99% is for alpha but no sub-object # 98% and lower will create a sub-object for alpha sorting if mf # set alphatest to 1 for transparent, 0 for solid or alpha if mf.texture stex = mf.texture.filename.upcase if stex.index(".TGA") then ps.alphatestmode=1 end end if mf.alpha < 1.0 ps.alphatestmode=0 ps.priority=mf.alpha*100 if ps.priority<99 subobj1=setSubObj(dlevel) end end end pstat1=findItem(ps,@prim_states) findItem shade1,subobj1.shaders findItem lmc1,subobj1.lightcfgs vset=SVtxset.new(vst1) vset1=findItem(vset,subobj1.vtx_sets) node= SGeomnode.new(id) nx1=findItem node,subobj1.geometry_nodes findItem pstat1,subobj1.geometry_nodes[nx1].pStates pr1=getPrim(subobj1,vset1,pstat1) end if mb fNormal2=findItem(o.normal.reverse,@normals) matb=findTexture(mb) shade2=findShader(mb) lmc2=findLightCnf(shade2) vst2=findVState(mb,id,lmc2) # calc prim_state ps=SPState.new() ps.shader=shade2 ps.lightCfg=lmc2 ps.vState=vst2 ps.tex_idxs.push matb if matb if @light_model_cfgs.at(lmc2)==2 then img=@images.index("env_map.ace") # compare image properties ps.tex_idxs.push @textures.index(img) end # set alphatest to 1 for transparent, 0 for solid or alpha if mb.texture stex = mb.texture.filename.upcase if stex.index(".TGA") then ps.alphatestmode=1 end end if mb.alpha < 1.0 ps.alphatestmode=0 ps.priority=mb.alpha*100 if ps.priority<99 subobj2=setSubObj(dlevel) end end pstat2=findItem(ps,@prim_states) findItem shade2,subobj2.shaders findItem lmc2,subobj2.lightcfgs vset=SVtxset.new(vst2) vset2=findItem(vset,subobj2.vtx_sets) node= SGeomnode.new(id) nx2=findItem node,subobj2.geometry_nodes findItem pstat2,subobj2.geometry_nodes[nx2].pStates pr2=getPrim(subobj2,vset2,pstat2) end 1.upto(mesh.count_polygons) do |j| p3,p2,p1 = mesh.polygon_at(j) p1 = p1.abs pt1=mesh.point_at p1 p2 = p2.abs pt2=mesh.point_at p2 p3 = p3.abs pt3=mesh.point_at p3 if trans pt1.transform! trans pt2.transform! trans pt3.transform! trans end # make sure we have a triangle if not pt3.on_line? [pt1,pt2] if mf or not mb @bb.add pt1 @bb.add pt2 @bb.add pt3 if mat uv1=uvhelp.get_front_UVQ pt1 uv1.x/=scaleu if scaleu uv1.y/=scalev if scalev uv2=uvhelp.get_front_UVQ pt2 uv2.x/=scaleu if scaleu uv2.y/=scalev if scalev uv3=uvhelp.get_front_UVQ pt3 uv3.x/=scaleu if scaleu uv3.y/=scalev if scalev else uv1,uv2,uv3=nil,nil,nil end pn=mesh.normal_at(p1) pn.transform! trans if trans pr1.vert_idxs.push storeVertex(subobj1,pt1,pn,uv1,vset1) pn=mesh.normal_at(p2) pn.transform! trans if trans pr1.vert_idxs.push storeVertex(subobj1,pt2,pn,uv2,vset1) pn=mesh.normal_at(p3) pn.transform! trans if trans pr1.vert_idxs.push storeVertex(subobj1,pt3,pn,uv3,vset1) subobj1.faceNormals +=1 polys+=1 pr1.normal_idxs.push fNormal1 subobj1.geometry_nodes[nx1].count+=1 #print uv1.to_s + "\n" + uv2.to_s + "\n" + uv3.to_s + "\n" end if mb then if matb uv1=uvhelp.get_back_UVQ pt1 uv2=uvhelp.get_back_UVQ pt2 uv3=uvhelp.get_back_UVQ pt3 else uv1,uv2,uv3=nil,nil,nil end # adjust order if reflected odd number of times if trans if trans.to_a[0]*trans.to_a[5]*trans.to_a[10]<0 p3,p1=p1,p3 uv3,uv1=uv1,uv3 pt3,pt1=pt1,pt3 end end # reverse order pn=mesh.normal_at(p3).reverse pn.transform! trans if trans pr2.vert_idxs.push storeVertex(subobj2,pt3,pn,uv3,vset2) pn=mesh.normal_at(p2).reverse pn.transform! trans if trans pr2.vert_idxs.push storeVertex(subobj2,pt2,pn,uv2,vset2) pn=mesh.normal_at(p1).reverse pn.transform! trans if trans pr2.vert_idxs.push storeVertex(subobj2,pt1,pn,uv1,vset2) #print uv1.to_s + "\n" + uv2.to_s + "\n" + uv3.to_s + "\n" subobj2.faceNormals +=1 polys+=1 pr2.normal_idxs.push fNormal2 subobj2.geometry_nodes[nx2].count+=1 end end end @matrices[id].polys+=polys if dlevel==0 end def storeVertex(so,p,n,u,vset) ip=findItem(p,@points) ix=findItem(n,@normals) iu=findItem(u,@uv_points) vert=SVertex.new vert.pointIdx=ip vert.normalIdx=ix vert.vertex_uvs.push iu if u findItem(vert,so.vtx_sets[vset].vertices) end def setSubObj(dl) if @distance_levels[dl].sub_objects.length==1 then so=SSObject.new() @distance_levels[dl].sub_objects.push so so.flags="00000500" so.vol=0 return so else return @distance_levels[dl].sub_objects[1] end end def getPrim(so,vs,ps) prim=SPrimitive.new prim.primstate=ps x=so.vtx_sets[vs] # 2 primitive entries prind=findItem prim,x.primitives if prind==(x.primitives.length-1) then x.primitives.push SPrimitive.new() end prind+=1 pr=x.primitives[prind] while pr.normal_idxs.length>2700 and not pr.primstate do # at very end - add new one if prind==(x.primitives.length-1) then x.primitives.push SPrimitive.new() end prind+=1 pr=x.primitives[prind] end if pr.primstate then x.primitives[prind]=[SPrimitive.new(),pr] x.primitives.flatten! end return x.primitives[prind] end def findTexture(m) if m and m.texture img=findImage(m.texture) end if not(img) return nil end # compare image properties 0.upto(@textures.length-1) do |e| if @textures.at(e).img==img return e end end t=STex.new(img) n=m.name.upcase.index("/BIAS") t.mipbias=m.name[n+5..n+7].to_i if n @textures.push t return @textures.length-1 end # used for points, normals, UV points and other objects that support == def findItem(v,array) if not v return nil end return array.addSearch(v) end # find vstate from material def findVState(m,id,cnf) vs=SVState.new(id) vs.lightCfg=cnf stex="" if m if m.name.upcase.index("HISHINE") vs.lightMat=-6 @specular=true elsif m.name.upcase.index("LOSHINE") vs.lightMat=-7 @specular=true elsif m.name.upcase.index("AMBIENT") vs.lightMat=-9 elsif m.name.upcase.index("DARKSHADE") vs.lightMat=-12 elsif m.name.upcase.index("HALFBRIGHT") vs.lightMat=-11 end if m.texture then stex=m.texture.filename end end #'''''' color of material if m then if stex.length==0 col = m.color end else col = Sketchup.active_model.rendering_options["FaceFrontColor"] end # new colour and light material if col then if @colours.length==0 # add black & white findItem(Sketchup;;Color.new(0,0,0),@colours) findItem(Sketchup;;Color.new(255,255,255),@colours) end c1=findItem(col,@colours) lm=c1.to_s + " " + c1.to_s + " 1 0 0" vs.lightMat = findItem(lm,@light_materials) end return findItem(vs,@vtx_states) end # find shader from material def findShader(m) if m and m.texture stex = m.texture.filename.upcase s="Tex" s << "Diff" if not m.name.upcase.index("BRIGHT") if stex.index(".TGA") then s="BlendA" + s end if m.name.upcase.index("GLOSS") then s="GlossMap" img=@images.addSearch("env_map.ace") # compare image properties 0.upto(@textures.length-1) do |e| if @textures.at(e).img==img return @shader_names.addSearch(s) end end t=STex.new(img) t.mipbias=0 @textures.push t end else s="Diffuse" end return @shader_names.addSearch(s) end # given a shader index, find the light config def findLightCnf(s) cn=1 cn=2 if @shader_names.at(s)=="GlossMap" cn=3 if @shader_names.at(s).index("Bumpmap") cn=4 if @shader_names.at(s)=="Diffuse" return @light_model_cfgs.addSearch(cn) end # find image ID def findImage(t) i=t.filename.rindex("\\") i=-1 if not i s=t.filename[i+1..t.filename.rindex(".")].upcase << "ACE" return @images.addSearch(s) end #''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' # perform the actual file save def saveS() # unicode file @fh.write "\377\376" $\="\015\012" @fh.uprintln "SIMISA@@@@@@@@@@JINX0s1t______" @fh.uprintln "" @fh.uprintln "shape (" shape_header volumes shader_names texture_filter_names points uv_points normals sort_vectors colours matrices images textures light_materials light_model_cfgs vtx_states prim_states lod_controls animations if @anim_nodes.length>0 @fh.uprint ")" @fh.close end def shape_header @fh.uprintln "\tshape_header sketchup20 ( 00000000 00000000 )" end def vector(v) @fh.uprint "vector ( " @fh.uprint v.x.to_m.fix.to_s + " " @fh.uprint v.z.to_m.fix.to_s + " " @fh.uprint v.y.to_m.fix @fh.uprintln " )" end def normal(v) @fh.uprint "vector ( " @fh.uprint v.x.fix.to_s + " " @fh.uprint v.z.fix.to_s + " " @fh.uprint v.y.fix @fh.uprintln " )" end def vol_sphere(v,r) $\=nil @fh.uprint "\t\tvol_sphere ( \015\012\t\t\t" vector v $\="\015\012" @fh.uprintln " " + r.to_m.fix.to_s @fh.uprintln "\t\t)" end def volumes @fh.uprint "\tvolumes ( " @fh.uprintln @volumes vol_sphere @bb.center, @bb.diagonal/2.0 @fh.uprintln "\t)" end def named_shader(s) @fh.uprintln "\t\tnamed_shader ( " + s + " )" end def shader_names @fh.uprint "\tshader_names ( " @fh.uprintln @shader_names.length @shader_names.each { |s| named_shader s } @fh.uprintln "\t)" end def texture_filter_names @fh.uprint "\ttexture_filter_names ( " @fh.uprintln 1 @fh.uprintln "\t\tnamed_filter_mode ( MipLinear )" @fh.uprintln "\t)" end def point(v) @fh.uprint "\t\tpoint ( " + v.x.to_m.fix.to_s + " " + v.z.to_m.fix.to_s + " " + v.y.to_m.fix.to_s @fh.uprintln " )" end def points @fh.uprint "\tpoints ( " @fh.uprintln @points.length @points.each { |e| point e } @fh.uprintln "\t)" end def uv_point(v) @fh.uprintln "\t\tuv_point ( " + v.x.fix.to_s + " " + (-v.y.fix).to_s + " )" end def uv_points @fh.uprint "\tuv_points ( " @fh.uprintln @uv_points.length @uv_points.each { |e| uv_point e } @fh.uprintln "\t)" end def normals @fh.uprint "\tnormals ( " @fh.uprintln @normals.length @normals.each { |e| @fh.uprint "\t\t"; normal e } @fh.uprintln "\t)" end def sort_vectors @fh.uprintln "\tsort_vectors ( 0 )" end def colour(v) @fh.uprintln "\t\tcolour ( " + (v.alpha/255.0).to_s + " " + (v.red/255.0).to_s + " " + (v.green/255.0).to_s + " " + (v.blue/255.0).to_s + " )" end def colours @fh.uprint "\tcolours ( " @fh.uprintln @colours.length @colours.each { |e| colour e } @fh.uprintln "\t)" end def matrix(v) @fh.uprint "\t\tmatrix " @fh.uprint v.name @fh.uprint " ( " @fh.uprint v.m[0].fix.to_s + " " + v.m[1].fix.to_s + " " + v.m[2].fix.to_s + " " @fh.uprint v.m[4].fix.to_s + " " + v.m[5].fix.to_s + " " + v.m[6].fix.to_s + " " @fh.uprint v.m[8].fix.to_s + " " + v.m[9].fix.to_s + " " + v.m[10].fix.to_s + " " @fh.uprintln v.m[12].to_m.fix.to_s + " " + v.m[13].to_m.fix.to_s + " " + v.m[14].to_m.fix.to_s + " )" @message << v.name + " " + v.polys.to_s + " Polygons " + (v.polys>2700 ? "<< Primitives split\n" ; "\n") end def matrices @message="Groups ;\n" @fh.uprint "\tmatrices ( " @fh.uprintln @matrices.length @matrices.each { |e| matrix e } @fh.uprintln "\t)" end def image(v) @fh.uprint "\t\timage ( " @fh.uprint v @fh.uprintln " )" end def images @fh.uprint "\timages ( " @fh.uprintln @images.length @images.each { |e| image e } @fh.uprintln "\t)" end def texture(v) @fh.uprint "\t\ttexture ( " @fh.uprint v.to_s @fh.uprintln " ff000000 )" end def textures @fh.uprint "\ttextures ( " @fh.uprintln @textures.length @textures.each { |e| texture e } @fh.uprintln "\t)" end def light_material(v) @fh.uprint "\t\tlight_material ( 00000000 " @fh.uprint v @fh.uprintln " )" end def light_materials @fh.uprint "\tlight_materials ( " @fh.uprintln @light_materials.length @light_materials.each { |e| light_material e } @fh.uprintln "\t)" end def light_model_cfg(v) case v when 1 # single stage @fh.uprintln "\t\tlight_model_cfg ( 00000000" @fh.uprintln "\t\t\tuv_ops ( 1" @fh.uprintln "\t\t\t\tuv_op_copy ( 1 0 )" @fh.uprintln "\t\t\t)" @fh.uprintln "\t\t)" when 2 # GlossMap @fh.uprintln "\t\tlight_model_cfg ( 00000000" @fh.uprintln "\t\t\tuv_ops ( 2" @fh.uprintln "\t\t\t\tuv_op_copy ( 1 0 )" @fh.uprintln "\t\t\t\tuv_op_reflectmapfull ( 1 )" @fh.uprintln "\t\t\t)" @fh.uprintln "\t\t)" when 3 # 3 stage bump maps @fh.uprintln "\t\tlight_model_cfg ( 00000000" @fh.uprintln "\t\t\tuv_ops ( 3" @fh.uprintln "\t\t\t\tuv_op_copy ( 1 0 )" @fh.uprintln "\t\t\t\tuv_op_copy ( 1 0 )" @fh.uprintln "\t\t\t\tuv_op_reflectmapfull ( 1 )" @fh.uprintln "\t\t\t)" @fh.uprintln "\t\t)" when 4 # no texture or uv @fh.uprintln "\t\tlight_model_cfg ( 00000000" @fh.uprintln "\t\t\tuv_ops ( 0 )" @fh.uprintln "\t\t)" end end def light_model_cfgs @fh.uprint "\tlight_model_cfgs ( " @fh.uprintln @light_model_cfgs.length @light_model_cfgs.each { |e| light_model_cfg e } @fh.uprintln "\t)" end def vtx_state(v) @fh.uprint "\t\tvtx_state ( 00000000 " @fh.uprint v.to_s @fh.uprintln " 00000002 )" end def vtx_states @fh.uprint "\tvtx_states ( " @fh.uprintln @vtx_states.length @vtx_states.each { |e| vtx_state e } @fh.uprintln "\t)" end def prim_state(v) @fh.uprint "\t\tprim_state " + @matrices[@vtx_states[v.vState].matrix].name + "_Prim" + v.sequence.to_s + " ( 00000000 " @fh.uprint v.to_s @fh.uprintln " 1\n\t\t)" end def prim_states @fh.uprint "\tprim_states ( " @fh.uprintln @prim_states.length seq=0 # sort the states in order, and sort the sequence 100.downto(96) do |pri| @prim_states.each do |e| if e.priority==pri e.sequence=seq seq+=1 prim_state e end end end @prim_states.each do |e| if e.priority<97 prim_state e e.sequence=seq seq+=1 end end @fh.uprintln "\t)" end def geometry_node(v) @fh.uprintln "\t\t\t\t\t\t\t\t\t\tgeometry_node ( 1 0 0 0 0" @fh.uprintln "\t\t\t\t\t\t\t\t\t\t\tcullable_prims ( " + v.pStates.length.to_s + " " + v.count.to_s + " " + (v.count*3).to_s + " )" @fh.uprintln "\t\t\t\t\t\t\t\t\t\t)" end def vertex(v) v.uprint @fh end def vertex_set(v,cnt) @fh.uprintln "\t\t\t\t\t\t\t\tvertex_set ( " + v.vtx_state.to_s + " " + cnt.to_s + " " + v.vertices.length.to_s + " )" end def primitive(v,cnt) v.offset=cnt if v.primstate then @fh.uprintln "\t\t\t\t\t\t\t\tprim_state_idx ( " + @prim_states[v.primstate].sequence.to_s + " )" else v.uprint @fh end end def sub_object(v) @fh.uprintln "\t\t\t\t\t\tsub_object ( " @fh.uprintln "\t\t\t\t\t\t\tsub_object_header ( " + v.flags + " " + v.sortVector.to_s + " " + v.vol.to_s + " 000001d2 " + v.destFlag @fh.uprintln "\t\t\t\t\t\t\t\tgeometry_info ( " + v.faceNormals.to_s + " " + v.vtx_sets.length.to_s + " 0 " + (v.faceNormals*3).to_s + " 0 0 " + (v.primitives/2).to_s + " 0 0 0" @fh.uprint "\t\t\t\t\t\t\t\t\tgeometry_nodes ( " @fh.uprintln v.geometry_nodes.length v.geometry_nodes.each { |e| geometry_node e } @fh.uprintln "\t\t\t\t\t\t\t\t\t)" # geometry_node_map ( 1 0 ) @fh.uprint "\t\t\t\t\t\t\t\t\tgeometry_node_map ( " @fh.uprint @matrices.length 0.upto(@matrices.length-1) do |e| @fh.uprint " " ind=v.geometry_nodes.index(SGeomnode.new(e)) @fh.uprint ind ? ind ; -1 end @fh.uprintln " )" @fh.uprintln "\t\t\t\t\t\t\t\t)" # subobject_shaders ( 1 0 ) @fh.uprint "\t\t\t\t\t\t\t\tsubobject_shaders ( " @fh.uprint v.shaders.length v.shaders.each { |e| @fh.uprint " "; @fh.uprint e } @fh.uprintln " )" # subobject_light_cfgs ( 1 0 ) 0 @fh.uprint "\t\t\t\t\t\t\t\tsubobject_light_cfgs ( " @fh.uprint v.lightcfgs.length v.lightcfgs.each { |e| @fh.uprint " "; @fh.uprint e } @fh.uprintln " ) " + v.id.to_s @fh.uprintln "\t\t\t\t\t\t\t)" @fh.uprint "\t\t\t\t\t\t\tvertices ( " @fh.uprintln v.vertices v.vtx_sets.each { |x| x.vertices.each { |e| vertex e } } @fh.uprintln "\t\t\t\t\t\t\t)" @fh.uprint "\t\t\t\t\t\t\tvertex_sets ( " @lastv=0 @fh.uprintln v.vtx_sets.length count=0 v.vtx_sets.each { |e| vertex_set e,count ; count+=e.vertices.length } @fh.uprintln "\t\t\t\t\t\t\t)" @fh.uprint "\t\t\t\t\t\t\tprimitives ( " @fh.uprintln v.primitives count=0 v.vtx_sets.each { |x| x.primitives.each { |e| primitive e,count} ; count+=x.vertices.length } @fh.uprintln "\t\t\t\t\t\t\t)" # end of sub_object @fh.uprintln "\t\t\t\t\t\t)" end def distance_level(v) @fh.uprintln "\t\t\t\tdistance_level ( " @fh.uprintln "\t\t\t\t\tdistance_level_header (" @fh.uprint "\t\t\t\t\t\tdlevel_selection ( " @fh.uprint v.distance @fh.uprintln " )" @fh.uprint "\t\t\t\t\t\thierarchy ( " @fh.uprint v.hierarchy.length v.hierarchy.each { |e| @fh.uprint " "; @fh.uprint e } @fh.uprintln " )" @fh.uprintln "\t\t\t\t\t)" @fh.uprint "\t\t\t\t\tsub_objects ( " @fh.uprintln v.sub_objects.length v.sub_objects.each { |e| sub_object e } @fh.uprintln "\t\t\t\t\t)" @fh.uprintln "\t\t\t\t)" end def lod_control @fh.uprintln "\t\tlod_control (" @fh.uprintln "\t\t\tdistance_levels_header ( 0 )" @fh.uprint "\t\t\tdistance_levels ( " @fh.uprintln @distance_levels.length @distance_levels.each { |e| distance_level e } @fh.uprintln "\t\t\t)" @fh.uprintln "\t\t)" end def lod_controls @fh.uprintln "\tlod_controls ( 1" lod_control @fh.uprintln "\t)" end def anim_node(v) @fh.uprint "\t\t\t\tanim_node " @fh.uprint v.name @fh.uprintln " (" # still to do @fh.uprintln "\t\t\t\t)" end def animations @fh.uprintln "\tanimations ( 1" @fh.uprintln "\t\tanimation ( " + @keys.to_s + " " + @fps.to_s @fh.uprint "\t\t\tanim_nodes ( " @fh.uprint @anim_nodes.length @anim_nodes.each { |e| anim_node e } @fh.uprintln "\t\t\t)" @fh.uprintln "\t\t)" @fh.uprintln "\t)" end # on creation of the TMXfile object def initialize(model,file) # set a few properties @model=model @name=model.title @fileName=file @shader_names=[] @points=[] @normals=[] @uv_points=[] @matrices=[] @colours=[] @images=[] @textures=[] @light_materials=[] @light_model_cfgs=[] @vtx_states=[] @prim_states=[] @distance_levels=[] @anim_nodes=[] @keys=8 @fps=30 @specular=false @fh = File.new(file,"wb") if @fh then @tw = Sketchup.create_texture_writer # get model bound box @bb=model.bounds @volumes=1 # add a single distance level @distance_levels.push SDLevel.new() # add first sub-object @distance_levels[0].sub_objects.push SSObject.new() l=@model.lods[0] @distance_levels[0].distance=l print "\nLOD #{l} 0" # scan the model geometry @lastMatrixid=nil scanModel1(model,-1,0,nil,l) # more layers? 1.upto(@model.lods.length-1) do |lay| @lastMatrixid=0 l=@model.lods[lay] # add a single distance level @distance_levels.push SDLevel.new() dl=@distance_levels.length-1 # add first sub-object @distance_levels[dl].sub_objects.push SSObject.new() # adjust previous DL @distance_levels[dl].distance=l print "\nLOD #{l} #{dl}" scanModel1(model,-1,dl,nil,l.to_i) end # sum up vertices and primitives @distance_levels.each do |dl| dl.sub_objects.each do |so| so.vtx_sets.each do |v| so.vertices+=v.vertices.length so.primitives+=v.primitives.length end if @specular if so.flags=="00000400" so.flags="00000000" else so.flags="00000100" end end end end end # model processing finished - time to save the S file end def saveSD() @fh = File.new(@fileName + "D","wb") # unicode file @fh.write "\377\376" $\="\015\012" @fh.uprintln "SIMISA@@@@@@@@@@JINX0s1t______" @fh.uprintln "" @fh.uprint "shape ( " s=@fileName i=s.rindex("\\") s=s[(i+1)..s.length] if i @fh.uprintln s @fh.uprintln " ESD_Detail_Level (0)" @fh.uprintln " ESD_Software_DLev (0)" @fh.uprintln " ESD_Alternative_Texture (0)" @fh.uprintln " ESD_Bounding_Box ( " + @bb.min.x.fix.to_m.to_s + " " + @bb.min.z.fix.to_m.to_s + " " + @bb.min.y.fix.to_m.to_s + " " + @bb.max.x.fix.to_m.to_s + " " + @bb.max.z.fix.to_m.to_s + " " + @bb.max.y.fix.to_m.to_s + " )" @fh.uprintln ")" @fh.close() end end #################################################################### # add unicode write to File class class File def uprint(s) # print unicode version of ascii s.to_s.each_byte { |c| write [c,0].pack("cc") } if s end def uprintln(s) uprint s uprint $\ if $\ end end #################################################################### # used by textures array class STex attr_accessor ;img,;filter,;mipbias def initialize(id) @mipbias = -3 @filter=0 @img=id end def to_s @img.to_s + " " + @filter.to_s + " " + @mipbias.to_s end end #################################################################### # used by vtx_states class SVState attr_accessor ;matrix,;lightMat,;lightCfg def initialize(id) @lightCfg=0 @lightMat=-5 @matrix=id end def ==(vs) return (@lightMat==vs.lightMat and @lightCfg == vs.lightCfg and @matrix==vs.matrix) end def to_s @matrix.to_s + " " + @lightMat.to_s + " " + @lightCfg.to_s end end #################################################################### # prim state class SPState attr_accessor ;shader, ;tex_idxs,;zBias,;vState,;alphatestmode,;lightCfg,;priority,;sequence def initialize @tex_idxs=[] @zBias=0 @priority=100 @alphatestmode=0 end def ==(o) if @tex_idxs.length>0 return false if @tex_idxs.length!=o.tex_idxs.length return false if @tex_idxs[0]!=o.tex_idxs[0] end return (@shader==o.shader and @vState==o.vState and @alphatestmode==o.alphatestmode and @lightCfg==o.lightCfg) end def to_s s=@shader.to_s + "\n\t\t\ttex_idxs ( " + @tex_idxs.length.to_s tex_idxs.each { |e| s << " " << e.to_s } s << " ) " + @zBias.to_s + " " + @vState.to_s + " " + @alphatestmode.to_s + " " + @lightCfg.to_s end end #################################################################### class SDLevel attr_accessor ;distance, ;hierarchy,;sub_objects def initialize @hierarchy=[] @distance=2000 @sub_objects=[] end end #################################################################### class SSObject attr_accessor ;vertices,;primitives,;vtx_sets,;sortVector,;vol,;destFlag,;flags,;faceNormals,;txLightCmds,;trilistIdxs,;trilists,;geometry_nodes,;lightcfgs,;shaders,;id def initialize @vertices=0 @primitives=0 @vtx_sets=[] @sortVector=-1 @vol=-1 @destFlag="000001c4" @flags="00000400" @geometry_nodes=[] @lightcfgs=[] @shaders=[] @id=0 @faceNormals=0 @txLightCmds=0 @trilistIdxs=0 @trilists=0 end end #################################################################### class SVertex attr_accessor ;pointIdx, ;normalIdx ,;colour1,;colour2, ;vertex_uvs def initialize @vertex_uvs=[] @colour1="ffffffff" @colour2="ff000000" end def ==(o) if @vertex_uvs.length>0 return false if @vertex_uvs.length!=o.vertex_uvs.length return false if @vertex_uvs[0]!=o.vertex_uvs[0] end return (@pointIdx==o.pointIdx and @normalIdx==o.normalIdx) end def uprint(fh) fh.uprint "\t\t\t\t\t\t\t\tvertex ( 00000000 " + @pointIdx.to_s + " " + @normalIdx.to_s + " " + @colour1 + " " + @colour2 + "\n\t\t\t\t\t\t\t\t\t vertex_uvs ( " + @vertex_uvs.length.to_s @vertex_uvs.each { |e| fh.uprint " " + e.to_s } fh.uprintln " )\n\t\t\t\t\t\t\t\t)" end end class SVtxset attr_accessor ;vtx_state, ;vertices, ;primitives def initialize(vs) @vtx_state=vs @vertices=[] @primitives=[] end def ==(o) return @vtx_state==o.vtx_state end end #################################################################### class SGeomnode attr_accessor ;pStates, ;count,;matrix def initialize(id) @pStates=[] @count=0 @matrix=id end def ==(o) return (@matrix == o.matrix) end end #################################################################### class SPrimitive attr_accessor ;vert_idxs, ;normal_idxs, ;primstate, ;offset def initialize @vert_idxs=[] @normal_idxs=[] end def ==(o) return @primstate==o.primstate end def uprint(fh) fh.uprintln "\t\t\t\t\t\t\t\tindexed_trilist (" fh.uprint "\t\t\t\t\t\t\t\t\tvertex_idxs ( " + @vert_idxs.length.to_s width=0 @vert_idxs.each do |e| fh.uprint " " + (e+@offset).to_s if width>1000 then fh.uprint "\015\012\t\t\t\t\t\t\t\t\t" width=0 else width+=e.to_s.length end end fh.uprintln " )" fh.uprint "\t\t\t\t\t\t\t\t\tnormal_idxs ( " + @normal_idxs.length.to_s width=0 @normal_idxs.each do |e| fh.uprint " " + e.to_s + " 3" if width>1000 then fh.uprint "\015\012\t\t\t\t\t\t\t\t\t" width=0 else width+=e.to_s.length end end fh.uprintln " )" fh.uprint "\t\t\t\t\t\t\t\t\tflags ( " + @normal_idxs.length.to_s width=0 @normal_idxs.each do |e| fh.uprint " 00000000" if width>1000 then fh.uprint "\015\012\t\t\t\t\t\t\t\t\t" width=0 else width+=9 end end fh.uprintln " )" fh.uprintln "\t\t\t\t\t\t\t\t)" end end #################################################################### # extend 3dmath class matrix class Matrix # add name attribute attr_accessor ;name,;polys # copy array to matrix (from SU transromation.to_a def setFromSU(mIn) @m=mIn # swap 2nd/3rd rows and cols @m[2],@m[1]=@m[1],@m[2] @m[10],@m[5]=@m[5],@m[10] @m[14],@m[13]=@m[13],@m[14] @m[4],@m[8]=@m[8],@m[4] @m[6],@m[9]=@m[9],@m[6] @m[7],@m[11]=@m[11],@m[7] end end #################################################################### class Numeric # use 6 decimal places only def fix (self*1000000.0).to_i.to_f/1000000.0 end end #################################################################### # return index, but add if not found in array class Array def addSearch(s) e=index(s) if e then return e else push s return length-1 end end end
Advertisement