|
@@ -27,7 +27,7 @@ import json
|
|
|
import bpy
|
|
|
import mathutils
|
|
|
from mathutils.geometry import tesselate_polygon
|
|
|
-from io_utils import load_image, unpack_list, unpack_face_list
|
|
|
+from bpy_extras.image_utils import load_image
|
|
|
|
|
|
# #####################################################
|
|
|
# Generators
|
|
@@ -40,43 +40,43 @@ def setColor(c, t):
|
|
|
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
|
|
@@ -84,14 +84,14 @@ def create_materials(data, modelpath):
|
|
|
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()
|
|
@@ -99,13 +99,13 @@ def create_materials(data, modelpath):
|
|
|
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"]
|
|
@@ -114,23 +114,23 @@ def create_mesh_object(name, vertices, materials, face_data, flipYZ, recalculate
|
|
|
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]:
|
|
@@ -139,24 +139,24 @@ def create_mesh_object(name, vertices, materials, face_data, flipYZ, recalculate
|
|
|
|
|
|
# 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
|
|
|
+ # - 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),
|
|
|
+ # 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
|
|
@@ -169,45 +169,45 @@ def create_mesh_object(name, vertices, materials, face_data, flipYZ, recalculate
|
|
|
#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]:
|
|
@@ -218,19 +218,19 @@ def create_mesh_object(name, vertices, materials, face_data, flipYZ, recalculate
|
|
|
|
|
|
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)
|
|
@@ -238,47 +238,47 @@ def create_mesh_object(name, vertices, materials, face_data, flipYZ, recalculate
|
|
|
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.use_image = True
|
|
|
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)")
|
|
|
+ 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 = bpy.data.objects.new(name, me)
|
|
|
ob.data = me # link the mesh data to the object
|
|
|
|
|
|
|
|
@@ -286,14 +286,14 @@ def create_mesh_object(name, vertices, materials, face_data, flipYZ, recalculate
|
|
|
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" : [],
|
|
@@ -303,14 +303,14 @@ def extract_faces(data):
|
|
|
"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", [])
|
|
@@ -351,23 +351,23 @@ def extract_faces(data):
|
|
|
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
|
|
@@ -376,26 +376,26 @@ def extract_faces(data):
|
|
|
|
|
|
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
|
|
@@ -407,9 +407,9 @@ def extract_faces(data):
|
|
|
for i in range(nUvLayers):
|
|
|
|
|
|
faceUv = None
|
|
|
-
|
|
|
+
|
|
|
if hasFaceUv:
|
|
|
-
|
|
|
+
|
|
|
uvLayer = data["uvs"][ i ]
|
|
|
|
|
|
uvIndex = faces[ offset ]
|
|
@@ -419,7 +419,7 @@ def extract_faces(data):
|
|
|
v = uvLayer[ uvIndex * 2 + 1 ]
|
|
|
|
|
|
faceUv = [u, v]
|
|
|
-
|
|
|
+
|
|
|
result["faceUVs"][i].append(faceUv)
|
|
|
|
|
|
|
|
@@ -452,18 +452,18 @@ def extract_faces(data):
|
|
|
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
|
|
@@ -472,14 +472,14 @@ def extract_faces(data):
|
|
|
x = normals[ normalIndex ]
|
|
|
y = normals[ normalIndex + 1 ]
|
|
|
z = normals[ normalIndex + 2 ]
|
|
|
-
|
|
|
+
|
|
|
vertexNormals.append( [x, y, z] )
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
vertexNormals = None
|
|
|
-
|
|
|
+
|
|
|
result["vertexNormals"].append(vertexNormals)
|
|
|
|
|
|
|
|
@@ -487,11 +487,11 @@ def extract_faces(data):
|
|
|
|
|
|
colorIndex = faces[ offset ]
|
|
|
offset += 1
|
|
|
-
|
|
|
+
|
|
|
faceColor = hexToTuple( colors[ colorIndex ] )
|
|
|
|
|
|
else:
|
|
|
-
|
|
|
+
|
|
|
faceColor = None
|
|
|
|
|
|
result["faceColors"].append(faceColor)
|
|
@@ -510,14 +510,14 @@ def extract_faces(data):
|
|
|
vertexColors.append( color )
|
|
|
|
|
|
else:
|
|
|
-
|
|
|
+
|
|
|
vertexColors = None
|
|
|
-
|
|
|
+
|
|
|
result["vertexColors"].append(vertexColors)
|
|
|
|
|
|
|
|
|
return result
|
|
|
-
|
|
|
+
|
|
|
# #####################################################
|
|
|
# Utils
|
|
|
# #####################################################
|
|
@@ -527,10 +527,10 @@ def hexToTuple( hexColor ):
|
|
|
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 = []
|
|
@@ -546,7 +546,7 @@ def splitArray(data, chunkSize):
|
|
|
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)
|
|
@@ -563,13 +563,13 @@ def get_path(filepath):
|
|
|
# #####################################################
|
|
|
|
|
|
def load(operator, context, filepath, option_flip_yz = True, recalculate_normals = True):
|
|
|
-
|
|
|
+
|
|
|
print('\nimporting %r' % filepath)
|
|
|
|
|
|
time_main = time.time()
|
|
|
|
|
|
print("\tparsing JSON file...")
|
|
|
-
|
|
|
+
|
|
|
time_sub = time.time()
|
|
|
|
|
|
file = open(filepath, 'rU')
|
|
@@ -578,24 +578,24 @@ def load(operator, context, filepath, option_flip_yz = True, recalculate_normals
|
|
|
|
|
|
json_string = extract_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]
|
|
|
+ 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')
|
|
@@ -606,19 +606,19 @@ def load(operator, context, filepath, option_flip_yz = True, recalculate_normals
|
|
|
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 ...' % (
|
|
|
+
|
|
|
+ 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 = bpy.context.scene
|
|
|
scene.update()
|
|
|
|
|
|
time_new = time.time()
|