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:
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
102
source/blender/blenkernel/BKE_cdderivedmesh.h
Normal file
102
source/blender/blenkernel/BKE_cdderivedmesh.h
Normal 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
|
||||
|
||||
161
source/blender/blenkernel/BKE_customdata.h
Normal file
161
source/blender/blenkernel/BKE_customdata.h
Normal 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
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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 ******************* */
|
||||
|
||||
1045
source/blender/blenkernel/intern/cdderivedmesh.c
Normal file
1045
source/blender/blenkernel/intern/cdderivedmesh.c
Normal file
File diff suppressed because it is too large
Load Diff
630
source/blender/blenkernel/intern/customdata.c
Normal file
630
source/blender/blenkernel/intern/customdata.c
Normal 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;
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 )
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user