/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. */ #pragma once /** \file * \ingroup bke * * Basic design of the DerivedMesh system: * * DerivedMesh is a common set of interfaces for mesh systems. * * There are three main mesh data structures in Blender: * #Mesh, #CDDerivedMesh and #BMesh. * * These, and a few others, all implement DerivedMesh interfaces, * which contains unified drawing interfaces, a few utility interfaces, * and a bunch of read-only interfaces intended mostly for conversion from * one format to another. * * All Mesh structures in blender make use of CustomData, which is used to store * per-element attributes and interpolate them (e.g. uvs, vcols, vgroups, etc). * * Mesh is the "serialized" structure, used for storing object-mode mesh data * and also for saving stuff to disk. Its interfaces are also what DerivedMesh * uses to communicate with. * * CDDM is a little mesh library, that uses Mesh data structures in the backend. * It's mostly used for modifiers, and has the advantages of not taking much * resources. * * BMesh is a full-on brep, used for editmode, some modifiers, etc. It's much * more capable (if memory-intensive) then CDDM. * * DerivedMesh is somewhat hackish. Many places assumes that a DerivedMesh is * a CDDM (most of the time by simply copying it and converting it to one). * CDDM is the original structure for modifiers, but has since been superseded * by BMesh, at least for the foreseeable future. */ /* * NOTE: This structure is read-only, for all practical purposes. * At some point in the future, we may want to consider * creating a replacement structure that implements a proper * abstract mesh kernel interface. Or, we can leave this * as it is and stick with using BMesh and CDDM. */ #include "DNA_customdata_types.h" #include "DNA_defs.h" #include "DNA_meshdata_types.h" #include "BLI_compiler_attrs.h" #include "BKE_bvhutils.h" #include "BKE_customdata.h" #ifdef __cplusplus extern "C" { #endif struct BMEditMesh; struct CCGElem; struct CCGKey; struct CustomData_MeshMasks; struct Depsgraph; struct MEdge; struct MFace; struct MVert; struct Mesh; struct ModifierData; struct Object; struct Scene; /* * NOTE: all mface interfaces now officially operate on tessellated data. * Also, the mface origindex layer indexes mpolys, not mfaces. */ /* keep in sync with MFace/MPoly types */ typedef struct DMFlagMat { short mat_nr; char flag; } DMFlagMat; typedef enum DerivedMeshType { DM_TYPE_CDDM, DM_TYPE_CCGDM, } DerivedMeshType; typedef enum DMDirtyFlag { /* dm has valid tessellated faces, but tessellated CDDATA need to be updated. */ DM_DIRTY_TESS_CDLAYERS = 1 << 0, /* check this with modifier dependsOnNormals callback to see if normals need recalculation */ DM_DIRTY_NORMALS = 1 << 1, } DMDirtyFlag; typedef struct DerivedMesh DerivedMesh; struct DerivedMesh { /** Private DerivedMesh data, only for internal DerivedMesh use */ CustomData vertData, edgeData, faceData, loopData, polyData; int numVertData, numEdgeData, numTessFaceData, numLoopData, numPolyData; int needsFree; /* checked on ->release, is set to 0 for cached results */ int deformedOnly; /* set by modifier stack if only deformed from original */ DerivedMeshType type; DMDirtyFlag dirty; /** * \warning Typical access is done via #getLoopTriArray, #getNumLoopTri. */ struct { /* WARNING! swapping between array (ready-to-be-used data) and array_wip * (where data is actually computed) shall always be protected by same * lock as one used for looptris computing. */ struct MLoopTri *array, *array_wip; int num; int num_alloc; } looptris; /* use for converting to BMesh which doesn't store bevel weight and edge crease by default */ char cd_flag; short tangent_mask; /* which tangent layers are calculated */ /** Calculate vert and face normals */ void (*calcNormals)(DerivedMesh *dm); /** Loop tessellation cache (WARNING! Only call inside threading-protected code!) */ void (*recalcLoopTri)(DerivedMesh *dm); /** accessor functions */ const struct MLoopTri *(*getLoopTriArray)(DerivedMesh *dm); int (*getNumLoopTri)(DerivedMesh *dm); /* Misc. Queries */ /* Also called in Editmode */ int (*getNumVerts)(DerivedMesh *dm); int (*getNumEdges)(DerivedMesh *dm); int (*getNumTessFaces)(DerivedMesh *dm); int (*getNumLoops)(DerivedMesh *dm); int (*getNumPolys)(DerivedMesh *dm); /** Return a pointer to the entire array of verts/edges/face from the * derived mesh. if such an array does not exist yet, it will be created, * and freed on the next ->release(). consider using getVert/Edge/Face if * you are only interested in a few verts/edges/faces. */ struct MVert *(*getVertArray)(DerivedMesh *dm); struct MEdge *(*getEdgeArray)(DerivedMesh *dm); struct MFace *(*getTessFaceArray)(DerivedMesh *dm); struct MLoop *(*getLoopArray)(DerivedMesh *dm); struct MPoly *(*getPolyArray)(DerivedMesh *dm); /** Copy all verts/edges/faces from the derived mesh into * *{vert/edge/face}_r (must point to a buffer large enough) */ void (*copyVertArray)(DerivedMesh *dm, struct MVert *r_vert); void (*copyEdgeArray)(DerivedMesh *dm, struct MEdge *r_edge); void (*copyTessFaceArray)(DerivedMesh *dm, struct MFace *r_face); void (*copyLoopArray)(DerivedMesh *dm, struct MLoop *r_loop); void (*copyPolyArray)(DerivedMesh *dm, struct MPoly *r_poly); /** Return a copy of all verts/edges/faces from the derived mesh * it is the caller's responsibility to free the returned pointer */ struct MVert *(*dupVertArray)(DerivedMesh *dm); struct MEdge *(*dupEdgeArray)(DerivedMesh *dm); struct MFace *(*dupTessFaceArray)(DerivedMesh *dm); struct MLoop *(*dupLoopArray)(DerivedMesh *dm); struct MPoly *(*dupPolyArray)(DerivedMesh *dm); /** Return a pointer to a single element of vert/edge/face custom data * from the derived mesh (this gives a pointer to the actual data, not * a copy) */ void *(*getVertData)(DerivedMesh *dm, int index, int type); void *(*getEdgeData)(DerivedMesh *dm, int index, int type); void *(*getTessFaceData)(DerivedMesh *dm, int index, int type); void *(*getPolyData)(DerivedMesh *dm, int index, int type); /** Return a pointer to the entire array of vert/edge/face custom data * from the derived mesh (this gives a pointer to the actual data, not * a copy) */ void *(*getVertDataArray)(DerivedMesh *dm, int type); void *(*getEdgeDataArray)(DerivedMesh *dm, int type); void *(*getTessFaceDataArray)(DerivedMesh *dm, int type); void *(*getLoopDataArray)(DerivedMesh *dm, int type); void *(*getPolyDataArray)(DerivedMesh *dm, int type); /** Retrieves the base CustomData structures for * verts/edges/tessfaces/loops/faces. */ CustomData *(*getVertDataLayout)(DerivedMesh *dm); CustomData *(*getEdgeDataLayout)(DerivedMesh *dm); CustomData *(*getTessFaceDataLayout)(DerivedMesh *dm); CustomData *(*getLoopDataLayout)(DerivedMesh *dm); CustomData *(*getPolyDataLayout)(DerivedMesh *dm); /** Optional grid access for subsurf */ int (*getNumGrids)(DerivedMesh *dm); int (*getGridSize)(DerivedMesh *dm); struct CCGElem **(*getGridData)(DerivedMesh *dm); int *(*getGridOffset)(DerivedMesh *dm); void (*getGridKey)(DerivedMesh *dm, struct CCGKey *key); DMFlagMat *(*getGridFlagMats)(DerivedMesh *dm); unsigned int **(*getGridHidden)(DerivedMesh *dm); /** Direct Access Operations * - Can be undefined * - Must be defined for modifiers that only deform however */ /** Get vertex location, undefined if index is not valid */ void (*getVertCo)(DerivedMesh *dm, int index, float r_co[3]); /** Get smooth vertex normal, undefined if index is not valid */ void (*getVertNo)(DerivedMesh *dm, int index, float r_no[3]); void (*getPolyNo)(DerivedMesh *dm, int index, float r_no[3]); /** Get a map of vertices to faces */ const struct MeshElemMap *(*getPolyMap)(struct Object *ob, DerivedMesh *dm); /** Release reference to the DerivedMesh. This function decides internally * if the DerivedMesh will be freed, or cached for later use. */ void (*release)(DerivedMesh *dm); }; /** * Utility function to initialize a #DerivedMesh's function pointers to * the default implementation (for those functions which have a default). */ void DM_init_funcs(DerivedMesh *dm); /** * Utility function to initialize a #DerivedMesh for the desired number * of vertices, edges and faces (doesn't allocate memory for them, just * sets up the custom data layers)> */ void DM_init(DerivedMesh *dm, DerivedMeshType type, int numVerts, int numEdges, int numTessFaces, int numLoops, int numPolys); /** * Utility function to initialize a DerivedMesh for the desired number * of vertices, edges and faces, with a layer setup copied from source */ void DM_from_template_ex(DerivedMesh *dm, DerivedMesh *source, DerivedMeshType type, int numVerts, int numEdges, int numTessFaces, int numLoops, int numPolys, const struct CustomData_MeshMasks *mask); void DM_from_template(DerivedMesh *dm, DerivedMesh *source, DerivedMeshType type, int numVerts, int numEdges, int numTessFaces, int numLoops, int numPolys); /** * Utility function to release a DerivedMesh's layers * returns true if DerivedMesh has to be released by the backend, false otherwise. */ bool DM_release(DerivedMesh *dm); /** * set the #CD_FLAG_NOCOPY flag in custom data layers where the mask is * zero for the layer type, so only layer types specified by the mask * will be copied */ void DM_set_only_copy(DerivedMesh *dm, const struct CustomData_MeshMasks *mask); /* Adds a vertex/edge/face custom data layer to a DerivedMesh, optionally * backed by an external data array * alloctype defines how the layer is allocated or copied, and how it is * freed, see BKE_customdata.h for the different options. */ void DM_add_vert_layer(struct DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer); void DM_add_edge_layer(struct DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer); void DM_add_tessface_layer(struct DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer); void DM_add_loop_layer(DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer); void DM_add_poly_layer(struct DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer); /* -------------------------------------------------------------------- */ /** \name Custom Data Access Functions * * \return pointer to data from first layer which matches type * if they return NULL for valid indices, data doesn't exist. * \note these return pointers - any change modifies the internals of the mesh. * \{ */ void *DM_get_vert_data(struct DerivedMesh *dm, int index, int type); void *DM_get_edge_data(struct DerivedMesh *dm, int index, int type); void *DM_get_tessface_data(struct DerivedMesh *dm, int index, int type); void *DM_get_poly_data(struct DerivedMesh *dm, int index, int type); /** \} */ /* -------------------------------------------------------------------- */ /** \name Custom Data Layer Access Functions * * \return pointer to first data layer which matches type (a flat array) * if they return NULL, data doesn't exist. * \note these return pointers - any change modifies the internals of the mesh. * \{ */ void *DM_get_vert_data_layer(struct DerivedMesh *dm, int type); void *DM_get_edge_data_layer(struct DerivedMesh *dm, int type); void *DM_get_tessface_data_layer(struct DerivedMesh *dm, int type); void *DM_get_poly_data_layer(struct DerivedMesh *dm, int type); void *DM_get_loop_data_layer(struct DerivedMesh *dm, int type); /** \} */ /** * Custom data copy functions * copy count elements from source_index in source to dest_index in dest * these copy all layers for which the CD_FLAG_NOCOPY flag is not set. */ void DM_copy_vert_data(struct DerivedMesh *source, struct DerivedMesh *dest, int source_index, int dest_index, int count); /** * Sets up mpolys for a DM based on face iterators in source. */ void DM_DupPolys(DerivedMesh *source, DerivedMesh *target); void DM_ensure_normals(DerivedMesh *dm); /** * Ensure the array is large enough. * * \note This function must always be thread-protected by caller. * It should only be used by internal code. */ void DM_ensure_looptri_data(DerivedMesh *dm); /** * Interpolates vertex data from the vertices indexed by `src_indices` in the * source mesh using the given weights and stores the result in the vertex * indexed by `dest_index` in the `dest` mesh. */ void DM_interp_vert_data(struct DerivedMesh *source, struct DerivedMesh *dest, int *src_indices, float *weights, int count, int dest_index); void mesh_get_mapped_verts_coords(struct Mesh *me_eval, float (*r_cos)[3], int totcos); /** * Same as above but won't use render settings. */ struct Mesh *editbmesh_get_eval_cage(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *, struct BMEditMesh *em, const struct CustomData_MeshMasks *dataMask); struct Mesh *editbmesh_get_eval_cage_from_orig(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *obedit, const struct CustomData_MeshMasks *dataMask); float (*editbmesh_vert_coords_alloc(struct BMEditMesh *em, int *r_vert_len))[3]; bool editbmesh_modifier_is_enabled(struct Scene *scene, const struct Object *ob, struct ModifierData *md, bool has_prev_mesh); void makeDerivedMesh(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, const struct CustomData_MeshMasks *dataMask); #ifdef __cplusplus } #endif