diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index d09cb458ba4..4506f5740fb 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -45,7 +45,7 @@ * conversion to DLM. */ -#include "BKE_customdata.h" +#include "DNA_customdata_types.h" struct MVert; struct MEdge; diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h index 6f8d9911d89..9733c26ade2 100644 --- a/source/blender/blenkernel/BKE_customdata.h +++ b/source/blender/blenkernel/BKE_customdata.h @@ -27,39 +27,12 @@ * ***** 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.). - */ +/* CustomData interface, see also DNA_customdata_types.h. */ #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 -}; +struct CustomData; #define ORIGINDEX_NONE -1 /* indicates no original index for this element */ @@ -77,19 +50,19 @@ enum { /* 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, +void CustomData_init(struct 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 + * and memory space for maxElems elements. flag is added to all layer flags */ -void CustomData_from_template(const CustomData *source, CustomData *dest, - int maxElems); +void CustomData_from_template(const struct CustomData *source, + struct CustomData *dest, int flag, int maxElems); /* frees data associated with a CustomData object (doesn't free the object * itself, though) */ -void CustomData_free(CustomData *data); +void CustomData_free(struct CustomData *data); /* adds a data layer of the given type to the CustomData object, optionally * backed by an external data array @@ -100,25 +73,38 @@ void CustomData_free(CustomData *data); * 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); +int CustomData_add_layer(struct CustomData *data, int type, int flag, + void *layer); + +/* frees the first data layer with the give type. + * returns 1 on succes, 0 if no layer with the given type is found + */ +int CustomData_free_layer(struct CustomData *data, int type); /* 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); +int CustomData_compat(const struct CustomData *data1, + const struct CustomData *data2); + +/* returns 1 if a layer with the specified type exists */ +int CustomData_has_layer(const struct CustomData *data, int type); /* 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); +int CustomData_copy_data(const struct CustomData *source, + struct CustomData *dest, int source_index, + int dest_index, int count); +int CustomData_em_copy_data(struct CustomData *data, void *src_block, + void **dest_block); /* frees data in a CustomData object * return 1 on success, 0 on failure */ -int CustomData_free_elem(CustomData *data, int index, int count); +int CustomData_free_elem(struct 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 @@ -134,28 +120,47 @@ int CustomData_free_elem(CustomData *data, int index, int count); * * returns 1 on success, 0 on failure */ -int CustomData_interp(const CustomData *source, CustomData *dest, +int CustomData_interp(const struct CustomData *source, struct CustomData *dest, int *src_indices, float *weights, float *sub_weights, int count, int dest_index); +int CustomData_em_interp(struct CustomData *data, void **src_blocks, + float *weights, float *sub_weights, int count, + void *dest_block); /* 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); +void *CustomData_get(const struct CustomData *data, int index, int type); +void *CustomData_em_get(const struct CustomData *data, void *block, 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); +void *CustomData_get_layer(const struct 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); +void CustomData_set(const struct CustomData *data, int index, int type, + void *source); +void CustomData_em_set(struct CustomData *data, void *block, 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); +void CustomData_set_num_elems(struct CustomData *data, int numElems); + +/* alloc/free a block of custom data attached to one element in editmode */ +void CustomData_em_set_default(struct CustomData *data, void **block); +void CustomData_em_free_block(struct CustomData *data, void **block); + +/* copy custom data to/from layers as in mesh/derivedmesh, to editmesh + blocks of data. the CustomData's must be compatible */ +void CustomData_to_em_block(const struct CustomData *source, + struct CustomData *dest, int index, void **block); +void CustomData_from_em_block(const struct CustomData *source, + struct CustomData *dest, void *block, int index); + #endif diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 308a32439d4..04cb371226b 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -59,6 +59,7 @@ #include "BKE_utildefines.h" #include "BKE_cdderivedmesh.h" +#include "BKE_customdata.h" #include "BKE_DerivedMesh.h" #include "BKE_displist.h" #include "BKE_effect.h" @@ -154,9 +155,9 @@ void DM_init(DerivedMesh *dm, void DM_from_template(DerivedMesh *dm, DerivedMesh *source, int numVerts, int numEdges, int numFaces) { - CustomData_from_template(&source->vertData, &dm->vertData, numVerts); - CustomData_from_template(&source->edgeData, &dm->edgeData, numEdges); - CustomData_from_template(&source->faceData, &dm->faceData, numFaces); + CustomData_from_template(&source->vertData, &dm->vertData, 0, numVerts); + CustomData_from_template(&source->edgeData, &dm->edgeData, 0, numEdges); + CustomData_from_template(&source->faceData, &dm->faceData, 0, numFaces); DM_init_funcs(dm); } @@ -335,7 +336,7 @@ void DM_interp_edge_data(DerivedMesh *source, DerivedMesh *dest, int count, int dest_index) { CustomData_interp(&source->edgeData, &dest->edgeData, src_indices, - weights, (float *)vert_weights, count, dest_index); + weights, (float*)vert_weights, count, dest_index); } void DM_interp_face_data(DerivedMesh *source, DerivedMesh *dest, @@ -344,7 +345,7 @@ void DM_interp_face_data(DerivedMesh *source, DerivedMesh *dest, int count, int dest_index) { CustomData_interp(&source->faceData, &dest->faceData, src_indices, - weights, (float *)vert_weights, count, dest_index); + weights, (float*)vert_weights, count, dest_index); } typedef struct { @@ -1087,24 +1088,27 @@ static void emDM_drawUVEdges(DerivedMesh *dm) { EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm; EditFace *efa; + TFace *tf; glBegin(GL_LINES); for(efa= emdm->em->faces.first; efa; efa= efa->next) { - if(!(efa->tf.flag&TF_HIDE)) { - glVertex2fv(efa->tf.uv[0]); - glVertex2fv(efa->tf.uv[1]); + tf = CustomData_em_get(&emdm->em->fdata, efa->data, LAYERTYPE_TFACE); - glVertex2fv(efa->tf.uv[1]); - glVertex2fv(efa->tf.uv[2]); + if(tf && !(tf->flag&TF_HIDE)) { + glVertex2fv(tf->uv[0]); + glVertex2fv(tf->uv[1]); + + glVertex2fv(tf->uv[1]); + glVertex2fv(tf->uv[2]); if (!efa->v4) { - glVertex2fv(efa->tf.uv[2]); - glVertex2fv(efa->tf.uv[0]); + glVertex2fv(tf->uv[2]); + glVertex2fv(tf->uv[0]); } else { - glVertex2fv(efa->tf.uv[2]); - glVertex2fv(efa->tf.uv[3]); - glVertex2fv(efa->tf.uv[3]); - glVertex2fv(efa->tf.uv[0]); + glVertex2fv(tf->uv[2]); + glVertex2fv(tf->uv[3]); + glVertex2fv(tf->uv[3]); + glVertex2fv(tf->uv[0]); } } } diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 1ec318ae455..21ad73aa240 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -37,6 +37,7 @@ #include "BIF_gl.h" #include "BKE_cdderivedmesh.h" +#include "BKE_customdata.h" #include "BKE_DerivedMesh.h" #include "BKE_displist.h" #include "BKE_mesh.h" @@ -751,13 +752,11 @@ DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *me) MEdge *medge = CDDM_get_edges(dm); MFace *mface = CDDM_get_faces(dm); int *index; + TFace *tf; - /* this maps from vert pointer to vert index */ - GHash *vertHash = BLI_ghash_new(BLI_ghashutil_ptrhash, - BLI_ghashutil_ptrcmp); - + /* set eve->hash to vert index */ for(i = 0, eve = em->verts.first; eve; eve = eve->next, ++i) - BLI_ghash_insert(vertHash, eve, (void *)i); + eve->hash = i; if(me->msticky) CustomData_add_layer(&dm->vertData, LAYERTYPE_MDEFORMVERT, 0, NULL); @@ -807,8 +806,8 @@ DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *me) i++, eed = eed->next, index++) { MEdge *med = &medge[i]; - med->v1 = (int) BLI_ghash_lookup(vertHash, eed->v1); - med->v2 = (int) BLI_ghash_lookup(vertHash, eed->v2); + med->v1 = eed->v1->hash; + med->v2 = eed->v2->hash; med->crease = (unsigned char) (eed->crease * 255.0f); med->flag = ME_EDGEDRAW|ME_EDGERENDER; @@ -824,22 +823,21 @@ DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *me) i++, efa = efa->next, index++) { MFace *mf = &mface[i]; - mf->v1 = (int) BLI_ghash_lookup(vertHash, efa->v1); - mf->v2 = (int) BLI_ghash_lookup(vertHash, efa->v2); - mf->v3 = (int) BLI_ghash_lookup(vertHash, efa->v3); - mf->v4 = efa->v4 ? (int)BLI_ghash_lookup(vertHash, efa->v4) : 0; + mf->v1 = efa->v1->hash; + mf->v2 = efa->v2->hash; + mf->v3 = efa->v3->hash; + mf->v4 = efa->v4 ? efa->v4->hash : 0; mf->mat_nr = efa->mat_nr; mf->flag = efa->flag; test_index_face(mf, NULL, NULL, efa->v4?4:3); *index = i; - if(me->tface) - DM_set_face_data(dm, i, LAYERTYPE_TFACE, &efa->tf); + tf = CustomData_em_get(&em->fdata, efa->data, LAYERTYPE_TFACE); + if(tf) + DM_set_face_data(dm, i, LAYERTYPE_TFACE, tf); } - BLI_ghash_free(vertHash, NULL, NULL); - return dm; } @@ -976,7 +974,7 @@ void CDDM_calc_edges(DerivedMesh *dm) } } - CustomData_from_template(&dm->edgeData, &edgeData, BLI_edgehash_size(eh)); + CustomData_from_template(&dm->edgeData, &edgeData, 0, BLI_edgehash_size(eh)); if(!CustomData_get_layer(&edgeData, LAYERTYPE_MEDGE)) CustomData_add_layer(&edgeData, LAYERTYPE_MEDGE, diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index d774324f1c1..b7b034be216 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -36,6 +36,7 @@ #include "BLI_linklist.h" +#include "DNA_customdata_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" @@ -46,13 +47,6 @@ /* 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 */ @@ -83,45 +77,12 @@ typedef struct LayerTypeInfo { */ void (*interp)(void **sources, float *weights, float *sub_weights, int count, void *dest); + + /* a function to set a layer's data to default values. if NULL, the + default is assumed to be all zeros */ + void (*set_default)(void *data); } 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) { @@ -210,6 +171,18 @@ static void layerInterp_mdeformvert(void **sources, float *weights, BLI_linklist_free(dest_dw, linklist_free_simple); } +static void layerCopy_tface(const void *source, void *dest, int count, int size) +{ + const TFace *source_tf = (const TFace*)source; + TFace *dest_tf = (TFace*)dest; + int i; + + for(i = 0; i < count; ++i) { + dest_tf[i] = source_tf[i]; + dest_tf[i].flag &= ~TF_ACTIVE; + } +} + static void layerInterp_tface(void **sources, float *weights, float *sub_weights, int count, void *dest) { @@ -217,30 +190,32 @@ static void layerInterp_tface(void **sources, float *weights, int i, j, k; float uv[4][2]; float col[4][4]; + float *sub_weight; if(count <= 0) return; memset(uv, 0, sizeof(uv)); memset(col, 0, sizeof(col)); + sub_weight = sub_weights; 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]; + for(k = 0; k < 4; ++k, ++sub_weight) { + float w = (*sub_weight) * weight; 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; + uv[j][0] += tmp_uv[0] * w; + uv[j][1] += tmp_uv[1] * w; - 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; + col[j][0] += tmp_col[0] * w; + col[j][1] += tmp_col[1] * w; + col[j][2] += tmp_col[2] * w; + col[j][3] += tmp_col[3] * w; } } else { char *tmp_col = (char *)&src->col[j]; @@ -269,6 +244,14 @@ static void layerInterp_tface(void **sources, float *weights, } } +static void layerDefault_tface(void *data) +{ + static TFace default_tf = {NULL, {{0, 1}, {0, 0}, {1, 0}, {1, 1}}, + {~0, ~0, ~0, ~0}, TF_SELECT, 0, TF_DYNAMIC, 0, 0}; + + *((TFace*)data) = default_tf; +} + static void layerInterp_mcol(void **sources, float *weights, float *sub_weights, int count, void *dest) { @@ -280,14 +263,15 @@ static void layerInterp_mcol(void **sources, float *weights, float g; float b; } col[4]; + float *sub_weight; if(count <= 0) return; memset(col, 0, sizeof(col)); - + + sub_weight = sub_weights; 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) { @@ -316,6 +300,41 @@ static void layerInterp_mcol(void **sources, float *weights, } } +static void layerDefault_mcol(void *data) +{ + static MCol default_mcol = {255, 255, 255, 255}; + MCol *mcol = (MCol*)data; + + mcol[0]= default_mcol; + mcol[1]= default_mcol; + mcol[2]= default_mcol; + mcol[3]= default_mcol; +} + +const LayerTypeInfo LAYERTYPEINFO[LAYERTYPE_NUMTYPES] = { + {sizeof(MVert), NULL, NULL, NULL, NULL}, + {sizeof(MSticky), NULL, NULL, NULL, NULL}, + {sizeof(MDeformVert), layerCopy_mdeformvert, + layerFree_mdeformvert, layerInterp_mdeformvert, NULL}, + {sizeof(MEdge), NULL, NULL, NULL, NULL}, + {sizeof(MFace), NULL, NULL, NULL, NULL}, + {sizeof(TFace), layerCopy_tface, NULL, layerInterp_tface, + layerDefault_tface}, + /* 4 MCol structs per face */ + {sizeof(MCol) * 4, NULL, NULL, layerInterp_mcol, layerDefault_mcol}, + {sizeof(int), NULL, NULL, NULL, NULL}, + /* 3 floats per normal vector */ + {sizeof(float) * 3, NULL, NULL, NULL, NULL}, + {sizeof(int), NULL, NULL, NULL, NULL}, +}; + +static const LayerTypeInfo *layerType_getInfo(int type) +{ + if(type < 0 || type >= LAYERTYPE_NUMTYPES) return NULL; + + return &LAYERTYPEINFO[type]; +} + /********************* CustomData functions *********************/ void CustomData_init(CustomData *data, int maxLayers, int maxElems, int subElems) @@ -329,19 +348,36 @@ void CustomData_init(CustomData *data, data->subElems = subElems; } -void CustomData_from_template(const CustomData *source, CustomData *dest, - int maxElems) +static void CustomData_update_offsets(CustomData *data) { - int i; + const LayerTypeInfo *typeInfo; + int i, offset = 0; + + for(i = 0; i < data->numLayers; ++i) { + typeInfo = layerType_getInfo(data->layers[i].type); + + data->layers[i].offset = offset; + offset += typeInfo->size; + } + + data->totSize = offset; +} + +void CustomData_from_template(const CustomData *source, CustomData *dest, + int flag, int maxElems) +{ + int i, layerflag; 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); + layerflag = (source->layers[i].flag & ~LAYERFLAG_NOFREE) | flag; + CustomData_add_layer(dest, source->layers[i].type, layerflag, NULL); } + + CustomData_update_offsets(dest); } void CustomData_free(CustomData *data) @@ -356,7 +392,8 @@ void CustomData_free(CustomData *data) typeInfo->free(data->layers[i].data, data->numElems, typeInfo->size); - MEM_freeN(data->layers[i].data); + if(data->layers[i].data) + MEM_freeN(data->layers[i].data); } } @@ -368,73 +405,6 @@ void CustomData_free(CustomData *data) } } -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 @@ -452,6 +422,99 @@ static int CustomData_find_next(const CustomData *data, int type, return -1; } +static int customData_resize(CustomData *data, int amount) +{ + CustomDataLayer *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_resize(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++; + + CustomData_update_offsets(data); + + 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, "CustomDataLayer.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_free_layer(CustomData *data, int type) +{ + int index = CustomData_find_next(data, type, -1); + + if (index < 0) return 0; + + for(++index; index < data->numLayers; ++index) + data->layers[index - 1] = data->layers[index]; + + data->numLayers--; + + if(data->numLayers <= data->maxLayers-CUSTOMDATA_GROW) + customData_resize(data, -CUSTOMDATA_GROW); + + CustomData_update_offsets(data); + + return 1; +} + +int CustomData_has_layer(const struct CustomData *data, int type) +{ + return (CustomData_find_next(data, type, -1) != -1); +} + +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; +} + int CustomData_copy_data(const CustomData *source, CustomData *dest, int source_index, int dest_index, int count) { @@ -558,7 +621,7 @@ int CustomData_interp(const CustomData *source, CustomData *dest, /* interpolates a layer at a time */ for(src_i = 0; src_i < source->numLayers; ++src_i) { - LayerDesc *source_layer = &source->layers[src_i]; + CustomDataLayer *source_layer = &source->layers[src_i]; const LayerTypeInfo *type_info = layerType_getInfo(source_layer->type); @@ -628,3 +691,177 @@ void CustomData_set_num_elems(CustomData *data, int numElems) if(numElems < data->maxElems) data->numElems = numElems; else data->numElems = data->maxElems; } + +/* EditMesh functions */ + +static void CustomData_em_alloc_block(CustomData *data, void **block) +{ + /* TODO: optimize free/alloc */ + + if (*block) + MEM_freeN(*block); + + if (data->totSize > 0) + *block = MEM_callocN(data->totSize, "CustomData EM block"); + else + *block = NULL; +} + +void CustomData_em_free_block(CustomData *data, void **block) +{ + if (*block) { + MEM_freeN(*block); + *block = NULL; + } +} + +int CustomData_em_copy_data(CustomData *data, void *src_block, void **dest_block) +{ + const LayerTypeInfo *type_info; + int i; + + if (!*dest_block) + CustomData_em_alloc_block(data, dest_block); + + /* copies a layer at a time */ + for(i = 0; i < data->numLayers; ++i) { + int offset = data->layers[i].offset; + char *src_data = (char*)src_block + offset; + char *dest_data = (char*)*dest_block + offset; + + type_info = layerType_getInfo(data->layers[i].type); + + if(type_info->copy) + type_info->copy(src_data, dest_data, 1, type_info->size); + else + memcpy(dest_data, src_data, type_info->size); + } + + return 1; +} + +void *CustomData_em_get(const CustomData *data, void *block, int type) +{ + int layer_index; + + /* get the layer index of the first layer of type */ + layer_index = CustomData_find_next(data, type, -1); + if(layer_index < 0) return NULL; + + return (char *)block + data->layers[layer_index].offset; +} + +void CustomData_em_set(CustomData *data, void *block, int type, void *source) +{ + void *dest = CustomData_em_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); +} + +int CustomData_em_interp(CustomData *data, void **src_blocks, float *weights, + float *sub_weights, int count, void *dest_block) +{ + int i, j; + void *source_buf[SOURCE_BUF_SIZE]; + void **sources = source_buf; + + if(count <= 0) 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(i = 0; i < data->numLayers; ++i) { + CustomDataLayer *layer = &data->layers[i]; + const LayerTypeInfo *type_info = layerType_getInfo(layer->type); + + if(type_info->interp) { + for(j = 0; j < count; ++j) + sources[j] = (char *)src_blocks[j] + layer->offset; + + type_info->interp(sources, weights, sub_weights, count, + (char *)dest_block + layer->offset); + } + } + + if(count > SOURCE_BUF_SIZE) MEM_freeN(sources); + return 1; +} + +void CustomData_em_set_default(CustomData *data, void **block) +{ + const LayerTypeInfo *type_info; + int i; + + if (!*block) + CustomData_em_alloc_block(data, block); + + for(i = 0; i < data->numLayers; ++i) { + int offset = data->layers[i].offset; + + type_info = layerType_getInfo(data->layers[i].type); + + if(type_info->set_default) + type_info->set_default((char*)*block + offset); + } +} + +void CustomData_to_em_block(const CustomData *source, CustomData *dest, + int src_index, void **dest_block) +{ + const LayerTypeInfo *type_info; + int i, src_offset; + + if (!*dest_block) + CustomData_em_alloc_block(dest, dest_block); + + /* copies a layer at a time */ + for(i = 0; i < dest->numLayers; ++i) { + int offset = dest->layers[i].offset; + char *src_data = source->layers[i].data; + char *dest_data = (char*)*dest_block + offset; + + type_info = layerType_getInfo(dest->layers[i].type); + src_offset = src_index * type_info->size; + + if(type_info->copy) + type_info->copy(src_data + src_offset, dest_data, 1, + type_info->size); + else + memcpy(dest_data, src_data + src_offset, type_info->size); + } +} + +void CustomData_from_em_block(const CustomData *source, CustomData *dest, + void *src_block, int dest_index) +{ + const LayerTypeInfo *type_info; + int i, dest_offset; + + /* copies a layer at a time */ + for(i = 0; i < dest->numLayers; ++i) { + int offset = source->layers[i].offset; + char *src_data = (char*)src_block + offset; + char *dest_data = dest->layers[i].data; + + type_info = layerType_getInfo(dest->layers[i].type); + dest_offset = dest_index * type_info->size; + + if(type_info->copy) + type_info->copy(src_data, dest_data + dest_offset, 1, + type_info->size); + else + memcpy(dest_data + dest_offset, src_data, type_info->size); + } +} + diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index f8798de2650..3b6a7dba40b 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -45,6 +45,7 @@ #include "BKE_bad_level_calls.h" #include "BKE_cdderivedmesh.h" +#include "BKE_customdata.h" #include "BKE_utildefines.h" #include "BKE_global.h" #include "BKE_mesh.h" diff --git a/source/blender/blenlib/BLI_editVert.h b/source/blender/blenlib/BLI_editVert.h index 0592f04f05d..25559043bc8 100644 --- a/source/blender/blenlib/BLI_editVert.h +++ b/source/blender/blenlib/BLI_editVert.h @@ -38,6 +38,7 @@ #ifndef BLI_EDITVERT_H #define BLI_EDITVERT_H +#include "DNA_customdata_types.h" #include "DNA_mesh_types.h" struct DerivedMesh; @@ -125,7 +126,6 @@ typedef struct EditFace float fp; } tmp; float n[3], cent[3]; - struct TFace tf; /* a copy of original tface. */ unsigned char mat_nr, flag; unsigned char f, f1, h; unsigned char fast; /* only 0 or 1, for editmesh_fastmalloc */ @@ -133,6 +133,7 @@ typedef struct EditFace /*#ifdef WITH_VERSE*/ void *vface; /*#endif*/ + void *data; /* custom face data */ } EditFace; @@ -167,6 +168,8 @@ typedef struct EditMesh char retopo_mode; /* 0=OFF, 1=ON, 2=PAINT */ struct RetopoPaintData *retopo_paint_data; + CustomData fdata; + #ifdef WITH_VERSE void *vnode; #endif diff --git a/source/blender/include/BIF_editmesh.h b/source/blender/include/BIF_editmesh.h index 0df24d17917..ef568b9d84f 100644 --- a/source/blender/include/BIF_editmesh.h +++ b/source/blender/include/BIF_editmesh.h @@ -104,6 +104,11 @@ extern int faceselectedAND(struct EditFace *efa, int flag); extern void recalc_editnormals(void); extern void flip_editnormals(void); +extern struct EditFace *EM_face_from_faces(struct EditFace *efa1, + struct EditFace *efa2, int i1, int i2, int i3, int i4); +extern void EM_interp_from_faces(struct EditFace *efa1, struct EditFace *efa2, + struct EditFace *efan, int i1, int i2, int i3, int i4); + /* ******************* editmesh_mods.c */ extern void EM_init_index_arrays(int forVert, int forEdge, int forFace); diff --git a/source/blender/include/BIF_verse.h b/source/blender/include/BIF_verse.h index 01b6123c966..2145b8209d0 100644 --- a/source/blender/include/BIF_verse.h +++ b/source/blender/include/BIF_verse.h @@ -83,7 +83,7 @@ struct VNode *create_geom_vnode_data_from_mesh(struct VerseSession *session, str void destroy_unused_geometry(struct VNode *vnode); void destroy_binding_between_versemesh_and_editmesh(struct VNode *vnode); -void destroy_verse_mesh(struct VNode *vnode); +void destroy_versemesh(struct VNode *vnode); void unsubscribe_from_geom_node(struct VNode *vnode); diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h new file mode 100644 index 00000000000..2886f012c8e --- /dev/null +++ b/source/blender/makesdna/DNA_customdata_types.h @@ -0,0 +1,69 @@ +/** + * $Id$ + * + * ***** BEGIN GPL/BL DUAL 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. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * 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) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef DNA_CUSTOMDATA_TYPES_H +#define DNA_CUSTOMDATA_TYPES_H + +/* descriptor and storage for a custom data layer */ +typedef struct CustomDataLayer { + int type; /* type of data in layer */ + int offset; /* in editmode, offset of layer in block */ + int flag, pad; /* general purpose flag */ + void *data; /* layer data */ +} CustomDataLayer; + +/* 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.). */ +typedef struct CustomData { + CustomDataLayer *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 */ + int totSize; /* in editmode, total size of all data layers */ +} CustomData; + +/* custom data types */ +#define LAYERTYPE_MVERT 0 +#define LAYERTYPE_MSTICKY 1 +#define LAYERTYPE_MDEFORMVERT 2 +#define LAYERTYPE_MEDGE 3 +#define LAYERTYPE_MFACE 4 +#define LAYERTYPE_TFACE 5 +#define LAYERTYPE_MCOL 6 +#define LAYERTYPE_ORIGINDEX 7 +#define LAYERTYPE_NORMAL 8 +#define LAYERTYPE_FLAGS 9 +#define LAYERTYPE_NUMTYPES 10 + +#endif diff --git a/source/blender/src/editmesh.c b/source/blender/src/editmesh.c index e138631e548..a891fe1adab 100644 --- a/source/blender/src/editmesh.c +++ b/source/blender/src/editmesh.c @@ -43,6 +43,7 @@ #include "PIL_time.h" +#include "DNA_customdata_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" @@ -64,6 +65,7 @@ #include "BKE_DerivedMesh.h" #include "BKE_depsgraph.h" +#include "BKE_customdata.h" #include "BKE_global.h" #include "BKE_key.h" #include "BKE_library.h" @@ -150,7 +152,6 @@ EditVert *addvertlist(float *vec) * have a pre-editmode vertex order */ eve->keyindex = -1; - #ifdef WITH_VERSE createVerseVert(eve); #endif @@ -325,9 +326,9 @@ void free_editface(EditFace *efa) } #endif EM_remove_selection(efa, EDITFACE); - if(efa->fast==0){ + CustomData_em_free_block(&G.editMesh->fdata, &efa->data); + if(efa->fast==0) free(efa); - } } void free_vertlist(ListBase *edve) @@ -409,17 +410,14 @@ EditFace *addfacelist(EditVert *v1, EditVert *v2, EditVert *v3, EditVert *v4, Ed if(example) { efa->mat_nr= example->mat_nr; - efa->tf= example->tf; - efa->tf.flag &= ~TF_ACTIVE; efa->flag= example->flag; + CustomData_em_copy_data(&em->fdata, example->data, &efa->data); } else { if (G.obedit && G.obedit->actcol) efa->mat_nr= G.obedit->actcol-1; - default_uv(efa->tf.uv, 1.0); - /* Initialize colors */ - efa->tf.col[0]= efa->tf.col[1]= efa->tf.col[2]= efa->tf.col[3]= vpaint_get_current_col(); + CustomData_em_set_default(&em->fdata, &efa->data); } BLI_addtail(&em->faces, efa); @@ -511,7 +509,6 @@ static void *calloc_fastface(size_t size, size_t nr) */ static void init_editmesh_fastmalloc(EditMesh *em, int totvert, int totedge, int totface) { - if(totvert) em->allverts= MEM_callocN(totvert*sizeof(EditVert), "allverts"); else em->allverts= NULL; em->curvert= em->allverts; @@ -556,6 +553,9 @@ void free_editMesh(EditMesh *em) if(em->edges.first) free_edgelist(&em->edges); if(em->faces.first) free_facelist(&em->faces); if(em->selected.first) BLI_freelistN(&(em->selected)); + + CustomData_free(&em->fdata); + if(em->derivedFinal) { if (em->derivedFinal!=em->derivedCage) { em->derivedFinal->release(em->derivedFinal); @@ -774,6 +774,7 @@ static void edge_drawflags(void) void make_editMesh() { Mesh *me= G.obedit->data; + EditMesh *em= G.editMesh; MFace *mface; TFace *tface; MVert *mvert; @@ -783,6 +784,7 @@ void make_editMesh() EditFace *efa; EditEdge *eed; EditSelection *ese; + CustomData mfdata; int tot, a, eekadoodle= 0; #ifdef WITH_VERSE @@ -793,7 +795,7 @@ void make_editMesh() #endif /* because of reload */ - free_editMesh(G.editMesh); + free_editMesh(em); G.totvert= tot= me->totvert; G.totedge= me->totedge; @@ -804,9 +806,8 @@ void make_editMesh() return; } - /* initialize fastmalloc for editmesh */ - init_editmesh_fastmalloc(G.editMesh, me->totvert, me->totedge, me->totface); + init_editmesh_fastmalloc(em, me->totvert, me->totedge, me->totface); actkey = ob_get_keyblock(G.obedit); if(actkey) { @@ -847,10 +848,9 @@ void make_editMesh() } } - + if(actkey && actkey->totelem!=me->totvert); else { - unsigned int *mcol; MEdge *medge= me->medge; /* make edges */ @@ -870,11 +870,19 @@ void make_editMesh() } } + /* fill a CustomData, this is only temporary until Mesh get its own */ + CustomData_init(&mfdata, 0, me->totface, SUB_ELEMS_FACE); + if(me->mcol) + CustomData_add_layer(&mfdata, LAYERTYPE_MCOL, LAYERFLAG_NOFREE, me->mcol); + if(me->tface) + CustomData_add_layer(&mfdata, LAYERTYPE_TFACE, LAYERFLAG_NOFREE, me->tface); + + CustomData_from_template(&mfdata, &em->fdata, 0, 0); + /* make faces */ mface= me->mface; tface= me->tface; - mcol= (unsigned int *)me->mcol; - + for(a=0; atotface; a++, mface++) { eve1= evlist[mface->v1]; eve2= evlist[mface->v2]; @@ -885,13 +893,8 @@ void make_editMesh() efa= addfacelist(eve1, eve2, eve3, eve4, NULL, NULL); if(efa) { - - if(mcol) memcpy(efa->tf.col, mcol, 4*sizeof(int)); + CustomData_to_em_block(&mfdata, &em->fdata, a, &efa->data); - if(me->tface) { - efa->tf= *tface; - } - efa->mat_nr= mface->mat_nr; efa->flag= mface->flag & ~ME_HIDE; @@ -902,18 +905,18 @@ void make_editMesh() } if(mface->flag & ME_HIDE) efa->h= 1; } - else if (tface) { - if( tface->flag & TF_HIDE) + else if((tface = CustomData_get(&mfdata, a, LAYERTYPE_TFACE))) { + if(tface->flag & TF_HIDE) efa->h= 1; - else if( tface->flag & TF_SELECT) { + else if(tface->flag & TF_SELECT) EM_select_face(efa, 1); - } } } if(me->tface) tface++; - if(mcol) mcol+=4; } + + CustomData_free(&mfdata); } if(eekadoodle) @@ -936,7 +939,7 @@ void make_editMesh() if(ese->type == EDITVERT) ese->data = EM_get_vert_for_index(mselect->index); else if(ese->type == EDITEDGE) ese->data = EM_get_edge_for_index(mselect->index); else if(ese->type == EDITFACE) ese->data = EM_get_face_for_index(mselect->index); - BLI_addtail(&(G.editMesh->selected),ese); + BLI_addtail(&(em->selected),ese); } } EM_free_index_arrays(); @@ -962,6 +965,7 @@ void load_editMesh(void) MFace *mface; MSticky *ms; MSelect *mselect; + TFace *tf; EditVert *eve; EditFace *efa; EditEdge *eed; @@ -969,7 +973,7 @@ void load_editMesh(void) float *fp, *newkey, *oldkey, nor[3]; int i, a, ototvert, totedge=0; MDeformVert *dvert; - + CustomData mfdata; #ifdef WITH_VERSE if(em->vnode) { @@ -1005,7 +1009,7 @@ void load_editMesh(void) /* new Face block */ if(G.totface==0) mface= NULL; else mface= MEM_callocN(G.totface*sizeof(MFace), "loadeditMesh face"); - + /* are we adding dverts? */ if (G.totvert==0) dvert= NULL; else if(G.obedit->defbase.first==NULL) dvert= NULL; @@ -1028,9 +1032,21 @@ void load_editMesh(void) me->totedge= totedge; if(me->mface) MEM_freeN(me->mface); + me->mface= mface; me->totface= G.totface; - + + /* face data */ + if(me->tface) { + MEM_freeN(me->tface); + me->tface = NULL; + } + if(me->mcol) { + MEM_freeN(me->mcol); + me->mcol = NULL; + } + CustomData_from_template(&em->fdata, &mfdata, LAYERFLAG_NOFREE, me->totface); + /* the vertices, use ->tmp.l as counter */ eve= em->verts.first; a= 0; @@ -1145,9 +1161,11 @@ void load_editMesh(void) efa->e4->f2= 2; } + CustomData_from_em_block(&em->fdata, &mfdata, efa->data, i); /* no index '0' at location 3 or 4 */ - test_index_face(mface, NULL, &efa->tf, efa->v4?4:3); + test_index_face(mface, CustomData_get(&mfdata, i, LAYERTYPE_MCOL), + CustomData_get(&mfdata, i, LAYERTYPE_TFACE), efa->v4?4:3); #ifdef WITH_VERSE if(efa->vface) { @@ -1159,55 +1177,27 @@ void load_editMesh(void) i++; efa= efa->next; } - - /* tface block */ - if( me->tface && me->totface ) { - TFace *tfn, *tf; - - tf=tfn= MEM_callocN(sizeof(TFace)*me->totface, "tface"); - efa= em->faces.first; - while(efa) { - - *tf= efa->tf; - - if(G.f & G_FACESELECT) { - if( efa->h) tf->flag |= TF_HIDE; + + /* sync hide and select flags with faceselect mode */ + if(G.f & G_FACESELECT) { + if(me->tface && (me->totface > 0)) { + efa= em->faces.first; + for(a=0, efa=em->faces.first; efa; a++, efa++) { + tf = CustomData_get(&mfdata, a, LAYERTYPE_TFACE); + + if(efa->h) tf->flag |= TF_HIDE; else tf->flag &= ~TF_HIDE; - if( efa->f & SELECT) tf->flag |= TF_SELECT; + if(efa->f & SELECT) tf->flag |= TF_SELECT; else tf->flag &= ~TF_SELECT; } - - tf++; - efa= efa->next; } + } - if(me->tface) MEM_freeN(me->tface); - me->tface= tfn; - } - else if(me->tface) { - MEM_freeN(me->tface); - me->tface= NULL; - } - - /* mcol: same as tface... */ - if(me->mcol && me->totface) { - unsigned int *mcn, *mc; + /* from CustomData to tface and mcol in Mesh */ + me->tface = CustomData_get(&mfdata, 0, LAYERTYPE_TFACE); + me->mcol = CustomData_get(&mfdata, 0, LAYERTYPE_MCOL); - mc=mcn= MEM_mallocN(4*sizeof(int)*me->totface, "mcol"); - efa= em->faces.first; - while(efa) { - memcpy(mc, efa->tf.col, 4*sizeof(int)); - - mc+=4; - efa= efa->next; - } - if(me->mcol) MEM_freeN(me->mcol); - me->mcol= (MCol *)mcn; - } - else if(me->mcol) { - MEM_freeN(me->mcol); - me->mcol= 0; - } + CustomData_free(&mfdata); /* patch hook indices */ { @@ -1576,6 +1566,7 @@ void separate_mesh(void) emcopy.alledges= NULL; emcopy.allfaces= NULL; emcopy.derivedFinal= emcopy.derivedCage= NULL; + memset(&emcopy.fdata, 0, sizeof(emcopy.fdata)); free_editMesh(&emcopy); em->verts= edve; @@ -1769,6 +1760,7 @@ void separate_mesh_loose(void) emcopy.alledges= NULL; emcopy.allfaces= NULL; emcopy.derivedFinal= emcopy.derivedCage= NULL; + memset(&emcopy.fdata, 0, sizeof(emcopy.fdata)); free_editMesh(&emcopy); em->verts= edve; @@ -1839,14 +1831,13 @@ typedef struct UndoMesh { EditEdgeC *edges; EditFaceC *faces; EditSelectionC *selected; - TFace *tfaces; - int totvert, totedge, totface,totsel; + int totvert, totedge, totface, totsel; short selectmode; RetopoPaintData *retopo_paint_data; char retopo_mode; + CustomData fdata; } UndoMesh; - /* for callbacks */ static void free_undoMesh(void *umv) @@ -1862,9 +1853,9 @@ static void free_undoMesh(void *umv) if(um->verts) MEM_freeN(um->verts); if(um->edges) MEM_freeN(um->edges); if(um->faces) MEM_freeN(um->faces); - if(um->tfaces) MEM_freeN(um->tfaces); if(um->selected) MEM_freeN(um->selected); if(um->retopo_paint_data) retopo_free_paint_data(um->retopo_paint_data); + CustomData_free(&um->fdata); MEM_freeN(um); } @@ -1872,7 +1863,6 @@ static void *editMesh_to_undoMesh(void) { EditMesh *em= G.editMesh; UndoMesh *um; - Mesh *me= G.obedit->data; EditVert *eve; EditEdge *eed; EditFace *efa; @@ -1881,7 +1871,6 @@ static void *editMesh_to_undoMesh(void) EditEdgeC *eedc=NULL; EditFaceC *efac=NULL; EditSelectionC *esec=NULL; - TFace *tface= NULL; int a; um= MEM_callocN(sizeof(UndoMesh), "undomesh"); @@ -1898,11 +1887,8 @@ static void *editMesh_to_undoMesh(void) if(um->totedge) eedc= um->edges= MEM_callocN(um->totedge*sizeof(EditEdgeC), "alledgesC"); if(um->totface) efac= um->faces= MEM_callocN(um->totface*sizeof(EditFaceC), "allfacesC"); if(um->totsel) esec= um->selected= MEM_callocN(um->totsel*sizeof(EditSelectionC), "allselections"); - - if(me->tface || me->mcol) tface= um->tfaces= MEM_mallocN(um->totface*sizeof(TFace), "all tfacesC"); - //printf("copy editmesh %d\n", um->totvert*sizeof(EditVert) + um->totedge*sizeof(EditEdge) + um->totface*sizeof(EditFace)); - //printf("copy undomesh %d\n", um->totvert*sizeof(EditVertC) + um->totedge*sizeof(EditEdgeC) + um->totface*sizeof(EditFaceC)); + if(um->totface) CustomData_from_template(&em->fdata, &um->fdata, 0, um->totface); /* now copy vertices */ a = 0; @@ -1946,12 +1932,10 @@ static void *editMesh_to_undoMesh(void) efac->f= efa->f; efac->h= efa->h; efac->fgonf= efa->fgonf; - - if(tface) { - *tface= efa->tf; - tface++; - } + efa->tmp.l = a; /*store index*/ + + CustomData_from_em_block(&em->fdata, &um->fdata, efa->data, a); } a = 0; @@ -1980,7 +1964,6 @@ static void undoMesh_to_editMesh(void *umv) EditEdgeC *eedc; EditFaceC *efac; EditSelectionC *esec; - TFace *tface; int a=0; #ifdef WITH_VERSE @@ -2031,7 +2014,9 @@ static void undoMesh_to_editMesh(void *umv) } /* copy faces */ - tface= um->tfaces; + CustomData_free(&em->fdata); + CustomData_from_template(&um->fdata, &em->fdata, 0, 0); + for(a=0, efac= um->faces; atotface; a++, efac++) { if(efac->v4 != -1) efa= addfacelist(evar[efac->v1], evar[efac->v2], evar[efac->v3], evar[efac->v4], NULL, NULL); @@ -2044,10 +2029,7 @@ static void undoMesh_to_editMesh(void *umv) efa->h= efac->h; efa->fgonf= efac->fgonf; - if(tface) { - efa->tf= *tface; - tface++; - } + CustomData_to_em_block(&um->fdata, &em->fdata, a, &efa->data); } end_editmesh_fastmalloc(); diff --git a/source/blender/src/editmesh_lib.c b/source/blender/src/editmesh_lib.c index 2f742d8e985..ca03dcef555 100644 --- a/source/blender/src/editmesh_lib.c +++ b/source/blender/src/editmesh_lib.c @@ -57,6 +57,7 @@ editmesh_lib: generic (no UI, no menus) operations/evaluators for editmesh data #include "BLI_arithb.h" #include "BLI_editVert.h" +#include "BKE_customdata.h" #include "BKE_global.h" #include "BKE_mesh.h" #include "BKE_utildefines.h" @@ -708,6 +709,44 @@ void EM_hide_reset(void) } +void EM_interp_from_faces(EditFace *efa1, EditFace *efa2, EditFace *efan, int i1, int i2, int i3, int i4) +{ + EditMesh *em= G.editMesh; + float w[2][4][4]; + void *src[2]; + int count = (efa2)? 2: 1; + + /* set weights for copying from corners directly to other corners */ + memset(w, 0, sizeof(w)); + + w[i1/4][0][i1%4]= 1.0f; + w[i2/4][1][i2%4]= 1.0f; + w[i3/4][2][i3%4]= 1.0f; + if (i4 != -1) + w[i4/4][3][i4%4]= 1.0f; + + src[0]= efa1->data; + src[1]= (efa2)? efa2->data: NULL; + + CustomData_em_interp(&em->fdata, src, NULL, (float*)w, count, efan->data); +} + +EditFace *EM_face_from_faces(EditFace *efa1, EditFace *efa2, int i1, int i2, int i3, int i4) +{ + EditFace *efan; + EditVert **v[2]; + + v[0]= &efa1->v1; + v[1]= (efa2)? &efa2->v1: NULL; + + efan= addfacelist(v[i1/4][i1%4], v[i2/4][i2%4], v[i3/4][i3%4], + (i4 == -1)? 0: v[i4/4][i4%4], efa1, NULL); + + if (efa1->data) + EM_interp_from_faces(efa1, efa2, efan, i1, i2, i3, i4); + + return efan; +} /* ******** EXTRUDE ********* */ @@ -1442,8 +1481,8 @@ short extrudeflag_vert(short flag, float *nor) if(eed->tmp.f) { efa = eed->tmp.f; efa2->mat_nr= efa->mat_nr; - efa2->tf= efa->tf; efa2->flag= efa->flag; + CustomData_em_copy_data(&em->fdata, &efa->data, &efa2->data); } /* Needs smarter adaption of existing creases. @@ -1761,18 +1800,15 @@ void flipface(EditFace *efa) SWAP(EditVert *, efa->v2, efa->v4); SWAP(EditEdge *, efa->e1, efa->e4); SWAP(EditEdge *, efa->e2, efa->e3); - SWAP(unsigned int, efa->tf.col[1], efa->tf.col[3]); - SWAP(float, efa->tf.uv[1][0], efa->tf.uv[3][0]); - SWAP(float, efa->tf.uv[1][1], efa->tf.uv[3][1]); + EM_interp_from_faces(efa, NULL, efa, 0, 3, 2, 1); } else { SWAP(EditVert *, efa->v2, efa->v3); SWAP(EditEdge *, efa->e1, efa->e3); - SWAP(unsigned int, efa->tf.col[1], efa->tf.col[2]); efa->e2->dir= 1-efa->e2->dir; - SWAP(float, efa->tf.uv[1][0], efa->tf.uv[2][0]); - SWAP(float, efa->tf.uv[1][1], efa->tf.uv[2][1]); + EM_interp_from_faces(efa, NULL, efa, 0, 2, 1, 3); } + if(efa->v4) CalcNormFloat4(efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co, efa->n); else CalcNormFloat(efa->v1->co, efa->v2->co, efa->v3->co, efa->n); } diff --git a/source/blender/src/editmesh_mods.c b/source/blender/src/editmesh_mods.c index d0e9302f82b..c5958be912b 100644 --- a/source/blender/src/editmesh_mods.c +++ b/source/blender/src/editmesh_mods.c @@ -62,6 +62,7 @@ editmesh_mods.c, UI level access, no geometry changes #include "BKE_displist.h" #include "BKE_depsgraph.h" #include "BKE_DerivedMesh.h" +#include "BKE_customdata.h" #include "BKE_global.h" #include "BKE_mesh.h" #include "BKE_material.h" @@ -824,13 +825,26 @@ int facegroup_select(short mode) } } } else if (mode==2) { /* same image */ + TFace *tf, *base_tf; + + base_tf = (TFace*)CustomData_em_get(&em->fdata, base_efa->data, + LAYERTYPE_TFACE); + + if(!base_tf) + return selcount; + for(efa= em->faces.first; efa; efa= efa->next) { - if (!(efa->f & SELECT) && !efa->h && base_efa->tf.tpage == efa->tf.tpage) { - EM_select_face(efa, 1); - selcount++; - deselcount--; - if (!deselcount) /*have we selected all posible faces?, if so return*/ - return selcount; + if (!(efa->f & SELECT) && !efa->h) { + tf = (TFace*)CustomData_em_get(&em->fdata, efa->data, + LAYERTYPE_TFACE); + + if(base_tf->tpage == tf->tpage) { + EM_select_face(efa, 1); + selcount++; + deselcount--; + if (!deselcount) /*have we selected all posible faces?, if so return*/ + return selcount; + } } } } else if (mode==3 || mode==4) { /* same area OR same perimeter, both use the same temp var */ @@ -2888,17 +2902,6 @@ static int tface_is_selected(TFace *tf) return (!(tf->flag & TF_HIDE) && (tf->flag & TF_SELECT)); } -static int faceselect_nfaces_selected(Mesh *me) -{ - int i, count= 0; - - for (i=0; itotface; i++) - if (tface_is_selected(&me->tface[i])) - count++; - - return count; -} - /* XXX, code for both these functions should be abstract, * then unified, then written for other things (like objects, * which would use same as vertices method), then added @@ -2906,38 +2909,39 @@ static int faceselect_nfaces_selected(Mesh *me) */ void faceselect_align_view_to_selected(View3D *v3d, Mesh *me, int axis) { - if (!faceselect_nfaces_selected(me)) { - error("No faces selected."); - } else { - float norm[3]; - int i; + float norm[3]; + int i, totselected = 0; - norm[0]= norm[1]= norm[2]= 0.0; - for (i=0; itotface; i++) { - MFace *mf= ((MFace*) me->mface) + i; - TFace *tf= ((TFace*) me->tface) + i; - - if (tface_is_selected(tf)) { - float *v1, *v2, *v3, fno[3]; + norm[0]= norm[1]= norm[2]= 0.0; + for (i=0; itotface; i++) { + MFace *mf= ((MFace*) me->mface) + i; + TFace *tf= ((TFace*) me->tface) + i; - v1= me->mvert[mf->v1].co; - v2= me->mvert[mf->v2].co; - v3= me->mvert[mf->v3].co; - if (mf->v4) { - float *v4= me->mvert[mf->v4].co; - CalcNormFloat4(v1, v2, v3, v4, fno); - } else { - CalcNormFloat(v1, v2, v3, fno); - } + if (tface_is_selected(tf)) { + float *v1, *v2, *v3, fno[3]; - norm[0]+= fno[0]; - norm[1]+= fno[1]; - norm[2]+= fno[2]; + v1= me->mvert[mf->v1].co; + v2= me->mvert[mf->v2].co; + v3= me->mvert[mf->v3].co; + if (mf->v4) { + float *v4= me->mvert[mf->v4].co; + CalcNormFloat4(v1, v2, v3, v4, fno); + } else { + CalcNormFloat(v1, v2, v3, fno); } - } - view3d_align_axis_to_vector(v3d, axis, norm); + norm[0]+= fno[0]; + norm[1]+= fno[1]; + norm[2]+= fno[2]; + + totselected++; + } } + + if (totselected == 0) + error("No faces selected."); + else + view3d_align_axis_to_vector(v3d, axis, norm); } void editmesh_align_view_to_selected(View3D *v3d, int axis) diff --git a/source/blender/src/editmesh_tools.c b/source/blender/src/editmesh_tools.c index 33f47fe76dd..2d10f93ef1c 100644 --- a/source/blender/src/editmesh_tools.c +++ b/source/blender/src/editmesh_tools.c @@ -66,6 +66,7 @@ editmesh_tool.c: UI called tools for editmesh, geometry changes here, otherwise #include "BLI_heap.h" #include "BKE_depsgraph.h" +#include "BKE_customdata.h" #include "BKE_global.h" #include "BKE_library.h" #include "BKE_mesh.h" @@ -163,41 +164,16 @@ void convert_to_triface(int direction) fac= VecLenf(efa->v1->co, efa->v3->co) - VecLenf(efa->v2->co, efa->v4->co); /* this makes sure exact squares get split different in both cases */ if( (direction==0 && fac0.0f) ) { - - efan= addfacelist(efa->v1, efa->v2, efa->v3, 0, efa, NULL); + efan= EM_face_from_faces(efa, NULL, 0, 1, 2, -1); if(efa->f & SELECT) EM_select_face(efan, 1); - efan= addfacelist(efa->v1, efa->v3, efa->v4, 0, efa, NULL); + efan= EM_face_from_faces(efa, NULL, 0, 2, 3, -1); if(efa->f & SELECT) EM_select_face(efan, 1); - - efan->tf.uv[1][0]= efan->tf.uv[2][0]; - efan->tf.uv[1][1]= efan->tf.uv[2][1]; - efan->tf.uv[2][0]= efan->tf.uv[3][0]; - efan->tf.uv[2][1]= efan->tf.uv[3][1]; - - efan->tf.col[1]= efan->tf.col[2]; - efan->tf.col[2]= efan->tf.col[3]; } else { - efan= addfacelist(efa->v1, efa->v2, efa->v4, 0, efa, NULL); + efan= EM_face_from_faces(efa, NULL, 0, 1, 3, -1); if(efa->f & SELECT) EM_select_face(efan, 1); - - efan->tf.uv[2][0]= efan->tf.uv[3][0]; - efan->tf.uv[2][1]= efan->tf.uv[3][1]; - efan->tf.col[2]= efan->tf.col[3]; - - efan= addfacelist(efa->v2, efa->v3, efa->v4, 0, efa, NULL); + efan= EM_face_from_faces(efa, NULL, 1, 2, 3, -1); if(efa->f & SELECT) EM_select_face(efan, 1); - - efan->tf.uv[0][0]= efan->tf.uv[1][0]; - efan->tf.uv[0][1]= efan->tf.uv[1][1]; - efan->tf.uv[1][0]= efan->tf.uv[2][0]; - efan->tf.uv[1][1]= efan->tf.uv[2][1]; - efan->tf.uv[2][0]= efan->tf.uv[3][0]; - efan->tf.uv[2][1]= efan->tf.uv[3][1]; - - efan->tf.col[0]= efan->tf.col[1]; - efan->tf.col[1]= efan->tf.col[2]; - efan->tf.col[2]= efan->tf.col[3]; } BLI_remlink(&em->faces, efa); @@ -217,7 +193,6 @@ void convert_to_triface(int direction) } - int removedoublesflag(short flag, float limit) /* return amount */ { EditMesh *em = G.editMesh; @@ -395,15 +370,11 @@ int removedoublesflag(short flag, float limit) /* return amount */ if(efa->v4) { if(test==1 || test==2) { efa->v2= efa->v3; - efa->tf.uv[1][0] = efa->tf.uv[2][0]; - efa->tf.uv[1][1] = efa->tf.uv[2][1]; - efa->tf.col[1] = efa->tf.col[2]; - efa->v3= efa->v4; - efa->tf.uv[2][0] = efa->tf.uv[3][0]; - efa->tf.uv[2][1] = efa->tf.uv[3][1]; - efa->tf.col[2] = efa->tf.col[3]; efa->v4= 0; + + EM_interp_from_faces(efa, NULL, efa, 0, 2, 3, 3); + test= 0; } else if(test==8 || test==16) { @@ -1424,21 +1395,21 @@ static void facecopy(EditFace *source, EditFace *target) { float *v1 = source->v1->co, *v2 = source->v2->co, *v3 = source->v3->co; float *v4 = source->v4? source->v4->co: NULL; + float w[4][4]; - interp_uv_vcol(v1, v2, v3, v4, target->v1->co, &source->tf, &target->tf, 0); - interp_uv_vcol(v1, v2, v3, v4, target->v2->co, &source->tf, &target->tf, 1); - interp_uv_vcol(v1, v2, v3, v4, target->v3->co, &source->tf, &target->tf, 2); + CustomData_em_copy_data(&G.editMesh->fdata, source->data, &target->data); + + target->mat_nr = source->mat_nr; + target->flag = source->flag; + + InterpWeightsQ3Dfl(v1, v2, v3, v4, target->v1->co, w[0]); + InterpWeightsQ3Dfl(v1, v2, v3, v4, target->v2->co, w[1]); + InterpWeightsQ3Dfl(v1, v2, v3, v4, target->v3->co, w[2]); if (target->v4) - interp_uv_vcol(v1, v2, v3, v4, target->v4->co, &source->tf, &target->tf, 3); - - target->mat_nr = source->mat_nr; - target->tf.flag = source->tf.flag&~TF_ACTIVE; - target->tf.transp = source->tf.transp; - target->tf.mode = source->tf.mode; - target->tf.tile = source->tf.tile; - target->tf.unwrap = source->tf.unwrap; - target->tf.tpage = source->tf.tpage; - target->flag = source->flag; + InterpWeightsQ3Dfl(v1, v2, v3, v4, target->v4->co, w[3]); + + CustomData_em_interp(&G.editMesh->fdata, &source->data, NULL, + (float*)w, 1, target->data); } static void fill_quad_single(EditFace *efa, struct GHash *gh, int numcuts, int seltype) @@ -1972,7 +1943,7 @@ static void fill_tri_double(EditFace *efa, struct GHash *gh, int numcuts) static void fill_quad_triple(EditFace *efa, struct GHash *gh, int numcuts) { - EditEdge *cedge[3]; + EditEdge *cedge[3]={0}; EditVert *v[4], **verts[3]; EditFace *hold; short start=0, start2=0, start3=0, vertsize, i, repeats; @@ -2924,99 +2895,47 @@ static int collect_quadedges(EVPTuple *efaa, EditEdge *eed, EditFace *efa) #define VTEST(face, num, other) \ (face->v##num != other->v1 && face->v##num != other->v2 && face->v##num != other->v3) -static void givequadverts(EditFace *efa, EditFace *efa1, EditVert **v1, EditVert **v2, EditVert **v3, EditVert **v4, float **uv, unsigned int *col) +static void givequadverts(EditFace *efa, EditFace *efa1, EditVert **v1, EditVert **v2, EditVert **v3, EditVert **v4, int *vindex) { if VTEST(efa, 1, efa1) { - //if(efa->v1!=efa1->v1 && efa->v1!=efa1->v2 && efa->v1!=efa1->v3) { *v1= efa->v1; *v2= efa->v2; - uv[0] = efa->tf.uv[0]; - uv[1] = efa->tf.uv[1]; - col[0] = efa->tf.col[0]; - col[1] = efa->tf.col[1]; + vindex[0]= 0; + vindex[1]= 1; } else if VTEST(efa, 2, efa1) { - //else if(efa->v2!=efa1->v1 && efa->v2!=efa1->v2 && efa->v2!=efa1->v3) { *v1= efa->v2; *v2= efa->v3; - uv[0] = efa->tf.uv[1]; - uv[1] = efa->tf.uv[2]; - col[0] = efa->tf.col[1]; - col[1] = efa->tf.col[2]; + vindex[0]= 1; + vindex[1]= 2; } else if VTEST(efa, 3, efa1) { - // else if(efa->v3!=efa1->v1 && efa->v3!=efa1->v2 && efa->v3!=efa1->v3) { *v1= efa->v3; *v2= efa->v1; - uv[0] = efa->tf.uv[2]; - uv[1] = efa->tf.uv[0]; - col[0] = efa->tf.col[2]; - col[1] = efa->tf.col[0]; + vindex[0]= 2; + vindex[1]= 0; } if VTEST(efa1, 1, efa) { - // if(efa1->v1!=efa->v1 && efa1->v1!=efa->v2 && efa1->v1!=efa->v3) { *v3= efa1->v1; - uv[2] = efa1->tf.uv[0]; - col[2] = efa1->tf.col[0]; - *v4= efa1->v2; - uv[3] = efa1->tf.uv[1]; - col[3] = efa1->tf.col[1]; -/* -if(efa1->v2== *v2) { - *v4= efa1->v3; - uv[3] = efa1->tf.uv[2]; - } else { - *v4= efa1->v2; - uv[3] = efa1->tf.uv[1]; - } - */ + vindex[2]= 0; + vindex[3]= 1; } else if VTEST(efa1, 2, efa) { - // else if(efa1->v2!=efa->v1 && efa1->v2!=efa->v2 && efa1->v2!=efa->v3) { *v3= efa1->v2; - uv[2] = efa1->tf.uv[1]; - col[2] = efa1->tf.col[1]; - *v4= efa1->v3; - uv[3] = efa1->tf.uv[2]; - col[3] = efa1->tf.col[2]; -/* -if(efa1->v3== *v2) { - *v4= efa1->v1; - uv[3] = efa1->tf.uv[0]; - } else { - *v4= efa1->v3; - uv[3] = efa1->tf.uv[2]; - } - */ + vindex[2]= 1; + vindex[3]= 2; } else if VTEST(efa1, 3, efa) { - // else if(efa1->v3!=efa->v1 && efa1->v3!=efa->v2 && efa1->v3!=efa->v3) { *v3= efa1->v3; - uv[2] = efa1->tf.uv[2]; - col[2] = efa1->tf.col[2]; - *v4= efa1->v1; - uv[3] = efa1->tf.uv[0]; - col[3] = efa1->tf.col[0]; -/* -if(efa1->v1== *v2) { - *v4= efa1->v2; - uv[3] = efa1->tf.uv[3]; - } else { - *v4= efa1->v1; - uv[3] = efa1->tf.uv[0]; - } - */ + vindex[2]= 2; + vindex[3]= 0; } - else { + else *v3= *v4= NULL; - - return; - } - } /* Helper functions for edge/quad edit features*/ @@ -3071,10 +2990,8 @@ void beauty_fill(void) // void **efaar, **efaa; EVPTuple *efaar; EVPtr *efaa; - float *uv[4]; - unsigned int col[4]; float len1, len2, len3, len4, len5, len6, opp1, opp2, fac1, fac2; - int totedge, ok, notbeauty=8, onedone; + int totedge, ok, notbeauty=8, onedone, vindex[4]; /* - all selected edges with two faces * - find the faces: store them in edges (using datablock) @@ -3121,7 +3038,7 @@ void beauty_fill(void) if(ok) { /* test convex */ - givequadverts(efaa[0], efaa[1], &v1, &v2, &v3, &v4, uv, col); + givequadverts(efaa[0], efaa[1], &v1, &v2, &v3, &v4, vindex); if(v1 && v2 && v3 && v4) { if( convex(v1->co, v2->co, v3->co, v4->co) ) { @@ -3174,22 +3091,14 @@ void beauty_fill(void) efa= efaa[1]; efa->f1= 1; - w= addfacelist(v1, v2, v3, 0, efa, NULL); - w->f |= SELECT; - - UVCOPY(w->tf.uv[0], uv[0]); - UVCOPY(w->tf.uv[1], uv[1]); - UVCOPY(w->tf.uv[2], uv[2]); - - w->tf.col[0] = col[0]; w->tf.col[1] = col[1]; w->tf.col[2] = col[2]; - w= addfacelist(v1, v3, v4, 0, efa, NULL); + w= EM_face_from_faces(efaa[0], efaa[1], + vindex[0], vindex[1], 4+vindex[2], -1); w->f |= SELECT; - UVCOPY(w->tf.uv[0], uv[0]); - UVCOPY(w->tf.uv[1], uv[2]); - UVCOPY(w->tf.uv[2], uv[3]); - w->tf.col[0] = col[0]; w->tf.col[1] = col[2]; w->tf.col[2] = col[3]; + w= EM_face_from_faces(efaa[0], efaa[1], + vindex[0], 4+vindex[2], 4+vindex[3], -1); + w->f |= SELECT; onedone= 1; } @@ -3202,20 +3111,16 @@ void beauty_fill(void) efa= efaa[1]; efa->f1= 1; - w= addfacelist(v2, v3, v4, 0, efa, NULL); + + w= EM_face_from_faces(efaa[0], efaa[1], + vindex[1], 4+vindex[2], 4+vindex[3], -1); w->f |= SELECT; - UVCOPY(w->tf.uv[0], uv[1]); - UVCOPY(w->tf.uv[1], uv[3]); - UVCOPY(w->tf.uv[2], uv[4]); - w= addfacelist(v1, v2, v4, 0, efa, NULL); + w= EM_face_from_faces(efaa[0], efaa[1], + vindex[0], 4+vindex[1], 4+vindex[3], -1); w->f |= SELECT; - UVCOPY(w->tf.uv[0], uv[0]); - UVCOPY(w->tf.uv[1], uv[1]); - UVCOPY(w->tf.uv[2], uv[3]); - onedone= 1; } } @@ -3414,10 +3319,15 @@ static int compareFaceUV(EditFace *f1, EditFace *f2) { EditVert **faceVert1, **faceVert2, *faceVerts1[5], *faceVerts2[5]; int i1, i2; + TFace *tf1, *tf2; + + tf1 = CustomData_em_get(&G.editMesh->fdata, f1->data, LAYERTYPE_TFACE); + tf2 = CustomData_em_get(&G.editMesh->fdata, f2->data, LAYERTYPE_TFACE); - if(f1->tf.tpage == NULL && f2->tf.tpage == NULL) + if(tf1 == NULL || tf2 == NULL) return 1; + else if(tf1->tpage == NULL && tf2->tpage == NULL) return 1; - else if(f1->tf.tpage != f2->tf.tpage) + else if(tf1->tpage != tf2->tpage) return 0; FILL_FACEVERTS(f1, faceVerts1); @@ -3430,7 +3340,7 @@ static int compareFaceUV(EditFace *f1, EditFace *f2) i2 = 0; while(*faceVert2){ if( *faceVert1 == *faceVert2){ - if(!compare2(f1->tf.uv[i1], f2->tf.uv[i2], UV_LIMIT)) + if(!compare2(tf1->uv[i1], tf2->uv[i2], UV_LIMIT)) return 0; } i2++; @@ -3447,6 +3357,18 @@ static int compareFaceCol(EditFace *f1, EditFace *f2) { EditVert **faceVert1, **faceVert2, *faceVerts1[5], *faceVerts2[5]; int i1, i2; + TFace *tf1, *tf2; + unsigned int *col1, *col2; + + tf1 = CustomData_em_get(&G.editMesh->fdata, f1->data, LAYERTYPE_TFACE); + tf2 = CustomData_em_get(&G.editMesh->fdata, f2->data, LAYERTYPE_TFACE); + + if(tf1) col1 = tf1->col; + else col1 = CustomData_em_get(&G.editMesh->fdata, f1->data, LAYERTYPE_MCOL); + if(tf2) col2 = tf2->col; + else col2 = CustomData_em_get(&G.editMesh->fdata, f2->data, LAYERTYPE_MCOL); + + if(!col1 || !col2) return 1; FILL_FACEVERTS(f1, faceVerts1); FILL_FACEVERTS(f2, faceVerts2); @@ -3458,7 +3380,7 @@ static int compareFaceCol(EditFace *f1, EditFace *f2) i2 = 0; while(*faceVert2){ if( *faceVert1 == *faceVert2){ - if(!compare3(f1->tf.col[i1], f2->tf.col[i2], COL_LIMIT)) + if(!compare3(col1[i1], col2[i2], COL_LIMIT)) return 0; } i2++; @@ -3475,7 +3397,6 @@ static void meshJoinFaces(EditEdge *joined) FacePairL *fpl = joined->tmp.p; EditFace *face1, *face2, *efa; EditVert *v1free, *v2free; - int i; face1 = fpl->face1; face2 = fpl->face2; @@ -3490,75 +3411,12 @@ static void meshJoinFaces(EditEdge *joined) face2->v2->f1 = 1; face2->v3->f1 = 2; -switch(v1free->f1){ - case 0: - i = 2; - break; - case 1: - i = 3; - break; - case 2: - i = 1; - break; - } - - switch(i){ - case 2: - /*this is really lazy...*/ - efa = addfacelist(face1->v1, face1->v2, v2free, face1->v3, face1, NULL); - efa->tf.uv[0][0] = face1->tf.uv[0][0]; - efa->tf.uv[0][1] = face1->tf.uv[0][1]; - efa->tf.col[0] = face1->tf.col[0]; - - efa->tf.uv[1][0] = face1->tf.uv[1][0]; - efa->tf.uv[1][1] = face1->tf.uv[1][1]; - efa->tf.col[1] = face1->tf.col[1]; - - efa->tf.uv[2][0] = face2->tf.uv[v2free->f1][0]; - efa->tf.uv[2][1] = face2->tf.uv[v2free->f1][1]; - efa->tf.col[2] = face2->tf.col[v2free->f1]; - - efa->tf.uv[3][0] = face1->tf.uv[2][0]; - efa->tf.uv[3][1] = face1->tf.uv[2][1]; - efa->tf.col[3] = face1->tf.col[2]; - break; - case 3: - efa = addfacelist(face1->v1, face1->v2, face1->v3, v2free, face1, NULL); - efa->tf.uv[0][0] = face1->tf.uv[0][0]; - efa->tf.uv[0][1] = face1->tf.uv[0][1]; - efa->tf.col[0] = face1->tf.col[0]; - - efa->tf.uv[1][0] = face1->tf.uv[1][0]; - efa->tf.uv[1][1] = face1->tf.uv[1][1]; - efa->tf.col[1] = face1->tf.col[1]; - - efa->tf.uv[2][0] = face1->tf.uv[2][0]; - efa->tf.uv[2][1] = face1->tf.uv[2][1]; - efa->tf.col[2] = face1->tf.col[2]; - - efa->tf.uv[3][0] = face2->tf.uv[v2free->f1][0]; - efa->tf.uv[3][1] = face2->tf.uv[v2free->f1][1]; - efa->tf.col[3] = face1->tf.col[v2free->f1]; - break; - case 1: - efa = addfacelist(face1->v1, v2free, face1->v2, face1->v3, face1, NULL); - efa->tf.uv[0][0] = face1->tf.uv[0][0]; - efa->tf.uv[0][1] = face1->tf.uv[0][1]; - efa->tf.col[0] = face1->tf.col[0]; - - efa->tf.uv[1][0] = face2->tf.uv[v2free->f1][0]; - efa->tf.uv[1][1] = face2->tf.uv[v2free->f1][1]; - efa->tf.col[1] = face2->tf.col[v2free->f1]; - - efa->tf.uv[2][0] = face1->tf.uv[1][0]; - efa->tf.uv[2][1] = face1->tf.uv[1][1]; - efa->tf.col[2] = face1->tf.col[1]; - - efa->tf.uv[3][0] = face1->tf.uv[2][0]; - efa->tf.uv[3][1] = face1->tf.uv[2][1]; - efa->tf.col[3] = face1->tf.col[2]; - break; - } + if(v1free->f1 == 0) + efa= EM_face_from_faces(face1, face2, 0, 1, 4+v2free->f1, 2); + else if(v1free->f1 == 1) + efa= EM_face_from_faces(face1, face2, 0, 1, 2, 4+v2free->f1); + else /* if(v1free->f1 == 2) */ + efa= EM_face_from_faces(face1, face2, 0, 4+v2free->f1, 1, 2); EM_select_face(efa,1); /*flag for removal*/ @@ -3771,11 +3629,7 @@ void edge_flip(void) //void **efaar, **efaa; EVPTuple *efaar; EVPtr *efaa; - - float *uv[4]; - unsigned int col[4]; - - int totedge, ok; + int totedge, ok, vindex[4]; /* - all selected edges with two faces * - find the faces: store them in edges (using datablock) @@ -3812,7 +3666,7 @@ void edge_flip(void) if(ok) { /* test convex */ - givequadverts(efaa[0], efaa[1], &v1, &v2, &v3, &v4, uv, col); + givequadverts(efaa[0], efaa[1], &v1, &v2, &v3, &v4, vindex); /* 4-----3 4-----3 @@ -3827,27 +3681,19 @@ void edge_flip(void) if (v1 && v2 && v3) { if( convex(v1->co, v2->co, v3->co, v4->co) ) { if(exist_face(v1, v2, v3, v4)==0) { - w = addfacelist(v1, v2, v3, 0, efaa[1], NULL); /* outch this may break seams */ + /* outch this may break seams */ + w= EM_face_from_faces(efaa[0], efaa[1], vindex[0], + vindex[1], 4+vindex[2], -1); + EM_select_face(w, 1); untag_edges(w); - UVCOPY(w->tf.uv[0], uv[0]); - UVCOPY(w->tf.uv[1], uv[1]); - UVCOPY(w->tf.uv[2], uv[2]); + /* outch this may break seams */ + w= EM_face_from_faces(efaa[0], efaa[1], vindex[0], + 4+vindex[2], 4+vindex[3], -1); - w->tf.col[0] = col[0]; w->tf.col[1] = col[1]; w->tf.col[2] = col[2]; - - w = addfacelist(v1, v3, v4, 0, efaa[1], NULL); /* outch this may break seams */ EM_select_face(w, 1); untag_edges(w); - - UVCOPY(w->tf.uv[0], uv[0]); - UVCOPY(w->tf.uv[1], uv[2]); - UVCOPY(w->tf.uv[2], uv[3]); - - w->tf.col[0] = col[0]; w->tf.col[1] = col[2]; w->tf.col[2] = col[3]; - - /* erase old faces and edge */ } /* tag as to-be-removed */ FACE_MARKCLEAR(efaa[1]); @@ -3880,326 +3726,153 @@ void edge_flip(void) static void edge_rotate(EditEdge *eed,int dir) { EditMesh *em = G.editMesh; + EditVert **verts[2]; EditFace *face[2], *efa, *newFace[2]; - EditVert *faces[2][4],*v1,*v2,*v3,*v4,*vtemp; - EditEdge *srchedge = NULL; - short facecount=0, p1=0,p2=0,p3=0,p4=0,fac1=4,fac2=4,i,j,numhidden; - EditEdge **hiddenedges; + EditEdge **edges[2], **hiddenedges, *srchedge; + int facecount, p1, p2, p3, p4, fac1, fac2, i, j; + int numhidden, numshared, p[2][4]; /* check to make sure that the edge is only part of 2 faces */ + facecount = 0; for(efa = em->faces.first;efa;efa = efa->next) { if((efa->e1 == eed || efa->e2 == eed) || (efa->e3 == eed || efa->e4 == eed)) { - if(facecount == 2) { + if(facecount >= 2) { + /* more than two faces with this edge */ return; } - if(facecount < 2) + else { face[facecount] = efa; - facecount++; + facecount++; + } } } - if(facecount < 2) { + if(facecount < 2) return; - } /* how many edges does each face have */ - if(face[0]->e4 == NULL) - fac1=3; - else - fac1=4; - if(face[1]->e4 == NULL) - fac2=3; - else - fac2=4; - - /*store the face info in a handy array */ - faces[0][0] = face[0]->v1; - faces[0][1] = face[0]->v2; - faces[0][2] = face[0]->v3; - if(face[0]->e4 != NULL) - faces[0][3] = face[0]->v4; - else - faces[0][3] = NULL; - - faces[1][0] = face[1]->v1; - faces[1][1] = face[1]->v2; - faces[1][2] = face[1]->v3; - if(face[1]->e4 != NULL) - faces[1][3] = face[1]->v4; - else - faces[1][3] = NULL; + if(face[0]->e4) fac1= 4; + else fac1= 3; + + if(face[1]->e4) fac2= 4; + else fac2= 3; + /* make a handy array for verts and edges */ + verts[0]= &face[0]->v1; + edges[0]= &face[0]->e1; + verts[1]= &face[1]->v1; + edges[1]= &face[1]->e1; /* we don't want to rotate edges between faces that share more than one edge */ - - j=0; - if(face[0]->e1 == face[1]->e1 || - face[0]->e1 == face[1]->e2 || - face[0]->e1 == face[1]->e3 || - ((face[1]->e4) && face[0]->e1 == face[1]->e4) ) - j++; - - if(face[0]->e2 == face[1]->e1 || - face[0]->e2 == face[1]->e2 || - face[0]->e2 == face[1]->e3 || - ((face[1]->e4) && face[0]->e2 == face[1]->e4) ) - j++; - - if(face[0]->e3 == face[1]->e1 || - face[0]->e3 == face[1]->e2 || - face[0]->e3 == face[1]->e3 || - ((face[1]->e4) && face[0]->e3 == face[1]->e4) ) - j++; + numshared= 0; + for(i=0; ie4) { - if(face[0]->e4 == face[1]->e1 || - face[0]->e4 == face[1]->e2 || - face[0]->e4 == face[1]->e3 || - ((face[1]->e4) && face[0]->e4 == face[1]->e4) ) - j++; - } - if(j > 1) { + if(numshared > 1) return; - } - /* Coplaner Faces Only Please */ - if(Inpf(face[0]->n,face[1]->n) <= 0.000001) { + /* coplaner faces only please */ + if(Inpf(face[0]->n,face[1]->n) <= 0.000001) return; + + /* we want to construct an array of vertex indicis in both faces, starting at + the last vertex of the edge being rotated. + - first we find the two vertices that lie on the rotating edge + - then we make sure they are ordered according to the face vertex order + - and then we construct the array */ + p1= p2= p3= p4= 0; + + for(i=0; i<4; i++) { + if(eed->v1 == verts[0][i]) p1 = i; + if(eed->v2 == verts[0][i]) p2 = i; + if(eed->v1 == verts[1][i]) p3 = i; + if(eed->v2 == verts[1][i]) p4 = i; } - /*get the edges verts */ - v1 = eed->v1; - v2 = eed->v2; - v3 = eed->v1; - v4 = eed->v2; - - /*figure out where the edges verts lie one the 2 faces */ - for(i=0;i<4;i++) { - if(v1 == faces[0][i]) - p1 = i; - if(v2 == faces[0][i]) - p2 = i; - if(v1 == faces[1][i]) - p3 = i; - if(v2 == faces[1][i]) - p4 = i; - } + if((p1+1)%fac1 == p2) + SWAP(int, p1, p2); + if((p3+1)%fac2 == p4) + SWAP(int, p3, p4); - /*make sure the verts are in the correct order */ - if((p1+1)%fac1 == p2) { - vtemp = v2; - v2 = v1; - v1 = vtemp; - - i = p1; - p1 = p2; - p2 = i; + for (i = 0; i < 4; i++) { + p[0][i]= (p1 + i)%fac1; + p[1][i]= (p3 + i)%fac2; } - if((p3+1)%fac2 == p4) { - vtemp = v4; - v4 = v3; - v3 = vtemp; - - i = p3; - p3 = p4; - p4 = i; - } - - /* Create an Array of the Edges who have h set prior to rotate */ + /* create an Array of the Edges who have h set prior to rotate */ numhidden = 0; - for(srchedge = em->edges.first;srchedge;srchedge = srchedge->next) { - if(srchedge->h && (srchedge->v1->f & SELECT || srchedge->v2->f & SELECT)) { + for(srchedge = em->edges.first;srchedge;srchedge = srchedge->next) + if(srchedge->h && ((srchedge->v1->f & SELECT) || (srchedge->v2->f & SELECT))) numhidden++; - } - } - hiddenedges = MEM_mallocN(sizeof(EditVert*)*numhidden+1,"Hidden Vert Scratch Array for Rotate Edges"); + + hiddenedges = MEM_mallocN(sizeof(EditVert*)*numhidden+1, "RotateEdgeHiddenVerts"); if(!hiddenedges) { error("Malloc Was not happy!"); return; } + numhidden = 0; - for(srchedge = em->edges.first;srchedge;srchedge = srchedge->next) { - if(srchedge->h && (srchedge->v1->f & SELECT || srchedge->v2->f & SELECT)) { - hiddenedges[numhidden] = srchedge; - numhidden++; - } - } - - /* create the 2 new faces */ + for(srchedge=em->edges.first; srchedge; srchedge=srchedge->next) + if(srchedge->h && (srchedge->v1->f & SELECT || srchedge->v2->f & SELECT)) + hiddenedges[numhidden++] = srchedge; + + /* create the 2 new faces */ if(fac1 == 3 && fac2 == 3) { - /*No need of reverse setup*/ - newFace[0] = addfacelist(faces[0][(p1+1 )%3],faces[0][(p1+2 )%3],faces[1][(p3+1 )%3],NULL,NULL,NULL); - newFace[1] = addfacelist(faces[1][(p3+1 )%3],faces[1][(p3+2 )%3],faces[0][(p1+1 )%3],NULL,NULL,NULL); - - newFace[0]->tf.col[0] = face[0]->tf.col[(p1+1 )%3]; - newFace[0]->tf.col[1] = face[0]->tf.col[(p1+2 )%3]; - newFace[0]->tf.col[2] = face[1]->tf.col[(p3+1 )%3]; - newFace[1]->tf.col[0] = face[1]->tf.col[(p3+1 )%3]; - newFace[1]->tf.col[1] = face[1]->tf.col[(p3+2 )%3]; - newFace[1]->tf.col[2] = face[0]->tf.col[(p1+1 )%3]; - - UVCOPY(newFace[0]->tf.uv[0],face[0]->tf.uv[(p1+1 )%3]); - UVCOPY(newFace[0]->tf.uv[1],face[0]->tf.uv[(p1+2 )%3]); - UVCOPY(newFace[0]->tf.uv[2],face[1]->tf.uv[(p3+1 )%3]); - UVCOPY(newFace[1]->tf.uv[0],face[1]->tf.uv[(p3+1 )%3]); - UVCOPY(newFace[1]->tf.uv[1],face[1]->tf.uv[(p3+2 )%3]); - UVCOPY(newFace[1]->tf.uv[2],face[0]->tf.uv[(p1+1 )%3]); + /* no need of reverse setup */ + + newFace[0]= EM_face_from_faces(face[0], face[1], p[0][1], p[0][2], 4+p[1][1], -1); + newFace[1]= EM_face_from_faces(face[1], face[0], p[1][1], p[1][2], 4+p[0][1], -1); } else if(fac1 == 4 && fac2 == 3) { if(dir == 1) { - newFace[0] = addfacelist(faces[0][(p1+1 )%4],faces[0][(p1+2 )%4],faces[0][(p1+3 )%4],faces[1][(p3+1 )%3],NULL,NULL); - newFace[1] = addfacelist(faces[1][(p3+1 )%3],faces[1][(p3+2 )%3],faces[0][(p1+1 )%4],NULL,NULL,NULL); - - newFace[0]->tf.col[0] = face[0]->tf.col[(p1+1 )%4]; - newFace[0]->tf.col[1] = face[0]->tf.col[(p1+2 )%4]; - newFace[0]->tf.col[2] = face[0]->tf.col[(p1+3 )%4]; - newFace[0]->tf.col[3] = face[1]->tf.col[(p3+1 )%3]; - newFace[1]->tf.col[0] = face[1]->tf.col[(p3+1 )%3]; - newFace[1]->tf.col[1] = face[1]->tf.col[(p3+2 )%3]; - newFace[1]->tf.col[2] = face[0]->tf.col[(p1+1 )%4]; - - UVCOPY(newFace[0]->tf.uv[0],face[0]->tf.uv[(p1+1 )%4]); - UVCOPY(newFace[0]->tf.uv[1],face[0]->tf.uv[(p1+2 )%4]); - UVCOPY(newFace[0]->tf.uv[2],face[0]->tf.uv[(p1+3 )%4]); - UVCOPY(newFace[0]->tf.uv[3],face[1]->tf.uv[(p3+1 )%3]); - UVCOPY(newFace[1]->tf.uv[0],face[1]->tf.uv[(p3+1 )%3]); - UVCOPY(newFace[1]->tf.uv[1],face[1]->tf.uv[(p3+2 )%3]); - UVCOPY(newFace[1]->tf.uv[2],face[0]->tf.uv[(p1+1 )%4]); + newFace[0]= EM_face_from_faces(face[0], face[1], p[0][1], p[0][2], p[0][3], 4+p[1][1]); + newFace[1]= EM_face_from_faces(face[1], face[0], p[1][1], p[1][2], 4+p[0][1], -1); } else if (dir == 2) { - newFace[0] = addfacelist(faces[0][(p1+2 )%4],faces[1][(p3+1)%3],faces[0][(p1)%4],faces[0][(p1+1 )%4],NULL,NULL); - newFace[1] = addfacelist(faces[0][(p1+2 )%4],faces[1][(p3)%3],faces[1][(p3+1 )%3],NULL,NULL,NULL); - - newFace[0]->tf.col[0] = face[0]->tf.col[(p1+2)%4]; - newFace[0]->tf.col[1] = face[1]->tf.col[(p3+1)%3]; - newFace[0]->tf.col[2] = face[0]->tf.col[(p1 )%4]; - newFace[0]->tf.col[3] = face[0]->tf.col[(p1+1)%4]; - newFace[1]->tf.col[0] = face[0]->tf.col[(p1+2)%4]; - newFace[1]->tf.col[1] = face[1]->tf.col[(p3 )%3]; - newFace[1]->tf.col[2] = face[1]->tf.col[(p3+1)%3]; - - UVCOPY(newFace[0]->tf.uv[0],face[0]->tf.uv[(p1+2)%4]); - UVCOPY(newFace[0]->tf.uv[1],face[1]->tf.uv[(p3+1)%3]); - UVCOPY(newFace[0]->tf.uv[2],face[0]->tf.uv[(p1 )%4]); - UVCOPY(newFace[0]->tf.uv[3],face[0]->tf.uv[(p1+1)%4]); - UVCOPY(newFace[1]->tf.uv[0],face[0]->tf.uv[(p1+2)%4]); - UVCOPY(newFace[1]->tf.uv[1],face[1]->tf.uv[(p3 )%3]); - UVCOPY(newFace[1]->tf.uv[2],face[1]->tf.uv[(p3+1)%3]); + newFace[0]= EM_face_from_faces(face[0], face[1], p[0][2], 4+p[1][1], p[0][0], p[0][1]); + newFace[1]= EM_face_from_faces(face[1], face[0], 4+p[0][2], p[1][0], p[1][1], -1); - faces[0][(p1+2)%fac1]->f |= SELECT; - faces[1][(p3+1)%fac2]->f |= SELECT; + verts[0][p[0][2]]->f |= SELECT; + verts[1][p[1][1]]->f |= SELECT; } } - else if(fac1 == 3 && fac2 == 4) { if(dir == 1) { - newFace[0] = addfacelist(faces[0][(p1+1 )%3],faces[0][(p1+2 )%3],faces[1][(p3+1 )%4],NULL,NULL,NULL); - newFace[1] = addfacelist(faces[1][(p3+1 )%4],faces[1][(p3+2 )%4],faces[1][(p3+3 )%4],faces[0][(p1+1 )%3],NULL,NULL); - - newFace[0]->tf.col[0] = face[0]->tf.col[(p1+1 )%3]; - newFace[0]->tf.col[1] = face[0]->tf.col[(p1+2 )%3]; - newFace[0]->tf.col[2] = face[1]->tf.col[(p3+1 )%4]; - newFace[1]->tf.col[0] = face[1]->tf.col[(p3+1 )%4]; - newFace[1]->tf.col[1] = face[1]->tf.col[(p3+2 )%4]; - newFace[1]->tf.col[2] = face[1]->tf.col[(p3+3 )%4]; - newFace[1]->tf.col[3] = face[0]->tf.col[(p1+1 )%3]; - - UVCOPY(newFace[0]->tf.uv[0],face[0]->tf.uv[(p1+1 )%3]); - UVCOPY(newFace[0]->tf.uv[1],face[0]->tf.uv[(p1+2 )%3]); - UVCOPY(newFace[0]->tf.uv[2],face[1]->tf.uv[(p3+1 )%4]); - UVCOPY(newFace[1]->tf.uv[0],face[1]->tf.uv[(p3+1 )%4]); - UVCOPY(newFace[1]->tf.uv[1],face[1]->tf.uv[(p3+2 )%4]); - UVCOPY(newFace[1]->tf.uv[2],face[1]->tf.uv[(p3+3 )%4]); - UVCOPY(newFace[1]->tf.uv[3],face[0]->tf.uv[(p1+1 )%3]); + newFace[0]= EM_face_from_faces(face[0], face[1], p[0][1], p[0][2], 4+p[1][1], -1); + newFace[1]= EM_face_from_faces(face[1], face[0], p[1][1], p[1][2], p[1][3], 4+p[0][1]); } else if (dir == 2) { - newFace[0] = addfacelist(faces[0][(p1)%3],faces[0][(p1+1 )%3],faces[1][(p3+2 )%4],NULL,NULL,NULL); - newFace[1] = addfacelist(faces[1][(p3+1 )%4],faces[1][(p3+2 )%4],faces[0][(p1+1 )%3],faces[0][(p1+2 )%3],NULL,NULL); - - newFace[0]->tf.col[0] = face[0]->tf.col[(p1 )%3]; - newFace[0]->tf.col[1] = face[0]->tf.col[(p1+1 )%3]; - newFace[0]->tf.col[2] = face[1]->tf.col[(p3+2 )%4]; - newFace[1]->tf.col[0] = face[1]->tf.col[(p3+1 )%4]; - newFace[1]->tf.col[1] = face[1]->tf.col[(p3+2 )%4]; - newFace[1]->tf.col[2] = face[0]->tf.col[(p1+1 )%3]; - newFace[1]->tf.col[3] = face[0]->tf.col[(p1+2 )%3]; - - UVCOPY(newFace[0]->tf.uv[0],face[0]->tf.uv[(p1 )%3]); - UVCOPY(newFace[0]->tf.uv[1],face[0]->tf.uv[(p1+1 )%3]); - UVCOPY(newFace[0]->tf.uv[2],face[1]->tf.uv[(p3+2 )%4]); - UVCOPY(newFace[1]->tf.uv[0],face[1]->tf.uv[(p3+1 )%4]); - UVCOPY(newFace[1]->tf.uv[1],face[1]->tf.uv[(p3+2 )%4]); - UVCOPY(newFace[1]->tf.uv[2],face[0]->tf.uv[(p1+1 )%3]); - UVCOPY(newFace[1]->tf.uv[3],face[0]->tf.uv[(p1+2 )%3]); + newFace[0]= EM_face_from_faces(face[0], face[1], p[0][0], p[0][1], 4+p[1][2], -1); + newFace[1]= EM_face_from_faces(face[1], face[0], p[1][1], p[1][2], 4+p[0][1], 4+p[0][2]); - faces[0][(p1+1)%fac1]->f |= SELECT; - faces[1][(p3+2)%fac2]->f |= SELECT; + verts[0][p[0][1]]->f |= SELECT; + verts[1][p[1][2]]->f |= SELECT; } } - else if(fac1 == 4 && fac2 == 4) { if(dir == 1) { - newFace[0] = addfacelist(faces[0][(p1+1 )%4],faces[0][(p1+2 )%4],faces[0][(p1+3 )%4],faces[1][(p3+1 )%4],NULL,NULL); - newFace[1] = addfacelist(faces[1][(p3+1 )%4],faces[1][(p3+2 )%4],faces[1][(p3+3 )%4],faces[0][(p1+1 )%4],NULL,NULL); - - newFace[0]->tf.col[0] = face[0]->tf.col[(p1+1 )%4]; - newFace[0]->tf.col[1] = face[0]->tf.col[(p1+2 )%4]; - newFace[0]->tf.col[2] = face[0]->tf.col[(p1+3 )%4]; - newFace[0]->tf.col[3] = face[1]->tf.col[(p3+1 )%4]; - newFace[1]->tf.col[0] = face[1]->tf.col[(p3+1 )%4]; - newFace[1]->tf.col[1] = face[1]->tf.col[(p3+2 )%4]; - newFace[1]->tf.col[2] = face[1]->tf.col[(p3+3 )%4]; - newFace[1]->tf.col[3] = face[0]->tf.col[(p1+1 )%4]; - - UVCOPY(newFace[0]->tf.uv[0],face[0]->tf.uv[(p1+1 )%4]); - UVCOPY(newFace[0]->tf.uv[1],face[0]->tf.uv[(p1+2 )%4]); - UVCOPY(newFace[0]->tf.uv[2],face[0]->tf.uv[(p1+3 )%4]); - UVCOPY(newFace[0]->tf.uv[3],face[1]->tf.uv[(p3+1 )%4]); - UVCOPY(newFace[1]->tf.uv[0],face[1]->tf.uv[(p3+1 )%4]); - UVCOPY(newFace[1]->tf.uv[1],face[1]->tf.uv[(p3+2 )%4]); - UVCOPY(newFace[1]->tf.uv[2],face[1]->tf.uv[(p3+3 )%4]); - UVCOPY(newFace[1]->tf.uv[3],face[0]->tf.uv[(p1+1 )%4]); + newFace[0]= EM_face_from_faces(face[0], face[1], p[0][1], p[0][2], p[0][3], 4+p[1][1]); + newFace[1]= EM_face_from_faces(face[1], face[0], p[1][1], p[1][2], p[1][3], 4+p[0][1]); } else if (dir == 2) { - newFace[0] = addfacelist(faces[0][(p1+2 )%4],faces[0][(p1+3 )%4],faces[1][(p3+1 )%4],faces[1][(p3+2 )%4],NULL,NULL); - newFace[1] = addfacelist(faces[1][(p3+2 )%4],faces[1][(p3+3 )%4],faces[0][(p1+1 )%4],faces[0][(p1+2 )%4],NULL,NULL); - - newFace[0]->tf.col[0] = face[0]->tf.col[(p1+2 )%4]; - newFace[0]->tf.col[1] = face[0]->tf.col[(p1+3 )%4]; - newFace[0]->tf.col[2] = face[1]->tf.col[(p3+1 )%4]; - newFace[0]->tf.col[3] = face[1]->tf.col[(p3+2 )%4]; - newFace[1]->tf.col[0] = face[1]->tf.col[(p3+2 )%4]; - newFace[1]->tf.col[1] = face[1]->tf.col[(p3+3 )%4]; - newFace[1]->tf.col[2] = face[0]->tf.col[(p1+1 )%4]; - newFace[1]->tf.col[3] = face[0]->tf.col[(p1+2 )%4]; - - UVCOPY(newFace[0]->tf.uv[0],face[0]->tf.uv[(p1+2 )%4]); - UVCOPY(newFace[0]->tf.uv[1],face[0]->tf.uv[(p1+3 )%4]); - UVCOPY(newFace[0]->tf.uv[2],face[1]->tf.uv[(p3+1 )%4]); - UVCOPY(newFace[0]->tf.uv[3],face[1]->tf.uv[(p3+2 )%4]); - UVCOPY(newFace[1]->tf.uv[0],face[1]->tf.uv[(p3+2 )%4]); - UVCOPY(newFace[1]->tf.uv[1],face[1]->tf.uv[(p3+3 )%4]); - UVCOPY(newFace[1]->tf.uv[2],face[0]->tf.uv[(p1+1 )%4]); - UVCOPY(newFace[1]->tf.uv[3],face[0]->tf.uv[(p1+2 )%4]); + newFace[0]= EM_face_from_faces(face[0], face[1], p[0][2], p[0][3], 4+p[1][1], 4+p[1][2]); + newFace[1]= EM_face_from_faces(face[1], face[0], p[1][2], p[1][3], 4+p[0][1], 4+p[0][2]); - faces[0][(p1+2)%fac1]->f |= SELECT; - faces[1][(p3+2)%fac2]->f |= SELECT; + verts[0][p[0][2]]->f |= SELECT; + verts[1][p[1][2]]->f |= SELECT; } - - } - else{ - /*This should never happen*/ - return; - } + else + return; /* This should never happen */ - if(dir == 1) { - faces[0][(p1+1)%fac1]->f |= SELECT; - faces[1][(p3+1)%fac2]->f |= SELECT; + if(dir == 1 || (fac1 == 3 && fac2 == 3)) { + verts[0][p[0][1]]->f |= SELECT; + verts[1][p[1][1]]->f |= SELECT; } - /*Copy old edge's flags to new center edge*/ + /* copy old edge's flags to new center edge*/ for(srchedge=em->edges.first;srchedge;srchedge=srchedge->next) { - if(srchedge->v1->f & SELECT &&srchedge->v2->f & SELECT ) { + if((srchedge->v1->f & SELECT) && (srchedge->v2->f & SELECT)) { srchedge->f = eed->f; srchedge->h = eed->h; srchedge->dir = eed->dir; @@ -4208,63 +3881,15 @@ static void edge_rotate(EditEdge *eed,int dir) } } - - /* copy flags and material */ - - newFace[0]->mat_nr = face[0]->mat_nr; - newFace[0]->tf.flag = face[0]->tf.flag; - newFace[0]->tf.transp = face[0]->tf.transp; - newFace[0]->tf.mode = face[0]->tf.mode; - newFace[0]->tf.tile = face[0]->tf.tile; - newFace[0]->tf.unwrap = face[0]->tf.unwrap; - newFace[0]->tf.tpage = face[0]->tf.tpage; - newFace[0]->flag = face[0]->flag; - - newFace[1]->mat_nr = face[1]->mat_nr; - newFace[1]->tf.flag = face[1]->tf.flag; - newFace[1]->tf.transp = face[1]->tf.transp; - newFace[1]->tf.mode = face[1]->tf.mode; - newFace[1]->tf.tile = face[1]->tf.tile; - newFace[1]->tf.unwrap = face[1]->tf.unwrap; - newFace[1]->tf.tpage = face[1]->tf.tpage; - newFace[1]->flag = face[1]->flag; - - /* Resetting Hidden Flag */ - for(numhidden--;numhidden>=0;numhidden--) { - hiddenedges[numhidden]->h = 1; - - } + /* resetting hidden flag */ + for(numhidden--; numhidden>=0; numhidden--) + hiddenedges[numhidden]->h= 1; /* check for orhphan edges */ - for(srchedge=em->edges.first;srchedge;srchedge = srchedge->next) { - srchedge->f1 = -1; - } + for(srchedge=em->edges.first; srchedge; srchedge=srchedge->next) + srchedge->f1= -1; - /*for(efa = em->faces.first;efa;efa = efa->next) { - if(efa->h == 0) { - efa->e1->f1 = 1; - efa->e2->f1 = 1; - efa->e3->f1 = 1; - if(efa->e4) { - efa->e4->f1 = 1; - } - } - if(efa->h == 1) { - if(efa->e1->f1 == -1) { - efa->e1->f1 = 0; - } - if(efa->e2->f1 == -1) { - efa->e2->f1 = 0; - } - if(efa->e1->f1 == -1) { - efa->e1->f1 = 0; - } - if(efa->e4) { - efa->e4->f1 = 1; - } - } - } - A Little Cleanup */ + /* cleanup */ MEM_freeN(hiddenedges); /* get rid of the old edge and faces*/ @@ -4274,8 +3899,7 @@ static void edge_rotate(EditEdge *eed,int dir) free_editface(face[0]); BLI_remlink(&em->faces, face[1]); free_editface(face[1]); - return; -} +} /* only accepts 1 selected edge, or 2 selected faces */ void edge_rotate_selected(int dir) @@ -6355,14 +5979,15 @@ static void append_weldedUV(EditFace *efa, EditVert *eve, int tfindex, ListBase wUV *curwvert, *newwvert; wUVNode *newnode; int found; + TFace *tf = CustomData_em_get(&G.editMesh->fdata, efa->data, LAYERTYPE_TFACE); found = 0; for(curwvert=uvverts->first; curwvert; curwvert=curwvert->next){ - if(curwvert->eve == eve && curwvert->u == efa->tf.uv[tfindex][0] && curwvert->v == efa->tf.uv[tfindex][1]){ + if(curwvert->eve == eve && curwvert->u == tf->uv[tfindex][0] && curwvert->v == tf->uv[tfindex][1]){ newnode = MEM_callocN(sizeof(wUVNode), "Welded UV Vert Node"); - newnode->u = &(efa->tf.uv[tfindex][0]); - newnode->v = &(efa->tf.uv[tfindex][1]); + newnode->u = &(tf->uv[tfindex][0]); + newnode->v = &(tf->uv[tfindex][1]); BLI_addtail(&(curwvert->nodes), newnode); found = 1; break; @@ -6371,8 +5996,8 @@ static void append_weldedUV(EditFace *efa, EditVert *eve, int tfindex, ListBase if(!found){ newnode = MEM_callocN(sizeof(wUVNode), "Welded UV Vert Node"); - newnode->u = &(efa->tf.uv[tfindex][0]); - newnode->v = &(efa->tf.uv[tfindex][1]); + newnode->u = &(tf->uv[tfindex][0]); + newnode->v = &(tf->uv[tfindex][1]); newwvert = MEM_callocN(sizeof(wUV), "Welded UV Vert"); newwvert->u = *(newnode->u); @@ -6400,21 +6025,22 @@ static void append_weldedUVEdge(EditFace *efa, EditEdge *eed, ListBase *uvedges) { wUVEdge *curwedge, *newwedge; int v1tfindex, v2tfindex, found; + TFace *tf = CustomData_em_get(&G.editMesh->fdata, efa->data, LAYERTYPE_TFACE); found = 0; if(eed->v1 == efa->v1) v1tfindex = 0; else if(eed->v1 == efa->v2) v1tfindex = 1; else if(eed->v1 == efa->v3) v1tfindex = 2; - else if(eed->v1 == efa->v4) v1tfindex = 3; + else /* if(eed->v1 == efa->v4) */ v1tfindex = 3; if(eed->v2 == efa->v1) v2tfindex = 0; else if(eed->v2 == efa->v2) v2tfindex = 1; else if(eed->v2 == efa->v3) v2tfindex = 2; - else if(eed->v2 == efa->v4) v2tfindex = 3; + else /* if(eed->v2 == efa->v4) */ v2tfindex = 3; for(curwedge=uvedges->first; curwedge; curwedge=curwedge->next){ - if(curwedge->eed == eed && curwedge->v1uv[0] == efa->tf.uv[v1tfindex][0] && curwedge->v1uv[1] == efa->tf.uv[v1tfindex][1] && curwedge->v2uv[0] == efa->tf.uv[v2tfindex][0] && curwedge->v2uv[1] == efa->tf.uv[v2tfindex][1]){ + if(curwedge->eed == eed && curwedge->v1uv[0] == tf->uv[v1tfindex][0] && curwedge->v1uv[1] == tf->uv[v1tfindex][1] && curwedge->v2uv[0] == tf->uv[v2tfindex][0] && curwedge->v2uv[1] == tf->uv[v2tfindex][1]){ found = 1; break; //do nothing, we don't need another welded uv edge } @@ -6422,10 +6048,10 @@ static void append_weldedUVEdge(EditFace *efa, EditEdge *eed, ListBase *uvedges) if(!found){ newwedge = MEM_callocN(sizeof(wUVEdge), "Welded UV Edge"); - newwedge->v1uv[0] = efa->tf.uv[v1tfindex][0]; - newwedge->v1uv[1] = efa->tf.uv[v1tfindex][1]; - newwedge->v2uv[0] = efa->tf.uv[v2tfindex][0]; - newwedge->v2uv[1] = efa->tf.uv[v2tfindex][1]; + newwedge->v1uv[0] = tf->uv[v1tfindex][0]; + newwedge->v1uv[1] = tf->uv[v1tfindex][1]; + newwedge->v2uv[0] = tf->uv[v2tfindex][0]; + newwedge->v2uv[1] = tf->uv[v2tfindex][1]; newwedge->eed = eed; BLI_addtail(uvedges, newwedge); @@ -6434,7 +6060,6 @@ static void append_weldedUVEdge(EditFace *efa, EditEdge *eed, ListBase *uvedges) static void build_weldedUVEdges(ListBase *uvedges, ListBase *uvverts) { - wUV *curwvert; wUVEdge *curwedge; EditFace *efa; @@ -6480,6 +6105,9 @@ static void collapse_edgeuvs(void) Collection *wuvecollection, *newcollection; int curtag, balanced, collectionfound, vcount; float avg[2]; + + if (!CustomData_has_layer(&G.editMesh->fdata, LAYERTYPE_TFACE)) + return; uvverts.first = uvverts.last = uvedges.first = uvedges.last = allcollections.first = allcollections.last = NULL; @@ -6576,62 +6204,64 @@ static void collapse_edgeuvs(void) static void collapseuvs(void) { EditFace *efa; + TFace *tf; int uvcount; float uvav[2]; + + if (!CustomData_has_layer(&G.editMesh->fdata, LAYERTYPE_TFACE)) + return; uvcount = 0; uvav[0] = 0; uvav[1] = 0; for(efa = G.editMesh->faces.first; efa; efa=efa->next){ + tf = CustomData_em_get(&G.editMesh->fdata, efa->data, LAYERTYPE_TFACE); + if(efa->v1->f1){ - uvav[0] += efa->tf.uv[0][0]; - uvav[1] += efa->tf.uv[0][1]; + uvav[0] += tf->uv[0][0]; + uvav[1] += tf->uv[0][1]; uvcount += 1; } if(efa->v2->f1){ - uvav[0] += efa->tf.uv[1][0]; - uvav[1] += efa->tf.uv[1][1]; + uvav[0] += tf->uv[1][0]; + uvav[1] += tf->uv[1][1]; uvcount += 1; } if(efa->v3->f1){ - uvav[0] += efa->tf.uv[2][0]; - uvav[1] += efa->tf.uv[2][1]; + uvav[0] += tf->uv[2][0]; + uvav[1] += tf->uv[2][1]; uvcount += 1; } - if(efa->v4){ - if(efa->v4->f1){ - uvav[0] += efa->tf.uv[3][0]; - uvav[1] += efa->tf.uv[3][1]; - uvcount += 1; - } + if(efa->v4 && efa->v4->f1){ + uvav[0] += tf->uv[3][0]; + uvav[1] += tf->uv[3][1]; + uvcount += 1; } } - - - if(uvav[0] && uvav[1]){ + if(uvcount > 0) { uvav[0] /= uvcount; uvav[1] /= uvcount; for(efa = G.editMesh->faces.first; efa; efa=efa->next){ + tf = CustomData_em_get(&G.editMesh->fdata, efa->data, LAYERTYPE_TFACE); + if(efa->v1->f1){ - efa->tf.uv[0][0] = uvav[0]; - efa->tf.uv[0][1] = uvav[1]; + tf->uv[0][0] = uvav[0]; + tf->uv[0][1] = uvav[1]; } if(efa->v2->f1){ - efa->tf.uv[1][0] = uvav[0]; - efa->tf.uv[1][1] = uvav[1]; + tf->uv[1][0] = uvav[0]; + tf->uv[1][1] = uvav[1]; } if(efa->v3->f1){ - efa->tf.uv[2][0] = uvav[0]; - efa->tf.uv[2][1] = uvav[1]; + tf->uv[2][0] = uvav[0]; + tf->uv[2][1] = uvav[1]; } - if(efa->v4){ - if(efa->v4->f1){ - efa->tf.uv[3][0] = uvav[0]; - efa->tf.uv[3][1] = uvav[1]; - } + if(efa->v4 && efa->v4->f1){ + tf->uv[3][0] = uvav[0]; + tf->uv[3][1] = uvav[1]; } } } @@ -6646,11 +6276,9 @@ int collapseEdges(void) CollectedEdge *curredge; Collection *edgecollection; - int totedges, groupcount, mergecount,vcount; float avgcount[3]; - allcollections.first = 0; allcollections.last = 0; @@ -6686,15 +6314,17 @@ int collapseEdges(void) VECCOPY(((EditEdge*)curredge->eed)->v2->co,avgcount); } - /*uv collapse*/ - for(eve=G.editMesh->verts.first; eve; eve=eve->next) eve->f1 = 0; - for(eed=G.editMesh->edges.first; eed; eed=eed->next) eed->f1 = 0; - for(curredge = edgecollection->collectionbase.first; curredge; curredge = curredge->next){ - curredge->eed->v1->f1 = 1; - curredge->eed->v2->f1 = 1; - curredge->eed->f1 = 1; + if (CustomData_has_layer(&G.editMesh->fdata, LAYERTYPE_TFACE)) { + /*uv collapse*/ + for(eve=G.editMesh->verts.first; eve; eve=eve->next) eve->f1 = 0; + for(eed=G.editMesh->edges.first; eed; eed=eed->next) eed->f1 = 0; + for(curredge = edgecollection->collectionbase.first; curredge; curredge = curredge->next){ + curredge->eed->v1->f1 = 1; + curredge->eed->v2->f1 = 1; + curredge->eed->f1 = 1; + } + collapse_edgeuvs(); } - collapse_edgeuvs(); } freecollections(&allcollections); @@ -6727,7 +6357,7 @@ int merge_firstlast(int first, int uvmerge) } } - if(uvmerge){ + if(uvmerge && CustomData_has_layer(&G.editMesh->fdata, LAYERTYPE_TFACE)){ for(eve=G.editMesh->verts.first; eve; eve=eve->next) eve->f1 = 0; for(eve=G.editMesh->verts.first; eve; eve=eve->next){ @@ -6748,7 +6378,7 @@ int merge_target(int target, int uvmerge) if(target) snap_sel_to_curs(); else snap_to_center(); - if(uvmerge){ + if(uvmerge && CustomData_has_layer(&G.editMesh->fdata, LAYERTYPE_TFACE)){ for(eve=G.editMesh->verts.first; eve; eve=eve->next) eve->f1 = 0; for(eve=G.editMesh->verts.first; eve; eve=eve->next){ if(eve->f&SELECT) eve->f1 = 1; @@ -7109,7 +6739,6 @@ void loop_to_region(void) if(efa->f1 == testflag){ if(efa->f&SELECT) EM_select_face(efa, 0); else EM_select_face(efa,1); - } } }