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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel/intern/customdata.c')
-rw-r--r--source/blender/blenkernel/intern/customdata.c432
1 files changed, 418 insertions, 14 deletions
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index d8ce311b5ca..e93266c85f3 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -36,6 +36,7 @@
#include "BLI_blenlib.h"
#include "BLI_linklist.h"
+#include "BLI_mempool.h"
#include "DNA_customdata_types.h"
#include "DNA_listBase.h"
@@ -97,11 +98,16 @@ static void layerCopy_mdeformvert(const void *source, void *dest,
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;
+ if(dvert->totweight) {
+ MDeformWeight *dw = MEM_callocN(dvert->totweight * sizeof(*dw),
+ "layerCopy_mdeformvert dw");
+
+ memcpy(dw, dvert->dw, dvert->totweight * sizeof(*dw));
+ dvert->dw = dw;
+ }
+ else
+ dvert->dw = NULL;
}
}
@@ -259,14 +265,34 @@ static void layerSwap_tface(void *data, int *corner_indices)
{
MTFace *tf = data;
float uv[4][2];
+ static const short pin_flags[4] =
+ { TF_PIN1, TF_PIN2, TF_PIN3, TF_PIN4 };
+ static const char sel_flags[4] =
+ { TF_SEL1, TF_SEL2, TF_SEL3, TF_SEL4 };
+ short unwrap = tf->unwrap & ~(TF_PIN1 | TF_PIN2 | TF_PIN3 | TF_PIN4);
+ char flag = tf->flag & ~(TF_SEL1 | TF_SEL2 | TF_SEL3 | TF_SEL4);
int j;
for(j = 0; j < 4; ++j) {
- uv[j][0] = tf->uv[corner_indices[j]][0];
- uv[j][1] = tf->uv[corner_indices[j]][1];
+ int source_index = corner_indices[j];
+
+ uv[j][0] = tf->uv[source_index][0];
+ uv[j][1] = tf->uv[source_index][1];
+
+ // swap pinning flags around
+ if(tf->unwrap & pin_flags[source_index]) {
+ unwrap |= pin_flags[j];
+ }
+
+ // swap selection flags around
+ if(tf->flag & sel_flags[source_index]) {
+ flag |= sel_flags[j];
+ }
}
memcpy(tf->uv, uv, sizeof(tf->uv));
+ tf->unwrap = unwrap;
+ tf->flag = flag;
}
static void layerDefault_tface(void *data, int count)
@@ -354,8 +380,80 @@ static void layerDefault_origspace_face(void *data, int count)
}
/* --------- */
+static void layerDefault_mloopcol(void *data, int count)
+{
+ static MLoopCol default_mloopcol = {255,255,255,255};
+ MLoopCol *mlcol = (MLoopCol*)data;
+ int i;
+ for(i = 0; i < count; i++)
+ mlcol[i] = default_mloopcol;
+
+}
+
+static void layerInterp_mloopcol(void **sources, float *weights,
+ float *sub_weights, int count, void *dest)
+{
+ MLoopCol *mc = dest;
+ int i;
+ float *sub_weight;
+ struct {
+ float a;
+ float r;
+ float g;
+ float b;
+ } col;
+ col.a = col.r = col.g = col.b = 0;
+ sub_weight = sub_weights;
+ for(i = 0; i < count; ++i){
+ float weight = weights ? weights[i] : 1;
+ MLoopCol *src = sources[i];
+ if(sub_weights){
+ col.a += src->a * (*sub_weight) * weight;
+ col.r += src->r * (*sub_weight) * weight;
+ col.g += src->g * (*sub_weight) * weight;
+ col.b += src->b * (*sub_weight) * weight;
+ sub_weight++;
+ } else {
+ col.a += src->a * weight;
+ col.r += src->r * weight;
+ col.g += src->g * weight;
+ col.b += src->b * weight;
+ }
+ }
+ mc->a = (int)col.a;
+ mc->r = (int)col.r;
+ mc->g = (int)col.g;
+ mc->b = (int)col.b;
+}
+static void layerInterp_mloopuv(void **sources, float *weights,
+ float *sub_weights, int count, void *dest)
+{
+ MLoopUV *mluv = dest;
+ int i;
+ float *sub_weight;
+ struct {
+ float u;
+ float v;
+ }uv;
+ uv.u = uv.v = 0.0;
+ sub_weight = sub_weights;
+ for(i = 0; i < count; ++i){
+ float weight = weights ? weights[i] : 1;
+ MLoopUV *src = sources[i];
+ if(sub_weights){
+ uv.u += src->uv[0] * (*sub_weight) * weight;
+ uv.v += src->uv[1] * (*sub_weight) * weight;
+ sub_weight++;
+ } else {
+ uv.u += src->uv[0] * weight;
+ uv.v += src->uv[1] * weight;
+ }
+ }
+ mluv->uv[0] = uv.u;
+ mluv->uv[1] = uv.v;
+}
static void layerInterp_mcol(void **sources, float *weights,
float *sub_weights, int count, void *dest)
@@ -427,6 +525,8 @@ static void layerDefault_mcol(void *data, int count)
mcol[i] = default_mcol;
}
+
+
const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
{sizeof(MVert), "MVert", 1, NULL, NULL, NULL, NULL, NULL, NULL},
{sizeof(MSticky), "MSticky", 1, NULL, NULL, NULL, layerInterp_msticky, NULL,
@@ -449,13 +549,17 @@ const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
{sizeof(MStringProperty), "MStringProperty",1,"String",NULL,NULL,NULL,NULL},
{sizeof(OrigSpaceFace), "OrigSpaceFace", 1, "UVTex", layerCopy_origspace_face, NULL,
layerInterp_origspace_face, layerSwap_origspace_face, layerDefault_origspace_face},
- {sizeof(float)*3, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}
+ {sizeof(float)*3, "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
+ {sizeof(MTexPoly), "MTexPoly", 1, "Face Texture", NULL, NULL, NULL, NULL, NULL},
+ {sizeof(MLoopUV), "MLoopUV", 1, "UV coord", NULL, NULL, layerInterp_mloopuv, NULL, NULL},
+ {sizeof(MLoopCol), "MLoopCol", 1, "Col", NULL, NULL, layerInterp_mloopcol, NULL, layerDefault_mloopcol},
+ {sizeof(float)*3*4, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}
};
const char *LAYERTYPENAMES[CD_NUMTYPES] = {
"CDMVert", "CDMSticky", "CDMDeformVert", "CDMEdge", "CDMFace", "CDMTFace",
"CDMCol", "CDOrigIndex", "CDNormal", "CDFlags","CDMFloatProperty",
- "CDMIntProperty","CDMStringProperty", "CDOrigSpace", "CDOrco"};
+ "CDMIntProperty","CDMStringProperty", "CDOrigSpace", "CDOrco", "CDMTexPoly", "CDMLoopUV", "CDMloopCol", "CDTangent"};
const CustomDataMask CD_MASK_BAREMESH =
CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MFACE;
@@ -469,7 +573,13 @@ const CustomDataMask CD_MASK_EDITMESH =
const CustomDataMask CD_MASK_DERIVEDMESH =
CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE |
CD_MASK_MCOL | CD_MASK_ORIGINDEX | CD_MASK_PROP_FLT | CD_MASK_PROP_INT |
- CD_MASK_PROP_STR | CD_MASK_ORIGSPACE | CD_MASK_ORCO;
+ CD_MASK_PROP_STR | CD_MASK_ORIGSPACE | CD_MASK_ORCO | CD_MASK_TANGENT;
+const CustomDataMask CD_MASK_BMESH =
+ CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR;
+const CustomDataMask CD_MASK_FACECORNERS =
+ CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV |
+ CD_MASK_MLOOPCOL;
+
static const LayerTypeInfo *layerType_getInfo(int type)
{
@@ -816,12 +926,9 @@ void *CustomData_add_layer_named(CustomData *data, int type, int alloctype,
int CustomData_free_layer(CustomData *data, int type, int totelem, int index)
{
int i;
- CustomDataLayer *layer;
if (index < 0) return 0;
- layer = &data->layers[index];
-
customData_free_layer__internal(&data->layers[index], totelem);
for (i=index+1; i < data->totlayer; ++i)
@@ -1236,7 +1343,8 @@ void CustomData_em_copy_data(const CustomData *source, CustomData *dest,
if(dest_i >= dest->totlayer) return;
/* if we found a matching layer, copy the data */
- if(dest->layers[dest_i].type == source->layers[src_i].type) {
+ if(dest->layers[dest_i].type == source->layers[src_i].type &&
+ strcmp(dest->layers[dest_i].name, source->layers[src_i].name) == 0) {
char *src_data = (char*)src_block + source->layers[src_i].offset;
char *dest_data = (char*)*dest_block + dest->layers[dest_i].offset;
@@ -1272,7 +1380,7 @@ void *CustomData_em_get_n(const CustomData *data, void *block, int type, int n)
int layer_index;
/* get the layer index of the first layer of type */
- layer_index = CustomData_get_active_layer_index(data, type);
+ layer_index = CustomData_get_layer_index(data, type);
if(layer_index < 0) return NULL;
return (char *)block + data->layers[layer_index+n].offset;
@@ -1443,6 +1551,302 @@ void CustomData_from_em_block(const CustomData *source, CustomData *dest,
}
+/*Bmesh functions*/
+/*needed to convert to/from different face reps*/
+void CustomData_to_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData *ldata)
+{
+ int i;
+ for(i=0; i < fdata->totlayer; i++){
+ if(fdata->layers[i].type == CD_MTFACE){
+ CustomData_add_layer(pdata, CD_MTEXPOLY, CD_CALLOC, &(fdata->layers[i].name), 0);
+ CustomData_add_layer(ldata, CD_MLOOPUV, CD_CALLOC, &(fdata->layers[i].name), 0);
+ }
+ else if(fdata->layers[i].type == CD_MCOL)
+ CustomData_add_layer(ldata, CD_MLOOPCOL, CD_CALLOC, &(fdata->layers[i].name), 0);
+ }
+}
+void CustomData_from_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData *ldata, int total){
+ int i;
+ for(i=0; i < pdata->totlayer; i++){
+ if(pdata->layers[i].type == CD_MTEXPOLY)
+ CustomData_add_layer(fdata, CD_MTFACE, CD_CALLOC, &(pdata->layers[i].name), total);
+ }
+ for(i=0; i < ldata->totlayer; i++){
+ if(ldata->layers[i].type == CD_MLOOPCOL)
+ CustomData_add_layer(fdata, CD_MCOL, CD_CALLOC, &(ldata->layers[i].name), total);
+ }
+}
+
+
+void CustomData_bmesh_init_pool(CustomData *data, int allocsize){
+ if(data->totlayer)data->pool = BLI_mempool_create(data->totsize, allocsize, allocsize);
+}
+
+void CustomData_bmesh_free_block(CustomData *data, void **block)
+{
+ const LayerTypeInfo *typeInfo;
+ int i;
+
+ if(!*block) return;
+ for(i = 0; i < data->totlayer; ++i) {
+ if(!(data->layers[i].flag & CD_FLAG_NOFREE)) {
+ typeInfo = layerType_getInfo(data->layers[i].type);
+
+ if(typeInfo->free) {
+ int offset = data->layers[i].offset;
+ typeInfo->free((char*)*block + offset, 1, typeInfo->size);
+ }
+ }
+ }
+
+ BLI_mempool_free(data->pool, *block);
+ *block = NULL;
+}
+
+static void CustomData_bmesh_alloc_block(CustomData *data, void **block)
+{
+
+ if (*block)
+ CustomData_bmesh_free_block(data, block);
+
+ if (data->totsize > 0)
+ *block = BLI_mempool_calloc(data->pool);
+ else
+ *block = NULL;
+}
+
+void CustomData_bmesh_copy_data(const CustomData *source, CustomData *dest,
+ void *src_block, void **dest_block)
+{
+ const LayerTypeInfo *typeInfo;
+ int dest_i, src_i;
+
+ if (!*dest_block)
+ CustomData_bmesh_alloc_block(dest, dest_block);
+
+ /* copies a layer at a time */
+ dest_i = 0;
+ for(src_i = 0; src_i < source->totlayer; ++src_i) {
+
+ /* find the first dest layer with type >= the source type
+ * (this should work because layers are ordered by type)
+ */
+ while(dest_i < dest->totlayer
+ && 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->totlayer) return;
+
+ /* if we found a matching layer, copy the data */
+ if(dest->layers[dest_i].type == source->layers[src_i].type &&
+ strcmp(dest->layers[dest_i].name, source->layers[src_i].name) == 0) {
+ char *src_data = (char*)src_block + source->layers[src_i].offset;
+ char *dest_data = (char*)*dest_block + dest->layers[dest_i].offset;
+
+ typeInfo = layerType_getInfo(source->layers[src_i].type);
+
+ if(typeInfo->copy)
+ typeInfo->copy(src_data, dest_data, 1);
+ else
+ memcpy(dest_data, src_data, typeInfo->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;
+ }
+ }
+}
+
+/*Bmesh Custom Data Functions. Should replace editmesh ones with these as well, due to more effecient memory alloc*/
+void *CustomData_bmesh_get(const CustomData *data, void *block, int type)
+{
+ int layer_index;
+
+ /* get the layer index of the first layer of type */
+ layer_index = CustomData_get_active_layer_index(data, type);
+ if(layer_index < 0) return NULL;
+
+ return (char *)block + data->layers[layer_index].offset;
+}
+
+void *CustomData_bmesh_get_n(const CustomData *data, void *block, int type, int n)
+{
+ int layer_index;
+
+ /* get the layer index of the first layer of type */
+ layer_index = CustomData_get_layer_index(data, type);
+ if(layer_index < 0) return NULL;
+
+ return (char *)block + data->layers[layer_index+n].offset;
+}
+
+void CustomData_bmesh_set(const CustomData *data, void *block, int type, void *source)
+{
+ void *dest = CustomData_bmesh_get(data, block, type);
+ const LayerTypeInfo *typeInfo = layerType_getInfo(type);
+
+ if(!dest) return;
+
+ if(typeInfo->copy)
+ typeInfo->copy(source, dest, 1);
+ else
+ memcpy(dest, source, typeInfo->size);
+}
+
+void CustomData_bmesh_set_n(CustomData *data, void *block, int type, int n, void *source)
+{
+ void *dest = CustomData_bmesh_get_n(data, block, type, n);
+ const LayerTypeInfo *typeInfo = layerType_getInfo(type);
+
+ if(!dest) return;
+
+ if(typeInfo->copy)
+ typeInfo->copy(source, dest, 1);
+ else
+ memcpy(dest, source, typeInfo->size);
+}
+
+void CustomData_bmesh_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;
+
+ /* 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->totlayer; ++i) {
+ CustomDataLayer *layer = &data->layers[i];
+ const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
+ if(typeInfo->interp) {
+ for(j = 0; j < count; ++j)
+ sources[j] = (char *)src_blocks[j] + layer->offset;
+
+ typeInfo->interp(sources, weights, sub_weights, count,
+ (char *)dest_block + layer->offset);
+ }
+ }
+
+ if(count > SOURCE_BUF_SIZE) MEM_freeN(sources);
+}
+
+void CustomData_bmesh_set_default(CustomData *data, void **block)
+{
+ const LayerTypeInfo *typeInfo;
+ int i;
+
+ if (!*block)
+ CustomData_bmesh_alloc_block(data, block);
+
+ for(i = 0; i < data->totlayer; ++i) {
+ int offset = data->layers[i].offset;
+
+ typeInfo = layerType_getInfo(data->layers[i].type);
+
+ if(typeInfo->set_default)
+ typeInfo->set_default((char*)*block + offset, 1);
+ }
+}
+
+void CustomData_to_bmesh_block(const CustomData *source, CustomData *dest,
+ int src_index, void **dest_block)
+{
+ const LayerTypeInfo *typeInfo;
+ int dest_i, src_i, src_offset;
+
+ if (!*dest_block)
+ CustomData_bmesh_alloc_block(dest, dest_block);
+
+ /* copies a layer at a time */
+ dest_i = 0;
+ for(src_i = 0; src_i < source->totlayer; ++src_i) {
+
+ /* find the first dest layer with type >= the source type
+ * (this should work because layers are ordered by type)
+ */
+ while(dest_i < dest->totlayer
+ && 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->totlayer) return;
+
+ /* if we found a matching layer, copy the data */
+ if(dest->layers[dest_i].type == source->layers[src_i].type) {
+ int offset = dest->layers[dest_i].offset;
+ char *src_data = source->layers[src_i].data;
+ char *dest_data = (char*)*dest_block + offset;
+
+ typeInfo = layerType_getInfo(dest->layers[dest_i].type);
+ src_offset = src_index * typeInfo->size;
+
+ if(typeInfo->copy)
+ typeInfo->copy(src_data + src_offset, dest_data, 1);
+ else
+ memcpy(dest_data, src_data + src_offset, typeInfo->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;
+ }
+ }
+}
+
+void CustomData_from_bmesh_block(const CustomData *source, CustomData *dest,
+ void *src_block, int dest_index)
+{
+ const LayerTypeInfo *typeInfo;
+ int dest_i, src_i, dest_offset;
+
+ /* copies a layer at a time */
+ dest_i = 0;
+ for(src_i = 0; src_i < source->totlayer; ++src_i) {
+
+ /* find the first dest layer with type >= the source type
+ * (this should work because layers are ordered by type)
+ */
+ while(dest_i < dest->totlayer
+ && 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->totlayer) return;
+
+ /* if we found a matching layer, copy the data */
+ if(dest->layers[dest_i].type == source->layers[src_i].type) {
+ int offset = source->layers[src_i].offset;
+ char *src_data = (char*)src_block + offset;
+ char *dest_data = dest->layers[dest_i].data;
+
+ typeInfo = layerType_getInfo(dest->layers[dest_i].type);
+ dest_offset = dest_index * typeInfo->size;
+
+ if(typeInfo->copy)
+ typeInfo->copy(src_data, dest_data + dest_offset, 1);
+ else
+ memcpy(dest_data + dest_offset, src_data, typeInfo->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;
+ }
+ }
+
+}
+
void CustomData_file_write_info(int type, char **structname, int *structnum)
{
const LayerTypeInfo *typeInfo = layerType_getInfo(type);