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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Batt <benbatt@gmail.com>2006-08-28 05:12:36 +0400
committerBen Batt <benbatt@gmail.com>2006-08-28 05:12:36 +0400
commit433f6c7043c06d8d0330fa69f63d475549b48e91 (patch)
treed147f943e4cfcc2f0df50818e18f983772a52c22 /source/blender
parent5dbc4c5f8fda61da055a2186a5080feec96828c0 (diff)
Integration of the Google Summer of Code Modifier Stack Upgrade project. The
main features are: * Modifiers can now be in any order in the modifier stack * DerivedMesh now has a standard framework for custom element data to be passed through the stack with mesh data (being copied and interpolated as appropriate), so modifiers can access whatever data they need * The modifier stack code has been refactored and a number of bugs have been removed * The EdgeSplit modifier has been added: http://mediawiki.blender.org/index.php/BlenderDev/EdgeSplitModifier * The DerivedMesh modifier has been added: http://mediawiki.blender.org/index.php/BlenderDev/DisplaceModifier * The UVProject modifier has been added: http://mediawiki.blender.org/index.php/BlenderDev/UVProjectModifier For more info, see: http://mediawiki.blender.org/index.php/User:Artificer/ModifierStackUpgrade (currently undergoing reorganisation)
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_DerivedMesh.h388
-rw-r--r--source/blender/blenkernel/BKE_booleanops.h5
-rw-r--r--source/blender/blenkernel/BKE_cdderivedmesh.h102
-rw-r--r--source/blender/blenkernel/BKE_customdata.h161
-rw-r--r--source/blender/blenkernel/BKE_lattice.h11
-rw-r--r--source/blender/blenkernel/BKE_modifier.h309
-rw-r--r--source/blender/blenkernel/BKE_subsurf.h5
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c985
-rw-r--r--source/blender/blenkernel/intern/armature.c105
-rw-r--r--source/blender/blenkernel/intern/cdderivedmesh.c1045
-rw-r--r--source/blender/blenkernel/intern/customdata.c630
-rw-r--r--source/blender/blenkernel/intern/displist.c27
-rw-r--r--source/blender/blenkernel/intern/lattice.c133
-rw-r--r--source/blender/blenkernel/intern/modifier.c2957
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c1520
-rw-r--r--source/blender/blenlib/BLI_editVert.h4
-rw-r--r--source/blender/blenlib/BLI_linklist.h4
-rw-r--r--source/blender/blenlib/intern/BLI_linklist.c4
-rw-r--r--source/blender/blenloader/intern/readfile.c7
-rw-r--r--source/blender/makesdna/DNA_meshdata_types.h4
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h63
-rw-r--r--source/blender/python/api2_2x/Mesh.c3
-rw-r--r--source/blender/render/intern/source/texture.c32
-rw-r--r--source/blender/src/booleanops.c346
-rw-r--r--source/blender/src/buttons_editing.c227
-rw-r--r--source/blender/src/drawobject.c2
-rw-r--r--source/blender/src/editmesh.c7
-rw-r--r--source/blender/src/editmesh_mods.c44
-rw-r--r--source/blender/src/editobject.c9
29 files changed, 7867 insertions, 1272 deletions
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h
index 8b2882ca4e6..fe371c32529 100644
--- a/source/blender/blenkernel/BKE_DerivedMesh.h
+++ b/source/blender/blenkernel/BKE_DerivedMesh.h
@@ -45,142 +45,342 @@
* conversion to DLM.
*/
+#include "BKE_customdata.h"
+
struct MVert;
+struct MEdge;
+struct MFace;
struct TFace;
struct Object;
+struct Mesh;
struct EditMesh;
struct DispListMesh;
struct ModifierData;
+/* number of sub-elements each mesh element has (for interpolation) */
+#define SUB_ELEMS_VERT 0
+#define SUB_ELEMS_EDGE 2
+#define SUB_ELEMS_FACE 4
+
typedef struct DerivedMesh DerivedMesh;
struct DerivedMesh {
+ /* custom data for verts, edges & faces */
+ CustomData vertData, edgeData, faceData;
+
/* Misc. Queries */
- /* Also called in Editmode */
+ /* Also called in Editmode */
int (*getNumVerts)(DerivedMesh *dm);
- /* Also called in Editmode */
+ /* Also called in Editmode */
int (*getNumFaces)(DerivedMesh *dm);
- /* Iterate over each mapped vertex in the derived mesh, calling the
- * given function with the original vert and the mapped vert's new
- * coordinate and normal. For historical reasons the normal can be
- * passed as a float or short array, only one should be non-NULL.
- */
- void (*foreachMappedVert)(DerivedMesh *dm, void (*func)(void *userData, int index, float *co, float *no_f, short *no_s), void *userData);
-
- /* Iterate over each mapped vertex in the derived mesh, calling the
- * given function with the original vert and the mapped edge's new
- * coordinates.
- */
- void (*foreachMappedEdge)(DerivedMesh *dm, void (*func)(void *userData, int index, float *v0co, float *v1co), void *userData);
-
- /* Iterate over each mapped face in the derived mesh, calling the
- * given function with the original face and the mapped face's (or
- * faces') center and normal.
- */
- void (*foreachMappedFaceCenter)(DerivedMesh *dm, void (*func)(void *userData, int index, float *cent, float *no), void *userData);
-
- /* Convert to new DispListMesh, should be free'd by caller.
- *
- * If allowShared is true then the caller is committing to not free'ng
- * the DerivedMesh before free'ng the DispListMesh, which means that
- * certain fields of the returned DispListMesh can safely be share with
- * the DerivedMesh's internal data.
- */
- struct DispListMesh* (*convertToDispListMesh)(DerivedMesh *dm, int allowShared);
-
- /* Iterate over all vertex points, calling DO_MINMAX with given args.
- *
- * Also called in Editmode
- */
+ int (*getNumEdges)(DerivedMesh *dm);
+
+ /* copy a single vert/edge/face from the derived mesh into
+ * *{vert/edge/face}_r
+ */
+ void (*getVert)(DerivedMesh *dm, int index, struct MVert *vert_r);
+ void (*getEdge)(DerivedMesh *dm, int index, struct MEdge *edge_r);
+ void (*getFace)(DerivedMesh *dm, int index, struct MFace *face_r);
+
+ /* copy all verts/edges/faces from the derived mesh into
+ * *{vert/edge/face}_r (must point to a buffer large enough)
+ */
+ void (*getVertArray)(DerivedMesh *dm, struct MVert *vert_r);
+ void (*getEdgeArray)(DerivedMesh *dm, struct MEdge *edge_r);
+ void (*getFaceArray)(DerivedMesh *dm, struct MFace *face_r);
+
+ /* 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 *(*dupFaceArray)(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 *(*getFaceData)(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 *(*getFaceDataArray)(DerivedMesh *dm, int type);
+
+ /* Iterate over each mapped vertex in the derived mesh, calling the
+ * given function with the original vert and the mapped vert's new
+ * coordinate and normal. For historical reasons the normal can be
+ * passed as a float or short array, only one should be non-NULL.
+ */
+ void (*foreachMappedVert)(
+ DerivedMesh *dm,
+ void (*func)(void *userData, int index, float *co,
+ float *no_f, short *no_s),
+ void *userData);
+
+ /* Iterate over each mapped edge in the derived mesh, calling the
+ * given function with the original edge and the mapped edge's new
+ * coordinates.
+ */
+ void (*foreachMappedEdge)(DerivedMesh *dm,
+ void (*func)(void *userData, int index,
+ float *v0co, float *v1co),
+ void *userData);
+
+ /* Iterate over each mapped face in the derived mesh, calling the
+ * given function with the original face and the mapped face's (or
+ * faces') center and normal.
+ */
+ void (*foreachMappedFaceCenter)(DerivedMesh *dm,
+ void (*func)(void *userData, int index,
+ float *cent, float *no),
+ void *userData);
+
+ /* Convert to new DispListMesh, should be free'd by caller.
+ *
+ * If allowShared is true then the caller is committing to not free'ng
+ * the DerivedMesh before free'ng the DispListMesh, which means that
+ * certain fields of the returned DispListMesh can safely be share with
+ * the DerivedMesh's internal data.
+ */
+ struct DispListMesh* (*convertToDispListMesh)(DerivedMesh *dm,
+ int allowShared);
+
+ /* Iterate over all vertex points, calling DO_MINMAX with given args.
+ *
+ * Also called in Editmode
+ */
void (*getMinMax)(DerivedMesh *dm, float min_r[3], float max_r[3]);
/* Direct Access Operations */
/* o Can be undefined */
/* o Must be defined for modifiers that only deform however */
-
- /* Get vertex location, undefined if index is not valid */
+
+ /* Get vertex location, undefined if index is not valid */
void (*getVertCo)(DerivedMesh *dm, int index, float co_r[3]);
- /* Fill the array (of length .getNumVerts()) with all vertex locations */
+ /* Fill the array (of length .getNumVerts()) with all vertex locations */
void (*getVertCos)(DerivedMesh *dm, float (*cos_r)[3]);
- /* Get vertex normal, undefined if index is not valid */
+ /* Get vertex normal, undefined if index is not valid */
void (*getVertNo)(DerivedMesh *dm, int index, float no_r[3]);
/* Drawing Operations */
- /* Draw all vertices as bgl points (no options) */
+ /* Draw all vertices as bgl points (no options) */
void (*drawVerts)(DerivedMesh *dm);
- /* Draw edges in the UV mesh (if exists) */
+ /* Draw edges in the UV mesh (if exists) */
void (*drawUVEdges)(DerivedMesh *dm);
- /* Draw all edges as lines (no options)
- *
- * Also called for *final* editmode DerivedMeshes
- */
+ /* Draw all edges as lines (no options)
+ *
+ * Also called for *final* editmode DerivedMeshes
+ */
void (*drawEdges)(DerivedMesh *dm, int drawLooseEdges);
- /* Draw all loose edges (edges w/ no adjoining faces) */
+ /* Draw all loose edges (edges w/ no adjoining faces) */
void (*drawLooseEdges)(DerivedMesh *dm);
- /* Draw all faces
- * o Set face normal or vertex normal based on inherited face flag
- * o Use inherited face material index to call setMaterial
- * o Only if setMaterial returns true
- *
- * Also called for *final* editmode DerivedMeshes
- */
+ /* Draw all faces
+ * o Set face normal or vertex normal based on inherited face flag
+ * o Use inherited face material index to call setMaterial
+ * o Only if setMaterial returns true
+ *
+ * Also called for *final* editmode DerivedMeshes
+ */
void (*drawFacesSolid)(DerivedMesh *dm, int (*setMaterial)(int));
- /* Draw all faces
- * o If useTwoSided, draw front and back using col arrays
- * o col1,col2 are arrays of length numFace*4 of 4 component colors
- * in ABGR format, and should be passed as per-face vertex color.
- */
- void (*drawFacesColored)(DerivedMesh *dm, int useTwoSided, unsigned char *col1, unsigned char *col2);
-
- /* Draw all faces using TFace
- * o Drawing options too complicated to enumerate, look at code.
- */
- void (*drawFacesTex)(DerivedMesh *dm, int (*setDrawOptions)(struct TFace *tface, int matnr));
-
- /* Draw mapped faces (no color, or texture)
- * o Only if !setDrawOptions or setDrawOptions(userData, mapped-face-index, drawSmooth_r) returns true
- *
- * If drawSmooth is set to true then vertex normals should be set and glShadeModel
- * called with GL_SMOOTH. Otherwise the face normal should be set and glShadeModel
- * called with GL_FLAT.
- *
- * The setDrawOptions is allowed to not set drawSmooth (for example, when lighting
- * is disabled), in which case the implementation should draw as smooth shaded.
- */
- void (*drawMappedFaces)(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors);
-
- /* Draw mapped faces using TFace
- * o Drawing options too complicated to enumerate, look at code.
- */
- void (*drawMappedFacesTex)(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData);
-
- /* Draw mapped edges as lines
- * o Only if !setDrawOptions or setDrawOptions(userData, mapped-edge) returns true
- */
- void (*drawMappedEdges)(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData);
-
- /* Draw mapped edges as lines with interpolation values
- * o Only if !setDrawOptions or setDrawOptions(userData, mapped-edge, mapped-v0, mapped-v1, t) returns true
- *
- * NOTE: This routine is optional!
- */
+ /* Draw all faces
+ * o If useTwoSided, draw front and back using col arrays
+ * o col1,col2 are arrays of length numFace*4 of 4 component colors
+ * in ABGR format, and should be passed as per-face vertex color.
+ */
+ void (*drawFacesColored)(DerivedMesh *dm, int useTwoSided,
+ unsigned char *col1, unsigned char *col2);
+
+ /* Draw all faces using TFace
+ * o Drawing options too complicated to enumerate, look at code.
+ */
+ void (*drawFacesTex)(DerivedMesh *dm,
+ int (*setDrawOptions)(struct TFace *tface, int matnr));
+
+ /* Draw mapped faces (no color, or texture)
+ * o Only if !setDrawOptions or
+ * setDrawOptions(userData, mapped-face-index, drawSmooth_r)
+ * returns true
+ *
+ * If drawSmooth is set to true then vertex normals should be set and
+ * glShadeModel called with GL_SMOOTH. Otherwise the face normal should
+ * be set and glShadeModel called with GL_FLAT.
+ *
+ * The setDrawOptions is allowed to not set drawSmooth (for example, when
+ * lighting is disabled), in which case the implementation should draw as
+ * smooth shaded.
+ */
+ void (*drawMappedFaces)(DerivedMesh *dm,
+ int (*setDrawOptions)(void *userData, int index,
+ int *drawSmooth_r),
+ void *userData, int useColors);
+
+ /* Draw mapped faces using TFace
+ * o Drawing options too complicated to enumerate, look at code.
+ */
+ void (*drawMappedFacesTex)(DerivedMesh *dm,
+ int (*setDrawOptions)(void *userData,
+ int index),
+ void *userData);
+
+ /* Draw mapped edges as lines
+ * o Only if !setDrawOptions or setDrawOptions(userData, mapped-edge)
+ * returns true
+ */
+ void (*drawMappedEdges)(DerivedMesh *dm,
+ int (*setDrawOptions)(void *userData, int index),
+ void *userData);
+
+ /* Draw mapped edges as lines with interpolation values
+ * o Only if !setDrawOptions or
+ * setDrawOptions(userData, mapped-edge, mapped-v0, mapped-v1, t)
+ * returns true
+ *
+ * NOTE: This routine is optional!
+ */
void (*drawMappedEdgesInterp)(DerivedMesh *dm,
- int (*setDrawOptions)(void *userData, int index),
- void (*setDrawInterpOptions)(void *userData, int index, float t),
- void *userData);
+ int (*setDrawOptions)(void *userData,
+ int index),
+ void (*setDrawInterpOptions)(void *userData,
+ int index,
+ float t),
+ void *userData);
void (*release)(DerivedMesh *dm);
};
+/* utility function to initialise 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 initialise 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, int numVerts, int numEdges, int numFaces);
+
+/* utility function to initialise a DerivedMesh for the desired number
+ * of vertices, edges and faces, with a layer setup copied from source
+ */
+void DM_from_template(DerivedMesh *dm, DerivedMesh *source,
+ int numVerts, int numEdges, int numFaces);
+
+/* utility function to release a DerivedMesh's layers
+ */
+void DM_release(DerivedMesh *dm);
+
+/* utility function to convert a DerivedMesh to a Mesh
+ */
+void DM_to_mesh(DerivedMesh *dm, struct Mesh *me);
+
+/* adds a vertex/edge/face custom data layer to a DerivedMesh, optionally
+ * backed by an external data array
+ * if layer != NULL, it is used as the layer data array, otherwise new memory
+ * is allocated
+ * the layer data will be freed by dm->release unless
+ * (flag & LAYERFLAG_NOFREE) is true
+ */
+void DM_add_vert_layer(struct DerivedMesh *dm, int type, int flag,
+ void *layer);
+void DM_add_edge_layer(struct DerivedMesh *dm, int type, int flag,
+ void *layer);
+void DM_add_face_layer(struct DerivedMesh *dm, int type, int flag,
+ void *layer);
+
+/* 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_face_data(struct DerivedMesh *dm, int index, int type);
+
+/* 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_face_data_layer(struct DerivedMesh *dm, int type);
+
+/* custom data setting functions
+ * copy supplied data into first layer of type using layer's copy function
+ * (deep copy if appropriate)
+ */
+void DM_set_vert_data(struct DerivedMesh *dm, int index, int type, void *data);
+void DM_set_edge_data(struct DerivedMesh *dm, int index, int type, void *data);
+void DM_set_face_data(struct DerivedMesh *dm, int index, int type, void *data);
+
+/* custom data copy functions
+ * copy count elements from source_index in source to dest_index in dest
+ * these copy all layers for which the LAYERFLAG_NOCOPY flag is not set
+ */
+void DM_copy_vert_data(struct DerivedMesh *source, struct DerivedMesh *dest,
+ int source_index, int dest_index, int count);
+void DM_copy_edge_data(struct DerivedMesh *source, struct DerivedMesh *dest,
+ int source_index, int dest_index, int count);
+void DM_copy_face_data(struct DerivedMesh *source, struct DerivedMesh *dest,
+ int source_index, int dest_index, int count);
+
+/* custom data free functions
+ * free count elements, starting at index
+ * they free all layers for which the LAYERFLAG_NOFREE flag is not set
+ */
+void DM_free_vert_data(struct DerivedMesh *dm, int index, int count);
+void DM_free_edge_data(struct DerivedMesh *dm, int index, int count);
+void DM_free_face_data(struct DerivedMesh *dm, int index, int count);
+
+/* 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);
+
+/* interpolates edge data from the edges indexed by src_indices in the
+ * source mesh using the given weights and stores the result in the edge indexed
+ * by dest_index in the dest mesh.
+ * if weights is NULL, all weights default to 1.
+ * if vert_weights is non-NULL, any per-vertex edge data is interpolated using
+ * vert_weights[i] multiplied by weights[i].
+ */
+typedef float EdgeVertWeight[SUB_ELEMS_EDGE][SUB_ELEMS_EDGE];
+void DM_interp_edge_data(struct DerivedMesh *source, struct DerivedMesh *dest,
+ int *src_indices,
+ float *weights, EdgeVertWeight *vert_weights,
+ int count, int dest_index);
+
+/* interpolates face data from the faces indexed by src_indices in the
+ * source mesh using the given weights and stores the result in the face indexed
+ * by dest_index in the dest mesh.
+ * if weights is NULL, all weights default to 1.
+ * if vert_weights is non-NULL, any per-vertex face data is interpolated using
+ * vert_weights[i] multiplied by weights[i].
+ */
+typedef float FaceVertWeight[SUB_ELEMS_FACE][SUB_ELEMS_FACE];
+void DM_interp_face_data(struct DerivedMesh *source, struct DerivedMesh *dest,
+ int *src_indices,
+ float *weights, FaceVertWeight *vert_weights,
+ int count, int dest_index);
+
/* Simple function to get me->totvert amount of vertices/normals,
correctly deformed and subsurfered. Needed especially when vertexgroups are involved.
In use now by vertex/weigt paint and particles */
diff --git a/source/blender/blenkernel/BKE_booleanops.h b/source/blender/blenkernel/BKE_booleanops.h
index f033dd70003..ddc24457ef4 100644
--- a/source/blender/blenkernel/BKE_booleanops.h
+++ b/source/blender/blenkernel/BKE_booleanops.h
@@ -57,7 +57,10 @@ NewBooleanMesh(
struct DispListMesh *NewBooleanMeshDLM(struct Object *ob, struct Object *ob_select, int int_op_type);
-
+struct DerivedMesh *NewBooleanDerivedMesh(struct Object *ob,
+ struct Object *ob_select,
+ int int_op_type);
+
/**
* Functions exposed for use by BKE_booleanops_mesh
*/
diff --git a/source/blender/blenkernel/BKE_cdderivedmesh.h b/source/blender/blenkernel/BKE_cdderivedmesh.h
new file mode 100644
index 00000000000..b8313440551
--- /dev/null
+++ b/source/blender/blenkernel/BKE_cdderivedmesh.h
@@ -0,0 +1,102 @@
+/*
+* $Id$
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* The Original Code is Copyright (C) 2006 Blender Foundation.
+* All rights reserved.
+*
+* The Original Code is: all of this file.
+*
+* Contributor(s): Ben Batt <benbatt@gmail.com>
+*
+* ***** END GPL LICENSE BLOCK *****
+*/
+
+/* CDDerivedMesh interface.
+ * CDDerivedMesh (CD = Custom Data) is a DerivedMesh backend which stores
+ * mesh elements (vertices, edges and faces) as layers of custom element data.
+ */
+
+#ifndef BKE_CDDERIVEDMESH_H
+#define BKE_CDDERIVEDMESH_H
+
+#include "BKE_DerivedMesh.h"
+
+struct DerivedMesh;
+struct EditMesh;
+struct Mesh;
+
+/* creates a new CDDerivedMesh */
+struct DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces);
+
+/* creates a CDDerivedMesh from the given Mesh */
+struct DerivedMesh *CDDM_from_mesh(struct Mesh *mesh);
+
+/* creates a CDDerivedMesh from the given EditMesh */
+struct DerivedMesh *CDDM_from_editmesh(struct EditMesh *em, struct Mesh *me);
+
+/* Copies the given DerivedMesh with verts, faces & edges stored as
+ * custom element data.
+ */
+struct DerivedMesh *CDDM_copy(struct DerivedMesh *dm);
+
+/* creates a CDDerivedMesh with the same layer stack configuration as the
+ * given DerivedMesh and containing the requested numbers of elements.
+ * elements are initialised to all zeros
+ */
+struct DerivedMesh *CDDM_from_template(struct DerivedMesh *source,
+ int numVerts, int numEdges, int numFaces);
+
+/* applies vertex coordinates to a CDDerivedMesh
+ */
+void CDDM_apply_vert_coords(struct DerivedMesh *cddm, float (*vertCoords)[3]);
+
+/* recalculates normals for a CDDerivedMesh
+ */
+void CDDM_calc_normals(struct DerivedMesh *dm);
+
+/* calculates edges for a CDDerivedMesh (from face data)
+ * this completely replaces the current edge data in the DerivedMesh
+ */
+void CDDM_calc_edges(struct DerivedMesh *dm);
+
+/* sets the number of vertices/edges/faces in a CDDerivedMesh
+ * if the value given is more than the maximum, the maximum is used
+ */
+void CDDM_set_num_verts(struct DerivedMesh *dm, int numVerts);
+void CDDM_set_num_edges(struct DerivedMesh *dm, int numEdges);
+void CDDM_set_num_faces(struct DerivedMesh *dm, int numFaces);
+
+/* vertex/edge/face access functions
+ * should always succeed if index is within bounds
+ * note these return pointers - any change modifies the internals of the mesh
+ */
+struct MVert *CDDM_get_vert(struct DerivedMesh *dm, int index);
+struct MEdge *CDDM_get_edge(struct DerivedMesh *dm, int index);
+struct MFace *CDDM_get_face(struct DerivedMesh *dm, int index);
+
+/* vertex/edge/face array access functions - return the array holding the
+ * desired data
+ * should always succeed
+ * note these return pointers - any change modifies the internals of the mesh
+ */
+struct MVert *CDDM_get_verts(struct DerivedMesh *dm);
+struct MEdge *CDDM_get_edges(struct DerivedMesh *dm);
+struct MFace *CDDM_get_faces(struct DerivedMesh *dm);
+#endif
+
diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h
new file mode 100644
index 00000000000..6f8d9911d89
--- /dev/null
+++ b/source/blender/blenkernel/BKE_customdata.h
@@ -0,0 +1,161 @@
+/*
+* $Id$
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* The Original Code is Copyright (C) 2006 Blender Foundation.
+* All rights reserved.
+*
+* The Original Code is: all of this file.
+*
+* Contributor(s): Ben Batt <benbatt@gmail.com>
+*
+* ***** END GPL LICENSE BLOCK *****
+*/
+
+/* CustomData interface.
+ * CustomData is a structure which stores custom element data associated
+ * with mesh elements (vertices, edges or faces). The custom data is
+ * organised into a series of layers, each with a data type (e.g. TFace,
+ * MDeformVert, etc.).
+ */
+
+#ifndef BKE_CUSTOMDATA_H
+#define BKE_CUSTOMDATA_H
+
+typedef struct CustomData {
+ struct LayerDesc *layers; /* data layer descriptors, ordered by type */
+ int numLayers; /* current number of layers */
+ int maxLayers; /* maximum number of layers */
+ int numElems; /* current number of elements */
+ int maxElems; /* maximum number of elements */
+ int subElems; /* number of sub-elements layers can have */
+} CustomData;
+
+/* custom data types */
+enum {
+ LAYERTYPE_MVERT = 0,
+ LAYERTYPE_MSTICKY,
+ LAYERTYPE_MDEFORMVERT,
+ LAYERTYPE_MEDGE,
+ LAYERTYPE_MFACE,
+ LAYERTYPE_TFACE,
+ LAYERTYPE_MCOL,
+ LAYERTYPE_ORIGINDEX,
+ LAYERTYPE_NORMAL,
+ LAYERTYPE_FLAGS,
+ LAYERTYPE_NUMTYPES
+};
+
+#define ORIGINDEX_NONE -1 /* indicates no original index for this element */
+
+/* layer flags - to be used with CustomData_add_layer */
+
+/* indicates layer should not be copied by CustomData_from_template or
+ * CustomData_copy_data (for temporary utility layers)
+ */
+#define LAYERFLAG_NOCOPY 1<<0
+
+/* indicates layer should not be freed (for layers backed by external data)
+ */
+#define LAYERFLAG_NOFREE 1<<1
+
+/* initialises a CustomData object with space for the given number
+ * of data layers and the given number of elements per layer
+ */
+void CustomData_init(CustomData *data,
+ int maxLayers, int maxElems, int subElems);
+
+/* initialises a CustomData object with the same layer setup as source
+ * and memory space for maxElems elements
+ */
+void CustomData_from_template(const CustomData *source, CustomData *dest,
+ int maxElems);
+
+/* frees data associated with a CustomData object (doesn't free the object
+ * itself, though)
+ */
+void CustomData_free(CustomData *data);
+
+/* adds a data layer of the given type to the CustomData object, optionally
+ * backed by an external data array
+ * if layer != NULL, it is used as the layer data array, otherwise new memory
+ * is allocated
+ * the layer data will be freed by CustomData_free unless
+ * (flag & LAYERFLAG_NOFREE) is true
+ * grows the number of layers in data if data->maxLayers has been reached
+ * returns 1 on success, 0 on failure
+ */
+int CustomData_add_layer(CustomData *data, int type, int flag, void *layer);
+
+/* returns 1 if the two objects are compatible (same layer types and
+ * flags in the same order), 0 if not
+ */
+int CustomData_compat(const CustomData *data1, const CustomData *data2);
+
+/* copies data from one CustomData object to another
+ * objects need not be compatible, each source layer is copied to the
+ * first dest layer of correct type (if there is none, the layer is skipped)
+ * return 1 on success, 0 on failure
+ */
+int CustomData_copy_data(const CustomData *source, CustomData *dest,
+ int source_index, int dest_index, int count);
+
+/* frees data in a CustomData object
+ * return 1 on success, 0 on failure
+ */
+int CustomData_free_elem(CustomData *data, int index, int count);
+
+/* interpolates data from one CustomData object to another
+ * objects need not be compatible, each source layer is interpolated to the
+ * first dest layer of correct type (if there is none, the layer is skipped)
+ * if weights == NULL or sub_weights == NULL, they default to all 1's
+ *
+ * src_indices gives the source elements to interpolate from
+ * weights gives the weight for each source element
+ * sub_weights is an array of matrices of weights for sub-elements (matrices
+ * should be source->subElems * source->subElems in size)
+ * count gives the number of source elements to interpolate from
+ * dest_index gives the dest element to write the interpolated value to
+ *
+ * returns 1 on success, 0 on failure
+ */
+int CustomData_interp(const CustomData *source, CustomData *dest,
+ int *src_indices, float *weights, float *sub_weights,
+ int count, int dest_index);
+
+/* gets a pointer to the data element at index from the first layer of type
+ * returns NULL if there is no layer of type
+ */
+void *CustomData_get(const CustomData *data, int index, int type);
+
+/* gets a pointer to the first layer of type
+ * returns NULL if there is no layer of type
+ */
+void *CustomData_get_layer(const CustomData *data, int type);
+
+/* copies the data from source to the data element at index in the first
+ * layer of type
+ * no effect if there is no layer of type
+ */
+void CustomData_set(const CustomData *data, int index, int type, void *source);
+
+/* sets the number of elements in a CustomData object
+ * if the value given is more than the maximum, the maximum is used
+ */
+void CustomData_set_num_elems(CustomData *data, int numElems);
+#endif
diff --git a/source/blender/blenkernel/BKE_lattice.h b/source/blender/blenkernel/BKE_lattice.h
index 2f7ae6bb329..a7533a614eb 100644
--- a/source/blender/blenkernel/BKE_lattice.h
+++ b/source/blender/blenkernel/BKE_lattice.h
@@ -36,6 +36,7 @@
struct Lattice;
struct Object;
+struct DerivedMesh;
struct BPoint;
extern struct Lattice *editLatt;
@@ -52,9 +53,13 @@ void calc_latt_deform(float *co, float weight);
void end_latt_deform(void);
int object_deform_mball(struct Object *ob);
void outside_lattice(struct Lattice *lt);
-void curve_deform_verts(struct Object *cuOb, struct Object *target, float (*vertexCos)[3], int numVerts, char *vgroup);
-void lattice_deform_verts(struct Object *laOb, struct Object *target, float (*vertexCos)[3], int numVerts, char *vgroup);
-void armature_deform_verts(struct Object *armOb, struct Object *target, float (*vertexCos)[3], int numVerts, int deformflag);
+void curve_deform_verts(struct Object *cuOb, struct Object *target, struct DerivedMesh *dm, float (*vertexCos)[3], int numVerts, char *vgroup);
+void lattice_deform_verts(struct Object *laOb, struct Object *target,
+ struct DerivedMesh *dm, float (*vertexCos)[3],
+ int numVerts, char *vgroup);
+void armature_deform_verts(struct Object *armOb, struct Object *target,
+ struct DerivedMesh *dm, float (*vertexCos)[3],
+ int numVerts, int deformflag);
float (*lattice_getVertexCos(struct Object *ob, int *numVerts_r))[3];
void lattice_applyVertexCos(struct Object *ob, float (*vertexCos)[3]);
void lattice_calc_modifiers(struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h
index 9afefbfc5a9..a4c050429e5 100644
--- a/source/blender/blenkernel/BKE_modifier.h
+++ b/source/blender/blenkernel/BKE_modifier.h
@@ -33,6 +33,7 @@
#ifndef BKE_MODIFIER_H
#define BKE_MODIFIER_H
+struct EditMesh;
struct DerivedMesh;
struct DagForest;
struct DagNode;
@@ -41,14 +42,14 @@ struct ListBase;
struct bArmature;
typedef enum {
- /* Should not be used, only for None modifier type */
+ /* Should not be used, only for None modifier type */
eModifierTypeType_None,
- /* Modifier only does deformation, implies that modifier
- * type should have a valid deformVerts function. OnlyDeform
- * style modifiers implicitly accept either mesh or CV
- * input but should still declare flags appropriately.
- */
+ /* Modifier only does deformation, implies that modifier
+ * type should have a valid deformVerts function. OnlyDeform
+ * style modifiers implicitly accept either mesh or CV
+ * input but should still declare flags appropriately.
+ */
eModifierTypeType_OnlyDeform,
eModifierTypeType_Constructive,
@@ -56,165 +57,203 @@ typedef enum {
} ModifierTypeType;
typedef enum {
- eModifierTypeFlag_AcceptsMesh = (1<<0),
- eModifierTypeFlag_AcceptsCVs = (1<<1),
- eModifierTypeFlag_SupportsMapping = (1<<2),
- eModifierTypeFlag_SupportsEditmode = (1<<3),
-
- /* For modifiers that support editmode this determines if the
- * modifier should be enabled by default in editmode. This should
- * only be used by modifiers that are relatively speedy and
- * also generally used in editmode, otherwise let the user enable
- * it by hand.
- */
- eModifierTypeFlag_EnableInEditmode = (1<<4),
-
- /* For modifiers that require original data and so cannot
- * be placed after any non-deformative modifier.
- */
+ eModifierTypeFlag_AcceptsMesh = (1<<0),
+ eModifierTypeFlag_AcceptsCVs = (1<<1),
+ eModifierTypeFlag_SupportsMapping = (1<<2),
+ eModifierTypeFlag_SupportsEditmode = (1<<3),
+
+ /* For modifiers that support editmode this determines if the
+ * modifier should be enabled by default in editmode. This should
+ * only be used by modifiers that are relatively speedy and
+ * also generally used in editmode, otherwise let the user enable
+ * it by hand.
+ */
+ eModifierTypeFlag_EnableInEditmode = (1<<4),
+
+ /* For modifiers that require original data and so cannot
+ * be placed after any non-deformative modifier.
+ */
eModifierTypeFlag_RequiresOriginalData = (1<<5),
} ModifierTypeFlag;
+typedef void (*ObjectWalkFunc)(void *userData, Object *ob, Object **obpoin);
+typedef void (*IDWalkFunc)(void *userData, Object *ob, ID **idpoin);
+
typedef struct ModifierTypeInfo {
- /* The user visible name for this modifier */
+ /* The user visible name for this modifier */
char name[32];
- /* The DNA struct name for the modifier data type, used to
- * write the DNA data out.
- */
+ /* The DNA struct name for the modifier data type, used to
+ * write the DNA data out.
+ */
char structName[32];
- /* The size of the modifier data type, used by allocation. */
+ /* The size of the modifier data type, used by allocation. */
int structSize;
ModifierTypeType type;
ModifierTypeFlag flags;
- /* Initialize new instance data for this modifier type, this function
- * should set modifier variables to their default values.
- *
- * This function is optional.
- */
- void (*initData)(ModifierData *md);
- /* Copy instance data for this modifier type. Should copy all user
- * level settings to the target modifier.
- */
+ /********************* Non-optional functions *********************/
+
+ /* Copy instance data for this modifier type. Should copy all user
+ * level settings to the target modifier.
+ */
void (*copyData)(ModifierData *md, ModifierData *target);
- /* Free internal modifier data variables, this function should
- * not free the _md_ variable itself.
- *
- * This function is optional.
- */
+
+ /********************* Deform modifier functions *********************/
+
+ /* Only for deform types, should apply the deformation
+ * to the given vertex array. If the deformer requires information from
+ * the object it can obtain it from the derivedData argument if non-NULL,
+ * and otherwise the ob argument.
+ */
+ void (*deformVerts)(ModifierData *md, struct Object *ob,
+ struct DerivedMesh *derivedData,
+ float (*vertexCos)[3], int numVerts);
+
+ /* Like deformVerts but called during editmode (for supporting modifiers)
+ */
+ void (*deformVertsEM)(
+ ModifierData *md, struct Object *ob,
+ struct EditMesh *editData, struct DerivedMesh *derivedData,
+ float (*vertexCos)[3], int numVerts);
+
+
+ /********************* Non-deform modifier functions *********************/
+
+ /* For non-deform types: apply the modifier and return a derived
+ * data object (type is dependent on object type).
+ *
+ * The derivedData argument should always be non-NULL; the modifier
+ * should read the object data from the derived object instead of the
+ * actual object data.
+ *
+ * The useRenderParams argument indicates if the modifier is being
+ * applied in the service of the renderer which may alter quality
+ * settings.
+ *
+ * The isFinalCalc parameter indicates if the modifier is being
+ * calculated for a final result or for something temporary
+ * (like orcos). This is a hack at the moment, it is meant so subsurf
+ * can know if it is safe to reuse its internal cache.
+ *
+ * The modifier may reuse the derivedData argument (i.e. return it in
+ * modified form), but must not release it.
+ */
+ struct DerivedMesh *(*applyModifier)(
+ ModifierData *md, struct Object *ob,
+ struct DerivedMesh *derivedData,
+ int useRenderParams, int isFinalCalc);
+
+ /* Like applyModifier but called during editmode (for supporting
+ * modifiers).
+ *
+ * The derived object that is returned must support the operations that
+ * are expected from editmode objects. The same qualifications regarding
+ * derivedData apply as for applyModifier.
+ */
+ struct DerivedMesh *(*applyModifierEM)(
+ ModifierData *md, struct Object *ob,
+ struct EditMesh *editData,
+ struct DerivedMesh *derivedData);
+
+
+ /********************* Optional functions *********************/
+
+ /* Initialize new instance data for this modifier type, this function
+ * should set modifier variables to their default values.
+ *
+ * This function is optional.
+ */
+ void (*initData)(ModifierData *md);
+
+ /* Free internal modifier data variables, this function should
+ * not free the md variable itself.
+ *
+ * This function is optional.
+ */
void (*freeData)(ModifierData *md);
- /* Return a boolean value indicating if this modifier is able to be calculated
- * based on the modifier data. This is *not* regarding the md->flag, that is
- * tested by the system, this is just if the data validates (for example, a
- * lattice will return false if the lattice object is not defined).
- *
- * This function is optional (assumes never disabled if not present).
- */
+ /* Return a boolean value indicating if this modifier is able to be
+ * calculated based on the modifier data. This is *not* regarding the
+ * md->flag, that is tested by the system, this is just if the data
+ * validates (for example, a lattice will return false if the lattice
+ * object is not defined).
+ *
+ * This function is optional (assumes never disabled if not present).
+ */
int (*isDisabled)(ModifierData *md);
- /* Add the appropriate relations to the DEP graph depending on the modifier
- * data.
- *
- * This function is optional.
- */
- void (*updateDepgraph)(ModifierData *md, struct DagForest *forest, struct Object *ob, struct DagNode *obNode);
-
- /* Should return true if the modifier needs to be recalculated on time changes.
- *
- * This function is optional (assumes false if not present).
- */
- int (*dependsOnTime)(ModifierData *md);
+ /* Add the appropriate relations to the DEP graph depending on the
+ * modifier data.
+ *
+ * This function is optional.
+ */
+ void (*updateDepgraph)(ModifierData *md, struct DagForest *forest,
+ struct Object *ob, struct DagNode *obNode);
- /* Should call the given _walk_ function on with a pointer to each Object pointer
- * that the modifier data stores. This is used for linking on file load and for
- * unlinking objects or forwarding object references.
- *
- * This function is optional.
- */
- void (*foreachObjectLink)(ModifierData *md, struct Object *ob, void (*walk)(void *userData, Object *ob, Object **obpoin), void *userData);
-
- /* Only for deform types, should apply the deformation
- * to the given vertex array. If the deformer requires information from
- * the object it can obtain it from the _derivedData_ argument if non-NULL,
- * and otherwise the _ob_ argument.
- */
- void (*deformVerts)(ModifierData *md, struct Object *ob, void *derivedData, float (*vertexCos)[3], int numVerts);
-
- /* Like deformVerts but called during editmode (for supporting modifiers) */
- void (*deformVertsEM)(ModifierData *md, struct Object *ob, void *editData, void *derivedData, float (*vertexCos)[3], int numVerts);
-
- /* For non-deform types: apply the modifier and return a new derived
- * data object (type is dependent on object type). If the _derivedData_
- * argument is non-NULL then the modifier should read the object data
- * from the derived object instead of the actual object data.
- *
- * If the _vertexCos_ argument is non-NULL then the modifier should read
- * the vertex coordinates from that (even if _derivedData_ is non-NULL).
- * The length of the _vertexCos_ array is either the number of verts in
- * the derived object (if non-NULL) or otherwise the number of verts in
- * the original object.
- *
- * The _useRenderParams_ indicates if the modifier is being applied in
- * the service of the renderer which may alter quality settings.
- *
- * The _isFinalCalc_ parameter indicates if the modifier is being calculated
- * for a final result or for something temporary (like orcos). This is a hack
- * at the moment, it is meant so subsurf can know if it is safe to reuse its
- * internal cache.
- *
- * The modifier *MAY NOT* reuse or release the _derivedData_ argument
- * if non-NULL. The modifier *MAY NOT* share the _vertexCos_ argument.
- */
- void *(*applyModifier)(ModifierData *md, struct Object *ob, void *derivedData, float (*vertexCos)[3], int useRenderParams, int isFinalCalc);
-
- /* Like applyModifier but called during editmode (for supporting modifiers).
- *
- * The derived object that is returned must support the operations that are expected
- * from editmode objects. The same qualifications regarding _derivedData_ and _vertexCos_
- * apply as for applyModifier.
- */
- void *(*applyModifierEM)(ModifierData *md, struct Object *ob, void *editData, void *derivedData, float (*vertexCos)[3]);
-} ModifierTypeInfo;
+ /* Should return true if the modifier needs to be recalculated on time
+ * changes.
+ *
+ * This function is optional (assumes false if not present).
+ */
+ int (*dependsOnTime)(ModifierData *md);
-ModifierTypeInfo* modifierType_getInfo (ModifierType type);
+ /* Should call the given walk function on with a pointer to each Object
+ * pointer that the modifier data stores. This is used for linking on file
+ * load and for unlinking objects or forwarding object references.
+ *
+ * This function is optional.
+ */
+ void (*foreachObjectLink)(ModifierData *md, struct Object *ob,
+ ObjectWalkFunc walk, void *userData);
- /* Modifier utility calls, do call through type pointer and return
- * default values if pointer is optional.
+ /* Should call the given walk function with a pointer to each ID
+ * pointer (i.e. each datablock pointer) that the modifier data
+ * stores. This is used for linking on file load and for
+ * unlinking datablocks or forwarding datablock references.
+ *
+ * This function is optional. If it is not present, foreachObjectLink
+ * will be used.
*/
-ModifierData* modifier_new (int type);
-void modifier_free (ModifierData *md);
+ void (*foreachIDLink)(ModifierData *md, struct Object *ob,
+ IDWalkFunc walk, void *userData);
+} ModifierTypeInfo;
-void modifier_copyData (ModifierData *md, ModifierData *target);
-int modifier_dependsOnTime (ModifierData *md);
-int modifier_supportsMapping (ModifierData *md);
-int modifier_couldBeCage (ModifierData *md);
-void modifier_setError (ModifierData *md, char *format, ...);
+ModifierTypeInfo *modifierType_getInfo (ModifierType type);
-void modifiers_foreachObjectLink (struct Object *ob, void (*walk)(void *userData, struct Object *ob, struct Object **obpoin), void *userData);
-ModifierData* modifiers_findByType (struct Object *ob, ModifierType type);
-void modifiers_clearErrors (struct Object *ob);
-int modifiers_getCageIndex (struct Object *ob, int *lastPossibleCageIndex_r);
+/* Modifier utility calls, do call through type pointer and return
+ * default values if pointer is optional.
+ */
+ModifierData *modifier_new(int type);
+void modifier_free(ModifierData *md);
-int modifiers_isSoftbodyEnabled (struct Object *ob);
-struct Object* modifiers_isDeformedByArmature(struct Object *ob);
-int modifiers_usesArmature(struct Object *ob, struct bArmature *arm);
-int modifiers_isDeformed (struct Object *ob);
+void modifier_copyData(ModifierData *md, ModifierData *target);
+int modifier_dependsOnTime(ModifierData *md);
+int modifier_supportsMapping(ModifierData *md);
+int modifier_couldBeCage(ModifierData *md);
+void modifier_setError(ModifierData *md, char *format, ...);
-ModifierData* modifiers_getVirtualModifierList (struct Object *ob);
+void modifiers_foreachObjectLink(struct Object *ob,
+ ObjectWalkFunc walk,
+ void *userData);
+void modifiers_foreachIDLink(struct Object *ob,
+ IDWalkFunc walk,
+ void *userData);
+ModifierData *modifiers_findByType(struct Object *ob, ModifierType type);
+void modifiers_clearErrors(struct Object *ob);
+int modifiers_getCageIndex(struct Object *ob,
+ int *lastPossibleCageIndex_r);
- /* Modifier utility calls, do call through type pointer and return
- * default values if pointer is optional.
- */
-struct ModifierData* modifier_new (int type);
-void modifier_free (struct ModifierData *md);
+int modifiers_isSoftbodyEnabled(struct Object *ob);
+struct Object *modifiers_isDeformedByArmature(struct Object *ob);
+int modifiers_usesArmature(struct Object *ob, struct bArmature *arm);
+int modifiers_isDeformed(struct Object *ob);
-int modifier_dependsOnTime (struct ModifierData *md);
+ModifierData *modifiers_getVirtualModifierList(struct Object *ob);
#endif
diff --git a/source/blender/blenkernel/BKE_subsurf.h b/source/blender/blenkernel/BKE_subsurf.h
index 2289fb027eb..3d1ffd3e52f 100644
--- a/source/blender/blenkernel/BKE_subsurf.h
+++ b/source/blender/blenkernel/BKE_subsurf.h
@@ -40,6 +40,11 @@ struct SubsurfModifierData;
struct DerivedMesh *subsurf_make_derived_from_editmesh(struct EditMesh *em, struct SubsurfModifierData *smd, float (*vertexCos)[3]);
struct DerivedMesh *subsurf_make_derived_from_dlm_em(struct DispListMesh *dlm, struct SubsurfModifierData *smd, float (*vertCos)[3]);
struct DerivedMesh *subsurf_make_derived_from_mesh(struct Mesh *me, struct DispListMesh *dlm, struct SubsurfModifierData *smd, int useRenderParams, float (*vertCos)[3], int isFinalCalc);
+struct DerivedMesh *subsurf_make_derived_from_derived(
+ struct DerivedMesh *dm,
+ struct SubsurfModifierData *smd,
+ int useRenderParams, float (*vertCos)[3],
+ int isFinalCalc, int editMode);
void subsurf_calculate_limit_positions(Mesh *me, float (*positions_r)[3]);
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index 4187e5c0320..016d5c298c3 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -44,6 +44,7 @@
#include "DNA_effect_types.h"
#include "DNA_mesh_types.h"
+#include "DNA_key_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
@@ -56,6 +57,7 @@
#include "BLI_editVert.h"
#include "BKE_utildefines.h"
+#include "BKE_cdderivedmesh.h"
#include "BKE_DerivedMesh.h"
#include "BKE_displist.h"
#include "BKE_effect.h"
@@ -82,6 +84,269 @@
///////////////////////////////////
///////////////////////////////////
+#define DERIVEDMESH_INITIAL_LAYERS 5
+
+MVert *dm_dupVertArray(DerivedMesh *dm)
+{
+ MVert *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumVerts(dm),
+ "dm_dupVertArray tmp");
+
+ if(tmp) dm->getVertArray(dm, tmp);
+
+ return tmp;
+}
+
+MEdge *dm_dupEdgeArray(DerivedMesh *dm)
+{
+ MEdge *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumEdges(dm),
+ "dm_dupEdgeArray tmp");
+
+ if(tmp) dm->getEdgeArray(dm, tmp);
+
+ return tmp;
+}
+
+MFace *dm_dupFaceArray(DerivedMesh *dm)
+{
+ MFace *tmp = MEM_callocN(sizeof(*tmp) * dm->getNumFaces(dm),
+ "dm_dupFaceArray tmp");
+
+ if(tmp) dm->getFaceArray(dm, tmp);
+
+ return tmp;
+}
+
+void DM_init_funcs(DerivedMesh *dm)
+{
+ /* default function implementations */
+ dm->dupVertArray = dm_dupVertArray;
+ dm->dupEdgeArray = dm_dupEdgeArray;
+ dm->dupFaceArray = dm_dupFaceArray;
+
+ dm->getVertData = DM_get_vert_data;
+ dm->getEdgeData = DM_get_edge_data;
+ dm->getFaceData = DM_get_face_data;
+ dm->getVertDataArray = DM_get_vert_data_layer;
+ dm->getEdgeDataArray = DM_get_edge_data_layer;
+ dm->getFaceDataArray = DM_get_face_data_layer;
+}
+
+void DM_init(DerivedMesh *dm,
+ int numVerts, int numEdges, int numFaces)
+{
+ if(numVerts > 0) {
+ CustomData_init(&dm->vertData, DERIVEDMESH_INITIAL_LAYERS, numVerts,
+ SUB_ELEMS_VERT);
+ CustomData_init(&dm->edgeData, DERIVEDMESH_INITIAL_LAYERS, numEdges,
+ SUB_ELEMS_EDGE);
+ CustomData_init(&dm->faceData, DERIVEDMESH_INITIAL_LAYERS, numFaces,
+ SUB_ELEMS_FACE);
+
+ CustomData_add_layer(&dm->vertData, LAYERTYPE_ORIGINDEX, 0, NULL);
+ CustomData_add_layer(&dm->edgeData, LAYERTYPE_ORIGINDEX, 0, NULL);
+ CustomData_add_layer(&dm->faceData, LAYERTYPE_ORIGINDEX, 0, NULL);
+ }
+
+ DM_init_funcs(dm);
+}
+
+void DM_from_template(DerivedMesh *dm, DerivedMesh *source,
+ int numVerts, int numEdges, int numFaces)
+{
+ if(numVerts > 0) {
+ CustomData_from_template(&source->vertData, &dm->vertData, numVerts);
+ CustomData_from_template(&source->edgeData, &dm->edgeData, numEdges);
+ CustomData_from_template(&source->faceData, &dm->faceData, numFaces);
+ }
+
+ DM_init_funcs(dm);
+}
+
+void DM_release(DerivedMesh *dm)
+{
+ CustomData_free(&dm->vertData);
+ CustomData_free(&dm->edgeData);
+ CustomData_free(&dm->faceData);
+}
+
+void DM_to_mesh(DerivedMesh *dm, Mesh *me)
+{
+ /* dm might depend on me, so we need to do everything with a local copy */
+ Mesh tmp_me = *me;
+ int numVerts = dm->getNumVerts(dm);
+
+ tmp_me.dvert = NULL;
+ tmp_me.tface = NULL;
+ tmp_me.mcol = NULL;
+
+ tmp_me.totvert = numVerts;
+ tmp_me.totedge = dm->getNumEdges(dm);
+ tmp_me.totface = dm->getNumFaces(dm);
+
+ tmp_me.mvert = dm->dupVertArray(dm);
+ tmp_me.medge = dm->dupEdgeArray(dm);
+ tmp_me.mface = dm->dupFaceArray(dm);
+
+ if(dm->getFaceDataArray(dm, LAYERTYPE_TFACE))
+ tmp_me.tface = MEM_dupallocN(dm->getFaceDataArray(dm,
+ LAYERTYPE_TFACE));
+ if(dm->getFaceDataArray(dm, LAYERTYPE_MCOL))
+ tmp_me.mcol = MEM_dupallocN(dm->getFaceDataArray(dm,
+ LAYERTYPE_MCOL));
+ if(dm->getVertDataArray(dm, LAYERTYPE_MDEFORMVERT)) {
+ int i;
+ MDeformVert *dv;
+
+ tmp_me.dvert = MEM_dupallocN(
+ dm->getVertDataArray(dm, LAYERTYPE_MDEFORMVERT));
+
+ for(i = 0, dv = tmp_me.dvert; i < numVerts; ++i, ++dv)
+ dv->dw = MEM_dupallocN(dv->dw);
+ }
+
+ if(me->mvert) MEM_freeN(me->mvert);
+ if(me->dvert) free_dverts(me->dvert, me->totvert);
+ if(me->mface) MEM_freeN(me->mface);
+ if(me->tface) MEM_freeN(me->tface);
+ if(me->mcol) MEM_freeN(me->mcol);
+ if(me->medge) MEM_freeN(me->medge);
+
+ /* if the number of verts has changed, remove invalid data */
+ if(numVerts != me->totvert) {
+ if(me->msticky) MEM_freeN(me->msticky);
+ me->msticky = NULL;
+
+ if(me->key) me->key->id.us--;
+ me->key = NULL;
+ }
+
+ *me = tmp_me;
+}
+
+void DM_add_vert_layer(DerivedMesh *dm, int type, int flag, void *layer)
+{
+ CustomData_add_layer(&dm->vertData, type, flag, layer);
+}
+
+void DM_add_edge_layer(DerivedMesh *dm, int type, int flag, void *layer)
+{
+ CustomData_add_layer(&dm->edgeData, type, flag, layer);
+}
+
+void DM_add_face_layer(DerivedMesh *dm, int type, int flag, void *layer)
+{
+ CustomData_add_layer(&dm->faceData, type, flag, layer);
+}
+
+void *DM_get_vert_data(DerivedMesh *dm, int index, int type)
+{
+ return CustomData_get(&dm->vertData, index, type);
+}
+
+void *DM_get_edge_data(DerivedMesh *dm, int index, int type)
+{
+ return CustomData_get(&dm->edgeData, index, type);
+}
+
+void *DM_get_face_data(DerivedMesh *dm, int index, int type)
+{
+ return CustomData_get(&dm->faceData, index, type);
+}
+
+void *DM_get_vert_data_layer(DerivedMesh *dm, int type)
+{
+ return CustomData_get_layer(&dm->vertData, type);
+}
+
+void *DM_get_edge_data_layer(DerivedMesh *dm, int type)
+{
+ return CustomData_get_layer(&dm->edgeData, type);
+}
+
+void *DM_get_face_data_layer(DerivedMesh *dm, int type)
+{
+ return CustomData_get_layer(&dm->faceData, type);
+}
+
+void DM_set_vert_data(DerivedMesh *dm, int index, int type, void *data)
+{
+ CustomData_set(&dm->vertData, index, type, data);
+}
+
+void DM_set_edge_data(DerivedMesh *dm, int index, int type, void *data)
+{
+ CustomData_set(&dm->edgeData, index, type, data);
+}
+
+void DM_set_face_data(DerivedMesh *dm, int index, int type, void *data)
+{
+ CustomData_set(&dm->faceData, index, type, data);
+}
+
+void DM_copy_vert_data(DerivedMesh *source, DerivedMesh *dest,
+ int source_index, int dest_index, int count)
+{
+ CustomData_copy_data(&source->vertData, &dest->vertData,
+ source_index, dest_index,
+ count);
+}
+
+void DM_copy_edge_data(DerivedMesh *source, DerivedMesh *dest,
+ int source_index, int dest_index, int count)
+{
+ CustomData_copy_data(&source->edgeData, &dest->edgeData,
+ source_index, dest_index,
+ count);
+}
+
+void DM_copy_face_data(DerivedMesh *source, DerivedMesh *dest,
+ int source_index, int dest_index, int count)
+{
+ CustomData_copy_data(&source->faceData, &dest->faceData,
+ source_index, dest_index,
+ count);
+}
+
+void DM_free_vert_data(struct DerivedMesh *dm, int index, int count)
+{
+ CustomData_free_elem(&dm->vertData, index, count);
+}
+
+void DM_free_edge_data(struct DerivedMesh *dm, int index, int count)
+{
+ CustomData_free_elem(&dm->edgeData, index, count);
+}
+
+void DM_free_face_data(struct DerivedMesh *dm, int index, int count)
+{
+ CustomData_free_elem(&dm->faceData, index, count);
+}
+
+void DM_interp_vert_data(DerivedMesh *source, DerivedMesh *dest,
+ int *src_indices, float *weights,
+ int count, int dest_index)
+{
+ CustomData_interp(&source->vertData, &dest->vertData, src_indices,
+ weights, NULL, count, dest_index);
+}
+
+void DM_interp_edge_data(DerivedMesh *source, DerivedMesh *dest,
+ int *src_indices,
+ float *weights, EdgeVertWeight *vert_weights,
+ int count, int dest_index)
+{
+ CustomData_interp(&source->edgeData, &dest->edgeData, src_indices,
+ weights, (float *)vert_weights, count, dest_index);
+}
+
+void DM_interp_face_data(DerivedMesh *source, DerivedMesh *dest,
+ int *src_indices,
+ float *weights, FaceVertWeight *vert_weights,
+ int count, int dest_index)
+{
+ CustomData_interp(&source->faceData, &dest->faceData, src_indices,
+ weights, (float *)vert_weights, count, dest_index);
+}
typedef struct {
DerivedMesh dm;
@@ -457,7 +722,7 @@ static void meshDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *
for (i=0; i<me->totface; i++) {
MFace *mf= &mface[i];
- int drawSmooth = 1;
+ int drawSmooth = (mf->flag & ME_SMOOTH);
if (!setDrawOptions || setDrawOptions(userData, i, &drawSmooth)) {
unsigned char *cp = NULL;
@@ -516,6 +781,15 @@ static int meshDM_getNumVerts(DerivedMesh *dm)
return me->totvert;
}
+
+static int meshDM_getNumEdges(DerivedMesh *dm)
+{
+ MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
+ Mesh *me = mdm->me;
+
+ return me->totedge;
+}
+
static int meshDM_getNumFaces(DerivedMesh *dm)
{
MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
@@ -524,10 +798,51 @@ static int meshDM_getNumFaces(DerivedMesh *dm)
return me->totface;
}
+void meshDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
+{
+ MVert *verts = ((MeshDerivedMesh *)dm)->verts;
+
+ *vert_r = verts[index];
+}
+
+void meshDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r)
+{
+ Mesh *me = ((MeshDerivedMesh *)dm)->me;
+
+ *edge_r = me->medge[index];
+}
+
+void meshDM_getFace(DerivedMesh *dm, int index, MFace *face_r)
+{
+ Mesh *me = ((MeshDerivedMesh *)dm)->me;
+
+ *face_r = me->mface[index];
+}
+
+void meshDM_getVertArray(DerivedMesh *dm, MVert *vert_r)
+{
+ MeshDerivedMesh *mdm = (MeshDerivedMesh *)dm;
+ memcpy(vert_r, mdm->verts, sizeof(*vert_r) * mdm->me->totvert);
+}
+
+void meshDM_getEdgeArray(DerivedMesh *dm, MEdge *edge_r)
+{
+ MeshDerivedMesh *mdm = (MeshDerivedMesh *)dm;
+ memcpy(edge_r, mdm->me->medge, sizeof(*edge_r) * mdm->me->totedge);
+}
+
+void meshDM_getFaceArray(DerivedMesh *dm, MFace *face_r)
+{
+ MeshDerivedMesh *mdm = (MeshDerivedMesh *)dm;
+ memcpy(face_r, mdm->me->mface, sizeof(*face_r) * mdm->me->totface);
+}
+
static void meshDM_release(DerivedMesh *dm)
{
MeshDerivedMesh *mdm = (MeshDerivedMesh*) dm;
+ DM_release(dm);
+
if (mdm->wpaintMCol) MEM_freeN(mdm->wpaintMCol);
if (mdm->freeNors) MEM_freeN(mdm->nors);
if (mdm->freeVerts) MEM_freeN(mdm->verts);
@@ -538,12 +853,22 @@ static DerivedMesh *getMeshDerivedMesh(Mesh *me, Object *ob, float (*vertCos)[3]
{
MeshDerivedMesh *mdm = MEM_callocN(sizeof(*mdm), "mdm");
+ DM_init(&mdm->dm, me->totvert, me->totedge, me->totface);
+
mdm->dm.getMinMax = meshDM_getMinMax;
mdm->dm.convertToDispListMesh = meshDM_convertToDispListMesh;
mdm->dm.getNumVerts = meshDM_getNumVerts;
+ mdm->dm.getNumEdges = meshDM_getNumEdges;
mdm->dm.getNumFaces = meshDM_getNumFaces;
+ mdm->dm.getVert = meshDM_getVert;
+ mdm->dm.getEdge = meshDM_getEdge;
+ mdm->dm.getFace = meshDM_getFace;
+ mdm->dm.getVertArray = meshDM_getVertArray;
+ mdm->dm.getEdgeArray = meshDM_getEdgeArray;
+ mdm->dm.getFaceArray = meshDM_getFaceArray;
+
mdm->dm.getVertCos = meshDM_getVertCos;
mdm->dm.getVertCo = meshDM_getVertCo;
mdm->dm.getVertNo = meshDM_getVertNo;
@@ -565,6 +890,21 @@ static DerivedMesh *getMeshDerivedMesh(Mesh *me, Object *ob, float (*vertCos)[3]
mdm->dm.release = meshDM_release;
+ /* add appropriate data layers (don't copy, just reference) */
+ if(me->msticky)
+ DM_add_vert_layer(&mdm->dm, LAYERTYPE_MSTICKY,
+ LAYERFLAG_NOFREE, me->msticky);
+ if(me->dvert)
+ DM_add_vert_layer(&mdm->dm, LAYERTYPE_MDEFORMVERT,
+ LAYERFLAG_NOFREE, me->dvert);
+
+ if(me->tface)
+ DM_add_face_layer(&mdm->dm, LAYERTYPE_TFACE,
+ LAYERFLAG_NOFREE, me->tface);
+ if(me->mcol)
+ DM_add_face_layer(&mdm->dm, LAYERTYPE_MCOL,
+ LAYERFLAG_NOFREE, me->mcol);
+
/* Works in conjunction with hack during modifier calc */
if ((G.f & G_WEIGHTPAINT) && ob==(G.scene->basact?G.scene->basact->object:NULL)) {
mdm->wpaintMCol = MEM_dupallocN(me->mcol);
@@ -793,12 +1133,12 @@ static void emDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *us
if (emdm->vertexCos) {
EditVert *eve, *preveve;
- int drawSmooth = 1;
for (i=0,eve=emdm->em->verts.first; eve; eve= eve->next)
eve->prev = (EditVert*) i++;
for (i=0,efa= emdm->em->faces.first; efa; i++,efa= efa->next) {
+ int drawSmooth = (efa->flag & ME_SMOOTH);
if(!setDrawOptions || setDrawOptions(userData, i, &drawSmooth)) {
glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
@@ -828,9 +1168,8 @@ static void emDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *us
for (preveve=NULL, eve=emdm->em->verts.first; eve; preveve=eve, eve= eve->next)
eve->prev = preveve;
} else {
- int drawSmooth = 1;
-
for (i=0,efa= emdm->em->faces.first; efa; i++,efa= efa->next) {
+ int drawSmooth = (efa->flag & ME_SMOOTH);
if(!setDrawOptions || setDrawOptions(userData, i, &drawSmooth)) {
glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
@@ -883,6 +1222,14 @@ static int emDM_getNumVerts(DerivedMesh *dm)
return BLI_countlist(&emdm->em->verts);
}
+
+static int emDM_getNumEdges(DerivedMesh *dm)
+{
+ EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
+
+ return BLI_countlist(&emdm->em->edges);
+}
+
static int emDM_getNumFaces(DerivedMesh *dm)
{
EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
@@ -890,10 +1237,182 @@ static int emDM_getNumFaces(DerivedMesh *dm)
return BLI_countlist(&emdm->em->faces);
}
+void emDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
+{
+ EditVert *ev = ((EditMeshDerivedMesh *)dm)->em->verts.first;
+ int i;
+
+ for(i = 0; i < index; ++i) ev = ev->next;
+
+ VECCOPY(vert_r->co, ev->co);
+
+ vert_r->no[0] = ev->no[0] * 32767.0;
+ vert_r->no[1] = ev->no[1] * 32767.0;
+ vert_r->no[2] = ev->no[2] * 32767.0;
+
+ /* TODO what to do with vert_r->flag and vert_r->mat_nr? */
+ vert_r->mat_nr = 0;
+}
+
+void emDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r)
+{
+ EditMesh *em = ((EditMeshDerivedMesh *)dm)->em;
+ EditEdge *ee = em->edges.first;
+ EditVert *ev, *v1, *v2;
+ int i;
+
+ for(i = 0; i < index; ++i) ee = ee->next;
+
+ edge_r->crease = (unsigned char) (ee->crease*255.0f);
+ /* TODO what to do with edge_r->flag? */
+ edge_r->flag = ME_EDGEDRAW|ME_EDGERENDER;
+ if (ee->seam) edge_r->flag |= ME_SEAM;
+ if (ee->sharp) edge_r->flag |= ME_SHARP;
+#if 0
+ /* this needs setup of f2 field */
+ if (!ee->f2) edge_r->flag |= ME_LOOSEEDGE;
+#endif
+
+ /* goddamn, we have to search all verts to find indices */
+ v1 = ee->v1;
+ v2 = ee->v2;
+ for(i = 0, ev = em->verts.first; v1 || v2; i++, ev = ev->next) {
+ if(ev == v1) {
+ edge_r->v1 = i;
+ v1 = NULL;
+ }
+ if(ev == v2) {
+ edge_r->v2 = i;
+ v2 = NULL;
+ }
+ }
+}
+
+void emDM_getFace(DerivedMesh *dm, int index, MFace *face_r)
+{
+ EditMesh *em = ((EditMeshDerivedMesh *)dm)->em;
+ EditFace *ef = em->faces.first;
+ EditVert *ev, *v1, *v2, *v3, *v4;
+ int i;
+
+ for(i = 0; i < index; ++i) ef = ef->next;
+
+ face_r->mat_nr = ef->mat_nr;
+ face_r->flag = ef->flag;
+
+ /* goddamn, we have to search all verts to find indices */
+ v1 = ef->v1;
+ v2 = ef->v2;
+ v3 = ef->v3;
+ v4 = ef->v4;
+ if(!v4) face_r->v4 = 0;
+
+ for(i = 0, ev = em->verts.first; v1 || v2 || v3 || v4;
+ i++, ev = ev->next) {
+ if(ev == v1) {
+ face_r->v1 = i;
+ v1 = NULL;
+ }
+ if(ev == v2) {
+ face_r->v2 = i;
+ v2 = NULL;
+ }
+ if(ev == v3) {
+ face_r->v3 = i;
+ v3 = NULL;
+ }
+ if(ev == v4) {
+ face_r->v4 = i;
+ v4 = NULL;
+ }
+ }
+
+ test_index_face(face_r, NULL, NULL, ef->v4?4:3);
+}
+
+void emDM_getVertArray(DerivedMesh *dm, MVert *vert_r)
+{
+ EditVert *ev = ((EditMeshDerivedMesh *)dm)->em->verts.first;
+
+ for( ; ev; ev = ev->next, ++vert_r) {
+ VECCOPY(vert_r->co, ev->co);
+
+ vert_r->no[0] = ev->no[0] * 32767.0;
+ vert_r->no[1] = ev->no[1] * 32767.0;
+ vert_r->no[2] = ev->no[2] * 32767.0;
+
+ /* TODO what to do with vert_r->flag and vert_r->mat_nr? */
+ vert_r->mat_nr = 0;
+ vert_r->flag = 0;
+ }
+}
+
+void emDM_getEdgeArray(DerivedMesh *dm, MEdge *edge_r)
+{
+ EditMesh *em = ((EditMeshDerivedMesh *)dm)->em;
+ EditEdge *ee = em->edges.first;
+ EditVert *ev, *prevev;
+ int i;
+
+ /* store vert indices in the prev pointer (kind of hacky) */
+ for(ev = em->verts.first, i = 0; ev; ev = ev->next, ++i)
+ ev->prev = (EditVert*) i++;
+
+ for( ; ee; ee = ee->next, ++edge_r) {
+ edge_r->crease = (unsigned char) (ee->crease*255.0f);
+ /* TODO what to do with edge_r->flag? */
+ edge_r->flag = ME_EDGEDRAW|ME_EDGERENDER;
+ if (ee->seam) edge_r->flag |= ME_SEAM;
+ if (ee->sharp) edge_r->flag |= ME_SHARP;
+#if 0
+ /* this needs setup of f2 field */
+ if (!ee->f2) edge_r->flag |= ME_LOOSEEDGE;
+#endif
+
+ edge_r->v1 = (int)ee->v1->prev;
+ edge_r->v2 = (int)ee->v2->prev;
+ }
+
+ /* restore prev pointers */
+ for(prevev = NULL, ev = em->verts.first; ev; prevev = ev, ev = ev->next)
+ ev->prev = prevev;
+}
+
+void emDM_getFaceArray(DerivedMesh *dm, MFace *face_r)
+{
+ EditMesh *em = ((EditMeshDerivedMesh *)dm)->em;
+ EditFace *ef = em->faces.first;
+ EditVert *ev, *prevev;
+ int i;
+
+ /* store vert indices in the prev pointer (kind of hacky) */
+ for(ev = em->verts.first, i = 0; ev; ev = ev->next, ++i)
+ ev->prev = (EditVert*) i++;
+
+ for( ; ef; ef = ef->next, ++face_r) {
+ face_r->mat_nr = ef->mat_nr;
+ face_r->flag = ef->flag;
+
+ face_r->v1 = (int)ef->v1->prev;
+ face_r->v2 = (int)ef->v2->prev;
+ face_r->v3 = (int)ef->v3->prev;
+ if(ef->v4) face_r->v4 = (int)ef->v4->prev;
+ else face_r->v4 = 0;
+
+ test_index_face(face_r, NULL, NULL, ef->v4?4:3);
+ }
+
+ /* restore prev pointers */
+ for(prevev = NULL, ev = em->verts.first; ev; prevev = ev, ev = ev->next)
+ ev->prev = prevev;
+}
+
static void emDM_release(DerivedMesh *dm)
{
EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
+ DM_release(dm);
+
if (emdm->vertexCos) {
MEM_freeN(emdm->vertexCos);
MEM_freeN(emdm->vertexNos);
@@ -903,14 +1422,28 @@ static void emDM_release(DerivedMesh *dm)
MEM_freeN(emdm);
}
-static DerivedMesh *getEditMeshDerivedMesh(EditMesh *em, float (*vertexCos)[3])
+static DerivedMesh *getEditMeshDerivedMesh(EditMesh *em, Object *ob,
+ float (*vertexCos)[3])
{
EditMeshDerivedMesh *emdm = MEM_callocN(sizeof(*emdm), "emdm");
+ Mesh *me = ob->data;
+
+ DM_init(&emdm->dm, BLI_countlist(&em->verts),
+ BLI_countlist(&em->edges), BLI_countlist(&em->faces));
emdm->dm.getMinMax = emDM_getMinMax;
emdm->dm.getNumVerts = emDM_getNumVerts;
+ emdm->dm.getNumEdges = emDM_getNumEdges;
emdm->dm.getNumFaces = emDM_getNumFaces;
+
+ emdm->dm.getVert = emDM_getVert;
+ emdm->dm.getEdge = emDM_getEdge;
+ emdm->dm.getFace = emDM_getFace;
+ emdm->dm.getVertArray = emDM_getVertArray;
+ emdm->dm.getEdgeArray = emDM_getEdgeArray;
+ emdm->dm.getFaceArray = emDM_getFaceArray;
+
emdm->dm.foreachMappedVert = emDM_foreachMappedVert;
emdm->dm.foreachMappedEdge = emDM_foreachMappedEdge;
emdm->dm.foreachMappedFaceCenter = emDM_foreachMappedFaceCenter;
@@ -925,7 +1458,19 @@ static DerivedMesh *getEditMeshDerivedMesh(EditMesh *em, float (*vertexCos)[3])
emdm->em = em;
emdm->vertexCos = vertexCos;
- if (vertexCos) {
+ if(me->dvert) {
+ EditVert *eve;
+ int i;
+ DM_add_vert_layer(&emdm->dm, LAYERTYPE_MDEFORMVERT, 0, NULL);
+
+ for(eve = em->verts.first, i = 0; eve; eve = eve->next, ++i) {
+ if(eve->keyindex != -1)
+ DM_set_vert_data(&emdm->dm, i, LAYERTYPE_MDEFORMVERT,
+ &me->dvert[eve->keyindex]);
+ }
+ }
+
+ if(vertexCos) {
EditVert *eve, *preveve;
EditFace *efa;
int totface = BLI_countlist(&em->faces);
@@ -960,7 +1505,8 @@ static DerivedMesh *getEditMeshDerivedMesh(EditMesh *em, float (*vertexCos)[3])
for(i=0, eve= em->verts.first; eve; i++, eve=eve->next) {
float *no = emdm->vertexNos[i];
- /* following Mesh convention; we use vertex coordinate itself for normal in this case */
+ /* following Mesh convention; we use vertex coordinate itself
+ * for normal in this case */
if (Normalise(no)==0.0) {
VECCOPY(no, vertexCos[i]);
Normalise(no);
@@ -986,47 +1532,44 @@ static void ssDM_foreachMappedVert(DerivedMesh *dm, void (*func)(void *userData,
{
SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
DispListMesh *dlm = ssdm->dlm;
- int i, index=-1;
+ int i;
+ int *index = dm->getVertDataArray(dm, LAYERTYPE_ORIGINDEX);
- for (i=0; i<dlm->totvert; i++) {
+ for (i=0; i<dlm->totvert; i++, index++) {
MVert *mv = &dlm->mvert[i];
- if (mv->flag&ME_VERT_STEPINDEX) {
- index++;
-
- func(userData, index, mv->co, NULL, mv->no);
- }
+ if(*index != ORIGINDEX_NONE)
+ func(userData, *index, mv->co, NULL, mv->no);
}
}
static void ssDM_foreachMappedEdge(DerivedMesh *dm, void (*func)(void *userData, int index, float *v0co, float *v1co), void *userData)
{
SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
DispListMesh *dlm = ssdm->dlm;
- int i, index=-1;
+ int i;
+ int *index = dm->getEdgeDataArray(dm, LAYERTYPE_ORIGINDEX);
- for (i=0; i<dlm->totedge; i++) {
+ for (i=0; i<dlm->totedge; i++, index++) {
MEdge *med = &dlm->medge[i];
- if (med->flag&ME_EDGE_STEPINDEX) index++;
-
- if (index!=-1) {
- func(userData, index, dlm->mvert[med->v1].co, dlm->mvert[med->v2].co);
- }
+ if(*index != ORIGINDEX_NONE)
+ func(userData, *index, dlm->mvert[med->v1].co,
+ dlm->mvert[med->v2].co);
}
}
static void ssDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
{
SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
DispListMesh *dlm = ssdm->dlm;
- int i, index=-1;
+ int i;
+ int *index = dm->getEdgeDataArray(dm, LAYERTYPE_ORIGINDEX);
glBegin(GL_LINES);
- for(i=0; i<dlm->totedge; i++) {
+ for(i=0; i<dlm->totedge; i++, index++) {
MEdge *med = &dlm->medge[i];
- if (med->flag&ME_EDGE_STEPINDEX) index++;
-
- if (index!=-1 && (!setDrawOptions || setDrawOptions(userData, index))) {
+ if(*index != ORIGINDEX_NONE
+ && (!setDrawOptions || setDrawOptions(userData, *index))) {
glVertex3fv(dlm->mvert[med->v1].co);
glVertex3fv(dlm->mvert[med->v2].co);
}
@@ -1038,14 +1581,13 @@ static void ssDM_foreachMappedFaceCenter(DerivedMesh *dm, void (*func)(void *use
{
SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
DispListMesh *dlm = ssdm->dlm;
- int i, index=-1;
+ int i;
+ int *index = dm->getFaceDataArray(dm, LAYERTYPE_ORIGINDEX);
- for (i=0; i<dlm->totface; i++) {
+ for (i=0; i<dlm->totface; i++, index++) {
MFace *mf = &dlm->mface[i];
- if (mf->flag&ME_FACE_STEPINDEX) index++;
-
- if(index!=-1) {
+ if(*index != ORIGINDEX_NONE) {
float cent[3];
float no[3];
@@ -1062,7 +1604,7 @@ static void ssDM_foreachMappedFaceCenter(DerivedMesh *dm, void (*func)(void *use
VecMulf(cent, 0.33333333333f);
}
- func(userData, index, cent, no);
+ func(userData, *index, cent, no);
}
}
}
@@ -1253,9 +1795,10 @@ static void ssDM_drawFacesTex_common(DerivedMesh *dm, int (*drawParams)(TFace *t
MFace *mface= dlm->mface;
TFace *tface = dlm->tface;
float *nors = dlm->nors;
- int a, index=-1;
+ int a;
+ int *index = dm->getFaceDataArray(dm, LAYERTYPE_ORIGINDEX);
- for (a=0; a<dlm->totface; a++) {
+ for (a=0; a<dlm->totface; a++, index++) {
MFace *mf= &mface[a];
TFace *tf = tface?&tface[a]:NULL;
int flag;
@@ -1265,8 +1808,8 @@ static void ssDM_drawFacesTex_common(DerivedMesh *dm, int (*drawParams)(TFace *t
flag = drawParams(tf, mf->mat_nr);
}
else {
- if (mf->flag&ME_FACE_STEPINDEX) index++;
- flag = drawParamsMapped(userData, index);
+ if(*index != ORIGINDEX_NONE)
+ flag = drawParamsMapped(userData, *index);
}
if (flag==0) {
@@ -1324,15 +1867,16 @@ static void ssDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *us
MVert *mvert= dlm->mvert;
MFace *mface= dlm->mface;
float *nors = dlm->nors;
- int i, index=-1;
+ int i;
+ int *index = dm->getFaceDataArray(dm, LAYERTYPE_ORIGINDEX);
- for (i=0; i<dlm->totface; i++) {
+ for (i=0; i<dlm->totface; i++, index++) {
MFace *mf = &mface[i];
- int drawSmooth = 1;
-
- if (mf->flag&ME_FACE_STEPINDEX) index++;
+ int drawSmooth = (mf->flag & ME_SMOOTH);
- if (index!=-1 && (!setDrawOptions || setDrawOptions(userData, index, &drawSmooth))) {
+ if(*index != ORIGINDEX_NONE
+ && (!setDrawOptions
+ || setDrawOptions(userData, *index, &drawSmooth))) {
unsigned char *cp = NULL;
if (useColors) {
@@ -1412,6 +1956,14 @@ static int ssDM_getNumVerts(DerivedMesh *dm)
return ssdm->dlm->totvert;
}
+
+static int ssDM_getNumEdges(DerivedMesh *dm)
+{
+ SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
+
+ return ssdm->dlm->totedge;
+}
+
static int ssDM_getNumFaces(DerivedMesh *dm)
{
SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
@@ -1419,6 +1971,39 @@ static int ssDM_getNumFaces(DerivedMesh *dm)
return ssdm->dlm->totface;
}
+void ssDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
+{
+ *vert_r = ((SSDerivedMesh *)dm)->dlm->mvert[index];
+}
+
+void ssDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r)
+{
+ *edge_r = ((SSDerivedMesh *)dm)->dlm->medge[index];
+}
+
+void ssDM_getFace(DerivedMesh *dm, int index, MFace *face_r)
+{
+ *face_r = ((SSDerivedMesh *)dm)->dlm->mface[index];
+}
+
+void ssDM_getVertArray(DerivedMesh *dm, MVert *vert_r)
+{
+ SSDerivedMesh *ssdm = (SSDerivedMesh *)dm;
+ memcpy(vert_r, ssdm->dlm->mvert, sizeof(*vert_r) * ssdm->dlm->totvert);
+}
+
+void ssDM_getEdgeArray(DerivedMesh *dm, MEdge *edge_r)
+{
+ SSDerivedMesh *ssdm = (SSDerivedMesh *)dm;
+ memcpy(edge_r, ssdm->dlm->medge, sizeof(*edge_r) * ssdm->dlm->totedge);
+}
+
+void ssDM_getFaceArray(DerivedMesh *dm, MFace *face_r)
+{
+ SSDerivedMesh *ssdm = (SSDerivedMesh *)dm;
+ memcpy(face_r, ssdm->dlm->mface, sizeof(*face_r) * ssdm->dlm->totface);
+}
+
static DispListMesh *ssDM_convertToDispListMesh(DerivedMesh *dm, int allowShared)
{
SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
@@ -1434,6 +2019,8 @@ static void ssDM_release(DerivedMesh *dm)
{
SSDerivedMesh *ssdm = (SSDerivedMesh*) dm;
+ DM_release(dm);
+
displistmesh_free(ssdm->dlm);
MEM_freeN(dm);
@@ -1443,10 +2030,21 @@ DerivedMesh *derivedmesh_from_displistmesh(DispListMesh *dlm, float (*vertexCos)
{
SSDerivedMesh *ssdm = MEM_callocN(sizeof(*ssdm), "ssdm");
+ DM_init(&ssdm->dm, dlm->totvert, dlm->totedge, dlm->totface);
+
ssdm->dm.getMinMax = ssDM_getMinMax;
ssdm->dm.getNumVerts = ssDM_getNumVerts;
+ ssdm->dm.getNumEdges = ssDM_getNumEdges;
ssdm->dm.getNumFaces = ssDM_getNumFaces;
+
+ ssdm->dm.getVert = ssDM_getVert;
+ ssdm->dm.getEdge = ssDM_getEdge;
+ ssdm->dm.getFace = ssDM_getFace;
+ ssdm->dm.getVertArray = ssDM_getVertArray;
+ ssdm->dm.getEdgeArray = ssDM_getEdgeArray;
+ ssdm->dm.getFaceArray = ssDM_getFaceArray;
+
ssdm->dm.convertToDispListMesh = ssDM_convertToDispListMesh;
ssdm->dm.getVertCos = ssDM_getVertCos;
@@ -1991,27 +2589,36 @@ DerivedMesh *mesh_create_derived_for_modifier(Object *ob, ModifierData *md)
MEM_freeN(deformedVerts);
} else {
- dm = mti->applyModifier(md, ob, NULL, NULL, 0, 0);
+ DerivedMesh *tdm = getMeshDerivedMesh(me, ob, NULL);
+ dm = mti->applyModifier(md, ob, tdm, 0, 0);
+
+ if(tdm != dm) tdm->release(tdm);
}
return dm;
}
-static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], DerivedMesh **deform_r, DerivedMesh **final_r, int useRenderParams, int useDeform, int needMapping)
+static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3],
+ DerivedMesh **deform_r, DerivedMesh **final_r,
+ int useRenderParams, int useDeform,
+ int needMapping)
{
Mesh *me = ob->data;
- ModifierData *md= modifiers_getVirtualModifierList(ob);
+ ModifierData *md = modifiers_getVirtualModifierList(ob);
float (*deformedVerts)[3] = NULL;
DerivedMesh *dm;
int numVerts = me->totvert;
int fluidsimMeshUsed = 0;
+ int required_mode;
modifiers_clearErrors(ob);
- if (deform_r) *deform_r = NULL;
+ if(deform_r) *deform_r = NULL;
*final_r = NULL;
- /* replace original mesh by fluidsim surface mesh for fluidsim domain objects */
+ /* replace original mesh by fluidsim surface mesh for fluidsim
+ * domain objects
+ */
if((G.obedit!=ob) && !needMapping) {
if (ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) {
if(ob->fluidsimSettings->type & OB_FLUIDSIM_DOMAIN) {
@@ -2023,30 +2630,35 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], DerivedM
}
}
}
-
- if (useDeform) {
- if(do_ob_key(ob)) /* shape key makes deform verts */
+
+ if(useRenderParams) required_mode = eModifierMode_Render;
+ else required_mode = eModifierMode_Realtime;
+
+ if(useDeform) {
+ if(do_ob_key(ob)) /* shape key makes deform verts */
deformedVerts = mesh_getVertexCos(me, &numVerts);
- /* Apply all leading deforming modifiers */
- for (; md; md=md->next) {
+ /* Apply all leading deforming modifiers */
+ for(; md; md = md->next) {
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
- if (!(md->mode&(1<<useRenderParams))) continue;
- if (mti->isDisabled && mti->isDisabled(md)) continue;
+ if((md->mode & required_mode) != required_mode) continue;
+ if(mti->isDisabled && mti->isDisabled(md)) continue;
+
+ if(mti->type == eModifierTypeType_OnlyDeform) {
+ if(!deformedVerts)
+ deformedVerts = mesh_getVertexCos(me, &numVerts);
- if (mti->type==eModifierTypeType_OnlyDeform) {
- if (!deformedVerts) deformedVerts = mesh_getVertexCos(me, &numVerts);
mti->deformVerts(md, ob, NULL, deformedVerts, numVerts);
} else {
break;
}
}
- /* Result of all leading deforming modifiers is cached for
- * places that wish to use the original mesh but with deformed
- * coordinates (vpaint, etc.)
- */
+ /* Result of all leading deforming modifiers is cached for
+ * places that wish to use the original mesh but with deformed
+ * coordinates (vpaint, etc.)
+ */
if (deform_r)
#ifdef WITH_VERSE
if(me->vnode) *deform_r = derivedmesh_from_versemesh(me->vnode, deformedVerts);
@@ -2056,46 +2668,50 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], DerivedM
#endif
} else {
if(!fluidsimMeshUsed) {
- // default behaviour for meshes
+ /* default behaviour for meshes */
deformedVerts = inputVertexCos;
} else {
- // the fluid sim mesh might have more vertices than the original
- // one, so inputVertexCos shouldnt be used
+ /* the fluid sim mesh might have more vertices than the original
+ * one, so inputVertexCos shouldnt be used
+ */
deformedVerts = mesh_getVertexCos(me, &numVerts);
}
}
- /* Now apply all remaining modifiers. If useDeform is off then skip
- * OnlyDeform ones.
- */
+ /* Now apply all remaining modifiers. If useDeform is off then skip
+ * OnlyDeform ones.
+ */
dm = NULL;
- for (; md; md=md->next) {
+ for(; md; md = md->next) {
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
- if (!(md->mode&(1<<useRenderParams))) continue;
- if (mti->type==eModifierTypeType_OnlyDeform && !useDeform) continue;
- if ((mti->flags&eModifierTypeFlag_RequiresOriginalData) && dm) {
- modifier_setError(md, "Internal error, modifier requires original data (bad stack position).");
+ if((md->mode & required_mode) != required_mode) continue;
+ if(mti->type == eModifierTypeType_OnlyDeform && !useDeform) continue;
+ if((mti->flags & eModifierTypeFlag_RequiresOriginalData) && dm) {
+ modifier_setError(md, "Internal error, modifier requires "
+ "original data (bad stack position).");
continue;
}
- if (mti->isDisabled && mti->isDisabled(md)) continue;
- if (needMapping && !modifier_supportsMapping(md)) continue;
+ if(mti->isDisabled && mti->isDisabled(md)) continue;
+ if(needMapping && !modifier_supportsMapping(md)) continue;
- /* How to apply modifier depends on (a) what we already have as
- * a result of previous modifiers (could be a DerivedMesh or just
- * deformed vertices) and (b) what type the modifier is.
- */
+ /* How to apply modifier depends on (a) what we already have as
+ * a result of previous modifiers (could be a DerivedMesh or just
+ * deformed vertices) and (b) what type the modifier is.
+ */
- if (mti->type==eModifierTypeType_OnlyDeform) {
- /* No existing verts to deform, need to build them. */
- if (!deformedVerts) {
- if (dm) {
- /* Deforming a derived mesh, read the vertex locations out of the mesh and
- * deform them. Once done with this run of deformers verts will be written back.
- */
+ if(mti->type == eModifierTypeType_OnlyDeform) {
+ /* No existing verts to deform, need to build them. */
+ if(!deformedVerts) {
+ if(dm) {
+ /* Deforming a derived mesh, read the vertex locations
+ * out of the mesh and deform them. Once done with this
+ * run of deformers verts will be written back.
+ */
numVerts = dm->getNumVerts(dm);
- deformedVerts = MEM_mallocN(sizeof(*deformedVerts)*numVerts, "dfmv");
+ deformedVerts =
+ MEM_mallocN(sizeof(*deformedVerts) * numVerts, "dfmv");
dm->getVertCos(dm, deformedVerts);
} else {
deformedVerts = mesh_getVertexCos(me, &numVerts);
@@ -2104,38 +2720,58 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], DerivedM
mti->deformVerts(md, ob, dm, deformedVerts, numVerts);
} else {
- /* There are 4 cases here (have deform? have dm?) but they all are handled
- * by the modifier apply function, which will also free the DerivedMesh if
- * it exists.
- */
- DerivedMesh *ndm = mti->applyModifier(md, ob, dm, deformedVerts, useRenderParams, !inputVertexCos);
+ DerivedMesh *ndm;
- if (ndm) {
- if (dm) dm->release(dm);
+ /* apply vertex coordinates or build a DerivedMesh as necessary */
+ if(dm) {
+ if(deformedVerts) {
+ DerivedMesh *tdm = CDDM_copy(dm);
+ dm->release(dm);
+ dm = tdm;
+
+ CDDM_apply_vert_coords(dm, deformedVerts);
+ CDDM_calc_normals(dm);
+ }
+ } else {
+ dm = CDDM_from_mesh(me);
+
+ if(deformedVerts) {
+ CDDM_apply_vert_coords(dm, deformedVerts);
+ CDDM_calc_normals(dm);
+ }
+ }
+
+ ndm = mti->applyModifier(md, ob, dm, useRenderParams,
+ !inputVertexCos);
+
+ if(ndm) {
+ /* if the modifier returned a new dm, release the old one */
+ if(dm && dm != ndm) dm->release(dm);
dm = ndm;
- if (deformedVerts) {
- if (deformedVerts!=inputVertexCos) {
+ if(deformedVerts) {
+ if(deformedVerts != inputVertexCos)
MEM_freeN(deformedVerts);
- }
+
deformedVerts = NULL;
}
}
}
}
- /* Yay, we are done. If we have a DerivedMesh and deformed vertices need to apply
- * these back onto the DerivedMesh. If we have no DerivedMesh then we need to build
- * one.
- */
- if (dm && deformedVerts) {
- DispListMesh *dlm = dm->convertToDispListMesh(dm, 0);
+ /* Yay, we are done. If we have a DerivedMesh and deformed vertices
+ * need to apply these back onto the DerivedMesh. If we have no
+ * DerivedMesh then we need to build one.
+ */
+ if(dm && deformedVerts) {
+ *final_r = CDDM_copy(dm);
dm->release(dm);
- *final_r = derivedmesh_from_displistmesh(dlm, deformedVerts);
- } else if (dm) {
+ CDDM_apply_vert_coords(*final_r, deformedVerts);
+ CDDM_calc_normals(*final_r);
+ } else if(dm) {
*final_r = dm;
} else {
#ifdef WITH_VERSE
@@ -2146,10 +2782,10 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], DerivedM
#endif
}
- if (deformedVerts && deformedVerts!=inputVertexCos) {
+ if(deformedVerts && deformedVerts != inputVertexCos)
MEM_freeN(deformedVerts);
- }
- // restore mesh in any case
+
+ /* restore mesh in any case */
if(fluidsimMeshUsed) ob->data = ob->fluidsimSettings->orgMesh;
}
@@ -2175,40 +2811,43 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r, DerivedMesh **final_r)
float (*deformedVerts)[3] = NULL;
DerivedMesh *dm;
int i, numVerts = 0, cageIndex = modifiers_getCageIndex(ob, NULL);
+ int required_mode = eModifierMode_Realtime | eModifierMode_Editmode;
modifiers_clearErrors(ob);
- if (cage_r && cageIndex==-1) {
- *cage_r = getEditMeshDerivedMesh(em, NULL);
+ if(cage_r && cageIndex == -1) {
+ *cage_r = getEditMeshDerivedMesh(em, ob, NULL);
}
dm = NULL;
- for (i=0,md= ob->modifiers.first; md; i++,md=md->next) {
+ for(i = 0, md = ob->modifiers.first; md; i++, md = md->next) {
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
- if (!(md->mode&eModifierMode_Realtime)) continue;
- if (!(md->mode&eModifierMode_Editmode)) continue;
- if ((mti->flags&eModifierTypeFlag_RequiresOriginalData) && dm) {
- modifier_setError(md, "Internal error, modifier requires original data (bad stack position).");
+ if((md->mode & required_mode) != required_mode) continue;
+ if((mti->flags & eModifierTypeFlag_RequiresOriginalData) && dm) {
+ modifier_setError(md, "Internal error, modifier requires"
+ "original data (bad stack position).");
continue;
}
- if (mti->isDisabled && mti->isDisabled(md)) continue;
- if (!(mti->flags&eModifierTypeFlag_SupportsEditmode)) continue;
+ if(mti->isDisabled && mti->isDisabled(md)) continue;
+ if(!(mti->flags & eModifierTypeFlag_SupportsEditmode)) continue;
- /* How to apply modifier depends on (a) what we already have as
- * a result of previous modifiers (could be a DerivedMesh or just
- * deformed vertices) and (b) what type the modifier is.
- */
+ /* How to apply modifier depends on (a) what we already have as
+ * a result of previous modifiers (could be a DerivedMesh or just
+ * deformed vertices) and (b) what type the modifier is.
+ */
- if (mti->type==eModifierTypeType_OnlyDeform) {
- /* No existing verts to deform, need to build them. */
- if (!deformedVerts) {
- if (dm) {
- /* Deforming a derived mesh, read the vertex locations out of the mesh and
- * deform them. Once done with this run of deformers verts will be written back.
- */
+ if(mti->type == eModifierTypeType_OnlyDeform) {
+ /* No existing verts to deform, need to build them. */
+ if(!deformedVerts) {
+ if(dm) {
+ /* Deforming a derived mesh, read the vertex locations
+ * out of the mesh and deform them. Once done with this
+ * run of deformers verts will be written back.
+ */
numVerts = dm->getNumVerts(dm);
- deformedVerts = MEM_mallocN(sizeof(*deformedVerts)*numVerts, "dfmv");
+ deformedVerts =
+ MEM_mallocN(sizeof(*deformedVerts) * numVerts, "dfmv");
dm->getVertCos(dm, deformedVerts);
} else {
deformedVerts = editmesh_getVertexCos(em, &numVerts);
@@ -2217,14 +2856,37 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r, DerivedMesh **final_r)
mti->deformVertsEM(md, ob, em, dm, deformedVerts, numVerts);
} else {
- /* There are 4 cases here (have deform? have dm?) but they all are handled
- * by the modifier apply function, which will also free the DerivedMesh if
- * it exists.
- */
- DerivedMesh *ndm = mti->applyModifierEM(md, ob, em, dm, deformedVerts);
+ DerivedMesh *ndm;
+
+ /* apply vertex coordinates or build a DerivedMesh as necessary */
+ if(dm) {
+ if(deformedVerts) {
+ DerivedMesh *tdm = CDDM_copy(dm);
+ if(!(cage_r && dm == *cage_r)) dm->release(dm);
+ dm = tdm;
+
+ CDDM_apply_vert_coords(dm, deformedVerts);
+ CDDM_calc_normals(dm);
+ } else if(cage_r && dm == *cage_r) {
+ /* dm may be changed by this modifier, so we need to copy it
+ */
+ dm = CDDM_copy(dm);
+ }
+
+ } else {
+ dm = CDDM_from_editmesh(em, ob->data);
+
+ if(deformedVerts) {
+ CDDM_apply_vert_coords(dm, deformedVerts);
+ CDDM_calc_normals(dm);
+ }
+ }
+
+ ndm = mti->applyModifierEM(md, ob, em, dm);
if (ndm) {
- if (dm && (!cage_r || dm!=*cage_r)) dm->release(dm);
+ if(dm && dm != ndm)
+ dm->release(dm);
dm = ndm;
@@ -2235,36 +2897,37 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r, DerivedMesh **final_r)
}
}
- if (cage_r && i==cageIndex) {
- if (dm && deformedVerts) {
- DispListMesh *dlm;
-
- dlm = dm->convertToDispListMesh(dm, 0);
-
- *cage_r = derivedmesh_from_displistmesh(dlm, deformedVerts);
- } else if (dm) {
+ if(cage_r && i == cageIndex) {
+ if(dm && deformedVerts) {
+ *cage_r = CDDM_copy(dm);
+ CDDM_apply_vert_coords(*cage_r, deformedVerts);
+ } else if(dm) {
*cage_r = dm;
} else {
- *cage_r = getEditMeshDerivedMesh(em, deformedVerts?MEM_dupallocN(deformedVerts):NULL);
+ *cage_r =
+ getEditMeshDerivedMesh(em, ob,
+ deformedVerts ? MEM_dupallocN(deformedVerts) : NULL);
}
}
}
- /* Yay, we are done. If we have a DerivedMesh and deformed vertices need to apply
- * these back onto the DerivedMesh. If we have no DerivedMesh then we need to build
- * one.
- */
- if (dm && deformedVerts) {
- DispListMesh *dlm = dm->convertToDispListMesh(dm, 0);
+ /* Yay, we are done. If we have a DerivedMesh and deformed vertices need
+ * to apply these back onto the DerivedMesh. If we have no DerivedMesh
+ * then we need to build one.
+ */
+ if(dm && deformedVerts) {
+ *final_r = CDDM_copy(dm);
- if (!cage_r || dm!=*cage_r) dm->release(dm);
+ if(!(cage_r && dm == *cage_r)) dm->release(dm);
+
+ CDDM_apply_vert_coords(*final_r, deformedVerts);
+ CDDM_calc_normals(*final_r);
- *final_r = derivedmesh_from_displistmesh(dlm, deformedVerts);
MEM_freeN(deformedVerts);
} else if (dm) {
*final_r = dm;
} else {
- *final_r = getEditMeshDerivedMesh(em, deformedVerts);
+ *final_r = getEditMeshDerivedMesh(em, ob, deformedVerts);
}
}
@@ -2384,18 +3047,22 @@ static void mesh_build_data(Object *ob)
MCol *mcol = me->mcol;
TFace *tface = me->tface;
- me->tface = NULL;
me->mcol = (MCol*) calc_weightpaint_colors(ob);
+ if(me->tface) {
+ me->tface = MEM_dupallocN(me->tface);
+ mcol_to_tface(me, 1);
+ }
mesh_calc_modifiers(ob, NULL, &ob->derivedDeform, &ob->derivedFinal, 0, 1,
needMapping);
- MEM_freeN(me->mcol);
+ if(me->mcol) MEM_freeN(me->mcol);
+ if(me->tface) MEM_freeN(me->tface);
me->mcol = mcol;
me->tface = tface;
} else {
- mesh_calc_modifiers(ob, NULL, &ob->derivedDeform, &ob->derivedFinal, 0, 1,
- needMapping);
+ mesh_calc_modifiers(ob, NULL, &ob->derivedDeform,
+ &ob->derivedFinal, 0, 1, needMapping);
}
INIT_MINMAX(min, max);
@@ -2525,7 +3192,7 @@ DerivedMesh *editmesh_get_derived_cage(int *needsFree_r)
DerivedMesh *editmesh_get_derived_base(void)
{
- return getEditMeshDerivedMesh(G.editMesh, NULL);
+ return getEditMeshDerivedMesh(G.editMesh, G.obedit, NULL);
}
@@ -2536,6 +3203,10 @@ static void make_vertexcosnos__mapFunc(void *userData, int index, float *co, flo
float *vec = userData;
vec+= 6*index;
+
+ /* check if we've been here before (normal should not be 0) */
+ if(vec[3] || vec[4] || vec[5]) return;
+
VECCOPY(vec, co);
vec+= 3;
if(no_f) {
@@ -2563,7 +3234,7 @@ float *mesh_get_mapped_verts_nors(Object *ob)
return NULL;
dm= mesh_get_derived_final(ob, &needsFree);
- vertexcosnos= MEM_mallocN(6*sizeof(float)*me->totvert, "vertexcosnos map");
+ vertexcosnos= MEM_callocN(6*sizeof(float)*me->totvert, "vertexcosnos map");
if(dm->foreachMappedVert) {
dm->foreachMappedVert(dm, make_vertexcosnos__mapFunc, vertexcosnos);
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index b0341e6ddcc..545efdf10e6 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -48,6 +48,7 @@
#include "BKE_curve.h"
#include "BKE_depsgraph.h"
+#include "BKE_DerivedMesh.h"
#include "BKE_displist.h"
#include "BKE_global.h"
#include "BKE_main.h"
@@ -661,16 +662,18 @@ static void pchan_bone_deform(bPoseChannel *pchan, float weight, float *vec, flo
(*contrib)+=weight;
}
-void armature_deform_verts(Object *armOb, Object *target, float (*vertexCos)[3], int numVerts, int deformflag)
+void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm,
+ float (*vertexCos)[3], int numVerts, int deformflag)
{
bPoseChannel *pchan, **defnrToPC = NULL;
- MDeformVert *dverts= NULL;
+ MDeformVert *dverts = NULL;
float obinv[4][4], premat[4][4], postmat[4][4];
- int use_envelope= deformflag & ARM_DEF_ENVELOPE;
- int numGroups= 0; /* safety for vertexgroup index overflow too */
+ int use_envelope = deformflag & ARM_DEF_ENVELOPE;
+ int numGroups = 0; /* safety for vertexgroup index overflow too */
int i;
+ int use_dverts = 0;
- if(armOb==G.obedit) return;
+ if(armOb == G.obedit) return;
Mat4Invert(obinv, target->obmat);
Mat4CpyMat4(premat, target->obmat);
@@ -681,23 +684,32 @@ void armature_deform_verts(Object *armOb, Object *target, float (*vertexCos)[3],
/* bone defmats are already in the channels, chan_mat */
/* initialize B_bone matrices */
- for(pchan= armOb->pose->chanbase.first; pchan; pchan= pchan->next) {
+ for(pchan = armOb->pose->chanbase.first; pchan; pchan = pchan->next) {
if(!(pchan->bone->flag & BONE_NO_DEFORM))
- if(pchan->bone->segments>1)
+ if(pchan->bone->segments > 1)
pchan_b_bone_defmats(pchan);
}
/* get a vertex-deform-index to posechannel array */
if(deformflag & ARM_DEF_VGROUP) {
- if (target->type==OB_MESH){
+ if(target->type == OB_MESH){
bDeformGroup *dg;
numGroups = BLI_countlist(&target->defbase);
-
dverts = ((Mesh*)target->data)->dvert;
- if(dverts) {
- defnrToPC = MEM_callocN(sizeof(*defnrToPC)*numGroups, "defnrToBone");
- for (i=0,dg=target->defbase.first; dg; i++,dg=dg->next) {
+
+ /* if we have a DerivedMesh, only use dverts if it has them */
+ if(dm)
+ if(dm->getVertData(dm, 0, LAYERTYPE_MDEFORMVERT))
+ use_dverts = 1;
+ else use_dverts = 0;
+ else if(dverts) use_dverts = 1;
+
+ if(use_dverts) {
+ defnrToPC = MEM_callocN(sizeof(*defnrToPC) * numGroups,
+ "defnrToBone");
+ for(i = 0, dg = target->defbase.first; dg;
+ i++, dg = dg->next) {
defnrToPC[i] = get_pose_channel(armOb->pose, dg->name);
/* exclude non-deforming bones */
if(defnrToPC[i]) {
@@ -709,77 +721,84 @@ void armature_deform_verts(Object *armOb, Object *target, float (*vertexCos)[3],
}
}
- for(i=0; i<numVerts; i++) {
+ for(i = 0; i < numVerts; i++) {
MDeformVert *dvert;
float *co = vertexCos[i];
float vec[3];
- float contrib=0.0;
+ float contrib = 0.0;
int j;
- vec[0]=vec[1]=vec[2]=0;
+ vec[0] = vec[1] = vec[2] = 0;
/* Apply the object's matrix */
Mat4MulVecfl(premat, co);
- if(dverts && i<((Mesh*)target->data)->totvert)
- dvert= dverts+i;
- else
- dvert= NULL;
+ if(use_dverts) {
+ if(dm) dvert = dm->getVertData(dm, i, LAYERTYPE_MDEFORMVERT);
+ else if(i < ((Mesh*)target->data)->totvert) dvert = dverts + i;
+ } else
+ dvert = NULL;
if(dvert && dvert->totweight) { // use weight groups ?
- int deformed= 0;
+ int deformed = 0;
- for (j=0; j<dvert->totweight; j++){
- int index= dvert->dw[j].def_nr;
- pchan = index<numGroups?defnrToPC[index]:NULL;
- if (pchan) {
- float weight= dvert->dw[j].weight;
- Bone *bone= pchan->bone;
+ for(j = 0; j < dvert->totweight; j++){
+ int index = dvert->dw[j].def_nr;
+ pchan = index < numGroups?defnrToPC[index]:NULL;
+ if(pchan) {
+ float weight = dvert->dw[j].weight;
+ Bone *bone = pchan->bone;
- deformed= 1;
+ deformed = 1;
if(bone && bone->flag & BONE_MULT_VG_ENV) {
-
- weight*= distfactor_to_bone(co, bone->arm_head, bone->arm_tail, bone->rad_head, bone->rad_tail, bone->dist);
+ weight *= distfactor_to_bone(co, bone->arm_head,
+ bone->arm_tail,
+ bone->rad_head,
+ bone->rad_tail,
+ bone->dist);
}
pchan_bone_deform(pchan, weight, vec, co, &contrib);
}
}
- /* if there are vertexgroups but not groups with bones (like for softbody groups) */
- if(deformed==0 && use_envelope) {
- for(pchan= armOb->pose->chanbase.first; pchan; pchan= pchan->next) {
+ /* if there are vertexgroups but not groups with bones
+ * (like for softbody groups)
+ */
+ if(deformed == 0 && use_envelope) {
+ for(pchan = armOb->pose->chanbase.first; pchan;
+ pchan = pchan->next) {
if(!(pchan->bone->flag & BONE_NO_DEFORM))
- contrib+= dist_bone_deform(pchan, vec, co);
+ contrib += dist_bone_deform(pchan, vec, co);
}
}
}
else if(use_envelope) {
- for(pchan= armOb->pose->chanbase.first; pchan; pchan= pchan->next) {
+ for(pchan = armOb->pose->chanbase.first; pchan;
+ pchan = pchan->next) {
if(!(pchan->bone->flag & BONE_NO_DEFORM))
- contrib+= dist_bone_deform(pchan, vec, co);
+ contrib += dist_bone_deform(pchan, vec, co);
}
}
- if (contrib>0.0){
- vec[0]/=contrib;
- vec[1]/=contrib;
- vec[2]/=contrib;
+ if(contrib > 0.0){
+ vec[0] /= contrib;
+ vec[1] /= contrib;
+ vec[2] /= contrib;
}
VecAddf(co, vec, co);
Mat4MulVecfl(postmat, co);
}
- if (defnrToPC) MEM_freeN(defnrToPC);
+ if(defnrToPC) MEM_freeN(defnrToPC);
/* free B_bone matrices */
- for(pchan= armOb->pose->chanbase.first; pchan; pchan= pchan->next) {
+ for(pchan = armOb->pose->chanbase.first; pchan; pchan = pchan->next) {
if(pchan->b_bone_mats) {
MEM_freeN(pchan->b_bone_mats);
- pchan->b_bone_mats= NULL;
+ pchan->b_bone_mats = NULL;
}
}
-
}
/* ************ END Armature Deform ******************* */
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
new file mode 100644
index 00000000000..2429da66c15
--- /dev/null
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -0,0 +1,1045 @@
+/*
+* $Id$
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* The Original Code is Copyright (C) 2006 Blender Foundation.
+* All rights reserved.
+*
+* The Original Code is: all of this file.
+*
+* Contributor(s): Ben Batt <benbatt@gmail.com>
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+* Implementation of CDDerivedMesh.
+*
+* BKE_cdderivedmesh.h contains the function prototypes for this file.
+*
+*/
+
+/* TODO maybe BIF_gl.h should include string.h? */
+#include <string.h>
+#include "BIF_gl.h"
+
+#include "BKE_cdderivedmesh.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_displist.h"
+#include "BKE_mesh.h"
+#include "BKE_utildefines.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "BLI_edgehash.h"
+#include "BLI_editVert.h"
+#include "BLI_ghash.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include <string.h>
+#include <limits.h>
+
+
+/**************** DerivedMesh interface functions ****************/
+static int cdDM_getNumVerts(DerivedMesh *dm)
+{
+ return dm->vertData.numElems;
+}
+
+static int cdDM_getNumFaces(DerivedMesh *dm)
+{
+ return dm->faceData.numElems;
+}
+
+static int cdDM_getNumEdges(DerivedMesh *dm)
+{
+ return dm->edgeData.numElems;
+}
+
+static void cdDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
+{
+ *vert_r = *CDDM_get_vert(dm, index);
+}
+
+static void cdDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r)
+{
+ *edge_r = *CDDM_get_edge(dm, index);
+}
+
+static void cdDM_getFace(DerivedMesh *dm, int index, MFace *face_r)
+{
+ *face_r = *CDDM_get_face(dm, index);
+}
+
+static void cdDM_getVertArray(DerivedMesh *dm, MVert *vert_r)
+{
+ memcpy(vert_r, CDDM_get_verts(dm), sizeof(*vert_r) * dm->getNumVerts(dm));
+}
+
+static void cdDM_getEdgeArray(DerivedMesh *dm, MEdge *edge_r)
+{
+ memcpy(edge_r, CDDM_get_edges(dm), sizeof(*edge_r) * dm->getNumEdges(dm));
+}
+
+static void cdDM_getFaceArray(DerivedMesh *dm, MFace *face_r)
+{
+ memcpy(face_r, CDDM_get_faces(dm), sizeof(*face_r) * dm->getNumFaces(dm));
+}
+
+static void cdDM_foreachMappedVert(
+ DerivedMesh *dm,
+ void (*func)(void *userData, int index, float *co,
+ float *no_f, short *no_s),
+ void *userData)
+{
+ int i;
+ int maxVerts = dm->getNumVerts(dm);
+ MVert *mv = CDDM_get_verts(dm);
+ int *index = DM_get_vert_data_layer(dm, LAYERTYPE_ORIGINDEX);
+
+ for(i = 0; i < maxVerts; i++, mv++, index++) {
+ if(*index == ORIGINDEX_NONE) continue;
+
+ func(userData, *index, mv->co, NULL, mv->no);
+ }
+}
+
+static void cdDM_foreachMappedEdge(
+ DerivedMesh *dm,
+ void (*func)(void *userData, int index,
+ float *v0co, float *v1co),
+ void *userData)
+{
+ int i;
+ int maxEdges = dm->getNumEdges(dm);
+ MEdge *med = CDDM_get_edges(dm);
+ MVert *mv = CDDM_get_verts(dm);
+ int *index = DM_get_edge_data_layer(dm, LAYERTYPE_ORIGINDEX);
+
+ for(i = 0; i < maxEdges; i++, med++, index++) {
+ if(*index == ORIGINDEX_NONE) continue;
+
+ func(userData, *index, mv[med->v1].co, mv[med->v2].co);
+ }
+}
+
+static void cdDM_foreachMappedFaceCenter(
+ DerivedMesh *dm,
+ void (*func)(void *userData, int index,
+ float *cent, float *no),
+ void *userData)
+{
+ int i;
+ int maxFaces = dm->getNumFaces(dm);
+ MFace *mf = CDDM_get_faces(dm);
+ MVert *mv = CDDM_get_verts(dm);
+ int *index = DM_get_face_data_layer(dm, LAYERTYPE_ORIGINDEX);
+
+ for(i = 0; i < maxFaces; i++, mf++, index++) {
+ float cent[3];
+ float no[3];
+
+ if(*index == ORIGINDEX_NONE) continue;
+
+ VECCOPY(cent, mv[mf->v1].co);
+ VecAddf(cent, cent, mv[mf->v2].co);
+ VecAddf(cent, cent, mv[mf->v3].co);
+
+ if (mf->v4) {
+ CalcNormFloat4(mv[mf->v1].co, mv[mf->v2].co,
+ mv[mf->v3].co, mv[mf->v4].co, no);
+ VecAddf(cent, cent, mv[mf->v4].co);
+ VecMulf(cent, 0.25f);
+ } else {
+ CalcNormFloat(mv[mf->v1].co, mv[mf->v2].co,
+ mv[mf->v3].co, no);
+ VecMulf(cent, 0.33333333333f);
+ }
+
+ func(userData, *index, cent, no);
+ }
+}
+
+static DispListMesh *cdDM_convertToDispListMesh(DerivedMesh *dm,
+ int allowShared)
+{
+ DispListMesh *dlm = MEM_callocN(sizeof(*dlm),
+ "cdDM_convertToDispListMesh dlm");
+
+ dlm->totvert = dm->vertData.numElems;
+ dlm->totedge = dm->edgeData.numElems;
+ dlm->totface = dm->faceData.numElems;
+ dlm->mvert = dm->dupVertArray(dm);
+ dlm->medge = dm->dupEdgeArray(dm);
+ dlm->mface = dm->dupFaceArray(dm);
+
+ dlm->tface = dm->getFaceDataArray(dm, LAYERTYPE_TFACE);
+ if(dlm->tface)
+ dlm->tface = MEM_dupallocN(dlm->tface);
+
+ dlm->mcol = dm->getFaceDataArray(dm, LAYERTYPE_MCOL);
+ if(dlm->mcol)
+ dlm->mcol = MEM_dupallocN(dlm->mcol);
+
+ dlm->nors = NULL;
+ dlm->dontFreeVerts = dlm->dontFreeOther = dlm->dontFreeNors = 0;
+
+ return dlm;
+}
+
+static void cdDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
+{
+ int i;
+
+ for(i = 0; i < dm->vertData.numElems; i++) {
+ DO_MINMAX(CDDM_get_vert(dm, i)->co, min_r, max_r);
+ }
+}
+
+static void cdDM_getVertCo(DerivedMesh *dm, int index, float co_r[3])
+{
+ VECCOPY(co_r, CDDM_get_vert(dm, index)->co);
+}
+
+static void cdDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3])
+{
+ int i;
+ MVert *mv = CDDM_get_verts(dm);
+
+ for(i = 0; i < dm->vertData.numElems; i++, mv++)
+ VECCOPY(cos_r[i], mv->co);
+}
+
+static void cdDM_getVertNo(DerivedMesh *dm, int index, float no_r[3])
+{
+ short *no = CDDM_get_vert(dm, index)->no;
+
+ no_r[0] = no[0] / 32767.f;
+ no_r[1] = no[1] / 32767.f;
+ no_r[2] = no[2] / 32767.f;
+}
+
+static void cdDM_drawVerts(DerivedMesh *dm)
+{
+ int i;
+ MVert *mv = CDDM_get_verts(dm);
+
+ glBegin(GL_POINTS);
+ for(i = 0; i < dm->vertData.numElems; i++, mv++)
+ glVertex3fv(mv->co);
+ glEnd();
+}
+
+static void cdDM_drawUVEdges(DerivedMesh *dm)
+{
+ int i;
+ TFace *tf = DM_get_face_data_layer(dm, LAYERTYPE_TFACE);
+ MFace *mf = CDDM_get_faces(dm);
+
+ if(tf) {
+ glBegin(GL_LINES);
+ for(i = 0; i < dm->faceData.numElems; i++, tf++, mf++) {
+ if(!(tf->flag&TF_HIDE)) {
+ glVertex2fv(tf->uv[0]);
+ glVertex2fv(tf->uv[1]);
+
+ glVertex2fv(tf->uv[1]);
+ glVertex2fv(tf->uv[2]);
+
+ if(!mf->v4) {
+ glVertex2fv(tf->uv[2]);
+ glVertex2fv(tf->uv[0]);
+ } else {
+ glVertex2fv(tf->uv[2]);
+ glVertex2fv(tf->uv[3]);
+
+ glVertex2fv(tf->uv[3]);
+ glVertex2fv(tf->uv[0]);
+ }
+ }
+ }
+ glEnd();
+ }
+}
+
+static void cdDM_drawEdges(DerivedMesh *dm, int drawLooseEdges)
+{
+ int i;
+ MEdge *medge = CDDM_get_edges(dm);
+ MVert *mvert = CDDM_get_verts(dm);
+
+ glBegin(GL_LINES);
+ for(i = 0; i < dm->edgeData.numElems; i++, medge++) {
+ if((medge->flag&ME_EDGEDRAW)
+ && (drawLooseEdges || !(medge->flag&ME_LOOSEEDGE))) {
+ glVertex3fv(mvert[medge->v1].co);
+ glVertex3fv(mvert[medge->v2].co);
+ }
+ }
+ glEnd();
+}
+
+static void cdDM_drawLooseEdges(DerivedMesh *dm)
+{
+ MEdge *medge = CDDM_get_edges(dm);
+ MVert *mvert = CDDM_get_verts(dm);
+ int i;
+
+ glBegin(GL_LINES);
+ for(i = 0; i < dm->edgeData.numElems; i++, medge++) {
+ if(medge->flag&ME_LOOSEEDGE) {
+ glVertex3fv(mvert[medge->v1].co);
+ glVertex3fv(mvert[medge->v2].co);
+ }
+ }
+ glEnd();
+}
+
+static void cdDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int))
+{
+ int a;
+ int glmode = -1, shademodel = -1, matnr = -1, drawCurrentMat = 1;
+ MFace *mface = CDDM_get_faces(dm);
+ MVert *mvert = CDDM_get_verts(dm);
+
+#define PASSVERT(index) { \
+ if(shademodel == GL_SMOOTH) { \
+ short *no = mvert[index].no; \
+ glNormal3sv(no); \
+ } \
+ glVertex3fv(mvert[index].co); \
+}
+
+ glBegin(glmode = GL_QUADS);
+ for(a = 0; a < dm->faceData.numElems; a++, mface++) {
+ int new_glmode, new_matnr, new_shademodel;
+
+ new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
+ new_matnr = mface->mat_nr + 1;
+ new_shademodel = (mface->flag & ME_SMOOTH)?GL_SMOOTH:GL_FLAT;
+
+ if(new_glmode != glmode || new_matnr != matnr
+ || new_shademodel != shademodel) {
+ glEnd();
+
+ drawCurrentMat = setMaterial(matnr = new_matnr);
+
+ glShadeModel(shademodel = new_shademodel);
+ glBegin(glmode = new_glmode);
+ }
+
+ if(drawCurrentMat) {
+ /* TODO make this better (cache facenormals as layer?) */
+ if(shademodel == GL_FLAT) {
+ float nor[3];
+ if(mface->v4) {
+ CalcNormFloat4(mvert[mface->v1].co, mvert[mface->v2].co,
+ mvert[mface->v3].co, mvert[mface->v4].co,
+ nor);
+ } else {
+ CalcNormFloat(mvert[mface->v1].co, mvert[mface->v2].co,
+ mvert[mface->v3].co, nor);
+ }
+ glNormal3fv(nor);
+ }
+
+ PASSVERT(mface->v1);
+ PASSVERT(mface->v2);
+ PASSVERT(mface->v3);
+ if(mface->v4) {
+ PASSVERT(mface->v4);
+ }
+ }
+ }
+ glEnd();
+
+ glShadeModel(GL_FLAT);
+#undef PASSVERT
+}
+
+static void cdDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned char *col1, unsigned char *col2)
+{
+ int a, glmode;
+ unsigned char *cp1, *cp2;
+ MFace *mface = CDDM_get_faces(dm);
+ MVert *mvert = CDDM_get_verts(dm);
+
+ cp1 = col1;
+ if(col2) {
+ cp2 = col2;
+ } else {
+ cp2 = NULL;
+ useTwoSided = 0;
+ }
+
+ /* there's a conflict here... twosided colors versus culling...? */
+ /* defined by history, only texture faces have culling option */
+ /* we need that as mesh option builtin, next to double sided lighting */
+ if(col1 && col2)
+ glEnable(GL_CULL_FACE);
+
+ glShadeModel(GL_SMOOTH);
+ glBegin(glmode = GL_QUADS);
+ for(a = 0; a < dm->faceData.numElems; a++, mface++, cp1 += 16) {
+ int new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
+
+ if(new_glmode != glmode) {
+ glEnd();
+ glBegin(glmode = new_glmode);
+ }
+
+ glColor3ub(cp1[3], cp1[2], cp1[1]);
+ glVertex3fv(mvert[mface->v1].co);
+ glColor3ub(cp1[7], cp1[6], cp1[5]);
+ glVertex3fv(mvert[mface->v2].co);
+ glColor3ub(cp1[11], cp1[10], cp1[9]);
+ glVertex3fv(mvert[mface->v3].co);
+ if(mface->v4) {
+ glColor3ub(cp1[15], cp1[14], cp1[13]);
+ glVertex3fv(mvert[mface->v4].co);
+ }
+
+ if(useTwoSided) {
+ glColor3ub(cp2[11], cp2[10], cp2[9]);
+ glVertex3fv(mvert[mface->v3].co );
+ glColor3ub(cp2[7], cp2[6], cp2[5]);
+ glVertex3fv(mvert[mface->v2].co );
+ glColor3ub(cp2[3], cp2[2], cp2[1]);
+ glVertex3fv(mvert[mface->v1].co );
+ if(mface->v4) {
+ glColor3ub(cp2[15], cp2[14], cp2[13]);
+ glVertex3fv(mvert[mface->v4].co );
+ }
+ }
+ if(col2) cp2 += 16;
+ }
+ glEnd();
+
+ glShadeModel(GL_FLAT);
+ glDisable(GL_CULL_FACE);
+}
+
+static void cdDM_drawFacesTex_common(DerivedMesh *dm,
+ int (*drawParams)(TFace *tface, int matnr),
+ int (*drawParamsMapped)(void *userData, int index),
+ void *userData)
+{
+ int i;
+ MFace *mf = CDDM_get_faces(dm);
+ TFace *tf = DM_get_face_data_layer(dm, LAYERTYPE_TFACE);
+ MVert *mv = CDDM_get_verts(dm);
+ int *index = DM_get_face_data_layer(dm, LAYERTYPE_ORIGINDEX);
+
+ for(i = 0; i < dm->faceData.numElems; i++, mf++, index++) {
+ MVert *mvert;
+ int flag;
+ unsigned char *cp = NULL;
+
+ if(drawParams)
+ if(tf) flag = drawParams(&tf[i], mf->mat_nr);
+ else flag = drawParams(NULL, mf->mat_nr);
+ else if(*index != ORIGINDEX_NONE)
+ flag = drawParamsMapped(userData, *index);
+ else
+ flag = 0;
+
+ if(flag == 0) {
+ continue;
+ } else if(flag == 1) {
+ if(tf) {
+ cp = (unsigned char *)tf[i].col;
+ } else {
+ cp = DM_get_face_data(dm, i, LAYERTYPE_MCOL);
+ }
+ }
+
+ /* TODO make this better (cache facenormals as layer?) */
+ if(!(mf->flag&ME_SMOOTH)) {
+ float nor[3];
+ if(mf->v4) {
+ CalcNormFloat4(mv[mf->v1].co, mv[mf->v2].co,
+ mv[mf->v3].co, mv[mf->v4].co, nor);
+ } else {
+ CalcNormFloat(mv[mf->v1].co, mv[mf->v2].co,
+ mv[mf->v3].co, nor);
+ }
+ glNormal3fv(nor);
+ }
+
+ glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
+ if(tf) glTexCoord2fv(tf[i].uv[0]);
+ if(cp) glColor3ub(cp[3], cp[2], cp[1]);
+ mvert = &mv[mf->v1];
+ if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
+ glVertex3fv(mvert->co);
+
+ if(tf) glTexCoord2fv(tf[i].uv[1]);
+ if(cp) glColor3ub(cp[7], cp[6], cp[5]);
+ mvert = &mv[mf->v2];
+ if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
+ glVertex3fv(mvert->co);
+
+ if(tf) glTexCoord2fv(tf[i].uv[2]);
+ if(cp) glColor3ub(cp[11], cp[10], cp[9]);
+ mvert = &mv[mf->v3];
+ if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
+ glVertex3fv(mvert->co);
+
+ if(mf->v4) {
+ if(tf) glTexCoord2fv(tf[i].uv[3]);
+ if(cp) glColor3ub(cp[15], cp[14], cp[13]);
+ mvert = &mv[mf->v4];
+ if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
+ glVertex3fv(mvert->co);
+ }
+ glEnd();
+ }
+}
+
+static void cdDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(TFace *tface, int matnr))
+{
+ cdDM_drawFacesTex_common(dm, setDrawOptions, NULL, NULL);
+}
+
+static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors)
+{
+ int i;
+ MFace *mf = CDDM_get_faces(dm);
+ MVert *mv = CDDM_get_verts(dm);
+ int *index = DM_get_face_data_layer(dm, LAYERTYPE_ORIGINDEX);
+ TFace *tf = DM_get_face_data_layer(dm, LAYERTYPE_TFACE);
+ MCol *mc = DM_get_face_data_layer(dm, LAYERTYPE_MCOL);
+
+ for(i = 0; i < dm->faceData.numElems; i++, mf++, index++) {
+ int drawSmooth = (mf->flag & ME_SMOOTH);
+
+ if(setDrawOptions && *index == ORIGINDEX_NONE) continue;
+
+ if(!setDrawOptions || setDrawOptions(userData, *index, &drawSmooth)) {
+ unsigned char *cp = NULL;
+
+ if(useColors) {
+ if(tf) {
+ cp = (unsigned char *)tf[i].col;
+ } else if(mc) {
+ cp = (unsigned char *)&mc[i * 4];
+ }
+ }
+
+ glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
+ glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
+
+ if(!drawSmooth) {
+ /* TODO make this better (cache facenormals as layer?) */
+ float nor[3];
+ if(mf->v4) {
+ CalcNormFloat4(mv[mf->v1].co, mv[mf->v2].co,
+ mv[mf->v3].co, mv[mf->v4].co, nor);
+ } else {
+ CalcNormFloat(mv[mf->v1].co, mv[mf->v2].co,
+ mv[mf->v3].co, nor);
+ }
+ glNormal3fv(nor);
+
+ if(cp) glColor3ub(cp[3], cp[2], cp[1]);
+ glVertex3fv(mv[mf->v1].co);
+ if(cp) glColor3ub(cp[7], cp[6], cp[5]);
+ glVertex3fv(mv[mf->v2].co);
+ if(cp) glColor3ub(cp[11], cp[10], cp[9]);
+ glVertex3fv(mv[mf->v3].co);
+ if(mf->v4) {
+ if(cp) glColor3ub(cp[15], cp[14], cp[13]);
+ glVertex3fv(mv[mf->v4].co);
+ }
+ } else {
+ if(cp) glColor3ub(cp[3], cp[2], cp[1]);
+ glNormal3sv(mv[mf->v1].no);
+ glVertex3fv(mv[mf->v1].co);
+ if(cp) glColor3ub(cp[7], cp[6], cp[5]);
+ glNormal3sv(mv[mf->v2].no);
+ glVertex3fv(mv[mf->v2].co);
+ if(cp) glColor3ub(cp[11], cp[10], cp[9]);
+ glNormal3sv(mv[mf->v3].no);
+ glVertex3fv(mv[mf->v3].co);
+ if(mf->v4) {
+ if(cp) glColor3ub(cp[15], cp[14], cp[13]);
+ glNormal3sv(mv[mf->v4].no);
+ glVertex3fv(mv[mf->v4].co);
+ }
+ }
+
+ glEnd();
+ }
+ }
+}
+
+static void cdDM_drawMappedFacesTex(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
+{
+ cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, userData);
+}
+
+static void cdDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
+{
+ int i;
+ int *index = DM_get_edge_data_layer(dm, LAYERTYPE_ORIGINDEX);
+ MEdge *edge = CDDM_get_edges(dm);
+ MVert *vert = CDDM_get_verts(dm);
+
+ glBegin(GL_LINES);
+ for(i = 0; i < dm->edgeData.numElems; i++, edge++, index++) {
+
+ if(setDrawOptions && *index == ORIGINDEX_NONE) continue;
+
+ if(!setDrawOptions || setDrawOptions(userData, *index)) {
+ glVertex3fv(vert[edge->v1].co);
+ glVertex3fv(vert[edge->v2].co);
+ }
+ }
+ glEnd();
+}
+
+static void cdDM_release(DerivedMesh *dm)
+{
+ CustomData_free(&dm->vertData);
+ CustomData_free(&dm->edgeData);
+ CustomData_free(&dm->faceData);
+
+ MEM_freeN(dm);
+}
+
+
+/**************** CDDM interface functions ****************/
+static DerivedMesh *cdDM_create(const char *desc)
+{
+ DerivedMesh *dm;
+
+ dm = MEM_callocN(sizeof(*dm), desc);
+
+ dm->getMinMax = cdDM_getMinMax;
+
+ dm->convertToDispListMesh = cdDM_convertToDispListMesh;
+
+ dm->getNumVerts = cdDM_getNumVerts;
+ dm->getNumFaces = cdDM_getNumFaces;
+ dm->getNumEdges = cdDM_getNumEdges;
+
+ dm->getVert = cdDM_getVert;
+ dm->getEdge = cdDM_getEdge;
+ dm->getFace = cdDM_getFace;
+ dm->getVertArray = cdDM_getVertArray;
+ dm->getEdgeArray = cdDM_getEdgeArray;
+ dm->getFaceArray = cdDM_getFaceArray;
+ dm->getVertData = DM_get_vert_data;
+ dm->getEdgeData = DM_get_edge_data;
+ dm->getFaceData = DM_get_face_data;
+ dm->getVertDataArray = DM_get_vert_data_layer;
+ dm->getEdgeDataArray = DM_get_edge_data_layer;
+ dm->getFaceDataArray = DM_get_face_data_layer;
+
+ dm->getVertCos = cdDM_getVertCos;
+ dm->getVertCo = cdDM_getVertCo;
+ dm->getVertNo = cdDM_getVertNo;
+
+ dm->drawVerts = cdDM_drawVerts;
+
+ dm->drawUVEdges = cdDM_drawUVEdges;
+ dm->drawEdges = cdDM_drawEdges;
+ dm->drawLooseEdges = cdDM_drawLooseEdges;
+ dm->drawMappedEdges = cdDM_drawMappedEdges;
+
+ dm->drawFacesSolid = cdDM_drawFacesSolid;
+ dm->drawFacesColored = cdDM_drawFacesColored;
+ dm->drawFacesTex = cdDM_drawFacesTex;
+ dm->drawMappedFaces = cdDM_drawMappedFaces;
+ dm->drawMappedFacesTex = cdDM_drawMappedFacesTex;
+
+ dm->foreachMappedVert = cdDM_foreachMappedVert;
+ dm->foreachMappedEdge = cdDM_foreachMappedEdge;
+ dm->foreachMappedFaceCenter = cdDM_foreachMappedFaceCenter;
+
+ dm->release = cdDM_release;
+
+ return dm;
+}
+
+DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces)
+{
+ DerivedMesh *dm = cdDM_create("CDDM_new dm");
+ DM_init(dm, numVerts, numEdges, numFaces);
+
+ CustomData_add_layer(&dm->vertData, LAYERTYPE_MVERT, LAYERFLAG_NOCOPY,
+ NULL);
+ CustomData_add_layer(&dm->edgeData, LAYERTYPE_MEDGE, LAYERFLAG_NOCOPY,
+ NULL);
+ CustomData_add_layer(&dm->faceData, LAYERTYPE_MFACE, LAYERFLAG_NOCOPY,
+ NULL);
+
+ return dm;
+}
+
+DerivedMesh *CDDM_from_mesh(Mesh *mesh)
+{
+ DerivedMesh *dm = CDDM_new(mesh->totvert, mesh->totedge, mesh->totface);
+ int i;
+
+ if(mesh->msticky)
+ CustomData_add_layer(&dm->vertData, LAYERTYPE_MSTICKY, 0, NULL);
+ if(mesh->dvert)
+ CustomData_add_layer(&dm->vertData, LAYERTYPE_MDEFORMVERT, 0, NULL);
+
+ if(mesh->tface)
+ CustomData_add_layer(&dm->faceData, LAYERTYPE_TFACE, 0, NULL);
+ if(mesh->mcol)
+ CustomData_add_layer(&dm->faceData, LAYERTYPE_MCOL, 0, NULL);
+
+ for(i = 0; i < mesh->totvert; ++i) {
+ DM_set_vert_data(dm, i, LAYERTYPE_MVERT, &mesh->mvert[i]);
+ if(mesh->msticky)
+ DM_set_vert_data(dm, i, LAYERTYPE_MSTICKY, &mesh->msticky[i]);
+ if(mesh->dvert)
+ DM_set_vert_data(dm, i, LAYERTYPE_MDEFORMVERT, &mesh->dvert[i]);
+
+ DM_set_vert_data(dm, i, LAYERTYPE_ORIGINDEX, &i);
+ }
+
+ for(i = 0; i < mesh->totedge; ++i) {
+ DM_set_edge_data(dm, i, LAYERTYPE_MEDGE, &mesh->medge[i]);
+
+ DM_set_edge_data(dm, i, LAYERTYPE_ORIGINDEX, &i);
+ }
+
+ for(i = 0; i < mesh->totface; ++i) {
+ DM_set_face_data(dm, i, LAYERTYPE_MFACE, &mesh->mface[i]);
+ if(mesh->tface)
+ DM_set_face_data(dm, i, LAYERTYPE_TFACE, &mesh->tface[i]);
+ if(mesh->mcol)
+ DM_set_face_data(dm, i, LAYERTYPE_MCOL, &mesh->mcol[i * 4]);
+
+ DM_set_face_data(dm, i, LAYERTYPE_ORIGINDEX, &i);
+ }
+
+ return dm;
+}
+
+DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *me)
+{
+ DerivedMesh *dm = CDDM_new(BLI_countlist(&em->verts),
+ BLI_countlist(&em->edges),
+ BLI_countlist(&em->faces));
+ EditVert *eve;
+ EditEdge *eed;
+ EditFace *efa;
+ int i;
+ MVert *mvert = CDDM_get_verts(dm);
+ MEdge *medge = CDDM_get_edges(dm);
+ MFace *mface = CDDM_get_faces(dm);
+ int *index;
+
+ /* this maps from vert pointer to vert index */
+ GHash *vertHash = BLI_ghash_new(BLI_ghashutil_ptrhash,
+ BLI_ghashutil_ptrcmp);
+
+ for(i = 0, eve = em->verts.first; eve; eve = eve->next, ++i)
+ BLI_ghash_insert(vertHash, eve, (void *)i);
+
+ if(me->msticky)
+ CustomData_add_layer(&dm->vertData, LAYERTYPE_MDEFORMVERT, 0, NULL);
+ if(me->dvert)
+ CustomData_add_layer(&dm->vertData, LAYERTYPE_MDEFORMVERT, 0, NULL);
+
+ if(me->tface)
+ CustomData_add_layer(&dm->faceData, LAYERTYPE_TFACE, 0, NULL);
+
+ /* Need to be able to mark loose edges */
+ for(eed = em->edges.first; eed; eed = eed->next) {
+ eed->f2 = 0;
+ }
+ for(efa = em->faces.first; efa; efa = efa->next) {
+ efa->e1->f2 = 1;
+ efa->e2->f2 = 1;
+ efa->e3->f2 = 1;
+ if(efa->e4) efa->e4->f2 = 1;
+ }
+
+ index = dm->getVertDataArray(dm, LAYERTYPE_ORIGINDEX);
+ for(i = 0, eve = em->verts.first; i < dm->vertData.numElems;
+ i++, eve = eve->next, index++) {
+ MVert *mv = &mvert[i];
+
+ VECCOPY(mv->co, eve->co);
+
+ mv->no[0] = eve->no[0] * 32767.0;
+ mv->no[1] = eve->no[1] * 32767.0;
+ mv->no[2] = eve->no[2] * 32767.0;
+
+ mv->mat_nr = 0;
+ mv->flag = 0;
+
+ *index = i;
+
+ if(me->msticky && eve->keyindex != -1)
+ DM_set_vert_data(dm, i, LAYERTYPE_MSTICKY,
+ &me->msticky[eve->keyindex]);
+ if(me->dvert && eve->keyindex != -1)
+ DM_set_vert_data(dm, i, LAYERTYPE_MDEFORMVERT,
+ &me->dvert[eve->keyindex]);
+ }
+
+ index = dm->getEdgeDataArray(dm, LAYERTYPE_ORIGINDEX);
+ for(i = 0, eed = em->edges.first; i < dm->edgeData.numElems;
+ i++, eed = eed->next, index++) {
+ MEdge *med = &medge[i];
+
+ med->v1 = (int) BLI_ghash_lookup(vertHash, eed->v1);
+ med->v2 = (int) BLI_ghash_lookup(vertHash, eed->v2);
+ med->crease = (unsigned char) (eed->crease * 255.0f);
+ med->flag = ME_EDGEDRAW|ME_EDGERENDER;
+
+ if(eed->seam) med->flag |= ME_SEAM;
+ if(eed->sharp) med->flag |= ME_SHARP;
+ if(!eed->f2) med->flag |= ME_LOOSEEDGE;
+
+ *index = i;
+ }
+
+ index = dm->getFaceDataArray(dm, LAYERTYPE_ORIGINDEX);
+ for(i = 0, efa = em->faces.first; i < dm->faceData.numElems;
+ i++, efa = efa->next, index++) {
+ MFace *mf = &mface[i];
+
+ mf->v1 = (int) BLI_ghash_lookup(vertHash, efa->v1);
+ mf->v2 = (int) BLI_ghash_lookup(vertHash, efa->v2);
+ mf->v3 = (int) BLI_ghash_lookup(vertHash, efa->v3);
+ mf->v4 = efa->v4 ? (int)BLI_ghash_lookup(vertHash, efa->v4) : 0;
+ mf->mat_nr = efa->mat_nr;
+ mf->flag = efa->flag;
+ test_index_face(mf, NULL, NULL, efa->v4?4:3);
+
+ *index = i;
+
+ if(me->tface)
+ DM_set_face_data(dm, i, LAYERTYPE_TFACE, &efa->tf);
+ }
+
+ BLI_ghash_free(vertHash, NULL, NULL);
+
+ return dm;
+}
+
+DerivedMesh *CDDM_copy(DerivedMesh *source)
+{
+ DerivedMesh *dest = CDDM_from_template(source,
+ source->vertData.numElems,
+ source->edgeData.numElems,
+ source->faceData.numElems);
+
+ CustomData_copy_data(&source->vertData, &dest->vertData, 0, 0,
+ source->vertData.numElems);
+ CustomData_copy_data(&source->edgeData, &dest->edgeData, 0, 0,
+ source->edgeData.numElems);
+ CustomData_copy_data(&source->faceData, &dest->faceData, 0, 0,
+ source->faceData.numElems);
+
+ /* copy vert/face/edge data from source */
+ source->getVertArray(source, CDDM_get_verts(dest));
+ source->getEdgeArray(source, CDDM_get_edges(dest));
+ source->getFaceArray(source, CDDM_get_faces(dest));
+
+ return dest;
+}
+
+DerivedMesh *CDDM_from_template(DerivedMesh *source,
+ int numVerts, int numEdges, int numFaces)
+{
+ DerivedMesh *dest = cdDM_create("CDDM_from_template dest");
+ DM_from_template(dest, source, numVerts, numEdges, numFaces);
+
+ /* if no vert/face/edge layers in custom data, add them */
+ if(!CDDM_get_verts(dest))
+ CustomData_add_layer(&dest->vertData, LAYERTYPE_MVERT,
+ LAYERFLAG_NOCOPY, NULL);
+ if(!CDDM_get_edges(dest))
+ CustomData_add_layer(&dest->edgeData, LAYERTYPE_MEDGE,
+ LAYERFLAG_NOCOPY, NULL);
+ if(!CDDM_get_faces(dest))
+ CustomData_add_layer(&dest->faceData, LAYERTYPE_MFACE,
+ LAYERFLAG_NOCOPY, NULL);
+
+ return dest;
+}
+
+void CDDM_apply_vert_coords(DerivedMesh *dm, float (*vertCoords)[3])
+{
+ int i;
+ MVert *vert = CDDM_get_verts(dm);
+
+ for(i = 0; i < dm->vertData.numElems; ++i, ++vert)
+ VECCOPY(vert->co, vertCoords[i]);
+}
+
+/* adapted from mesh_calc_normals */
+void CDDM_calc_normals(DerivedMesh *dm)
+{
+ float (*temp_nors)[3];
+ float (*face_nors)[3];
+ int i;
+ int numVerts = dm->getNumVerts(dm);
+ int numFaces = dm->getNumFaces(dm);
+ MFace *mf;
+ MVert *mv = CDDM_get_verts(dm);
+
+ if(!mv) return;
+
+ temp_nors = MEM_callocN(numVerts * sizeof(*temp_nors),
+ "CDDM_calc_normals temp_nors");
+ face_nors = MEM_mallocN(numFaces * sizeof(*face_nors),
+ "CDDM_calc_normals face_nors");
+
+ mf = CDDM_get_faces(dm);
+ for(i = 0; i < numFaces; i++, mf++) {
+ float *f_no = face_nors[i];
+
+ if(mf->v4)
+ CalcNormFloat4(mv[mf->v1].co, mv[mf->v2].co,
+ mv[mf->v3].co, mv[mf->v4].co, f_no);
+ else
+ CalcNormFloat(mv[mf->v1].co, mv[mf->v2].co,
+ mv[mf->v3].co, f_no);
+
+ VecAddf(temp_nors[mf->v1], temp_nors[mf->v1], f_no);
+ VecAddf(temp_nors[mf->v2], temp_nors[mf->v2], f_no);
+ VecAddf(temp_nors[mf->v3], temp_nors[mf->v3], f_no);
+ if(mf->v4)
+ VecAddf(temp_nors[mf->v4], temp_nors[mf->v4], f_no);
+ }
+
+ for(i = 0; i < numVerts; i++, mv++) {
+ float *no = temp_nors[i];
+
+ if (Normalise(no) == 0.0) {
+ VECCOPY(no, mv->co);
+ Normalise(no);
+ }
+
+ mv->no[0] = (short)(no[0] * 32767.0);
+ mv->no[1] = (short)(no[1] * 32767.0);
+ mv->no[2] = (short)(no[2] * 32767.0);
+ }
+
+ MEM_freeN(temp_nors);
+
+ /* TODO maybe cache face normals here? */
+ MEM_freeN(face_nors);
+}
+
+void CDDM_calc_edges(DerivedMesh *dm)
+{
+ CustomData edgeData;
+ EdgeHash *eh = BLI_edgehash_new();
+ EdgeHashIterator *ehi;
+ int i;
+ int maxFaces = dm->getNumFaces(dm);
+ MFace *mf = CDDM_get_faces(dm);
+ MEdge *med;
+
+ for (i = 0; i < maxFaces; i++, mf++) {
+ if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2))
+ BLI_edgehash_insert(eh, mf->v1, mf->v2, NULL);
+ if (!BLI_edgehash_haskey(eh, mf->v2, mf->v3))
+ BLI_edgehash_insert(eh, mf->v2, mf->v3, NULL);
+
+ if (mf->v4) {
+ if (!BLI_edgehash_haskey(eh, mf->v3, mf->v4))
+ BLI_edgehash_insert(eh, mf->v3, mf->v4, NULL);
+ if (!BLI_edgehash_haskey(eh, mf->v4, mf->v1))
+ BLI_edgehash_insert(eh, mf->v4, mf->v1, NULL);
+ } else {
+ if (!BLI_edgehash_haskey(eh, mf->v3, mf->v1))
+ BLI_edgehash_insert(eh, mf->v3, mf->v1, NULL);
+ }
+ }
+
+ CustomData_from_template(&dm->edgeData, &edgeData, BLI_edgehash_size(eh));
+
+ if(!CustomData_get_layer(&edgeData, LAYERTYPE_MEDGE))
+ CustomData_add_layer(&edgeData, LAYERTYPE_MEDGE,
+ LAYERFLAG_NOCOPY, NULL);
+
+ ehi = BLI_edgehashIterator_new(eh);
+ med = CustomData_get_layer(&edgeData, LAYERTYPE_MEDGE);
+ for(i = 0; !BLI_edgehashIterator_isDone(ehi);
+ BLI_edgehashIterator_step(ehi), ++i, ++med) {
+ BLI_edgehashIterator_getKey(ehi, &med->v1, &med->v2);
+
+ med->flag = ME_EDGEDRAW|ME_EDGERENDER;
+ }
+ BLI_edgehashIterator_free(ehi);
+
+ CustomData_free(&dm->edgeData);
+ dm->edgeData = edgeData;
+
+ BLI_edgehash_free(eh, NULL);
+}
+
+void CDDM_set_num_verts(DerivedMesh *dm, int numVerts)
+{
+ CustomData_set_num_elems(&dm->vertData, numVerts);
+}
+
+void CDDM_set_num_edges(DerivedMesh *dm, int numEdges)
+{
+ CustomData_set_num_elems(&dm->edgeData, numEdges);
+}
+
+void CDDM_set_num_faces(DerivedMesh *dm, int numFaces)
+{
+ CustomData_set_num_elems(&dm->faceData, numFaces);
+}
+
+MVert *CDDM_get_vert(DerivedMesh *dm, int index)
+{
+ return CustomData_get(&dm->vertData, index, LAYERTYPE_MVERT);
+}
+
+MEdge *CDDM_get_edge(DerivedMesh *dm, int index)
+{
+ return CustomData_get(&dm->edgeData, index, LAYERTYPE_MEDGE);
+}
+
+MFace *CDDM_get_face(DerivedMesh *dm, int index)
+{
+ return CustomData_get(&dm->faceData, index, LAYERTYPE_MFACE);
+}
+
+MVert *CDDM_get_verts(DerivedMesh *dm)
+{
+ return CustomData_get_layer(&dm->vertData, LAYERTYPE_MVERT);
+}
+
+MEdge *CDDM_get_edges(DerivedMesh *dm)
+{
+ return CustomData_get_layer(&dm->edgeData, LAYERTYPE_MEDGE);
+}
+
+MFace *CDDM_get_faces(DerivedMesh *dm)
+{
+ return CustomData_get_layer(&dm->faceData, LAYERTYPE_MFACE);
+}
+
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
new file mode 100644
index 00000000000..d774324f1c1
--- /dev/null
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -0,0 +1,630 @@
+/*
+* $Id$
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* The Original Code is Copyright (C) 2006 Blender Foundation.
+* All rights reserved.
+*
+* The Original Code is: all of this file.
+*
+* Contributor(s): Ben Batt <benbatt@gmail.com>
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+* Implementation of CustomData.
+*
+* BKE_customdata.h contains the function prototypes for this file.
+*
+*/
+
+#include "BKE_customdata.h"
+
+#include "BLI_linklist.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include <string.h>
+
+/* number of layers to add when growing a CustomData object */
+#define CUSTOMDATA_GROW 5
+
+/* descriptor and storage for a custom data layer */
+typedef struct LayerDesc {
+ int type; /* type of data in layer */
+ int flag; /* general purpose flag */
+ void *data; /* layer data */
+} LayerDesc;
+
+/********************* Layer type information **********************/
+typedef struct LayerTypeInfo {
+ int size; /* the memory size of one element of this layer's data */
+
+ /* a function to copy count elements of this layer's data
+ * (deep copy if appropriate)
+ * size should be the size of one element of this layer's data (e.g.
+ * LayerTypeInfo.size)
+ * if NULL, memcpy is used
+ */
+ void (*copy)(const void *source, void *dest, int count, int size);
+
+ /* a function to free any dynamically allocated components of this
+ * layer's data (note the data pointer itself should not be freed)
+ * size should be the size of one element of this layer's data (e.g.
+ * LayerTypeInfo.size)
+ */
+ void (*free)(void *data, int count, int size);
+
+ /* a function to interpolate between count source elements of this
+ * layer's data and store the result in dest
+ * if weights == NULL or sub_weights == NULL, they should default to 1
+ *
+ * weights gives the weight for each element in sources
+ * sub_weights gives the sub-element weights for each element in sources
+ * (there should be (sub element count)^2 weights per element)
+ * count gives the number of elements in sources
+ */
+ void (*interp)(void **sources, float *weights, float *sub_weights,
+ int count, void *dest);
+} LayerTypeInfo;
+
+static void layerCopy_mdeformvert(const void *source, void *dest,
+ int count, int size);
+
+static void layerFree_mdeformvert(void *data, int count, int size);
+
+static void layerInterp_mdeformvert(void **sources, float *weights,
+ float *sub_weights, int count, void *dest);
+
+static void layerInterp_tface(void **sources, float *weights,
+ float *sub_weights, int count, void *dest);
+
+static void layerInterp_mcol(void **sources, float *weights,
+ float *sub_weights, int count, void *dest);
+
+const LayerTypeInfo LAYERTYPEINFO[LAYERTYPE_NUMTYPES] = {
+ {sizeof(MVert), NULL, NULL, NULL},
+ {sizeof(MSticky), NULL, NULL, NULL},
+ {sizeof(MDeformVert),
+ layerCopy_mdeformvert, layerFree_mdeformvert, layerInterp_mdeformvert},
+ {sizeof(MEdge), NULL, NULL, NULL},
+ {sizeof(MFace), NULL, NULL, NULL},
+ {sizeof(TFace), NULL, NULL, layerInterp_tface},
+ /* 4 MCol structs per face */
+ {sizeof(MCol) * 4, NULL, NULL, layerInterp_mcol},
+ {sizeof(int), NULL, NULL, NULL},
+ /* 3 floats per normal vector */
+ {sizeof(float) * 3, NULL, NULL, NULL},
+ {sizeof(int), NULL, NULL, NULL},
+};
+
+const LayerTypeInfo *layerType_getInfo(int type)
+{
+ if(type < 0 || type >= LAYERTYPE_NUMTYPES) return NULL;
+
+ return &LAYERTYPEINFO[type];
+}
+
+static void layerCopy_mdeformvert(const void *source, void *dest,
+ int count, int size)
+{
+ int i;
+
+ memcpy(dest, source, count * size);
+
+ for(i = 0; i < count; ++i) {
+ MDeformVert *dvert = (MDeformVert *)((char *)dest + i * size);
+ MDeformWeight *dw = MEM_callocN(dvert->totweight * sizeof(*dw),
+ "layerCopy_mdeformvert dw");
+
+ memcpy(dw, dvert->dw, dvert->totweight * sizeof(*dw));
+ dvert->dw = dw;
+ }
+}
+
+static void layerFree_mdeformvert(void *data, int count, int size)
+{
+ int i;
+
+ for(i = 0; i < count; ++i) {
+ MDeformVert *dvert = (MDeformVert *)((char *)data + i * size);
+
+ if(dvert->dw) {
+ MEM_freeN(dvert->dw);
+ dvert->dw = NULL;
+ }
+ }
+}
+
+static void linklist_free_simple(void *link)
+{
+ MEM_freeN(link);
+}
+
+static void layerInterp_mdeformvert(void **sources, float *weights,
+ float *sub_weights, int count, void *dest)
+{
+ MDeformVert *dvert = dest;
+ LinkNode *dest_dw = NULL; /* a list of lists of MDeformWeight pointers */
+ LinkNode *node;
+ int i, j, totweight;
+
+ if(count <= 0) return;
+
+ /* build a list of unique def_nrs for dest */
+ totweight = 0;
+ for(i = 0; i < count; ++i) {
+ MDeformVert *source = sources[i];
+ float interp_weight = weights ? weights[i] : 1.0f;
+
+ for(j = 0; j < source->totweight; ++j) {
+ MDeformWeight *dw = &source->dw[j];
+
+ for(node = dest_dw; node; node = node->next) {
+ MDeformWeight *tmp_dw = (MDeformWeight *)node->link;
+
+ if(tmp_dw->def_nr == dw->def_nr) {
+ tmp_dw->weight += dw->weight * interp_weight;
+ break;
+ }
+ }
+
+ /* if this def_nr is not in the list, add it */
+ if(!node) {
+ MDeformWeight *tmp_dw = MEM_callocN(sizeof(*tmp_dw),
+ "layerInterp_mdeformvert tmp_dw");
+ tmp_dw->def_nr = dw->def_nr;
+ tmp_dw->weight = dw->weight * interp_weight;
+ BLI_linklist_prepend(&dest_dw, tmp_dw);
+ totweight++;
+ }
+ }
+ }
+
+ /* now we know how many unique deform weights there are, so realloc */
+ if(dvert->dw) MEM_freeN(dvert->dw);
+ dvert->dw = MEM_callocN(sizeof(*dvert->dw) * totweight,
+ "layerInterp_mdeformvert dvert->dw");
+ dvert->totweight = totweight;
+
+ for(i = 0, node = dest_dw; node; node = node->next, ++i)
+ dvert->dw[i] = *((MDeformWeight *)node->link);
+
+ BLI_linklist_free(dest_dw, linklist_free_simple);
+}
+
+static void layerInterp_tface(void **sources, float *weights,
+ float *sub_weights, int count, void *dest)
+{
+ TFace *tf = dest;
+ int i, j, k;
+ float uv[4][2];
+ float col[4][4];
+
+ if(count <= 0) return;
+
+ memset(uv, 0, sizeof(uv));
+ memset(col, 0, sizeof(col));
+
+ for(i = 0; i < count; ++i) {
+ float weight = weights ? weights[i] : 1;
+ TFace *src = sources[i];
+
+ for(j = 0; j < 4; ++j) {
+ if(sub_weights) {
+ for(k = 0; k < 4; ++k) {
+ float sub_weight = sub_weights[j * 4 + k];
+ char *tmp_col = (char *)&src->col[k];
+ float *tmp_uv = src->uv[k];
+
+ uv[j][0] += tmp_uv[0] * sub_weight * weight;
+ uv[j][1] += tmp_uv[1] * sub_weight * weight;
+
+ col[j][0] += tmp_col[0] * sub_weight * weight;
+ col[j][1] += tmp_col[1] * sub_weight * weight;
+ col[j][2] += tmp_col[2] * sub_weight * weight;
+ col[j][3] += tmp_col[3] * sub_weight * weight;
+ }
+ } else {
+ char *tmp_col = (char *)&src->col[j];
+ uv[j][0] += src->uv[j][0] * weight;
+ uv[j][1] += src->uv[j][1] * weight;
+
+ col[j][0] += tmp_col[0] * weight;
+ col[j][1] += tmp_col[1] * weight;
+ col[j][2] += tmp_col[2] * weight;
+ col[j][3] += tmp_col[3] * weight;
+ }
+ }
+ }
+
+ *tf = *(TFace *)sources[0];
+ for(j = 0; j < 4; ++j) {
+ char *tmp_col = (char *)&tf->col[j];
+
+ tf->uv[j][0] = uv[j][0];
+ tf->uv[j][1] = uv[j][1];
+
+ tmp_col[0] = (int)col[j][0];
+ tmp_col[1] = (int)col[j][1];
+ tmp_col[2] = (int)col[j][2];
+ tmp_col[3] = (int)col[j][3];
+ }
+}
+
+static void layerInterp_mcol(void **sources, float *weights,
+ float *sub_weights, int count, void *dest)
+{
+ MCol *mc = dest;
+ int i, j, k;
+ struct {
+ float a;
+ float r;
+ float g;
+ float b;
+ } col[4];
+
+ if(count <= 0) return;
+
+ memset(col, 0, sizeof(col));
+
+ for(i = 0; i < count; ++i) {
+ float weight = weights ? weights[i] : 1;
+ float *sub_weight = sub_weights;
+
+ for(j = 0; j < 4; ++j) {
+ if(sub_weights) {
+ MCol *src = sources[i];
+ for(k = 0; k < 4; ++k, ++sub_weight, ++src) {
+ col[j].a += src->a * (*sub_weight) * weight;
+ col[j].r += src->r * (*sub_weight) * weight;
+ col[j].g += src->g * (*sub_weight) * weight;
+ col[j].b += src->b * (*sub_weight) * weight;
+ }
+ } else {
+ MCol *src = sources[i];
+ col[j].a += src[j].a * weight;
+ col[j].r += src[j].r * weight;
+ col[j].g += src[j].g * weight;
+ col[j].b += src[j].b * weight;
+ }
+ }
+ }
+
+ for(j = 0; j < 4; ++j) {
+ mc[j].a = (int)col[j].a;
+ mc[j].r = (int)col[j].r;
+ mc[j].g = (int)col[j].g;
+ mc[j].b = (int)col[j].b;
+ }
+}
+
+/********************* CustomData functions *********************/
+void CustomData_init(CustomData *data,
+ int maxLayers, int maxElems, int subElems)
+{
+ data->layers = MEM_callocN(maxLayers * sizeof(*data->layers),
+ "CustomData->layers");
+ data->numLayers = 0;
+ data->maxLayers = maxLayers;
+ data->numElems = maxElems;
+ data->maxElems = maxElems;
+ data->subElems = subElems;
+}
+
+void CustomData_from_template(const CustomData *source, CustomData *dest,
+ int maxElems)
+{
+ int i;
+
+ CustomData_init(dest, source->maxLayers, maxElems, source->subElems);
+
+ for(i = 0; i < source->numLayers; ++i) {
+ if(source->layers[i].flag & LAYERFLAG_NOCOPY) continue;
+
+ CustomData_add_layer(dest, source->layers[i].type,
+ source->layers[i].flag & ~LAYERFLAG_NOFREE, NULL);
+ }
+}
+
+void CustomData_free(CustomData *data)
+{
+ int i;
+ const LayerTypeInfo *typeInfo;
+
+ for(i = 0; i < data->numLayers; ++i) {
+ if(!(data->layers[i].flag & LAYERFLAG_NOFREE)) {
+ typeInfo = layerType_getInfo(data->layers[i].type);
+ if(typeInfo->free)
+ typeInfo->free(data->layers[i].data, data->numElems,
+ typeInfo->size);
+
+ MEM_freeN(data->layers[i].data);
+ }
+ }
+
+ data->numLayers = 0;
+
+ if(data->layers) {
+ MEM_freeN(data->layers);
+ data->layers = NULL;
+ }
+}
+
+static int customData_grow(CustomData *data, int amount)
+{
+ LayerDesc *tmp = MEM_callocN(sizeof(*tmp) * (data->maxLayers + amount),
+ "CustomData->layers");
+ if(!tmp) return 0;
+
+ data->maxLayers += amount;
+ memcpy(tmp, data->layers, sizeof(*tmp) * data->numLayers);
+
+ MEM_freeN(data->layers);
+ data->layers = tmp;
+
+ return 1;
+}
+
+static int customData_add_layer__internal(CustomData *data, int type,
+ int flag, void *layer)
+{
+ int index = data->numLayers;
+
+ if(index >= data->maxLayers)
+ if(!customData_grow(data, CUSTOMDATA_GROW)) return 0;
+
+ /* keep layers ordered by type */
+ for( ; index > 0 && data->layers[index - 1].type > type; --index)
+ data->layers[index] = data->layers[index - 1];
+
+ data->layers[index].type = type;
+ data->layers[index].flag = flag;
+ data->layers[index].data = layer;
+
+ data->numLayers++;
+
+ return 1;
+}
+
+int CustomData_add_layer(CustomData *data, int type, int flag, void *layer)
+{
+ int size = layerType_getInfo(type)->size * data->numElems;
+ void *tmp_layer = layer;
+
+ if(!layer) tmp_layer = MEM_callocN(size, "LayerDesc.data");
+
+ if(!tmp_layer) return 0;
+
+ if(customData_add_layer__internal(data, type, flag, tmp_layer))
+ return 1;
+ else {
+ MEM_freeN(tmp_layer);
+ return 0;
+ }
+}
+
+int CustomData_compat(const CustomData *data1, const CustomData *data2)
+{
+ int i;
+
+ if(data1->numLayers != data2->numLayers) return 0;
+
+ for(i = 0; i < data1->numLayers; ++i) {
+ if(data1->layers[i].type != data2->layers[i].type) return 0;
+ if(data1->layers[i].flag != data2->layers[i].flag) return 0;
+ }
+
+ return 1;
+}
+
+/* gets index of first layer matching type after start_index
+ * if start_index < 0, starts searching at 0
+ * returns -1 if there is no layer of type
+ */
+static int CustomData_find_next(const CustomData *data, int type,
+ int start_index)
+{
+ int i = start_index + 1;
+
+ if(i < 0) i = 0;
+
+ for(; i < data->numLayers; ++i)
+ if(data->layers[i].type == type) return i;
+
+ return -1;
+}
+
+int CustomData_copy_data(const CustomData *source, CustomData *dest,
+ int source_index, int dest_index, int count)
+{
+ const LayerTypeInfo *type_info;
+ int src_i, dest_i;
+ int src_offset;
+ int dest_offset;
+
+ if(count < 0) return 0;
+ if(source_index < 0 || (source_index + count) > source->numElems)
+ return 0;
+ if(dest_index < 0 || (dest_index + count) > dest->numElems)
+ return 0;
+
+ /* copies a layer at a time */
+ dest_i = 0;
+ for(src_i = 0; src_i < source->numLayers; ++src_i) {
+ if(source->layers[src_i].flag & LAYERFLAG_NOCOPY) continue;
+
+ /* find the first dest layer with type >= the source type
+ * (this should work because layers are ordered by type)
+ */
+ while(dest_i < dest->numLayers
+ && dest->layers[dest_i].type < source->layers[src_i].type)
+ ++dest_i;
+
+ /* if there are no more dest layers, we're done */
+ if(dest_i >= dest->numLayers) return 1;
+
+ /* if we found a matching layer, copy the data */
+ if(dest->layers[dest_i].type == source->layers[src_i].type) {
+ char *src_data = source->layers[src_i].data;
+ char *dest_data = dest->layers[dest_i].data;
+
+ type_info = layerType_getInfo(source->layers[src_i].type);
+
+ src_offset = source_index * type_info->size;
+ dest_offset = dest_index * type_info->size;
+
+ if(type_info->copy)
+ type_info->copy(src_data + src_offset,
+ dest_data + dest_offset,
+ count, type_info->size);
+ else
+ memcpy(dest_data + dest_offset,
+ src_data + src_offset,
+ count * type_info->size);
+
+ /* if there are multiple source & dest layers of the same type,
+ * we don't want to copy all source layers to the same dest, so
+ * increment dest_i
+ */
+ ++dest_i;
+ }
+ }
+
+ return 1;
+}
+
+int CustomData_free_elem(CustomData *data, int index, int count)
+{
+ int i;
+ const LayerTypeInfo *typeInfo;
+
+ if(index < 0 || count <= 0 || index + count > data->numElems) return 0;
+
+ for(i = 0; i < data->numLayers; ++i) {
+ if(!(data->layers[i].flag & LAYERFLAG_NOFREE)) {
+ typeInfo = layerType_getInfo(data->layers[i].type);
+
+ if(typeInfo->free) {
+ int offset = typeInfo->size * index;
+
+ typeInfo->free((char *)data->layers[i].data + offset,
+ count, typeInfo->size);
+ }
+ }
+ }
+
+ return 1;
+}
+
+#define SOURCE_BUF_SIZE 100
+
+int CustomData_interp(const CustomData *source, CustomData *dest,
+ int *src_indices, float *weights, float *sub_weights,
+ int count, int dest_index)
+{
+ int src_i, dest_i;
+ int dest_offset;
+ int j;
+ void *source_buf[SOURCE_BUF_SIZE];
+ void **sources = source_buf;
+
+ if(count <= 0) return 0;
+ if(dest_index < 0 || dest_index >= dest->numElems) return 0;
+
+ /* slow fallback in case we're interpolating a ridiculous number of
+ * elements
+ */
+ if(count > SOURCE_BUF_SIZE)
+ sources = MEM_callocN(sizeof(*sources) * count,
+ "CustomData_interp sources");
+
+ /* interpolates a layer at a time */
+ for(src_i = 0; src_i < source->numLayers; ++src_i) {
+ LayerDesc *source_layer = &source->layers[src_i];
+ const LayerTypeInfo *type_info =
+ layerType_getInfo(source_layer->type);
+
+ dest_i = CustomData_find_next(dest, source_layer->type, -1);
+
+ if(dest_i >= 0 && type_info->interp) {
+ void *src_data = source_layer->data;
+
+ for(j = 0; j < count; ++j)
+ sources[j] = (char *)src_data
+ + type_info->size * src_indices[j];
+
+ dest_offset = dest_index * type_info->size;
+
+ type_info->interp(sources, weights, sub_weights, count,
+ (char *)dest->layers[dest_i].data + dest_offset);
+ }
+ }
+
+ if(count > SOURCE_BUF_SIZE) MEM_freeN(sources);
+ return 1;
+}
+
+void *CustomData_get(const CustomData *data, int index, int type)
+{
+ int offset;
+ int layer_index;
+
+ if(index < 0 || index > data->numElems) return NULL;
+
+ /* get the layer index of the first layer of type */
+ layer_index = CustomData_find_next(data, type, -1);
+ if(layer_index < 0) return NULL;
+
+ /* get the offset of the desired element */
+ offset = layerType_getInfo(type)->size * index;
+
+ return (char *)data->layers[layer_index].data + offset;
+}
+
+void *CustomData_get_layer(const CustomData *data, int type)
+{
+ /* get the layer index of the first layer of type */
+ int layer_index = CustomData_find_next(data, type, -1);
+
+ if(layer_index < 0) return NULL;
+
+ return data->layers[layer_index].data;
+}
+
+void CustomData_set(const CustomData *data, int index, int type, void *source)
+{
+ void *dest = CustomData_get(data, index, type);
+ const LayerTypeInfo *type_info = layerType_getInfo(type);
+
+ if(!dest) return;
+
+ if(type_info->copy)
+ type_info->copy(source, dest, 1, type_info->size);
+ else
+ memcpy(dest, source, type_info->size);
+}
+
+void CustomData_set_num_elems(CustomData *data, int numElems)
+{
+ if(numElems < 0) return;
+ if(numElems < data->maxElems) data->numElems = numElems;
+ else data->numElems = data->maxElems;
+}
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index 8f92a0a0d68..b262dac695a 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -1189,13 +1189,18 @@ static ModifierData *curve_get_tesselate_point(Object *ob, int forRender, int ed
{
ModifierData *md = modifiers_getVirtualModifierList(ob);
ModifierData *preTesselatePoint;
+ int required_mode;
+
+ if(forRender) required_mode = eModifierMode_Render;
+ else required_mode = eModifierMode_Realtime;
+
+ if(editmode) required_mode |= eModifierMode_Editmode;
preTesselatePoint = NULL;
for (; md; md=md->next) {
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
- if (!(md->mode&(1<<forRender))) continue;
- if (editmode && !(md->mode&eModifierMode_Editmode)) continue;
+ if ((md->mode & required_mode) != required_mode) continue;
if (mti->isDisabled && mti->isDisabled(md)) continue;
if (md->type==eModifierType_Hook || md->type==eModifierType_Softbody) {
@@ -1214,6 +1219,12 @@ void curve_calc_modifiers_pre(Object *ob, ListBase *nurb, int forRender, float (
int numVerts = 0;
float (*originalVerts)[3] = NULL;
float (*deformedVerts)[3] = NULL;
+ int required_mode;
+
+ if(forRender) required_mode = eModifierMode_Render;
+ else required_mode = eModifierMode_Realtime;
+
+ if(editmode) required_mode |= eModifierMode_Editmode;
if(ob!=G.obedit && do_ob_key(ob)) {
deformedVerts = curve_getVertexCos(ob->data, nurb, &numVerts);
@@ -1224,8 +1235,7 @@ void curve_calc_modifiers_pre(Object *ob, ListBase *nurb, int forRender, float (
for (; md; md=md->next) {
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
- if (!(md->mode&(1<<forRender))) continue;
- if (editmode && !(md->mode&eModifierMode_Editmode)) continue;
+ if ((md->mode & required_mode) != required_mode) continue;
if (mti->isDisabled && mti->isDisabled(md)) continue;
if (mti->type!=eModifierTypeType_OnlyDeform) continue;
@@ -1256,6 +1266,12 @@ void curve_calc_modifiers_post(Object *ob, ListBase *nurb, ListBase *dispbase, i
ModifierData *md = modifiers_getVirtualModifierList(ob);
ModifierData *preTesselatePoint = curve_get_tesselate_point(ob, forRender, editmode);
DispList *dl;
+ int required_mode;
+
+ if(forRender) required_mode = eModifierMode_Render;
+ else required_mode = eModifierMode_Realtime;
+
+ if(editmode) required_mode |= eModifierMode_Editmode;
if (preTesselatePoint) {
md = preTesselatePoint->next;
@@ -1264,8 +1280,7 @@ void curve_calc_modifiers_post(Object *ob, ListBase *nurb, ListBase *dispbase, i
for (; md; md=md->next) {
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
- if (!(md->mode&(1<<forRender))) continue;
- if (editmode && !(md->mode&eModifierMode_Editmode)) continue;
+ if ((md->mode & required_mode) != required_mode) continue;
if (mti->isDisabled && mti->isDisabled(md)) continue;
if (mti->type!=eModifierTypeType_OnlyDeform) continue;
diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c
index 81f7eb7a0eb..768fedd86ea 100644
--- a/source/blender/blenkernel/intern/lattice.c
+++ b/source/blender/blenkernel/intern/lattice.c
@@ -56,6 +56,8 @@
#include "BKE_anim.h"
#include "BKE_armature.h"
#include "BKE_curve.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_DerivedMesh.h"
#include "BKE_deform.h"
#include "BKE_displist.h"
#include "BKE_global.h"
@@ -161,7 +163,7 @@ void resizelattice(Lattice *lt, int uNew, int vNew, int wNew, Object *ltOb)
Mat4CpyMat4(mat, ltOb->obmat);
Mat4One(ltOb->obmat);
- lattice_deform_verts(ltOb, NULL, vertexCos, uNew*vNew*wNew, NULL);
+ lattice_deform_verts(ltOb, NULL, NULL, vertexCos, uNew*vNew*wNew, NULL);
Mat4CpyMat4(ltOb->obmat, mat);
lt->typeu = typeu;
@@ -556,52 +558,85 @@ static void calc_curve_deform(Object *par, float *co, short axis, CurveDeform *c
}
-void curve_deform_verts(Object *cuOb, Object *target, float (*vertexCos)[3], int numVerts, char *vgroup)
+void curve_deform_verts(Object *cuOb, Object *target, DerivedMesh *dm, float (*vertexCos)[3], int numVerts, char *vgroup)
{
Curve *cu = cuOb->data;
int a, flag = cu->flag;
CurveDeform cd;
+ int use_vgroups;
cu->flag |= (CU_PATH|CU_FOLLOW); // needed for path & bevlist
init_curve_deform(cuOb, target, &cd);
- INIT_MINMAX(cd.dmin, cd.dmax);
-
- for(a=0; a<numVerts; a++) {
- Mat4MulVecfl(cd.curvespace, vertexCos[a]);
- DO_MINMAX(vertexCos[a], cd.dmin, cd.dmax);
- }
-
- if(vgroup && vgroup[0] && target->type==OB_MESH) {
+ /* check whether to use vertex groups (only possible if target is a Mesh)
+ * we want either a Mesh with no derived data, or derived data with
+ * deformverts
+ */
+ if(target && target->type==OB_MESH) {
+ /* if there's derived data without deformverts, don't use vgroups */
+ if(dm && !dm->getVertData(dm, 0, LAYERTYPE_MDEFORMVERT))
+ use_vgroups = 0;
+ else
+ use_vgroups = 1;
+ } else
+ use_vgroups = 0;
+
+ if(vgroup && vgroup[0] && use_vgroups) {
bDeformGroup *curdef;
Mesh *me= target->data;
- int index= 0;
+ int index;
/* find the group (weak loop-in-loop) */
- for (curdef = target->defbase.first; curdef; curdef=curdef->next, index++)
+ for(index = 0, curdef = target->defbase.first; curdef;
+ curdef = curdef->next, index++)
if (!strcmp(curdef->name, vgroup))
break;
- /* check for numVerts because old files can have modifier over subsurf still */
- if(curdef && me->dvert && numVerts==me->totvert) {
- MDeformVert *dvert= me->dvert;
+
+ if(curdef && (me->dvert || dm)) {
+ MDeformVert *dvert = me->dvert;
float vec[3];
int j;
-
- for(a=0; a<numVerts; a++, dvert++) {
- for(j=0; j<dvert->totweight; j++) {
- if (dvert->dw[j].def_nr == index) {
+
+ INIT_MINMAX(cd.dmin, cd.dmax);
+
+ for(a = 0; a < numVerts; a++, dvert++) {
+ if(dm) dvert = dm->getVertData(dm, a, LAYERTYPE_MDEFORMVERT);
+
+ for(j = 0; j < dvert->totweight; j++) {
+ if(dvert->dw[j].def_nr == index) {
+ Mat4MulVecfl(cd.curvespace, vertexCos[a]);
+ DO_MINMAX(vertexCos[a], cd.dmin, cd.dmax);
+ break;
+ }
+ }
+ }
+
+ dvert = me->dvert;
+ for(a = 0; a < numVerts; a++, dvert++) {
+ if(dm) dvert = dm->getVertData(dm, a, LAYERTYPE_MDEFORMVERT);
+
+ for(j = 0; j < dvert->totweight; j++) {
+ if(dvert->dw[j].def_nr == index) {
VECCOPY(vec, vertexCos[a]);
calc_curve_deform(cuOb, vec, target->trackflag, &cd);
- VecLerpf(vertexCos[a], vertexCos[a], vec, dvert->dw[j].weight);
+ VecLerpf(vertexCos[a], vertexCos[a], vec,
+ dvert->dw[j].weight);
Mat4MulVecfl(cd.objectspace, vertexCos[a]);
+ break;
}
}
}
}
- }
- else {
- for(a=0; a<numVerts; a++) {
+ } else {
+ INIT_MINMAX(cd.dmin, cd.dmax);
+
+ for(a = 0; a < numVerts; a++) {
+ Mat4MulVecfl(cd.curvespace, vertexCos[a]);
+ DO_MINMAX(vertexCos[a], cd.dmin, cd.dmax);
+ }
+
+ for(a = 0; a < numVerts; a++) {
calc_curve_deform(cuOb, vertexCos[a], target->trackflag, &cd);
Mat4MulVecfl(cd.objectspace, vertexCos[a]);
}
@@ -609,37 +644,52 @@ void curve_deform_verts(Object *cuOb, Object *target, float (*vertexCos)[3], int
cu->flag = flag;
}
-void lattice_deform_verts(Object *laOb, Object *target, float (*vertexCos)[3], int numVerts, char *vgroup)
+void lattice_deform_verts(Object *laOb, Object *target, DerivedMesh *dm,
+ float (*vertexCos)[3], int numVerts, char *vgroup)
{
int a;
+ int use_vgroups;
init_latt_deform(laOb, target);
-
- if(vgroup && vgroup[0] && target->type==OB_MESH) {
+
+ /* check whether to use vertex groups (only possible if target is a Mesh)
+ * we want either a Mesh with no derived data, or derived data with
+ * deformverts
+ */
+ if(target && target->type==OB_MESH) {
+ /* if there's derived data without deformverts, don't use vgroups */
+ if(dm && !dm->getVertData(dm, 0, LAYERTYPE_MDEFORMVERT))
+ use_vgroups = 0;
+ else
+ use_vgroups = 1;
+ } else
+ use_vgroups = 0;
+
+ if(vgroup && vgroup[0] && use_vgroups) {
bDeformGroup *curdef;
- Mesh *me= target->data;
- int index= 0;
+ Mesh *me = target->data;
+ int index = 0;
/* find the group (weak loop-in-loop) */
- for (curdef = target->defbase.first; curdef; curdef=curdef->next, index++)
- if (!strcmp(curdef->name, vgroup))
- break;
- /* check for numVerts because old files can have modifier over subsurf still */
- if(curdef && me->dvert && numVerts==me->totvert) {
- MDeformVert *dvert= me->dvert;
+ for(curdef = target->defbase.first; curdef;
+ curdef = curdef->next, index++)
+ if(!strcmp(curdef->name, vgroup)) break;
+
+ if(curdef && (me->dvert || dm)) {
+ MDeformVert *dvert = me->dvert;
int j;
- for(a=0; a<numVerts; a++, dvert++) {
- for(j=0; j<dvert->totweight; j++) {
+ for(a = 0; a < numVerts; a++, dvert++) {
+ if(dm) dvert = dm->getVertData(dm, a, LAYERTYPE_MDEFORMVERT);
+ for(j = 0; j < dvert->totweight; j++) {
if (dvert->dw[j].def_nr == index) {
calc_latt_deform(vertexCos[a], dvert->dw[j].weight);
}
}
}
}
- }
- else {
- for(a=0; a<numVerts; a++) {
+ } else {
+ for(a = 0; a < numVerts; a++) {
calc_latt_deform(vertexCos[a], 1.0f);
}
}
@@ -652,7 +702,8 @@ int object_deform_mball(Object *ob)
DispList *dl;
for (dl=ob->disp.first; dl; dl=dl->next) {
- lattice_deform_verts(ob->parent, ob, (float(*)[3]) dl->verts, dl->nr, NULL);
+ lattice_deform_verts(ob->parent, ob, NULL,
+ (float(*)[3]) dl->verts, dl->nr, NULL);
}
return 1;
@@ -765,7 +816,7 @@ void lattice_calc_modifiers(Object *ob)
for (; md; md=md->next) {
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
- if (!(md->mode&(1<<0))) continue;
+ if (!(md->mode&eModifierMode_Realtime)) continue;
if (editmode && !(md->mode&eModifierMode_Editmode)) continue;
if (mti->isDisabled && mti->isDisabled(md)) continue;
if (mti->type!=eModifierTypeType_OnlyDeform) continue;
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index c565cfa5979..9e43e30fa7c 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -1,3 +1,41 @@
+/*
+* $Id$
+*
+* ***** BEGIN GPL LICENSE BLOCK *****
+*
+* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* The Original Code is Copyright (C) 2005 by the Blender Foundation.
+* All rights reserved.
+*
+* The Original Code is: all of this file.
+*
+* Contributor(s): Daniel Dunbar
+* Ton Roosendaal,
+* Ben Batt,
+* Brecht Van Lommel,
+* Campbell Barton
+*
+* ***** END GPL LICENSE BLOCK *****
+*
+* Modifier stack implementation.
+*
+* BKE_modifier.h contains the function prototypes for this file.
+*
+*/
+
#include "string.h"
#include "stdarg.h"
#include "math.h"
@@ -5,29 +43,36 @@
#include "BLI_blenlib.h"
#include "BLI_rand.h"
#include "BLI_arithb.h"
+#include "BLI_linklist.h"
#include "BLI_edgehash.h"
+#include "BLI_ghash.h"
#include "MEM_guardedalloc.h"
#include "DNA_armature_types.h"
#include "DNA_effect_types.h"
+#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
#include "DNA_object_force.h"
#include "DNA_scene_types.h"
+#include "DNA_texture_types.h"
#include "DNA_curve_types.h"
+#include "DNA_camera_types.h"
#include "BLI_editVert.h"
#include "MTC_matrixops.h"
#include "MTC_vectorops.h"
+#include "BKE_main.h"
#include "BKE_anim.h"
#include "BKE_bad_level_calls.h"
#include "BKE_global.h"
#include "BKE_utildefines.h"
+#include "BKE_cdderivedmesh.h"
#include "BKE_DerivedMesh.h"
#include "BKE_booleanops.h"
#include "BKE_displist.h"
@@ -37,6 +82,7 @@
#include "BKE_object.h"
#include "BKE_mesh.h"
#include "BKE_softbody.h"
+#include "BKE_material.h"
#include "depsgraph_private.h"
#include "LOD_DependKludge.h"
@@ -44,6 +90,8 @@
#include "CCGSubSurf.h"
+#include "RE_shader_ext.h"
+
/* helper function for modifiers - usage is of this is discouraged, but
avoids duplicate modifier code for DispListMesh and EditMesh */
@@ -85,7 +133,7 @@ DispListMesh *displistmesh_from_editmesh(EditMesh *em)
VECCOPY(mv->co, eve->co);
mv->mat_nr = 0;
- mv->flag = ME_VERT_STEPINDEX;
+ mv->flag = 0;
}
for (i=0,eed=em->edges.first; i<outDLM->totedge; i++,eed=eed->next) {
MEdge *med = &outDLM->medge[i];
@@ -93,7 +141,7 @@ DispListMesh *displistmesh_from_editmesh(EditMesh *em)
med->v1 = (int) eed->v1->prev;
med->v2 = (int) eed->v2->prev;
med->crease = (unsigned char) (eed->crease*255.0f);
- med->flag = ME_EDGEDRAW|ME_EDGERENDER|ME_EDGE_STEPINDEX;
+ med->flag = ME_EDGEDRAW | ME_EDGERENDER;
if (eed->seam) med->flag |= ME_SEAM;
if (!eed->f2) med->flag |= ME_LOOSEEDGE;
@@ -105,7 +153,7 @@ DispListMesh *displistmesh_from_editmesh(EditMesh *em)
mf->v3 = (int) efa->v3->prev;
mf->v4 = efa->v4?(int) efa->v4->prev:0;
mf->mat_nr = efa->mat_nr;
- mf->flag = efa->flag|ME_FACE_STEPINDEX;
+ mf->flag = efa->flag;
test_index_face(mf, NULL, NULL, efa->v4?4:3);
}
@@ -139,34 +187,51 @@ static int curveModifier_isDisabled(ModifierData *md)
return !cmd->object;
}
-static void curveModifier_foreachObjectLink(ModifierData *md, Object *ob, void (*walk)(void *userData, Object *ob, Object **obpoin), void *userData)
+static void curveModifier_foreachObjectLink(
+ ModifierData *md, Object *ob,
+ void (*walk)(void *userData, Object *ob, Object **obpoin),
+ void *userData)
{
CurveModifierData *cmd = (CurveModifierData*) md;
walk(userData, ob, &cmd->object);
}
-static void curveModifier_updateDepgraph(ModifierData *md, DagForest *forest, Object *ob, DagNode *obNode)
+static void curveModifier_updateDepgraph(
+ ModifierData *md, DagForest *forest,
+ Object *ob, DagNode *obNode)
{
CurveModifierData *cmd = (CurveModifierData*) md;
if (cmd->object) {
DagNode *curNode = dag_get_node(forest, cmd->object);
- dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA|DAG_RL_OB_DATA);
+ dag_add_relation(forest, curNode, obNode,
+ DAG_RL_DATA_DATA | DAG_RL_OB_DATA);
}
}
-static void curveModifier_deformVerts(ModifierData *md, Object *ob, void *derivedData, float (*vertexCos)[3], int numVerts)
+static void curveModifier_deformVerts(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ float (*vertexCos)[3], int numVerts)
{
CurveModifierData *cmd = (CurveModifierData*) md;
- curve_deform_verts(cmd->object, ob, vertexCos, numVerts, cmd->name);
+ curve_deform_verts(cmd->object, ob, derivedData, vertexCos, numVerts,
+ cmd->name);
}
-static void curveModifier_deformVertsEM(ModifierData *md, Object *ob, void *editData, void *derivedData, float (*vertexCos)[3], int numVerts)
+static void curveModifier_deformVertsEM(
+ ModifierData *md, Object *ob, EditMesh *editData,
+ DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
- curveModifier_deformVerts(md, ob, NULL, vertexCos, numVerts);
+ DerivedMesh *dm = derivedData;
+
+ if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
+
+ curveModifier_deformVerts(md, ob, dm, vertexCos, numVerts);
+
+ if(!derivedData) dm->release(dm);
}
/* Lattice */
@@ -186,34 +251,50 @@ static int latticeModifier_isDisabled(ModifierData *md)
return !lmd->object;
}
-static void latticeModifier_foreachObjectLink(ModifierData *md, Object *ob, void (*walk)(void *userData, Object *ob, Object **obpoin), void *userData)
+static void latticeModifier_foreachObjectLink(
+ ModifierData *md, Object *ob,
+ void (*walk)(void *userData, Object *ob, Object **obpoin),
+ void *userData)
{
LatticeModifierData *lmd = (LatticeModifierData*) md;
walk(userData, ob, &lmd->object);
}
-static void latticeModifier_updateDepgraph(ModifierData *md, DagForest *forest, Object *ob, DagNode *obNode)
+static void latticeModifier_updateDepgraph(ModifierData *md, DagForest *forest,
+ Object *ob, DagNode *obNode)
{
LatticeModifierData *lmd = (LatticeModifierData*) md;
- if (lmd->object) {
+ if(lmd->object) {
DagNode *latNode = dag_get_node(forest, lmd->object);
- dag_add_relation(forest, latNode, obNode, DAG_RL_DATA_DATA|DAG_RL_OB_DATA);
+ dag_add_relation(forest, latNode, obNode,
+ DAG_RL_DATA_DATA | DAG_RL_OB_DATA);
}
}
-static void latticeModifier_deformVerts(ModifierData *md, Object *ob, void *derivedData, float (*vertexCos)[3], int numVerts)
+static void latticeModifier_deformVerts(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ float (*vertexCos)[3], int numVerts)
{
LatticeModifierData *lmd = (LatticeModifierData*) md;
- lattice_deform_verts(lmd->object, ob, vertexCos, numVerts, lmd->name);
+ lattice_deform_verts(lmd->object, ob, derivedData,
+ vertexCos, numVerts, lmd->name);
}
-static void latticeModifier_deformVertsEM(ModifierData *md, Object *ob, void *editData, void *derivedData, float (*vertexCos)[3], int numVerts)
+static void latticeModifier_deformVertsEM(
+ ModifierData *md, Object *ob, EditMesh *editData,
+ DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
- latticeModifier_deformVerts(md, ob, NULL, vertexCos, numVerts);
+ DerivedMesh *dm = derivedData;
+
+ if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
+
+ latticeModifier_deformVerts(md, ob, dm, vertexCos, numVerts);
+
+ if(!derivedData) dm->release(dm);
}
/* Subsurf */
@@ -221,7 +302,7 @@ static void latticeModifier_deformVertsEM(ModifierData *md, Object *ob, void *ed
static void subsurfModifier_initData(ModifierData *md)
{
SubsurfModifierData *smd = (SubsurfModifierData*) md;
-
+
smd->levels = 1;
smd->renderLevels = 2;
smd->flags |= eSubsurfModifierFlag_SubsurfUv;
@@ -242,55 +323,39 @@ static void subsurfModifier_freeData(ModifierData *md)
{
SubsurfModifierData *smd = (SubsurfModifierData*) md;
- if (smd->mCache) {
+ if(smd->mCache) {
ccgSubSurf_free(smd->mCache);
}
- if (smd->emCache) {
+ if(smd->emCache) {
ccgSubSurf_free(smd->emCache);
}
-}
+}
-static void *subsurfModifier_applyModifier(ModifierData *md, Object *ob, void *derivedData, float (*vertexCos)[3], int useRenderParams, int isFinalCalc)
+static DerivedMesh *subsurfModifier_applyModifier(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ int useRenderParams, int isFinalCalc)
{
- DerivedMesh *dm = derivedData;
SubsurfModifierData *smd = (SubsurfModifierData*) md;
- Mesh *me = ob->data;
-
- if (dm) {
- DispListMesh *dlm = dm->convertToDispListMesh(dm, 0);
- int i;
-
- if (vertexCos) {
- int numVerts = dm->getNumVerts(dm);
-
- for (i=0; i<numVerts; i++) {
- VECCOPY(dlm->mvert[i].co, vertexCos[i]);
- }
- }
+ DerivedMesh *result;
- dm = subsurf_make_derived_from_mesh(me, dlm, smd, useRenderParams, NULL, isFinalCalc);
+ result = subsurf_make_derived_from_derived(derivedData, smd,
+ useRenderParams, NULL,
+ isFinalCalc, 0);
- return dm;
- } else {
- return subsurf_make_derived_from_mesh(me, NULL, smd, useRenderParams, vertexCos, isFinalCalc);
- }
+ return result;
}
-static void *subsurfModifier_applyModifierEM(ModifierData *md, Object *ob, void *editData, void *derivedData, float (*vertexCos)[3])
+static DerivedMesh *subsurfModifier_applyModifierEM(
+ ModifierData *md, Object *ob, EditMesh *editData,
+ DerivedMesh *derivedData)
{
- EditMesh *em = editData;
- DerivedMesh *dm = derivedData;
SubsurfModifierData *smd = (SubsurfModifierData*) md;
+ DerivedMesh *result;
- if (dm) {
- DispListMesh *dlm = dm->convertToDispListMesh(dm, 0);
-
- dm = subsurf_make_derived_from_dlm_em(dlm, smd, vertexCos);
+ result = subsurf_make_derived_from_derived(derivedData, smd, 0,
+ NULL, 0, 1);
- return dm;
- } else {
- return subsurf_make_derived_from_editmesh(em, smd, vertexCos);
- }
+ return result;
}
/* Build */
@@ -319,214 +384,213 @@ static int buildModifier_dependsOnTime(ModifierData *md)
return 1;
}
-static void *buildModifier_applyModifier(ModifierData *md, Object *ob, void *derivedData, float (*vertexCos)[3], int useRenderParams, int isFinalCalc)
+static DerivedMesh *buildModifier_applyModifier(ModifierData *md, Object *ob,
+ DerivedMesh *derivedData,
+ int useRenderParams, int isFinalCalc)
{
DerivedMesh *dm = derivedData;
+ DerivedMesh *result;
BuildModifierData *bmd = (BuildModifierData*) md;
- DispListMesh *dlm=NULL, *ndlm = MEM_callocN(sizeof(*ndlm), "build_dlm");
- MVert *mvert;
- MEdge *medge;
- MFace *mface;
- MCol *mcol;
- TFace *tface;
- int totvert, totedge, totface;
- int i,j;
+ int i;
+ int numFaces, numEdges;
+ int maxVerts, maxEdges, maxFaces;
+ int *vertMap, *edgeMap, *faceMap;
float frac;
-
- if (dm) {
- dlm = dm->convertToDispListMesh(dm, 1);
- mvert = dlm->mvert;
- medge = dlm->medge;
- mface = dlm->mface;
- mcol = dlm->mcol;
- tface = dlm->tface;
- totvert = dlm->totvert;
- totedge = dlm->totedge;
- totface = dlm->totface;
- } else {
- Mesh *me = ob->data;
- mvert = me->mvert;
- medge = me->medge;
- mface = me->mface;
- mcol = me->mcol;
- tface = me->tface;
- totvert = me->totvert;
- totedge = me->totedge;
- totface = me->totface;
- }
+ GHashIterator *hashIter;
+ /* maps vert indices in old mesh to indices in new mesh */
+ GHash *vertHash = BLI_ghash_new(BLI_ghashutil_inthash,
+ BLI_ghashutil_intcmp);
+ /* maps edge indices in new mesh to indices in old mesh */
+ GHash *edgeHash = BLI_ghash_new(BLI_ghashutil_inthash,
+ BLI_ghashutil_intcmp);
+
+ maxVerts = dm->getNumVerts(dm);
+ vertMap = MEM_callocN(sizeof(*vertMap) * maxVerts,
+ "build modifier vertMap");
+ for(i = 0; i < maxVerts; ++i) vertMap[i] = i;
+
+ maxEdges = dm->getNumEdges(dm);
+ edgeMap = MEM_callocN(sizeof(*edgeMap) * maxEdges,
+ "build modifier edgeMap");
+ for(i = 0; i < maxEdges; ++i) edgeMap[i] = i;
+
+ maxFaces = dm->getNumFaces(dm);
+ faceMap = MEM_callocN(sizeof(*faceMap) * maxFaces,
+ "build modifier faceMap");
+ for(i = 0; i < maxFaces; ++i) faceMap[i] = i;
if (ob) {
- frac = bsystem_time(ob, 0, (float)G.scene->r.cfra, bmd->start-1.0f)/bmd->length;
+ frac = bsystem_time(ob, 0, (float)G.scene->r.cfra,
+ bmd->start - 1.0f) / bmd->length;
} else {
- frac = G.scene->r.cfra - bmd->start/bmd->length;
+ frac = G.scene->r.cfra - bmd->start / bmd->length;
}
CLAMP(frac, 0.0, 1.0);
- ndlm->totface = totface*frac;
- ndlm->totedge = totedge*frac;
- if (ndlm->totface) {
- ndlm->mvert = MEM_mallocN(sizeof(*ndlm->mvert)*totvert, "build_mvert");
- memcpy(ndlm->mvert, mvert, sizeof(*mvert)*totvert);
- for (i=0; i<totvert; i++) {
- if (vertexCos)
- VECCOPY(ndlm->mvert[i].co, vertexCos[i]);
- ndlm->mvert[i].flag = 0;
- }
+ numFaces = dm->getNumFaces(dm) * frac;
+ numEdges = dm->getNumEdges(dm) * frac;
- if (bmd->randomize) {
- ndlm->mface = MEM_dupallocN(mface);
- BLI_array_randomize(ndlm->mface, sizeof(*mface), totface, bmd->seed);
-
- if (tface) {
- ndlm->tface = MEM_dupallocN(tface);
- BLI_array_randomize(ndlm->tface, sizeof(*tface), totface, bmd->seed);
- } else if (mcol) {
- ndlm->mcol = MEM_dupallocN(mcol);
- BLI_array_randomize(ndlm->mcol, sizeof(*mcol)*4, totface, bmd->seed);
- }
- } else {
- ndlm->mface = MEM_mallocN(sizeof(*ndlm->mface)*ndlm->totface, "build_mf");
- memcpy(ndlm->mface, mface, sizeof(*mface)*ndlm->totface);
-
- if (tface) {
- ndlm->tface = MEM_mallocN(sizeof(*ndlm->tface)*ndlm->totface, "build_tf");
- memcpy(ndlm->tface, tface, sizeof(*tface)*ndlm->totface);
- } else if (mcol) {
- ndlm->mcol = MEM_mallocN(sizeof(*ndlm->mcol)*4*ndlm->totface, "build_mcol");
- memcpy(ndlm->mcol, mcol, sizeof(*mcol)*4*ndlm->totface);
- }
- }
+ /* if there's at least one face, build based on faces */
+ if(numFaces) {
+ int maxEdges;
- for (i=0; i<ndlm->totface; i++) {
- MFace *mf = &ndlm->mface[i];
+ if(bmd->randomize)
+ BLI_array_randomize(faceMap, sizeof(*faceMap),
+ maxFaces, bmd->seed);
- ndlm->mvert[mf->v1].flag = 1;
- ndlm->mvert[mf->v2].flag = 1;
- ndlm->mvert[mf->v3].flag = 1;
- if (mf->v4) ndlm->mvert[mf->v4].flag = 1;
+ /* get the set of all vert indices that will be in the final mesh,
+ * mapped to the new indices
+ */
+ for(i = 0; i < numFaces; ++i) {
+ MFace mf;
+ dm->getFace(dm, faceMap[i], &mf);
+
+ if(!BLI_ghash_haskey(vertHash, (void *)mf.v1))
+ BLI_ghash_insert(vertHash, (void *)mf.v1,
+ (void *)BLI_ghash_size(vertHash));
+ if(!BLI_ghash_haskey(vertHash, (void *)mf.v2))
+ BLI_ghash_insert(vertHash, (void *)mf.v2,
+ (void *)BLI_ghash_size(vertHash));
+ if(!BLI_ghash_haskey(vertHash, (void *)mf.v3))
+ BLI_ghash_insert(vertHash, (void *)mf.v3,
+ (void *)BLI_ghash_size(vertHash));
+ if(mf.v4 && !BLI_ghash_haskey(vertHash, (void *)mf.v4))
+ BLI_ghash_insert(vertHash, (void *)mf.v4,
+ (void *)BLI_ghash_size(vertHash));
}
- /* Store remapped indices in *((int*) mv->no) */
- ndlm->totvert = 0;
- for (i=0; i<totvert; i++) {
- MVert *mv = &ndlm->mvert[i];
-
- if (mv->flag)
- *((int*) mv->no) = ndlm->totvert++;
+ /* get the set of edges that will be in the new mesh (i.e. all edges
+ * that have both verts in the new mesh)
+ */
+ maxEdges = dm->getNumEdges(dm);
+ for(i = 0; i < maxEdges; ++i) {
+ MEdge me;
+ dm->getEdge(dm, i, &me);
+
+ if(BLI_ghash_haskey(vertHash, (void *)me.v1)
+ && BLI_ghash_haskey(vertHash, (void *)me.v2))
+ BLI_ghash_insert(edgeHash,
+ (void *)BLI_ghash_size(edgeHash), (void *)i);
}
+ } else if(numEdges) {
+ if(bmd->randomize)
+ BLI_array_randomize(edgeMap, sizeof(*edgeMap),
+ maxEdges, bmd->seed);
- /* Remap face vertex indices */
- for (i=0; i<ndlm->totface; i++) {
- MFace *mf = &ndlm->mface[i];
-
- mf->v1 = *((int*) ndlm->mvert[mf->v1].no);
- mf->v2 = *((int*) ndlm->mvert[mf->v2].no);
- mf->v3 = *((int*) ndlm->mvert[mf->v3].no);
- if (mf->v4) mf->v4 = *((int*) ndlm->mvert[mf->v4].no);
+ /* get the set of all vert indices that will be in the final mesh,
+ * mapped to the new indices
+ */
+ for(i = 0; i < numEdges; ++i) {
+ MEdge me;
+ dm->getEdge(dm, edgeMap[i], &me);
+
+ if(!BLI_ghash_haskey(vertHash, (void *)me.v1))
+ BLI_ghash_insert(vertHash, (void *)me.v1,
+ (void *)BLI_ghash_size(vertHash));
+ if(!BLI_ghash_haskey(vertHash, (void *)me.v2))
+ BLI_ghash_insert(vertHash, (void *)me.v2,
+ (void *)BLI_ghash_size(vertHash));
}
- /* Copy in all edges that have both vertices (remap in process) */
- if (totedge) {
- ndlm->totedge = 0;
- ndlm->medge = MEM_mallocN(sizeof(*ndlm->medge)*totedge, "build_med");
-
- for (i=0; i<totedge; i++) {
- MEdge *med = &medge[i];
- if (ndlm->mvert[med->v1].flag && ndlm->mvert[med->v2].flag) {
- MEdge *nmed = &ndlm->medge[ndlm->totedge++];
-
- memcpy(nmed, med, sizeof(*med));
+ /* get the set of edges that will be in the new mesh
+ */
+ for(i = 0; i < numEdges; ++i) {
+ MEdge me;
+ dm->getEdge(dm, edgeMap[i], &me);
- nmed->v1 = *((int*) ndlm->mvert[nmed->v1].no);
- nmed->v2 = *((int*) ndlm->mvert[nmed->v2].no);
- }
- }
+ BLI_ghash_insert(edgeHash, (void *)BLI_ghash_size(edgeHash),
+ (void *)edgeMap[i]);
}
+ } else {
+ int numVerts = dm->getNumVerts(dm) * frac;
- /* Collapse vertex array to remove unused verts */
- for(i=j=0; i<totvert; i++) {
- MVert *mv = &ndlm->mvert[i];
+ if(bmd->randomize)
+ BLI_array_randomize(vertMap, sizeof(*vertMap),
+ maxVerts, bmd->seed);
- if (mv->flag) {
- if (j!=i)
- memcpy(&ndlm->mvert[j], mv, sizeof(*mv));
- j++;
- }
- }
- } else if (ndlm->totedge) {
- ndlm->mvert = MEM_mallocN(sizeof(*ndlm->mvert)*totvert, "build_mvert");
- memcpy(ndlm->mvert, mvert, sizeof(*mvert)*totvert);
- for (i=0; i<totvert; i++) {
- if (vertexCos)
- VECCOPY(ndlm->mvert[i].co, vertexCos[i]);
- ndlm->mvert[i].flag = 0;
- }
+ /* get the set of all vert indices that will be in the final mesh,
+ * mapped to the new indices
+ */
+ for(i = 0; i < numVerts; ++i)
+ BLI_ghash_insert(vertHash, (void *)vertMap[i], (void *)i);
+ }
- if (bmd->randomize) {
- ndlm->medge = MEM_dupallocN(medge);
- BLI_array_randomize(ndlm->medge, sizeof(*medge), totedge, bmd->seed);
- } else {
- ndlm->medge = MEM_mallocN(sizeof(*ndlm->medge)*ndlm->totedge, "build_mf");
- memcpy(ndlm->medge, medge, sizeof(*medge)*ndlm->totedge);
- }
+ /* now we know the number of verts, edges and faces, we can create
+ * the mesh
+ */
+ result = CDDM_from_template(dm, BLI_ghash_size(vertHash),
+ BLI_ghash_size(edgeHash), numFaces);
+
+ /* copy the vertices across */
+ for(hashIter = BLI_ghashIterator_new(vertHash);
+ !BLI_ghashIterator_isDone(hashIter);
+ BLI_ghashIterator_step(hashIter)) {
+ MVert source;
+ MVert *dest;
+ int oldIndex = (int)BLI_ghashIterator_getKey(hashIter);
+ int newIndex = (int)BLI_ghashIterator_getValue(hashIter);
+
+ dm->getVert(dm, oldIndex, &source);
+ dest = CDDM_get_vert(result, newIndex);
+
+ DM_copy_vert_data(dm, result, oldIndex, newIndex, 1);
+ *dest = source;
+ }
+ BLI_ghashIterator_free(hashIter);
- for (i=0; i<ndlm->totedge; i++) {
- MEdge *med = &ndlm->medge[i];
+ /* copy the edges across, remapping indices */
+ for(i = 0; i < BLI_ghash_size(edgeHash); ++i) {
+ MEdge source;
+ MEdge *dest;
+ int oldIndex = (int)BLI_ghash_lookup(edgeHash, (void *)i);
- ndlm->mvert[med->v1].flag = 1;
- ndlm->mvert[med->v2].flag = 1;
- }
+ dm->getEdge(dm, oldIndex, &source);
+ dest = CDDM_get_edge(result, i);
- /* Store remapped indices in *((int*) mv->no) */
- ndlm->totvert = 0;
- for (i=0; i<totvert; i++) {
- MVert *mv = &ndlm->mvert[i];
+ source.v1 = (int)BLI_ghash_lookup(vertHash, (void *)source.v1);
+ source.v2 = (int)BLI_ghash_lookup(vertHash, (void *)source.v2);
- if (mv->flag)
- *((int*) mv->no) = ndlm->totvert++;
- }
+ DM_copy_edge_data(dm, result, oldIndex, i, 1);
+ *dest = source;
+ }
- /* Remap edge vertex indices */
- for (i=0; i<ndlm->totedge; i++) {
- MEdge *med = &ndlm->medge[i];
+ /* copy the faces across, remapping indices */
+ for(i = 0; i < numFaces; ++i) {
+ MFace source;
+ MFace *dest;
+ TFace *tf;
+ MCol *mc;
+ int orig_v4;
- med->v1 = *((int*) ndlm->mvert[med->v1].no);
- med->v2 = *((int*) ndlm->mvert[med->v2].no);
- }
+ dm->getFace(dm, faceMap[i], &source);
+ dest = CDDM_get_face(result, i);
- /* Collapse vertex array to remove unused verts */
- for(i=j=0; i<totvert; i++) {
- MVert *mv = &ndlm->mvert[i];
+ orig_v4 = source.v4;
- if (mv->flag) {
- if (j!=i)
- memcpy(&ndlm->mvert[j], mv, sizeof(*mv));
- j++;
- }
- }
- } else {
- ndlm->totvert = totvert*frac;
+ source.v1 = (int)BLI_ghash_lookup(vertHash, (void *)source.v1);
+ source.v2 = (int)BLI_ghash_lookup(vertHash, (void *)source.v2);
+ source.v3 = (int)BLI_ghash_lookup(vertHash, (void *)source.v3);
+ if(source.v4)
+ source.v4 = (int)BLI_ghash_lookup(vertHash, (void *)source.v4);
- if (bmd->randomize) {
- ndlm->mvert = MEM_dupallocN(mvert);
- BLI_array_randomize(ndlm->mvert, sizeof(*mvert), totvert, bmd->seed);
- } else {
- ndlm->mvert = MEM_mallocN(sizeof(*ndlm->mvert)*ndlm->totvert, "build_mvert");
- memcpy(ndlm->mvert, mvert, sizeof(*mvert)*ndlm->totvert);
- }
+ DM_copy_face_data(dm, result, faceMap[i], i, 1);
+ *dest = source;
- if (vertexCos) {
- for (i=0; i<ndlm->totvert; i++) {
- VECCOPY(ndlm->mvert[i].co, vertexCos[i]);
- }
- }
+ tf = DM_get_face_data(result, i, LAYERTYPE_TFACE);
+ mc = DM_get_face_data(result, i, LAYERTYPE_MCOL);
+ test_index_face(dest, mc, tf, (orig_v4 ? 4 : 3));
}
- if (dlm) displistmesh_free(dlm);
+ CDDM_calc_normals(result);
- mesh_calc_normals(ndlm->mvert, ndlm->totvert, ndlm->mface, ndlm->totface, &ndlm->nors);
-
- return derivedmesh_from_displistmesh(ndlm, NULL);
+ BLI_ghash_free(vertHash, NULL, NULL);
+ BLI_ghash_free(edgeHash, NULL, NULL);
+
+ MEM_freeN(vertMap);
+ MEM_freeN(edgeMap);
+ MEM_freeN(faceMap);
+
+ return result;
}
/* Array */
@@ -569,10 +633,10 @@ static void arrayModifier_copyData(ModifierData *md, ModifierData *target)
tamd->flags = amd->flags;
}
-static void arrayModifier_foreachObjectLink(ModifierData *md,
- Object *ob,
- void (*walk)(void *userData, Object *ob, Object **obpoin),
- void *userData)
+static void arrayModifier_foreachObjectLink(
+ ModifierData *md, Object *ob,
+ void (*walk)(void *userData, Object *ob, Object **obpoin),
+ void *userData)
{
ArrayModifierData *amd = (ArrayModifierData*) md;
@@ -580,10 +644,8 @@ static void arrayModifier_foreachObjectLink(ModifierData *md,
walk(userData, ob, &amd->offset_ob);
}
-static void arrayModifier_updateDepgraph(ModifierData *md,
- DagForest *forest,
- Object *ob,
- DagNode *obNode)
+static void arrayModifier_updateDepgraph(ModifierData *md, DagForest *forest,
+ Object *ob, DagNode *obNode)
{
ArrayModifierData *amd = (ArrayModifierData*) md;
@@ -591,32 +653,30 @@ static void arrayModifier_updateDepgraph(ModifierData *md,
DagNode *curNode = dag_get_node(forest, amd->curve_ob);
dag_add_relation(forest, curNode, obNode,
- DAG_RL_DATA_DATA|DAG_RL_OB_DATA);
+ DAG_RL_DATA_DATA | DAG_RL_OB_DATA);
}
if (amd->offset_ob) {
DagNode *curNode = dag_get_node(forest, amd->offset_ob);
dag_add_relation(forest, curNode, obNode,
- DAG_RL_DATA_DATA|DAG_RL_OB_DATA);
+ DAG_RL_DATA_DATA | DAG_RL_OB_DATA);
}
}
-float displistmesh_width(DispListMesh *dlm, int axis)
+float vertarray_size(MVert *mvert, int numVerts, int axis)
{
int i;
float min_co, max_co;
- MVert *mv;
/* if there are no vertices, width is 0 */
- if(dlm->totvert == 0) return 0;
+ if(numVerts == 0) return 0;
/* find the minimum and maximum coordinates on the desired axis */
- min_co = max_co = dlm->mvert[0].co[axis];
- for (i=1; i < dlm->totvert; i++) {
- mv = &dlm->mvert[i];
-
- if(mv->co[axis] < min_co) min_co = mv->co[axis];
- if(mv->co[axis] > max_co) max_co = mv->co[axis];
+ min_co = max_co = mvert->co[axis];
+ ++mvert;
+ for(i = 1; i < numVerts; ++i, ++mvert) {
+ if(mvert->co[axis] < min_co) min_co = mvert->co[axis];
+ if(mvert->co[axis] > max_co) max_co = mvert->co[axis];
}
return max_co - min_co;
@@ -650,6 +710,7 @@ static int calc_mapping(IndexMapEntry *indexMap, int oldVert, int copy)
int mergeVert = indexMap[oldVert].merge;
/* follow the chain of merges to the end */
+ /* TODO should this only go as far as the number of copies allows? */
while(indexMap[mergeVert].merge >= 0
&& indexMap[mergeVert].merge != mergeVert)
mergeVert = indexMap[mergeVert].merge;
@@ -665,10 +726,9 @@ static int calc_mapping(IndexMapEntry *indexMap, int oldVert, int copy)
return newVert;
}
-static DispListMesh *arrayModifier_doArray(ArrayModifierData *amd,
- Object *ob, DispListMesh *inDLM,
- float (*vertexCos)[3],
- int initFlags)
+static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
+ Object *ob, DerivedMesh *dm,
+ int initFlags)
{
int i, j;
/* offset matrix */
@@ -677,7 +737,12 @@ static DispListMesh *arrayModifier_doArray(ArrayModifierData *amd,
float tmp_mat[4][4];
float length = amd->length;
int count = amd->count;
- DispListMesh *dlm = MEM_callocN(sizeof(*dlm), "array_dlm");
+ int numVerts, numEdges, numFaces;
+ int maxVerts, maxEdges, maxFaces;
+ DerivedMesh *result;
+ MVert *mvert, *src_mvert;
+ MEdge *medge;
+ MFace *mface;
IndexMapEntry *indexMap;
@@ -685,11 +750,19 @@ static DispListMesh *arrayModifier_doArray(ArrayModifierData *amd,
MTC_Mat4One(offset);
+ indexMap = MEM_callocN(sizeof(*indexMap) * dm->getNumVerts(dm),
+ "indexmap");
+
+ src_mvert = dm->dupVertArray(dm);
+
+ maxVerts = dm->getNumVerts(dm);
+
if(amd->offset_type & MOD_ARR_OFF_CONST)
VecAddf(offset[3], offset[3], amd->offset);
if(amd->offset_type & MOD_ARR_OFF_RELATIVE) {
for(j = 0; j < 3; j++)
- offset[3][j] += amd->scale[j] * displistmesh_width(inDLM, j);
+ offset[3][j] += amd->scale[j] * vertarray_size(src_mvert,
+ maxVerts, j);
}
if((amd->offset_type & MOD_ARR_OFF_OBJ) && (amd->offset_ob)) {
@@ -736,24 +809,10 @@ static DispListMesh *arrayModifier_doArray(ArrayModifierData *amd,
if(count < 1)
count = 1;
- dlm->totvert = dlm->totedge = dlm->totface = 0;
- indexMap = MEM_callocN(sizeof(*indexMap)*inDLM->totvert, "indexmap");
-
/* allocate memory for count duplicates (including original) */
- dlm->mvert = MEM_callocN(sizeof(*dlm->mvert)*inDLM->totvert*count,
- "dlm_mvert");
- dlm->mface = MEM_callocN(sizeof(*dlm->mface)*inDLM->totface*count,
- "dlm_mface");
-
- if (inDLM->medge)
- dlm->medge = MEM_callocN(sizeof(*dlm->medge)*inDLM->totedge*count,
- "dlm_medge");
- if (inDLM->tface)
- dlm->tface = MEM_callocN(sizeof(*dlm->tface)*inDLM->totface*count,
- "dlm_tface");
- if (inDLM->mcol)
- dlm->mcol = MEM_callocN(sizeof(*dlm->mcol)*inDLM->totface*4*count,
- "dlm_mcol");
+ result = CDDM_from_template(dm, dm->getNumVerts(dm) * count,
+ dm->getNumEdges(dm) * count,
+ dm->getNumFaces(dm) * count);
/* calculate the offset matrix of the final copy (for merging) */
MTC_Mat4One(final_offset);
@@ -763,20 +822,22 @@ static DispListMesh *arrayModifier_doArray(ArrayModifierData *amd,
MTC_Mat4CpyMat4(final_offset, tmp_mat);
}
- for (i=0; i<inDLM->totvert; i++) {
- MVert *inMV = &inDLM->mvert[i];
- MVert *mv = &dlm->mvert[dlm->totvert++];
+ numVerts = numEdges = numFaces = 0;
+ mvert = CDDM_get_verts(result);
+
+ for (i = 0; i < maxVerts; i++) {
+ MVert *inMV;
+ MVert *mv = &mvert[numVerts];
MVert *mv2;
float co[3];
- *mv = *inMV;
+ inMV = &src_mvert[i];
- if (vertexCos) {
- VECCOPY(mv->co, vertexCos[i]);
- }
- if (initFlags) mv->flag |= ME_VERT_STEPINDEX;
+ DM_copy_vert_data(dm, result, i, numVerts, 1);
+ *mv = *inMV;
+ numVerts++;
- indexMap[i].new = dlm->totvert-1;
+ indexMap[i].new = numVerts - 1;
indexMap[i].merge = -1; /* default to no merge */
indexMap[i].merge_final = 0; /* default to no merge */
@@ -793,16 +854,16 @@ static DispListMesh *arrayModifier_doArray(ArrayModifierData *amd,
VECCOPY(tmp_co, mv->co);
MTC_Mat4MulVecfl(offset, tmp_co);
- for(j = 0; j < inDLM->totvert; j++) {
- inMV = &inDLM->mvert[j];
+ for(j = 0; j < maxVerts; j++) {
+ inMV = &src_mvert[j];
/* if this vert is within merge limit, merge */
if(VecLenCompare(tmp_co, inMV->co, amd->merge_dist)) {
indexMap[i].merge = j;
/* test for merging with final copy of merge target */
if(amd->flags & MOD_ARR_MERGEFINAL) {
- inMV = &inDLM->mvert[i];
- VECCOPY(tmp_co, inDLM->mvert[j].co);
+ VECCOPY(tmp_co, inMV->co);
+ inMV = &src_mvert[i];
MTC_Mat4MulVecfl(final_offset, tmp_co);
if(VecLenCompare(tmp_co, inMV->co, amd->merge_dist))
indexMap[i].merge_final = 1;
@@ -815,67 +876,79 @@ static DispListMesh *arrayModifier_doArray(ArrayModifierData *amd,
/* if no merging, generate copies of this vert */
if(indexMap[i].merge < 0) {
for(j=0; j < count - 1; j++) {
- mv2 = &dlm->mvert[dlm->totvert++];
+ mv2 = &mvert[numVerts];
+ DM_copy_vert_data(result, result, numVerts - 1, numVerts, 1);
*mv2 = *mv;
+ numVerts++;
+
MTC_Mat4MulVecfl(offset, co);
VECCOPY(mv2->co, co);
- mv2->flag &= ~ME_VERT_STEPINDEX;
}
} else if(indexMap[i].merge != i && indexMap[i].merge_final) {
/* if this vert is not merging with itself, and it is merging
* with the final copy of its merge target, remove the first copy
*/
- dlm->totvert--;
+ numVerts--;
+ DM_free_vert_data(result, numVerts, 1);
}
}
/* make a hashtable so we can avoid duplicate edges from merging */
edges = BLI_edgehash_new();
- for (i=0; i<inDLM->totedge; i++) {
- MEdge *inMED = &inDLM->medge[i];
+ maxEdges = dm->getNumEdges(dm);
+ medge = CDDM_get_edges(result);
+ for(i = 0; i < maxEdges; i++) {
+ MEdge inMED;
MEdge med;
MEdge *med2;
int vert1, vert2;
- med = *inMED;
- med.v1 = indexMap[inMED->v1].new;
- med.v2 = indexMap[inMED->v2].new;
+ dm->getEdge(dm, i, &inMED);
+
+ med = inMED;
+ med.v1 = indexMap[inMED.v1].new;
+ med.v2 = indexMap[inMED.v2].new;
/* if vertices are to be merged with the final copies of their
* merge targets, calculate that final copy
*/
- if(indexMap[inMED->v1].merge_final) {
- med.v1 = calc_mapping(indexMap, indexMap[inMED->v1].merge,
+ if(indexMap[inMED.v1].merge_final) {
+ med.v1 = calc_mapping(indexMap, indexMap[inMED.v1].merge,
count - 2);
}
- if(indexMap[inMED->v2].merge_final) {
- med.v2 = calc_mapping(indexMap, indexMap[inMED->v2].merge,
+ if(indexMap[inMED.v2].merge_final) {
+ med.v2 = calc_mapping(indexMap, indexMap[inMED.v2].merge,
count - 2);
}
if (initFlags) {
- med.flag |= ME_EDGEDRAW|ME_EDGERENDER|ME_EDGE_STEPINDEX;
+ med.flag |= ME_EDGEDRAW | ME_EDGERENDER;
}
if(!BLI_edgehash_haskey(edges, med.v1, med.v2)) {
- dlm->medge[dlm->totedge++] = med;
+ DM_copy_edge_data(dm, result, i, numEdges, 1);
+ medge[numEdges] = med;
+ numEdges++;
+
BLI_edgehash_insert(edges, med.v1, med.v2, NULL);
}
for(j=0; j < count - 1; j++)
{
- vert1 = calc_mapping(indexMap, inMED->v1, j);
- vert2 = calc_mapping(indexMap, inMED->v2, j);
+ vert1 = calc_mapping(indexMap, inMED.v1, j);
+ vert2 = calc_mapping(indexMap, inMED.v2, j);
/* avoid duplicate edges */
if(!BLI_edgehash_haskey(edges, vert1, vert2)) {
- med2 = &dlm->medge[dlm->totedge++];
+ med2 = &medge[numEdges];
+ DM_copy_edge_data(dm, result, i, numEdges, 1);
*med2 = med;
+ numEdges++;
+
med2->v1 = vert1;
med2->v2 = vert2;
- med2->flag &= ~ME_EDGE_STEPINDEX;
BLI_edgehash_insert(edges, med2->v1, med2->v2, NULL);
}
@@ -885,168 +958,103 @@ static DispListMesh *arrayModifier_doArray(ArrayModifierData *amd,
/* don't need the hashtable any more */
BLI_edgehash_free(edges, NULL);
- for (i=0; i<inDLM->totface; i++) {
- MFace *inMF = &inDLM->mface[i];
- MFace *mf = &dlm->mface[dlm->totface++];
- MFace *mf2;
- TFace *tf = NULL;
- MCol *mc = NULL;
+ maxFaces = dm->getNumFaces(dm);
+ mface = CDDM_get_faces(result);
+ for (i=0; i < maxFaces; i++) {
+ MFace inMF;
+ TFace *tf;
+ MCol *mc;
+ MFace *mf = &mface[numFaces];
- *mf = *inMF;
- mf->v1 = indexMap[inMF->v1].new;
- mf->v2 = indexMap[inMF->v2].new;
- mf->v3 = indexMap[inMF->v3].new;
- if(inMF->v4)
- mf->v4 = indexMap[inMF->v4].new;
+ dm->getFace(dm, i, &inMF);
+
+ DM_copy_face_data(dm, result, i, numFaces, 1);
+ tf = DM_get_face_data(result, numFaces, LAYERTYPE_TFACE);
+ mc = DM_get_face_data(result, numFaces, LAYERTYPE_MCOL);
+ *mf = inMF;
+ numFaces++;
+
+ mf->v1 = indexMap[inMF.v1].new;
+ mf->v2 = indexMap[inMF.v2].new;
+ mf->v3 = indexMap[inMF.v3].new;
+ if(inMF.v4)
+ mf->v4 = indexMap[inMF.v4].new;
/* if vertices are to be merged with the final copies of their
* merge targets, calculate that final copy
*/
- if(indexMap[inMF->v1].merge_final)
- mf->v1 = calc_mapping(indexMap, indexMap[inMF->v1].merge, count-2);
- if(indexMap[inMF->v2].merge_final)
- mf->v2 = calc_mapping(indexMap, indexMap[inMF->v2].merge, count-2);
- if(indexMap[inMF->v3].merge_final)
- mf->v3 = calc_mapping(indexMap, indexMap[inMF->v3].merge, count-2);
- if(inMF->v4 && indexMap[inMF->v4].merge_final)
- mf->v4 = calc_mapping(indexMap, indexMap[inMF->v4].merge, count-2);
-
- if (initFlags) mf->flag |= ME_FACE_STEPINDEX;
-
- if (inDLM->tface) {
- TFace *inTF = &inDLM->tface[i];
- tf = &dlm->tface[dlm->totface-1];
-
- *tf = *inTF;
- } else if (inDLM->mcol) {
- MCol *inMC = &inDLM->mcol[i*4];
- mc = &dlm->mcol[(dlm->totface-1)*4];
-
- mc[0] = inMC[0];
- mc[1] = inMC[1];
- mc[2] = inMC[2];
- mc[3] = inMC[3];
- }
-
- test_index_face(mf, mc, tf, inMF->v4?4:3);
+ if(indexMap[inMF.v1].merge_final)
+ mf->v1 = calc_mapping(indexMap, indexMap[inMF.v1].merge, count-2);
+ if(indexMap[inMF.v2].merge_final)
+ mf->v2 = calc_mapping(indexMap, indexMap[inMF.v2].merge, count-2);
+ if(indexMap[inMF.v3].merge_final)
+ mf->v3 = calc_mapping(indexMap, indexMap[inMF.v3].merge, count-2);
+ if(inMF.v4 && indexMap[inMF.v4].merge_final)
+ mf->v4 = calc_mapping(indexMap, indexMap[inMF.v4].merge, count-2);
+
+ test_index_face(mf, mc, tf, inMF.v4?4:3);
/* if the face has fewer than 3 vertices, don't create it */
- if(mf->v3 == 0)
- dlm->totface--;
+ if(mf->v3 == 0) {
+ numFaces--;
+ DM_free_face_data(result, numFaces, 1);
+ }
for(j=0; j < count - 1; j++)
{
- mf2 = &dlm->mface[dlm->totface++];
+ MFace *mf2 = &mface[numFaces];
+ DM_copy_face_data(dm, result, i, numFaces, 1);
+ tf = DM_get_face_data(result, numFaces, LAYERTYPE_TFACE);
+ mc = DM_get_face_data(result, numFaces, LAYERTYPE_MCOL);
*mf2 = *mf;
+ numFaces++;
- mf2->v1 = calc_mapping(indexMap, inMF->v1, j);
- mf2->v2 = calc_mapping(indexMap, inMF->v2, j);
- mf2->v3 = calc_mapping(indexMap, inMF->v3, j);
- if (inMF->v4)
- mf2->v4 = calc_mapping(indexMap, inMF->v4, j);
-
- mf2->flag &= ~ME_FACE_STEPINDEX;
-
- if (inDLM->tface) {
- TFace *inTF = &inDLM->tface[i];
- tf = &dlm->tface[dlm->totface-1];
-
- *tf = *inTF;
- } else if (inDLM->mcol) {
- MCol *inMC = &inDLM->mcol[i*4];
- mc = &dlm->mcol[(dlm->totface-1)*4];
-
- mc[0] = inMC[0];
- mc[1] = inMC[1];
- mc[2] = inMC[2];
- mc[3] = inMC[3];
- }
+ mf2->v1 = calc_mapping(indexMap, inMF.v1, j);
+ mf2->v2 = calc_mapping(indexMap, inMF.v2, j);
+ mf2->v3 = calc_mapping(indexMap, inMF.v3, j);
+ if (inMF.v4)
+ mf2->v4 = calc_mapping(indexMap, inMF.v4, j);
- test_index_face(mf2, mc, tf, inMF->v4?4:3);
+ test_index_face(mf2, mc, tf, inMF.v4?4:3);
/* if the face has fewer than 3 vertices, don't create it */
- if(mf2->v3 == 0)
- dlm->totface--;
+ if(mf2->v3 == 0) {
+ numFaces--;
+ DM_free_face_data(result, numFaces, 1);
+ }
}
}
+ MEM_freeN(src_mvert);
MEM_freeN(indexMap);
- return dlm;
+ CDDM_set_num_verts(result, numVerts);
+ CDDM_set_num_edges(result, numEdges);
+ CDDM_set_num_faces(result, numFaces);
+
+ return result;
}
-static void *arrayModifier_applyModifier_internal(ModifierData *md,
- Object *ob,
- void *derivedData,
- float (*vertexCos)[3],
- int useRenderParams,
- int isFinalCalc)
+static DerivedMesh *arrayModifier_applyModifier(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ int useRenderParams, int isFinalCalc)
{
- DerivedMesh *dm = derivedData;
+ DerivedMesh *result;
ArrayModifierData *amd = (ArrayModifierData*) md;
- DispListMesh *outDLM, *inDLM;
- if (dm) {
- inDLM = dm->convertToDispListMesh(dm, 1);
- } else {
- Mesh *me = ob->data;
+ result = arrayModifier_doArray(amd, ob, derivedData, 0);
- inDLM = MEM_callocN(sizeof(*inDLM), "inDLM");
- inDLM->dontFreeVerts = inDLM->dontFreeOther = 1;
- inDLM->mvert = me->mvert;
- inDLM->medge = me->medge;
- inDLM->mface = me->mface;
- inDLM->tface = me->tface;
- inDLM->mcol = me->mcol;
- inDLM->totvert = me->totvert;
- inDLM->totedge = me->totedge;
- inDLM->totface = me->totface;
- }
-
- outDLM = arrayModifier_doArray(amd, ob, inDLM, vertexCos, dm?0:1);
+ CDDM_calc_normals(result);
- displistmesh_free(inDLM);
-
- mesh_calc_normals(outDLM->mvert, outDLM->totvert, outDLM->mface,
- outDLM->totface, &outDLM->nors);
-
- return derivedmesh_from_displistmesh(outDLM, NULL);
+ return result;
}
-static void *arrayModifier_applyModifier(ModifierData *md,
- Object *ob,
- void *derivedData,
- float (*vertexCos)[3],
- int useRenderParams,
- int isFinalCalc)
+static DerivedMesh *arrayModifier_applyModifierEM(
+ ModifierData *md, Object *ob, EditMesh *editData,
+ DerivedMesh *derivedData)
{
- return arrayModifier_applyModifier_internal(md, ob, derivedData,
- vertexCos, 0, 1);
-}
-
-static void *arrayModifier_applyModifierEM(ModifierData *md,
- Object *ob,
- void *editData,
- void *derivedData,
- float (*vertexCos)[3])
-{
- if (derivedData) {
- return arrayModifier_applyModifier_internal(md, ob, derivedData,
- vertexCos, 0, 1);
- } else {
- ArrayModifierData *amd = (ArrayModifierData*) md;
- DispListMesh *outDLM, *inDLM = displistmesh_from_editmesh(editData);
-
- outDLM = arrayModifier_doArray(amd, ob, inDLM, vertexCos, 0);
-
- displistmesh_free(inDLM);
-
- mesh_calc_normals(outDLM->mvert, outDLM->totvert,
- outDLM->mface, outDLM->totface, &outDLM->nors);
-
- return derivedmesh_from_displistmesh(outDLM, NULL);
- }
+ return arrayModifier_applyModifier(md, ob, derivedData, 0, 1);
}
/* Mirror */
@@ -1067,127 +1075,120 @@ static void mirrorModifier_copyData(ModifierData *md, ModifierData *target)
tmmd->tolerance = mmd->tolerance;
}
-static DispListMesh *mirrorModifier__doMirror(MirrorModifierData *mmd, DispListMesh *inDLM, float (*vertexCos)[3], int initFlags)
+static DerivedMesh *mirrorModifier__doMirror(MirrorModifierData *mmd,
+ DerivedMesh *dm,
+ int initFlags)
{
int i, axis = mmd->axis;
float tolerance = mmd->tolerance;
- DispListMesh *dlm = MEM_callocN(sizeof(*dlm), "mirror_dlm");
+ DerivedMesh *result;
+ int numVerts, numEdges, numFaces;
+ int maxVerts = dm->getNumVerts(dm);
+ int maxEdges = dm->getNumEdges(dm);
+ int maxFaces = dm->getNumFaces(dm);
int (*indexMap)[2];
- dlm->totvert = dlm->totedge = dlm->totface = 0;
- indexMap = MEM_mallocN(sizeof(*indexMap)*inDLM->totvert, "indexmap");
- dlm->mvert = MEM_callocN(sizeof(*dlm->mvert)*inDLM->totvert*2, "dlm_mvert");
- dlm->mface = MEM_callocN(sizeof(*dlm->mface)*inDLM->totface*2, "dlm_mface");
+ numVerts = numEdges = numFaces = 0;
- if (inDLM->medge) dlm->medge = MEM_callocN(sizeof(*dlm->medge)*inDLM->totedge*2, "dlm_medge");
- if (inDLM->tface) dlm->tface = MEM_callocN(sizeof(*dlm->tface)*inDLM->totface*2, "dlm_tface");
- if (inDLM->mcol) dlm->mcol = MEM_callocN(sizeof(*dlm->mcol)*inDLM->totface*4*2, "dlm_mcol");
+ indexMap = MEM_mallocN(sizeof(*indexMap) * maxVerts, "indexmap");
- for (i=0; i<inDLM->totvert; i++) {
- MVert *inMV = &inDLM->mvert[i];
- MVert *mv = &dlm->mvert[dlm->totvert++];
- int isShared = ABS(inMV->co[axis])<=tolerance;
+ result = CDDM_from_template(dm, maxVerts * 2, maxEdges * 2, maxFaces * 2);
- /* Because the topology result (# of vertices) must be the same
- * if the mesh data is overridden by vertex cos, have to calc sharedness
- * based on original coordinates. This is why we test before copy.
- */
- *mv = *inMV;
- if (vertexCos) {
- VECCOPY(mv->co, vertexCos[i]);
- }
- if (initFlags) mv->flag |= ME_VERT_STEPINDEX;
+ for(i = 0; i < maxVerts; i++) {
+ MVert inMV;
+ MVert *mv = CDDM_get_vert(result, numVerts);
+ int isShared;
+
+ dm->getVert(dm, i, &inMV);
+ isShared = ABS(inMV.co[axis])<=tolerance;
+
+ /* Because the topology result (# of vertices) must be the same if
+ * the mesh data is overridden by vertex cos, have to calc sharedness
+ * based on original coordinates. This is why we test before copy.
+ */
+ DM_copy_vert_data(dm, result, i, numVerts, 1);
+ *mv = inMV;
+ numVerts++;
- indexMap[i][0] = dlm->totvert-1;
+ indexMap[i][0] = numVerts - 1;
indexMap[i][1] = !isShared;
- if (isShared) {
+ if(isShared) {
mv->co[axis] = 0;
mv->flag |= ME_VERT_MERGED;
} else {
- MVert *mv2 = &dlm->mvert[dlm->totvert++];
+ MVert *mv2 = CDDM_get_vert(result, numVerts);
+ DM_copy_vert_data(dm, result, i, numVerts, 1);
*mv2 = *mv;
+ numVerts++;
+
mv2->co[axis] = -mv2->co[axis];
- mv2->flag &= ~ME_VERT_STEPINDEX;
}
}
- for (i=0; i<inDLM->totedge; i++) {
- MEdge *inMED = &inDLM->medge[i];
- MEdge *med = &dlm->medge[dlm->totedge++];
+ for(i = 0; i < maxEdges; i++) {
+ MEdge inMED;
+ MEdge *med = CDDM_get_edge(result, numEdges);
+
+ dm->getEdge(dm, i, &inMED);
- *med = *inMED;
- med->v1 = indexMap[inMED->v1][0];
- med->v2 = indexMap[inMED->v2][0];
- if (initFlags) med->flag |= ME_EDGEDRAW|ME_EDGERENDER|ME_EDGE_STEPINDEX;
+ DM_copy_edge_data(dm, result, i, numEdges, 1);
+ *med = inMED;
+ numEdges++;
- if (indexMap[inMED->v1][1] || indexMap[inMED->v2][1]) {
- MEdge *med2 = &dlm->medge[dlm->totedge++];
+ med->v1 = indexMap[inMED.v1][0];
+ med->v2 = indexMap[inMED.v2][0];
+ if(initFlags)
+ med->flag |= ME_EDGEDRAW | ME_EDGERENDER;
+ if(indexMap[inMED.v1][1] || indexMap[inMED.v2][1]) {
+ MEdge *med2 = CDDM_get_edge(result, numEdges);
+
+ DM_copy_edge_data(dm, result, i, numEdges, 1);
*med2 = *med;
- med2->v1 += indexMap[inMED->v1][1];
- med2->v2 += indexMap[inMED->v2][1];
- med2->flag &= ~ME_EDGE_STEPINDEX;
+ numEdges++;
+
+ med2->v1 += indexMap[inMED.v1][1];
+ med2->v2 += indexMap[inMED.v2][1];
}
}
- for (i=0; i<inDLM->totface; i++) {
- MFace *inMF = &inDLM->mface[i];
- MFace *mf = &dlm->mface[dlm->totface++];
-
- *mf = *inMF;
- mf->v1 = indexMap[inMF->v1][0];
- mf->v2 = indexMap[inMF->v2][0];
- mf->v3 = indexMap[inMF->v3][0];
- mf->v4 = indexMap[inMF->v4][0];
- if (initFlags) mf->flag |= ME_FACE_STEPINDEX;
+ for(i = 0; i < maxFaces; i++) {
+ MFace inMF;
+ MFace *mf = CDDM_get_face(result, numFaces);
- if (inDLM->tface) {
- TFace *inTF = &inDLM->tface[i];
- TFace *tf = &dlm->tface[dlm->totface-1];
+ dm->getFace(dm, i, &inMF);
- *tf = *inTF;
- } else if (inDLM->mcol) {
- MCol *inMC = &inDLM->mcol[i*4];
- MCol *mc = &dlm->mcol[(dlm->totface-1)*4];
+ DM_copy_face_data(dm, result, i, numFaces, 1);
+ *mf = inMF;
+ numFaces++;
- mc[0] = inMC[0];
- mc[1] = inMC[1];
- mc[2] = inMC[2];
- mc[3] = inMC[3];
- }
+ mf->v1 = indexMap[inMF.v1][0];
+ mf->v2 = indexMap[inMF.v2][0];
+ mf->v3 = indexMap[inMF.v3][0];
+ mf->v4 = indexMap[inMF.v4][0];
- if (indexMap[inMF->v1][1] || indexMap[inMF->v2][1] || indexMap[inMF->v3][1] || (mf->v4 && indexMap[inMF->v4][1])) {
- MFace *mf2 = &dlm->mface[dlm->totface++];
- TFace *tf = NULL;
- MCol *mc = NULL;
-
+ if(indexMap[inMF.v1][1]
+ || indexMap[inMF.v2][1]
+ || indexMap[inMF.v3][1]
+ || (mf->v4 && indexMap[inMF.v4][1])) {
+ MFace *mf2 = CDDM_get_face(result, numFaces);
+ TFace *tf = DM_get_face_data(result, numFaces, LAYERTYPE_TFACE);
+ MCol *mc = DM_get_face_data(result, numFaces, LAYERTYPE_MCOL);
+
+ DM_copy_face_data(dm, result, i, numFaces, 1);
*mf2 = *mf;
- mf2->v1 += indexMap[inMF->v1][1];
- mf2->v2 += indexMap[inMF->v2][1];
- mf2->v3 += indexMap[inMF->v3][1];
- if (inMF->v4) mf2->v4 += indexMap[inMF->v4][1];
- mf2->flag &= ~ME_FACE_STEPINDEX;
-
- if (inDLM->tface) {
- TFace *inTF = &inDLM->tface[i];
- tf = &dlm->tface[dlm->totface-1];
-
- *tf = *inTF;
- } else if (inDLM->mcol) {
- MCol *inMC = &inDLM->mcol[i*4];
- mc = &dlm->mcol[(dlm->totface-1)*4];
-
- mc[0] = inMC[0];
- mc[1] = inMC[1];
- mc[2] = inMC[2];
- mc[3] = inMC[3];
- }
+ numFaces++;
+
+ mf2->v1 += indexMap[inMF.v1][1];
+ mf2->v2 += indexMap[inMF.v2][1];
+ mf2->v3 += indexMap[inMF.v3][1];
+ if(inMF.v4) mf2->v4 += indexMap[inMF.v4][1];
- /* Flip face normal */
+ /* Flip face normal */
SWAP(int, mf2->v1, mf2->v3);
- if (tf) {
+ if(tf) {
SWAP(unsigned int, tf->col[0], tf->col[2]);
SWAP(float, tf->uv[0][0], tf->uv[2][0]);
SWAP(float, tf->uv[0][1], tf->uv[2][1]);
@@ -1195,68 +1196,1479 @@ static DispListMesh *mirrorModifier__doMirror(MirrorModifierData *mmd, DispListM
SWAP(MCol, mc[0], mc[2]);
}
- test_index_face(mf2, mc, tf, inMF->v4?4:3);
+ test_index_face(mf2, mc, tf, inMF.v4?4:3);
}
}
MEM_freeN(indexMap);
- return dlm;
+ CDDM_set_num_verts(result, numVerts);
+ CDDM_set_num_edges(result, numEdges);
+ CDDM_set_num_faces(result, numFaces);
+
+ return result;
}
-static void *mirrorModifier_applyModifier__internal(ModifierData *md, Object *ob, void *derivedData, float (*vertexCos)[3], int useRenderParams, int isFinalCalc)
+static DerivedMesh *mirrorModifier_applyModifier(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ int useRenderParams, int isFinalCalc)
{
- DerivedMesh *dm = derivedData;
+ DerivedMesh *result;
MirrorModifierData *mmd = (MirrorModifierData*) md;
- DispListMesh *outDLM, *inDLM;
- if (dm) {
- inDLM = dm->convertToDispListMesh(dm, 1);
- } else {
- Mesh *me = ob->data;
+ result = mirrorModifier__doMirror(mmd, derivedData, 0);
+
+ CDDM_calc_normals(result);
+
+ return result;
+}
+
+static DerivedMesh *mirrorModifier_applyModifierEM(
+ ModifierData *md, Object *ob, EditMesh *editData,
+ DerivedMesh *derivedData)
+{
+ return mirrorModifier_applyModifier(md, ob, derivedData, 0, 1);
+}
+
+/* EdgeSplit */
+/* EdgeSplit modifier: Splits edges in the mesh according to sharpness flag
+ * or edge angle (can be used to achieve autosmoothing)
+*/
+#if 0
+#define EDGESPLIT_DEBUG_1
+#define EDGESPLIT_DEBUG_2
+#define EDGESPLIT_DEBUG_0
+#endif
+
+static void edgesplitModifier_initData(ModifierData *md)
+{
+ EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
+
+ /* default to 30-degree split angle, sharpness from both angle & flag
+ */
+ emd->split_angle = 30;
+ emd->flags = MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG;
+}
+
+static void edgesplitModifier_copyData(ModifierData *md, ModifierData *target)
+{
+ EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
+ EdgeSplitModifierData *tamd = (EdgeSplitModifierData*) target;
- inDLM = MEM_callocN(sizeof(*inDLM), "inDLM");
- inDLM->dontFreeVerts = inDLM->dontFreeOther = 1;
- inDLM->mvert = me->mvert;
- inDLM->medge = me->medge;
- inDLM->mface = me->mface;
- inDLM->tface = me->tface;
- inDLM->mcol = me->mcol;
- inDLM->totvert = me->totvert;
- inDLM->totedge = me->totedge;
- inDLM->totface = me->totface;
+ tamd->split_angle = emd->split_angle;
+ tamd->flags = emd->flags;
+}
+
+static void linklist_copy(LinkNode **target, LinkNode *source);
+
+/* Mesh data for edgesplit operation */
+typedef struct SmoothVert {
+ LinkNode *faces; /* all faces which use this vert */
+ int oldIndex; /* the index of the original DispListMesh vert */
+ int newIndex; /* the index of the new DispListMesh vert */
+} SmoothVert;
+
+static SmoothVert *smoothvert_copy(SmoothVert *vert)
+{
+ SmoothVert *copy = MEM_callocN(sizeof(*copy), "copy_smoothvert");
+
+ *copy = *vert;
+ linklist_copy(&copy->faces, vert->faces);
+
+ return copy;
+}
+
+static void smoothvert_free(void *vert)
+{
+ BLI_linklist_free(((SmoothVert *)vert)->faces, NULL);
+ MEM_freeN(vert);
+}
+
+#define SMOOTHEDGE_NUM_VERTS 2
+
+typedef struct SmoothEdge {
+ SmoothVert *verts[SMOOTHEDGE_NUM_VERTS]; /* the verts used by this edge */
+ LinkNode *faces; /* all faces which use this edge */
+ int oldIndex; /* the index of the original DispListMesh edge */
+ int newIndex; /* the index of the new DispListMesh edge */
+ short flag; /* the flags from the original DispListMesh edge */
+} SmoothEdge;
+
+static void smoothedge_free(void *edge)
+{
+ BLI_linklist_free(((SmoothEdge *)edge)->faces, NULL);
+ MEM_freeN(edge);
+}
+
+static SmoothEdge *smoothedge_copy(SmoothEdge *edge)
+{
+ SmoothEdge *copy = MEM_callocN(sizeof(*copy), "copy_smoothedge");
+
+ *copy = *edge;
+ linklist_copy(&copy->faces, edge->faces);
+
+ return copy;
+}
+
+static int smoothedge_has_vert(SmoothEdge *edge, SmoothVert *vert)
+{
+ int i;
+ for(i = 0; i < SMOOTHEDGE_NUM_VERTS; i++)
+ if(edge->verts[i] == vert) return 1;
+
+ return 0;
+}
+
+#define SMOOTHFACE_MAX_EDGES 4
+
+typedef struct SmoothFace {
+ SmoothEdge *edges[SMOOTHFACE_MAX_EDGES]; /* nonexistent edges == NULL */
+ int flip[SMOOTHFACE_MAX_EDGES]; /* 1 = flip edge dir, 0 = don't flip */
+ float normal[3]; /* the normal of this face */
+ int oldIndex; /* the index of the original DispListMesh face */
+ int newIndex; /* the index of the new DispListMesh face */
+} SmoothFace;
+
+static void smoothface_free(void *face)
+{
+ MEM_freeN(face);
+}
+
+static int smoothface_has_edge(SmoothFace *face, SmoothEdge *edge)
+{
+ int i;
+ for(i = 0; i < SMOOTHFACE_MAX_EDGES && face->edges[i]; i++)
+ if(face->edges[i] == edge) return 1;
+
+ return 0;
+}
+
+
+typedef struct SmoothMesh {
+ GHash *verts;
+ GHash *edges;
+ GHash *faces;
+ DerivedMesh *dm;
+} SmoothMesh;
+
+static SmoothMesh *smoothmesh_new()
+{
+ SmoothMesh *mesh = MEM_callocN(sizeof(*mesh), "smoothmesh");
+ mesh->verts = BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp);
+ mesh->edges = BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp);
+ mesh->faces = BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp);
+
+ return mesh;
+}
+
+static void smoothmesh_free(SmoothMesh *mesh)
+{
+ BLI_ghash_free(mesh->verts, NULL, smoothvert_free);
+ BLI_ghash_free(mesh->edges, NULL, smoothedge_free);
+ BLI_ghash_free(mesh->faces, NULL, smoothface_free);
+ MEM_freeN(mesh);
+}
+
+static void smoothmesh_print(SmoothMesh *mesh)
+{
+ int i, j;
+ DerivedMesh *dm = mesh->dm;
+
+ printf("--- SmoothMesh ---\n");
+ printf("--- Vertices ---\n");
+ for(i = 0; i < BLI_ghash_size(mesh->verts); i++) {
+ SmoothVert *vert = BLI_ghash_lookup(mesh->verts, (void *)i);
+ LinkNode *node;
+ MVert mv;
+
+ dm->getVert(dm, vert->oldIndex, &mv);
+
+ printf("%3d: ind={%3d, %3d}, pos={% 5.1f, % 5.1f, % 5.1f}",
+ i, vert->oldIndex, vert->newIndex,
+ mv.co[0], mv.co[1], mv.co[2]);
+ printf(", faces={");
+ for(node = vert->faces; node != NULL; node = node->next) {
+ printf(" %d", ((SmoothFace *)node->link)->newIndex);
+ }
+ printf("}\n");
+ }
+
+ printf("\n--- Edges ---\n");
+ for(i = 0; i < BLI_ghash_size(mesh->edges); i++) {
+ SmoothEdge *edge = BLI_ghash_lookup(mesh->edges, (void *)i);
+ LinkNode *node;
+
+ printf("%4d: indices={%4d, %4d}, verts={%4d, %4d}",
+ i,
+ edge->oldIndex, edge->newIndex,
+ edge->verts[0]->newIndex, edge->verts[1]->newIndex);
+ if(edge->verts[0] == edge->verts[1]) printf(" <- DUPLICATE VERTEX");
+ printf(", faces={");
+ for(node = edge->faces; node != NULL; node = node->next) {
+ printf(" %d", ((SmoothFace *)node->link)->newIndex);
+ }
+ printf("}\n");
}
- outDLM = mirrorModifier__doMirror(mmd, inDLM, vertexCos, dm?0:1);
+ printf("\n--- Faces ---\n");
+ for(i = 0; i < BLI_ghash_size(mesh->faces); i++) {
+ SmoothFace *face = BLI_ghash_lookup(mesh->faces, (void *)i);
+
+ printf("%4d: indices={%4d, %4d}, edges={", i,
+ face->oldIndex, face->newIndex);
+ for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
+ if(face->flip[j])
+ printf(" -%-2d", face->edges[j]->newIndex);
+ else
+ printf(" %-2d", face->edges[j]->newIndex);
+ }
+ printf("}, verts={");
+ for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
+ printf(" %d", face->edges[j]->verts[face->flip[j]]->newIndex);
+ }
+ printf("}\n");
+ }
+}
- displistmesh_free(inDLM);
-
- mesh_calc_normals(outDLM->mvert, outDLM->totvert, outDLM->mface, outDLM->totface, &outDLM->nors);
-
- return derivedmesh_from_displistmesh(outDLM, NULL);
+static SmoothMesh *smoothmesh_from_derivedmesh(DerivedMesh *dm)
+{
+ SmoothMesh *mesh = smoothmesh_new();
+ EdgeHash *edges = BLI_edgehash_new();
+ int i;
+ int totvert, totedge, totface;
+
+ mesh->dm = dm;
+
+ totvert = dm->getNumVerts(dm);
+ for(i = 0; i < totvert; i++) {
+ SmoothVert *vert = MEM_callocN(sizeof(*vert), "smoothvert");
+
+ vert->oldIndex = vert->newIndex = i;
+ BLI_ghash_insert(mesh->verts, (void *)i, vert);
+ }
+
+ totedge = dm->getNumEdges(dm);
+ for(i = 0; i < totedge; i++) {
+ SmoothEdge *edge = MEM_callocN(sizeof(*edge), "smoothedge");
+ MEdge med;
+
+ dm->getEdge(dm, i, &med);
+ edge->verts[0] = BLI_ghash_lookup(mesh->verts, (void *)med.v1);
+ edge->verts[1] = BLI_ghash_lookup(mesh->verts, (void *)med.v2);
+ edge->oldIndex = edge->newIndex = i;
+ edge->flag = med.flag;
+ BLI_ghash_insert(mesh->edges, (void *)i, edge);
+ BLI_edgehash_insert(edges, med.v1, med.v2, edge);
+ }
+
+ totface = dm->getNumFaces(dm);
+ for(i = 0; i < totface; i++) {
+ SmoothFace *face = MEM_callocN(sizeof(*face), "smoothface");
+ MFace mf;
+ MVert v1, v2, v3;
+ int j;
+
+ dm->getFace(dm, i, &mf);
+
+ dm->getVert(dm, mf.v1, &v1);
+ dm->getVert(dm, mf.v2, &v2);
+ dm->getVert(dm, mf.v3, &v3);
+ face->edges[0] = BLI_edgehash_lookup(edges, mf.v1, mf.v2);
+ if(face->edges[0]->verts[1]->oldIndex == mf.v1) face->flip[0] = 1;
+ face->edges[1] = BLI_edgehash_lookup(edges, mf.v2, mf.v3);
+ if(face->edges[1]->verts[1]->oldIndex == mf.v2) face->flip[1] = 1;
+ if(mf.v4) {
+ MVert v4;
+ dm->getVert(dm, mf.v4, &v4);
+ face->edges[2] = BLI_edgehash_lookup(edges, mf.v3, mf.v4);
+ if(face->edges[2]->verts[1]->oldIndex == mf.v3) face->flip[2] = 1;
+ face->edges[3] = BLI_edgehash_lookup(edges, mf.v4, mf.v1);
+ if(face->edges[3]->verts[1]->oldIndex == mf.v4) face->flip[3] = 1;
+ CalcNormFloat4(v1.co, v2.co, v3.co, v4.co, face->normal);
+ } else {
+ face->edges[2] = BLI_edgehash_lookup(edges, mf.v3, mf.v1);
+ if(face->edges[2]->verts[1]->oldIndex == mf.v3) face->flip[2] = 1;
+ face->edges[3] = NULL;
+ CalcNormFloat(v1.co, v2.co, v3.co, face->normal);
+ }
+
+ for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
+ SmoothEdge *edge = face->edges[j];
+ BLI_linklist_prepend(&edge->faces, face);
+ BLI_linklist_prepend(&edge->verts[face->flip[j]]->faces, face);
+ }
+
+ face->oldIndex = face->newIndex = i;
+ BLI_ghash_insert(mesh->faces, (void *)i, face);
+ }
+
+ BLI_edgehash_free(edges, NULL);
+
+ return mesh;
+}
+
+static DerivedMesh *CDDM_from_smoothmesh(SmoothMesh *mesh)
+{
+ DerivedMesh *result = CDDM_from_template(mesh->dm,
+ BLI_ghash_size(mesh->verts),
+ BLI_ghash_size(mesh->edges),
+ BLI_ghash_size(mesh->faces));
+ GHashIterator *i;
+ MVert *new_verts = CDDM_get_verts(result);
+ MEdge *new_edges = CDDM_get_edges(result);
+ MFace *new_faces = CDDM_get_faces(result);
+
+ for(i = BLI_ghashIterator_new(mesh->verts); !BLI_ghashIterator_isDone(i);
+ BLI_ghashIterator_step(i)) {
+ SmoothVert *vert = BLI_ghashIterator_getValue(i);
+ MVert *newMV = &new_verts[vert->newIndex];
+
+ DM_copy_vert_data(mesh->dm, result,
+ vert->oldIndex, vert->newIndex, 1);
+ mesh->dm->getVert(mesh->dm, vert->oldIndex, newMV);
+ }
+ BLI_ghashIterator_free(i);
+
+ for(i = BLI_ghashIterator_new(mesh->edges); !BLI_ghashIterator_isDone(i);
+ BLI_ghashIterator_step(i)) {
+ SmoothEdge *edge = BLI_ghashIterator_getValue(i);
+ MEdge *newME = &new_edges[edge->newIndex];
+
+ DM_copy_edge_data(mesh->dm, result,
+ edge->oldIndex, edge->newIndex, 1);
+ mesh->dm->getEdge(mesh->dm, edge->oldIndex, newME);
+ newME->v1 = edge->verts[0]->newIndex;
+ newME->v2 = edge->verts[1]->newIndex;
+ }
+ BLI_ghashIterator_free(i);
+
+ for(i = BLI_ghashIterator_new(mesh->faces); !BLI_ghashIterator_isDone(i);
+ BLI_ghashIterator_step(i)) {
+ SmoothFace *face = BLI_ghashIterator_getValue(i);
+ MFace *newMF = &new_faces[face->newIndex];
+
+ DM_copy_face_data(mesh->dm, result,
+ face->oldIndex, face->newIndex, 1);
+ mesh->dm->getFace(mesh->dm, face->oldIndex, newMF);
+
+ newMF->v1 = face->edges[0]->verts[face->flip[0]]->newIndex;
+ newMF->v2 = face->edges[1]->verts[face->flip[1]]->newIndex;
+ newMF->v3 = face->edges[2]->verts[face->flip[2]]->newIndex;
+
+ if(face->edges[3]) {
+ newMF->v4 = face->edges[3]->verts[face->flip[3]]->newIndex;
+ } else {
+ newMF->v4 = 0;
+ }
+ }
+ BLI_ghashIterator_free(i);
+
+ return result;
+}
+
+/* returns the other edge in the given face that uses the given vert
+ * returns NULL if no other edge in the given face uses the given vert
+ * (this should never happen)
+ */
+static SmoothEdge *other_edge(SmoothFace *face, SmoothVert *vert,
+ SmoothEdge *edge)
+{
+ int i,j;
+ for(i = 0; i < SMOOTHFACE_MAX_EDGES && face->edges[i]; i++) {
+ SmoothEdge *tmp_edge = face->edges[i];
+ if(tmp_edge == edge) continue;
+
+ for(j = 0; j < SMOOTHEDGE_NUM_VERTS; j++)
+ if(tmp_edge->verts[j] == vert) return tmp_edge;
+ }
+
+ /* if we get to here, something's wrong (there should always be 2 edges
+ * which use the same vert in a face)
+ */
+ return NULL;
+}
+
+/* returns the face attached to the given edge which is smoothest with the
+ * given face. Returns NULL if no other faces use this edge.
+ */
+static SmoothFace *smoothest_face(SmoothEdge *edge, SmoothFace *face)
+{
+ /* face with maximum dot product to this face's normal is smoothest */
+ float max_dot = -2;
+ SmoothFace *best_face = NULL;
+ LinkNode *node;
+
+ for(node = edge->faces; node != NULL; node = node->next) {
+ SmoothFace *tmp_face = node->link;
+ float dot;
+ if(tmp_face == face) continue;
+
+ dot = MTC_dot3Float(tmp_face->normal, face->normal);
+
+ if(dot > max_dot) {
+ max_dot = dot;
+ best_face = tmp_face;
+ }
+ }
+
+ return best_face;
+}
+
+/* copies source list to target, overwriting target (target is not freed)
+ * nodes in the copy will be in the same order as in source
+ */
+static void linklist_copy(LinkNode **target, LinkNode *source)
+{
+ LinkNode *node = NULL;
+ *target = NULL;
+
+ for(; source; source = source->next) {
+ if(node) {
+ node->next = MEM_mallocN(sizeof(*node->next), "nlink_copy");
+ node = node->next;
+ } else {
+ node = *target = MEM_mallocN(sizeof(**target), "nlink_copy");
+ }
+ node->link = source->link;
+ node->next = NULL;
+ }
+}
+
+/* appends source to target if it's not already in target */
+static void linklist_append_unique(LinkNode **target, void *source)
+{
+ LinkNode *node;
+ LinkNode *prev = NULL;
+
+ /* check if source value is already in the list */
+ for(node = *target; node; prev = node, node = node->next)
+ if(node->link == source) return;
+
+ node = MEM_mallocN(sizeof(*node), "nlink");
+ node->next = NULL;
+ node->link = source;
+
+ if(prev) prev->next = node;
+ else *target = node;
+}
+
+/* appends elements of source which aren't already in target to target */
+static void linklist_append_list_unique(LinkNode **target, LinkNode *source)
+{
+ for(; source; source = source->next)
+ linklist_append_unique(target, source->link);
+}
+
+/* prepends prepend to list - doesn't copy nodes, just joins the lists */
+static void linklist_prepend_linklist(LinkNode **list, LinkNode *prepend)
+{
+ if(prepend) {
+ LinkNode *node = prepend;
+ while(node->next) node = node->next;
+
+ node->next = *list;
+ *list = prepend;
+ }
+}
+
+/* empties the linked list
+ * frees pointers with freefunc if freefunc is not NULL
+ */
+static void linklist_empty(LinkNode **list, LinkNodeFreeFP freefunc)
+{
+ BLI_linklist_free(*list, freefunc);
+ *list = NULL;
+}
+
+/* removes the first instance of value from the linked list
+ * frees the pointer with freefunc if freefunc is not NULL
+ */
+static void linklist_remove_first(LinkNode **list, void *value,
+ LinkNodeFreeFP freefunc)
+{
+ LinkNode *node = *list;
+ LinkNode *prev = NULL;
+
+ while(node && node->link != value) {
+ prev = node;
+ node = node->next;
+ }
+
+ if(node) {
+ if(prev)
+ prev->next = node->next;
+ else
+ *list = node->next;
+
+ if(freefunc)
+ freefunc(node->link);
+
+ MEM_freeN(node);
+ }
+}
+
+/* removes all elements in source from target */
+static void linklist_remove_list(LinkNode **target, LinkNode *source,
+ LinkNodeFreeFP freefunc)
+{
+ for(; source; source = source->next)
+ linklist_remove_first(target, source->link, freefunc);
+}
+
+static void print_ptr(void *ptr)
+{
+ printf("%p\n", ptr);
+}
+
+static void print_edge(void *ptr)
+{
+ SmoothEdge *edge = ptr;
+ printf(" %4d", edge->newIndex);
+}
+
+static void print_face(void *ptr)
+{
+ SmoothFace *face = ptr;
+ printf(" %4d", face->newIndex);
+}
+
+typedef struct ReplaceData {
+ void *find;
+ void *replace;
+} ReplaceData;
+
+static void edge_replace_vert(void *ptr, void *userdata)
+{
+ SmoothEdge *edge = ptr;
+ SmoothVert *find = ((ReplaceData *)userdata)->find;
+ SmoothVert *replace = ((ReplaceData *)userdata)->replace;
+ int i;
+
+#ifdef EDGESPLIT_DEBUG_2
+ printf("replacing vert %4d with %4d in edge %4d",
+ find->newIndex, replace->newIndex, edge->newIndex);
+ printf(": {%4d, %4d}", edge->verts[0]->newIndex, edge->verts[1]->newIndex);
+#endif
+
+ for(i = 0; i < SMOOTHEDGE_NUM_VERTS; i++) {
+ if(edge->verts[i] == find) {
+ linklist_append_list_unique(&replace->faces, edge->faces);
+ linklist_remove_list(&find->faces, edge->faces, NULL);
+
+ edge->verts[i] = replace;
+ }
+ }
+
+#ifdef EDGESPLIT_DEBUG_2
+ printf(" -> {%4d, %4d}\n", edge->verts[0]->newIndex, edge->verts[1]->newIndex);
+#endif
+}
+
+static void face_replace_vert(void *ptr, void *userdata)
+{
+ SmoothFace *face = ptr;
+ int i;
+
+ for(i = 0; i < SMOOTHFACE_MAX_EDGES && face->edges[i]; i++)
+ edge_replace_vert(face->edges[i], userdata);
+}
+
+static void face_replace_edge(void *ptr, void *userdata)
+{
+ SmoothFace *face = ptr;
+ SmoothEdge *find = ((ReplaceData *)userdata)->find;
+ SmoothEdge *replace = ((ReplaceData *)userdata)->replace;
+ int i;
+
+#ifdef EDGESPLIT_DEBUG_2
+ printf("replacing edge %4d with %4d in face %4d",
+ find->newIndex, replace->newIndex, face->newIndex);
+ if(face->edges[3])
+ printf(": {%2d %2d %2d %2d}",
+ face->edges[0]->newIndex, face->edges[1]->newIndex,
+ face->edges[2]->newIndex, face->edges[3]->newIndex);
+ else
+ printf(": {%2d %2d %2d}",
+ face->edges[0]->newIndex, face->edges[1]->newIndex,
+ face->edges[2]->newIndex);
+#endif
+
+ for(i = 0; i < SMOOTHFACE_MAX_EDGES && face->edges[i]; i++) {
+ if(face->edges[i] == find) {
+ linklist_remove_first(&face->edges[i]->faces, face, NULL);
+ BLI_linklist_prepend(&replace->faces, face);
+ face->edges[i] = replace;
+ }
+ }
+
+#ifdef EDGESPLIT_DEBUG_2
+ if(face->edges[3])
+ printf(" -> {%2d %2d %2d %2d}\n",
+ face->edges[0]->newIndex, face->edges[1]->newIndex,
+ face->edges[2]->newIndex, face->edges[3]->newIndex);
+ else
+ printf(" -> {%2d %2d %2d}\n",
+ face->edges[0]->newIndex, face->edges[1]->newIndex,
+ face->edges[2]->newIndex);
+#endif
+}
+
+static int edge_is_sharp(SmoothEdge *edge, int flags,
+ float threshold)
+{
+ /* if all flags are disabled, edge cannot be sharp */
+ if(!(flags & (MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG)))
+ return 0;
+
+ /* edge can only be sharp if it has at least 2 faces */
+ if(edge->faces && edge->faces->next) {
+ LinkNode *node1;
+ LinkNode *node2;
+
+ if((flags & MOD_EDGESPLIT_FROMFLAG) && (edge->flag & ME_SHARP))
+ return 1;
+
+ if(flags & MOD_EDGESPLIT_FROMANGLE) {
+ /* check angles between all faces */
+ for(node1 = edge->faces; node1; node1 = node1->next) {
+ SmoothFace *face1 = node1->link;
+ for(node2 = node1->next; node2; node2 = node2->next) {
+ SmoothFace *face2 = node2->link;
+ float edge_angle_cos = MTC_dot3Float(face1->normal,
+ face2->normal);
+ if(edge_angle_cos < threshold) return 1;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+/* returns 1 if vert was split, 0 if not */
+static int split_vert(SmoothVert *vert,
+ SmoothEdge *start_edge, SmoothEdge *copy_edge,
+ SmoothFace *start_face, SmoothMesh *mesh,
+ float threshold, int flags)
+{
+ ReplaceData repdata;
+ SmoothVert *copy_vert;
+ LinkNode *split_edges = NULL; /* edges to use the copy vert */
+
+ SmoothFace *current_face = start_face;
+ SmoothEdge *current_edge;
+ SmoothEdge *sharp_edge = NULL;
+ SmoothFace *end_face = NULL;
+ GHash *visited_edges;
+
+#ifdef EDGESPLIT_DEBUG_2
+ printf(">>>>>>>>>>>>>>>>>>>>> split_vert start >>>>>>>>>>>>>>>>>>>>>\n");
+ printf("vert = %4d, start_edge =%4d, copy_edge = %4d, start_face = %4d\n",
+ vert->newIndex, start_edge->newIndex, copy_edge->newIndex,
+ start_face->newIndex);
+ printf("*** Beginning face traversal ***\n");
+#endif
+
+ /* sanity check */
+ if(!smoothface_has_edge(current_face, copy_edge)) return 0;
+ if(!smoothedge_has_vert(copy_edge, vert)) return 0;
+
+ visited_edges = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+
+ /* make sure we don't include start_edge in the split edge list */
+ BLI_ghash_insert(visited_edges, start_edge, NULL);
+
+ end_face = current_face;
+ current_edge = other_edge(current_face, vert, copy_edge);
+ current_face = smoothest_face(current_edge, current_face);
+
+ /* find another sharp edge attached to the current vert */
+ while(current_face && !BLI_ghash_haskey(visited_edges, current_edge)) {
+ BLI_ghash_insert(visited_edges, current_edge, NULL);
+
+ /* if this edge is sharp, use it */
+ if(edge_is_sharp(current_edge, flags, threshold)) {
+ sharp_edge = current_edge;
+ break;
+ }
+
+ /* save end face for edge replacement later */
+ end_face = current_face;
+
+ /* this edge should use the copy vert */
+ BLI_linklist_prepend(&split_edges, current_edge);
+
+ /* get the next edge around the vert */
+ current_edge = other_edge(current_face, vert, current_edge);
+ /* get the smoothest next face */
+ current_face = smoothest_face(current_edge, current_face);
+ }
+#ifdef EDGESPLIT_DEBUG_2
+ printf("*** Ending face traversal ***\n");
+#endif
+ BLI_ghash_free(visited_edges, NULL, NULL);
+
+ /* if we've returned to the starting point without finding a sharp edge,
+ * don't split the vert
+ */
+ if(current_edge == start_edge || (current_face && !sharp_edge)) {
+ BLI_linklist_free(split_edges, NULL);
+ return 0;
+ }
+
+ /* if current_face == NULL, we've hit a loose edge
+ * before finding a sharp edge
+ */
+ if(!current_face) BLI_linklist_prepend(&split_edges, current_edge);
+
+ /* copy the vertex */
+ copy_vert = smoothvert_copy(vert);
+ copy_vert->newIndex = BLI_ghash_size(mesh->verts);
+ linklist_empty(&copy_vert->faces, NULL);
+ BLI_ghash_insert(mesh->verts, (void *)copy_vert->newIndex, copy_vert);
+
+ /* add copy_edge to split_edges so it will undergo vertex replacement */
+ BLI_linklist_prepend(&split_edges, copy_edge);
+
+ /* replace the vertex with the copy in edges being split off */
+ repdata.find = vert;
+ repdata.replace = copy_vert;
+ BLI_linklist_apply(split_edges, edge_replace_vert, &repdata);
+
+ /* if sharp_edge == NULL, we didn't find a sharp edge, so don't split
+ * any more edges
+ */
+ if(sharp_edge) {
+ /* copy the sharpest edge */
+ SmoothEdge *copy_sharp = smoothedge_copy(sharp_edge);
+ copy_sharp->newIndex = BLI_ghash_size(mesh->edges);
+ linklist_empty(&copy_sharp->faces, NULL);
+ BLI_ghash_insert(mesh->edges, (void *)copy_sharp->newIndex, copy_sharp);
+
+#ifdef EDGESPLIT_DEBUG_2
+ printf("sharpest edge is %4d\n",
+ sharp_edge->newIndex);
+#endif
+ /* replace the sharpest edge with the copy in end_face
+ */
+ repdata.find = sharp_edge;
+ repdata.replace = copy_sharp;
+ face_replace_edge(end_face, &repdata);
+
+ /* replace the vertex with its copy in copy_sharp */
+ repdata.find = vert;
+ repdata.replace = copy_vert;
+ edge_replace_vert(copy_sharp, &repdata);
+
+ /* split the other vertex (don't need to check return value as it
+ * doesn't matter if the split succeeds - the edge will be split
+ * regardless
+ */
+ if(copy_sharp->verts[0] == copy_vert)
+ split_vert(copy_sharp->verts[1], sharp_edge, copy_sharp,
+ end_face, mesh, threshold, flags);
+ else
+ split_vert(copy_sharp->verts[0], sharp_edge, copy_sharp,
+ end_face, mesh, threshold, flags);
+ }
+
+ BLI_linklist_free(split_edges, NULL);
+#ifdef EDGESPLIT_DEBUG_2
+ printf("<<<<<<<<<<<<<<<<<<<<< split_vert end <<<<<<<<<<<<<<<<<<<<<\n");
+#endif
+
+ return 1;
+}
+
+static void split_edge(SmoothEdge *edge, SmoothMesh *mesh, float threshold,
+ int flags)
+{
+ LinkNode *split_node;
+
+ /* split all the faces off but the first */
+ for(split_node = edge->faces->next; split_node; ) {
+ ReplaceData repdata;
+ int success[2];
+ SmoothFace *split_face = split_node->link;
+
+ /* copy the start edge */
+ SmoothEdge *copy_edge = smoothedge_copy(edge);
+ copy_edge->newIndex = BLI_ghash_size(mesh->edges);
+ linklist_empty(&copy_edge->faces, NULL);
+ BLI_ghash_insert(mesh->edges, (void *)copy_edge->newIndex, copy_edge);
+
+#ifdef EDGESPLIT_DEBUG_2
+ printf(">>>>>>>>>>>>>>>>>>>> split_edge start >>>>>>>>>>>>>>>>>>>>\n");
+#endif
+ /* we need to go to the next node before we replace the edge,
+ * otherwise the current node will have been removed from the list
+ */
+ split_node = split_node->next;
+
+ /* replace the start edge with the copy in the face being split off */
+ repdata.find = edge;
+ repdata.replace = copy_edge;
+ face_replace_edge(split_face, &repdata);
+
+#ifdef EDGESPLIT_DEBUG_2
+ printf("******************* splitting verts[0] *******************\n");
+#endif
+ success[0] = split_vert(edge->verts[0], edge, copy_edge,
+ split_face, mesh, threshold, flags);
+#ifdef EDGESPLIT_DEBUG_2
+ printf("******************* splitting verts[1] *******************\n");
+#endif
+ success[1] = split_vert(edge->verts[1], edge, copy_edge,
+ split_face, mesh, threshold, flags);
+#ifdef EDGESPLIT_DEBUG_2
+ printf("<<<<<<<<<<<<<<<<<<<<< split_edge end <<<<<<<<<<<<<<<<<<<<<\n");
+#endif
+ /* if neither split operation succeeded, remove the edge */
+ if(!success[0] && !success[1]) {
+ repdata.find = copy_edge;
+ repdata.replace = edge;
+ face_replace_edge(split_face, &repdata);
+
+ BLI_ghash_remove(mesh->edges, (void *)copy_edge->newIndex,
+ NULL, smoothedge_free);
+ }
+ }
+}
+
+static void split_sharp_edges(SmoothMesh *mesh, float split_angle, int flags)
+{
+ int i;
+ int num_edges = BLI_ghash_size(mesh->edges);
+ /* if normal1 dot normal2 < threshold, angle is greater, so split */
+ /* FIXME not sure if this always works */
+ /* 0.00001 added for floating-point rounding */
+ float threshold = cos((split_angle + 0.00001) * M_PI / 180.0);
+
+ /* loop through edges, splitting sharp ones */
+ /* can't use an iterator here, because we'll be adding edges */
+ for(i = 0; i < num_edges; i++) {
+ SmoothEdge *edge = BLI_ghash_lookup(mesh->edges, (void *)i);
+
+ if(edge_is_sharp(edge, flags, threshold))
+ split_edge(edge, mesh, threshold, flags);
+ }
+
+}
+
+static void split_single_vert(SmoothVert *vert, SmoothFace *face,
+ SmoothMesh *mesh)
+{
+ SmoothVert *copy_vert;
+ ReplaceData repdata;
+
+ copy_vert = smoothvert_copy(vert);
+ copy_vert->newIndex = BLI_ghash_size(mesh->verts);
+ linklist_empty(&copy_vert->faces, NULL);
+ BLI_ghash_insert(mesh->verts, (void *)copy_vert->newIndex, copy_vert);
+
+ repdata.find = vert;
+ repdata.replace = copy_vert;
+ face_replace_vert(face, &repdata);
+}
+
+static void split_single_verts(SmoothMesh *mesh)
+{
+ int num_faces = BLI_ghash_size(mesh->faces);
+ int i,j;
+
+ for(i = 0; i < num_faces; i++) {
+ SmoothFace *face = BLI_ghash_lookup(mesh->faces, (void *)i);
+
+ for(j = 0; j < SMOOTHFACE_MAX_EDGES && face->edges[j]; j++) {
+ SmoothEdge *edge = face->edges[j];
+ SmoothEdge *next_edge;
+ SmoothVert *vert = edge->verts[1 - face->flip[j]];
+ int next = (j + 1) % SMOOTHFACE_MAX_EDGES;
+
+ /* wrap next around if at last edge */
+ if(!face->edges[next]) next = 0;
+
+ next_edge = face->edges[next];
+
+ /* if there are other faces sharing this vertex but not
+ * these edges, split the vertex
+ */
+ /* vert has to have at least one face (this one), so faces != 0 */
+ if(!edge->faces->next && !next_edge->faces->next
+ && vert->faces->next)
+ /* FIXME this needs to find all faces that share edges with
+ * this one and split off together
+ */
+ split_single_vert(vert, face, mesh);
+ }
+ }
+}
+
+static DerivedMesh *edgesplitModifier_do(EdgeSplitModifierData *emd,
+ Object *ob, DerivedMesh *dm)
+{
+ SmoothMesh *mesh;
+ DerivedMesh *result;
+
+ mesh = smoothmesh_from_derivedmesh(dm);
+
+#ifdef EDGESPLIT_DEBUG_1
+ printf("********** Pre-split **********\n");
+ smoothmesh_print(mesh);
+#endif
+
+ split_sharp_edges(mesh, emd->split_angle, emd->flags);
+#ifdef EDGESPLIT_DEBUG_1
+ printf("********** Post-edge-split **********\n");
+ smoothmesh_print(mesh);
+#endif
+ split_single_verts(mesh);
+
+#ifdef EDGESPLIT_DEBUG_1
+ printf("********** Post-vert-split **********\n");
+ smoothmesh_print(mesh);
+#endif
+
+ result = CDDM_from_smoothmesh(mesh);
+ smoothmesh_free(mesh);
+
+ return result;
+}
+
+static DerivedMesh *edgesplitModifier_applyModifier(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ int useRenderParams, int isFinalCalc)
+{
+ DerivedMesh *result;
+ EdgeSplitModifierData *emd = (EdgeSplitModifierData*) md;
+
+ result = edgesplitModifier_do(emd, ob, derivedData);
+
+ CDDM_calc_normals(result);
+
+ return result;
+}
+
+static DerivedMesh *edgesplitModifier_applyModifierEM(
+ ModifierData *md, Object *ob, EditMesh *editData,
+ DerivedMesh *derivedData)
+{
+ return edgesplitModifier_applyModifier(md, ob, derivedData, 0, 1);
+}
+
+/* Displace */
+
+static void displaceModifier_initData(ModifierData *md)
+{
+ DisplaceModifierData *dmd = (DisplaceModifierData*) md;
+
+ dmd->texture = NULL;
+ dmd->strength = 1;
+ dmd->direction = MOD_DISP_DIR_NOR;
+ dmd->midlevel = 0.5;
+}
+
+static void displaceModifier_copyData(ModifierData *md, ModifierData *target)
+{
+ DisplaceModifierData *dmd = (DisplaceModifierData*) md;
+ DisplaceModifierData *tdmd = (DisplaceModifierData*) target;
+
+ *tdmd = *dmd;
+}
+
+static void displaceModifier_foreachObjectLink(ModifierData *md, Object *ob,
+ ObjectWalkFunc walk, void *userData)
+{
+ DisplaceModifierData *dmd = (DisplaceModifierData*) md;
+
+ walk(userData, ob, &dmd->map_object);
+}
+
+static void displaceModifier_foreachIDLink(ModifierData *md, Object *ob,
+ IDWalkFunc walk, void *userData)
+{
+ DisplaceModifierData *dmd = (DisplaceModifierData*) md;
+
+ walk(userData, ob, (ID **)&dmd->texture);
+
+ displaceModifier_foreachObjectLink(md, ob, (ObjectWalkFunc) walk, userData);
+}
+
+static int displaceModifier_isDisabled(ModifierData *md)
+{
+ DisplaceModifierData *dmd = (DisplaceModifierData*) md;
+
+ return !dmd->texture;
+}
+
+static void displaceModifier_updateDepgraph(
+ ModifierData *md, DagForest *forest,
+ Object *ob, DagNode *obNode)
+{
+ DisplaceModifierData *dmd = (DisplaceModifierData*) md;
+
+ if(dmd->map_object) {
+ DagNode *curNode = dag_get_node(forest, dmd->map_object);
+
+ dag_add_relation(forest, curNode, obNode,
+ DAG_RL_DATA_DATA | DAG_RL_OB_DATA);
+ }
}
-static void *mirrorModifier_applyModifier(ModifierData *md, Object *ob, void *derivedData, float (*vertexCos)[3], int useRenderParams, int isFinalCalc)
+static void get_texture_coords(DisplaceModifierData *dmd, Object *ob,
+ DerivedMesh *dm,
+ float (*co)[3], float (*texco)[3],
+ int numVerts)
{
- return mirrorModifier_applyModifier__internal(md, ob, derivedData, vertexCos, 0, 1);
+ int i;
+ int texmapping = dmd->texmapping;
+
+ if(texmapping == MOD_DISP_MAP_OBJECT) {
+ if(dmd->map_object)
+ Mat4Invert(dmd->map_object->imat, dmd->map_object->obmat);
+ else /* if there is no map object, default to local */
+ texmapping = MOD_DISP_MAP_LOCAL;
+ }
+
+ /* UVs need special handling, since they come from faces */
+ if(texmapping == MOD_DISP_MAP_UV) {
+ if(dm->getFaceDataArray(dm, LAYERTYPE_TFACE)) {
+ MFace *mface = dm->dupFaceArray(dm);
+ MFace *mf;
+ char *done = MEM_callocN(sizeof(*done) * numVerts,
+ "get_texture_coords done");
+ TFace *tf = dm->getFaceDataArray(dm, LAYERTYPE_TFACE);
+ int numFaces = dm->getNumFaces(dm);
+
+ /* verts are given the UV from the first face that uses them */
+ for(i = 0, mf = mface; i < numFaces; ++i, ++mf, ++tf) {
+ if(!done[mf->v1]) {
+ texco[mf->v1][0] = tf->uv[0][0];
+ texco[mf->v1][1] = tf->uv[0][1];
+ texco[mf->v1][2] = 0;
+ done[mf->v1] = 1;
+ }
+ if(!done[mf->v2]) {
+ texco[mf->v2][0] = tf->uv[1][0];
+ texco[mf->v2][1] = tf->uv[1][1];
+ texco[mf->v2][2] = 0;
+ done[mf->v2] = 1;
+ }
+ if(!done[mf->v3]) {
+ texco[mf->v3][0] = tf->uv[2][0];
+ texco[mf->v3][1] = tf->uv[2][1];
+ texco[mf->v3][2] = 0;
+ done[mf->v3] = 1;
+ }
+ if(!done[mf->v4]) {
+ texco[mf->v4][0] = tf->uv[3][0];
+ texco[mf->v4][1] = tf->uv[3][1];
+ texco[mf->v4][2] = 0;
+ done[mf->v4] = 1;
+ }
+ }
+
+ /* remap UVs from [0, 1] to [-1, 1] */
+ for(i = 0; i < numVerts; ++i) {
+ texco[i][0] = texco[i][0] * 2 - 1;
+ texco[i][1] = texco[i][1] * 2 - 1;
+ }
+
+ MEM_freeN(done);
+ MEM_freeN(mface);
+ return;
+ } else /* if there are no UVs, default to local */
+ texmapping = MOD_DISP_MAP_LOCAL;
+ }
+
+ for(i = 0; i < numVerts; ++i, ++co, ++texco) {
+ switch(texmapping) {
+ case MOD_DISP_MAP_LOCAL:
+ VECCOPY(*texco, *co);
+ break;
+ case MOD_DISP_MAP_GLOBAL:
+ VECCOPY(*texco, *co);
+ Mat4MulVecfl(ob->obmat, *texco);
+ break;
+ case MOD_DISP_MAP_OBJECT:
+ VECCOPY(*texco, *co);
+ Mat4MulVecfl(ob->obmat, *texco);
+ Mat4MulVecfl(dmd->map_object->imat, *texco);
+ break;
+ }
+ }
}
-static void *mirrorModifier_applyModifierEM(ModifierData *md, Object *ob, void *editData, void *derivedData, float (*vertexCos)[3])
+/* dm must be a CDDerivedMesh */
+static void displaceModifier_do(
+ DisplaceModifierData *dmd, Object *ob,
+ DerivedMesh *dm, float (*vertexCos)[3], int numVerts)
{
- if (derivedData) {
- return mirrorModifier_applyModifier__internal(md, ob, derivedData, vertexCos, 0, 1);
+ int i;
+ MVert *mvert;
+ MDeformVert *dvert = NULL;
+ int defgrp_index;
+ float (*tex_co)[3];
+
+ if(!dmd->texture) return;
+
+ defgrp_index = -1;
+
+ if(dmd->defgrp_name[0]) {
+ bDeformGroup *def;
+ for(i = 0, def = ob->defbase.first; def; def = def->next, i++) {
+ if(!strcmp(def->name, dmd->defgrp_name)) {
+ defgrp_index = i;
+ break;
+ }
+ }
+ }
+
+ mvert = CDDM_get_verts(dm);
+ if(defgrp_index >= 0)
+ dvert = dm->getVertDataArray(dm, LAYERTYPE_MDEFORMVERT);
+
+ tex_co = MEM_callocN(sizeof(*tex_co) * numVerts,
+ "displaceModifier_do tex_co");
+ get_texture_coords(dmd, ob, dm, vertexCos, tex_co, numVerts);
+
+ for(i = 0; i < numVerts; ++i) {
+ TexResult texres;
+ float delta = 0;
+ MDeformWeight *def_weight = NULL;
+
+ if(dvert) {
+ int j;
+ for(j = 0; j < dvert[i].totweight; ++j) {
+ if(dvert[i].dw[j].def_nr == defgrp_index) {
+ def_weight = &dvert[i].dw[j];
+ break;
+ }
+ }
+ if(!def_weight) continue;
+ }
+
+ texres.nor = NULL;
+ multitex_ext(dmd->texture, tex_co[i], NULL, NULL, 1, &texres);
+
+ delta = texres.tin - dmd->midlevel;
+
+ if(def_weight) delta *= def_weight->weight;
+
+ switch(dmd->direction) {
+ case MOD_DISP_DIR_X:
+ vertexCos[i][0] += delta * dmd->strength;
+ break;
+ case MOD_DISP_DIR_Y:
+ vertexCos[i][1] += delta * dmd->strength;
+ break;
+ case MOD_DISP_DIR_Z:
+ vertexCos[i][2] += delta * dmd->strength;
+ break;
+ case MOD_DISP_DIR_NOR:
+ delta *= dmd->strength;
+ vertexCos[i][0] += delta * mvert[i].no[0] / 32767.0f;
+ vertexCos[i][1] += delta * mvert[i].no[1] / 32767.0f;
+ vertexCos[i][2] += delta * mvert[i].no[2] / 32767.0f;
+ break;
+ }
+ }
+
+ MEM_freeN(tex_co);
+}
+
+static void displaceModifier_deformVerts(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ float (*vertexCos)[3], int numVerts)
+{
+ DerivedMesh *dm;
+
+ if(derivedData) dm = CDDM_copy(derivedData);
+ else dm = CDDM_from_mesh(ob->data);
+
+ CDDM_apply_vert_coords(dm, vertexCos);
+ CDDM_calc_normals(dm);
+
+ displaceModifier_do((DisplaceModifierData *)md, ob, dm,
+ vertexCos, numVerts);
+
+ dm->release(dm);
+}
+
+static void displaceModifier_deformVertsEM(
+ ModifierData *md, Object *ob, EditMesh *editData,
+ DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
+{
+ DerivedMesh *dm;
+
+ if(derivedData) dm = CDDM_copy(derivedData);
+ else dm = CDDM_from_editmesh(editData, ob->data);
+
+ CDDM_apply_vert_coords(dm, vertexCos);
+ CDDM_calc_normals(dm);
+
+ displaceModifier_do((DisplaceModifierData *)md, ob, dm,
+ vertexCos, numVerts);
+
+ dm->release(dm);
+}
+
+/* UVProject */
+/* UV Project modifier: Generates UVs projected from an object
+*/
+
+static void uvprojectModifier_initData(ModifierData *md)
+{
+ UVProjectModifierData *umd = (UVProjectModifierData*) md;
+ int i;
+
+ for(i = 0; i < MOD_UVPROJECT_MAXPROJECTORS; ++i)
+ umd->projectors[i] = NULL;
+ umd->image = NULL;
+ umd->flags = MOD_UVPROJECT_ADDUVS;
+ umd->num_projectors = 1;
+}
+
+static void uvprojectModifier_copyData(ModifierData *md, ModifierData *target)
+{
+ UVProjectModifierData *umd = (UVProjectModifierData*) md;
+ UVProjectModifierData *tumd = (UVProjectModifierData*) target;
+ int i;
+
+ for(i = 0; i < MOD_UVPROJECT_MAXPROJECTORS; ++i)
+ tumd->projectors[i] = umd->projectors[i];
+ tumd->image = umd->image;
+ tumd->flags = umd->flags;
+ tumd->num_projectors = umd->num_projectors;
+}
+
+static void uvprojectModifier_foreachObjectLink(ModifierData *md, Object *ob,
+ ObjectWalkFunc walk, void *userData)
+{
+ UVProjectModifierData *umd = (UVProjectModifierData*) md;
+ int i;
+
+ for(i = 0; i < MOD_UVPROJECT_MAXPROJECTORS; ++i)
+ walk(userData, ob, &umd->projectors[i]);
+}
+
+static void uvprojectModifier_foreachIDLink(ModifierData *md, Object *ob,
+ IDWalkFunc walk, void *userData)
+{
+ UVProjectModifierData *umd = (UVProjectModifierData*) md;
+
+ walk(userData, ob, (ID **)&umd->image);
+
+ uvprojectModifier_foreachObjectLink(md, ob, (ObjectWalkFunc)walk,
+ userData);
+}
+
+static void uvprojectModifier_updateDepgraph(ModifierData *md,
+ DagForest *forest, Object *ob, DagNode *obNode)
+{
+ UVProjectModifierData *umd = (UVProjectModifierData*) md;
+ int i;
+
+ for(i = 0; i < umd->num_projectors; ++i) {
+ if(umd->projectors[i]) {
+ DagNode *curNode = dag_get_node(forest, umd->projectors[i]);
+
+ dag_add_relation(forest, curNode, obNode,
+ DAG_RL_DATA_DATA | DAG_RL_OB_DATA);
+ }
+ }
+}
+
+typedef struct Projector {
+ Object *ob; /* object this projector is derived from */
+ float imat[4][4]; /* world space -> projector space matrix */
+ float normal[3]; /* projector normal in world space */
+} Projector;
+
+static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd,
+ Object *ob, DerivedMesh *dm)
+{
+ float (*coords)[3], (*co)[3];
+ TFace *tface;
+ MCol *mcol = NULL;
+ int i, numVerts, numFaces;
+ Image *image = umd->image;
+ MFace *mface, *mf;
+ int new_tfaces = 0;
+ Projector projectors[MOD_UVPROJECT_MAXPROJECTORS];
+ int num_projectors = 0;
+
+ for(i = 0; i < umd->num_projectors; ++i)
+ if(umd->projectors[i])
+ projectors[num_projectors++].ob = umd->projectors[i];
+
+ tface = dm->getFaceDataArray(dm, LAYERTYPE_TFACE);
+
+ if(num_projectors == 0) return dm;
+
+ if(!tface) {
+ if(!(umd->flags & MOD_UVPROJECT_ADDUVS)) return dm;
+
+ DM_add_face_layer(dm, LAYERTYPE_TFACE, 0, NULL);
+ tface = dm->getFaceDataArray(dm, LAYERTYPE_TFACE);
+ mcol = dm->getFaceDataArray(dm, LAYERTYPE_MCOL);
+ new_tfaces = 1;
+ }
+
+ numVerts = dm->getNumVerts(dm);
+
+ coords = MEM_callocN(sizeof(*coords) * numVerts,
+ "uvprojectModifier_do coords");
+ dm->getVertCos(dm, coords);
+
+ /* convert coords to world space */
+ for(i = 0, co = coords; i < numVerts; ++i, ++co)
+ Mat4MulVecfl(ob->obmat, *co);
+
+ if(num_projectors == 1) {
+ float imat[4][4];
+
+ /* get projector space matrix */
+ Mat4Invert(imat, projectors[0].ob->obmat);
+ if(projectors[0].ob->type == OB_CAMERA) {
+ Camera *cam = (Camera *)projectors[0].ob->data;
+ if(cam->type == CAM_ORTHO)
+ Mat4MulFloat3(imat[0], 1 / cam->ortho_scale);
+ }
+
+ /* convert coords to projector space */
+ for(i = 0, co = coords; i < numVerts; ++i, ++co)
+ Mat4MulVecfl(imat, *co);
} else {
- DispListMesh *inDLM, *outDLM;
- MirrorModifierData *mmd = (MirrorModifierData*) md;
-
- inDLM = displistmesh_from_editmesh((EditMesh*)editData);
- outDLM = mirrorModifier__doMirror(mmd, inDLM, vertexCos, 0);
- displistmesh_free(inDLM);
+ /* calculate a world space -> projector space matrix and normal
+ * for each projector
+ */
+ for(i = 0; i < num_projectors; ++i) {
+ Mat4Invert(projectors[i].imat, projectors[i].ob->obmat);
+ if(projectors[i].ob->type == OB_CAMERA) {
+ Camera *cam = (Camera *)projectors[i].ob->data;
+ if(cam->type == CAM_ORTHO)
+ Mat4MulFloat3(*projectors[i].imat, 1 / cam->ortho_scale);
+ }
+ projectors[i].normal[0] = 0;
+ projectors[i].normal[1] = 0;
+ projectors[i].normal[2] = 1;
+ Mat4Mul3Vecfl(projectors[i].ob->obmat, projectors[i].normal);
+ }
+ }
- mesh_calc_normals(outDLM->mvert, outDLM->totvert, outDLM->mface, outDLM->totface, &outDLM->nors);
+ mface = dm->dupFaceArray(dm);
+ numFaces = dm->getNumFaces(dm);
+
+ /* apply coords as UVs, and apply image if tfaces are new */
+ for(i = 0, mf = mface; i < numFaces; ++i, ++mf, ++tface) {
+ if(new_tfaces || !image || tface->tpage == image) {
+ if(num_projectors == 1) {
+ /* apply transformed coords as UVs */
+ tface->uv[0][0] = coords[mf->v1][0];
+ tface->uv[0][1] = coords[mf->v1][1];
+ tface->uv[1][0] = coords[mf->v2][0];
+ tface->uv[1][1] = coords[mf->v2][1];
+ tface->uv[2][0] = coords[mf->v3][0];
+ tface->uv[2][1] = coords[mf->v3][1];
+ if(mf->v4) {
+ tface->uv[3][0] = coords[mf->v4][0];
+ tface->uv[3][1] = coords[mf->v4][1];
+ }
+ } else {
+ /* multiple projectors, select the closest to face normal
+ * direction
+ */
+ float co1[3], co2[3], co3[3], co4[3];
+ float face_no[3];
+ int j;
+ Projector *best_projector;
+ float best_dot;
+
+ VECCOPY(co1, coords[mf->v1]);
+ VECCOPY(co2, coords[mf->v2]);
+ VECCOPY(co3, coords[mf->v3]);
+
+ /* get the untransformed face normal */
+ if(mf->v4) {
+ VECCOPY(co4, coords[mf->v4]);
+ CalcNormFloat4(co1, co2, co3, co4, face_no);
+ } else {
+ CalcNormFloat(co1, co2, co3, face_no);
+ }
+
+ /* find the projector which the face points at most directly
+ * (projector normal with largest dot product is best)
+ */
+ best_dot = MTC_dot3Float(projectors[0].normal, face_no);
+ best_projector = &projectors[0];
+
+ for(j = 1; j < num_projectors; ++j) {
+ float tmp_dot = MTC_dot3Float(projectors[j].normal,
+ face_no);
+ if(tmp_dot > best_dot) {
+ best_dot = tmp_dot;
+ best_projector = &projectors[j];
+ }
+ }
- return derivedmesh_from_displistmesh(outDLM, NULL);
+ Mat4MulVecfl(best_projector->imat, co1);
+ Mat4MulVecfl(best_projector->imat, co2);
+ Mat4MulVecfl(best_projector->imat, co3);
+ if(mf->v4)
+ Mat4MulVecfl(best_projector->imat, co4);
+
+ /* apply transformed coords as UVs */
+ tface->uv[0][0] = co1[0];
+ tface->uv[0][1] = co1[1];
+ tface->uv[1][0] = co2[0];
+ tface->uv[1][1] = co2[1];
+ tface->uv[2][0] = co3[0];
+ tface->uv[2][1] = co3[1];
+ if(mf->v4) {
+ tface->uv[3][0] = co4[0];
+ tface->uv[3][1] = co4[1];
+ }
+ }
+ }
+
+ if(new_tfaces) {
+ /* make sure we don't overwrite vert colours */
+ if(mcol) {
+ memcpy(tface->col, mcol, 16); /* based on mcol_to_tface() */
+ mcol += 4;
+ } else
+ memset(tface->col, 0xFF, 16);
+
+ tface->mode = TF_TEX;
+ if(image)
+ tface->tpage = image;
+ }
}
+
+ MEM_freeN(mface);
+ MEM_freeN(coords);
+
+ return dm;
+}
+
+static DerivedMesh *uvprojectModifier_applyModifier(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ int useRenderParams, int isFinalCalc)
+{
+ DerivedMesh *result;
+ UVProjectModifierData *umd = (UVProjectModifierData*) md;
+
+ result = uvprojectModifier_do(umd, ob, derivedData);
+
+ return result;
+}
+
+static DerivedMesh *uvprojectModifier_applyModifierEM(
+ ModifierData *md, Object *ob, EditMesh *editData,
+ DerivedMesh *derivedData)
+{
+ return uvprojectModifier_applyModifier(md, ob, derivedData, 0, 1);
}
/* Decimate */
@@ -1276,11 +2688,12 @@ static void decimateModifier_copyData(ModifierData *md, ModifierData *target)
tdmd->percent = dmd->percent;
}
-static void *decimateModifier_applyModifier(ModifierData *md, Object *ob, void *derivedData, float (*vertexCos)[3], int useRenderParams, int isFinalCalc)
+static DerivedMesh *decimateModifier_applyModifier(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ int useRenderParams, int isFinalCalc)
{
DecimateModifierData *dmd = (DecimateModifierData*) md;
DerivedMesh *dm = derivedData;
- Mesh *me = ob->data;
MVert *mvert;
MFace *mface;
DispListMesh *ndlm=NULL, *dlm=NULL;
@@ -1288,18 +2701,11 @@ static void *decimateModifier_applyModifier(ModifierData *md, Object *ob, void *
int totvert, totface;
int a, numTris;
- if (dm) {
- dlm = dm->convertToDispListMesh(dm, 1);
- mvert = dlm->mvert;
- mface = dlm->mface;
- totvert = dlm->totvert;
- totface = dlm->totface;
- } else {
- mvert = me->mvert;
- mface = me->mface;
- totvert = me->totvert;
- totface = me->totface;
- }
+ dlm = dm->convertToDispListMesh(dm, 1);
+ mvert = dlm->mvert;
+ mface = dlm->mface;
+ totvert = dlm->totvert;
+ totface = dlm->totface;
numTris = 0;
for (a=0; a<totface; a++) {
@@ -1309,7 +2715,8 @@ static void *decimateModifier_applyModifier(ModifierData *md, Object *ob, void *
}
if(numTris<3) {
- modifier_setError(md, "There must be more than 3 input faces (triangles).");
+ modifier_setError(md,
+ "There must be more than 3 input faces (triangles).");
goto exit;
}
@@ -1324,11 +2731,7 @@ static void *decimateModifier_applyModifier(ModifierData *md, Object *ob, void *
float *vbCo = &lod.vertex_buffer[a*3];
float *vbNo = &lod.vertex_normal_buffer[a*3];
- if (vertexCos) {
- VECCOPY(vbCo, vertexCos[a]);
- } else {
- VECCOPY(vbCo, mv->co);
- }
+ VECCOPY(vbCo, mv->co);
vbNo[0] = mv->no[0]/32767.0f;
vbNo[1] = mv->no[1]/32767.0f;
@@ -1404,7 +2807,8 @@ exit:
if (dlm) displistmesh_free(dlm);
if (ndlm) {
- mesh_calc_normals(ndlm->mvert, ndlm->totvert, ndlm->mface, ndlm->totface, &ndlm->nors);
+ mesh_calc_normals(ndlm->mvert, ndlm->totvert, ndlm->mface,
+ ndlm->totface, &ndlm->nors);
return derivedmesh_from_displistmesh(ndlm, NULL);
} else {
@@ -1450,61 +2854,68 @@ static int waveModifier_dependsOnTime(ModifierData *md)
return 1;
}
-static void waveModifier_deformVerts(ModifierData *md, Object *ob, void *derivedData, float (*vertexCos)[3], int numVerts)
+static void waveModifier_deformVerts(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ float (*vertexCos)[3], int numVerts)
{
WaveModifierData *wmd = (WaveModifierData*) md;
float ctime = bsystem_time(ob, 0, (float)G.scene->r.cfra, 0.0);
- float minfac = (float)(1.0/exp(wmd->width*wmd->narrow*wmd->width*wmd->narrow));
+ float minfac =
+ (float)(1.0 / exp(wmd->width * wmd->narrow * wmd->width * wmd->narrow));
float lifefac = wmd->height;
- if(wmd->damp==0) wmd->damp= 10.0f;
+ if(wmd->damp == 0) wmd->damp = 10.0f;
- if(wmd->lifetime!=0.0) {
- float x= ctime - wmd->timeoffs;
+ if(wmd->lifetime != 0.0) {
+ float x = ctime - wmd->timeoffs;
- if(x>wmd->lifetime) {
- lifefac= x-wmd->lifetime;
+ if(x > wmd->lifetime) {
+ lifefac = x - wmd->lifetime;
- if(lifefac > wmd->damp) lifefac= 0.0;
- else lifefac= (float)(wmd->height*(1.0 - sqrt(lifefac/wmd->damp)));
+ if(lifefac > wmd->damp) lifefac = 0.0;
+ else lifefac =
+ (float)(wmd->height * (1.0 - sqrt(lifefac / wmd->damp)));
}
}
- if(lifefac!=0.0) {
+ if(lifefac != 0.0) {
int i;
- for (i=0; i<numVerts; i++) {
+ for(i = 0; i < numVerts; i++) {
float *co = vertexCos[i];
- float x= co[0]-wmd->startx;
- float y= co[1]-wmd->starty;
+ float x = co[0] - wmd->startx;
+ float y = co[1] - wmd->starty;
float amplit= 0.0f;
if(wmd->flag & WAV_X) {
- if(wmd->flag & WAV_Y) amplit= (float)sqrt( (x*x + y*y));
- else amplit= x;
+ if(wmd->flag & WAV_Y) amplit = (float)sqrt(x*x + y*y);
+ else amplit = x;
}
else if(wmd->flag & WAV_Y)
amplit= y;
/* this way it makes nice circles */
- amplit-= (ctime-wmd->timeoffs)*wmd->speed;
+ amplit -= (ctime - wmd->timeoffs) * wmd->speed;
if(wmd->flag & WAV_CYCL) {
- amplit = (float)fmod(amplit-wmd->width, 2.0*wmd->width) + wmd->width;
+ amplit = (float)fmod(amplit - wmd->width, 2.0 * wmd->width)
+ + wmd->width;
}
- /* GAUSSIAN */
- if(amplit> -wmd->width && amplit<wmd->width) {
- amplit = amplit*wmd->narrow;
- amplit= (float)(1.0/exp(amplit*amplit) - minfac);
+ /* GAUSSIAN */
+ if(amplit > -wmd->width && amplit < wmd->width) {
+ amplit = amplit * wmd->narrow;
+ amplit = (float)(1.0 / exp(amplit * amplit) - minfac);
- co[2]+= lifefac*amplit;
+ co[2] += lifefac * amplit;
}
}
}
}
-static void waveModifier_deformVertsEM(ModifierData *md, Object *ob, void *editData, void *derivedData, float (*vertexCos)[3], int numVerts)
+static void waveModifier_deformVertsEM(
+ ModifierData *md, Object *ob, EditMesh *editData,
+ DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
waveModifier_deformVerts(md, ob, NULL, vertexCos, numVerts);
}
@@ -1515,7 +2926,7 @@ static void armatureModifier_initData(ModifierData *md)
{
ArmatureModifierData *amd = (ArmatureModifierData*) md;
- amd->deformflag = ARM_DEF_ENVELOPE|ARM_DEF_VGROUP;
+ amd->deformflag = ARM_DEF_ENVELOPE | ARM_DEF_VGROUP;
}
static void armatureModifier_copyData(ModifierData *md, ModifierData *target)
@@ -1534,36 +2945,53 @@ static int armatureModifier_isDisabled(ModifierData *md)
return !amd->object;
}
-static void armatureModifier_foreachObjectLink(ModifierData *md, Object *ob, void (*walk)(void *userData, Object *ob, Object **obpoin), void *userData)
+static void armatureModifier_foreachObjectLink(
+ ModifierData *md, Object *ob,
+ void (*walk)(void *userData, Object *ob, Object **obpoin),
+ void *userData)
{
ArmatureModifierData *amd = (ArmatureModifierData*) md;
walk(userData, ob, &amd->object);
}
-static void armatureModifier_updateDepgraph(ModifierData *md, DagForest *forest, Object *ob, DagNode *obNode)
+static void armatureModifier_updateDepgraph(
+ ModifierData *md, DagForest *forest, Object *ob,
+ DagNode *obNode)
{
ArmatureModifierData *amd = (ArmatureModifierData*) md;
if (amd->object) {
DagNode *curNode = dag_get_node(forest, amd->object);
- dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA|DAG_RL_OB_DATA);
+ dag_add_relation(forest, curNode, obNode,
+ DAG_RL_DATA_DATA | DAG_RL_OB_DATA);
}
}
-static void armatureModifier_deformVerts(ModifierData *md, Object *ob, void *derivedData, float (*vertexCos)[3], int numVerts)
+static void armatureModifier_deformVerts(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ float (*vertexCos)[3], int numVerts)
{
ArmatureModifierData *amd = (ArmatureModifierData*) md;
- armature_deform_verts(amd->object, ob, vertexCos, numVerts, amd->deformflag);
+ armature_deform_verts(amd->object, ob, derivedData, vertexCos, numVerts,
+ amd->deformflag);
}
-static void armatureModifier_deformVertsEM(ModifierData *md, Object *ob, void *editData, void *derivedData, float (*vertexCos)[3], int numVerts)
+static void armatureModifier_deformVertsEM(
+ ModifierData *md, Object *ob, EditMesh *editData,
+ DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
ArmatureModifierData *amd = (ArmatureModifierData*) md;
+ DerivedMesh *dm = derivedData;
+
+ if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
- armature_deform_verts(amd->object, ob, vertexCos, numVerts, amd->deformflag);
+ armature_deform_verts(amd->object, ob, dm, vertexCos, numVerts,
+ amd->deformflag);
+
+ if(!derivedData) dm->release(dm);
}
/* Hook */
@@ -1603,14 +3031,18 @@ static int hookModifier_isDisabled(ModifierData *md)
return !hmd->object;
}
-static void hookModifier_foreachObjectLink(ModifierData *md, Object *ob, void (*walk)(void *userData, Object *ob, Object **obpoin), void *userData)
+static void hookModifier_foreachObjectLink(
+ ModifierData *md, Object *ob,
+ void (*walk)(void *userData, Object *ob, Object **obpoin),
+ void *userData)
{
HookModifierData *hmd = (HookModifierData*) md;
walk(userData, ob, &hmd->object);
}
-static void hookModifier_updateDepgraph(ModifierData *md, DagForest *forest, Object *ob, DagNode *obNode)
+static void hookModifier_updateDepgraph(ModifierData *md, DagForest *forest,
+ Object *ob, DagNode *obNode)
{
HookModifierData *hmd = (HookModifierData*) md;
@@ -1621,87 +3053,139 @@ static void hookModifier_updateDepgraph(ModifierData *md, DagForest *forest, Obj
}
}
-static void hookModifier_deformVerts(ModifierData *md, Object *ob, void *derivedData, float (*vertexCos)[3], int numVerts)
+static void hookModifier_deformVerts(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ float (*vertexCos)[3], int numVerts)
{
HookModifierData *hmd = (HookModifierData*) md;
float vec[3], mat[4][4];
int i;
+ DerivedMesh *dm = derivedData;
Mat4Invert(ob->imat, ob->obmat);
- Mat4MulSerie(mat, ob->imat, hmd->object->obmat, hmd->parentinv, NULL, NULL, NULL, NULL, NULL);
+ Mat4MulSerie(mat, ob->imat, hmd->object->obmat, hmd->parentinv,
+ NULL, NULL, NULL, NULL, NULL);
/* vertex indices? */
if(hmd->indexar) {
- for (i=0; i<hmd->totindex; i++) {
+ for(i = 0; i < hmd->totindex; i++) {
int index = hmd->indexar[i];
- /* This should always be true and I don't generally like
- * "paranoid" style code like this, but old files can have
- * indices that are out of range because old blender did
- * not correct them on exit editmode. - zr
- */
- if (index<numVerts) {
+ /* This should always be true and I don't generally like
+ * "paranoid" style code like this, but old files can have
+ * indices that are out of range because old blender did
+ * not correct them on exit editmode. - zr
+ */
+ if(index < numVerts) {
float *co = vertexCos[index];
float fac = hmd->force;
- if(hmd->falloff!=0.0) {
- float len= VecLenf(co, hmd->cent);
- if(len > hmd->falloff) fac = 0.0;
- else if(len>0.0) fac *= sqrt(1.0 - len/hmd->falloff);
- }
+ /* if DerivedMesh is present and has original index data,
+ * use it
+ */
+ if(dm && dm->getVertData(dm, 0, LAYERTYPE_ORIGINDEX)) {
+ int j;
+ int orig_index;
+ for(j = 0; j < numVerts; ++j) {
+ fac = hmd->force;
+ orig_index = *(int *)dm->getVertData(dm, j,
+ LAYERTYPE_ORIGINDEX);
+ if(orig_index == index) {
+ co = vertexCos[j];
+ if(hmd->falloff != 0.0) {
+ float len = VecLenf(co, hmd->cent);
+ if(len > hmd->falloff) fac = 0.0;
+ else if(len > 0.0)
+ fac *= sqrt(1.0 - len / hmd->falloff);
+ }
+
+ if(fac != 0.0) {
+ VecMat4MulVecfl(vec, mat, co);
+ VecLerpf(co, co, vec, fac);
+ }
+ }
+ }
+ } else {
+ if(hmd->falloff != 0.0) {
+ float len = VecLenf(co, hmd->cent);
+ if(len > hmd->falloff) fac = 0.0;
+ else if(len > 0.0)
+ fac *= sqrt(1.0 - len / hmd->falloff);
+ }
- if(fac!=0.0) {
- VecMat4MulVecfl(vec, mat, co);
- VecLerpf(co, co, vec, fac);
+ if(fac != 0.0) {
+ VecMat4MulVecfl(vec, mat, co);
+ VecLerpf(co, co, vec, fac);
+ }
}
}
}
- }
- else { /* vertex group hook */
+ } else { /* vertex group hook */
bDeformGroup *curdef;
- Mesh *me= ob->data;
- int index=0;
+ Mesh *me = ob->data;
+ int index = 0;
+ int use_dverts;
+ int maxVerts;
/* find the group (weak loop-in-loop) */
- for (curdef = ob->defbase.first; curdef; curdef=curdef->next, index++)
- if (!strcmp(curdef->name, hmd->name))
- break;
+ for(curdef = ob->defbase.first; curdef; curdef = curdef->next, index++)
+ if(!strcmp(curdef->name, hmd->name)) break;
+
+ if(dm)
+ if(dm->getVertData(dm, 0, LAYERTYPE_MDEFORMVERT)) {
+ use_dverts = 1;
+ maxVerts = dm->getNumVerts(dm);
+ } else use_dverts = 0;
+ else if(me->dvert) {
+ use_dverts = 1;
+ maxVerts = me->totvert;
+ } else use_dverts = 0;
- if(curdef && me->dvert) {
- MDeformVert *dvert= me->dvert;
+ if(curdef && use_dverts) {
+ MDeformVert *dvert = me->dvert;
int i, j;
- for (i=0; i < me->totvert; i++, dvert++) {
- for(j=0; j<dvert->totweight; j++) {
- if (dvert->dw[j].def_nr == index) {
+ for(i = 0; i < maxVerts; i++, dvert++) {
+ if(dm) dvert = dm->getVertData(dm, i, LAYERTYPE_MDEFORMVERT);
+ for(j = 0; j < dvert->totweight; j++) {
+ if(dvert->dw[j].def_nr == index) {
float fac = hmd->force*dvert->dw[j].weight;
float *co = vertexCos[i];
- if(hmd->falloff!=0.0) {
- float len= VecLenf(co, hmd->cent);
+ if(hmd->falloff != 0.0) {
+ float len = VecLenf(co, hmd->cent);
if(len > hmd->falloff) fac = 0.0;
- else if(len>0.0) fac *= sqrt(1.0 - len/hmd->falloff);
+ else if(len > 0.0)
+ fac *= sqrt(1.0 - len / hmd->falloff);
}
VecMat4MulVecfl(vec, mat, co);
VecLerpf(co, co, vec, fac);
-
}
}
}
}
-
}
}
-static void hookModifier_deformVertsEM(ModifierData *md, Object *ob, void *editData, void *derivedData, float (*vertexCos)[3], int numVerts)
+static void hookModifier_deformVertsEM(
+ ModifierData *md, Object *ob, EditMesh *editData,
+ DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
{
+ DerivedMesh *dm = derivedData;
+
+ if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
+
hookModifier_deformVerts(md, ob, derivedData, vertexCos, numVerts);
+
+ if(!derivedData) dm->release(dm);
}
/* Softbody */
-static void softbodyModifier_deformVerts(ModifierData *md, Object *ob, void *derivedData, float (*vertexCos)[3], int numVerts)
+static void softbodyModifier_deformVerts(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ float (*vertexCos)[3], int numVerts)
{
sbObjectStep(ob, (float)G.scene->r.cfra, vertexCos, numVerts);
}
@@ -1724,41 +3208,51 @@ static int booleanModifier_isDisabled(ModifierData *md)
return !bmd->object;
}
-static void booleanModifier_foreachObjectLink(ModifierData *md, Object *ob, void (*walk)(void *userData, Object *ob, Object **obpoin), void *userData)
+static void booleanModifier_foreachObjectLink(
+ ModifierData *md, Object *ob,
+ void (*walk)(void *userData, Object *ob, Object **obpoin),
+ void *userData)
{
BooleanModifierData *bmd = (BooleanModifierData*) md;
walk(userData, ob, &bmd->object);
}
-static void booleanModifier_updateDepgraph(ModifierData *md, DagForest *forest, Object *ob, DagNode *obNode)
+static void booleanModifier_updateDepgraph(
+ ModifierData *md, DagForest *forest, Object *ob,
+ DagNode *obNode)
{
BooleanModifierData *bmd = (BooleanModifierData*) md;
- if (bmd->object) {
+ if(bmd->object) {
DagNode *curNode = dag_get_node(forest, bmd->object);
- dag_add_relation(forest, curNode, obNode, DAG_RL_DATA_DATA|DAG_RL_OB_DATA);
+ dag_add_relation(forest, curNode, obNode,
+ DAG_RL_DATA_DATA | DAG_RL_OB_DATA);
}
}
-static void *booleanModifier_applyModifier(ModifierData *md, Object *ob, void *derivedData, float (*vertexCos)[3], int useRenderParams, int isFinalCalc)
-{
- // XXX doesn't handle derived data
+static DerivedMesh *booleanModifier_applyModifier(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ int useRenderParams, int isFinalCalc)
+{
+ // XXX doesn't handle derived data
BooleanModifierData *bmd = (BooleanModifierData*) md;
-
+
/* we do a quick sanity check */
- if( ((Mesh *)ob->data)->totface>3 && bmd->object && ((Mesh *)bmd->object->data)->totface>3) {
- DispListMesh *dlm= NewBooleanMeshDLM(bmd->object, ob, 1+bmd->operation);
-
- /* if new mesh returned, get derived mesh; otherwise there was
- * an error, so delete the modifier object */
+ if(((Mesh *)ob->data)->totface > 3
+ && bmd->object && ((Mesh *)bmd->object->data)->totface > 3) {
+ DerivedMesh *result = NewBooleanDerivedMesh(bmd->object, ob,
+ 1 + bmd->operation);
- if( dlm )
- return derivedmesh_from_displistmesh(dlm, NULL);
+ /* if new mesh returned, return it; otherwise there was
+ * an error, so delete the modifier object */
+ if(result)
+ return result;
else
bmd->object = NULL;
}
+
return derivedData;
}
@@ -1780,9 +3274,11 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type)
* structName == typeName + 'ModifierData'
*/
#define INIT_TYPE(typeName) \
- ( strcpy(typeArr[eModifierType_##typeName].name, #typeName), \
- strcpy(typeArr[eModifierType_##typeName].structName, #typeName "ModifierData"), \
- typeArr[eModifierType_##typeName].structSize = sizeof(typeName##ModifierData), \
+ (strcpy(typeArr[eModifierType_##typeName].name, #typeName), \
+ strcpy(typeArr[eModifierType_##typeName].structName, \
+ #typeName "ModifierData"), \
+ typeArr[eModifierType_##typeName].structSize = \
+ sizeof(typeName##ModifierData), \
&typeArr[eModifierType_##typeName])
mti = &typeArr[eModifierType_None];
@@ -1790,12 +3286,14 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type)
strcpy(mti->structName, "ModifierData");
mti->structSize = sizeof(ModifierData);
mti->type = eModifierType_None;
- mti->flags = eModifierTypeFlag_AcceptsMesh|eModifierTypeFlag_AcceptsCVs;
+ mti->flags = eModifierTypeFlag_AcceptsMesh
+ | eModifierTypeFlag_AcceptsCVs;
mti->isDisabled = noneModifier_isDisabled;
mti = INIT_TYPE(Curve);
mti->type = eModifierTypeType_OnlyDeform;
- mti->flags = eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_RequiresOriginalData;
+ mti->flags = eModifierTypeFlag_AcceptsCVs
+ | eModifierTypeFlag_SupportsEditmode;
mti->copyData = curveModifier_copyData;
mti->isDisabled = curveModifier_isDisabled;
mti->foreachObjectLink = curveModifier_foreachObjectLink;
@@ -1805,7 +3303,8 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type)
mti = INIT_TYPE(Lattice);
mti->type = eModifierTypeType_OnlyDeform;
- mti->flags = eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_RequiresOriginalData;
+ mti->flags = eModifierTypeFlag_AcceptsCVs
+ | eModifierTypeFlag_SupportsEditmode;
mti->copyData = latticeModifier_copyData;
mti->isDisabled = latticeModifier_isDisabled;
mti->foreachObjectLink = latticeModifier_foreachObjectLink;
@@ -1815,7 +3314,10 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type)
mti = INIT_TYPE(Subsurf);
mti->type = eModifierTypeType_Constructive;
- mti->flags = eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode;
+ mti->flags = eModifierTypeFlag_AcceptsMesh
+ | eModifierTypeFlag_SupportsMapping
+ | eModifierTypeFlag_SupportsEditmode
+ | eModifierTypeFlag_EnableInEditmode;
mti->initData = subsurfModifier_initData;
mti->copyData = subsurfModifier_copyData;
mti->freeData = subsurfModifier_freeData;
@@ -1845,12 +3347,53 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type)
mti = INIT_TYPE(Mirror);
mti->type = eModifierTypeType_Constructive;
- mti->flags = eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode;
+ mti->flags = eModifierTypeFlag_AcceptsMesh
+ | eModifierTypeFlag_SupportsMapping
+ | eModifierTypeFlag_SupportsEditmode
+ | eModifierTypeFlag_EnableInEditmode;
mti->initData = mirrorModifier_initData;
mti->copyData = mirrorModifier_copyData;
mti->applyModifier = mirrorModifier_applyModifier;
mti->applyModifierEM = mirrorModifier_applyModifierEM;
+ mti = INIT_TYPE(EdgeSplit);
+ mti->type = eModifierTypeType_Constructive;
+ mti->flags = eModifierTypeFlag_AcceptsMesh
+ | eModifierTypeFlag_SupportsMapping
+ | eModifierTypeFlag_SupportsEditmode
+ | eModifierTypeFlag_EnableInEditmode;
+ mti->initData = edgesplitModifier_initData;
+ mti->copyData = edgesplitModifier_copyData;
+ mti->applyModifier = edgesplitModifier_applyModifier;
+ mti->applyModifierEM = edgesplitModifier_applyModifierEM;
+
+ mti = INIT_TYPE(Displace);
+ mti->type = eModifierTypeType_OnlyDeform;
+ mti->flags = eModifierTypeFlag_AcceptsCVs
+ | eModifierTypeFlag_SupportsEditmode;
+ mti->initData = displaceModifier_initData;
+ mti->copyData = displaceModifier_copyData;
+ mti->foreachObjectLink = displaceModifier_foreachObjectLink;
+ mti->foreachIDLink = displaceModifier_foreachIDLink;
+ mti->updateDepgraph = displaceModifier_updateDepgraph;
+ mti->isDisabled = displaceModifier_isDisabled;
+ mti->deformVerts = displaceModifier_deformVerts;
+ mti->deformVertsEM = displaceModifier_deformVertsEM;
+
+ mti = INIT_TYPE(UVProject);
+ mti->type = eModifierTypeType_Nonconstructive;
+ mti->flags = eModifierTypeFlag_AcceptsMesh
+ | eModifierTypeFlag_SupportsMapping
+ | eModifierTypeFlag_SupportsEditmode
+ | eModifierTypeFlag_EnableInEditmode;
+ mti->initData = uvprojectModifier_initData;
+ mti->copyData = uvprojectModifier_copyData;
+ mti->foreachObjectLink = uvprojectModifier_foreachObjectLink;
+ mti->foreachIDLink = uvprojectModifier_foreachIDLink;
+ mti->updateDepgraph = uvprojectModifier_updateDepgraph;
+ mti->applyModifier = uvprojectModifier_applyModifier;
+ mti->applyModifierEM = uvprojectModifier_applyModifierEM;
+
mti = INIT_TYPE(Decimate);
mti->type = eModifierTypeType_Nonconstructive;
mti->flags = eModifierTypeFlag_AcceptsMesh;
@@ -1860,7 +3403,8 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type)
mti = INIT_TYPE(Wave);
mti->type = eModifierTypeType_OnlyDeform;
- mti->flags = eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_SupportsEditmode;
+ mti->flags = eModifierTypeFlag_AcceptsCVs
+ | eModifierTypeFlag_SupportsEditmode;
mti->initData = waveModifier_initData;
mti->copyData = waveModifier_copyData;
mti->dependsOnTime = waveModifier_dependsOnTime;
@@ -1869,7 +3413,8 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type)
mti = INIT_TYPE(Armature);
mti->type = eModifierTypeType_OnlyDeform;
- mti->flags = eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_RequiresOriginalData;
+ mti->flags = eModifierTypeFlag_AcceptsCVs
+ | eModifierTypeFlag_SupportsEditmode;
mti->initData = armatureModifier_initData;
mti->copyData = armatureModifier_copyData;
mti->isDisabled = armatureModifier_isDisabled;
@@ -1880,7 +3425,8 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type)
mti = INIT_TYPE(Hook);
mti->type = eModifierTypeType_OnlyDeform;
- mti->flags = eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_RequiresOriginalData;
+ mti->flags = eModifierTypeFlag_AcceptsCVs
+ | eModifierTypeFlag_SupportsEditmode;
mti->initData = hookModifier_initData;
mti->copyData = hookModifier_copyData;
mti->freeData = hookModifier_freeData;
@@ -1892,7 +3438,8 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type)
mti = INIT_TYPE(Softbody);
mti->type = eModifierTypeType_OnlyDeform;
- mti->flags = eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_RequiresOriginalData;
+ mti->flags = eModifierTypeFlag_AcceptsCVs
+ | eModifierTypeFlag_RequiresOriginalData;
mti->deformVerts = softbodyModifier_deformVerts;
mti = INIT_TYPE(Boolean);
@@ -1925,9 +3472,10 @@ ModifierData *modifier_new(int type)
strcpy(md->name, mti->name);
md->type = type;
- md->mode = eModifierMode_Realtime|eModifierMode_Render|eModifierMode_Expanded;
+ md->mode = eModifierMode_Realtime
+ | eModifierMode_Render | eModifierMode_Expanded;
- if (mti->flags&eModifierTypeFlag_EnableInEditmode)
+ if (mti->flags & eModifierTypeFlag_EnableInEditmode)
md->mode |= eModifierMode_Editmode;
if (mti->initData) mti->initData(md);
@@ -1956,9 +3504,9 @@ int modifier_supportsMapping(ModifierData *md)
{
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
- return ( (mti->flags&eModifierTypeFlag_SupportsEditmode) &&
+ return ( (mti->flags & eModifierTypeFlag_SupportsEditmode) &&
( (mti->type==eModifierTypeType_OnlyDeform ||
- (mti->flags&eModifierTypeFlag_SupportsMapping))) );
+ (mti->flags & eModifierTypeFlag_SupportsMapping))) );
}
ModifierData *modifiers_findByType(Object *ob, ModifierType type)
@@ -1989,14 +3537,32 @@ void modifiers_clearErrors(Object *ob)
if (qRedraw) allqueue(REDRAWBUTSEDIT, 0);
}
-void modifiers_foreachObjectLink(Object *ob, void (*walk)(void *userData, Object *ob, Object **obpoin), void *userData)
+void modifiers_foreachObjectLink(Object *ob, ObjectWalkFunc walk,
+ void *userData)
+{
+ ModifierData *md = ob->modifiers.first;
+
+ for (; md; md=md->next) {
+ ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+
+ if (mti->foreachObjectLink)
+ mti->foreachObjectLink(md, ob, walk, userData);
+ }
+}
+
+void modifiers_foreachIDLink(Object *ob, IDWalkFunc walk, void *userData)
{
ModifierData *md = ob->modifiers.first;
for (; md; md=md->next) {
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
- if (mti->foreachObjectLink) mti->foreachObjectLink(md, ob, walk, userData);
+ if(mti->foreachIDLink) mti->foreachIDLink(md, ob, walk, userData);
+ else if(mti->foreachObjectLink) {
+ /* each Object can masquerade as an ID, so this should be OK */
+ ObjectWalkFunc fp = (ObjectWalkFunc)walk;
+ mti->foreachObjectLink(md, ob, fp, userData);
+ }
}
}
@@ -2014,8 +3580,8 @@ int modifier_couldBeCage(ModifierData *md)
{
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
- return ( (md->mode&eModifierMode_Realtime) &&
- (md->mode&eModifierMode_Editmode) &&
+ return ( (md->mode & eModifierMode_Realtime) &&
+ (md->mode & eModifierMode_Editmode) &&
(!mti->isDisabled || !mti->isDisabled(md)) &&
modifier_supportsMapping(md));
}
@@ -2037,8 +3603,12 @@ void modifier_setError(ModifierData *md, char *format, ...)
allqueue(REDRAWBUTSEDIT, 0);
}
-/* used for buttons, to find out if the 'draw deformed in editmode' option is there */
-/* also used in transform_conversion.c, to detect CrazySpace [tm] (2nd arg then is NULL) */
+/* used for buttons, to find out if the 'draw deformed in editmode' option is
+ * there
+ *
+ * also used in transform_conversion.c, to detect CrazySpace [tm] (2nd arg
+ * then is NULL)
+ */
int modifiers_getCageIndex(Object *ob, int *lastPossibleCageIndex_r)
{
ModifierData *md = ob->modifiers.first;
@@ -2048,16 +3618,16 @@ int modifiers_getCageIndex(Object *ob, int *lastPossibleCageIndex_r)
for (i=0; md; i++,md=md->next) {
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
- if (!(md->mode&eModifierMode_Realtime)) continue;
- if (!(md->mode&eModifierMode_Editmode)) continue;
+ if (!(md->mode & eModifierMode_Realtime)) continue;
+ if (!(md->mode & eModifierMode_Editmode)) continue;
if (mti->isDisabled && mti->isDisabled(md)) continue;
- if (!(mti->flags&eModifierTypeFlag_SupportsEditmode)) continue;
+ if (!(mti->flags & eModifierTypeFlag_SupportsEditmode)) continue;
if (!modifier_supportsMapping(md))
break;
if (lastPossibleCageIndex_r) *lastPossibleCageIndex_r = i;
- if (md->mode&eModifierMode_OnCage)
+ if (md->mode & eModifierMode_OnCage)
cageIndex = i;
}
@@ -2069,15 +3639,7 @@ int modifiers_isSoftbodyEnabled(Object *ob)
{
ModifierData *md = modifiers_findByType(ob, eModifierType_Softbody);
- /* Softbody not allowed in this situation, enforce! */
- /* if (md && ob->pd && ob->pd->deflect) { */
- /* no reason for that any more BM */
- if (0) {
- md->mode &= ~(eModifierMode_Realtime|eModifierMode_Render|eModifierMode_Editmode);
- md = NULL;
- }
-
- return (md && md->mode&(eModifierMode_Realtime|eModifierMode_Render));
+ return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render));
}
ModifierData *modifiers_getVirtualModifierList(Object *ob)
@@ -2131,14 +3693,17 @@ ModifierData *modifiers_getVirtualModifierList(Object *ob)
return ob->modifiers.first;
}
-/* Takes an object and returns its first selected armature, else just its armature
- This should work for multiple armatures per object */
+/* Takes an object and returns its first selected armature, else just its
+ * armature
+ * This should work for multiple armatures per object
+ */
Object *modifiers_isDeformedByArmature(Object *ob)
{
ModifierData *md = modifiers_getVirtualModifierList(ob);
ArmatureModifierData *amd= NULL;
- /* return the first selected armaturem, this lets us use multiple armatures */
+ /* return the first selected armature, this lets us use multiple armatures
+ */
for (; md; md=md->next) {
if (md->type==eModifierType_Armature) {
amd = (ArmatureModifierData*) md;
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index 44feaf46233..f8798de2650 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -44,6 +44,7 @@
#include "DNA_object_types.h"
#include "BKE_bad_level_calls.h"
+#include "BKE_cdderivedmesh.h"
#include "BKE_utildefines.h"
#include "BKE_global.h"
#include "BKE_mesh.h"
@@ -75,6 +76,11 @@ struct CCGDerivedMesh {
Mesh *me;
DispListMesh *dlm;
+
+ struct {int startVert; CCGVert *vert;} *vertMap;
+ struct {int startVert; int startEdge; CCGEdge *edge;} *edgeMap;
+ struct {int startVert; int startEdge;
+ int startFace; CCGFace *face;} *faceMap;
};
typedef struct CCGDerivedMesh CCGDerivedMesh;
@@ -392,7 +398,7 @@ static DispListMesh *ss_to_displistmesh(CCGSubSurf *ss, CCGDerivedMesh *ccgdm, i
int edgeSize = ccgSubSurf_getEdgeSize(ss);
int gridSize = ccgSubSurf_getGridSize(ss);
int edgeBase, faceBase;
- int i, j, k, S, x, y, index, lastIndex;
+ int i, j, k, S, x, y, index;
int vertBase = 0;
TFace *tface = NULL;
MEdge *medge = NULL;
@@ -503,6 +509,9 @@ static DispListMesh *ss_to_displistmesh(CCGSubSurf *ss, CCGDerivedMesh *ccgdm, i
* note that the vertex with index 0 is always a face
* center vert, this is relied upon to ensure we don't
* need to do silly test_index_face calls.
+ *
+ * NOTE (artificer): The STEPINDEX flag has been removed, so this
+ * funny order is no longer strictly necessary, but it works.
*/
faceBase = i = 0;
@@ -544,15 +553,10 @@ static DispListMesh *ss_to_displistmesh(CCGSubSurf *ss, CCGDerivedMesh *ccgdm, i
}
vertBase = i;
- lastIndex = -1;
for (index=0; index<totvert; index++) {
CCGVert *v = vertMap2[index];
- int mapIndex = ccgDM_getVertMapIndex(ccgdm, ss, v);
VecCopyf(dlm->mvert[i].co, ccgSubSurf_getVertData(ss, v));
- if (mapIndex!=lastIndex)
- dlm->mvert[i].flag = ME_VERT_STEPINDEX;
*((int*) ccgSubSurf_getVertUserData(ss, v)) = i++;
- lastIndex = mapIndex;
}
// load edges
@@ -591,11 +595,8 @@ static DispListMesh *ss_to_displistmesh(CCGSubSurf *ss, CCGDerivedMesh *ccgdm, i
}
}
- lastIndex = -1;
for (index=0; index<totedge; index++) {
CCGEdge *e= edgeMap2[index];
- int mapIndex = ccgDM_getEdgeMapIndex(ccgdm, ss, e);
- int edgeStart = i;
unsigned int flags = 0;
if (!ccgSubSurf_getEdgeNumFaces(ss, e)) flags |= ME_LOOSEEDGE;
@@ -607,18 +608,20 @@ static DispListMesh *ss_to_displistmesh(CCGSubSurf *ss, CCGDerivedMesh *ccgdm, i
if (eed->seam) {
flags |= ME_SEAM;
}
- } else {
+ } else if(medge){
int edgeIdx = (int) ccgSubSurf_getEdgeEdgeHandle(ss, e);
if (edgeIdx!=-1) {
MEdge *origMed = &medge[edgeIdx];
if (inDLM) {
- flags |= origMed->flag&~ME_EDGE_STEPINDEX;
+ flags |= origMed->flag;
} else {
flags |= (origMed->flag&ME_SEAM)|ME_EDGEDRAW|ME_EDGERENDER;
}
}
+ } else {
+ flags |= ME_EDGEDRAW | ME_EDGERENDER;
}
for (x=0; x<edgeSize-1; x++) {
@@ -628,16 +631,11 @@ static DispListMesh *ss_to_displistmesh(CCGSubSurf *ss, CCGDerivedMesh *ccgdm, i
med->flag = flags;
i++;
}
-
- if (mapIndex!=lastIndex)
- dlm->medge[edgeStart].flag |= ME_EDGE_STEPINDEX;
- lastIndex = mapIndex;
}
// load faces
i=0;
- lastIndex = -1;
for (index=0; index<totface; index++) {
CCGFace *f = faceMap2[index];
CCGFace *uvf = faceMap2Uv? faceMap2Uv[index]: NULL;
@@ -649,9 +647,8 @@ static DispListMesh *ss_to_displistmesh(CCGSubSurf *ss, CCGDerivedMesh *ccgdm, i
TFace *origTFace = NULL;
int mat_nr;
int flag;
- int mapIndex = ccgDM_getFaceMapIndex(ccgdm, ss, f);
- if (!ssFromEditmesh) {
+ if (!ssFromEditmesh && mface) {
int origIdx = (int) ccgSubSurf_getFaceFaceHandle(ss, f);
MFace *origMFace = &mface[origIdx];
@@ -695,10 +692,13 @@ static DispListMesh *ss_to_displistmesh(CCGSubSurf *ss, CCGDerivedMesh *ccgdm, i
mat_nr = origMFace->mat_nr;
flag = origMFace->flag;
- } else {
+ } else if(ssFromEditmesh) {
EditFace *ef = ccgSubSurf_getFaceFaceHandle(ss, f);
mat_nr = ef->mat_nr;
flag = ef->flag;
+ } else {
+ mat_nr = 0;
+ flag = 0;
}
for (S=0; S<numVerts; S++) {
@@ -714,7 +714,7 @@ static DispListMesh *ss_to_displistmesh(CCGSubSurf *ss, CCGDerivedMesh *ccgdm, i
mf->v3 = getFaceIndex(ss, f, S, x+1, y+1, edgeSize, gridSize);
mf->v4 = getFaceIndex(ss, f, S, x+1, y+0, edgeSize, gridSize);
mf->mat_nr = mat_nr;
- mf->flag = flag&~ME_FACE_STEPINDEX;
+ mf->flag = flag;
if(uvf) {
VECCOPY(smoothuv[0], getFaceUV(uvss, uvf, S, x+0, y+0, edgeSize, gridSize));
@@ -723,12 +723,6 @@ static DispListMesh *ss_to_displistmesh(CCGSubSurf *ss, CCGDerivedMesh *ccgdm, i
VECCOPY(smoothuv[3], getFaceUV(uvss, uvf, S, x+1, y+0, edgeSize, gridSize));
}
- if (S==0 && x==0 && y==0) {
- if (mapIndex!=lastIndex)
- mf->flag |= ME_FACE_STEPINDEX;
- lastIndex = mapIndex;
- }
-
for (j=0; j<4; j++) {
int fx = x + (j==2||j==3);
int fy = y + (j==1||j==2);
@@ -795,6 +789,478 @@ static DispListMesh *ss_to_displistmesh(CCGSubSurf *ss, CCGDerivedMesh *ccgdm, i
return dlm;
}
+/* face weighting - taken from Brecht's element data patch */
+static void calc_ss_weights(int gridFaces,
+ FaceVertWeight **qweight, FaceVertWeight **tweight)
+{
+ FaceVertWeight *qw, *tw;
+ int x, y, j;
+ int numWeights = gridFaces * gridFaces;
+
+ *tweight = MEM_mallocN(sizeof(**tweight) * numWeights, "ssTriWeight");
+ *qweight = MEM_mallocN(sizeof(**qweight) * numWeights, "ssQuadWeight");
+
+ qw = *qweight;
+ tw = *tweight;
+
+ for (y = 0; y < gridFaces; y++) {
+ for (x = 0; x < gridFaces; x++) {
+ for (j = 0; j < 4; j++) {
+ int fx = x + (j == 2 || j == 3);
+ int fy = y + (j == 1 || j == 2);
+ float x_v = (float) fx / gridFaces;
+ float y_v = (float) fy / gridFaces;
+ float tx_v = (1.0f - x_v), ty_v = (1.0f - y_v);
+ float center = (1.0f / 3.0f) * tx_v * ty_v;
+
+ (*tw)[j][0] = center + 0.5f * tx_v * y_v;
+ (*tw)[j][2] = center + 0.5f * x_v * ty_v;
+ (*tw)[j][1] = 1.0f - (*tw)[j][0] - (*tw)[j][2];
+ (*tw)[j][3] = 0.0f;
+
+ tx_v *= 0.5f;
+ ty_v *= 0.5f;
+
+ (*qw)[j][3] = tx_v * ty_v;
+ (*qw)[j][0] = (*qw)[j][3] + tx_v * y_v;
+ (*qw)[j][2] = (*qw)[j][3] + x_v * ty_v;
+ (*qw)[j][1] = 1.0f - (*qw)[j][0] - (*qw)[j][2] - (*qw)[j][3];
+
+ }
+ tw++;
+ qw++;
+ }
+ }
+}
+
+DerivedMesh *ss_to_cdderivedmesh(CCGSubSurf *ss, int ssFromEditmesh,
+ int drawInteriorEdges, int useSubsurfUv,
+ DerivedMesh *dm)
+{
+ DerivedMesh *result;
+ int edgeSize = ccgSubSurf_getEdgeSize(ss);
+ int gridSize = ccgSubSurf_getGridSize(ss);
+ int gridFaces = gridSize - 1;
+ int edgeBase, faceBase;
+ int i, j, k, S, x, y, index;
+ int vertBase = 0;
+ CCGVertIterator *vi;
+ CCGEdgeIterator *ei;
+ CCGFaceIterator *fi;
+ CCGFace **faceMap2, **faceMap2Uv = NULL;
+ CCGEdge **edgeMap2;
+ CCGVert **vertMap2;
+ int totvert, totedge, totface;
+ MVert *mvert;
+ MEdge *med;
+ MFace *mf;
+ TFace *tface;
+ CCGSubSurf *uvss = NULL;
+ int *origIndex;
+ FaceVertWeight *qweight, *tweight;
+
+ calc_ss_weights(gridFaces, &qweight, &tweight);
+
+ /* vert map */
+ totvert = ccgSubSurf_getNumVerts(ss);
+ vertMap2 = MEM_mallocN(totvert*sizeof(*vertMap2), "vertmap");
+ vi = ccgSubSurf_getVertIterator(ss);
+ for(; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
+ CCGVert *v = ccgVertIterator_getCurrent(vi);
+
+ if(ssFromEditmesh) {
+ vertMap2[ccgDM_getVertMapIndex(NULL, ss, v)] = v;
+ } else {
+ vertMap2[(int) ccgSubSurf_getVertVertHandle(ss, v)] = v;
+ }
+ }
+ ccgVertIterator_free(vi);
+
+ totedge = ccgSubSurf_getNumEdges(ss);
+ edgeMap2 = MEM_mallocN(totedge*sizeof(*edgeMap2), "edgemap");
+ ei = ccgSubSurf_getEdgeIterator(ss);
+ for(; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
+ CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
+
+ if(ssFromEditmesh) {
+ edgeMap2[ccgDM_getEdgeMapIndex(NULL, ss, e)] = e;
+ } else {
+ edgeMap2[(int) ccgSubSurf_getEdgeEdgeHandle(ss, e)] = e;
+ }
+ }
+
+ totface = ccgSubSurf_getNumFaces(ss);
+ faceMap2 = MEM_mallocN(totface*sizeof(*faceMap2), "facemap");
+ fi = ccgSubSurf_getFaceIterator(ss);
+ for(; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
+ CCGFace *f = ccgFaceIterator_getCurrent(fi);
+
+ if(ssFromEditmesh) {
+ faceMap2[ccgDM_getFaceMapIndex(NULL, ss, f)] = f;
+ } else {
+ faceMap2[(int) ccgSubSurf_getFaceFaceHandle(ss, f)] = f;
+ }
+ }
+ ccgFaceIterator_free(fi);
+
+ if(dm) {
+ result = CDDM_from_template(dm, ccgSubSurf_getNumFinalVerts(ss),
+ ccgSubSurf_getNumFinalEdges(ss),
+ ccgSubSurf_getNumFinalFaces(ss));
+ tface = dm->getFaceDataArray(dm, LAYERTYPE_TFACE);
+ } else {
+ result = CDDM_new(ccgSubSurf_getNumFinalVerts(ss),
+ ccgSubSurf_getNumFinalEdges(ss),
+ ccgSubSurf_getNumFinalFaces(ss));
+ tface = NULL;
+ }
+
+ if(useSubsurfUv && tface) {
+ /* slightly dodgy hack to use current ss_sync_from_uv function */
+ DispListMesh dlm;
+
+ dlm.mface = dm->dupFaceArray(dm);
+ dlm.tface = tface;
+ dlm.mvert = dm->dupVertArray(dm);
+ dlm.totvert = dm->getNumVerts(dm);
+ dlm.totface = dm->getNumFaces(dm);
+
+ /* not for editmesh currently */
+ uvss = _getSubSurf(NULL, ccgSubSurf_getSubdivisionLevels(ss),
+ 0, 1, 0);
+
+ if(ss_sync_from_uv(uvss, ss, NULL, &dlm)) {
+ faceMap2Uv = MEM_mallocN(totface * sizeof(*faceMap2Uv),
+ "facemapuv");
+
+ fi = ccgSubSurf_getFaceIterator(uvss);
+ for(; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
+ CCGFace *f = ccgFaceIterator_getCurrent(fi);
+ faceMap2Uv[(int) ccgSubSurf_getFaceFaceHandle(uvss, f)] = f;
+ }
+ ccgFaceIterator_free(fi);
+ }
+
+ MEM_freeN(dlm.mface);
+ MEM_freeN(dlm.mvert);
+ }
+
+ // load verts
+ faceBase = i = 0;
+ mvert = CDDM_get_verts(result);
+ origIndex = result->getVertData(result, 0, LAYERTYPE_ORIGINDEX);
+
+ for(index = 0; index < totface; index++) {
+ CCGFace *f = faceMap2[index];
+ int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
+ FaceVertWeight *weight = (numVerts == 4) ? qweight : tweight;
+ int vertIdx[4];
+
+ for(S = 0; S < numVerts; S++) {
+ CCGVert *v = ccgSubSurf_getFaceVert(ss, f, S);
+
+ if(ssFromEditmesh)
+ vertIdx[S] = ccgDM_getVertMapIndex(NULL, ss, v);
+ else
+ vertIdx[S] = (int)ccgSubSurf_getVertVertHandle(ss, v);
+ }
+
+ DM_interp_vert_data(dm, result, vertIdx, weight[0][0], numVerts, i);
+ VecCopyf(mvert->co, ccgSubSurf_getFaceCenterData(ss, f));
+ *origIndex = ORIGINDEX_NONE;
+ ++mvert;
+ ++origIndex;
+ i++;
+
+ for(S = 0; S < numVerts; S++) {
+ int prevS = (S - 1 + numVerts) % numVerts;
+ int nextS = (S + 1) % numVerts;
+ int otherS = (numVerts == 4) ? (S + 2) % numVerts : 3;
+ for(x = 1; x < gridFaces; x++) {
+ float w[4];
+ w[prevS] = weight[x][0][0];
+ w[S] = weight[x][0][1];
+ w[nextS] = weight[x][0][2];
+ w[otherS] = weight[x][0][3];
+ DM_interp_vert_data(dm, result, vertIdx, w, numVerts, i);
+ VecCopyf(mvert->co,
+ ccgSubSurf_getFaceGridEdgeData(ss, f, S, x));
+ *origIndex = ORIGINDEX_NONE;
+ ++mvert;
+ ++origIndex;
+ i++;
+ }
+ }
+
+ for(S = 0; S < numVerts; S++) {
+ int prevS = (S - 1 + numVerts) % numVerts;
+ int nextS = (S + 1) % numVerts;
+ int otherS = (numVerts == 4) ? (S + 2) % numVerts : 3;
+ for(y = 1; y < gridFaces; y++) {
+ for(x = 1; x < gridFaces; x++) {
+ float w[4];
+ w[prevS] = weight[y * gridFaces + x][0][0];
+ w[S] = weight[y * gridFaces + x][0][1];
+ w[nextS] = weight[y * gridFaces + x][0][2];
+ w[otherS] = weight[y * gridFaces + x][0][3];
+ DM_interp_vert_data(dm, result, vertIdx, w, numVerts, i);
+ VecCopyf(mvert->co,
+ ccgSubSurf_getFaceGridData(ss, f, S, x, y));
+ *origIndex = ORIGINDEX_NONE;
+ ++mvert;
+ ++origIndex;
+ i++;
+ }
+ }
+ }
+
+ *((int*)ccgSubSurf_getFaceUserData(ss, f)) = faceBase;
+ faceBase += 1 + numVerts * ((gridSize-2) + (gridSize-2) * (gridSize-2));
+ }
+
+ edgeBase = i;
+ for(index = 0; index < totedge; index++) {
+ CCGEdge *e = edgeMap2[index];
+ int x;
+ int vertIdx[2];
+
+ if(ssFromEditmesh) {
+ CCGVert *v;
+ v = ccgSubSurf_getEdgeVert0(ss, e);
+ vertIdx[0] = ccgDM_getVertMapIndex(NULL, ss, v);
+ v = ccgSubSurf_getEdgeVert1(ss, e);
+ vertIdx[1] = ccgDM_getVertMapIndex(NULL, ss, v);
+ } else {
+ CCGVert *v;
+ v = ccgSubSurf_getEdgeVert0(ss, e);
+ vertIdx[0] = (int)ccgSubSurf_getVertVertHandle(ss, v);
+ v = ccgSubSurf_getEdgeVert1(ss, e);
+ vertIdx[1] = (int)ccgSubSurf_getVertVertHandle(ss, v);
+ }
+
+ for(x = 1; x < edgeSize - 1; x++) {
+ float w[2];
+ w[1] = (float) x / (edgeSize - 1);
+ w[0] = 1 - w[1];
+ DM_interp_vert_data(dm, result, vertIdx, w, 2, i);
+ VecCopyf(mvert->co, ccgSubSurf_getEdgeData(ss, e, x));
+ *origIndex = ORIGINDEX_NONE;
+ ++mvert;
+ ++origIndex;
+ i++;
+ }
+
+ *((int*)ccgSubSurf_getEdgeUserData(ss, e)) = edgeBase;
+ edgeBase += edgeSize-2;
+ }
+
+ vertBase = i;
+ for(index = 0; index < totvert; index++) {
+ CCGVert *v = vertMap2[index];
+ int vertIdx;
+
+ if(ssFromEditmesh)
+ vertIdx = ccgDM_getVertMapIndex(NULL, ss, v);
+ else
+ vertIdx = (int)ccgSubSurf_getVertVertHandle(ss, v);
+
+ DM_copy_vert_data(dm, result, vertIdx, i, 1);
+ VecCopyf(mvert->co, ccgSubSurf_getVertData(ss, v));
+
+ *((int*)ccgSubSurf_getVertUserData(ss, v)) = i;
+ *origIndex = ccgDM_getVertMapIndex(NULL, ss, v);
+ ++mvert;
+ ++origIndex;
+ i++;
+ }
+
+ // load edges
+ i = 0;
+ med = CDDM_get_edges(result);
+ origIndex = result->getEdgeData(result, 0, LAYERTYPE_ORIGINDEX);
+
+ for(index = 0; index < totface; index++) {
+ CCGFace *f = faceMap2[index];
+ int numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
+
+ for(k = 0; k < numVerts; k++) {
+ for(x = 0; x < gridFaces; x++) {
+ if(drawInteriorEdges) med->flag = ME_EDGEDRAW | ME_EDGERENDER;
+ med->v1 = getFaceIndex(ss, f, k, x, 0, edgeSize, gridSize);
+ med->v2 = getFaceIndex(ss, f, k, x+1, 0, edgeSize, gridSize);
+ *origIndex = ORIGINDEX_NONE;
+ ++med;
+ ++origIndex;
+ i++;
+ }
+
+ for(x = 1; x < gridFaces; x++) {
+ for(y = 0; y < gridFaces; y++) {
+ if(drawInteriorEdges)
+ med->flag = ME_EDGEDRAW | ME_EDGERENDER;
+ med->v1 = getFaceIndex(ss, f, k, x, y, edgeSize, gridSize);
+ med->v2 = getFaceIndex(ss, f, k, x, y + 1,
+ edgeSize, gridSize);
+ *origIndex = ORIGINDEX_NONE;
+ ++med;
+ ++origIndex;
+ i++;
+
+ if(drawInteriorEdges)
+ med->flag = ME_EDGEDRAW | ME_EDGERENDER;
+ med->v1 = getFaceIndex(ss, f, k, y, x, edgeSize, gridSize);
+ med->v2 = getFaceIndex(ss, f, k, y + 1, x,
+ edgeSize, gridSize);
+ *origIndex = ORIGINDEX_NONE;
+ ++med;
+ ++origIndex;
+ i++;
+ }
+ }
+ }
+ }
+
+ for(index = 0; index < totedge; index++) {
+ CCGEdge *e = edgeMap2[index];
+ unsigned int flags = 0;
+
+ if(!ccgSubSurf_getEdgeNumFaces(ss, e)) flags |= ME_LOOSEEDGE;
+
+ if(ssFromEditmesh) {
+ EditEdge *eed = ccgSubSurf_getEdgeEdgeHandle(ss, e);
+
+ flags |= ME_EDGEDRAW | ME_EDGERENDER;
+ if(eed->seam) {
+ flags |= ME_SEAM;
+ }
+ if(eed->sharp) flags |= ME_SHARP;
+ } else {
+ int edgeIdx = (int)ccgSubSurf_getEdgeEdgeHandle(ss, e);
+
+ if(edgeIdx != -1 && dm) {
+ MEdge origMed;
+ dm->getEdge(dm, edgeIdx, &origMed);
+
+ flags |= origMed.flag;
+ }
+ }
+
+ for(x = 0; x < edgeSize - 1; x++) {
+ med->v1 = getEdgeIndex(ss, e, x, edgeSize);
+ med->v2 = getEdgeIndex(ss, e, x + 1, edgeSize);
+ med->flag = flags;
+ *origIndex = ccgDM_getEdgeMapIndex(NULL, ss, e);
+ ++med;
+ ++origIndex;
+ i++;
+ }
+ }
+
+ // load faces
+ i = 0;
+ mf = CDDM_get_faces(result);
+ origIndex = result->getFaceData(result, 0, LAYERTYPE_ORIGINDEX);
+
+ for(index = 0; index < totface; index++) {
+ CCGFace *f = faceMap2[index];
+ CCGFace *uvf = faceMap2Uv ? faceMap2Uv[index] : NULL;
+ int numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
+ int mat_nr;
+ int flag;
+ int mapIndex = ccgDM_getFaceMapIndex(NULL, ss, f);
+ int faceIdx = (int)ccgSubSurf_getFaceFaceHandle(ss, f);
+
+ if(!ssFromEditmesh) {
+ MFace origMFace;
+ dm->getFace(dm, faceIdx, &origMFace);
+
+ mat_nr = origMFace.mat_nr;
+ flag = origMFace.flag;
+ } else {
+ EditFace *ef = ccgSubSurf_getFaceFaceHandle(ss, f);
+ mat_nr = ef->mat_nr;
+ flag = ef->flag;
+ }
+
+ for(S = 0; S < numVerts; S++) {
+ FaceVertWeight *weight = (numVerts == 4) ? qweight : tweight;
+
+ for(y = 0; y < gridFaces; y++) {
+ for(x = 0; x < gridFaces; x++) {
+ mf->v1 = getFaceIndex(ss, f, S, x + 0, y + 0,
+ edgeSize, gridSize);
+ mf->v2 = getFaceIndex(ss, f, S, x + 0, y + 1,
+ edgeSize, gridSize);
+ mf->v3 = getFaceIndex(ss, f, S, x + 1, y + 1,
+ edgeSize, gridSize);
+ mf->v4 = getFaceIndex(ss, f, S, x + 1, y + 0,
+ edgeSize, gridSize);
+ mf->mat_nr = mat_nr;
+ mf->flag = flag;
+
+ if(dm) {
+ int prevS = (S - 1 + numVerts) % numVerts;
+ int nextS = (S + 1) % numVerts;
+ int otherS = (numVerts == 4) ? (S + 2) % numVerts : 3;
+ FaceVertWeight w;
+
+ for(j = 0; j < 4; ++j) {
+ w[j][prevS] = (*weight)[j][0];
+ w[j][S] = (*weight)[j][1];
+ w[j][nextS] = (*weight)[j][2];
+ w[j][otherS] = (*weight)[j][3];
+ }
+
+ DM_interp_face_data(dm, result, &faceIdx, NULL,
+ &w, 1, i);
+ weight++;
+ }
+
+ if(uvf) {
+ TFace *tf = DM_get_face_data(result, i,
+ LAYERTYPE_TFACE);
+ float *newuv;
+
+ newuv = getFaceUV(uvss, uvf, S, x + 0, y + 0,
+ edgeSize, gridSize);
+ tf->uv[0][0] = newuv[0]; tf->uv[0][1] = newuv[1];
+ newuv = getFaceUV(uvss, uvf, S, x + 0, y + 1,
+ edgeSize, gridSize);
+ tf->uv[1][0] = newuv[0]; tf->uv[1][1] = newuv[1];
+ newuv = getFaceUV(uvss, uvf, S, x + 1, y + 1,
+ edgeSize, gridSize);
+ tf->uv[2][0] = newuv[0]; tf->uv[2][1] = newuv[1];
+ newuv = getFaceUV(uvss, uvf, S, x + 1, y + 0,
+ edgeSize, gridSize);
+ tf->uv[3][0] = newuv[0]; tf->uv[3][1] = newuv[1];
+ }
+
+ *origIndex = mapIndex;
+ ++mf;
+ ++origIndex;
+ i++;
+ }
+ }
+ }
+ }
+
+ MEM_freeN(faceMap2);
+ MEM_freeN(edgeMap2);
+ MEM_freeN(vertMap2);
+
+ MEM_freeN(tweight);
+ MEM_freeN(qweight);
+
+ if(uvss) {
+ ccgSubSurf_free(uvss);
+ MEM_freeN(faceMap2Uv);
+ }
+
+ CDDM_calc_normals(result);
+
+ return result;
+}
+
static void ss_sync_from_mesh(CCGSubSurf *ss, Mesh *me, DispListMesh *dlm, float (*vertexCos)[3], int useFlatSubdiv) {
float creaseFactor = (float) ccgSubSurf_getSubdivisionLevels(ss);
CCGVertHDL fVerts[4];
@@ -812,7 +1278,7 @@ static void ss_sync_from_mesh(CCGSubSurf *ss, Mesh *me, DispListMesh *dlm, float
CCGVert *v;
ccgSubSurf_syncVert(ss, (CCGVertHDL) i, vertexCos?vertexCos[i]:mvert[i].co, 0, &v);
- if (!dlm || (mvert[i].flag&ME_VERT_STEPINDEX)) index++;
+ if (!dlm) index++;
((int*) ccgSubSurf_getVertUserData(ss, v))[1] = index;
}
@@ -824,7 +1290,7 @@ static void ss_sync_from_mesh(CCGSubSurf *ss, Mesh *me, DispListMesh *dlm, float
ccgSubSurf_syncEdge(ss, (CCGEdgeHDL) i, (CCGVertHDL) med->v1, (CCGVertHDL) med->v2, crease, &e);
- if (!dlm || (med->flag&ME_EDGE_STEPINDEX)) index++;
+ if (!dlm) index++;
((int*) ccgSubSurf_getEdgeUserData(ss, e))[1] = index;
}
}
@@ -833,7 +1299,7 @@ static void ss_sync_from_mesh(CCGSubSurf *ss, Mesh *me, DispListMesh *dlm, float
MFace *mf = &((MFace*) mface)[i];
CCGFace *f;
- if (!dlm || (mf->flag&ME_FACE_STEPINDEX)) index++;
+ if (!dlm) index++;
fVerts[0] = (CCGVertHDL) mf->v1;
fVerts[1] = (CCGVertHDL) mf->v2;
@@ -866,6 +1332,92 @@ static void ss_sync_from_mesh(CCGSubSurf *ss, Mesh *me, DispListMesh *dlm, float
ccgSubSurf_processSync(ss);
}
+static void ss_sync_from_derivedmesh(CCGSubSurf *ss, DerivedMesh *dm,
+ float (*vertexCos)[3], int useFlatSubdiv)
+{
+ float creaseFactor = (float) ccgSubSurf_getSubdivisionLevels(ss);
+ CCGVertHDL fVerts[4];
+ int totvert = dm->getNumVerts(dm);
+ int totedge = dm->getNumEdges(dm);
+ int totface = dm->getNumFaces(dm);
+ int i;
+ int *index;
+ MVert *mvert = dm->dupVertArray(dm);
+ MEdge *medge = dm->dupEdgeArray(dm);
+ MFace *mface = dm->dupFaceArray(dm);
+ MVert *mv;
+ MEdge *me;
+ MFace *mf;
+
+ ccgSubSurf_initFullSync(ss);
+
+ mv = mvert;
+ index = (int *)dm->getVertDataArray(dm, LAYERTYPE_ORIGINDEX);
+ for(i = 0; i < totvert; i++, mv++, index++) {
+ CCGVert *v;
+
+ if(vertexCos) {
+ ccgSubSurf_syncVert(ss, (CCGVertHDL)i, vertexCos[i], 0, &v);
+ } else {
+ ccgSubSurf_syncVert(ss, (CCGVertHDL)i, mv->co, 0, &v);
+ }
+
+ ((int*)ccgSubSurf_getVertUserData(ss, v))[1] = *index;
+ }
+
+ me = medge;
+ index = (int *)dm->getEdgeDataArray(dm, LAYERTYPE_ORIGINDEX);
+ for(i = 0; i < totedge; i++, me++, index++) {
+ CCGEdge *e;
+ float crease;
+
+ crease = useFlatSubdiv ? creaseFactor :
+ me->crease * creaseFactor / 255.0f;
+
+ ccgSubSurf_syncEdge(ss, (CCGEdgeHDL)i, (CCGVertHDL)me->v1,
+ (CCGVertHDL)me->v2, crease, &e);
+
+ ((int*)ccgSubSurf_getEdgeUserData(ss, e))[1] = *index;
+ }
+
+ mf = mface;
+ index = (int *)dm->getFaceDataArray(dm, LAYERTYPE_ORIGINDEX);
+ for (i = 0; i < totface; i++, mf++, index++) {
+ CCGFace *f;
+
+ fVerts[0] = (CCGVertHDL) mf->v1;
+ fVerts[1] = (CCGVertHDL) mf->v2;
+ fVerts[2] = (CCGVertHDL) mf->v3;
+ fVerts[3] = (CCGVertHDL) mf->v4;
+
+ // this is very bad, means mesh is internally consistent.
+ // it is not really possible to continue without modifying
+ // other parts of code significantly to handle missing faces.
+ // since this really shouldn't even be possible we just bail.
+ if(ccgSubSurf_syncFace(ss, (CCGFaceHDL)i, fVerts[3] ? 4 : 3,
+ fVerts, &f) == eCCGError_InvalidValue) {
+ static int hasGivenError = 0;
+
+ if(!hasGivenError) {
+ error("Unrecoverable error in SubSurf calculation,"
+ " mesh is inconsistent.");
+
+ hasGivenError = 1;
+ }
+
+ return;
+ }
+
+ ((int*)ccgSubSurf_getFaceUserData(ss, f))[1] = *index;
+ }
+
+ ccgSubSurf_processSync(ss);
+
+ MEM_freeN(mvert);
+ MEM_freeN(medge);
+ MEM_freeN(mface);
+}
+
void ss_sync_from_editmesh(CCGSubSurf *ss, EditMesh *em, float (*vertCos)[3], int useFlatSubdiv)
{
float creaseFactor = (float) ccgSubSurf_getSubdivisionLevels(ss);
@@ -974,11 +1526,445 @@ static int ccgDM_getNumVerts(DerivedMesh *dm) {
return ccgSubSurf_getNumFinalVerts(ccgdm->ss);
}
+static int ccgDM_getNumEdges(DerivedMesh *dm) {
+ CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
+
+ return ccgSubSurf_getNumFinalEdges(ccgdm->ss);
+}
static int ccgDM_getNumFaces(DerivedMesh *dm) {
CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
return ccgSubSurf_getNumFinalFaces(ccgdm->ss);
}
+
+static void ccgDM_getFinalVert(DerivedMesh *dm, int vertNum, MVert *mv)
+{
+ CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
+ CCGSubSurf *ss = ccgdm->ss;
+ int i;
+
+ memset(mv, 0, sizeof(*mv));
+
+ if(vertNum < ccgdm->edgeMap[0].startVert) {
+ /* this vert comes from face data */
+ int lastface = ccgSubSurf_getNumFaces(ss) - 1;
+ CCGFace *f;
+ int x, y, grid, numVerts;
+ int offset;
+ int gridSize = ccgSubSurf_getGridSize(ss);
+ int gridSideVerts;
+ int gridInternalVerts;
+ int gridSideEnd;
+ int gridInternalEnd;
+
+ i = 0;
+ while(i < lastface && vertNum >= ccgdm->faceMap[i + 1].startVert)
+ ++i;
+
+ f = ccgdm->faceMap[i].face;
+ numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
+
+ gridSideVerts = gridSize - 2;
+ gridInternalVerts = gridSideVerts * gridSideVerts;
+
+ gridSideEnd = 1 + numVerts * gridSideVerts;
+ gridInternalEnd = gridSideEnd + numVerts * gridInternalVerts;
+
+ offset = vertNum - ccgdm->faceMap[i].startVert;
+ if(offset < 1) {
+ VecCopyf(mv->co, ccgSubSurf_getFaceCenterData(ss, f));
+ } else if(offset < gridSideEnd) {
+ offset -= 1;
+ grid = offset / gridSideVerts;
+ x = offset % gridSideVerts + 1;
+ VecCopyf(mv->co, ccgSubSurf_getFaceGridEdgeData(ss, f, grid, x));
+ } else if(offset < gridInternalEnd) {
+ offset -= gridSideEnd;
+ grid = offset / gridInternalVerts;
+ offset %= gridInternalVerts;
+ y = offset / gridSideVerts + 1;
+ x = offset % gridSideVerts + 1;
+ VecCopyf(mv->co, ccgSubSurf_getFaceGridData(ss, f, grid, x, y));
+ }
+ } else if(vertNum < ccgdm->vertMap[0].startVert) {
+ /* this vert comes from edge data */
+ CCGEdge *e;
+ int lastedge = ccgSubSurf_getNumEdges(ss) - 1;
+ int x;
+
+ i = 0;
+ while(i < lastedge && vertNum >= ccgdm->edgeMap[i + 1].startVert)
+ ++i;
+
+ e = ccgdm->edgeMap[i].edge;
+
+ x = vertNum - ccgdm->edgeMap[i].startVert + 1;
+ VecCopyf(mv->co, ccgSubSurf_getEdgeData(ss, e, x));
+ } else {
+ /* this vert comes from vert data */
+ CCGVert *v;
+ i = vertNum - ccgdm->vertMap[0].startVert;
+
+ v = ccgdm->vertMap[i].vert;
+ VecCopyf(mv->co, ccgSubSurf_getVertData(ss, v));
+ }
+}
+
+static void ccgDM_getFinalEdge(DerivedMesh *dm, int edgeNum, MEdge *med)
+{
+ CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
+ CCGSubSurf *ss = ccgdm->ss;
+ int i;
+
+ memset(med, 0, sizeof(*med));
+
+ if(edgeNum < ccgdm->edgeMap[0].startEdge) {
+ /* this edge comes from face data */
+ int lastface = ccgSubSurf_getNumFaces(ss) - 1;
+ CCGFace *f;
+ int x, y, grid, numVerts;
+ int offset;
+ int gridSize = ccgSubSurf_getGridSize(ss);
+ int edgeSize = ccgSubSurf_getEdgeSize(ss);
+ int gridSideEdges;
+ int gridInternalEdges;
+
+ i = 0;
+ while(i < lastface && edgeNum >= ccgdm->faceMap[i + 1].startEdge)
+ ++i;
+
+ f = ccgdm->faceMap[i].face;
+ numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
+
+ gridSideEdges = gridSize - 1;
+ gridInternalEdges = (gridSideEdges - 1) * gridSideEdges * 2;
+
+ offset = edgeNum - ccgdm->faceMap[i].startEdge;
+ grid = offset / (gridSideEdges + gridInternalEdges);
+ offset %= (gridSideEdges + gridInternalEdges);
+
+ if(offset < gridSideEdges) {
+ x = offset;
+ med->v1 = getFaceIndex(ss, f, grid, x, 0, edgeSize, gridSize);
+ med->v2 = getFaceIndex(ss, f, grid, x+1, 0, edgeSize, gridSize);
+ } else {
+ offset -= gridSideEdges;
+ x = (offset / 2) / gridSideEdges + 1;
+ y = (offset / 2) % gridSideEdges;
+ if(offset % 2 == 0) {
+ med->v1 = getFaceIndex(ss, f, grid, x, y, edgeSize, gridSize);
+ med->v2 = getFaceIndex(ss, f, grid, x, y+1, edgeSize, gridSize);
+ } else {
+ med->v1 = getFaceIndex(ss, f, grid, y, x, edgeSize, gridSize);
+ med->v2 = getFaceIndex(ss, f, grid, y+1, x, edgeSize, gridSize);
+ }
+ }
+ } else {
+ /* this vert comes from edge data */
+ CCGEdge *e;
+ int edgeSize = ccgSubSurf_getEdgeSize(ss);
+ int x;
+ unsigned int flags = 0;
+
+ i = (edgeNum - ccgdm->edgeMap[0].startEdge) / (edgeSize - 1);
+
+ e = ccgdm->edgeMap[i].edge;
+
+ if(!ccgSubSurf_getEdgeNumFaces(ss, e)) flags |= ME_LOOSEEDGE;
+
+ x = edgeNum - ccgdm->edgeMap[i].startEdge;
+
+ med->v1 = getEdgeIndex(ss, e, x, edgeSize);
+ med->v2 = getEdgeIndex(ss, e, x+1, edgeSize);
+
+ if(ccgdm->fromEditmesh) {
+ EditEdge *eed = ccgSubSurf_getEdgeEdgeHandle(ss, e);
+
+ flags |= ME_EDGEDRAW | ME_EDGERENDER;
+ if(eed->seam) {
+ flags |= ME_SEAM;
+ }
+ if(eed->sharp) flags |= ME_SHARP;
+ } else if(ccgdm->dlm || ccgdm->me) {
+ int edgeIdx = (int) ccgSubSurf_getEdgeEdgeHandle(ss, e);
+
+ if(edgeIdx!=-1) {
+ MEdge *medge = (ccgdm->dlm ? ccgdm->dlm->medge
+ : ccgdm->me->medge);
+ MEdge *origMed = &medge[edgeIdx];
+
+ if(ccgdm->dlm) {
+ flags |= origMed->flag;
+ } else {
+ flags |= (origMed->flag & (ME_SEAM | ME_SHARP))
+ | ME_EDGEDRAW | ME_EDGERENDER;
+ }
+ }
+ } else {
+ flags |= ME_EDGEDRAW | ME_EDGERENDER;
+ }
+
+ med->flag = flags;
+ }
+}
+
+static void ccgDM_getFinalFace(DerivedMesh *dm, int faceNum, MFace *mf)
+{
+ CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
+ CCGSubSurf *ss = ccgdm->ss;
+ int gridSize = ccgSubSurf_getGridSize(ss);
+ int edgeSize = ccgSubSurf_getEdgeSize(ss);
+ int gridSideEdges = gridSize - 1;
+ int gridFaces = gridSideEdges * gridSideEdges;
+ int i;
+ CCGFace *f;
+ int numVerts;
+ int offset;
+ int grid;
+ int x, y;
+ int lastface = ccgSubSurf_getNumFaces(ss) - 1;
+ int *faceFlags = dm->getFaceData(dm, faceNum, LAYERTYPE_FLAGS);
+
+ memset(mf, 0, sizeof(*mf));
+
+ i = 0;
+ while(i < lastface && faceNum >= ccgdm->faceMap[i + 1].startFace)
+ ++i;
+
+ f = ccgdm->faceMap[i].face;
+ numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
+
+ offset = faceNum - ccgdm->faceMap[i].startFace;
+ grid = offset / gridFaces;
+ offset %= gridFaces;
+ y = offset / gridSideEdges;
+ x = offset % gridSideEdges;
+
+ mf->v1 = getFaceIndex(ss, f, grid, x+0, y+0, edgeSize, gridSize);
+ mf->v2 = getFaceIndex(ss, f, grid, x+0, y+1, edgeSize, gridSize);
+ mf->v3 = getFaceIndex(ss, f, grid, x+1, y+1, edgeSize, gridSize);
+ mf->v4 = getFaceIndex(ss, f, grid, x+1, y+0, edgeSize, gridSize);
+
+ if(faceFlags) mf->flag = *faceFlags;
+ else mf->flag = ME_SMOOTH;
+}
+
+static void ccgDM_getFinalVertArray(DerivedMesh *dm, MVert *mvert)
+{
+ CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
+ CCGSubSurf *ss = ccgdm->ss;
+ int index;
+ int totvert, totedge, totface;
+ int gridSize = ccgSubSurf_getGridSize(ss);
+ int edgeSize = ccgSubSurf_getEdgeSize(ss);
+ int i = 0;
+
+ totface = ccgSubSurf_getNumFaces(ss);
+ for(index = 0; index < totface; index++) {
+ CCGFace *f = ccgdm->faceMap[index].face;
+ int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
+
+ VecCopyf(mvert[i++].co, ccgSubSurf_getFaceCenterData(ss, f));
+
+ for(S = 0; S < numVerts; S++) {
+ for(x = 1; x < gridSize - 1; x++) {
+ VecCopyf(mvert[i++].co,
+ ccgSubSurf_getFaceGridEdgeData(ss, f, S, x));
+ }
+ }
+
+ for(S = 0; S < numVerts; S++) {
+ for(y = 1; y < gridSize - 1; y++) {
+ for(x = 1; x < gridSize - 1; x++) {
+ VecCopyf(mvert[i++].co,
+ ccgSubSurf_getFaceGridData(ss, f, S, x, y));
+ }
+ }
+ }
+ }
+
+ totedge = ccgSubSurf_getNumEdges(ss);
+ for(index = 0; index < totedge; index++) {
+ CCGEdge *e = ccgdm->edgeMap[index].edge;
+ int x;
+
+ for(x = 1; x < edgeSize - 1; x++) {
+ VecCopyf(mvert[i++].co, ccgSubSurf_getEdgeData(ss, e, x));
+ }
+ }
+
+ totvert = ccgSubSurf_getNumVerts(ss);
+ for(index = 0; index < totvert; index++) {
+ CCGVert *v = ccgdm->vertMap[index].vert;
+
+ VecCopyf(mvert[i].co, ccgSubSurf_getVertData(ss, v));
+
+ i++;
+ }
+}
+
+static void ccgDM_getFinalEdgeArray(DerivedMesh *dm, MEdge *medge)
+{
+ CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
+ CCGSubSurf *ss = ccgdm->ss;
+ int index;
+ int totedge, totface;
+ int gridSize = ccgSubSurf_getGridSize(ss);
+ int edgeSize = ccgSubSurf_getEdgeSize(ss);
+ int i = 0;
+ MEdge *origEdges = NULL;
+
+ if(!ccgdm->fromEditmesh) {
+ if(ccgdm->dlm) origEdges = ccgdm->dlm->medge;
+ else if(ccgdm->me) origEdges = ccgdm->me->medge;
+ }
+
+ totface = ccgSubSurf_getNumFaces(ss);
+ for(index = 0; index < totface; index++) {
+ CCGFace *f = ccgdm->faceMap[index].face;
+ int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
+
+ for(S = 0; S < numVerts; S++) {
+ for(x = 0; x < gridSize - 1; x++) {
+ MEdge *med = &medge[i];
+
+ if(ccgdm->drawInteriorEdges)
+ med->flag = ME_EDGEDRAW | ME_EDGERENDER;
+ med->v1 = getFaceIndex(ss, f, S, x, 0, edgeSize, gridSize);
+ med->v2 = getFaceIndex(ss, f, S, x + 1, 0, edgeSize, gridSize);
+ i++;
+ }
+
+ for(x = 1; x < gridSize - 1; x++) {
+ for(y = 0; y < gridSize - 1; y++) {
+ MEdge *med;
+
+ med = &medge[i];
+ if(ccgdm->drawInteriorEdges)
+ med->flag = ME_EDGEDRAW | ME_EDGERENDER;
+ med->v1 = getFaceIndex(ss, f, S, x, y,
+ edgeSize, gridSize);
+ med->v2 = getFaceIndex(ss, f, S, x, y + 1,
+ edgeSize, gridSize);
+ i++;
+
+ med = &medge[i];
+ if(ccgdm->drawInteriorEdges)
+ med->flag = ME_EDGEDRAW | ME_EDGERENDER;
+ med->v1 = getFaceIndex(ss, f, S, y, x,
+ edgeSize, gridSize);
+ med->v2 = getFaceIndex(ss, f, S, y + 1, x,
+ edgeSize, gridSize);
+ i++;
+ }
+ }
+ }
+ }
+
+ totedge = ccgSubSurf_getNumEdges(ss);
+ for(index = 0; index < totedge; index++) {
+ CCGEdge *e = ccgdm->edgeMap[index].edge;
+ unsigned int flags = 0;
+ int x;
+
+ if(!ccgSubSurf_getEdgeNumFaces(ss, e)) flags |= ME_LOOSEEDGE;
+
+ if(ccgdm->fromEditmesh) {
+ EditEdge *eed = ccgSubSurf_getEdgeEdgeHandle(ss, e);
+
+ flags |= ME_EDGEDRAW | ME_EDGERENDER;
+ if (eed->seam) {
+ flags |= ME_SEAM;
+ }
+ if(eed->sharp) flags |= ME_SHARP;
+ } else if(origEdges){
+ int edgeIdx = (int)ccgSubSurf_getEdgeEdgeHandle(ss, e);
+
+ if(edgeIdx != -1) {
+ MEdge *origMed = &origEdges[edgeIdx];
+
+ if(ccgdm->dlm) {
+ flags |= origMed->flag;
+ } else {
+ flags |= (origMed->flag & (ME_SEAM | ME_SHARP))
+ | ME_EDGEDRAW | ME_EDGERENDER;
+ }
+ }
+ } else {
+ flags |= ME_EDGEDRAW | ME_EDGERENDER;
+ }
+
+ for(x = 0; x < edgeSize - 1; x++) {
+ MEdge *med = &medge[i];
+ med->v1 = getEdgeIndex(ss, e, x, edgeSize);
+ med->v2 = getEdgeIndex(ss, e, x + 1, edgeSize);
+ med->flag = flags;
+ i++;
+ }
+ }
+}
+
+static void ccgDM_getFinalFaceArray(DerivedMesh *dm, MFace *mface)
+{
+ CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
+ CCGSubSurf *ss = ccgdm->ss;
+ int index;
+ int totface;
+ int gridSize = ccgSubSurf_getGridSize(ss);
+ int edgeSize = ccgSubSurf_getEdgeSize(ss);
+ int i = 0;
+ MFace *origFaces = NULL;
+ int *faceFlags = dm->getFaceDataArray(dm, LAYERTYPE_FLAGS);
+
+ if(!ccgdm->fromEditmesh) {
+ if(ccgdm->dlm) origFaces = ccgdm->dlm->mface;
+ else if(ccgdm->me) origFaces = ccgdm->me->mface;
+ }
+
+ totface = ccgSubSurf_getNumFaces(ss);
+ for(index = 0; index < totface; index++) {
+ CCGFace *f = ccgdm->faceMap[index].face;
+ int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
+ int mat_nr = 0;
+ int flag = ME_SMOOTH; /* assume face is smooth by default */
+
+ if(!faceFlags) {
+ if(!ccgdm->fromEditmesh && origFaces) {
+ int origIdx = (int) ccgSubSurf_getFaceFaceHandle(ss, f);
+ MFace *origMFace = &origFaces[origIdx];
+
+ mat_nr = origMFace->mat_nr;
+ flag = origMFace->flag;
+ } else if(ccgdm->fromEditmesh) {
+ EditFace *ef = ccgSubSurf_getFaceFaceHandle(ss, f);
+ mat_nr = ef->mat_nr;
+ flag = ef->flag;
+ }
+ }
+
+ for(S = 0; S < numVerts; S++) {
+ for(y = 0; y < gridSize - 1; y++) {
+ for(x = 0; x < gridSize - 1; x++) {
+ MFace *mf = &mface[i];
+ mf->v1 = getFaceIndex(ss, f, S, x + 0, y + 0,
+ edgeSize, gridSize);
+ mf->v2 = getFaceIndex(ss, f, S, x + 0, y + 1,
+ edgeSize, gridSize);
+ mf->v3 = getFaceIndex(ss, f, S, x + 1, y + 1,
+ edgeSize, gridSize);
+ mf->v4 = getFaceIndex(ss, f, S, x + 1, y + 0,
+ edgeSize, gridSize);
+ mf->mat_nr = mat_nr;
+ if(faceFlags) mf->flag = faceFlags[i];
+ else mf->flag = flag;
+
+ i++;
+ }
+ }
+ }
+ }
+}
+
static void ccgdm_getVertCos(DerivedMesh *dm, float (*cos)[3]) {
CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
CCGSubSurf *ss = ccgdm->ss;
@@ -1509,11 +2495,21 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *u
CCGSubSurf *ss = ccgdm->ss;
CCGFaceIterator *fi = ccgSubSurf_getFaceIterator(ss);
int i, gridSize = ccgSubSurf_getGridSize(ss);
+ int *faceFlags = dm->getFaceDataArray(dm, LAYERTYPE_FLAGS);
for (i=0; !ccgFaceIterator_isStopped(fi); i++,ccgFaceIterator_next(fi)) {
CCGFace *f = ccgFaceIterator_getCurrent(fi);
int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
- int drawSmooth = 1, index = ccgDM_getFaceMapIndex(ccgdm, ss, f);
+ int drawSmooth, index = ccgDM_getFaceMapIndex(ccgdm, ss, f);
+ int origIndex;
+
+ if(ccgdm->fromEditmesh) {
+ origIndex = index;
+ } else {
+ origIndex = (int)ccgSubSurf_getFaceFaceHandle(ss, f);
+ }
+ if(faceFlags) drawSmooth = (*faceFlags & ME_SMOOTH);
+ else drawSmooth = 1;
if (index!=-1 && (!setDrawOptions || setDrawOptions(userData, index, &drawSmooth))) {
for (S=0; S<numVerts; S++) {
@@ -1649,17 +2645,79 @@ static void ccgDM_foreachMappedFaceCenter(DerivedMesh *dm, void (*func)(void *us
static void ccgDM_release(DerivedMesh *dm) {
CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
+ DM_release(dm);
+
if (ccgdm->dlm) displistmesh_free(ccgdm->dlm);
+ MEM_freeN(ccgdm->vertMap);
+ MEM_freeN(ccgdm->edgeMap);
+ MEM_freeN(ccgdm->faceMap);
MEM_freeN(ccgdm);
}
-static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, int fromEditmesh, int drawInteriorEdges, int useSubsurfUv, Mesh *me, DispListMesh *dlm) {
+static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, int fromEditmesh,
+ int drawInteriorEdges,
+ int useSubsurfUv, Mesh *me,
+ DispListMesh *dlm, DerivedMesh *dm)
+{
CCGDerivedMesh *ccgdm = MEM_callocN(sizeof(*ccgdm), "ccgdm");
+ CCGVertIterator *vi;
+ CCGEdgeIterator *ei;
+ CCGFaceIterator *fi;
+ int index, totvert, totedge, totface;
+ int i;
+ int vertNum, edgeNum, faceNum;
+ int *vertOrigIndex, *edgeOrigIndex, *faceOrigIndex;
+ int *faceFlags;
+ int edgeSize;
+ int gridSize;
+ int gridFaces;
+ int gridSideVerts;
+ int gridInternalVerts;
+ int gridSideEdges;
+ int gridInternalEdges;
+ MVert *mvert = NULL;
+ MEdge *medge = NULL;
+ MFace *mface = NULL;
+ TFace *tface;
+ CCGSubSurf *uvss = NULL;
+ CCGFace **faceMap2Uv = NULL;
+ FaceVertWeight *qweight, *tweight;
+
+ if(dm) {
+ DM_from_template(&ccgdm->dm, dm, ccgSubSurf_getNumFinalVerts(ss),
+ ccgSubSurf_getNumFinalEdges(ss),
+ ccgSubSurf_getNumFinalFaces(ss));
+ tface = dm->getFaceDataArray(dm, LAYERTYPE_TFACE);
+ DM_add_face_layer(&ccgdm->dm, LAYERTYPE_FLAGS, LAYERFLAG_NOCOPY, NULL);
+ } else {
+ DM_init(&ccgdm->dm, ccgSubSurf_getNumFinalVerts(ss),
+ ccgSubSurf_getNumFinalEdges(ss),
+ ccgSubSurf_getNumFinalFaces(ss));
+
+ if(dlm) tface = dlm->tface;
+ else if(me) tface = me->tface;
+ else tface = NULL;
+ }
ccgdm->dm.getMinMax = ccgDM_getMinMax;
ccgdm->dm.getNumVerts = ccgDM_getNumVerts;
ccgdm->dm.getNumFaces = ccgDM_getNumFaces;
+
+ ccgdm->dm.getNumEdges = ccgDM_getNumEdges;
+ ccgdm->dm.getVert = ccgDM_getFinalVert;
+ ccgdm->dm.getEdge = ccgDM_getFinalEdge;
+ ccgdm->dm.getFace = ccgDM_getFinalFace;
+ ccgdm->dm.getVertArray = ccgDM_getFinalVertArray;
+ ccgdm->dm.getEdgeArray = ccgDM_getFinalEdgeArray;
+ ccgdm->dm.getFaceArray = ccgDM_getFinalFaceArray;
+ ccgdm->dm.getVertData = DM_get_vert_data;
+ ccgdm->dm.getEdgeData = DM_get_edge_data;
+ ccgdm->dm.getFaceData = DM_get_face_data;
+ ccgdm->dm.getVertDataArray = DM_get_vert_data_layer;
+ ccgdm->dm.getEdgeDataArray = DM_get_edge_data_layer;
+ ccgdm->dm.getFaceDataArray = DM_get_face_data_layer;
+
ccgdm->dm.getVertCos = ccgdm_getVertCos;
ccgdm->dm.foreachMappedVert = ccgDM_foreachMappedVert;
ccgdm->dm.foreachMappedEdge = ccgDM_foreachMappedEdge;
@@ -1687,6 +2745,323 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, int fromEditmesh, int d
ccgdm->me = me;
ccgdm->dlm = dlm;
+ totvert = ccgSubSurf_getNumVerts(ss);
+ ccgdm->vertMap = MEM_mallocN(totvert * sizeof(*ccgdm->vertMap), "vertMap");
+ vi = ccgSubSurf_getVertIterator(ss);
+ for(; !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) {
+ CCGVert *v = ccgVertIterator_getCurrent(vi);
+
+ if(fromEditmesh) {
+ ccgdm->vertMap[ccgDM_getVertMapIndex(ccgdm, ss, v)].vert = v;
+ } else {
+ ccgdm->vertMap[(int) ccgSubSurf_getVertVertHandle(ss, v)].vert = v;
+ }
+ }
+ ccgVertIterator_free(vi);
+
+ totedge = ccgSubSurf_getNumEdges(ss);
+ ccgdm->edgeMap = MEM_mallocN(totedge * sizeof(*ccgdm->edgeMap), "edgeMap");
+ ei = ccgSubSurf_getEdgeIterator(ss);
+ for(; !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) {
+ CCGEdge *e = ccgEdgeIterator_getCurrent(ei);
+
+ if(fromEditmesh) {
+ ccgdm->edgeMap[ccgDM_getEdgeMapIndex(ccgdm,ss,e)].edge = e;
+ } else {
+ ccgdm->edgeMap[(int) ccgSubSurf_getEdgeEdgeHandle(ss, e)].edge = e;
+ }
+ }
+
+ totface = ccgSubSurf_getNumFaces(ss);
+ ccgdm->faceMap = MEM_mallocN(totface * sizeof(*ccgdm->faceMap), "faceMap");
+ fi = ccgSubSurf_getFaceIterator(ss);
+ for(; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
+ CCGFace *f = ccgFaceIterator_getCurrent(fi);
+
+ if(fromEditmesh) {
+ ccgdm->faceMap[ccgDM_getFaceMapIndex(ccgdm,ss,f)].face = f;
+ } else {
+ ccgdm->faceMap[(int) ccgSubSurf_getFaceFaceHandle(ss, f)].face = f;
+ }
+ }
+ ccgFaceIterator_free(fi);
+
+ if(useSubsurfUv && tface) {
+ /* slightly dodgy hack to use current ss_sync_from_uv function */
+ DispListMesh dlm;
+
+ dlm.mface = dm->dupFaceArray(dm);
+ dlm.tface = tface;
+ dlm.mvert = dm->dupVertArray(dm);
+ dlm.totvert = dm->getNumVerts(dm);
+ dlm.totface = dm->getNumFaces(dm);
+
+ /* not for editmesh currently */
+ uvss = _getSubSurf(NULL, ccgSubSurf_getSubdivisionLevels(ss),
+ 0, 1, 0);
+
+ if(ss_sync_from_uv(uvss, ss, NULL, &dlm)) {
+ faceMap2Uv = MEM_mallocN(totface * sizeof(*faceMap2Uv),
+ "facemapuv");
+
+ fi = ccgSubSurf_getFaceIterator(uvss);
+ for(; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
+ CCGFace *f = ccgFaceIterator_getCurrent(fi);
+ faceMap2Uv[(int) ccgSubSurf_getFaceFaceHandle(uvss, f)] = f;
+ }
+ ccgFaceIterator_free(fi);
+ }
+
+ MEM_freeN(dlm.mface);
+ MEM_freeN(dlm.mvert);
+ }
+
+ edgeSize = ccgSubSurf_getEdgeSize(ss);
+ gridSize = ccgSubSurf_getGridSize(ss);
+ gridFaces = gridSize - 1;
+ gridSideVerts = gridSize - 2;
+ gridInternalVerts = gridSideVerts * gridSideVerts;
+ gridSideEdges = gridSize - 1;
+ gridInternalEdges = (gridSideEdges - 1) * gridSideEdges * 2;
+
+ calc_ss_weights(gridFaces, &qweight, &tweight);
+
+ vertNum = 0;
+ edgeNum = 0;
+ faceNum = 0;
+
+ if(dm) {
+ mvert = dm->dupVertArray(dm);
+ medge = dm->dupEdgeArray(dm);
+ mface = dm->dupFaceArray(dm);
+ } else if(dlm) {
+ mvert = dlm->mvert;
+ medge = dlm->medge;
+ mface = dlm->mface;
+ } else if(me) {
+ mvert = me->mvert;
+ medge = me->medge;
+ mface = me->mface;
+ }
+
+ vertOrigIndex = DM_get_vert_data_layer(&ccgdm->dm, LAYERTYPE_ORIGINDEX);
+ edgeOrigIndex = DM_get_edge_data_layer(&ccgdm->dm, LAYERTYPE_ORIGINDEX);
+ faceOrigIndex = DM_get_face_data_layer(&ccgdm->dm, LAYERTYPE_ORIGINDEX);
+
+ faceFlags = DM_get_face_data_layer(&ccgdm->dm, LAYERTYPE_FLAGS);
+
+ for(index = 0; index < totface; ++index) {
+ CCGFace *f = ccgdm->faceMap[index].face;
+ CCGFace *uvf = faceMap2Uv ? faceMap2Uv[index] : NULL;
+ int numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
+ int numFinalEdges = numVerts * (gridSideEdges + gridInternalEdges);
+ int mapIndex = ccgDM_getFaceMapIndex(ccgdm, ss, f);
+ int origIndex = (int)ccgSubSurf_getFaceFaceHandle(ss, f);
+ FaceVertWeight *weight = (numVerts == 4) ? qweight : tweight;
+ int S, x, y;
+ int vertIdx[4];
+
+ ccgdm->faceMap[index].startVert = vertNum;
+ ccgdm->faceMap[index].startEdge = edgeNum;
+ ccgdm->faceMap[index].startFace = faceNum;
+
+ /* set the face base vert */
+ *((int*)ccgSubSurf_getFaceUserData(ss, f)) = vertNum;
+
+ for(S = 0; S < numVerts; S++) {
+ CCGVert *v = ccgSubSurf_getFaceVert(ss, f, S);
+
+ if(fromEditmesh)
+ vertIdx[S] = ccgDM_getVertMapIndex(NULL, ss, v);
+ else
+ vertIdx[S] = (int)ccgSubSurf_getVertVertHandle(ss, v);
+ }
+
+ DM_interp_vert_data(dm, &ccgdm->dm, vertIdx, weight[0][0],
+ numVerts, vertNum);
+ *vertOrigIndex = ORIGINDEX_NONE;
+ ++vertOrigIndex;
+ ++vertNum;
+
+ for(S = 0; S < numVerts; S++) {
+ int prevS = (S - 1 + numVerts) % numVerts;
+ int nextS = (S + 1) % numVerts;
+ int otherS = (numVerts == 4) ? (S + 2) % numVerts : 3;
+ for(x = 1; x < gridFaces; x++) {
+ float w[4];
+ w[prevS] = weight[x][0][0];
+ w[S] = weight[x][0][1];
+ w[nextS] = weight[x][0][2];
+ w[otherS] = weight[x][0][3];
+ DM_interp_vert_data(dm, &ccgdm->dm, vertIdx, w,
+ numVerts, vertNum);
+ *vertOrigIndex = ORIGINDEX_NONE;
+ ++vertOrigIndex;
+ ++vertNum;
+ }
+ }
+
+ for(S = 0; S < numVerts; S++) {
+ int prevS = (S - 1 + numVerts) % numVerts;
+ int nextS = (S + 1) % numVerts;
+ int otherS = (numVerts == 4) ? (S + 2) % numVerts : 3;
+ for(y = 1; y < gridFaces; y++) {
+ for(x = 1; x < gridFaces; x++) {
+ float w[4];
+ w[prevS] = weight[y * gridFaces + x][0][0];
+ w[S] = weight[y * gridFaces + x][0][1];
+ w[nextS] = weight[y * gridFaces + x][0][2];
+ w[otherS] = weight[y * gridFaces + x][0][3];
+ DM_interp_vert_data(dm, &ccgdm->dm, vertIdx, w,
+ numVerts, vertNum);
+ *vertOrigIndex = ORIGINDEX_NONE;
+ ++vertOrigIndex;
+ ++vertNum;
+ }
+ }
+ }
+
+ for(i = 0; i < numFinalEdges; ++i)
+ *(int *)DM_get_edge_data(&ccgdm->dm, edgeNum + i,
+ LAYERTYPE_ORIGINDEX) = ORIGINDEX_NONE;
+
+ for(S = 0; S < numVerts; S++) {
+ int prevS = (S - 1 + numVerts) % numVerts;
+ int nextS = (S + 1) % numVerts;
+ int otherS = (numVerts == 4) ? (S + 2) % numVerts : 3;
+
+ weight = (numVerts == 4) ? qweight : tweight;
+
+ for(y = 0; y < gridFaces; y++) {
+ for(x = 0; x < gridFaces; x++) {
+ FaceVertWeight w;
+ int j;
+
+ for(j = 0; j < 4; ++j) {
+ w[j][prevS] = (*weight)[j][0];
+ w[j][S] = (*weight)[j][1];
+ w[j][nextS] = (*weight)[j][2];
+ w[j][otherS] = (*weight)[j][3];
+ }
+
+ DM_interp_face_data(dm, &ccgdm->dm, &origIndex, NULL,
+ &w, 1, faceNum);
+ weight++;
+
+ if(uvf) {
+ TFace *tf = DM_get_face_data(&ccgdm->dm, faceNum,
+ LAYERTYPE_TFACE);
+ float *newuv;
+
+ newuv = getFaceUV(uvss, uvf, S, x + 0, y + 0,
+ edgeSize, gridSize);
+ tf->uv[0][0] = newuv[0]; tf->uv[0][1] = newuv[1];
+ newuv = getFaceUV(uvss, uvf, S, x + 0, y + 1,
+ edgeSize, gridSize);
+ tf->uv[1][0] = newuv[0]; tf->uv[1][1] = newuv[1];
+ newuv = getFaceUV(uvss, uvf, S, x + 1, y + 1,
+ edgeSize, gridSize);
+ tf->uv[2][0] = newuv[0]; tf->uv[2][1] = newuv[1];
+ newuv = getFaceUV(uvss, uvf, S, x + 1, y + 0,
+ edgeSize, gridSize);
+ tf->uv[3][0] = newuv[0]; tf->uv[3][1] = newuv[1];
+ }
+
+ *faceOrigIndex = mapIndex;
+ if(mface)
+ *faceFlags = mface[origIndex].flag;
+ else
+ *faceFlags = ME_SMOOTH;
+
+ ++faceOrigIndex;
+ ++faceFlags;
+ ++faceNum;
+ }
+ }
+ }
+
+ edgeNum += numFinalEdges;
+ }
+
+ if(uvss) {
+ ccgSubSurf_free(uvss);
+ MEM_freeN(faceMap2Uv);
+ }
+
+ for(index = 0; index < totedge; ++index) {
+ CCGEdge *e = ccgdm->edgeMap[index].edge;
+ int numFinalEdges = edgeSize - 1;
+ int mapIndex = ccgDM_getEdgeMapIndex(ccgdm, ss, e);
+ int x;
+ int vertIdx[2];
+
+ if(fromEditmesh) {
+ CCGVert *v;
+ v = ccgSubSurf_getEdgeVert0(ss, e);
+ vertIdx[0] = ccgDM_getVertMapIndex(NULL, ss, v);
+ v = ccgSubSurf_getEdgeVert1(ss, e);
+ vertIdx[1] = ccgDM_getVertMapIndex(NULL, ss, v);
+ } else {
+ CCGVert *v;
+ v = ccgSubSurf_getEdgeVert0(ss, e);
+ vertIdx[0] = (int)ccgSubSurf_getVertVertHandle(ss, v);
+ v = ccgSubSurf_getEdgeVert1(ss, e);
+ vertIdx[1] = (int)ccgSubSurf_getVertVertHandle(ss, v);
+ }
+
+ ccgdm->edgeMap[index].startVert = vertNum;
+ ccgdm->edgeMap[index].startEdge = edgeNum;
+
+ /* set the edge base vert */
+ *((int*)ccgSubSurf_getEdgeUserData(ss, e)) = vertNum;
+
+ for(x = 1; x < edgeSize - 1; x++) {
+ float w[2];
+ w[1] = (float) x / (edgeSize - 1);
+ w[0] = 1 - w[1];
+ DM_interp_vert_data(dm, &ccgdm->dm, vertIdx, w, 2, vertNum);
+ *vertOrigIndex = ORIGINDEX_NONE;
+ ++vertOrigIndex;
+ ++vertNum;
+ }
+
+ for(i = 0; i < numFinalEdges; ++i)
+ *(int *)DM_get_edge_data(&ccgdm->dm, edgeNum + i,
+ LAYERTYPE_ORIGINDEX) = mapIndex;
+
+ edgeNum += numFinalEdges;
+ }
+
+ for(index = 0; index < totvert; ++index) {
+ CCGVert *v = ccgdm->vertMap[index].vert;
+ int mapIndex = ccgDM_getVertMapIndex(ccgdm, ccgdm->ss, v);
+ int vertIdx;
+
+ if(fromEditmesh)
+ vertIdx = ccgDM_getVertMapIndex(NULL, ss, v);
+ else
+ vertIdx = (int)ccgSubSurf_getVertVertHandle(ss, v);
+
+ ccgdm->vertMap[index].startVert = vertNum;
+
+ /* set the vert base vert */
+ *((int*) ccgSubSurf_getVertUserData(ss, v)) = vertNum;
+
+ DM_copy_vert_data(dm, &ccgdm->dm, vertIdx, vertNum, 1);
+ *vertOrigIndex = mapIndex;
+ ++vertOrigIndex;
+ ++vertNum;
+ }
+
+ if(dm) {
+ MEM_freeN(mvert);
+ MEM_freeN(medge);
+ MEM_freeN(mface);
+ }
+
+ MEM_freeN(qweight);
+ MEM_freeN(tweight);
+
return ccgdm;
}
@@ -1700,7 +3075,7 @@ DerivedMesh *subsurf_make_derived_from_editmesh(EditMesh *em, SubsurfModifierDat
smd->emCache = _getSubSurf(smd->emCache, smd->levels, useAging, 0, useSimple);
ss_sync_from_editmesh(smd->emCache, em, vertCos, useSimple);
- return (DerivedMesh*) getCCGDerivedMesh(smd->emCache, 1, drawInteriorEdges, 0, NULL, NULL);
+ return (DerivedMesh*) getCCGDerivedMesh(smd->emCache, 1, drawInteriorEdges, 0, NULL, NULL, NULL);
}
DerivedMesh *subsurf_make_derived_from_dlm_em(DispListMesh *dlm, SubsurfModifierData *smd, float (*vertCos)[3]) {
@@ -1713,7 +3088,7 @@ DerivedMesh *subsurf_make_derived_from_dlm_em(DispListMesh *dlm, SubsurfModifier
ss_sync_from_mesh(smd->emCache, NULL, dlm, vertCos, useSimple);
- return (DerivedMesh*) getCCGDerivedMesh(smd->emCache, 0, drawInteriorEdges, useSubsurfUv, NULL, dlm);
+ return (DerivedMesh*) getCCGDerivedMesh(smd->emCache, 0, drawInteriorEdges, useSubsurfUv, NULL, dlm, NULL);
}
DerivedMesh *subsurf_make_derived_from_mesh(Mesh *me, DispListMesh *dlm, SubsurfModifierData *smd, int useRenderParams, float (*vertCos)[3], int isFinalCalc) {
@@ -1757,7 +3132,7 @@ DerivedMesh *subsurf_make_derived_from_mesh(Mesh *me, DispListMesh *dlm, Subsurf
ss_sync_from_mesh(ss, me, dlm, vertCos, useSimple);
- return (DerivedMesh*) getCCGDerivedMesh(ss, 0, drawInteriorEdges, useSubsurfUv, me, dlm);
+ return (DerivedMesh*) getCCGDerivedMesh(ss, 0, drawInteriorEdges, useSubsurfUv, me, dlm, NULL);
} else {
if (smd->mCache && isFinalCalc) {
ccgSubSurf_free(smd->mCache);
@@ -1777,6 +3152,83 @@ DerivedMesh *subsurf_make_derived_from_mesh(Mesh *me, DispListMesh *dlm, Subsurf
}
}
+struct DerivedMesh *subsurf_make_derived_from_derived(
+ struct DerivedMesh *dm,
+ struct SubsurfModifierData *smd,
+ int useRenderParams, float (*vertCos)[3],
+ int isFinalCalc, int editMode)
+{
+ int useSimple = smd->subdivType == ME_SIMPLE_SUBSURF;
+ int useAging = smd->flags & eSubsurfModifierFlag_DebugIncr;
+ int useSubsurfUv = smd->flags & eSubsurfModifierFlag_SubsurfUv;
+ int drawInteriorEdges = !(smd->flags & eSubsurfModifierFlag_ControlEdges);
+ DerivedMesh *result;
+
+ if(editMode) {
+ smd->emCache = _getSubSurf(smd->emCache, smd->levels, useAging, 0,
+ useSimple);
+ ss_sync_from_derivedmesh(smd->emCache, dm, vertCos, useSimple);
+
+ return (DerivedMesh *)getCCGDerivedMesh(smd->emCache, 0,
+ drawInteriorEdges,
+ useSubsurfUv, NULL, NULL, dm);
+ } else if(useRenderParams) {
+ /* Do not use cache in render mode. */
+ CCGSubSurf *ss = _getSubSurf(NULL, smd->renderLevels, 0, 1, useSimple);
+
+ ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple);
+
+ result = ss_to_cdderivedmesh(ss, 0, drawInteriorEdges,
+ useSubsurfUv, dm);
+
+ ccgSubSurf_free(ss);
+
+ return result;
+ } else {
+ int useIncremental = (smd->flags & eSubsurfModifierFlag_Incremental);
+ int useAging = smd->flags & eSubsurfModifierFlag_DebugIncr;
+ CCGSubSurf *ss;
+
+ /* It is quite possible there is a much better place to do this. It
+ * depends a bit on how rigourously we expect this function to never
+ * be called in editmode. In semi-theory we could share a single
+ * cache, but the handles used inside and outside editmode are not
+ * the same so we would need some way of converting them. Its probably
+ * not worth the effort. But then why am I even writing this long
+ * comment that no one will read? Hmmm. - zr
+ */
+ if(smd->emCache) {
+ ccgSubSurf_free(smd->emCache);
+ smd->emCache = NULL;
+ }
+
+ if(useIncremental && isFinalCalc) {
+ smd->mCache = ss = _getSubSurf(smd->mCache, smd->levels,
+ useAging, 0, useSimple);
+
+ ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple);
+
+ return ss_to_cdderivedmesh(ss, 0, drawInteriorEdges,
+ useSubsurfUv, dm);
+ } else {
+ if (smd->mCache && isFinalCalc) {
+ ccgSubSurf_free(smd->mCache);
+ smd->mCache = NULL;
+ }
+
+ ss = _getSubSurf(NULL, smd->levels, 0, 1, useSimple);
+ ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple);
+
+ result = ss_to_cdderivedmesh(ss, 0, drawInteriorEdges,
+ useSubsurfUv, dm);
+
+ ccgSubSurf_free(ss);
+
+ return result;
+ }
+ }
+}
+
void subsurf_calculate_limit_positions(Mesh *me, float (*positions_r)[3])
{
/* Finds the subsurf limit positions for the verts in a mesh
diff --git a/source/blender/blenlib/BLI_editVert.h b/source/blender/blenlib/BLI_editVert.h
index 2c8df6efd43..7b3515c5135 100644
--- a/source/blender/blenlib/BLI_editVert.h
+++ b/source/blender/blenlib/BLI_editVert.h
@@ -38,6 +38,8 @@
#ifndef BLI_EDITVERT_H
#define BLI_EDITVERT_H
+#include "DNA_mesh_types.h"
+
struct DerivedMesh;
/* note; changing this also might affect the undo copy in editmesh.c */
@@ -97,7 +99,7 @@ typedef struct EditEdge
float fp;
} tmp;
short f1, f2; /* short, f1 is (ab)used in subdiv */
- unsigned char f, h, dir, seam;
+ unsigned char f, h, dir, seam, sharp;
float crease;
short fast; /* only 0 or 1, for editmesh_fastmalloc */
short fgoni; /* index for fgon, for search */
diff --git a/source/blender/blenlib/BLI_linklist.h b/source/blender/blenlib/BLI_linklist.h
index 2e75420a1ff..9982047ec9e 100644
--- a/source/blender/blenlib/BLI_linklist.h
+++ b/source/blender/blenlib/BLI_linklist.h
@@ -39,7 +39,7 @@
struct MemArena;
typedef void (*LinkNodeFreeFP)(void *link);
-typedef void (*LinkNodeApplyFP)(void *link);
+typedef void (*LinkNodeApplyFP)(void *link, void *userdata);
struct LinkNode;
typedef struct LinkNode {
@@ -56,7 +56,7 @@ void BLI_linklist_append (struct LinkNode **listp, void *ptr);
void BLI_linklist_prepend_arena (struct LinkNode **listp, void *ptr, struct MemArena *ma);
void BLI_linklist_free (struct LinkNode *list, LinkNodeFreeFP freefunc);
-void BLI_linklist_apply (struct LinkNode *list, LinkNodeApplyFP applyfunc);
+void BLI_linklist_apply (struct LinkNode *list, LinkNodeApplyFP applyfunc, void *userdata);
#endif
diff --git a/source/blender/blenlib/intern/BLI_linklist.c b/source/blender/blenlib/intern/BLI_linklist.c
index 253d127db38..6bb828a44bf 100644
--- a/source/blender/blenlib/intern/BLI_linklist.c
+++ b/source/blender/blenlib/intern/BLI_linklist.c
@@ -113,7 +113,7 @@ void BLI_linklist_free(LinkNode *list, LinkNodeFreeFP freefunc) {
}
}
-void BLI_linklist_apply(LinkNode *list, LinkNodeApplyFP applyfunc) {
+void BLI_linklist_apply(LinkNode *list, LinkNodeApplyFP applyfunc, void *userdata) {
for (; list; list= list->next)
- applyfunc(list->link);
+ applyfunc(list->link, userdata);
}
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 87125c2130f..6176d01e967 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -2290,15 +2290,16 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh)
/* ************ READ OBJECT ***************** */
-static void lib_link_modifiers__linkModifiers(void *userData, Object *ob, Object **obpoin)
+static void lib_link_modifiers__linkModifiers(void *userData, Object *ob,
+ ID **idpoin)
{
FileData *fd = userData;
- *obpoin = newlibadr(fd, ob->id.lib, *obpoin);
+ *idpoin = newlibadr(fd, ob->id.lib, *idpoin);
}
static void lib_link_modifiers(FileData *fd, Object *ob)
{
- modifiers_foreachObjectLink(ob, lib_link_modifiers__linkModifiers, fd);
+ modifiers_foreachIDLink(ob, lib_link_modifiers__linkModifiers, fd);
}
static void lib_link_object(FileData *fd, Main *main)
diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h
index 691696f1c80..34c3cc904f1 100644
--- a/source/blender/makesdna/DNA_meshdata_types.h
+++ b/source/blender/makesdna/DNA_meshdata_types.h
@@ -80,7 +80,6 @@ typedef struct MSelect {
#define ME_SPHERETEMP 4
#define ME_HIDE 16
#define ME_VERT_MERGED (1<<6)
-#define ME_VERT_STEPINDEX (1<<7)
/* medge->flag (1=SELECT)*/
#define ME_EDGEDRAW (1<<1)
@@ -90,7 +89,7 @@ typedef struct MSelect {
#define ME_EDGERENDER (1<<5)
#define ME_LOOSEEDGE (1<<7)
#define ME_SEAM_LAST (1<<8)
-#define ME_EDGE_STEPINDEX (1<<15)
+#define ME_SHARP (1<<9)
/* puno = vertexnormal (mface) */
#define ME_FLIPV1 1
@@ -112,7 +111,6 @@ typedef struct MSelect {
#define ME_SMOOTH 1
#define ME_FACE_SEL 2
/* flag ME_HIDE==16 is used here too */
-#define ME_FACE_STEPINDEX (1<<7)
#endif
/* mselect->type */
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index 24400996831..522d25c9d90 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -5,6 +5,8 @@
#ifndef DNA_MODIFIER_TYPES_H
#define DNA_MODIFIER_TYPES_H
+#define MODSTACK_DEBUG 1
+
/* WARNING ALERT! TYPEDEF VALUES ARE WRITTEN IN FILES! SO DO NOT CHANGE! */
typedef enum ModifierType {
@@ -21,14 +23,13 @@ typedef enum ModifierType {
eModifierType_Softbody,
eModifierType_Boolean,
eModifierType_Array,
+ eModifierType_EdgeSplit,
+ eModifierType_Displace,
+ eModifierType_UVProject,
NUM_MODIFIER_TYPES
} ModifierType;
- /* These numerical values are explicitly chosen so that
- * (mode&1) is true for realtime calc and (mode&2) is true
- * for render calc.
- */
typedef enum ModifierMode {
eModifierMode_Realtime = (1<<0),
eModifierMode_Render = (1<<1),
@@ -147,6 +148,60 @@ typedef struct MirrorModifierData {
/* MirrorModifierData->flag */
#define MOD_MIR_CLIPPING 1
+typedef struct EdgeSplitModifierData {
+ ModifierData modifier;
+
+ float split_angle; /* angle above which edges should be split */
+ int flags;
+} EdgeSplitModifierData;
+
+/* EdgeSplitModifierData->flags */
+#define MOD_EDGESPLIT_FROMANGLE 1<<1
+#define MOD_EDGESPLIT_FROMFLAG 1<<2
+
+typedef struct DisplaceModifierData {
+ ModifierData modifier;
+
+ struct Tex *texture;
+ float strength;
+ int direction;
+ char defgrp_name[32];
+ float midlevel;
+ int texmapping;
+ struct Object *map_object;
+} DisplaceModifierData;
+
+/* DisplaceModifierData->direction */
+enum {
+ MOD_DISP_DIR_X,
+ MOD_DISP_DIR_Y,
+ MOD_DISP_DIR_Z,
+ MOD_DISP_DIR_NOR,
+};
+
+/* DisplaceModifierData->texmapping */
+enum {
+ MOD_DISP_MAP_LOCAL,
+ MOD_DISP_MAP_GLOBAL,
+ MOD_DISP_MAP_OBJECT,
+ MOD_DISP_MAP_UV,
+};
+
+typedef struct UVProjectModifierData {
+ ModifierData modifier;
+
+ /* the objects which do the projecting */
+ struct Object *projectors[10];
+ struct Image *image; /* the image to project */
+ int flags;
+ int num_projectors;
+} UVProjectModifierData;
+
+#define MOD_UVPROJECT_MAXPROJECTORS 10
+
+/* UVProjectModifierData->flags */
+#define MOD_UVPROJECT_ADDUVS 1<<0
+
typedef struct DecimateModifierData {
ModifierData modifier;
diff --git a/source/blender/python/api2_2x/Mesh.c b/source/blender/python/api2_2x/Mesh.c
index 5ebb74f088e..10e03a690f9 100644
--- a/source/blender/python/api2_2x/Mesh.c
+++ b/source/blender/python/api2_2x/Mesh.c
@@ -2221,8 +2221,7 @@ static int MEdge_setFlag( BPy_MEdge * self, PyObject * value )
| ME_HIDE
| ME_EDGERENDER
| ME_LOOSEEDGE
- | ME_SEAM_LAST
- | ME_EDGE_STEPINDEX;
+ | ME_SEAM_LAST;
MEdge *edge = MEdge_get_pointer( self );
if( !edge )
diff --git a/source/blender/render/intern/source/texture.c b/source/blender/render/intern/source/texture.c
index 8b7740ccf8c..08281dbd23d 100644
--- a/source/blender/render/intern/source/texture.c
+++ b/source/blender/render/intern/source/texture.c
@@ -1156,6 +1156,7 @@ static void do_2d_mapping(MTex *mtex, float *t, VlakRen *vlr, float *dxt, float
static int multitex(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, TexResult *texres)
{
+ float tmpvec[3];
int retval=0; /* return value, int:0, col:1, nor:2, everything:3 */
texres->talpha= 0; /* is set when image texture returns alpha (considered premul) */
@@ -1200,35 +1201,44 @@ static int multitex(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex,
case TEX_MUSGRAVE:
/* newnoise: musgrave types */
- /* ton: added this, for Blender convention reason. scaling texvec here is so-so ... */
- VecMulf(texvec, 1.0/tex->noisesize);
+ /* ton: added this, for Blender convention reason.
+ * artificer: added the use of tmpvec to avoid scaling texvec
+ */
+ VECCOPY(tmpvec, texvec);
+ VecMulf(tmpvec, 1.0/tex->noisesize);
switch(tex->stype) {
case TEX_MFRACTAL:
case TEX_FBM:
- retval= mg_mFractalOrfBmTex(tex, texvec, texres);
+ retval= mg_mFractalOrfBmTex(tex, tmpvec, texres);
break;
case TEX_RIDGEDMF:
case TEX_HYBRIDMF:
- retval= mg_ridgedOrHybridMFTex(tex, texvec, texres);
+ retval= mg_ridgedOrHybridMFTex(tex, tmpvec, texres);
break;
case TEX_HTERRAIN:
- retval= mg_HTerrainTex(tex, texvec, texres);
+ retval= mg_HTerrainTex(tex, tmpvec, texres);
break;
}
break;
/* newnoise: voronoi type */
case TEX_VORONOI:
- /* ton: added this, for Blender convention reason. scaling texvec here is so-so ... */
- VecMulf(texvec, 1.0/tex->noisesize);
+ /* ton: added this, for Blender convention reason.
+ * artificer: added the use of tmpvec to avoid scaling texvec
+ */
+ VECCOPY(tmpvec, texvec);
+ VecMulf(tmpvec, 1.0/tex->noisesize);
- retval= voronoiTex(tex, texvec, texres);
+ retval= voronoiTex(tex, tmpvec, texres);
break;
case TEX_DISTNOISE:
- /* ton: added this, for Blender convention reason. scaling texvec here is so-so ... */
- VecMulf(texvec, 1.0/tex->noisesize);
+ /* ton: added this, for Blender convention reason.
+ * artificer: added the use of tmpvec to avoid scaling texvec
+ */
+ VECCOPY(tmpvec, texvec);
+ VecMulf(tmpvec, 1.0/tex->noisesize);
- retval= mg_distNoiseTex(tex, texvec, texres);
+ retval= mg_distNoiseTex(tex, tmpvec, texres);
break;
}
diff --git a/source/blender/src/booleanops.c b/source/blender/src/booleanops.c
index b38600d182b..8a2d6d4d7f9 100644
--- a/source/blender/src/booleanops.c
+++ b/source/blender/src/booleanops.c
@@ -46,8 +46,10 @@
#include "CSG_BooleanOps.h"
#include "BKE_booleanops.h"
+#include "BKE_cdderivedmesh.h"
#include "BKE_depsgraph.h"
#include "BKE_displist.h"
+#include "BKE_DerivedMesh.h"
#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_material.h"
@@ -74,6 +76,12 @@ static void ConvertCSGDescriptorsToDLM(
CSG_VertexIteratorDescriptor *vertex_it,
float parinv[][4]);
+static DerivedMesh *ConvertCSGDescriptorsToDerivedMesh(
+ Object *ob, CSG_MeshPropertyDescriptor *props,
+ CSG_FaceIteratorDescriptor *face_it,
+ CSG_VertexIteratorDescriptor *vertex_it,
+ float parinv[][4]);
+
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -571,6 +579,196 @@ DispListMesh *NewBooleanMeshDLM(Object *ob, Object *ob_select, int int_op_type)
return dlm;
}
+DerivedMesh *NewBooleanDerivedMesh(struct Object *ob, struct Object *ob_select,
+ int int_op_type)
+{
+ Mesh *me2 = get_mesh(ob_select);
+ Mesh *me = get_mesh(ob);
+ int free_tface1, free_tface2;
+ DerivedMesh *result;
+
+ float inv_mat[4][4];
+ int success = 0;
+ // build and fill new descriptors for these meshes
+ CSG_VertexIteratorDescriptor vd_1;
+ CSG_VertexIteratorDescriptor vd_2;
+ CSG_FaceIteratorDescriptor fd_1;
+ CSG_FaceIteratorDescriptor fd_2;
+
+ CSG_MeshPropertyDescriptor mpd1, mpd2;
+
+ // work out the operation they chose and pick the appropriate
+ // enum from the csg module.
+
+ CSG_OperationType op_type;
+
+ if(me == NULL || me2 == NULL) return 0;
+
+ if(!me->totface || !me2->totface) return 0;
+
+ success = 0;
+
+ switch(int_op_type) {
+ case 1 : op_type = e_csg_intersection; break;
+ case 2 : op_type = e_csg_union; break;
+ case 3 : op_type = e_csg_difference; break;
+ case 4 : op_type = e_csg_classify; break;
+ default : op_type = e_csg_intersection;
+ }
+
+ // Here is the section where we describe the properties of
+ // both meshes to the bsp module.
+
+ if(me->mcol != NULL) {
+ // Then this mesh has vertex colors only
+ // well this is awkward because there is no equivalent
+ // test_index_mface just for vertex colors!
+ // as a temporary hack we can convert these vertex colors
+ // into tfaces do the operation and turn them back again.
+
+ // create some memory for the tfaces.
+ me->tface = (TFace *)MEM_callocN(sizeof(TFace) * me->totface,
+ "BooleanOps_TempTFace");
+ mcol_to_tface(me, 1);
+ free_tface1 = 1;
+ } else {
+ free_tface1 = 0;
+ }
+
+ mpd1.user_face_vertex_data_size = 0;
+ mpd1.user_data_size = sizeof(FaceData);
+
+ if(me->tface) {
+ mpd1.user_face_vertex_data_size = sizeof(FaceVertexData);
+ }
+
+ // same for mesh2
+
+ if(me2->mcol != NULL) {
+ // create some memory for the tfaces.
+ me2->tface = (TFace *)MEM_callocN(sizeof(TFace) * me2->totface,
+ "BooleanOps_TempTFace");
+ mcol_to_tface(me2, 1);
+ free_tface2 = 1;
+ } else {
+ free_tface2 = 0;
+ }
+
+ mpd2.user_face_vertex_data_size = 0;
+ mpd2.user_data_size = sizeof(FaceData);
+
+ if(me2->tface) {
+ mpd2.user_face_vertex_data_size = sizeof(FaceVertexData);
+ }
+
+ // we map the final object back into object 1's (ob)
+ // local coordinate space. For this we need to compute
+ // the inverse transform from global to local.
+
+ Mat4Invert(inv_mat, ob_select->obmat);
+
+ // make a boolean operation;
+ {
+ CSG_BooleanOperation *bool_op = CSG_NewBooleanFunction();
+ CSG_MeshPropertyDescriptor output_mpd = CSG_DescibeOperands(bool_op,
+ mpd1, mpd2);
+ // analyse the result and choose mesh descriptors accordingly
+ int output_type;
+ if(output_mpd. user_face_vertex_data_size) {
+ output_type = 1;
+ } else {
+ output_type = 0;
+ }
+
+ BuildMeshDescriptors(ob, &fd_1, &vd_1);
+ BuildMeshDescriptors(ob_select, &fd_2, &vd_2);
+
+ // perform the operation
+
+ if(output_type == 0) {
+ success = CSG_PerformBooleanOperation(bool_op, op_type,
+ fd_1, vd_1, fd_2, vd_2,
+ InterpNoUserData);
+ } else {
+ success = CSG_PerformBooleanOperation(bool_op, op_type,
+ fd_1, vd_1, fd_2, vd_2,
+ InterpFaceVertexData);
+ }
+
+ switch(success) {
+ case 1:
+ {
+ // descriptions of the output;
+ CSG_VertexIteratorDescriptor vd_o;
+ CSG_FaceIteratorDescriptor fd_o;
+
+ CSG_OutputFaceDescriptor(bool_op, &fd_o);
+ CSG_OutputVertexDescriptor(bool_op, &vd_o);
+
+ // iterate through results of operation and insert
+ // into new object
+
+ result = ConvertCSGDescriptorsToDerivedMesh(
+ NULL, &output_mpd,
+ &fd_o, &vd_o, inv_mat);
+
+ // free up the memory
+
+ CSG_FreeVertexDescriptor(&vd_o);
+ CSG_FreeFaceDescriptor(&fd_o);
+ }
+ break;
+ case -1:
+ error("Selected meshes must have faces to perform "
+ "boolean operations");
+ break;
+ case -2:
+ error("Both meshes must be closed");
+ break;
+ default:
+ error("unknown internal error");
+ break;
+ }
+
+ CSG_FreeBooleanOperation(bool_op);
+ }
+
+ // We may need to map back the tfaces to mcols here.
+ if(free_tface1) {
+ tface_to_mcol(me);
+ MEM_freeN(me->tface);
+ me->tface = NULL;
+ }
+ if(free_tface2) {
+ tface_to_mcol(me2);
+ MEM_freeN(me2->tface);
+ me2->tface = NULL;
+ }
+
+ if(free_tface1 && free_tface2) {
+ // then we need to map the output tfaces into mcols
+ if(result && DM_get_vert_data(result, 0, LAYERTYPE_TFACE)) {
+ int i;
+ int maxFaces = result->getNumFaces(result);
+
+ if(!DM_get_vert_data(result, 0, LAYERTYPE_MCOL))
+ DM_add_vert_layer(result, LAYERTYPE_MCOL, 0, NULL);
+
+ for(i = 0; i < maxFaces; ++i) {
+ MCol *mcol = DM_get_vert_data(result, i, LAYERTYPE_MCOL);
+ TFace *tface = DM_get_vert_data(result, i, LAYERTYPE_TFACE);
+
+ memcpy(mcol, tface->col, sizeof(*mcol) * 4);
+ }
+ }
+ }
+
+ FreeMeshDescriptors(&fd_1, &vd_1);
+ FreeMeshDescriptors(&fd_2, &vd_2);
+
+ return result;
+}
+
int
NewBooleanMesh(
struct Base * base,
@@ -999,6 +1197,154 @@ ConvertCSGDescriptorsToDLM(
}
MEM_freeN(face.user_face_data);
}
+
+static DerivedMesh *ConvertCSGDescriptorsToDerivedMesh(
+ Object *ob, CSG_MeshPropertyDescriptor *props,
+ CSG_FaceIteratorDescriptor *face_it,
+ CSG_VertexIteratorDescriptor *vertex_it,
+ float parinv[][4])
+{
+ FaceVertexData *user_face_vertex_data;
+ GHash *material_hash;
+ CSG_IVertex vert;
+ CSG_IFace face;
+ DerivedMesh *result;
+ int i;
+#if 0
+ MFace *mfaces;
+ TFace *tfaces;
+#endif
+ int fi_insert_pos, nmaterials;
+
+ // create some memory for the Iface according to output mesh props.
+
+ // initialize the face structure for readback
+
+ face.user_face_data = MEM_callocN(sizeof(FaceData),"BooleanOp_IFaceData");
+
+ if(props->user_face_vertex_data_size) {
+ user_face_vertex_data = MEM_callocN(sizeof(FaceVertexData) * 4,
+ "BooleanOp_IFaceData");
+ face.user_face_vertex_data[0] = &user_face_vertex_data[0];
+ face.user_face_vertex_data[1] = &user_face_vertex_data[1];
+ face.user_face_vertex_data[2] = &user_face_vertex_data[2];
+ face.user_face_vertex_data[3] = &user_face_vertex_data[3];
+ } else {
+ user_face_vertex_data = NULL;
+ }
+
+ // create memory for the vertex array.
+
+ result = CDDM_new(vertex_it->num_elements, 0, face_it->num_elements);
+
+ if(user_face_vertex_data)
+ DM_add_face_layer(result, LAYERTYPE_TFACE, 0, NULL);
+
+ // step through the iterators.
+
+ i = 0;
+ while(!vertex_it->Done(vertex_it->it)) {
+ MVert *insert_pos = CDDM_get_vert(result, i);
+ vertex_it->Fill(vertex_it->it, &vert);
+
+ // map output vertex into insert_pos
+ // and transform at by parinv at the same time.
+
+ VecMat4MulVecfl(insert_pos->co, parinv, vert.position);
+
+ vertex_it->Step(vertex_it->it);
+ i++;
+ }
+
+ // a hash table to remap materials to indices with
+ material_hash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+ nmaterials = 0;
+
+ fi_insert_pos = 0;
+ while(!face_it->Done(face_it->it)) {
+ MFace *mface = CDDM_get_face(result, fi_insert_pos);
+ FaceData *fdata;
+
+ face_it->Fill(face_it->it, &face);
+ fdata = face.user_face_data;
+
+ // cheat CSG never dumps out quads.
+
+ if(face.vertex_number>3) {
+ // QUAD
+ mface->v1 = face.vertex_index[0];
+ mface->v2 = face.vertex_index[1];
+ mface->v3 = face.vertex_index[2];
+ mface->v4 = face.vertex_index[3];
+ } else {
+ // TRIANGLE
+ mface->v1 = face.vertex_index[0];
+ mface->v2 = face.vertex_index[1];
+ mface->v3 = face.vertex_index[2];
+ mface->v4 = 0;
+ }
+
+ mface->mat_nr = 0;
+ mface->flag = fdata->faceflag;
+
+ /* HACK, perform material to index mapping using a general
+ * hash table, just tuck the int into a void *.
+ */
+
+ if(ob && !BLI_ghash_haskey(material_hash, fdata->material)) {
+ int matnr = nmaterials++;
+ BLI_ghash_insert(material_hash, fdata->material, (void*)matnr);
+ assign_material(ob, fdata->material, matnr + 1);
+ }
+ mface->mat_nr = (int)BLI_ghash_lookup(material_hash, fdata->material);
+
+ // grab the vertex colors and texture cos and dump them into the tface.
+
+ if(user_face_vertex_data) {
+ TFace *tface = DM_get_face_data(result, fi_insert_pos,
+ LAYERTYPE_TFACE);
+
+ // copy all the tface settings back
+ tface->tpage = fdata->tpage;
+ tface->flag = fdata->flag;
+ tface->transp = fdata->transp;
+ tface->mode = fdata->mode;
+ tface->tile = fdata->tile;
+
+ for(i = 0; i < 4; i++) {
+ FaceVertexData *fvdata = face.user_face_vertex_data[i];
+ float *color = fvdata->color;
+
+ tface->uv[i][0] = fvdata->uv[0];
+ tface->uv[i][1] = fvdata->uv[1];
+ tface->col[i] =
+ ((((unsigned int)floor(color[0] + 0.5f)) & 0xff) << 24)
+ | ((((unsigned int)floor(color[1] + 0.5f)) & 0xff) << 16)
+ | ((((unsigned int)floor(color[2] + 0.5f)) & 0xff) << 8)
+ | ((((unsigned int)floor(color[3] + 0.5f)) & 0xff) << 0);
+ }
+
+ test_index_face(mface, NULL, tface, face.vertex_number);
+ } else {
+ test_index_face(mface, NULL, NULL, face.vertex_number);
+ }
+
+ fi_insert_pos++;
+ face_it->Step(face_it->it);
+ }
+
+ BLI_ghash_free(material_hash, NULL, NULL);
+
+ CDDM_calc_edges(result);
+
+ CDDM_calc_normals(result);
+
+ // thats it!
+ if(user_face_vertex_data) MEM_freeN(user_face_vertex_data);
+ MEM_freeN(face.user_face_data);
+
+ return result;
+}
void
BuildMeshDescriptors(
diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c
index c3e45f49123..ad066544442 100644
--- a/source/blender/src/buttons_editing.c
+++ b/source/blender/src/buttons_editing.c
@@ -765,27 +765,50 @@ static void modifiers_add(void *ob_v, int type)
BIF_undo_push("Add modifier");
}
+typedef struct MenuEntry {
+ char *name;
+ int ID;
+} MenuEntry;
+
+static int menuEntry_compare_names(const void *entry1, const void *entry2)
+{
+ return strcmp(((MenuEntry *)entry1)->name, ((MenuEntry *)entry2)->name);
+}
+
static uiBlock *modifiers_add_menu(void *ob_v)
{
Object *ob = ob_v;
uiBlock *block;
int i, yco=0;
+ int numEntries = 0;
+ MenuEntry entries[NUM_MODIFIER_TYPES];
- block= uiNewBlock(&curarea->uiblocks, "modifier_add_menu", UI_EMBOSSP, UI_HELV, curarea->win);
+ block= uiNewBlock(&curarea->uiblocks, "modifier_add_menu",
+ UI_EMBOSSP, UI_HELV, curarea->win);
uiBlockSetButmFunc(block, modifiers_add, ob);
for (i=eModifierType_None+1; i<NUM_MODIFIER_TYPES; i++) {
ModifierTypeInfo *mti = modifierType_getInfo(i);
- /* Only allow adding through appropriate other interfaces */
- if (ELEM(i, eModifierType_Softbody, eModifierType_Hook)) continue;
-
- if ( (mti->flags&eModifierTypeFlag_AcceptsCVs) ||
- (ob->type==OB_MESH && (mti->flags&eModifierTypeFlag_AcceptsMesh))) {
- uiDefBut(block, BUTM, B_MODIFIER_RECALC, mti->name, 0, yco-=20, 160, 19, NULL, 0, 0, 1, i, "");
+ /* Only allow adding through appropriate other interfaces */
+ if(ELEM(i, eModifierType_Softbody, eModifierType_Hook)) continue;
+
+ if((mti->flags&eModifierTypeFlag_AcceptsCVs) ||
+ (ob->type==OB_MESH && (mti->flags&eModifierTypeFlag_AcceptsMesh))) {
+ entries[numEntries].name = mti->name;
+ entries[numEntries].ID = i;
+
+ ++numEntries;
}
}
-
+
+ qsort(entries, numEntries, sizeof(*entries), menuEntry_compare_names);
+
+
+ for(i = 0; i < numEntries; ++i)
+ uiDefBut(block, BUTM, B_MODIFIER_RECALC, entries[i].name,
+ 0, yco -= 20, 160, 19, NULL, 0, 0, 1, entries[i].ID, "");
+
uiTextBoundsBlock(block, 50);
uiBlockSetDirection(block, UI_DOWN);
@@ -943,12 +966,85 @@ static void modifier_testArmatureObj(char *name, ID **idpp)
*idpp= 0;
}
+static void modifier_testTexture(char *name, ID **idpp)
+{
+ ID *id;
+
+ for(id = G.main->tex.first; id; id = id->next) {
+ if(strcmp(name, id->name + 2) == 0) {
+ *idpp = id;
+ return;
+ }
+ }
+ *idpp = 0;
+}
+
+static void modifier_testMaterial(char *name, ID **idpp)
+{
+ ID *id;
+
+ for(id = G.main->mat.first; id; id = id->next) {
+ if(strcmp(name, id->name + 2) == 0) {
+ *idpp = id;
+ return;
+ }
+ }
+ *idpp = 0;
+}
+
+static void modifier_testImage(char *name, ID **idpp)
+{
+ ID *id;
+
+ for(id = G.main->image.first; id; id = id->next) {
+ if(strcmp(name, id->name + 2) == 0) {
+ *idpp = id;
+ return;
+ }
+ }
+ *idpp = 0;
+}
+
+/* autocomplete callback for ID buttons */
+void autocomplete_image(char *str, void *arg_v)
+{
+ char truncate[40] = {0};
+
+ /* search if str matches the beginning of an ID struct */
+ if(str[0]) {
+ ID *id;
+
+ for(id = G.main->image.first; id; id = id->next) {
+ int a;
+
+ for(a = 0; a < 24 - 2; a++) {
+ if(str[a] == 0 || str[a] != id->name[a + 2])
+ break;
+ }
+ /* found a match */
+ if(str[a] == 0) {
+ /* first match */
+ if(truncate[0] == 0)
+ BLI_strncpy(truncate, id->name + 2, 24);
+ else {
+ /* remove from truncate what is not in bone->name */
+ for(a = 0; a < 23; a++) {
+ if(truncate[a] != id->name[a])
+ truncate[a] = 0;
+ }
+ }
+ }
+ }
+ if(truncate[0])
+ BLI_strncpy(str, truncate, 24);
+ }
+}
+
static void modifiers_applyModifier(void *obv, void *mdv)
{
Object *ob = obv;
ModifierData *md = mdv;
DerivedMesh *dm;
- DispListMesh *dlm;
Mesh *me = ob->data;
int converted = 0;
@@ -972,20 +1068,9 @@ static void modifiers_applyModifier(void *obv, void *mdv)
return;
}
- dlm= dm->convertToDispListMesh(dm, 0);
+ DM_to_mesh(dm, me);
+ converted = 1;
- if ((!me->tface || dlm->tface) || okee("Applying will delete mesh UVs and vertex colors")) {
- if ((!me->mcol || dlm->mcol) || okee("Applying will delete mesh vertex colors")) {
- if (dlm->totvert==me->totvert || okee("Applying will delete mesh sticky, keys, and vertex groups")) {
- displistmesh_to_mesh(dlm, me);
- converted = 1;
- }
- }
- }
-
- if (!converted) {
- displistmesh_free(dlm);
- }
dm->release(dm);
}
else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
@@ -1234,6 +1319,14 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
height = 86;
} else if (md->type==eModifierType_Mirror) {
height = 46;
+ } else if (md->type==eModifierType_EdgeSplit) {
+ height = 46;
+ } else if (md->type==eModifierType_Displace) {
+ DisplaceModifierData *dmd = (DisplaceModifierData *)md;
+ height = 134;
+ if(dmd->texmapping == MOD_DISP_MAP_OBJECT) height += 19;
+ } else if (md->type==eModifierType_UVProject) {
+ height = 67 + ((UVProjectModifierData *)md)->num_projectors * 19;
} else if (md->type==eModifierType_Decimate) {
height = 46;
} else if (md->type==eModifierType_Wave) {
@@ -1279,7 +1372,7 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
char subsurfmenu[]="Subsurf Type%t|Catmull-Clark%x0|Simple Subdiv.%x1";
uiDefButS(block, MENU, B_MODIFIER_RECALC, subsurfmenu, lx,(cy-=19),buttonWidth,19, &smd->subdivType, 0, 0, 0, 0, "Selects type of subdivision algorithm.");
uiDefButS(block, NUM, B_MODIFIER_RECALC, "Levels:", lx, (cy-=19), buttonWidth,19, &smd->levels, 1, 6, 0, 0, "Number subdivisions to perform");
- uiDefButS(block, NUM, B_MODIFIER_RECALC, "Render Levels:", lx, (cy-=19), buttonWidth,19, &smd->renderLevels, 1, 6, 0, 0, "Number subdivisions to perform when rendering");
+ uiDefButS(block, NUM, B_MODIFIER_REDRAW, "Render Levels:", lx, (cy-=19), buttonWidth,19, &smd->renderLevels, 1, 6, 0, 0, "Number subdivisions to perform when rendering");
/* Disabled until non-EM DerivedMesh implementation is complete */
@@ -1294,12 +1387,12 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
LatticeModifierData *lmd = (LatticeModifierData*) md;
uiDefIDPoinBut(block, modifier_testLatticeObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &lmd->object, "Lattice object to deform with");
but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ", lx, (cy-=19), buttonWidth,19, &lmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
- uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)lmd->object);
+ uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
} else if (md->type==eModifierType_Curve) {
CurveModifierData *cmd = (CurveModifierData*) md;
uiDefIDPoinBut(block, modifier_testCurveObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &cmd->object, "Curve object to deform with");
but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ", lx, (cy-=19), buttonWidth,19, &cmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
- uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)cmd->object);
+ uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
} else if (md->type==eModifierType_Build) {
BuildModifierData *bmd = (BuildModifierData*) md;
uiDefButF(block, NUM, B_MODIFIER_RECALC, "Start:", lx, (cy-=19), buttonWidth,19, &bmd->start, 1.0, MAXFRAMEF, 100, 0, "Specify the start frame of the effect");
@@ -1313,6 +1406,86 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
uiDefButS(block, ROW, B_MODIFIER_RECALC, "Y", lx+20, cy, 20,19, &mmd->axis, 1, 1, 0, 0, "Specify the axis to mirror about");
uiDefButS(block, ROW, B_MODIFIER_RECALC, "Z", lx+40, cy, 20,19, &mmd->axis, 1, 2, 0, 0, "Specify the axis to mirror about");
uiDefButBitS(block, TOG, MOD_MIR_CLIPPING, B_MODIFIER_RECALC, "Do Clipping", lx+60, cy, buttonWidth-60,19, &mmd->flag, 1, 2, 0, 0, "Prevents during Transform vertices to go through Mirror");
+ } else if (md->type==eModifierType_EdgeSplit) {
+ EdgeSplitModifierData *amd = (EdgeSplitModifierData*) md;
+ uiDefButF(block, NUM, B_MODIFIER_RECALC, "Split Angle:",
+ lx, (cy -= 19), buttonWidth, 19, &amd->split_angle,
+ 0.0, 180.0, 100, 2,
+ "Angle above which to split edges");
+ uiDefButBitI(block, TOG, MOD_EDGESPLIT_FROMANGLE,
+ B_MODIFIER_RECALC, "From Angle",
+ lx, (cy-=19), buttonWidth/2, 19,
+ &amd->flags, 0, 0, 0, 0,
+ "Get edge sharpness from angle");
+ uiDefButBitI(block, TOG, MOD_EDGESPLIT_FROMFLAG,
+ B_MODIFIER_RECALC, "From Flag",
+ lx + buttonWidth/2, cy, (buttonWidth + 1)/2, 19,
+ &amd->flags, 0, 0, 0, 0,
+ "Get edge sharpness from flag");
+ } else if (md->type==eModifierType_Displace) {
+ DisplaceModifierData *dmd = (DisplaceModifierData*) md;
+ but = uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ",
+ lx, (cy -= 19), buttonWidth, 19,
+ &dmd->defgrp_name, 0.0, 31.0, 0, 0,
+ "Name of vertex group to displace"
+ " (displace whole mesh if blank)");
+ uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
+ uiDefIDPoinBut(block, modifier_testTexture, ID_TE, B_CHANGEDEP,
+ "Texture: ", lx, (cy -= 19), buttonWidth, 19,
+ &dmd->texture,
+ "Texture to use as displacement input");
+ uiDefButF(block, NUM, B_MODIFIER_RECALC, "Midlevel:",
+ lx, (cy -= 19), buttonWidth, 19, &dmd->midlevel,
+ 0, 1, 10, 3,
+ "Material value that gives no displacement");
+ uiDefButF(block, NUM, B_MODIFIER_RECALC, "Strength:",
+ lx, (cy -= 19), buttonWidth, 19, &dmd->strength,
+ -1000, 1000, 10, 10,
+ "Strength of displacement");
+ sprintf(str, "Direction%%t|Normal%%x%d|Z%%x%d|Y%%x%d|X%%x%d",
+ MOD_DISP_DIR_NOR,
+ MOD_DISP_DIR_Z, MOD_DISP_DIR_Y, MOD_DISP_DIR_X);
+ uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
+ lx, (cy -= 19), buttonWidth, 19, &dmd->direction,
+ 0.0, 1.0, 0, 0, "Displace direction");
+ sprintf(str, "Texture Coordinates%%t"
+ "|Local%%x%d|Global%%x%d|Object%%x%d|UV%%x%d",
+ MOD_DISP_MAP_LOCAL, MOD_DISP_MAP_GLOBAL,
+ MOD_DISP_MAP_OBJECT, MOD_DISP_MAP_UV);
+ uiDefButI(block, MENU, B_MODIFIER_RECALC, str,
+ lx, (cy -= 19), buttonWidth, 19, &dmd->texmapping,
+ 0.0, 1.0, 0, 0,
+ "Texture coordinates used for displacement input");
+ if(dmd->texmapping == MOD_DISP_MAP_OBJECT) {
+ uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
+ "Ob: ", lx, (cy -= 19), buttonWidth, 19,
+ &dmd->map_object,
+ "Object to get texture coordinates from");
+ }
+ } else if (md->type==eModifierType_UVProject) {
+ UVProjectModifierData *umd = (UVProjectModifierData *) md;
+ int i;
+ uiDefButBitI(block, TOG, MOD_UVPROJECT_ADDUVS,
+ B_MODIFIER_RECALC, "Add UVs",
+ lx, (cy-=19), buttonWidth, 19,
+ &umd->flags, 0, 0, 0, 0,
+ "Add UV coordinates if missing");
+ uiDefButI(block, NUM, B_MODIFIER_RECALC, "Projectors:",
+ lx, (cy -= 19), buttonWidth, 19, &umd->num_projectors,
+ 1, MOD_UVPROJECT_MAXPROJECTORS, 0, 0,
+ "Number of objects to use as projectors");
+ for(i = 0; i < umd->num_projectors; ++i) {
+ uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP,
+ "Ob: ", lx, (cy -= 19), buttonWidth, 19,
+ &umd->projectors[i],
+ "Object to use as projector");
+ }
+ uiDefIDPoinBut(block, modifier_testImage, ID_IM, B_CHANGEDEP,
+ "Image: ", lx, (cy -= 19), buttonWidth, 19,
+ &umd->image,
+ "Image to project (only faces with this image "
+ "will be altered");
+ uiButSetCompleteFunc(but, autocomplete_image, (void *)ob);
} else if (md->type==eModifierType_Decimate) {
DecimateModifierData *dmd = (DecimateModifierData*) md;
uiDefButF(block, NUM, B_MODIFIER_RECALC, "Ratio:", lx,(cy-=19),buttonWidth,19, &dmd->percent, 0.0, 1.0, 10, 0, "Defines the percentage of triangles to reduce to");
@@ -1340,7 +1513,7 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
uiDefIDPoinBut(block, modifier_testArmatureObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &amd->object, "Armature object to deform with");
uiDefButBitS(block, TOG, ARM_DEF_VGROUP, B_ARM_RECALCDATA, "Vert.Groups", lx,cy-=19,buttonWidth/2,20, &amd->deformflag, 0, 0, 0, 0, "Enable VertexGroups defining deform");
- uiDefButBitS(block, TOG, ARM_DEF_ENVELOPE, B_ARM_RECALCDATA, "Envelopes", lx+buttonWidth/2,cy,buttonWidth/2,20, &amd->deformflag, 0, 0, 0, 0, "Enable Bone Envelopes defining deform");
+ uiDefButBitS(block, TOG, ARM_DEF_ENVELOPE, B_ARM_RECALCDATA, "Envelopes", lx+buttonWidth/2,cy,(buttonWidth + 1)/2,20, &amd->deformflag, 0, 0, 0, 0, "Enable Bone Envelopes defining deform");
} else if (md->type==eModifierType_Hook) {
HookModifierData *hmd = (HookModifierData*) md;
@@ -1349,7 +1522,7 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &hmd->object, "Parent Object for hook, also recalculates and clears offset");
if(hmd->indexar==NULL) {
but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ", lx, (cy-=19), buttonWidth,19, &hmd->name, 0.0, 31.0, 0, 0, "Vertex Group name");
- uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)hmd->object);
+ uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob);
}
uiBlockBeginAlign(block);
but = uiDefBut(block, BUT, B_MODIFIER_RECALC, "Reset", lx, (cy-=19), 80,19, NULL, 0.0, 0.0, 0, 0, "Recalculate and clear offset (transform) of hook");
diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c
index ee098b2ee7c..7149441093a 100644
--- a/source/blender/src/drawobject.c
+++ b/source/blender/src/drawobject.c
@@ -1370,7 +1370,6 @@ static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *dra
if (efa->h==0) {
glColor4ubv(cols[(efa->f&SELECT)?1:0]);
- *drawSmooth_r = (efa->flag&ME_SMOOTH);
return 1;
} else {
return 0;
@@ -1750,7 +1749,6 @@ static int draw_em_fancy__setFaceOpts(void *userData, int index, int *drawSmooth
if (efa->h==0) {
set_gl_material(efa->mat_nr+1);
- *drawSmooth_r = efa->flag&ME_SMOOTH;
return 1;
} else {
return 0;
diff --git a/source/blender/src/editmesh.c b/source/blender/src/editmesh.c
index 6c351a09dc4..72b118b56a2 100644
--- a/source/blender/src/editmesh.c
+++ b/source/blender/src/editmesh.c
@@ -286,6 +286,7 @@ EditEdge *addedgelist(EditVert *v1, EditVert *v2, EditEdge *example)
rule is to do this with addedgelist call, before addfacelist */
if(example) {
eed->crease= example->crease;
+ eed->sharp = example->sharp;
eed->seam = example->seam;
eed->h |= (example->h & EM_FGON);
}
@@ -858,6 +859,7 @@ void make_editMesh()
eed->crease= ((float)medge->crease)/255.0;
if(medge->flag & ME_SEAM) eed->seam= 1;
+ if(medge->flag & ME_SHARP) eed->sharp = 1;
if(medge->flag & SELECT) eed->f |= SELECT;
if(medge->flag & ME_FGON) eed->h= EM_FGON; // 2 different defines!
if(medge->flag & ME_HIDE) eed->h |= 1;
@@ -1081,6 +1083,7 @@ void load_editMesh(void)
medge->flag= (eed->f & SELECT) | ME_EDGERENDER;
if(eed->f2<2) medge->flag |= ME_EDGEDRAW;
if(eed->f2==0) medge->flag |= ME_LOOSEEDGE;
+ if(eed->sharp) medge->flag |= ME_SHARP;
if(eed->seam) medge->flag |= ME_SEAM;
if(eed->h & EM_FGON) medge->flag |= ME_FGON; // different defines yes
if(eed->h & 1) medge->flag |= ME_HIDE;
@@ -1782,7 +1785,7 @@ typedef struct EditVertC
typedef struct EditEdgeC
{
int v1, v2;
- unsigned char f, h, seam, pad;
+ unsigned char f, h, seam, sharp, pad;
short crease, fgoni;
} EditEdgeC;
@@ -1888,6 +1891,7 @@ static void *editMesh_to_undoMesh(void)
eedc->f= eed->f;
eedc->h= eed->h;
eedc->seam= eed->seam;
+ eedc->sharp= eed->sharp;
eedc->crease= (short)(eed->crease*255.0);
eedc->fgoni= eed->fgoni;
eed->tmp.l = a; /*store index*/
@@ -1983,6 +1987,7 @@ static void undoMesh_to_editMesh(void *umv)
eed->f= eedc->f;
eed->h= eedc->h;
eed->seam= eedc->seam;
+ eed->sharp= eedc->sharp;
eed->fgoni= eedc->fgoni;
eed->crease= ((float)eedc->crease)/255.0;
}
diff --git a/source/blender/src/editmesh_mods.c b/source/blender/src/editmesh_mods.c
index cf24bbd05a9..0416c31237a 100644
--- a/source/blender/src/editmesh_mods.c
+++ b/source/blender/src/editmesh_mods.c
@@ -2548,10 +2548,42 @@ void editmesh_mark_seam(int clear)
allqueue(REDRAWVIEW3D, 0);
}
+void editmesh_mark_sharp(int set)
+{
+ EditMesh *em= G.editMesh;
+ EditEdge *eed;
+
+#if 0
+ /* auto-enable sharp edge drawing */
+ if(set) {
+ if(!(G.f & G_DRAWSEAMS)) {
+ G.f |= G_DRAWSEAMS;
+ allqueue(REDRAWBUTSEDIT, 0);
+ }
+ }
+#endif
+
+ if(set) {
+ eed= em->edges.first;
+ while(eed) {
+ if(!eed->h && (eed->f & SELECT)) eed->sharp = 1;
+ eed = eed->next;
+ }
+ } else {
+ eed= em->edges.first;
+ while(eed) {
+ if(!eed->h && (eed->f & SELECT)) eed->sharp = 0;
+ eed = eed->next;
+ }
+ }
+
+ allqueue(REDRAWVIEW3D, 0);
+}
+
void Edge_Menu() {
short ret;
- ret= pupmenu("Edge Specials%t|Mark Seam %x1|Clear Seam %x2|Rotate Edge CW%x3|Rotate Edge CCW%x4|Loopcut%x6|Edge Slide%x5|Edge Loop Select%x7|Edge Ring Select%x8|Loop to Region%x9|Region to Loop%x10");
+ ret= pupmenu("Edge Specials%t|Mark Seam %x1|Clear Seam %x2|Rotate Edge CW%x3|Rotate Edge CCW%x4|Loopcut%x6|Edge Slide%x5|Edge Loop Select%x7|Edge Ring Select%x8|Loop to Region%x9|Region to Loop%x10|Mark Sharp%x11|Clear Sharp%x12");
switch(ret)
{
@@ -2587,6 +2619,16 @@ void Edge_Menu() {
case 10:
region_to_loop();
break;
+ case 11:
+ editmesh_mark_sharp(1);
+ BIF_undo_push("Mark Sharp");
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+ break;
+ case 12:
+ editmesh_mark_sharp(0);
+ BIF_undo_push("Clear Sharp");
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+ break;
}
}
diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c
index 5dd7bab5176..ede9d198b15 100644
--- a/source/blender/src/editobject.c
+++ b/source/blender/src/editobject.c
@@ -4312,9 +4312,11 @@ void make_local(int mode)
BIF_undo_push("Make local");
}
-static void adduplicate__forwardModifierLinks(void *userData, Object *ob, Object **obpoin)
+static void adduplicate__forwardModifierLinks(void *userData, Object *ob,
+ ID **idpoin)
{
- ID_NEW(*obpoin);
+ /* this is copied from ID_NEW; it might be better to have a macro */
+ if(*idpoin && (*idpoin)->newid) *idpoin = (*idpoin)->newid;
}
/* This function duplicated the current visible selection, its used by Duplicate and Linked Duplicate
@@ -4543,7 +4545,8 @@ void adduplicate(int mode, int dupflag)
relink_constraints(&chan->constraints);
}
}
- modifiers_foreachObjectLink(base->object, adduplicate__forwardModifierLinks, NULL);
+ modifiers_foreachIDLink(base->object,
+ adduplicate__forwardModifierLinks, NULL);
ID_NEW(base->object->parent);
ID_NEW(base->object->track);