Create a gist now

Instantly share code, notes, and snippets.

WebGLExport.py Blender WebGL exporter fork
#!BPY
"""
Name: 'WebGL JavaScript (.js)'
Blender: 249
Group: 'Export'
Tooltip: 'WebGL JavaScript'
"""
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# Copyright (C) 2010 Dennis Ippel
#
# 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 *****
# --------------------------------------------------------------------------
#bl_addon_info = {
#'name': 'WebGL mesh exporter',
#'author': 'Ilmari Heikkinen, Dennis Ippel, Rehno Lindeque',
#'version': (0,3),
#'blender': (2,5,5),
#'category': 'Import/Export',
#'location': 'File > Export',
#'description': "WebGL export",
#'doc': """\
#Export selected meshes for use with WebGL.
#"""}
__author__ = "Dennis Ippel, Rehno Lindeque, Ilmari Heikkinen"
__url__ = ("http://www.rozengain.com")
__version__ = "0.2.2"
__bpydoc__ = """
For more information please go to:
http://www.rozengain.com
"""
import Blender
from Blender import *
from Blender.Mathutils import *
import bpy
import os
from Blender.BGL import *
EVENT_NOEVENT = 1
EVENT_DRAW = 2
EVENT_EXIT = 3
EVENT_EXPORT = 4
EVENT_BROWSEFILE = 5
file_button = Draw.Create("")
engine_menu = Draw.Create(1)
exp_all = Draw.Create(0)
exp_normals = Draw.Create(1)
exp_weights = Draw.Create(1)
animation_button = Draw.Create(1)
animation_start = Draw.Create(0)
animation_end = Draw.Create(0)
def vector_str(vec):
return str.join(",", ["%.6f" % x for x in vec])
def matrix_str(mat):
return "[%s]" % (str.join(",", [vector_str(x) for x in mat]))
def append_bones(s, class_name, mesh, ob):
mods = ob.modifiers
armatures = []
for m in mods:
if m.type == Modifier.Types.ARMATURE:
armatures.append(m[Modifier.Settings.OBJECT])
if len(armatures) > 0:
bones = []
arma = armatures[0]
pose = arma.getPose()
to_armature = ob.matrixWorld * arma.matrixWorld.copy().invert()
armaPosition = arma.matrixWorld
Blender.Set('curframe', 0)
abones = {}
pbones = pose.bones.values()
for bone in pbones:
if animation_button.val:
bone_frames = []
for frame in xrange(animation_start.val-1, animation_end.val):
Blender.Set('curframe', frame)
bone_frames.append("new Float32Array(%s)" % (matrix_str(to_armature * bone.localMatrix * armaPosition)))
bones.append("\"%s\": [%s]" % (bone.name, str.join(",", bone_frames)))
s.append("BlenderExport.%s.bones = {%s};\n" % (class_name, str.join(",", bones)))
def append_materials(s, class_name, mesh, ob):
materialDefs = ["BlenderExport.%s.materialDefinitions = [" % (class_name)]
for m in mesh.materials:
materialDefs.append("{ name: '%s'," % (m.name))
materialDefs.append("diffuse: [%.6f,%.6f,%.6f,%.6f]," % (m.R, m.G, m.B, m.alpha))
materialDefs.append("specular: [%.6f,%.6f,%.6f,1.0]," % (m.specR, m.specG, m.specB))
materialDefs.append("mirror: [%.6f,%.6f,%.6f,1.0]," % (m.mirR, m.mirG, m.mirB))
materialDefs.append("specularIntensity: %.6f," % (m.spec))
materialDefs.append("emit: %.6f, ambient: %.6f}, " % (m.emit, m.amb))
materialDefs.append("];\n")
s.append(str.join("", materialDefs))
def append_vertex_groups(s, class_name, mesh, ob):
vertGroups = {}
vertex_groups = []
idx=0
for m in mesh.getVertGroupNames():
vertGroups[m] = idx
vertex_groups.append("\"%s\"" % m)
idx += 1
vertex_groups_s = "BlenderExport.%s.vertexGroups = [%s];\n" % (class_name, str.join(",", vertex_groups))
s.append(vertex_groups_s)
return vertGroups
def export_native(class_name, mesh, ob):
s = ["if (typeof BlenderExport == 'undefined') BlenderExport = {};\n"]
s.append("BlenderExport.%s = {};\n" % (class_name))
s.append("BlenderExport.%s.frameCount = %s;\n" % (class_name, animation_end.val-animation_start.val+1))
append_bones(s, class_name, mesh, ob)
append_materials(s, class_name, mesh, ob)
if (exp_weights == 1):
vertGroups = append_vertex_groups(s, class_name, mesh, ob)
vertices_s = "BlenderExport.%s.vertices = new Float32Array([" % (class_name)
normals_s = "BlenderExport.%s.normals = new Float32Array([" % (class_name)
weights_s = "BlenderExport.%s.normals = new Float32Array([" % (class_name)
colors_s = "BlenderExport.%s.colors = new Float32Array([" % (class_name)
texCoords_s = "BlenderExport.%s.texCoords = new Float32Array([" % (class_name)
materials_s = "BlenderExport.%s.materials = new Float32Array([" % (class_name)
weights_s = "BlenderExport.%s.weights = [" % (class_name)
indices = []
vertices = []
normals = []
colors = []
texCoords = []
materials = []
weights = []
indexcount = 0
for f in mesh.faces:
face_indexes = [0,1,2]
for j in xrange(3, len(f.verts)):
face_indexes += [0, j-1, j]
for i in face_indexes:
v = f.verts[i]
if (exp_weights == 1):
wts = mesh.getVertexInfluences(v.index)
ws = []
for w in wts:
if w[1] > 0.0:
ws.append("[%d, %.6f]" % (vertGroups[w[0]], w[1]))
weights.append("[" + str.join(",", ws) + "]")
vertices.append("%.6f, %.6f, %.6f" % (v.co.x, v.co.y, v.co.z))
normals.append("%.6f, %.6f, %.6f" % (v.no.x, v.no.y, v.no.z))
materials.append("%d" % (f.mat))
if (mesh.vertexColors):
color = f.col[i]
colors.append("%.6f,%.6f,%.6f,%.6f" % ( color.r / 255.0, color.g / 255.0, color.b / 255.0, color.a / 255.0))
if (mesh.faceUV):
texCoords.append("%.6f,%.6f" % (f.uv[i][0], f.uv[i][1]))
indexcount += 1
s.append( vertices_s )
s.append( str.join(",", vertices) )
s.append( "]);\n" )
s.append( materials_s )
s.append( str.join(",", materials) )
s.append( "]);\n" )
if (exp_weights == 1):
s.append( weights_s )
s.append( str.join(",", weights) )
s.append( "];\n" )
if (exp_normals == 1):
s.append( normals_s )
s.append( str.join(",", normals) )
s.append( "]);\n" )
if (mesh.vertexColors):
s.append( colors_s )
s.append( str.join(",", colors) )
s.append( "]);\n" )
if (mesh.faceUV):
s.append( texCoords_s )
s.append( str.join(",", texCoords) )
s.append( "]);\n" )
return str.join("", s)
def export_native_indexed(class_name, mesh, ob):
s = ["if (typeof BlenderExport == 'undefined') BlenderExport = {};\n"]
s.append("BlenderExport.%s = {};\n" % (class_name))
s.append("BlenderExport.%s.frameCount = %s;\n" % (class_name, animation_end.val-animation_start.val+1))
append_bones(s, class_name, mesh, ob)
append_materials(s, class_name, mesh, ob)
if (exp_weights == 1):
vertGroups = append_vertex_groups(s, class_name, mesh, ob)
indices_s = "BlenderExport.%s.indices = new Uint16Array([" % (class_name)
vertices_s = "BlenderExport.%s.vertices = new Float32Array([" % (class_name)
normals_s = "BlenderExport.%s.normals = new Float32Array([" % (class_name)
weights_s = "BlenderExport.%s.normals = new Float32Array([" % (class_name)
texCoords_s = "BlenderExport.%s.texCoords = new Float32Array([" % (class_name)
weights_s = "BlenderExport.%s.weights = [" % (class_name)
indices = []
vertices = []
normals = []
texCoords = []
weights = []
indexcount = 0
for v in mesh.verts:
if (exp_weights == 1):
wts = mesh.getVertexInfluences(v.index)
ws = []
for w in wts:
if w[1] > 0.0:
ws.append("[%d, %.6f]" % (vertGroups[w[0]], w[1]))
weights.append("[" + str.join(",", ws) + "]")
vertices.append("%.6f, %.6f, %.6f" % (v.co.x, v.co.y, v.co.z))
normals.append("%.6f, %.6f, %.6f" % (v.no.x, v.no.y, v.no.z))
if (mesh.vertexUV):
texCoords.append("%.6f,%.6f" % (v.uvco[0], v.uvco[1]))
for f in mesh.faces:
face_indexes = [0,1,2]
for j in xrange(3, len(f.verts)):
face_indexes += [0, j-1, j]
for i in face_indexes:
v = f.verts[i]
indices.append(v.index)
indexcount += 1
s.append( indices_s )
s.append( str.join(",", [str(i) for i in indices]) )
s.append( "]);\n" )
s.append( vertices_s )
s.append( str.join(",", vertices) )
s.append( "]);\n" )
if (exp_weights == 1):
s.append( weights_s )
s.append( str.join(",", weights) )
s.append( "];\n" )
if (exp_normals == 1):
s.append( normals_s )
s.append( str.join(",", normals) )
s.append( "]);\n" )
if (mesh.vertexUV):
s.append( texCoords_s )
s.append( str.join(",", texCoords) )
s.append( "]);\n" )
return str.join("", s)
def event(evt, val):
if (evt == Draw.QKEY and not val):
Draw.Exit()
def bevent(evt):
global EVENT_NOEVENT,EVENT_DRAW,EVENT_EXIT
if (evt == EVENT_EXIT):
Draw.Exit()
elif (evt== EVENT_DRAW):
Draw.Redraw()
elif (evt== EVENT_EXPORT):
sce = bpy.data.scenes.active
obs = None
if(exp_all == 1):
# export all scene objects
obs = [ob for ob in sce.objects if ob.type == 'Mesh']
else:
# export the selected objects
obs = [ob for ob in sce.objects.selected if ob.type == 'Mesh']
if (len(obs) == 0):
Draw.PupMenu("Nothing to export. Please select a Mesh.")
Draw.Exit()
return
# export all object names
for ob in obs:
me = Mesh.New()
if exp_weights == 1:
me = ob.getData(mesh=1)
else:
me.getFromObject(ob,0)
class_name = ob.name.replace(".", "")
ext = ""
if(engine_menu.val ==4): ext = ".xml"
else: ext = ".js"
out = open(file_button.val+""+class_name+ext, 'w')#file(file_button.val, 'w')
data_string = ""
if (engine_menu.val == 1):
data_string = export_native(class_name, me, ob)
elif(engine_menu.val == 6):
data_string = export_native_indexed(class_name, me, ob)
out.write(data_string)
out.close()
Draw.PupMenu("Export Successful")
elif (evt== EVENT_BROWSEFILE):
if (engine_menu.val == 4):
Window.FileSelector(FileSelected,"Export .xml", exp_file_name)
else:
Window.FileSelector(FileSelected,"Export .js", exp_file_name)
Draw.Redraw(1)
def FileSelected(file_name):
global file_button
if file_name != '':
file_button.val = file_name
else:
cutils.Debug.Debug('ERROR: filename is empty','ERROR')
def draw():
global file_button, exp_file_name, animation_button, animation_start, animation_end
global engine_menu, engine_name, exp_normals, exp_weights, exp_all
global EVENT_NOEVENT, EVENT_DRAW, EVENT_EXIT, EVENT_EXPORT
exp_file_name = ""
glClear(GL_COLOR_BUFFER_BIT)
glRasterPos2i(40, 240)
engine_name = "Native WebGL%x1|Native WebGL (indexed)%x6"
engine_menu = Draw.Menu(engine_name, EVENT_NOEVENT, 40, 100, 200, 20, engine_menu.val, "Choose your engine")
file_button = Draw.String('File location: ', EVENT_NOEVENT, 40, 70, 250, 20, file_button.val, 255)
Draw.PushButton('...', EVENT_BROWSEFILE, 300, 70, 30, 20, 'browse file')
exp_normals = Draw.Toggle('Export normals', EVENT_NOEVENT, 250, 45, 100, 20, exp_normals.val)
exp_weights = Draw.Toggle('Export weights', EVENT_NOEVENT, 360, 45, 100, 20, exp_weights.val)
anim_down = 0
if animation_button.val == 1:
anim_down = 1
animation_button = Draw.Toggle('Export animation frames', EVENT_NOEVENT, 470, 70, 300, 20, animation_button.val, 'Export keyframe animation')
animation_start = Draw.Number('First frame', EVENT_NOEVENT, 470, 45, 160, 20, animation_start.val, 1, 9999)
animation_end = Draw.Number('Last frame', EVENT_NOEVENT, 470, 20, 160, 20, animation_end.val, 1, 9999)
exp_all = Draw.Toggle('Export ALL scene objects', EVENT_NOEVENT, 40, 45, 200, 20, exp_all.val)
Draw.Button("Export",EVENT_EXPORT , 40, 20, 80, 18)
Draw.Button("Exit",EVENT_EXIT , 140, 20, 80, 18)
Draw.Register(draw, event, bevent)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment