Powered By Blogger

22 November 2008

ruby sketchup export to *.x ( for directx)

exportx.rb
place in folder Plugins
C:\Program Files\Google\Google SketchUp 6\Plugins

# add item if menu is not already loaded
if( $directxExport_loaded != true ) then
UI.menu("PlugIns").add_item("Export DirectX...") { export_directx3 }
$directxExport_loaded = true
end

#Collect objects and explode group or components, apply transformation
def get_all_model_faces(entities, trans)
# get the array of entities
if entities.class == Sketchup::ComponentInstance
entity_list=entities.definition.entities
elsif entities.class == Sketchup::Group
entity_list=entities.entities
else
entity_list=entities
end
# for each element
for e in entity_list
# if the element is a Group or a Component
if (e.layer.visible? and (e.class == Sketchup::Group or e.class == Sketchup::ComponentInstance)) then
$groups +=1 if e.class == Sketchup::Group
$components += 1 if e.class == Sketchup::ComponentInstance
#check for material to set it to the children on next recusive call
if e.material != nil
$parent_mat.push(e.material)
else
$parent_mat.push($parent_mat.last)
end
# recurs call on the group or component
get_all_model_faces(e, trans*e.transformation)
$parent_mat.pop
end
# if the object is a simple Face
if( e.class == Sketchup::Face and e.layer.visible?) then
# check for material
if e.material == nil
mat=$parent_mat.last
else
mat = e.material
end
# add object to the global collection
$face_trans_collection.push([e,trans,mat])
#print e.to_s + "#" + trans.to_s + "\n"
$faces += 1
end
end
end

# Main entry point
def export_directx3()
# display ruby panel for messages
Sketchup.send_action "showRubyPanel:"
# call Save Dialog function
filename = get_filename
if filename == nil then # exit if cancel was choosen
return
end
print "Saving to : #{filename} \n"

# get the active sketchup model
model = Sketchup.active_model
# get a new writer for textures export
texturewriter = Sketchup.create_texture_writer

#global array that stores each individual text mesh
meshes = []
vertex_collection = []
normal_objects = []
normal_collection = []
normal_faces = []
texture_coords = []
face_collection = []
material_collection = []
material_face = []
# array to store material
all_materials = []
# add a default material when nothing special is specified for a face
material_collection += ["{ Default_Material }"]

# global push/pop array for children material propagation
$parent_mat = []
# global collection that stores a triplet [face, transformation, material]
$face_trans_collection = []
$faces = 0
$groups = 0
$components = 0

#get model entities
entities = model.entities

$parent_mat.push(nil)
# collect faces
get_all_model_faces(entities, Geom::Transformation.new)

print "#{$groups} group(s), #{$components} component(s), #{$faces} faces."

startindex = 0
# for all Faces
for ft in $face_trans_collection
entity = ft[0]
trans = ft[1]
mat = ft[2]
if(entity.typename == "Face") then
# Get a the MeshPolygon from the Face
#0 (Include PolygonMeshPoints), 1 (Include PolygonMeshUVQFront), 2 (Include PolygonMeshUVQBack), 4 (Include PolygonMeshNormals).
mesh = entity.mesh 1 4
# apply transformation when the object was in a group or in a component
mesh.transform! trans
# For all points
#print "mesh\n"
for p in (1..mesh.count_points)
# get the 3D point
pos = mesh.point_at(p).to_a
# get the normal at this point
norm = mesh.normal_at(p)
normal_objects +=[norm]
norm = norm.to_a
# default texture size
texsize = Geom::Point3d.new(1,1,1)

# if the material was obtained from the group or component
if mat!=nil and mat.texture!=nil and entity.material==nil then
# get the texture size
texsize = Geom::Point3d.new(mat.texture.width, mat.texture.height, 1)
end
# get the mesh texture coords (texture deformation: texture can only be streshed, rotated, translated (no parallel deformation)
uv = [mesh.uv_at(p,1).x/texsize.x, mesh.uv_at(p,1).y/texsize.y, mesh.uv_at(p,1).z/texsize.z]
# change to left hand counter clockwise
pos = counterclockwise(pos)
v = "#{"%.4f" %(pos[0])};#{"%.4f" %(pos[1])};#{"%.4f" %(pos[2])};"
vertex_collection += [v]
# change to left hand counter clockwise
norm = counterclockwise(norm)
n = "#{"%.4f" %(norm[0])};#{"%.4f" %(norm[1])};#{"%.4f" %(norm[2])};"
normal_collection += [n]
u = "#{"%.4f" %(uv[0]+1)},#{"%.4f" %(-uv[1])};"
texture_coords += [u]
end

