Files
test/source/blender/blenkernel/intern/customdata.cc

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

5462 lines
154 KiB
C++
Raw Normal View History

/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2006 Blender Foundation. All rights reserved. */
2011-02-27 20:40:57 +00:00
/** \file
* \ingroup bke
* Implementation of CustomData.
*
* BKE_customdata.h contains the function prototypes for this file.
2011-02-27 20:40:57 +00:00
*/
#include "MEM_guardedalloc.h"
/* Since we have versioning code here (CustomData_verify_versions()). */
#define DNA_DEPRECATED_ALLOW
#include "DNA_ID.h"
#include "DNA_customdata_types.h"
#include "DNA_meshdata_types.h"
#include "BLI_bitmap.h"
#include "BLI_color.hh"
#include "BLI_endian_switch.h"
#include "BLI_index_range.hh"
#include "BLI_math.h"
#include "BLI_math_color_blend.h"
#include "BLI_math_vector.hh"
#include "BLI_mempool.h"
#include "BLI_path_util.h"
#include "BLI_span.hh"
#include "BLI_string.h"
#include "BLI_string_ref.hh"
#include "BLI_string_utils.h"
#include "BLI_utildefines.h"
#ifndef NDEBUG
# include "BLI_dynstr.h"
#endif
#include "BLT_translation.h"
#include "BKE_anonymous_attribute.h"
#include "BKE_customdata.h"
#include "BKE_customdata_file.h"
#include "BKE_deform.h"
#include "BKE_main.h"
#include "BKE_mesh_mapping.h"
#include "BKE_mesh_remap.h"
#include "BKE_multires.h"
#include "BKE_subsurf.h"
#include "BLO_read_write.h"
#include "bmesh.h"
#include "CLG_log.h"
2017-03-27 09:14:40 +11:00
/* only for customdata_data_transfer_interp_normal_normals */
#include "data_transfer_intern.h"
using blender::IndexRange;
using blender::Span;
using blender::StringRef;
using blender::Vector;
/* number of layers to add when growing a CustomData object */
#define CUSTOMDATA_GROW 5
2012-10-25 04:44:46 +00:00
/* ensure typemap size is ok */
BLI_STATIC_ASSERT(ARRAY_SIZE(((CustomData *)nullptr)->typemap) == CD_NUMTYPES, "size mismatch");
2012-10-25 04:44:46 +00:00
static CLG_LogRef LOG = {"bke.customdata"};
2012-10-25 04:44:46 +00:00
/* -------------------------------------------------------------------- */
/** \name Mesh Mask Utilities
* \{ */
void CustomData_MeshMasks_update(CustomData_MeshMasks *mask_dst,
const CustomData_MeshMasks *mask_src)
{
mask_dst->vmask |= mask_src->vmask;
mask_dst->emask |= mask_src->emask;
mask_dst->fmask |= mask_src->fmask;
mask_dst->pmask |= mask_src->pmask;
mask_dst->lmask |= mask_src->lmask;
}
bool CustomData_MeshMasks_are_matching(const CustomData_MeshMasks *mask_ref,
const CustomData_MeshMasks *mask_required)
{
return (((mask_required->vmask & mask_ref->vmask) == mask_required->vmask) &&
((mask_required->emask & mask_ref->emask) == mask_required->emask) &&
((mask_required->fmask & mask_ref->fmask) == mask_required->fmask) &&
((mask_required->pmask & mask_ref->pmask) == mask_required->pmask) &&
((mask_required->lmask & mask_ref->lmask) == mask_required->lmask));
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Layer Type Information
* \{ */
struct LayerTypeInfo {
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
int size; /* the memory size of one element of this layer's data */
/** name of the struct used, for file writing */
const char *structname;
/** number of structs per element, for file writing */
int structnum;
/**
* default layer name.
*
* \note when null this is a way to ensure there is only ever one item
* see: CustomData_layertype_is_singleton().
*/
const char *defaultname;
/**
* a function to copy count elements of this layer's data
* (deep copy if appropriate)
* if null, memcpy is used
*/
cd_copy copy;
/**
* a function to free any dynamically allocated components of this
* layer's data (note the data pointer itself should not be freed)
* size should be the size of one element of this layer's data (e.g.
* LayerTypeInfo.size)
*/
void (*free)(void *data, int count, int size);
/**
* a function to interpolate between count source elements of this
* layer's data and store the result in dest
* if weights == null or sub_weights == null, they should default to 1
*
* weights gives the weight for each element in sources
* sub_weights gives the sub-element weights for each element in sources
* (there should be (sub element count)^2 weights per element)
* count gives the number of elements in sources
*
* \note in some cases \a dest pointer is in \a sources
* so all functions have to take this into account and delay
* applying changes while reading from sources.
* See bug T32395 - Campbell.
*/
cd_interp interp;
/** a function to swap the data in corners of the element */
void (*swap)(void *data, const int *corner_indices);
/**
* a function to set a layer's data to default values. if null, the
* default is assumed to be all zeros */
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
void (*set_default)(void *data, int count);
/** A function used by mesh validating code, must ensures passed item has valid data. */
cd_validate validate;
/** functions necessary for geometry collapse */
bool (*equal)(const void *data1, const void *data2);
void (*multiply)(void *data, float fac);
void (*initminmax)(void *min, void *max);
void (*add)(void *data1, const void *data2);
void (*dominmax)(const void *data1, void *min, void *max);
void (*copyvalue)(const void *source, void *dest, const int mixmode, const float mixfactor);
/** a function to read data from a cdf file */
bool (*read)(CDataFile *cdf, void *data, int count);
/** a function to write data to a cdf file */
bool (*write)(CDataFile *cdf, const void *data, int count);
/** a function to determine file size */
size_t (*filesize)(CDataFile *cdf, const void *data, int count);
/** a function to determine max allowed number of layers,
* should be null or return -1 if no limit */
int (*layers_max)();
};
/** \} */
/* -------------------------------------------------------------------- */
/** \name Callbacks for (#MDeformVert, #CD_MDEFORMVERT)
* \{ */
static void layerCopy_mdeformvert(const void *source, void *dest, int count)
{
int i, size = sizeof(MDeformVert);
memcpy(dest, source, count * size);
for (i = 0; i < count; i++) {
MDeformVert *dvert = static_cast<MDeformVert *>(POINTER_OFFSET(dest, i * size));
if (dvert->totweight) {
MDeformWeight *dw = static_cast<MDeformWeight *>(
MEM_malloc_arrayN(dvert->totweight, sizeof(*dw), __func__));
memcpy(dw, dvert->dw, dvert->totweight * sizeof(*dw));
dvert->dw = dw;
}
else {
dvert->dw = nullptr;
}
}
}
static void layerFree_mdeformvert(void *data, int count, int size)
{
2020-09-09 15:43:09 +02:00
for (int i = 0; i < count; i++) {
MDeformVert *dvert = static_cast<MDeformVert *>(POINTER_OFFSET(data, i * size));
if (dvert->dw) {
MEM_freeN(dvert->dw);
dvert->dw = nullptr;
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
dvert->totweight = 0;
}
}
}
/* copy just zeros in this case */
static void layerCopy_bmesh_elem_py_ptr(const void *UNUSED(source), void *dest, int count)
{
2021-01-26 09:21:42 -06:00
const int size = sizeof(void *);
2021-01-26 09:21:42 -06:00
for (int i = 0; i < count; i++) {
void **ptr = (void **)POINTER_OFFSET(dest, i * size);
*ptr = nullptr;
}
}
#ifndef WITH_PYTHON
void bpy_bm_generic_invalidate(struct BPy_BMGeneric *UNUSED(self))
{
/* dummy */
}
#endif
static void layerFree_bmesh_elem_py_ptr(void *data, int count, int size)
{
2020-09-09 15:43:09 +02:00
for (int i = 0; i < count; i++) {
void **ptr = (void **)POINTER_OFFSET(data, i * size);
if (*ptr) {
bpy_bm_generic_invalidate(static_cast<BPy_BMGeneric *>(*ptr));
}
}
}
static void layerInterp_mdeformvert(const void **sources,
const float *weights,
const float *UNUSED(sub_weights),
int count,
void *dest)
{
/* a single linked list of MDeformWeight's
* use this to avoid double allocs (which LinkNode would do) */
struct MDeformWeight_Link {
struct MDeformWeight_Link *next;
MDeformWeight dw;
};
MDeformVert *dvert = static_cast<MDeformVert *>(dest);
MDeformWeight_Link *dest_dwlink = nullptr;
MDeformWeight_Link *node;
/* build a list of unique def_nrs for dest */
2021-01-26 09:21:42 -06:00
int totweight = 0;
for (int i = 0; i < count; i++) {
const MDeformVert *source = static_cast<const MDeformVert *>(sources[i]);
float interp_weight = weights[i];
2021-01-26 09:21:42 -06:00
for (int j = 0; j < source->totweight; j++) {
MDeformWeight *dw = &source->dw[j];
float weight = dw->weight * interp_weight;
if (weight == 0.0f) {
continue;
}
for (node = dest_dwlink; node; node = node->next) {
MDeformWeight *tmp_dw = &node->dw;
if (tmp_dw->def_nr == dw->def_nr) {
tmp_dw->weight += weight;
break;
}
}
/* if this def_nr is not in the list, add it */
if (!node) {
MDeformWeight_Link *tmp_dwlink = static_cast<MDeformWeight_Link *>(
alloca(sizeof(*tmp_dwlink)));
tmp_dwlink->dw.def_nr = dw->def_nr;
tmp_dwlink->dw.weight = weight;
2022-01-06 13:54:52 +11:00
/* Inline linked-list. */
tmp_dwlink->next = dest_dwlink;
dest_dwlink = tmp_dwlink;
totweight++;
}
}
}
2019-08-17 00:54:22 +10:00
/* Delay writing to the destination in case dest is in sources. */
/* now we know how many unique deform weights there are, so realloc */
if (dvert->dw && (dvert->totweight == totweight)) {
2020-07-07 12:44:47 +10:00
/* pass (fast-path if we don't need to realloc). */
}
else {
if (dvert->dw) {
MEM_freeN(dvert->dw);
}
if (totweight) {
dvert->dw = static_cast<MDeformWeight *>(
MEM_malloc_arrayN(totweight, sizeof(*dvert->dw), __func__));
}
}
if (totweight) {
dvert->totweight = totweight;
2021-01-26 09:21:42 -06:00
int i = 0;
for (node = dest_dwlink; node; node = node->next, i++) {
if (node->dw.weight > 1.0f) {
node->dw.weight = 1.0f;
}
dvert->dw[i] = node->dw;
}
}
else {
memset(dvert, 0, sizeof(*dvert));
}
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Callbacks for (#vec3f, #CD_NORMAL)
* \{ */
static void layerInterp_normal(const void **sources,
const float *weights,
const float *UNUSED(sub_weights),
int count,
void *dest)
{
/* NOTE: This is linear interpolation, which is not optimal for vectors.
* Unfortunately, spherical interpolation of more than two values is hairy,
* so for now it will do... */
float no[3] = {0.0f};
while (count--) {
madd_v3_v3fl(no, (const float *)sources[count], weights[count]);
}
/* Weighted sum of normalized vectors will **not** be normalized, even if weights are. */
normalize_v3_v3((float *)dest, no);
}
static void layerCopyValue_normal(const void *source,
void *dest,
const int mixmode,
const float mixfactor)
{
const float *no_src = (const float *)source;
float *no_dst = (float *)dest;
float no_tmp[3];
if (ELEM(mixmode,
CDT_MIX_NOMIX,
CDT_MIX_REPLACE_ABOVE_THRESHOLD,
CDT_MIX_REPLACE_BELOW_THRESHOLD)) {
/* Above/below threshold modes are not supported here, fallback to nomix (just in case). */
copy_v3_v3(no_dst, no_src);
}
else { /* Modes that support 'real' mix factor. */
/* Since we normalize in the end, MIX and ADD are the same op here. */
if (ELEM(mixmode, CDT_MIX_MIX, CDT_MIX_ADD)) {
add_v3_v3v3(no_tmp, no_dst, no_src);
normalize_v3(no_tmp);
}
else if (mixmode == CDT_MIX_SUB) {
sub_v3_v3v3(no_tmp, no_dst, no_src);
normalize_v3(no_tmp);
}
else if (mixmode == CDT_MIX_MUL) {
mul_v3_v3v3(no_tmp, no_dst, no_src);
normalize_v3(no_tmp);
}
else {
copy_v3_v3(no_tmp, no_src);
}
interp_v3_v3v3_slerp_safe(no_dst, no_dst, no_tmp, mixfactor);
}
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Callbacks for (#MTFace, #CD_MTFACE)
* \{ */
static void layerCopy_tface(const void *source, void *dest, int count)
{
2012-05-12 16:11:34 +00:00
const MTFace *source_tf = (const MTFace *)source;
MTFace *dest_tf = (MTFace *)dest;
2020-09-09 15:43:09 +02:00
for (int i = 0; i < count; i++) {
dest_tf[i] = source_tf[i];
}
}
static void layerInterp_tface(
const void **sources, const float *weights, const float *sub_weights, int count, void *dest)
{
MTFace *tf = static_cast<MTFace *>(dest);
float uv[4][2] = {{0.0f}};
2021-01-26 09:21:42 -06:00
const float *sub_weight = sub_weights;
for (int i = 0; i < count; i++) {
const float interp_weight = weights[i];
const MTFace *src = static_cast<const MTFace *>(sources[i]);
2021-01-26 09:21:42 -06:00
for (int j = 0; j < 4; j++) {
if (sub_weights) {
2021-01-26 09:21:42 -06:00
for (int k = 0; k < 4; k++, sub_weight++) {
madd_v2_v2fl(uv[j], src->uv[k], (*sub_weight) * interp_weight);
}
}
else {
madd_v2_v2fl(uv[j], src->uv[j], interp_weight);
}
}
}
2019-08-17 00:54:22 +10:00
/* Delay writing to the destination in case dest is in sources. */
*tf = *(MTFace *)(*sources);
memcpy(tf->uv, uv, sizeof(tf->uv));
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
}
static void layerSwap_tface(void *data, const int *corner_indices)
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
{
MTFace *tf = static_cast<MTFace *>(data);
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
float uv[4][2];
2021-01-26 09:21:42 -06:00
for (int j = 0; j < 4; j++) {
const int source_index = corner_indices[j];
copy_v2_v2(uv[j], tf->uv[source_index]);
}
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
memcpy(tf->uv, uv, sizeof(tf->uv));
}
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
static void layerDefault_tface(void *data, int count)
{
static MTFace default_tf = {{{0, 0}, {1, 0}, {1, 1}, {0, 1}}};
2012-05-12 16:11:34 +00:00
MTFace *tf = (MTFace *)data;
2020-09-09 15:43:09 +02:00
for (int i = 0; i < count; i++) {
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
tf[i] = default_tf;
}
}
static int layerMaxNum_tface()
{
return MAX_MTFACE;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Callbacks for (#MFloatProperty, #CD_PROP_FLOAT)
* \{ */
2011-04-16 13:00:41 +00:00
static void layerCopy_propFloat(const void *source, void *dest, int count)
{
2012-05-12 16:11:34 +00:00
memcpy(dest, source, sizeof(MFloatProperty) * count);
2011-04-16 13:00:41 +00:00
}
static void layerInterp_propFloat(const void **sources,
const float *weights,
const float *UNUSED(sub_weights),
int count,
void *dest)
{
float result = 0.0f;
for (int i = 0; i < count; i++) {
const float interp_weight = weights[i];
const float src = *(const float *)sources[i];
result += src * interp_weight;
}
*(float *)dest = result;
}
static bool layerValidate_propFloat(void *data, const uint totitems, const bool do_fixes)
{
MFloatProperty *fp = static_cast<MFloatProperty *>(data);
bool has_errors = false;
for (int i = 0; i < totitems; i++, fp++) {
if (!isfinite(fp->f)) {
if (do_fixes) {
fp->f = 0.0f;
}
has_errors = true;
}
}
return has_errors;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Callbacks for (#MIntProperty, #CD_PROP_INT32)
* \{ */
2011-04-16 13:00:41 +00:00
static void layerCopy_propInt(const void *source, void *dest, int count)
{
2012-05-12 16:11:34 +00:00
memcpy(dest, source, sizeof(MIntProperty) * count);
2011-04-16 13:00:41 +00:00
}
static void layerInterp_propInt(const void **sources,
const float *weights,
const float *UNUSED(sub_weights),
int count,
void *dest)
{
float result = 0.0f;
for (const int i : IndexRange(count)) {
const float weight = weights[i];
const float src = *static_cast<const int *>(sources[i]);
result += src * weight;
}
const int rounded_result = static_cast<int>(round(result));
*static_cast<int *>(dest) = rounded_result;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Callbacks for (#MStringProperty, #CD_PROP_STRING)
* \{ */
2011-04-16 13:00:41 +00:00
static void layerCopy_propString(const void *source, void *dest, int count)
{
2012-05-12 16:11:34 +00:00
memcpy(dest, source, sizeof(MStringProperty) * count);
2011-04-16 13:00:41 +00:00
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Callbacks for (#OrigSpaceFace, #CD_ORIGSPACE)
* \{ */
static void layerCopy_origspace_face(const void *source, void *dest, int count)
{
2012-05-12 16:11:34 +00:00
const OrigSpaceFace *source_tf = (const OrigSpaceFace *)source;
OrigSpaceFace *dest_tf = (OrigSpaceFace *)dest;
2020-09-09 15:43:09 +02:00
for (int i = 0; i < count; i++) {
dest_tf[i] = source_tf[i];
}
}
static void layerInterp_origspace_face(
const void **sources, const float *weights, const float *sub_weights, int count, void *dest)
{
OrigSpaceFace *osf = static_cast<OrigSpaceFace *>(dest);
float uv[4][2] = {{0.0f}};
2021-01-26 09:21:42 -06:00
const float *sub_weight = sub_weights;
for (int i = 0; i < count; i++) {
const float interp_weight = weights[i];
const OrigSpaceFace *src = static_cast<const OrigSpaceFace *>(sources[i]);
2021-01-26 09:21:42 -06:00
for (int j = 0; j < 4; j++) {
if (sub_weights) {
2021-01-26 09:21:42 -06:00
for (int k = 0; k < 4; k++, sub_weight++) {
madd_v2_v2fl(uv[j], src->uv[k], (*sub_weight) * interp_weight);
}
}
else {
madd_v2_v2fl(uv[j], src->uv[j], interp_weight);
}
}
}
2019-08-17 00:54:22 +10:00
/* Delay writing to the destination in case dest is in sources. */
memcpy(osf->uv, uv, sizeof(osf->uv));
}
static void layerSwap_origspace_face(void *data, const int *corner_indices)
{
OrigSpaceFace *osf = static_cast<OrigSpaceFace *>(data);
float uv[4][2];
2021-01-26 09:21:42 -06:00
for (int j = 0; j < 4; j++) {
copy_v2_v2(uv[j], osf->uv[corner_indices[j]]);
}
memcpy(osf->uv, uv, sizeof(osf->uv));
}
static void layerDefault_origspace_face(void *data, int count)
{
static OrigSpaceFace default_osf = {{{0, 0}, {1, 0}, {1, 1}, {0, 1}}};
2012-05-12 16:11:34 +00:00
OrigSpaceFace *osf = (OrigSpaceFace *)data;
2020-09-09 15:43:09 +02:00
for (int i = 0; i < count; i++) {
osf[i] = default_osf;
}
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Callbacks for (#MDisps, #CD_MDISPS)
* \{ */
static void layerSwap_mdisps(void *data, const int *ci)
{
MDisps *s = static_cast<MDisps *>(data);
if (s->disps) {
2012-05-12 16:11:34 +00:00
int nverts = (ci[1] == 3) ? 4 : 3; /* silly way to know vertex count of face */
2021-01-26 09:21:42 -06:00
int corners = multires_mdisp_corners(s);
int cornersize = s->totdisp / corners;
2012-05-12 16:11:34 +00:00
if (corners != nverts) {
/* happens when face changed vertex count in edit mode
* if it happened, just forgot displacement */
MEM_freeN(s->disps);
2012-05-12 16:11:34 +00:00
s->totdisp = (s->totdisp / corners) * nverts;
s->disps = (float(*)[3])MEM_calloc_arrayN(s->totdisp, sizeof(float[3]), "mdisp swap");
return;
}
float(*d)[3] = (float(*)[3])MEM_calloc_arrayN(s->totdisp, sizeof(float[3]), "mdisps swap");
2021-01-26 09:21:42 -06:00
for (int S = 0; S < corners; S++) {
memcpy(d + cornersize * S, s->disps + cornersize * ci[S], sizeof(float[3]) * cornersize);
}
2018-06-17 17:05:51 +02:00
MEM_freeN(s->disps);
2012-05-12 16:11:34 +00:00
s->disps = d;
}
}
static void layerCopy_mdisps(const void *source, void *dest, int count)
{
const MDisps *s = static_cast<const MDisps *>(source);
MDisps *d = static_cast<MDisps *>(dest);
2020-09-09 15:43:09 +02:00
for (int i = 0; i < count; i++) {
if (s[i].disps) {
d[i].disps = static_cast<float(*)[3]>(MEM_dupallocN(s[i].disps));
d[i].hidden = static_cast<unsigned int *>(MEM_dupallocN(s[i].hidden));
}
else {
d[i].disps = nullptr;
d[i].hidden = nullptr;
}
/* still copy even if not in memory, displacement can be external */
d[i].totdisp = s[i].totdisp;
d[i].level = s[i].level;
}
}
static void layerFree_mdisps(void *data, int count, int UNUSED(size))
{
MDisps *d = static_cast<MDisps *>(data);
2020-09-09 15:43:09 +02:00
for (int i = 0; i < count; i++) {
if (d[i].disps) {
MEM_freeN(d[i].disps);
}
if (d[i].hidden) {
MEM_freeN(d[i].hidden);
}
d[i].disps = nullptr;
d[i].hidden = nullptr;
d[i].totdisp = 0;
d[i].level = 0;
}
}
static bool layerRead_mdisps(CDataFile *cdf, void *data, int count)
{
MDisps *d = static_cast<MDisps *>(data);
for (int i = 0; i < count; i++) {
if (!d[i].disps) {
d[i].disps = (float(*)[3])MEM_calloc_arrayN(d[i].totdisp, sizeof(float[3]), "mdisps read");
}
if (!cdf_read_data(cdf, sizeof(float[3]) * d[i].totdisp, d[i].disps)) {
CLOG_ERROR(&LOG, "failed to read multires displacement %d/%d %d", i, count, d[i].totdisp);
return false;
}
}
return true;
}
static bool layerWrite_mdisps(CDataFile *cdf, const void *data, int count)
{
const MDisps *d = static_cast<const MDisps *>(data);
for (int i = 0; i < count; i++) {
if (!cdf_write_data(cdf, sizeof(float[3]) * d[i].totdisp, d[i].disps)) {
CLOG_ERROR(&LOG, "failed to write multires displacement %d/%d %d", i, count, d[i].totdisp);
return false;
}
}
return true;
}
static size_t layerFilesize_mdisps(CDataFile *UNUSED(cdf), const void *data, int count)
{
const MDisps *d = static_cast<const MDisps *>(data);
size_t size = 0;
2020-09-09 15:43:09 +02:00
for (int i = 0; i < count; i++) {
size += sizeof(float[3]) * d[i].totdisp;
}
return size;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Callbacks for (`float`, #CD_PAINT_MASK)
* \{ */
static void layerInterp_paint_mask(const void **sources,
const float *weights,
const float *UNUSED(sub_weights),
int count,
void *dest)
{
float mask = 0.0f;
for (int i = 0; i < count; i++) {
const float interp_weight = weights[i];
const float *src = static_cast<const float *>(sources[i]);
mask += (*src) * interp_weight;
}
*(float *)dest = mask;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Callbacks for (#GridPaintMask, #CD_GRID_PAINT_MASK)
* \{ */
static void layerCopy_grid_paint_mask(const void *source, void *dest, int count)
{
const GridPaintMask *s = static_cast<const GridPaintMask *>(source);
GridPaintMask *d = static_cast<GridPaintMask *>(dest);
2020-09-09 15:43:09 +02:00
for (int i = 0; i < count; i++) {
2012-05-12 16:11:34 +00:00
if (s[i].data) {
d[i].data = static_cast<float *>(MEM_dupallocN(s[i].data));
d[i].level = s[i].level;
}
else {
d[i].data = nullptr;
d[i].level = 0;
}
}
}
static void layerFree_grid_paint_mask(void *data, int count, int UNUSED(size))
{
GridPaintMask *gpm = static_cast<GridPaintMask *>(data);
2020-09-09 15:43:09 +02:00
for (int i = 0; i < count; i++) {
2021-08-06 13:59:38 +10:00
MEM_SAFE_FREE(gpm[i].data);
gpm[i].level = 0;
}
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Callbacks for (#MLoopCol, #CD_PROP_BYTE_COLOR)
* \{ */
static void layerCopyValue_mloopcol(const void *source,
void *dest,
const int mixmode,
const float mixfactor)
{
const MLoopCol *m1 = static_cast<const MLoopCol *>(source);
MLoopCol *m2 = static_cast<MLoopCol *>(dest);
unsigned char tmp_col[4];
if (ELEM(mixmode,
CDT_MIX_NOMIX,
CDT_MIX_REPLACE_ABOVE_THRESHOLD,
CDT_MIX_REPLACE_BELOW_THRESHOLD)) {
/* Modes that do a full copy or nothing. */
if (ELEM(mixmode, CDT_MIX_REPLACE_ABOVE_THRESHOLD, CDT_MIX_REPLACE_BELOW_THRESHOLD)) {
/* TODO: Check for a real valid way to get 'factor' value of our dest color? */
const float f = ((float)m2->r + (float)m2->g + (float)m2->b) / 3.0f;
if (mixmode == CDT_MIX_REPLACE_ABOVE_THRESHOLD && f < mixfactor) {
return; /* Do Nothing! */
}
if (mixmode == CDT_MIX_REPLACE_BELOW_THRESHOLD && f > mixfactor) {
return; /* Do Nothing! */
}
}
m2->r = m1->r;
m2->g = m1->g;
m2->b = m1->b;
m2->a = m1->a;
}
else { /* Modes that support 'real' mix factor. */
unsigned char src[4] = {m1->r, m1->g, m1->b, m1->a};
unsigned char dst[4] = {m2->r, m2->g, m2->b, m2->a};
if (mixmode == CDT_MIX_MIX) {
blend_color_mix_byte(tmp_col, dst, src);
}
else if (mixmode == CDT_MIX_ADD) {
blend_color_add_byte(tmp_col, dst, src);
}
else if (mixmode == CDT_MIX_SUB) {
blend_color_sub_byte(tmp_col, dst, src);
}
else if (mixmode == CDT_MIX_MUL) {
blend_color_mul_byte(tmp_col, dst, src);
}
else {
memcpy(tmp_col, src, sizeof(tmp_col));
}
blend_color_interpolate_byte(dst, dst, tmp_col, mixfactor);
m2->r = (char)dst[0];
m2->g = (char)dst[1];
m2->b = (char)dst[2];
m2->a = (char)dst[3];
}
}
static bool layerEqual_mloopcol(const void *data1, const void *data2)
{
const MLoopCol *m1 = static_cast<const MLoopCol *>(data1);
const MLoopCol *m2 = static_cast<const MLoopCol *>(data2);
float r, g, b, a;
r = m1->r - m2->r;
g = m1->g - m2->g;
b = m1->b - m2->b;
a = m1->a - m2->a;
return r * r + g * g + b * b + a * a < 0.001f;
}
static void layerMultiply_mloopcol(void *data, float fac)
{
MLoopCol *m = static_cast<MLoopCol *>(data);
m->r = (float)m->r * fac;
m->g = (float)m->g * fac;
m->b = (float)m->b * fac;
m->a = (float)m->a * fac;
}
static void layerAdd_mloopcol(void *data1, const void *data2)
{
MLoopCol *m = static_cast<MLoopCol *>(data1);
const MLoopCol *m2 = static_cast<const MLoopCol *>(data2);
m->r += m2->r;
m->g += m2->g;
m->b += m2->b;
m->a += m2->a;
}
static void layerDoMinMax_mloopcol(const void *data, void *vmin, void *vmax)
{
const MLoopCol *m = static_cast<const MLoopCol *>(data);
MLoopCol *min = static_cast<MLoopCol *>(vmin);
MLoopCol *max = static_cast<MLoopCol *>(vmax);
if (m->r < min->r) {
min->r = m->r;
}
if (m->g < min->g) {
min->g = m->g;
}
if (m->b < min->b) {
min->b = m->b;
}
if (m->a < min->a) {
min->a = m->a;
}
if (m->r > max->r) {
max->r = m->r;
}
if (m->g > max->g) {
max->g = m->g;
}
if (m->b > max->b) {
max->b = m->b;
}
if (m->a > max->a) {
max->a = m->a;
}
}
static void layerInitMinMax_mloopcol(void *vmin, void *vmax)
{
MLoopCol *min = static_cast<MLoopCol *>(vmin);
MLoopCol *max = static_cast<MLoopCol *>(vmax);
min->r = 255;
min->g = 255;
min->b = 255;
min->a = 255;
max->r = 0;
max->g = 0;
max->b = 0;
max->a = 0;
}
static void layerDefault_mloopcol(void *data, int count)
{
2012-04-29 15:47:02 +00:00
MLoopCol default_mloopcol = {255, 255, 255, 255};
2012-05-12 16:11:34 +00:00
MLoopCol *mlcol = (MLoopCol *)data;
2020-09-09 15:43:09 +02:00
for (int i = 0; i < count; i++) {
mlcol[i] = default_mloopcol;
}
}
static void layerInterp_mloopcol(const void **sources,
const float *weights,
const float *UNUSED(sub_weights),
int count,
void *dest)
{
MLoopCol *mc = static_cast<MLoopCol *>(dest);
struct {
float a;
float r;
float g;
float b;
} col = {0};
for (int i = 0; i < count; i++) {
const float interp_weight = weights[i];
const MLoopCol *src = static_cast<const MLoopCol *>(sources[i]);
col.r += src->r * interp_weight;
col.g += src->g * interp_weight;
col.b += src->b * interp_weight;
col.a += src->a * interp_weight;
}
/* Subdivide smooth or fractal can cause problems without clamping
* although weights should also not cause this situation */
2019-08-17 00:54:22 +10:00
/* Also delay writing to the destination in case dest is in sources. */
mc->r = round_fl_to_uchar_clamp(col.r);
mc->g = round_fl_to_uchar_clamp(col.g);
mc->b = round_fl_to_uchar_clamp(col.b);
mc->a = round_fl_to_uchar_clamp(col.a);
}
static int layerMaxNum_mloopcol()
{
return MAX_MCOL;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Callbacks for (#MLoopUV, #CD_MLOOPUV)
* \{ */
static void layerCopyValue_mloopuv(const void *source,
void *dest,
const int mixmode,
const float mixfactor)
{
const MLoopUV *luv1 = static_cast<const MLoopUV *>(source);
MLoopUV *luv2 = static_cast<MLoopUV *>(dest);
/* We only support a limited subset of advanced mixing here -
* namely the mixfactor interpolation. */
if (mixmode == CDT_MIX_NOMIX) {
copy_v2_v2(luv2->uv, luv1->uv);
}
else {
interp_v2_v2v2(luv2->uv, luv2->uv, luv1->uv, mixfactor);
}
}
static bool layerEqual_mloopuv(const void *data1, const void *data2)
{
const MLoopUV *luv1 = static_cast<const MLoopUV *>(data1);
const MLoopUV *luv2 = static_cast<const MLoopUV *>(data2);
return len_squared_v2v2(luv1->uv, luv2->uv) < 0.00001f;
}
static void layerMultiply_mloopuv(void *data, float fac)
{
MLoopUV *luv = static_cast<MLoopUV *>(data);
mul_v2_fl(luv->uv, fac);
}
static void layerInitMinMax_mloopuv(void *vmin, void *vmax)
{
MLoopUV *min = static_cast<MLoopUV *>(vmin);
MLoopUV *max = static_cast<MLoopUV *>(vmax);
INIT_MINMAX2(min->uv, max->uv);
}
static void layerDoMinMax_mloopuv(const void *data, void *vmin, void *vmax)
{
const MLoopUV *luv = static_cast<const MLoopUV *>(data);
MLoopUV *min = static_cast<MLoopUV *>(vmin);
MLoopUV *max = static_cast<MLoopUV *>(vmax);
minmax_v2v2_v2(min->uv, max->uv, luv->uv);
}
static void layerAdd_mloopuv(void *data1, const void *data2)
{
MLoopUV *l1 = static_cast<MLoopUV *>(data1);
const MLoopUV *l2 = static_cast<const MLoopUV *>(data2);
add_v2_v2(l1->uv, l2->uv);
}
static void layerInterp_mloopuv(const void **sources,
const float *weights,
const float *UNUSED(sub_weights),
int count,
void *dest)
{
float uv[2];
int flag = 0;
zero_v2(uv);
for (int i = 0; i < count; i++) {
const float interp_weight = weights[i];
const MLoopUV *src = static_cast<const MLoopUV *>(sources[i]);
madd_v2_v2fl(uv, src->uv, interp_weight);
if (interp_weight > 0.0f) {
flag |= src->flag;
}
}
2019-08-17 00:54:22 +10:00
/* Delay writing to the destination in case dest is in sources. */
copy_v2_v2(((MLoopUV *)dest)->uv, uv);
((MLoopUV *)dest)->flag = flag;
}
static bool layerValidate_mloopuv(void *data, const uint totitems, const bool do_fixes)
{
MLoopUV *uv = static_cast<MLoopUV *>(data);
bool has_errors = false;
for (int i = 0; i < totitems; i++, uv++) {
if (!is_finite_v2(uv->uv)) {
if (do_fixes) {
zero_v2(uv->uv);
}
has_errors = true;
}
}
return has_errors;
}
/* origspace is almost exact copy of mloopuv's, keep in sync */
static void layerCopyValue_mloop_origspace(const void *source,
void *dest,
const int UNUSED(mixmode),
const float UNUSED(mixfactor))
{
const OrigSpaceLoop *luv1 = static_cast<const OrigSpaceLoop *>(source);
OrigSpaceLoop *luv2 = static_cast<OrigSpaceLoop *>(dest);
copy_v2_v2(luv2->uv, luv1->uv);
}
static bool layerEqual_mloop_origspace(const void *data1, const void *data2)
{
const OrigSpaceLoop *luv1 = static_cast<const OrigSpaceLoop *>(data1);
const OrigSpaceLoop *luv2 = static_cast<const OrigSpaceLoop *>(data2);
return len_squared_v2v2(luv1->uv, luv2->uv) < 0.00001f;
}
static void layerMultiply_mloop_origspace(void *data, float fac)
{
OrigSpaceLoop *luv = static_cast<OrigSpaceLoop *>(data);
mul_v2_fl(luv->uv, fac);
}
static void layerInitMinMax_mloop_origspace(void *vmin, void *vmax)
{
OrigSpaceLoop *min = static_cast<OrigSpaceLoop *>(vmin);
OrigSpaceLoop *max = static_cast<OrigSpaceLoop *>(vmax);
INIT_MINMAX2(min->uv, max->uv);
}
static void layerDoMinMax_mloop_origspace(const void *data, void *vmin, void *vmax)
{
const OrigSpaceLoop *luv = static_cast<const OrigSpaceLoop *>(data);
OrigSpaceLoop *min = static_cast<OrigSpaceLoop *>(vmin);
OrigSpaceLoop *max = static_cast<OrigSpaceLoop *>(vmax);
minmax_v2v2_v2(min->uv, max->uv, luv->uv);
}
static void layerAdd_mloop_origspace(void *data1, const void *data2)
{
OrigSpaceLoop *l1 = static_cast<OrigSpaceLoop *>(data1);
const OrigSpaceLoop *l2 = static_cast<const OrigSpaceLoop *>(data2);
add_v2_v2(l1->uv, l2->uv);
}
static void layerInterp_mloop_origspace(const void **sources,
const float *weights,
const float *UNUSED(sub_weights),
int count,
void *dest)
{
float uv[2];
zero_v2(uv);
for (int i = 0; i < count; i++) {
const float interp_weight = weights[i];
const OrigSpaceLoop *src = static_cast<const OrigSpaceLoop *>(sources[i]);
madd_v2_v2fl(uv, src->uv, interp_weight);
}
2019-08-17 00:54:22 +10:00
/* Delay writing to the destination in case dest is in sources. */
copy_v2_v2(((OrigSpaceLoop *)dest)->uv, uv);
}
/* --- end copy */
static void layerInterp_mcol(
const void **sources, const float *weights, const float *sub_weights, int count, void *dest)
{
MCol *mc = static_cast<MCol *>(dest);
struct {
float a;
float r;
float g;
float b;
} col[4] = {{0.0f}};
2020-09-09 15:43:09 +02:00
const float *sub_weight = sub_weights;
for (int i = 0; i < count; i++) {
const float interp_weight = weights[i];
2020-09-09 15:43:09 +02:00
for (int j = 0; j < 4; j++) {
if (sub_weights) {
const MCol *src = static_cast<const MCol *>(sources[i]);
2020-09-09 15:43:09 +02:00
for (int k = 0; k < 4; k++, sub_weight++, src++) {
const float w = (*sub_weight) * interp_weight;
col[j].a += src->a * w;
col[j].r += src->r * w;
col[j].g += src->g * w;
col[j].b += src->b * w;
}
}
else {
const MCol *src = static_cast<const MCol *>(sources[i]);
col[j].a += src[j].a * interp_weight;
col[j].r += src[j].r * interp_weight;
col[j].g += src[j].g * interp_weight;
col[j].b += src[j].b * interp_weight;
}
}
}
2019-08-17 00:54:22 +10:00
/* Delay writing to the destination in case dest is in sources. */
2020-09-09 15:43:09 +02:00
for (int j = 0; j < 4; j++) {
/* Subdivide smooth or fractal can cause problems without clamping
* although weights should also not cause this situation */
mc[j].a = round_fl_to_uchar_clamp(col[j].a);
mc[j].r = round_fl_to_uchar_clamp(col[j].r);
mc[j].g = round_fl_to_uchar_clamp(col[j].g);
mc[j].b = round_fl_to_uchar_clamp(col[j].b);
}
}
static void layerSwap_mcol(void *data, const int *corner_indices)
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
{
MCol *mcol = static_cast<MCol *>(data);
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
MCol col[4];
2021-01-26 09:21:42 -06:00
for (int j = 0; j < 4; j++) {
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
col[j] = mcol[corner_indices[j]];
}
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
memcpy(mcol, col, sizeof(col));
}
static void layerDefault_mcol(void *data, int count)
{
static MCol default_mcol = {255, 255, 255, 255};
2012-05-12 16:11:34 +00:00
MCol *mcol = (MCol *)data;
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
2020-09-09 15:43:09 +02:00
for (int i = 0; i < 4 * count; i++) {
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
mcol[i] = default_mcol;
}
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
}
static void layerDefault_origindex(void *data, int count)
{
copy_vn_i((int *)data, count, ORIGINDEX_NONE);
}
static void layerInterp_bweight(const void **sources,
const float *weights,
const float *UNUSED(sub_weights),
int count,
void *dest)
{
float **in = (float **)sources;
2018-06-17 17:05:51 +02:00
if (count <= 0) {
return;
}
2020-09-09 15:43:09 +02:00
float f = 0.0f;
for (int i = 0; i < count; i++) {
const float interp_weight = weights[i];
f += *in[i] * interp_weight;
}
2019-08-17 00:54:22 +10:00
/* Delay writing to the destination in case dest is in sources. */
*((float *)dest) = f;
}
static void layerInterp_shapekey(const void **sources,
const float *weights,
const float *UNUSED(sub_weights),
int count,
void *dest)
{
float **in = (float **)sources;
if (count <= 0) {
return;
}
2020-09-09 15:43:09 +02:00
float co[3];
zero_v3(co);
for (int i = 0; i < count; i++) {
const float interp_weight = weights[i];
madd_v3_v3fl(co, in[i], interp_weight);
}
2019-08-17 00:54:22 +10:00
/* Delay writing to the destination in case dest is in sources. */
copy_v3_v3((float *)dest, co);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Callbacks for (#MVertSkin, #CD_MVERT_SKIN)
* \{ */
static void layerDefault_mvert_skin(void *data, int count)
{
MVertSkin *vs = static_cast<MVertSkin *>(data);
2018-06-17 17:05:51 +02:00
2020-09-09 15:43:09 +02:00
for (int i = 0; i < count; i++) {
copy_v3_fl(vs[i].radius, 0.25f);
vs[i].flag = 0;
}
}
2012-05-22 22:03:41 +00:00
static void layerCopy_mvert_skin(const void *source, void *dest, int count)
{
2018-12-13 12:30:38 +11:00
memcpy(dest, source, sizeof(MVertSkin) * count);
}
static void layerInterp_mvert_skin(const void **sources,
const float *weights,
const float *UNUSED(sub_weights),
int count,
void *dest)
{
2020-09-09 15:43:09 +02:00
float radius[3];
zero_v3(radius);
2020-09-09 15:43:09 +02:00
for (int i = 0; i < count; i++) {
const float interp_weight = weights[i];
const MVertSkin *vs_src = static_cast<const MVertSkin *>(sources[i]);
madd_v3_v3fl(radius, vs_src->radius, interp_weight);
}
2019-08-17 00:54:22 +10:00
/* Delay writing to the destination in case dest is in sources. */
MVertSkin *vs_dst = static_cast<MVertSkin *>(dest);
copy_v3_v3(vs_dst->radius, radius);
vs_dst->flag &= ~MVERT_SKIN_ROOT;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Callbacks for (`short[4][3]`, #CD_TESSLOOPNORMAL)
* \{ */
static void layerSwap_flnor(void *data, const int *corner_indices)
{
short(*flnors)[4][3] = static_cast<short(*)[4][3]>(data);
short nors[4][3];
int i = 4;
while (i--) {
copy_v3_v3_short(nors[i], (*flnors)[corner_indices[i]]);
}
memcpy(flnors, nors, sizeof(nors));
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Callbacks for (`int`, #CD_FACEMAP)
* \{ */
static void layerDefault_fmap(void *data, int count)
{
int *fmap_num = (int *)data;
for (int i = 0; i < count; i++) {
fmap_num[i] = -1;
}
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Callbacks for (#MPropCol, #CD_PROP_COLOR)
* \{ */
static void layerCopyValue_propcol(const void *source,
void *dest,
const int mixmode,
const float mixfactor)
{
const MPropCol *m1 = static_cast<const MPropCol *>(source);
MPropCol *m2 = static_cast<MPropCol *>(dest);
float tmp_col[4];
if (ELEM(mixmode,
CDT_MIX_NOMIX,
CDT_MIX_REPLACE_ABOVE_THRESHOLD,
CDT_MIX_REPLACE_BELOW_THRESHOLD)) {
/* Modes that do a full copy or nothing. */
if (ELEM(mixmode, CDT_MIX_REPLACE_ABOVE_THRESHOLD, CDT_MIX_REPLACE_BELOW_THRESHOLD)) {
/* TODO: Check for a real valid way to get 'factor' value of our dest color? */
const float f = (m2->color[0] + m2->color[1] + m2->color[2]) / 3.0f;
if (mixmode == CDT_MIX_REPLACE_ABOVE_THRESHOLD && f < mixfactor) {
return; /* Do Nothing! */
}
if (mixmode == CDT_MIX_REPLACE_BELOW_THRESHOLD && f > mixfactor) {
return; /* Do Nothing! */
}
}
copy_v4_v4(m2->color, m1->color);
}
else { /* Modes that support 'real' mix factor. */
if (mixmode == CDT_MIX_MIX) {
blend_color_mix_float(tmp_col, m2->color, m1->color);
}
else if (mixmode == CDT_MIX_ADD) {
blend_color_add_float(tmp_col, m2->color, m1->color);
}
else if (mixmode == CDT_MIX_SUB) {
blend_color_sub_float(tmp_col, m2->color, m1->color);
}
else if (mixmode == CDT_MIX_MUL) {
blend_color_mul_float(tmp_col, m2->color, m1->color);
}
else {
memcpy(tmp_col, m1->color, sizeof(tmp_col));
}
blend_color_interpolate_float(m2->color, m2->color, tmp_col, mixfactor);
copy_v4_v4(m2->color, m1->color);
}
}
static bool layerEqual_propcol(const void *data1, const void *data2)
{
const MPropCol *m1 = static_cast<const MPropCol *>(data1);
const MPropCol *m2 = static_cast<const MPropCol *>(data2);
float tot = 0;
for (int i = 0; i < 4; i++) {
float c = (m1->color[i] - m2->color[i]);
tot += c * c;
}
return tot < 0.001f;
}
static void layerMultiply_propcol(void *data, float fac)
{
MPropCol *m = static_cast<MPropCol *>(data);
mul_v4_fl(m->color, fac);
}
static void layerAdd_propcol(void *data1, const void *data2)
{
MPropCol *m = static_cast<MPropCol *>(data1);
const MPropCol *m2 = static_cast<const MPropCol *>(data2);
add_v4_v4(m->color, m2->color);
}
static void layerDoMinMax_propcol(const void *data, void *vmin, void *vmax)
{
const MPropCol *m = static_cast<const MPropCol *>(data);
MPropCol *min = static_cast<MPropCol *>(vmin);
MPropCol *max = static_cast<MPropCol *>(vmax);
minmax_v4v4_v4(min->color, max->color, m->color);
}
static void layerInitMinMax_propcol(void *vmin, void *vmax)
{
MPropCol *min = static_cast<MPropCol *>(vmin);
MPropCol *max = static_cast<MPropCol *>(vmax);
copy_v4_fl(min->color, FLT_MAX);
copy_v4_fl(max->color, FLT_MIN);
}
static void layerDefault_propcol(void *data, int count)
{
/* Default to white, full alpha. */
2020-05-28 14:33:37 +10:00
MPropCol default_propcol = {{1.0f, 1.0f, 1.0f, 1.0f}};
MPropCol *pcol = (MPropCol *)data;
2020-09-09 15:43:09 +02:00
for (int i = 0; i < count; i++) {
copy_v4_v4(pcol[i].color, default_propcol.color);
}
}
static void layerInterp_propcol(const void **sources,
const float *weights,
const float *UNUSED(sub_weights),
int count,
void *dest)
{
MPropCol *mc = static_cast<MPropCol *>(dest);
float col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
for (int i = 0; i < count; i++) {
const float interp_weight = weights[i];
const MPropCol *src = static_cast<const MPropCol *>(sources[i]);
madd_v4_v4fl(col, src->color, interp_weight);
}
copy_v4_v4(mc->color, col);
}
static int layerMaxNum_propcol()
{
return MAX_MCOL;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Callbacks for (#vec3f, #CD_PROP_FLOAT3)
* \{ */
static void layerInterp_propfloat3(const void **sources,
const float *weights,
const float *UNUSED(sub_weights),
int count,
void *dest)
{
vec3f result = {0.0f, 0.0f, 0.0f};
for (int i = 0; i < count; i++) {
const float interp_weight = weights[i];
const vec3f *src = static_cast<const vec3f *>(sources[i]);
madd_v3_v3fl(&result.x, &src->x, interp_weight);
}
copy_v3_v3((float *)dest, &result.x);
}
static void layerMultiply_propfloat3(void *data, float fac)
{
vec3f *vec = static_cast<vec3f *>(data);
vec->x *= fac;
vec->y *= fac;
vec->z *= fac;
}
static void layerAdd_propfloat3(void *data1, const void *data2)
{
vec3f *vec1 = static_cast<vec3f *>(data1);
const vec3f *vec2 = static_cast<const vec3f *>(data2);
vec1->x += vec2->x;
vec1->y += vec2->y;
vec1->z += vec2->z;
}
static bool layerValidate_propfloat3(void *data, const uint totitems, const bool do_fixes)
{
float *values = static_cast<float *>(data);
bool has_errors = false;
for (int i = 0; i < totitems * 3; i++) {
if (!isfinite(values[i])) {
if (do_fixes) {
values[i] = 0.0f;
}
has_errors = true;
}
}
return has_errors;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Callbacks for (#vec2f, #CD_PROP_FLOAT2)
* \{ */
static void layerInterp_propfloat2(const void **sources,
const float *weights,
const float *UNUSED(sub_weights),
int count,
void *dest)
{
vec2f result = {0.0f, 0.0f};
for (int i = 0; i < count; i++) {
const float interp_weight = weights[i];
const vec2f *src = static_cast<const vec2f *>(sources[i]);
madd_v2_v2fl(&result.x, &src->x, interp_weight);
}
copy_v2_v2((float *)dest, &result.x);
}
static void layerMultiply_propfloat2(void *data, float fac)
{
vec2f *vec = static_cast<vec2f *>(data);
vec->x *= fac;
vec->y *= fac;
}
static void layerAdd_propfloat2(void *data1, const void *data2)
{
vec2f *vec1 = static_cast<vec2f *>(data1);
const vec2f *vec2 = static_cast<const vec2f *>(data2);
vec1->x += vec2->x;
vec1->y += vec2->y;
}
static bool layerValidate_propfloat2(void *data, const uint totitems, const bool do_fixes)
{
float *values = static_cast<float *>(data);
bool has_errors = false;
for (int i = 0; i < totitems * 2; i++) {
if (!isfinite(values[i])) {
if (do_fixes) {
values[i] = 0.0f;
}
has_errors = true;
}
}
return has_errors;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Callbacks for (`bool`, #CD_PROP_BOOL)
* \{ */
static void layerInterp_propbool(const void **sources,
const float *weights,
const float *UNUSED(sub_weights),
int count,
void *dest)
{
bool result = false;
for (int i = 0; i < count; i++) {
const float interp_weight = weights[i];
const bool src = *(const bool *)sources[i];
result |= src && (interp_weight > 0.0f);
}
*(bool *)dest = result;
}
static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
/* 0: CD_MVERT */
{sizeof(MVert), "MVert", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
/* 1: CD_MSTICKY */ /* DEPRECATED */
{sizeof(float[2]), "", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
/* 2: CD_MDEFORMVERT */
{sizeof(MDeformVert),
"MDeformVert",
1,
nullptr,
layerCopy_mdeformvert,
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
layerFree_mdeformvert,
layerInterp_mdeformvert,
nullptr,
nullptr},
/* 3: CD_MEDGE */
{sizeof(MEdge), "MEdge", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
/* 4: CD_MFACE */
{sizeof(MFace), "MFace", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
/* 5: CD_MTFACE */
{sizeof(MTFace), "MTFace", 1,
N_("UVMap"), layerCopy_tface, nullptr,
layerInterp_tface, layerSwap_tface, layerDefault_tface,
nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr,
nullptr, layerMaxNum_tface},
/* 6: CD_MCOL */
/* 4 MCol structs per face */
{sizeof(MCol[4]),
"MCol",
4,
N_("Col"),
nullptr,
nullptr,
layerInterp_mcol,
layerSwap_mcol,
layerDefault_mcol,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
layerMaxNum_mloopcol},
/* 7: CD_ORIGINDEX */
{sizeof(int), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, layerDefault_origindex},
/* 8: CD_NORMAL */
/* 3 floats per normal vector */
{sizeof(float[3]),
"vec3f",
1,
nullptr,
nullptr,
nullptr,
layerInterp_normal,
nullptr,
nullptr,
Refactor: Move normals out of MVert, lazy calculation As described in T91186, this commit moves mesh vertex normals into a contiguous array of float vectors in a custom data layer, how face normals are currently stored. The main interface is documented in `BKE_mesh.h`. Vertex and face normals are now calculated on-demand and cached, retrieved with an "ensure" function. Since the logical state of a mesh is now "has normals when necessary", they can be retrieved from a `const` mesh. The goal is to use on-demand calculation for all derived data, but leave room for eager calculation for performance purposes (modifier evaluation is threaded, but viewport data generation is not). **Benefits** This moves us closer to a SoA approach rather than the current AoS paradigm. Accessing a contiguous `float3` is much more efficient than retrieving data from a larger struct. The memory requirements for accessing only normals or vertex locations are smaller, and at the cost of more memory usage for just normals, they now don't have to be converted between float and short, which also simplifies code In the future, the remaining items can be removed from `MVert`, leaving only `float3`, which has similar benefits (see T93602). Removing the combination of derived and original data makes it conceptually simpler to only calculate normals when necessary. This is especially important now that we have more opportunities for temporary meshes in geometry nodes. **Performance** In addition to the theoretical future performance improvements by making `MVert == float3`, I've done some basic performance testing on this patch directly. The data is fairly rough, but it gives an idea about where things stand generally. - Mesh line primitive 4m Verts: 1.16x faster (36 -> 31 ms), showing that accessing just `MVert` is now more efficient. - Spring Splash Screen: 1.03-1.06 -> 1.06-1.11 FPS, a very slight change that at least shows there is no regression. - Sprite Fright Snail Smoosh: 3.30-3.40 -> 3.42-3.50 FPS, a small but observable speedup. - Set Position Node with Scaled Normal: 1.36x faster (53 -> 39 ms), shows that using normals in geometry nodes is faster. - Normal Calculation 1.6m Vert Cube: 1.19x faster (25 -> 21 ms), shows that calculating normals is slightly faster now. - File Size of 1.6m Vert Cube: 1.03x smaller (214.7 -> 208.4 MB), Normals are not saved in files, which can help with large meshes. As for memory usage, it may be slightly more in some cases, but I didn't observe any difference in the production files I tested. **Tests** Some modifiers and cycles test results need to be updated with this commit, for two reasons: - The subdivision surface modifier is not responsible for calculating normals anymore. In master, the modifier creates different normals than the result of the `Mesh` normal calculation, so this is a bug fix. - There are small differences in the results of some modifiers that use normals because they are not converted to and from `short` anymore. **Future improvements** - Remove `ModifierTypeInfo::dependsOnNormals`. Code in each modifier already retrieves normals if they are needed anyway. - Copy normals as part of a better CoW system for attributes. - Make more areas use lazy instead of eager normal calculation. - Remove `BKE_mesh_normals_tag_dirty` in more places since that is now the default state of a new mesh. - Possibly apply a similar change to derived face corner normals. Differential Revision: https://developer.blender.org/D12770
2022-01-13 14:37:58 -06:00
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
layerCopyValue_normal},
/* 9: CD_FACEMAP */
{sizeof(int), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, layerDefault_fmap, nullptr},
/* 10: CD_PROP_FLOAT */
{sizeof(MFloatProperty),
"MFloatProperty",
1,
N_("Float"),
layerCopy_propFloat,
nullptr,
layerInterp_propFloat,
nullptr,
nullptr,
layerValidate_propFloat},
/* 11: CD_PROP_INT32 */
{sizeof(MIntProperty),
"MIntProperty",
1,
N_("Int"),
layerCopy_propInt,
nullptr,
layerInterp_propInt,
nullptr},
/* 12: CD_PROP_STRING */
{sizeof(MStringProperty),
"MStringProperty",
1,
N_("String"),
layerCopy_propString,
nullptr,
nullptr,
nullptr},
/* 13: CD_ORIGSPACE */
{sizeof(OrigSpaceFace),
"OrigSpaceFace",
1,
N_("UVMap"),
layerCopy_origspace_face,
nullptr,
layerInterp_origspace_face,
layerSwap_origspace_face,
layerDefault_origspace_face},
/* 14: CD_ORCO */
{sizeof(float[3]), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
/* 15: CD_MTEXPOLY */ /* DEPRECATED */
/* NOTE: when we expose the UV Map / TexFace split to the user,
* change this back to face Texture. */
{sizeof(int), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
/* 16: CD_MLOOPUV */
{sizeof(MLoopUV),
"MLoopUV",
1,
N_("UVMap"),
nullptr,
nullptr,
layerInterp_mloopuv,
nullptr,
nullptr,
layerValidate_mloopuv,
layerEqual_mloopuv,
layerMultiply_mloopuv,
layerInitMinMax_mloopuv,
layerAdd_mloopuv,
layerDoMinMax_mloopuv,
layerCopyValue_mloopuv,
nullptr,
nullptr,
nullptr,
layerMaxNum_tface},
/* 17: CD_PROP_BYTE_COLOR */
{sizeof(MLoopCol),
"MLoopCol",
1,
N_("Col"),
nullptr,
nullptr,
layerInterp_mloopcol,
nullptr,
layerDefault_mloopcol,
nullptr,
layerEqual_mloopcol,
layerMultiply_mloopcol,
layerInitMinMax_mloopcol,
layerAdd_mloopcol,
layerDoMinMax_mloopcol,
layerCopyValue_mloopcol,
nullptr,
nullptr,
nullptr,
layerMaxNum_mloopcol},
2015-07-10 16:47:39 +10:00
/* 18: CD_TANGENT */
{sizeof(float[4][4]), "", 0, N_("Tangent"), nullptr, nullptr, nullptr, nullptr, nullptr},
/* 19: CD_MDISPS */
2015-07-10 16:47:39 +10:00
{sizeof(MDisps),
"MDisps",
1,
nullptr,
2015-07-10 16:47:39 +10:00
layerCopy_mdisps,
layerFree_mdisps,
nullptr,
layerSwap_mdisps,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
layerRead_mdisps,
layerWrite_mdisps,
layerFilesize_mdisps},
/* 20: CD_PREVIEW_MCOL */
{sizeof(MCol[4]),
"MCol",
4,
N_("PreviewCol"),
nullptr,
nullptr,
layerInterp_mcol,
layerSwap_mcol,
layerDefault_mcol},
/* 21: CD_ID_MCOL */ /* DEPRECATED */
{sizeof(MCol[4]), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
/* 22: CD_TEXTURE_MCOL */
{sizeof(MCol[4]),
"MCol",
4,
N_("TexturedCol"),
nullptr,
nullptr,
layerInterp_mcol,
layerSwap_mcol,
layerDefault_mcol},
2012-05-12 16:11:34 +00:00
/* 23: CD_CLOTH_ORCO */
{sizeof(float[3]), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
2012-05-12 16:11:34 +00:00
/* 24: CD_RECAST */
{sizeof(MRecast), "MRecast", 1, N_("Recast"), nullptr, nullptr, nullptr, nullptr},
/* 25: CD_MPOLY */
{sizeof(MPoly), "MPoly", 1, N_("NGon Face"), nullptr, nullptr, nullptr, nullptr, nullptr},
/* 26: CD_MLOOP */
{sizeof(MLoop),
"MLoop",
1,
N_("NGon Face-Vertex"),
nullptr,
nullptr,
nullptr,
nullptr,
nullptr},
/* 27: CD_SHAPE_KEYINDEX */
{sizeof(int), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
/* 28: CD_SHAPEKEY */
{sizeof(float[3]), "", 0, N_("ShapeKey"), nullptr, nullptr, layerInterp_shapekey},
/* 29: CD_BWEIGHT */
{sizeof(float), "", 0, N_("BevelWeight"), nullptr, nullptr, layerInterp_bweight},
/* 30: CD_CREASE */
/* NOTE: we do not interpolate crease data as it should be either inherited for subdivided
* edges, or for vertex creases, only present on the original vertex. */
{sizeof(float), "", 0, N_("SubSurfCrease"), nullptr, nullptr, nullptr},
/* 31: CD_ORIGSPACE_MLOOP */
{sizeof(OrigSpaceLoop),
"OrigSpaceLoop",
1,
N_("OS Loop"),
nullptr,
nullptr,
layerInterp_mloop_origspace,
nullptr,
nullptr,
nullptr,
layerEqual_mloop_origspace,
layerMultiply_mloop_origspace,
layerInitMinMax_mloop_origspace,
layerAdd_mloop_origspace,
layerDoMinMax_mloop_origspace,
layerCopyValue_mloop_origspace},
/* 32: CD_PREVIEW_MLOOPCOL */
{sizeof(MLoopCol),
"MLoopCol",
1,
N_("PreviewLoopCol"),
nullptr,
nullptr,
layerInterp_mloopcol,
nullptr,
layerDefault_mloopcol,
nullptr,
layerEqual_mloopcol,
layerMultiply_mloopcol,
layerInitMinMax_mloopcol,
layerAdd_mloopcol,
layerDoMinMax_mloopcol,
layerCopyValue_mloopcol},
/* 33: CD_BM_ELEM_PYPTR */
{sizeof(void *),
"",
1,
nullptr,
layerCopy_bmesh_elem_py_ptr,
layerFree_bmesh_elem_py_ptr,
nullptr,
nullptr,
nullptr},
/* 34: CD_PAINT_MASK */
{sizeof(float), "", 0, nullptr, nullptr, nullptr, layerInterp_paint_mask, nullptr, nullptr},
/* 35: CD_GRID_PAINT_MASK */
{sizeof(GridPaintMask),
"GridPaintMask",
1,
nullptr,
layerCopy_grid_paint_mask,
layerFree_grid_paint_mask,
nullptr,
nullptr,
nullptr},
/* 36: CD_MVERT_SKIN */
{sizeof(MVertSkin),
"MVertSkin",
1,
nullptr,
layerCopy_mvert_skin,
nullptr,
layerInterp_mvert_skin,
nullptr,
layerDefault_mvert_skin},
/* 37: CD_FREESTYLE_EDGE */
{sizeof(FreestyleEdge),
"FreestyleEdge",
1,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr},
/* 38: CD_FREESTYLE_FACE */
{sizeof(FreestyleFace),
"FreestyleFace",
1,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr},
/* 39: CD_MLOOPTANGENT */
{sizeof(float[4]), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
/* 40: CD_TESSLOOPNORMAL */
{sizeof(short[4][3]), "", 0, nullptr, nullptr, nullptr, nullptr, layerSwap_flnor, nullptr},
/* 41: CD_CUSTOMLOOPNORMAL */
{sizeof(short[2]), "vec2s", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
2020-03-05 14:53:23 +01:00
/* 42: CD_SCULPT_FACE_SETS */
{sizeof(int), "", 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
/* 43: CD_LOCATION */
{sizeof(float[3]), "vec3f", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
/* 44: CD_RADIUS */
{sizeof(float), "MFloatProperty", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
/* 45: CD_PROP_INT8 */
{sizeof(int8_t), "MInt8Property", 1, N_("Int8"), nullptr, nullptr, nullptr, nullptr, nullptr},
/* 46: CD_HAIRMAPPING */ /* UNUSED */
{-1, "", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
/* 47: CD_PROP_COLOR */
{sizeof(MPropCol),
"MPropCol",
1,
N_("Color"),
nullptr,
nullptr,
layerInterp_propcol,
nullptr,
layerDefault_propcol,
nullptr,
layerEqual_propcol,
layerMultiply_propcol,
layerInitMinMax_propcol,
layerAdd_propcol,
layerDoMinMax_propcol,
layerCopyValue_propcol,
nullptr,
nullptr,
nullptr,
layerMaxNum_propcol},
/* 48: CD_PROP_FLOAT3 */
{sizeof(float[3]),
"vec3f",
1,
N_("Float3"),
nullptr,
nullptr,
layerInterp_propfloat3,
nullptr,
nullptr,
layerValidate_propfloat3,
nullptr,
layerMultiply_propfloat3,
nullptr,
layerAdd_propfloat3},
/* 49: CD_PROP_FLOAT2 */
{sizeof(float[2]),
"vec2f",
1,
N_("Float2"),
nullptr,
nullptr,
layerInterp_propfloat2,
nullptr,
nullptr,
layerValidate_propfloat2,
nullptr,
layerMultiply_propfloat2,
nullptr,
layerAdd_propfloat2},
/* 50: CD_PROP_BOOL */
{sizeof(bool),
"bool",
1,
N_("Boolean"),
nullptr,
nullptr,
layerInterp_propbool,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr},
/* 51: CD_HAIRLENGTH */
{sizeof(float), "float", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
};
static const char *LAYERTYPENAMES[CD_NUMTYPES] = {
/* 0-4 */ "CDMVert",
"CDMSticky",
"CDMDeformVert",
"CDMEdge",
"CDMFace",
/* 5-9 */ "CDMTFace",
"CDMCol",
"CDOrigIndex",
"CDNormal",
"CDFaceMap",
2012-04-29 15:47:02 +00:00
/* 10-14 */ "CDMFloatProperty",
"CDMIntProperty",
"CDMStringProperty",
"CDOrigSpace",
"CDOrco",
/* 15-19 */ "CDMTexPoly",
"CDMLoopUV",
"CDMloopCol",
"CDTangent",
"CDMDisps",
2012-05-12 16:11:34 +00:00
/* 20-24 */ "CDPreviewMCol",
"CDIDMCol",
"CDTextureMCol",
"CDClothOrco",
"CDMRecast",
/* BMESH ONLY */
/* 25-29 */ "CDMPoly",
"CDMLoop",
"CDShapeKeyIndex",
"CDShapeKey",
"CDBevelWeight",
/* 30-34 */ "CDSubSurfCrease",
"CDOrigSpaceLoop",
"CDPreviewLoopCol",
"CDBMElemPyPtr",
"CDPaintMask",
/* 35-36 */ "CDGridPaintMask",
"CDMVertSkin",
/* 37-38 */ "CDFreestyleEdge",
"CDFreestyleFace",
/* 39-42 */ "CDMLoopTangent",
"CDTessLoopNormal",
"CDCustomLoopNormal",
2020-03-05 14:53:23 +01:00
"CDSculptFaceGroups",
/* 43-46 */ "CDHairPoint",
"CDPropInt8",
"CDHairMapping",
"CDPoint",
"CDPropCol",
"CDPropFloat3",
"CDPropFloat2",
"CDPropBoolean",
"CDHairLength",
};
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
const CustomData_MeshMasks CD_MASK_BAREMESH = {
/* vmask */ CD_MASK_MVERT | CD_MASK_BWEIGHT,
/* emask */ CD_MASK_MEDGE | CD_MASK_BWEIGHT,
/* fmask */ 0,
/* pmask */ CD_MASK_MPOLY | CD_MASK_FACEMAP,
/* lmask */ CD_MASK_MLOOP,
};
const CustomData_MeshMasks CD_MASK_BAREMESH_ORIGINDEX = {
/* vmask */ CD_MASK_MVERT | CD_MASK_BWEIGHT | CD_MASK_ORIGINDEX,
/* emask */ CD_MASK_MEDGE | CD_MASK_BWEIGHT | CD_MASK_ORIGINDEX,
/* fmask */ 0,
/* pmask */ CD_MASK_MPOLY | CD_MASK_FACEMAP | CD_MASK_ORIGINDEX,
/* lmask */ CD_MASK_MLOOP,
};
const CustomData_MeshMasks CD_MASK_MESH = {
/* vmask */ (CD_MASK_MVERT | CD_MASK_MDEFORMVERT | CD_MASK_MVERT_SKIN | CD_MASK_PAINT_MASK |
CD_MASK_PROP_ALL | CD_MASK_CREASE),
/* emask */ (CD_MASK_MEDGE | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL),
/* fmask */ 0,
/* pmask */
(CD_MASK_MPOLY | CD_MASK_FACEMAP | CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL |
CD_MASK_SCULPT_FACE_SETS),
/* lmask */
(CD_MASK_MLOOP | CD_MASK_MDISPS | CD_MASK_MLOOPUV | CD_MASK_CUSTOMLOOPNORMAL |
CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL),
};
const CustomData_MeshMasks CD_MASK_DERIVEDMESH = {
/* vmask */ (CD_MASK_ORIGINDEX | CD_MASK_MDEFORMVERT | CD_MASK_SHAPEKEY | CD_MASK_MVERT_SKIN |
CD_MASK_PAINT_MASK | CD_MASK_ORCO | CD_MASK_CLOTH_ORCO | CD_MASK_PROP_ALL |
CD_MASK_CREASE),
/* emask */ (CD_MASK_ORIGINDEX | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL),
/* fmask */ (CD_MASK_ORIGINDEX | CD_MASK_ORIGSPACE | CD_MASK_PREVIEW_MCOL | CD_MASK_TANGENT),
/* pmask */
(CD_MASK_ORIGINDEX | CD_MASK_FREESTYLE_FACE | CD_MASK_FACEMAP | CD_MASK_PROP_ALL |
CD_MASK_SCULPT_FACE_SETS),
/* lmask */
(CD_MASK_MLOOPUV | CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_PREVIEW_MLOOPCOL |
CD_MASK_ORIGSPACE_MLOOP | CD_MASK_PROP_ALL), /* XXX MISSING CD_MASK_MLOOPTANGENT ? */
};
const CustomData_MeshMasks CD_MASK_BMESH = {
/* vmask */ (CD_MASK_MDEFORMVERT | CD_MASK_BWEIGHT | CD_MASK_MVERT_SKIN | CD_MASK_SHAPEKEY |
CD_MASK_SHAPE_KEYINDEX | CD_MASK_PAINT_MASK | CD_MASK_PROP_ALL | CD_MASK_CREASE),
/* emask */ (CD_MASK_BWEIGHT | CD_MASK_CREASE | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL),
/* fmask */ 0,
/* pmask */
(CD_MASK_FREESTYLE_FACE | CD_MASK_FACEMAP | CD_MASK_PROP_ALL | CD_MASK_SCULPT_FACE_SETS),
/* lmask */
(CD_MASK_MDISPS | CD_MASK_MLOOPUV | CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_GRID_PAINT_MASK |
CD_MASK_PROP_ALL),
};
const CustomData_MeshMasks CD_MASK_EVERYTHING = {
/* vmask */ (CD_MASK_MVERT | CD_MASK_BM_ELEM_PYPTR | CD_MASK_ORIGINDEX | CD_MASK_MDEFORMVERT |
CD_MASK_BWEIGHT | CD_MASK_MVERT_SKIN | CD_MASK_ORCO | CD_MASK_CLOTH_ORCO |
CD_MASK_SHAPEKEY | CD_MASK_SHAPE_KEYINDEX | CD_MASK_PAINT_MASK |
CD_MASK_PROP_ALL | CD_MASK_CREASE),
/* emask */
(CD_MASK_MEDGE | CD_MASK_BM_ELEM_PYPTR | CD_MASK_ORIGINDEX | CD_MASK_BWEIGHT | CD_MASK_CREASE |
CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL),
/* fmask */
(CD_MASK_MFACE | CD_MASK_ORIGINDEX | CD_MASK_NORMAL | CD_MASK_MTFACE | CD_MASK_MCOL |
CD_MASK_ORIGSPACE | CD_MASK_TANGENT | CD_MASK_TESSLOOPNORMAL | CD_MASK_PREVIEW_MCOL |
CD_MASK_PROP_ALL),
/* pmask */
(CD_MASK_MPOLY | CD_MASK_BM_ELEM_PYPTR | CD_MASK_ORIGINDEX | CD_MASK_FACEMAP |
CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL | CD_MASK_SCULPT_FACE_SETS),
/* lmask */
(CD_MASK_MLOOP | CD_MASK_BM_ELEM_PYPTR | CD_MASK_MDISPS | CD_MASK_NORMAL | CD_MASK_MLOOPUV |
CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_MLOOPTANGENT | CD_MASK_PREVIEW_MLOOPCOL |
CD_MASK_ORIGSPACE_MLOOP | CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL),
};
static const LayerTypeInfo *layerType_getInfo(int type)
{
if (type < 0 || type >= CD_NUMTYPES) {
return nullptr;
}
return &LAYERTYPEINFO[type];
}
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
static const char *layerType_getName(int type)
{
if (type < 0 || type >= CD_NUMTYPES) {
return nullptr;
}
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
return LAYERTYPENAMES[type];
}
void customData_mask_layers__print(const CustomData_MeshMasks *mask)
{
printf("verts mask=0x%" PRIx64 ":\n", mask->vmask);
2020-09-09 15:43:09 +02:00
for (int i = 0; i < CD_NUMTYPES; i++) {
if (mask->vmask & CD_TYPE_AS_MASK(i)) {
printf(" %s\n", layerType_getName(i));
}
}
printf("edges mask=0x%" PRIx64 ":\n", mask->emask);
2020-09-09 15:43:09 +02:00
for (int i = 0; i < CD_NUMTYPES; i++) {
if (mask->emask & CD_TYPE_AS_MASK(i)) {
printf(" %s\n", layerType_getName(i));
}
}
printf("faces mask=0x%" PRIx64 ":\n", mask->fmask);
2020-09-09 15:43:09 +02:00
for (int i = 0; i < CD_NUMTYPES; i++) {
if (mask->fmask & CD_TYPE_AS_MASK(i)) {
printf(" %s\n", layerType_getName(i));
}
}
printf("loops mask=0x%" PRIx64 ":\n", mask->lmask);
2020-09-09 15:43:09 +02:00
for (int i = 0; i < CD_NUMTYPES; i++) {
if (mask->lmask & CD_TYPE_AS_MASK(i)) {
printf(" %s\n", layerType_getName(i));
}
}
printf("polys mask=0x%" PRIx64 ":\n", mask->pmask);
2020-09-09 15:43:09 +02:00
for (int i = 0; i < CD_NUMTYPES; i++) {
if (mask->pmask & CD_TYPE_AS_MASK(i)) {
printf(" %s\n", layerType_getName(i));
2012-05-28 21:25:17 +00:00
}
}
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name CustomData Functions
* \{ */
static void customData_update_offsets(CustomData *data);
2018-05-30 10:28:24 +02:00
static CustomDataLayer *customData_add_layer__internal(CustomData *data,
int type,
eCDAllocType alloctype,
void *layerdata,
int totelem,
const char *name);
void CustomData_update_typemap(CustomData *data)
{
2021-01-26 09:21:42 -06:00
int lasttype = -1;
2021-01-26 09:21:42 -06:00
for (int i = 0; i < CD_NUMTYPES; i++) {
data->typemap[i] = -1;
}
2021-01-26 09:21:42 -06:00
for (int i = 0; i < data->totlayer; i++) {
const int type = data->layers[i].type;
if (type != lasttype) {
data->typemap[type] = i;
lasttype = type;
}
}
}
2013-02-04 16:20:39 +00:00
/* currently only used in BLI_assert */
#ifndef NDEBUG
static bool customdata_typemap_is_valid(const CustomData *data)
{
CustomData data_copy = *data;
CustomData_update_typemap(&data_copy);
return (memcmp(data->typemap, data_copy.typemap, sizeof(data->typemap)) == 0);
}
2013-02-04 16:20:39 +00:00
#endif
bool CustomData_merge(const CustomData *source,
CustomData *dest,
eCustomDataMask mask,
2018-05-30 10:28:24 +02:00
eCDAllocType alloctype,
int totelem)
{
// const LayerTypeInfo *typeInfo;
CustomDataLayer *layer, *newlayer;
2021-01-26 09:21:42 -06:00
int lasttype = -1, lastactive = 0, lastrender = 0, lastclone = 0, lastmask = 0;
int number = 0, maxnumber = -1;
bool changed = false;
2021-01-26 09:21:42 -06:00
for (int i = 0; i < source->totlayer; i++) {
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
layer = &source->layers[i];
// typeInfo = layerType_getInfo(layer->type); /* UNUSED */
2021-01-26 09:21:42 -06:00
int type = layer->type;
int flag = layer->flag;
if (type != lasttype) {
number = 0;
maxnumber = CustomData_layertype_layers_max(type);
lastactive = layer->active;
lastrender = layer->active_rnd;
lastclone = layer->active_clone;
lastmask = layer->active_mask;
lasttype = type;
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
}
else {
number++;
}
if (flag & CD_FLAG_NOCOPY) {
continue;
}
if (!(mask & CD_TYPE_AS_MASK(type))) {
continue;
}
if ((maxnumber != -1) && (number >= maxnumber)) {
continue;
}
if (CustomData_get_named_layer_index(dest, type, layer->name) != -1) {
continue;
}
2021-01-26 09:21:42 -06:00
void *data;
switch (alloctype) {
case CD_ASSIGN:
case CD_REFERENCE:
case CD_DUPLICATE:
data = layer->data;
break;
default:
data = nullptr;
break;
}
if ((alloctype == CD_ASSIGN) && (flag & CD_FLAG_NOFREE)) {
newlayer = customData_add_layer__internal(
dest, type, CD_REFERENCE, data, totelem, layer->name);
}
else {
newlayer = customData_add_layer__internal(dest, type, alloctype, data, totelem, layer->name);
}
if (newlayer) {
newlayer->uid = layer->uid;
newlayer->active = lastactive;
newlayer->active_rnd = lastrender;
newlayer->active_clone = lastclone;
newlayer->active_mask = lastmask;
newlayer->flag |= flag & (CD_FLAG_EXTERNAL | CD_FLAG_IN_MEMORY | CD_FLAG_COLOR_ACTIVE |
CD_FLAG_COLOR_RENDER);
changed = true;
if (layer->anonymous_id != nullptr) {
BKE_anonymous_attribute_id_increment_weak(layer->anonymous_id);
newlayer->anonymous_id = layer->anonymous_id;
}
}
}
CustomData_update_typemap(dest);
return changed;
}
void CustomData_realloc(CustomData *data, int totelem)
{
2020-09-09 15:43:09 +02:00
for (int i = 0; i < data->totlayer; i++) {
CustomDataLayer *layer = &data->layers[i];
const LayerTypeInfo *typeInfo;
if (layer->flag & CD_FLAG_NOFREE) {
continue;
}
typeInfo = layerType_getInfo(layer->type);
Geometry Nodes: Extrude Mesh Node This patch introduces an extrude node with three modes. The vertex mode is quite simple, and just attaches new edges to the selected vertices. The edge mode attaches new faces to the selected edges. The faces mode extrudes patches of selected faces, or each selected face individually, depending on the "Individual" boolean input. The default value of the "Offset" input is the mesh's normals, which can be scaled with the "Offset Scale" input. **Attribute Propagation** Attributes are transferred to the new elements with specific rules. Attributes will never change domains for interpolations. Generally boolean attributes are propagated with "or", meaning any connected "true" value that is mixed in for other types will cause the new value to be "true" as well. The `"id"` attribute does not have any special handling currently. Vertex Mode - Vertex: Copied values of selected vertices. - Edge: Averaged values of selected edges. For booleans, edges are selected if any connected edges are selected. Edge Mode - Vertex: Copied values of extruded vertices. - Connecting edges (vertical): Average values of connected extruded edges. For booleans, the edges are selected if any connected extruded edges are selected. - Duplicate edges: Copied values of selected edges. - Face: Averaged values of all faces connected to the selected edge. For booleans, faces are selected if any connected original faces are selected. - Corner: Averaged values of corresponding corners in all faces connected to selected edges. For booleans, corners are selected if one of those corners are selected. Face Mode - Vertex: Copied values of extruded vertices. - Connecting edges (vertical): Average values of connected selected edges, not including the edges "on top" of extruded regions. For booleans, edges are selected when any connected extruded edges were selected. - Duplicate edges: Copied values of extruded edges. - Face: Copied values of the corresponding selected faces. - Corner: Copied values of corresponding corners in selected faces. Individual Face Mode - Vertex: Copied values of extruded vertices. - Connecting edges (vertical): Average values of the two neighboring edges on each extruded face. For booleans, edges are selected when at least one neighbor on the extruded face was selected. - Duplicate edges: Copied values of extruded edges. - Face: Copied values of the corresponding selected faces. - Corner: Copied values of corresponding corners in selected faces. **Differences from edit mode** In face mode (non-individual), the behavior can be different than the extrude tools in edit mode-- this node doesn't handle keeping the back- faces around in the cases that the edit mode tools do. The planned "Solidify" node will handle that use case instead. Keeping this node simpler and faster is preferable at this point, especially because that sort of "smart" behavior is not that predictable and makes less sense in a procedural context. In the future, an "Even Offset" option could be added to this node hopefully fairly simply. For now it is left out in order to keep the patch simpler. **Implementation** For the implementation, the `Mesh` data structure is used directly rather than converting to `BMesh` and back like D12224. This optimizes for large extrusion operations rather than many sequential extrusions. While this is potentially more verbose, it has some important benefits: First, there is no conversion to and from `BMesh`. The code only has to fill arrays and it can do that all at once, making each component of the algorithm much easier to optimize. It also makes the attribute interpolation more explicit, and likely faster. Only limited topology maps must be created in most cases. While there are some necessary loops and allocations with the size of the entire mesh, I tried to keep everything I could on the order of the size of the selection rather than the size of the mesh. In that respect, the individual faces mode is the best, since there is no topology information necessary, and the amount of work just depends on the size of the selection. Modifying an existing mesh instead of generating a new one was a bit of a toss-up, but has a few potential benefits: - Avoids manually copying over attribute data for original elements. - Avoids some overhead of creating a new mesh. - Can potentially take advantage of future ammortized mesh growth. This could be changed easily if it turns out to be the wrong choice. Differential Revision: https://developer.blender.org/D13709
2022-01-23 22:42:49 -06:00
/* Use calloc to avoid the need to manually initialize new data in layers.
* Useful for types like #MDeformVert which contain a pointer. */
layer->data = MEM_recallocN(layer->data, (size_t)totelem * typeInfo->size);
}
}
void CustomData_copy(const CustomData *source,
CustomData *dest,
eCustomDataMask mask,
2018-05-30 10:28:24 +02:00
eCDAllocType alloctype,
int totelem)
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
{
CustomData_reset(dest);
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
if (source->external) {
dest->external = static_cast<CustomDataExternal *>(MEM_dupallocN(source->external));
}
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
CustomData_merge(source, dest, mask, alloctype, totelem);
}
static void customData_free_layer__internal(CustomDataLayer *layer, int totelem)
{
const LayerTypeInfo *typeInfo;
if (layer->anonymous_id != nullptr) {
BKE_anonymous_attribute_id_decrement_weak(layer->anonymous_id);
layer->anonymous_id = nullptr;
}
if (!(layer->flag & CD_FLAG_NOFREE) && layer->data) {
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
typeInfo = layerType_getInfo(layer->type);
if (typeInfo->free) {
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
typeInfo->free(layer->data, totelem, typeInfo->size);
}
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
if (layer->data) {
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
MEM_freeN(layer->data);
}
}
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
}
static void CustomData_external_free(CustomData *data)
{
if (data->external) {
MEM_freeN(data->external);
data->external = nullptr;
}
}
void CustomData_reset(CustomData *data)
{
memset(data, 0, sizeof(*data));
copy_vn_i(data->typemap, CD_NUMTYPES, -1);
}
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
void CustomData_free(CustomData *data, int totelem)
{
2020-09-09 15:43:09 +02:00
for (int i = 0; i < data->totlayer; i++) {
customData_free_layer__internal(&data->layers[i], totelem);
}
if (data->layers) {
MEM_freeN(data->layers);
}
2018-06-17 17:05:51 +02:00
CustomData_external_free(data);
CustomData_reset(data);
}
void CustomData_free_typemask(CustomData *data, int totelem, eCustomDataMask mask)
{
2020-09-09 15:43:09 +02:00
for (int i = 0; i < data->totlayer; i++) {
CustomDataLayer *layer = &data->layers[i];
if (!(mask & CD_TYPE_AS_MASK(layer->type))) {
continue;
}
customData_free_layer__internal(layer, totelem);
}
if (data->layers) {
MEM_freeN(data->layers);
}
CustomData_external_free(data);
CustomData_reset(data);
}
static void customData_update_offsets(CustomData *data)
{
const LayerTypeInfo *typeInfo;
2020-09-09 15:43:09 +02:00
int offset = 0;
2020-09-09 15:43:09 +02:00
for (int i = 0; i < data->totlayer; i++) {
typeInfo = layerType_getInfo(data->layers[i].type);
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
data->layers[i].offset = offset;
offset += typeInfo->size;
}
data->totsize = offset;
CustomData_update_typemap(data);
}
/* to use when we're in the middle of modifying layers */
static int CustomData_get_layer_index__notypemap(const CustomData *data, int type)
{
2020-09-09 15:43:09 +02:00
for (int i = 0; i < data->totlayer; i++) {
if (data->layers[i].type == type) {
return i;
}
}
return -1;
}
/* -------------------------------------------------------------------- */
/* index values to access the layers (offset from the layer start) */
int CustomData_get_layer_index(const CustomData *data, int type)
{
BLI_assert(customdata_typemap_is_valid(data));
return data->typemap[type];
}
int CustomData_get_layer_index_n(const CustomData *data, int type, int n)
2009-11-02 06:31:23 +00:00
{
BLI_assert(n >= 0);
int i = CustomData_get_layer_index(data, type);
2009-11-02 06:31:23 +00:00
if (i != -1) {
BLI_assert(i + n < data->totlayer);
i = (data->layers[i + n].type == type) ? (i + n) : (-1);
}
2009-11-02 06:31:23 +00:00
return i;
2009-11-02 06:31:23 +00:00
}
int CustomData_get_named_layer_index(const CustomData *data, int type, const char *name)
{
2020-09-09 15:43:09 +02:00
for (int i = 0; i < data->totlayer; i++) {
if (data->layers[i].type == type) {
if (STREQ(data->layers[i].name, name)) {
return i;
}
}
}
return -1;
}
int CustomData_get_active_layer_index(const CustomData *data, int type)
{
const int layer_index = data->typemap[type];
BLI_assert(customdata_typemap_is_valid(data));
2014-01-12 22:27:55 +11:00
return (layer_index != -1) ? layer_index + data->layers[layer_index].active : -1;
}
int CustomData_get_render_layer_index(const CustomData *data, int type)
{
const int layer_index = data->typemap[type];
BLI_assert(customdata_typemap_is_valid(data));
return (layer_index != -1) ? layer_index + data->layers[layer_index].active_rnd : -1;
}
int CustomData_get_clone_layer_index(const CustomData *data, int type)
{
const int layer_index = data->typemap[type];
BLI_assert(customdata_typemap_is_valid(data));
return (layer_index != -1) ? layer_index + data->layers[layer_index].active_clone : -1;
}
int CustomData_get_stencil_layer_index(const CustomData *data, int type)
{
const int layer_index = data->typemap[type];
BLI_assert(customdata_typemap_is_valid(data));
return (layer_index != -1) ? layer_index + data->layers[layer_index].active_mask : -1;
}
/* -------------------------------------------------------------------- */
/* index values per layer type */
int CustomData_get_named_layer(const CustomData *data, int type, const char *name)
{
const int named_index = CustomData_get_named_layer_index(data, type, name);
const int layer_index = data->typemap[type];
BLI_assert(customdata_typemap_is_valid(data));
return (named_index != -1) ? named_index - layer_index : -1;
}
int CustomData_get_active_layer(const CustomData *data, int type)
{
const int layer_index = data->typemap[type];
BLI_assert(customdata_typemap_is_valid(data));
return (layer_index != -1) ? data->layers[layer_index].active : -1;
}
int CustomData_get_render_layer(const CustomData *data, int type)
{
const int layer_index = data->typemap[type];
BLI_assert(customdata_typemap_is_valid(data));
return (layer_index != -1) ? data->layers[layer_index].active_rnd : -1;
}
int CustomData_get_clone_layer(const CustomData *data, int type)
{
const int layer_index = data->typemap[type];
BLI_assert(customdata_typemap_is_valid(data));
return (layer_index != -1) ? data->layers[layer_index].active_clone : -1;
}
int CustomData_get_stencil_layer(const CustomData *data, int type)
{
const int layer_index = data->typemap[type];
BLI_assert(customdata_typemap_is_valid(data));
return (layer_index != -1) ? data->layers[layer_index].active_mask : -1;
}
const char *CustomData_get_active_layer_name(const CustomData *data, const int type)
{
/* Get the layer index of the active layer of this type. */
const int layer_index = CustomData_get_active_layer_index(data, type);
return layer_index < 0 ? nullptr : data->layers[layer_index].name;
}
void CustomData_set_layer_active(CustomData *data, int type, int n)
{
2020-09-09 15:43:09 +02:00
for (int i = 0; i < data->totlayer; i++) {
if (data->layers[i].type == type) {
data->layers[i].active = n;
}
}
}
void CustomData_set_layer_render(CustomData *data, int type, int n)
{
2020-09-09 15:43:09 +02:00
for (int i = 0; i < data->totlayer; i++) {
if (data->layers[i].type == type) {
data->layers[i].active_rnd = n;
}
}
}
void CustomData_set_layer_clone(CustomData *data, int type, int n)
{
2020-09-09 15:43:09 +02:00
for (int i = 0; i < data->totlayer; i++) {
if (data->layers[i].type == type) {
data->layers[i].active_clone = n;
}
}
}
void CustomData_set_layer_stencil(CustomData *data, int type, int n)
{
2020-09-09 15:43:09 +02:00
for (int i = 0; i < data->totlayer; i++) {
if (data->layers[i].type == type) {
data->layers[i].active_mask = n;
}
}
}
void CustomData_set_layer_active_index(CustomData *data, int type, int n)
{
const int layer_index = data->typemap[type];
BLI_assert(customdata_typemap_is_valid(data));
2020-09-09 15:43:09 +02:00
for (int i = 0; i < data->totlayer; i++) {
if (data->layers[i].type == type) {
data->layers[i].active = n - layer_index;
}
}
}
void CustomData_set_layer_render_index(CustomData *data, int type, int n)
{
const int layer_index = data->typemap[type];
BLI_assert(customdata_typemap_is_valid(data));
2020-09-09 15:43:09 +02:00
for (int i = 0; i < data->totlayer; i++) {
if (data->layers[i].type == type) {
data->layers[i].active_rnd = n - layer_index;
}
}
}
void CustomData_set_layer_clone_index(CustomData *data, int type, int n)
{
const int layer_index = data->typemap[type];
BLI_assert(customdata_typemap_is_valid(data));
2020-09-09 15:43:09 +02:00
for (int i = 0; i < data->totlayer; i++) {
if (data->layers[i].type == type) {
data->layers[i].active_clone = n - layer_index;
}
}
}
void CustomData_set_layer_stencil_index(CustomData *data, int type, int n)
{
const int layer_index = data->typemap[type];
BLI_assert(customdata_typemap_is_valid(data));
2020-09-09 15:43:09 +02:00
for (int i = 0; i < data->totlayer; i++) {
if (data->layers[i].type == type) {
data->layers[i].active_mask = n - layer_index;
}
}
}
void CustomData_set_layer_flag(CustomData *data, int type, int flag)
{
2020-09-09 15:43:09 +02:00
for (int i = 0; i < data->totlayer; i++) {
if (data->layers[i].type == type) {
data->layers[i].flag |= flag;
}
}
}
void CustomData_clear_layer_flag(CustomData *data, int type, int flag)
{
const int nflag = ~flag;
for (int i = 0; i < data->totlayer; i++) {
if (data->layers[i].type == type) {
data->layers[i].flag &= nflag;
}
}
}
static bool customData_resize(CustomData *data, int amount)
{
CustomDataLayer *tmp = static_cast<CustomDataLayer *>(
MEM_calloc_arrayN((data->maxlayer + amount), sizeof(*tmp), __func__));
if (!tmp) {
return false;
}
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
data->maxlayer += amount;
if (data->layers) {
memcpy(tmp, data->layers, sizeof(*tmp) * data->totlayer);
MEM_freeN(data->layers);
}
data->layers = tmp;
return true;
}
2018-05-30 10:28:24 +02:00
static CustomDataLayer *customData_add_layer__internal(CustomData *data,
int type,
eCDAllocType alloctype,
void *layerdata,
int totelem,
const char *name)
{
2012-05-12 16:11:34 +00:00
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
int flag = 0, index = data->totlayer;
void *newlayerdata = nullptr;
2019-06-12 09:04:10 +10:00
/* Passing a layer-data to copy from with an alloctype that won't copy is
* most likely a bug */
2021-01-26 09:21:42 -06:00
BLI_assert(!layerdata || ELEM(alloctype, CD_ASSIGN, CD_DUPLICATE, CD_REFERENCE));
if (!typeInfo->defaultname && CustomData_has_layer(data, type)) {
return &data->layers[CustomData_get_layer_index(data, type)];
}
2020-11-06 12:30:59 +11:00
if (ELEM(alloctype, CD_ASSIGN, CD_REFERENCE)) {
newlayerdata = layerdata;
}
else if (totelem > 0 && typeInfo->size > 0) {
if (alloctype == CD_DUPLICATE && layerdata) {
newlayerdata = MEM_malloc_arrayN((size_t)totelem, typeInfo->size, layerType_getName(type));
}
else {
newlayerdata = MEM_calloc_arrayN((size_t)totelem, typeInfo->size, layerType_getName(type));
}
if (!newlayerdata) {
return nullptr;
}
}
if (alloctype == CD_DUPLICATE && layerdata) {
if (totelem > 0) {
if (typeInfo->copy) {
typeInfo->copy(layerdata, newlayerdata, totelem);
}
else {
memcpy(newlayerdata, layerdata, (size_t)totelem * typeInfo->size);
}
}
}
else if (alloctype == CD_DEFAULT) {
if (typeInfo->set_default) {
typeInfo->set_default(newlayerdata, totelem);
}
}
else if (alloctype == CD_REFERENCE) {
flag |= CD_FLAG_NOFREE;
}
if (index >= data->maxlayer) {
if (!customData_resize(data, CUSTOMDATA_GROW)) {
if (newlayerdata != layerdata) {
MEM_freeN(newlayerdata);
}
return nullptr;
}
}
data->totlayer++;
/* keep layers ordered by type */
for (; index > 0 && data->layers[index - 1].type > type; index--) {
data->layers[index] = data->layers[index - 1];
}
/* Clear remaining data on the layer. The original data on the layer has been moved to another
* index. Without this, it can happen that information from the previous layer at that index
* leaks into the new layer. */
memset(data->layers + index, 0, sizeof(CustomDataLayer));
data->layers[index].type = type;
data->layers[index].flag = flag;
data->layers[index].data = newlayerdata;
/* Set default name if none exists. Note we only call DATA_() once
* we know there is a default name, to avoid overhead of locale lookups
* in the depsgraph. */
if (!name && typeInfo->defaultname) {
name = DATA_(typeInfo->defaultname);
}
if (name) {
BLI_strncpy(data->layers[index].name, name, sizeof(data->layers[index].name));
CustomData_set_layer_unique_name(data, index);
}
else {
data->layers[index].name[0] = '\0';
}
2012-05-12 16:11:34 +00:00
if (index > 0 && data->layers[index - 1].type == type) {
data->layers[index].active = data->layers[index - 1].active;
data->layers[index].active_rnd = data->layers[index - 1].active_rnd;
data->layers[index].active_clone = data->layers[index - 1].active_clone;
data->layers[index].active_mask = data->layers[index - 1].active_mask;
}
else {
data->layers[index].active = 0;
data->layers[index].active_rnd = 0;
data->layers[index].active_clone = 0;
data->layers[index].active_mask = 0;
}
customData_update_offsets(data);
return &data->layers[index];
}
2018-05-30 10:28:24 +02:00
void *CustomData_add_layer(
CustomData *data, int type, eCDAllocType alloctype, void *layerdata, int totelem)
{
2012-05-12 16:11:34 +00:00
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
2018-06-17 17:05:51 +02:00
2021-01-26 09:21:42 -06:00
CustomDataLayer *layer = customData_add_layer__internal(
2012-05-12 16:11:34 +00:00
data, type, alloctype, layerdata, totelem, typeInfo->defaultname);
CustomData_update_typemap(data);
if (layer) {
return layer->data;
}
return nullptr;
}
2018-05-30 10:28:24 +02:00
void *CustomData_add_layer_named(CustomData *data,
int type,
eCDAllocType alloctype,
void *layerdata,
int totelem,
const char *name)
{
2021-01-26 09:21:42 -06:00
CustomDataLayer *layer = customData_add_layer__internal(
data, type, alloctype, layerdata, totelem, name);
CustomData_update_typemap(data);
if (layer) {
return layer->data;
}
return nullptr;
}
void *CustomData_add_layer_anonymous(CustomData *data,
int type,
eCDAllocType alloctype,
void *layerdata,
int totelem,
const AnonymousAttributeID *anonymous_id)
{
const char *name = BKE_anonymous_attribute_id_internal_name(anonymous_id);
CustomDataLayer *layer = customData_add_layer__internal(
data, type, alloctype, layerdata, totelem, name);
CustomData_update_typemap(data);
if (layer == nullptr) {
return nullptr;
}
BKE_anonymous_attribute_id_increment_weak(anonymous_id);
layer->anonymous_id = anonymous_id;
return layer->data;
}
2013-05-08 12:57:18 +00:00
bool CustomData_free_layer(CustomData *data, int type, int totelem, int index)
{
const int index_first = CustomData_get_layer_index(data, type);
const int n = index - index_first;
BLI_assert(index >= index_first);
if ((index_first == -1) || (n < 0)) {
return false;
}
BLI_assert(data->layers[index].type == type);
customData_free_layer__internal(&data->layers[index], totelem);
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
2020-09-09 15:43:09 +02:00
for (int i = index + 1; i < data->totlayer; i++) {
2012-05-12 16:11:34 +00:00
data->layers[i - 1] = data->layers[i];
}
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
data->totlayer--;
/* if layer was last of type in array, set new active layer */
2020-09-09 15:43:09 +02:00
int i = CustomData_get_layer_index__notypemap(data, type);
if (i != -1) {
/* don't decrement zero index */
const int index_nonzero = n ? n : 1;
CustomDataLayer *layer;
for (layer = &data->layers[i]; i < data->totlayer && layer->type == type; i++, layer++) {
if (layer->active >= index_nonzero) {
layer->active--;
}
if (layer->active_rnd >= index_nonzero) {
layer->active_rnd--;
}
if (layer->active_clone >= index_nonzero) {
layer->active_clone--;
}
if (layer->active_mask >= index_nonzero) {
layer->active_mask--;
}
}
}
if (data->totlayer <= data->maxlayer - CUSTOMDATA_GROW) {
customData_resize(data, -CUSTOMDATA_GROW);
}
customData_update_offsets(data);
2014-12-01 17:11:18 +01:00
return true;
}
bool CustomData_free_layer_named(CustomData *data, const char *name, const int totelem)
{
for (const int i : IndexRange(data->totlayer)) {
const CustomDataLayer &layer = data->layers[i];
if (StringRef(layer.name) == name) {
CustomData_free_layer(data, layer.type, totelem, i);
return true;
}
}
return false;
}
2013-05-08 12:57:18 +00:00
bool CustomData_free_layer_active(CustomData *data, int type, int totelem)
{
2020-09-09 15:43:09 +02:00
const int index = CustomData_get_active_layer_index(data, type);
if (index == -1) {
2014-12-01 17:11:18 +01:00
return false;
}
return CustomData_free_layer(data, type, totelem, index);
}
void CustomData_free_layers(CustomData *data, int type, int totelem)
{
const int index = CustomData_get_layer_index(data, type);
while (CustomData_free_layer(data, type, totelem, index)) {
/* pass */
}
}
2013-05-08 12:57:18 +00:00
bool CustomData_has_layer(const CustomData *data, int type)
{
return (CustomData_get_layer_index(data, type) != -1);
}
int CustomData_number_of_layers(const CustomData *data, int type)
{
2020-09-09 15:43:09 +02:00
int number = 0;
2020-09-09 15:43:09 +02:00
for (int i = 0; i < data->totlayer; i++) {
if (data->layers[i].type == type) {
number++;
}
}
2018-06-17 17:05:51 +02:00
return number;
}
int CustomData_number_of_layers_typemask(const CustomData *data, eCustomDataMask mask)
{
2020-09-09 15:43:09 +02:00
int number = 0;
2020-09-09 15:43:09 +02:00
for (int i = 0; i < data->totlayer; i++) {
if (mask & CD_TYPE_AS_MASK(data->layers[i].type)) {
number++;
}
}
return number;
}
static void *customData_duplicate_referenced_layer_index(CustomData *data,
const int layer_index,
const int totelem)
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
{
if (layer_index == -1) {
return nullptr;
}
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
2020-09-09 15:43:09 +02:00
CustomDataLayer *layer = &data->layers[layer_index];
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
if (layer->flag & CD_FLAG_NOFREE) {
2012-03-01 12:20:18 +00:00
/* MEM_dupallocN won't work in case of complex layers, like e.g.
* CD_MDEFORMVERT, which has pointers to allocated data...
* So in case a custom copy function is defined, use it!
*/
const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
if (typeInfo->copy) {
void *dst_data = MEM_malloc_arrayN(
(size_t)totelem, typeInfo->size, "CD duplicate ref layer");
typeInfo->copy(layer->data, dst_data, totelem);
layer->data = dst_data;
}
else {
layer->data = MEM_dupallocN(layer->data);
}
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
layer->flag &= ~CD_FLAG_NOFREE;
}
return layer->data;
}
void *CustomData_duplicate_referenced_layer(CustomData *data, const int type, const int totelem)
{
/* get the layer index of the first layer of type */
2020-09-09 15:43:09 +02:00
int layer_index = CustomData_get_active_layer_index(data, type);
return customData_duplicate_referenced_layer_index(data, layer_index, totelem);
}
void *CustomData_duplicate_referenced_layer_n(CustomData *data,
const int type,
const int n,
const int totelem)
{
/* get the layer index of the desired layer */
2020-09-09 15:43:09 +02:00
int layer_index = CustomData_get_layer_index_n(data, type, n);
return customData_duplicate_referenced_layer_index(data, layer_index, totelem);
}
void *CustomData_duplicate_referenced_layer_named(CustomData *data,
const int type,
const char *name,
const int totelem)
{
/* get the layer index of the desired layer */
2020-09-09 15:43:09 +02:00
int layer_index = CustomData_get_named_layer_index(data, type, name);
return customData_duplicate_referenced_layer_index(data, layer_index, totelem);
}
void *CustomData_duplicate_referenced_layer_anonymous(CustomData *data,
const int UNUSED(type),
const AnonymousAttributeID *anonymous_id,
const int totelem)
{
for (int i = 0; i < data->totlayer; i++) {
if (data->layers[i].anonymous_id == anonymous_id) {
return customData_duplicate_referenced_layer_index(data, i, totelem);
}
}
BLI_assert_unreachable();
return nullptr;
}
void CustomData_duplicate_referenced_layers(CustomData *data, int totelem)
{
for (int i = 0; i < data->totlayer; i++) {
CustomDataLayer *layer = &data->layers[i];
layer->data = customData_duplicate_referenced_layer_index(data, i, totelem);
}
}
bool CustomData_is_referenced_layer(CustomData *data, int type)
{
/* get the layer index of the first layer of type */
2020-09-09 15:43:09 +02:00
int layer_index = CustomData_get_active_layer_index(data, type);
if (layer_index == -1) {
2014-12-01 17:11:18 +01:00
return false;
}
2020-09-09 15:43:09 +02:00
CustomDataLayer *layer = &data->layers[layer_index];
return (layer->flag & CD_FLAG_NOFREE) != 0;
}
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
void CustomData_free_temporary(CustomData *data, int totelem)
{
int i, j;
bool changed = false;
for (i = 0, j = 0; i < data->totlayer; i++) {
2021-01-26 09:21:42 -06:00
CustomDataLayer *layer = &data->layers[i];
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
if (i != j) {
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
data->layers[j] = data->layers[i];
}
if ((layer->flag & CD_FLAG_TEMPORARY) == CD_FLAG_TEMPORARY) {
customData_free_layer__internal(layer, totelem);
changed = true;
}
else {
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
j++;
}
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
}
data->totlayer = j;
if (data->totlayer <= data->maxlayer - CUSTOMDATA_GROW) {
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
customData_resize(data, -CUSTOMDATA_GROW);
changed = true;
}
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
if (changed) {
customData_update_offsets(data);
}
}
void CustomData_set_only_copy(const CustomData *data, eCustomDataMask mask)
{
2020-09-09 15:43:09 +02:00
for (int i = 0; i < data->totlayer; i++) {
if (!(mask & CD_TYPE_AS_MASK(data->layers[i].type))) {
data->layers[i].flag |= CD_FLAG_NOCOPY;
}
}
}
void CustomData_copy_elements(int type, void *src_data_ofs, void *dst_data_ofs, int count)
2009-08-18 20:05:08 +00:00
{
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
if (typeInfo->copy) {
typeInfo->copy(src_data_ofs, dst_data_ofs, count);
}
else {
2016-05-17 03:01:32 +10:00
memcpy(dst_data_ofs, src_data_ofs, (size_t)count * typeInfo->size);
}
2009-08-18 20:05:08 +00:00
}
void CustomData_copy_data_layer(const CustomData *source,
CustomData *dest,
int src_layer_index,
int dst_layer_index,
int src_index,
int dst_index,
int count)
2015-08-06 12:34:31 +10:00
{
const LayerTypeInfo *typeInfo;
const void *src_data = source->layers[src_layer_index].data;
void *dst_data = dest->layers[dst_layer_index].data;
typeInfo = layerType_getInfo(source->layers[src_layer_index].type);
2016-05-17 03:01:32 +10:00
const size_t src_offset = (size_t)src_index * typeInfo->size;
const size_t dst_offset = (size_t)dst_index * typeInfo->size;
if (!count || !src_data || !dst_data) {
if (count && !(src_data == nullptr && dst_data == nullptr)) {
CLOG_WARN(&LOG,
"null data for %s type (%p --> %p), skipping",
layerType_getName(source->layers[src_layer_index].type),
(void *)src_data,
(void *)dst_data);
}
return;
}
2016-05-17 03:01:32 +10:00
if (typeInfo->copy) {
typeInfo->copy(
POINTER_OFFSET(src_data, src_offset), POINTER_OFFSET(dst_data, dst_offset), count);
2016-05-17 03:01:32 +10:00
}
else {
memcpy(POINTER_OFFSET(dst_data, dst_offset),
POINTER_OFFSET(src_data, src_offset),
2016-05-17 03:01:32 +10:00
(size_t)count * typeInfo->size);
}
}
void CustomData_copy_data_named(
const CustomData *source, CustomData *dest, int source_index, int dest_index, int count)
{
/* copies a layer at a time */
2020-09-09 15:43:09 +02:00
for (int src_i = 0; src_i < source->totlayer; src_i++) {
2020-09-09 15:43:09 +02:00
int dest_i = CustomData_get_named_layer_index(
dest, source->layers[src_i].type, source->layers[src_i].name);
/* if we found a matching layer, copy the data */
if (dest_i != -1) {
CustomData_copy_data_layer(source, dest, src_i, dest_i, source_index, dest_index, count);
}
}
}
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
void CustomData_copy_data(
2012-05-12 16:11:34 +00:00
const CustomData *source, CustomData *dest, int source_index, int dest_index, int count)
{
/* copies a layer at a time */
2020-09-09 15:43:09 +02:00
int dest_i = 0;
for (int 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) {
CustomData_copy_data_layer(source, dest, src_i, dest_i, source_index, dest_index, count);
2018-06-17 17:05:51 +02:00
/* 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_copy_layer_type_data(const CustomData *source,
CustomData *destination,
int type,
int source_index,
int destination_index,
int count)
{
const int source_layer_index = CustomData_get_layer_index(source, type);
if (source_layer_index == -1) {
return;
}
const int destinaiton_layer_index = CustomData_get_layer_index(destination, type);
if (destinaiton_layer_index == -1) {
return;
}
CustomData_copy_data_layer(source,
destination,
source_layer_index,
destinaiton_layer_index,
source_index,
destination_index,
count);
}
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
void CustomData_free_elem(CustomData *data, int index, int count)
{
2020-09-09 15:43:09 +02:00
for (int i = 0; i < data->totlayer; i++) {
if (!(data->layers[i].flag & CD_FLAG_NOFREE)) {
2020-09-09 15:43:09 +02:00
const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[i].type);
if (typeInfo->free) {
2016-05-17 03:01:32 +10:00
size_t offset = (size_t)index * typeInfo->size;
typeInfo->free(POINTER_OFFSET(data->layers[i].data, offset), count, typeInfo->size);
}
}
}
}
#define SOURCE_BUF_SIZE 100
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
void CustomData_interp(const CustomData *source,
CustomData *dest,
2016-05-17 03:07:40 +10:00
const int *src_indices,
const float *weights,
const float *sub_weights,
2012-05-12 16:11:34 +00:00
int count,
int dest_index)
{
if (count <= 0) {
return;
}
const void *source_buf[SOURCE_BUF_SIZE];
const void **sources = source_buf;
2019-08-17 00:54:22 +10:00
/* Slow fallback in case we're interpolating a ridiculous number of elements. */
if (count > SOURCE_BUF_SIZE) {
sources = static_cast<const void **>(MEM_malloc_arrayN(count, sizeof(*sources), __func__));
}
/* If no weights are given, generate default ones to produce an average result. */
float default_weights_buf[SOURCE_BUF_SIZE];
float *default_weights = nullptr;
if (weights == nullptr) {
default_weights = (count > SOURCE_BUF_SIZE) ?
static_cast<float *>(
MEM_mallocN(sizeof(*weights) * (size_t)count, __func__)) :
default_weights_buf;
copy_vn_fl(default_weights, count, 1.0f / count);
weights = default_weights;
}
/* interpolates a layer at a time */
2020-09-09 15:43:09 +02:00
int dest_i = 0;
for (int src_i = 0; src_i < source->totlayer; src_i++) {
2012-05-12 16:11:34 +00:00
const LayerTypeInfo *typeInfo = layerType_getInfo(source->layers[src_i].type);
if (!typeInfo->interp) {
continue;
}
/* 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) {
break;
}
/* if we found a matching layer, copy the data */
if (dest->layers[dest_i].type == source->layers[src_i].type) {
void *src_data = source->layers[src_i].data;
2020-09-09 15:43:09 +02:00
for (int j = 0; j < count; j++) {
2016-05-17 03:01:32 +10:00
sources[j] = POINTER_OFFSET(src_data, (size_t)src_indices[j] * typeInfo->size);
}
typeInfo->interp(
sources,
weights,
sub_weights,
count,
2016-05-17 03:01:32 +10:00
POINTER_OFFSET(dest->layers[dest_i].data, (size_t)dest_index * 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++;
}
}
if (count > SOURCE_BUF_SIZE) {
2015-04-19 22:03:42 +10:00
MEM_freeN((void *)sources);
}
if (!ELEM(default_weights, nullptr, default_weights_buf)) {
MEM_freeN(default_weights);
}
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
}
void CustomData_swap_corners(CustomData *data, int index, const int *corner_indices)
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
{
2020-09-09 15:43:09 +02:00
for (int i = 0; i < data->totlayer; i++) {
const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[i].type);
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
if (typeInfo->swap) {
2016-05-17 03:01:32 +10:00
const size_t offset = (size_t)index * typeInfo->size;
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
typeInfo->swap(POINTER_OFFSET(data->layers[i].data, offset), corner_indices);
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
}
}
}
void CustomData_swap(CustomData *data, const int index_a, const int index_b)
{
char buff_static[256];
if (index_a == index_b) {
return;
}
2020-09-09 15:43:09 +02:00
for (int i = 0; i < data->totlayer; i++) {
const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[i].type);
const size_t size = typeInfo->size;
const size_t offset_a = size * index_a;
const size_t offset_b = size * index_b;
void *buff = size <= sizeof(buff_static) ? buff_static : MEM_mallocN(size, __func__);
memcpy(buff, POINTER_OFFSET(data->layers[i].data, offset_a), size);
memcpy(POINTER_OFFSET(data->layers[i].data, offset_a),
POINTER_OFFSET(data->layers[i].data, offset_b),
size);
memcpy(POINTER_OFFSET(data->layers[i].data, offset_b), buff, size);
if (buff != buff_static) {
MEM_freeN(buff);
}
}
}
void *CustomData_get(const CustomData *data, int index, int type)
{
BLI_assert(index >= 0);
/* get the layer index of the active layer of type */
2020-09-09 15:43:09 +02:00
int layer_index = CustomData_get_active_layer_index(data, type);
if (layer_index == -1) {
return nullptr;
}
/* get the offset of the desired element */
2016-05-17 03:01:32 +10:00
const size_t offset = (size_t)index * layerType_getInfo(type)->size;
return POINTER_OFFSET(data->layers[layer_index].data, offset);
}
void *CustomData_get_n(const CustomData *data, int type, int index, int n)
{
BLI_assert(index >= 0 && n >= 0);
/* get the layer index of the first layer of type */
2020-09-09 15:43:09 +02:00
int layer_index = data->typemap[type];
if (layer_index == -1) {
return nullptr;
}
2016-05-17 03:01:32 +10:00
const size_t offset = (size_t)index * layerType_getInfo(type)->size;
return POINTER_OFFSET(data->layers[layer_index + n].data, offset);
}
void *CustomData_get_layer(const CustomData *data, int type)
{
/* get the layer index of the active layer of type */
int layer_index = CustomData_get_active_layer_index(data, type);
if (layer_index == -1) {
return nullptr;
}
return data->layers[layer_index].data;
}
void *CustomData_get_layer_n(const CustomData *data, int type, int n)
{
/* get the layer index of the active layer of type */
int layer_index = CustomData_get_layer_index_n(data, type, n);
if (layer_index == -1) {
return nullptr;
}
return data->layers[layer_index].data;
}
void *CustomData_get_layer_named(const CustomData *data, int type, const char *name)
{
int layer_index = CustomData_get_named_layer_index(data, type, name);
if (layer_index == -1) {
return nullptr;
}
return data->layers[layer_index].data;
}
int CustomData_get_offset(const CustomData *data, int type)
{
/* get the layer index of the active layer of type */
int layer_index = CustomData_get_active_layer_index(data, type);
if (layer_index == -1) {
return -1;
}
return data->layers[layer_index].offset;
}
int CustomData_get_n_offset(const CustomData *data, int type, int n)
{
/* get the layer index of the active layer of type */
int layer_index = CustomData_get_layer_index_n(data, type, n);
if (layer_index == -1) {
return -1;
}
return data->layers[layer_index].offset;
}
2013-05-08 12:57:18 +00:00
bool CustomData_set_layer_name(const CustomData *data, int type, int n, const char *name)
{
/* get the layer index of the first layer of type */
const int layer_index = CustomData_get_layer_index_n(data, type, n);
if ((layer_index == -1) || !name) {
2014-12-01 17:11:18 +01:00
return false;
}
2018-06-17 17:05:51 +02:00
BLI_strncpy(data->layers[layer_index].name, name, sizeof(data->layers[layer_index].name));
2018-06-17 17:05:51 +02:00
2013-05-08 12:57:18 +00:00
return true;
}
const char *CustomData_get_layer_name(const CustomData *data, int type, int n)
{
const int layer_index = CustomData_get_layer_index_n(data, type, n);
return (layer_index == -1) ? nullptr : data->layers[layer_index].name;
}
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
void *CustomData_set_layer(const CustomData *data, int type, void *ptr)
{
/* get the layer index of the first layer of type */
int layer_index = CustomData_get_active_layer_index(data, type);
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
if (layer_index == -1) {
return nullptr;
}
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
data->layers[layer_index].data = ptr;
return ptr;
}
void *CustomData_set_layer_n(const CustomData *data, int type, int n, void *ptr)
{
/* get the layer index of the first layer of type */
int layer_index = CustomData_get_layer_index_n(data, type, n);
if (layer_index == -1) {
return nullptr;
}
data->layers[layer_index].data = ptr;
return ptr;
}
2015-02-23 15:55:48 +11:00
void CustomData_set(const CustomData *data, int index, int type, const void *source)
{
void *dest = CustomData_get(data, index, type);
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
if (!dest) {
return;
}
if (typeInfo->copy) {
typeInfo->copy(source, dest, 1);
}
else {
memcpy(dest, source, typeInfo->size);
}
}
/* BMesh functions */
void CustomData_to_bmeshpoly(CustomData *fdata, CustomData *ldata, int totloop)
{
for (int i = 0; i < fdata->totlayer; i++) {
if (fdata->layers[i].type == CD_MTFACE) {
CustomData_add_layer_named(
ldata, CD_MLOOPUV, CD_CALLOC, nullptr, totloop, fdata->layers[i].name);
}
else if (fdata->layers[i].type == CD_MCOL) {
CustomData_add_layer_named(
ldata, CD_PROP_BYTE_COLOR, CD_CALLOC, nullptr, totloop, fdata->layers[i].name);
}
else if (fdata->layers[i].type == CD_MDISPS) {
CustomData_add_layer_named(
ldata, CD_MDISPS, CD_CALLOC, nullptr, totloop, fdata->layers[i].name);
}
else if (fdata->layers[i].type == CD_TESSLOOPNORMAL) {
CustomData_add_layer_named(
ldata, CD_NORMAL, CD_CALLOC, nullptr, totloop, fdata->layers[i].name);
}
}
}
void CustomData_from_bmeshpoly(CustomData *fdata, CustomData *ldata, int total)
{
/* avoid accumulating extra layers */
BLI_assert(!CustomData_from_bmeshpoly_test(fdata, ldata, false));
2020-09-09 15:43:09 +02:00
for (int i = 0; i < ldata->totlayer; i++) {
if (ldata->layers[i].type == CD_MLOOPUV) {
CustomData_add_layer_named(
fdata, CD_MTFACE, CD_CALLOC, nullptr, total, ldata->layers[i].name);
}
if (ldata->layers[i].type == CD_PROP_BYTE_COLOR) {
CustomData_add_layer_named(fdata, CD_MCOL, CD_CALLOC, nullptr, total, ldata->layers[i].name);
}
else if (ldata->layers[i].type == CD_PREVIEW_MLOOPCOL) {
CustomData_add_layer_named(
fdata, CD_PREVIEW_MCOL, CD_CALLOC, nullptr, total, ldata->layers[i].name);
}
else if (ldata->layers[i].type == CD_ORIGSPACE_MLOOP) {
CustomData_add_layer_named(
fdata, CD_ORIGSPACE, CD_CALLOC, nullptr, total, ldata->layers[i].name);
}
else if (ldata->layers[i].type == CD_NORMAL) {
CustomData_add_layer_named(
fdata, CD_TESSLOOPNORMAL, CD_CALLOC, nullptr, total, ldata->layers[i].name);
}
else if (ldata->layers[i].type == CD_TANGENT) {
CustomData_add_layer_named(
fdata, CD_TANGENT, CD_CALLOC, nullptr, total, ldata->layers[i].name);
}
}
CustomData_bmesh_update_active_layers(fdata, ldata);
}
#ifndef NDEBUG
bool CustomData_from_bmeshpoly_test(CustomData *fdata, CustomData *ldata, bool fallback)
{
int a_num = 0, b_num = 0;
# define LAYER_CMP(l_a, t_a, l_b, t_b) \
((a_num += CustomData_number_of_layers(l_a, t_a)) == \
(b_num += CustomData_number_of_layers(l_b, t_b)))
if (!LAYER_CMP(ldata, CD_MLOOPUV, fdata, CD_MTFACE)) {
return false;
}
if (!LAYER_CMP(ldata, CD_PROP_BYTE_COLOR, fdata, CD_MCOL)) {
return false;
}
if (!LAYER_CMP(ldata, CD_PREVIEW_MLOOPCOL, fdata, CD_PREVIEW_MCOL)) {
return false;
}
if (!LAYER_CMP(ldata, CD_ORIGSPACE_MLOOP, fdata, CD_ORIGSPACE)) {
return false;
}
if (!LAYER_CMP(ldata, CD_NORMAL, fdata, CD_TESSLOOPNORMAL)) {
return false;
}
if (!LAYER_CMP(ldata, CD_TANGENT, fdata, CD_TANGENT)) {
return false;
}
# undef LAYER_CMP
/* if no layers are on either CustomData's,
* then there was nothing to do... */
return a_num ? true : fallback;
}
#endif
void CustomData_bmesh_update_active_layers(CustomData *fdata, CustomData *ldata)
{
int act;
if (CustomData_has_layer(ldata, CD_MLOOPUV)) {
act = CustomData_get_active_layer(ldata, CD_MLOOPUV);
CustomData_set_layer_active(fdata, CD_MTFACE, act);
act = CustomData_get_render_layer(ldata, CD_MLOOPUV);
CustomData_set_layer_render(fdata, CD_MTFACE, act);
act = CustomData_get_clone_layer(ldata, CD_MLOOPUV);
CustomData_set_layer_clone(fdata, CD_MTFACE, act);
act = CustomData_get_stencil_layer(ldata, CD_MLOOPUV);
CustomData_set_layer_stencil(fdata, CD_MTFACE, act);
}
if (CustomData_has_layer(ldata, CD_PROP_BYTE_COLOR)) {
act = CustomData_get_active_layer(ldata, CD_PROP_BYTE_COLOR);
CustomData_set_layer_active(fdata, CD_MCOL, act);
act = CustomData_get_render_layer(ldata, CD_PROP_BYTE_COLOR);
CustomData_set_layer_render(fdata, CD_MCOL, act);
act = CustomData_get_clone_layer(ldata, CD_PROP_BYTE_COLOR);
CustomData_set_layer_clone(fdata, CD_MCOL, act);
act = CustomData_get_stencil_layer(ldata, CD_PROP_BYTE_COLOR);
CustomData_set_layer_stencil(fdata, CD_MCOL, act);
}
}
void CustomData_bmesh_do_versions_update_active_layers(CustomData *fdata, CustomData *ldata)
{
int act;
if (CustomData_has_layer(fdata, CD_MTFACE)) {
act = CustomData_get_active_layer(fdata, CD_MTFACE);
CustomData_set_layer_active(ldata, CD_MLOOPUV, act);
act = CustomData_get_render_layer(fdata, CD_MTFACE);
CustomData_set_layer_render(ldata, CD_MLOOPUV, act);
act = CustomData_get_clone_layer(fdata, CD_MTFACE);
CustomData_set_layer_clone(ldata, CD_MLOOPUV, act);
act = CustomData_get_stencil_layer(fdata, CD_MTFACE);
CustomData_set_layer_stencil(ldata, CD_MLOOPUV, act);
}
if (CustomData_has_layer(fdata, CD_MCOL)) {
act = CustomData_get_active_layer(fdata, CD_MCOL);
CustomData_set_layer_active(ldata, CD_PROP_BYTE_COLOR, act);
act = CustomData_get_render_layer(fdata, CD_MCOL);
CustomData_set_layer_render(ldata, CD_PROP_BYTE_COLOR, act);
act = CustomData_get_clone_layer(fdata, CD_MCOL);
CustomData_set_layer_clone(ldata, CD_PROP_BYTE_COLOR, act);
act = CustomData_get_stencil_layer(fdata, CD_MCOL);
CustomData_set_layer_stencil(ldata, CD_PROP_BYTE_COLOR, act);
}
}
void CustomData_bmesh_init_pool(CustomData *data, int totelem, const char htype)
{
int chunksize;
/* Dispose old pools before calling here to avoid leaks */
BLI_assert(data->pool == nullptr);
switch (htype) {
case BM_VERT:
chunksize = bm_mesh_chunksize_default.totvert;
break;
case BM_EDGE:
chunksize = bm_mesh_chunksize_default.totedge;
break;
case BM_LOOP:
chunksize = bm_mesh_chunksize_default.totloop;
break;
case BM_FACE:
chunksize = bm_mesh_chunksize_default.totface;
break;
default:
BLI_assert_unreachable();
chunksize = 512;
break;
}
/* If there are no layers, no pool is needed just yet */
if (data->totlayer) {
data->pool = BLI_mempool_create(data->totsize, totelem, chunksize, BLI_MEMPOOL_NOP);
}
}
2015-02-23 15:55:48 +11:00
bool CustomData_bmesh_merge(const CustomData *source,
CustomData *dest,
eCustomDataMask mask,
2018-05-30 10:28:24 +02:00
eCDAllocType alloctype,
BMesh *bm,
const char htype)
{
if (CustomData_number_of_layers_typemask(source, mask) == 0) {
return false;
}
/* copy old layer description so that old data can be copied into
2012-04-22 11:54:53 +00:00
* the new allocation */
2020-09-09 15:43:09 +02:00
CustomData destold = *dest;
if (destold.layers) {
destold.layers = static_cast<CustomDataLayer *>(MEM_dupallocN(destold.layers));
}
if (CustomData_merge(source, dest, mask, alloctype, 0) == false) {
if (destold.layers) {
MEM_freeN(destold.layers);
}
return false;
}
2020-09-09 15:43:09 +02:00
int iter_type;
int totelem;
switch (htype) {
case BM_VERT:
iter_type = BM_VERTS_OF_MESH;
totelem = bm->totvert;
break;
case BM_EDGE:
iter_type = BM_EDGES_OF_MESH;
totelem = bm->totedge;
break;
case BM_LOOP:
iter_type = BM_LOOPS_OF_FACE;
totelem = bm->totloop;
break;
case BM_FACE:
iter_type = BM_FACES_OF_MESH;
totelem = bm->totface;
break;
default: /* should never happen */
BLI_assert_msg(0, "invalid type given");
iter_type = BM_VERTS_OF_MESH;
totelem = bm->totvert;
break;
}
dest->pool = nullptr;
CustomData_bmesh_init_pool(dest, totelem, htype);
if (iter_type != BM_LOOPS_OF_FACE) {
2020-09-09 15:43:09 +02:00
BMHeader *h;
BMIter iter;
/* Ensure all current elements follow new customdata layout. */
BM_ITER_MESH (h, &iter, bm, iter_type) {
void *tmp = nullptr;
CustomData_bmesh_copy_data(&destold, dest, h->data, &tmp);
CustomData_bmesh_free_block(&destold, &h->data);
h->data = tmp;
}
}
else {
BMFace *f;
BMLoop *l;
2020-09-09 15:43:09 +02:00
BMIter iter;
BMIter liter;
/* Ensure all current elements follow new customdata layout. */
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
void *tmp = nullptr;
CustomData_bmesh_copy_data(&destold, dest, l->head.data, &tmp);
CustomData_bmesh_free_block(&destold, &l->head.data);
l->head.data = tmp;
}
}
}
if (destold.pool) {
BLI_mempool_destroy(destold.pool);
}
if (destold.layers) {
MEM_freeN(destold.layers);
}
return true;
}
void CustomData_bmesh_free_block(CustomData *data, void **block)
{
if (*block == nullptr) {
return;
}
2020-09-09 15:43:09 +02:00
for (int i = 0; i < data->totlayer; i++) {
if (!(data->layers[i].flag & CD_FLAG_NOFREE)) {
2020-09-09 15:43:09 +02:00
const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[i].type);
if (typeInfo->free) {
int offset = data->layers[i].offset;
typeInfo->free(POINTER_OFFSET(*block, offset), 1, typeInfo->size);
}
}
}
if (data->totsize) {
BLI_mempool_free(data->pool, *block);
}
*block = nullptr;
}
void CustomData_bmesh_free_block_data(CustomData *data, void *block)
{
if (block == nullptr) {
return;
}
for (int i = 0; i < data->totlayer; i++) {
if (!(data->layers[i].flag & CD_FLAG_NOFREE)) {
const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[i].type);
if (typeInfo->free) {
2016-05-17 03:01:32 +10:00
const size_t offset = data->layers[i].offset;
typeInfo->free(POINTER_OFFSET(block, offset), 1, typeInfo->size);
}
}
}
if (data->totsize) {
memset(block, 0, data->totsize);
}
}
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_alloc(data->pool);
}
else {
*block = nullptr;
}
}
void CustomData_bmesh_free_block_data_exclude_by_type(CustomData *data,
void *block,
const eCustomDataMask mask_exclude)
{
if (block == nullptr) {
return;
}
for (int i = 0; i < data->totlayer; i++) {
if ((CD_TYPE_AS_MASK(data->layers[i].type) & mask_exclude) == 0) {
const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[i].type);
const size_t offset = data->layers[i].offset;
if (!(data->layers[i].flag & CD_FLAG_NOFREE)) {
if (typeInfo->free) {
typeInfo->free(POINTER_OFFSET(block, offset), 1, typeInfo->size);
}
}
memset(POINTER_OFFSET(block, offset), 0, typeInfo->size);
}
}
}
static void CustomData_bmesh_set_default_n(CustomData *data, void **block, int n)
{
int offset = data->layers[n].offset;
2021-01-26 09:21:42 -06:00
const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[n].type);
if (typeInfo->set_default) {
typeInfo->set_default(POINTER_OFFSET(*block, offset), 1);
}
else {
memset(POINTER_OFFSET(*block, offset), 0, typeInfo->size);
}
}
void CustomData_bmesh_set_default(CustomData *data, void **block)
{
if (*block == nullptr) {
CustomData_bmesh_alloc_block(data, block);
}
2020-09-09 15:43:09 +02:00
for (int i = 0; i < data->totlayer; i++) {
CustomData_bmesh_set_default_n(data, block, i);
}
}
void CustomData_bmesh_copy_data_exclude_by_type(const CustomData *source,
CustomData *dest,
void *src_block,
void **dest_block,
const eCustomDataMask mask_exclude)
{
/* Note that having a version of this function without a 'mask_exclude'
* would cause too much duplicate code, so add a check instead. */
const bool no_mask = (mask_exclude == 0);
if (*dest_block == nullptr) {
CustomData_bmesh_alloc_block(dest, dest_block);
if (*dest_block) {
memset(*dest_block, 0, dest->totsize);
}
}
2018-06-17 17:05:51 +02:00
/* copies a layer at a time */
2020-09-09 15:43:09 +02:00
int dest_i = 0;
for (int 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) {
CustomData_bmesh_set_default_n(dest, dest_block, dest_i);
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 &&
STREQ(dest->layers[dest_i].name, source->layers[src_i].name)) {
if (no_mask || ((CD_TYPE_AS_MASK(dest->layers[dest_i].type) & mask_exclude) == 0)) {
const void *src_data = POINTER_OFFSET(src_block, source->layers[src_i].offset);
void *dest_data = POINTER_OFFSET(*dest_block, dest->layers[dest_i].offset);
const LayerTypeInfo *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++;
}
}
while (dest_i < dest->totlayer) {
CustomData_bmesh_set_default_n(dest, dest_block, dest_i);
dest_i++;
}
}
void CustomData_bmesh_copy_data(const CustomData *source,
CustomData *dest,
void *src_block,
void **dest_block)
{
CustomData_bmesh_copy_data_exclude_by_type(source, dest, src_block, dest_block, 0);
}
void *CustomData_bmesh_get(const CustomData *data, void *block, int type)
{
/* get the layer index of the first layer of type */
2020-09-09 15:43:09 +02:00
int layer_index = CustomData_get_active_layer_index(data, type);
if (layer_index == -1) {
return nullptr;
}
return POINTER_OFFSET(block, data->layers[layer_index].offset);
}
void *CustomData_bmesh_get_n(const CustomData *data, void *block, int type, int n)
{
/* get the layer index of the first layer of type */
2020-09-09 15:43:09 +02:00
int layer_index = CustomData_get_layer_index(data, type);
if (layer_index == -1) {
return nullptr;
}
return POINTER_OFFSET(block, data->layers[layer_index + n].offset);
}
void *CustomData_bmesh_get_layer_n(const CustomData *data, void *block, int n)
{
if (n < 0 || n >= data->totlayer) {
return nullptr;
}
return POINTER_OFFSET(block, data->layers[n].offset);
}
bool CustomData_layer_has_math(const CustomData *data, int layer_n)
{
2012-03-18 07:38:51 +00:00
const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[layer_n].type);
2018-06-17 17:05:51 +02:00
if (typeInfo->equal && typeInfo->add && typeInfo->multiply && typeInfo->initminmax &&
typeInfo->dominmax) {
2013-05-08 12:57:18 +00:00
return true;
}
2018-06-17 17:05:51 +02:00
2013-05-08 12:57:18 +00:00
return false;
}
bool CustomData_layer_has_interp(const CustomData *data, int layer_n)
{
const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[layer_n].type);
if (typeInfo->interp) {
2013-05-08 12:57:18 +00:00
return true;
}
2013-05-08 12:57:18 +00:00
return false;
}
bool CustomData_has_math(const CustomData *data)
{
/* interpolates a layer at a time */
2020-09-09 15:43:09 +02:00
for (int i = 0; i < data->totlayer; i++) {
if (CustomData_layer_has_math(data, i)) {
2013-05-08 12:57:18 +00:00
return true;
}
}
2013-05-08 12:57:18 +00:00
return false;
}
bool CustomData_bmesh_has_free(const CustomData *data)
{
2020-09-09 15:43:09 +02:00
for (int i = 0; i < data->totlayer; i++) {
if (!(data->layers[i].flag & CD_FLAG_NOFREE)) {
2020-09-09 15:43:09 +02:00
const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[i].type);
if (typeInfo->free) {
return true;
}
}
}
return false;
}
bool CustomData_has_interp(const CustomData *data)
{
/* interpolates a layer at a time */
2020-09-09 15:43:09 +02:00
for (int i = 0; i < data->totlayer; i++) {
if (CustomData_layer_has_interp(data, i)) {
2013-05-08 12:57:18 +00:00
return true;
}
}
2013-05-08 12:57:18 +00:00
return false;
}
bool CustomData_has_referenced(const CustomData *data)
{
2020-09-09 15:43:09 +02:00
for (int i = 0; i < data->totlayer; i++) {
if (data->layers[i].flag & CD_FLAG_NOFREE) {
return true;
}
}
return false;
}
void CustomData_data_copy_value(int type, const void *source, void *dest)
{
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
if (!dest) {
return;
}
if (typeInfo->copyvalue) {
typeInfo->copyvalue(source, dest, CDT_MIX_NOMIX, 0.0f);
}
else {
memcpy(dest, source, typeInfo->size);
}
}
void CustomData_data_mix_value(
int type, const void *source, void *dest, const int mixmode, const float mixfactor)
{
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
if (!dest) {
return;
}
if (typeInfo->copyvalue) {
typeInfo->copyvalue(source, dest, mixmode, mixfactor);
}
else {
/* Mere copy if no advanced interpolation is supported. */
memcpy(dest, source, typeInfo->size);
}
}
bool CustomData_data_equals(int type, const void *data1, const void *data2)
{
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
if (typeInfo->equal) {
return typeInfo->equal(data1, data2);
}
return !memcmp(data1, data2, typeInfo->size);
}
void CustomData_data_initminmax(int type, void *min, void *max)
{
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
if (typeInfo->initminmax) {
typeInfo->initminmax(min, max);
}
}
void CustomData_data_dominmax(int type, const void *data, void *min, void *max)
{
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
if (typeInfo->dominmax) {
typeInfo->dominmax(data, min, max);
}
}
void CustomData_data_multiply(int type, void *data, float fac)
{
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
if (typeInfo->multiply) {
typeInfo->multiply(data, fac);
}
}
void CustomData_data_add(int type, void *data1, const void *data2)
{
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
if (typeInfo->add) {
typeInfo->add(data1, data2);
}
}
2015-02-23 15:55:48 +11:00
void CustomData_bmesh_set(const CustomData *data, void *block, int type, const 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);
}
}
2015-02-23 15:55:48 +11:00
void CustomData_bmesh_set_n(CustomData *data, void *block, int type, int n, const 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);
}
}
2015-02-23 15:55:48 +11:00
void CustomData_bmesh_set_layer_n(CustomData *data, void *block, int n, const void *source)
{
void *dest = CustomData_bmesh_get_layer_n(data, block, n);
const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[n].type);
if (!dest) {
return;
}
if (typeInfo->copy) {
typeInfo->copy(source, dest, 1);
}
else {
memcpy(dest, source, typeInfo->size);
}
}
void CustomData_bmesh_interp_n(CustomData *data,
const void **src_blocks_ofs,
const float *weights,
const float *sub_weights,
int count,
void *dst_block_ofs,
int n)
{
BLI_assert(weights != nullptr);
BLI_assert(count > 0);
CustomDataLayer *layer = &data->layers[n];
const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
typeInfo->interp(src_blocks_ofs, weights, sub_weights, count, dst_block_ofs);
}
void CustomData_bmesh_interp(CustomData *data,
const void **src_blocks,
const float *weights,
const float *sub_weights,
int count,
void *dst_block)
{
if (count <= 0) {
return;
}
void *source_buf[SOURCE_BUF_SIZE];
const void **sources = (const void **)source_buf;
2019-08-17 00:54:22 +10:00
/* Slow fallback in case we're interpolating a ridiculous number of elements. */
if (count > SOURCE_BUF_SIZE) {
sources = (const void **)MEM_malloc_arrayN(count, sizeof(*sources), __func__);
}
/* If no weights are given, generate default ones to produce an average result. */
float default_weights_buf[SOURCE_BUF_SIZE];
float *default_weights = nullptr;
if (weights == nullptr) {
default_weights = (count > SOURCE_BUF_SIZE) ?
(float *)MEM_mallocN(sizeof(*weights) * (size_t)count, __func__) :
default_weights_buf;
copy_vn_fl(default_weights, count, 1.0f / count);
weights = default_weights;
}
/* interpolates a layer at a time */
2021-01-26 09:21:42 -06:00
for (int i = 0; i < data->totlayer; i++) {
CustomDataLayer *layer = &data->layers[i];
const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
if (typeInfo->interp) {
2021-01-26 09:21:42 -06:00
for (int j = 0; j < count; j++) {
sources[j] = POINTER_OFFSET(src_blocks[j], layer->offset);
}
CustomData_bmesh_interp_n(
data, sources, weights, sub_weights, count, POINTER_OFFSET(dst_block, layer->offset), i);
}
}
if (count > SOURCE_BUF_SIZE) {
MEM_freeN((void *)sources);
}
if (!ELEM(default_weights, nullptr, default_weights_buf)) {
MEM_freeN(default_weights);
}
}
void CustomData_to_bmesh_block(const CustomData *source,
CustomData *dest,
int src_index,
void **dest_block,
bool use_default_init)
{
if (*dest_block == nullptr) {
CustomData_bmesh_alloc_block(dest, dest_block);
}
/* copies a layer at a time */
2020-09-09 15:43:09 +02:00
int dest_i = 0;
for (int 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) {
if (use_default_init) {
CustomData_bmesh_set_default_n(dest, dest_block, dest_i);
}
dest_i++;
}
/* if there are no more dest layers, we're done */
if (dest_i >= dest->totlayer) {
break;
}
/* 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;
const void *src_data = source->layers[src_i].data;
void *dest_data = POINTER_OFFSET(*dest_block, offset);
2020-09-09 15:43:09 +02:00
const LayerTypeInfo *typeInfo = layerType_getInfo(dest->layers[dest_i].type);
2016-05-17 03:01:32 +10:00
const size_t src_offset = (size_t)src_index * typeInfo->size;
if (typeInfo->copy) {
typeInfo->copy(POINTER_OFFSET(src_data, src_offset), dest_data, 1);
}
else {
memcpy(dest_data, POINTER_OFFSET(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++;
}
}
if (use_default_init) {
while (dest_i < dest->totlayer) {
CustomData_bmesh_set_default_n(dest, dest_block, dest_i);
dest_i++;
}
}
}
void CustomData_from_bmesh_block(const CustomData *source,
CustomData *dest,
void *src_block,
int dest_index)
{
/* copies a layer at a time */
2020-09-09 15:43:09 +02:00
int dest_i = 0;
for (int src_i = 0; src_i < source->totlayer; src_i++) {
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
/* 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++;
}
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
/* if there are no more dest layers, we're done */
if (dest_i >= dest->totlayer) {
return;
}
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
/* if we found a matching layer, copy the data */
if (dest->layers[dest_i].type == source->layers[src_i].type) {
const LayerTypeInfo *typeInfo = layerType_getInfo(dest->layers[dest_i].type);
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
int offset = source->layers[src_i].offset;
const void *src_data = POINTER_OFFSET(src_block, offset);
2016-05-17 03:01:32 +10:00
void *dst_data = POINTER_OFFSET(dest->layers[dest_i].data,
(size_t)dest_index * typeInfo->size);
if (typeInfo->copy) {
typeInfo->copy(src_data, dst_data, 1);
}
else {
memcpy(dst_data, src_data, typeInfo->size);
}
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
/* 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++;
}
}
}
2016-05-17 03:07:40 +10:00
void CustomData_file_write_info(int type, const char **r_struct_name, int *r_struct_num)
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
{
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
2016-05-17 03:07:40 +10:00
*r_struct_name = typeInfo->structname;
*r_struct_num = typeInfo->structnum;
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
}
void CustomData_blend_write_prepare(CustomData &data, Vector<CustomDataLayer, 16> &layers_to_write)
{
for (const CustomDataLayer &layer : Span(data.layers, data.totlayer)) {
if (layer.flag & CD_FLAG_NOCOPY) {
continue;
}
if (layer.anonymous_id != nullptr) {
continue;
}
layers_to_write.append(layer);
}
data.totlayer = layers_to_write.size();
data.maxlayer = data.totlayer;
}
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
int CustomData_sizeof(int type)
{
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
return typeInfo->size;
Added custom vertex/edge/face data for meshes: All data layers, including MVert/MEdge/MFace, are now managed as custom data layers. The pointers like Mesh.mvert, Mesh.dvert or Mesh.mcol are still used of course, but allocating, copying or freeing these arrays should be done through the CustomData API. Work in progress documentation on this is here: http://mediawiki.blender.org/index.php/BlenderDev/BlenderArchitecture/CustomData Replaced TFace by MTFace: This is the same struct, except that it does not contain color, that now always stays separated in MCol. This was not a good design decision to begin with, and it is needed for adding multiple color layers later. Note that this does mean older Blender versions will not be able to read UV coordinates from the next release, due to an SDNA limitation. Removed DispListMesh: This now fully replaced by DerivedMesh. To provide access to arrays of vertices, edges and faces, like DispListMesh does. The semantics of the DerivedMesh.getVertArray() and similar functions were changed to return a pointer to an array if one exists, or otherwise allocate a temporary one. On releasing the DerivedMesh, this temporary array will be removed automatically. Removed ssDM and meshDM DerivedMesh backends: The ssDM backend was for DispListMesh, so that became obsolete automatically. The meshDM backend was replaced by the custom data backend, that now figures out which layers need to be modified, and only duplicates those. This changes code in many places, and overall removes 2514 lines of code. So, there's a good chance this might break some stuff, although I've been testing it for a few days now. The good news is, adding multiple color and uv layers should now become easy.
2006-11-20 04:28:02 +00:00
}
const char *CustomData_layertype_name(int type)
{
return layerType_getName(type);
}
2013-05-08 12:57:18 +00:00
bool CustomData_layertype_is_singleton(int type)
{
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
return typeInfo->defaultname == nullptr;
}
bool CustomData_layertype_is_dynamic(int type)
{
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
return (typeInfo->free != nullptr);
}
int CustomData_layertype_layers_max(const int type)
{
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
/* Same test as for singleton above. */
if (typeInfo->defaultname == nullptr) {
return 1;
}
if (typeInfo->layers_max == nullptr) {
return -1;
}
return typeInfo->layers_max();
}
static bool cd_layer_find_dupe(CustomData *data, const char *name, int type, int index)
{
/* see if there is a duplicate */
2020-09-09 15:43:09 +02:00
for (int i = 0; i < data->totlayer; i++) {
if (i != index) {
2012-05-12 16:11:34 +00:00
CustomDataLayer *layer = &data->layers[i];
2018-06-17 17:05:51 +02:00
if (CD_TYPE_AS_MASK(type) & CD_MASK_PROP_ALL) {
if ((CD_TYPE_AS_MASK(layer->type) & CD_MASK_PROP_ALL) && STREQ(layer->name, name)) {
return true;
}
}
else {
if (i != index && layer->type == type && STREQ(layer->name, name)) {
return true;
}
}
}
}
2018-06-17 17:05:51 +02:00
return false;
}
struct CustomDataUniqueCheckData {
CustomData *data;
int type;
int index;
};
static bool customdata_unique_check(void *arg, const char *name)
{
CustomDataUniqueCheckData *data_arg = static_cast<CustomDataUniqueCheckData *>(arg);
return cd_layer_find_dupe(data_arg->data, name, data_arg->type, data_arg->index);
}
void CustomData_set_layer_unique_name(CustomData *data, int index)
2018-06-17 17:05:51 +02:00
{
2012-05-12 16:11:34 +00:00
CustomDataLayer *nlayer = &data->layers[index];
const LayerTypeInfo *typeInfo = layerType_getInfo(nlayer->type);
CustomDataUniqueCheckData data_arg{data, nlayer->type, index};
if (!typeInfo->defaultname) {
return;
}
/* Set default name if none specified. Note we only call DATA_() when
* needed to avoid overhead of locale lookups in the depsgraph. */
if (nlayer->name[0] == '\0') {
STRNCPY(nlayer->name, DATA_(typeInfo->defaultname));
}
BLI_uniquename_cb(
customdata_unique_check, &data_arg, nullptr, '.', nlayer->name, sizeof(nlayer->name));
}
void CustomData_validate_layer_name(const CustomData *data,
int type,
const char *name,
char *outname)
{
int index = -1;
/* if a layer name was given, try to find that layer */
if (name[0]) {
index = CustomData_get_named_layer_index(data, type, name);
}
if (index == -1) {
/* either no layer was specified, or the layer we want has been
* deleted, so assign the active layer to name
*/
index = CustomData_get_active_layer_index(data, type);
BLI_strncpy(outname, data->layers[index].name, MAX_CUSTOMDATA_LAYER_NAME);
}
else {
BLI_strncpy(outname, name, MAX_CUSTOMDATA_LAYER_NAME);
}
}
bool CustomData_verify_versions(CustomData *data, int index)
{
const LayerTypeInfo *typeInfo;
CustomDataLayer *layer = &data->layers[index];
2013-05-08 12:57:18 +00:00
bool keeplayer = true;
if (layer->type >= CD_NUMTYPES) {
2013-05-08 12:57:18 +00:00
keeplayer = false; /* unknown layer type from future version */
}
else {
typeInfo = layerType_getInfo(layer->type);
2012-05-12 16:11:34 +00:00
if (!typeInfo->defaultname && (index > 0) && data->layers[index - 1].type == layer->type) {
2013-05-08 12:57:18 +00:00
keeplayer = false; /* multiple layers of which we only support one */
}
2019-08-28 01:55:43 +10:00
/* This is a preemptive fix for cases that should not happen
* (layers that should not be written in .blend files),
* but can happen due to bugs (see e.g. T62318).
* Also for forward compatibility, in future,
* we may put into `.blend` file some currently un-written data types,
* this should cover that case as well.
* Better to be safe here, and fix issue on the fly rather than crash... */
/* 0 structnum is used in writing code to tag layer types that should not be written. */
else if (typeInfo->structnum == 0 &&
/* XXX Not sure why those three are exception, maybe that should be fixed? */
!ELEM(layer->type,
CD_PAINT_MASK,
CD_FACEMAP,
CD_MTEXPOLY,
CD_SCULPT_FACE_SETS,
CD_CREASE)) {
keeplayer = false;
CLOG_WARN(&LOG, ".blend file read: removing a data layer that should not have been written");
}
}
if (!keeplayer) {
2020-09-09 15:43:09 +02:00
for (int i = index + 1; i < data->totlayer; i++) {
2012-05-12 16:11:34 +00:00
data->layers[i - 1] = data->layers[i];
}
data->totlayer--;
}
return keeplayer;
}
bool CustomData_layer_validate(CustomDataLayer *layer, const uint totitems, const bool do_fixes)
{
const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
if (typeInfo->validate != nullptr) {
return typeInfo->validate(layer->data, totitems, do_fixes);
}
return false;
}
void CustomData_layers__print(CustomData *data)
{
printf("{\n");
2020-09-09 15:43:09 +02:00
int i;
const CustomDataLayer *layer;
for (i = 0, layer = data->layers; i < data->totlayer; i++, layer++) {
const char *name = CustomData_layertype_name(layer->type);
const int size = CustomData_sizeof(layer->type);
const char *structname;
int structnum;
CustomData_file_write_info(layer->type, &structname, &structnum);
printf(" dict(name='%s', struct='%s', type=%d, ptr='%p', elem=%d, length=%d),\n",
name,
structname,
layer->type,
(const void *)layer->data,
size,
(int)(MEM_allocN_len(layer->data) / size));
}
printf("}\n");
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name External Files
* \{ */
static void customdata_external_filename(char filepath[FILE_MAX],
ID *id,
CustomDataExternal *external)
{
BLI_strncpy(filepath, external->filepath, FILE_MAX);
BLI_path_abs(filepath, ID_BLEND_PATH_FROM_GLOBAL(id));
}
void CustomData_external_reload(CustomData *data,
ID *UNUSED(id),
eCustomDataMask mask,
int totelem)
2010-06-01 19:26:35 +00:00
{
2020-09-09 15:43:09 +02:00
for (int i = 0; i < data->totlayer; i++) {
CustomDataLayer *layer = &data->layers[i];
const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
2010-06-01 19:26:35 +00:00
2012-10-07 09:48:59 +00:00
if (!(mask & CD_TYPE_AS_MASK(layer->type))) {
/* pass */
}
else if ((layer->flag & CD_FLAG_EXTERNAL) && (layer->flag & CD_FLAG_IN_MEMORY)) {
if (typeInfo->free) {
2010-06-01 19:26:35 +00:00
typeInfo->free(layer->data, totelem, typeInfo->size);
}
2010-06-01 19:26:35 +00:00
layer->flag &= ~CD_FLAG_IN_MEMORY;
}
}
}
void CustomData_external_read(CustomData *data, ID *id, eCustomDataMask mask, int totelem)
{
2012-05-12 16:11:34 +00:00
CustomDataExternal *external = data->external;
CustomDataLayer *layer;
char filepath[FILE_MAX];
2020-09-09 15:43:09 +02:00
int update = 0;
if (!external) {
return;
}
2020-09-09 15:43:09 +02:00
for (int i = 0; i < data->totlayer; i++) {
layer = &data->layers[i];
2021-01-26 09:21:42 -06:00
const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
2012-10-07 09:48:59 +00:00
if (!(mask & CD_TYPE_AS_MASK(layer->type))) {
/* pass */
}
else if (layer->flag & CD_FLAG_IN_MEMORY) {
/* pass */
}
else if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->read) {
2012-05-12 16:11:34 +00:00
update = 1;
2012-10-07 09:48:59 +00:00
}
}
if (!update) {
return;
}
customdata_external_filename(filepath, id, external);
2021-01-26 09:21:42 -06:00
CDataFile *cdf = cdf_create(CDF_TYPE_MESH);
if (!cdf_read_open(cdf, filepath)) {
cdf_free(cdf);
CLOG_ERROR(&LOG, "Failed to read %s layer from %s.", layerType_getName(layer->type), filepath);
return;
}
2020-09-09 15:43:09 +02:00
for (int i = 0; i < data->totlayer; i++) {
layer = &data->layers[i];
2021-01-26 09:21:42 -06:00
const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
2012-10-07 09:48:59 +00:00
if (!(mask & CD_TYPE_AS_MASK(layer->type))) {
/* pass */
}
else if (layer->flag & CD_FLAG_IN_MEMORY) {
/* pass */
}
else if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->read) {
2021-01-26 09:21:42 -06:00
CDataFileLayer *blay = cdf_layer_find(cdf, layer->type, layer->name);
if (blay) {
if (cdf_read_layer(cdf, blay)) {
2012-10-07 09:48:59 +00:00
if (typeInfo->read(cdf, layer->data, totelem)) {
/* pass */
}
else {
break;
}
layer->flag |= CD_FLAG_IN_MEMORY;
}
else {
break;
}
}
}
}
cdf_read_close(cdf);
cdf_free(cdf);
}
void CustomData_external_write(
CustomData *data, ID *id, eCustomDataMask mask, int totelem, int free)
{
2012-05-12 16:11:34 +00:00
CustomDataExternal *external = data->external;
2020-09-09 15:43:09 +02:00
int update = 0;
char filepath[FILE_MAX];
if (!external) {
return;
}
/* test if there is anything to write */
2020-09-09 15:43:09 +02:00
for (int i = 0; i < data->totlayer; i++) {
2021-01-26 09:21:42 -06:00
CustomDataLayer *layer = &data->layers[i];
const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
2012-10-07 09:48:59 +00:00
if (!(mask & CD_TYPE_AS_MASK(layer->type))) {
/* pass */
}
else if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->write) {
2012-05-12 16:11:34 +00:00
update = 1;
2012-10-07 09:48:59 +00:00
}
}
if (!update) {
return;
}
/* make sure data is read before we try to write */
CustomData_external_read(data, id, mask, totelem);
customdata_external_filename(filepath, id, external);
2021-01-26 09:21:42 -06:00
CDataFile *cdf = cdf_create(CDF_TYPE_MESH);
2020-09-09 15:43:09 +02:00
for (int i = 0; i < data->totlayer; i++) {
2021-01-26 09:21:42 -06:00
CustomDataLayer *layer = &data->layers[i];
const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->filesize) {
if (layer->flag & CD_FLAG_IN_MEMORY) {
cdf_layer_add(
2012-05-12 16:11:34 +00:00
cdf, layer->type, layer->name, typeInfo->filesize(cdf, layer->data, totelem));
}
else {
cdf_free(cdf);
return; /* read failed for a layer! */
}
}
}
if (!cdf_write_open(cdf, filepath)) {
CLOG_ERROR(&LOG, "Failed to open %s for writing.", filepath);
cdf_free(cdf);
return;
}
2020-09-09 15:43:09 +02:00
int i;
2012-05-12 16:11:34 +00:00
for (i = 0; i < data->totlayer; i++) {
2021-01-26 09:21:42 -06:00
CustomDataLayer *layer = &data->layers[i];
const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->write) {
2021-01-26 09:21:42 -06:00
CDataFileLayer *blay = cdf_layer_find(cdf, layer->type, layer->name);
if (cdf_write_layer(cdf, blay)) {
2012-10-07 09:48:59 +00:00
if (typeInfo->write(cdf, layer->data, totelem)) {
/* pass */
}
else {
break;
}
2012-10-07 09:48:59 +00:00
}
else {
break;
}
2012-10-07 09:48:59 +00:00
}
}
if (i != data->totlayer) {
CLOG_ERROR(&LOG, "Failed to write data to %s.", filepath);
cdf_write_close(cdf);
cdf_free(cdf);
return;
}
2012-05-12 16:11:34 +00:00
for (i = 0; i < data->totlayer; i++) {
2021-01-26 09:21:42 -06:00
CustomDataLayer *layer = &data->layers[i];
const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
if ((layer->flag & CD_FLAG_EXTERNAL) && typeInfo->write) {
if (free) {
if (typeInfo->free) {
typeInfo->free(layer->data, totelem, typeInfo->size);
}
layer->flag &= ~CD_FLAG_IN_MEMORY;
}
}
}
cdf_write_close(cdf);
cdf_free(cdf);
}
void CustomData_external_add(
CustomData *data, ID *UNUSED(id), int type, int UNUSED(totelem), const char *filepath)
{
2012-05-12 16:11:34 +00:00
CustomDataExternal *external = data->external;
2021-01-26 09:21:42 -06:00
int layer_index = CustomData_get_active_layer_index(data, type);
if (layer_index == -1) {
return;
}
2021-01-26 09:21:42 -06:00
CustomDataLayer *layer = &data->layers[layer_index];
if (layer->flag & CD_FLAG_EXTERNAL) {
return;
}
if (!external) {
external = MEM_cnew<CustomDataExternal>(__func__);
2012-05-12 16:11:34 +00:00
data->external = external;
}
BLI_strncpy(external->filepath, filepath, sizeof(external->filepath));
2012-05-12 16:11:34 +00:00
layer->flag |= CD_FLAG_EXTERNAL | CD_FLAG_IN_MEMORY;
}
void CustomData_external_remove(CustomData *data, ID *id, int type, int totelem)
{
2012-05-12 16:11:34 +00:00
CustomDataExternal *external = data->external;
2020-09-09 15:43:09 +02:00
int layer_index = CustomData_get_active_layer_index(data, type);
if (layer_index == -1) {
return;
}
2020-09-09 15:43:09 +02:00
CustomDataLayer *layer = &data->layers[layer_index];
if (!external) {
return;
}
if (layer->flag & CD_FLAG_EXTERNAL) {
if (!(layer->flag & CD_FLAG_IN_MEMORY)) {
CustomData_external_read(data, id, CD_TYPE_AS_MASK(layer->type), totelem);
}
layer->flag &= ~CD_FLAG_EXTERNAL;
}
}
2013-05-08 12:57:18 +00:00
bool CustomData_external_test(CustomData *data, int type)
{
2020-09-09 15:43:09 +02:00
int layer_index = CustomData_get_active_layer_index(data, type);
if (layer_index == -1) {
return false;
}
2020-09-09 15:43:09 +02:00
CustomDataLayer *layer = &data->layers[layer_index];
2013-05-08 12:57:18 +00:00
return (layer->flag & CD_FLAG_EXTERNAL) != 0;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Mesh-to-Mesh Data Transfer
* \{ */
static void copy_bit_flag(void *dst, const void *src, const size_t data_size, const uint64_t flag)
{
#define COPY_BIT_FLAG(_type, _dst, _src, _f) \
{ \
const _type _val = *((_type *)(_src)) & ((_type)(_f)); \
*((_type *)(_dst)) &= ~((_type)(_f)); \
*((_type *)(_dst)) |= _val; \
} \
(void)0
switch (data_size) {
case 1:
COPY_BIT_FLAG(uint8_t, dst, src, flag);
break;
case 2:
COPY_BIT_FLAG(uint16_t, dst, src, flag);
break;
case 4:
COPY_BIT_FLAG(uint32_t, dst, src, flag);
break;
case 8:
COPY_BIT_FLAG(uint64_t, dst, src, flag);
break;
default:
// CLOG_ERROR(&LOG, "Unknown flags-container size (%zu)", datasize);
break;
}
#undef COPY_BIT_FLAG
}
static bool check_bit_flag(const void *data, const size_t data_size, const uint64_t flag)
{
switch (data_size) {
case 1:
return ((*((uint8_t *)data) & ((uint8_t)flag)) != 0);
case 2:
return ((*((uint16_t *)data) & ((uint16_t)flag)) != 0);
case 4:
return ((*((uint32_t *)data) & ((uint32_t)flag)) != 0);
case 8:
return ((*((uint64_t *)data) & ((uint64_t)flag)) != 0);
default:
// CLOG_ERROR(&LOG, "Unknown flags-container size (%zu)", datasize);
return false;
}
}
static void customdata_data_transfer_interp_generic(const CustomDataTransferLayerMap *laymap,
void *data_dst,
const void **sources,
const float *weights,
const int count,
const float mix_factor)
{
BLI_assert(weights != nullptr);
BLI_assert(count > 0);
/* Fake interpolation, we actually copy highest weighted source to dest.
* Note we also handle bitflags here,
* in which case we rather choose to transfer value of elements totaling
* more than 0.5 of weight. */
int best_src_idx = 0;
const int data_type = laymap->data_type;
const int mix_mode = laymap->mix_mode;
size_t data_size;
const uint64_t data_flag = laymap->data_flag;
cd_interp interp_cd = nullptr;
cd_copy copy_cd = nullptr;
if (!sources) {
/* Not supported here, abort. */
return;
}
if (data_type & CD_FAKE) {
data_size = laymap->data_size;
}
else {
const LayerTypeInfo *type_info = layerType_getInfo(data_type);
data_size = (size_t)type_info->size;
interp_cd = type_info->interp;
copy_cd = type_info->copy;
}
2021-01-26 09:21:42 -06:00
void *tmp_dst = MEM_mallocN(data_size, __func__);
if (count > 1 && !interp_cd) {
if (data_flag) {
/* Boolean case, we can 'interpolate' in two groups,
* and choose value from highest weighted group. */
float tot_weight_true = 0.0f;
int item_true_idx = -1, item_false_idx = -1;
2020-09-09 15:43:09 +02:00
for (int i = 0; i < count; i++) {
if (check_bit_flag(sources[i], data_size, data_flag)) {
tot_weight_true += weights[i];
item_true_idx = i;
}
else {
item_false_idx = i;
}
}
best_src_idx = (tot_weight_true >= 0.5f) ? item_true_idx : item_false_idx;
}
else {
/* We just choose highest weighted source. */
float max_weight = 0.0f;
2020-09-09 15:43:09 +02:00
for (int i = 0; i < count; i++) {
if (weights[i] > max_weight) {
max_weight = weights[i];
best_src_idx = i;
}
}
}
}
BLI_assert(best_src_idx >= 0);
if (interp_cd) {
interp_cd(sources, weights, nullptr, count, tmp_dst);
}
else if (data_flag) {
copy_bit_flag(tmp_dst, sources[best_src_idx], data_size, data_flag);
}
/* No interpolation, just copy highest weight source element's data. */
else if (copy_cd) {
copy_cd(sources[best_src_idx], tmp_dst, 1);
}
else {
memcpy(tmp_dst, sources[best_src_idx], data_size);
}
if (data_flag) {
/* Bool flags, only copy if dest data is set (resp. unset) -
* only 'advanced' modes we can support here! */
if (mix_factor >= 0.5f && ((mix_mode == CDT_MIX_TRANSFER) ||
(mix_mode == CDT_MIX_REPLACE_ABOVE_THRESHOLD &&
check_bit_flag(data_dst, data_size, data_flag)) ||
(mix_mode == CDT_MIX_REPLACE_BELOW_THRESHOLD &&
!check_bit_flag(data_dst, data_size, data_flag)))) {
copy_bit_flag(data_dst, tmp_dst, data_size, data_flag);
}
}
else if (!(data_type & CD_FAKE)) {
CustomData_data_mix_value(data_type, tmp_dst, data_dst, mix_mode, mix_factor);
}
/* Else we can do nothing by default, needs custom interp func!
* Note this is here only for sake of consistency, not expected to be used much actually? */
else {
if (mix_factor >= 0.5f) {
memcpy(data_dst, tmp_dst, data_size);
}
}
MEM_freeN(tmp_dst);
}
void customdata_data_transfer_interp_normal_normals(const CustomDataTransferLayerMap *laymap,
void *data_dst,
const void **sources,
const float *weights,
const int count,
const float mix_factor)
{
BLI_assert(weights != nullptr);
BLI_assert(count > 0);
const int data_type = laymap->data_type;
const int mix_mode = laymap->mix_mode;
SpaceTransform *space_transform = static_cast<SpaceTransform *>(laymap->interp_data);
const LayerTypeInfo *type_info = layerType_getInfo(data_type);
cd_interp interp_cd = type_info->interp;
float tmp_dst[3];
BLI_assert(data_type == CD_NORMAL);
if (!sources) {
/* Not supported here, abort. */
return;
}
interp_cd(sources, weights, nullptr, count, tmp_dst);
if (space_transform) {
/* tmp_dst is in source space so far, bring it back in destination space. */
BLI_space_transform_invert_normal(space_transform, tmp_dst);
}
CustomData_data_mix_value(data_type, tmp_dst, data_dst, mix_mode, mix_factor);
}
void CustomData_data_transfer(const MeshPairRemap *me_remap,
const CustomDataTransferLayerMap *laymap)
{
MeshPairRemapItem *mapit = me_remap->items;
const int totelem = me_remap->items_num;
const int data_type = laymap->data_type;
const void *data_src = laymap->data_src;
void *data_dst = laymap->data_dst;
size_t data_step;
size_t data_size;
size_t data_offset;
cd_datatransfer_interp interp = nullptr;
size_t tmp_buff_size = 32;
const void **tmp_data_src = nullptr;
/* NOTE: null data_src may happen and be valid (see vgroups...). */
if (!data_dst) {
return;
}
if (data_src) {
tmp_data_src = (const void **)MEM_malloc_arrayN(
tmp_buff_size, sizeof(*tmp_data_src), __func__);
}
if (data_type & CD_FAKE) {
data_step = laymap->elem_size;
data_size = laymap->data_size;
data_offset = laymap->data_offset;
}
else {
const LayerTypeInfo *type_info = layerType_getInfo(data_type);
/* NOTE: we can use 'fake' CDLayers, like e.g. for crease, bweight, etc. :/. */
data_size = (size_t)type_info->size;
data_step = laymap->elem_size ? laymap->elem_size : data_size;
data_offset = laymap->data_offset;
}
interp = laymap->interp ? laymap->interp : customdata_data_transfer_interp_generic;
2020-09-09 15:43:09 +02:00
for (int i = 0; i < totelem; i++, data_dst = POINTER_OFFSET(data_dst, data_step), mapit++) {
const int sources_num = mapit->sources_num;
const float mix_factor = laymap->mix_factor *
(laymap->mix_weights ? laymap->mix_weights[i] : 1.0f);
if (!sources_num) {
/* No sources for this element, skip it. */
continue;
}
if (tmp_data_src) {
if (UNLIKELY(sources_num > tmp_buff_size)) {
tmp_buff_size = (size_t)sources_num;
tmp_data_src = (const void **)MEM_reallocN((void *)tmp_data_src,
sizeof(*tmp_data_src) * tmp_buff_size);
}
2020-09-09 15:43:09 +02:00
for (int j = 0; j < sources_num; j++) {
const size_t src_idx = (size_t)mapit->indices_src[j];
tmp_data_src[j] = POINTER_OFFSET(data_src, (data_step * src_idx) + data_offset);
}
}
interp(laymap,
POINTER_OFFSET(data_dst, data_offset),
tmp_data_src,
mapit->weights_src,
sources_num,
mix_factor);
}
MEM_SAFE_FREE(tmp_data_src);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Custom Data IO
* \{ */
2022-05-22 20:06:24 +02:00
static void write_mdisps(BlendWriter *writer, int count, const MDisps *mdlist, int external)
{
if (mdlist) {
BLO_write_struct_array(writer, MDisps, count, mdlist);
for (int i = 0; i < count; i++) {
const MDisps *md = &mdlist[i];
if (md->disps) {
if (!external) {
BLO_write_float3_array(writer, md->totdisp, &md->disps[0][0]);
}
}
if (md->hidden) {
BLO_write_raw(writer, BLI_BITMAP_SIZE(md->totdisp), md->hidden);
}
}
}
}
2022-05-22 20:06:24 +02:00
static void write_grid_paint_mask(BlendWriter *writer,
int count,
const GridPaintMask *grid_paint_mask)
{
if (grid_paint_mask) {
BLO_write_struct_array(writer, GridPaintMask, count, grid_paint_mask);
for (int i = 0; i < count; i++) {
2022-05-22 20:06:24 +02:00
const GridPaintMask *gpm = &grid_paint_mask[i];
if (gpm->data) {
const int gridsize = BKE_ccg_gridsize(gpm->level);
BLO_write_raw(writer, sizeof(*gpm->data) * gridsize * gridsize, gpm->data);
}
}
}
}
void CustomData_blend_write(BlendWriter *writer,
CustomData *data,
Span<CustomDataLayer> layers_to_write,
int count,
eCustomDataMask cddata_mask,
ID *id)
{
/* write external customdata (not for undo) */
if (data->external && !BLO_write_is_undo(writer)) {
CustomData_external_write(data, id, cddata_mask, count, 0);
}
BLO_write_struct_array_at_address(
writer, CustomDataLayer, data->totlayer, data->layers, layers_to_write.data());
for (const CustomDataLayer &layer : layers_to_write) {
switch (layer.type) {
case CD_MDEFORMVERT:
BKE_defvert_blend_write(writer, count, static_cast<const MDeformVert *>(layer.data));
break;
case CD_MDISPS:
write_mdisps(
writer, count, static_cast<const MDisps *>(layer.data), layer.flag & CD_FLAG_EXTERNAL);
break;
case CD_PAINT_MASK:
BLO_write_raw(writer, sizeof(float) * count, static_cast<const float *>(layer.data));
break;
case CD_SCULPT_FACE_SETS:
BLO_write_raw(writer, sizeof(float) * count, static_cast<const float *>(layer.data));
break;
case CD_GRID_PAINT_MASK:
write_grid_paint_mask(writer, count, static_cast<const GridPaintMask *>(layer.data));
break;
case CD_FACEMAP:
BLO_write_raw(writer, sizeof(int) * count, static_cast<const int *>(layer.data));
break;
case CD_PROP_BOOL:
BLO_write_raw(writer, sizeof(bool) * count, static_cast<const bool *>(layer.data));
break;
case CD_CREASE:
BLO_write_raw(writer, sizeof(float) * count, static_cast<const float *>(layer.data));
break;
default: {
const char *structname;
int structnum;
CustomData_file_write_info(layer.type, &structname, &structnum);
if (structnum) {
int datasize = structnum * count;
BLO_write_struct_array_by_name(writer, structname, datasize, layer.data);
}
else if (!BLO_write_is_undo(writer)) { /* Do not warn on undo. */
printf("%s error: layer '%s':%d - can't be written to file\n",
__func__,
structname,
layer.type);
}
}
}
}
if (data->external) {
BLO_write_struct(writer, CustomDataExternal, data->external);
}
}
static void blend_read_mdisps(BlendDataReader *reader, int count, MDisps *mdisps, int external)
{
if (mdisps) {
for (int i = 0; i < count; i++) {
BLO_read_data_address(reader, &mdisps[i].disps);
BLO_read_data_address(reader, &mdisps[i].hidden);
if (mdisps[i].totdisp && !mdisps[i].level) {
/* this calculation is only correct for loop mdisps;
* if loading pre-BMesh face mdisps this will be
* overwritten with the correct value in
* bm_corners_to_loops() */
float gridsize = sqrtf(mdisps[i].totdisp);
mdisps[i].level = (int)(logf(gridsize - 1.0f) / (float)M_LN2) + 1;
}
if (BLO_read_requires_endian_switch(reader) && (mdisps[i].disps)) {
/* DNA_struct_switch_endian doesn't do endian swap for (*disps)[] */
/* this does swap for data written at write_mdisps() - readfile.c */
BLI_endian_switch_float_array(*mdisps[i].disps, mdisps[i].totdisp * 3);
}
if (!external && !mdisps[i].disps) {
mdisps[i].totdisp = 0;
}
}
}
}
static void blend_read_paint_mask(BlendDataReader *reader,
int count,
GridPaintMask *grid_paint_mask)
{
if (grid_paint_mask) {
for (int i = 0; i < count; i++) {
GridPaintMask *gpm = &grid_paint_mask[i];
if (gpm->data) {
BLO_read_data_address(reader, &gpm->data);
}
}
}
}
void CustomData_blend_read(BlendDataReader *reader, CustomData *data, int count)
{
BLO_read_data_address(reader, &data->layers);
/* Annoying workaround for bug T31079 loading legacy files with
* no polygons _but_ have stale custom-data. */
if (UNLIKELY(count == 0 && data->layers == nullptr && data->totlayer != 0)) {
CustomData_reset(data);
return;
}
BLO_read_data_address(reader, &data->external);
int i = 0;
while (i < data->totlayer) {
CustomDataLayer *layer = &data->layers[i];
if (layer->flag & CD_FLAG_EXTERNAL) {
layer->flag &= ~CD_FLAG_IN_MEMORY;
}
layer->flag &= ~CD_FLAG_NOFREE;
if (CustomData_verify_versions(data, i)) {
BLO_read_data_address(reader, &layer->data);
if (layer->data == nullptr && count > 0 && layer->type == CD_PROP_BOOL) {
/* Usually this should never happen, except when a custom data layer has not been written
* to a file correctly. */
CLOG_WARN(&LOG, "Reallocating custom data layer that was not saved correctly.");
const LayerTypeInfo *info = layerType_getInfo(layer->type);
layer->data = MEM_calloc_arrayN((size_t)count, info->size, layerType_getName(layer->type));
if (info->set_default) {
info->set_default(layer->data, count);
}
}
if (layer->type == CD_MDISPS) {
blend_read_mdisps(
reader, count, static_cast<MDisps *>(layer->data), layer->flag & CD_FLAG_EXTERNAL);
}
else if (layer->type == CD_GRID_PAINT_MASK) {
blend_read_paint_mask(reader, count, static_cast<GridPaintMask *>(layer->data));
}
i++;
}
}
/* Ensure allocated size is set to the size of the read array. While this should always be the
* case (see #CustomData_blend_write_prepare), there can be some corruption in rare cases (e.g.
* files saved between ff3d535bc2a63092 and 945f32e66d6ada2a). */
data->maxlayer = data->totlayer;
CustomData_update_typemap(data);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Custom Data Debugging
* \{ */
#ifndef NDEBUG
void CustomData_debug_info_from_layers(const CustomData *data, const char *indent, DynStr *dynstr)
{
for (int type = 0; type < CD_NUMTYPES; type++) {
if (CustomData_has_layer(data, type)) {
/* NOTE: doesn't account for multiple layers. */
const char *name = CustomData_layertype_name(type);
const int size = CustomData_sizeof(type);
const void *pt = CustomData_get_layer(data, type);
const int pt_size = pt ? (int)(MEM_allocN_len(pt) / size) : 0;
const char *structname;
int structnum;
CustomData_file_write_info(type, &structname, &structnum);
BLI_dynstr_appendf(
dynstr,
"%sdict(name='%s', struct='%s', type=%d, ptr='%p', elem=%d, length=%d),\n",
indent,
name,
structname,
type,
(const void *)pt,
size,
pt_size);
}
}
}
#endif /* NDEBUG */
/** \} */
namespace blender::bke {
/* -------------------------------------------------------------------- */
/** \name Custom Data C++ API
* \{ */
const blender::CPPType *custom_data_type_to_cpp_type(const eCustomDataType type)
{
switch (type) {
case CD_PROP_FLOAT:
return &CPPType::get<float>();
case CD_PROP_FLOAT2:
return &CPPType::get<float2>();
case CD_PROP_FLOAT3:
return &CPPType::get<float3>();
case CD_PROP_INT32:
return &CPPType::get<int>();
case CD_PROP_COLOR:
return &CPPType::get<ColorGeometry4f>();
case CD_PROP_BOOL:
return &CPPType::get<bool>();
case CD_PROP_INT8:
return &CPPType::get<int8_t>();
case CD_PROP_BYTE_COLOR:
return &CPPType::get<ColorGeometry4b>();
default:
return nullptr;
}
return nullptr;
}
eCustomDataType cpp_type_to_custom_data_type(const blender::CPPType &type)
{
if (type.is<float>()) {
return CD_PROP_FLOAT;
}
if (type.is<float2>()) {
return CD_PROP_FLOAT2;
}
if (type.is<float3>()) {
return CD_PROP_FLOAT3;
}
if (type.is<int>()) {
return CD_PROP_INT32;
}
if (type.is<ColorGeometry4f>()) {
return CD_PROP_COLOR;
}
if (type.is<bool>()) {
return CD_PROP_BOOL;
}
if (type.is<int8_t>()) {
return CD_PROP_INT8;
}
if (type.is<ColorGeometry4b>()) {
return CD_PROP_BYTE_COLOR;
}
return static_cast<eCustomDataType>(-1);
}
/** \} */
} // namespace blender::bke