Welcome to mirror list, hosted at ThFree Co, Russian Federation.

multires_reshape.h « intern « blenkernel « blender « source - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: f27618b21453d3e4e8f9cf3fcfd793c53e90caba (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
/* SPDX-License-Identifier: GPL-2.0-or-later
 * Copyright 2020 Blender Foundation. All rights reserved. */

/** \file
 * \ingroup bke
 */

#pragma once

#include "BLI_sys_types.h"

#include "BKE_multires.h"

struct Depsgraph;
struct GridPaintMask;
struct MDisps;
struct MEdge;
struct Mesh;
struct MLoop;
struct MPoly;
struct MultiresModifierData;
struct MVert;
struct Object;
struct Subdiv;
struct SubdivCCG;

typedef struct MultiresReshapeContext {
  /* NOTE: Only available when context is initialized from object. */
  struct Depsgraph *depsgraph;
  struct Object *object;

  struct MultiresModifierData *mmd;

  /* Base mesh from original object.
   * NOTE: Does NOT include any leading modifiers in it. */
  struct Mesh *base_mesh;
  const struct MVert *base_verts;
  const struct MEdge *base_edges;
  const struct MPoly *base_polys;
  const struct MLoop *base_loops;

  /* Subdivision surface created for multires modifier.
   *
   * The coarse mesh of this subdivision surface is a base mesh with all deformation modifiers
   * leading multires applied on it. */
  struct Subdiv *subdiv;
  bool need_free_subdiv;

  struct {
    /* Level at which displacement is being assigned to.
     * It will be propagated up from this level to top.level. */
    int level;

    /* Grid size for reshape.level. */
    int grid_size;
  } reshape;

  struct {
    /* Top level of the displacement grids.
     * The displacement will be propagated up to this level. */
    int level;

    /* Grid size for top.level. */
    int grid_size;
  } top;

  struct {
    /* Copy of original displacement and painting masks. */
    struct MDisps *mdisps;
    struct GridPaintMask *grid_paint_masks;
  } orig;

  /* Number of grids which are required for base_mesh. */
  int num_grids;

  /* Destination displacement and mask.
   * Points to a custom data on a destination mesh. */
  struct MDisps *mdisps;
  struct GridPaintMask *grid_paint_masks;

  /* Indexed by face index, gives first grid index of the face. */
  int *face_start_grid_index;

  /* Indexed by grid index, contains face (poly) index in the base mesh from which the grid has
   * been created (in other words, index of a poly which contains loop corresponding to the grid
   * index). */
  int *grid_to_face_index;

  /* Indexed by ptex face index, gives first grid index of the ptex face.
   *
   * For non-quad base faces ptex face is created for every face corner, so it's similar to a
   * grid in this case. In this case start grid index will be the only one for this ptex face.
   *
   * For quad base faces there is a single ptex face but 4 grids. So in this case there will be
   * 4 grids for the ptex, starting at a value stored in this mapping. */
  int *ptex_start_grid_index;

  /* Indexed by base face index, returns first ptex face index corresponding
   * to that base face. */
  int *face_ptex_offset;

  /* Vertex crease custom data layer, null if none is present. */
  const float *cd_vertex_crease;
  /* Edge crease custom data layer, null if none is present. */
  const float *cd_edge_crease;
} MultiresReshapeContext;

/**
 * Coordinate which identifies element of a grid.
 * This is directly related on how #CD_MDISPS stores displacement.
 */
typedef struct GridCoord {
  int grid_index;
  float u, v;
} GridCoord;

/**
 * Coordinate within ptex, which is what OpenSubdiv API operates on.
 */
typedef struct PTexCoord {
  int ptex_face_index;
  float u, v;
} PTexCoord;

/**
 * Element of a grid data stored in the destination mesh.
 * This is where reshaped coordinates and mask values will be written to.
 */
typedef struct ReshapeGridElement {
  float *displacement;
  float *mask;
} ReshapeGridElement;

typedef struct ReshapeConstGridElement {
  float displacement[3];
  float mask;
} ReshapeConstGridElement;

/* --------------------------------------------------------------------
 * Construct/destruct reshape context.
 */

/**
 * Create subdivision surface descriptor which is configured for surface evaluation at a given
 * multi-res modifier.
 */
struct Subdiv *multires_reshape_create_subdiv(struct Depsgraph *depsgraph,
                                              struct Object *object,
                                              const struct MultiresModifierData *mmd);

/**
 * \note Initialized base mesh to object's mesh, the Subdivision is created from the deformed
 * mesh prior to the multi-res modifier if depsgraph is not NULL. If the depsgraph is NULL
 * then Subdivision is created from base mesh (without any deformation applied).
 */
bool multires_reshape_context_create_from_object(MultiresReshapeContext *reshape_context,
                                                 struct Depsgraph *depsgraph,
                                                 struct Object *object,
                                                 struct MultiresModifierData *mmd);

bool multires_reshape_context_create_from_base_mesh(MultiresReshapeContext *reshape_context,
                                                    struct Depsgraph *depsgraph,
                                                    struct Object *object,
                                                    struct MultiresModifierData *mmd);

bool multires_reshape_context_create_from_ccg(MultiresReshapeContext *reshape_context,
                                              struct SubdivCCG *subdiv_ccg,
                                              struct Mesh *base_mesh,
                                              int top_level);

bool multires_reshape_context_create_from_modifier(MultiresReshapeContext *reshape_context,
                                                   struct Object *object,
                                                   struct MultiresModifierData *mmd,
                                                   int top_level);

bool multires_reshape_context_create_from_subdiv(MultiresReshapeContext *reshape_context,
                                                 struct Object *object,
                                                 struct MultiresModifierData *mmd,
                                                 struct Subdiv *subdiv,
                                                 int top_level);

void multires_reshape_free_original_grids(MultiresReshapeContext *reshape_context);
void multires_reshape_context_free(MultiresReshapeContext *reshape_context);

/* --------------------------------------------------------------------
 * Helper accessors.
 */

/**
 * For the given grid index get index of face it was created for.
 */
int multires_reshape_grid_to_face_index(const MultiresReshapeContext *reshape_context,
                                        int grid_index);

/**
 * For the given grid index get corner of a face it was created for.
 */
int multires_reshape_grid_to_corner(const MultiresReshapeContext *reshape_context, int grid_index);

bool multires_reshape_is_quad_face(const MultiresReshapeContext *reshape_context, int face_index);

/**
 * For the given grid index get index of corresponding PTEX face.
 */
int multires_reshape_grid_to_ptex_index(const MultiresReshapeContext *reshape_context,
                                        int grid_index);

/**
 * Convert normalized coordinate within a grid to a normalized coordinate within a PTEX face.
 */
PTexCoord multires_reshape_grid_coord_to_ptex(const MultiresReshapeContext *reshape_context,
                                              const GridCoord *grid_coord);

/**
 * Convert a normalized coordinate within a PTEX face to a normalized coordinate within a grid.
 */
GridCoord multires_reshape_ptex_coord_to_grid(const MultiresReshapeContext *reshape_context,
                                              const PTexCoord *ptex_coord);

/**
 * Calculate tangent matrix which converts displacement to a object vector.
 * Is calculated for the given surface derivatives at a given base face corner.
 */
void multires_reshape_tangent_matrix_for_corner(const MultiresReshapeContext *reshape_context,
                                                int face_index,
                                                int corner,
                                                const float dPdu[3],
                                                const float dPdv[3],
                                                float r_tangent_matrix[3][3]);

/**
 * Get grid elements which are to be reshaped at a given or PTEX coordinate.
 * The data is coming from final custom mdata layers.
 */
ReshapeGridElement multires_reshape_grid_element_for_grid_coord(
    const MultiresReshapeContext *reshape_context, const GridCoord *grid_coord);
ReshapeGridElement multires_reshape_grid_element_for_ptex_coord(
    const MultiresReshapeContext *reshape_context, const PTexCoord *ptex_coord);

/**
 * Get original grid element for the given coordinate.
 */
ReshapeConstGridElement multires_reshape_orig_grid_element_for_grid_coord(
    const MultiresReshapeContext *reshape_context, const GridCoord *grid_coord);

/* --------------------------------------------------------------------
 * Sample limit surface of the base mesh.
 */

/**
 * Evaluate limit surface created from base mesh.
 * This is the limit surface which defines tangent space for MDisps.
 */
void multires_reshape_evaluate_limit_at_grid(const MultiresReshapeContext *reshape_context,
                                             const GridCoord *grid_coord,
                                             float r_P[3],
                                             float r_tangent_matrix[3][3]);

/* --------------------------------------------------------------------
 * Custom data preparation.
 */

/**
 * Make sure custom data is allocated for the given level.
 */
void multires_reshape_ensure_grids(struct Mesh *mesh, int level);

/* --------------------------------------------------------------------
 * Functions specific to reshaping from a set of vertices in a object position.
 */

/**
 * Set displacement grids values at a reshape level to a object coordinates of the given source.
 *
 * \returns truth if all coordinates were assigned.
 *
 * False will be returned if the number of vertex coordinates did not match required number of
 * vertices at a reshape level.
 */
bool multires_reshape_assign_final_coords_from_vertcos(
    const MultiresReshapeContext *reshape_context,
    const float (*vert_coords)[3],
    int num_vert_coords);

/* --------------------------------------------------------------------
 * Functions specific to reshaping from CCG.
 */

/**
 * Store final object-space coordinates in the displacement grids.
 * The reason why displacement grids are used for storage is based on memory
 * footprint optimization.
 *
 * \note Displacement grids to be at least at a reshape level.
 *
 * \return truth if all coordinates have been updated.
 */
bool multires_reshape_assign_final_coords_from_ccg(const MultiresReshapeContext *reshape_context,
                                                   struct SubdivCCG *subdiv_ccg);

/* --------------------------------------------------------------------
 * Functions specific to reshaping from MDISPS.
 */

/**
 * Reads and writes to the current mesh #CD_MDISPS.
 */
void multires_reshape_assign_final_coords_from_mdisps(
    const MultiresReshapeContext *reshape_context);

/**
 * Reads from original #CD_MIDTSPS, writes to the current mesh #CD_MDISPS.
 */
void multires_reshape_assign_final_elements_from_orig_mdisps(
    const MultiresReshapeContext *reshape_context);

/* --------------------------------------------------------------------
 * Displacement smooth.
 */

/**
 * Operates on a displacement grids (CD_MDISPS) which contains object space coordinates stored for
 * the reshape level.
 *
 * The result is grids which are defining mesh with a smooth surface and details starting from
 * reshape level up to top level added back from original displacement grids.
 */
void multires_reshape_smooth_object_grids_with_details(
    const MultiresReshapeContext *reshape_context);

/**
 * Operates on a displacement grids (CD_MDISPS) which contains object space-coordinates stored for
 * the reshape level.
 *
 * Makes it so surface on top level looks smooth. Details are not preserved
 */
void multires_reshape_smooth_object_grids(const MultiresReshapeContext *reshape_context,
                                          enum eMultiresSubdivideModeType mode);

/* --------------------------------------------------------------------
 * Displacement, space conversion.
 */

/**
 * Store original grid data, so then it's possible to calculate delta from it and add
 * high-frequency content on top of reshaped grids.
 */
void multires_reshape_store_original_grids(MultiresReshapeContext *reshape_context);

void multires_reshape_object_grids_to_tangent_displacement(
    const MultiresReshapeContext *reshape_context);

/* --------------------------------------------------------------------
 * Apply base.
 */

/**
 * Update mesh coordinates to the final positions of displacement in object space.
 * This is effectively desired position of base mesh vertices after canceling out displacement.
 *
 * \note Expects that mesh's CD_MDISPS has been set to object space positions.
 */
void multires_reshape_apply_base_update_mesh_coords(MultiresReshapeContext *reshape_context);

/**
 * Perform better fitting of the base mesh so its subdivided version brings vertices to their
 * desired locations.
 */
void multires_reshape_apply_base_refit_base_mesh(MultiresReshapeContext *reshape_context);

/**
 * Refine subdivision surface to the new positions of the base mesh.
 */
void multires_reshape_apply_base_refine_from_base(MultiresReshapeContext *reshape_context);

/**
 * Refine subdivision surface to the new positions of the deformed mesh (base mesh with all
 * modifiers leading the multi-res applied).
 *
 * \note Will re-evaluate all leading modifiers, so it's not cheap.
 */
void multires_reshape_apply_base_refine_from_deform(MultiresReshapeContext *reshape_context);