浏览代码

Added edges computation to OBJ converter.

If you want to get edges, run converter like with "-e" flag:

python convert_obj_three.py -i model.obj -o model.js -e

Output seems to match Blender exporter.
alteredq 14 年之前
父节点
当前提交
f7e3a80d70

+ 1 - 1
examples/obj/female02/Female02_bin.js

@@ -1,6 +1,6 @@
 // Converted from: ../../examples/obj/female02/female02.obj
 // Converted from: ../../examples/obj/female02/female02.obj
 //  vertices: 3274
 //  vertices: 3274
-//  faces: 6233 
+//  faces: 6233
 //  materials: 6
 //  materials: 6
 //
 //
 //  Generated with OBJ -> Three.js converter
 //  Generated with OBJ -> Three.js converter

文件差异内容过多而无法显示
+ 3 - 2
examples/obj/female02/Female02_slim.js


+ 1 - 1
examples/obj/lucy/Lucy100k_bin.js

@@ -1,6 +1,6 @@
 // Converted from: ../../examples/obj/lucy/lucy100k.obj
 // Converted from: ../../examples/obj/lucy/lucy100k.obj
 //  vertices: 50002
 //  vertices: 50002
-//  faces: 100000 
+//  faces: 100000
 //  materials: 0
 //  materials: 0
 //
 //
 //  Generated with OBJ -> Three.js converter
 //  Generated with OBJ -> Three.js converter

文件差异内容过多而无法显示
+ 3 - 2
examples/obj/lucy/Lucy100k_slim.js


+ 1 - 1
examples/obj/male02/Male02_bin.js

@@ -1,6 +1,6 @@
 // Converted from: ../../examples/obj/male02/male02.obj
 // Converted from: ../../examples/obj/male02/male02.obj
 //  vertices: 2746
 //  vertices: 2746
-//  faces: 5004 
+//  faces: 5004
 //  materials: 5
 //  materials: 5
 //
 //
 //  Generated with OBJ -> Three.js converter
 //  Generated with OBJ -> Three.js converter

文件差异内容过多而无法显示
+ 3 - 2
examples/obj/male02/Male02_slim.js


+ 1 - 1
examples/obj/ninja/NinjaLo_bin.js

@@ -1,6 +1,6 @@
 // Converted from: ../../examples/obj/ninja/ninjaHead_Low.obj
 // Converted from: ../../examples/obj/ninja/ninjaHead_Low.obj
 //  vertices: 4485
 //  vertices: 4485
-//  faces: 4810 
+//  faces: 4810
 //  materials: 0
 //  materials: 0
 //
 //
 //  Generated with OBJ -> Three.js converter
 //  Generated with OBJ -> Three.js converter

+ 1 - 1
examples/obj/torus/Torus_bin.js

@@ -1,6 +1,6 @@
 // Converted from: ../../examples/obj/torus/Torus.obj
 // Converted from: ../../examples/obj/torus/Torus.obj
 //  vertices: 576
 //  vertices: 576
-//  faces: 576 
+//  faces: 576
 //  materials: 1
 //  materials: 1
 //
 //
 //  Generated with OBJ -> Three.js converter
 //  Generated with OBJ -> Three.js converter

文件差异内容过多而无法显示
+ 3 - 2
examples/obj/torus/Torus_slim.js


+ 1 - 1
examples/obj/walt/WaltHead_bin.js

@@ -1,6 +1,6 @@
 // Converted from: ../../examples/obj/walt/WaltHead.obj
 // Converted from: ../../examples/obj/walt/WaltHead.obj
 //  vertices: 8146
 //  vertices: 8146
-//  faces: 16160 
+//  faces: 16160
 //  materials: 1
 //  materials: 1
 //
 //
 //  Generated with OBJ -> Three.js converter
 //  Generated with OBJ -> Three.js converter

文件差异内容过多而无法显示
+ 3 - 2
examples/obj/walt/WaltHead_slim.js


+ 1 - 1
src/core/Geometry.js

@@ -404,7 +404,7 @@ THREE.Geometry.prototype = {
 
 
 		function edge_hash( a, b ) {
 		function edge_hash( a, b ) {
 
 
-			 return Math.min( a, b ) + "_" + Math.max( a, b );
+			return Math.min( a, b ) + "_" + Math.max( a, b );
 
 
 		};
 		};
 
 

+ 118 - 13
utils/exporters/convert_obj_three.py

@@ -4,15 +4,28 @@
 How to use this converter
 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] [-b]
