[Bf-blender-cvs] [82e0783f608] temp-lineart-embree: LineArt: Workable embree intersection stage.

YimingWu noreply at git.blender.org
Sun Mar 13 14:37:27 CET 2022


Commit: 82e0783f608bccd3c2814a0f009e39a25c703b09
Author: YimingWu
Date:   Sun Jan 16 20:49:00 2022 +0800
Branches: temp-lineart-embree
https://developer.blender.org/rB82e0783f608bccd3c2814a0f009e39a25c703b09

LineArt: Workable embree intersection stage.

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

M	source/blender/gpencil_modifiers/CMakeLists.txt
M	source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h
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 5ee75619259..d02a01fe8fb 100644
--- a/source/blender/gpencil_modifiers/CMakeLists.txt
+++ b/source/blender/gpencil_modifiers/CMakeLists.txt
@@ -44,6 +44,15 @@ set(INC_SYS
   ${ZLIB_INCLUDE_DIRS}
 )
 
+if(WITH_CYCLES_EMBREE)
+  add_definitions(-DWITH_EMBREE)
+  add_definitions(-DEMBREE_STATIC_LIB)
+  include_directories(
+    SYSTEM
+    ${EMBREE_INCLUDE_DIRS}
+  )
+endif()
+
 set(SRC
   intern/MOD_gpencil_ui_common.c
 
diff --git a/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h b/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h
index 8c5820c9667..2eab9490676 100644
--- a/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h
+++ b/source/blender/gpencil_modifiers/intern/lineart/MOD_lineart.h
@@ -28,6 +28,8 @@
 #include "BLI_math.h" /* Needed here for inline functions. */
 #include "BLI_threads.h"
 
+#include <embree3/rtcore.h>
+
 #include <math.h>
 
 typedef struct LineartStaticMemPoolNode {
@@ -216,6 +218,25 @@ enum eLineArtTileRecursiveLimit {
 #define LRT_TILE_SPLITTING_TRIANGLE_LIMIT 100
 #define LRT_TILE_EDGE_COUNT_INITIAL 32
 
+struct MLoopTri;
+struct MLoop;
+typedef struct LineartPointArrayFinal {
+  float *points;
+  int numpoints;
+  struct MLoopTri *looptri; /* Refernce to original_me->runtime->looptri; */
+  struct MLoop *loop;       /* Refernce to original_me->mloop; */
+} LineartPointArrayFinal;
+
+typedef struct LineartMeshRecord {
+  LineartPointArrayFinal *array;
+  uint32_t next;
+  uint32_t max_length;
+
+  float *intersection_record;
+  uint32_t intersection_pair_max;
+  uint32_t intersection_pair_next;
+} LineartMeshRecord;
+
 typedef struct LineartRenderBuffer {
   struct LineartRenderBuffer *prev, *next;
 
@@ -260,6 +281,15 @@ typedef struct LineartRenderBuffer {
 
   int triangle_size;
 
+  RTCDevice rtcdevice;
+  /* According to embree manual, geometries and buffers are destroyed when their reference count
+   * drops to 0, so in principle we don't need to retain pointers to them if we destroy the scene
+   * at once. */
+  RTCScene rtcscene_geom;
+  RTCScene rtcscene_view;
+
+  LineartMeshRecord mesh_record;
+
   /* Although using ListBase here, LineartEdge is single linked list.
    * list.last is used to store worker progress along the list.
    * See lineart_main_occlusion_begin() for more info. */
diff --git a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
index f08d35891ce..7fea53934d5 100644
--- a/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
+++ b/source/blender/gpencil_modifiers/intern/lineart/lineart_cpu.c
@@ -44,6 +44,7 @@
 #include "BKE_lib_id.h"
 #include "BKE_material.h"
 #include "BKE_mesh.h"
+#include "BKE_mesh_runtime.h"
 #include "BKE_object.h"
 #include "BKE_pointcache.h"
 #include "BKE_scene.h"
@@ -64,6 +65,8 @@
 
 #include "lineart_intern.h"
 
+#define LINEART_USE_EMBREE
+
 static LineartBoundingArea *lineart_edge_first_bounding_area(LineartRenderBuffer *rb,
                                                              LineartEdge *e);
 
@@ -1719,7 +1722,7 @@ static void lineart_geometry_object_load(LineartObjectInfo *obi, LineartRenderBu
   }
 
   if (obi->free_use_mesh) {
-    BKE_id_free(NULL, obi->original_me);
+    // BKE_id_free(NULL, obi->original_me);
   }
 
   if (rb->remove_doubles) {
@@ -2087,6 +2090,105 @@ static bool lineart_geometry_check_visible(double (*model_view_proj)[4],
   return true;
 }
 
+static void lineart_embree_clear_mesh_record(LineartRenderBuffer *rb)
+{
+  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);
+      }
+    }
+    MEM_freeN(rb->mesh_record.array);
+  }
+  rb->mesh_record.max_length = 0;
+
+  if (rb->mesh_record.intersection_record) {
+    MEM_freeN(rb->mesh_record.intersection_record);
+  }
+  rb->mesh_record.intersection_pair_max = rb->mesh_record.intersection_pair_next = 0;
+
+  if (rb->rtcdevice) {
+    rtcReleaseDevice(rb->rtcdevice);
+    rb->rtcdevice = NULL;
+  }
+  if (rb->rtcscene_geom) {
+    rtcReleaseScene(rb->rtcscene_geom);
+    rb->rtcscene_geom = NULL;
+  }
+}
+static void lineart_embree_init_mesh_record(LineartRenderBuffer *rb)
+{
+  /* In case anything dirty. */
+  lineart_embree_clear_mesh_record(rb);
+
+  const char *config = "verbose=3";
+  rb->rtcdevice = rtcNewDevice(config);
+  rb->rtcscene_geom = rtcNewScene(rb->rtcdevice);
+
+  rb->mesh_record.max_length = 100;
+  rb->mesh_record.array = MEM_callocN(sizeof(LineartPointArrayFinal) * rb->mesh_record.max_length,
+                                      "LineartPointArrayFinal");
+  rb->mesh_record.intersection_pair_max = 100;
+  rb->mesh_record.intersection_record = MEM_callocN(
+      sizeof(float) * rb->mesh_record.intersection_pair_max * 6, "Lineart intersection_record");
+}
+
+static void lineart_embree_mesh_bounds_func(const struct RTCBoundsFunctionArguments *args)
+{
+  LineartPointArrayFinal *rec = args->geometryUserPtr;
+  float *p0 = &rec->points[rec->loop[rec->looptri[args->primID].tri[0]].v * 3];
+  float *p1 = &rec->points[rec->loop[rec->looptri[args->primID].tri[1]].v * 3];
+  float *p2 = &rec->points[rec->loop[rec->looptri[args->primID].tri[2]].v * 3];
+  struct RTCBounds *o = args->bounds_o;
+  o->lower_x = MIN3(p0[0], p1[0], p2[0]);
+  o->upper_x = MAX3(p0[0], p1[0], p2[0]);
+  o->lower_y = MIN3(p0[1], p1[1], p2[1]);
+  o->upper_y = MAX3(p0[1], p1[1], p2[1]);
+  o->lower_z = MIN3(p0[2], p1[2], p2[2]);
+  o->upper_z = MAX3(p0[2], p1[2], p2[2]);
+}
+static void lineart_embree_transform_point_array(LineartRenderBuffer *rb, Object *ob, Mesh *me)
+{
+  int pcount = me->totvert;
+
+  RTCGeometry geom = rtcNewGeometry(rb->rtcdevice, RTC_GEOMETRY_TYPE_USER);
+  uint32_t geom_id = rtcAttachGeometry(rb->rtcscene_geom, geom);
+  if (geom_id >= rb->mesh_record.max_length) {
+    LineartPointArrayFinal *new_array = MEM_callocN(sizeof(LineartPointArrayFinal) *
+                                                        rb->mesh_record.max_length * 2,
+                                                    "new LineartPointArrayFinal");
+    memcpy(new_array,
+           rb->mesh_record.array,
+           sizeof(LineartPointArrayFinal) * rb->mesh_record.max_length);
+    MEM_freeN(rb->mesh_record.array);
+    rb->mesh_record.max_length *= 2;
+    rb->mesh_record.array = new_array;
+  }
+  /* Because in the collide callback, only geom_id is available so it needs to be the same as the
+   * array index for convenience of lookup. */
+  LineartPointArrayFinal *rec = &rb->mesh_record.array[geom_id];
+  rb->mesh_record.next = geom_id + 1;
+
+  if (!me->runtime.looptris.array) {
+    BKE_mesh_runtime_looptri_recalc(me);
+  }
+
+  rec->numpoints = pcount;
+  rec->looptri = me->runtime.looptris.array;
+  rec->loop = me->mloop;
+  rec->points = MEM_mallocN(sizeof(float) * 3 * pcount, "LineartPointArrayFinal::points");
+  for (int i = 0; i < pcount; i++) {
+    mul_v3_m4v3(&rec->points[i * 3], ob->obmat, me->mvert[i].co);
+  }
+
+  /* Only user typed geometry supports rtcCollide(). */
+  rtcSetGeometryUserPrimitiveCount(geom, me->runtime.looptris.len);
+  /* Reduce the geom user count to 1, and when scene is destroyed the geom is destroyed
+   * automatically. */
+  rtcReleaseGeometry(geom);
+}
+
 static void lineart_main_load_geometries(
     Depsgraph *depsgraph,
     Scene *scene,
@@ -2151,12 +2253,16 @@ static void lineart_main_load_geometries(
 
   bool is_render = DEG_get_mode(depsgraph) == DAG_EVAL_RENDER;
 
+#ifdef LINEART_USE_EMBREE
+  lineart_embree_init_mesh_record(rb);
+#endif
+
   DEG_OBJECT_ITER_BEGIN (depsgraph, ob, flags) {
     LineartObjectInfo *obi = lineart_mem_acquire(&rb->render_data_pool, sizeof(LineartObjectInfo));
     obi->usage = lineart_usage_check(scene->master_collection, ob, is_render);
     obi->override_intersection_mask = lineart_intersection_mask_check(scene->master_collection,
                                                                       ob);
-    Mesh *use_mesh;
+    Mesh *use_mesh = NULL;
 
     if (obi->usage == OBJECT_LRT_EXCLUDE) {
       continue;
@@ -2189,7 +2295,7 @@ static void lineart_main_load_geometries(
       if (allow_duplicates) {
         continue;
       }
-      use_mesh = BKE_mesh_new_from_object(depsgraph, use_ob, true, true);
+      // use_mesh = BKE_mesh_new_from_object(depsgraph, use_ob, true, true);
     }
 
     /* In case we still can not get any mesh geometry data from the object */
@@ -2201,6 +2307,11 @@ static void lineart_main_load_geometries(
       obi->free_use_mesh = true;
     }
 
+#ifdef LINEART_USE_EMBREE
+    /* Link vertices and faces to embree geometry. */
+    lineart_embree_transform_point_array(rb, ob, use_mesh);
+#endif
+
     /* Make normal matrix. */
     float imat[4][4];
     invert_m4_m4(imat, ob->obmat);
@@ -2249,6 +2360,140 @@ static void lineart_main_load_geometries(
   }
 }
 
+static void lineart_add_intersection_record_thread(LineartRenderBuffer *rb, float *i1, float *i2)
+{
+  LineartMeshRecord *rec = &rb->mesh_record;
+  BLI_spin_lock(&rb->lock_task);
+  if (rec->intersection_pair_next >= rec->intersection_pair_max) {
+    float *new_array = MEM_mallocN(sizeof(float) * 6 * rec->intersection_pair_max * 2,
+                                   "new intersection_record");
+    memcpy(new_array, rec->intersection_record, sizeof(float) * 6 * rec->intersection_pair_max);
+    MEM_freeN(rec->intersection_record);
+    rec->intersection_record = new_array;
+    rec->intersection_pair_max *= 2;
+  }
+  float *write = &rec->intersection_record[rec->intersection_pair_next * 6];
+  rec->intersection_pair_next++;
+
+  copy_v3_v3(write, i1);
+  copy_v3_v3(&write[3], i2);
+  BLI_spin_unlock(&rb->lock_task);
+}
+
+static bool lineart_triangle_share_edge_generic(const float *a0,
+                                                const float *a1,
+                                                const float *a2,
+                                                const float *b0,
+                                               

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list