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