diff --git a/io_scene_x3d/__init__.py b/io_scene_x3d/__init__.py
index 492de10c2c10bd62e5e1cb80931ef491d39ab471..b795f6ab0f93b20ae4f23a05dc4ecd6e9dd2cf70 100644
--- a/io_scene_x3d/__init__.py
+++ b/io_scene_x3d/__init__.py
@@ -96,7 +96,7 @@ class ExportX3D(bpy.types.Operator, ExportHelper):
 
     use_selection = BoolProperty(name="Selection Only", description="Export selected objects only", default=False)
     use_apply_modifiers = BoolProperty(name="Apply Modifiers", description="Use transformed mesh data from each object", default=True)
-    use_triangulate = BoolProperty(name="Triangulate", description="Write quads into 'IndexedTriangleSet'", default=False)
+    use_triangulate = BoolProperty(name="Triangulate", description="Write quads into 'IndexedTriangleSet'", default=True)
     use_compress = BoolProperty(name="Compress", description="GZip the resulting file, requires a full python install", default=False)
 
     axis_forward = EnumProperty(
diff --git a/io_scene_x3d/export_x3d.py b/io_scene_x3d/export_x3d.py
index ef20d9df1c441d7027a66a8a7a74684817e4fec1..aebc2f25ece3cc634a7bfe4dec503348ec358df7 100644
--- a/io_scene_x3d/export_x3d.py
+++ b/io_scene_x3d/export_x3d.py
@@ -341,8 +341,10 @@ def export(file,
 
             mesh_materials_use_face_texture = [getattr(material, "use_face_texture", True) for material in mesh_materials]
 
+            # fast access!
             mesh_faces = mesh.faces[:]
             mesh_faces_materials = [f.material_index for f in mesh_faces]
+            mesh_faces_vertices = [f.vertices[:] for f in mesh_faces]
 
             if is_uv and True in mesh_materials_use_face_texture:
                 mesh_faces_image = [(fuv.image if (mesh_materials_use_face_texture[mesh_faces_materials[i]] and fuv.use_image) else mesh_material_images[mesh_faces_materials[i]]) for i, fuv in enumerate(mesh.uv_textures.active.data)]
@@ -423,125 +425,192 @@ def export(file,
                     ident = ident[:-1]
                     fw("%s</Appearance>\n" % ident)
 
+                    mesh_faces_col = mesh.vertex_colors.active.data if is_col else None
+                    mesh_faces_uv = mesh.uv_textures.active.data if is_uv else None
+
                     #-- IndexedFaceSet or IndexedLineSet
                     if EXPORT_TRI:
                         fw("%s<IndexedTriangleSet " % ident)
+                        ident += "\t"
+
+                        # --- Write IndexedTriangleSet Attributes (same as IndexedFaceSet)
+                        fw("solid=\"%s\" " % ("true" if mesh.show_double_sided else "false"))
+                        if is_smooth:
+                            fw("creaseAngle=\"%.4g\" " % mesh.auto_smooth_angle)
+
+                        slot_uv = None
+                        slot_col = None
+
+                        if is_uv and is_col:
+                            slot_uv = 0
+                            slot_col = 1
+
+                            def vertex_key(fidx, f_cnr_idx):
+                                return (
+                                    mesh_faces_uv[fidx].uv[f_cnr_idx][:],
+                                    getattr(mesh_faces_col[fidx], "color%d" % (f_cnr_idx + 1))[:],
+                                )
+                        elif is_uv:
+                            slot_uv = 0
+
+                            def vertex_key(fidx, f_cnr_idx):
+                                return (
+                                    mesh_faces_uv[fidx].uv[f_cnr_idx].to_tuple(4),
+                                )
+                        elif is_col:
+                            slot_col = 0
+
+                            def vertex_key(fidx, f_cnr_idx):
+                                return (
+                                    getattr(mesh_faces_col[fidx], "color%d" % (f_cnr_idx))[:],
+                                )
+                        else:
+                            # ack, not especially efficient in this case
+                            def vertex_key(fidx, f_cnr_idx):
+                                return None
+
+                        # build a mesh mapping dict
+                        vertex_hash = [{} for i in range(len(mesh.vertices))]
+                        # worst case every face is a quad
+                        face_tri_list = [[None, None, None] for i in range(len(mesh.faces) * 2)]
+                        vert_tri_list = []
+                        totvert = 0
+                        totface = 0
+                        temp_face = [None] * 4
+                        for i in face_group:
+                            fv = mesh_faces_vertices[i]
+                            for j, v_idx in enumerate(fv):
+                                key = vertex_key(i, j)
+                                vh = vertex_hash[v_idx]
+                                x3d_v = vh.get(key)
+                                if x3d_v is None:
+                                    x3d_v = key, v_idx, totvert
+                                    vh[key] = x3d_v
+                                    # key / original_vertex / new_vertex
+                                    vert_tri_list.append(x3d_v)
+                                    totvert += 1
+                                temp_face[j] = x3d_v
+
+                            if len(fv) == 4:
+                                f_iter = ((0, 1, 2), (0, 2, 3))
+                            else:
+                                f_iter = ((0, 1, 2), )
+
+                            for f_it in f_iter:
+                                # loop over a quad as 2 tris
+                                f_tri = face_tri_list[totface]
+                                for ji, j in enumerate(f_it):
+                                    f_tri[ji] = temp_face[j]
+                                # quads run this twice
+                                totface += 1
+
+                        # clear unused faces
+                        face_tri_list[totface:] = []
+
+                        fw("index=\"")
+                        for x3d_f in face_tri_list:
+                            fw("%i %i %i " % (x3d_f[0][2], x3d_f[1][2], x3d_f[2][2]))
+                        fw("\" ")
+
+                        # close IndexedTriangleSet
+                        fw(">\n")
+
+                        fw("%s<Coordinate " % ident)
+                        fw("point=\"")
+                        mesh_vertices = mesh.vertices
+                        for x3d_v in vert_tri_list:
+                            fw("%.6g %.6g %.6g, " % mesh_vertices[x3d_v[1]].co[:])
+                        fw("\" />\n")
+
+                        if is_uv:
+                            fw("%s<TextureCoordinate point=\"" % ident)
+                            for x3d_v in vert_tri_list:
+                                fw("%.4g %.4g, " % x3d_v[0][slot_uv])
+                            fw("\" />\n")
+
+                        if is_col:
+                            fw("%s<Color color=\"" % ident)
+                            for x3d_v in vert_tri_list:
+                                fw("%.3g %.3g %.3g, " % x3d_v[0][slot_col])
+                            fw("\" />\n")
+
+                        fw("%s</IndexedTriangleSet>\n" % ident)
+
                     else:
                         fw("%s<IndexedFaceSet " % ident)
-                    ident += "\t"
+                        ident += "\t"
 
-                    # --- Write IndexedFaceSet Attributes
-                    if mesh.show_double_sided:
-                        fw("solid=\"true\" ")
-                    else:
-                        fw("solid=\"false\" ")
+                        # --- Write IndexedFaceSet Attributes (same as IndexedTriangleSet)
+                        fw("solid=\"%s\" " % ("true" if mesh.show_double_sided else "false"))
+                        if is_smooth:
+                            fw("creaseAngle=\"%.4g\" " % mesh.auto_smooth_angle)
 
-                    if is_smooth:
-                        fw("creaseAngle=\"%.4g\" " % mesh.auto_smooth_angle)
+                        # IndexedTriangleSet assumes true
+                        if is_col:
+                            fw("colorPerVertex=\"false\" ")
 
-                    if is_uv:
-                        if EXPORT_TRI:
-                            fw("texIndex=\"")
-                        else:
+                        # for IndexedTriangleSet we use a uv per vertex so this isnt needed.
+                        if is_uv:
                             fw("texCoordIndex=\"")
 
-                        j = 0
-                        if EXPORT_TRI:
+                            j = 0
                             for i in face_group:
-                                if len(mesh_faces[i].vertices) == 4:
-                                    fw("%d %d %d " % (j, j + 1, j + 2))
-                                    fw("%d %d %d " % (j, j + 2, j + 3))
-                                    j += 4
-                                else:
-                                    fw("%d %d %d " % (j, j + 1, j + 2))
-                                    j += 3
-                        else:
-                            for i in face_group:
-                                if len(mesh_faces[i].vertices) == 4:
+                                if len(mesh_faces_vertices[i]) == 4:
                                     fw("%d %d %d %d -1, " % (j, j + 1, j + 2, j + 3))
                                     j += 4
                                 else:
                                     fw("%d %d %d -1, " % (j, j + 1, j + 2))
                                     j += 3
-                        fw("\" ")
-                        # --- end texCoordIndex
+                            fw("\" ")
+                            # --- end texCoordIndex
 
-                    if is_col:
-                        fw("colorPerVertex=\"false\" ")
-
-                    if True:
-                        # "coordIndex"
-                        if EXPORT_TRI:
-                            fw("index=\"")
-                        else:
+                        if True:
                             fw("coordIndex=\"")
-
-                        if EXPORT_TRI:
-                            for i in face_group:
-                                fv = mesh_faces[i].vertices[:]
-                                if len(fv) == 3:
-                                    fw("%i %i %i " % fv)
-                                else:
-                                    fw("%i %i %i " % (fv[0], fv[1], fv[2]))
-                                    fw("%i %i %i " % (fv[0], fv[2], fv[3]))
-                        else:
                             for i in face_group:
-                                fv = mesh_faces[i].vertices[:]
+                                fv = mesh_faces_vertices[i]
                                 if len(fv) == 3:
                                     fw("%i %i %i -1, " % fv)
                                 else:
                                     fw("%i %i %i %i -1, " % fv)
 
-                        fw("\" ")
-                        # --- end coordIndex
+                            fw("\" ")
+                            # --- end coordIndex
 
-                    # close IndexedFaceSet
-                    fw(">\n")
+                        # close IndexedFaceSet
+                        fw(">\n")
 
-                    # --- Write IndexedFaceSet Elements
-                    if True:
-                        if is_coords_written:
-                            fw("%s<Coordinate USE=\"%s%s\" />\n" % (ident, "coord_", mesh_name_x3d))
-                        else:
-                            fw("%s<Coordinate DEF=\"%s%s\" " % (ident, "coord_", mesh_name_x3d))
-                            fw("point=\"")
-                            for v in mesh.vertices:
-                                fw("%.6g %.6g %.6g, " % v.co[:])
+                        # --- Write IndexedFaceSet Elements
+                        if True:
+                            if is_coords_written:
+                                fw("%s<Coordinate USE=\"%s%s\" />\n" % (ident, "coord_", mesh_name_x3d))
+                            else:
+                                fw("%s<Coordinate DEF=\"%s%s\" " % (ident, "coord_", mesh_name_x3d))
+                                fw("point=\"")
+                                for v in mesh.vertices:
+                                    fw("%.6g %.6g %.6g, " % v.co[:])
+                                fw("\" />\n")
+                                is_coords_written = True
+
+                        if is_uv:
+                            fw("%s<TextureCoordinate point=\"" % ident)
+                            for i in face_group:
+                                for uv in mesh_faces_uv[i].uv:
+                                    fw("%.4g %.4g, " % uv[:])
+                            del mesh_faces_uv
                             fw("\" />\n")
-                            is_coords_written = True
 
-                    if is_uv:
-                        fw("%s<TextureCoordinate point=\"" % ident)
-                        mesh_faces_uv = mesh.uv_textures.active.data
-                        for i in face_group:
-                            for uv in mesh_faces_uv[i].uv:
-                                fw("%.4g %.4g, " % uv[:])
-                        del mesh_faces_uv
-                        fw("\" />\n")
-
-                    if is_col:
-                        fw("%s<Color color=\"" % ident)
-                        # XXX, 1 color per face, only
-                        mesh_faces_col = mesh.vertex_colors.active.data
-                        if EXPORT_TRI:
-                            for i in face_group:
-                                fw("%.3g %.3g %.3g, " % mesh_faces_col[i].color1[:])
-                                if len(mesh_faces[i].vertices) == 4:
-                                    fw("%.3g %.3g %.3g, " % mesh_faces_col[i].color1[:])
-                        else:
+                        if is_col:
+                            fw("%s<Color color=\"" % ident)
+                            # XXX, 1 color per face, only
                             for i in face_group:
                                 fw("%.3g %.3g %.3g, " % mesh_faces_col[i].color1[:])
-                        del mesh_faces_col
-                        fw("\" />\n")
+                            fw("\" />\n")
 
-                    #--- output vertexColors
+                        #--- output vertexColors
 
-                    #--- output closing braces
-                    ident = ident[:-1]
+                        #--- output closing braces
+                        ident = ident[:-1]
 
-                    if EXPORT_TRI:
-                        fw("%s</IndexedTriangleSet>\n" % ident)
-                    else:
                         fw("%s</IndexedFaceSet>\n" % ident)
 
                     ident = ident[:-1]