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. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org List details, subscription details or unsubscribe: https://lists.blender.org/mailman/listinfo/bf-blender-cvs