+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] [-e]
 
 
 Notes: 
 Notes: 
+    - flags
+        -i infile.obj			input OBJ file
+        -o outfile.js			output JS file
+        -m "morphfiles*.obj"	morph OBJ files (can use wildcards, enclosed in quotes multiple patterns separate by space)
+        -c "morphcolors*.obj"	morph colors OBJ files (can use wildcards, enclosed in quotes multiple patterns separate by space)
+        -a center|centerxz|top|bottom|none model alignment
+        -s smooth|flat			smooth = export vertex normals, flat = no normals (face normals computed in loader)
+        -t ascii|binary			export ascii or binary format (ascii has more features, binary just supports vertices, faces, normals, uvs and materials)
+        -d invert|normal		invert transparency
+        -b						bake material colors into face colors
+        -e						export edges
 
 
     - by default:
     - by default:
         converted model will be centered (middle of bounding box goes to 0,0,0)
         converted model will be centered (middle of bounding box goes to 0,0,0)
         use smooth shading (if there were vertex normals in the original model)
         use smooth shading (if there were vertex normals in the original model)
         will be in ASCII format
         will be in ASCII format
         original model is assumed to use non-inverted transparency / dissolve (0.0 fully transparent, 1.0 fully opaque)
         original model is assumed to use non-inverted transparency / dissolve (0.0 fully transparent, 1.0 fully opaque)
+        no face colors baking
+        no edges export
  
  
     - binary conversion will create two files: 
     - binary conversion will create two files: 
         outfile.js  (materials)
         outfile.js  (materials)
@@ -62,10 +75,7 @@ Current limitations
     - for the moment, only diffuse color and texture are used 
     - for the moment, only diffuse color and texture are used 
       (will need to extend shaders / renderers / materials in Three)
       (will need to extend shaders / renderers / materials in Three)
      
      
