[Bf-blender-cvs] [51b467afe3c] temp-lineart-embree: LineArt: Use thread local stroage for occlusion pair results

YimingWu noreply at git.blender.org
Fri Mar 25 12:38:56 CET 2022


Commit: 51b467afe3c4e09c2a4d56e5728188ace2f78935
Author: YimingWu
Date:   Thu Mar 24 20:07:19 2022 +0800
Branches: temp-lineart-embree
https://developer.blender.org/rB51b467afe3c4e09c2a4d56e5728188ace2f78935

LineArt: Use thread local stroage for occlusion pair results

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

M	source/blender/gpencil_modifiers/CMakeLists.txt
M	source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h
A	source/blender/gpencil_modifiers/intern/lineart/lineart_cpp_bridge.cpp
M	source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c

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

diff --git a/source/blender/gpencil_modifiers/CMakeLists.txt b/source/blender/gpencil_modifiers/CMakeLists.txt
index 8ed186d978d..6801c11a3ae 100644
--- a/source/blender/gpencil_modifiers/CMakeLists.txt
+++ b/source/blender/gpencil_modifiers/CMakeLists.txt
@@ -1,6 +1,18 @@
 # SPDX-License-Identifier: GPL-2.0-or-later
 # Copyright 2018 Blender Foundation. All rights reserved.
 
