Commit: efab0bc704ece3a79dba5da890891df2acb1c22a
Author: Ankit Meel
Date:   Fri Aug 21 00:37:42 2020 +0530
Branches: soc-2020-io-performance
https://developer.blender.org/rBefab0bc704ece3a79dba5da890891df2acb1c22a

Commit as it is ngon-tessellate.

The code is totally untested and will very likely crash.

===================================================================

M       source/blender/io/wavefront_obj/CMakeLists.txt
A       source/blender/io/wavefront_obj/intern/mesh_utils.cc
A       source/blender/io/wavefront_obj/intern/mesh_utils.hh
M       source/blender/io/wavefront_obj/intern/wavefront_obj_im_mesh.cc
M       source/blender/io/wavefront_obj/intern/wavefront_obj_im_mesh.hh
M       source/blender/io/wavefront_obj/intern/wavefront_obj_im_objects.cc
M       source/blender/io/wavefront_obj/intern/wavefront_obj_im_objects.hh

===================================================================

diff --git a/source/blender/io/wavefront_obj/CMakeLists.txt 
b/source/blender/io/wavefront_obj/CMakeLists.txt
index e270ac407c0..c73f5fa32bb 100644
--- a/source/blender/io/wavefront_obj/CMakeLists.txt
+++ b/source/blender/io/wavefront_obj/CMakeLists.txt
@@ -36,6 +36,7 @@ set(INC_SYS
 )
 
 set(SRC
+  intern/mesh_utils.cc
   intern/wavefront_obj.cc
   intern/wavefront_obj_exporter.cc
   intern/wavefront_obj_ex_mesh.cc
@@ -50,6 +51,7 @@ set(SRC
   intern/wavefront_obj_im_objects.cc
 
   IO_wavefront_obj.h
+  intern/mesh_utils.hh
   intern/wavefront_obj_exporter.hh
   intern/wavefront_obj_ex_mesh.hh
   intern/wavefront_obj_ex_mtl.hh
diff --git a/source/blender/io/wavefront_obj/intern/mesh_utils.cc 
b/source/blender/io/wavefront_obj/intern/mesh_utils.cc
new file mode 100644
index 00000000000..5176553d873
--- /dev/null
+++ b/source/blender/io/wavefront_obj/intern/mesh_utils.cc
@@ -0,0 +1,292 @@
+/*
+ * 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.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup obj
+ */
+
+#include "mesh_utils.hh"
+
+#include "BKE_displist.h"
+
+#include "BLI_array.hh"
+#include "BLI_set.hh"
+
+namespace blender::io::obj {
+
+static float manhatten_len(const float3 coord)
+{
+  return abs(coord[0]) + abs(coord[1]) + abs(coord[2]);
+}
+
+struct vert_treplet {
+  const float3 v;
+  const int i;
+  const float mlen;
+
+  vert_treplet(float3 v, int i) : v(v), i(i), mlen(manhatten_len(v))
+  {
+  }
+  friend bool operator==(const vert_treplet &one, const vert_treplet &other)
+  {
+    return other.i == one.i;
+  }
+  friend bool operator!=(const vert_treplet &one, const vert_treplet &other)
+  {
+    return !(one == other);
+  }
+};
+
+static std::pair<int, int> ed_key_mlen(const vert_treplet &v1, const 
vert_treplet &v2)
+{
+  if (v1.mlen > v2.mlen) {
+    return {v2.i, v1.i};
+  }
+  return {v1.i, v2.i};
+}
+
+static bool join_segments(Vector<vert_treplet> &seg1, Vector<vert_treplet> 
&seg2)
+{
+  if (seg1.last().v == seg2.last().v) {
+    Vector<vert_treplet> &temp = seg1;
+    seg1 = seg2;
+    seg2 = temp;
+  }
+  else {
+    return false;
+  }
+  seg1.remove_last();
+  seg2.extend(seg1);
+  if (seg1.last().v == seg1[0].v) {
+    seg1.remove_last();
+  }
+  seg2.clear();
+  return true;
+}
+
+static void tessellate_polygon(Vector<Vector<const float3 *>> &polyLineSeq,
+                               Vector<Vector<int>> &r_new_line_seq)
+{
+  int64_t totpoints = 0;
+  /* Display #ListBase. */
+  ListBase dispbase = {NULL, NULL};
+  DispList *dl;
+  const int64_t len_polylines{polyLineSeq.size()};
+
+  for (int i = 0; i < len_polylines; i++) {
+    Vector<const float3 *> &polyLine = polyLineSeq[i];
+
+    const int64_t len_polypoints{polyLine.size()};
+    totpoints += len_polypoints;
+    if (len_polypoints > 0) { /* don't bother adding edges as polylines */
+      dl = static_cast<DispList *>(MEM_callocN(sizeof(DispList), __func__));
+      BLI_addtail(&dispbase, dl);
+      dl->type = DL_INDEX3;
+      dl->nr = len_polypoints;
+      dl->type = DL_POLY;
+      dl->parts = 1; /* no faces, 1 edge loop */
+      dl->col = 0;   /* no material */
+      dl->verts = static_cast<float *>(MEM_mallocN(sizeof(float[3]) * 
len_polypoints, "dl verts"));
+      dl->index = static_cast<int *>(MEM_callocN(sizeof(int[3]) * 
len_polypoints, "dl index"));
+    }
+  }
+
+  if (totpoints) {
+    /* now make the list to return */
+    BKE_displist_fill(&dispbase, &dispbase, NULL, false);
+
+    /* The faces are stored in a new DisplayList
+     * that's added to the head of the #ListBase. */
+    dl = static_cast<DispList *>(dispbase.first);
+
+    int *dl_face = dl->index;
+    r_new_line_seq.append({dl_face[0], dl_face[1], dl_face[2]});
+    BKE_displist_free(&dispbase);
+  }
+  else {
+    /* no points, do this so scripts don't barf */
+    BKE_displist_free(&dispbase); /* possible some dl was allocated */
+  }
+}
+
+Vector<Vector<int>> ngon_tessellate(Span<float3> vertex_coords, Span<int> 
face_vertex_indices)
+{
+  if (face_vertex_indices.is_empty()) {
+    return {};
+  }
+  Vector<vert_treplet> verts;
+  verts.reserve(face_vertex_indices.size());
+
+  for (int i = 0; i < verts.size(); i++) {
+    verts.append_unchecked({vertex_coords[i], i});
+  }
+
+  Vector<Array<int, 2>> edges;
+  for (int i = 0; i < face_vertex_indices.size(); i++) {
+    edges[i] = {i, i - 1};
+  }
+  edges[0] = {0, static_cast<int>(face_vertex_indices.size() - 1)};
+
+  Set<std::pair<int, int>> used_edges;
+  Set<std::pair<int, int>> double_edges;
+
+  for (const Array<int, 2> &edge : edges) {
+    std::pair<int, int> edge_key = ed_key_mlen(verts[edge[0]], verts[edge[1]]);
+    if (used_edges.contains(edge_key)) {
+      double_edges.add(edge_key);
+    }
+    else {
+      used_edges.add(edge_key);
+    }
+  }
+
+  Vector<Vector<vert_treplet>> loop_segments;
+  {
+    const vert_treplet *vert_prev = &verts[0];
+    Vector<vert_treplet> contex_loop{1, *vert_prev};
+    loop_segments.append(contex_loop);
+    for (const vert_treplet &vertex : verts) {
+      if (vertex == *vert_prev) {
+        continue;
+      }
+      if (double_edges.contains(ed_key_mlen(vertex, *vert_prev))) {
+        contex_loop = {vertex};
+        loop_segments.append(contex_loop);
+      }
+      else {
+        if (!contex_loop.is_empty() && contex_loop.last() == vertex) {
+        }
+        else {
+          contex_loop.append(vertex);
+        }
+      }
+      vert_prev = &vertex;
+    }
+  }
+
+  bool joining_segements = true;
+  while (joining_segements) {
+    joining_segements = false;
+    const int segcount = loop_segments.size();
+    for (int j = segcount - 1; j >= 0; j--) {
+      Vector<vert_treplet> seg_j = loop_segments[j];
+      if (seg_j.is_empty()) {
+        continue;
+      }
+      for (int k = j - 1; k >= 0; k--) {
+        if (seg_j.is_empty()) {
+          break;
+        }
+        Vector<vert_treplet> seg_k = loop_segments[k];
+        if (!seg_j.is_empty() && join_segments(seg_j, seg_k)) {
+          joining_segements = true;
+        }
+      }
+    }
+  }
+
+  for (Vector<vert_treplet> &loop : loop_segments) {
+    if (!loop.is_empty() && loop[0].v == loop.last().v) {
+      loop.remove_last();
+    }
+  }
+
+  Vector<Vector<vert_treplet>> loop_list;
+  for (Vector<vert_treplet> &loop : loop_segments) {
+    if (loop.size() > 2) {
+      loop_list.append(loop);
+    }
+  }
+  // Done with loop fixing.
+
+  Vector<int> vert_map{face_vertex_indices.size()};
+  int ii = 0;
+  for (Vector<vert_treplet> &verts : loop_list) {
+    if (verts.size() <= 2) {
+      continue;
+    }
+    for (int i = 0; i < verts.size(); i++) {
+      vert_map[i + ii] = verts[i].i;
+    }
+  }
+
+  Vector<Vector<const float3 *>> coord_list;
+  for (int i = 0; i < loop_list.size(); i++) {
+    Span<vert_treplet> loop = loop_list[i];
+    Vector<const float3 *> vert_ptrs;
+    for (const vert_treplet &vert : loop) {
+      vert_ptrs.append(&vert.v);
+    }
+    coord_list.append(vert_ptrs);
+  }
+  Vector<Vector<int>> fill;
+  tessellate_polygon(coord_list, fill);
+
+  Vector<Vector<int>> fill_indices;
+  Vector<Vector<int>> fill_indices_reversed;
+  for (Span<int> f : fill) {
+    Vector<int> corner(f.size());
+    for (const int i : f) {
+      corner.append(vert_map[i]);
+    }
+    fill_indices.append(corner);
+  }
+
+  if (fill_indices.is_empty()) {
+    std::cerr << "Warning: could not scanfill, fallback on triangle fan" << 
std::endl;
+    for (int i = 0; i < face_vertex_indices.size(); i++) {
+      fill_indices.append({0, i - 1, i});
+    }
+  }
+  else {
+    int flip = -1;
+    for (Span<int> fi : fill_indices) {
+      if (flip != -1) {
+        break;
+      }
+      for (int i = 0; i < fi.size(); i++) {
+        if (fi[i] == 0 && fi[i - 1] == 1) {
+          flip = 0;
+          break;
+        }
+        if (fi[i] == 1 && fi[i - 1] == 0) {
+          flip = 1;
+          break;
+        }
+      }
+    }
+    if (flip != 1) {
+      for (int i = 0; i < fill_indices.size(); i++) {
+        Vector<int> rev_face(fill_indices[i].size());
+        for (const int fi : fill_indices[i]) {
+          rev_face.append(fi);
+        }
+        fill_indices_reversed.append(rev_face);
+      }
+    }
+  }
+
+  if (!fill_indices_reversed.is_empty()) {
+    fill_indices.clear();
+    return fill_indices_reversed;
+  }
+  return fill_indices;
+}
+
+}  // namespace blender::io::obj
diff --git a/source/blender/io/wavefront_obj/intern/mesh_utils.hh 
b/source/blender/io/wavefront_obj/intern/mesh_utils.hh
new file mode 100644
index 00000000000..ca5f30541ec
--- /dev/null
+++ b/source/blender/io/wavefront_obj/intern/mesh_utils.hh
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ *
+ * The Original Code is Copyright (C) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \f

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to