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)
This commit is contained in:
2006-08-28 01:12:36 +00:00
parent 5dbc4c5f8f
commit 433f6c7043
30 changed files with 7885 additions and 1290 deletions

View File

@@ -45,15 +45,28 @@
* 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 */
@@ -61,24 +74,73 @@ struct DerivedMesh {
/* Also called in Editmode */
int (*getNumFaces)(DerivedMesh *dm);
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);
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
/* 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);
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);
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.
*
@@ -87,7 +149,8 @@ struct DerivedMesh {
* certain fields of the returned DispListMesh can safely be share with
* the DerivedMesh's internal data.
*/
struct DispListMesh* (*convertToDispListMesh)(DerivedMesh *dm, int allowShared);
struct DispListMesh* (*convertToDispListMesh)(DerivedMesh *dm,
int allowShared);
/* Iterate over all vertex points, calling DO_MINMAX with given args.
*
@@ -139,48 +202,185 @@ struct DerivedMesh {
* 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);
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));
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
* 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.
* 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.
* 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);
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);
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
* o Only if !setDrawOptions or setDrawOptions(userData, mapped-edge)
* returns true
*/
void (*drawMappedEdges)(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData);
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
* 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),
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 */

View File

@@ -57,6 +57,9 @@ 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

View File

@@ -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

View File

@@ -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

View File

@@ -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);

View File

@@ -33,6 +33,7 @@
#ifndef BKE_MODIFIER_H
#define BKE_MODIFIER_H
struct EditMesh;
struct DerivedMesh;
struct DagForest;
struct DagNode;
@@ -75,6 +76,9 @@ typedef enum {
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 */
char name[32];
@@ -90,6 +94,75 @@ typedef struct ModifierTypeInfo {
ModifierTypeType type;
ModifierTypeFlag flags;
/********************* 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);
/********************* 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.
*
@@ -97,124 +170,90 @@ typedef struct ModifierTypeInfo {
*/
void (*initData)(ModifierData *md);
/* 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.
* 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).
/* 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.
/* 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);
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.
/* 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);
/* 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.
/* 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);
void (*foreachObjectLink)(ModifierData *md, struct Object *ob,
ObjectWalkFunc walk, 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.
/* 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.
*/
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]);
void (*foreachIDLink)(ModifierData *md, struct Object *ob,
IDWalkFunc walk, void *userData);
} ModifierTypeInfo;
ModifierTypeInfo* modifierType_getInfo (ModifierType type);
ModifierTypeInfo *modifierType_getInfo (ModifierType type);
/* Modifier utility calls, do call through type pointer and return
/* 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);
ModifierData *modifier_new(int type);
void modifier_free(ModifierData *md);
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, ...);
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, ...);
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);
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);
int modifiers_isSoftbodyEnabled (struct Object *ob);
struct Object* modifiers_isDeformedByArmature(struct Object *ob);
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 modifiers_isDeformed(struct Object *ob);
ModifierData* modifiers_getVirtualModifierList (struct Object *ob);
/* 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 modifier_dependsOnTime (struct ModifierData *md);
ModifierData *modifiers_getVirtualModifierList(struct Object *ob);
#endif

View File

@@ -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]);

File diff suppressed because it is too large Load Diff

View File

@@ -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 ******************* */

File diff suppressed because it is too large Load Diff

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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);
/* 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;
/* find the group (weak loop-in-loop) */
for(index = 0, curdef = target->defbase.first; curdef;
curdef = curdef->next, index++)
if (!strcmp(curdef->name, vgroup))
break;
if(curdef && (me->dvert || dm)) {
MDeformVert *dvert = me->dvert;
float vec[3];
int j;
INIT_MINMAX(cd.dmin, cd.dmax);
for(a=0; a<numVerts; a++) {
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);
Mat4MulVecfl(cd.objectspace, vertexCos[a]);
break;
}
}
}
}
} 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);
}
if(vgroup && vgroup[0] && target->type==OB_MESH) {
bDeformGroup *curdef;
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;
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) {
VECCOPY(vec, vertexCos[a]);
calc_curve_deform(cuOb, vec, target->trackflag, &cd);
VecLerpf(vertexCos[a], vertexCos[a], vec, dvert->dw[j].weight);
Mat4MulVecfl(cd.objectspace, vertexCos[a]);
}
}
}
}
}
else {
for(a=0; a<numVerts; a++) {
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;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -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 */

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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)

View File

@@ -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 */

View File

@@ -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;

View File

@@ -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 )

View File

@@ -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;
}

View File

@@ -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,
@@ -1000,6 +1198,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(
struct Object *ob,

View File

@@ -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(ELEM(i, eModifierType_Softbody, eModifierType_Hook)) continue;
if ( (mti->flags&eModifierTypeFlag_AcceptsCVs) ||
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, "");
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);
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);
DM_to_mesh(dm, 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");

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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);

View File

@@ -175,7 +175,7 @@ void BL_SkinDeformer::Update(void)
for (int v =0; v<m_bmesh->totvert; v++)
VECCOPY(m_transverts[v], m_bmesh->mvert[v].co);
armature_deform_verts( par_arma, m_objMesh, m_transverts, m_bmesh->totvert, ARM_DEF_VGROUP );
armature_deform_verts( par_arma, m_objMesh, NULL, m_transverts, m_bmesh->totvert, ARM_DEF_VGROUP );
RecalcNormals();
/* Update the current frame */