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

Merge branch 'master' into dev

# ##### 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 #####
# ################################################################
# Init
# ################################################################
bl_info = {
"name": "three.js format",
"author": "mrdoob, kikko, alteredq, remoe, pxf",
"version": (1, 3, 0),
"blender": (2, 6, 0),
"api": 35622,
"location": "File > Import-Export",
"description": "Import-Export three.js meshes",
"warning": "",
"wiki_url": "https://github.com/mrdoob/three.js/tree/master/utils/exporters/blender",
"tracker_url": "https://github.com/mrdoob/three.js/issues",
"category": "Import-Export"}
# To support reload properly, try to access a package var,
# if it's there, reload everything
import bpy
if "bpy" in locals():
import imp
if "export_threejs" in locals():
imp.reload(export_threejs)
if "import_threejs" in locals():
imp.reload(import_threejs)
from bpy.props import *
from bpy_extras.io_utils import ExportHelper, ImportHelper
# ################################################################
# Custom properties
# ################################################################
bpy.types.Object.THREE_castShadow = bpy.props.BoolProperty()
bpy.types.Object.THREE_receiveShadow = bpy.props.BoolProperty()
bpy.types.Object.THREE_doubleSided = bpy.props.BoolProperty()
bpy.types.Object.THREE_exportGeometry = bpy.props.BoolProperty(default = True)
bpy.types.Material.THREE_useVertexColors = bpy.props.BoolProperty()
bpy.types.Material.THREE_depthWrite = bpy.props.BoolProperty(default = True)
bpy.types.Material.THREE_depthTest = bpy.props.BoolProperty(default = True)
THREE_material_types = [("Basic", "Basic", "Basic"), ("Phong", "Phong", "Phong"), ("Lambert", "Lambert", "Lambert")]
bpy.types.Material.THREE_materialType = EnumProperty(name = "Material type", description = "Material type", items = THREE_material_types, default = "Lambert")
THREE_blending_types = [("NoBlending", "NoBlending", "NoBlending"), ("NormalBlending", "NormalBlending", "NormalBlending"),
("AdditiveBlending", "AdditiveBlending", "AdditiveBlending"), ("SubtractiveBlending", "SubtractiveBlending", "SubtractiveBlending"),
("MultiplyBlending", "MultiplyBlending", "MultiplyBlending"), ("AdditiveAlphaBlending", "AdditiveAlphaBlending", "AdditiveAlphaBlending")]
bpy.types.Material.THREE_blendingType = EnumProperty(name = "Blending type", description = "Blending type", items = THREE_blending_types, default = "NormalBlending")
class OBJECT_PT_hello( bpy.types.Panel ):
bl_label = "THREE"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "object"
def draw(self, context):
layout = self.layout
obj = context.object
row = layout.row()
row.label(text="Selected object: " + obj.name )
row = layout.row()
row.prop( obj, "THREE_exportGeometry", text="Export geometry" )
row = layout.row()
row.prop( obj, "THREE_castShadow", text="Casts shadow" )
row = layout.row()
row.prop( obj, "THREE_receiveShadow", text="Receives shadow" )
row = layout.row()
row.prop( obj, "THREE_doubleSided", text="Double sided" )
class MATERIAL_PT_hello( bpy.types.Panel ):
bl_label = "THREE"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "material"
def draw(self, context):
layout = self.layout
mat = context.material
row = layout.row()
row.label(text="Selected material: " + mat.name )
row = layout.row()
row.prop( mat, "THREE_materialType", text="Material type" )
row = layout.row()
row.prop( mat, "THREE_blendingType", text="Blending type" )
row = layout.row()
row.prop( mat, "THREE_useVertexColors", text="Use vertex colors" )
row = layout.row()
row.prop( mat, "THREE_depthWrite", text="Enable depth writing" )
row = layout.row()
row.prop( mat, "THREE_depthTest", text="Enable depth testing" )
# ################################################################
# Importer
# ################################################################
class ImportTHREEJS(bpy.types.Operator, ImportHelper):
'''Load a Three.js ASCII JSON model'''
bl_idname = "import.threejs"
bl_label = "Import Three.js"
filename_ext = ".js"
filter_glob = StringProperty(default="*.js", options={'HIDDEN'})
option_flip_yz = BoolProperty(name="Flip YZ", description="Flip YZ", default=True)
recalculate_normals = BoolProperty(name="Recalculate normals", description="Recalculate vertex normals", default=True)
option_worker = BoolProperty(name="Worker", description="Old format using workers", default=False)
def execute(self, context):
import io_mesh_threejs.import_threejs
return io_mesh_threejs.import_threejs.load(self, context, **self.properties)
def draw(self, context):
layout = self.layout
row = layout.row()
row.prop(self.properties, "option_flip_yz")
row = layout.row()
row.prop(self.properties, "recalculate_normals")
row = layout.row()
row.prop(self.properties, "option_worker")
# ################################################################
# Exporter - settings
# ################################################################
SETTINGS_FILE_EXPORT = "threejs_settings_export.js"
import os
import json
def file_exists(filename):
"""Return true if file exists and accessible for reading.
Should be safer than just testing for existence due to links and
permissions magic on Unix filesystems.
@rtype: boolean
"""
try:
f = open(filename, 'r')
f.close()
return True
except IOError:
return False
def get_settings_fullpath():
return os.path.join(bpy.app.tempdir, SETTINGS_FILE_EXPORT)
def save_settings_export(properties):
settings = {
"option_export_scene" : properties.option_export_scene,
"option_embed_meshes" : properties.option_embed_meshes,
"option_url_base_html" : properties.option_url_base_html,
"option_copy_textures" : properties.option_copy_textures,
"option_lights" : properties.option_lights,
"option_cameras" : properties.option_cameras,
"option_animation" : properties.option_animation,
"option_frame_step" : properties.option_frame_step,
"option_all_meshes" : properties.option_all_meshes,
"option_flip_yz" : properties.option_flip_yz,
"option_materials" : properties.option_materials,
"option_normals" : properties.option_normals,
"option_colors" : properties.option_colors,
"option_uv_coords" : properties.option_uv_coords,
"option_faces" : properties.option_faces,
"option_vertices" : properties.option_vertices,
"option_vertices_truncate" : properties.option_vertices_truncate,
"option_scale" : properties.option_scale,
"align_model" : properties.align_model
}
fname = get_settings_fullpath()
f = open(fname, "w")
json.dump(settings, f)
def restore_settings_export(properties):
settings = {}
fname = get_settings_fullpath()
if file_exists(fname):
f = open(fname, "r")
settings = json.load(f)
properties.option_vertices = settings.get("option_vertices", True)
properties.option_vertices_truncate = settings.get("option_vertices_truncate", False)
properties.option_faces = settings.get("option_faces", True)
properties.option_normals = settings.get("option_normals", True)
properties.option_colors = settings.get("option_colors", True)
properties.option_uv_coords = settings.get("option_uv_coords", True)
properties.option_materials = settings.get("option_materials", True)
properties.align_model = settings.get("align_model", "None")
properties.option_scale = settings.get("option_scale", 1.0)
properties.option_flip_yz = settings.get("option_flip_yz", True)
properties.option_export_scene = settings.get("option_export_scene", False)
properties.option_embed_meshes = settings.get("option_embed_meshes", True)
properties.option_url_base_html = settings.get("option_url_base_html", False)
properties.option_copy_textures = settings.get("option_copy_textures", False)
properties.option_lights = settings.get("option_lights", False)
properties.option_cameras = settings.get("option_cameras", False)
properties.option_animation = settings.get("option_animation", False)
properties.option_frame_step = settings.get("option_frame_step", 1)
properties.option_all_meshes = settings.get("option_all_meshes", True)
# ################################################################
# Exporter
# ################################################################
class ExportTHREEJS(bpy.types.Operator, ExportHelper):
'''Export selected object / scene for Three.js (ASCII JSON format).'''
bl_idname = "export.threejs"
bl_label = "Export Three.js"
filename_ext = ".js"
option_vertices = BoolProperty(name = "Vertices", description = "Export vertices", default = True)
option_vertices_deltas = BoolProperty(name = "Deltas", description = "Delta vertices", default = False)
option_vertices_truncate = BoolProperty(name = "Truncate", description = "Truncate vertices", default = False)
option_faces = BoolProperty(name = "Faces", description = "Export faces", default = True)
option_faces_deltas = BoolProperty(name = "Deltas", description = "Delta faces", default = False)
option_normals = BoolProperty(name = "Normals", description = "Export normals", default = True)
option_colors = BoolProperty(name = "Colors", description = "Export vertex colors", default = True)
option_uv_coords = BoolProperty(name = "UVs", description = "Export texture coordinates", default = True)
option_materials = BoolProperty(name = "Materials", description = "Export materials", 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 = "None")
option_scale = FloatProperty(name = "Scale", description = "Scale vertices", min = 0.01, max = 1000.0, soft_min = 0.01, soft_max = 1000.0, default = 1.0)
option_flip_yz = BoolProperty(name = "Flip YZ", description = "Flip YZ", default = True)
option_export_scene = BoolProperty(name = "Scene", description = "Export scene", default = False)
option_embed_meshes = BoolProperty(name = "Embed meshes", description = "Embed meshes", default = True)
option_copy_textures = BoolProperty(name = "Copy textures", description = "Copy textures", default = False)
option_url_base_html = BoolProperty(name = "HTML as url base", description = "Use HTML as url base ", default = False)
option_lights = BoolProperty(name = "Lights", description = "Export default scene lights", default = False)
option_cameras = BoolProperty(name = "Cameras", description = "Export default scene cameras", default = False)
option_animation = BoolProperty(name = "Animation", description = "Export animation (morphs)", default = False)
option_frame_step = IntProperty(name = "Frame step", description = "Animation frame step", min = 1, max = 1000, soft_min = 1, soft_max = 1000, default = 1)
option_all_meshes = BoolProperty(name = "All meshes", description = "All meshes (merged)", default = True)
def invoke(self, context, event):
restore_settings_export(self.properties)
return ExportHelper.invoke(self, context, event)
@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")
save_settings_export(self.properties)
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.label(text="Geometry:")
row = layout.row()
row.prop(self.properties, "option_vertices")
# row = layout.row()
# row.enabled = self.properties.option_vertices
# row.prop(self.properties, "option_vertices_deltas")
row.prop(self.properties, "option_vertices_truncate")
layout.separator()
row = layout.row()
row.prop(self.properties, "option_faces")
row = layout.row()
row.enabled = self.properties.option_faces
# row.prop(self.properties, "option_faces_deltas")
layout.separator()
row = layout.row()
row.prop(self.properties, "option_normals")
layout.separator()
row = layout.row()
row.label(text="Materials:")
row = layout.row()
row.prop(self.properties, "option_uv_coords")
row.prop(self.properties, "option_colors")
row = layout.row()
row.prop(self.properties, "option_materials")
layout.separator()
row = layout.row()
row.label(text="Settings:")
row = layout.row()
row.prop(self.properties, "align_model")
row = layout.row()
row.prop(self.properties, "option_flip_yz")
row.prop(self.properties, "option_scale")
layout.separator()
row = layout.row()
row.label(text="--------- Experimental ---------")
layout.separator()
row = layout.row()
row.label(text="Scene:")
row = layout.row()
row.prop(self.properties, "option_export_scene")
row.prop(self.properties, "option_embed_meshes")
row = layout.row()
row.prop(self.properties, "option_lights")
row.prop(self.properties, "option_cameras")
layout.separator()
row = layout.row()
row.label(text="Animation:")
row = layout.row()
row.prop(self.properties, "option_animation")
row.prop(self.properties, "option_frame_step")
layout.separator()
row = layout.row()
row.label(text="Settings:")
row = layout.row()
row.prop(self.properties, "option_all_meshes")
row = layout.row()
row.prop(self.properties, "option_copy_textures")
row = layout.row()
row.prop(self.properties, "option_url_base_html")
layout.separator()
# ################################################################
# Common
# ################################################################
def menu_func_export(self, context):
default_path = bpy.data.filepath.replace(".blend", ".js")
self.layout.operator(ExportTHREEJS.bl_idname, text="Three.js (.js)").filepath = default_path
def menu_func_import(self, context):
self.layout.operator(ImportTHREEJS.bl_idname, text="Three.js (.js)")
def register():
bpy.utils.register_module(__name__)
bpy.types.INFO_MT_file_export.append(menu_func_export)
bpy.types.INFO_MT_file_import.append(menu_func_import)
def unregister():
bpy.utils.unregister_module(__name__)
bpy.types.INFO_MT_file_export.remove(menu_func_export)
bpy.types.INFO_MT_file_import.remove(menu_func_import)
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 #####
"""
Blender importer for Three.js (ASCII JSON format).
"""
import os
import time
import json
import bpy
import mathutils
from mathutils.geometry import tesselate_polygon
from bpy_extras.image_utils import load_image
# #####################################################
# Generators
# #####################################################
def setColor(c, t):
c.r = t[0]
c.g = t[1]
c.b = t[2]
def create_texture(filename, modelpath):
name = filename
texture = bpy.data.textures.new(name, type='IMAGE')
image = load_image(filename, modelpath)
has_data = False
if image:
texture.image = image
has_data = image.has_data
return texture
def create_materials(data, modelpath):
materials = []
materials_data = data.get("materials", [])
for i, m in enumerate(materials_data):
name = m.get("DbgName", "material_%d" % i)
colorAmbient = m.get("colorAmbient", None)
colorDiffuse = m.get("colorDiffuse", None)
colorSpecular = m.get("colorSpecular", None)
alpha = m.get("transparency", 1.0)
specular_hardness = m.get("specularCoef", 0)
mapDiffuse = m.get("mapDiffuse", None)
mapLightmap = m.get("mapLightmap", None)
vertexColorsType = m.get("vertexColors", False)
useVertexColors = False
if vertexColorsType:
useVertexColors = True
material = bpy.data.materials.new(name)
material.THREE_useVertexColors = useVertexColors
if colorDiffuse:
setColor(material.diffuse_color, colorDiffuse)
material.diffuse_intensity = 1.0
if colorSpecular:
setColor(material.specular_color, colorSpecular)
material.specular_intensity = 1.0
if alpha < 1.0:
material.alpha = alpha
material.use_transparency = True
if specular_hardness:
material.specular_hardness = specular_hardness
if mapDiffuse:
texture = create_texture(mapDiffuse, modelpath)
mtex = material.texture_slots.add()
mtex.texture = texture
mtex.texture_coords = 'UV'
mtex.use = True
mtex.use_map_color_diffuse = True
material.active_texture = texture
materials.append(material)
return materials
def create_mesh_object(name, vertices, materials, face_data, flipYZ, recalculate_normals):
faces = face_data["faces"]
vertexNormals = face_data["vertexNormals"]
vertexColors = face_data["vertexColors"]
vertexUVs = face_data["vertexUVs"]
faceMaterials = face_data["materials"]
faceColors = face_data["faceColors"]
edges = []
# Create a new mesh
me = bpy.data.meshes.new(name)
me.from_pydata(vertices, edges, faces)
# Handle normals
if not recalculate_normals:
me.update(calc_edges = True)
if face_data["hasVertexNormals"]:
print("setting vertex normals")
for fi in range(len(faces)):
if vertexNormals[fi]:
#print("setting face %i with %i vertices" % (fi, len(normals[fi])))
# if me.update() is called after setting vertex normals
# setting face.use_smooth overrides these normals
# - this fixes weird shading artefacts (seems to come from sharing
# of vertices between faces, didn't find a way how to set vertex normals
# per face use of vertex as opposed to per vertex),
# - probably this just overrides all custom vertex normals
# - to preserve vertex normals from the original data
# call me.update() before setting them
me.faces[fi].use_smooth = True
if not recalculate_normals:
for j in range(len(vertexNormals[fi])):
vertexNormal = vertexNormals[fi][j]
x = vertexNormal[0]
y = vertexNormal[1]
z = vertexNormal[2]
if flipYZ:
tmp = y
y = -z
z = tmp
# flip normals (this make them look consistent with the original before export)
#x = -x
#y = -y
#z = -z
vi = me.faces[fi].vertices[j]
me.vertices[vi].normal.x = x
me.vertices[vi].normal.y = y
me.vertices[vi].normal.z = z
if recalculate_normals:
me.update(calc_edges = True)
# Handle colors
if face_data["hasVertexColors"]:
print("setting vertex colors")
me.vertex_colors.new("vertex_color_layer_0")
for fi in range(len(faces)):
if vertexColors[fi]:
face_colors = me.vertex_colors[0].data[fi]
face_colors = face_colors.color1, face_colors.color2, face_colors.color3, face_colors.color4
for vi in range(len(vertexColors[fi])):
r = vertexColors[fi][vi][0]
g = vertexColors[fi][vi][1]
b = vertexColors[fi][vi][2]
face_colors[vi].r = r
face_colors[vi].g = g
face_colors[vi].b = b
elif face_data["hasFaceColors"]:
print("setting vertex colors from face colors")
me.vertex_colors.new("vertex_color_layer_0")
for fi in range(len(faces)):
if faceColors[fi]:
r = faceColors[fi][0]
g = faceColors[fi][1]
b = faceColors[fi][2]
face_colors = me.vertex_colors[0].data[fi]
face_colors = face_colors.color1, face_colors.color2, face_colors.color3, face_colors.color4
for vi in range(len(faces[fi])):
face_colors[vi].r = r
face_colors[vi].g = g
face_colors[vi].b = b
# Handle uvs
if face_data["hasVertexUVs"]:
print("setting vertex uvs")
for li, layer in enumerate(vertexUVs):
me.uv_textures.new("uv_layer_%d" % li)
for fi in range(len(faces)):
if layer[fi]:
uv_face = me.uv_textures[li].data[fi]
face_uvs = uv_face.uv1, uv_face.uv2, uv_face.uv3, uv_face.uv4
for vi in range(len(layer[fi])):
u = layer[fi][vi][0]
v = layer[fi][vi][1]
face_uvs[vi].x = u
face_uvs[vi].y = 1.0 - v
active_texture = materials[faceMaterials[fi]].active_texture
if active_texture:
uv_face.image = active_texture.image
# Handle materials # 1
if face_data["hasMaterials"]:
print("setting materials (mesh)")
for m in materials:
me.materials.append(m)
print("setting materials (faces)")
for fi in range(len(faces)):
if faceMaterials[fi] >= 0:
me.faces[fi].material_index = faceMaterials[fi]
# Create a new object
ob = bpy.data.objects.new(name, me)
ob.data = me # link the mesh data to the object
scene = bpy.context.scene # get the current scene
scene.objects.link(ob) # link the object into the scene
ob.location = scene.cursor_location # position object at 3d-cursor
# #####################################################
# Faces
# #####################################################
def extract_faces(data):
result = {
"faces" : [],
"materials" : [],
"faceUVs" : [],
"vertexUVs" : [],
"faceNormals" : [],
"vertexNormals" : [],
"faceColors" : [],
"vertexColors" : [],
"hasVertexNormals" : False,
"hasVertexUVs" : False,
"hasVertexColors" : False,
"hasFaceColors" : False,
"hasMaterials" : False
}
faces = data.get("faces", [])
normals = data.get("normals", [])
colors = data.get("colors", [])
offset = 0
zLength = len(faces)
# disregard empty arrays
nUvLayers = 0
for layer in data["uvs"]:
if len(layer) > 0:
nUvLayers += 1
result["faceUVs"].append([])
result["vertexUVs"].append([])
while ( offset < zLength ):
type = faces[ offset ]
offset += 1
isQuad = isBitSet( type, 0 )
hasMaterial = isBitSet( type, 1 )
hasFaceUv = isBitSet( type, 2 )
hasFaceVertexUv = isBitSet( type, 3 )
hasFaceNormal = isBitSet( type, 4 )
hasFaceVertexNormal = isBitSet( type, 5 )
hasFaceColor = isBitSet( type, 6 )
hasFaceVertexColor = isBitSet( type, 7 )
#print("type", type, "bits", isQuad, hasMaterial, hasFaceUv, hasFaceVertexUv, hasFaceNormal, hasFaceVertexNormal, hasFaceColor, hasFaceVertexColor)
result["hasVertexUVs"] = result["hasVertexUVs"] or hasFaceVertexUv
result["hasVertexNormals"] = result["hasVertexNormals"] or hasFaceVertexNormal
result["hasVertexColors"] = result["hasVertexColors"] or hasFaceVertexColor
result["hasFaceColors"] = result["hasFaceColors"] or hasFaceColor
result["hasMaterials"] = result["hasMaterials"] or hasMaterial
# vertices
if isQuad:
a = faces[ offset ]
offset += 1
b = faces[ offset ]
offset += 1
c = faces[ offset ]
offset += 1
d = faces[ offset ]
offset += 1
face = [a, b, c, d]
nVertices = 4
else:
a = faces[ offset ]
offset += 1
b = faces[ offset ]
offset += 1
c = faces[ offset ]
offset += 1
face = [a, b, c]
nVertices = 3
result["faces"].append(face)
# material
if hasMaterial:
materialIndex = faces[ offset ]
offset += 1
else:
materialIndex = -1
result["materials"].append(materialIndex)
# uvs
for i in range(nUvLayers):
faceUv = None
if hasFaceUv:
uvLayer = data["uvs"][ i ]
uvIndex = faces[ offset ]
offset += 1
u = uvLayer[ uvIndex * 2 ]
v = uvLayer[ uvIndex * 2 + 1 ]
faceUv = [u, v]
result["faceUVs"][i].append(faceUv)
if hasFaceVertexUv:
uvLayer = data["uvs"][ i ]
vertexUvs = []
for j in range(nVertices):
uvIndex = faces[ offset ]
offset += 1
u = uvLayer[ uvIndex * 2 ]
v = uvLayer[ uvIndex * 2 + 1 ]
vertexUvs.append([u, v])
result["vertexUVs"][i].append(vertexUvs)
if hasFaceNormal:
normalIndex = faces[ offset ] * 3
offset += 1
x = normals[ normalIndex ]
y = normals[ normalIndex + 1 ]
z = normals[ normalIndex + 2 ]
faceNormal = [x, y, z]
else:
faceNormal = None
result["faceNormals"].append(faceNormal)
if hasFaceVertexNormal:
vertexNormals = []
for j in range(nVertices):
normalIndex = faces[ offset ] * 3
offset += 1
x = normals[ normalIndex ]
y = normals[ normalIndex + 1 ]
z = normals[ normalIndex + 2 ]
vertexNormals.append( [x, y, z] )
else:
vertexNormals = None
result["vertexNormals"].append(vertexNormals)
if hasFaceColor:
colorIndex = faces[ offset ]
offset += 1
faceColor = hexToTuple( colors[ colorIndex ] )
else:
faceColor = None
result["faceColors"].append(faceColor)
if hasFaceVertexColor:
vertexColors = []
for j in range(nVertices):
colorIndex = faces[ offset ]
offset += 1
color = hexToTuple( colors[ colorIndex ] )
vertexColors.append( color )
else:
vertexColors = None
result["vertexColors"].append(vertexColors)
return result
# #####################################################
# Utils
# #####################################################
def hexToTuple( hexColor ):
r = (( hexColor >> 16 ) & 0xff) / 255.0
g = (( hexColor >> 8 ) & 0xff) / 255.0
b = ( hexColor & 0xff) / 255.0
return (r, g, b)
def isBitSet(value, position):
return value & ( 1 << position )
def splitArray(data, chunkSize):
result = []
chunk = []
for i in range(len(data)):
if i > 0 and i % chunkSize == 0:
result.append(chunk)
chunk = []
chunk.append(data[i])
result.append(chunk)
return result
def extract_json_string(text):
marker_begin = "var model ="
marker_end = "postMessage"
start = text.find(marker_begin) + len(marker_begin)
end = text.find(marker_end)
end = text.rfind("}", start, end)
return text[start:end+1].strip()
def get_name(filepath):
return os.path.splitext(os.path.basename(filepath))[0]
def get_path(filepath):
return os.path.dirname(filepath)
# #####################################################
# Parser
# #####################################################
def load(operator, context, filepath, option_flip_yz = True, recalculate_normals = True, option_worker = False):
print('\nimporting %r' % filepath)
time_main = time.time()
print("\tparsing JSON file...")
time_sub = time.time()
file = open(filepath, 'rU')
rawcontent = file.read()
file.close()
if option_worker:
json_string = extract_json_string(rawcontent)
else:
json_string = rawcontent
data = json.loads( json_string )
time_new = time.time()
print('parsing %.4f sec' % (time_new - time_sub))
time_sub = time_new
# flip YZ
vertices = splitArray(data["vertices"], 3)
if option_flip_yz:
vertices[:] = [(v[0], -v[2], v[1]) for v in vertices]
# extract faces
face_data = extract_faces(data)
# deselect all
bpy.ops.object.select_all(action='DESELECT')
nfaces = len(face_data["faces"])
nvertices = len(vertices)
nnormals = len(data.get("normals", [])) / 3
ncolors = len(data.get("colors", [])) / 3
nuvs = len(data.get("uvs", [])) / 2
nmaterials = len(data.get("materials", []))
print('\tbuilding geometry...\n\tfaces:%i, vertices:%i, vertex normals: %i, vertex uvs: %i, vertex colors: %i, materials: %i ...' % (
nfaces, nvertices, nnormals, nuvs, ncolors, nmaterials ))
# Create materials
materials = create_materials(data, get_path(filepath))
# Create new obj
create_mesh_object(get_name(filepath), vertices, materials, face_data, option_flip_yz, recalculate_normals)
scene = bpy.context.scene
scene.update()
time_new = time.time()
print('finished importing: %r in %.4f sec.' % (filepath, (time_new - time_main)))
return {'FINISHED'}
if __name__ == "__main__":
register()
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册