+if(WITH_TBB)
+  add_definitions(-DWITH_TBB)
+
+  list(APPEND INC_SYS
+    ${TBB_INCLUDE_DIRS}
+  )
+
+  list(APPEND LIB
+    ${TBB_LIBRARIES}
+  )
+endif()
+
 set(INC
   .
   intern
@@ -70,6 +82,7 @@ set(SRC
   intern/MOD_gpencil_util.h
 
   # Lineart code
+  intern/lineart/lineart_cpp_bridge.cpp
   intern/lineart/lineart_chain.c
   intern/lineart/lineart_cpu.c
   intern/lineart/lineart_ops.c
diff --git a/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h b/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h
index 38b5c53c32f..1b8684ad8c2 100644
--- a/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h
+++ b/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h
@@ -210,17 +210,17 @@ struct MLoopTri;
 struct MLoop;
 struct LineartRenderBuffer;
 typedef struct LineartPointArrayFinal {
-  float *points;
-  int numpoints;
-  struct MLoopTri *looptri; /* Refernce to original_me->runtime->looptri; */
-  struct MLoop *loop;       /* Refernce to original_me->mloop; */
+  // float *points;
+  // int numpoints;
+  // struct MLoopTri *looptri; /* Refernce to original_me->runtime->looptri; */
+  // struct MLoop *loop;       /* Refernce to original_me->mloop; */
   LineartElementLinkNode *eln_triangle;
   struct LineartRenderBuffer *rb;
 } LineartPointArrayFinal;
 
 typedef struct LineartIntersectionRecord {
-  float p1[3];
-  float p2[3];
+  double p1[3];
+  double p2[3];
   struct LineartTriangle *t1;
   struct LineartTriangle *t2;
 } LineartIntersectionRecord;
@@ -249,6 +249,8 @@ typedef struct LineartOcclusionPairRecord {
   uint32_t scheduled_next;
 } LineartOcclusionPairRecord;
 
+typedef struct LineartThreadOcclusionData LineartThreadOcclusionData;
+
 typedef struct LineartRenderBuffer {
   struct LineartRenderBuffer *prev, *next;
 
@@ -300,6 +302,7 @@ typedef struct LineartRenderBuffer {
   RTCScene rtcscene_geom;
   RTCScene rtcscene_view;
 
+  struct LineartThreadOcclusionData *thread_occlusion_data;
   LineartMeshRecord mesh_record;
   LineartOcclusionPairRecord occlusion_record;
 
@@ -780,3 +783,20 @@ void MOD_lineart_gpencil_generate(LineartCache *cache,
 float MOD_lineart_chain_compute_length(LineartEdgeChain *ec);
 
 void ED_operatortypes_lineart(void);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LineartThreadOcclusionData *lineart_thread_init_occlusion_result(void);
+void lineart_thread_add_occlusion_pair(LineartThreadOcclusionData *data,
+                                       LineartElementLinkNode *eln_edge,
+                                       LineartElementLinkNode *eln_triangle,
+                                       LineartEdge *e,
+                                       LineartTriangle *t);
+LineartOcclusionPair *lineart_thread_finalize_occlusion_result(LineartThreadOcclusionData *data,
+                                                               int *result_count);
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpp_bridge.cpp b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpp_bridge.cpp
new file mode 100644
index 00000000000..339a8050091
--- /dev/null
+++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpp_bridge.cpp
@@ -0,0 +1,47 @@
+
+#include "MOD_lineart.h"
+
+#include "lineart_intern.h"
+
+#include "BLI_enumerable_thread_specific.hh"
+#include "BLI_task.h"
+#include "BLI_utildefines.h"
+#include "BLI_vector.hh"
+
+using blender::Vector;
+using blender::threading::EnumerableThreadSpecific;
+
+typedef EnumerableThreadSpecific<Vector<LineartOcclusionPair>> _LineartThreadOcclusionData;
+typedef struct LineartThreadOcclusionData LineartThreadOcclusionData;
+
+LineartThreadOcclusionData *lineart_thread_init_occlusion_result()
+{
+  _LineartThreadOcclusionData *result = new _LineartThreadOcclusionData;
+  return (LineartThreadOcclusionData *)result;
+};
+
+void lineart_thread_add_occlusion_pair(LineartThreadOcclusionData *data,
+                                       LineartElementLinkNode *eln_edge,
+                                       LineartElementLinkNode *eln_triangle,
+                                       LineartEdge *e,
+                                       LineartTriangle *t)
+{
+  LineartOcclusionPair op;
+  op.e = e;
+  op.t = t;
+  op.eln_edge = eln_edge;
+  op.eln_triangle = eln_triangle;
+  ((_LineartThreadOcclusionData *)data)->local().append(op);
+}
+
+/* Memory returned by this needs to be freed manually. */
+LineartOcclusionPair *lineart_thread_finalize_occlusion_result(LineartThreadOcclusionData *data,
+                                                               int *result_count)
+{
+  Vector<LineartOcclusionPair> *result = new Vector<LineartOcclusionPair>;
+  for (const Vector<LineartOcclusionPair> &local : (*(_LineartThreadOcclusionData *)data)) {
+    result->extend(local);
+  }
+  *result_count = result->size();
+  return (LineartOcclusionPair *)result->data();
+};
diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
index 40fb91dd15c..32a1b29c1df 100644
--- a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
+++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
@@ -98,6 +98,14 @@ static bool lineart_triangle_edge_image_space_occlusion(SpinLock *spl,
                                                         double *from,
                                                         double *to);
 
+static LineartVert *lineart_triangle_share_point(const LineartTriangle *l,
+                                                 const LineartTriangle *r);
+
+static bool lineart_triangle_get_other_verts(const LineartTriangle *tri,
+                                             const LineartVert *vt,
+                                             LineartVert **l,
+                                             LineartVert **r);
+
 static void OcclusionCollideFunc(void *userPtr,
                                  struct RTCCollision *collisions,
                                  unsigned int num_collisions);
@@ -2209,15 +2217,167 @@ static bool lineart_geometry_check_visible(double (*model_view_proj)[4],
   return true;
 }
 
-static void lineart_embree_clear_mesh_record(LineartRenderBuffer *rb)
+static bool lineart_embree_triangle_2v_intersection_test(LineartVert *v1,
+                                                         LineartVert *v2,
+                                                         LineartTriangle *tri,
+                                                         LineartTriangle *testing,
+                                                         double *last,
+                                                         double *result)
 {
-  if (rb->mesh_record.array) {
-    for (int i = 0; i < rb->mesh_record.max_length; i++) {
-      LineartPointArrayFinal *rec = &rb->mesh_record.array[i];
-      if (rec->points) {
-        MEM_freeN(rec->points);
+  double Lv[3];
+  double Rv[3];
+  double dot_l, dot_r;
+  double gloc[3];
+  LineartVert *l = v1, *r = v2;
+
+  sub_v3_v3v3_db(Lv, l->gloc, testing->v[0]->gloc);
+  sub_v3_v3v3_db(Rv, r->gloc, testing->v[0]->gloc);
+
+  dot_l = dot_v3v3_db(Lv, testing->gn);
+  dot_r = dot_v3v3_db(Rv, testing->gn);
+
+  if (dot_l * dot_r > 0 || (!dot_l && !dot_r)) {
+    return false;
+  }
+
+  dot_l = fabs(dot_l);
+  dot_r = fabs(dot_r);
+
+  interp_v3_v3v3_db(gloc, l->gloc, r->gloc, dot_l / (dot_l + dot_r));
+
+  /* Due to precision issue, we might end up with the same point as the one we already detected.
+   */
+  if (last && LRT_DOUBLE_CLOSE_ENOUGH(last[0], gloc[0]) &&
+      LRT_DOUBLE_CLOSE_ENOUGH(last[1], gloc[1]) && LRT_DOUBLE_CLOSE_ENOUGH(last[2], gloc[2])) {
+    return false;
+  }
+
+  if (!(lineart_point_inside_triangle3d(
+          gloc, testing->v[0]->gloc, testing->v[1]->gloc, testing->v[2]->gloc))) {
+    return false;
+  }
+
+  copy_v3_v3_db(result, gloc);
+
+  return true;
+}
+
+static bool lineart_embree_triangle_intersect(LineartTriangle *tri,
+                                              LineartTriangle *testing,
+                                              double *r_v1,
+                                              double *r_v2)
+{
+  double va1[3], va2[3];
+  double *v1 = va1, *v2 = va2;
+  double **next = &v1;
+  double E0T[3];
+  double E1T[3];
+  double E2T[3];
+  double TE0[3];
+  double TE1[3];
+  double TE2[3];
+  LineartVert *sv1, *sv2;
+  double cl[3];
+  bool isuccess;
+
+  LineartVert *share = lineart_triangle_share_point(testing, tri);
+
+  if (share) {
+    /* If triangles have sharing points like `abc` and `acd`, then we only need to detect `bc`
+     * against `acd` or `cd` against `abc`. */
+
+    LineartVert *new_share;
+    lineart_triangle_get_other_verts(tri, share, &sv1, &sv2);
+
+    new_share = share;
+    v1 = share->gloc;
+
+    isuccess = lineart_embree_triangle_2v_intersection_test(sv1, sv2, tri, testing, 0, v2);
+
+    if (!isuccess) {
+      lineart_triangle_get_other_verts(testing, share, &sv1, &sv2);
+      isuccess = lineart_embree_triangle_2v_intersection_test(sv1, sv2, testing, tri, 0, v2);
+      if (!isuccess) {
+        return false;
       }
     }
+  }
+  else {
+    /* If not sharing any points, then we need to try all the possibilities. */
+
+    int pcount = 0;
+
+    isuccess = lineart_embree_triangle_2v_intersection_test(
+        tri->v[0], tri->v[1], tri, testing, 0, E0T);
+    if (isuccess && (pcount < 2)) {
+      (*next) = E0T;
+      next = &v2;
+      pcount++;
+    }
+    isuccess = lineart_embree_triangle_2v_intersection_test(
+        tri->v[1], tri->v[2], tri, testing, v1, E1T);
+    if (isuccess && (pcount < 2)) {
+      (*next) = E1T;
+      next = &v2;
+      pcount++;
+    }
+    if (pcount < 2) {
+      isuccess = lineart_embree_triangle_2v_intersection_test(
+    

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list