Blender V4.3
subdiv_ccg.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2018 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include "BKE_subdiv_ccg.hh"
10
11#include "MEM_guardedalloc.h"
12
14#include "BLI_index_mask.hh"
15#include "BLI_math_bits.h"
16#include "BLI_math_geom.h"
17#include "BLI_math_vector.h"
18#include "BLI_set.hh"
19#include "BLI_task.hh"
20#include "BLI_vector_set.hh"
21
22#include "BKE_ccg.hh"
23#include "BKE_mesh.hh"
24#include "BKE_subdiv.hh"
25#include "BKE_subdiv_eval.hh"
26
27#ifdef WITH_OPENSUBDIV
29#endif
30
31using blender::Array;
32using blender::float3;
39using blender::Span;
40using blender::Vector;
42using namespace blender::bke::subdiv;
43using namespace blender::bke::ccg;
44
45/* -------------------------------------------------------------------- */
49#ifdef WITH_OPENSUBDIV
50
51static void subdiv_ccg_average_inner_face_grids(SubdivCCG &subdiv_ccg,
52 const CCGKey &key,
53 const IndexRange face);
54
55void subdiv_ccg_average_faces_boundaries_and_corners(SubdivCCG &subdiv_ccg,
56 const CCGKey &key,
57 const IndexMask &face_mask);
58
61/* -------------------------------------------------------------------- */
65/* TODO(sergey): Make it more accessible function. */
66static int topology_refiner_count_face_corners(
67 const blender::opensubdiv::TopologyRefinerImpl *topology_refiner)
68{
69 const int num_faces = topology_refiner->base_level().GetNumFaces();
70 int num_corners = 0;
71 for (int face_index = 0; face_index < num_faces; face_index++) {
72 num_corners += topology_refiner->base_level().GetFaceVertices(face_index).size();
73 }
74 return num_corners;
75}
76
77/* NOTE: Grid size and layer flags are to be filled in before calling this
78 * function. */
79static void subdiv_ccg_alloc_elements(SubdivCCG &subdiv_ccg,
80 Subdiv &subdiv,
81 const SubdivToCCGSettings &settings)
82{
83 const blender::opensubdiv::TopologyRefinerImpl *topology_refiner = subdiv.topology_refiner;
84 /* Allocate memory for surface grids. */
85 const int64_t num_grids = topology_refiner_count_face_corners(topology_refiner);
86 const int64_t grid_size = grid_size_from_level(subdiv_ccg.level);
87 const int64_t grid_area = grid_size * grid_size;
88 subdiv_ccg.positions.reinitialize(num_grids * grid_area);
89 if (settings.need_normal) {
90 subdiv_ccg.normals.reinitialize(num_grids * grid_area);
91 }
92 if (settings.need_mask) {
93 subdiv_ccg.masks.reinitialize(num_grids * grid_area);
94 }
95 /* TODO(sergey): Allocate memory for loose elements. */
96}
97
100/* -------------------------------------------------------------------- */
104static void subdiv_ccg_eval_grid_element_limit(Subdiv &subdiv,
105 SubdivCCG &subdiv_ccg,
106 const int ptex_face_index,
107 const float u,
108 const float v,
109 const int element)
110{
111 if (subdiv.displacement_evaluator != nullptr) {
112 eval_final_point(&subdiv, ptex_face_index, u, v, subdiv_ccg.positions[element]);
113 }
114 else if (!subdiv_ccg.normals.is_empty()) {
116 ptex_face_index,
117 u,
118 v,
119 subdiv_ccg.positions[element],
120 subdiv_ccg.normals[element]);
121 }
122 else {
123 eval_limit_point(&subdiv, ptex_face_index, u, v, subdiv_ccg.positions[element]);
124 }
125}
126
127static void subdiv_ccg_eval_grid_element_mask(SubdivCCG &subdiv_ccg,
128 SubdivCCGMaskEvaluator *mask_evaluator,
129 const int ptex_face_index,
130 const float u,
131 const float v,
132 const int element)
133{
134 if (subdiv_ccg.masks.is_empty()) {
135 return;
136 }
137 if (mask_evaluator != nullptr) {
138 subdiv_ccg.masks[element] = mask_evaluator->eval_mask(mask_evaluator, ptex_face_index, u, v);
139 }
140 else {
141 subdiv_ccg.masks[element] = 0.0f;
142 }
143}
144
145static void subdiv_ccg_eval_grid_element(Subdiv &subdiv,
146 SubdivCCG &subdiv_ccg,
147 SubdivCCGMaskEvaluator *mask_evaluator,
148 const int ptex_face_index,
149 const float u,
150 const float v,
151 const int element)
152{
153 subdiv_ccg_eval_grid_element_limit(subdiv, subdiv_ccg, ptex_face_index, u, v, element);
154 subdiv_ccg_eval_grid_element_mask(subdiv_ccg, mask_evaluator, ptex_face_index, u, v, element);
155}
156
157static void subdiv_ccg_eval_regular_grid(Subdiv &subdiv,
158 SubdivCCG &subdiv_ccg,
159 const Span<int> face_ptex_offset,
160 SubdivCCGMaskEvaluator *mask_evaluator,
161 const int face_index)
162{
163 const int ptex_face_index = face_ptex_offset[face_index];
164 const int grid_size = subdiv_ccg.grid_size;
165 const int grid_area = subdiv_ccg.grid_area;
166 const float grid_size_1_inv = 1.0f / (grid_size - 1);
167 const IndexRange face = subdiv_ccg.faces[face_index];
168 for (int corner = 0; corner < face.size(); corner++) {
169 const int grid_index = face.start() + corner;
170 const IndexRange range = grid_range(grid_area, grid_index);
171 for (int y = 0; y < grid_size; y++) {
172 const float grid_v = y * grid_size_1_inv;
173 for (int x = 0; x < grid_size; x++) {
174 const float grid_u = x * grid_size_1_inv;
175 float u, v;
176 rotate_grid_to_quad(corner, grid_u, grid_v, &u, &v);
177 const int element = range[CCG_grid_xy_to_index(grid_size, x, y)];
178 subdiv_ccg_eval_grid_element(
179 subdiv, subdiv_ccg, mask_evaluator, ptex_face_index, u, v, element);
180 }
181 }
182 }
183}
184
185static void subdiv_ccg_eval_special_grid(Subdiv &subdiv,
186 SubdivCCG &subdiv_ccg,
187 const Span<int> face_ptex_offset,
188 SubdivCCGMaskEvaluator *mask_evaluator,
189 const int face_index)
190{
191 const int grid_size = subdiv_ccg.grid_size;
192 const int grid_area = subdiv_ccg.grid_area;
193 const float grid_size_1_inv = 1.0f / (grid_size - 1);
194 const IndexRange face = subdiv_ccg.faces[face_index];
195 for (int corner = 0; corner < face.size(); corner++) {
196 const int grid_index = face.start() + corner;
197 const int ptex_face_index = face_ptex_offset[face_index] + corner;
198 const IndexRange range = grid_range(grid_area, grid_index);
199 for (int y = 0; y < grid_size; y++) {
200 const float u = 1.0f - (y * grid_size_1_inv);
201 for (int x = 0; x < grid_size; x++) {
202 const float v = 1.0f - (x * grid_size_1_inv);
203 const int element = range[CCG_grid_xy_to_index(grid_size, x, y)];
204 subdiv_ccg_eval_grid_element(
205 subdiv, subdiv_ccg, mask_evaluator, ptex_face_index, u, v, element);
206 }
207 }
208 }
209}
210
211static bool subdiv_ccg_evaluate_grids(SubdivCCG &subdiv_ccg,
212 Subdiv &subdiv,
213 SubdivCCGMaskEvaluator *mask_evaluator)
214{
215 using namespace blender;
216 const blender::opensubdiv::TopologyRefinerImpl *topology_refiner = subdiv.topology_refiner;
217 const int num_faces = topology_refiner->base_level().GetNumFaces();
218 const Span<int> face_ptex_offset(face_ptex_offset_get(&subdiv), subdiv_ccg.faces.size());
219 threading::parallel_for(IndexRange(num_faces), 1024, [&](const IndexRange range) {
220 for (const int face_index : range) {
221 if (subdiv_ccg.faces[face_index].size() == 4) {
222 subdiv_ccg_eval_regular_grid(
223 subdiv, subdiv_ccg, face_ptex_offset, mask_evaluator, face_index);
224 }
225 else {
226 subdiv_ccg_eval_special_grid(
227 subdiv, subdiv_ccg, face_ptex_offset, mask_evaluator, face_index);
228 }
229 }
230 });
231 /* If displacement is used, need to calculate normals after all final
232 * coordinates are known. */
233 if (subdiv.displacement_evaluator != nullptr) {
235 }
236 return true;
237}
238
239static void subdiv_ccg_allocate_adjacent_edges(SubdivCCG &subdiv_ccg, const int num_edges)
240{
242}
243
244static SubdivCCGCoord subdiv_ccg_coord(int grid_index, int x, int y)
245{
246 SubdivCCGCoord coord{};
247 coord.grid_index = grid_index;
248 coord.x = x;
249 coord.y = y;
250 return coord;
251}
252
253/* Returns storage where boundary elements are to be stored. */
254static SubdivCCGCoord *subdiv_ccg_adjacent_edge_add_face(SubdivCCG &subdiv_ccg,
255 SubdivCCGAdjacentEdge &adjacent_edge)
256{
257 const int grid_size = subdiv_ccg.grid_size * 2;
258 const int adjacent_face_index = adjacent_edge.num_adjacent_faces;
259 ++adjacent_edge.num_adjacent_faces;
260 /* Allocate memory for the boundary elements. */
261 adjacent_edge.boundary_coords = static_cast<SubdivCCGCoord **>(
262 MEM_reallocN(adjacent_edge.boundary_coords,
263 adjacent_edge.num_adjacent_faces * sizeof(*adjacent_edge.boundary_coords)));
264 adjacent_edge.boundary_coords[adjacent_face_index] = static_cast<SubdivCCGCoord *>(
265 MEM_malloc_arrayN(grid_size * 2, sizeof(SubdivCCGCoord), "ccg adjacent boundary"));
266 return adjacent_edge.boundary_coords[adjacent_face_index];
267}
268
269static void subdiv_ccg_init_faces_edge_neighborhood(SubdivCCG &subdiv_ccg)
270{
271 Subdiv *subdiv = subdiv_ccg.subdiv;
272 const OffsetIndices<int> faces = subdiv_ccg.faces;
273 const OpenSubdiv::Far::TopologyLevel &base_level = subdiv->topology_refiner->base_level();
274 const int num_edges = base_level.GetNumEdges();
275 const int grid_size = subdiv_ccg.grid_size;
276 if (num_edges == 0) {
277 /* Early output, nothing to do in this case. */
278 return;
279 }
280 subdiv_ccg_allocate_adjacent_edges(subdiv_ccg, num_edges);
281
282 /* Store adjacency for all faces. */
283 for (const int face_index : faces.index_range()) {
284 const IndexRange face = faces[face_index];
285 const int num_face_grids = face.size();
286 const OpenSubdiv::Far::ConstIndexArray face_vertices = base_level.GetFaceVertices(face_index);
287 /* Note that order of edges is same as order of MLoops, which also
288 * means it's the same as order of grids. */
289 const OpenSubdiv::Far::ConstIndexArray face_edges = base_level.GetFaceEdges(face_index);
290 /* Store grids adjacency for this edge. */
291 for (int corner = 0; corner < num_face_grids; corner++) {
292 const int vertex_index = face_vertices[corner];
293 const int edge_index = face_edges[corner];
294 const OpenSubdiv::Far::ConstIndexArray edge_vertices = base_level.GetEdgeVertices(
295 edge_index);
296 const bool is_edge_flipped = (edge_vertices[0] != vertex_index);
297 /* Grid which is adjacent to the current corner. */
298 const int current_grid_index = face.start() + corner;
299 /* Grid which is adjacent to the next corner. */
300 const int next_grid_index = face.start() + (corner + 1) % num_face_grids;
301 /* Add new face to the adjacent edge. */
302 SubdivCCGAdjacentEdge &adjacent_edge = subdiv_ccg.adjacent_edges[edge_index];
303 SubdivCCGCoord *boundary_coords = subdiv_ccg_adjacent_edge_add_face(subdiv_ccg,
304 adjacent_edge);
305 /* Fill CCG elements along the edge. */
306 int boundary_element_index = 0;
307 if (is_edge_flipped) {
308 for (int i = 0; i < grid_size; i++) {
309 boundary_coords[boundary_element_index++] = subdiv_ccg_coord(
310 next_grid_index, grid_size - i - 1, grid_size - 1);
311 }
312 for (int i = 0; i < grid_size; i++) {
313 boundary_coords[boundary_element_index++] = subdiv_ccg_coord(
314 current_grid_index, grid_size - 1, i);
315 }
316 }
317 else {
318 for (int i = 0; i < grid_size; i++) {
319 boundary_coords[boundary_element_index++] = subdiv_ccg_coord(
320 current_grid_index, grid_size - 1, grid_size - i - 1);
321 }
322 for (int i = 0; i < grid_size; i++) {
323 boundary_coords[boundary_element_index++] = subdiv_ccg_coord(
324 next_grid_index, i, grid_size - 1);
325 }
326 }
327 }
328 }
329}
330
331static void subdiv_ccg_allocate_adjacent_vertices(SubdivCCG &subdiv_ccg, const int num_vertices)
332{
333 subdiv_ccg.adjacent_verts = Array<SubdivCCGAdjacentVertex>(num_vertices,
335}
336
337/* Returns storage where corner elements are to be stored. This is a pointer
338 * to the actual storage. */
339static SubdivCCGCoord *subdiv_ccg_adjacent_vertex_add_face(
340 SubdivCCGAdjacentVertex &adjacent_vertex)
341{
342 const int adjacent_face_index = adjacent_vertex.num_adjacent_faces;
343 ++adjacent_vertex.num_adjacent_faces;
344 /* Allocate memory for the boundary elements. */
345 adjacent_vertex.corner_coords = static_cast<SubdivCCGCoord *>(
346 MEM_reallocN(adjacent_vertex.corner_coords,
347 adjacent_vertex.num_adjacent_faces * sizeof(*adjacent_vertex.corner_coords)));
348 return &adjacent_vertex.corner_coords[adjacent_face_index];
349}
350
351static void subdiv_ccg_init_faces_vertex_neighborhood(SubdivCCG &subdiv_ccg)
352{
353 Subdiv *subdiv = subdiv_ccg.subdiv;
354 const OffsetIndices<int> faces = subdiv_ccg.faces;
355 const blender::opensubdiv::TopologyRefinerImpl *topology_refiner = subdiv->topology_refiner;
356 const int num_vertices = topology_refiner->base_level().GetNumVertices();
357 const int grid_size = subdiv_ccg.grid_size;
358 if (num_vertices == 0) {
359 /* Early output, nothing to do in this case. */
360 return;
361 }
362 subdiv_ccg_allocate_adjacent_vertices(subdiv_ccg, num_vertices);
363 /* Store adjacency for all faces. */
364 for (const int face_index : faces.index_range()) {
365 const IndexRange face = faces[face_index];
366 const int num_face_grids = face.size();
367 const OpenSubdiv::Far::ConstIndexArray face_vertices =
368 topology_refiner->base_level().GetFaceVertices(face_index);
369 for (int corner = 0; corner < num_face_grids; corner++) {
370 const int vertex_index = face_vertices[corner];
371 /* Grid which is adjacent to the current corner. */
372 const int grid_index = face.start() + corner;
373 /* Add new face to the adjacent edge. */
374 SubdivCCGAdjacentVertex &adjacent_vertex = subdiv_ccg.adjacent_verts[vertex_index];
375 SubdivCCGCoord *corner_coord = subdiv_ccg_adjacent_vertex_add_face(adjacent_vertex);
376 *corner_coord = subdiv_ccg_coord(grid_index, grid_size - 1, grid_size - 1);
377 }
378 }
379}
380
381static void subdiv_ccg_init_faces_neighborhood(SubdivCCG &subdiv_ccg)
382{
383 subdiv_ccg_init_faces_edge_neighborhood(subdiv_ccg);
384 subdiv_ccg_init_faces_vertex_neighborhood(subdiv_ccg);
385}
386
387#endif
388
391/* -------------------------------------------------------------------- */
395std::unique_ptr<SubdivCCG> BKE_subdiv_to_ccg(Subdiv &subdiv,
396 const SubdivToCCGSettings &settings,
397 const Mesh &coarse_mesh,
398 SubdivCCGMaskEvaluator *mask_evaluator)
399{
400#ifdef WITH_OPENSUBDIV
402 std::unique_ptr<SubdivCCG> subdiv_ccg = std::make_unique<SubdivCCG>();
403 subdiv_ccg->subdiv = &subdiv;
404 subdiv_ccg->level = bitscan_forward_i(settings.resolution - 1);
405 subdiv_ccg->grid_size = grid_size_from_level(subdiv_ccg->level);
406 subdiv_ccg->grid_area = subdiv_ccg->grid_size * subdiv_ccg->grid_size;
407 subdiv_ccg->faces = coarse_mesh.faces();
408 subdiv_ccg->grids_num = subdiv_ccg->faces.total_size();
409 subdiv_ccg->grid_to_face_map = coarse_mesh.corner_to_face_map();
410 subdiv_ccg_alloc_elements(*subdiv_ccg, subdiv, settings);
411 subdiv_ccg_init_faces_neighborhood(*subdiv_ccg);
412 if (!subdiv_ccg_evaluate_grids(*subdiv_ccg, subdiv, mask_evaluator)) {
414 return nullptr;
415 }
417 return subdiv_ccg;
418#else
419 UNUSED_VARS(subdiv, settings, coarse_mesh, mask_evaluator);
420 return {};
421#endif
422}
423
425 const SubdivToCCGSettings &settings,
426 const Mesh &coarse_mesh)
427{
428 /* Make sure evaluator is ready. */
430 if (!eval_begin_from_mesh(&subdiv, &coarse_mesh, {}, SUBDIV_EVALUATOR_TYPE_CPU, nullptr)) {
431 if (coarse_mesh.faces_num) {
432 return nullptr;
433 }
434 }
436 SubdivCCGMaskEvaluator mask_evaluator;
437 bool has_mask = BKE_subdiv_ccg_mask_init_from_paint(&mask_evaluator, &coarse_mesh);
438 std::unique_ptr<SubdivCCG> subdiv_ccg = BKE_subdiv_to_ccg(
439 subdiv, settings, coarse_mesh, has_mask ? &mask_evaluator : nullptr);
440 if (has_mask) {
441 mask_evaluator.free(&mask_evaluator);
442 }
443 if (!subdiv_ccg) {
444 return nullptr;
445 }
446 Mesh *result = BKE_mesh_new_nomain_from_template(&coarse_mesh, 0, 0, 0, 0);
447 result->runtime->subdiv_ccg = std::move(subdiv_ccg);
448 return result;
449}
450
452{
453 if (this->subdiv != nullptr) {
454 free(this->subdiv);
455 }
456
457 for (const int i : this->adjacent_edges.index_range()) {
458 SubdivCCGAdjacentEdge *adjacent_edge = &this->adjacent_edges[i];
459 for (int face_index = 0; face_index < adjacent_edge->num_adjacent_faces; face_index++) {
460 MEM_SAFE_FREE(adjacent_edge->boundary_coords[face_index]);
461 }
462 MEM_SAFE_FREE(adjacent_edge->boundary_coords);
463 }
464
465 for (const int i : this->adjacent_verts.index_range()) {
466 SubdivCCGAdjacentVertex *adjacent_vertex = &this->adjacent_verts[i];
467 MEM_SAFE_FREE(adjacent_vertex->corner_coords);
468 }
469}
470
471CCGKey BKE_subdiv_ccg_key(const SubdivCCG & /*subdiv_ccg*/, int level)
472{
473#ifdef WITH_OPENSUBDIV
474 /* Most #CCGKey fields are unused for #SubdivCCG but still used in other areas of Blender.
475 * Initialize them to invalid values to catch mistaken use more easily. */
476 CCGKey key;
477 key.level = level;
478 key.elem_size = -1;
479 key.grid_size = grid_size_from_level(level);
480 key.grid_area = key.grid_size * key.grid_size;
481 key.grid_bytes = -1;
482
483 key.normal_offset = -1;
484 key.mask_offset = -1;
485
486 key.has_normals = false;
487 key.has_mask = false;
488 return key;
489#else
490 UNUSED_VARS(level);
491 return {};
492#endif
493}
494
496{
497 return BKE_subdiv_ccg_key(subdiv_ccg, subdiv_ccg.level);
498}
499
502/* -------------------------------------------------------------------- */
506#ifdef WITH_OPENSUBDIV
507
508/* Evaluate high-res face normals, for faces which corresponds to grid elements
509 *
510 * {(x, y), {x + 1, y}, {x + 1, y + 1}, {x, y + 1}}
511 *
512 * The result is stored in normals storage from TLS. */
513static void subdiv_ccg_recalc_inner_face_normals(const SubdivCCG &subdiv_ccg,
514 MutableSpan<float3> face_normals,
515 const int corner)
516{
517 const int grid_size = subdiv_ccg.grid_size;
518 const int grid_area = subdiv_ccg.grid_area;
519 const int grid_size_1 = grid_size - 1;
520 const Span grid_positions = subdiv_ccg.positions.as_span().slice(grid_range(grid_area, corner));
521 for (int y = 0; y < grid_size - 1; y++) {
522 for (int x = 0; x < grid_size - 1; x++) {
523 const int face_index = y * grid_size_1 + x;
524 float *face_normal = face_normals[face_index];
525 normal_quad_v3(face_normal,
526 grid_positions[CCG_grid_xy_to_index(grid_size, x, y + 1)],
527 grid_positions[CCG_grid_xy_to_index(grid_size, x + 1, y + 1)],
528 grid_positions[CCG_grid_xy_to_index(grid_size, x + 1, y)],
529 grid_positions[CCG_grid_xy_to_index(grid_size, x, y)]);
530 }
531 }
532}
533
534/* Average normals at every grid element, using adjacent faces normals. */
535static void subdiv_ccg_average_inner_face_normals(SubdivCCG &subdiv_ccg,
536 const Span<float3> face_normals,
537 const int corner)
538{
539 const int grid_size = subdiv_ccg.grid_size;
540 const int grid_area = subdiv_ccg.grid_area;
541 const int grid_size_1 = grid_size - 1;
542 MutableSpan grid_normals = subdiv_ccg.normals.as_mutable_span().slice(
543 grid_range(grid_area, corner));
544 for (int y = 0; y < grid_size; y++) {
545 for (int x = 0; x < grid_size; x++) {
546 float normal_acc[3] = {0.0f, 0.0f, 0.0f};
547 int counter = 0;
548 /* Accumulate normals of all adjacent faces. */
549 if (x < grid_size_1 && y < grid_size_1) {
550 add_v3_v3(normal_acc, face_normals[y * grid_size_1 + x]);
551 counter++;
552 }
553 if (x >= 1) {
554 if (y < grid_size_1) {
555 add_v3_v3(normal_acc, face_normals[y * grid_size_1 + (x - 1)]);
556 counter++;
557 }
558 if (y >= 1) {
559 add_v3_v3(normal_acc, face_normals[(y - 1) * grid_size_1 + (x - 1)]);
560 counter++;
561 }
562 }
563 if (y >= 1 && x < grid_size_1) {
564 add_v3_v3(normal_acc, face_normals[(y - 1) * grid_size_1 + x]);
565 counter++;
566 }
567 /* Normalize and store. */
568 mul_v3_v3fl(grid_normals[CCG_grid_xy_to_index(grid_size, x, y)], normal_acc, 1.0f / counter);
569 }
570 }
571}
572
573/* Recalculate normals which corresponds to non-boundaries elements of grids. */
574static void subdiv_ccg_recalc_inner_grid_normals(SubdivCCG &subdiv_ccg, const IndexMask &face_mask)
575{
576 using namespace blender;
577 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
578
579 const int grid_size_1 = subdiv_ccg.grid_size - 1;
581 [&]() { return Array<float3>(grid_size_1 * grid_size_1); });
582
583 const OffsetIndices<int> faces = subdiv_ccg.faces;
584 face_mask.foreach_segment(GrainSize(512), [&](const IndexMaskSegment segment) {
585 MutableSpan<float3> face_normals = face_normals_tls.local();
586 for (const int face_index : segment) {
587 const IndexRange face = faces[face_index];
588 for (const int grid_index : face) {
589 subdiv_ccg_recalc_inner_face_normals(subdiv_ccg, face_normals, grid_index);
590 subdiv_ccg_average_inner_face_normals(subdiv_ccg, face_normals, grid_index);
591 }
592 subdiv_ccg_average_inner_face_grids(subdiv_ccg, key, face);
593 }
594 });
595}
596
597#endif
598
600{
601#ifdef WITH_OPENSUBDIV
602 if (subdiv_ccg.normals.is_empty()) {
603 /* Grids don't have normals, can do early output. */
604 return;
605 }
606 subdiv_ccg_recalc_inner_grid_normals(subdiv_ccg, subdiv_ccg.faces.index_range());
608#else
609 UNUSED_VARS(subdiv_ccg);
610#endif
611}
612
613void BKE_subdiv_ccg_update_normals(SubdivCCG &subdiv_ccg, const IndexMask &face_mask)
614{
615#ifdef WITH_OPENSUBDIV
616 if (subdiv_ccg.normals.is_empty()) {
617 /* Grids don't have normals, can do early output. */
618 return;
619 }
620 if (face_mask.is_empty()) {
621 /* No faces changed, so nothing to do here. */
622 return;
623 }
624 subdiv_ccg_recalc_inner_grid_normals(subdiv_ccg, face_mask);
625
626 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
627 subdiv_ccg_average_faces_boundaries_and_corners(subdiv_ccg, key, face_mask);
628#else
629 UNUSED_VARS(subdiv_ccg, face_mask);
630#endif
631}
632
635/* -------------------------------------------------------------------- */
639#ifdef WITH_OPENSUBDIV
640
641static void average_grid_element_value_v3(float a[3], float b[3])
642{
643 add_v3_v3(a, b);
644 mul_v3_fl(a, 0.5f);
645 copy_v3_v3(b, a);
646}
647
648static void average_grid_element(SubdivCCG &subdiv_ccg,
649 const int grid_element_a,
650 const int grid_element_b)
651{
652 average_grid_element_value_v3(subdiv_ccg.positions[grid_element_a],
653 subdiv_ccg.positions[grid_element_b]);
654 if (!subdiv_ccg.normals.is_empty()) {
655 average_grid_element_value_v3(subdiv_ccg.normals[grid_element_a],
656 subdiv_ccg.normals[grid_element_b]);
657 }
658 if (!subdiv_ccg.masks.is_empty()) {
659 float mask = (subdiv_ccg.masks[grid_element_a] + subdiv_ccg.masks[grid_element_b]) * 0.5f;
660 subdiv_ccg.masks[grid_element_a] = mask;
661 subdiv_ccg.masks[grid_element_b] = mask;
662 }
663}
664
665/* Accumulator to hold data during averaging. */
666struct GridElementAccumulator {
667 float3 co;
668 float3 no;
669 float mask;
670};
671
672static void element_accumulator_init(GridElementAccumulator &accumulator)
673{
674 zero_v3(accumulator.co);
675 zero_v3(accumulator.no);
676 accumulator.mask = 0.0f;
677}
678
679static void element_accumulator_add(GridElementAccumulator &accumulator,
680 const SubdivCCG &subdiv_ccg,
681 const int elem)
682{
683 accumulator.co += subdiv_ccg.positions[elem];
684 if (!subdiv_ccg.normals.is_empty()) {
685 accumulator.no += subdiv_ccg.normals[elem];
686 }
687 if (!subdiv_ccg.masks.is_empty()) {
688 accumulator.mask += subdiv_ccg.masks[elem];
689 }
690}
691
692static void element_accumulator_mul_fl(GridElementAccumulator &accumulator, const float f)
693{
694 mul_v3_fl(accumulator.co, f);
695 mul_v3_fl(accumulator.no, f);
696 accumulator.mask *= f;
697}
698
699static void element_accumulator_copy(SubdivCCG &subdiv_ccg,
700 const int destination,
701 const GridElementAccumulator &accumulator)
702{
703 subdiv_ccg.positions[destination] = accumulator.co;
704 if (!subdiv_ccg.normals.is_empty()) {
705 subdiv_ccg.normals[destination] = accumulator.no;
706 }
707 if (!subdiv_ccg.masks.is_empty()) {
708 subdiv_ccg.masks[destination] = accumulator.mask;
709 }
710}
711
712static void subdiv_ccg_average_inner_face_grids(SubdivCCG &subdiv_ccg,
713 const CCGKey &key,
714 const IndexRange face)
715{
716 const int num_face_grids = face.size();
717 const int grid_size = subdiv_ccg.grid_size;
718 int prev_grid = face.start() + num_face_grids - 1;
719 /* Average boundary between neighbor grid. */
720 for (const int grid : face) {
721 for (int i = 1; i < grid_size; i++) {
722 const int prev_grid_element = grid_xy_to_vert(key, prev_grid, i, 0);
723 const int grid_element = grid_xy_to_vert(key, grid, 0, i);
724 average_grid_element(subdiv_ccg, prev_grid_element, grid_element);
725 }
726 prev_grid = grid;
727 }
728 /* Average all grids centers into a single accumulator, and share it.
729 * Guarantees correct and smooth averaging in the center. */
730 GridElementAccumulator center_accumulator;
731 element_accumulator_init(center_accumulator);
732 for (const int grid : face) {
733 const int grid_center_element = grid_xy_to_vert(key, grid, 0, 0);
734 element_accumulator_add(center_accumulator, subdiv_ccg, grid_center_element);
735 }
736 element_accumulator_mul_fl(center_accumulator, 1.0f / num_face_grids);
737 for (const int grid : face) {
738 const int grid_center_element = grid_xy_to_vert(key, grid, 0, 0);
739 element_accumulator_copy(subdiv_ccg, grid_center_element, center_accumulator);
740 }
741}
742
743static void subdiv_ccg_average_grids_boundary(SubdivCCG &subdiv_ccg,
744 const CCGKey &key,
745 const SubdivCCGAdjacentEdge &adjacent_edge,
747{
748 const int num_adjacent_faces = adjacent_edge.num_adjacent_faces;
749 const int grid_size2 = subdiv_ccg.grid_size * 2;
750 if (num_adjacent_faces == 1) {
751 /* Nothing to average with. */
752 return;
753 }
754 for (int i = 1; i < grid_size2 - 1; i++) {
755 element_accumulator_init(accumulators[i]);
756 }
757 for (int face_index = 0; face_index < num_adjacent_faces; face_index++) {
758 for (int i = 1; i < grid_size2 - 1; i++) {
759 const int grid_element = adjacent_edge.boundary_coords[face_index][i].to_index(key);
760 element_accumulator_add(accumulators[i], subdiv_ccg, grid_element);
761 }
762 }
763 for (int i = 1; i < grid_size2 - 1; i++) {
764 element_accumulator_mul_fl(accumulators[i], 1.0f / num_adjacent_faces);
765 }
766 /* Copy averaged value to all the other faces. */
767 for (int face_index = 0; face_index < num_adjacent_faces; face_index++) {
768 for (int i = 1; i < grid_size2 - 1; i++) {
769 const int grid_element = adjacent_edge.boundary_coords[face_index][i].to_index(key);
770 element_accumulator_copy(subdiv_ccg, grid_element, accumulators[i]);
771 }
772 }
773}
774
775struct AverageGridsCornerData {
776 SubdivCCG *subdiv_ccg;
777 CCGKey *key;
778
779 /* Optional lookup table. Maps task range index to index in `subdiv_ccg.adjacent_verts`. */
780 const int *adjacent_vert_index_map;
781};
782
783static void subdiv_ccg_average_grids_corners(SubdivCCG &subdiv_ccg,
784 const CCGKey &key,
785 const SubdivCCGAdjacentVertex &adjacent_vertex)
786{
787 const int num_adjacent_faces = adjacent_vertex.num_adjacent_faces;
788 if (num_adjacent_faces == 1) {
789 /* Nothing to average with. */
790 return;
791 }
792 GridElementAccumulator accumulator;
793 element_accumulator_init(accumulator);
794 for (int face_index = 0; face_index < num_adjacent_faces; face_index++) {
795 const int grid_element = adjacent_vertex.corner_coords[face_index].to_index(key);
796 element_accumulator_add(accumulator, subdiv_ccg, grid_element);
797 }
798 element_accumulator_mul_fl(accumulator, 1.0f / num_adjacent_faces);
799 /* Copy averaged value to all the other faces. */
800 for (int face_index = 0; face_index < num_adjacent_faces; face_index++) {
801 const int grid_element = adjacent_vertex.corner_coords[face_index].to_index(key);
802 element_accumulator_copy(subdiv_ccg, grid_element, accumulator);
803 }
804}
805
806static void subdiv_ccg_average_boundaries(SubdivCCG &subdiv_ccg,
807 const CCGKey &key,
808 const IndexMask &adjacent_edge_mask)
809{
810 using namespace blender;
812 [&]() { return Array<GridElementAccumulator>(subdiv_ccg.grid_size * 2); });
813
814 adjacent_edge_mask.foreach_segment(GrainSize(1024), [&](const IndexMaskSegment segment) {
815 MutableSpan<GridElementAccumulator> accumulators = all_accumulators.local();
816 for (const int i : segment) {
817 const SubdivCCGAdjacentEdge &adjacent_edge = subdiv_ccg.adjacent_edges[i];
818 subdiv_ccg_average_grids_boundary(subdiv_ccg, key, adjacent_edge, accumulators);
819 }
820 });
821}
822
823static void subdiv_ccg_average_corners(SubdivCCG &subdiv_ccg,
824 const CCGKey &key,
825 const IndexMask &adjacent_vert_mask)
826{
827 using namespace blender;
828 adjacent_vert_mask.foreach_index(GrainSize(1024), [&](const int i) {
829 const SubdivCCGAdjacentVertex &adjacent_vert = subdiv_ccg.adjacent_verts[i];
830 subdiv_ccg_average_grids_corners(subdiv_ccg, key, adjacent_vert);
831 });
832}
833
834#endif
835
837{
838#ifdef WITH_OPENSUBDIV
839 using namespace blender;
840 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
841 /* Average inner boundaries of grids (within one face), across faces
842 * from different face-corners. */
843 BKE_subdiv_ccg_average_stitch_faces(subdiv_ccg, subdiv_ccg.faces.index_range());
844 subdiv_ccg_average_boundaries(subdiv_ccg, key, subdiv_ccg.adjacent_edges.index_range());
845 subdiv_ccg_average_corners(subdiv_ccg, key, subdiv_ccg.adjacent_verts.index_range());
846#else
847 UNUSED_VARS(subdiv_ccg);
848#endif
849}
850
851#ifdef WITH_OPENSUBDIV
852
853static void subdiv_ccg_affected_face_adjacency(SubdivCCG &subdiv_ccg,
854 const IndexMask &face_mask,
855 blender::Set<int> &adjacent_verts,
856 blender::Set<int> &adjacent_edges)
857{
858 Subdiv *subdiv = subdiv_ccg.subdiv;
859 const blender::opensubdiv::TopologyRefinerImpl *topology_refiner = subdiv->topology_refiner;
860
861 face_mask.foreach_index([&](const int face_index) {
862 const OpenSubdiv::Far::ConstIndexArray face_vertices =
863 topology_refiner->base_level().GetFaceVertices(face_index);
864 adjacent_verts.add_multiple({face_vertices.begin(), face_vertices.size()});
865
866 const OpenSubdiv::Far::ConstIndexArray face_edges =
867 topology_refiner->base_level().GetFaceEdges(face_index);
868 adjacent_edges.add_multiple({face_edges.begin(), face_edges.size()});
869 });
870}
871
872void subdiv_ccg_average_faces_boundaries_and_corners(SubdivCCG &subdiv_ccg,
873 const CCGKey &key,
874 const IndexMask &face_mask)
875{
876 blender::Set<int> adjacent_vert_set;
877 blender::Set<int> adjacent_edge_set;
878 subdiv_ccg_affected_face_adjacency(subdiv_ccg, face_mask, adjacent_vert_set, adjacent_edge_set);
879
880 Vector<int> adjacent_verts(adjacent_vert_set.begin(), adjacent_vert_set.end());
881 Vector<int> adjacent_edges(adjacent_edge_set.begin(), adjacent_edge_set.end());
882
883 std::sort(adjacent_verts.begin(), adjacent_verts.end());
884 std::sort(adjacent_edges.begin(), adjacent_edges.end());
885
886 IndexMaskMemory memory;
887 subdiv_ccg_average_boundaries(
888 subdiv_ccg, key, IndexMask::from_indices(adjacent_edges.as_span(), memory));
889
890 subdiv_ccg_average_corners(
891 subdiv_ccg, key, IndexMask::from_indices(adjacent_verts.as_span(), memory));
892}
893
894#endif
895
896void BKE_subdiv_ccg_average_stitch_faces(SubdivCCG &subdiv_ccg, const IndexMask &face_mask)
897{
898#ifdef WITH_OPENSUBDIV
899 using namespace blender;
900 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
901 face_mask.foreach_index(GrainSize(512), [&](const int face_index) {
902 subdiv_ccg_average_inner_face_grids(subdiv_ccg, key, subdiv_ccg.faces[face_index]);
903 });
904 /* TODO(sergey): Only average elements which are adjacent to modified
905 * faces. */
906 subdiv_ccg_average_boundaries(subdiv_ccg, key, subdiv_ccg.adjacent_edges.index_range());
907 subdiv_ccg_average_corners(subdiv_ccg, key, subdiv_ccg.adjacent_verts.index_range());
908#else
909 UNUSED_VARS(subdiv_ccg, face_mask);
910#endif
911}
912
914 int &r_num_vertices,
915 int &r_num_edges,
916 int &r_num_faces,
917 int &r_num_loops)
918{
919 const int num_grids = subdiv_ccg.grids_num;
920 const int grid_size = subdiv_ccg.grid_size;
921 const int grid_area = grid_size * grid_size;
922 const int num_edges_per_grid = 2 * (grid_size * (grid_size - 1));
923 r_num_vertices = num_grids * grid_area;
924 r_num_edges = num_grids * num_edges_per_grid;
925 r_num_faces = num_grids * (grid_size - 1) * (grid_size - 1);
926 r_num_loops = r_num_faces * 4;
927}
928
931/* -------------------------------------------------------------------- */
935void BKE_subdiv_ccg_print_coord(const char *message, const SubdivCCGCoord &coord)
936{
937 printf("%s: grid index: %d, coord: (%d, %d)\n", message, coord.grid_index, coord.x, coord.y);
938}
939
940bool BKE_subdiv_ccg_check_coord_valid(const SubdivCCG &subdiv_ccg, const SubdivCCGCoord &coord)
941{
942 if (coord.grid_index < 0 || coord.grid_index >= subdiv_ccg.grids_num) {
943 return false;
944 }
945 const int grid_size = subdiv_ccg.grid_size;
946 if (coord.x < 0 || coord.x >= grid_size) {
947 return false;
948 }
949 if (coord.y < 0 || coord.y >= grid_size) {
950 return false;
951 }
952 return true;
953}
954
956 const int num_unique,
957 const int num_duplicates)
958{
959 const int size = num_unique + num_duplicates;
960 neighbors.coords.reinitialize(size);
961 neighbors.num_duplicates = num_duplicates;
962}
963
964/* Check whether given coordinate belongs to a grid corner. */
965BLI_INLINE bool is_corner_grid_coord(const SubdivCCG &subdiv_ccg, const SubdivCCGCoord &coord)
966{
967 const int grid_size_1 = subdiv_ccg.grid_size - 1;
968 return (coord.x == 0 && coord.y == 0) || (coord.x == 0 && coord.y == grid_size_1) ||
969 (coord.x == grid_size_1 && coord.y == grid_size_1) ||
970 (coord.x == grid_size_1 && coord.y == 0);
971}
972
973/* Check whether given coordinate belongs to a grid boundary. */
974BLI_INLINE bool is_boundary_grid_coord(const SubdivCCG &subdiv_ccg, const SubdivCCGCoord &coord)
975{
976 const int grid_size_1 = subdiv_ccg.grid_size - 1;
977 return coord.x == 0 || coord.y == 0 || coord.x == grid_size_1 || coord.y == grid_size_1;
978}
979
980/* Check whether coordinate is at the boundary between two grids of the same face. */
982 const SubdivCCGCoord &coord)
983{
984 const int grid_size_1 = subdiv_ccg.grid_size - 1;
985 if (coord.x == 0) {
986 return coord.y > 0 && coord.y < grid_size_1;
987 }
988 if (coord.y == 0) {
989 return coord.x > 0 && coord.x < grid_size_1;
990 }
991 return false;
992}
993
995 const SubdivCCGCoord &coord)
996{
997 BLI_assert(coord.y > 0);
998 SubdivCCGCoord result = coord;
999 result.y -= 1;
1000 return result;
1001}
1003 const SubdivCCGCoord &coord)
1004{
1005 UNUSED_VARS_NDEBUG(subdiv_ccg);
1006 BLI_assert(coord.y < subdiv_ccg.grid_size - 1);
1007 SubdivCCGCoord result = coord;
1008 result.y += 1;
1009 return result;
1010}
1011
1013 const SubdivCCGCoord &coord)
1014{
1015 BLI_assert(coord.x > 0);
1016 SubdivCCGCoord result = coord;
1017 result.x -= 1;
1018 return result;
1019}
1021 const SubdivCCGCoord &coord)
1022{
1023 UNUSED_VARS_NDEBUG(subdiv_ccg);
1024 BLI_assert(coord.x < subdiv_ccg.grid_size - 1);
1025 SubdivCCGCoord result = coord;
1026 result.x += 1;
1027 return result;
1028}
1029
1030#ifdef WITH_OPENSUBDIV
1031
1032/* For the input coordinate which is at the boundary of the grid do one step inside. */
1033static SubdivCCGCoord coord_step_inside_from_boundary(const SubdivCCG &subdiv_ccg,
1034 const SubdivCCGCoord &coord)
1035
1036{
1037 SubdivCCGCoord result = coord;
1038 const int grid_size_1 = subdiv_ccg.grid_size - 1;
1039 if (result.x == grid_size_1) {
1040 --result.x;
1041 }
1042 else if (result.y == grid_size_1) {
1043 --result.y;
1044 }
1045 else if (result.x == 0) {
1046 ++result.x;
1047 }
1048 else if (result.y == 0) {
1049 ++result.y;
1050 }
1051 else {
1052 BLI_assert_msg(0, "non-boundary element given");
1053 }
1054 return result;
1055}
1056
1058int next_grid_index_from_coord(const SubdivCCG &subdiv_ccg, const SubdivCCGCoord &coord)
1059{
1060 const IndexRange face = subdiv_ccg.faces[subdiv_ccg.grid_to_face_map[coord.grid_index]];
1061 const int face_grid_index = coord.grid_index;
1062 int next_face_grid_index = face_grid_index + 1 - face.start();
1063 if (next_face_grid_index == face.size()) {
1064 next_face_grid_index = 0;
1065 }
1066 return face.start() + next_face_grid_index;
1067}
1068BLI_INLINE int prev_grid_index_from_coord(const SubdivCCG &subdiv_ccg, const SubdivCCGCoord &coord)
1069{
1070 const IndexRange face = subdiv_ccg.faces[subdiv_ccg.grid_to_face_map[coord.grid_index]];
1071 const int face_grid_index = coord.grid_index;
1072 int prev_face_grid_index = face_grid_index - 1 - face.start();
1073 if (prev_face_grid_index < 0) {
1074 prev_face_grid_index = face.size() - 1;
1075 }
1076 return face.start() + prev_face_grid_index;
1077}
1078
1079/* Simple case of getting neighbors of a corner coordinate: the corner is a face center, so
1080 * can only iterate over grid of a single face, without looking into adjacency. */
1081static void neighbor_coords_corner_center_get(const SubdivCCG &subdiv_ccg,
1082 const SubdivCCGCoord &coord,
1083 const bool include_duplicates,
1084 SubdivCCGNeighbors &r_neighbors)
1085{
1086 const IndexRange face = subdiv_ccg.faces[subdiv_ccg.grid_to_face_map[coord.grid_index]];
1087 const int num_adjacent_grids = face.size();
1088
1090 r_neighbors, num_adjacent_grids, (include_duplicates) ? num_adjacent_grids - 1 : 0);
1091
1092 int duplicate_face_grid_index = num_adjacent_grids;
1093 for (int face_grid_index = 0; face_grid_index < num_adjacent_grids; ++face_grid_index) {
1094 SubdivCCGCoord neighbor_coord;
1095 neighbor_coord.grid_index = face.start() + face_grid_index;
1096 neighbor_coord.x = 1;
1097 neighbor_coord.y = 0;
1098 r_neighbors.coords[face_grid_index] = neighbor_coord;
1099
1100 if (include_duplicates && neighbor_coord.grid_index != coord.grid_index) {
1101 neighbor_coord.x = 0;
1102 r_neighbors.coords[duplicate_face_grid_index++] = neighbor_coord;
1103 }
1104 }
1105}
1106
1107/* Get index within adjacent_verts array for the given CCG coordinate. */
1108static int adjacent_vertex_index_from_coord(const SubdivCCG &subdiv_ccg,
1109 const SubdivCCGCoord &coord)
1110{
1111 Subdiv *subdiv = subdiv_ccg.subdiv;
1112 const blender::opensubdiv::TopologyRefinerImpl *topology_refiner = subdiv->topology_refiner;
1113
1114 const int face_index = subdiv_ccg.grid_to_face_map[coord.grid_index];
1115 const IndexRange face = subdiv_ccg.faces[face_index];
1116 const int face_grid_index = coord.grid_index - face.start();
1117
1118 const OpenSubdiv::Far::ConstIndexArray face_vertices =
1119 topology_refiner->base_level().GetFaceVertices(face_index);
1120
1121 const int adjacent_vertex_index = face_vertices[face_grid_index];
1122 return adjacent_vertex_index;
1123}
1124
1125/* The corner is adjacent to a coarse vertex. */
1126static void neighbor_coords_corner_vertex_get(const SubdivCCG &subdiv_ccg,
1127 const SubdivCCGCoord &coord,
1128 const bool include_duplicates,
1129 SubdivCCGNeighbors &r_neighbors)
1130{
1131 Subdiv *subdiv = subdiv_ccg.subdiv;
1132 const blender::opensubdiv::TopologyRefinerImpl *topology_refiner = subdiv->topology_refiner;
1133
1134 const int adjacent_vertex_index = adjacent_vertex_index_from_coord(subdiv_ccg, coord);
1135 const OpenSubdiv::Far::ConstIndexArray vertex_edges =
1136 topology_refiner->base_level().GetVertexEdges(adjacent_vertex_index);
1137
1138 const SubdivCCGAdjacentVertex &adjacent_vert = subdiv_ccg.adjacent_verts[adjacent_vertex_index];
1139 const int num_adjacent_faces = adjacent_vert.num_adjacent_faces;
1140
1142 r_neighbors, vertex_edges.size(), (include_duplicates) ? num_adjacent_faces - 1 : 0);
1143
1144 for (int i = 0; i < vertex_edges.size(); ++i) {
1145 const int edge_index = vertex_edges[i];
1146
1147 /* Use very first grid of every edge. */
1148 const int edge_face_index = 0;
1149
1150 /* Depending edge orientation we use first (zero-based) or previous-to-last point. */
1151 const OpenSubdiv::Far::ConstIndexArray edge_vertices_indices =
1152 topology_refiner->base_level().GetEdgeVertices(edge_index);
1153 int edge_point_index, duplicate_edge_point_index;
1154 if (edge_vertices_indices[0] == adjacent_vertex_index) {
1155 duplicate_edge_point_index = 0;
1156 edge_point_index = duplicate_edge_point_index + 1;
1157 }
1158 else {
1159 /* Edge "consists" of 2 grids, which makes it 2 * grid_size elements per edge.
1160 * The index of last edge element is 2 * grid_size - 1 (due to zero-based indices),
1161 * and we are interested in previous to last element. */
1162 duplicate_edge_point_index = subdiv_ccg.grid_size * 2 - 1;
1163 edge_point_index = duplicate_edge_point_index - 1;
1164 }
1165
1166 const SubdivCCGAdjacentEdge &adjacent_edge = subdiv_ccg.adjacent_edges[edge_index];
1167 r_neighbors.coords[i] = adjacent_edge.boundary_coords[edge_face_index][edge_point_index];
1168 }
1169
1170 if (include_duplicates) {
1171 /* Add duplicates of the current grid vertex in adjacent faces if requested. */
1172 for (int i = 0, duplicate_i = vertex_edges.size(); i < num_adjacent_faces; i++) {
1173 SubdivCCGCoord neighbor_coord = adjacent_vert.corner_coords[i];
1174 if (neighbor_coord.grid_index != coord.grid_index) {
1175 r_neighbors.coords[duplicate_i++] = neighbor_coord;
1176 }
1177 }
1178 }
1179}
1180
1181static int adjacent_edge_index_from_coord(const SubdivCCG &subdiv_ccg, const SubdivCCGCoord &coord)
1182{
1183 Subdiv *subdiv = subdiv_ccg.subdiv;
1184 const blender::opensubdiv::TopologyRefinerImpl *topology_refiner = subdiv->topology_refiner;
1185
1186 const int face_index = subdiv_ccg.grid_to_face_map[coord.grid_index];
1187 const IndexRange face = subdiv_ccg.faces[face_index];
1188 const int face_grid_index = coord.grid_index - face.start();
1189
1190 const OpenSubdiv::Far::ConstIndexArray face_edges = topology_refiner->base_level().GetFaceEdges(
1191 face_index);
1192
1193 const int grid_size_1 = subdiv_ccg.grid_size - 1;
1194 int adjacent_edge_index = -1;
1195 if (coord.x == grid_size_1) {
1196 adjacent_edge_index = face_edges[face_grid_index];
1197 }
1198 else {
1199 BLI_assert(coord.y == grid_size_1);
1200 adjacent_edge_index = face_edges[face_grid_index == 0 ? face.size() - 1 : face_grid_index - 1];
1201 }
1202
1203 return adjacent_edge_index;
1204}
1205
1206static int adjacent_edge_point_index_from_coord(const SubdivCCG &subdiv_ccg,
1207 const SubdivCCGCoord &coord,
1208 const int adjacent_edge_index)
1209{
1210 Subdiv *subdiv = subdiv_ccg.subdiv;
1211 const blender::opensubdiv::TopologyRefinerImpl *topology_refiner = subdiv->topology_refiner;
1212
1213 const int adjacent_vertex_index = adjacent_vertex_index_from_coord(subdiv_ccg, coord);
1214 const OpenSubdiv::Far::ConstIndexArray edge_vertices_indices =
1215 topology_refiner->base_level().GetEdgeVertices(adjacent_edge_index);
1216
1217 /* Vertex index of an edge which is used to see whether edge points in the right direction.
1218 * Tricky part here is that depending whether input coordinate is are maximum X or Y coordinate
1219 * of the grid we need to use different edge direction.
1220 * Basically, the edge adjacent to a previous loop needs to point opposite direction. */
1221 int directional_edge_vertex_index = -1;
1222
1223 const int grid_size_1 = subdiv_ccg.grid_size - 1;
1224 int adjacent_edge_point_index = -1;
1225 if (coord.x == grid_size_1) {
1226 adjacent_edge_point_index = subdiv_ccg.grid_size - coord.y - 1;
1227 directional_edge_vertex_index = edge_vertices_indices[0];
1228 }
1229 else {
1230 BLI_assert(coord.y == grid_size_1);
1231 adjacent_edge_point_index = subdiv_ccg.grid_size + coord.x;
1232 directional_edge_vertex_index = edge_vertices_indices[1];
1233 }
1234
1235 /* Flip the index if the edge points opposite direction. */
1236 if (adjacent_vertex_index != directional_edge_vertex_index) {
1237 const int num_edge_points = subdiv_ccg.grid_size * 2;
1238 adjacent_edge_point_index = num_edge_points - adjacent_edge_point_index - 1;
1239 }
1240
1241 return adjacent_edge_point_index;
1242}
1243
1244/* Adjacent edge has two points in the middle which corresponds to grid corners, but which are
1245 * the same point in the final geometry.
1246 * So need to use extra step when calculating next/previous points, so we don't go from a corner
1247 * of one grid to a corner of adjacent grid. */
1248static int next_adjacent_edge_point_index(const SubdivCCG &subdiv_ccg, const int point_index)
1249{
1250 if (point_index == subdiv_ccg.grid_size - 1) {
1251 return point_index + 2;
1252 }
1253 return point_index + 1;
1254}
1255static int prev_adjacent_edge_point_index(const SubdivCCG &subdiv_ccg, const int point_index)
1256{
1257 if (point_index == subdiv_ccg.grid_size) {
1258 return point_index - 2;
1259 }
1260 return point_index - 1;
1261}
1262
1263/* When the point index corresponds to a grid corner, returns the point index which corresponds to
1264 * the corner of the adjacent grid, as the adjacent edge has two separate points for each grid
1265 * corner at the middle of the edge. */
1266static int adjacent_grid_corner_point_index_on_edge(const SubdivCCG &subdiv_ccg,
1267 const int point_index)
1268{
1269 if (point_index == subdiv_ccg.grid_size) {
1270 return point_index - 1;
1271 }
1272 return point_index + 1;
1273}
1274
1275/* Common implementation of neighbor calculation when input coordinate is at the edge between two
1276 * coarse faces, but is not at the coarse vertex. */
1277static void neighbor_coords_edge_get(const SubdivCCG &subdiv_ccg,
1278 const SubdivCCGCoord &coord,
1279 const bool include_duplicates,
1280 SubdivCCGNeighbors &r_neighbors)
1281
1282{
1283 const bool is_corner = is_corner_grid_coord(subdiv_ccg, coord);
1284 const int adjacent_edge_index = adjacent_edge_index_from_coord(subdiv_ccg, coord);
1285 const SubdivCCGAdjacentEdge *adjacent_edge = &subdiv_ccg.adjacent_edges[adjacent_edge_index];
1286
1287 /* 2 neighbor points along the edge, plus one inner point per every adjacent grid. */
1288 const int num_adjacent_faces = adjacent_edge->num_adjacent_faces;
1289 int num_duplicates = 0;
1290 if (include_duplicates) {
1291 num_duplicates += num_adjacent_faces - 1;
1292 if (is_corner) {
1293 /* When the coord is a grid corner, add an extra duplicate per adjacent grid in all adjacent
1294 * faces to the edge. */
1295 num_duplicates += num_adjacent_faces;
1296 }
1297 }
1298 subdiv_ccg_neighbors_init(r_neighbors, num_adjacent_faces + 2, num_duplicates);
1299
1300 const int point_index = adjacent_edge_point_index_from_coord(
1301 subdiv_ccg, coord, adjacent_edge_index);
1302 const int point_index_duplicate = adjacent_grid_corner_point_index_on_edge(subdiv_ccg,
1303 point_index);
1304
1305 const int next_point_index = next_adjacent_edge_point_index(subdiv_ccg, point_index);
1306 const int prev_point_index = prev_adjacent_edge_point_index(subdiv_ccg, point_index);
1307
1308 int duplicate_i = num_adjacent_faces;
1309 for (int i = 0; i < num_adjacent_faces; ++i) {
1310 const SubdivCCGCoord *boundary_coords = adjacent_edge->boundary_coords[i];
1311 /* One step into the grid from the edge for each adjacent face. */
1312 SubdivCCGCoord grid_coord = boundary_coords[point_index];
1313 r_neighbors.coords[i + 2] = coord_step_inside_from_boundary(subdiv_ccg, grid_coord);
1314
1315 if (grid_coord.grid_index == coord.grid_index) {
1316 /* Previous and next along the edge for the current grid. */
1317 r_neighbors.coords[0] = boundary_coords[prev_point_index];
1318 r_neighbors.coords[1] = boundary_coords[next_point_index];
1319 }
1320 else if (include_duplicates) {
1321 /* Same coordinate on neighboring grids if requested. */
1322 r_neighbors.coords[duplicate_i + 2] = grid_coord;
1323 duplicate_i++;
1324 }
1325
1326 /* When it is a corner, add the duplicate of the adjacent grid in the same face. */
1327 if (include_duplicates && is_corner) {
1328 SubdivCCGCoord duplicate_corner_grid_coord = boundary_coords[point_index_duplicate];
1329 r_neighbors.coords[duplicate_i + 2] = duplicate_corner_grid_coord;
1330 duplicate_i++;
1331 }
1332 }
1333 BLI_assert(duplicate_i - num_adjacent_faces == num_duplicates);
1334}
1335
1336/* The corner is at the middle of edge between faces. */
1337static void neighbor_coords_corner_edge_get(const SubdivCCG &subdiv_ccg,
1338 const SubdivCCGCoord &coord,
1339 const bool include_duplicates,
1340 SubdivCCGNeighbors &r_neighbors)
1341{
1342 neighbor_coords_edge_get(subdiv_ccg, coord, include_duplicates, r_neighbors);
1343}
1344
1345/* Input coordinate is at one of 4 corners of its grid corners. */
1346static void neighbor_coords_corner_get(const SubdivCCG &subdiv_ccg,
1347 const SubdivCCGCoord &coord,
1348 const bool include_duplicates,
1349 SubdivCCGNeighbors &r_neighbors)
1350{
1351 if (coord.x == 0 && coord.y == 0) {
1352 neighbor_coords_corner_center_get(subdiv_ccg, coord, include_duplicates, r_neighbors);
1353 }
1354 else {
1355 const int grid_size_1 = subdiv_ccg.grid_size - 1;
1356 if (coord.x == grid_size_1 && coord.y == grid_size_1) {
1357 neighbor_coords_corner_vertex_get(subdiv_ccg, coord, include_duplicates, r_neighbors);
1358 }
1359 else {
1360 neighbor_coords_corner_edge_get(subdiv_ccg, coord, include_duplicates, r_neighbors);
1361 }
1362 }
1363}
1364
1365/* Simple case of getting neighbors of a boundary coordinate: the input coordinate is at the
1366 * boundary between two grids of the same face and there is no need to check adjacency with
1367 * other faces. */
1368static void neighbor_coords_boundary_inner_get(const SubdivCCG &subdiv_ccg,
1369 const SubdivCCGCoord &coord,
1370 const bool include_duplicates,
1371 SubdivCCGNeighbors &r_neighbors)
1372{
1373 subdiv_ccg_neighbors_init(r_neighbors, 4, (include_duplicates) ? 1 : 0);
1374
1375 if (coord.x == 0) {
1376 r_neighbors.coords[0] = coord_at_prev_row(subdiv_ccg, coord);
1377 r_neighbors.coords[1] = coord_at_next_row(subdiv_ccg, coord);
1378 r_neighbors.coords[2] = coord_at_next_col(subdiv_ccg, coord);
1379
1380 r_neighbors.coords[3].grid_index = prev_grid_index_from_coord(subdiv_ccg, coord);
1381 r_neighbors.coords[3].x = coord.y;
1382 r_neighbors.coords[3].y = 1;
1383
1384 if (include_duplicates) {
1385 r_neighbors.coords[4] = r_neighbors.coords[3];
1386 r_neighbors.coords[4].y = 0;
1387 }
1388 }
1389 else if (coord.y == 0) {
1390 r_neighbors.coords[0] = coord_at_prev_col(subdiv_ccg, coord);
1391 r_neighbors.coords[1] = coord_at_next_col(subdiv_ccg, coord);
1392 r_neighbors.coords[2] = coord_at_next_row(subdiv_ccg, coord);
1393
1394 r_neighbors.coords[3].grid_index = next_grid_index_from_coord(subdiv_ccg, coord);
1395 r_neighbors.coords[3].x = 1;
1396 r_neighbors.coords[3].y = coord.x;
1397
1398 if (include_duplicates) {
1399 r_neighbors.coords[4] = r_neighbors.coords[3];
1400 r_neighbors.coords[4].x = 0;
1401 }
1402 }
1403}
1404
1405/* Input coordinate is on an edge between two faces. Need to check adjacency. */
1406static void neighbor_coords_boundary_outer_get(const SubdivCCG &subdiv_ccg,
1407 const SubdivCCGCoord &coord,
1408 const bool include_duplicates,
1409 SubdivCCGNeighbors &r_neighbors)
1410{
1411 neighbor_coords_edge_get(subdiv_ccg, coord, include_duplicates, r_neighbors);
1412}
1413
1414/* Input coordinate is at one of 4 boundaries of its grid.
1415 * It could either be an inner boundary (which connects face center to the face edge) or could be
1416 * a part of coarse face edge. */
1417static void neighbor_coords_boundary_get(const SubdivCCG &subdiv_ccg,
1418 const SubdivCCGCoord &coord,
1419 const bool include_duplicates,
1420 SubdivCCGNeighbors &r_neighbors)
1421{
1422 if (is_inner_edge_grid_coordinate(subdiv_ccg, coord)) {
1423 neighbor_coords_boundary_inner_get(subdiv_ccg, coord, include_duplicates, r_neighbors);
1424 }
1425 else {
1426 neighbor_coords_boundary_outer_get(subdiv_ccg, coord, include_duplicates, r_neighbors);
1427 }
1428}
1429
1430/* Input coordinate is inside of its grid, all the neighbors belong to the same grid. */
1431static void neighbor_coords_inner_get(const SubdivCCG &subdiv_ccg,
1432 const SubdivCCGCoord &coord,
1433 SubdivCCGNeighbors &r_neighbors)
1434{
1435 subdiv_ccg_neighbors_init(r_neighbors, 4, 0);
1436
1437 r_neighbors.coords[0] = coord_at_prev_row(subdiv_ccg, coord);
1438 r_neighbors.coords[1] = coord_at_next_row(subdiv_ccg, coord);
1439 r_neighbors.coords[2] = coord_at_prev_col(subdiv_ccg, coord);
1440 r_neighbors.coords[3] = coord_at_next_col(subdiv_ccg, coord);
1441}
1442
1443#endif
1444
1446 const SubdivCCGCoord &coord,
1447 const bool include_duplicates,
1448 SubdivCCGNeighbors &r_neighbors)
1449{
1450#ifdef WITH_OPENSUBDIV
1451 BLI_assert(coord.grid_index >= 0);
1452 BLI_assert(coord.grid_index < subdiv_ccg.grids_num);
1453 BLI_assert(coord.x >= 0);
1454 BLI_assert(coord.x < subdiv_ccg.grid_size);
1455 BLI_assert(coord.y >= 0);
1456 BLI_assert(coord.y < subdiv_ccg.grid_size);
1457
1458 if (is_corner_grid_coord(subdiv_ccg, coord)) {
1459 neighbor_coords_corner_get(subdiv_ccg, coord, include_duplicates, r_neighbors);
1460 }
1461 else if (is_boundary_grid_coord(subdiv_ccg, coord)) {
1462 neighbor_coords_boundary_get(subdiv_ccg, coord, include_duplicates, r_neighbors);
1463 }
1464 else {
1465 neighbor_coords_inner_get(subdiv_ccg, coord, r_neighbors);
1466 }
1467
1468# ifndef NDEBUG
1469 for (const int i : r_neighbors.coords.index_range()) {
1470 BLI_assert(BKE_subdiv_ccg_check_coord_valid(subdiv_ccg, r_neighbors.coords[i]));
1471 }
1472# endif
1473#else
1474 UNUSED_VARS(subdiv_ccg, coord, include_duplicates, r_neighbors);
1475#endif
1476}
1477
1479{
1480#ifdef WITH_OPENSUBDIV
1481 if (subdiv_ccg.cache_.start_face_grid_index.is_empty()) {
1482 const Subdiv *subdiv = subdiv_ccg.subdiv;
1483 const blender::opensubdiv::TopologyRefinerImpl *topology_refiner = subdiv->topology_refiner;
1484 if (topology_refiner == nullptr) {
1485 return nullptr;
1486 }
1487
1488 const int num_coarse_faces = topology_refiner->base_level().GetNumFaces();
1489
1490 subdiv_ccg.cache_.start_face_grid_index.reinitialize(num_coarse_faces);
1491
1492 int start_grid_index = 0;
1493 for (int face_index = 0; face_index < num_coarse_faces; face_index++) {
1494 const int num_face_grids = topology_refiner->base_level().GetFaceVertices(face_index).size();
1495 subdiv_ccg.cache_.start_face_grid_index[face_index] = start_grid_index;
1496 start_grid_index += num_face_grids;
1497 }
1498 }
1499#endif
1500
1501 return subdiv_ccg.cache_.start_face_grid_index.data();
1502}
1503
1505{
1506 return subdiv_ccg.cache_.start_face_grid_index.data();
1507}
1508
1510 const SubdivCCGCoord &coord,
1511 const blender::Span<int> corner_verts,
1512 const blender::OffsetIndices<int> faces,
1513 int &r_v1,
1514 int &r_v2)
1515{
1516 const int grid_size_1 = subdiv_ccg.grid_size - 1;
1517 const int face_index = BKE_subdiv_ccg_grid_to_face_index(subdiv_ccg, coord.grid_index);
1518 const blender::IndexRange face = faces[face_index];
1519 r_v1 = corner_verts[coord.grid_index];
1520
1521 const int corner = blender::bke::mesh::face_find_corner_from_vert(face, corner_verts, r_v1);
1522 if (coord.x == grid_size_1) {
1523 const int next = blender::bke::mesh::face_corner_next(face, corner);
1524 r_v2 = corner_verts[next];
1525 }
1526 if (coord.y == grid_size_1) {
1527 const int prev = blender::bke::mesh::face_corner_prev(face, corner);
1528 r_v2 = corner_verts[prev];
1529 }
1530}
1531
1533 const SubdivCCG &subdiv_ccg,
1534 const SubdivCCGCoord &coord,
1535 const blender::Span<int> corner_verts,
1536 const blender::OffsetIndices<int> faces,
1537 int &r_v1,
1538 int &r_v2)
1539{
1540
1541 const int grid_size_1 = subdiv_ccg.grid_size - 1;
1542 if (is_corner_grid_coord(subdiv_ccg, coord)) {
1543 if (coord.x == 0 && coord.y == 0) {
1544 /* Grid corner in the center of a face. */
1546 }
1547 if (coord.x == grid_size_1 && coord.y == grid_size_1) {
1548 /* Grid corner adjacent to a coarse mesh vertex. */
1549 r_v1 = r_v2 = corner_verts[coord.grid_index];
1551 }
1552 /* Grid corner adjacent to the middle of a coarse mesh edge. */
1553 adjacent_vertices_index_from_adjacent_edge(subdiv_ccg, coord, corner_verts, faces, r_v1, r_v2);
1555 }
1556
1557 if (is_boundary_grid_coord(subdiv_ccg, coord)) {
1558 if (!is_inner_edge_grid_coordinate(subdiv_ccg, coord)) {
1559 /* Grid boundary adjacent to a coarse mesh edge. */
1561 subdiv_ccg, coord, corner_verts, faces, r_v1, r_v2);
1563 }
1564 }
1566}
1567
1568bool BKE_subdiv_ccg_coord_is_mesh_boundary(const OffsetIndices<int> faces,
1569 const Span<int> corner_verts,
1570 const blender::BitSpan boundary_verts,
1571 const SubdivCCG &subdiv_ccg,
1572 const SubdivCCGCoord coord)
1573{
1574 int v1, v2;
1576 subdiv_ccg, coord, corner_verts, faces, v1, v2);
1577 switch (adjacency) {
1579 return boundary_verts[v1];
1581 return boundary_verts[v1] && boundary_verts[v2];
1583 return false;
1584 }
1586 return false;
1587}
1588
1590{
1591 if (subdiv_ccg.grid_hidden.is_empty()) {
1592 const int grid_area = subdiv_ccg.grid_area;
1593 subdiv_ccg.grid_hidden = blender::BitGroupVector<>(subdiv_ccg.grids_num, grid_area, false);
1594 }
1595 return subdiv_ccg.grid_hidden;
1596}
1597
1599{
1600 subdiv_ccg.grid_hidden = {};
1601}
1602
1603static void subdiv_ccg_coord_to_ptex_coord(const SubdivCCG &subdiv_ccg,
1604 const SubdivCCGCoord &coord,
1605 int *r_ptex_face_index,
1606 float *r_u,
1607 float *r_v)
1608{
1609 Subdiv *subdiv = subdiv_ccg.subdiv;
1610
1611 const float grid_size = subdiv_ccg.grid_size;
1612 const float grid_size_1_inv = 1.0f / (grid_size - 1);
1613
1614 const float grid_u = coord.x * grid_size_1_inv;
1615 const float grid_v = coord.y * grid_size_1_inv;
1616
1617 const int face_index = BKE_subdiv_ccg_grid_to_face_index(subdiv_ccg, coord.grid_index);
1618 const OffsetIndices<int> faces = subdiv_ccg.faces;
1619 const IndexRange face = faces[face_index];
1620 const int *face_ptex_offset = face_ptex_offset_get(subdiv);
1621 *r_ptex_face_index = face_ptex_offset[face_index];
1622
1623 const float corner = coord.grid_index - face.start();
1624
1625 if (face.size() == 4) {
1626 rotate_grid_to_quad(corner, grid_u, grid_v, r_u, r_v);
1627 }
1628 else {
1629 *r_ptex_face_index += corner;
1630 *r_u = 1.0f - grid_v;
1631 *r_v = 1.0f - grid_u;
1632 }
1633}
1634
1636 const SubdivCCGCoord &coord,
1637 float r_point[3])
1638{
1639 Subdiv *subdiv = subdiv_ccg.subdiv;
1640 int ptex_face_index;
1641 float u, v;
1642 subdiv_ccg_coord_to_ptex_coord(subdiv_ccg, coord, &ptex_face_index, &u, &v);
1643 eval_limit_point(subdiv, ptex_face_index, u, v, r_point);
1644}
1645
1647 const CCGKey &key,
1648 const int grid_index,
1649 const MutableSpan<float3> r_limit_positions)
1650{
1651 SubdivCCGCoord coord{};
1652 coord.grid_index = grid_index;
1653 for (const int y : IndexRange(key.grid_size)) {
1654 for (const int x : IndexRange(key.grid_size)) {
1655 const int i = CCG_grid_xy_to_index(key.grid_size, x, y);
1656 coord.x = x;
1657 coord.y = y;
1658 BKE_subdiv_ccg_eval_limit_point(subdiv_ccg, coord, r_limit_positions[i]);
1659 }
1660 }
1661}
1662
int CCG_grid_xy_to_index(const int grid_size, const int x, const int y)
Definition BKE_ccg.hh:77
Mesh * BKE_mesh_new_nomain_from_template(const Mesh *me_src, int verts_num, int edges_num, int faces_num, int corners_num)
int BKE_subdiv_ccg_grid_to_face_index(const SubdivCCG &subdiv_ccg, const int grid_index)
bool BKE_subdiv_ccg_mask_init_from_paint(SubdivCCGMaskEvaluator *mask_evaluator, const Mesh *mesh)
SubdivCCGAdjacencyType
@ SUBDIV_CCG_ADJACENT_EDGE
@ SUBDIV_CCG_ADJACENT_VERTEX
@ SUBDIV_CCG_ADJACENT_NONE
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:57
#define BLI_INLINE
MINLINE int bitscan_forward_i(int a)
float normal_quad_v3(float n[3], const float v1[3], const float v2[3], const float v3[3], const float v4[3])
Definition math_geom.cc:56
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void zero_v3(float r[3])
MINLINE void mul_v3_v3fl(float r[3], const float a[3], float f)
MINLINE void add_v3_v3(float r[3], const float a[3])
#define UNUSED_VARS(...)
#define UNUSED_VARS_NDEBUG(...)
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
#define MEM_reallocN(vmemh, len)
ATTR_WARN_UNUSED_RESULT const void * element
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert * v
const T * data() const
Definition BLI_array.hh:301
IndexRange index_range() const
Definition BLI_array.hh:349
void reinitialize(const int64_t new_size)
Definition BLI_array.hh:388
bool is_empty() const
Definition BLI_array.hh:253
constexpr int64_t size() const
Iterator begin() const
Definition BLI_set.hh:461
Iterator end() const
Definition BLI_set.hh:471
void add_multiple(Span< Key > keys)
Definition BLI_set.hh:268
IndexRange index_range() const
void reinitialize(const int64_t new_size)
const OpenSubdiv::Far::TopologyLevel & base_level() const
local_group_size(16, 16) .push_constant(Type b
#define printf
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition mallocn.cc:45
ccl_device_inline float4 mask(const int4 mask, const float4 a)
static ulong * next
IndexRange grid_range(const int grid_area, const int grid)
int grid_xy_to_vert(const CCGKey &key, const int grid, const int x, const int y)
int face_corner_prev(const IndexRange face, const int corner)
Definition BKE_mesh.hh:243
int face_find_corner_from_vert(const IndexRange face, const Span< int > corner_verts, const int vert)
Definition BKE_mesh.hh:264
int face_corner_next(const IndexRange face, const int corner)
Definition BKE_mesh.hh:252
void free(Subdiv *subdiv)
Definition subdiv.cc:192
BLI_INLINE void rotate_grid_to_quad(int corner, float grid_u, float grid_v, float *r_quad_u, float *r_quad_v)
bool eval_begin_from_mesh(Subdiv *subdiv, const Mesh *mesh, Span< float3 > coarse_vert_positions, eSubdivEvaluatorType evaluator_type, OpenSubdiv_EvaluatorCache *evaluator_cache)
void eval_limit_point(Subdiv *subdiv, int ptex_face_index, float u, float v, float r_P[3])
void eval_limit_point_and_normal(Subdiv *subdiv, int ptex_face_index, float u, float v, float r_P[3], float r_N[3])
BLI_INLINE int grid_size_from_level(int level)
void stats_begin(SubdivStats *stats, StatsValue value)
int * face_ptex_offset_get(Subdiv *subdiv)
Definition subdiv.cc:219
void stats_end(SubdivStats *stats, StatsValue value)
void eval_final_point(Subdiv *subdiv, int ptex_face_index, float u, float v, float r_P[3])
__int64 int64_t
Definition stdint.h:89
int has_mask
Definition BKE_ccg.hh:48
int mask_offset
Definition BKE_ccg.hh:45
int grid_size
Definition BKE_ccg.hh:33
int grid_bytes
Definition BKE_ccg.hh:37
int grid_area
Definition BKE_ccg.hh:35
int level
Definition BKE_ccg.hh:26
int normal_offset
Definition BKE_ccg.hh:41
int elem_size
Definition BKE_ccg.hh:30
int has_normals
Definition BKE_ccg.hh:47
int faces_num
SubdivCCGCoord ** boundary_coords
SubdivCCGCoord * corner_coords
int to_index(const CCGKey &key) const
float(* eval_mask)(SubdivCCGMaskEvaluator *mask_evaluator, int ptex_face_index, float u, float v)
void(* free)(SubdivCCGMaskEvaluator *mask_evaluator)
blender::Vector< SubdivCCGCoord, 256 > coords
blender::Array< blender::float3 > normals
blender::BitGroupVector grid_hidden
blender::Array< float > masks
struct SubdivCCG::@65 cache_
blender::Array< SubdivCCGAdjacentVertex > adjacent_verts
blender::bke::subdiv::Subdiv * subdiv
blender::Array< int > start_face_grid_index
blender::OffsetIndices< int > faces
blender::Array< SubdivCCGAdjacentEdge > adjacent_edges
blender::Span< int > grid_to_face_map
blender::Array< blender::float3 > positions
Displacement * displacement_evaluator
blender::opensubdiv::TopologyRefinerImpl * topology_refiner
void BKE_subdiv_ccg_update_normals(SubdivCCG &subdiv_ccg, const IndexMask &face_mask)
BLI_INLINE SubdivCCGCoord coord_at_prev_col(const SubdivCCG &, const SubdivCCGCoord &coord)
BLI_INLINE void subdiv_ccg_neighbors_init(SubdivCCGNeighbors &neighbors, const int num_unique, const int num_duplicates)
const int * BKE_subdiv_ccg_start_face_grid_index_get(const SubdivCCG &subdiv_ccg)
const int * BKE_subdiv_ccg_start_face_grid_index_ensure(SubdivCCG &subdiv_ccg)
void BKE_subdiv_ccg_recalc_normals(SubdivCCG &subdiv_ccg)
CCGKey BKE_subdiv_ccg_key_top_level(const SubdivCCG &subdiv_ccg)
void BKE_subdiv_ccg_eval_limit_point(const SubdivCCG &subdiv_ccg, const SubdivCCGCoord &coord, float r_point[3])
Mesh * BKE_subdiv_to_ccg_mesh(Subdiv &subdiv, const SubdivToCCGSettings &settings, const Mesh &coarse_mesh)
bool BKE_subdiv_ccg_coord_is_mesh_boundary(const OffsetIndices< int > faces, const Span< int > corner_verts, const blender::BitSpan boundary_verts, const SubdivCCG &subdiv_ccg, const SubdivCCGCoord coord)
blender::BitGroupVector & BKE_subdiv_ccg_grid_hidden_ensure(SubdivCCG &subdiv_ccg)
BLI_INLINE bool is_inner_edge_grid_coordinate(const SubdivCCG &subdiv_ccg, const SubdivCCGCoord &coord)
static void adjacent_vertices_index_from_adjacent_edge(const SubdivCCG &subdiv_ccg, const SubdivCCGCoord &coord, const blender::Span< int > corner_verts, const blender::OffsetIndices< int > faces, int &r_v1, int &r_v2)
void BKE_subdiv_ccg_print_coord(const char *message, const SubdivCCGCoord &coord)
void BKE_subdiv_ccg_eval_limit_positions(const SubdivCCG &subdiv_ccg, const CCGKey &key, const int grid_index, const MutableSpan< float3 > r_limit_positions)
BLI_INLINE bool is_corner_grid_coord(const SubdivCCG &subdiv_ccg, const SubdivCCGCoord &coord)
void BKE_subdiv_ccg_average_stitch_faces(SubdivCCG &subdiv_ccg, const IndexMask &face_mask)
CCGKey BKE_subdiv_ccg_key(const SubdivCCG &, int level)
static void subdiv_ccg_coord_to_ptex_coord(const SubdivCCG &subdiv_ccg, const SubdivCCGCoord &coord, int *r_ptex_face_index, float *r_u, float *r_v)
SubdivCCGAdjacencyType BKE_subdiv_ccg_coarse_mesh_adjacency_info_get(const SubdivCCG &subdiv_ccg, const SubdivCCGCoord &coord, const blender::Span< int > corner_verts, const blender::OffsetIndices< int > faces, int &r_v1, int &r_v2)
bool BKE_subdiv_ccg_check_coord_valid(const SubdivCCG &subdiv_ccg, const SubdivCCGCoord &coord)
void BKE_subdiv_ccg_topology_counters(const SubdivCCG &subdiv_ccg, int &r_num_vertices, int &r_num_edges, int &r_num_faces, int &r_num_loops)
void BKE_subdiv_ccg_average_grids(SubdivCCG &subdiv_ccg)
BLI_INLINE bool is_boundary_grid_coord(const SubdivCCG &subdiv_ccg, const SubdivCCGCoord &coord)
BLI_INLINE SubdivCCGCoord coord_at_next_col(const SubdivCCG &subdiv_ccg, const SubdivCCGCoord &coord)
void BKE_subdiv_ccg_neighbor_coords_get(const SubdivCCG &subdiv_ccg, const SubdivCCGCoord &coord, const bool include_duplicates, SubdivCCGNeighbors &r_neighbors)
BLI_INLINE SubdivCCGCoord coord_at_next_row(const SubdivCCG &subdiv_ccg, const SubdivCCGCoord &coord)
std::unique_ptr< SubdivCCG > BKE_subdiv_to_ccg(Subdiv &subdiv, const SubdivToCCGSettings &settings, const Mesh &coarse_mesh, SubdivCCGMaskEvaluator *mask_evaluator)
BLI_INLINE SubdivCCGCoord coord_at_prev_row(const SubdivCCG &, const SubdivCCGCoord &coord)
void BKE_subdiv_ccg_grid_hidden_free(SubdivCCG &subdiv_ccg)