blender/release/scripts/wings_export.py
Willian Padovani Germano ad579abf00 Scripts:
Final (?) updates for 2.40 :) :

- Bob Holcomb sent a better version of his 3ds importer
- Added doc info to bvh2arm: links to doc and mocap tute from author
Jean-Baptiste Perin
- Alessandro Pirovano improved the Lightwave importer.
- Mikael Lagre updated the collada scripts (fixed a bug with camera
lens value)
- Adam Saltsman improved the wings importer (ongoing work with
his pal Toastie).
- Anthony D'Agostino GPL'd his scripts (used Blender's BAL
license previously)

Thanks to all script authors for their work, interest and kindness.
Again, Tom (LetterRip) has played an important part in this, thanks and
welcome :).
2005-12-19 17:21:55 +00:00

376 lines
15 KiB
Python

#!BPY
"""
Name: 'Wings3D (.wings)...'
Blender: 232
Group: 'Export'
Tooltip: 'Export selected mesh to Wings3D File Format (.wings)'
"""
__author__ = "Anthony D'Agostino (Scorpius)"
__url__ = ("blender", "elysiun",
"Author's homepage, http://www.redrival.com/scorpius",
"Wings 3D, http://www.wings3d.com")
__version__ = "Part of IOSuite 0.5"
__bpydoc__ = """\
This script exports meshes to Wings3D file format.
Wings3D is an open source polygon modeler written in Erlang, a
language similar to Lisp. The .wings file format is a binary
representation of erlang terms (lists, tuples, atoms, etc.) and is
compressed with zlib.
Usage:<br>
Select meshes to be exported and run this script from "File->Export" menu.
Supported:<br>
1. Exports meshes only. Hint: use ALT-C to convert non-mesh objects,
and CTRL-ALT-A if you have "dupliverts" objects.<br>
2. Exports Vertex Colors & Radiosity Solutions.
Missing:<br>
Materials and UV Coordinates info will be ignored.
Known issues:<br>
Exports only well-behaved and topologically correct meshes (i.e,
closed meshes, manifolds, meshes imported from wings, etc). The mesh
cannot have duplicate vertices, missing faces (holes), open edges, etc.<br>
PowerUser Hint: In editmode, if CTRL-ALT-SHIFT-M results in a selection,
then your mesh is not a manifold and most likely will not export.
Notes:<br>
Last tested with Wings 3D 0.98.25 & Blender 2.35a.
"""
# $Id$
#
# +---------------------------------------------------------+
# | Copyright (c) 2002 Anthony D'Agostino |
# | http://www.redrival.com/scorpius |
# | scorpius@netzero.com |
# | Feb 19, 2002 |
# | Read and write Wings3D File Format (*.wings) |
# +---------------------------------------------------------+
# ***** BEGIN GPL LICENSE BLOCK *****
#
# 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 2
# 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, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
import Blender, meshtools
import struct, time, sys, os, zlib, cStringIO
# ===============================================
# === Write The 'Header' Common To All Chunks ===
# ===============================================
def write_chunkheader(data, version, tag, name):
data.write(struct.pack(">BB", version, tag))
data.write(struct.pack(">BH", 0x64, len(name)))
data.write(name)
# ===================
# === Write Faces ===
# ===================
def write_faces(data, mesh):
numfaces = len(mesh.faces)
data.write(struct.pack(">BL", 0x6C, numfaces))
#for i in range(numfaces):
# if not i%100 and meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/numfaces, "Writing Faces")
# data.write("\x6A")
data.write("\x6A" * numfaces) # same, but faster than the above loop
data.write("\x6A")
# ===================
# === Write Verts ===
# ===================
def write_verts(data, mesh):
numverts = len(mesh.verts)
data.write(struct.pack(">BL", 0x6C, numverts))
for i in range(numverts):
if not i%100 and meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/numverts, "Writing Verts")
data.write(struct.pack(">BLBL", 0x6C, 1, 0x6D, 24))
#data.write("\x6c\x00\x00\x00\x01\x6D\x00\x00\x00\x30")
x, y, z = mesh.verts[i].co
data.write(struct.pack(">ddd", x, z, -y))
data.write("\x6A")
data.write("\x6A")
# ===================
# === Write Edges ===
# ===================
def write_edges(data, mesh, edge_table):
numedges = len(edge_table)
data.write(struct.pack(">BL", 0x6C, numedges))
keys = edge_table.keys()
keys.sort()
for key in keys:
i = edge_table[key][6]
if not i%100 and meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/numedges, "Writing Edges")
if meshtools.has_vertex_colors(mesh):
r1, g1, b1 = edge_table[key][7]
r2, g2, b2 = edge_table[key][8]
data.write("\x6C\x00\x00\x00\x02")
data.write("\x68\x02\x64\x00\x05color")
data.write("\x6D\x00\x00\x00\x30")
data.write(struct.pack(">dddddd", r1, g1, b1, r2, g2, b2))
#print "%f %f %f - %f %f %f" % (r1, g1, b1, r2, g2, b2)
else:
data.write("\x6C\x00\x00\x00\x01") # BL
#$write_chunkheader(data, 0x68, 0x09, "edge")
data.write("\x68\x09\x64\x00\x04edge") # faster
# Sv Ev (Reversed)
data.write(struct.pack(">BLBL", 0x62, key[1], 0x62, key[0]))
# Lf Rf LP LS RP RS
for i in range(6):
if edge_table[key][i] < 256:
data.write(struct.pack(">BB", 0x61, edge_table[key][i]))
else:
data.write(struct.pack(">BL", 0x62, edge_table[key][i]))
data.write("\x6A")
data.write("\x6A")
# ===============================
# === Write The Material Mode ===
# ===============================
def write_mode(data, mesh):
data.write("\x6A")
data.write(struct.pack(">BL", 0x6C, 1))
write_chunkheader(data, 0x68, 0x02, "mode")
if meshtools.has_vertex_colors(mesh):
data.write(struct.pack(">BH6s", 0x64, 6, "vertex"))
else:
data.write(struct.pack(">BH8s", 0x64, 8, "material"))
data.write("\x6A")
# ======================
# === Write Material ===
# ======================
def write_material(data, mesh):
data.write("\x6A")
data.write(struct.pack(">BL", 0x6C, 1))
write_chunkheader(data, 0x68, 0x02, "my default")
data.write(struct.pack(">BL", 0x6C, 2))
write_chunkheader(data, 0x68, 0x02, "maps")
data.write("\x6A")
write_chunkheader(data, 0x68, 0x02, "opengl")
# === The Material Components ===
data.write(struct.pack(">BL", 0x6C, 5))
write_chunkheader(data, 0x68, 0x02, "diffuse")
data.write("\x68\x04")
data.write("\x63"+"1.00000000000000000000"+"e+000"+"\x00"*4)
data.write("\x63"+"1.00000000000000000000"+"e+000"+"\x00"*4)
data.write("\x63"+"1.00000000000000000000"+"e+000"+"\x00"*4)
data.write("\x63"+"1.00000000000000000000"+"e+000"+"\x00"*4)
write_chunkheader(data, 0x68, 0x02, "ambient")
data.write("\x68\x04")
data.write("\x63"+"1.00000000000000000000"+"e+000"+"\x00"*4)
data.write("\x63"+"1.00000000000000000000"+"e+000"+"\x00"*4)
data.write("\x63"+"1.00000000000000000000"+"e+000"+"\x00"*4)
data.write("\x63"+"1.00000000000000000000"+"e+000"+"\x00"*4)
write_chunkheader(data, 0x68, 0x02, "specular")
data.write("\x68\x04")
data.write("\x63"+"1.00000000000000000000"+"e+000"+"\x00"*4)
data.write("\x63"+"1.00000000000000000000"+"e+000"+"\x00"*4)
data.write("\x63"+"1.00000000000000000000"+"e+000"+"\x00"*4)
data.write("\x63"+"1.00000000000000000000"+"e+000"+"\x00"*4)
write_chunkheader(data, 0x68, 0x02, "emission")
data.write("\x68\x04")
data.write("\x63"+"0.00000000000000000000"+"e+000"+"\x00"*4)
data.write("\x63"+"0.00000000000000000000"+"e+000"+"\x00"*4)
data.write("\x63"+"0.00000000000000000000"+"e+000"+"\x00"*4)
data.write("\x63"+"0.00000000000000000000"+"e+000"+"\x00"*4)
write_chunkheader(data, 0x68, 0x02, "shininess")
data.write("\x63"+"0.00000000000000000000"+"e+000"+"\x00"*4)
#write_chunkheader(data, 0x68, 0x02, "twosided")
#data.write(struct.pack(">BH4s", 0x64, 4, "true"))
data.write("\x6A"*3) # use *4 if no ambient light
# =====================
# === Generate Data ===
# =====================
def generate_data(objname, edge_table, mesh):
data = cStringIO.StringIO()
# === wings chunk ===
write_chunkheader(data, 0x68, 0x03, "wings")
numobjs = 1 # len(Blender.Object.GetSelected())
data.write("\x61\x02\x68\x03") # misc bytes
data.write(struct.pack(">BL", 0x6C, numobjs))
# === object chunk ===
write_chunkheader(data, 0x68, 0x04, "object")
data.write(struct.pack(">BH", 0x6B, len(objname)))
data.write(objname)
# === winged chunk ===
write_chunkheader(data, 0x68, 0x05, "winged")
write_edges(data, mesh, edge_table)
write_faces(data, mesh)
write_verts(data, mesh)
write_mode(data, mesh)
write_material(data, mesh)
write_ambient_light(data)
return data.getvalue()
# ===========================
# === Write Ambient Light ===
# ===========================
def write_ambient_light(data):
light = [ # A quick cheat ;)
0x6C, 0x00, 0x00, 0x00, 0x01, 0x68, 0x02, 0x64, 0x00, 0x06, 0x6C, 0x69,
0x67, 0x68, 0x74, 0x73, 0x6C, 0x00, 0x00, 0x00, 0x01, 0x68, 0x02, 0x6B,
0x00, 0x07, 0x41, 0x6D, 0x62, 0x69, 0x65, 0x6E, 0x74, 0x6C, 0x00, 0x00,
0x00, 0x08, 0x68, 0x02, 0x64, 0x00, 0x07, 0x76, 0x69, 0x73, 0x69, 0x62,
0x6C, 0x65, 0x64, 0x00, 0x04, 0x74, 0x72, 0x75, 0x65, 0x68, 0x02, 0x64,
0x00, 0x06, 0x6C, 0x6F, 0x63, 0x6B, 0x65, 0x64, 0x64, 0x00, 0x05, 0x66,
0x61, 0x6C, 0x73, 0x65, 0x68, 0x02, 0x64, 0x00, 0x06, 0x6F, 0x70, 0x65,
0x6E, 0x67, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x03, 0x68, 0x02, 0x64, 0x00,
0x04, 0x74, 0x79, 0x70, 0x65, 0x64, 0x00, 0x07, 0x61, 0x6D, 0x62, 0x69,
0x65, 0x6E, 0x74, 0x68, 0x02, 0x64, 0x00, 0x07, 0x61, 0x6D, 0x62, 0x69,
0x65, 0x6E, 0x74, 0x68, 0x04, 0x63, 0x31, 0x2E, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x65, 0x2B, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00,
0x00, 0x63, 0x31, 0x2E, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x65, 0x2B, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x63, 0x31, 0x2E,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x65, 0x2B, 0x30, 0x30,
0x30, 0x00, 0x00, 0x00, 0x00, 0x63, 0x31, 0x2E, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x65, 0x2B, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00,
0x00, 0x68, 0x02, 0x64, 0x00, 0x08, 0x70, 0x6F, 0x73, 0x69, 0x74, 0x69,
0x6F, 0x6E, 0x68, 0x03, 0x63, 0x30, 0x2E, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x65, 0x2B, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00,
0x63, 0x33, 0x2E, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x65,
0x2B, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x63, 0x30, 0x2E, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x65, 0x2B, 0x30, 0x30, 0x30,
0x00, 0x00, 0x00, 0x00, 0x6A, 0x68, 0x02, 0x64, 0x00, 0x07, 0x76, 0x69,
0x73, 0x69, 0x62, 0x6C, 0x65, 0x64, 0x00, 0x04, 0x74, 0x72, 0x75, 0x65,
0x68, 0x02, 0x64, 0x00, 0x06, 0x6C, 0x6F, 0x63, 0x6B, 0x65, 0x64, 0x64,
0x00, 0x05, 0x66, 0x61, 0x6C, 0x73, 0x65, 0x68, 0x02, 0x64, 0x00, 0x06,
0x79, 0x61, 0x66, 0x72, 0x61, 0x79, 0x6C, 0x00, 0x00, 0x00, 0x0B, 0x68,
0x02, 0x64, 0x00, 0x09, 0x6D, 0x69, 0x6E, 0x69, 0x6D, 0x69, 0x7A, 0x65,
0x64, 0x64, 0x00, 0x04, 0x74, 0x72, 0x75, 0x65, 0x68, 0x02, 0x64, 0x00,
0x05, 0x70, 0x6F, 0x77, 0x65, 0x72, 0x63, 0x31, 0x2E, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x65, 0x2B, 0x30, 0x30, 0x30, 0x00, 0x00,
0x00, 0x00, 0x68, 0x02, 0x64, 0x00, 0x04, 0x74, 0x79, 0x70, 0x65, 0x64,
0x00, 0x09, 0x68, 0x65, 0x6D, 0x69, 0x6C, 0x69, 0x67, 0x68, 0x74, 0x68,
0x02, 0x64, 0x00, 0x07, 0x73, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x73, 0x62,
0x00, 0x00, 0x01, 0x00, 0x68, 0x02, 0x64, 0x00, 0x05, 0x64, 0x65, 0x70,
0x74, 0x68, 0x61, 0x03, 0x68, 0x02, 0x64, 0x00, 0x0A, 0x62, 0x61, 0x63,
0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x64, 0x00, 0x09, 0x75, 0x6E,
0x64, 0x65, 0x66, 0x69, 0x6E, 0x65, 0x64, 0x68, 0x02, 0x64, 0x00, 0x18,
0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x5F, 0x66,
0x69, 0x6C, 0x65, 0x6E, 0x61, 0x6D, 0x65, 0x5F, 0x48, 0x44, 0x52, 0x49,
0x6A, 0x68, 0x02, 0x64, 0x00, 0x19, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72,
0x6F, 0x75, 0x6E, 0x64, 0x5F, 0x66, 0x69, 0x6C, 0x65, 0x6E, 0x61, 0x6D,
0x65, 0x5F, 0x69, 0x6D, 0x61, 0x67, 0x65, 0x6A, 0x68, 0x02, 0x64, 0x00,
0x1A, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x5F,
0x65, 0x78, 0x70, 0x6F, 0x73, 0x75, 0x72, 0x65, 0x5F, 0x61, 0x64, 0x6A,
0x75, 0x73, 0x74, 0x61, 0x00, 0x68, 0x02, 0x64, 0x00, 0x12, 0x62, 0x61,
0x63, 0x6B, 0x67, 0x72, 0x6F, 0x75, 0x6E, 0x64, 0x5F, 0x6D, 0x61, 0x70,
0x70, 0x69, 0x6E, 0x67, 0x64, 0x00, 0x05, 0x70, 0x72, 0x6F, 0x62, 0x65,
0x68, 0x02, 0x64, 0x00, 0x10, 0x62, 0x61, 0x63, 0x6B, 0x67, 0x72, 0x6F,
0x75, 0x6E, 0x64, 0x5F, 0x70, 0x6F, 0x77, 0x65, 0x72, 0x63, 0x31, 0x2E,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x65, 0x2B, 0x30, 0x30,
0x30, 0x00, 0x00, 0x00, 0x00, 0x6A, 0x68, 0x02, 0x64, 0x00, 0x07, 0x76,
0x69, 0x73, 0x69, 0x62, 0x6C, 0x65, 0x64, 0x00, 0x04, 0x74, 0x72, 0x75,
0x65, 0x68, 0x02, 0x64, 0x00, 0x06, 0x6C, 0x6F, 0x63, 0x6B, 0x65, 0x64,
0x64, 0x00, 0x05, 0x66, 0x61, 0x6C, 0x73, 0x65, 0x6A, 0x6A, 0x6A]
data.write("".join(map(chr, light)))
# ==========================
# === Write Wings Format ===
# ==========================
def write(filename):
start = time.clock()
objects = Blender.Object.GetSelected()
objname = objects[0].name
meshname = objects[0].data.name
mesh = Blender.NMesh.GetRaw(meshname)
obj = Blender.Object.Get(objname)
try:
edge_table = meshtools.generate_edgetable(mesh)
except:
edge_table = {}
message = "Unable to generate\nEdge Table for mesh.\n"
message += "Object name is: " + meshname
meshtools.print_boxed(message)
Blender.Draw.PupMenu("Wings Export error|Unable to generate Edge Table for mesh")
return
data = generate_data(objname, edge_table, mesh)
dsize = len(data)
Blender.Window.DrawProgressBar(0.98, "Compressing Data")
data = zlib.compress(data, 6)
fsize = len(data)+6
header = "#!WINGS-1.0\r\n\032\04"
misc = 0x8350
file = open(filename, "wb")
file.write(header)
file.write(struct.pack(">L", fsize))
file.write(struct.pack(">H", misc))
file.write(struct.pack(">L", dsize))
file.write(data)
# Blender.Window.RedrawAll()
Blender.Window.DrawProgressBar(1.0, '') # clear progressbar
file.close()
end = time.clock()
seconds = " in %.2f %s" % (end-start, "seconds")
message = "Successfully exported " + os.path.basename(filename) + seconds + '\n\n'
message += "objname : " + objname + '\n'
message += "faces : " + `len(mesh.faces)` + '\n'
message += "edges : " + `len(edge_table)` + '\n'
message += "verts : " + `len(mesh.verts)` + '\n'
meshtools.print_boxed(message)
def fs_callback(filename):
if filename.find('.wings', -6) <= 0: filename += '.wings'
write(filename)
if Blender.Object.GetSelected()[0].getType() != "Mesh":
Blender.Draw.PupMenu("Wings Export error|Selected object is not a mesh!")
else:
Blender.Window.FileSelector(fs_callback, "Export Wings3D")