Merge remote-tracking branch 'origin/blender-v3.1-release'
This commit is contained in:
commit
3a0df7d37b
|
@ -14,6 +14,7 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
struct Mesh;
|
||||
struct MEdge;
|
||||
struct Subdiv;
|
||||
|
||||
typedef struct SubdivToMeshSettings {
|
||||
|
@ -33,6 +34,14 @@ struct Mesh *BKE_subdiv_to_mesh(struct Subdiv *subdiv,
|
|||
const SubdivToMeshSettings *settings,
|
||||
const struct Mesh *coarse_mesh);
|
||||
|
||||
/* Interpolate a position along the `coarse_edge` at the relative `u` coordinate. If `is_simple` is
|
||||
* false, this will perform a B-Spline interpolation using the edge neighbors, otherwise a linear
|
||||
* interpolation will be done base on the edge vertices. */
|
||||
void BKE_subdiv_mesh_interpolate_position_on_edge(const struct Mesh *coarse_mesh,
|
||||
const struct MEdge *coarse_edge,
|
||||
bool is_simple,
|
||||
float u,
|
||||
float pos_r[3]);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -930,11 +930,10 @@ static void subdiv_mesh_vertex_loose(const SubdivForeachContext *foreach_context
|
|||
/* Get neighbor edges of the given one.
|
||||
* - neighbors[0] is an edge adjacent to edge->v1.
|
||||
* - neighbors[1] is an edge adjacent to edge->v2. */
|
||||
static void find_edge_neighbors(const SubdivMeshContext *ctx,
|
||||
static void find_edge_neighbors(const Mesh *coarse_mesh,
|
||||
const MEdge *edge,
|
||||
const MEdge *neighbors[2])
|
||||
{
|
||||
const Mesh *coarse_mesh = ctx->coarse_mesh;
|
||||
const MEdge *coarse_medge = coarse_mesh->medge;
|
||||
neighbors[0] = NULL;
|
||||
neighbors[1] = NULL;
|
||||
|
@ -964,12 +963,11 @@ static void find_edge_neighbors(const SubdivMeshContext *ctx,
|
|||
}
|
||||
}
|
||||
|
||||
static void points_for_loose_edges_interpolation_get(SubdivMeshContext *ctx,
|
||||
static void points_for_loose_edges_interpolation_get(const Mesh *coarse_mesh,
|
||||
const MEdge *coarse_edge,
|
||||
const MEdge *neighbors[2],
|
||||
float points_r[4][3])
|
||||
{
|
||||
const Mesh *coarse_mesh = ctx->coarse_mesh;
|
||||
const MVert *coarse_mvert = coarse_mesh->mvert;
|
||||
/* Middle points corresponds to the edge. */
|
||||
copy_v3_v3(points_r[1], coarse_mvert[coarse_edge->v1].co);
|
||||
|
@ -1002,6 +1000,30 @@ static void points_for_loose_edges_interpolation_get(SubdivMeshContext *ctx,
|
|||
}
|
||||
}
|
||||
|
||||
void BKE_subdiv_mesh_interpolate_position_on_edge(const Mesh *coarse_mesh,
|
||||
const MEdge *coarse_edge,
|
||||
const bool is_simple,
|
||||
const float u,
|
||||
float pos_r[3])
|
||||
{
|
||||
if (is_simple) {
|
||||
const MVert *coarse_mvert = coarse_mesh->mvert;
|
||||
const MVert *vert_1 = &coarse_mvert[coarse_edge->v1];
|
||||
const MVert *vert_2 = &coarse_mvert[coarse_edge->v2];
|
||||
interp_v3_v3v3(pos_r, vert_1->co, vert_2->co, u);
|
||||
}
|
||||
else {
|
||||
/* Find neighbors of the coarse edge. */
|
||||
const MEdge *neighbors[2];
|
||||
find_edge_neighbors(coarse_mesh, coarse_edge, neighbors);
|
||||
float points[4][3];
|
||||
points_for_loose_edges_interpolation_get(coarse_mesh, coarse_edge, neighbors, points);
|
||||
float weights[4];
|
||||
key_curve_position_weights(u, weights, KEY_BSPLINE);
|
||||
interp_v3_v3v3v3v3(pos_r, points[0], points[1], points[2], points[3], weights);
|
||||
}
|
||||
}
|
||||
|
||||
static void subdiv_mesh_vertex_of_loose_edge_interpolate(SubdivMeshContext *ctx,
|
||||
const MEdge *coarse_edge,
|
||||
const float u,
|
||||
|
@ -1038,9 +1060,6 @@ static void subdiv_mesh_vertex_of_loose_edge(const struct SubdivForeachContext *
|
|||
Mesh *subdiv_mesh = ctx->subdiv_mesh;
|
||||
MVert *subdiv_mvert = subdiv_mesh->mvert;
|
||||
const bool is_simple = ctx->subdiv->settings.is_simple;
|
||||
/* Find neighbors of the current loose edge. */
|
||||
const MEdge *neighbors[2];
|
||||
find_edge_neighbors(ctx, coarse_edge, neighbors);
|
||||
/* Interpolate custom data when not an end point.
|
||||
* This data has already been copied from the original vertex by #subdiv_mesh_vertex_loose. */
|
||||
if (!ELEM(u, 0.0, 1.0)) {
|
||||
|
@ -1048,19 +1067,8 @@ static void subdiv_mesh_vertex_of_loose_edge(const struct SubdivForeachContext *
|
|||
}
|
||||
/* Interpolate coordinate. */
|
||||
MVert *subdiv_vertex = &subdiv_mvert[subdiv_vertex_index];
|
||||
if (is_simple) {
|
||||
const MVert *coarse_mvert = coarse_mesh->mvert;
|
||||
const MVert *vert_1 = &coarse_mvert[coarse_edge->v1];
|
||||
const MVert *vert_2 = &coarse_mvert[coarse_edge->v2];
|
||||
interp_v3_v3v3(subdiv_vertex->co, vert_1->co, vert_2->co, u);
|
||||
}
|
||||
else {
|
||||
float points[4][3];
|
||||
points_for_loose_edges_interpolation_get(ctx, coarse_edge, neighbors, points);
|
||||
float weights[4];
|
||||
key_curve_position_weights(u, weights, KEY_BSPLINE);
|
||||
interp_v3_v3v3v3v3(subdiv_vertex->co, points[0], points[1], points[2], points[3], weights);
|
||||
}
|
||||
BKE_subdiv_mesh_interpolate_position_on_edge(
|
||||
coarse_mesh, coarse_edge, is_simple, u, subdiv_vertex->co);
|
||||
/* Reset flags and such. */
|
||||
subdiv_vertex->flag = 0;
|
||||
/* TODO(sergey): This matches old behavior, but we can as well interpolate
|
||||
|
|
|
@ -806,7 +806,27 @@ static void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache *cache,
|
|||
extractors.append(&extract_fdots_pos);
|
||||
}
|
||||
|
||||
EXTRACT_ADD_REQUESTED(ibo, lines);
|
||||
if (DRW_ibo_requested(mbuflist->ibo.lines_loose)) {
|
||||
/* `ibo.lines_loose` require the `ibo.lines` buffer. */
|
||||
if (mbuflist->ibo.lines == nullptr) {
|
||||
DRW_ibo_request(nullptr, &mbuflist->ibo.lines);
|
||||
}
|
||||
const MeshExtract *extractor = DRW_ibo_requested(mbuflist->ibo.lines) ?
|
||||
&extract_lines_with_lines_loose :
|
||||
&extract_lines_loose_only;
|
||||
extractors.append(extractor);
|
||||
}
|
||||
else if (DRW_ibo_requested(mbuflist->ibo.lines)) {
|
||||
const MeshExtract *extractor;
|
||||
if (mbuflist->ibo.lines_loose != nullptr) {
|
||||
/* Update `ibo.lines_loose` as it depends on `ibo.lines`. */
|
||||
extractor = &extract_lines_with_lines_loose;
|
||||
}
|
||||
else {
|
||||
extractor = &extract_lines;
|
||||
}
|
||||
extractors.append(extractor);
|
||||
}
|
||||
EXTRACT_ADD_REQUESTED(ibo, edituv_points);
|
||||
EXTRACT_ADD_REQUESTED(ibo, edituv_tris);
|
||||
EXTRACT_ADD_REQUESTED(ibo, edituv_lines);
|
||||
|
@ -835,6 +855,7 @@ static void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache *cache,
|
|||
|
||||
mesh_render_data_update_looptris(mr, MR_ITER_LOOPTRI, MR_DATA_LOOPTRI);
|
||||
mesh_render_data_update_loose_geom(mr, mbc, MR_ITER_LEDGE | MR_ITER_LVERT, MR_DATA_LOOSE_GEOM);
|
||||
DRW_subdivide_loose_geom(subdiv_cache, mbc);
|
||||
|
||||
void *data_stack = MEM_mallocN(extractors.data_size_total(), __func__);
|
||||
uint32_t data_offset = 0;
|
||||
|
@ -868,7 +889,7 @@ static void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache *cache,
|
|||
}
|
||||
|
||||
if (extractor->iter_loose_geom_subdiv) {
|
||||
extractor->iter_loose_geom_subdiv(subdiv_cache, mr, &mbc->loose_geom, buffer, data);
|
||||
extractor->iter_loose_geom_subdiv(subdiv_cache, mr, buffer, data);
|
||||
}
|
||||
|
||||
if (extractor->finish_subdiv) {
|
||||
|
|
|
@ -518,6 +518,11 @@ static void draw_patch_map_free(DRWPatchMap *gpu_patch_map)
|
|||
/** \name DRWSubdivCache
|
||||
* \{ */
|
||||
|
||||
static bool draw_subdiv_cache_need_polygon_data(const DRWSubdivCache *cache)
|
||||
{
|
||||
return cache->subdiv && cache->subdiv->evaluator && cache->num_subdiv_loops != 0;
|
||||
}
|
||||
|
||||
static void draw_subdiv_cache_free_material_data(DRWSubdivCache *cache)
|
||||
{
|
||||
GPU_VERTBUF_DISCARD_SAFE(cache->polygon_mat_offset);
|
||||
|
@ -550,6 +555,7 @@ void draw_subdiv_cache_free(DRWSubdivCache *cache)
|
|||
cache->num_subdiv_triangles = 0;
|
||||
cache->num_coarse_poly = 0;
|
||||
cache->num_subdiv_quads = 0;
|
||||
cache->may_have_loose_geom = false;
|
||||
draw_subdiv_free_edit_mode_cache(cache);
|
||||
draw_subdiv_cache_free_material_data(cache);
|
||||
draw_patch_map_free(&cache->gpu_patch_map);
|
||||
|
@ -557,6 +563,11 @@ void draw_subdiv_cache_free(DRWSubdivCache *cache)
|
|||
GPU_uniformbuf_free(cache->ubo);
|
||||
cache->ubo = nullptr;
|
||||
}
|
||||
MEM_SAFE_FREE(cache->loose_geom.edges);
|
||||
MEM_SAFE_FREE(cache->loose_geom.verts);
|
||||
cache->loose_geom.edge_len = 0;
|
||||
cache->loose_geom.vert_len = 0;
|
||||
cache->loose_geom.loop_len = 0;
|
||||
}
|
||||
|
||||
/* Flags used in #DRWSubdivCache.extra_coarse_face_data. The flags are packed in the upper bits of
|
||||
|
@ -729,19 +740,25 @@ static bool draw_subdiv_topology_info_cb(const SubdivForeachContext *foreach_con
|
|||
const int num_polygons,
|
||||
const int *subdiv_polygon_offset)
|
||||
{
|
||||
if (num_loops == 0) {
|
||||
/* num_loops does not take into account meshes with only loose geometry, which might be meshes
|
||||
* used as custom bone shapes, so let's check the num_vertices also. */
|
||||
if (num_vertices == 0 && num_loops == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DRWCacheBuildingContext *ctx = (DRWCacheBuildingContext *)(foreach_context->user_data);
|
||||
DRWSubdivCache *cache = ctx->cache;
|
||||
|
||||
/* Set topology information. */
|
||||
cache->num_subdiv_edges = (uint)num_edges;
|
||||
cache->num_subdiv_loops = (uint)num_loops;
|
||||
cache->num_subdiv_verts = (uint)num_vertices;
|
||||
cache->num_subdiv_quads = (uint)num_polygons;
|
||||
cache->subdiv_polygon_offset = static_cast<int *>(MEM_dupallocN(subdiv_polygon_offset));
|
||||
/* Set topology information only if we have loops. */
|
||||
if (num_loops != 0) {
|
||||
cache->num_subdiv_edges = (uint)num_edges;
|
||||
cache->num_subdiv_loops = (uint)num_loops;
|
||||
cache->num_subdiv_verts = (uint)num_vertices;
|
||||
cache->num_subdiv_quads = (uint)num_polygons;
|
||||
cache->subdiv_polygon_offset = static_cast<int *>(MEM_dupallocN(subdiv_polygon_offset));
|
||||
}
|
||||
|
||||
cache->may_have_loose_geom = num_vertices != 0 || num_edges != 0;
|
||||
|
||||
/* Initialize cache buffers, prefer dynamic usage so we can reuse memory on the host even after
|
||||
* it was sent to the device, since we may use the data while building other buffers on the CPU
|
||||
|
@ -780,16 +797,20 @@ static bool draw_subdiv_topology_info_cb(const SubdivForeachContext *foreach_con
|
|||
ctx->e_origindex = static_cast<int *>(
|
||||
CustomData_get_layer(&ctx->coarse_mesh->edata, CD_ORIGINDEX));
|
||||
|
||||
ctx->vert_origindex_map = static_cast<int *>(
|
||||
MEM_mallocN(cache->num_subdiv_verts * sizeof(int), "subdiv_vert_origindex_map"));
|
||||
for (int i = 0; i < num_vertices; i++) {
|
||||
ctx->vert_origindex_map[i] = -1;
|
||||
if (cache->num_subdiv_verts) {
|
||||
ctx->vert_origindex_map = static_cast<int *>(
|
||||
MEM_mallocN(cache->num_subdiv_verts * sizeof(int), "subdiv_vert_origindex_map"));
|
||||
for (int i = 0; i < num_vertices; i++) {
|
||||
ctx->vert_origindex_map[i] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
ctx->edge_origindex_map = static_cast<int *>(
|
||||
MEM_mallocN(cache->num_subdiv_edges * sizeof(int), "subdiv_edge_origindex_map"));
|
||||
for (int i = 0; i < num_edges; i++) {
|
||||
ctx->edge_origindex_map[i] = -1;
|
||||
if (cache->num_subdiv_edges) {
|
||||
ctx->edge_origindex_map = static_cast<int *>(
|
||||
MEM_mallocN(cache->num_subdiv_edges * sizeof(int), "subdiv_edge_origindex_map"));
|
||||
for (int i = 0; i < num_edges; i++) {
|
||||
ctx->edge_origindex_map[i] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -833,6 +854,10 @@ static void draw_subdiv_edge_cb(const SubdivForeachContext *foreach_context,
|
|||
{
|
||||
DRWCacheBuildingContext *ctx = (DRWCacheBuildingContext *)(foreach_context->user_data);
|
||||
|
||||
if (!ctx->edge_origindex_map) {
|
||||
return;
|
||||
}
|
||||
|
||||
int coarse_index = coarse_edge_index;
|
||||
|
||||
if (coarse_index != -1) {
|
||||
|
@ -983,7 +1008,8 @@ static bool draw_subdiv_build_cache(DRWSubdivCache *cache,
|
|||
cache_building_context.cache = cache;
|
||||
|
||||
do_subdiv_traversal(&cache_building_context, subdiv);
|
||||
if (cache->num_subdiv_loops == 0) {
|
||||
if (cache->num_subdiv_loops == 0 && cache->num_subdiv_verts == 0 &&
|
||||
!cache->may_have_loose_geom) {
|
||||
/* Either the traversal failed, or we have an empty mesh, either way we cannot go any further.
|
||||
* The subdiv_polygon_offset cannot then be reliably stored in the cache, so free it directly.
|
||||
*/
|
||||
|
@ -991,44 +1017,47 @@ static bool draw_subdiv_build_cache(DRWSubdivCache *cache,
|
|||
return false;
|
||||
}
|
||||
|
||||
/* Build buffers for the PatchMap. */
|
||||
draw_patch_map_build(&cache->gpu_patch_map, subdiv);
|
||||
/* Only build polygon related data if we have polygons. */
|
||||
if (cache->num_subdiv_loops != 0) {
|
||||
/* Build buffers for the PatchMap. */
|
||||
draw_patch_map_build(&cache->gpu_patch_map, subdiv);
|
||||
|
||||
cache->face_ptex_offset = BKE_subdiv_face_ptex_offset_get(subdiv);
|
||||
cache->face_ptex_offset = BKE_subdiv_face_ptex_offset_get(subdiv);
|
||||
|
||||
/* Build patch coordinates for all the face dots. */
|
||||
cache->fdots_patch_coords = gpu_vertbuf_create_from_format(get_blender_patch_coords_format(),
|
||||
mesh_eval->totpoly);
|
||||
CompressedPatchCoord *blender_fdots_patch_coords = (CompressedPatchCoord *)GPU_vertbuf_get_data(
|
||||
cache->fdots_patch_coords);
|
||||
for (int i = 0; i < mesh_eval->totpoly; i++) {
|
||||
const int ptex_face_index = cache->face_ptex_offset[i];
|
||||
if (mesh_eval->mpoly[i].totloop == 4) {
|
||||
/* For quads, the center coordinate of the coarse face has `u = v = 0.5`. */
|
||||
blender_fdots_patch_coords[i] = make_patch_coord(ptex_face_index, 0.5f, 0.5f);
|
||||
}
|
||||
else {
|
||||
/* For N-gons, since they are split into quads from the center, and since the center is
|
||||
* chosen to be the top right corner of each quad, the center coordinate of the coarse face
|
||||
* is any one of those top right corners with `u = v = 1.0`. */
|
||||
blender_fdots_patch_coords[i] = make_patch_coord(ptex_face_index, 1.0f, 1.0f);
|
||||
/* Build patch coordinates for all the face dots. */
|
||||
cache->fdots_patch_coords = gpu_vertbuf_create_from_format(get_blender_patch_coords_format(),
|
||||
mesh_eval->totpoly);
|
||||
CompressedPatchCoord *blender_fdots_patch_coords = (CompressedPatchCoord *)
|
||||
GPU_vertbuf_get_data(cache->fdots_patch_coords);
|
||||
for (int i = 0; i < mesh_eval->totpoly; i++) {
|
||||
const int ptex_face_index = cache->face_ptex_offset[i];
|
||||
if (mesh_eval->mpoly[i].totloop == 4) {
|
||||
/* For quads, the center coordinate of the coarse face has `u = v = 0.5`. */
|
||||
blender_fdots_patch_coords[i] = make_patch_coord(ptex_face_index, 0.5f, 0.5f);
|
||||
}
|
||||
else {
|
||||
/* For N-gons, since they are split into quads from the center, and since the center is
|
||||
* chosen to be the top right corner of each quad, the center coordinate of the coarse face
|
||||
* is any one of those top right corners with `u = v = 1.0`. */
|
||||
blender_fdots_patch_coords[i] = make_patch_coord(ptex_face_index, 1.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
cache->subdiv_polygon_offset_buffer = draw_subdiv_build_origindex_buffer(
|
||||
cache->subdiv_polygon_offset, mesh_eval->totpoly);
|
||||
|
||||
cache->face_ptex_offset_buffer = draw_subdiv_build_origindex_buffer(cache->face_ptex_offset,
|
||||
mesh_eval->totpoly + 1);
|
||||
|
||||
build_vertex_face_adjacency_maps(cache);
|
||||
}
|
||||
|
||||
cache->resolution = to_mesh_settings.resolution;
|
||||
|
||||
cache->subdiv_polygon_offset_buffer = draw_subdiv_build_origindex_buffer(
|
||||
cache->subdiv_polygon_offset, mesh_eval->totpoly);
|
||||
|
||||
cache->face_ptex_offset_buffer = draw_subdiv_build_origindex_buffer(cache->face_ptex_offset,
|
||||
mesh_eval->totpoly + 1);
|
||||
cache->num_coarse_poly = mesh_eval->totpoly;
|
||||
|
||||
build_vertex_face_adjacency_maps(cache);
|
||||
|
||||
/* Cleanup. */
|
||||
MEM_freeN(cache_building_context.vert_origindex_map);
|
||||
MEM_freeN(cache_building_context.edge_origindex_map);
|
||||
MEM_SAFE_FREE(cache_building_context.vert_origindex_map);
|
||||
MEM_SAFE_FREE(cache_building_context.edge_origindex_map);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1184,6 +1213,11 @@ static void drw_subdiv_compute_dispatch(const DRWSubdivCache *cache,
|
|||
|
||||
void draw_subdiv_extract_pos_nor(const DRWSubdivCache *cache, GPUVertBuf *pos_nor)
|
||||
{
|
||||
if (!draw_subdiv_cache_need_polygon_data(cache)) {
|
||||
/* Happens on meshes with only loose geometry. */
|
||||
return;
|
||||
}
|
||||
|
||||
Subdiv *subdiv = cache->subdiv;
|
||||
OpenSubdiv_Evaluator *evaluator = subdiv->evaluator;
|
||||
|
||||
|
@ -1241,6 +1275,11 @@ void draw_subdiv_extract_uvs(const DRWSubdivCache *cache,
|
|||
const int face_varying_channel,
|
||||
const int dst_offset)
|
||||
{
|
||||
if (!draw_subdiv_cache_need_polygon_data(cache)) {
|
||||
/* Happens on meshes with only loose geometry. */
|
||||
return;
|
||||
}
|
||||
|
||||
Subdiv *subdiv = cache->subdiv;
|
||||
OpenSubdiv_Evaluator *evaluator = subdiv->evaluator;
|
||||
|
||||
|
@ -1462,6 +1501,11 @@ void draw_subdiv_build_tris_buffer(const DRWSubdivCache *cache,
|
|||
GPUIndexBuf *subdiv_tris,
|
||||
const int material_count)
|
||||
{
|
||||
if (!draw_subdiv_cache_need_polygon_data(cache)) {
|
||||
/* Happens on meshes with only loose geometry. */
|
||||
return;
|
||||
}
|
||||
|
||||
const bool do_single_material = material_count <= 1;
|
||||
|
||||
const char *defines = "#define SUBDIV_POLYGON_OFFSET\n";
|
||||
|
@ -1498,6 +1542,11 @@ void draw_subdiv_build_fdots_buffers(const DRWSubdivCache *cache,
|
|||
GPUVertBuf *fdots_nor,
|
||||
GPUIndexBuf *fdots_indices)
|
||||
{
|
||||
if (!draw_subdiv_cache_need_polygon_data(cache)) {
|
||||
/* Happens on meshes with only loose geometry. */
|
||||
return;
|
||||
}
|
||||
|
||||
Subdiv *subdiv = cache->subdiv;
|
||||
OpenSubdiv_Evaluator *evaluator = subdiv->evaluator;
|
||||
|
||||
|
@ -1616,6 +1665,11 @@ void draw_subdiv_build_lnor_buffer(const DRWSubdivCache *cache,
|
|||
GPUVertBuf *pos_nor,
|
||||
GPUVertBuf *lnor)
|
||||
{
|
||||
if (!draw_subdiv_cache_need_polygon_data(cache)) {
|
||||
/* Happens on meshes with only loose geometry. */
|
||||
return;
|
||||
}
|
||||
|
||||
GPUShader *shader = get_subdiv_shader(SHADER_BUFFER_LNOR, "#define SUBDIV_POLYGON_OFFSET\n");
|
||||
GPU_shader_bind(shader);
|
||||
|
||||
|
@ -1831,7 +1885,15 @@ static bool draw_subdiv_create_requested_buffers(const Scene *scene,
|
|||
|
||||
if (!BKE_subdiv_eval_begin_from_mesh(
|
||||
subdiv, mesh_eval, nullptr, SUBDIV_EVALUATOR_TYPE_GLSL_COMPUTE, evaluator_cache)) {
|
||||
return false;
|
||||
/* This could happen in two situations:
|
||||
* - OpenSubdiv is disabled.
|
||||
* - Something totally bad happened, and OpenSubdiv rejected our
|
||||
* topology.
|
||||
* In either way, we can't safely continue. However, we still have to handle potential loose
|
||||
* geometry, which is done separately. */
|
||||
if (mesh_eval->totpoly) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
DRWSubdivCache *draw_cache = mesh_batch_cache_ensure_subdiv_cache(batch_cache);
|
||||
|
@ -1868,6 +1930,104 @@ static bool draw_subdiv_create_requested_buffers(const Scene *scene,
|
|||
return true;
|
||||
}
|
||||
|
||||
void DRW_subdivide_loose_geom(DRWSubdivCache *subdiv_cache, MeshBufferCache *cache)
|
||||
{
|
||||
const int coarse_loose_vert_len = cache->loose_geom.vert_len;
|
||||
const int coarse_loose_edge_len = cache->loose_geom.edge_len;
|
||||
|
||||
if (coarse_loose_vert_len == 0 && coarse_loose_edge_len == 0) {
|
||||
/* Nothing to do. */
|
||||
return;
|
||||
}
|
||||
|
||||
if (subdiv_cache->loose_geom.edges || subdiv_cache->loose_geom.verts) {
|
||||
/* Already processed. */
|
||||
return;
|
||||
}
|
||||
|
||||
const Mesh *coarse_mesh = subdiv_cache->mesh;
|
||||
const bool is_simple = subdiv_cache->subdiv->settings.is_simple;
|
||||
const int resolution = subdiv_cache->resolution;
|
||||
const int resolution_1 = resolution - 1;
|
||||
const float inv_resolution_1 = 1.0f / (float)resolution_1;
|
||||
const int num_subdiv_vertices_per_coarse_edge = resolution - 2;
|
||||
|
||||
const int num_subdivided_edge = coarse_loose_edge_len *
|
||||
(num_subdiv_vertices_per_coarse_edge + 1);
|
||||
|
||||
/* Each edge will store data for its 2 verts, that way we can keep the overall logic simple, here
|
||||
* and in the buffer extractors. Although it duplicates memory (and work), the buffers also store
|
||||
* duplicate values. */
|
||||
const int num_subdivided_verts = num_subdivided_edge * 2;
|
||||
|
||||
DRWSubdivLooseEdge *loose_subd_edges = static_cast<DRWSubdivLooseEdge *>(
|
||||
MEM_callocN(sizeof(DRWSubdivLooseEdge) * num_subdivided_edge, "DRWSubdivLooseEdge"));
|
||||
|
||||
DRWSubdivLooseVertex *loose_subd_verts = static_cast<DRWSubdivLooseVertex *>(
|
||||
MEM_callocN(sizeof(DRWSubdivLooseVertex) * (num_subdivided_verts + coarse_loose_vert_len),
|
||||
"DRWSubdivLooseEdge"));
|
||||
|
||||
int subd_edge_offset = 0;
|
||||
int subd_vert_offset = 0;
|
||||
|
||||
/* Subdivide each loose coarse edge. */
|
||||
for (int i = 0; i < coarse_loose_edge_len; i++) {
|
||||
const int coarse_edge_index = cache->loose_geom.edges[i];
|
||||
const MEdge *coarse_edge = &coarse_mesh->medge[cache->loose_geom.edges[i]];
|
||||
|
||||
/* Perform interpolation of each vertex. */
|
||||
for (int i = 0; i < resolution - 1; i++, subd_edge_offset++) {
|
||||
DRWSubdivLooseEdge &subd_edge = loose_subd_edges[subd_edge_offset];
|
||||
subd_edge.coarse_edge_index = coarse_edge_index;
|
||||
|
||||
/* First vert. */
|
||||
DRWSubdivLooseVertex &subd_v1 = loose_subd_verts[subd_vert_offset];
|
||||
subd_v1.coarse_vertex_index = (i == 0) ? coarse_edge->v1 : -1u;
|
||||
const float u1 = i * inv_resolution_1;
|
||||
BKE_subdiv_mesh_interpolate_position_on_edge(
|
||||
coarse_mesh, coarse_edge, is_simple, u1, subd_v1.co);
|
||||
|
||||
subd_edge.loose_subdiv_v1_index = subd_vert_offset++;
|
||||
|
||||
/* Second vert. */
|
||||
DRWSubdivLooseVertex &subd_v2 = loose_subd_verts[subd_vert_offset];
|
||||
subd_v2.coarse_vertex_index = ((i + 1) == resolution - 1) ? coarse_edge->v2 : -1u;
|
||||
const float u2 = (i + 1) * inv_resolution_1;
|
||||
BKE_subdiv_mesh_interpolate_position_on_edge(
|
||||
coarse_mesh, coarse_edge, is_simple, u2, subd_v2.co);
|
||||
|
||||
subd_edge.loose_subdiv_v2_index = subd_vert_offset++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy the remaining loose_verts. */
|
||||
for (int i = 0; i < coarse_loose_vert_len; i++) {
|
||||
const int coarse_vertex_index = cache->loose_geom.verts[i];
|
||||
const MVert &coarse_vertex = coarse_mesh->mvert[coarse_vertex_index];
|
||||
|
||||
DRWSubdivLooseVertex &subd_v = loose_subd_verts[subd_vert_offset++];
|
||||
subd_v.coarse_vertex_index = cache->loose_geom.verts[i];
|
||||
copy_v3_v3(subd_v.co, coarse_vertex.co);
|
||||
}
|
||||
|
||||
subdiv_cache->loose_geom.edges = loose_subd_edges;
|
||||
subdiv_cache->loose_geom.verts = loose_subd_verts;
|
||||
subdiv_cache->loose_geom.edge_len = num_subdivided_edge;
|
||||
subdiv_cache->loose_geom.vert_len = coarse_loose_vert_len;
|
||||
subdiv_cache->loose_geom.loop_len = num_subdivided_edge * 2 + coarse_loose_vert_len;
|
||||
}
|
||||
|
||||
blender::Span<DRWSubdivLooseEdge> draw_subdiv_cache_get_loose_edges(const DRWSubdivCache *cache)
|
||||
{
|
||||
return {cache->loose_geom.edges, static_cast<int64_t>(cache->loose_geom.edge_len)};
|
||||
}
|
||||
|
||||
blender::Span<DRWSubdivLooseVertex> draw_subdiv_cache_get_loose_verts(const DRWSubdivCache *cache)
|
||||
{
|
||||
return {cache->loose_geom.verts + cache->loose_geom.edge_len * 2,
|
||||
static_cast<int64_t>(cache->loose_geom.vert_len)};
|
||||
}
|
||||
|
||||
static OpenSubdiv_EvaluatorCache *g_evaluator_cache = nullptr;
|
||||
|
||||
void DRW_create_subdivision(const Scene *scene,
|
||||
|
|
|
@ -40,6 +40,56 @@ typedef struct DRWPatchMap {
|
|||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name DRWSubdivLooseEdge
|
||||
*
|
||||
* This stores information about a subdivided loose edge.
|
||||
* \{ */
|
||||
|
||||
typedef struct DRWSubdivLooseEdge {
|
||||
/* The corresponding coarse edge, this is always valid. */
|
||||
int coarse_edge_index;
|
||||
/* Pointers into #DRWSubdivLooseGeom.verts. */
|
||||
int loose_subdiv_v1_index;
|
||||
int loose_subdiv_v2_index;
|
||||
} DRWSubdivLooseEdge;
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name DRWSubdivLooseVertex
|
||||
*
|
||||
* This stores information about a subdivided loose vertex, that may or may not come from a loose
|
||||
* edge.
|
||||
* \{ */
|
||||
|
||||
typedef struct DRWSubdivLooseVertex {
|
||||
/* The corresponding coarse vertex, or -1 if this vertex is the result
|
||||
* of subdivision. */
|
||||
unsigned int coarse_vertex_index;
|
||||
/* Position and normal of the vertex. */
|
||||
float co[3];
|
||||
float nor[3];
|
||||
} DRWSubdivLooseVertex;
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name DRWSubdivLooseGeom
|
||||
*
|
||||
* This stores the subdivided vertices and edges of loose geometry from #MeshExtractLooseGeom.
|
||||
* \{ */
|
||||
|
||||
typedef struct DRWSubdivLooseGeom {
|
||||
DRWSubdivLooseEdge *edges;
|
||||
DRWSubdivLooseVertex *verts;
|
||||
int edge_len;
|
||||
int vert_len;
|
||||
int loop_len;
|
||||
} DRWSubdivLooseGeom;
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name DRWSubdivCache
|
||||
*
|
||||
|
@ -69,6 +119,11 @@ typedef struct DRWSubdivCache {
|
|||
uint num_subdiv_verts;
|
||||
uint num_subdiv_quads;
|
||||
|
||||
/* We only do the subdivision traversal for full faces, however we may have geometries that only
|
||||
* have loose edges (e.g. a custom bone shape). This flag is used to detect those cases, as the
|
||||
* counters above will all be set to zero if we do not have subdivision loops. */
|
||||
bool may_have_loose_geom;
|
||||
|
||||
/* Number of polygons in the coarse mesh, notably used to compute a coarse polygon index given a
|
||||
* subdivision loop index. */
|
||||
int num_coarse_poly;
|
||||
|
@ -113,6 +168,8 @@ typedef struct DRWSubdivCache {
|
|||
|
||||
DRWPatchMap gpu_patch_map;
|
||||
|
||||
DRWSubdivLooseGeom loose_geom;
|
||||
|
||||
/* UBO to store settings for the various compute shaders. */
|
||||
struct GPUUniformBuf *ubo;
|
||||
} DRWSubdivCache;
|
||||
|
@ -228,3 +285,15 @@ void draw_subdiv_build_edituv_stretch_angle_buffer(const DRWSubdivCache *cache,
|
|||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
# include "BLI_span.hh"
|
||||
|
||||
/* Helper to access the loose edges. */
|
||||
blender::Span<DRWSubdivLooseEdge> draw_subdiv_cache_get_loose_edges(const DRWSubdivCache *cache);
|
||||
|
||||
/* Helper to access only the loose vertices, i.e. not the ones attached to loose edges. To access
|
||||
* loose vertices of loose edges #draw_subdiv_cache_get_loose_edges should be used. */
|
||||
blender::Span<DRWSubdivLooseVertex> draw_subdiv_cache_get_loose_verts(const DRWSubdivCache *cache);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -190,7 +190,6 @@ typedef void(ExtractLVertMeshFn)(const MeshRenderData *mr,
|
|||
void *data);
|
||||
typedef void(ExtractLooseGeomSubdivFn)(const struct DRWSubdivCache *subdiv_cache,
|
||||
const MeshRenderData *mr,
|
||||
const MeshExtractLooseGeom *loose_geom,
|
||||
void *buffer,
|
||||
void *data);
|
||||
typedef void(ExtractInitFn)(const MeshRenderData *mr,
|
||||
|
|
|
@ -142,30 +142,35 @@ static void extract_lines_finish(const MeshRenderData *UNUSED(mr),
|
|||
}
|
||||
|
||||
static void extract_lines_init_subdiv(const DRWSubdivCache *subdiv_cache,
|
||||
const MeshRenderData *mr,
|
||||
const MeshRenderData *UNUSED(mr),
|
||||
struct MeshBatchCache *UNUSED(cache),
|
||||
void *buffer,
|
||||
void *UNUSED(data))
|
||||
{
|
||||
const DRWSubdivLooseGeom &loose_geom = subdiv_cache->loose_geom;
|
||||
GPUIndexBuf *ibo = static_cast<GPUIndexBuf *>(buffer);
|
||||
GPU_indexbuf_init_build_on_device(ibo,
|
||||
subdiv_cache->num_subdiv_loops * 2 + mr->edge_loose_len * 2);
|
||||
subdiv_cache->num_subdiv_loops * 2 + loose_geom.edge_len * 2);
|
||||
|
||||
if (subdiv_cache->num_subdiv_loops == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
draw_subdiv_build_lines_buffer(subdiv_cache, ibo);
|
||||
}
|
||||
|
||||
static void extract_lines_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache,
|
||||
const MeshRenderData *UNUSED(mr),
|
||||
const MeshExtractLooseGeom *loose_geom,
|
||||
void *buffer,
|
||||
void *UNUSED(data))
|
||||
{
|
||||
if (loose_geom->edge_len == 0) {
|
||||
const DRWSubdivLooseGeom &loose_geom = subdiv_cache->loose_geom;
|
||||
if (loose_geom.edge_len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
GPUIndexBuf *ibo = static_cast<GPUIndexBuf *>(buffer);
|
||||
draw_subdiv_build_lines_loose_buffer(subdiv_cache, ibo, static_cast<uint>(loose_geom->edge_len));
|
||||
draw_subdiv_build_lines_loose_buffer(subdiv_cache, ibo, static_cast<uint>(loose_geom.edge_len));
|
||||
}
|
||||
|
||||
constexpr MeshExtract create_extractor_lines()
|
||||
|
@ -215,6 +220,20 @@ static void extract_lines_with_lines_loose_finish(const MeshRenderData *mr,
|
|||
extract_lines_loose_subbuffer(mr, cache);
|
||||
}
|
||||
|
||||
static void extract_lines_with_lines_loose_finish_subdiv(const struct DRWSubdivCache *subdiv_cache,
|
||||
const MeshRenderData *UNUSED(mr),
|
||||
struct MeshBatchCache *cache,
|
||||
void *UNUSED(buf),
|
||||
void *UNUSED(_data))
|
||||
{
|
||||
/* Multiply by 2 because these are edges indices. */
|
||||
const int start = subdiv_cache->num_subdiv_loops * 2;
|
||||
const int len = subdiv_cache->loose_geom.edge_len * 2;
|
||||
GPU_indexbuf_create_subrange_in_place(
|
||||
cache->final.buff.ibo.lines_loose, cache->final.buff.ibo.lines, start, len);
|
||||
cache->no_loose_wire = (len == 0);
|
||||
}
|
||||
|
||||
constexpr MeshExtract create_extractor_lines_with_lines_loose()
|
||||
{
|
||||
MeshExtract extractor = {nullptr};
|
||||
|
@ -225,6 +244,9 @@ constexpr MeshExtract create_extractor_lines_with_lines_loose()
|
|||
extractor.iter_ledge_mesh = extract_lines_iter_ledge_mesh;
|
||||
extractor.task_reduce = extract_lines_task_reduce;
|
||||
extractor.finish = extract_lines_with_lines_loose_finish;
|
||||
extractor.init_subdiv = extract_lines_init_subdiv;
|
||||
extractor.iter_loose_geom_subdiv = extract_lines_loose_geom_subdiv;
|
||||
extractor.finish_subdiv = extract_lines_with_lines_loose_finish_subdiv;
|
||||
extractor.data_type = MR_DATA_NONE;
|
||||
extractor.data_size = sizeof(GPUIndexBufBuilder);
|
||||
extractor.use_threading = true;
|
||||
|
@ -248,10 +270,22 @@ static void extract_lines_loose_only_init(const MeshRenderData *mr,
|
|||
extract_lines_loose_subbuffer(mr, cache);
|
||||
}
|
||||
|
||||
static void extract_lines_loose_only_init_subdiv(const DRWSubdivCache *UNUSED(subdiv_cache),
|
||||
const MeshRenderData *mr,
|
||||
struct MeshBatchCache *cache,
|
||||
void *buffer,
|
||||
void *UNUSED(data))
|
||||
{
|
||||
BLI_assert(buffer == cache->final.buff.ibo.lines_loose);
|
||||
UNUSED_VARS_NDEBUG(buffer);
|
||||
extract_lines_loose_subbuffer(mr, cache);
|
||||
}
|
||||
|
||||
constexpr MeshExtract create_extractor_lines_loose_only()
|
||||
{
|
||||
MeshExtract extractor = {nullptr};
|
||||
extractor.init = extract_lines_loose_only_init;
|
||||
extractor.init_subdiv = extract_lines_loose_only_init_subdiv;
|
||||
extractor.data_type = MR_DATA_LOOSE_GEOM;
|
||||
extractor.data_size = 0;
|
||||
extractor.use_threading = false;
|
||||
|
|
|
@ -147,8 +147,10 @@ static void extract_points_init_subdiv(const DRWSubdivCache *subdiv_cache,
|
|||
void *data)
|
||||
{
|
||||
GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(data);
|
||||
GPU_indexbuf_init(
|
||||
elb, GPU_PRIM_POINTS, mr->vert_len, subdiv_cache->num_subdiv_loops + mr->loop_loose_len);
|
||||
GPU_indexbuf_init(elb,
|
||||
GPU_PRIM_POINTS,
|
||||
mr->vert_len,
|
||||
subdiv_cache->num_subdiv_loops + subdiv_cache->loose_geom.loop_len);
|
||||
}
|
||||
|
||||
static void extract_points_iter_subdiv_common(GPUIndexBufBuilder *elb,
|
||||
|
@ -196,46 +198,70 @@ static void extract_points_iter_subdiv_mesh(const DRWSubdivCache *subdiv_cache,
|
|||
|
||||
static void extract_points_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache,
|
||||
const MeshRenderData *mr,
|
||||
const MeshExtractLooseGeom *loose_geom,
|
||||
void *UNUSED(buffer),
|
||||
void *data)
|
||||
{
|
||||
const int loop_loose_len = loose_geom->edge_len + loose_geom->vert_len;
|
||||
const DRWSubdivLooseGeom &loose_geom = subdiv_cache->loose_geom;
|
||||
const int loop_loose_len = loose_geom.loop_len;
|
||||
if (loop_loose_len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(data);
|
||||
|
||||
uint offset = subdiv_cache->num_subdiv_loops;
|
||||
|
||||
if (mr->extract_type == MR_EXTRACT_MESH) {
|
||||
const Mesh *coarse_mesh = subdiv_cache->mesh;
|
||||
const MEdge *coarse_edges = coarse_mesh->medge;
|
||||
if (mr->extract_type != MR_EXTRACT_BMESH) {
|
||||
blender::Span<DRWSubdivLooseEdge> loose_edges = draw_subdiv_cache_get_loose_edges(
|
||||
subdiv_cache);
|
||||
|
||||
for (const DRWSubdivLooseEdge &loose_edge : loose_edges) {
|
||||
const DRWSubdivLooseVertex &v1 = loose_geom.verts[loose_edge.loose_subdiv_v1_index];
|
||||
const DRWSubdivLooseVertex &v2 = loose_geom.verts[loose_edge.loose_subdiv_v2_index];
|
||||
if (v1.coarse_vertex_index != -1u) {
|
||||
vert_set_mesh(elb, mr, v1.coarse_vertex_index, offset);
|
||||
}
|
||||
if (v2.coarse_vertex_index != -1u) {
|
||||
vert_set_mesh(elb, mr, v2.coarse_vertex_index, offset + 1);
|
||||
}
|
||||
|
||||
for (int i = 0; i < loose_geom->edge_len; i++) {
|
||||
const MEdge *loose_edge = &coarse_edges[loose_geom->edges[i]];
|
||||
vert_set_mesh(elb, mr, loose_edge->v1, offset);
|
||||
vert_set_mesh(elb, mr, loose_edge->v2, offset + 1);
|
||||
offset += 2;
|
||||
}
|
||||
blender::Span<DRWSubdivLooseVertex> loose_verts = draw_subdiv_cache_get_loose_verts(
|
||||
subdiv_cache);
|
||||
|
||||
for (int i = 0; i < loose_geom->vert_len; i++) {
|
||||
vert_set_mesh(elb, mr, loose_geom->verts[i], offset);
|
||||
for (const DRWSubdivLooseVertex &loose_vert : loose_verts) {
|
||||
vert_set_mesh(elb, mr, loose_vert.coarse_vertex_index, offset);
|
||||
offset += 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
BMesh *bm = mr->bm;
|
||||
for (int i = 0; i < loose_geom->edge_len; i++) {
|
||||
const BMEdge *loose_edge = BM_edge_at_index(bm, loose_geom->edges[i]);
|
||||
vert_set_bm(elb, loose_edge->v1, offset);
|
||||
vert_set_bm(elb, loose_edge->v2, offset + 1);
|
||||
blender::Span<DRWSubdivLooseEdge> loose_edges = draw_subdiv_cache_get_loose_edges(
|
||||
subdiv_cache);
|
||||
|
||||
for (const DRWSubdivLooseEdge &loose_edge : loose_edges) {
|
||||
const DRWSubdivLooseVertex &v1 = loose_geom.verts[loose_edge.loose_subdiv_v1_index];
|
||||
const DRWSubdivLooseVertex &v2 = loose_geom.verts[loose_edge.loose_subdiv_v2_index];
|
||||
if (v1.coarse_vertex_index != -1u) {
|
||||
BMVert *eve = mr->v_origindex ? bm_original_vert_get(mr, v1.coarse_vertex_index) :
|
||||
BM_vert_at_index(mr->bm, v1.coarse_vertex_index);
|
||||
vert_set_bm(elb, eve, offset);
|
||||
}
|
||||
if (v2.coarse_vertex_index != -1u) {
|
||||
BMVert *eve = mr->v_origindex ? bm_original_vert_get(mr, v2.coarse_vertex_index) :
|
||||
BM_vert_at_index(mr->bm, v2.coarse_vertex_index);
|
||||
vert_set_bm(elb, eve, offset + 1);
|
||||
}
|
||||
|
||||
offset += 2;
|
||||
}
|
||||
blender::Span<DRWSubdivLooseVertex> loose_verts = draw_subdiv_cache_get_loose_verts(
|
||||
subdiv_cache);
|
||||
|
||||
for (int i = 0; i < loose_geom->vert_len; i++) {
|
||||
const BMVert *loose_vert = BM_vert_at_index(bm, loose_geom->verts[i]);
|
||||
vert_set_bm(elb, loose_vert, offset);
|
||||
for (const DRWSubdivLooseVertex &loose_vert : loose_verts) {
|
||||
BMVert *eve = mr->v_origindex ? bm_original_vert_get(mr, loose_vert.coarse_vertex_index) :
|
||||
BM_vert_at_index(mr->bm, loose_vert.coarse_vertex_index);
|
||||
vert_set_bm(elb, eve, offset);
|
||||
offset += 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -217,16 +217,17 @@ static GPUVertFormat *get_subdiv_edge_fac_format()
|
|||
}
|
||||
|
||||
static void extract_edge_fac_init_subdiv(const DRWSubdivCache *subdiv_cache,
|
||||
const MeshRenderData *mr,
|
||||
const MeshRenderData *UNUSED(mr),
|
||||
struct MeshBatchCache *cache,
|
||||
void *buffer,
|
||||
void *UNUSED(data))
|
||||
{
|
||||
const DRWSubdivLooseGeom &loose_geom = subdiv_cache->loose_geom;
|
||||
GPUVertBuf *edge_idx = cache->final.buff.vbo.edge_idx;
|
||||
GPUVertBuf *pos_nor = cache->final.buff.vbo.pos_nor;
|
||||
GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buffer);
|
||||
GPU_vertbuf_init_build_on_device(
|
||||
vbo, get_subdiv_edge_fac_format(), subdiv_cache->num_subdiv_loops + mr->loop_loose_len);
|
||||
vbo, get_subdiv_edge_fac_format(), subdiv_cache->num_subdiv_loops + loose_geom.loop_len);
|
||||
|
||||
/* Create a temporary buffer for the edge original indices if it was not requested. */
|
||||
const bool has_edge_idx = edge_idx != nullptr;
|
||||
|
@ -252,11 +253,11 @@ static void extract_edge_fac_init_subdiv(const DRWSubdivCache *subdiv_cache,
|
|||
|
||||
static void extract_edge_fac_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache,
|
||||
const MeshRenderData *UNUSED(mr),
|
||||
const MeshExtractLooseGeom *loose_geom,
|
||||
void *buffer,
|
||||
void *UNUSED(data))
|
||||
{
|
||||
if (loose_geom->edge_len == 0) {
|
||||
const DRWSubdivLooseGeom &loose_geom = subdiv_cache->loose_geom;
|
||||
if (loose_geom.edge_len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -266,7 +267,7 @@ static void extract_edge_fac_loose_geom_subdiv(const DRWSubdivCache *subdiv_cach
|
|||
GPU_vertbuf_use(vbo);
|
||||
|
||||
uint offset = subdiv_cache->num_subdiv_loops;
|
||||
for (int i = 0; i < loose_geom->edge_len; i++) {
|
||||
for (int i = 0; i < loose_geom.edge_len; i++) {
|
||||
if (GPU_crappy_amd_driver()) {
|
||||
float loose_edge_fac[2] = {1.0f, 1.0f};
|
||||
GPU_vertbuf_update_sub(vbo, offset * sizeof(float), sizeof(loose_edge_fac), loose_edge_fac);
|
||||
|
|
|
@ -240,14 +240,15 @@ static void extract_edit_data_iter_lvert_mesh(const MeshRenderData *mr,
|
|||
}
|
||||
|
||||
static void extract_edit_data_init_subdiv(const DRWSubdivCache *subdiv_cache,
|
||||
const MeshRenderData *mr,
|
||||
const MeshRenderData *UNUSED(mr),
|
||||
MeshBatchCache *UNUSED(cache),
|
||||
void *buf,
|
||||
void *data)
|
||||
{
|
||||
const DRWSubdivLooseGeom &loose_geom = subdiv_cache->loose_geom;
|
||||
GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
|
||||
GPU_vertbuf_init_with_format(vbo, get_edit_data_format());
|
||||
GPU_vertbuf_data_alloc(vbo, subdiv_cache->num_subdiv_loops + mr->loop_loose_len);
|
||||
GPU_vertbuf_data_alloc(vbo, subdiv_cache->num_subdiv_loops + loose_geom.loop_len);
|
||||
EditLoopData *vbo_data = (EditLoopData *)GPU_vertbuf_get_data(vbo);
|
||||
*(EditLoopData **)data = vbo_data;
|
||||
}
|
||||
|
@ -306,27 +307,38 @@ static void extract_edit_data_iter_subdiv_mesh(const DRWSubdivCache *subdiv_cach
|
|||
|
||||
static void extract_edit_data_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache,
|
||||
const MeshRenderData *mr,
|
||||
const MeshExtractLooseGeom *loose_geom,
|
||||
void *UNUSED(buffer),
|
||||
void *_data)
|
||||
{
|
||||
if (loose_geom->edge_len == 0) {
|
||||
const DRWSubdivLooseGeom &loose_geom = subdiv_cache->loose_geom;
|
||||
if (loose_geom.edge_len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
EditLoopData *vbo_data = *(EditLoopData **)_data;
|
||||
blender::Span<DRWSubdivLooseEdge> loose_edges = draw_subdiv_cache_get_loose_edges(subdiv_cache);
|
||||
|
||||
for (int ledge_index = 0; ledge_index < loose_geom->edge_len; ledge_index++) {
|
||||
const int offset = subdiv_cache->num_subdiv_loops + ledge_index * 2;
|
||||
EditLoopData *vbo_data = *(EditLoopData **)_data;
|
||||
int ledge_index = 0;
|
||||
|
||||
for (const DRWSubdivLooseEdge &loose_edge : loose_edges) {
|
||||
const int offset = subdiv_cache->num_subdiv_loops + ledge_index++ * 2;
|
||||
EditLoopData *data = &vbo_data[offset];
|
||||
memset(data, 0, sizeof(EditLoopData));
|
||||
const int edge_index = loose_geom->edges[ledge_index];
|
||||
const int edge_index = loose_edge.coarse_edge_index;
|
||||
BMEdge *eed = mr->e_origindex ? bm_original_edge_get(mr, edge_index) :
|
||||
BM_edge_at_index(mr->bm, edge_index);
|
||||
mesh_render_data_edge_flag(mr, eed, &data[0]);
|
||||
data[1] = data[0];
|
||||
mesh_render_data_vert_flag(mr, eed->v1, &data[0]);
|
||||
mesh_render_data_vert_flag(mr, eed->v2, &data[1]);
|
||||
|
||||
const DRWSubdivLooseVertex &v1 = loose_geom.verts[loose_edge.loose_subdiv_v1_index];
|
||||
const DRWSubdivLooseVertex &v2 = loose_geom.verts[loose_edge.loose_subdiv_v2_index];
|
||||
|
||||
if (v1.coarse_vertex_index != -1u) {
|
||||
mesh_render_data_vert_flag(mr, eed->v1, &data[0]);
|
||||
}
|
||||
if (v2.coarse_vertex_index != -1u) {
|
||||
mesh_render_data_vert_flag(mr, eed->v2, &data[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -211,16 +211,21 @@ static GPUVertFormat *get_custom_normals_format()
|
|||
}
|
||||
|
||||
static void extract_pos_nor_init_subdiv(const DRWSubdivCache *subdiv_cache,
|
||||
const MeshRenderData *mr,
|
||||
const MeshRenderData *UNUSED(mr),
|
||||
struct MeshBatchCache *UNUSED(cache),
|
||||
void *buffer,
|
||||
void *UNUSED(data))
|
||||
{
|
||||
GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buffer);
|
||||
const DRWSubdivLooseGeom &loose_geom = subdiv_cache->loose_geom;
|
||||
|
||||
/* Initialize the vertex buffer, it was already allocated. */
|
||||
GPU_vertbuf_init_build_on_device(
|
||||
vbo, get_pos_nor_format(), subdiv_cache->num_subdiv_loops + mr->loop_loose_len);
|
||||
vbo, get_pos_nor_format(), subdiv_cache->num_subdiv_loops + loose_geom.loop_len);
|
||||
|
||||
if (subdiv_cache->num_subdiv_loops == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
draw_subdiv_extract_pos_nor(subdiv_cache, vbo);
|
||||
|
||||
|
@ -273,13 +278,12 @@ static void extract_pos_nor_init_subdiv(const DRWSubdivCache *subdiv_cache,
|
|||
}
|
||||
|
||||
static void extract_pos_nor_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache,
|
||||
const MeshRenderData *mr,
|
||||
const MeshExtractLooseGeom *loose_geom,
|
||||
const MeshRenderData *UNUSED(mr),
|
||||
void *buffer,
|
||||
void *UNUSED(data))
|
||||
{
|
||||
const int loop_loose_len = loose_geom->edge_len + loose_geom->vert_len;
|
||||
if (loop_loose_len == 0) {
|
||||
const DRWSubdivLooseGeom &loose_geom = subdiv_cache->loose_geom;
|
||||
if (loose_geom.loop_len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -293,75 +297,38 @@ static void extract_pos_nor_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache
|
|||
float flag;
|
||||
};
|
||||
|
||||
if (mr->extract_type == MR_EXTRACT_MESH) {
|
||||
const Mesh *coarse_mesh = subdiv_cache->mesh;
|
||||
const MEdge *coarse_edges = coarse_mesh->medge;
|
||||
const MVert *coarse_verts = coarse_mesh->mvert;
|
||||
/* Make sure buffer is active for sending loose data. */
|
||||
GPU_vertbuf_use(vbo);
|
||||
|
||||
SubdivPosNorLoop edge_data[2];
|
||||
memset(&edge_data, 0, sizeof(SubdivPosNorLoop) * 2);
|
||||
for (int i = 0; i < loose_geom->edge_len; i++) {
|
||||
const MEdge *loose_edge = &coarse_edges[loose_geom->edges[i]];
|
||||
const MVert *loose_vert1 = &coarse_verts[loose_edge->v1];
|
||||
const MVert *loose_vert2 = &coarse_verts[loose_edge->v2];
|
||||
blender::Span<DRWSubdivLooseEdge> loose_edges = draw_subdiv_cache_get_loose_edges(subdiv_cache);
|
||||
|
||||
copy_v3_v3(edge_data[0].pos, loose_vert1->co);
|
||||
copy_v3_v3(edge_data[1].pos, loose_vert2->co);
|
||||
SubdivPosNorLoop edge_data[2];
|
||||
memset(edge_data, 0, sizeof(SubdivPosNorLoop) * 2);
|
||||
for (const DRWSubdivLooseEdge &loose_edge : loose_edges) {
|
||||
const DRWSubdivLooseVertex &v1 = loose_geom.verts[loose_edge.loose_subdiv_v1_index];
|
||||
const DRWSubdivLooseVertex &v2 = loose_geom.verts[loose_edge.loose_subdiv_v2_index];
|
||||
|
||||
GPU_vertbuf_update_sub(
|
||||
vbo, offset * sizeof(SubdivPosNorLoop), sizeof(SubdivPosNorLoop) * 2, &edge_data);
|
||||
copy_v3_v3(edge_data[0].pos, v1.co);
|
||||
copy_v3_v3(edge_data[1].pos, v2.co);
|
||||
|
||||
offset += 2;
|
||||
}
|
||||
GPU_vertbuf_update_sub(
|
||||
vbo, offset * sizeof(SubdivPosNorLoop), sizeof(SubdivPosNorLoop) * 2, &edge_data);
|
||||
|
||||
SubdivPosNorLoop vert_data;
|
||||
memset(&vert_data, 0, sizeof(SubdivPosNorLoop));
|
||||
for (int i = 0; i < loose_geom->vert_len; i++) {
|
||||
const MVert *loose_vertex = &coarse_verts[loose_geom->verts[i]];
|
||||
|
||||
copy_v3_v3(vert_data.pos, loose_vertex->co);
|
||||
|
||||
GPU_vertbuf_update_sub(
|
||||
vbo, offset * sizeof(SubdivPosNorLoop), sizeof(SubdivPosNorLoop), &vert_data);
|
||||
|
||||
offset += 1;
|
||||
}
|
||||
offset += 2;
|
||||
}
|
||||
else {
|
||||
BMesh *bm = subdiv_cache->bm;
|
||||
|
||||
SubdivPosNorLoop edge_data[2];
|
||||
memset(&edge_data, 0, sizeof(SubdivPosNorLoop) * 2);
|
||||
for (int i = 0; i < loose_geom->edge_len; i++) {
|
||||
const BMEdge *loose_edge = BM_edge_at_index(bm, loose_geom->edges[i]);
|
||||
const BMVert *loose_vert1 = loose_edge->v1;
|
||||
const BMVert *loose_vert2 = loose_edge->v2;
|
||||
SubdivPosNorLoop vert_data;
|
||||
memset(&vert_data, 0, sizeof(SubdivPosNorLoop));
|
||||
blender::Span<DRWSubdivLooseVertex> loose_verts = draw_subdiv_cache_get_loose_verts(
|
||||
subdiv_cache);
|
||||
|
||||
copy_v3_v3(edge_data[0].pos, loose_vert1->co);
|
||||
copy_v3_v3(edge_data[0].nor, loose_vert1->no);
|
||||
for (const DRWSubdivLooseVertex &loose_vert : loose_verts) {
|
||||
copy_v3_v3(vert_data.pos, loose_vert.co);
|
||||
|
||||
copy_v3_v3(edge_data[1].pos, loose_vert2->co);
|
||||
copy_v3_v3(edge_data[1].nor, loose_vert2->no);
|
||||
GPU_vertbuf_update_sub(
|
||||
vbo, offset * sizeof(SubdivPosNorLoop), sizeof(SubdivPosNorLoop), &vert_data);
|
||||
|
||||
GPU_vertbuf_update_sub(
|
||||
vbo, offset * sizeof(SubdivPosNorLoop), sizeof(SubdivPosNorLoop) * 2, &edge_data);
|
||||
|
||||
offset += 2;
|
||||
}
|
||||
|
||||
SubdivPosNorLoop vert_data;
|
||||
memset(&vert_data, 0, sizeof(SubdivPosNorLoop));
|
||||
for (int i = 0; i < loose_geom->vert_len; i++) {
|
||||
const BMVert *loose_vertex = BM_vert_at_index(bm, loose_geom->verts[i]);
|
||||
|
||||
copy_v3_v3(vert_data.pos, loose_vertex->co);
|
||||
copy_v3_v3(vert_data.nor, loose_vertex->no);
|
||||
|
||||
GPU_vertbuf_update_sub(
|
||||
vbo, offset * sizeof(SubdivPosNorLoop), sizeof(SubdivPosNorLoop), &vert_data);
|
||||
|
||||
offset += 1;
|
||||
}
|
||||
offset += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -188,12 +188,12 @@ static void extract_vert_idx_init_subdiv(const DRWSubdivCache *subdiv_cache,
|
|||
void *UNUSED(data))
|
||||
{
|
||||
GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
|
||||
const DRWSubdivLooseGeom &loose_geom = subdiv_cache->loose_geom;
|
||||
/* Each element points to an element in the ibo.points. */
|
||||
draw_subdiv_init_origindex_buffer(vbo,
|
||||
(int *)GPU_vertbuf_get_data(subdiv_cache->verts_orig_index),
|
||||
subdiv_cache->num_subdiv_loops,
|
||||
mr->loop_loose_len);
|
||||
|
||||
loose_geom.loop_len);
|
||||
if (!mr->v_origindex) {
|
||||
return;
|
||||
}
|
||||
|
@ -212,12 +212,11 @@ static void extract_vert_idx_init_subdiv(const DRWSubdivCache *subdiv_cache,
|
|||
|
||||
static void extract_vert_idx_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache,
|
||||
const MeshRenderData *mr,
|
||||
const MeshExtractLooseGeom *loose_geom,
|
||||
void *buffer,
|
||||
void *UNUSED(data))
|
||||
{
|
||||
const int loop_loose_len = loose_geom->edge_len + loose_geom->vert_len;
|
||||
if (loop_loose_len == 0) {
|
||||
const DRWSubdivLooseGeom &loose_geom = subdiv_cache->loose_geom;
|
||||
if (loose_geom.loop_len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -225,60 +224,57 @@ static void extract_vert_idx_loose_geom_subdiv(const DRWSubdivCache *subdiv_cach
|
|||
uint *vert_idx_data = (uint *)GPU_vertbuf_get_data(vbo);
|
||||
uint offset = subdiv_cache->num_subdiv_loops;
|
||||
|
||||
if (mr->extract_type == MR_EXTRACT_MESH) {
|
||||
const Mesh *coarse_mesh = subdiv_cache->mesh;
|
||||
const MEdge *coarse_edges = coarse_mesh->medge;
|
||||
for (int i = 0; i < loose_geom->edge_len; i++) {
|
||||
const MEdge *loose_edge = &coarse_edges[loose_geom->edges[i]];
|
||||
vert_idx_data[offset] = loose_edge->v1;
|
||||
vert_idx_data[offset + 1] = loose_edge->v2;
|
||||
offset += 2;
|
||||
blender::Span<DRWSubdivLooseEdge> loose_edges = draw_subdiv_cache_get_loose_edges(subdiv_cache);
|
||||
|
||||
for (const DRWSubdivLooseEdge &loose_edge : loose_edges) {
|
||||
const DRWSubdivLooseVertex &v1 = loose_geom.verts[loose_edge.loose_subdiv_v1_index];
|
||||
const DRWSubdivLooseVertex &v2 = loose_geom.verts[loose_edge.loose_subdiv_v2_index];
|
||||
|
||||
if (v1.coarse_vertex_index != -1u) {
|
||||
vert_idx_data[offset] = mr->v_origindex ? mr->v_origindex[v1.coarse_vertex_index] :
|
||||
v1.coarse_vertex_index;
|
||||
}
|
||||
|
||||
for (int i = 0; i < loose_geom->vert_len; i++) {
|
||||
vert_idx_data[offset] = loose_geom->verts[i];
|
||||
offset += 1;
|
||||
if (v2.coarse_vertex_index != -1u) {
|
||||
vert_idx_data[offset + 1] = mr->v_origindex ? mr->v_origindex[v2.coarse_vertex_index] :
|
||||
v2.coarse_vertex_index;
|
||||
}
|
||||
|
||||
offset += 2;
|
||||
}
|
||||
else {
|
||||
BMesh *bm = mr->bm;
|
||||
for (int i = 0; i < loose_geom->edge_len; i++) {
|
||||
const BMEdge *loose_edge = BM_edge_at_index(bm, loose_geom->edges[i]);
|
||||
vert_idx_data[offset] = BM_elem_index_get(loose_edge->v1);
|
||||
vert_idx_data[offset + 1] = BM_elem_index_get(loose_edge->v2);
|
||||
offset += 2;
|
||||
}
|
||||
|
||||
for (int i = 0; i < loose_geom->vert_len; i++) {
|
||||
const BMVert *loose_vert = BM_vert_at_index(bm, loose_geom->verts[i]);
|
||||
vert_idx_data[offset] = BM_elem_index_get(loose_vert);
|
||||
offset += 1;
|
||||
}
|
||||
blender::Span<DRWSubdivLooseVertex> loose_verts = draw_subdiv_cache_get_loose_verts(
|
||||
subdiv_cache);
|
||||
|
||||
for (const DRWSubdivLooseVertex &loose_vert : loose_verts) {
|
||||
vert_idx_data[offset] = mr->v_origindex ? mr->v_origindex[loose_vert.coarse_vertex_index] :
|
||||
loose_vert.coarse_vertex_index;
|
||||
offset += 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void extract_edge_idx_init_subdiv(const DRWSubdivCache *subdiv_cache,
|
||||
const MeshRenderData *mr,
|
||||
const MeshRenderData *UNUSED(mr),
|
||||
MeshBatchCache *UNUSED(cache),
|
||||
void *buf,
|
||||
void *UNUSED(data))
|
||||
{
|
||||
GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
|
||||
const DRWSubdivLooseGeom &loose_geom = subdiv_cache->loose_geom;
|
||||
draw_subdiv_init_origindex_buffer(
|
||||
vbo,
|
||||
static_cast<int *>(GPU_vertbuf_get_data(subdiv_cache->edges_orig_index)),
|
||||
subdiv_cache->num_subdiv_loops,
|
||||
mr->edge_loose_len * 2);
|
||||
loose_geom.edge_len * 2);
|
||||
}
|
||||
|
||||
static void extract_edge_idx_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache,
|
||||
const MeshRenderData *UNUSED(mr),
|
||||
const MeshExtractLooseGeom *loose_geom,
|
||||
const MeshRenderData *mr,
|
||||
void *buffer,
|
||||
void *UNUSED(data))
|
||||
{
|
||||
const int loop_loose_len = loose_geom->edge_len + loose_geom->vert_len;
|
||||
if (loop_loose_len == 0) {
|
||||
const DRWSubdivLooseGeom &loose_geom = subdiv_cache->loose_geom;
|
||||
if (loose_geom.edge_len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -286,9 +282,12 @@ static void extract_edge_idx_loose_geom_subdiv(const DRWSubdivCache *subdiv_cach
|
|||
uint *vert_idx_data = (uint *)GPU_vertbuf_get_data(vbo);
|
||||
uint offset = subdiv_cache->num_subdiv_loops;
|
||||
|
||||
for (int i = 0; i < loose_geom->edge_len; i++) {
|
||||
vert_idx_data[offset] = loose_geom->edges[i];
|
||||
vert_idx_data[offset + 1] = loose_geom->edges[i];
|
||||
blender::Span<DRWSubdivLooseEdge> loose_edges = draw_subdiv_cache_get_loose_edges(subdiv_cache);
|
||||
for (const DRWSubdivLooseEdge &loose_edge : loose_edges) {
|
||||
const int coarse_edge_index = mr->e_origindex ? mr->e_origindex[loose_edge.coarse_edge_index] :
|
||||
loose_edge.coarse_edge_index;
|
||||
vert_idx_data[offset] = coarse_edge_index;
|
||||
vert_idx_data[offset + 1] = coarse_edge_index;
|
||||
offset += 2;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -451,9 +451,7 @@ bool ED_spreadsheet_context_path_is_active(const bContext *C, SpaceSpreadsheet *
|
|||
if (modifier == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (!(modifier->flag & eModifierFlag_Active)) {
|
||||
return false;
|
||||
}
|
||||
const bool modifier_is_active = modifier->flag & eModifierFlag_Active;
|
||||
if (modifier->type != eModifierType_Nodes) {
|
||||
return false;
|
||||
}
|
||||
|
@ -480,6 +478,12 @@ bool ED_spreadsheet_context_path_is_active(const bContext *C, SpaceSpreadsheet *
|
|||
if (snode->nodetree != root_node_tree) {
|
||||
continue;
|
||||
}
|
||||
if (!modifier_is_active) {
|
||||
if (!(snode->flag & SNODE_PIN)) {
|
||||
/* Node tree has to be pinned when the modifier is not active. */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (snode->id != &object->id) {
|
||||
continue;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue