Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/pbvh.c
| Show All 27 Lines | |||||
| #include "BLI_rand.h" | #include "BLI_rand.h" | ||||
| #include "BLI_task.h" | #include "BLI_task.h" | ||||
| #include "DNA_mesh_types.h" | #include "DNA_mesh_types.h" | ||||
| #include "DNA_meshdata_types.h" | #include "DNA_meshdata_types.h" | ||||
| #include "BKE_ccg.h" | #include "BKE_ccg.h" | ||||
| #include "BKE_mesh.h" /* for BKE_mesh_calc_normals */ | #include "BKE_mesh.h" /* for BKE_mesh_calc_normals */ | ||||
| #include "BKE_mesh_mapping.h" | |||||
| #include "BKE_paint.h" | #include "BKE_paint.h" | ||||
| #include "BKE_pbvh.h" | #include "BKE_pbvh.h" | ||||
| #include "BKE_subdiv_ccg.h" | #include "BKE_subdiv_ccg.h" | ||||
| #include "PIL_time.h" | #include "PIL_time.h" | ||||
| #include "GPU_buffers.h" | #include "GPU_buffers.h" | ||||
| ▲ Show 20 Lines • Show All 962 Lines • ▼ Show 20 Lines | static bool update_search_cb(PBVHNode *node, void *data_v) | ||||
| return true; | return true; | ||||
| } | } | ||||
| typedef struct PBVHUpdateData { | typedef struct PBVHUpdateData { | ||||
| PBVH *pbvh; | PBVH *pbvh; | ||||
| PBVHNode **nodes; | PBVHNode **nodes; | ||||
| int totnode; | int totnode; | ||||
| MeshElemMap *pmap; | |||||
| float (*vnors)[3]; | float (*vnors)[3]; | ||||
| int flag; | int flag; | ||||
| bool show_sculpt_face_sets; | bool show_sculpt_face_sets; | ||||
| } PBVHUpdateData; | } PBVHUpdateData; | ||||
| static void pbvh_update_normals_accum_task_cb(void *__restrict userdata, | static void pbvh_update_normals_accum_task_cb(void *__restrict userdata, | ||||
| const int n, | const int n, | ||||
| ▲ Show 20 Lines • Show All 101 Lines • ▼ Show 20 Lines | static void pbvh_faces_update_normals(PBVH *pbvh, PBVHNode **nodes, int totnode) | ||||
| BKE_pbvh_parallel_range_settings(&settings, true, totnode); | BKE_pbvh_parallel_range_settings(&settings, true, totnode); | ||||
| BLI_task_parallel_range(0, totnode, &data, pbvh_update_normals_accum_task_cb, &settings); | BLI_task_parallel_range(0, totnode, &data, pbvh_update_normals_accum_task_cb, &settings); | ||||
| BLI_task_parallel_range(0, totnode, &data, pbvh_update_normals_store_task_cb, &settings); | BLI_task_parallel_range(0, totnode, &data, pbvh_update_normals_store_task_cb, &settings); | ||||
| MEM_freeN(vnors); | MEM_freeN(vnors); | ||||
| } | } | ||||
| static void pbvh_update_mesh_normals_pmap_cb(void *__restrict userdata, | |||||
| const int n, | |||||
| const TaskParallelTLS *__restrict UNUSED(tls)) | |||||
| { | |||||
| PBVHUpdateData *data = userdata; | |||||
| PBVH *pbvh = data->pbvh; | |||||
| PBVHNode *node = data->nodes[n]; | |||||
| MeshElemMap *pmap = data->pmap; | |||||
| if (!(node->flag & PBVH_UpdateNormals)) { | |||||
| return; | |||||
| } | |||||
| const int *verts = node->vert_indices; | |||||
| const int totvert = node->uniq_verts; | |||||
| for (int i = 0; i < totvert; i++) { | |||||
| const int v = verts[i]; | |||||
| MVert *mvert = &pbvh->verts[v]; | |||||
| if (!(mvert->flag & ME_VERT_PBVH_UPDATE)) { | |||||
| continue; | |||||
| } | |||||
| float normal_accum[3] = {0.0f, 0.0f, 0.0f}; | |||||
| MeshElemMap *vert_map = &pmap[v]; | |||||
| for (int j = 0; j < pmap[v].count; j++) { | |||||
| const MPoly *mpoly = &pbvh->mpoly[vert_map->indices[j]]; | |||||
| float poly_normal[3]; | |||||
| BKE_mesh_calc_poly_normal(mpoly, &pbvh->mloop[mpoly->loopstart], pbvh->verts, poly_normal); | |||||
| add_v3_v3(normal_accum, poly_normal); | |||||
| } | |||||
| normalize_v3(normal_accum); | |||||
| normal_float_to_short_v3(mvert->no, normal_accum); | |||||
| mvert->flag &= ~ME_VERT_PBVH_UPDATE; | |||||
| } | |||||
| node->flag &= ~PBVH_UpdateNormals; | |||||
| } | |||||
| static void pbvh_faces_update_normals_pmap(PBVH *pbvh, | |||||
| PBVHNode **nodes, | |||||
| int totnode, | |||||
| MeshElemMap *pmap) | |||||
| { | |||||
| PBVHUpdateData data = { | |||||
| .pbvh = pbvh, | |||||
| .nodes = nodes, | |||||
| .pmap = pmap, | |||||
| }; | |||||
| TaskParallelSettings settings; | |||||
| BKE_pbvh_parallel_range_settings(&settings, true, totnode); | |||||
| BLI_task_parallel_range(0, totnode, &data, pbvh_update_mesh_normals_pmap_cb, &settings); | |||||
| } | |||||
| static void pbvh_update_mask_redraw_task_cb(void *__restrict userdata, | static void pbvh_update_mask_redraw_task_cb(void *__restrict userdata, | ||||
| const int n, | const int n, | ||||
| const TaskParallelTLS *__restrict UNUSED(tls)) | const TaskParallelTLS *__restrict UNUSED(tls)) | ||||
| { | { | ||||
| PBVHUpdateData *data = userdata; | PBVHUpdateData *data = userdata; | ||||
| PBVH *pbvh = data->pbvh; | PBVH *pbvh = data->pbvh; | ||||
| PBVHNode *node = data->nodes[n]; | PBVHNode *node = data->nodes[n]; | ||||
| Show All 12 Lines | if (node->flag & PBVH_Leaf) { | ||||
| if (vd.mask && *vd.mask > 0.0f) { | if (vd.mask && *vd.mask > 0.0f) { | ||||
| has_masked = false; | has_masked = false; | ||||
| } | } | ||||
| } | } | ||||
| BKE_pbvh_vertex_iter_end; | BKE_pbvh_vertex_iter_end; | ||||
| } | } | ||||
| else { | else { | ||||
| has_unmasked = true; | has_unmasked = true; | ||||
| has_masked = true; | has_masked = true; | ||||
mont29: This optimization can be added to orig code as well I think (in… | |||||
| } | } | ||||
| BKE_pbvh_node_fully_masked_set(node, !has_unmasked); | BKE_pbvh_node_fully_masked_set(node, !has_unmasked); | ||||
| BKE_pbvh_node_fully_unmasked_set(node, has_masked); | BKE_pbvh_node_fully_unmasked_set(node, has_masked); | ||||
| node->flag &= ~PBVH_UpdateMask; | node->flag &= ~PBVH_UpdateMask; | ||||
| } | } | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 1,460 Lines • ▼ Show 20 Lines | bool BKE_pbvh_node_frustum_exclude_AABB(PBVHNode *node, void *data) | ||||
| const float *bb_min, *bb_max; | const float *bb_min, *bb_max; | ||||
| /* BKE_pbvh_node_get_BB */ | /* BKE_pbvh_node_get_BB */ | ||||
| bb_min = node->vb.bmin; | bb_min = node->vb.bmin; | ||||
| bb_max = node->vb.bmax; | bb_max = node->vb.bmax; | ||||
| return test_frustum_aabb(bb_min, bb_max, data) != ISECT_INSIDE; | return test_frustum_aabb(bb_min, bb_max, data) != ISECT_INSIDE; | ||||
| } | } | ||||
| void BKE_pbvh_update_normals(PBVH *pbvh, struct SubdivCCG *subdiv_ccg) | void BKE_pbvh_update_normals(PBVH *pbvh, struct SubdivCCG *subdiv_ccg, struct MeshElemMap *pmap) | ||||
| { | { | ||||
| /* Update normals */ | /* Update normals */ | ||||
| PBVHNode **nodes; | PBVHNode **nodes; | ||||
| int totnode; | int totnode; | ||||
| BKE_pbvh_search_gather( | BKE_pbvh_search_gather( | ||||
| pbvh, update_search_cb, POINTER_FROM_INT(PBVH_UpdateNormals), &nodes, &totnode); | pbvh, update_search_cb, POINTER_FROM_INT(PBVH_UpdateNormals), &nodes, &totnode); | ||||
| if (totnode > 0) { | if (totnode > 0) { | ||||
| if (pbvh->type == PBVH_BMESH) { | if (pbvh->type == PBVH_BMESH) { | ||||
| pbvh_bmesh_normals_update(nodes, totnode); | pbvh_bmesh_normals_update(nodes, totnode); | ||||
| } | } | ||||
| else if (pbvh->type == PBVH_FACES) { | else if (pbvh->type == PBVH_FACES) { | ||||
| if (pmap) { | |||||
| double time_start = PIL_check_seconds_timer(); | |||||
| pbvh_faces_update_normals_pmap(pbvh, nodes, totnode, pmap); | |||||
| double time_end = PIL_check_seconds_timer(); | |||||
| printf("PMAP UPDATE %f\n", time_end - time_start); | |||||
| } | |||||
| else { | |||||
| double time_start = PIL_check_seconds_timer(); | |||||
| pbvh_faces_update_normals(pbvh, nodes, totnode); | pbvh_faces_update_normals(pbvh, nodes, totnode); | ||||
| double time_end = PIL_check_seconds_timer(); | |||||
| printf("REGULAR UPDATE %f\n", time_end - time_start); | |||||
| } | |||||
| } | } | ||||
| else if (pbvh->type == PBVH_GRIDS) { | else if (pbvh->type == PBVH_GRIDS) { | ||||
| struct CCGFace **faces; | struct CCGFace **faces; | ||||
| int num_faces; | int num_faces; | ||||
| BKE_pbvh_get_grid_updates(pbvh, true, (void ***)&faces, &num_faces); | BKE_pbvh_get_grid_updates(pbvh, true, (void ***)&faces, &num_faces); | ||||
| if (num_faces > 0) { | if (num_faces > 0) { | ||||
| BKE_subdiv_ccg_update_normals(subdiv_ccg, faces, num_faces); | BKE_subdiv_ccg_update_normals(subdiv_ccg, faces, num_faces); | ||||
| MEM_freeN(faces); | MEM_freeN(faces); | ||||
| ▲ Show 20 Lines • Show All 411 Lines • Show Last 20 Lines | |||||
This optimization can be added to orig code as well I think (in pbvh_update_normals_accum_task_cb)?