# for each polygon
for poly in mesh.polygons
v1 = (poly[0]>=0?poly[0]:-poly[0])+startindex
v2 = (poly[1]>=0?poly[1]:-poly[1])+startindex
v3 = (poly[2]>=0?poly[2]:-poly[2])+startindex
f = "3;#{v3-1},#{v2-1},#{v1-1}"
face_collection += [f]

mat_index = 0
# get the material
material = mat
if material then
# add the material to the global list if this is a new one
# ! only export texture on front faces (back faces are ignored)
if !(all_materials.index(material)) then
all_materials += [material]
if material.texture then
# build a filename based on the targetfilename and the texture name
f = filename + File.basename(material.texture.filename)
# load the texture of the entity into the texture writer object
texturewriter.load entity, true
# serialize the texture to disk
texturewriter.write entity, true, f
end
m = material.name.gsub(/[^a-zA-Z0-9]/, "_")
material_collection += ["{ " + m + " }"]
end
# get the index for the future added material
mat_index = all_materials.index(material)+1
end
# add the index of the material in the list
material_face += [mat_index.to_s]
end
startindex = startindex + mesh.count_points
end
end

text = "xof 0303txt 0032
// SketchUp 6 -> DirectX (c)2008 edecadoudal, supports: faces, normals and textures
Material Default_Material{
1.0;1.0;1.0;1.0;;
3.2;
0.000000;0.000000;0.000000;;
0.000000;0.000000;0.000000;;
}
"
#model.materials.purge_unused

all_materials.each{mat
# replace '[' and ']' in name by a '_'
n = mat.name.gsub(/[^a-zA-Z0-9]/, "_")
mat_string = "Material " + n + "{ \n"
# faceColor
mat_string += (mat.color.red/255.0).to_s + ";" +(mat.color.green/255.0).to_s + ";" + (mat.color.blue/255.0).to_s + ";"
# Alpha
mat_string += mat.alpha.to_s + ";;\n"
#power
mat_string += "3.2;\n"
# specularColor ColorRGB
mat_string += "0.000000;0.000000;0.000000;;\n"
# emissiveColor ColorRGB
mat_string += "0.000000;0.000000;0.000000;;\n"
if mat.texture && mat.texture.filename != "" then
mat_string += " TextureFilename { "
mat_string += "\"" + File.basename(filename) + File.basename(mat.texture.filename) + "\";"
mat_string += " } \n"
end
mat_string += "} \n"
text += mat_string
}
text+= "Mesh {\n"
text+= " #{vertex_collection.length};\n"
stxt = vertex_collection.to_a.join(",\n ")
text+= " #{stxt};\n"
text+= " #{face_collection.length};\n"
stxt = face_collection.to_a.join(",\n ")
text+= " #{stxt};;\n"
text+= " MeshMaterialList {\n"
text+= " #{material_collection.length};\n"
text+= " #{material_face.length};\n"
stxt = material_face.to_a.join(",\n ")
text+= " #{stxt};\n"
stxt = material_collection.to_a.join("\n ")
text+= " #{stxt}\n"
text+= " }\n"
text+= " MeshTextureCoords {\n"
text+= " #{texture_coords.length};\n"
stxt = texture_coords.to_a.join("\n ")
text+= " #{stxt};\n"
text+= " }\n"
text+= " MeshNormals {\n"
text+= " #{normal_collection.length};\n "
stxt = normal_collection.to_a.join("\n")
text+= " #{stxt};\n"
text+= " #{face_collection.length};\n"
stxt = face_collection.to_a.join(";\n ")
text+= " #{stxt};;\n"

text+= " }\n"
text+= " }\n"

write_file(filename, text)
print "end.\n"
end

def get_filename
model = Sketchup.active_model
model_filename = File.basename(model.path)
if model_filename != ""
model_name = model_filename.split(".")[0]
model_name += ".x"
else
model_name = "Untitled.x"
end
my_str = UI.savepanel("Export as", "", model_name)
end

#convert a clockwise vector in a counterclockwise vector
def counterclockwise(v)
v2 = Array.new
v2 += [-v.to_a[1]]
v2 += [v.to_a[2]]
v2 += [v.to_a[0]]
my_a = v2
end

def write_file(filename, text)
fout = File.open(filename, "w")
fout.puts text
fout.close
end

No comments: