09fcce369d49d8201a5daf7221102c848852bb98
[blender.git] / source / blender / blenkernel / BKE_subdiv.h
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2018 by Blender Foundation.
19  * All rights reserved.
20  *
21  * Contributor(s): Sergey Sharybin.
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file BKE_subdiv.h
27  *  \ingroup bke
28  *  \since July 2018
29  *  \author Sergey Sharybin
30  */
31
32 #ifndef __BKE_SUBDIV_H__
33 #define __BKE_SUBDIV_H__
34
35 #include "BLI_sys_types.h"
36
37 struct Mesh;
38 struct MultiresModifierData;
39 struct Object;
40 struct OpenSubdiv_Converter;
41 struct OpenSubdiv_Evaluator;
42 struct OpenSubdiv_TopologyRefiner;
43 struct Subdiv;
44 struct SubdivToMeshSettings;
45
46 typedef enum {
47         SUBDIV_FVAR_LINEAR_INTERPOLATION_NONE,
48         SUBDIV_FVAR_LINEAR_INTERPOLATION_CORNERS_ONLY,
49         SUBDIV_FVAR_LINEAR_INTERPOLATION_CORNERS_AND_JUNCTIONS,
50         SUBDIV_FVAR_LINEAR_INTERPOLATION_CORNERS_JUNCTIONS_AND_CONCAVE,
51         SUBDIV_FVAR_LINEAR_INTERPOLATION_BOUNDARIES,
52         SUBDIV_FVAR_LINEAR_INTERPOLATION_ALL,
53 } eSubdivFVarLinearInterpolation;
54
55 typedef struct SubdivSettings {
56         bool is_simple;
57         bool is_adaptive;
58         int level;
59         eSubdivFVarLinearInterpolation fvar_linear_interpolation;
60 } SubdivSettings;
61
62 /* NOTE: Order of enumerators MUST match order of values in SubdivStats. */
63 typedef enum eSubdivStatsValue {
64         SUBDIV_STATS_TOPOLOGY_REFINER_CREATION_TIME = 0,
65         SUBDIV_STATS_SUBDIV_TO_MESH,
66         SUBDIV_STATS_SUBDIV_TO_MESH_GEOMETRY,
67         SUBDIV_STATS_EVALUATOR_CREATE,
68         SUBDIV_STATS_EVALUATOR_REFINE,
69         SUBDIV_STATS_SUBDIV_TO_CCG,
70         SUBDIV_STATS_SUBDIV_TO_CCG_ELEMENTS,
71
72         NUM_SUBDIV_STATS_VALUES,
73 } eSubdivStatsValue;
74
75 typedef struct SubdivStats {
76         union {
77                 struct {
78                         /* Time spend on creating topology refiner, which includes time
79                          * spend on conversion from Blender data to OpenSubdiv data, and
80                          * time spend on topology orientation on OpenSubdiv C-API side.
81                          */
82                         double topology_refiner_creation_time;
83                         /* Total time spent in BKE_subdiv_to_mesh(). */
84                         double subdiv_to_mesh_time;
85                         /* Geometry (MVert and co) creation time during SUBDIV_TYO_MESH. */
86                         double subdiv_to_mesh_geometry_time;
87                         /* Time spent on evaluator creation from topology refiner. */
88                         double evaluator_creation_time;
89                         /* Time spent on evaluator->refine(). */
90                         double evaluator_refine_time;
91                         /* Total time spent on whole CCG creation. */
92                         double subdiv_to_ccg_time;
93                         /* Time spent on CCG elements evaluation/initialization. */
94                         double subdiv_to_ccg_elements_time;
95                 };
96                 double values_[NUM_SUBDIV_STATS_VALUES];
97         };
98
99         /* Per-value timestamp on when corresponding BKE_subdiv_stats_begin() was
100          * called.
101          */
102         double begin_timestamp_[NUM_SUBDIV_STATS_VALUES];
103 } SubdivStats;
104
105 /* Functor which evaluates dispalcement at a given (u, v) of given ptex face. */
106 typedef struct SubdivDisplacement {
107         /* Return displacement which is to be added to the original coordinate.
108          *
109          * NOTE: This function is supposed to return "continuous" displacement for
110          * each pf PTex faces created for special (non-quad) polygon. This means,
111          * if displacement is stored on per-corner manner (like MDisps for multires)
112          * this is up the displacement implementation to average boundaries of the
113          * displacement grids if needed.
114          *
115          * Averaging of displacement for vertices created for over coarse vertices
116          * and edges is done by subdiv code.
117          */
118         void (*eval_displacement)(struct SubdivDisplacement *displacement,
119                                   const int ptex_face_index,
120                                   const float u, const float v,
121                                   const float dPdu[3], const float dPdv[3],
122                                   float r_D[3]);
123
124         /* Free the data, not the evaluator itself. */
125         void (*free)(struct SubdivDisplacement *displacement);
126
127         void *user_data;
128 } SubdivDisplacement;
129
130 /* This structure contains everything needed to construct subdivided surface.
131  * It does not specify storage, memory layout or anything else.
132  * It is possible to create different storages (like, grid based CPU side
133  * buffers, GPU subdivision mesh, CPU side fully qualified mesh) from the same
134  * Subdiv structure.
135  */
136 typedef struct Subdiv {
137         /* Settings this subdivision surface is created for.
138          *
139          * It is read-only after assignment in BKE_subdiv_new_from_FOO().
140          */
141         SubdivSettings settings;
142         /* Topology refiner includes all the glue logic to feed Blender side
143          * topology to OpenSubdiv. It can be shared by both evaluator and GL mesh
144          * drawer.
145          */
146         struct OpenSubdiv_TopologyRefiner *topology_refiner;
147         /* CPU side evaluator. */
148         struct OpenSubdiv_Evaluator *evaluator;
149         /* Optional displacement evaluator. */
150         struct SubdivDisplacement *displacement_evaluator;
151         /* Statistics for debugging. */
152         SubdivStats stats;
153
154         /* Cached values, are not supposed to be accessed directly. */
155         struct {
156                 /* Indexed by base face index, element indicates total number of ptex
157                  *faces created for preceding base faces.
158                  */
159                 int *face_ptex_offset;
160         } cache_;
161 } Subdiv;
162
163 /* ================================ HELPERS ================================= */
164
165 /* NOTE: uv_smooth is eSubsurfUVSmooth. */
166 eSubdivFVarLinearInterpolation
167 BKE_subdiv_fvar_interpolation_from_uv_smooth(int uv_smooth);
168
169 /* =============================== STATISTICS =============================== */
170
171 void BKE_subdiv_stats_init(SubdivStats *stats);
172
173 void BKE_subdiv_stats_begin(SubdivStats *stats, eSubdivStatsValue value);
174 void BKE_subdiv_stats_end(SubdivStats *stats, eSubdivStatsValue value);
175
176 void BKE_subdiv_stats_print(const SubdivStats *stats);
177
178 /* ============================== CONSTRUCTION ============================== */
179
180 Subdiv *BKE_subdiv_new_from_converter(const SubdivSettings *settings,
181                                       struct OpenSubdiv_Converter *converter);
182
183 Subdiv *BKE_subdiv_new_from_mesh(const SubdivSettings *settings,
184                                  struct Mesh *mesh);
185
186 void BKE_subdiv_free(Subdiv *subdiv);
187
188 /* ============================ DISPLACEMENT API ============================ */
189
190 void BKE_subdiv_displacement_attach_from_multires(
191         Subdiv *subdiv,
192         const struct Mesh *mesh,
193         const struct MultiresModifierData *mmd);
194
195 void BKE_subdiv_displacement_detach(Subdiv *subdiv);
196
197 /* ============================ TOPOLOGY HELPERS ============================ */
198
199 int *BKE_subdiv_face_ptex_offset_get(Subdiv *subdiv);
200
201 #endif  /* __BKE_SUBDIV_H__ */