提交 00b0f6df 编写于 作者: A alteredq

Fleshed out more face color pipeline (OBJ converter, Blender importer and loaders).

- OBJ converter now has "-b" option for baking materials' diffuse colors into face colors
  (if there are morph colormap OBJs/MTLs, first colormap will be used)
  (material will get "vertexColors" property set to "face")

- Blender importer now bakes JSON face colors into Blender vertex colors

- Loader now handles "material.vertexColors" with more options
    - nonexistant property or false will set material to THREE.NoColors
    - "face" will set material to THREE.FaceColors
    - anything else will get THREE.VertexColors

- fixed bug in JSONLoader where face colors were not properly initialized
上级 db96a4a8
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -258,7 +258,9 @@ THREE.JSONLoader.prototype.createModel = function ( json, callback, texture_path
if ( hasFaceColor ) {
color = new THREE.Color( faces[ offset ++ ] );
colorIndex = faces[ offset ++ ];
color = new THREE.Color( colors[ colorIndex ] );
face.color = color;
}
......
......@@ -120,13 +120,15 @@ THREE.Loader.prototype = {
}
var material, mtype, mpars, texture, color;
var material, mtype, mpars, texture, color, vertexColors;
// defaults
mtype = "MeshLambertMaterial";
mpars = { color: 0xeeeeee, opacity: 1.0, map: null, lightMap: null, vertexColors: m.vertexColors ? THREE.VertexColors : false, wireframe: m.wireframe };
vertexColors
mpars = { color: 0xeeeeee, opacity: 1.0, map: null, lightMap: null, wireframe: m.wireframe };
// parameters from model file
......@@ -157,6 +159,20 @@ THREE.Loader.prototype = {
}
if ( m.vertexColors !== undefined ) {
if ( m.vertexColors == "face" ) {
mpars.vertexColors = THREE.FaceColors;
} else if ( m.vertexColors ) {
mpars.vertexColors = THREE.VertexColors;
}
}
if ( m.mapDiffuse && texture_path ) {
texture = document.createElement( 'canvas' );
......
......@@ -108,11 +108,12 @@ def create_materials(data, modelpath):
def create_mesh_object(name, vertices, materials, face_data, flipYZ, recalculate_normals):
faces = face_data["faces"]
faces = face_data["faces"]
vertexNormals = face_data["vertexNormals"]
vertexColors = face_data["vertexColors"]
vertexUVs = face_data["vertexUVs"]
vertexColors = face_data["vertexColors"]
vertexUVs = face_data["vertexUVs"]
faceMaterials = face_data["materials"]
faceColors = face_data["faceColors"]
edges = []
......@@ -200,7 +201,29 @@ def create_mesh_object(name, vertices, materials, face_data, flipYZ, recalculate
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
......@@ -284,6 +307,7 @@ def extract_faces(data):
"hasVertexNormals" : False,
"hasVertexUVs" : False,
"hasVertexColors" : False,
"hasFaceColors" : False,
"hasMaterials" : False
}
......@@ -325,6 +349,7 @@ def extract_faces(data):
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
......
......@@ -4,7 +4,7 @@
How to use this converter
-------------------------
python convert_obj_three.py -i infile.obj -o outfile.js [-m morphfiles*.obj] [-c morphcolors*.obj] [-a center|centerxz|top|bottom|none] [-s smooth|flat] [-t ascii|binary] [-d invert|normal]
python convert_obj_three.py -i infile.obj -o outfile.js [-m morphfiles*.obj] [-c morphcolors*.obj] [-a center|centerxz|top|bottom|none] [-s smooth|flat] [-t ascii|binary] [-d invert|normal] [-b]
Notes:
......@@ -137,6 +137,8 @@ SHADING = "smooth" # smooth flat
TYPE = "ascii" # ascii binary
TRANSPARENCY = "normal" # normal invert
BAKE_COLORS = False
# 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]
......@@ -149,6 +151,7 @@ TEMPLATE_FILE_ASCII = u"""\
// vertices: %(nvertex)d
// faces: %(nface)d
// normals: %(nnormal)d
// colors: %(ncolor)d
// uvs: %(nuv)d
// materials: %(nmaterial)d
//
......@@ -170,6 +173,8 @@ var model = {
"normals": [%(normals)s],
"colors": [%(colors)s],
"uvs": [[%(uvs)s]],
"faces": [%(faces)s]
......@@ -207,6 +212,7 @@ TEMPLATE_VERTEX = "%f,%f,%f"
TEMPLATE_N = "%f,%f,%f"
TEMPLATE_UV = "%f,%f"
TEMPLATE_COLOR = "%.3f,%.3f,%.3f"
TEMPLATE_COLOR_DEC = "%d"
TEMPLATE_MORPH_VERTICES = '\t{ "name": "%s", "vertices": [%s] }'
TEMPLATE_MORPH_COLORS = '\t{ "name": "%s", "colors": [%s] }'
......@@ -579,7 +585,7 @@ def setBit(value, position, on):
mask = ~(1 << position)
return (value & mask)
def generate_face(f):
def generate_face(f, fc):
isTriangle = ( len(f['vertex']) == 3 )
if isTriangle:
......@@ -595,7 +601,7 @@ def generate_face(f):
hasFaceNormals = False # don't export any face normals (as they are computed in engine)
hasFaceVertexNormals = ( len(f["normal"]) >= nVertices and SHADING == "smooth" )
hasFaceColors = False # not supported in OBJ
hasFaceColors = BAKE_COLORS
hasFaceVertexColors = False # not supported in OBJ
faceType = 0
......@@ -617,12 +623,15 @@ def generate_face(f):
# material index
# face uvs index
# face vertex uvs indices
# face normal index
# face vertex normals indices
# face color index
# face vertex colors indices
faceData.append(faceType)
# must clamp in case on polygons bigger than quads
for i in xrange(nVertices):
index = f['vertex'][i] - 1
faceData.append(index)
......@@ -638,12 +647,19 @@ def generate_face(f):
for i in xrange(nVertices):
index = f['normal'][i] - 1
faceData.append(index)
if hasFaceColors:
index = fc['material']
faceData.append(index)
return ",".join( map(str, faceData) )
# #####################################################
# Generator - chunks
# #####################################################
def hexcolor(c):
return ( int(c[0] * 255) << 16 ) + ( int(c[1] * 255) << 8 ) + int(c[2] * 255)
def generate_vertex(v):
return TEMPLATE_VERTEX % (v[0], v[1], v[2])
......@@ -656,6 +672,9 @@ def generate_uv(uv):
def generate_color_rgb(c):
return TEMPLATE_COLOR % (c[0], c[1], c[2])
def generate_color_decimal(c):
return TEMPLATE_COLOR_DEC % hexcolor(c)
# #####################################################
# Morphs
# #####################################################
......@@ -667,31 +686,36 @@ def generate_morph_color(name, colors):
color_string = ",".join(generate_color_rgb(c) for c in colors)
return TEMPLATE_MORPH_COLORS % (name, color_string)
def extract_face_colors(faces, materials, mtlfilename, basename):
# extract diffuse colors from MTL materials
def extract_material_colors(materials, mtlfilename, basename):
"""Extract diffuse colors from MTL materials
"""
if not materials:
materials = { 'default': 0 }
mtl = create_materials(materials, mtlfilename, basename)
mtl_array = []
mtlColorArraySrt = []
for m in mtl:
if m in materials:
index = materials[m]
color = mtl[m].get("colorDiffuse", [1,0,0])
mtl_array.append([index, color])
mtlColorArraySrt.append([index, color])
mtl_array.sort()
mtlColorArraySrt.sort()
mtlColorArray = [x[1] for x in mtlColorArraySrt]
# assign colors to faces
return mtlColorArray
def extract_face_colors(faces, material_colors):
"""Extract colors from materials and assign them to faces
"""
faceColors = []
for face in faces:
material_index = face['material']
faceColors.append(mtl_array[material_index][1])
faceColors.append(material_colors[material_index])
return faceColors
......@@ -744,7 +768,9 @@ def generate_morph_targets(morphfiles, n_vertices, infile):
def generate_morph_colors(colorfiles, n_vertices, n_faces):
morphColorData = []
colorFaces = []
materialColors = []
for mfilepattern in colorfiles.split():
matches = glob.glob(mfilepattern)
......@@ -768,15 +794,23 @@ def generate_morph_colors(colorfiles, n_vertices, n_faces):
else:
morphFaceColors = extract_face_colors(morphFaces, morphMaterials, morphMtllib, normpath)
morphMaterialColors = extract_material_colors(morphMaterials, morphMtllib, normpath)
morphFaceColors = extract_face_colors(morphFaces, morphMaterialColors)
morphColorData.append((get_name(name), morphFaceColors))
# take first color map for baking into face colors
if len(colorFaces) == 0:
colorFaces = morphFaces
materialColors = morphMaterialColors
print "adding [%s] with %d face colors" % (name, len(morphFaceColors))
morphColors = ""
if len(morphColorData):
morphColors = "\n%s\n\t" % ",\n".join(generate_morph_color(name, colors) for name, colors in morphColorData)
return morphColors
return morphColors, colorFaces, materialColors
# #####################################################
# Materials
......@@ -800,6 +834,8 @@ def generate_color(i):
def value2string(v):
if type(v)==str and v[0:2] != "0x":
return '"%s"' % v
elif type(v) == bool:
return str(v).lower()
return str(v)
def generate_materials(mtl, materials):
......@@ -822,6 +858,9 @@ def generate_materials(mtl, materials):
mtl[m]['DbgIndex'] = index
mtl[m]['DbgColor'] = generate_color(index)
if BAKE_COLORS:
mtl[m]['vertexColors'] = "face"
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])
......@@ -992,8 +1031,21 @@ def convert_ascii(infile, morphfiles, colorfiles, outfile):
# extract morph colors
morphColors = generate_morph_colors(colorfiles, n_vertices, n_faces)
morphColors, colorFaces, materialColors = generate_morph_colors(colorfiles, n_vertices, n_faces)
# generate colors string
ncolor = 0
colors_string = ""
if len(colorFaces) < len(faces):
colorFaces = faces
materialColors = extract_material_colors(materials, mtllib, infile)
if BAKE_COLORS:
colors_string = ",".join(generate_color_decimal(c) for c in materialColors)
ncolor = len(materialColors)
# generate ascii model string
text = TEMPLATE_FILE_ASCII % {
......@@ -1003,18 +1055,20 @@ def convert_ascii(infile, morphfiles, colorfiles, outfile):
"nface" : len(faces),
"nuv" : len(uvs),
"nnormal" : nnormal,
"ncolor" : ncolor,
"nmaterial" : len(materials),
"materials" : generate_materials_string(materials, mtllib, infile),
"normals" : normals_string,
"colors" : colors_string,
"uvs" : ",".join(generate_uv(uv) for uv in uvs),
"vertices" : ",".join(generate_vertex(v) for v in vertices),
"morphTargets" : morphTargets,
"morphColors" : morphColors,
"faces" : ",".join(generate_face(f) for f in faces)
"faces" : ",".join(generate_face(f, fc) for f, fc in zip(faces, colorFaces))
}
out = open(outfile, "w")
......@@ -1349,7 +1403,7 @@ if __name__ == "__main__":
# get parameters from the command line
try:
opts, args = getopt.getopt(sys.argv[1:], "hi:m:c:o:a:s:t:d:", ["help", "input=", "morphs=", "colors=", "output=", "align=", "shading=", "type=", "dissolve="])
opts, args = getopt.getopt(sys.argv[1:], "hbi:m:c:b:o:a:s:t:d:", ["help", "bakecolors", "input=", "morphs=", "colors=", "output=", "align=", "shading=", "type=", "dissolve="])
except getopt.GetoptError:
usage()
......@@ -1392,6 +1446,9 @@ if __name__ == "__main__":
if a in ("normal", "invert"):
TRANSPARENCY = a
elif o in ("-b", "--bakecolors"):
BAKE_COLORS = True
if infile == "" or outfile == "":
usage()
sys.exit(2)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册