-    - models can have more than 65,536 vertices,
-      but in most cases it will not work well with browsers,
-      which currently seem to have troubles with handling
-      large JS files
+    - models can have more than 65,536 vertices
        
        
     - texture coordinates can be wrong in canvas renderer
     - texture coordinates can be wrong in canvas renderer
       (there is crude normalization, but it doesn't
       (there is crude normalization, but it doesn't
@@ -138,6 +148,7 @@ TYPE = "ascii"          # ascii binary
 TRANSPARENCY = "normal" # normal invert
 TRANSPARENCY = "normal" # normal invert
 
 
 BAKE_COLORS = False
 BAKE_COLORS = False
+EXPORT_EDGES = False
 
 
 # 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
 # white, red, green, blue, yellow, cyan, magenta
@@ -149,11 +160,12 @@ COLORS = [0xeeeeee, 0xee0000, 0x00ee00, 0x0000ee, 0xeeee00, 0x00eeee, 0xee00ee]
 TEMPLATE_FILE_ASCII = u"""\
 TEMPLATE_FILE_ASCII = u"""\
 // Converted from: %(fname)s
 // Converted from: %(fname)s
 //  vertices: %(nvertex)d
 //  vertices: %(nvertex)d
-//  faces: %(nface)d 
+//  faces: %(nface)d
 //  normals: %(nnormal)d
 //  normals: %(nnormal)d
 //  colors: %(ncolor)d
 //  colors: %(ncolor)d
-//  uvs: %(nuv)d 
+//  uvs: %(nuv)d
 //  materials: %(nmaterial)d
 //  materials: %(nmaterial)d
+//  edges: %(nedge)d
 //
 //
 //  Generated with OBJ -> Three.js converter
 //  Generated with OBJ -> Three.js converter
 //  http://github.com/alteredq/three.js/blob/master/utils/exporters/convert_obj_three.py
 //  http://github.com/alteredq/three.js/blob/master/utils/exporters/convert_obj_three.py
@@ -177,7 +189,9 @@ var model = {
 
 
     "uvs": [[%(uvs)s]],
     "uvs": [[%(uvs)s]],
 
 
-    "faces": [%(faces)s]
+    "faces": [%(faces)s],
+
+    "edges" : [%(edges)s]
 
 
 };
 };
 
 
@@ -187,7 +201,7 @@ postMessage( model );
 TEMPLATE_FILE_BIN = u"""\
 TEMPLATE_FILE_BIN = u"""\
 // Converted from: %(fname)s
 // Converted from: %(fname)s
 //  vertices: %(nvertex)d
 //  vertices: %(nvertex)d
-//  faces: %(nface)d 
+//  faces: %(nface)d
 //  materials: %(nmaterial)d
 //  materials: %(nmaterial)d
 //
 //
 //  Generated with OBJ -> Three.js converter
 //  Generated with OBJ -> Three.js converter
@@ -213,6 +227,7 @@ TEMPLATE_N = "%f,%f,%f"
 TEMPLATE_UV = "%f,%f"
 TEMPLATE_UV = "%f,%f"
 TEMPLATE_COLOR = "%.3f,%.3f,%.3f"
 TEMPLATE_COLOR = "%.3f,%.3f,%.3f"
 TEMPLATE_COLOR_DEC = "%d"
 TEMPLATE_COLOR_DEC = "%d"
+TEMPLATE_EDGE = "%d,%d"
 
 
 TEMPLATE_MORPH_VERTICES = '\t{ "name": "%s", "vertices": [%s] }'
 TEMPLATE_MORPH_VERTICES = '\t{ "name": "%s", "vertices": [%s] }'
 TEMPLATE_MORPH_COLORS   = '\t{ "name": "%s", "colors": [%s] }'
 TEMPLATE_MORPH_COLORS   = '\t{ "name": "%s", "colors": [%s] }'
@@ -339,6 +354,9 @@ def normalize(v):
         v[1] /= l
         v[1] /= l
         v[2] /= l
         v[2] /= l
 
 
+def veckey3(v):
+    return round(v[0], 6), round(v[1], 6), round(v[2], 6)
+
 # #####################################################
 # #####################################################
 # MTL parser
 # MTL parser
 # #####################################################
 # #####################################################
@@ -675,6 +693,9 @@ def generate_color_rgb(c):
 def generate_color_decimal(c):
 def generate_color_decimal(c):
     return TEMPLATE_COLOR_DEC % hexcolor(c)
     return TEMPLATE_COLOR_DEC % hexcolor(c)
     
     
+def generate_edge(e):
+    return TEMPLATE_EDGE % (e[0], e[1])
+    
 # #####################################################
 # #####################################################
 # Morphs
 # Morphs
 # #####################################################
 # #####################################################
@@ -812,6 +833,74 @@ def generate_morph_colors(colorfiles, n_vertices, n_faces):
     
     
     return morphColors, colorFaces, materialColors
     return morphColors, colorFaces, materialColors
 
 
+# #####################################################
+# Edges
+# #####################################################
+def edge_hash(a, b):
+    return "%d_%d" % (min(a, b), max(a, b))
+    
+def add_unique_edge(a, b, edge_set, edges):
+    h = edge_hash(a[0], b[0])
+    if h not in edge_set:
+        x = min(a[1], b[1])
+        y = max(a[1], b[1])
+        edges.append([x, y])
+        edge_set.add(h)
+    
+def compute_edges(faces, vertices):
+    edges = []
+    
+    # compute unique vertices
+
+    unique_vertices = {}
+    vertex_count = 0
+    
+    for i, v in enumerate(vertices):
+        key = veckey3(v)
+        if key not in unique_vertices:
+            unique_vertices[key] = [vertex_count, i]
+            vertex_count += 1
+
+    # find edges between unique vertices
+    
+    edge_set = set()    
+
+    for f in faces:
+        vertex_indices = f["vertex"]
+        unique_indices = []
+
+        for vi in vertex_indices:
+            v = vertices[vi - 1]
+            key = veckey3(v)
+            unique_indices.append(unique_vertices[key])
+        
+        if len(unique_indices) == 3:
+            a = unique_indices[0]
+            b = unique_indices[1]
+            c = unique_indices[2]
+            
+            add_unique_edge(a, b, edge_set, edges)
+            add_unique_edge(b, c, edge_set, edges)
+            add_unique_edge(a, c, edge_set, edges)
+
+        elif len(unique_indices) == 4:
+            a = unique_indices[0]
+            b = unique_indices[1]
+            c = unique_indices[2]
+            d = unique_indices[3]
+            
+            # this should be inside edge of quad, should it go in?
+            # add_unique_edge(b, d, edge_set, edges) 
+            
+            add_unique_edge(a, b, edge_set, edges)
+            add_unique_edge(a, d, edge_set, edges)
+            add_unique_edge(b, c, edge_set, edges)
+            add_unique_edge(c, d, edge_set, edges)
+
+    edges.sort()
+    
+    return edges
+
 # #####################################################
 # #####################################################
 # Materials
 # Materials
 # #####################################################
 # #####################################################
@@ -1034,10 +1123,10 @@ def convert_ascii(infile, morphfiles, colorfiles, outfile):
     morphColors, colorFaces, materialColors = generate_morph_colors(colorfiles, n_vertices, n_faces)    
     morphColors, colorFaces, materialColors = generate_morph_colors(colorfiles, n_vertices, n_faces)    
 
 
     # generate colors string
     # generate colors string
-    
+
     ncolor = 0
     ncolor = 0
     colors_string = ""
     colors_string = ""
-    
+
     if len(colorFaces) < len(faces):
     if len(colorFaces) < len(faces):
         colorFaces = faces
         colorFaces = faces
         materialColors = extract_material_colors(materials, mtllib, infile)
         materialColors = extract_material_colors(materials, mtllib, infile)
@@ -1046,6 +1135,16 @@ def convert_ascii(infile, morphfiles, colorfiles, outfile):
         colors_string = ",".join(generate_color_decimal(c) for c in materialColors)
         colors_string = ",".join(generate_color_decimal(c) for c in materialColors)
         ncolor = len(materialColors)
         ncolor = len(materialColors)
         
         
+    # generate edges string
+    
+    nedge = 0
+    edges_string = ""
+    
+    if EXPORT_EDGES:
+        edges = compute_edges(faces, vertices)
+        nedge = len(edges) 
+        edges_string  = ",".join(generate_edge(e) for e in edges)
+        
     # generate ascii model string
     # generate ascii model string
 
 
     text = TEMPLATE_FILE_ASCII % {
     text = TEMPLATE_FILE_ASCII % {
@@ -1057,6 +1156,7 @@ def convert_ascii(infile, morphfiles, colorfiles, outfile):
     "nnormal"   : nnormal,
     "nnormal"   : nnormal,
     "ncolor"    : ncolor,
     "ncolor"    : ncolor,
     "nmaterial" : len(materials),
     "nmaterial" : len(materials),
+    "nedge"     : nedge,
 
 
     "materials" : generate_materials_string(materials, mtllib, infile),
     "materials" : generate_materials_string(materials, mtllib, infile),
 
 
@@ -1068,7 +1168,9 @@ def convert_ascii(infile, morphfiles, colorfiles, outfile):
     "morphTargets"  : morphTargets,
     "morphTargets"  : morphTargets,
     "morphColors"   : morphColors,
     "morphColors"   : morphColors,
     
     
-    "faces"     : ",".join(generate_face(f, fc) for f, fc in zip(faces, colorFaces))
+    "faces"     : ",".join(generate_face(f, fc) for f, fc in zip(faces, colorFaces)),
+        
+    "edges"    : edges_string
     }
     }
     
     
     out = open(outfile, "w")
     out = open(outfile, "w")
@@ -1403,7 +1505,7 @@ if __name__ == "__main__":
     
     
     # get parameters from the command line
     # get parameters from the command line
     try:
     try:
-        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="])
+        opts, args = getopt.getopt(sys.argv[1:], "hbei:m:c:b:o:a:s:t:d:", ["help", "bakecolors", "edges", "input=", "morphs=", "colors=", "output=", "align=", "shading=", "type=", "dissolve="])
     
     
     except getopt.GetoptError:
     except getopt.GetoptError:
         usage()
         usage()
@@ -1449,6 +1551,9 @@ if __name__ == "__main__":
         elif o in ("-b", "--bakecolors"):
         elif o in ("-b", "--bakecolors"):
             BAKE_COLORS = True
             BAKE_COLORS = True
 
 
+        elif o in ("-e", "--edges"):
+            EXPORT_EDGES = True
+
     if infile == "" or outfile == "":
     if infile == "" or outfile == "":
         usage()
         usage()
         sys.exit(2)
         sys.exit(2)

部分文件因为文件数量过多而无法显示