Cycles: working towards texture workflow design
[blender.git] / source / blender / blenkernel / BKE_DerivedMesh.h
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 #ifndef BKE_DERIVEDMESH_H
31 #define BKE_DERIVEDMESH_H
32
33 /** \file BKE_DerivedMesh.h
34  *  \ingroup bke
35  *
36  *  \todo
37  *  - Make drawMapped* functions take a predicate function that
38  *    determines whether to draw the edge (this predicate can
39  *    also set color, etc). This will be slightly more general 
40  *    and allow some of the functions to be collapsed.
41  *  - Once accessor functions are added then single element draw
42  *    functions can be implemented using primitive accessors.
43  *  - Add function to dispatch to renderer instead of using
44  *    conversion to DLM.
45  */
46
47 #include "DNA_customdata_types.h"
48 #include "BKE_customdata.h"
49 #include "BKE_bvhutils.h"
50
51 struct MVert;
52 struct MEdge;
53 struct MFace;
54 struct MTFace;
55 struct Object;
56 struct Scene;
57 struct Mesh;
58 struct EditMesh;
59 struct KeyBlock;
60 struct ModifierData;
61 struct MCol;
62 struct ColorBand;
63 struct GPUVertexAttribs;
64 struct GPUDrawObject;
65 struct ListBase;
66 struct PBVH;
67
68 /* number of sub-elements each mesh element has (for interpolation) */
69 #define SUB_ELEMS_VERT 0
70 #define SUB_ELEMS_EDGE 2
71 #define SUB_ELEMS_FACE 4
72
73 typedef struct DMGridData {
74         float co[3];
75         float no[3];
76 } DMGridData;
77
78 typedef struct DMGridAdjacency {
79         int index[4];
80         int rotation[4];
81 } DMGridAdjacency;
82
83 typedef enum DerivedMeshType {
84         DM_TYPE_CDDM,
85         DM_TYPE_EDITMESH,
86         DM_TYPE_CCGDM
87 } DerivedMeshType;
88
89 typedef struct DerivedMesh DerivedMesh;
90 struct DerivedMesh {
91         /* Private DerivedMesh data, only for internal DerivedMesh use */
92         CustomData vertData, edgeData, faceData;
93         int numVertData, numEdgeData, numFaceData;
94         int needsFree; /* checked on ->release, is set to 0 for cached results */
95         int deformedOnly; /* set by modifier stack if only deformed from original */
96         BVHCache bvhCache;
97         struct GPUDrawObject *drawObject;
98         DerivedMeshType type;
99
100         /* Misc. Queries */
101
102         /* Also called in Editmode */
103         int (*getNumVerts)(DerivedMesh *dm);
104         /* Also called in Editmode */
105         int (*getNumFaces)(DerivedMesh *dm);
106
107         int (*getNumEdges)(DerivedMesh *dm);
108
109         /* copy a single vert/edge/face from the derived mesh into
110          * *{vert/edge/face}_r. note that the current implementation
111          * of this function can be quite slow, iterating over all
112          * elements (editmesh)
113          */
114         void (*getVert)(DerivedMesh *dm, int index, struct MVert *vert_r);
115         void (*getEdge)(DerivedMesh *dm, int index, struct MEdge *edge_r);
116         void (*getFace)(DerivedMesh *dm, int index, struct MFace *face_r);
117
118         /* return a pointer to the entire array of verts/edges/face from the
119          * derived mesh. if such an array does not exist yet, it will be created,
120          * and freed on the next ->release(). consider using getVert/Edge/Face if
121          * you are only interested in a few verts/edges/faces.
122          */
123         struct MVert *(*getVertArray)(DerivedMesh *dm);
124         struct MEdge *(*getEdgeArray)(DerivedMesh *dm);
125         struct MFace *(*getFaceArray)(DerivedMesh *dm);
126
127         /* copy all verts/edges/faces from the derived mesh into
128          * *{vert/edge/face}_r (must point to a buffer large enough)
129          */
130         void (*copyVertArray)(DerivedMesh *dm, struct MVert *vert_r);
131         void (*copyEdgeArray)(DerivedMesh *dm, struct MEdge *edge_r);
132         void (*copyFaceArray)(DerivedMesh *dm, struct MFace *face_r);
133
134         /* return a copy of all verts/edges/faces from the derived mesh
135          * it is the caller's responsibility to free the returned pointer
136          */
137         struct MVert *(*dupVertArray)(DerivedMesh *dm);
138         struct MEdge *(*dupEdgeArray)(DerivedMesh *dm);
139         struct MFace *(*dupFaceArray)(DerivedMesh *dm);
140
141         /* return a pointer to a single element of vert/edge/face custom data
142          * from the derived mesh (this gives a pointer to the actual data, not
143          * a copy)
144          */
145         void *(*getVertData)(DerivedMesh *dm, int index, int type);
146         void *(*getEdgeData)(DerivedMesh *dm, int index, int type);
147         void *(*getFaceData)(DerivedMesh *dm, int index, int type);
148
149         /* return a pointer to the entire array of vert/edge/face custom data
150          * from the derived mesh (this gives a pointer to the actual data, not
151          * a copy)
152          */
153         void *(*getVertDataArray)(DerivedMesh *dm, int type);
154         void *(*getEdgeDataArray)(DerivedMesh *dm, int type);
155         void *(*getFaceDataArray)(DerivedMesh *dm, int type);
156
157         /* optional grid access for subsurf */
158         int (*getNumGrids)(DerivedMesh *dm);
159         int (*getGridSize)(DerivedMesh *dm);
160         DMGridData **(*getGridData)(DerivedMesh *dm);
161         DMGridAdjacency *(*getGridAdjacency)(DerivedMesh *dm);
162         int *(*getGridOffset)(DerivedMesh *dm);
163
164         /* Iterate over each mapped vertex in the derived mesh, calling the
165          * given function with the original vert and the mapped vert's new
166          * coordinate and normal. For historical reasons the normal can be
167          * passed as a float or short array, only one should be non-NULL.
168          */
169         void (*foreachMappedVert)(
170                                                   DerivedMesh *dm,
171                                                   void (*func)(void *userData, int index, float *co,
172                                                                            float *no_f, short *no_s),
173                                                   void *userData);
174
175         /* Iterate over each mapped edge in the derived mesh, calling the
176          * given function with the original edge and the mapped edge's new
177          * coordinates.
178          */
179         void (*foreachMappedEdge)(DerivedMesh *dm,
180                                                           void (*func)(void *userData, int index,
181                                                                                    float *v0co, float *v1co),
182                                                           void *userData);
183
184         /* Iterate over each mapped face in the derived mesh, calling the
185          * given function with the original face and the mapped face's (or
186          * faces') center and normal.
187          */
188         void (*foreachMappedFaceCenter)(DerivedMesh *dm,
189                                                                         void (*func)(void *userData, int index,
190                                                                                                  float *cent, float *no),
191                                                                         void *userData);
192
193         /* Iterate over all vertex points, calling DO_MINMAX with given args.
194          *
195          * Also called in Editmode
196          */
197         void (*getMinMax)(DerivedMesh *dm, float min_r[3], float max_r[3]);
198
199         /* Direct Access Operations */
200         /*  o Can be undefined */
201         /*  o Must be defined for modifiers that only deform however */
202
203         /* Get vertex location, undefined if index is not valid */
204         void (*getVertCo)(DerivedMesh *dm, int index, float co_r[3]);
205
206         /* Fill the array (of length .getNumVerts()) with all vertex locations */
207         void (*getVertCos)(DerivedMesh *dm, float (*cos_r)[3]);
208
209         /* Get smooth vertex normal, undefined if index is not valid */
210         void (*getVertNo)(DerivedMesh *dm, int index, float no_r[3]);
211
212         /* Get a map of vertices to faces
213          */
214         struct ListBase *(*getFaceMap)(struct Object *ob, DerivedMesh *dm);
215
216         /* Get the BVH used for paint modes
217          */
218         struct PBVH *(*getPBVH)(struct Object *ob, DerivedMesh *dm);
219
220         /* Drawing Operations */
221
222         /* Draw all vertices as bgl points (no options) */
223         void (*drawVerts)(DerivedMesh *dm);
224
225         /* Draw edges in the UV mesh (if exists) */
226         void (*drawUVEdges)(DerivedMesh *dm);
227
228         /* Draw all edges as lines (no options) 
229          *
230          * Also called for *final* editmode DerivedMeshes
231          */
232         void (*drawEdges)(DerivedMesh *dm, int drawLooseEdges, int drawAllEdges);
233         
234         /* Draw all loose edges (edges w/ no adjoining faces) */
235         void (*drawLooseEdges)(DerivedMesh *dm);
236
237         /* Draw all faces
238          *  o Set face normal or vertex normal based on inherited face flag
239          *  o Use inherited face material index to call setMaterial
240          *  o Only if setMaterial returns true
241          *
242          * Also called for *final* editmode DerivedMeshes
243          */
244         void (*drawFacesSolid)(DerivedMesh *dm, float (*partial_redraw_planes)[4],
245                                                    int fast, int (*setMaterial)(int, void *attribs));
246
247         /* Draw all faces
248          *  o If useTwoSided, draw front and back using col arrays
249          *  o col1,col2 are arrays of length numFace*4 of 4 component colors
250          *    in ABGR format, and should be passed as per-face vertex color.
251          */
252         void (*drawFacesColored)(DerivedMesh *dm, int useTwoSided,
253                                                          unsigned char *col1, unsigned char *col2);
254
255         /* Draw all faces using MTFace 
256          *  o Drawing options too complicated to enumerate, look at code.
257          */
258         void (*drawFacesTex)(DerivedMesh *dm,
259                                                  int (*setDrawOptions)(struct MTFace *tface,
260                                                  struct MCol *mcol, int matnr));
261
262         /* Draw all faces with GLSL materials
263          *  o setMaterial is called for every different material nr
264          *  o Only if setMaterial returns true
265          */
266         void (*drawFacesGLSL)(DerivedMesh *dm,
267                 int (*setMaterial)(int, void *attribs));
268
269         /* Draw mapped faces (no color, or texture)
270          *  o Only if !setDrawOptions or
271          *    setDrawOptions(userData, mapped-face-index, drawSmooth_r)
272          *    returns true
273          *
274          * If drawSmooth is set to true then vertex normals should be set and
275          * glShadeModel called with GL_SMOOTH. Otherwise the face normal should
276          * be set and glShadeModel called with GL_FLAT.
277          *
278          * The setDrawOptions is allowed to not set drawSmooth (for example, when
279          * lighting is disabled), in which case the implementation should draw as
280          * smooth shaded.
281          */
282         void (*drawMappedFaces)(DerivedMesh *dm,
283                                                         int (*setDrawOptions)(void *userData, int index,
284                                                                                                   int *drawSmooth_r),
285                                                         void *userData, int useColors,
286                                                         int (*setMaterial)(int, void *attribs));
287
288         /* Draw mapped faces using MTFace 
289          *  o Drawing options too complicated to enumerate, look at code.
290          */
291         void (*drawMappedFacesTex)(DerivedMesh *dm,
292                                                            int (*setDrawOptions)(void *userData,
293                                                                                                          int index),
294                                                            void *userData);
295
296         /* Draw mapped faces with GLSL materials
297          *  o setMaterial is called for every different material nr
298          *  o setDrawOptions is called for every face
299          *  o Only if setMaterial and setDrawOptions return true
300          */
301         void (*drawMappedFacesGLSL)(DerivedMesh *dm,
302                 int (*setMaterial)(int, void *attribs),
303                 int (*setDrawOptions)(void *userData, int index), void *userData);
304
305         /* Draw mapped edges as lines
306          *  o Only if !setDrawOptions or setDrawOptions(userData, mapped-edge)
307          *    returns true
308          */
309         void (*drawMappedEdges)(DerivedMesh *dm,
310                                                         int (*setDrawOptions)(void *userData, int index),
311                                                         void *userData);
312
313         /* Draw mapped edges as lines with interpolation values
314          *  o Only if !setDrawOptions or
315          *    setDrawOptions(userData, mapped-edge, mapped-v0, mapped-v1, t)
316          *    returns true
317          *
318          * NOTE: This routine is optional!
319          */
320         void (*drawMappedEdgesInterp)(DerivedMesh *dm, 
321                                                                   int (*setDrawOptions)(void *userData,
322                                                                                                                 int index), 
323                                                                   void (*setDrawInterpOptions)(void *userData,
324                                                                                                                            int index,
325                                                                                                                            float t),
326                                                                   void *userData);
327
328         /* Draw all faces with materials
329          *  o setMaterial is called for every different material nr
330          *  o setFace is called to verify if a face must be hidden
331          */
332         void (*drawMappedFacesMat)(DerivedMesh *dm,
333                 void (*setMaterial)(void *userData, int, void *attribs),
334                 int (*setFace)(void *userData, int index), void *userData);
335
336         /* Release reference to the DerivedMesh. This function decides internally
337          * if the DerivedMesh will be freed, or cached for later use. */
338         void (*release)(DerivedMesh *dm);
339 };
340
341 /* utility function to initialise a DerivedMesh's function pointers to
342  * the default implementation (for those functions which have a default)
343  */
344 void DM_init_funcs(DerivedMesh *dm);
345
346 /* utility function to initialise a DerivedMesh for the desired number
347  * of vertices, edges and faces (doesn't allocate memory for them, just
348  * sets up the custom data layers)
349  */
350 void DM_init(DerivedMesh *dm, DerivedMeshType type,
351                          int numVerts, int numEdges, int numFaces);
352
353 /* utility function to initialise a DerivedMesh for the desired number
354  * of vertices, edges and faces, with a layer setup copied from source
355  */
356 void DM_from_template(DerivedMesh *dm, DerivedMesh *source,
357                                           DerivedMeshType type,
358                                           int numVerts, int numEdges, int numFaces);
359
360 /* utility function to release a DerivedMesh's layers
361  * returns 1 if DerivedMesh has to be released by the backend, 0 otherwise
362  */
363 int DM_release(DerivedMesh *dm);
364
365 /* utility function to convert a DerivedMesh to a Mesh
366  */
367 void DM_to_mesh(DerivedMesh *dm, struct Mesh *me);
368
369 /* utility function to convert a DerivedMesh to a shape key block 
370  */
371 void DM_to_meshkey(DerivedMesh *dm, struct Mesh *me, struct KeyBlock *kb);
372
373 /* set the CD_FLAG_NOCOPY flag in custom data layers where the mask is
374  * zero for the layer type, so only layer types specified by the mask
375  * will be copied
376  */
377 void DM_set_only_copy(DerivedMesh *dm, CustomDataMask mask);
378
379 /* adds a vertex/edge/face custom data layer to a DerivedMesh, optionally
380  * backed by an external data array
381  * alloctype defines how the layer is allocated or copied, and how it is
382  * freed, see BKE_customdata.h for the different options
383  */
384 void DM_add_vert_layer(struct DerivedMesh *dm, int type, int alloctype,
385                                            void *layer);
386 void DM_add_edge_layer(struct DerivedMesh *dm, int type, int alloctype,
387                                            void *layer);
388 void DM_add_face_layer(struct DerivedMesh *dm, int type, int alloctype,
389                                            void *layer);
390
391 /* custom data access functions
392  * return pointer to data from first layer which matches type
393  * if they return NULL for valid indices, data doesn't exist
394  * note these return pointers - any change modifies the internals of the mesh
395  */
396 void *DM_get_vert_data(struct DerivedMesh *dm, int index, int type);
397 void *DM_get_edge_data(struct DerivedMesh *dm, int index, int type);
398 void *DM_get_face_data(struct DerivedMesh *dm, int index, int type);
399
400 /* custom data layer access functions
401  * return pointer to first data layer which matches type (a flat array)
402  * if they return NULL, data doesn't exist
403  * note these return pointers - any change modifies the internals of the mesh
404  */
405 void *DM_get_vert_data_layer(struct DerivedMesh *dm, int type);
406 void *DM_get_edge_data_layer(struct DerivedMesh *dm, int type);
407 void *DM_get_face_data_layer(struct DerivedMesh *dm, int type);
408
409 /* custom data setting functions
410  * copy supplied data into first layer of type using layer's copy function
411  * (deep copy if appropriate)
412  */
413 void DM_set_vert_data(struct DerivedMesh *dm, int index, int type, void *data);
414 void DM_set_edge_data(struct DerivedMesh *dm, int index, int type, void *data);
415 void DM_set_face_data(struct DerivedMesh *dm, int index, int type, void *data);
416
417 /* custom data copy functions
418  * copy count elements from source_index in source to dest_index in dest
419  * these copy all layers for which the CD_FLAG_NOCOPY flag is not set
420  */
421 void DM_copy_vert_data(struct DerivedMesh *source, struct DerivedMesh *dest,
422                                            int source_index, int dest_index, int count);
423 void DM_copy_edge_data(struct DerivedMesh *source, struct DerivedMesh *dest,
424                                            int source_index, int dest_index, int count);
425 void DM_copy_face_data(struct DerivedMesh *source, struct DerivedMesh *dest,
426                                            int source_index, int dest_index, int count);
427
428 /* custom data free functions
429  * free count elements, starting at index
430  * they free all layers for which the CD_FLAG_NOCOPY flag is not set
431  */
432 void DM_free_vert_data(struct DerivedMesh *dm, int index, int count);
433 void DM_free_edge_data(struct DerivedMesh *dm, int index, int count);
434 void DM_free_face_data(struct DerivedMesh *dm, int index, int count);
435
436 /* interpolates vertex data from the vertices indexed by src_indices in the
437  * source mesh using the given weights and stores the result in the vertex
438  * indexed by dest_index in the dest mesh
439  */
440 void DM_interp_vert_data(struct DerivedMesh *source, struct DerivedMesh *dest,
441                                                  int *src_indices, float *weights,
442                                                  int count, int dest_index);
443
444 /* interpolates edge data from the edges indexed by src_indices in the
445  * source mesh using the given weights and stores the result in the edge indexed
446  * by dest_index in the dest mesh.
447  * if weights is NULL, all weights default to 1.
448  * if vert_weights is non-NULL, any per-vertex edge data is interpolated using
449  * vert_weights[i] multiplied by weights[i].
450  */
451 typedef float EdgeVertWeight[SUB_ELEMS_EDGE][SUB_ELEMS_EDGE];
452 void DM_interp_edge_data(struct DerivedMesh *source, struct DerivedMesh *dest,
453                                                  int *src_indices,
454                                                  float *weights, EdgeVertWeight *vert_weights,
455                                                  int count, int dest_index);
456
457 /* interpolates face data from the faces indexed by src_indices in the
458  * source mesh using the given weights and stores the result in the face indexed
459  * by dest_index in the dest mesh.
460  * if weights is NULL, all weights default to 1.
461  * if vert_weights is non-NULL, any per-vertex face data is interpolated using
462  * vert_weights[i] multiplied by weights[i].
463  */
464 typedef float FaceVertWeight[SUB_ELEMS_FACE][SUB_ELEMS_FACE];
465 void DM_interp_face_data(struct DerivedMesh *source, struct DerivedMesh *dest,
466                                                  int *src_indices,
467                                                  float *weights, FaceVertWeight *vert_weights,
468                                                  int count, int dest_index);
469
470 void DM_swap_face_data(struct DerivedMesh *dm, int index, const int *corner_indices);
471
472 /* Temporary? A function to give a colorband to derivedmesh for vertexcolor ranges */
473 void vDM_ColorBand_store(struct ColorBand *coba);
474
475 /* Simple function to get me->totvert amount of vertices/normals,
476    correctly deformed and subsurfered. Needed especially when vertexgroups are involved.
477    In use now by vertex/weigt paint and particles */
478 float *mesh_get_mapped_verts_nors(struct Scene *scene, struct Object *ob);
479
480         /* */
481 DerivedMesh *mesh_get_derived_final(struct Scene *scene, struct Object *ob,
482                                                                         CustomDataMask dataMask);
483 DerivedMesh *mesh_get_derived_deform(struct Scene *scene, struct Object *ob,
484                                                                          CustomDataMask dataMask);
485
486 DerivedMesh *mesh_create_derived_for_modifier(struct Scene *scene, struct Object *ob, struct ModifierData *md);
487
488 DerivedMesh *mesh_create_derived_render(struct Scene *scene, struct Object *ob,
489                                                                                 CustomDataMask dataMask);
490
491 DerivedMesh *mesh_create_derived_index_render(struct Scene *scene, struct Object *ob, CustomDataMask dataMask, int index);
492
493                 /* same as above but wont use render settings */
494 DerivedMesh *mesh_create_derived(struct Mesh *me, struct Object *ob, float (*vertCos)[3]);
495 DerivedMesh *mesh_create_derived_view(struct Scene *scene, struct Object *ob,
496                                                                           CustomDataMask dataMask);
497 DerivedMesh *mesh_create_derived_no_deform(struct Scene *scene, struct Object *ob,
498                                                                                    float (*vertCos)[3],
499                                                                                    CustomDataMask dataMask);
500 DerivedMesh *mesh_create_derived_no_deform_render(struct Scene *scene, struct Object *ob,
501                                                                                                   float (*vertCos)[3],
502                                                                                                   CustomDataMask dataMask);
503 /* for gameengine */
504 DerivedMesh *mesh_create_derived_no_virtual(struct Scene *scene, struct Object *ob, float (*vertCos)[3],
505                                                                                         CustomDataMask dataMask);
506 DerivedMesh *mesh_create_derived_physics(struct Scene *scene, struct Object *ob, float (*vertCos)[3],
507                                                                                         CustomDataMask dataMask);
508
509 DerivedMesh *editmesh_get_derived(struct EditMesh *em, float (*vertexCos)[3]);
510 DerivedMesh *editmesh_get_derived_base(struct Object *, struct EditMesh *em);
511 DerivedMesh *editmesh_get_derived_cage(struct Scene *scene, struct Object *, 
512                                                                            struct EditMesh *em, CustomDataMask dataMask);
513 DerivedMesh *editmesh_get_derived_cage_and_final(struct Scene *scene, struct Object *, 
514                                                                                                  struct EditMesh *em, DerivedMesh **final_r,
515                                                                                                  CustomDataMask dataMask);
516 float (*editmesh_get_vertex_cos(struct EditMesh *em, int *numVerts_r))[3];
517 int editmesh_modifier_is_enabled(struct Scene *scene, struct ModifierData *md, DerivedMesh *dm);
518 void makeDerivedMesh(struct Scene *scene, struct Object *ob, struct EditMesh *em, CustomDataMask dataMask);
519
520 /* returns an array of deform matrices for crazyspace correction, and the
521    number of modifiers left */
522 int editmesh_get_first_deform_matrices(struct Scene *, struct Object *, struct EditMesh *em,
523                                                                            float (**deformmats)[3][3], float (**deformcos)[3]);
524
525 /* returns an array of deform matrices for crazyspace correction when sculpting,
526    and the number of modifiers left */
527 int sculpt_get_deform_matrices(struct Scene *scene, struct Object *ob,
528                                                                 float (**deformmats)[3][3], float (**deformcos)[3]);
529
530 void weight_to_rgb(float input, float *fr, float *fg, float *fb);
531
532 /* convert layers requested by a GLSL material to actually available layers in
533  * the DerivedMesh, with both a pointer for arrays and an offset for editmesh */
534 typedef struct DMVertexAttribs {
535         struct {
536                 struct MTFace *array;
537                 int emOffset, glIndex, glTexco;
538         } tface[MAX_MTFACE];
539
540         struct {
541                 struct MCol *array;
542                 int emOffset, glIndex;
543         } mcol[MAX_MCOL];
544
545         struct {
546                 float (*array)[4];
547                 int emOffset, glIndex;
548         } tang;
549
550         struct {
551                 float (*array)[3];
552                 int emOffset, glIndex, glTexco;
553         } orco;
554
555         int tottface, totmcol, tottang, totorco;
556 } DMVertexAttribs;
557
558 void DM_vertex_attributes_from_gpu(DerivedMesh *dm,
559         struct GPUVertexAttribs *gattribs, DMVertexAttribs *attribs);
560
561 void DM_add_tangent_layer(DerivedMesh *dm);
562
563 /* Set object's bounding box based on DerivedMesh min/max data */
564 void DM_set_object_boundbox(struct Object *ob, DerivedMesh *dm);
565
566 #endif
567