提交 34f802e3 编写于 作者: M Mr.doob

Code clean up.

Removed old Blender exporters.
Slim exporter is now Normal exporter (needs some testing).
上级 a2acf0b3
此差异已折叠。
此差异已折叠。
......@@ -239,23 +239,23 @@
function loop() {
if ( moveForward ) camera.position.z -= 5; // camera.moveZ( 5 );
if ( moveBackwards ) camera.position.z += 5; // camera.moveZ( - 5 );
if ( moveForward ) camera.position.z -= 5;
if ( moveBackwards ) camera.position.z += 5;
if ( moveUp ) camera.position.y += 5; // camera.moveZ( 5 );
if ( moveDown ) camera.position.y -= 5; // camera.moveZ( - 5 );
if ( moveUp ) camera.position.y += 5;
if ( moveDown ) camera.position.y -= 5;
if ( moveLeft ) camera.position.x -= 5; // camera.moveX( - 5 );
if ( moveRight ) camera.position.x += 5; // camera.moveX( 5 );
if ( moveLeft ) camera.position.x -= 5;
if ( moveRight ) camera.position.x += 5;
if ( pitchUp ) camera.rotation.x += 0.01; // camera.rotateX( 1 );
if ( pitchDown ) camera.rotation.x -= 0.01; // camera.rotateX( - 1 );
if ( pitchUp ) camera.rotation.x += 0.01;
if ( pitchDown ) camera.rotation.x -= 0.01;
if ( yawLeft ) camera.target.position.x -= 5; // camera.rotation.y += 0.01; // camera.rotateY( 1 );
if ( yawRight ) camera.target.position.x += 5; // camera.rotation.y -= 0.01; // camera.rotateY( - 1 );
if ( yawLeft ) camera.target.position.x -= 5;
if ( yawRight ) camera.target.position.x += 5;
if ( rollLeft ) camera.rotation.z += 0.01; // camera.rotateZ( 1 );
if ( rollRight ) camera.rotation.z -= 0.01; // camera.rotateZ( - 1 );
if ( rollLeft ) camera.rotation.z += 0.01;
if ( rollRight ) camera.rotation.z -= 0.01;
debugContext.clearRect( -256, -256, 512, 512 );
......
......@@ -27,7 +27,7 @@ THREE.CanvasRenderer = function () {
_color4 = new THREE.Color(),
_2near, _farPlusNear, _farMinusNear,
_bitmap, _bitmapWidth, _bitmapHeight,
_bitmap,
_clipRect = new THREE.Rectangle(),
_clearRect = new THREE.Rectangle(),
......@@ -41,7 +41,6 @@ THREE.CanvasRenderer = function () {
_pi2 = Math.PI * 2,
_vector3 = new THREE.Vector3(), // Needed for PointLight
_uv1 = new THREE.UV(), _uv2 = new THREE.UV(), _uv3 = new THREE.UV(), _uv4 = new THREE.UV(),
_pixelMap, _pixelMapContext, _pixelMapImage, _pixelMapData,
_gradientMap, _gradientMapContext, _gradientMapQuality = 16;
......@@ -583,6 +582,7 @@ THREE.CanvasRenderer = function () {
}
/*
function drawQuad( x0, y0, x1, y1, x2, y2, x3, y3 ) {
_context.beginPath();
......@@ -594,6 +594,7 @@ THREE.CanvasRenderer = function () {
_context.closePath();
}
*/
function strokePath( color, linewidth ) {
......@@ -616,7 +617,8 @@ THREE.CanvasRenderer = function () {
// http://extremelysatisfactorytotalitarianism.com/blog/?p=2120
var width = bitmap.width - 1,
var a, b, c, d, e, f, det,
width = bitmap.width - 1,
height = bitmap.height - 1;
u0 *= width; v0 *= height;
......@@ -629,7 +631,7 @@ THREE.CanvasRenderer = function () {
u1 -= u0; v1 -= v0;
u2 -= u0; v2 -= v0;
var det = 1 / ( u1 * v2 - u2 * v1 ),
det = 1 / ( u1 * v2 - u2 * v1 ),
a = ( v2 * x1 - v1 * x2 ) * det,
b = ( v2 * y1 - v1 * y2 ) * det,
......
......@@ -8,7 +8,6 @@ THREE.Projector = function() {
var _renderList = null,
_face3, _face32, _face3Count, _face3Pool = [],
//_face4, _face4Count, _face4Pool = [],
_line, _lineCount, _linePool = [],
_particle, _particleCount, _particlePool = [],
......@@ -19,7 +18,7 @@ THREE.Projector = function() {
_clippedVertex1PositionScreen = new THREE.Vector4(),
_clippedVertex2PositionScreen = new THREE.Vector4(),
_face3VertexNormals, _face4VertexNormals;
_face3VertexNormals;
this.projectScene = function ( scene, camera ) {
......@@ -29,7 +28,7 @@ THREE.Projector = function() {
faces, face, faceVertexNormals, normal, v1, v2, v3, v4;
_renderList = [];
_face3Count = _face4Count = _lineCount = _particleCount = 0;
_face3Count = _lineCount = _particleCount = 0;
camera.autoUpdateMatrix && camera.updateMatrix();
......@@ -49,8 +48,6 @@ THREE.Projector = function() {
if ( object instanceof THREE.Mesh ) {
// _projScreenObjectMatrix.multiply( _projScreenMatrix, objectMatrix );
// vertices
vertices = object.geometry.vertices;
......
# ##### 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# To support reload properly, try to access a package var, if it's there, reload everything
if "bpy" in locals():
import sys
reload(sys.modules.get("io_mesh_threejs.export_threejs", sys))
import bpy
from bpy.props import *
from io_utils import ExportHelper
class ExportTHREEJS(bpy.types.Operator, ExportHelper):
'''This script exports the selected object for the three.js engine.'''
bl_idname = "export.threejs"
bl_label = "Export Three.js"
filename_ext = ".js"
use_modifiers = BoolProperty(name="Apply Modifiers", description="Apply Modifiers to the exported mesh", default=True)
use_normals = BoolProperty(name="Normals", description="Export Normals for smooth and hard shaded faces", default=True)
use_uv_coords = BoolProperty(name="UVs", description="Exort the active UV layer", default=True)
use_colors = BoolProperty(name="Vertex Colors", description="Exort the active vertex color layer", default=True)
@classmethod
def poll(cls, context):
return context.active_object != None
def execute(self, context):
print("Selected: " + context.active_object.name)
if not self.properties.filepath:
raise Exception("filename not set")
filepath = self.filepath
import io_mesh_threejs.export_threejs
return io_mesh_threejs.export_threejs.save(self, context, **self.properties)
def draw(self, context):
layout = self.layout
row = layout.row()
row.prop(self.properties, "use_modifiers")
row.prop(self.properties, "use_normals")
row = layout.row()
row.prop(self.properties, "use_uv_coords")
row.prop(self.properties, "use_colors")
def menu_func(self, context):
default_path = bpy.data.filepath.replace(".blend", ".js")
self.layout.operator(ExportTHREEJS.bl_idname, text="Three.js (.js)").filepath = default_path
def register():
bpy.types.INFO_MT_file_export.append(menu_func)
def unregister():
bpy.types.INFO_MT_file_export.remove(menu_func)
if __name__ == "__main__":
register()
# ##### 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# Based on export_ply.py
# Contributors: Mr.doob, Kikko, alteredq
"""
This script exports the selected object for the three.js engine.
"""
import bpy
import mathutils
import os
import os.path
import math
def save(operator, context, filepath="", use_modifiers=True, use_normals=True, use_uv_coords=True, use_colors=True):
def rvec3d(v):
return round(v[0], 6), round(v[1], 6), round(v[2], 6)
def rvec2d(v):
return round(v[0], 6), round(v[1], 6)
scene = context.scene
obj = context.object
if not filepath.lower().endswith('.js'):
filepath += '.js'
classname = os.path.basename(filepath).split(".")[0]
if not obj:
raise Exception("Error, Select 1 active object")
file = open(filepath, 'w')
if scene.objects.active:
bpy.ops.object.mode_set(mode='OBJECT')
if use_modifiers:
mesh = obj.create_mesh(scene, True, 'PREVIEW')
else:
mesh = obj.data
if not mesh:
raise Exception("Error, could not get mesh data from active object")
# that's what Blender's native export_obj.py does
x_rot = mathutils.Matrix.Rotation(-math.pi/2, 4, 'X')
mesh.transform(x_rot * obj.matrix_world)
mesh.calc_normals()
faceUV = (len(mesh.uv_textures) > 0)
vertexUV = (len(mesh.sticky) > 0)
vertexColors = len(mesh.vertex_colors) > 0
if (not faceUV) and (not vertexUV):
use_uv_coords = False
if not vertexColors:
use_colors = False
if not use_uv_coords:
faceUV = vertexUV = False
if not use_colors:
vertexColors = False
if faceUV:
active_uv_layer = mesh.uv_textures.active
if not active_uv_layer:
use_uv_coords = False
faceUV = None
else:
active_uv_layer = active_uv_layer.data
if vertexColors:
active_col_layer = mesh.vertex_colors.active
if not active_col_layer:
use_colors = False
vertexColors = None
else:
active_col_layer = active_col_layer.data
# incase
color = uvcoord = uvcoord_key = normal = normal_key = None
file.write('// Generated with Blender exporter (compatible with Blender 2.54 / 2.55)\n')
file.write('// http://github.com/mrdoob/three.js/tree/master/utils/exporters/blender\n\n')
file.write('var %s = function () {\n\n' % classname)
file.write('\tvar scope = this;\n\n')
file.write('\tTHREE.Geometry.call( this );\n\n')
for v in mesh.vertices:
file.write('\tv( %.6f, %.6f, %.6f );\n' % (v.co.x, v.co.y, v.co.z)) # co
file.write('\n')
if use_normals:
for f in mesh.faces:
if len(f.vertices) == 3:
file.write('\tf3( %d, %d, %d, %.6f, %.6f, %.6f );\n' % (f.vertices[0], f.vertices[1], f.vertices[2], f.normal[0], f.normal[1], f.normal[2]))
else:
file.write('\tf4( %d, %d, %d, %d, %.6f, %.6f, %.6f );\n' % (f.vertices[0], f.vertices[1], f.vertices[2], f.vertices[3], f.normal[0], f.normal[1], f.normal[2]))
else:
for f in mesh.faces:
if len(f.vertices) == 3:
file.write('\tf3( %d, %d, %d );\n' % (f.vertices[0], f.vertices[1], f.vertices[2]))
else:
file.write('\tf4( %d, %d, %d, %d );\n' % (f.vertices[0], f.vertices[1], f.vertices[2], f.vertices[3]))
face_index_pairs = [ (face, index) for index, face in enumerate(mesh.faces)]
if use_uv_coords:
file.write('\n')
for f, f_index in face_index_pairs:
tface = mesh.uv_textures[0].data[f_index]
if len(f.vertices) == 3:
file.write('\tuv( %.6f, %.6f, %.6f, %.6f, %.6f, %.6f );\n' % (tface.uv1[0], 1.0-tface.uv1[1], tface.uv2[0], 1.0-tface.uv2[1], tface.uv3[0], 1.0-tface.uv3[1]))
else:
file.write('\tuv( %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f );\n' % (tface.uv1[0], 1.0-tface.uv1[1], tface.uv2[0], 1.0-tface.uv2[1], tface.uv3[0], 1.0-tface.uv3[1], tface.uv4[0], 1.0-tface.uv4[1]))
file.write('\n')
file.write('\tfunction v( x, y, z ) {\n\n')
file.write('\t\tscope.vertices.push( new THREE.Vertex( new THREE.Vector3( x, y, z ) ) );\n\n')
file.write('\t}\n\n')
file.write('\tfunction f3( a, b, c, nx, ny, nz ) {\n\n')
file.write('\t\tscope.faces.push( new THREE.Face3( a, b, c, (nx || ny || nz) ? new THREE.Vector3( nx, ny, nz ) : null ) );\n\n')
file.write('\t}\n\n')
file.write('\tfunction f4( a, b, c, d, nx, ny, nz ) {\n\n')
file.write('\t\tscope.faces.push( new THREE.Face4( a, b, c, d, (nx || ny || nz) ? new THREE.Vector3( nx, ny, nz ) : null ) );\n\n')
file.write('\t}\n\n')
file.write('\tfunction uv( u1, v1, u2, v2, u3, v3, u4, v4 ) {\n\n')
file.write('\t\tvar uv = [];\n')
file.write('\t\tuv.push( new THREE.UV( u1, v1 ) );\n')
file.write('\t\tuv.push( new THREE.UV( u2, v2 ) );\n')
file.write('\t\tuv.push( new THREE.UV( u3, v3 ) );\n')
file.write('\t\tif ( u4 && v4 ) uv.push( new THREE.UV( u4, v4 ) );\n')
file.write('\t\tscope.uvs.push( uv );\n')
file.write('\t}\n\n')
file.write('\tthis.computeCentroids();\n')
if not use_normals:
file.write('\tthis.computeNormals();\n')
file.write('\n}\n\n')
file.write('%s.prototype = new THREE.Geometry();\n' % classname)
file.write('%s.prototype.constructor = %s;' % (classname, classname))
file.close()
print("writing", filepath, "done")
if use_modifiers:
bpy.data.meshes.remove(mesh)
return {'FINISHED'}
......@@ -19,7 +19,7 @@
# To support reload properly, try to access a package var, if it's there, reload everything
if "bpy" in locals():
import sys
reload(sys.modules.get("io_mesh_threejs_slim.export_threejs_slim", sys))
reload(sys.modules.get("io_mesh_threejs.export_threejs", sys))
import bpy
......@@ -27,17 +27,17 @@ from bpy.props import *
from io_utils import ExportHelper
class ExportTHREEJSSlim(bpy.types.Operator, ExportHelper):
class ExportTHREEJS(bpy.types.Operator, ExportHelper):
'''Export selected object for Three.js (ASCII JSON format).'''
bl_idname = "export.threejs_slim"
bl_label = "Export Three.js Slim"
bl_idname = "export.threejs"
bl_label = "Export Three.js"
filename_ext = ".js"
use_modifiers = BoolProperty(name="Apply Modifiers", description="Apply modifiers to the exported mesh", default=True)
use_normals = BoolProperty(name="Normals", description="Export normals", default=True)
use_uv_coords = BoolProperty(name="UVs", description="Export texture coordinates", default=True)
align_types = [("None","None","None"), ("Center","Center","Center"), ("Bottom","Bottom","Bottom"), ("Top","Top","Top")]
align_model = EnumProperty(name="Align model", description="Align model", items=align_types, default="Center")
......@@ -52,8 +52,8 @@ class ExportTHREEJSSlim(bpy.types.Operator, ExportHelper):
raise Exception("filename not set")
filepath = self.filepath
import io_mesh_threejs_slim.export_threejs_slim
return io_mesh_threejs_slim.export_threejs_slim.save(self, context, **self.properties)
import io_mesh_threejs.export_threejs
return io_mesh_threejs.export_threejs.save(self, context, **self.properties)
def draw(self, context):
layout = self.layout
......@@ -66,11 +66,11 @@ class ExportTHREEJSSlim(bpy.types.Operator, ExportHelper):
row.prop(self.properties, "use_uv_coords")
row = layout.row()
row.prop(self.properties, "align_model")
def menu_func(self, context):
default_path = bpy.data.filepath.replace(".blend", ".js")
self.layout.operator(ExportTHREEJSSlim.bl_idname, text="Three.js (.js) Slim").filepath = default_path
self.layout.operator(ExportTHREEJS.bl_idname, text="Three.js (.js)").filepath = default_path
def register():
......
......@@ -42,7 +42,7 @@ import random
# Configuration
# #####################################################
# default colors for debugging (each material gets one distinct color):
# default colors for debugging (each material gets one distinct color):
# white, red, green, blue, yellow, cyan, magenta
COLORS = [0xeeeeee, 0xee0000, 0x00ee00, 0x0000ee, 0xeeee00, 0x00eeee, 0xee00ee]
......@@ -51,36 +51,40 @@ COLORS = [0xeeeeee, 0xee0000, 0x00ee00, 0x0000ee, 0xeeee00, 0x00eeee, 0xee00ee]
# Templates
# #####################################################
TEMPLATE_FILE_ASCII = """\
// vertices: %(nvertex)d
// faces: %(nface)d
// materials: %(nmaterial)d
//
// Generated with Blender slim exporter (compatible with Blender 2.54 / 2.55)
// https://github.com/alteredq/three.js/tree/master/utils/exporters/blender/
/*
* File generated with Blender 2.55 Exporter
* https://github.com/mrdoob/three.js/tree/master/utils/exporters/blender/
*
* vertices: %(nvertex)d
* faces: %(nface)d
* materials: %(nmaterial)d
*
*/
var model = {
'materials': [%(materials)s],
'normals': [%(normals)s],
'materials': [%(materials)s],
'vertices': [%(vertices)s],
'normals': [%(normals)s],
'uvs': [%(uvs)s],
'vertices': [%(vertices)s],
'triangles': [%(triangles)s],
'triangles_n': [%(triangles_n)s],
'triangles_uv': [%(triangles_uv)s],
'triangles_n_uv': [%(triangles_n_uv)s],
'uvs': [%(uvs)s],
'quads': [%(quads)s],
'quads_n': [%(quads_n)s],
'quads_uv': [%(quads_uv)s],
'quads_n_uv': [%(quads_n_uv)s],
'triangles': [%(triangles)s],
'triangles_n': [%(triangles_n)s],
'triangles_uv': [%(triangles_uv)s],
'triangles_n_uv': [%(triangles_n_uv)s],
'quads': [%(quads)s],
'quads_n': [%(quads_n)s],
'quads_uv': [%(quads_uv)s],
'quads_n_uv': [%(quads_n_uv)s],
'end': (new Date).getTime()
}
'end': (new Date).getTime()
}
postMessage( model );
"""
......@@ -134,18 +138,18 @@ def get_uv_indices(f, uvs, mesh):
def bbox(vertices):
"""Compute bounding box of vertex array.
"""
if len(vertices)>0:
minx = maxx = vertices[0].co.x
miny = maxy = vertices[0].co.y
minz = maxz = vertices[0].co.z
for v in vertices[1:]:
if v.co.x < minx:
minx = v.co.x
elif v.co.x > maxx:
maxx = v.co.x
if v.co.y < miny:
miny = v.co.y
elif v.co.y > maxy:
......@@ -157,14 +161,14 @@ def bbox(vertices):
maxz = v.co.z
return { 'x':[minx,maxx], 'y':[miny,maxy], 'z':[minz,maxz] }
else:
return { 'x':[0,0], 'y':[0,0], 'z':[0,0] }
def translate(vertices, t):
"""Translate array of vertices by vector t.
"""
for i in range(len(vertices)):
vertices[i].co.x += t[0]
vertices[i].co.y += t[1]
......@@ -173,37 +177,37 @@ def translate(vertices, t):
def center(vertices):
"""Center model (middle of bounding box).
"""
bb = bbox(vertices)
cx = bb['x'][0] + (bb['x'][1] - bb['x'][0])/2.0
cy = bb['y'][0] + (bb['y'][1] - bb['y'][0])/2.0
cz = bb['z'][0] + (bb['z'][1] - bb['z'][0])/2.0
translate(vertices, [-cx,-cy,-cz])
def top(vertices):
"""Align top of the model with the floor (Y-axis) and center it around X and Z.
"""
bb = bbox(vertices)
cx = bb['x'][0] + (bb['x'][1] - bb['x'][0])/2.0
cy = bb['y'][1]
cz = bb['z'][0] + (bb['z'][1] - bb['z'][0])/2.0
translate(vertices, [-cx,-cy,-cz])
def bottom(vertices):
"""Align bottom of the model with the floor (Y-axis) and center it around X and Z.
"""
bb = bbox(vertices)
cx = bb['x'][0] + (bb['x'][1] - bb['x'][0])/2.0
cy = bb['y'][0]
cy = bb['y'][0]
cz = bb['z'][0] + (bb['z'][1] - bb['z'][0])/2.0
translate(vertices, [-cx,-cy,-cz])
# #####################################################
......@@ -221,73 +225,73 @@ def generate_uv(uv):
def generate_triangle(f):
v = f[0].vertices
m = f[0].material_index
return TEMPLATE_TRI % (v[0], v[1], v[2],
return TEMPLATE_TRI % (v[0], v[1], v[2],
m)
def generate_quad(f):
v = f[0].vertices
m = f[0].material_index
return TEMPLATE_QUAD % (v[0], v[1], v[2], v[3],
return TEMPLATE_QUAD % (v[0], v[1], v[2], v[3],
m)
def generate_triangle_n(f, normals, mesh):
def generate_triangle_n(f, normals, mesh):
v = f[0].vertices
m = f[0].material_index
n = get_normal_indices(v, normals, mesh)
return TEMPLATE_TRI_N % (v[0], v[1], v[2],
m,
return TEMPLATE_TRI_N % (v[0], v[1], v[2],
m,
n[0], n[1], n[2])
def generate_quad_n(f, normals, mesh):
def generate_quad_n(f, normals, mesh):
v = f[0].vertices
m = f[0].material_index
n = get_normal_indices(v, normals, mesh)
return TEMPLATE_QUAD_N % (v[0], v[1], v[2], v[3],
m,
m,
n[0], n[1], n[2], n[3])
def generate_triangle_uv(f, uvs, mesh):
v = f[0].vertices
v = f[0].vertices
m = f[0].material_index
uv = get_uv_indices(f, uvs, mesh)
return TEMPLATE_TRI_UV % (v[0], v[1], v[2],
m,
return TEMPLATE_TRI_UV % (v[0], v[1], v[2],
m,
uv[0], uv[1], uv[2])
def generate_quad_uv(f, uvs, mesh):
v = f[0].vertices
v = f[0].vertices
m = f[0].material_index
uv = get_uv_indices(f, uvs, mesh)
return TEMPLATE_QUAD_UV % (v[0], v[1], v[2], v[3],
m,
m,
uv[0], uv[1], uv[2], uv[3])
def generate_triangle_n_uv(f, normals, uvs, mesh):
v = f[0].vertices
v = f[0].vertices
m = f[0].material_index
n = get_normal_indices(v, normals, mesh)
uv = get_uv_indices(f, uvs, mesh)
return TEMPLATE_TRI_N_UV % (v[0], v[1], v[2],
m,
n[0], n[1], n[2],
uv = get_uv_indices(f, uvs, mesh)
return TEMPLATE_TRI_N_UV % (v[0], v[1], v[2],
m,
n[0], n[1], n[2],
uv[0], uv[1], uv[2])
def generate_quad_n_uv(f, normals, uvs, mesh):
v = f[0].vertices
v = f[0].vertices
m = f[0].material_index
n = get_normal_indices(v, normals, mesh)
uv = get_uv_indices(f, uvs, mesh)
return TEMPLATE_QUAD_N_UV % (v[0], v[1], v[2], v[3],
m,
uv = get_uv_indices(f, uvs, mesh)
return TEMPLATE_QUAD_N_UV % (v[0], v[1], v[2], v[3],
m,
n[0], n[1], n[2], n[3],
uv[0], uv[1], uv[2], uv[3])
# #####################################################
# Faces
# #####################################################
......@@ -297,17 +301,17 @@ def sort_faces(faces, use_normals, use_uv_coords):
'triangles_flat_uv': [],
'triangles_smooth': [],
'triangles_smooth_uv': [],
'quads_flat': [],
'quads_flat_uv': [],
'quads_smooth': [],
'quads_smooth_uv': []
}
for i, f in enumerate(faces):
if len(f.vertices) == 3:
if use_normals and use_uv_coords:
data['triangles_smooth_uv'].append([f,i])
elif use_normals and not use_uv_coords:
......@@ -316,9 +320,9 @@ def sort_faces(faces, use_normals, use_uv_coords):
data['triangles_flat_uv'].append([f,i])
else:
data['triangles_flat'].append([f,i])
elif len(f.vertices) == 4:
if use_normals and use_uv_coords:
data['quads_smooth_uv'].append([f,i])
elif use_normals and not use_uv_coords:
......@@ -327,81 +331,81 @@ def sort_faces(faces, use_normals, use_uv_coords):
data['quads_flat_uv'].append([f,i])
else:
data['quads_flat'].append([f,i])
return data
# #####################################################
# Normals
# #####################################################
def extract_vertex_normals(mesh, use_normals):
if not use_normals:
return {}
count = 0
normals = {}
for f in mesh.faces:
for v in f.vertices:
key = veckey3d(mesh.vertices[v].normal)
if key not in normals:
normals[key] = count
count += 1
return normals
def generate_normals(normals, use_normals):
if not use_normals:
return ""
chunks = []
for key, index in sorted(normals.items(), key=operator.itemgetter(1)):
chunks.append(key)
return ",".join(generate_normal(n) for n in chunks)
# #####################################################
# UVs
# #####################################################
def extract_uvs(mesh, use_uv_coords):
if not use_uv_coords:
return {}
count = 0
uvs = {}
uv_layer = mesh.uv_textures.active.data
for face_index, face in enumerate(mesh.faces):
for uv_index, uv in enumerate(uv_layer[face_index].uv):
key = veckey2d(uv)
if key not in uvs:
uvs[key] = count
count += 1
return uvs
def generate_uvs(uvs, use_uv_coords):
if not use_uv_coords:
return ""
chunks = []
for key, index in sorted(uvs.items(), key=operator.itemgetter(1)):
chunks.append(key)
return ",".join(generate_uv(n) for n in chunks)
# #####################################################
# Materials
# #####################################################
def generate_color(i):
"""Generate hex color corresponding to integer.
Colors should have well defined ordering.
First N colors are hardcoded, then colors are random
(must seed random number generator with deterministic value
First N colors are hardcoded, then colors are random
(must seed random number generator with deterministic value
before getting colors).
"""
if i < len(COLORS):
return "0x%06x" % COLORS[i]
else:
......@@ -410,7 +414,7 @@ def generate_color(i):
def generate_mtl(materials):
"""Generate dummy materials.
"""
mtl = {}
for m in materials:
index = materials[m]
......@@ -425,15 +429,15 @@ def value2string(v):
if type(v)==str and v[0] != "0":
return '"%s"' % v
return str(v)
def generate_materials(mtl, materials):
"""Generate JS array of materials objects
"""Generate JS array of materials objects
"""
mtl_array = []
for m in mtl:
index = materials[m]
# add debug information
# materials should be sorted according to how
# they appeared in OBJ file (for the first time)
......@@ -441,13 +445,13 @@ def generate_materials(mtl, materials):
mtl[m]['a_dbg_name'] = m
mtl[m]['a_dbg_index'] = index
mtl[m]['a_dbg_color'] = generate_color(index)
mtl_raw = ",\n".join(['\t"%s" : %s' % (n, value2string(v)) for n,v in sorted(mtl[m].items())])
mtl_string = "\t{\n%s\n\t}" % mtl_raw
mtl_array.append([index, mtl_string])
return ",\n\n".join([m for i,m in sorted(mtl_array)])
def extract_materials(mesh, scene):
world = scene.world
......@@ -455,33 +459,33 @@ def extract_materials(mesh, scene):
for m in mesh.materials:
if m:
materials[m.name] = {}
materials[m.name]['col_diffuse'] = [m.diffuse_intensity * m.diffuse_color[0],
m.diffuse_intensity * m.diffuse_color[1],
materials[m.name]['col_diffuse'] = [m.diffuse_intensity * m.diffuse_color[0],
m.diffuse_intensity * m.diffuse_color[1],
m.diffuse_intensity * m.diffuse_color[2]]
materials[m.name]['col_specular'] = [m.specular_intensity * m.specular_color[0],
m.specular_intensity * m.specular_color[1],
materials[m.name]['col_specular'] = [m.specular_intensity * m.specular_color[0],
m.specular_intensity * m.specular_color[1],
m.specular_intensity * m.specular_color[2]]
materials[m.name]['col_ambient'] = [m.ambient * world.ambient_color[0],
m.ambient * world.ambient_color[1],
materials[m.name]['col_ambient'] = [m.ambient * world.ambient_color[0],
m.ambient * world.ambient_color[1],
m.ambient * world.ambient_color[2]]
materials[m.name]['transparency'] = m.alpha
# not sure about mapping values to Blinn-Phong shader
# Blender uses INT from [1,511] with default 0
# http://www.blender.org/documentation/blender_python_api_2_54_0/bpy.types.Material.html#bpy.types.Material.specular_hardness
materials[m.name]["specular_coef"] = m.specular_hardness
materials[m.name]["specular_coef"] = m.specular_hardness
if m.active_texture and m.active_texture.type == 'IMAGE':
fn = bpy.path.abspath(m.active_texture.image.filepath)
fn = os.path.normpath(fn)
fn_strip = os.path.basename(fn)
materials[m.name]['map_diffuse'] = fn_strip
return materials
def generate_materials_string(mesh, scene):
random.seed(42) # to get well defined color order for debug materials
......@@ -493,61 +497,61 @@ def generate_materials_string(mesh, scene):
materials[m.name] = i
else:
materials["undefined_dummy_%0d" % i] = i
if not materials:
materials = { 'default':0 }
# default dummy materials
mtl = generate_mtl(materials)
# extract real materials from the mesh
mtl.update(extract_materials(mesh, scene))
return generate_materials(mtl, materials)
# #####################################################
# ASCII exporter
# #####################################################
def generate_ascii_model(mesh, scene, use_normals, use_uv_coords, align_model):
vertices = mesh.vertices[:]
if align_model == 1:
center(vertices)
elif align_model == 2:
bottom(vertices)
elif align_model == 3:
top(vertices)
sfaces = sort_faces(mesh.faces, use_normals, use_uv_coords)
normals = extract_vertex_normals(mesh, use_normals)
uvs = extract_uvs(mesh, use_uv_coords)
text = TEMPLATE_FILE_ASCII % {
"vertices" : ",".join(generate_vertex(v) for v in vertices),
"triangles" : ",".join(generate_triangle(f) for f in sfaces['triangles_flat']),
"triangles_n" : ",".join(generate_triangle_n(f, normals, mesh) for f in sfaces['triangles_smooth']),
"triangles_uv" : ",".join(generate_triangle_uv(f, uvs, mesh) for f in sfaces['triangles_flat_uv']),
"triangles_n_uv": ",".join(generate_triangle_n_uv(f, normals, uvs, mesh) for f in sfaces['triangles_smooth_uv']),
"quads" : ",".join(generate_quad(f) for f in sfaces['quads_flat']),
"quads_n" : ",".join(generate_quad_n(f, normals, mesh) for f in sfaces['quads_smooth']),
"quads_uv" : ",".join(generate_quad_uv(f, uvs, mesh) for f in sfaces['quads_flat_uv']),
"quads_n_uv" : ",".join(generate_quad_n_uv(f, normals, uvs, mesh) for f in sfaces['quads_smooth_uv']),
"uvs" : generate_uvs(uvs, use_uv_coords),
"normals" : generate_normals(normals, use_normals),
"materials" : generate_materials_string(mesh, scene),
"nvertex" : len(mesh.vertices),
"nface" : len(mesh.faces),
"nmaterial" : 0
}
return text
# #####################################################
......@@ -587,7 +591,7 @@ def save(operator, context, filepath="", use_modifiers=True, use_normals=True, u
x_rot = mathutils.Matrix.Rotation(-math.pi/2, 4, 'X')
mesh.transform(x_rot * obj.matrix_world)
mesh.calc_normals()
faceUV = (len(mesh.uv_textures) > 0)
vertexUV = (len(mesh.sticky) > 0)
......
__author__ = "Mr.doob, Kikko"
__url__ = ['http://mrdoob.com', 'http://github.com/kikko']
__version__ = "1"
__bpydoc__ = """\
This script exports the selected object for the three.js engine.
"""
import bpy
def rvec3d(v):
return round(v[0], 6), round(v[1], 6), round(v[2], 6)
def rvec2d(v):
return round(v[0], 6), round(v[1], 6)
def write(filename, scene, ob, \
EXPORT_APPLY_MODIFIERS=True,\
EXPORT_NORMALS=True,\
EXPORT_UV=True,\
EXPORT_COLORS=True):
if not filename.lower().endswith('.js'):
filename += '.js'
classname = filename.split('/')[-1].replace('.js','')
if not ob:
raise Exception("Error, Select the object to export")
return
file = open(filename, 'w')
if EXPORT_APPLY_MODIFIERS:
mesh = ob.create_mesh(scene, True, 'PREVIEW')
else:
mesh = ob.data
if not mesh:
raise ("Error, could not get mesh data from selected object")
return
faceUV = len(mesh.uv_textures) > 0
vertexUV = len(mesh.sticky) > 0
vertexColors = len(mesh.vertex_colors) > 0
if (not faceUV) and (not vertexUV):
EXPORT_UV = False
if not vertexColors:
EXPORT_COLORS = False
if not EXPORT_UV:
faceUV = vertexUV = False
if not EXPORT_COLORS:
vertexColors = False
if faceUV:
active_uv_layer = mesh.active_uv_texture
if not active_uv_layer:
EXPORT_UV = False
faceUV = None
else:
active_uv_layer = active_uv_layer.data
if vertexColors:
active_col_layer = mesh.active_vertex_color
if not active_col_layer:
EXPORT_COLORS = False
vertexColors = None
else:
active_col_layer = active_col_layer.data
# incase
color = uvcoord = uvcoord_key = normal = normal_key = None
file.write('var %s = function () {\n\n' % classname)
file.write('\tvar scope = this;\n\n')
file.write('\tTHREE.Geometry.call(this);\n\n')
for v in mesh.verts:
file.write('\tv( %.6f, %.6f, %.6f );\n' % (v.co.x, v.co.z, -v.co.y)) # co
file.write('\n')
if EXPORT_NORMALS:
for f in mesh.faces:
if len(f.verts) == 3:
file.write('\tf3( %d, %d, %d, %.6f, %.6f, %.6f );\n' % (f.verts[0], f.verts[1], f.verts[2], f.normal[0], f.normal[1], f.normal[2]))
else:
file.write('\tf4( %d, %d, %d, %d, %.6f, %.6f, %.6f );\n' % (f.verts[0], f.verts[1], f.verts[2], f.verts[3], f.normal[0], f.normal[1], f.normal[2]))
else:
for f in mesh.faces:
if len(f.verts) == 3:
file.write('\tf3( %d, %d, %d );\n' % (f.verts[0], f.verts[1], f.verts[2]))
else:
file.write('\tf4( %d, %d, %d, %d );\n' % (f.verts[0], f.verts[1], f.verts[2], f.verts[3]))
face_index_pairs = [ (face, index) for index, face in enumerate(mesh.faces)]
if EXPORT_UV:
file.write('\n')
for f, f_index in face_index_pairs:
tface = mesh.uv_textures[0].data[f_index]
if len(f.verts) == 3:
file.write('\tuv( %.6f, %.6f, %.6f, %.6f, %.6f, %.6f );\n' % (tface.uv1[0], 1.0-tface.uv1[1], tface.uv2[0], 1.0-tface.uv2[1], tface.uv3[0], 1.0-tface.uv3[1]))
else:
file.write('\tuv( %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f );\n' % (tface.uv1[0], 1.0-tface.uv1[1], tface.uv2[0], 1.0-tface.uv2[1], tface.uv3[0], 1.0-tface.uv3[1], tface.uv4[0], 1.0-tface.uv4[1]))
file.write('\n')
file.write('\tfunction v( x, y, z ) {\n\n')
file.write('\t\tscope.vertices.push( new THREE.Vertex( new THREE.Vector3( x, y, z ) ) );\n\n')
file.write('\t}\n\n')
file.write('\tfunction f3( a, b, c, nx, ny, nz ) {\n\n')
file.write('\t\tscope.faces.push( new THREE.Face3( a, b, c, nx && ny && nz ? new THREE.Vector3( nx, ny, nz ) : null ) );\n\n')
file.write('\t}\n\n')
file.write('\tfunction f4( a, b, c, d, nx, ny, nz ) {\n\n')
file.write('\t\tscope.faces.push( new THREE.Face4( a, b, c, d, nx && ny && nz ? new THREE.Vector3( nx, ny, nz ) : null ) );\n\n')
file.write('\t}\n\n')
file.write('\tfunction uv( u1, v1, u2, v2, u3, v3, u4, v4 ) {\n\n')
file.write('\t\tvar uv = [];\n')
file.write('\t\tuv.push( new THREE.UV( u1, v1 ) );\n')
file.write('\t\tuv.push( new THREE.UV( u2, v2 ) );\n')
file.write('\t\tuv.push( new THREE.UV( u3, v3 ) );\n')
file.write('\t\tif ( u4 && v4 ) uv.push( new THREE.UV( u4, v4 ) );\n')
file.write('\t\tscope.uvs.push( uv );\n')
file.write('\t}\n\n')
file.write('}\n\n')
file.write('%s.prototype = new THREE.Geometry();\n' % classname)
file.write('%s.prototype.constructor = %s;' % (classname, classname))
file.close()
print("writing", filename, "done")
if EXPORT_APPLY_MODIFIERS:
bpy.data.meshes.remove(mesh)
from bpy.props import *
class ExportTHREEJS(bpy.types.Operator):
'''TODO'''
bl_idname = "export.three_js"
bl_label = "Export three.js"
# List of operator properties, the attributes will be assigned
# to the class instance from the operator settings before calling.
filepath = StringProperty(name="File Path", description="File path used for exporting the PLY file", maxlen=1024, default="")
check_existing = BoolProperty(name="Check Existing", description="Check and warn on overwriting existing files", default=True, options={'HIDDEN'})
use_modifiers = BoolProperty(name="Apply Modifiers", description="Apply Modifiers to the exported mesh", default=True)
use_normals = BoolProperty(name="Normals", description="Export Normals for smooth and hard shaded faces", default=True)
use_uvs = BoolProperty(name="UVs", description="Exort the active UV layer", default=True)
use_colors = BoolProperty(name="Vertex Colors", description="Exort the active vertex color layer", default=True)
def poll(self, context):
return context.active_object != None
def execute(self, context):
print("Selected: " + context.active_object.name)
if not self.properties.filepath:
raise Exception("filename not set")
write(self.properties.filepath, context.scene, context.active_object,\
EXPORT_APPLY_MODIFIERS=self.properties.use_modifiers,
EXPORT_NORMALS=self.properties.use_normals,
EXPORT_UV=self.properties.use_uvs,
EXPORT_COLORS=self.properties.use_colors,
)
return {'FINISHED'}
def invoke(self, context, event):
wm = context.manager
wm.add_fileselect(self)
return {'RUNNING_MODAL'}
def draw(self, context):
layout = self.layout
props = self.properties
row = layout.row()
row.prop(props, "use_modifiers")
row.prop(props, "use_normals")
row = layout.row()
row.prop(props, "use_uvs")
row.prop(props, "use_colors")
def menu_func(self, context):
default_path = bpy.data.filepath.replace(".blend", ".js")
self.layout.operator(ExportTHREEJS.bl_idname, text="three.js (.js)").filepath = default_path
def register():
bpy.types.register(ExportTHREEJS)
bpy.types.INFO_MT_file_export.append(menu_func)
def unregister():
bpy.types.unregister(ExportTHREEJS)
bpy.types.INFO_MT_file_export.remove(menu_func)
if __name__ == "__main__":
register()
__author__ = "Mr.doob, Kikko"
__url__ = ['http://mrdoob.com', 'http://github.com/kikko']
__version__ = "1"
__bpydoc__ = """\
This script exports the selected object for the three.js engine.
"""
import bpy
def rvec3d(v):
return round(v[0], 6), round(v[1], 6), round(v[2], 6)
def rvec2d(v):
return round(v[0], 6), round(v[1], 6)
def write(filename, scene, ob, \
EXPORT_APPLY_MODIFIERS=True,\
EXPORT_NORMALS=True,\
EXPORT_UV=True,\
EXPORT_COLORS=True):
if not filename.lower().endswith('.js'):
filename += '.js'
classname = filename.split('/')[-1].replace('.js','')
if not ob:
raise Exception("Error, Select the object to export")
return
file = open(filename, 'w')
if EXPORT_APPLY_MODIFIERS:
mesh = ob.create_mesh(True, 'PREVIEW')
else:
mesh = ob.data
if not mesh:
raise ("Error, could not get mesh data from selected object")
return
faceUV = len(mesh.uv_textures) > 0
vertexUV = len(mesh.sticky) > 0
vertexColors = len(mesh.vertex_colors) > 0
if (not faceUV) and (not vertexUV):
EXPORT_UV = False
if not vertexColors:
EXPORT_COLORS = False
if not EXPORT_UV:
faceUV = vertexUV = False
if not EXPORT_COLORS:
vertexColors = False
if faceUV:
active_uv_layer = mesh.active_uv_texture
if not active_uv_layer:
EXPORT_UV = False
faceUV = None
else:
active_uv_layer = active_uv_layer.data
if vertexColors:
active_col_layer = mesh.active_vertex_color
if not active_col_layer:
EXPORT_COLORS = False
vertexColors = None
else:
active_col_layer = active_col_layer.data
# incase
color = uvcoord = uvcoord_key = normal = normal_key = None
file.write('var %s = function () {\n\n' % classname)
file.write('\tvar scope = this;\n\n')
file.write('\tTHREE.Geometry.call(this);\n\n')
for v in mesh.verts:
file.write('\tv( %.6f, %.6f, %.6f );\n' % (v.co.x, v.co.z, -v.co.y)) # co
file.write('\n')
if EXPORT_NORMALS:
for f in mesh.faces:
if len(f.verts) == 3:
file.write('\tf3( %d, %d, %d, %.6f, %.6f, %.6f );\n' % (f.verts[0], f.verts[1], f.verts[2], f.normal[0], f.normal[1], f.normal[2]))
else:
file.write('\tf4( %d, %d, %d, %d, %.6f, %.6f, %.6f );\n' % (f.verts[0], f.verts[1], f.verts[2], f.verts[3], f.normal[0], f.normal[1], f.normal[2]))
else:
for f in mesh.faces:
if len(f.verts) == 3:
file.write('\tf3( %d, %d, %d );\n' % (f.verts[0], f.verts[1], f.verts[2]))
else:
file.write('\tf4( %d, %d, %d, %d );\n' % (f.verts[0], f.verts[1], f.verts[2], f.verts[3]))
face_index_pairs = [ (face, index) for index, face in enumerate(mesh.faces)]
if EXPORT_UV:
file.write('\n')
for f, f_index in face_index_pairs:
tface = mesh.uv_textures[0].data[f_index]
if len(f.verts) == 3:
file.write('\tuv( %.6f, %.6f, %.6f, %.6f, %.6f, %.6f );\n' % (tface.uv1[0], 1.0-tface.uv1[1], tface.uv2[0], 1.0-tface.uv2[1], tface.uv3[0], 1.0-tface.uv3[1]))
else:
file.write('\tuv( %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f );\n' % (tface.uv1[0], 1.0-tface.uv1[1], tface.uv2[0], 1.0-tface.uv2[1], tface.uv3[0], 1.0-tface.uv3[1], tface.uv4[0], 1.0-tface.uv4[1]))
file.write('\n')
file.write('\tfunction v( x, y, z ) {\n\n')
file.write('\t\tscope.vertices.push( new THREE.Vertex( new THREE.Vector3( x, y, z ) ) );\n\n')
file.write('\t}\n\n')
file.write('\tfunction f3( a, b, c, nx, ny, nz ) {\n\n')
file.write('\t\tscope.faces.push( new THREE.Face3( a, b, c, nx && ny && nz ? new THREE.Vector3( nx, ny, nz ) : null ) );\n\n')
file.write('\t}\n\n')
file.write('\tfunction f4( a, b, c, d, nx, ny, nz ) {\n\n')
file.write('\t\tscope.faces.push( new THREE.Face4( a, b, c, d, nx && ny && nz ? new THREE.Vector3( nx, ny, nz ) : null ) );\n\n')
file.write('\t}\n\n')
file.write('\tfunction uv( u1, v1, u2, v2, u3, v3, u4, v4 ) {\n\n')
file.write('\t\tvar uv = [];\n')
file.write('\t\tuv.push( new THREE.UV( u1, v1 ) );\n')
file.write('\t\tuv.push( new THREE.UV( u2, v2 ) );\n')
file.write('\t\tuv.push( new THREE.UV( u3, v3 ) );\n')
file.write('\t\tif ( u4 && v4 ) uv.push( new THREE.UV( u4, v4 ) );\n')
file.write('\t\tscope.uvs.push( uv );\n')
file.write('\t}\n\n')
file.write('}\n\n')
file.write('%s.prototype = new THREE.Geometry();\n' % classname)
file.write('%s.prototype.constructor = %s;' % (classname, classname))
file.close()
print("writing", filename, "done")
if EXPORT_APPLY_MODIFIERS:
bpy.data.meshes.remove(mesh)
from bpy.props import *
class ExportTHREEJS(bpy.types.Operator):
'''TODO'''
bl_idname = "export.three_js"
bl_label = "Export three.js"
# List of operator properties, the attributes will be assigned
# to the class instance from the operator settings before calling.
path = StringProperty(name="File Path", description="File path used for exporting the PLY file", maxlen=1024, default="")
check_existing = BoolProperty(name="Check Existing", description="Check and warn on overwriting existing files", default=True, options={'HIDDEN'})
use_modifiers = BoolProperty(name="Apply Modifiers", description="Apply Modifiers to the exported mesh", default=True)
use_normals = BoolProperty(name="Normals", description="Export Normals for smooth and hard shaded faces", default=True)
use_uvs = BoolProperty(name="UVs", description="Exort the active UV layer", default=True)
use_colors = BoolProperty(name="Vertex Colors", description="Exort the active vertex color layer", default=True)
def poll(self, context):
return context.active_object != None
def execute(self, context):
print("Selected: " + context.active_object.name)
if not self.properties.path:
raise Exception("filename not set")
write(self.properties.path, context.scene, context.active_object,\
EXPORT_APPLY_MODIFIERS=self.properties.use_modifiers,
EXPORT_NORMALS=self.properties.use_normals,
EXPORT_UV=self.properties.use_uvs,
EXPORT_COLORS=self.properties.use_colors,
)
return {'FINISHED'}
def invoke(self, context, event):
wm = context.manager
wm.add_fileselect(self)
return {'RUNNING_MODAL'}
def draw(self, context):
layout = self.layout
props = self.properties
row = layout.row()
row.prop(props, "use_modifiers")
row.prop(props, "use_normals")
row = layout.row()
row.prop(props, "use_uvs")
row.prop(props, "use_colors")
def menu_func(self, context):
default_path = bpy.data.filename.replace(".blend", ".js")
self.layout.operator(ExportTHREEJS.bl_idname, text="three.js (.js)").path = default_path
def register():
bpy.types.register(ExportTHREEJS)
bpy.types.INFO_MT_file_export.append(menu_func)
def unregister():
bpy.types.unregister(ExportTHREEJS)
bpy.types.INFO_MT_file_export.remove(menu_func)
if __name__ == "__main__":
register()
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册