Blender  V2.93
subdiv_mesh.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2018 by Blender Foundation.
17  * All rights reserved.
18  */
19 
24 #include "BKE_subdiv_mesh.h"
25 
26 #include "atomic_ops.h"
27 
28 #include "DNA_key_types.h"
29 #include "DNA_mesh_types.h"
30 #include "DNA_meshdata_types.h"
31 
32 #include "BLI_alloca.h"
33 #include "BLI_math_vector.h"
34 
35 #include "BKE_customdata.h"
36 #include "BKE_key.h"
37 #include "BKE_mesh.h"
38 #include "BKE_subdiv.h"
39 #include "BKE_subdiv_eval.h"
40 #include "BKE_subdiv_foreach.h"
41 
42 #include "MEM_guardedalloc.h"
43 
44 /* -------------------------------------------------------------------- */
48 typedef struct SubdivMeshContext {
50  const Mesh *coarse_mesh;
53  /* Cached custom data arrays for fastter access. */
58  /* UV layers interpolation. */
61  /* Accumulated values.
62  *
63  * Averaging is happening for vertices along the coarse edges and corners.
64  * This is needed for both displacement and normals.
65  *
66  * Displacement is being accumulated to a vertices coordinates, since those
67  * are not needed during traversal of edge/corner vertices.
68  *
69  * For normals we are using dedicated array, since we can not use same
70  * vertices (normals are `short`, which will cause a lot of precision
71  * issues). */
73  /* Per-subdivided vertex counter of averaged values. */
75  /* Denotes whether normals can be evaluated from a limit surface. One case
76  * when it's not possible is when displacement is used. */
80 
82 {
83  Mesh *subdiv_mesh = ctx->subdiv_mesh;
85  for (int layer_index = 0; layer_index < ctx->num_uv_layers; layer_index++) {
86  ctx->uv_layers[layer_index] = CustomData_get_layer_n(
87  &subdiv_mesh->ldata, CD_MLOOPUV, layer_index);
88  }
89 }
90 
92 {
93  Mesh *subdiv_mesh = ctx->subdiv_mesh;
94  /* Pointers to original indices layers. */
95  ctx->vert_origindex = CustomData_get_layer(&subdiv_mesh->vdata, CD_ORIGINDEX);
96  ctx->edge_origindex = CustomData_get_layer(&subdiv_mesh->edata, CD_ORIGINDEX);
98  ctx->poly_origindex = CustomData_get_layer(&subdiv_mesh->pdata, CD_ORIGINDEX);
99  /* UV layers interpolation. */
101 }
102 
103 static void subdiv_mesh_prepare_accumulator(SubdivMeshContext *ctx, int num_vertices)
104 {
105  if (!ctx->can_evaluate_normals && !ctx->have_displacement) {
106  return;
107  }
108  /* TODO(sergey): Technically, this is overallocating, we don't need memory
109  * for an inner subdivision vertices. */
111  sizeof(*ctx->accumulated_normals), num_vertices, "subdiv accumulated normals");
113  sizeof(*ctx->accumulated_counters), num_vertices, "subdiv accumulated counters");
114 }
115 
117 {
120 }
121 
124 /* -------------------------------------------------------------------- */
128 typedef struct LoopsOfPtex {
129  /* First loop of the ptex, starts at ptex (0, 0) and goes in u direction. */
131  /* Last loop of the ptex, starts at ptex (0, 0) and goes in v direction. */
132  const MLoop *last_loop;
133  /* For quad coarse faces only. */
137 
138 static void loops_of_ptex_get(const SubdivMeshContext *ctx,
139  LoopsOfPtex *loops_of_ptex,
140  const MPoly *coarse_poly,
141  const int ptex_of_poly_index)
142 {
143  const MLoop *coarse_mloop = ctx->coarse_mesh->mloop;
144  const int first_ptex_loop_index = coarse_poly->loopstart + ptex_of_poly_index;
145  /* Loop which look in the (opposite) V direction of the current
146  * ptex face.
147  *
148  * TODO(sergey): Get rid of using module on every iteration. */
149  const int last_ptex_loop_index = coarse_poly->loopstart +
150  (ptex_of_poly_index + coarse_poly->totloop - 1) %
151  coarse_poly->totloop;
152  loops_of_ptex->first_loop = &coarse_mloop[first_ptex_loop_index];
153  loops_of_ptex->last_loop = &coarse_mloop[last_ptex_loop_index];
154  if (coarse_poly->totloop == 4) {
155  loops_of_ptex->second_loop = loops_of_ptex->first_loop + 1;
156  loops_of_ptex->third_loop = loops_of_ptex->first_loop + 2;
157  }
158  else {
159  loops_of_ptex->second_loop = NULL;
160  loops_of_ptex->third_loop = NULL;
161  }
162 }
163 
166 /* -------------------------------------------------------------------- */
170 /* TODO(sergey): Somehow de-duplicate with loops storage, without too much
171  * exception cases all over the code. */
172 
173 typedef struct VerticesForInterpolation {
174  /* This field points to a vertex data which is to be used for interpolation.
175  * The idea is to avoid unnecessary allocations for regular faces, where
176  * we can simply use corner vertices. */
178  /* Vertices data calculated for ptex corners. There are always 4 elements
179  * in this custom data, aligned the following way:
180  *
181  * index 0 -> uv (0, 0)
182  * index 1 -> uv (0, 1)
183  * index 2 -> uv (1, 1)
184  * index 3 -> uv (1, 0)
185  *
186  * Is allocated for non-regular faces (triangles and n-gons). */
189  /* Indices within vertex_data to interpolate for. The indices are aligned
190  * with uv coordinates in a similar way as indices in loop_data_storage. */
193 
195  VerticesForInterpolation *vertex_interpolation,
196  const MPoly *coarse_poly)
197 {
198  const Mesh *coarse_mesh = ctx->coarse_mesh;
199  const MLoop *coarse_mloop = coarse_mesh->mloop;
200  if (coarse_poly->totloop == 4) {
201  vertex_interpolation->vertex_data = &coarse_mesh->vdata;
202  vertex_interpolation->vertex_indices[0] = coarse_mloop[coarse_poly->loopstart + 0].v;
203  vertex_interpolation->vertex_indices[1] = coarse_mloop[coarse_poly->loopstart + 1].v;
204  vertex_interpolation->vertex_indices[2] = coarse_mloop[coarse_poly->loopstart + 2].v;
205  vertex_interpolation->vertex_indices[3] = coarse_mloop[coarse_poly->loopstart + 3].v;
206  vertex_interpolation->vertex_data_storage_allocated = false;
207  }
208  else {
209  vertex_interpolation->vertex_data = &vertex_interpolation->vertex_data_storage;
210  /* Allocate storage for loops corresponding to ptex corners. */
211  CustomData_copy(&ctx->coarse_mesh->vdata,
212  &vertex_interpolation->vertex_data_storage,
214  CD_CALLOC,
215  4);
216  /* Initialize indices. */
217  vertex_interpolation->vertex_indices[0] = 0;
218  vertex_interpolation->vertex_indices[1] = 1;
219  vertex_interpolation->vertex_indices[2] = 2;
220  vertex_interpolation->vertex_indices[3] = 3;
221  vertex_interpolation->vertex_data_storage_allocated = true;
222  /* Interpolate center of poly right away, it stays unchanged for all
223  * ptex faces. */
224  const float weight = 1.0f / (float)coarse_poly->totloop;
225  float *weights = BLI_array_alloca(weights, coarse_poly->totloop);
226  int *indices = BLI_array_alloca(indices, coarse_poly->totloop);
227  for (int i = 0; i < coarse_poly->totloop; i++) {
228  weights[i] = weight;
229  indices[i] = coarse_mloop[coarse_poly->loopstart + i].v;
230  }
231  CustomData_interp(&coarse_mesh->vdata,
232  &vertex_interpolation->vertex_data_storage,
233  indices,
234  weights,
235  NULL,
236  coarse_poly->totloop,
237  2);
238  }
239 }
240 
242  VerticesForInterpolation *vertex_interpolation,
243  const MPoly *coarse_poly,
244  const int corner)
245 {
246  if (coarse_poly->totloop == 4) {
247  /* Nothing to do, all indices and data is already assigned. */
248  }
249  else {
250  const CustomData *vertex_data = &ctx->coarse_mesh->vdata;
251  const Mesh *coarse_mesh = ctx->coarse_mesh;
252  const MLoop *coarse_mloop = coarse_mesh->mloop;
253  LoopsOfPtex loops_of_ptex;
254  loops_of_ptex_get(ctx, &loops_of_ptex, coarse_poly, corner);
255  /* Ptex face corner corresponds to a poly loop with same index. */
256  CustomData_copy_data(vertex_data,
257  &vertex_interpolation->vertex_data_storage,
258  coarse_mloop[coarse_poly->loopstart + corner].v,
259  0,
260  1);
261  /* Interpolate remaining ptex face corners, which hits loops
262  * middle points.
263  *
264  * TODO(sergey): Re-use one of interpolation results from previous
265  * iteration. */
266  const float weights[2] = {0.5f, 0.5f};
267  const int first_loop_index = loops_of_ptex.first_loop - coarse_mloop;
268  const int last_loop_index = loops_of_ptex.last_loop - coarse_mloop;
269  const int first_indices[2] = {
270  coarse_mloop[first_loop_index].v,
271  coarse_mloop[coarse_poly->loopstart +
272  (first_loop_index - coarse_poly->loopstart + 1) % coarse_poly->totloop]
273  .v};
274  const int last_indices[2] = {
275  coarse_mloop[first_loop_index].v,
276  coarse_mloop[last_loop_index].v,
277  };
278  CustomData_interp(vertex_data,
279  &vertex_interpolation->vertex_data_storage,
280  first_indices,
281  weights,
282  NULL,
283  2,
284  1);
285  CustomData_interp(vertex_data,
286  &vertex_interpolation->vertex_data_storage,
287  last_indices,
288  weights,
289  NULL,
290  2,
291  3);
292  }
293 }
294 
295 static void vertex_interpolation_end(VerticesForInterpolation *vertex_interpolation)
296 {
297  if (vertex_interpolation->vertex_data_storage_allocated) {
298  CustomData_free(&vertex_interpolation->vertex_data_storage, 4);
299  }
300 }
301 
304 /* -------------------------------------------------------------------- */
308 typedef struct LoopsForInterpolation {
309  /* This field points to a loop data which is to be used for interpolation.
310  * The idea is to avoid unnecessary allocations for regular faces, where
311  * we can simply interpolate corner vertices. */
313  /* Loops data calculated for ptex corners. There are always 4 elements
314  * in this custom data, aligned the following way:
315  *
316  * index 0 -> uv (0, 0)
317  * index 1 -> uv (0, 1)
318  * index 2 -> uv (1, 1)
319  * index 3 -> uv (1, 0)
320  *
321  * Is allocated for non-regular faces (triangles and n-gons). */
324  /* Infices within loop_data to interpolate for. The indices are aligned with
325  * uv coordinates in a similar way as indices in loop_data_storage. */
326  int loop_indices[4];
328 
330  LoopsForInterpolation *loop_interpolation,
331  const MPoly *coarse_poly)
332 {
333  const Mesh *coarse_mesh = ctx->coarse_mesh;
334  if (coarse_poly->totloop == 4) {
335  loop_interpolation->loop_data = &coarse_mesh->ldata;
336  loop_interpolation->loop_indices[0] = coarse_poly->loopstart + 0;
337  loop_interpolation->loop_indices[1] = coarse_poly->loopstart + 1;
338  loop_interpolation->loop_indices[2] = coarse_poly->loopstart + 2;
339  loop_interpolation->loop_indices[3] = coarse_poly->loopstart + 3;
340  loop_interpolation->loop_data_storage_allocated = false;
341  }
342  else {
343  loop_interpolation->loop_data = &loop_interpolation->loop_data_storage;
344  /* Allocate storage for loops corresponding to ptex corners. */
346  &loop_interpolation->loop_data_storage,
348  CD_CALLOC,
349  4);
350  /* Initialize indices. */
351  loop_interpolation->loop_indices[0] = 0;
352  loop_interpolation->loop_indices[1] = 1;
353  loop_interpolation->loop_indices[2] = 2;
354  loop_interpolation->loop_indices[3] = 3;
355  loop_interpolation->loop_data_storage_allocated = true;
356  /* Interpolate center of poly right away, it stays unchanged for all
357  * ptex faces. */
358  const float weight = 1.0f / (float)coarse_poly->totloop;
359  float *weights = BLI_array_alloca(weights, coarse_poly->totloop);
360  int *indices = BLI_array_alloca(indices, coarse_poly->totloop);
361  for (int i = 0; i < coarse_poly->totloop; i++) {
362  weights[i] = weight;
363  indices[i] = coarse_poly->loopstart + i;
364  }
365  CustomData_interp(&coarse_mesh->ldata,
366  &loop_interpolation->loop_data_storage,
367  indices,
368  weights,
369  NULL,
370  coarse_poly->totloop,
371  2);
372  }
373 }
374 
376  LoopsForInterpolation *loop_interpolation,
377  const MPoly *coarse_poly,
378  const int corner)
379 {
380  if (coarse_poly->totloop == 4) {
381  /* Nothing to do, all indices and data is already assigned. */
382  }
383  else {
384  const CustomData *loop_data = &ctx->coarse_mesh->ldata;
385  const Mesh *coarse_mesh = ctx->coarse_mesh;
386  const MLoop *coarse_mloop = coarse_mesh->mloop;
387  LoopsOfPtex loops_of_ptex;
388  loops_of_ptex_get(ctx, &loops_of_ptex, coarse_poly, corner);
389  /* Ptex face corner corresponds to a poly loop with same index. */
390  CustomData_free_elem(&loop_interpolation->loop_data_storage, 0, 1);
392  loop_data, &loop_interpolation->loop_data_storage, coarse_poly->loopstart + corner, 0, 1);
393  /* Interpolate remaining ptex face corners, which hits loops
394  * middle points.
395  *
396  * TODO(sergey): Re-use one of interpolation results from previous
397  * iteration. */
398  const float weights[2] = {0.5f, 0.5f};
399  const int base_loop_index = coarse_poly->loopstart;
400  const int first_loop_index = loops_of_ptex.first_loop - coarse_mloop;
401  const int second_loop_index = base_loop_index +
402  (first_loop_index - base_loop_index + 1) % coarse_poly->totloop;
403  const int first_indices[2] = {first_loop_index, second_loop_index};
404  const int last_indices[2] = {
405  loops_of_ptex.last_loop - coarse_mloop,
406  loops_of_ptex.first_loop - coarse_mloop,
407  };
409  loop_data, &loop_interpolation->loop_data_storage, first_indices, weights, NULL, 2, 1);
411  loop_data, &loop_interpolation->loop_data_storage, last_indices, weights, NULL, 2, 3);
412  }
413 }
414 
415 static void loop_interpolation_end(LoopsForInterpolation *loop_interpolation)
416 {
417  if (loop_interpolation->loop_data_storage_allocated) {
418  CustomData_free(&loop_interpolation->loop_data_storage, 4);
419  }
420 }
421 
424 /* -------------------------------------------------------------------- */
428 typedef struct SubdivMeshTLS {
433 
439 
440 static void subdiv_mesh_tls_free(void *tls_v)
441 {
442  SubdivMeshTLS *tls = tls_v;
445  }
448  }
449 }
450 
453 /* -------------------------------------------------------------------- */
458  const int ptex_face_index,
459  const float u,
460  const float v,
461  float r_P[3],
462  short r_N[3])
463 {
464  if (subdiv->displacement_evaluator == NULL) {
465  BKE_subdiv_eval_limit_point_and_short_normal(subdiv, ptex_face_index, u, v, r_P, r_N);
466  }
467  else {
468  BKE_subdiv_eval_final_point(subdiv, ptex_face_index, u, v, r_P);
469  }
470 }
471 
474 /* -------------------------------------------------------------------- */
479  const int ptex_face_index,
480  const float u,
481  const float v,
482  MVert *subdiv_vert)
483 {
484  Subdiv *subdiv = ctx->subdiv;
485  const int subdiv_vertex_index = subdiv_vert - ctx->subdiv_mesh->mvert;
486  float dummy_P[3], dPdu[3], dPdv[3], D[3];
487  BKE_subdiv_eval_limit_point_and_derivatives(subdiv, ptex_face_index, u, v, dummy_P, dPdu, dPdv);
488  /* Accumulate normal. */
489  if (ctx->can_evaluate_normals) {
490  float N[3];
491  cross_v3_v3v3(N, dPdu, dPdv);
492  normalize_v3(N);
493  add_v3_v3(ctx->accumulated_normals[subdiv_vertex_index], N);
494  }
495  /* Accumulate displacement if needed. */
496  if (ctx->have_displacement) {
497  /* NOTE: The subdivided mesh is allocated in this module, and its vertices are kept at zero
498  * locations as a default calloc(). */
499  BKE_subdiv_eval_displacement(subdiv, ptex_face_index, u, v, dPdu, dPdv, D);
500  add_v3_v3(subdiv_vert->co, D);
501  }
502  if (ctx->accumulated_counters) {
503  ++ctx->accumulated_counters[subdiv_vertex_index];
504  }
505 }
506 
509 /* -------------------------------------------------------------------- */
513 static bool subdiv_mesh_topology_info(const SubdivForeachContext *foreach_context,
514  const int num_vertices,
515  const int num_edges,
516  const int num_loops,
517  const int num_polygons)
518 {
519  /* Multires grid data will be applied or become invalid after subdivision,
520  * so don't try to preserve it and use memory. */
522  mask.lmask &= ~CD_MASK_MULTIRES_GRIDS;
523 
524  SubdivMeshContext *subdiv_context = foreach_context->user_data;
526  subdiv_context->coarse_mesh, num_vertices, num_edges, 0, num_loops, num_polygons, mask);
528  subdiv_mesh_prepare_accumulator(subdiv_context, num_vertices);
529  return true;
530 }
531 
534 /* -------------------------------------------------------------------- */
539  const MVert *coarse_vertex,
540  MVert *subdiv_vertex)
541 {
542  const Mesh *coarse_mesh = ctx->coarse_mesh;
543  Mesh *subdiv_mesh = ctx->subdiv_mesh;
544  const int coarse_vertex_index = coarse_vertex - coarse_mesh->mvert;
545  const int subdiv_vertex_index = subdiv_vertex - subdiv_mesh->mvert;
547  &coarse_mesh->vdata, &ctx->subdiv_mesh->vdata, coarse_vertex_index, subdiv_vertex_index, 1);
548 }
549 
551  MVert *subdiv_vertex,
552  const VerticesForInterpolation *vertex_interpolation,
553  const float u,
554  const float v)
555 {
556  const int subdiv_vertex_index = subdiv_vertex - ctx->subdiv_mesh->mvert;
557  const float weights[4] = {(1.0f - u) * (1.0f - v), u * (1.0f - v), u * v, (1.0f - u) * v};
558  CustomData_interp(vertex_interpolation->vertex_data,
559  &ctx->subdiv_mesh->vdata,
560  vertex_interpolation->vertex_indices,
561  weights,
562  NULL,
563  4,
564  subdiv_vertex_index);
565  if (ctx->vert_origindex != NULL) {
566  ctx->vert_origindex[subdiv_vertex_index] = ORIGINDEX_NONE;
567  }
568 }
569 
571  const int ptex_face_index,
572  const float u,
573  const float v,
574  const MVert *coarse_vert,
575  MVert *subdiv_vert)
576 {
577  const int subdiv_vertex_index = subdiv_vert - ctx->subdiv_mesh->mvert;
578  /* Displacement is accumulated in subdiv vertex position.
579  * Needs to be backed up before copying data from original vertex. */
580  float D[3] = {0.0f, 0.0f, 0.0f};
581  if (ctx->have_displacement) {
582  const float inv_num_accumulated = 1.0f / ctx->accumulated_counters[subdiv_vertex_index];
583  copy_v3_v3(D, subdiv_vert->co);
584  mul_v3_fl(D, inv_num_accumulated);
585  }
586  /* Copy custom data and evaluate position. */
587  subdiv_vertex_data_copy(ctx, coarse_vert, subdiv_vert);
588  BKE_subdiv_eval_limit_point(ctx->subdiv, ptex_face_index, u, v, subdiv_vert->co);
589  /* Apply displacement. */
590  add_v3_v3(subdiv_vert->co, D);
591  /* Copy normal from accumulated storage. */
592  if (ctx->can_evaluate_normals) {
593  float N[3];
594  copy_v3_v3(N, ctx->accumulated_normals[subdiv_vertex_index]);
595  normalize_v3(N);
596  normal_float_to_short_v3(subdiv_vert->no, N);
597  }
598  /* Remove facedot flag. This can happen if there is more than one subsurf modifier. */
599  subdiv_vert->flag &= ~ME_VERT_FACEDOT;
600 }
601 
603  const SubdivMeshContext *ctx,
604  const int ptex_face_index,
605  const float u,
606  const float v,
607  VerticesForInterpolation *vertex_interpolation,
608  MVert *subdiv_vert)
609 {
610  const int subdiv_vertex_index = subdiv_vert - ctx->subdiv_mesh->mvert;
611  /* Displacement is accumulated in subdiv vertex position.
612  * Needs to be backed up before copying data from original vertex. */
613  float D[3] = {0.0f, 0.0f, 0.0f};
614  if (ctx->have_displacement) {
615  const float inv_num_accumulated = 1.0f / ctx->accumulated_counters[subdiv_vertex_index];
616  copy_v3_v3(D, subdiv_vert->co);
617  mul_v3_fl(D, inv_num_accumulated);
618  }
619  /* Interpolate custom data and evaluate position. */
620  subdiv_vertex_data_interpolate(ctx, subdiv_vert, vertex_interpolation, u, v);
621  BKE_subdiv_eval_limit_point(ctx->subdiv, ptex_face_index, u, v, subdiv_vert->co);
622  /* Apply displacement. */
623  add_v3_v3(subdiv_vert->co, D);
624  /* Copy normal from accumulated storage. */
625  if (ctx->can_evaluate_normals) {
626  const float inv_num_accumulated = 1.0f / ctx->accumulated_counters[subdiv_vertex_index];
627  float N[3];
628  copy_v3_v3(N, ctx->accumulated_normals[subdiv_vertex_index]);
629  mul_v3_fl(N, inv_num_accumulated);
630  normalize_v3(N);
631  normal_float_to_short_v3(subdiv_vert->no, N);
632  }
633 }
634 
636  void *UNUSED(tls),
637  const int ptex_face_index,
638  const float u,
639  const float v,
640  const int subdiv_vertex_index)
641 {
642  SubdivMeshContext *ctx = foreach_context->user_data;
643  Mesh *subdiv_mesh = ctx->subdiv_mesh;
644  MVert *subdiv_mvert = subdiv_mesh->mvert;
645  MVert *subdiv_vert = &subdiv_mvert[subdiv_vertex_index];
646  subdiv_accumulate_vertex_normal_and_displacement(ctx, ptex_face_index, u, v, subdiv_vert);
647 }
648 
649 static void subdiv_mesh_vertex_every_corner(const SubdivForeachContext *foreach_context,
650  void *tls,
651  const int ptex_face_index,
652  const float u,
653  const float v,
654  const int UNUSED(coarse_vertex_index),
655  const int UNUSED(coarse_poly_index),
656  const int UNUSED(coarse_corner),
657  const int subdiv_vertex_index)
658 {
660  foreach_context, tls, ptex_face_index, u, v, subdiv_vertex_index);
661 }
662 
663 static void subdiv_mesh_vertex_every_edge(const SubdivForeachContext *foreach_context,
664  void *tls,
665  const int ptex_face_index,
666  const float u,
667  const float v,
668  const int UNUSED(coarse_edge_index),
669  const int UNUSED(coarse_poly_index),
670  const int UNUSED(coarse_corner),
671  const int subdiv_vertex_index)
672 {
674  foreach_context, tls, ptex_face_index, u, v, subdiv_vertex_index);
675 }
676 
677 static void subdiv_mesh_vertex_corner(const SubdivForeachContext *foreach_context,
678  void *UNUSED(tls),
679  const int ptex_face_index,
680  const float u,
681  const float v,
682  const int coarse_vertex_index,
683  const int UNUSED(coarse_poly_index),
684  const int UNUSED(coarse_corner),
685  const int subdiv_vertex_index)
686 {
687  BLI_assert(coarse_vertex_index != ORIGINDEX_NONE);
688  SubdivMeshContext *ctx = foreach_context->user_data;
689  const Mesh *coarse_mesh = ctx->coarse_mesh;
690  const MVert *coarse_mvert = coarse_mesh->mvert;
691  Mesh *subdiv_mesh = ctx->subdiv_mesh;
692  MVert *subdiv_mvert = subdiv_mesh->mvert;
693  const MVert *coarse_vert = &coarse_mvert[coarse_vertex_index];
694  MVert *subdiv_vert = &subdiv_mvert[subdiv_vertex_index];
696  ctx, ptex_face_index, u, v, coarse_vert, subdiv_vert);
697 }
698 
700  SubdivMeshTLS *tls,
701  const MPoly *coarse_poly,
702  const int coarse_corner)
703 {
704  /* Check whether we've moved to another corner or polygon. */
706  if (tls->vertex_interpolation_coarse_poly != coarse_poly ||
707  tls->vertex_interpolation_coarse_corner != coarse_corner) {
710  }
711  }
712  /* Initialize the interpolation. */
714  vertex_interpolation_init(ctx, &tls->vertex_interpolation, coarse_poly);
715  }
716  /* Update it for a new corner if needed. */
718  tls->vertex_interpolation_coarse_corner != coarse_corner) {
719  vertex_interpolation_from_corner(ctx, &tls->vertex_interpolation, coarse_poly, coarse_corner);
720  }
721  /* Store settings used for the current state of interpolator. */
723  tls->vertex_interpolation_coarse_poly = coarse_poly;
724  tls->vertex_interpolation_coarse_corner = coarse_corner;
725 }
726 
727 static void subdiv_mesh_vertex_edge(const SubdivForeachContext *foreach_context,
728  void *tls_v,
729  const int ptex_face_index,
730  const float u,
731  const float v,
732  const int UNUSED(coarse_edge_index),
733  const int coarse_poly_index,
734  const int coarse_corner,
735  const int subdiv_vertex_index)
736 {
737  SubdivMeshContext *ctx = foreach_context->user_data;
738  SubdivMeshTLS *tls = tls_v;
739  const Mesh *coarse_mesh = ctx->coarse_mesh;
740  const MPoly *coarse_mpoly = coarse_mesh->mpoly;
741  const MPoly *coarse_poly = &coarse_mpoly[coarse_poly_index];
742  Mesh *subdiv_mesh = ctx->subdiv_mesh;
743  MVert *subdiv_mvert = subdiv_mesh->mvert;
744  MVert *subdiv_vert = &subdiv_mvert[subdiv_vertex_index];
745  subdiv_mesh_ensure_vertex_interpolation(ctx, tls, coarse_poly, coarse_corner);
747  ctx, ptex_face_index, u, v, &tls->vertex_interpolation, subdiv_vert);
748 }
749 
750 static bool subdiv_mesh_is_center_vertex(const MPoly *coarse_poly, const float u, const float v)
751 {
752  if (coarse_poly->totloop == 4) {
753  if (u == 0.5f && v == 0.5f) {
754  return true;
755  }
756  }
757  else {
758  if (u == 1.0f && v == 1.0f) {
759  return true;
760  }
761  }
762  return false;
763 }
764 
765 static void subdiv_mesh_tag_center_vertex(const MPoly *coarse_poly,
766  MVert *subdiv_vert,
767  const float u,
768  const float v)
769 {
770  if (subdiv_mesh_is_center_vertex(coarse_poly, u, v)) {
771  subdiv_vert->flag |= ME_VERT_FACEDOT;
772  }
773 }
774 
775 static void subdiv_mesh_vertex_inner(const SubdivForeachContext *foreach_context,
776  void *tls_v,
777  const int ptex_face_index,
778  const float u,
779  const float v,
780  const int coarse_poly_index,
781  const int coarse_corner,
782  const int subdiv_vertex_index)
783 {
784  SubdivMeshContext *ctx = foreach_context->user_data;
785  SubdivMeshTLS *tls = tls_v;
786  Subdiv *subdiv = ctx->subdiv;
787  const Mesh *coarse_mesh = ctx->coarse_mesh;
788  const MPoly *coarse_mpoly = coarse_mesh->mpoly;
789  const MPoly *coarse_poly = &coarse_mpoly[coarse_poly_index];
790  Mesh *subdiv_mesh = ctx->subdiv_mesh;
791  MVert *subdiv_mvert = subdiv_mesh->mvert;
792  MVert *subdiv_vert = &subdiv_mvert[subdiv_vertex_index];
793  subdiv_mesh_ensure_vertex_interpolation(ctx, tls, coarse_poly, coarse_corner);
794  subdiv_vertex_data_interpolate(ctx, subdiv_vert, &tls->vertex_interpolation, u, v);
796  subdiv, ptex_face_index, u, v, subdiv_vert->co, subdiv_vert->no);
797  subdiv_mesh_tag_center_vertex(coarse_poly, subdiv_vert, u, v);
798 }
799 
802 /* -------------------------------------------------------------------- */
807  MEdge *subdiv_edge,
808  const MEdge *coarse_edge)
809 {
810  const int subdiv_edge_index = subdiv_edge - ctx->subdiv_mesh->medge;
811  if (coarse_edge == NULL) {
812  subdiv_edge->crease = 0;
813  subdiv_edge->bweight = 0;
814  subdiv_edge->flag = 0;
815  if (!ctx->settings->use_optimal_display) {
816  subdiv_edge->flag |= ME_EDGERENDER;
817  }
818  if (ctx->edge_origindex != NULL) {
819  ctx->edge_origindex[subdiv_edge_index] = ORIGINDEX_NONE;
820  }
821  return;
822  }
823  const int coarse_edge_index = coarse_edge - ctx->coarse_mesh->medge;
825  &ctx->coarse_mesh->edata, &ctx->subdiv_mesh->edata, coarse_edge_index, subdiv_edge_index, 1);
826  subdiv_edge->flag |= ME_EDGERENDER;
827 }
828 
829 static void subdiv_mesh_edge(const SubdivForeachContext *foreach_context,
830  void *UNUSED(tls),
831  const int coarse_edge_index,
832  const int subdiv_edge_index,
833  const int subdiv_v1,
834  const int subdiv_v2)
835 {
836  SubdivMeshContext *ctx = foreach_context->user_data;
837  Mesh *subdiv_mesh = ctx->subdiv_mesh;
838  MEdge *subdiv_medge = subdiv_mesh->medge;
839  MEdge *subdiv_edge = &subdiv_medge[subdiv_edge_index];
840  const MEdge *coarse_edge = NULL;
841  if (coarse_edge_index != ORIGINDEX_NONE) {
842  const Mesh *coarse_mesh = ctx->coarse_mesh;
843  const MEdge *coarse_medge = coarse_mesh->medge;
844  coarse_edge = &coarse_medge[coarse_edge_index];
845  }
846  subdiv_copy_edge_data(ctx, subdiv_edge, coarse_edge);
847  subdiv_edge->v1 = subdiv_v1;
848  subdiv_edge->v2 = subdiv_v2;
849 }
850 
853 /* -------------------------------------------------------------------- */
858  MLoop *subdiv_loop,
859  const LoopsForInterpolation *loop_interpolation,
860  const float u,
861  const float v)
862 {
863  const int subdiv_loop_index = subdiv_loop - ctx->subdiv_mesh->mloop;
864  const float weights[4] = {(1.0f - u) * (1.0f - v), u * (1.0f - v), u * v, (1.0f - u) * v};
865  CustomData_interp(loop_interpolation->loop_data,
866  &ctx->subdiv_mesh->ldata,
867  loop_interpolation->loop_indices,
868  weights,
869  NULL,
870  4,
871  subdiv_loop_index);
872  /* TODO(sergey): Set ORIGINDEX. */
873 }
874 
876  MLoop *subdiv_loop,
877  const int ptex_face_index,
878  const float u,
879  const float v)
880 {
881  if (ctx->num_uv_layers == 0) {
882  return;
883  }
884  Subdiv *subdiv = ctx->subdiv;
885  const int mloop_index = subdiv_loop - ctx->subdiv_mesh->mloop;
886  for (int layer_index = 0; layer_index < ctx->num_uv_layers; layer_index++) {
887  MLoopUV *subdiv_loopuv = &ctx->uv_layers[layer_index][mloop_index];
888  BKE_subdiv_eval_face_varying(subdiv, layer_index, ptex_face_index, u, v, subdiv_loopuv->uv);
889  }
890 }
891 
893  SubdivMeshTLS *tls,
894  const MPoly *coarse_poly,
895  const int coarse_corner)
896 {
897  /* Check whether we've moved to another corner or polygon. */
899  if (tls->loop_interpolation_coarse_poly != coarse_poly ||
900  tls->loop_interpolation_coarse_corner != coarse_corner) {
902  tls->loop_interpolation_initialized = false;
903  }
904  }
905  /* Initialize the interpolation. */
906  if (!tls->loop_interpolation_initialized) {
907  loop_interpolation_init(ctx, &tls->loop_interpolation, coarse_poly);
908  }
909  /* Update it for a new corner if needed. */
910  if (!tls->loop_interpolation_initialized ||
911  tls->loop_interpolation_coarse_corner != coarse_corner) {
912  loop_interpolation_from_corner(ctx, &tls->loop_interpolation, coarse_poly, coarse_corner);
913  }
914  /* Store settings used for the current state of interpolator. */
915  tls->loop_interpolation_initialized = true;
916  tls->loop_interpolation_coarse_poly = coarse_poly;
917  tls->loop_interpolation_coarse_corner = coarse_corner;
918 }
919 
920 static void subdiv_mesh_loop(const SubdivForeachContext *foreach_context,
921  void *tls_v,
922  const int ptex_face_index,
923  const float u,
924  const float v,
925  const int UNUSED(coarse_loop_index),
926  const int coarse_poly_index,
927  const int coarse_corner,
928  const int subdiv_loop_index,
929  const int subdiv_vertex_index,
930  const int subdiv_edge_index)
931 {
932  SubdivMeshContext *ctx = foreach_context->user_data;
933  SubdivMeshTLS *tls = tls_v;
934  const Mesh *coarse_mesh = ctx->coarse_mesh;
935  const MPoly *coarse_mpoly = coarse_mesh->mpoly;
936  const MPoly *coarse_poly = &coarse_mpoly[coarse_poly_index];
937  Mesh *subdiv_mesh = ctx->subdiv_mesh;
938  MLoop *subdiv_mloop = subdiv_mesh->mloop;
939  MLoop *subdiv_loop = &subdiv_mloop[subdiv_loop_index];
940  subdiv_mesh_ensure_loop_interpolation(ctx, tls, coarse_poly, coarse_corner);
941  subdiv_interpolate_loop_data(ctx, subdiv_loop, &tls->loop_interpolation, u, v);
942  subdiv_eval_uv_layer(ctx, subdiv_loop, ptex_face_index, u, v);
943  subdiv_loop->v = subdiv_vertex_index;
944  subdiv_loop->e = subdiv_edge_index;
945 }
946 
949 /* -------------------------------------------------------------------- */
954  MPoly *subdiv_poly,
955  const MPoly *coarse_poly)
956 {
957  const int coarse_poly_index = coarse_poly - ctx->coarse_mesh->mpoly;
958  const int subdiv_poly_index = subdiv_poly - ctx->subdiv_mesh->mpoly;
960  &ctx->coarse_mesh->pdata, &ctx->subdiv_mesh->pdata, coarse_poly_index, subdiv_poly_index, 1);
961 }
962 
963 static void subdiv_mesh_poly(const SubdivForeachContext *foreach_context,
964  void *UNUSED(tls),
965  const int coarse_poly_index,
966  const int subdiv_poly_index,
967  const int start_loop_index,
968  const int num_loops)
969 {
970  BLI_assert(coarse_poly_index != ORIGINDEX_NONE);
971  SubdivMeshContext *ctx = foreach_context->user_data;
972  const Mesh *coarse_mesh = ctx->coarse_mesh;
973  const MPoly *coarse_mpoly = coarse_mesh->mpoly;
974  const MPoly *coarse_poly = &coarse_mpoly[coarse_poly_index];
975  Mesh *subdiv_mesh = ctx->subdiv_mesh;
976  MPoly *subdiv_mpoly = subdiv_mesh->mpoly;
977  MPoly *subdiv_poly = &subdiv_mpoly[subdiv_poly_index];
978  subdiv_copy_poly_data(ctx, subdiv_poly, coarse_poly);
979  subdiv_poly->loopstart = start_loop_index;
980  subdiv_poly->totloop = num_loops;
981 }
982 
985 /* -------------------------------------------------------------------- */
989 static void subdiv_mesh_vertex_loose(const SubdivForeachContext *foreach_context,
990  void *UNUSED(tls),
991  const int coarse_vertex_index,
992  const int subdiv_vertex_index)
993 {
994  SubdivMeshContext *ctx = foreach_context->user_data;
995  const Mesh *coarse_mesh = ctx->coarse_mesh;
996  const MVert *coarse_mvert = coarse_mesh->mvert;
997  const MVert *coarse_vertex = &coarse_mvert[coarse_vertex_index];
998  Mesh *subdiv_mesh = ctx->subdiv_mesh;
999  MVert *subdiv_mvert = subdiv_mesh->mvert;
1000  MVert *subdiv_vertex = &subdiv_mvert[subdiv_vertex_index];
1001  subdiv_vertex_data_copy(ctx, coarse_vertex, subdiv_vertex);
1002 }
1003 
1004 /* Get neighbor edges of the given one.
1005  * - neighbors[0] is an edge adjacent to edge->v1.
1006  * - neighbors[1] is an edge adjacent to edge->v2. */
1008  const MEdge *edge,
1009  const MEdge *neighbors[2])
1010 {
1011  const Mesh *coarse_mesh = ctx->coarse_mesh;
1012  const MEdge *coarse_medge = coarse_mesh->medge;
1013  neighbors[0] = NULL;
1014  neighbors[1] = NULL;
1015  int neighbor_counters[2] = {0, 0};
1016  for (int edge_index = 0; edge_index < coarse_mesh->totedge; edge_index++) {
1017  const MEdge *current_edge = &coarse_medge[edge_index];
1018  if (current_edge == edge) {
1019  continue;
1020  }
1021  if (ELEM(edge->v1, current_edge->v1, current_edge->v2)) {
1022  neighbors[0] = current_edge;
1023  ++neighbor_counters[0];
1024  }
1025  if (ELEM(edge->v2, current_edge->v1, current_edge->v2)) {
1026  neighbors[1] = current_edge;
1027  ++neighbor_counters[1];
1028  }
1029  }
1030  /* Vertices which has more than one neighbor are considered infinitely
1031  * sharp. This is also how topology factory treats vertices of a surface
1032  * which are adjacent to a loose edge. */
1033  if (neighbor_counters[0] > 1) {
1034  neighbors[0] = NULL;
1035  }
1036  if (neighbor_counters[1] > 1) {
1037  neighbors[1] = NULL;
1038  }
1039 }
1040 
1042  const MEdge *coarse_edge,
1043  const MEdge *neighbors[2],
1044  float points_r[4][3])
1045 {
1046  const Mesh *coarse_mesh = ctx->coarse_mesh;
1047  const MVert *coarse_mvert = coarse_mesh->mvert;
1048  /* Middle points corresponds to the edge. */
1049  copy_v3_v3(points_r[1], coarse_mvert[coarse_edge->v1].co);
1050  copy_v3_v3(points_r[2], coarse_mvert[coarse_edge->v2].co);
1051  /* Start point, duplicate from edge start if no neighbor. */
1052  if (neighbors[0] != NULL) {
1053  if (neighbors[0]->v1 == coarse_edge->v1) {
1054  copy_v3_v3(points_r[0], coarse_mvert[neighbors[0]->v2].co);
1055  }
1056  else {
1057  copy_v3_v3(points_r[0], coarse_mvert[neighbors[0]->v1].co);
1058  }
1059  }
1060  else {
1061  sub_v3_v3v3(points_r[0], points_r[1], points_r[2]);
1062  add_v3_v3(points_r[0], points_r[1]);
1063  }
1064  /* End point, duplicate from edge end if no neighbor. */
1065  if (neighbors[1] != NULL) {
1066  if (neighbors[1]->v1 == coarse_edge->v2) {
1067  copy_v3_v3(points_r[3], coarse_mvert[neighbors[1]->v2].co);
1068  }
1069  else {
1070  copy_v3_v3(points_r[3], coarse_mvert[neighbors[1]->v1].co);
1071  }
1072  }
1073  else {
1074  sub_v3_v3v3(points_r[3], points_r[2], points_r[1]);
1075  add_v3_v3(points_r[3], points_r[2]);
1076  }
1077 }
1078 
1080  const MEdge *coarse_edge,
1081  const float u,
1082  const int subdiv_vertex_index)
1083 {
1084  const Mesh *coarse_mesh = ctx->coarse_mesh;
1085  Mesh *subdiv_mesh = ctx->subdiv_mesh;
1086  if (u == 0.0f) {
1088  &coarse_mesh->vdata, &subdiv_mesh->vdata, coarse_edge->v1, subdiv_vertex_index, 1);
1089  }
1090  else if (u == 1.0f) {
1092  &coarse_mesh->vdata, &subdiv_mesh->vdata, coarse_edge->v2, subdiv_vertex_index, 1);
1093  }
1094  else {
1095  BLI_assert(u > 0.0f);
1096  BLI_assert(u < 1.0f);
1097  const float interpolation_weights[2] = {1.0f - u, u};
1098  const int coarse_vertex_indices[2] = {coarse_edge->v1, coarse_edge->v2};
1099  CustomData_interp(&coarse_mesh->vdata,
1100  &subdiv_mesh->vdata,
1101  coarse_vertex_indices,
1102  interpolation_weights,
1103  NULL,
1104  2,
1105  subdiv_vertex_index);
1106  if (ctx->vert_origindex != NULL) {
1107  ctx->vert_origindex[subdiv_vertex_index] = ORIGINDEX_NONE;
1108  }
1109  }
1110 }
1111 
1112 static void subdiv_mesh_vertex_of_loose_edge(const struct SubdivForeachContext *foreach_context,
1113  void *UNUSED(tls),
1114  const int coarse_edge_index,
1115  const float u,
1116  const int subdiv_vertex_index)
1117 {
1118  SubdivMeshContext *ctx = foreach_context->user_data;
1119  const Mesh *coarse_mesh = ctx->coarse_mesh;
1120  const MEdge *coarse_edge = &coarse_mesh->medge[coarse_edge_index];
1121  Mesh *subdiv_mesh = ctx->subdiv_mesh;
1122  MVert *subdiv_mvert = subdiv_mesh->mvert;
1123  const bool is_simple = ctx->subdiv->settings.is_simple;
1124  /* Find neighbors of the current loose edge. */
1125  const MEdge *neighbors[2];
1126  find_edge_neighbors(ctx, coarse_edge, neighbors);
1127  /* Interpolate custom data. */
1128  subdiv_mesh_vertex_of_loose_edge_interpolate(ctx, coarse_edge, u, subdiv_vertex_index);
1129  /* Interpolate coordinate. */
1130  MVert *subdiv_vertex = &subdiv_mvert[subdiv_vertex_index];
1131  if (is_simple) {
1132  const MVert *coarse_mvert = coarse_mesh->mvert;
1133  const MVert *vert_1 = &coarse_mvert[coarse_edge->v1];
1134  const MVert *vert_2 = &coarse_mvert[coarse_edge->v2];
1135  interp_v3_v3v3(subdiv_vertex->co, vert_1->co, vert_2->co, u);
1136  }
1137  else {
1138  float points[4][3];
1139  points_for_loose_edges_interpolation_get(ctx, coarse_edge, neighbors, points);
1140  float weights[4];
1142  interp_v3_v3v3v3v3(subdiv_vertex->co, points[0], points[1], points[2], points[3], weights);
1143  }
1144  /* Reset flags and such. */
1145  subdiv_vertex->flag = 0;
1146  /* TODO(sergey): This matches old behavior, but we can as well interpolate
1147  * it. Maybe even using vertex varying attributes. */
1148  subdiv_vertex->bweight = 0.0f;
1149  /* Reset normal, initialize it in a similar way as edit mode does for a
1150  * vertices adjacent to a loose edges.
1151  * See `mesh_evaluate#mesh_calc_normals_vert_fallback` */
1152  float no[3];
1153  normalize_v3_v3(no, subdiv_vertex->co);
1154  normal_float_to_short_v3(subdiv_vertex->no, no);
1155 }
1156 
1159 /* -------------------------------------------------------------------- */
1163 static void setup_foreach_callbacks(const SubdivMeshContext *subdiv_context,
1164  SubdivForeachContext *foreach_context)
1165 {
1166  memset(foreach_context, 0, sizeof(*foreach_context));
1167  /* General information. */
1168  foreach_context->topology_info = subdiv_mesh_topology_info;
1169  /* Every boundary geometry. Used for displacement and normals averaging. */
1170  if (subdiv_context->can_evaluate_normals || subdiv_context->have_displacement) {
1173  }
1174  else {
1177  }
1178  foreach_context->vertex_corner = subdiv_mesh_vertex_corner;
1179  foreach_context->vertex_edge = subdiv_mesh_vertex_edge;
1180  foreach_context->vertex_inner = subdiv_mesh_vertex_inner;
1181  foreach_context->edge = subdiv_mesh_edge;
1182  foreach_context->loop = subdiv_mesh_loop;
1183  foreach_context->poly = subdiv_mesh_poly;
1184  foreach_context->vertex_loose = subdiv_mesh_vertex_loose;
1186  foreach_context->user_data_tls_free = subdiv_mesh_tls_free;
1187 }
1188 
1191 /* -------------------------------------------------------------------- */
1196  const SubdivToMeshSettings *settings,
1197  const Mesh *coarse_mesh)
1198 {
1200  /* Make sure evaluator is up to date with possible new topology, and that
1201  * it is refined for the new positions of coarse vertices. */
1202  if (!BKE_subdiv_eval_begin_from_mesh(subdiv, coarse_mesh, NULL)) {
1203  /* This could happen in two situations:
1204  * - OpenSubdiv is disabled.
1205  * - Something totally bad happened, and OpenSubdiv rejected our
1206  * topology.
1207  * In either way, we can't safely continue. */
1208  if (coarse_mesh->totpoly) {
1210  return NULL;
1211  }
1212  }
1213  /* Initialize subdivision mesh creation context. */
1214  SubdivMeshContext subdiv_context = {0};
1215  subdiv_context.settings = settings;
1216  subdiv_context.coarse_mesh = coarse_mesh;
1217  subdiv_context.subdiv = subdiv;
1218  subdiv_context.have_displacement = (subdiv->displacement_evaluator != NULL);
1219  subdiv_context.can_evaluate_normals = !subdiv_context.have_displacement &&
1220  subdiv_context.subdiv->settings.is_adaptive;
1221  /* Multi-threaded traversal/evaluation. */
1223  SubdivForeachContext foreach_context;
1224  setup_foreach_callbacks(&subdiv_context, &foreach_context);
1225  SubdivMeshTLS tls = {0};
1226  foreach_context.user_data = &subdiv_context;
1227  foreach_context.user_data_tls_size = sizeof(SubdivMeshTLS);
1228  foreach_context.user_data_tls = &tls;
1229  BKE_subdiv_foreach_subdiv_geometry(subdiv, &foreach_context, settings, coarse_mesh);
1231  Mesh *result = subdiv_context.subdiv_mesh;
1232  // BKE_mesh_validate(result, true, true);
1234  if (!subdiv_context.can_evaluate_normals) {
1235  result->runtime.cd_dirty_vert |= CD_MASK_NORMAL;
1236  }
1237  /* Free used memory. */
1238  subdiv_mesh_context_free(&subdiv_context);
1239  return result;
1240 }
1241 
typedef float(TangentPoint)[2]
CustomData interface, see also DNA_customdata_types.h.
const CustomData_MeshMasks CD_MASK_EVERYTHING
Definition: customdata.c:1986
void CustomData_free(struct CustomData *data, int totelem)
Definition: customdata.c:2239
int CustomData_number_of_layers(const struct CustomData *data, int type)
@ CD_CALLOC
void CustomData_interp(const struct CustomData *source, struct CustomData *dest, const int *src_indices, const float *weights, const float *sub_weights, int count, int dest_index)
#define ORIGINDEX_NONE
void * CustomData_get_layer_n(const struct CustomData *data, int type, int n)
void * CustomData_get_layer(const struct CustomData *data, int type)
void CustomData_free_elem(struct CustomData *data, int index, int count)
Definition: customdata.c:3004
void CustomData_copy(const struct CustomData *source, struct CustomData *dest, CustomDataMask mask, eCDAllocType alloctype, int totelem)
Definition: customdata.c:2193
void CustomData_copy_data(const struct CustomData *source, struct CustomData *dest, int source_index, int dest_index, int count)
void key_curve_position_weights(float t, float data[4], int type)
Definition: key.c:348
struct Mesh * BKE_mesh_new_nomain_from_template_ex(const struct Mesh *me_src, int verts_len, int edges_len, int tessface_len, int loops_len, int polys_len, struct CustomData_MeshMasks mask)
@ SUBDIV_STATS_SUBDIV_TO_MESH_GEOMETRY
Definition: BKE_subdiv.h:94
@ SUBDIV_STATS_SUBDIV_TO_MESH
Definition: BKE_subdiv.h:93
void BKE_subdiv_stats_end(SubdivStats *stats, eSubdivStatsValue value)
Definition: subdiv_stats.c:47
void BKE_subdiv_stats_begin(SubdivStats *stats, eSubdivStatsValue value)
Definition: subdiv_stats.c:42
void BKE_subdiv_eval_limit_point_and_short_normal(struct Subdiv *subdiv, const int ptex_face_index, const float u, const float v, float r_P[3], short r_N[3])
Definition: subdiv_eval.c:224
void BKE_subdiv_eval_limit_point(struct Subdiv *subdiv, const int ptex_face_index, const float u, const float v, float r_P[3])
Definition: subdiv_eval.c:171
void BKE_subdiv_eval_displacement(struct Subdiv *subdiv, const int ptex_face_index, const float u, const float v, const float dPdu[3], const float dPdv[3], float r_D[3])
Definition: subdiv_eval.c:247
bool BKE_subdiv_eval_begin_from_mesh(struct Subdiv *subdiv, const struct Mesh *mesh, const float(*coarse_vertex_cos)[3])
void BKE_subdiv_eval_limit_point_and_derivatives(struct Subdiv *subdiv, const int ptex_face_index, const float u, const float v, float r_P[3], float r_dPdu[3], float r_dPdv[3])
Definition: subdiv_eval.c:177
void BKE_subdiv_eval_final_point(struct Subdiv *subdiv, const int ptex_face_index, const float u, const float v, float r_P[3])
Definition: subdiv_eval.c:263
void BKE_subdiv_eval_face_varying(struct Subdiv *subdiv, const int face_varying_channel, const int ptex_face_index, const float u, const float v, float r_face_varying[2])
Definition: subdiv_eval.c:236
bool BKE_subdiv_foreach_subdiv_geometry(struct Subdiv *subdiv, const struct SubdivForeachContext *context, const struct SubdivToMeshSettings *mesh_settings, const struct Mesh *coarse_mesh)
#define BLI_array_alloca(arr, realsize)
Definition: BLI_alloca.h:36
#define BLI_assert(a)
Definition: BLI_assert.h:58
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], const float t)
Definition: math_vector.c:49
MINLINE void normal_float_to_short_v3(short r[3], const float n[3])
MINLINE float normalize_v3(float r[3])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
void interp_v3_v3v3v3v3(float p[3], const float v1[3], const float v2[3], const float v3[3], const float v4[3], const float w[4])
Definition: math_vector.c:201
MINLINE float normalize_v3_v3(float r[3], const float a[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
#define UNUSED(x)
#define ELEM(...)
#define CD_MASK_NORMAL
@ CD_ORIGINDEX
@ CD_MLOOPUV
#define CD_MASK_MULTIRES_GRIDS
#define MAX_MTFACE
@ KEY_BSPLINE
@ ME_VERT_FACEDOT
@ ME_EDGERENDER
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
Provides wrapper around system-specific atomic primitives, and some extensions (faked-atomic operatio...
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert * v
static ushort indices[]
void *(* MEM_calloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:46
params N
const CustomData * loop_data
Definition: subdiv_mesh.c:312
CustomData loop_data_storage
Definition: subdiv_mesh.c:322
const MLoop * third_loop
Definition: subdiv_mesh.c:135
const MLoop * second_loop
Definition: subdiv_mesh.c:134
const MLoop * last_loop
Definition: subdiv_mesh.c:132
const MLoop * first_loop
Definition: subdiv_mesh.c:130
unsigned int v1
unsigned int v2
unsigned int e
unsigned int v
float co[3]
short no[3]
struct MEdge * medge
struct CustomData pdata ldata
struct MVert * mvert
int totedge
struct MLoop * mloop
int totpoly
struct MPoly * mpoly
SubdivForeachVertexFromEdgeCb vertex_every_edge
SubdivForeachPolygonCb poly
SubdivForeachTopologyInformationCb topology_info
SubdivForeachLooseCb vertex_loose
SubdivForeachVertexInnerCb vertex_inner
SubdivForeachVertexOfLooseEdgeCb vertex_of_loose_edge
SubdivForeachEdgeCb edge
void(* user_data_tls_free)(void *tls)
SubdivForeachVertexFromEdgeCb vertex_edge
SubdivForeachVertexFromCornerCb vertex_corner
SubdivForeachVertexFromCornerCb vertex_every_corner
SubdivForeachLoopCb loop
const Mesh * coarse_mesh
Definition: subdiv_mesh.c:50
int * accumulated_counters
Definition: subdiv_mesh.c:74
const SubdivToMeshSettings * settings
Definition: subdiv_mesh.c:49
bool can_evaluate_normals
Definition: subdiv_mesh.c:77
MLoopUV * uv_layers[MAX_MTFACE]
Definition: subdiv_mesh.c:60
float(* accumulated_normals)[3]
Definition: subdiv_mesh.c:72
const MPoly * loop_interpolation_coarse_poly
Definition: subdiv_mesh.c:436
VerticesForInterpolation vertex_interpolation
Definition: subdiv_mesh.c:430
int loop_interpolation_coarse_corner
Definition: subdiv_mesh.c:437
bool loop_interpolation_initialized
Definition: subdiv_mesh.c:434
bool vertex_interpolation_initialized
Definition: subdiv_mesh.c:429
const MPoly * vertex_interpolation_coarse_poly
Definition: subdiv_mesh.c:431
int vertex_interpolation_coarse_corner
Definition: subdiv_mesh.c:432
LoopsForInterpolation loop_interpolation
Definition: subdiv_mesh.c:435
bool is_adaptive
Definition: BKE_subdiv.h:76
SubdivSettings settings
Definition: BKE_subdiv.h:176
SubdivStats stats
Definition: BKE_subdiv.h:186
struct SubdivDisplacement * displacement_evaluator
Definition: BKE_subdiv.h:184
CustomData vertex_data_storage
Definition: subdiv_mesh.c:187
const CustomData * vertex_data
Definition: subdiv_mesh.c:177
static void subdiv_vertex_data_interpolate(const SubdivMeshContext *ctx, MVert *subdiv_vertex, const VerticesForInterpolation *vertex_interpolation, const float u, const float v)
Definition: subdiv_mesh.c:550
static void subdiv_mesh_loop(const SubdivForeachContext *foreach_context, void *tls_v, const int ptex_face_index, const float u, const float v, const int UNUSED(coarse_loop_index), const int coarse_poly_index, const int coarse_corner, const int subdiv_loop_index, const int subdiv_vertex_index, const int subdiv_edge_index)
Definition: subdiv_mesh.c:920
static void loop_interpolation_init(const SubdivMeshContext *ctx, LoopsForInterpolation *loop_interpolation, const MPoly *coarse_poly)
Definition: subdiv_mesh.c:329
static void subdiv_mesh_vertex_corner(const SubdivForeachContext *foreach_context, void *UNUSED(tls), const int ptex_face_index, const float u, const float v, const int coarse_vertex_index, const int UNUSED(coarse_poly_index), const int UNUSED(coarse_corner), const int subdiv_vertex_index)
Definition: subdiv_mesh.c:677
static void evaluate_vertex_and_apply_displacement_copy(const SubdivMeshContext *ctx, const int ptex_face_index, const float u, const float v, const MVert *coarse_vert, MVert *subdiv_vert)
Definition: subdiv_mesh.c:570
struct SubdivMeshTLS SubdivMeshTLS
static void subdiv_mesh_vertex_of_loose_edge(const struct SubdivForeachContext *foreach_context, void *UNUSED(tls), const int coarse_edge_index, const float u, const int subdiv_vertex_index)
Definition: subdiv_mesh.c:1112
static void loops_of_ptex_get(const SubdivMeshContext *ctx, LoopsOfPtex *loops_of_ptex, const MPoly *coarse_poly, const int ptex_of_poly_index)
Definition: subdiv_mesh.c:138
static void vertex_interpolation_from_corner(const SubdivMeshContext *ctx, VerticesForInterpolation *vertex_interpolation, const MPoly *coarse_poly, const int corner)
Definition: subdiv_mesh.c:241
struct VerticesForInterpolation VerticesForInterpolation
static void subdiv_copy_poly_data(const SubdivMeshContext *ctx, MPoly *subdiv_poly, const MPoly *coarse_poly)
Definition: subdiv_mesh.c:953
static void find_edge_neighbors(const SubdivMeshContext *ctx, const MEdge *edge, const MEdge *neighbors[2])
Definition: subdiv_mesh.c:1007
static void subdiv_mesh_context_free(SubdivMeshContext *ctx)
Definition: subdiv_mesh.c:116
static bool subdiv_mesh_is_center_vertex(const MPoly *coarse_poly, const float u, const float v)
Definition: subdiv_mesh.c:750
static void loop_interpolation_end(LoopsForInterpolation *loop_interpolation)
Definition: subdiv_mesh.c:415
static void subdiv_mesh_vertex_every_corner(const SubdivForeachContext *foreach_context, void *tls, const int ptex_face_index, const float u, const float v, const int UNUSED(coarse_vertex_index), const int UNUSED(coarse_poly_index), const int UNUSED(coarse_corner), const int subdiv_vertex_index)
Definition: subdiv_mesh.c:649
static void subdiv_mesh_edge(const SubdivForeachContext *foreach_context, void *UNUSED(tls), const int coarse_edge_index, const int subdiv_edge_index, const int subdiv_v1, const int subdiv_v2)
Definition: subdiv_mesh.c:829
struct LoopsOfPtex LoopsOfPtex
static void subdiv_interpolate_loop_data(const SubdivMeshContext *ctx, MLoop *subdiv_loop, const LoopsForInterpolation *loop_interpolation, const float u, const float v)
Definition: subdiv_mesh.c:857
static void subdiv_mesh_vertex_every_edge(const SubdivForeachContext *foreach_context, void *tls, const int ptex_face_index, const float u, const float v, const int UNUSED(coarse_edge_index), const int UNUSED(coarse_poly_index), const int UNUSED(coarse_corner), const int subdiv_vertex_index)
Definition: subdiv_mesh.c:663
static void setup_foreach_callbacks(const SubdivMeshContext *subdiv_context, SubdivForeachContext *foreach_context)
Definition: subdiv_mesh.c:1163
static void subdiv_mesh_tag_center_vertex(const MPoly *coarse_poly, MVert *subdiv_vert, const float u, const float v)
Definition: subdiv_mesh.c:765
static void subdiv_mesh_ensure_vertex_interpolation(SubdivMeshContext *ctx, SubdivMeshTLS *tls, const MPoly *coarse_poly, const int coarse_corner)
Definition: subdiv_mesh.c:699
static void subdiv_mesh_tls_free(void *tls_v)
Definition: subdiv_mesh.c:440
static void subdiv_vertex_data_copy(const SubdivMeshContext *ctx, const MVert *coarse_vertex, MVert *subdiv_vertex)
Definition: subdiv_mesh.c:538
static void subdiv_eval_uv_layer(SubdivMeshContext *ctx, MLoop *subdiv_loop, const int ptex_face_index, const float u, const float v)
Definition: subdiv_mesh.c:875
static void subdiv_mesh_vertex_of_loose_edge_interpolate(SubdivMeshContext *ctx, const MEdge *coarse_edge, const float u, const int subdiv_vertex_index)
Definition: subdiv_mesh.c:1079
static void subdiv_mesh_ctx_cache_custom_data_layers(SubdivMeshContext *ctx)
Definition: subdiv_mesh.c:91
static void vertex_interpolation_end(VerticesForInterpolation *vertex_interpolation)
Definition: subdiv_mesh.c:295
static void subdiv_accumulate_vertex_normal_and_displacement(SubdivMeshContext *ctx, const int ptex_face_index, const float u, const float v, MVert *subdiv_vert)
Definition: subdiv_mesh.c:478
static void evaluate_vertex_and_apply_displacement_interpolate(const SubdivMeshContext *ctx, const int ptex_face_index, const float u, const float v, VerticesForInterpolation *vertex_interpolation, MVert *subdiv_vert)
Definition: subdiv_mesh.c:602
static void subdiv_mesh_vertex_every_corner_or_edge(const SubdivForeachContext *foreach_context, void *UNUSED(tls), const int ptex_face_index, const float u, const float v, const int subdiv_vertex_index)
Definition: subdiv_mesh.c:635
static void subdiv_mesh_poly(const SubdivForeachContext *foreach_context, void *UNUSED(tls), const int coarse_poly_index, const int subdiv_poly_index, const int start_loop_index, const int num_loops)
Definition: subdiv_mesh.c:963
struct SubdivMeshContext SubdivMeshContext
static void subdiv_mesh_vertex_inner(const SubdivForeachContext *foreach_context, void *tls_v, const int ptex_face_index, const float u, const float v, const int coarse_poly_index, const int coarse_corner, const int subdiv_vertex_index)
Definition: subdiv_mesh.c:775
static void subdiv_copy_edge_data(SubdivMeshContext *ctx, MEdge *subdiv_edge, const MEdge *coarse_edge)
Definition: subdiv_mesh.c:806
static void subdiv_mesh_vertex_edge(const SubdivForeachContext *foreach_context, void *tls_v, const int ptex_face_index, const float u, const float v, const int UNUSED(coarse_edge_index), const int coarse_poly_index, const int coarse_corner, const int subdiv_vertex_index)
Definition: subdiv_mesh.c:727
static void vertex_interpolation_init(const SubdivMeshContext *ctx, VerticesForInterpolation *vertex_interpolation, const MPoly *coarse_poly)
Definition: subdiv_mesh.c:194
Mesh * BKE_subdiv_to_mesh(Subdiv *subdiv, const SubdivToMeshSettings *settings, const Mesh *coarse_mesh)
Definition: subdiv_mesh.c:1195
static void loop_interpolation_from_corner(const SubdivMeshContext *ctx, LoopsForInterpolation *loop_interpolation, const MPoly *coarse_poly, const int corner)
Definition: subdiv_mesh.c:375
struct LoopsForInterpolation LoopsForInterpolation
static void eval_final_point_and_vertex_normal(Subdiv *subdiv, const int ptex_face_index, const float u, const float v, float r_P[3], short r_N[3])
Definition: subdiv_mesh.c:457
static void subdiv_mesh_ctx_cache_uv_layers(SubdivMeshContext *ctx)
Definition: subdiv_mesh.c:81
static void subdiv_mesh_vertex_loose(const SubdivForeachContext *foreach_context, void *UNUSED(tls), const int coarse_vertex_index, const int subdiv_vertex_index)
Definition: subdiv_mesh.c:989
static void subdiv_mesh_ensure_loop_interpolation(SubdivMeshContext *ctx, SubdivMeshTLS *tls, const MPoly *coarse_poly, const int coarse_corner)
Definition: subdiv_mesh.c:892
static void points_for_loose_edges_interpolation_get(SubdivMeshContext *ctx, const MEdge *coarse_edge, const MEdge *neighbors[2], float points_r[4][3])
Definition: subdiv_mesh.c:1041
static void subdiv_mesh_prepare_accumulator(SubdivMeshContext *ctx, int num_vertices)
Definition: subdiv_mesh.c:103
static bool subdiv_mesh_topology_info(const SubdivForeachContext *foreach_context, const int num_vertices, const int num_edges, const int num_loops, const int num_polygons)
Definition: subdiv_mesh.c:513
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
BLI_INLINE float D(const float *data, const int res[3], int x, int y, int z)
Definition: voxel.c:29