Mesh: Move UV layers to generic attributes

Currently the `MLoopUV` struct stores UV coordinates and flags related
to editing UV maps in the UV editor. This patch changes the coordinates
to use the generic 2D vector type, and moves the flags into three
separate boolean attributes. This follows the design in T95965, with
the ultimate intention of simplifying code and improving performance.

Importantly, the change allows exporters and renderers to use UVs
"touched" by geometry nodes, which only creates generic attributes.
It also allows geometry nodes to create "proper" UV maps from scratch,
though only with the Store Named Attribute node for now.

The new design considers any 2D vector attribute on the corner domain
to be a UV map. In the future, they might be distinguished from regular
2D vectors with attribute metadata, which may be helpful because they
are often interpolated differently.

Most of the code changes deal with passing around UV BMesh custom data
offsets and tracking the boolean "sublayers". The boolean layers are
use the following prefixes for attribute names: vert selection: `.vs.`,
edge selection: `.es.`, pinning: `.pn.`. Currently these are short to
avoid using up the maximum length of attribute names. To accommodate
for these 4 extra characters, the name length limit is enlarged to 68
bytes, while the maximum user settable name length is still 64 bytes.

Unfortunately Python/RNA API access to the UV flag data becomes slower.
Accessing the boolean layers directly is be better for performance in
general.

Like the other mesh SoA refactors, backward and forward compatibility
aren't affected, and won't be changed until 4.0. We pay for that by
making mesh reading and writing more expensive with conversions.

Resolves T85962

Differential Revision: https://developer.blender.org/D14365
This commit is contained in:
Martijn Versteegh
2023-01-10 00:47:04 -05:00
committed by Hans Goudey
parent 6ef8db35e7
commit 6c774feba2
150 changed files with 3111 additions and 2437 deletions
@@ -607,7 +607,6 @@ class DATA_PT_mesh_attributes(MeshButtonsPanel, Panel):
# Built-in names.
{"shade_smooth": None, "normal": None, "crease": None},
mesh.attributes,
mesh.uv_layers,
None if ob is None else ob.vertex_groups,
):
if collection is None:
@@ -131,6 +131,10 @@ struct CustomDataLayer *BKE_id_attributes_color_find(const struct ID *id, const
bool BKE_id_attribute_calc_unique_name(struct ID *id, const char *name, char *outname);
const char *BKE_uv_map_vert_select_name_get(const char *uv_map_name, char *buffer);
const char *BKE_uv_map_edge_select_name_get(const char *uv_map_name, char *buffer);
const char *BKE_uv_map_pin_name_get(const char *uv_map_name, char *buffer);
#ifdef __cplusplus
}
#endif
+34 -3
View File
@@ -31,6 +31,28 @@ struct CustomData_MeshMasks;
struct ID;
typedef uint64_t eCustomDataMask;
/* These names are used as prefixes for UV layer names to find the associated boolean
* layers. They should never be longer than 2 chars, as MAX_CUSTOMDATA_LAYER_NAME
* has 4 extra bytes above what can be used for the base layer name, and these
* prefixes are placed between 2 '.'s at the start of the layer name.
* For example The uv vert selection layer of a layer named 'UVMap.001'
* will be called '.vs.UVMap.001' . */
#define UV_VERTSEL_NAME "vs"
#define UV_EDGESEL_NAME "es"
#define UV_PINNED_NAME "pn"
/**
* UV map related customdata offsets into BMesh attribute blocks. See #BM_uv_map_get_offsets.
* Defined in #BKE_customdata.h to avoid including bmesh.h in many unrelated areas.
* An offset of -1 means that the corresponding layer does not exist.
*/
typedef struct BMUVOffsets {
int uv;
int select_vert;
int select_edge;
int pin;
} BMUVOffsets;
/* A data type large enough to hold 1 element from any custom-data layer type. */
typedef struct {
unsigned char data[64];
@@ -125,7 +147,7 @@ void CustomData_data_mix_value(
/**
* Compares if data1 is equal to data2. type is a valid CustomData type
* enum (e.g. #CD_MLOOPUV). the layer type's equal function is used to compare
* enum (e.g. #CD_PROP_FLOAT). the layer type's equal function is used to compare
* the data, if it exists, otherwise #memcmp is used.
*/
bool CustomData_data_equals(int type, const void *data1, const void *data2);
@@ -422,6 +444,7 @@ int CustomData_get_n_offset(const struct CustomData *data, int type, int n);
int CustomData_get_layer_index(const struct CustomData *data, int type);
int CustomData_get_layer_index_n(const struct CustomData *data, int type, int n);
int CustomData_get_named_layer_index(const struct CustomData *data, int type, const char *name);
int CustomData_get_named_layer_index_notype(const struct CustomData *data, const char *name);
int CustomData_get_active_layer_index(const struct CustomData *data, int type);
int CustomData_get_render_layer_index(const struct CustomData *data, int type);
int CustomData_get_clone_layer_index(const struct CustomData *data, int type);
@@ -531,6 +554,13 @@ bool CustomData_layertype_is_dynamic(int type);
*/
int CustomData_layertype_layers_max(int type);
#ifdef __cplusplus
/** \return The maximum length for a layer name with the given prefix. */
int CustomData_name_max_length_calc(blender::StringRef name);
#endif
/**
* Make sure the name of layer at index is unique.
*/
@@ -604,8 +634,9 @@ enum {
CD_FAKE_SEAM = CD_FAKE | 100, /* UV seam flag for edges. */
/* Multiple types of mesh elements... */
CD_FAKE_UV = CD_FAKE |
CD_MLOOPUV, /* UV flag, because we handle both loop's UVs and poly's textures. */
CD_FAKE_UV =
CD_FAKE |
CD_PROP_FLOAT2, /* UV flag, because we handle both loop's UVs and poly's textures. */
CD_FAKE_LNOR = CD_FAKE |
CD_CUSTOMLOOPNORMAL, /* Because we play with clnor and temp lnor layers here. */
@@ -9,6 +9,7 @@
#ifdef __cplusplus
extern "C" {
#endif
#include "DNA_customdata_types.h"
/**
* \see #BKE_mesh_calc_loop_tangent, same logic but used arrays instead of #BMesh data.
@@ -19,7 +20,7 @@ extern "C" {
*/
void BKE_editmesh_loop_tangent_calc(BMEditMesh *em,
bool calc_active_tangent,
const char (*tangent_names)[MAX_NAME],
const char (*tangent_names)[MAX_CUSTOMDATA_LAYER_NAME],
int tangent_names_len,
const float (*poly_normals)[3],
const float (*loop_normals)[3],
-2
View File
@@ -36,7 +36,6 @@ struct MEdge;
struct MFace;
struct MLoop;
struct MLoopTri;
struct MLoopUV;
struct MPoly;
struct Main;
struct MemArena;
@@ -693,7 +692,6 @@ float BKE_mesh_calc_poly_area(const struct MPoly *mpoly,
const struct MLoop *loopstart,
const float (*vert_positions)[3]);
float BKE_mesh_calc_area(const struct Mesh *me);
float BKE_mesh_calc_poly_uv_area(const struct MPoly *mpoly, const struct MLoopUV *uv_array);
void BKE_mesh_calc_poly_angles(const struct MPoly *mpoly,
const struct MLoop *loopstart,
const float (*vert_positions)[3],
@@ -26,6 +26,11 @@ struct MFace;
#ifdef __cplusplus
void BKE_mesh_legacy_convert_uvs_to_struct(Mesh *mesh,
blender::ResourceScope &temp_mloopuv_for_convert,
blender::Vector<CustomDataLayer, 16> &layers_to_write);
void BKE_mesh_legacy_convert_uvs_to_generic(Mesh *mesh);
/**
* Move face sets to the legacy type from a generic type.
*/
+3 -4
View File
@@ -17,7 +17,6 @@ extern "C" {
struct MEdge;
struct MLoop;
struct MLoopTri;
struct MLoopUV;
struct MPoly;
/* UvVertMap */
@@ -105,7 +104,7 @@ UvVertMap *BKE_mesh_uv_vert_map_create(const struct MPoly *mpoly,
const bool *hide_poly,
const bool *select_poly,
const struct MLoop *mloop,
const struct MLoopUV *mloopuv,
const float (*mloopuv)[2],
unsigned int totpoly,
unsigned int totvert,
const float limit[2],
@@ -288,7 +287,7 @@ bool BKE_mesh_calc_islands_loop_poly_edgeseam(const float (*vert_positions)[3],
/**
* Calculate UV islands.
*
* \note If no MLoopUV layer is passed, we only consider edges tagged as seams as UV boundaries.
* \note If no UV layer is passed, we only consider edges tagged as seams as UV boundaries.
* This has the advantages of simplicity, and being valid/common to all UV maps.
* However, it means actual UV islands without matching UV seams will not be handled correctly.
* If a valid UV layer is passed as \a luvs parameter,
@@ -306,7 +305,7 @@ bool BKE_mesh_calc_islands_loop_poly_uvmap(float (*vert_positions)[3],
int totpoly,
struct MLoop *loops,
int totloop,
const struct MLoopUV *luvs,
const float (*luvs)[2],
MeshIslandStore *r_island_store);
/**
+4 -4
View File
@@ -22,7 +22,7 @@ void BKE_mesh_calc_loop_tangent_single_ex(const float (*vert_positions)[3],
const struct MLoop *mloops,
float (*r_looptangent)[4],
const float (*loop_normals)[3],
const struct MLoopUV *loopuv,
const float (*loopuv)[2],
int numLoops,
const struct MPoly *mpolys,
int numPolys,
@@ -50,7 +50,7 @@ void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3],
struct CustomData *loopdata,
bool calc_active_tangent,
const char (*tangent_names)[64],
const char (*tangent_names)[MAX_CUSTOMDATA_LAYER_NAME],
int tangent_names_len,
const float (*vert_normals)[3],
const float (*poly_normals)[3],
@@ -63,7 +63,7 @@ void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3],
void BKE_mesh_calc_loop_tangents(struct Mesh *me_eval,
bool calc_active_tangent,
const char (*tangent_names)[MAX_NAME],
const char (*tangent_names)[MAX_CUSTOMDATA_LAYER_NAME],
int tangent_names_len);
/* Helpers */
@@ -81,7 +81,7 @@ void BKE_mesh_add_loop_tangent_named_layer_for_uv(struct CustomData *uv_data,
*/
void BKE_mesh_calc_loop_tangent_step_0(const struct CustomData *loopData,
bool calc_active_tangent,
const char (*tangent_names)[64],
const char (*tangent_names)[MAX_CUSTOMDATA_LAYER_NAME],
int tangent_names_count,
bool *rcalc_act,
bool *rcalc_ren,
@@ -1690,7 +1690,7 @@ static void object_get_datamask(const Depsgraph *depsgraph,
/* check if we need tfaces & mcols due to face select or texture paint */
if ((ob->mode & OB_MODE_TEXTURE_PAINT) || editing) {
r_mask->lmask |= CD_MASK_MLOOPUV | CD_MASK_PROP_BYTE_COLOR;
r_mask->lmask |= CD_MASK_PROP_FLOAT2 | CD_MASK_PROP_BYTE_COLOR;
r_mask->fmask |= CD_MASK_MTFACE;
}
+136 -8
View File
@@ -141,6 +141,19 @@ bool BKE_attribute_allow_procedural_access(const char *attribute_name)
return blender::bke::allow_procedural_attribute_access(attribute_name);
}
static bool bke_id_attribute_rename_if_exists(ID *id,
const char *old_name,
const char *new_name,
ReportList *reports)
{
CustomDataLayer *layer = BKE_id_attribute_search(
id, old_name, CD_MASK_PROP_ALL, ATTR_DOMAIN_MASK_ALL);
if (layer == nullptr) {
return false;
}
return BKE_id_attribute_rename(id, old_name, new_name, reports);
}
bool BKE_id_attribute_rename(ID *id,
const char *old_name,
const char *new_name,
@@ -155,8 +168,18 @@ bool BKE_id_attribute_rename(ID *id,
BKE_report(reports, RPT_ERROR, "Attribute name can not be empty");
return false;
}
if (STREQ(old_name, new_name)) {
return false;
/* NOTE: Checking if the new name matches the old name only makes sense when the name
* is clamped to it's maximum length, otherwise assigning an over-long name multiple times
* will add `.001` suffix unnecessarily. */
{
const int maxlength = CustomData_name_max_length_calc(new_name);
/* NOTE: A function that performs a clamped comparison without copying would be handy here. */
char new_name_clamped[MAX_CUSTOMDATA_LAYER_NAME];
BLI_strncpy_utf8(new_name_clamped, new_name, maxlength);
if (STREQ(old_name, new_name_clamped)) {
return false;
}
}
CustomDataLayer *layer = BKE_id_attribute_search(
@@ -169,6 +192,24 @@ bool BKE_id_attribute_rename(ID *id,
char result_name[MAX_CUSTOMDATA_LAYER_NAME];
BKE_id_attribute_calc_unique_name(id, new_name, result_name);
if (layer->type == CD_PROP_FLOAT2 && GS(id->name) == ID_ME) {
/* Rename UV sub-attributes. */
char buffer_src[MAX_CUSTOMDATA_LAYER_NAME];
char buffer_dst[MAX_CUSTOMDATA_LAYER_NAME];
bke_id_attribute_rename_if_exists(id,
BKE_uv_map_vert_select_name_get(layer->name, buffer_src),
BKE_uv_map_vert_select_name_get(result_name, buffer_dst),
reports);
bke_id_attribute_rename_if_exists(id,
BKE_uv_map_edge_select_name_get(layer->name, buffer_src),
BKE_uv_map_edge_select_name_get(result_name, buffer_dst),
reports);
bke_id_attribute_rename_if_exists(id,
BKE_uv_map_pin_name_get(layer->name, buffer_src),
BKE_uv_map_pin_name_get(result_name, buffer_dst),
reports);
}
if (StringRef(old_name) == BKE_id_attributes_active_color_name(id)) {
BKE_id_attributes_active_color_set(id, result_name);
}
@@ -213,18 +254,18 @@ static bool unique_name_cb(void *arg, const char *name)
bool BKE_id_attribute_calc_unique_name(ID *id, const char *name, char *outname)
{
AttrUniqueData data{id};
const int maxlength = CustomData_name_max_length_calc(name);
/* Set default name if none specified.
* NOTE: We only call IFACE_() if needed to avoid locale lookup overhead. */
if (!name || name[0] == '\0') {
BLI_strncpy(outname, IFACE_("Attribute"), MAX_CUSTOMDATA_LAYER_NAME);
BLI_strncpy(outname, IFACE_("Attribute"), maxlength);
}
else {
BLI_strncpy_utf8(outname, name, MAX_CUSTOMDATA_LAYER_NAME);
BLI_strncpy_utf8(outname, name, maxlength);
}
return BLI_uniquename_cb(
unique_name_cb, &data, nullptr, '.', outname, MAX_CUSTOMDATA_LAYER_NAME);
return BLI_uniquename_cb(unique_name_cb, &data, nullptr, '.', outname, maxlength);
}
CustomDataLayer *BKE_id_attribute_new(
@@ -263,6 +304,24 @@ CustomDataLayer *BKE_id_attribute_new(
return (index == -1) ? nullptr : &(customdata->layers[index]);
}
static void bke_id_attribute_copy_if_exists(ID *id, const char *srcname, const char *dstname)
{
using namespace blender::bke;
std::optional<MutableAttributeAccessor> attributes = get_attribute_accessor_for_write(*id);
if (!attributes) {
return;
}
GAttributeReader src = attributes->lookup(srcname);
if (!src) {
return;
}
const eCustomDataType type = cpp_type_to_custom_data_type(src.varray.type());
attributes->add(dstname, src.domain, type, AttributeInitVArray(src.varray));
}
CustomDataLayer *BKE_id_attribute_duplicate(ID *id, const char *name, ReportList *reports)
{
using namespace blender::bke;
@@ -292,6 +351,22 @@ CustomDataLayer *BKE_id_attribute_duplicate(ID *id, const char *name, ReportList
const eCustomDataType type = cpp_type_to_custom_data_type(src.varray.type());
attributes->add(uniquename, src.domain, type, AttributeInitVArray(src.varray));
if (GS(id->name) == ID_ME && type == CD_PROP_FLOAT2) {
/* Duplicate UV sub-attributes. */
char buffer_src[MAX_CUSTOMDATA_LAYER_NAME];
char buffer_dst[MAX_CUSTOMDATA_LAYER_NAME];
bke_id_attribute_copy_if_exists(id,
BKE_uv_map_vert_select_name_get(name, buffer_src),
BKE_uv_map_vert_select_name_get(uniquename, buffer_dst));
bke_id_attribute_copy_if_exists(id,
BKE_uv_map_edge_select_name_get(name, buffer_src),
BKE_uv_map_edge_select_name_get(uniquename, buffer_dst));
bke_id_attribute_copy_if_exists(id,
BKE_uv_map_pin_name_get(name, buffer_src),
BKE_uv_map_pin_name_get(uniquename, buffer_dst));
}
return BKE_id_attribute_search(id, uniquename, CD_MASK_PROP_ALL, ATTR_DOMAIN_MASK_ALL);
}
@@ -316,11 +391,27 @@ bool BKE_id_attribute_remove(ID *id, const char *name, ReportList *reports)
if (BMEditMesh *em = mesh->edit_mesh) {
for (const int domain : IndexRange(ATTR_DOMAIN_NUM)) {
if (CustomData *data = info[domain].customdata) {
int layer_index = CustomData_get_named_layer_index_notype(data, name);
if (layer_index >= 0) {
if (data->layers[layer_index].type == CD_PROP_FLOAT2) {
/* free associated UV map bool layers */
char buffer_src[MAX_CUSTOMDATA_LAYER_NAME];
BM_data_layer_free_named(
em->bm, data, BKE_uv_map_vert_select_name_get(name, buffer_src));
BM_data_layer_free_named(
em->bm, data, BKE_uv_map_edge_select_name_get(name, buffer_src));
BM_data_layer_free_named(em->bm, data, BKE_uv_map_pin_name_get(name, buffer_src));
}
}
/* Because it's possible that name is owned by the layer and will be freed
* when freeing the layer, do these checks before freeing. */
const bool is_active_color_attribute = name == StringRef(mesh->active_color_attribute);
const bool is_default_color_attribute = name == StringRef(mesh->default_color_attribute);
if (BM_data_layer_free_named(em->bm, data, name)) {
if (name == StringRef(mesh->active_color_attribute)) {
if (is_active_color_attribute) {
MEM_SAFE_FREE(mesh->active_color_attribute);
}
else if (name == StringRef(mesh->default_color_attribute)) {
else if (is_default_color_attribute) {
MEM_SAFE_FREE(mesh->default_color_attribute);
}
return true;
@@ -332,10 +423,23 @@ bool BKE_id_attribute_remove(ID *id, const char *name, ReportList *reports)
}
std::optional<MutableAttributeAccessor> attributes = get_attribute_accessor_for_write(*id);
if (!attributes) {
return false;
}
if (GS(id->name) == ID_ME) {
std::optional<blender::bke::AttributeMetaData> metadata = attributes->lookup_meta_data(name);
if (metadata->data_type == CD_PROP_FLOAT2) {
/* remove UV sub-attributes. */
char buffer_src[MAX_CUSTOMDATA_LAYER_NAME];
BKE_id_attribute_remove(id, BKE_uv_map_vert_select_name_get(name, buffer_src), reports);
BKE_id_attribute_remove(id, BKE_uv_map_edge_select_name_get(name, buffer_src), reports);
BKE_id_attribute_remove(id, BKE_uv_map_pin_name_get(name, buffer_src), reports);
}
}
return attributes->remove(name);
}
@@ -784,3 +888,27 @@ void BKE_id_attribute_copy_domains_temp(short id_type,
*((short *)r_id->name) = id_type;
}
const char *BKE_uv_map_vert_select_name_get(const char *uv_map_name, char *buffer)
{
BLI_assert(strlen(UV_VERTSEL_NAME) == 2);
BLI_assert(strlen(uv_map_name) < MAX_CUSTOMDATA_LAYER_NAME - 4);
BLI_snprintf(buffer, MAX_CUSTOMDATA_LAYER_NAME, ".%s.%s", UV_VERTSEL_NAME, uv_map_name);
return buffer;
}
const char *BKE_uv_map_edge_select_name_get(const char *uv_map_name, char *buffer)
{
BLI_assert(strlen(UV_EDGESEL_NAME) == 2);
BLI_assert(strlen(uv_map_name) < MAX_CUSTOMDATA_LAYER_NAME - 4);
BLI_snprintf(buffer, MAX_CUSTOMDATA_LAYER_NAME, ".%s.%s", UV_EDGESEL_NAME, uv_map_name);
return buffer;
}
const char *BKE_uv_map_pin_name_get(const char *uv_map_name, char *buffer)
{
BLI_assert(strlen(UV_PINNED_NAME) == 2);
BLI_assert(strlen(uv_map_name) < MAX_CUSTOMDATA_LAYER_NAME - 4);
BLI_snprintf(buffer, MAX_CUSTOMDATA_LAYER_NAME, ".%s.%s", UV_PINNED_NAME, uv_map_name);
return buffer;
}
@@ -54,8 +54,25 @@ const char *no_procedural_access_message =
bool allow_procedural_attribute_access(StringRef attribute_name)
{
return !attribute_name.startswith(".sculpt") && !attribute_name.startswith(".select") &&
!attribute_name.startswith(".hide");
if (attribute_name.startswith(".select")) {
return false;
}
if (attribute_name.startswith(".sculpt")) {
return false;
}
if (attribute_name.startswith(".hide")) {
return false;
}
if (attribute_name.startswith("." UV_VERTSEL_NAME ".")) {
return false;
}
if (attribute_name.startswith("." UV_EDGESEL_NAME ".")) {
return false;
}
if (attribute_name.startswith("." UV_PINNED_NAME ".")) {
return false;
}
return true;
}
static int attribute_data_type_complexity(const eCustomDataType data_type)
@@ -204,7 +221,7 @@ static void *add_generic_custom_data_layer(CustomData &custom_data,
const AttributeIDRef &attribute_id)
{
if (!attribute_id.is_anonymous()) {
char attribute_name_c[MAX_NAME];
char attribute_name_c[MAX_CUSTOMDATA_LAYER_NAME];
attribute_id.name().copy(attribute_name_c);
return CustomData_add_layer_named(
&custom_data, data_type, alloctype, layer_data, domain_num, attribute_name_c);
@@ -522,88 +539,6 @@ bool CustomDataAttributeProvider::foreach_attribute(const void *owner,
return true;
}
GAttributeReader NamedLegacyCustomDataProvider::try_get_for_read(
const void *owner, const AttributeIDRef &attribute_id) const
{
const CustomData *custom_data = custom_data_access_.get_const_custom_data(owner);
if (custom_data == nullptr) {
return {};
}
for (const CustomDataLayer &layer : Span(custom_data->layers, custom_data->totlayer)) {
if (layer.type == stored_type_) {
if (custom_data_layer_matches_attribute_id(layer, attribute_id)) {
const int domain_num = custom_data_access_.get_element_num(owner);
return {as_read_attribute_(layer.data, domain_num), domain_};
}
}
}
return {};
}
GAttributeWriter NamedLegacyCustomDataProvider::try_get_for_write(
void *owner, const AttributeIDRef &attribute_id) const
{
CustomData *custom_data = custom_data_access_.get_custom_data(owner);
if (custom_data == nullptr) {
return {};
}
for (CustomDataLayer &layer : MutableSpan(custom_data->layers, custom_data->totlayer)) {
if (layer.type == stored_type_) {
if (custom_data_layer_matches_attribute_id(layer, attribute_id)) {
const int element_num = custom_data_access_.get_element_num(owner);
void *data = CustomData_duplicate_referenced_layer_named(
custom_data, stored_type_, layer.name, element_num);
return {as_write_attribute_(data, element_num), domain_};
}
}
}
return {};
}
bool NamedLegacyCustomDataProvider::try_delete(void *owner,
const AttributeIDRef &attribute_id) const
{
CustomData *custom_data = custom_data_access_.get_custom_data(owner);
if (custom_data == nullptr) {
return false;
}
for (const int i : IndexRange(custom_data->totlayer)) {
const CustomDataLayer &layer = custom_data->layers[i];
if (layer.type == stored_type_) {
if (custom_data_layer_matches_attribute_id(layer, attribute_id)) {
const int element_num = custom_data_access_.get_element_num(owner);
CustomData_free_layer(custom_data, stored_type_, element_num, i);
return true;
}
}
}
return false;
}
bool NamedLegacyCustomDataProvider::foreach_attribute(
const void *owner, const AttributeForeachCallback callback) const
{
const CustomData *custom_data = custom_data_access_.get_const_custom_data(owner);
if (custom_data == nullptr) {
return true;
}
for (const CustomDataLayer &layer : Span(custom_data->layers, custom_data->totlayer)) {
if (layer.type == stored_type_) {
AttributeMetaData meta_data{domain_, attribute_type_};
if (!callback(layer.name, meta_data)) {
return false;
}
}
}
return true;
}
void NamedLegacyCustomDataProvider::foreach_domain(
const FunctionRef<void(eAttrDomain)> callback) const
{
callback(domain_);
}
CustomDataAttributes::CustomDataAttributes()
{
CustomData_reset(&data);
@@ -170,44 +170,6 @@ class CustomDataAttributeProvider final : public DynamicAttributesProvider {
}
};
/**
* This attribute provider is used for uv maps and vertex colors.
*/
class NamedLegacyCustomDataProvider final : public DynamicAttributesProvider {
private:
using AsReadAttribute = GVArray (*)(const void *data, int domain_num);
using AsWriteAttribute = GVMutableArray (*)(void *data, int domain_num);
const eAttrDomain domain_;
const eCustomDataType attribute_type_;
const eCustomDataType stored_type_;
const CustomDataAccessInfo custom_data_access_;
const AsReadAttribute as_read_attribute_;
const AsWriteAttribute as_write_attribute_;
public:
NamedLegacyCustomDataProvider(const eAttrDomain domain,
const eCustomDataType attribute_type,
const eCustomDataType stored_type,
const CustomDataAccessInfo custom_data_access,
const AsReadAttribute as_read_attribute,
const AsWriteAttribute as_write_attribute)
: domain_(domain),
attribute_type_(attribute_type),
stored_type_(stored_type),
custom_data_access_(custom_data_access),
as_read_attribute_(as_read_attribute),
as_write_attribute_(as_write_attribute)
{
}
GAttributeReader try_get_for_read(const void *owner,
const AttributeIDRef &attribute_id) const final;
GAttributeWriter try_get_for_write(void *owner, const AttributeIDRef &attribute_id) const final;
bool try_delete(void *owner, const AttributeIDRef &attribute_id) const final;
bool foreach_attribute(const void *owner, const AttributeForeachCallback callback) const final;
void foreach_domain(const FunctionRef<void(eAttrDomain)> callback) const final;
};
template<typename T> GVArray make_array_read_attribute(const void *data, const int domain_num)
{
return VArray<T>::ForSpan(Span<T>((const T *)data, domain_num));
+90 -139
View File
@@ -58,6 +58,7 @@
/* only for customdata_data_transfer_interp_normal_normals */
#include "data_transfer_intern.h"
using blender::float2;
using blender::IndexRange;
using blender::Set;
using blender::Span;
@@ -1011,110 +1012,9 @@ static void layerInterp_mloopcol(const void **sources,
/** \} */
/* -------------------------------------------------------------------- */
/** \name Callbacks for (#MLoopUV, #CD_MLOOPUV)
/** \name Callbacks for #OrigSpaceLoop
* \{ */
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, const 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 * /*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;
}
}
/* 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,
@@ -1616,6 +1516,46 @@ static bool layerValidate_propfloat2(void *data, const uint totitems, const bool
return has_errors;
}
static bool layerEqual_propfloat2(const void *data1, const void *data2)
{
const float2 &a = *static_cast<const float2 *>(data1);
const float2 &b = *static_cast<const float2 *>(data2);
return blender::math::distance_squared(a, b) < 0.00001f;
}
static void layerInitMinMax_propfloat2(void *vmin, void *vmax)
{
float2 &min = *static_cast<float2 *>(vmin);
float2 &max = *static_cast<float2 *>(vmax);
INIT_MINMAX2(min, max);
}
static void layerDoMinMax_propfloat2(const void *data, void *vmin, void *vmax)
{
const float2 &value = *static_cast<const float2 *>(data);
float2 &a = *static_cast<float2 *>(vmin);
float2 &b = *static_cast<float2 *>(vmax);
blender::math::min_max(value, a, b);
}
static void layerCopyValue_propfloat2(const void *source,
void *dest,
const int mixmode,
const float mixfactor)
{
const float2 &a = *static_cast<const float2 *>(source);
float2 &b = *static_cast<float2 *>(dest);
/* We only support a limited subset of advanced mixing here-
* namely the mixfactor interpolation. */
if (mixmode == CDT_MIX_NOMIX) {
b = a;
}
else {
b = blender::math::interpolate(b, a, mixfactor);
}
}
/** \} */
/* -------------------------------------------------------------------- */
@@ -1757,28 +1697,8 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
/* 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,
nullptr,
layerValidate_mloopuv,
layerEqual_mloopuv,
layerMultiply_mloopuv,
layerInitMinMax_mloopuv,
layerAdd_mloopuv,
layerDoMinMax_mloopuv,
layerCopyValue_mloopuv,
nullptr,
nullptr,
nullptr,
layerMaxNum_tface},
/* 16: CD_MLOOPUV */ /* DEPRECATED */
{sizeof(MLoopUV), "MLoopUV", 1, N_("UVMap")},
/* 17: CD_PROP_BYTE_COLOR */
{sizeof(MLoopCol),
"MLoopCol",
@@ -2025,10 +1945,12 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
nullptr,
nullptr,
layerValidate_propfloat2,
nullptr,
layerEqual_propfloat2,
layerMultiply_propfloat2,
nullptr,
layerAdd_propfloat2},
layerInitMinMax_propfloat2,
layerAdd_propfloat2,
layerDoMinMax_propfloat2,
layerCopyValue_propfloat2},
/* 50: CD_PROP_BOOL */
{sizeof(bool),
"bool",
@@ -2128,8 +2050,8 @@ const CustomData_MeshMasks CD_MASK_MESH = {
/* pmask */
(CD_MASK_MPOLY | CD_MASK_FACEMAP | CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL),
/* lmask */
(CD_MASK_MLOOP | CD_MASK_MDISPS | CD_MASK_MLOOPUV | CD_MASK_CUSTOMLOOPNORMAL |
CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL),
(CD_MASK_MLOOP | CD_MASK_MDISPS | 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 |
@@ -2142,8 +2064,8 @@ const CustomData_MeshMasks CD_MASK_DERIVEDMESH = {
/* pmask */
(CD_MASK_ORIGINDEX | CD_MASK_FREESTYLE_FACE | CD_MASK_FACEMAP | CD_MASK_PROP_ALL),
/* lmask */
(CD_MASK_MLOOPUV | CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_PREVIEW_MLOOPCOL |
CD_MASK_ORIGSPACE_MLOOP | CD_MASK_PROP_ALL), /* XXX MISSING CD_MASK_MLOOPTANGENT ? */
(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 |
@@ -2153,8 +2075,7 @@ const CustomData_MeshMasks CD_MASK_BMESH = {
/* pmask */
(CD_MASK_FREESTYLE_FACE | CD_MASK_FACEMAP | CD_MASK_PROP_ALL),
/* lmask */
(CD_MASK_MDISPS | CD_MASK_MLOOPUV | CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_GRID_PAINT_MASK |
CD_MASK_PROP_ALL),
(CD_MASK_MDISPS | CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL),
};
const CustomData_MeshMasks CD_MASK_EVERYTHING = {
/* vmask */ (CD_MASK_BM_ELEM_PYPTR | CD_MASK_ORIGINDEX | CD_MASK_MDEFORMVERT |
@@ -2172,7 +2093,7 @@ const CustomData_MeshMasks CD_MASK_EVERYTHING = {
(CD_MASK_MPOLY | CD_MASK_BM_ELEM_PYPTR | CD_MASK_ORIGINDEX | CD_MASK_FACEMAP |
CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL),
/* lmask */
(CD_MASK_MLOOP | CD_MASK_BM_ELEM_PYPTR | CD_MASK_MDISPS | CD_MASK_NORMAL | CD_MASK_MLOOPUV |
(CD_MASK_MLOOP | CD_MASK_BM_ELEM_PYPTR | CD_MASK_MDISPS | CD_MASK_NORMAL |
CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_MLOOPTANGENT | CD_MASK_PREVIEW_MLOOPCOL |
CD_MASK_ORIGSPACE_MLOOP | CD_MASK_GRID_PAINT_MASK | CD_MASK_PROP_ALL),
};
@@ -2399,7 +2320,7 @@ CustomData CustomData_shallow_copy_remove_non_bmesh_attributes(const CustomData
CustomData dst = *src;
dst.layers = static_cast<CustomDataLayer *>(
MEM_calloc_arrayN(dst_layers.size(), sizeof(CustomDataLayer), __func__));
dst.totlayer = dst_layers.size();
dst.maxlayer = dst.totlayer = dst_layers.size();
memcpy(dst.layers, dst_layers.data(), dst_layers.as_span().size_in_bytes());
CustomData_update_typemap(&dst);
@@ -2586,6 +2507,17 @@ int CustomData_get_named_layer_index(const CustomData *data, const int type, con
return -1;
}
int CustomData_get_named_layer_index_notype(const CustomData *data, const char *name)
{
for (int i = 0; i < data->totlayer; i++) {
if (STREQ(data->layers[i].name, name)) {
return i;
}
}
return -1;
}
int CustomData_get_active_layer_index(const CustomData *data, const int type)
{
const int layer_index = data->typemap[type];
@@ -4234,6 +4166,9 @@ void CustomData_from_bmesh_block(const CustomData *source,
/* copies a layer at a time */
int dest_i = 0;
for (int src_i = 0; src_i < source->totlayer; src_i++) {
if (source->layers[src_i].flag & CD_FLAG_NOCOPY) {
continue;
}
/* find the first dest layer with type >= the source type
* (this should work because layers are ordered by type)
@@ -4374,6 +4309,20 @@ static bool customdata_unique_check(void *arg, const char *name)
return cd_layer_find_dupe(data_arg->data, name, data_arg->type, data_arg->index);
}
int CustomData_name_max_length_calc(const blender::StringRef name)
{
if (name.startswith(".")) {
return MAX_CUSTOMDATA_LAYER_NAME_NO_PREFIX;
}
for (const blender::StringRef prefix :
{"." UV_VERTSEL_NAME, UV_EDGESEL_NAME ".", UV_PINNED_NAME "."}) {
if (name.startswith(prefix)) {
return MAX_CUSTOMDATA_LAYER_NAME;
}
}
return MAX_CUSTOMDATA_LAYER_NAME_NO_PREFIX;
}
void CustomData_set_layer_unique_name(CustomData *data, const int index)
{
CustomDataLayer *nlayer = &data->layers[index];
@@ -4385,14 +4334,15 @@ void CustomData_set_layer_unique_name(CustomData *data, const int index)
return;
}
const int max_length = CustomData_name_max_length_calc(nlayer->name);
/* 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));
BLI_uniquename_cb(customdata_unique_check, &data_arg, nullptr, '.', nlayer->name, max_length);
}
void CustomData_validate_layer_name(const CustomData *data,
@@ -4477,8 +4427,9 @@ static bool CustomData_layer_ensure_data_exists(CustomDataLayer *layer, size_t c
switch (layer->type) {
/* When more instances of corrupt files are found, add them here. */
case CD_PROP_BOOL: /* See T84935. */
case CD_MLOOPUV: /* See T90620. */
case CD_PROP_BOOL: /* See T84935. */
case CD_MLOOPUV: /* See T90620. */
case CD_PROP_FLOAT2: /* See T90620. */
layer->data = MEM_calloc_arrayN(count, typeInfo->size, layerType_getName(layer->type));
BLI_assert(layer->data);
if (typeInfo->set_default_value) {
@@ -67,7 +67,7 @@ void BKE_object_data_transfer_dttypes_to_cdmask(const int dtdata_types,
r_data_masks->vmask |= CD_MASK_MDEFORMVERT; /* Exception for vgroups :/ */
}
else if (cddata_type == CD_FAKE_UV) {
r_data_masks->lmask |= CD_MASK_MLOOPUV;
r_data_masks->lmask |= CD_MASK_PROP_FLOAT2;
}
else if (cddata_type == CD_FAKE_LNOR) {
r_data_masks->lmask |= CD_MASK_NORMAL | CD_MASK_CUSTOMLOOPNORMAL;
@@ -989,7 +989,7 @@ static bool data_transfer_layersmapping_generate(ListBase *r_map,
}
else if (elem_type == ME_LOOP) {
if (cddata_type == CD_FAKE_UV) {
cddata_type = CD_MLOOPUV;
cddata_type = CD_PROP_FLOAT2;
}
else if (cddata_type == CD_FAKE_LNOR) {
/* Pre-process should have generated it,
@@ -1028,7 +1028,7 @@ static bool data_transfer_layersmapping_generate(ListBase *r_map,
}
else if (elem_type == ME_POLY) {
if (cddata_type == CD_FAKE_UV) {
cddata_type = CD_MLOOPUV;
cddata_type = CD_PROP_FLOAT2;
}
if (!(cddata_type & CD_FAKE)) {
+36 -35
View File
@@ -1468,7 +1468,7 @@ typedef struct DynamicPaintSetInitColorData {
const DynamicPaintSurface *surface;
const MLoop *mloop;
const MLoopUV *mloopuv;
const float (*mloopuv)[2];
const MLoopTri *mlooptri;
const MLoopCol *mloopcol;
struct ImagePool *pool;
@@ -1486,7 +1486,7 @@ static void dynamic_paint_set_init_color_tex_to_vcol_cb(
const MLoop *mloop = data->mloop;
const MLoopTri *mlooptri = data->mlooptri;
const MLoopUV *mloopuv = data->mloopuv;
const float(*mloopuv)[2] = data->mloopuv;
struct ImagePool *pool = data->pool;
Tex *tex = data->surface->init_texture;
@@ -1499,8 +1499,8 @@ static void dynamic_paint_set_init_color_tex_to_vcol_cb(
const uint vert = mloop[mlooptri[i].tri[j]].v;
/* remap to [-1.0, 1.0] */
uv[0] = mloopuv[mlooptri[i].tri[j]].uv[0] * 2.0f - 1.0f;
uv[1] = mloopuv[mlooptri[i].tri[j]].uv[1] * 2.0f - 1.0f;
uv[0] = mloopuv[mlooptri[i].tri[j]][0] * 2.0f - 1.0f;
uv[1] = mloopuv[mlooptri[i].tri[j]][1] * 2.0f - 1.0f;
multitex_ext_safe(tex, uv, &texres, pool, scene_color_manage, false);
@@ -1520,7 +1520,7 @@ static void dynamic_paint_set_init_color_tex_to_imseq_cb(
PaintPoint *pPoint = (PaintPoint *)sData->type_data;
const MLoopTri *mlooptri = data->mlooptri;
const MLoopUV *mloopuv = data->mloopuv;
const float(*mloopuv)[2] = data->mloopuv;
Tex *tex = data->surface->init_texture;
ImgSeqFormatData *f_data = (ImgSeqFormatData *)sData->format_data;
const int samples = (data->surface->flags & MOD_DPAINT_ANTIALIAS) ? 5 : 1;
@@ -1534,7 +1534,7 @@ static void dynamic_paint_set_init_color_tex_to_imseq_cb(
/* collect all uvs */
for (int j = 3; j--;) {
copy_v2_v2(&uv[j * 3], mloopuv[mlooptri[f_data->uv_p[i].tri_index].tri[j]].uv);
copy_v2_v2(&uv[j * 3], mloopuv[mlooptri[f_data->uv_p[i].tri_index].tri[j]]);
}
/* interpolate final uv pos */
@@ -1615,8 +1615,9 @@ static void dynamicPaint_setInitialColor(const Scene *scene, DynamicPaintSurface
}
/* get uv map */
CustomData_validate_layer_name(&mesh->ldata, CD_MLOOPUV, surface->init_layername, uvname);
const MLoopUV *mloopuv = CustomData_get_layer_named(&mesh->ldata, CD_MLOOPUV, uvname);
CustomData_validate_layer_name(&mesh->ldata, CD_PROP_FLOAT2, surface->init_layername, uvname);
const float(*mloopuv)[2] = CustomData_get_layer_named(&mesh->ldata, CD_PROP_FLOAT2, uvname);
if (!mloopuv) {
return;
}
@@ -2178,7 +2179,7 @@ typedef struct DynamicPaintCreateUVSurfaceData {
Vec3f *tempWeights;
const MLoopTri *mlooptri;
const MLoopUV *mloopuv;
const float (*mloopuv)[2];
const MLoop *mloop;
const int tottri;
@@ -2196,7 +2197,7 @@ static void dynamic_paint_create_uv_surface_direct_cb(
Vec3f *tempWeights = data->tempWeights;
const MLoopTri *mlooptri = data->mlooptri;
const MLoopUV *mloopuv = data->mloopuv;
const float(*mloopuv)[2] = data->mloopuv;
const MLoop *mloop = data->mloop;
const int tottri = data->tottri;
@@ -2249,9 +2250,9 @@ static void dynamic_paint_create_uv_surface_direct_cb(
continue;
}
const float *uv1 = mloopuv[mlooptri[i].tri[0]].uv;
const float *uv2 = mloopuv[mlooptri[i].tri[1]].uv;
const float *uv3 = mloopuv[mlooptri[i].tri[2]].uv;
const float *uv1 = mloopuv[mlooptri[i].tri[0]];
const float *uv2 = mloopuv[mlooptri[i].tri[1]];
const float *uv3 = mloopuv[mlooptri[i].tri[2]];
/* If point is inside the face */
if (isect_point_tri_v2(point[sample], uv1, uv2, uv3) != 0) {
@@ -2291,7 +2292,7 @@ static void dynamic_paint_create_uv_surface_neighbor_cb(
Vec3f *tempWeights = data->tempWeights;
const MLoopTri *mlooptri = data->mlooptri;
const MLoopUV *mloopuv = data->mloopuv;
const float(*mloopuv)[2] = data->mloopuv;
const MLoop *mloop = data->mloop;
uint32_t *active_points = data->active_points;
@@ -2332,9 +2333,9 @@ static void dynamic_paint_create_uv_surface_neighbor_cb(
if (tempPoints[ind].neighbor_pixel == -1 && tempPoints[ind].tri_index != -1) {
float uv[2];
const int i = tempPoints[ind].tri_index;
const float *uv1 = mloopuv[mlooptri[i].tri[0]].uv;
const float *uv2 = mloopuv[mlooptri[i].tri[1]].uv;
const float *uv3 = mloopuv[mlooptri[i].tri[2]].uv;
const float *uv1 = mloopuv[mlooptri[i].tri[0]];
const float *uv2 = mloopuv[mlooptri[i].tri[1]];
const float *uv3 = mloopuv[mlooptri[i].tri[2]];
/* tri index */
/* There is a low possibility of actually having a neighbor point which tri is
@@ -2378,7 +2379,7 @@ static void dynamic_paint_create_uv_surface_neighbor_cb(
#undef JITTER_SAMPLES
static float dist_squared_to_looptri_uv_edges(const MLoopTri *mlooptri,
const MLoopUV *mloopuv,
const float (*mloopuv)[2],
int tri_index,
const float point[2])
{
@@ -2389,8 +2390,8 @@ static float dist_squared_to_looptri_uv_edges(const MLoopTri *mlooptri,
for (int i = 0; i < 3; i++) {
const float dist_squared = dist_squared_to_line_segment_v2(
point,
mloopuv[mlooptri[tri_index].tri[(i + 0)]].uv,
mloopuv[mlooptri[tri_index].tri[(i + 1) % 3]].uv);
mloopuv[mlooptri[tri_index].tri[(i + 0)]],
mloopuv[mlooptri[tri_index].tri[(i + 1) % 3]]);
if (dist_squared < min_distance) {
min_distance = dist_squared;
@@ -2503,7 +2504,7 @@ static void dynamic_paint_find_island_border(const DynamicPaintCreateUVSurfaceDa
{
const MLoop *mloop = data->mloop;
const MLoopTri *mlooptri = data->mlooptri;
const MLoopUV *mloopuv = data->mloopuv;
const float(*mloopuv)[2] = data->mloopuv;
const uint *loop_idx = mlooptri[tri_index].tri;
@@ -2516,9 +2517,9 @@ static void dynamic_paint_find_island_border(const DynamicPaintCreateUVSurfaceDa
float uv0[2], uv1[2], uv2[2];
copy_v2_v2(uv0, mloopuv[loop_idx[(edge_idx + 0)]].uv);
copy_v2_v2(uv1, mloopuv[loop_idx[(edge_idx + 1) % 3]].uv);
copy_v2_v2(uv2, mloopuv[loop_idx[(edge_idx + 2) % 3]].uv);
copy_v2_v2(uv0, mloopuv[loop_idx[(edge_idx + 0)]]);
copy_v2_v2(uv1, mloopuv[loop_idx[(edge_idx + 1) % 3]]);
copy_v2_v2(uv2, mloopuv[loop_idx[(edge_idx + 2) % 3]]);
/* Verify the target point is on the opposite side of the edge from the third triangle
* vertex, to ensure that we always move closer to the goal point. */
@@ -2569,13 +2570,13 @@ static void dynamic_paint_find_island_border(const DynamicPaintCreateUVSurfaceDa
/* Allow for swapped vertex order */
if (overt0 == vert0 && overt1 == vert1) {
found_other = true;
copy_v2_v2(ouv0, mloopuv[other_loop_idx[(j + 0)]].uv);
copy_v2_v2(ouv1, mloopuv[other_loop_idx[(j + 1) % 3]].uv);
copy_v2_v2(ouv0, mloopuv[other_loop_idx[(j + 0)]]);
copy_v2_v2(ouv1, mloopuv[other_loop_idx[(j + 1) % 3]]);
}
else if (overt0 == vert1 && overt1 == vert0) {
found_other = true;
copy_v2_v2(ouv1, mloopuv[other_loop_idx[(j + 0)]].uv);
copy_v2_v2(ouv0, mloopuv[other_loop_idx[(j + 1) % 3]].uv);
copy_v2_v2(ouv1, mloopuv[other_loop_idx[(j + 0)]]);
copy_v2_v2(ouv0, mloopuv[other_loop_idx[(j + 1) % 3]]);
}
if (found_other) {
@@ -2798,7 +2799,7 @@ int dynamicPaint_createUVSurface(Scene *scene,
PaintUVPoint *tempPoints = NULL;
Vec3f *tempWeights = NULL;
const MLoopTri *mlooptri = NULL;
const MLoopUV *mloopuv = NULL;
const float(*mloopuv)[2] = NULL;
const MLoop *mloop = NULL;
Bounds2D *faceBB = NULL;
@@ -2819,9 +2820,9 @@ int dynamicPaint_createUVSurface(Scene *scene,
const int tottri = BKE_mesh_runtime_looptri_len(mesh);
/* get uv map */
if (CustomData_has_layer(&mesh->ldata, CD_MLOOPUV)) {
CustomData_validate_layer_name(&mesh->ldata, CD_MLOOPUV, surface->uvlayer_name, uvname);
mloopuv = CustomData_get_layer_named(&mesh->ldata, CD_MLOOPUV, uvname);
if (CustomData_has_layer(&mesh->ldata, CD_PROP_FLOAT2)) {
CustomData_validate_layer_name(&mesh->ldata, CD_PROP_FLOAT2, surface->uvlayer_name, uvname);
mloopuv = CustomData_get_layer_named(&mesh->ldata, CD_PROP_FLOAT2, uvname);
}
/* Check for validity */
@@ -2880,11 +2881,11 @@ int dynamicPaint_createUVSurface(Scene *scene,
if (!error) {
for (int i = 0; i < tottri; i++) {
copy_v2_v2(faceBB[i].min, mloopuv[mlooptri[i].tri[0]].uv);
copy_v2_v2(faceBB[i].max, mloopuv[mlooptri[i].tri[0]].uv);
copy_v2_v2(faceBB[i].min, mloopuv[mlooptri[i].tri[0]]);
copy_v2_v2(faceBB[i].max, mloopuv[mlooptri[i].tri[0]]);
for (int j = 1; j < 3; j++) {
minmax_v2v2_v2(faceBB[i].min, faceBB[i].max, mloopuv[mlooptri[i].tri[j]].uv);
minmax_v2v2_v2(faceBB[i].min, faceBB[i].max, mloopuv[mlooptri[i].tri[j]]);
}
}
@@ -151,7 +151,7 @@ static void emDM_calc_loop_tangents_thread(TaskPool *__restrict /*pool*/, void *
void BKE_editmesh_loop_tangent_calc(BMEditMesh *em,
bool calc_active_tangent,
const char (*tangent_names)[MAX_NAME],
const char (*tangent_names)[MAX_CUSTOMDATA_LAYER_NAME],
int tangent_names_len,
const float (*poly_normals)[3],
const float (*loop_normals)[3],
@@ -254,7 +254,7 @@ void BKE_editmesh_loop_tangent_calc(BMEditMesh *em,
/* NOTE: we assume we do have tessellated loop normals at this point
* (in case it is object-enabled), have to check this is valid. */
mesh2tangent->precomputedLoopNormals = loop_normals;
mesh2tangent->cd_loop_uv_offset = CustomData_get_n_offset(&bm->ldata, CD_MLOOPUV, n);
mesh2tangent->cd_loop_uv_offset = CustomData_get_n_offset(&bm->ldata, CD_PROP_FLOAT2, n);
/* needed for indexing loop-tangents */
int htype_index = BM_LOOP;
@@ -270,8 +270,8 @@ void BKE_editmesh_loop_tangent_calc(BMEditMesh *em,
else {
/* Fill the resulting tangent_mask */
int uv_ind = CustomData_get_named_layer_index(
&bm->ldata, CD_MLOOPUV, loopdata_out->layers[index].name);
int uv_start = CustomData_get_layer_index(&bm->ldata, CD_MLOOPUV);
&bm->ldata, CD_PROP_FLOAT2, loopdata_out->layers[index].name);
int uv_start = CustomData_get_layer_index(&bm->ldata, CD_PROP_FLOAT2);
BLI_assert(uv_ind != -1 && uv_start != -1);
BLI_assert(uv_ind - uv_start < MAX_MTFACE);
tangent_mask_curr |= 1 << (uv_ind - uv_start);
@@ -306,7 +306,7 @@ void BKE_editmesh_loop_tangent_calc(BMEditMesh *em,
*tangent_mask_curr_p = tangent_mask_curr;
int act_uv_index = CustomData_get_layer_index_n(&bm->ldata, CD_MLOOPUV, act_uv_n);
int act_uv_index = CustomData_get_layer_index_n(&bm->ldata, CD_PROP_FLOAT2, act_uv_n);
if (act_uv_index >= 0) {
int tan_index = CustomData_get_named_layer_index(
loopdata_out, CD_TANGENT, bm->ldata.layers[act_uv_index].name);
@@ -314,7 +314,7 @@ void BKE_editmesh_loop_tangent_calc(BMEditMesh *em,
} /* else tangent has been built from orco */
/* Update render layer index */
int ren_uv_index = CustomData_get_layer_index_n(&bm->ldata, CD_MLOOPUV, ren_uv_n);
int ren_uv_index = CustomData_get_layer_index_n(&bm->ldata, CD_PROP_FLOAT2, ren_uv_n);
if (ren_uv_index >= 0) {
int tan_index = CustomData_get_named_layer_index(
loopdata_out, CD_TANGENT, bm->ldata.layers[ren_uv_index].name);
+7 -6
View File
@@ -1789,7 +1789,7 @@ static void sample_mesh(FluidFlowSettings *ffs,
const float (*vert_normals)[3],
const MLoop *mloop,
const MLoopTri *mlooptri,
const MLoopUV *mloopuv,
const float (*mloopuv)[2],
float *influence_map,
float *velocity_map,
int index,
@@ -1909,9 +1909,9 @@ static void sample_mesh(FluidFlowSettings *ffs,
}
else if (mloopuv) {
const float *uv[3];
uv[0] = mloopuv[mlooptri[f_index].tri[0]].uv;
uv[1] = mloopuv[mlooptri[f_index].tri[1]].uv;
uv[2] = mloopuv[mlooptri[f_index].tri[2]].uv;
uv[0] = mloopuv[mlooptri[f_index].tri[0]];
uv[1] = mloopuv[mlooptri[f_index].tri[1]];
uv[2] = mloopuv[mlooptri[f_index].tri[2]];
interp_v2_v2v2v2(tex_co, UNPACK3(uv), weights);
@@ -1984,7 +1984,7 @@ typedef struct EmitFromDMData {
const float (*vert_normals)[3];
const MLoop *mloop;
const MLoopTri *mlooptri;
const MLoopUV *mloopuv;
const float (*mloopuv)[2];
const MDeformVert *dvert;
int defgrp_index;
@@ -2070,7 +2070,8 @@ static void emit_from_mesh(
const MLoopTri *mlooptri = BKE_mesh_runtime_looptri_ensure(me);
const int numverts = me->totvert;
const MDeformVert *dvert = BKE_mesh_deform_verts(me);
const MLoopUV *mloopuv = CustomData_get_layer_named(&me->ldata, CD_MLOOPUV, ffs->uvlayer_name);
const float(*mloopuv)[2] = CustomData_get_layer_named(
&me->ldata, CD_PROP_FLOAT2, ffs->uvlayer_name);
if (ffs->flags & FLUID_FLOW_INITVELOCITY) {
vert_vel = MEM_callocN(sizeof(float[3]) * numverts, "manta_flow_velocity");
@@ -922,16 +922,6 @@ static void set_shade_smooth(MPoly &mpoly, bool value)
SET_FLAG_FROM_TEST(mpoly.flag, value, ME_SMOOTH);
}
static float2 get_loop_uv(const MLoopUV &uv)
{
return float2(uv.uv);
}
static void set_loop_uv(MLoopUV &uv, float2 co)
{
copy_v2_v2(uv.uv, co);
}
static float get_crease(const float &crease)
{
return crease;
@@ -1299,14 +1289,6 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh()
make_derived_write_attribute<float, float, get_crease, set_crease>,
nullptr);
static NamedLegacyCustomDataProvider uvs(
ATTR_DOMAIN_CORNER,
CD_PROP_FLOAT2,
CD_MLOOPUV,
corner_access,
make_derived_read_attribute<MLoopUV, float2, get_loop_uv>,
make_derived_write_attribute<MLoopUV, float2, get_loop_uv, set_loop_uv>);
static VertexGroupsAttributeProvider vertex_groups;
static CustomDataAttributeProvider corner_custom_data(ATTR_DOMAIN_CORNER, corner_access);
static CustomDataAttributeProvider point_custom_data(ATTR_DOMAIN_POINT, point_access);
@@ -1315,8 +1297,7 @@ static ComponentAttributeProviders create_attribute_providers_for_mesh()
return ComponentAttributeProviders(
{&position, &id, &material_index, &shade_smooth, &normal, &crease},
{&uvs,
&corner_custom_data,
{&corner_custom_data,
&vertex_groups,
&point_custom_data,
&edge_custom_data,
@@ -248,7 +248,7 @@ bool BKE_view_layer_filter_edit_mesh_has_uvs(const Object *ob, void *UNUSED(user
const Mesh *me = ob->data;
const BMEditMesh *em = me->edit_mesh;
if (em != NULL) {
if (CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV) != -1) {
if (CustomData_has_layer(&em->bm->ldata, CD_PROP_FLOAT2)) {
return true;
}
}
+47 -19
View File
@@ -288,6 +288,10 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address
CustomData_blend_write_prepare(mesh->edata, edge_layers, names_to_skip);
CustomData_blend_write_prepare(mesh->ldata, loop_layers, names_to_skip);
CustomData_blend_write_prepare(mesh->pdata, poly_layers, names_to_skip);
if (!BLO_write_is_undo(writer)) {
BKE_mesh_legacy_convert_uvs_to_struct(mesh, temp_arrays_for_legacy_format, loop_layers);
}
}
mesh->runtime = nullptr;
@@ -479,35 +483,71 @@ static const char *cmpcode_to_str(int code)
}
}
static bool is_sublayer_name(char const *sublayer_name, char const *name)
{
BLI_assert(strlen(sublayer_name) == 2);
if (name[1] != sublayer_name[0]) {
return false;
}
if (name[2] != sublayer_name[1]) {
return false;
}
if (name[3] != '.') {
return false;
}
return true;
}
static bool is_uv_bool_sublayer(CustomDataLayer const *l)
{
char const *name = l->name;
if (name[0] != '.') {
return false;
}
return is_sublayer_name(UV_VERTSEL_NAME, name) || is_sublayer_name(UV_EDGESEL_NAME, name) ||
is_sublayer_name(UV_PINNED_NAME, name);
}
/** Thresh is threshold for comparing vertices, UV's, vertex colors, weights, etc. */
static int customdata_compare(
CustomData *c1, CustomData *c2, const int total_length, Mesh *m1, Mesh *m2, const float thresh)
{
const float thresh_sq = thresh * thresh;
CustomDataLayer *l1, *l2;
int layer_count1 = 0, layer_count2 = 0, j;
const uint64_t cd_mask_non_generic = CD_MASK_MEDGE | CD_MASK_MPOLY | CD_MASK_MLOOPUV |
CD_MASK_PROP_BYTE_COLOR | CD_MASK_MDEFORMVERT;
const uint64_t cd_mask_non_generic = CD_MASK_MEDGE | CD_MASK_MPOLY | CD_MASK_PROP_BYTE_COLOR |
CD_MASK_MDEFORMVERT;
const uint64_t cd_mask_all_attr = CD_MASK_PROP_ALL | cd_mask_non_generic;
const Span<MLoop> loops_1 = m1->loops();
const Span<MLoop> loops_2 = m2->loops();
/* The uv selection / pin layers are ignored in the comparisons because
* the original flags they replace were ignored as well. Because of the
* lazy creation of these layers it would need careful handling of the
* test files to compare these layers. For now it has been decided to
* skip them.
*/
for (int i = 0; i < c1->totlayer; i++) {
l1 = &c1->layers[i];
if ((CD_TYPE_AS_MASK(l1->type) & cd_mask_all_attr) && l1->anonymous_id == nullptr) {
if ((CD_TYPE_AS_MASK(l1->type) & cd_mask_all_attr) && l1->anonymous_id == nullptr &&
!is_uv_bool_sublayer(l1)) {
layer_count1++;
}
}
for (int i = 0; i < c2->totlayer; i++) {
l2 = &c2->layers[i];
if ((CD_TYPE_AS_MASK(l2->type) & cd_mask_all_attr) && l2->anonymous_id == nullptr) {
if ((CD_TYPE_AS_MASK(l2->type) & cd_mask_all_attr) && l2->anonymous_id == nullptr &&
!is_uv_bool_sublayer(l2)) {
layer_count2++;
}
}
if (layer_count1 != layer_count2) {
/* TODO(@HooglyBoogly): Re-enable after tests are updated for material index refactor. */
/* TODO(@HooglyBoogly): Re-enable after tests are updated for material index refactor and UV as
* generic attribute refactor. */
// return MESHCMP_CDLAYERS_MISMATCH;
}
@@ -516,7 +556,7 @@ static int customdata_compare(
for (int i1 = 0; i1 < c1->totlayer; i1++) {
l1 = c1->layers + i1;
if (l1->anonymous_id != nullptr) {
if (l1->anonymous_id != nullptr || is_uv_bool_sublayer(l1)) {
continue;
}
bool found_corresponding_layer = false;
@@ -584,18 +624,6 @@ static int customdata_compare(
}
break;
}
case CD_MLOOPUV: {
MLoopUV *lp1 = (MLoopUV *)l1->data;
MLoopUV *lp2 = (MLoopUV *)l2->data;
int ltot = m1->totloop;
for (j = 0; j < ltot; j++, lp1++, lp2++) {
if (len_squared_v2v2(lp1->uv, lp2->uv) > thresh_sq) {
return MESHCMP_LOOPUVMISMATCH;
}
}
break;
}
case CD_PROP_BYTE_COLOR: {
MLoopCol *lp1 = (MLoopCol *)l1->data;
MLoopCol *lp2 = (MLoopCol *)l2->data;
@@ -198,8 +198,8 @@ static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispba
MutableAttributeAccessor attributes = mesh->attributes_for_write();
SpanAttributeWriter<int> material_indices = attributes.lookup_or_add_for_write_only_span<int>(
"material_index", ATTR_DOMAIN_FACE);
MLoopUV *mloopuv = static_cast<MLoopUV *>(CustomData_add_layer_named(
&mesh->ldata, CD_MLOOPUV, CD_SET_DEFAULT, nullptr, mesh->totloop, DATA_("UVMap")));
blender::float2 *mloopuv = static_cast<blender::float2 *>(CustomData_add_layer_named(
&mesh->ldata, CD_PROP_FLOAT2, CD_SET_DEFAULT, nullptr, mesh->totloop, DATA_("UVMap")));
int dst_vert = 0;
int dst_edge = 0;
@@ -278,8 +278,8 @@ static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispba
if (mloopuv) {
for (int i = 0; i < 3; i++, mloopuv++) {
mloopuv->uv[0] = (loops[dst_loop + i].v - startvert) / float(dl->nr - 1);
mloopuv->uv[1] = 0.0f;
(*mloopuv)[0] = (loops[dst_loop + i].v - startvert) / float(dl->nr - 1);
(*mloopuv)[1] = 0.0f;
}
}
@@ -355,15 +355,15 @@ static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispba
/* find uv based on vertex index into grid array */
int v = loops[dst_loop + i].v - startvert;
mloopuv->uv[0] = (v / dl->nr) / float(orco_sizev);
mloopuv->uv[1] = (v % dl->nr) / float(orco_sizeu);
(*mloopuv)[0] = (v / dl->nr) / float(orco_sizev);
(*mloopuv)[1] = (v % dl->nr) / float(orco_sizeu);
/* cyclic correction */
if (ELEM(i, 1, 2) && mloopuv->uv[0] == 0.0f) {
mloopuv->uv[0] = 1.0f;
if ((ELEM(i, 1, 2)) && (*mloopuv)[0] == 0.0f) {
(*mloopuv)[0] = 1.0f;
}
if (ELEM(i, 0, 1) && mloopuv->uv[1] == 0.0f) {
mloopuv->uv[1] = 1.0f;
if ((ELEM(i, 0, 1)) && (*mloopuv)[1] == 0.0f) {
(*mloopuv)[1] = 1.0f;
}
}
}
@@ -114,24 +114,6 @@ float BKE_mesh_calc_area(const Mesh *me)
return total_area;
}
float BKE_mesh_calc_poly_uv_area(const MPoly *mpoly, const MLoopUV *uv_array)
{
int i, l_iter = mpoly->loopstart;
float area;
float(*vertexcos)[2] = (float(*)[2])BLI_array_alloca(vertexcos, size_t(mpoly->totloop));
/* pack vertex cos into an array for area_poly_v2 */
for (i = 0; i < mpoly->totloop; i++, l_iter++) {
copy_v2_v2(vertexcos[i], uv_array[l_iter].uv);
}
/* finally calculate the area */
area = area_poly_v2(vertexcos, uint(mpoly->totloop));
return area;
}
static float UNUSED_FUNCTION(mesh_calc_poly_volume_centroid)(const MPoly *mpoly,
const MLoop *loopstart,
const float (*positions)[3],
@@ -302,17 +302,18 @@ static void bm_corners_to_loops_ex(ID *id,
for (int i = 0; i < numTex; i++) {
const MTFace *texface = (const MTFace *)CustomData_get_n(fdata, CD_MTFACE, findex, i);
MLoopUV *mloopuv = (MLoopUV *)CustomData_get_n(ldata, CD_MLOOPUV, loopstart, i);
copy_v2_v2(mloopuv->uv, texface->uv[0]);
mloopuv++;
copy_v2_v2(mloopuv->uv, texface->uv[1]);
mloopuv++;
copy_v2_v2(mloopuv->uv, texface->uv[2]);
mloopuv++;
blender::float2 *uv = static_cast<blender::float2 *>(
CustomData_get_n(ldata, CD_PROP_FLOAT2, loopstart, i));
copy_v2_v2(*uv, texface->uv[0]);
uv++;
copy_v2_v2(*uv, texface->uv[1]);
uv++;
copy_v2_v2(*uv, texface->uv[2]);
uv++;
if (mf->v4) {
copy_v2_v2(mloopuv->uv, texface->uv[3]);
mloopuv++;
copy_v2_v2(*uv, texface->uv[3]);
uv++;
}
}
@@ -394,7 +395,7 @@ static void CustomData_to_bmeshpoly(CustomData *fdata, CustomData *ldata, int to
for (int i = 0; i < fdata->totlayer; i++) {
if (fdata->layers[i].type == CD_MTFACE) {
CustomData_add_layer_named(
ldata, CD_MLOOPUV, CD_SET_DEFAULT, nullptr, totloop, fdata->layers[i].name);
ldata, CD_PROP_FLOAT2, CD_SET_DEFAULT, nullptr, totloop, fdata->layers[i].name);
}
else if (fdata->layers[i].type == CD_MCOL) {
CustomData_add_layer_named(
@@ -537,17 +538,17 @@ static void update_active_fdata_layers(Mesh &mesh, CustomData *fdata, CustomData
{
int act;
if (CustomData_has_layer(ldata, CD_MLOOPUV)) {
act = CustomData_get_active_layer(ldata, CD_MLOOPUV);
if (CustomData_has_layer(ldata, CD_PROP_FLOAT2)) {
act = CustomData_get_active_layer(ldata, CD_PROP_FLOAT2);
CustomData_set_layer_active(fdata, CD_MTFACE, act);
act = CustomData_get_render_layer(ldata, CD_MLOOPUV);
act = CustomData_get_render_layer(ldata, CD_PROP_FLOAT2);
CustomData_set_layer_render(fdata, CD_MTFACE, act);
act = CustomData_get_clone_layer(ldata, CD_MLOOPUV);
act = CustomData_get_clone_layer(ldata, CD_PROP_FLOAT2);
CustomData_set_layer_clone(fdata, CD_MTFACE, act);
act = CustomData_get_stencil_layer(ldata, CD_MLOOPUV);
act = CustomData_get_stencil_layer(ldata, CD_PROP_FLOAT2);
CustomData_set_layer_stencil(fdata, CD_MTFACE, act);
}
@@ -584,7 +585,7 @@ static bool check_matching_legacy_layer_counts(CustomData *fdata, CustomData *ld
((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)) {
if (!LAYER_CMP(ldata, CD_PROP_FLOAT2, fdata, CD_MTFACE)) {
return false;
}
if (!LAYER_CMP(ldata, CD_PROP_BYTE_COLOR, fdata, CD_MCOL)) {
@@ -617,7 +618,7 @@ static void add_mface_layers(Mesh &mesh, CustomData *fdata, CustomData *ldata, i
BLI_assert(!check_matching_legacy_layer_counts(fdata, ldata, false));
for (int i = 0; i < ldata->totlayer; i++) {
if (ldata->layers[i].type == CD_MLOOPUV) {
if (ldata->layers[i].type == CD_PROP_FLOAT2) {
CustomData_add_layer_named(
fdata, CD_MTFACE, CD_SET_DEFAULT, nullptr, total, ldata->layers[i].name);
}
@@ -655,7 +656,7 @@ static void mesh_ensure_tessellation_customdata(Mesh *me)
* Callers could also check but safer to do here - campbell */
}
else {
const int tottex_original = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV);
const int tottex_original = CustomData_number_of_layers(&me->ldata, CD_PROP_FLOAT2);
const int totcol_original = CustomData_number_of_layers(&me->ldata, CD_PROP_BYTE_COLOR);
const int tottex_tessface = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
@@ -674,7 +675,7 @@ static void mesh_ensure_tessellation_customdata(Mesh *me)
* some info to help troubleshoot what's going on. */
printf(
"%s: warning! Tessellation uvs or vcol data got out of sync, "
"had to reset!\n CD_MTFACE: %d != CD_MLOOPUV: %d || CD_MCOL: %d != "
"had to reset!\n CD_MTFACE: %d != CD_PROP_FLOAT2: %d || CD_MCOL: %d != "
"CD_PROP_BYTE_COLOR: "
"%d\n",
__func__,
@@ -717,16 +718,16 @@ static void CustomData_bmesh_do_versions_update_active_layers(CustomData *fdata,
if (CustomData_has_layer(fdata, CD_MTFACE)) {
act = CustomData_get_active_layer(fdata, CD_MTFACE);
CustomData_set_layer_active(ldata, CD_MLOOPUV, act);
CustomData_set_layer_active(ldata, CD_PROP_FLOAT2, act);
act = CustomData_get_render_layer(fdata, CD_MTFACE);
CustomData_set_layer_render(ldata, CD_MLOOPUV, act);
CustomData_set_layer_render(ldata, CD_PROP_FLOAT2, act);
act = CustomData_get_clone_layer(fdata, CD_MTFACE);
CustomData_set_layer_clone(ldata, CD_MLOOPUV, act);
CustomData_set_layer_clone(ldata, CD_PROP_FLOAT2, act);
act = CustomData_get_stencil_layer(fdata, CD_MTFACE);
CustomData_set_layer_stencil(ldata, CD_MLOOPUV, act);
CustomData_set_layer_stencil(ldata, CD_PROP_FLOAT2, act);
}
if (CustomData_has_layer(fdata, CD_MCOL)) {
@@ -792,7 +793,7 @@ static void mesh_loops_to_tessdata(CustomData *fdata,
* we could be ~25% quicker with dedicated code.
* The issue is, unless having two different functions with nearly the same code,
* there's not much ways to solve this. Better IMHO to live with it for now (sigh). */
const int numUV = CustomData_number_of_layers(ldata, CD_MLOOPUV);
const int numUV = CustomData_number_of_layers(ldata, CD_PROP_FLOAT2);
const int numCol = CustomData_number_of_layers(ldata, CD_PROP_BYTE_COLOR);
const bool hasPCol = CustomData_has_layer(ldata, CD_PREVIEW_MLOOPCOL);
const bool hasOrigSpace = CustomData_has_layer(ldata, CD_ORIGSPACE_MLOOP);
@@ -804,12 +805,13 @@ static void mesh_loops_to_tessdata(CustomData *fdata,
for (i = 0; i < numUV; i++) {
MTFace *texface = (MTFace *)CustomData_get_layer_n(fdata, CD_MTFACE, i);
const MLoopUV *mloopuv = (const MLoopUV *)CustomData_get_layer_n(ldata, CD_MLOOPUV, i);
const blender::float2 *uv = static_cast<const blender::float2 *>(
CustomData_get_layer_n(ldata, CD_PROP_FLOAT2, i));
for (findex = 0, pidx = polyindices, lidx = loopindices; findex < num_faces;
pidx++, lidx++, findex++, texface++) {
for (j = (mface ? mface[findex].v4 : (*lidx)[3]) ? 4 : 3; j--;) {
copy_v2_v2(texface->uv[j], mloopuv[(*lidx)[j]].uv);
copy_v2_v2(texface->uv[j], uv[(*lidx)[j]]);
}
}
}
@@ -1469,6 +1471,179 @@ void BKE_mesh_legacy_convert_mpoly_to_material_indices(Mesh *mesh)
/** \} */
/* -------------------------------------------------------------------- */
/** \name Generic UV Map Conversion
* \{ */
void BKE_mesh_legacy_convert_uvs_to_struct(
Mesh *mesh,
blender::ResourceScope &temp_mloopuv_for_convert,
blender::Vector<CustomDataLayer, 16> &face_corner_layers_to_write)
{
using namespace blender;
using namespace blender::bke;
const AttributeAccessor attributes = mesh->attributes();
Vector<CustomDataLayer, 16> new_layer_to_write;
/* Don't write the boolean UV map sublayers which will be written in the legacy #MLoopUV type. */
Set<std::string> uv_sublayers_to_skip;
char vert_name[MAX_CUSTOMDATA_LAYER_NAME];
char edge_name[MAX_CUSTOMDATA_LAYER_NAME];
char pin_name[MAX_CUSTOMDATA_LAYER_NAME];
for (const CustomDataLayer &layer : face_corner_layers_to_write) {
uv_sublayers_to_skip.add_multiple_new({BKE_uv_map_vert_select_name_get(layer.name, vert_name),
BKE_uv_map_edge_select_name_get(layer.name, edge_name),
BKE_uv_map_pin_name_get(layer.name, pin_name)});
}
for (const CustomDataLayer &layer : face_corner_layers_to_write) {
if (uv_sublayers_to_skip.contains_as(layer.name)) {
continue;
}
if (layer.type != CD_PROP_FLOAT2) {
new_layer_to_write.append(layer);
continue;
}
const Span<float2> coords{static_cast<const float2 *>(layer.data), mesh->totloop};
CustomDataLayer mloopuv_layer = layer;
mloopuv_layer.type = CD_MLOOPUV;
MutableSpan<MLoopUV> mloopuv = temp_mloopuv_for_convert.construct<Array<MLoopUV>>(
mesh->totloop);
mloopuv_layer.data = mloopuv.data();
char buffer[MAX_CUSTOMDATA_LAYER_NAME];
const VArray<bool> vert_selection = attributes.lookup_or_default<bool>(
BKE_uv_map_vert_select_name_get(layer.name, buffer), ATTR_DOMAIN_CORNER, false);
const VArray<bool> edge_selection = attributes.lookup_or_default<bool>(
BKE_uv_map_edge_select_name_get(layer.name, buffer), ATTR_DOMAIN_CORNER, false);
const VArray<bool> pin = attributes.lookup_or_default<bool>(
BKE_uv_map_pin_name_get(layer.name, buffer), ATTR_DOMAIN_CORNER, false);
threading::parallel_for(mloopuv.index_range(), 2048, [&](IndexRange range) {
for (const int i : range) {
copy_v2_v2(mloopuv[i].uv, coords[i]);
SET_FLAG_FROM_TEST(mloopuv[i].flag, vert_selection[i], MLOOPUV_VERTSEL);
SET_FLAG_FROM_TEST(mloopuv[i].flag, edge_selection[i], MLOOPUV_EDGESEL);
SET_FLAG_FROM_TEST(mloopuv[i].flag, pin[i], MLOOPUV_PINNED);
}
});
new_layer_to_write.append(mloopuv_layer);
}
face_corner_layers_to_write = new_layer_to_write;
mesh->ldata.totlayer = new_layer_to_write.size();
mesh->ldata.maxlayer = mesh->ldata.totlayer;
}
void BKE_mesh_legacy_convert_uvs_to_generic(Mesh *mesh)
{
using namespace blender;
using namespace blender::bke;
/* Store layer names since they will be removed, used to set the active status of new layers.
* Use intermediate #StringRef because the names can be null. */
const std::string active_uv = StringRef(
CustomData_get_active_layer_name(&mesh->ldata, CD_MLOOPUV));
const std::string default_uv = StringRef(
CustomData_get_render_layer_name(&mesh->ldata, CD_MLOOPUV));
Set<std::string> uv_layers_to_convert;
for (const int uv_layer_i : IndexRange(CustomData_number_of_layers(&mesh->ldata, CD_MLOOPUV))) {
uv_layers_to_convert.add_as(CustomData_get_layer_name(&mesh->ldata, CD_MLOOPUV, uv_layer_i));
}
for (const StringRefNull name : uv_layers_to_convert) {
const MLoopUV *mloopuv = static_cast<const MLoopUV *>(
CustomData_get_layer_named(&mesh->ldata, CD_MLOOPUV, name.c_str()));
const uint32_t needed_boolean_attributes = threading::parallel_reduce(
IndexRange(mesh->totloop),
4096,
0,
[&](const IndexRange range, uint32_t init) {
for (const int i : range) {
init |= mloopuv[i].flag;
}
return init;
},
[](const uint32_t a, const uint32_t b) { return a | b; });
float2 *coords = static_cast<float2 *>(
MEM_malloc_arrayN(mesh->totloop, sizeof(float2), __func__));
bool *vert_selection = nullptr;
bool *edge_selection = nullptr;
bool *pin = nullptr;
if (needed_boolean_attributes & MLOOPUV_VERTSEL) {
vert_selection = static_cast<bool *>(
MEM_malloc_arrayN(mesh->totloop, sizeof(bool), __func__));
}
if (needed_boolean_attributes & MLOOPUV_EDGESEL) {
edge_selection = static_cast<bool *>(
MEM_malloc_arrayN(mesh->totloop, sizeof(bool), __func__));
}
if (needed_boolean_attributes & MLOOPUV_PINNED) {
pin = static_cast<bool *>(MEM_malloc_arrayN(mesh->totloop, sizeof(bool), __func__));
}
threading::parallel_for(IndexRange(mesh->totloop), 4096, [&](IndexRange range) {
for (const int i : range) {
coords[i] = mloopuv[i].uv;
}
if (vert_selection) {
for (const int i : range) {
vert_selection[i] = mloopuv[i].flag & MLOOPUV_VERTSEL;
}
}
if (edge_selection) {
for (const int i : range) {
edge_selection[i] = mloopuv[i].flag & MLOOPUV_EDGESEL;
}
}
if (pin) {
for (const int i : range) {
pin[i] = mloopuv[i].flag & MLOOPUV_PINNED;
}
}
});
CustomData_free_layer_named(&mesh->ldata, name.c_str(), mesh->totloop);
CustomData_add_layer_named(
&mesh->ldata, CD_PROP_FLOAT2, CD_ASSIGN, coords, mesh->totloop, name.c_str());
char buffer[MAX_CUSTOMDATA_LAYER_NAME];
if (vert_selection) {
CustomData_add_layer_named(&mesh->ldata,
CD_PROP_BOOL,
CD_ASSIGN,
vert_selection,
mesh->totloop,
BKE_uv_map_vert_select_name_get(name.c_str(), buffer));
}
if (edge_selection) {
CustomData_add_layer_named(&mesh->ldata,
CD_PROP_BOOL,
CD_ASSIGN,
edge_selection,
mesh->totloop,
BKE_uv_map_edge_select_name_get(name.c_str(), buffer));
}
if (pin) {
CustomData_add_layer_named(&mesh->ldata,
CD_PROP_BOOL,
CD_ASSIGN,
pin,
mesh->totloop,
BKE_uv_map_pin_name_get(name.c_str(), buffer));
}
}
CustomData_set_layer_active_index(
&mesh->ldata,
CD_PROP_FLOAT2,
CustomData_get_named_layer_index(&mesh->ldata, CD_PROP_FLOAT2, active_uv.c_str()));
CustomData_set_layer_render_index(
&mesh->ldata,
CD_PROP_FLOAT2,
CustomData_get_named_layer_index(&mesh->ldata, CD_PROP_FLOAT2, default_uv.c_str()));
}
/** \name Selection Attribute and Legacy Flag Conversion
* \{ */
@@ -34,7 +34,7 @@ UvVertMap *BKE_mesh_uv_vert_map_create(const MPoly *mpoly,
const bool *hide_poly,
const bool *select_poly,
const MLoop *mloop,
const MLoopUV *mloopuv,
const float (*mloopuv)[2],
uint totpoly,
uint totvert,
const float limit[2],
@@ -95,7 +95,7 @@ UvVertMap *BKE_mesh_uv_vert_map_create(const MPoly *mpoly,
vmap->vert[mloop[mp->loopstart + i].v] = buf;
if (use_winding) {
copy_v2_v2(tf_uv[i], mloopuv[mpoly[a].loopstart + i].uv);
copy_v2_v2(tf_uv[i], mloopuv[mpoly[a].loopstart + i]);
}
buf++;
@@ -120,14 +120,14 @@ UvVertMap *BKE_mesh_uv_vert_map_create(const MPoly *mpoly,
v->next = newvlist;
newvlist = v;
uv = mloopuv[mpoly[v->poly_index].loopstart + v->loop_of_poly_index].uv;
uv = mloopuv[mpoly[v->poly_index].loopstart + v->loop_of_poly_index];
lastv = nullptr;
iterv = vlist;
while (iterv) {
next = iterv->next;
uv2 = mloopuv[mpoly[iterv->poly_index].loopstart + iterv->loop_of_poly_index].uv;
uv2 = mloopuv[mpoly[iterv->poly_index].loopstart + iterv->loop_of_poly_index];
sub_v2_v2v2(uvdiff, uv2, uv);
if (fabsf(uv[0] - uv2[0]) < limit[0] && fabsf(uv[1] - uv2[1]) < limit[1] &&
@@ -1004,7 +1004,7 @@ void BKE_mesh_loop_islands_add(MeshIslandStore *island_store,
*/
struct MeshCheckIslandBoundaryUv {
const MLoop *loops;
const MLoopUV *luvs;
const float (*luvs)[2];
const MeshElemMap *edge_loop_map;
};
@@ -1020,27 +1020,27 @@ static bool mesh_check_island_boundary_uv(const MPoly * /*mp*/,
const MeshCheckIslandBoundaryUv *data = static_cast<const MeshCheckIslandBoundaryUv *>(
user_data);
const MLoop *loops = data->loops;
const MLoopUV *luvs = data->luvs;
const float(*luvs)[2] = data->luvs;
const MeshElemMap *edge_to_loops = &data->edge_loop_map[ml->e];
BLI_assert(edge_to_loops->count >= 2 && (edge_to_loops->count % 2) == 0);
const uint v1 = loops[edge_to_loops->indices[0]].v;
const uint v2 = loops[edge_to_loops->indices[1]].v;
const float *uvco_v1 = luvs[edge_to_loops->indices[0]].uv;
const float *uvco_v2 = luvs[edge_to_loops->indices[1]].uv;
const float *uvco_v1 = luvs[edge_to_loops->indices[0]];
const float *uvco_v2 = luvs[edge_to_loops->indices[1]];
for (int i = 2; i < edge_to_loops->count; i += 2) {
if (loops[edge_to_loops->indices[i]].v == v1) {
if (!equals_v2v2(uvco_v1, luvs[edge_to_loops->indices[i]].uv) ||
!equals_v2v2(uvco_v2, luvs[edge_to_loops->indices[i + 1]].uv)) {
if (!equals_v2v2(uvco_v1, luvs[edge_to_loops->indices[i]]) ||
!equals_v2v2(uvco_v2, luvs[edge_to_loops->indices[i + 1]])) {
return true;
}
}
else {
BLI_assert(loops[edge_to_loops->indices[i]].v == v2);
UNUSED_VARS_NDEBUG(v2);
if (!equals_v2v2(uvco_v2, luvs[edge_to_loops->indices[i]].uv) ||
!equals_v2v2(uvco_v1, luvs[edge_to_loops->indices[i + 1]].uv)) {
if (!equals_v2v2(uvco_v2, luvs[edge_to_loops->indices[i]]) ||
!equals_v2v2(uvco_v1, luvs[edge_to_loops->indices[i + 1]])) {
return true;
}
}
@@ -1058,7 +1058,7 @@ static bool mesh_calc_islands_loop_poly_uv(const MEdge *edges,
const int totpoly,
const MLoop *loops,
const int totloop,
const MLoopUV *luvs,
const float (*luvs)[2],
MeshIslandStore *r_island_store)
{
int *poly_groups = nullptr;
@@ -1223,7 +1223,7 @@ bool BKE_mesh_calc_islands_loop_poly_uvmap(float (*vert_positions)[3],
const int totpoly,
MLoop *loops,
const int totloop,
const MLoopUV *luvs,
const float (*luvs)[2],
MeshIslandStore *r_island_store)
{
UNUSED_VARS(vert_positions, totvert);
@@ -10,6 +10,7 @@
#include "DNA_meshdata_types.h"
#include "BLI_math.h"
#include "BLI_math_vector_types.hh"
#include "BLI_task.hh"
#include "BLI_utildefines.h"
@@ -57,7 +58,7 @@ static int compare_v2_classify(const float uv_a[2], const float uv_b[2])
return CMP_APART;
}
static void merge_uvs_for_vertex(const Span<int> loops_for_vert, Span<MLoopUV *> mloopuv_layers)
static void merge_uvs_for_vertex(const Span<int> loops_for_vert, Span<float2 *> mloopuv_layers)
{
if (loops_for_vert.size() <= 1) {
return;
@@ -65,14 +66,14 @@ static void merge_uvs_for_vertex(const Span<int> loops_for_vert, Span<MLoopUV *>
/* Manipulate a copy of the loop indices, de-duplicating UV's per layer. */
Vector<int, 32> loops_merge;
loops_merge.reserve(loops_for_vert.size());
for (MLoopUV *mloopuv : mloopuv_layers) {
for (float2 *mloopuv : mloopuv_layers) {
BLI_assert(loops_merge.is_empty());
loops_merge.extend_unchecked(loops_for_vert);
while (loops_merge.size() > 1) {
uint i_last = uint(loops_merge.size()) - 1;
const float *uv_src = mloopuv[loops_merge[0]].uv;
const float *uv_src = mloopuv[loops_merge[0]];
for (uint i = 1; i <= i_last;) {
float *uv_dst = mloopuv[loops_merge[i]].uv;
float *uv_dst = mloopuv[loops_merge[i]];
switch (compare_v2_classify(uv_src, uv_dst)) {
case CMP_CLOSE: {
uv_dst[0] = uv_src[0];
@@ -106,7 +107,7 @@ void BKE_mesh_merge_customdata_for_apply_modifier(Mesh *me)
if (me->totloop == 0) {
return;
}
const int mloopuv_layers_num = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV);
const int mloopuv_layers_num = CustomData_number_of_layers(&me->ldata, CD_PROP_FLOAT2);
if (mloopuv_layers_num == 0) {
return;
}
@@ -121,14 +122,15 @@ void BKE_mesh_merge_customdata_for_apply_modifier(Mesh *me)
me->totpoly,
me->totloop);
Vector<MLoopUV *> mloopuv_layers;
Vector<float2 *> mloopuv_layers;
mloopuv_layers.reserve(mloopuv_layers_num);
for (int a = 0; a < mloopuv_layers_num; a++) {
MLoopUV *mloopuv = static_cast<MLoopUV *>(CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, a));
float2 *mloopuv = static_cast<float2 *>(CustomData_get_layer_n(&me->ldata, CD_PROP_FLOAT2, a));
mloopuv_layers.append_unchecked(mloopuv);
}
Span<MLoopUV *> mloopuv_layers_as_span = mloopuv_layers.as_span();
Span<float2 *> mloopuv_layers_as_span = mloopuv_layers.as_span();
threading::parallel_for(IndexRange(me->totvert), 1024, [&](IndexRange range) {
for (const int64_t v_index : range) {
MeshElemMap &loops_for_vert = vert_to_loop[v_index];
+11 -11
View File
@@ -357,34 +357,34 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
/* If set, flip around center of each tile. */
const bool do_mirr_udim = (mmd->flag & MOD_MIR_MIRROR_UDIM) != 0;
const int totuv = CustomData_number_of_layers(&result->ldata, CD_MLOOPUV);
const int totuv = CustomData_number_of_layers(&result->ldata, CD_PROP_FLOAT2);
for (a = 0; a < totuv; a++) {
MLoopUV *dmloopuv = static_cast<MLoopUV *>(
CustomData_get_layer_n(&result->ldata, CD_MLOOPUV, a));
float(*dmloopuv)[2] = static_cast<float(*)[2]>(
CustomData_get_layer_n(&result->ldata, CD_PROP_FLOAT2, a));
int j = maxLoops;
dmloopuv += j; /* second set of loops only */
for (; j-- > 0; dmloopuv++) {
if (do_mirr_u) {
float u = dmloopuv->uv[0];
float u = (*dmloopuv)[0];
if (do_mirr_udim) {
dmloopuv->uv[0] = ceilf(u) - fmodf(u, 1.0f) + mmd->uv_offset[0];
(*dmloopuv)[0] = ceilf(u) - fmodf(u, 1.0f) + mmd->uv_offset[0];
}
else {
dmloopuv->uv[0] = 1.0f - u + mmd->uv_offset[0];
(*dmloopuv)[0] = 1.0f - u + mmd->uv_offset[0];
}
}
if (do_mirr_v) {
float v = dmloopuv->uv[1];
float v = (*dmloopuv)[1];
if (do_mirr_udim) {
dmloopuv->uv[1] = ceilf(v) - fmodf(v, 1.0f) + mmd->uv_offset[1];
(*dmloopuv)[1] = ceilf(v) - fmodf(v, 1.0f) + mmd->uv_offset[1];
}
else {
dmloopuv->uv[1] = 1.0f - v + mmd->uv_offset[1];
(*dmloopuv)[1] = 1.0f - v + mmd->uv_offset[1];
}
}
dmloopuv->uv[0] += mmd->uv_offset_copy[0];
dmloopuv->uv[1] += mmd->uv_offset_copy[1];
(*dmloopuv)[0] += mmd->uv_offset_copy[0];
(*dmloopuv)[1] += mmd->uv_offset_copy[1];
}
}
}
@@ -18,6 +18,7 @@
#include "BLI_task.h"
#include "BLI_utildefines.h"
#include "BKE_attribute.hh"
#include "BKE_customdata.h"
#include "BKE_mesh.h"
#include "BKE_mesh_runtime.h"
@@ -29,6 +30,8 @@
#include "atomic_ops.h"
#include "mikktspace.hh"
using blender::float2;
/* -------------------------------------------------------------------- */
/** \name Mesh Tangent Calculations (Single Layer)
* \{ */
@@ -52,7 +55,7 @@ struct BKEMeshToTangent {
mikk::float3 GetTexCoord(const uint face_num, const uint vert_num)
{
const float *uv = luvs[uint(mpolys[face_num].loopstart) + vert_num].uv;
const float *uv = luvs[uint(mpolys[face_num].loopstart) + vert_num];
return mikk::float3(uv[0], uv[1], 1.0f);
}
@@ -70,7 +73,7 @@ struct BKEMeshToTangent {
const MPoly *mpolys; /* faces */
const MLoop *mloops; /* faces vertices */
const float (*positions)[3]; /* vertices */
const MLoopUV *luvs; /* texture coordinates */
const float (*luvs)[2]; /* texture coordinates */
const float (*loop_normals)[3]; /* loops' normals */
float (*tangents)[4]; /* output tangents */
int num_polys; /* number of polygons */
@@ -81,7 +84,7 @@ void BKE_mesh_calc_loop_tangent_single_ex(const float (*vert_positions)[3],
const MLoop *mloops,
float (*r_looptangent)[4],
const float (*loop_normals)[3],
const MLoopUV *loopuvs,
const float (*loop_uvs)[2],
const int /*numLoops*/,
const MPoly *mpolys,
const int numPolys,
@@ -92,7 +95,7 @@ void BKE_mesh_calc_loop_tangent_single_ex(const float (*vert_positions)[3],
mesh_to_tangent.mpolys = mpolys;
mesh_to_tangent.mloops = mloops;
mesh_to_tangent.positions = vert_positions;
mesh_to_tangent.luvs = loopuvs;
mesh_to_tangent.luvs = loop_uvs;
mesh_to_tangent.loop_normals = loop_normals;
mesh_to_tangent.tangents = r_looptangent;
mesh_to_tangent.num_polys = numPolys;
@@ -116,16 +119,16 @@ void BKE_mesh_calc_loop_tangent_single(Mesh *mesh,
float (*r_looptangents)[4],
ReportList *reports)
{
const MLoopUV *loopuvs;
using namespace blender;
using namespace blender::bke;
/* Check we have valid texture coordinates first! */
if (uvmap) {
loopuvs = static_cast<MLoopUV *>(CustomData_get_layer_named(&mesh->ldata, CD_MLOOPUV, uvmap));
if (!uvmap) {
uvmap = CustomData_get_active_layer_name(&mesh->ldata, CD_PROP_FLOAT2);
}
else {
loopuvs = static_cast<MLoopUV *>(CustomData_get_layer(&mesh->ldata, CD_MLOOPUV));
}
if (!loopuvs) {
const AttributeAccessor attributes = mesh->attributes();
const VArraySpan<float2> uv_map = attributes.lookup<float2>(uvmap, ATTR_DOMAIN_CORNER);
if (uv_map.is_empty()) {
BKE_reportf(reports,
RPT_ERROR,
"Tangent space computation needs a UV Map, \"%s\" not found, aborting",
@@ -146,7 +149,7 @@ void BKE_mesh_calc_loop_tangent_single(Mesh *mesh,
BKE_mesh_loops(mesh),
r_looptangents,
loop_normals,
loopuvs,
reinterpret_cast<const float(*)[2]>(uv_map.data()),
mesh->totloop,
BKE_mesh_polys(mesh),
mesh->totpoly,
@@ -221,7 +224,7 @@ struct SGLSLMeshToTangent {
const MLoopTri *lt;
uint loop_index = GetLoop(face_num, vert_num, lt);
if (mloopuv != nullptr) {
const float *uv = mloopuv[loop_index].uv;
const float2 &uv = mloopuv[loop_index];
return mikk::float3(uv[0], uv[1], 1.0f);
}
const float *l_orco = orco[mloop[loop_index].v];
@@ -275,7 +278,7 @@ struct SGLSLMeshToTangent {
const float (*precomputedFaceNormals)[3];
const float (*precomputedLoopNormals)[3];
const MLoopTri *looptri;
const MLoopUV *mloopuv; /* texture coordinates */
const float2 *mloopuv; /* texture coordinates */
const MPoly *mpoly; /* indices */
const MLoop *mloop; /* indices */
const float (*positions)[3]; /* vertex coordinates */
@@ -306,7 +309,7 @@ void BKE_mesh_add_loop_tangent_named_layer_for_uv(CustomData *uv_data,
const char *layer_name)
{
if (CustomData_get_named_layer_index(tan_data, CD_TANGENT, layer_name) == -1 &&
CustomData_get_named_layer_index(uv_data, CD_MLOOPUV, layer_name) != -1) {
CustomData_get_named_layer_index(uv_data, CD_PROP_FLOAT2, layer_name) != -1) {
CustomData_add_layer_named(
tan_data, CD_TANGENT, CD_SET_DEFAULT, nullptr, numLoopData, layer_name);
}
@@ -314,7 +317,7 @@ void BKE_mesh_add_loop_tangent_named_layer_for_uv(CustomData *uv_data,
void BKE_mesh_calc_loop_tangent_step_0(const CustomData *loopData,
bool calc_active_tangent,
const char (*tangent_names)[MAX_NAME],
const char (*tangent_names)[MAX_CUSTOMDATA_LAYER_NAME],
int tangent_names_count,
bool *rcalc_act,
bool *rcalc_ren,
@@ -325,15 +328,15 @@ void BKE_mesh_calc_loop_tangent_step_0(const CustomData *loopData,
short *rtangent_mask)
{
/* Active uv in viewport */
int layer_index = CustomData_get_layer_index(loopData, CD_MLOOPUV);
*ract_uv_n = CustomData_get_active_layer(loopData, CD_MLOOPUV);
int layer_index = CustomData_get_layer_index(loopData, CD_PROP_FLOAT2);
*ract_uv_n = CustomData_get_active_layer(loopData, CD_PROP_FLOAT2);
ract_uv_name[0] = 0;
if (*ract_uv_n != -1) {
strcpy(ract_uv_name, loopData->layers[*ract_uv_n + layer_index].name);
}
/* Active tangent in render */
*rren_uv_n = CustomData_get_render_layer(loopData, CD_MLOOPUV);
*rren_uv_n = CustomData_get_render_layer(loopData, CD_PROP_FLOAT2);
rren_uv_name[0] = 0;
if (*rren_uv_n != -1) {
strcpy(rren_uv_name, loopData->layers[*rren_uv_n + layer_index].name);
@@ -361,9 +364,9 @@ void BKE_mesh_calc_loop_tangent_step_0(const CustomData *loopData,
}
*rtangent_mask = 0;
const int uv_layer_num = CustomData_number_of_layers(loopData, CD_MLOOPUV);
const int uv_layer_num = CustomData_number_of_layers(loopData, CD_PROP_FLOAT2);
for (int n = 0; n < uv_layer_num; n++) {
const char *name = CustomData_get_layer_name(loopData, CD_MLOOPUV, n);
const char *name = CustomData_get_layer_name(loopData, CD_PROP_FLOAT2, n);
bool add = false;
for (int i = 0; i < tangent_names_count; i++) {
if (tangent_names[i][0] && STREQ(tangent_names[i], name)) {
@@ -394,7 +397,7 @@ void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3],
CustomData *loopdata,
bool calc_active_tangent,
const char (*tangent_names)[MAX_NAME],
const char (*tangent_names)[MAX_CUSTOMDATA_LAYER_NAME],
int tangent_names_len,
const float (*vert_normals)[3],
const float (*poly_normals)[3],
@@ -409,8 +412,8 @@ void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3],
int ren_uv_n = -1;
bool calc_act = false;
bool calc_ren = false;
char act_uv_name[MAX_NAME];
char ren_uv_name[MAX_NAME];
char act_uv_name[MAX_CUSTOMDATA_LAYER_NAME];
char ren_uv_name[MAX_CUSTOMDATA_LAYER_NAME];
short tangent_mask = 0;
short tangent_mask_curr = *tangent_mask_curr_p;
@@ -501,8 +504,8 @@ void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3],
mesh2tangent->precomputedFaceNormals = poly_normals;
mesh2tangent->orco = nullptr;
mesh2tangent->mloopuv = static_cast<const MLoopUV *>(
CustomData_get_layer_named(loopdata, CD_MLOOPUV, loopdata_out->layers[index].name));
mesh2tangent->mloopuv = static_cast<const float2 *>(CustomData_get_layer_named(
loopdata, CD_PROP_FLOAT2, loopdata_out->layers[index].name));
/* Fill the resulting tangent_mask */
if (!mesh2tangent->mloopuv) {
@@ -515,8 +518,8 @@ void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3],
}
else {
int uv_ind = CustomData_get_named_layer_index(
loopdata, CD_MLOOPUV, loopdata_out->layers[index].name);
int uv_start = CustomData_get_layer_index(loopdata, CD_MLOOPUV);
loopdata, CD_PROP_FLOAT2, loopdata_out->layers[index].name);
int uv_start = CustomData_get_layer_index(loopdata, CD_PROP_FLOAT2);
BLI_assert(uv_ind != -1 && uv_start != -1);
BLI_assert(uv_ind - uv_start < MAX_MTFACE);
tangent_mask_curr |= short(1 << (uv_ind - uv_start));
@@ -545,7 +548,7 @@ void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3],
/* Update active layer index */
int act_uv_index = (act_uv_n != -1) ?
CustomData_get_layer_index_n(loopdata, CD_MLOOPUV, act_uv_n) :
CustomData_get_layer_index_n(loopdata, CD_PROP_FLOAT2, act_uv_n) :
-1;
if (act_uv_index != -1) {
int tan_index = CustomData_get_named_layer_index(
@@ -555,7 +558,7 @@ void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3],
/* Update render layer index */
int ren_uv_index = (ren_uv_n != -1) ?
CustomData_get_layer_index_n(loopdata, CD_MLOOPUV, ren_uv_n) :
CustomData_get_layer_index_n(loopdata, CD_PROP_FLOAT2, ren_uv_n) :
-1;
if (ren_uv_index != -1) {
int tan_index = CustomData_get_named_layer_index(
@@ -567,7 +570,7 @@ void BKE_mesh_calc_loop_tangent_ex(const float (*vert_positions)[3],
void BKE_mesh_calc_loop_tangents(Mesh *me_eval,
bool calc_active_tangent,
const char (*tangent_names)[MAX_NAME],
const char (*tangent_names)[MAX_CUSTOMDATA_LAYER_NAME],
int tangent_names_len)
{
/* TODO(@campbellbarton): store in Mesh.runtime to avoid recalculation. */
@@ -1022,7 +1022,7 @@ bool BKE_mesh_validate_all_customdata(CustomData *vdata,
is_valid &= mesh_validate_customdata(
pdata, mask.pmask, totpoly, do_verbose, do_fixes, &is_change_p);
const int tot_uvloop = CustomData_number_of_layers(ldata, CD_MLOOPUV);
const int tot_uvloop = CustomData_number_of_layers(ldata, CD_PROP_FLOAT2);
if (tot_uvloop > MAX_MTFACE) {
PRINT_ERR(
"\tMore UV layers than %d allowed, %d last ones won't be available for render, shaders, "
@@ -1032,12 +1032,12 @@ bool BKE_mesh_validate_all_customdata(CustomData *vdata,
}
/* check indices of clone/stencil */
if (do_fixes && CustomData_get_clone_layer(ldata, CD_MLOOPUV) >= tot_uvloop) {
CustomData_set_layer_clone(ldata, CD_MLOOPUV, 0);
if (do_fixes && CustomData_get_clone_layer(ldata, CD_PROP_FLOAT2) >= tot_uvloop) {
CustomData_set_layer_clone(ldata, CD_PROP_FLOAT2, 0);
is_change_l = true;
}
if (do_fixes && CustomData_get_stencil_layer(ldata, CD_MLOOPUV) >= tot_uvloop) {
CustomData_set_layer_stencil(ldata, CD_MLOOPUV, 0);
if (do_fixes && CustomData_get_stencil_layer(ldata, CD_PROP_FLOAT2) >= tot_uvloop) {
CustomData_set_layer_stencil(ldata, CD_PROP_FLOAT2, 0);
is_change_l = true;
}
@@ -67,6 +67,7 @@
#include "RNA_types.h"
using blender::Array;
using blender::float2;
using blender::float3;
using blender::float4x4;
using blender::Span;
@@ -1062,7 +1063,7 @@ struct FaceDupliData_Mesh {
const MLoop *mloop;
Span<float3> vert_positions;
const float (*orco)[3];
const MLoopUV *mloopuv;
const float2 *mloopuv;
};
struct FaceDupliData_EditMesh {
@@ -1211,7 +1212,7 @@ static void make_child_duplis_faces_from_mesh(const DupliContext *ctx,
const MPoly *mpoly = fdd->mpoly, *mp;
const MLoop *mloop = fdd->mloop;
const float(*orco)[3] = fdd->orco;
const MLoopUV *mloopuv = fdd->mloopuv;
const float2 *mloopuv = fdd->mloopuv;
const int totface = fdd->totface;
const bool use_scale = fdd->params.use_scale;
int a;
@@ -1243,7 +1244,7 @@ static void make_child_duplis_faces_from_mesh(const DupliContext *ctx,
}
if (mloopuv) {
for (int j = 0; j < mp->totloop; j++) {
madd_v2_v2fl(dob->uv, mloopuv[mp->loopstart + j].uv, w);
madd_v2_v2fl(dob->uv, mloopuv[mp->loopstart + j], w);
}
}
}
@@ -1304,7 +1305,7 @@ static void make_duplis_faces(const DupliContext *ctx)
FaceDupliData_Params fdd_params = {ctx, (parent->transflag & OB_DUPLIFACES_SCALE) != 0};
if (em != nullptr) {
const int uv_idx = CustomData_get_render_layer(&em->bm->ldata, CD_MLOOPUV);
const int uv_idx = CustomData_get_render_layer(&em->bm->ldata, CD_PROP_FLOAT2);
FaceDupliData_EditMesh fdd{};
fdd.params = fdd_params;
fdd.em = em;
@@ -1312,20 +1313,20 @@ static void make_duplis_faces(const DupliContext *ctx)
fdd.has_orco = (vert_positions_deform != nullptr);
fdd.has_uvs = (uv_idx != -1);
fdd.cd_loop_uv_offset = (uv_idx != -1) ?
CustomData_get_n_offset(&em->bm->ldata, CD_MLOOPUV, uv_idx) :
CustomData_get_n_offset(&em->bm->ldata, CD_PROP_FLOAT2, uv_idx) :
-1;
make_child_duplis(ctx, &fdd, make_child_duplis_faces_from_editmesh);
}
else {
const int uv_idx = CustomData_get_render_layer(&me_eval->ldata, CD_MLOOPUV);
const int uv_idx = CustomData_get_render_layer(&me_eval->ldata, CD_PROP_FLOAT2);
FaceDupliData_Mesh fdd{};
fdd.params = fdd_params;
fdd.totface = me_eval->totpoly;
fdd.mpoly = me_eval->polys().data();
fdd.mloop = me_eval->loops().data();
fdd.vert_positions = me_eval->vert_positions();
fdd.mloopuv = (uv_idx != -1) ? (const MLoopUV *)CustomData_get_layer_n(
&me_eval->ldata, CD_MLOOPUV, uv_idx) :
fdd.mloopuv = (uv_idx != -1) ? (const float2 *)CustomData_get_layer_n(
&me_eval->ldata, CD_PROP_FLOAT2, uv_idx) :
nullptr;
fdd.orco = (const float(*)[3])CustomData_get_layer(&me_eval->vdata, CD_ORCO);
@@ -158,7 +158,7 @@ void BKE_object_handle_data_update(Depsgraph *depsgraph, Scene *scene, Object *o
#endif
if (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER) {
/* Always compute UVs, vertex colors as orcos for render. */
cddata_masks.lmask |= CD_MASK_MLOOPUV | CD_MASK_PROP_BYTE_COLOR;
cddata_masks.lmask |= CD_MASK_PROP_FLOAT2 | CD_MASK_PROP_BYTE_COLOR;
cddata_masks.vmask |= CD_MASK_ORCO | CD_MASK_PROP_COLOR;
}
makeDerivedMesh(depsgraph, scene, ob, &cddata_masks); /* was CD_MASK_BAREMESH */
@@ -80,7 +80,7 @@ int BKE_paint_canvas_uvmap_layer_index_get(const struct PaintModeSettings *setti
}
const Mesh *mesh = static_cast<Mesh *>(ob->data);
return CustomData_get_active_layer_index(&mesh->ldata, CD_MLOOPUV);
return CustomData_get_active_layer_index(&mesh->ldata, CD_PROP_FLOAT2);
}
case PAINT_CANVAS_SOURCE_MATERIAL: {
/* Use uv map of the canvas. */
@@ -98,7 +98,7 @@ int BKE_paint_canvas_uvmap_layer_index_get(const struct PaintModeSettings *setti
}
const Mesh *mesh = static_cast<Mesh *>(ob->data);
return CustomData_get_named_layer_index(&mesh->ldata, CD_MLOOPUV, slot->uvname);
return CustomData_get_named_layer_index(&mesh->ldata, CD_PROP_FLOAT2, slot->uvname);
}
}
return -1;
@@ -147,7 +147,7 @@ struct EncodePixelsUserData {
ImageUser *image_user;
PBVH *pbvh;
Vector<PBVHNode *> *nodes;
const MLoopUV *ldata_uv;
const float2 *ldata_uv;
const uv_islands::UVIslandsMask *uv_masks;
/** Lookup to retrieve the UV primitives based on the primitive index. */
const UVPrimitiveLookup *uv_primitive_lookup;
@@ -355,8 +355,8 @@ static void update_pixels(PBVH *pbvh, Mesh *mesh, Image *image, ImageUser *image
return;
}
const MLoopUV *ldata_uv = static_cast<const MLoopUV *>(
CustomData_get_layer(&mesh->ldata, CD_MLOOPUV));
const float2 *ldata_uv = static_cast<const float2 *>(
CustomData_get_layer(&mesh->ldata, CD_PROP_FLOAT2));
if (ldata_uv == nullptr) {
return;
}
@@ -116,7 +116,7 @@ static void mesh_data_init_primitives(MeshData &mesh_data)
MeshUVVert uv_vert;
uv_vert.loop = tri.tri[j];
uv_vert.vertex = &mesh_data.vertices[mesh_data.loops[uv_vert.loop].v];
uv_vert.uv = mesh_data.mloopuv[uv_vert.loop].uv;
uv_vert.uv = mesh_data.mloopuv[uv_vert.loop];
primitive.vertices.append(uv_vert);
}
mesh_data.primitives.append(primitive);
@@ -218,7 +218,7 @@ static void mesh_data_init(MeshData &mesh_data)
MeshData::MeshData(const Span<MLoopTri> looptris,
const Span<MLoop> loops,
const int verts_num,
const Span<MLoopUV> mloopuv)
const Span<float2> mloopuv)
: looptris(looptris), verts_num(verts_num), loops(loops), mloopuv(mloopuv)
{
mesh_data_init(*this);
@@ -95,7 +95,7 @@ struct MeshData {
const Span<MLoopTri> looptris;
const int64_t verts_num;
const Span<MLoop> loops;
const Span<MLoopUV> mloopuv;
const Span<float2> mloopuv;
Vector<MeshPrimitive> primitives;
Vector<MeshEdge> edges;
@@ -107,7 +107,7 @@ struct MeshData {
explicit MeshData(const Span<MLoopTri> looptris,
const Span<MLoop> loops,
const int verts_num,
const Span<MLoopUV> mloopuv);
const Span<float2> mloopuv);
};
struct UVVertex {
@@ -193,14 +193,14 @@ static int get_num_uv_layers(const OpenSubdiv_Converter *converter)
{
ConverterStorage *storage = converter->user_data;
const Mesh *mesh = storage->mesh;
return CustomData_number_of_layers(&mesh->ldata, CD_MLOOPUV);
return CustomData_number_of_layers(&mesh->ldata, CD_PROP_FLOAT2);
}
static void precalc_uv_layer(const OpenSubdiv_Converter *converter, const int layer_index)
{
ConverterStorage *storage = converter->user_data;
const Mesh *mesh = storage->mesh;
const MLoopUV *mloopuv = CustomData_get_layer_n(&mesh->ldata, CD_MLOOPUV, layer_index);
const float(*mloopuv)[2] = CustomData_get_layer_n(&mesh->ldata, CD_PROP_FLOAT2, layer_index);
const int num_poly = mesh->totpoly;
const int num_vert = mesh->totvert;
const float limit[2] = {STD_UV_CONNECT_LIMIT, STD_UV_CONNECT_LIMIT};
@@ -126,7 +126,7 @@ typedef struct FaceVaryingDataFromUVContext {
OpenSubdiv_TopologyRefiner *topology_refiner;
const Mesh *mesh;
const MPoly *polys;
const MLoopUV *mloopuv;
const float (*mloopuv)[2];
float (*buffer)[2];
int layer_index;
} FaceVaryingDataFromUVContext;
@@ -139,7 +139,7 @@ static void set_face_varying_data_from_uv_task(void *__restrict userdata,
OpenSubdiv_TopologyRefiner *topology_refiner = ctx->topology_refiner;
const int layer_index = ctx->layer_index;
const MPoly *mpoly = &ctx->polys[face_index];
const MLoopUV *mluv = &ctx->mloopuv[mpoly->loopstart];
const float(*mluv)[2] = &ctx->mloopuv[mpoly->loopstart];
/* TODO(sergey): OpenSubdiv's C-API converter can change winding of
* loops of a face, need to watch for that, to prevent wrong UVs assigned.
@@ -148,19 +148,19 @@ static void set_face_varying_data_from_uv_task(void *__restrict userdata,
const int *uv_indices = topology_refiner->getFaceFVarValueIndices(
topology_refiner, face_index, layer_index);
for (int vertex_index = 0; vertex_index < num_face_vertices; vertex_index++, mluv++) {
copy_v2_v2(ctx->buffer[uv_indices[vertex_index]], mluv->uv);
copy_v2_v2(ctx->buffer[uv_indices[vertex_index]], *mluv);
}
}
static void set_face_varying_data_from_uv(Subdiv *subdiv,
const Mesh *mesh,
const MLoopUV *mloopuv,
const float (*mloopuv)[2],
const int layer_index)
{
OpenSubdiv_TopologyRefiner *topology_refiner = subdiv->topology_refiner;
OpenSubdiv_Evaluator *evaluator = subdiv->evaluator;
const int num_faces = topology_refiner->getNumFaces(topology_refiner);
const MLoopUV *mluv = mloopuv;
const float(*mluv)[2] = mloopuv;
const int num_fvar_values = topology_refiner->getNumFVarValues(topology_refiner, layer_index);
/* Use a temporary buffer so we do not upload UVs one at a time to the GPU. */
@@ -249,9 +249,9 @@ bool BKE_subdiv_eval_refine_from_mesh(Subdiv *subdiv,
/* Set coordinates of base mesh vertices. */
set_coarse_positions(subdiv, mesh, coarse_vertex_cos);
/* Set face-varying data to UV maps. */
const int num_uv_layers = CustomData_number_of_layers(&mesh->ldata, CD_MLOOPUV);
const int num_uv_layers = CustomData_number_of_layers(&mesh->ldata, CD_PROP_FLOAT2);
for (int layer_index = 0; layer_index < num_uv_layers; layer_index++) {
const MLoopUV *mloopuv = CustomData_get_layer_n(&mesh->ldata, CD_MLOOPUV, layer_index);
const float(*mloopuv)[2] = CustomData_get_layer_n(&mesh->ldata, CD_PROP_FLOAT2, layer_index);
set_face_varying_data_from_uv(subdiv, mesh, mloopuv, layer_index);
}
/* Set vertex data to orco. */
@@ -16,6 +16,7 @@
#include "BLI_array.hh"
#include "BLI_bitmap.h"
#include "BLI_math_vector.h"
#include "BLI_math_vector_types.hh"
#include "BKE_customdata.h"
#include "BKE_key.h"
@@ -28,6 +29,7 @@
#include "MEM_guardedalloc.h"
using blender::float2;
using blender::float3;
using blender::Span;
@@ -57,7 +59,8 @@ struct SubdivMeshContext {
int *poly_origindex;
/* UV layers interpolation. */
int num_uv_layers;
MLoopUV *uv_layers[MAX_MTFACE];
float2 *uv_layers[MAX_MTFACE];
/* Original coordinates (ORCO) interpolation. */
float (*orco)[3];
float (*cloth_orco)[3];
@@ -74,10 +77,10 @@ struct SubdivMeshContext {
static void subdiv_mesh_ctx_cache_uv_layers(SubdivMeshContext *ctx)
{
Mesh *subdiv_mesh = ctx->subdiv_mesh;
ctx->num_uv_layers = CustomData_number_of_layers(&subdiv_mesh->ldata, CD_MLOOPUV);
ctx->num_uv_layers = CustomData_number_of_layers(&subdiv_mesh->ldata, CD_PROP_FLOAT2);
for (int layer_index = 0; layer_index < ctx->num_uv_layers; layer_index++) {
ctx->uv_layers[layer_index] = static_cast<MLoopUV *>(
CustomData_get_layer_n(&subdiv_mesh->ldata, CD_MLOOPUV, layer_index));
ctx->uv_layers[layer_index] = static_cast<float2 *>(
CustomData_get_layer_n(&subdiv_mesh->ldata, CD_PROP_FLOAT2, layer_index));
}
}
@@ -858,8 +861,8 @@ static void subdiv_eval_uv_layer(SubdivMeshContext *ctx,
Subdiv *subdiv = ctx->subdiv;
const int mloop_index = subdiv_loop - ctx->subdiv_loops;
for (int layer_index = 0; layer_index < ctx->num_uv_layers; layer_index++) {
MLoopUV *subdiv_loopuv = &ctx->uv_layers[layer_index][mloop_index];
BKE_subdiv_eval_face_varying(subdiv, layer_index, ptex_face_index, u, v, subdiv_loopuv->uv);
BKE_subdiv_eval_face_varying(
subdiv, layer_index, ptex_face_index, u, v, ctx->uv_layers[layer_index][mloop_index]);
}
}
+12 -12
View File
@@ -262,7 +262,7 @@ static void get_face_uv_map_vert(
static int ss_sync_from_uv(CCGSubSurf *ss,
CCGSubSurf *origss,
DerivedMesh *dm,
const MLoopUV *mloopuv)
const float (*mloopuv)[2])
{
MPoly *mpoly = dm->getPolyArray(dm);
MLoop *mloop = dm->getLoopArray(dm);
@@ -312,7 +312,7 @@ static int ss_sync_from_uv(CCGSubSurf *ss,
int loopid = mpoly[v->poly_index].loopstart + v->loop_of_poly_index;
CCGVertHDL vhdl = POINTER_FROM_INT(loopid);
copy_v2_v2(uv, mloopuv[loopid].uv);
copy_v2_v2(uv, mloopuv[loopid]);
ccgSubSurf_syncVert(ss, vhdl, uv, seam, &ssv);
}
@@ -387,11 +387,11 @@ static void set_subsurf_legacy_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *
{
CCGFaceIterator fi;
int index, gridSize, gridFaces, /*edgeSize,*/ totface, x, y, S;
const MLoopUV *dmloopuv = CustomData_get_layer_n(&dm->loopData, CD_MLOOPUV, n);
/* need to update both CD_MTFACE & CD_MLOOPUV, hrmf, we could get away with
const float(*dmloopuv)[2] = CustomData_get_layer_n(&dm->loopData, CD_PROP_FLOAT2, n);
/* need to update both CD_MTFACE & CD_PROP_FLOAT2, hrmf, we could get away with
* just tface except applying the modifier then looses subsurf UV */
MTFace *tface = CustomData_get_layer_n(&result->faceData, CD_MTFACE, n);
MLoopUV *mloopuv = CustomData_get_layer_n(&result->loopData, CD_MLOOPUV, n);
float(*mloopuv)[2] = CustomData_get_layer_n(&result->loopData, CD_PROP_FLOAT2, n);
if (!dmloopuv || (!tface && !mloopuv)) {
return;
@@ -421,7 +421,7 @@ static void set_subsurf_legacy_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *
/* load coordinates from uvss into tface */
MTFace *tf = tface;
MLoopUV *mluv = mloopuv;
float(*mluv)[2] = mloopuv;
for (index = 0; index < totface; index++) {
CCGFace *f = faceMap[index];
@@ -446,10 +446,10 @@ static void set_subsurf_legacy_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *
}
if (mluv) {
copy_v2_v2(mluv[0].uv, a);
copy_v2_v2(mluv[1].uv, d);
copy_v2_v2(mluv[2].uv, c);
copy_v2_v2(mluv[3].uv, b);
copy_v2_v2(mluv[0], a);
copy_v2_v2(mluv[1], d);
copy_v2_v2(mluv[2], c);
copy_v2_v2(mluv[3], b);
mluv += 4;
}
}
@@ -1801,8 +1801,8 @@ static void set_ccgdm_all_geometry(CCGDerivedMesh *ccgdm,
if (useSubsurfUv) {
CustomData *ldata = &ccgdm->dm.loopData;
CustomData *dmldata = &dm->loopData;
int numlayer = CustomData_number_of_layers(ldata, CD_MLOOPUV);
int dmnumlayer = CustomData_number_of_layers(dmldata, CD_MLOOPUV);
int numlayer = CustomData_number_of_layers(ldata, CD_PROP_FLOAT2);
int dmnumlayer = CustomData_number_of_layers(dmldata, CD_PROP_FLOAT2);
for (i = 0; i < numlayer && i < dmnumlayer; i++) {
set_subsurf_uv(ss, dm, &ccgdm->dm, i);
@@ -1792,7 +1792,8 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
if (DNA_struct_find(fd->filesdna, "MTexPoly")) {
for (Mesh *me = bmain->meshes.first; me; me = me->id.next) {
/* If we have UV's, so this file will have MTexPoly layers too! */
if (CustomData_has_layer(&me->ldata, CD_MLOOPUV)) {
if (CustomData_has_layer(&me->ldata, CD_MLOOPUV) ||
CustomData_has_layer(&me->ldata, CD_PROP_FLOAT2)) {
CustomData_update_typemap(&me->pdata);
CustomData_free_layers(&me->pdata, CD_MTEXPOLY, me->totpoly);
}
@@ -29,6 +29,7 @@ static void version_mesh_legacy_to_struct_of_array_format(Mesh &mesh)
{
BKE_mesh_legacy_convert_flags_to_selection_layers(&mesh);
BKE_mesh_legacy_convert_flags_to_hide_layers(&mesh);
BKE_mesh_legacy_convert_uvs_to_generic(&mesh);
BKE_mesh_legacy_convert_mpoly_to_material_indices(&mesh);
BKE_mesh_legacy_bevel_weight_to_layers(&mesh);
BKE_mesh_legacy_face_set_to_generic(&mesh);
@@ -351,17 +351,16 @@ static void blo_update_defaults_scene(Main *bmain, Scene *scene)
/* Correct default startup UV's. */
Mesh *me = static_cast<Mesh *>(BLI_findstring(&bmain->meshes, "Cube", offsetof(ID, name) + 2));
if (me && (me->totloop == 24) && CustomData_has_layer(&me->ldata, CD_MLOOPUV)) {
MLoopUV *mloopuv = static_cast<MLoopUV *>(CustomData_get_layer(&me->ldata, CD_MLOOPUV));
if (me && (me->totloop == 24) && CustomData_has_layer(&me->ldata, CD_PROP_FLOAT2)) {
const float uv_values[24][2] = {
{0.625, 0.50}, {0.875, 0.50}, {0.875, 0.75}, {0.625, 0.75}, {0.375, 0.75}, {0.625, 0.75},
{0.625, 1.00}, {0.375, 1.00}, {0.375, 0.00}, {0.625, 0.00}, {0.625, 0.25}, {0.375, 0.25},
{0.125, 0.50}, {0.375, 0.50}, {0.375, 0.75}, {0.125, 0.75}, {0.375, 0.50}, {0.625, 0.50},
{0.625, 0.75}, {0.375, 0.75}, {0.375, 0.25}, {0.625, 0.25}, {0.625, 0.50}, {0.375, 0.50},
};
for (int i = 0; i < ARRAY_SIZE(uv_values); i++) {
copy_v2_v2(mloopuv[i].uv, uv_values[i]);
}
float(*mloopuv)[2] = static_cast<float(*)[2]>(
CustomData_get_layer(&me->ldata, CD_PROP_FLOAT2));
memcpy(mloopuv, uv_values, sizeof(float[2]) * me->totloop);
}
/* Make sure that the curve profile is initialized */
+1
View File
@@ -173,6 +173,7 @@
* - Use two different iterator types for BMO map/buffer types.
*/
#include "BKE_customdata.h"
#include "DNA_customdata_types.h" /* BMesh struct in bmesh_class.h uses */
#include "DNA_listBase.h" /* selection history uses */
+13
View File
@@ -533,6 +533,19 @@ typedef bool (*BMLoopPairFilterFunc)(const BMLoop *, const BMLoop *, void *user_
#define BM_ELEM_CD_GET_BOOL(ele, offset) \
(BLI_assert(offset != -1), *((bool *)((char *)(ele)->head.data + (offset))))
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
# define BM_ELEM_CD_GET_BOOL_P(ele, offset) \
(BLI_assert(offset != -1), \
_Generic(ele, \
GENERIC_TYPE_ANY((bool *)POINTER_OFFSET((ele)->head.data, offset), \
_BM_GENERIC_TYPE_ELEM_NONCONST), \
GENERIC_TYPE_ANY((const bool *)POINTER_OFFSET((ele)->head.data, offset), \
_BM_GENERIC_TYPE_ELEM_CONST)))
#else
# define BM_ELEM_CD_GET_BOOL_P(ele, offset) \
(BLI_assert(offset != -1), (bool *)((char *)(ele)->head.data + (offset)))
#endif
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
# define BM_ELEM_CD_GET_VOID_P(ele, offset) \
(BLI_assert(offset != -1), \
@@ -15,8 +15,10 @@
#include "BLI_linklist.h"
#include "BLI_math.h"
#include "BLI_memarena.h"
#include "BLI_string.h"
#include "BLI_task.h"
#include "BKE_attribute.h"
#include "BKE_customdata.h"
#include "BKE_multires.h"
@@ -864,6 +866,61 @@ void BM_data_layer_add_named(BMesh *bm, CustomData *data, int type, const char *
}
}
void BM_data_layer_ensure_named(BMesh *bm, CustomData *data, int type, const char *name)
{
if (CustomData_get_named_layer_index(data, type, name) == -1) {
BM_data_layer_add_named(bm, data, type, name);
}
}
void BM_uv_map_ensure_select_and_pin_attrs(BMesh *bm)
{
const int nr_uv_layers = CustomData_number_of_layers(&bm->ldata, CD_PROP_FLOAT2);
for (int l = 0; l < nr_uv_layers; l++) {
/* NOTE: you can't re-use the returnvalue of CustomData_get_layer_name() because adding layers
* can invalidate that. */
char name[MAX_CUSTOMDATA_LAYER_NAME];
BM_data_layer_ensure_named(
bm,
&bm->ldata,
CD_PROP_BOOL,
BKE_uv_map_vert_select_name_get(CustomData_get_layer_name(&bm->ldata, CD_PROP_FLOAT2, l),
name));
BM_data_layer_ensure_named(
bm,
&bm->ldata,
CD_PROP_BOOL,
BKE_uv_map_edge_select_name_get(CustomData_get_layer_name(&bm->ldata, CD_PROP_FLOAT2, l),
name));
BM_data_layer_ensure_named(
bm,
&bm->ldata,
CD_PROP_BOOL,
BKE_uv_map_pin_name_get(CustomData_get_layer_name(&bm->ldata, CD_PROP_FLOAT2, l), name));
}
}
void BM_uv_map_ensure_vert_select_attr(BMesh *bm, const char *uv_map_name)
{
char name[MAX_CUSTOMDATA_LAYER_NAME];
BM_data_layer_ensure_named(
bm, &bm->ldata, CD_PROP_BOOL, BKE_uv_map_vert_select_name_get(uv_map_name, name));
}
void BM_uv_map_ensure_edge_select_attr(BMesh *bm, const char *uv_map_name)
{
char name[MAX_CUSTOMDATA_LAYER_NAME];
BM_data_layer_ensure_named(
bm, &bm->ldata, CD_PROP_BOOL, BKE_uv_map_edge_select_name_get(uv_map_name, name));
}
void BM_uv_map_ensure_pin_attr(BMesh *bm, const char *uv_map_name)
{
char name[MAX_CUSTOMDATA_LAYER_NAME];
BM_data_layer_ensure_named(
bm, &bm->ldata, CD_PROP_BOOL, BKE_uv_map_pin_name_get(uv_map_name, name));
}
void BM_data_layer_free(BMesh *bm, CustomData *data, int type)
{
CustomData olddata = *data;
@@ -62,7 +62,16 @@ void BM_data_interp_face_vert_edge(
BMesh *bm, const BMVert *v_src_1, const BMVert *v_src_2, BMVert *v, BMEdge *e, float fac);
void BM_data_layer_add(BMesh *bm, CustomData *data, int type);
void BM_data_layer_add_named(BMesh *bm, CustomData *data, int type, const char *name);
void BM_data_layer_ensure_named(BMesh *bm, CustomData *data, int type, const char *name);
void BM_data_layer_free(BMesh *bm, CustomData *data, int type);
/** Ensure the dependent boolean layers exist for all face corner #CD_PROP_FLOAT2 layers. */
void BM_uv_map_ensure_select_and_pin_attrs(BMesh *bm);
void BM_uv_map_ensure_vert_select_attr(BMesh *bm, const char *uv_map_name);
void BM_uv_map_ensure_edge_select_attr(BMesh *bm, const char *uv_map_name);
void BM_uv_map_ensure_pin_attr(BMesh *bm, const char *uv_map_name);
/**
* Remove a named custom data layer, if it existed. Return true if the layer was removed.
*/
@@ -149,7 +149,40 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar
mask.pmask);
CustomData mesh_ldata = CustomData_shallow_copy_remove_non_bmesh_attributes(&me->ldata,
mask.lmask);
blender::Vector<std::string> temporary_layers_to_delete;
for (const int layer_index :
IndexRange(CustomData_number_of_layers(&mesh_ldata, CD_PROP_FLOAT2))) {
char name[MAX_CUSTOMDATA_LAYER_NAME];
BKE_uv_map_vert_select_name_get(
CustomData_get_layer_name(&mesh_ldata, CD_PROP_FLOAT2, layer_index), name);
if (CustomData_get_named_layer_index(&mesh_ldata, CD_PROP_BOOL, name) < 0) {
CustomData_add_layer_named(
&mesh_ldata, CD_PROP_BOOL, CD_SET_DEFAULT, nullptr, me->totloop, name);
temporary_layers_to_delete.append(std::string(name));
}
BKE_uv_map_edge_select_name_get(
CustomData_get_layer_name(&mesh_ldata, CD_PROP_FLOAT2, layer_index), name);
if (CustomData_get_named_layer_index(&mesh_ldata, CD_PROP_BOOL, name) < 0) {
CustomData_add_layer_named(
&mesh_ldata, CD_PROP_BOOL, CD_SET_DEFAULT, nullptr, me->totloop, name);
temporary_layers_to_delete.append(std::string(name));
}
BKE_uv_map_pin_name_get(CustomData_get_layer_name(&mesh_ldata, CD_PROP_FLOAT2, layer_index),
name);
if (CustomData_get_named_layer_index(&mesh_ldata, CD_PROP_BOOL, name) < 0) {
CustomData_add_layer_named(
&mesh_ldata, CD_PROP_BOOL, CD_SET_DEFAULT, nullptr, me->totloop, name);
temporary_layers_to_delete.append(std::string(name));
}
}
BLI_SCOPED_DEFER([&]() {
for (const std::string &name : temporary_layers_to_delete) {
CustomData_free_layer_named(&mesh_ldata, name.c_str(), me->totloop);
}
MEM_SAFE_FREE(mesh_vdata.layers);
MEM_SAFE_FREE(mesh_edata.layers);
MEM_SAFE_FREE(mesh_pdata.layers);
@@ -956,6 +989,54 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
me->totface = 0;
me->act_face = -1;
/* Mark UV selection layers which are all false as 'nocopy'. */
for (const int layer_index :
IndexRange(CustomData_number_of_layers(&bm->ldata, CD_PROP_FLOAT2))) {
char const *layer_name = CustomData_get_layer_name(&bm->ldata, CD_PROP_FLOAT2, layer_index);
char sub_layer_name[MAX_CUSTOMDATA_LAYER_NAME];
int vertsel_layer_index = CustomData_get_named_layer_index(
&bm->ldata, CD_PROP_BOOL, BKE_uv_map_vert_select_name_get(layer_name, sub_layer_name));
int edgesel_layer_index = CustomData_get_named_layer_index(
&bm->ldata, CD_PROP_BOOL, BKE_uv_map_edge_select_name_get(layer_name, sub_layer_name));
int pin_layer_index = CustomData_get_named_layer_index(
&bm->ldata, CD_PROP_BOOL, BKE_uv_map_pin_name_get(layer_name, sub_layer_name));
int vertsel_offset = bm->ldata.layers[vertsel_layer_index].offset;
int edgesel_offset = bm->ldata.layers[edgesel_layer_index].offset;
int pin_offset = bm->ldata.layers[pin_layer_index].offset;
bool need_vertsel = false;
bool need_edgesel = false;
bool need_pin = false;
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
BMIter liter;
BMLoop *l;
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
need_vertsel |= BM_ELEM_CD_GET_BOOL(l, vertsel_offset);
need_edgesel |= BM_ELEM_CD_GET_BOOL(l, edgesel_offset);
need_pin |= BM_ELEM_CD_GET_BOOL(l, pin_offset);
}
}
if (need_vertsel) {
bm->ldata.layers[vertsel_layer_index].flag &= ~CD_FLAG_NOCOPY;
}
else {
bm->ldata.layers[vertsel_layer_index].flag |= CD_FLAG_NOCOPY;
}
if (need_edgesel) {
bm->ldata.layers[edgesel_layer_index].flag &= ~CD_FLAG_NOCOPY;
}
else {
bm->ldata.layers[edgesel_layer_index].flag |= CD_FLAG_NOCOPY;
}
if (need_pin) {
bm->ldata.layers[pin_layer_index].flag &= ~CD_FLAG_NOCOPY;
}
else {
bm->ldata.layers[pin_layer_index].flag |= CD_FLAG_NOCOPY;
}
}
{
CustomData_MeshMasks mask = CD_MASK_MESH;
CustomData_MeshMasks_update(&mask, &params->cd_mask_extra);
+3 -3
View File
@@ -234,9 +234,9 @@ float BM_face_calc_area_uv(const BMFace *f, int cd_loop_uv_offset)
/* The Trapezium Area Rule */
float cross = 0.0f;
do {
const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset);
const MLoopUV *luv_next = BM_ELEM_CD_GET_VOID_P(l_iter->next, cd_loop_uv_offset);
cross += (luv_next->uv[0] - luv->uv[0]) * (luv_next->uv[1] + luv->uv[1]);
const float *luv = BM_ELEM_CD_GET_FLOAT_P(l_iter, cd_loop_uv_offset);
const float *luv_next = BM_ELEM_CD_GET_FLOAT_P(l_iter->next, cd_loop_uv_offset);
cross += (luv_next[0] - luv[0]) * (luv_next[1] + luv[1]);
} while ((l_iter = l_iter->next) != l_first);
return fabsf(cross * 0.5f);
}
+43 -22
View File
@@ -12,6 +12,7 @@
#include "BLI_math_vector_types.hh"
#include "BLI_utildefines_stack.h"
#include "BKE_attribute.hh"
#include "BKE_customdata.h"
#include "DNA_meshdata_types.h"
@@ -19,12 +20,36 @@
#include "bmesh.h"
#include "intern/bmesh_private.h"
BMUVOffsets BM_uv_map_get_offsets(const BMesh *bm)
{
using namespace blender;
using namespace blender::bke;
const int layer_index = CustomData_get_active_layer_index(&bm->ldata, CD_PROP_FLOAT2);
if (layer_index == -1) {
return {-1, -1, -1, -1};
}
char const *name = bm->ldata.layers[layer_index].name;
char buffer[MAX_CUSTOMDATA_LAYER_NAME];
BMUVOffsets offsets;
offsets.uv = bm->ldata.layers[layer_index].offset;
offsets.select_vert = CustomData_get_offset_named(
&bm->ldata, CD_PROP_BOOL, BKE_uv_map_vert_select_name_get(name, buffer));
offsets.select_edge = CustomData_get_offset_named(
&bm->ldata, CD_PROP_BOOL, BKE_uv_map_edge_select_name_get(name, buffer));
offsets.pin = CustomData_get_offset_named(
&bm->ldata, CD_PROP_BOOL, BKE_uv_map_pin_name_get(name, buffer));
return offsets;
}
static void uv_aspect(const BMLoop *l,
const float aspect[2],
const int cd_loop_uv_offset,
float r_uv[2])
{
const float *uv = ((const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset))->uv;
const float *uv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset);
r_uv[0] = uv[0] * aspect[0];
r_uv[1] = uv[1] * aspect[1];
}
@@ -81,8 +106,8 @@ void BM_face_uv_calc_center_median(const BMFace *f, const int cd_loop_uv_offset,
zero_v2(r_cent);
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
const MLoopUV *luv = (const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset);
add_v2_v2(r_cent, luv->uv);
const float *luv = BM_ELEM_CD_GET_FLOAT_P(l_iter, cd_loop_uv_offset);
add_v2_v2(r_cent, luv);
} while ((l_iter = l_iter->next) != l_first);
mul_v2_fl(r_cent, 1.0f / float(f->len));
@@ -96,8 +121,7 @@ float BM_face_uv_calc_cross(const BMFace *f, const int cd_loop_uv_offset)
int i = 0;
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
const MLoopUV *luv = (const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset);
uvs[i++] = luv->uv;
uvs[i++] = BM_ELEM_CD_GET_FLOAT2_P(l_iter, cd_loop_uv_offset);
} while ((l_iter = l_iter->next) != l_first);
return cross_poly_v2(reinterpret_cast<const float(*)[2]>(uvs.data()), f->len);
}
@@ -108,31 +132,30 @@ void BM_face_uv_minmax(const BMFace *f, float min[2], float max[2], const int cd
const BMLoop *l_first;
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
const MLoopUV *luv = (const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset);
minmax_v2v2_v2(min, max, luv->uv);
const float *luv = BM_ELEM_CD_GET_FLOAT_P(l_iter, cd_loop_uv_offset);
minmax_v2v2_v2(min, max, luv);
} while ((l_iter = l_iter->next) != l_first);
}
bool BM_loop_uv_share_edge_check(BMLoop *l_a, BMLoop *l_b, const int cd_loop_uv_offset)
{
BLI_assert(l_a->e == l_b->e);
MLoopUV *luv_a_curr = (MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_a, cd_loop_uv_offset);
MLoopUV *luv_a_next = (MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_a->next, cd_loop_uv_offset);
MLoopUV *luv_b_curr = (MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_b, cd_loop_uv_offset);
MLoopUV *luv_b_next = (MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_b->next, cd_loop_uv_offset);
float *luv_a_curr = BM_ELEM_CD_GET_FLOAT_P(l_a, cd_loop_uv_offset);
float *luv_a_next = BM_ELEM_CD_GET_FLOAT_P(l_a->next, cd_loop_uv_offset);
float *luv_b_curr = BM_ELEM_CD_GET_FLOAT_P(l_b, cd_loop_uv_offset);
float *luv_b_next = BM_ELEM_CD_GET_FLOAT_P(l_b->next, cd_loop_uv_offset);
if (l_a->v != l_b->v) {
std::swap(luv_b_curr, luv_b_next);
}
return (equals_v2v2(luv_a_curr->uv, luv_b_curr->uv) &&
equals_v2v2(luv_a_next->uv, luv_b_next->uv));
return (equals_v2v2(luv_a_curr, luv_b_curr) && equals_v2v2(luv_a_next, luv_b_next));
}
bool BM_loop_uv_share_vert_check(BMLoop *l_a, BMLoop *l_b, const int cd_loop_uv_offset)
{
BLI_assert(l_a->v == l_b->v);
const MLoopUV *luv_a = (const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_a, cd_loop_uv_offset);
const MLoopUV *luv_b = (const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_b, cd_loop_uv_offset);
if (!equals_v2v2(luv_a->uv, luv_b->uv)) {
const float *luv_a = BM_ELEM_CD_GET_FLOAT_P(l_a, cd_loop_uv_offset);
const float *luv_b = BM_ELEM_CD_GET_FLOAT_P(l_b, cd_loop_uv_offset);
if (!equals_v2v2(luv_a, luv_b)) {
return false;
}
return true;
@@ -150,11 +173,9 @@ bool BM_edge_uv_share_vert_check(BMEdge *e, BMLoop *l_a, BMLoop *l_b, const int
const BMLoop *l_other_b = BM_loop_other_vert_loop_by_edge(l_b, e);
{
const MLoopUV *luv_other_a = (const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_other_a,
cd_loop_uv_offset);
const MLoopUV *luv_other_b = (const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_other_b,
cd_loop_uv_offset);
if (!equals_v2v2(luv_other_a->uv, luv_other_b->uv)) {
const float *luv_other_a = BM_ELEM_CD_GET_FLOAT_P(l_other_a, cd_loop_uv_offset);
const float *luv_other_b = BM_ELEM_CD_GET_FLOAT_P(l_other_b, cd_loop_uv_offset);
if (!equals_v2v2(luv_other_a, luv_other_b)) {
return false;
}
}
@@ -172,7 +193,7 @@ bool BM_face_uv_point_inside_test(const BMFace *f, const float co[2], const int
BLI_assert(BM_face_is_normal_valid(f));
for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f); i < f->len; i++, l_iter = l_iter->next) {
projverts[i] = ((const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset))->uv;
projverts[i] = BM_ELEM_CD_GET_FLOAT2_P(l_iter, cd_loop_uv_offset);
}
return isect_point_poly_v2(
@@ -10,6 +10,11 @@
extern "C" {
#endif
/**
* Retrieve the custom data offsets for layers used for user interaction with the active UV map.
*/
BMUVOffsets BM_uv_map_get_offsets(const BMesh *bm);
float BM_loop_uv_calc_edge_length_squared(const BMLoop *l,
int cd_loop_uv_offset) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
@@ -277,7 +277,8 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op)
}
if (BMO_slot_bool_get(op->slots_in, "cmp_uvs") &&
bm_edge_delimit_cdata(&bm->ldata, CD_MLOOPUV, &delimit_data.cdata[delimit_data.cdata_len])) {
bm_edge_delimit_cdata(
&bm->ldata, CD_PROP_FLOAT2, &delimit_data.cdata[delimit_data.cdata_len])) {
delimit_data.cdata_len += 1;
}
+9 -9
View File
@@ -67,30 +67,30 @@ void bmo_mirror_exec(BMesh *bm, BMOperator *op)
if (mirror_u || mirror_v) {
BMFace *f;
BMLoop *l;
MLoopUV *luv;
const int totlayer = CustomData_number_of_layers(&bm->ldata, CD_MLOOPUV);
float *luv;
const int totlayer = CustomData_number_of_layers(&bm->ldata, CD_PROP_FLOAT2);
BMIter liter;
BMO_ITER (f, &siter, dupeop.slots_out, "geom.out", BM_FACE) {
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
for (i = 0; i < totlayer; i++) {
luv = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPUV, i);
luv = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_PROP_FLOAT2, i);
if (mirror_u) {
float uv_u = luv->uv[0];
float uv_u = luv[0];
if (mirror_udim) {
luv->uv[0] = ceilf(uv_u) - fmodf(uv_u, 1.0f);
luv[0] = ceilf(uv_u) - fmodf(uv_u, 1.0f);
}
else {
luv->uv[0] = 1.0f - uv_u;
luv[0] = 1.0f - uv_u;
}
}
if (mirror_v) {
float uv_v = luv->uv[1];
float uv_v = luv[1];
if (mirror_udim) {
luv->uv[1] = ceilf(uv_v) - fmodf(uv_v, 1.0f);
luv[1] = ceilf(uv_v) - fmodf(uv_v, 1.0f);
}
else {
luv->uv[1] = 1.0f - uv_v;
luv[1] = 1.0f - uv_v;
}
}
}
+43 -43
View File
@@ -719,7 +719,7 @@ void bmo_create_grid_exec(BMesh *bm, BMOperator *op)
const float xtot_inv2 = 2.0f / (xtot);
const float ytot_inv2 = 2.0f / (ytot);
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_PROP_FLOAT2);
const bool calc_uvs = (cd_loop_uv_offset != -1) && BMO_slot_bool_get(op->slots_in, "calc_uvs");
BMVert **varr;
@@ -799,7 +799,7 @@ void BM_mesh_calc_uvs_grid(BMesh *bm,
}
BM_ITER_ELEM_INDEX (l, &liter, f, BM_LOOPS_OF_FACE, loop_index) {
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset);
switch (loop_index) {
case 0:
@@ -818,8 +818,8 @@ void BM_mesh_calc_uvs_grid(BMesh *bm,
break;
}
luv->uv[0] = x;
luv->uv[1] = y;
luv[0] = x;
luv[1] = y;
}
x += dx;
@@ -836,7 +836,7 @@ void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op)
const int seg = BMO_slot_int_get(op->slots_in, "u_segments");
const int tot = BMO_slot_int_get(op->slots_in, "v_segments");
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_PROP_FLOAT2);
const bool calc_uvs = (cd_loop_uv_offset != -1) && BMO_slot_bool_get(op->slots_in, "calc_uvs");
BMOperator bmop, prevop;
@@ -955,7 +955,7 @@ void bmo_create_icosphere_exec(BMesh *bm, BMOperator *op)
const float rad_div = rad / 200.0f;
const int subdiv = BMO_slot_int_get(op->slots_in, "subdivisions");
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_PROP_FLOAT2);
const bool calc_uvs = (cd_loop_uv_offset != -1) && BMO_slot_bool_get(op->slots_in, "calc_uvs");
BMVert *eva[12];
@@ -1000,9 +1000,9 @@ void bmo_create_icosphere_exec(BMesh *bm, BMOperator *op)
if (calc_uvs) {
int loop_index;
BM_ITER_ELEM_INDEX (l, &liter, f, BM_LOOPS_OF_FACE, loop_index) {
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
luv->uv[0] = icouvs[uvi][0];
luv->uv[1] = icouvs[uvi][1];
float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset);
luv[0] = icouvs[uvi][0];
luv[1] = icouvs[uvi][1];
uvi++;
}
}
@@ -1063,7 +1063,7 @@ static void bm_mesh_calc_uvs_sphere_face(BMFace *f, const int cd_loop_uv_offset)
avgy /= 3.0f;
BM_ITER_ELEM_INDEX (l, &iter, f, BM_LOOPS_OF_FACE, loop_index) {
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset);
float x = l->v->co[0];
float y = l->v->co[1];
float z = l->v->co[2];
@@ -1084,10 +1084,10 @@ static void bm_mesh_calc_uvs_sphere_face(BMFace *f, const int cd_loop_uv_offset)
}
float phi = saacos(z / len);
luv->uv[0] = 0.5f + theta / ((float)M_PI * 2);
luv->uv[1] = 1.0f - phi / (float)M_PI;
luv[0] = 0.5f + theta / ((float)M_PI * 2);
luv[1] = 1.0f - phi / (float)M_PI;
uvs[loop_index] = luv->uv;
uvs[loop_index] = luv;
}
/* Fix awkwardly-wrapping UVs */
@@ -1133,9 +1133,9 @@ void BM_mesh_calc_uvs_sphere(BMesh *bm, const short oflag, const int cd_loop_uv_
continue;
}
BM_ITER_ELEM_INDEX (l, &iter2, f, BM_LOOPS_OF_FACE, loop_index) {
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (luv->uv[0] < minx) {
minx = luv->uv[0];
float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset);
if (luv[0] < minx) {
minx = luv[0];
}
}
}
@@ -1145,8 +1145,8 @@ void BM_mesh_calc_uvs_sphere(BMesh *bm, const short oflag, const int cd_loop_uv_
continue;
}
BM_ITER_ELEM_INDEX (l, &iter2, f, BM_LOOPS_OF_FACE, loop_index) {
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
luv->uv[0] -= minx;
float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset);
luv[0] -= minx;
}
}
}
@@ -1159,7 +1159,7 @@ void bmo_create_monkey_exec(BMesh *bm, BMOperator *op)
BMO_slot_mat4_get(op->slots_in, "matrix", mat);
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_PROP_FLOAT2);
const bool calc_uvs = (cd_loop_uv_offset != -1) && BMO_slot_bool_get(op->slots_in, "calc_uvs");
for (i = 0; i < monkeynv; i++) {
@@ -1213,15 +1213,15 @@ void bmo_create_monkey_exec(BMesh *bm, BMOperator *op)
BMLoop *l;
BMIter liter;
BM_ITER_ELEM (l, &liter, f_new_a, BM_LOOPS_OF_FACE) {
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
luv->uv[0] = monkeyuvs[uvi * 2 + 0];
luv->uv[1] = monkeyuvs[uvi * 2 + 1];
float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset);
luv[0] = monkeyuvs[uvi * 2 + 0];
luv[1] = monkeyuvs[uvi * 2 + 1];
uvi++;
}
BM_ITER_ELEM (l, &liter, f_new_b, BM_LOOPS_OF_FACE) {
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
luv->uv[0] = monkeyuvs[uvi * 2 + 0];
luv->uv[1] = monkeyuvs[uvi * 2 + 1];
float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset);
luv[0] = monkeyuvs[uvi * 2 + 0];
luv[1] = monkeyuvs[uvi * 2 + 1];
uvi++;
}
}
@@ -1239,7 +1239,7 @@ void bmo_create_circle_exec(BMesh *bm, BMOperator *op)
const bool cap_ends = BMO_slot_bool_get(op->slots_in, "cap_ends");
const bool cap_tris = BMO_slot_bool_get(op->slots_in, "cap_tris");
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_PROP_FLOAT2);
const bool calc_uvs = (cd_loop_uv_offset != -1) && BMO_slot_bool_get(op->slots_in, "calc_uvs");
BMVert *v1, *lastv1 = NULL, *cent1, *firstv1 = NULL;
@@ -1335,7 +1335,7 @@ void BM_mesh_calc_uvs_circle(
}
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset);
float uv_vco[3];
copy_v3_v3(uv_vco, l->v->co);
@@ -1343,8 +1343,8 @@ void BM_mesh_calc_uvs_circle(
mul_m4_v3(inv_mat, uv_vco);
/* then just take those coords for UVs */
luv->uv[0] = uv_center + uv_scale * uv_vco[0];
luv->uv[1] = uv_center + uv_scale * uv_vco[1];
luv[0] = uv_center + uv_scale * uv_vco[0];
luv[1] = uv_center + uv_scale * uv_vco[1];
}
}
}
@@ -1361,7 +1361,7 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op)
const bool cap_ends = BMO_slot_bool_get(op->slots_in, "cap_ends");
const bool cap_tris = BMO_slot_bool_get(op->slots_in, "cap_tris");
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_PROP_FLOAT2);
const bool calc_uvs = (cd_loop_uv_offset != -1) && BMO_slot_bool_get(op->slots_in, "calc_uvs");
if (!segs) {
@@ -1556,7 +1556,7 @@ void BM_mesh_calc_uvs_cone(BMesh *bm,
if (f->len == 4 && radius_top && radius_bottom) {
/* side face - so unwrap it in a rectangle */
BM_ITER_ELEM_INDEX (l, &liter, f, BM_LOOPS_OF_FACE, loop_index) {
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset);
switch (loop_index) {
case 0:
@@ -1575,8 +1575,8 @@ void BM_mesh_calc_uvs_cone(BMesh *bm,
break;
}
luv->uv[0] = x;
luv->uv[1] = y;
luv[0] = x;
luv[1] = y;
}
}
else {
@@ -1585,18 +1585,18 @@ void BM_mesh_calc_uvs_cone(BMesh *bm,
BM_face_normal_update(f);
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset);
float uv_vco[3];
mul_v3_m4v3(uv_vco, inv_mat, l->v->co);
if (dot_v3v3(f->no, local_up) > 0.0f) { /* if this is a top face of the cone */
luv->uv[0] = uv_center_x_top + uv_vco[0] * uv_scale_top;
luv->uv[1] = uv_center_y + uv_vco[1] * uv_scale_top;
luv[0] = uv_center_x_top + uv_vco[0] * uv_scale_top;
luv[1] = uv_center_y + uv_vco[1] * uv_scale_top;
}
else {
luv->uv[0] = uv_center_x_bottom + uv_vco[0] * uv_scale_bottom;
luv->uv[1] = uv_center_y + uv_vco[1] * uv_scale_bottom;
luv[0] = uv_center_x_bottom + uv_vco[0] * uv_scale_bottom;
luv[1] = uv_center_y + uv_vco[1] * uv_scale_bottom;
}
}
}
@@ -1609,7 +1609,7 @@ void bmo_create_cube_exec(BMesh *bm, BMOperator *op)
float mat[4][4];
float off = BMO_slot_float_get(op->slots_in, "size") / 2.0f;
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_PROP_FLOAT2);
const bool calc_uvs = (cd_loop_uv_offset != -1) && BMO_slot_bool_get(op->slots_in, "calc_uvs");
/* rotation order set to match 'BM_mesh_calc_uvs_cube' */
@@ -1670,7 +1670,7 @@ void BM_mesh_calc_uvs_cube(BMesh *bm, const short oflag)
BMIter fiter, liter;
const float width = 0.25f;
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_PROP_FLOAT2);
float x = 0.375f;
float y = 0.0f;
@@ -1685,10 +1685,10 @@ void BM_mesh_calc_uvs_cube(BMesh *bm, const short oflag)
}
BM_ITER_ELEM_INDEX (l, &liter, f, BM_LOOPS_OF_FACE, loop_index) {
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset);
luv->uv[0] = x;
luv->uv[1] = y;
luv[0] = x;
luv[1] = y;
switch (loop_index) {
case 0:
+20 -20
View File
@@ -462,56 +462,56 @@ void bmo_rotate_uvs_exec(BMesh *bm, BMOperator *op)
BMIter l_iter; /* iteration loop */
const bool use_ccw = BMO_slot_bool_get(op->slots_in, "use_ccw");
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_PROP_FLOAT2);
if (cd_loop_uv_offset != -1) {
BMO_ITER (fs, &fs_iter, op->slots_in, "faces", BM_FACE) {
if (use_ccw == false) { /* same loops direction */
BMLoop *lf; /* current face loops */
MLoopUV *f_luv; /* first face loop uv */
float *f_luv; /* first face loop uv */
float p_uv[2]; /* previous uvs */
float t_uv[2]; /* temp uvs */
int n = 0;
BM_ITER_ELEM (lf, &l_iter, fs, BM_LOOPS_OF_FACE) {
/* current loop uv is the previous loop uv */
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(lf, cd_loop_uv_offset);
float *luv = BM_ELEM_CD_GET_FLOAT_P(lf, cd_loop_uv_offset);
if (n == 0) {
f_luv = luv;
copy_v2_v2(p_uv, luv->uv);
copy_v2_v2(p_uv, luv);
}
else {
copy_v2_v2(t_uv, luv->uv);
copy_v2_v2(luv->uv, p_uv);
copy_v2_v2(t_uv, luv);
copy_v2_v2(luv, p_uv);
copy_v2_v2(p_uv, t_uv);
}
n++;
}
copy_v2_v2(f_luv->uv, p_uv);
copy_v2_v2(f_luv, p_uv);
}
else { /* counter loop direction */
BMLoop *lf; /* current face loops */
MLoopUV *p_luv; /* previous loop uv */
MLoopUV *luv;
else { /* counter loop direction */
BMLoop *lf; /* current face loops */
float *p_luv; /* previous loop uv */
float *luv;
float t_uv[2]; /* current uvs */
int n = 0;
BM_ITER_ELEM (lf, &l_iter, fs, BM_LOOPS_OF_FACE) {
/* previous loop uv is the current loop uv */
luv = BM_ELEM_CD_GET_VOID_P(lf, cd_loop_uv_offset);
luv = BM_ELEM_CD_GET_FLOAT_P(lf, cd_loop_uv_offset);
if (n == 0) {
p_luv = luv;
copy_v2_v2(t_uv, luv->uv);
copy_v2_v2(t_uv, luv);
}
else {
copy_v2_v2(p_luv->uv, luv->uv);
copy_v2_v2(p_luv, luv);
p_luv = luv;
}
n++;
}
copy_v2_v2(luv->uv, t_uv);
copy_v2_v2(luv, t_uv);
}
}
}
@@ -530,22 +530,22 @@ static void bm_face_reverse_uvs(BMFace *f, const int cd_loop_uv_offset)
float(*uvs)[2] = BLI_array_alloca(uvs, f->len);
BM_ITER_ELEM_INDEX (l, &iter, f, BM_LOOPS_OF_FACE, i) {
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
copy_v2_v2(uvs[i], luv->uv);
float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset);
copy_v2_v2(uvs[i], luv);
}
/* now that we have the uvs in the array, reverse! */
BM_ITER_ELEM_INDEX (l, &iter, f, BM_LOOPS_OF_FACE, i) {
/* current loop uv is the previous loop uv */
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
copy_v2_v2(luv->uv, uvs[(f->len - i - 1)]);
float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset);
copy_v2_v2(luv, uvs[(f->len - i - 1)]);
}
}
void bmo_reverse_uvs_exec(BMesh *bm, BMOperator *op)
{
BMOIter iter;
BMFace *f;
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_PROP_FLOAT2);
if (cd_loop_uv_offset != -1) {
BMO_ITER (f, &iter, op->slots_in, "faces", BM_FACE) {
+17 -17
View File
@@ -811,7 +811,7 @@ static void math_layer_info_init(BevelParams *bp, BMesh *bm)
bp->math_layer_info.has_math_layers = false;
bp->math_layer_info.face_component = NULL;
for (int i = 0; i < bm->ldata.totlayer; i++) {
if (CustomData_has_layer(&bm->ldata, CD_MLOOPUV)) {
if (CustomData_has_layer(&bm->ldata, CD_PROP_FLOAT2)) {
bp->math_layer_info.has_math_layers = true;
break;
}
@@ -1009,10 +1009,10 @@ static BMFace *choose_rep_face(BevelParams *bp, BMFace **face, int nfaces)
* Caller should ensure that no seams are violated by doing this. */
static void bev_merge_uvs(BMesh *bm, BMVert *v)
{
int num_of_uv_layers = CustomData_number_of_layers(&bm->ldata, CD_MLOOPUV);
int num_of_uv_layers = CustomData_number_of_layers(&bm->ldata, CD_PROP_FLOAT2);
for (int i = 0; i < num_of_uv_layers; i++) {
int cd_loop_uv_offset = CustomData_get_n_offset(&bm->ldata, CD_MLOOPUV, i);
int cd_loop_uv_offset = CustomData_get_n_offset(&bm->ldata, CD_PROP_FLOAT2, i);
if (cd_loop_uv_offset == -1) {
return;
@@ -1023,15 +1023,15 @@ static void bev_merge_uvs(BMesh *bm, BMVert *v)
BMIter iter;
BMLoop *l;
BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
add_v2_v2(uv, luv->uv);
float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset);
add_v2_v2(uv, luv);
n++;
}
if (n > 1) {
mul_v2_fl(uv, 1.0f / (float)n);
BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
copy_v2_v2(luv->uv, uv);
float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset);
copy_v2_v2(luv, uv);
}
}
}
@@ -1041,7 +1041,7 @@ static void bev_merge_uvs(BMesh *bm, BMVert *v)
* and part of faces that share edge bme. */
static void bev_merge_edge_uvs(BMesh *bm, BMEdge *bme, BMVert *v)
{
int num_of_uv_layers = CustomData_number_of_layers(&bm->ldata, CD_MLOOPUV);
int num_of_uv_layers = CustomData_number_of_layers(&bm->ldata, CD_PROP_FLOAT2);
BMLoop *l1 = NULL;
BMLoop *l2 = NULL;
@@ -1060,22 +1060,22 @@ static void bev_merge_edge_uvs(BMesh *bm, BMEdge *bme, BMVert *v)
}
for (int i = 0; i < num_of_uv_layers; i++) {
int cd_loop_uv_offset = CustomData_get_n_offset(&bm->ldata, CD_MLOOPUV, i);
int cd_loop_uv_offset = CustomData_get_n_offset(&bm->ldata, CD_PROP_FLOAT2, i);
if (cd_loop_uv_offset == -1) {
return;
}
float uv[2] = {0.0f, 0.0f};
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l1, cd_loop_uv_offset);
add_v2_v2(uv, luv->uv);
luv = BM_ELEM_CD_GET_VOID_P(l2, cd_loop_uv_offset);
add_v2_v2(uv, luv->uv);
float *luv = BM_ELEM_CD_GET_FLOAT_P(l1, cd_loop_uv_offset);
add_v2_v2(uv, luv);
luv = BM_ELEM_CD_GET_FLOAT_P(l2, cd_loop_uv_offset);
add_v2_v2(uv, luv);
mul_v2_fl(uv, 0.5f);
luv = BM_ELEM_CD_GET_VOID_P(l1, cd_loop_uv_offset);
copy_v2_v2(luv->uv, uv);
luv = BM_ELEM_CD_GET_VOID_P(l2, cd_loop_uv_offset);
copy_v2_v2(luv->uv, uv);
luv = BM_ELEM_CD_GET_FLOAT_P(l1, cd_loop_uv_offset);
copy_v2_v2(luv, uv);
luv = BM_ELEM_CD_GET_FLOAT_P(l2, cd_loop_uv_offset);
copy_v2_v2(luv, uv);
}
}
@@ -289,14 +289,14 @@ void BM_mesh_decimate_dissolve_ex(BMesh *bm,
int i;
if (delimit & BMO_DELIM_UV) {
const int layer_len = CustomData_number_of_layers(&bm->ldata, CD_MLOOPUV);
const int layer_len = CustomData_number_of_layers(&bm->ldata, CD_PROP_FLOAT2);
if (layer_len == 0) {
delimit &= ~BMO_DELIM_UV;
}
else {
delimit_data.cd_loop_type = CD_MLOOPUV;
delimit_data.cd_loop_type = CD_PROP_FLOAT2;
delimit_data.cd_loop_size = CustomData_sizeof(delimit_data.cd_loop_type);
delimit_data.cd_loop_offset = CustomData_get_n_offset(&bm->ldata, CD_MLOOPUV, 0);
delimit_data.cd_loop_offset = CustomData_get_n_offset(&bm->ldata, CD_PROP_FLOAT2, 0);
delimit_data.cd_loop_offset_end = delimit_data.cd_loop_size * layer_len;
}
}
+19 -20
View File
@@ -67,23 +67,23 @@ static void verttag_add_adjacent_uv(HeapSimple *heap,
BLI_assert(params->aspect_y != 0.0f);
const int cd_loop_uv_offset = params->cd_loop_uv_offset;
const int l_a_index = BM_elem_index_get(l_a);
const MLoopUV *luv_a = BM_ELEM_CD_GET_VOID_P(l_a, cd_loop_uv_offset);
const float uv_a[2] = {luv_a->uv[0], luv_a->uv[1] / params->aspect_y};
const float *luv_a = BM_ELEM_CD_GET_FLOAT_P(l_a, cd_loop_uv_offset);
const float uv_a[2] = {luv_a[0], luv_a[1] / params->aspect_y};
{
BMIter liter;
BMLoop *l;
/* Loop over faces of face, but do so by first looping over loops. */
BM_ITER_ELEM (l, &liter, l_a->v, BM_LOOPS_OF_VERT) {
const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (equals_v2v2(luv_a->uv, luv->uv)) {
const float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset);
if (equals_v2v2(luv_a, luv)) {
/* 'l_a' is already tagged, tag all adjacent. */
BM_elem_flag_enable(l, BM_ELEM_TAG);
BMLoop *l_b = l->next;
do {
if (!BM_elem_flag_test(l_b, BM_ELEM_TAG)) {
const MLoopUV *luv_b = BM_ELEM_CD_GET_VOID_P(l_b, cd_loop_uv_offset);
const float uv_b[2] = {luv_b->uv[0], luv_b->uv[1] / params->aspect_y};
const float *luv_b = BM_ELEM_CD_GET_FLOAT_P(l_b, cd_loop_uv_offset);
const float uv_b[2] = {luv_b[0], luv_b[1] / params->aspect_y};
/* We know 'l_b' is not visited, check it out! */
const int l_b_index = BM_elem_index_get(l_b);
const float cost_cut = params->use_topology_distance ? 1.0f : len_v2v2(uv_a, uv_b);
@@ -189,13 +189,13 @@ static float edgetag_cut_cost_vert_uv(
BMLoop *l_v1 = (l_v->v == l_e_a->v) ? l_e_a->next : l_e_a;
BMLoop *l_v2 = (l_v->v == l_e_b->v) ? l_e_b->next : l_e_b;
MLoopUV *luv_v1 = BM_ELEM_CD_GET_VOID_P(l_v1, cd_loop_uv_offset);
MLoopUV *luv_v2 = BM_ELEM_CD_GET_VOID_P(l_v2, cd_loop_uv_offset);
MLoopUV *luv_v = BM_ELEM_CD_GET_VOID_P(l_v, cd_loop_uv_offset);
float *luv_v1 = BM_ELEM_CD_GET_FLOAT_P(l_v1, cd_loop_uv_offset);
float *luv_v2 = BM_ELEM_CD_GET_FLOAT_P(l_v2, cd_loop_uv_offset);
float *luv_v = BM_ELEM_CD_GET_FLOAT_P(l_v, cd_loop_uv_offset);
float uv_v1[2] = {luv_v1->uv[0], luv_v1->uv[1] / aspect_y};
float uv_v2[2] = {luv_v2->uv[0], luv_v2->uv[1] / aspect_y};
float uv_v[2] = {luv_v->uv[0], luv_v->uv[1] / aspect_y};
float uv_v1[2] = {luv_v1[0], luv_v1[1] / aspect_y};
float uv_v2[2] = {luv_v2[0], luv_v2[1] / aspect_y};
float uv_v[2] = {luv_v[0], luv_v[1] / aspect_y};
return step_cost_3_v2(uv_v1, uv_v, uv_v2);
}
@@ -204,11 +204,11 @@ static float edgetag_cut_cost_face_uv(
BMLoop *l_e_a, BMLoop *l_e_b, BMFace *f, const float aspect_v2[2], const int cd_loop_uv_offset)
{
float l_e_a_cent[2], l_e_b_cent[2], f_cent[2];
MLoopUV *luv_e_a = BM_ELEM_CD_GET_VOID_P(l_e_a, cd_loop_uv_offset);
MLoopUV *luv_e_b = BM_ELEM_CD_GET_VOID_P(l_e_b, cd_loop_uv_offset);
float *luv_e_a = BM_ELEM_CD_GET_FLOAT_P(l_e_a, cd_loop_uv_offset);
float *luv_e_b = BM_ELEM_CD_GET_FLOAT_P(l_e_b, cd_loop_uv_offset);
mid_v2_v2v2(l_e_a_cent, luv_e_a->uv, luv_e_a->uv);
mid_v2_v2v2(l_e_b_cent, luv_e_b->uv, luv_e_b->uv);
mid_v2_v2v2(l_e_a_cent, luv_e_a, luv_e_a);
mid_v2_v2v2(l_e_b_cent, luv_e_b, luv_e_b);
mul_v2_v2(l_e_a_cent, aspect_v2);
mul_v2_v2(l_e_b_cent, aspect_v2);
@@ -397,9 +397,8 @@ static float facetag_cut_cost_edge_uv(BMFace *f_a,
BM_face_uv_calc_center_median_weighted(f_a, aspect_v2, cd_loop_uv_offset, f_a_cent);
BM_face_uv_calc_center_median_weighted(f_b, aspect_v2, cd_loop_uv_offset, f_b_cent);
const float *co_v1 = ((const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_edge, cd_loop_uv_offset))->uv;
const float *co_v2 =
((const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_edge->next, cd_loop_uv_offset))->uv;
const float *co_v1 = BM_ELEM_CD_GET_FLOAT_P(l_edge, cd_loop_uv_offset);
const float *co_v2 = BM_ELEM_CD_GET_FLOAT_P(l_edge->next, cd_loop_uv_offset);
#if 0
mid_v2_v2v2(e_cent, co_v1, co_v2);
@@ -444,7 +443,7 @@ static float facetag_cut_cost_vert_uv(BMFace *f_a,
BM_face_uv_calc_center_median_weighted(f_a, aspect_v2, cd_loop_uv_offset, f_a_cent);
BM_face_uv_calc_center_median_weighted(f_b, aspect_v2, cd_loop_uv_offset, f_b_cent);
copy_v2_v2(v_cent, ((const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_vert, cd_loop_uv_offset))->uv);
copy_v2_v2(v_cent, BM_ELEM_CD_GET_FLOAT_P(l_vert, cd_loop_uv_offset));
mul_v2_v2(f_a_cent, aspect_v2);
mul_v2_v2(f_b_cent, aspect_v2);
@@ -442,10 +442,11 @@ static void overlay_edit_uv_cache_populate(OVERLAY_Data *vedata, Object *ob)
const DRWContextState *draw_ctx = DRW_context_state_get();
const bool is_edit_object = DRW_object_is_in_edit_mode(ob);
Mesh *me = (Mesh *)ob->data;
const bool has_active_object_uvmap = CustomData_get_active_layer(&me->ldata, CD_MLOOPUV) != -1;
const bool has_active_object_uvmap = CustomData_get_active_layer(&me->ldata, CD_PROP_FLOAT2) !=
-1;
const bool has_active_edit_uvmap = is_edit_object &&
(CustomData_get_active_layer(&me->edit_mesh->bm->ldata,
CD_MLOOPUV) != -1);
CD_PROP_FLOAT2) != -1);
const bool draw_shadows = (draw_ctx->object_mode != OB_MODE_OBJECT) &&
(ob->mode == draw_ctx->object_mode);
@@ -297,7 +297,7 @@ static eV3DShadingColorType workbench_color_type_get(WORKBENCH_PrivateData *wpd,
if (ob->dt < OB_TEXTURE) {
color_type = V3D_SHADING_MATERIAL_COLOR;
}
else if ((me == NULL) || !CustomData_has_layer(ldata, CD_MLOOPUV)) {
else if ((me == NULL) || !CustomData_has_layer(ldata, CD_PROP_FLOAT2)) {
/* Disable color mode if data layer is unavailable. */
color_type = V3D_SHADING_MATERIAL_COLOR;
}
@@ -322,7 +322,7 @@ static eV3DShadingColorType workbench_color_type_get(WORKBENCH_PrivateData *wpd,
if (!is_sculpt_pbvh && !is_render) {
/* Force texture or vertex mode if object is in paint mode. */
if (is_texpaint_mode && me && CustomData_has_layer(ldata, CD_MLOOPUV)) {
if (is_texpaint_mode && me && CustomData_has_layer(ldata, CD_PROP_FLOAT2)) {
color_type = V3D_SHADING_TEXTURE_COLOR;
if (r_texpaint_mode) {
*r_texpaint_mode = true;
+1 -1
View File
@@ -3371,7 +3371,7 @@ void DRW_cdlayer_attr_aliases_add(GPUVertFormat *format,
/* Active render layer name. */
if (is_active_render) {
GPU_vertformat_alias_add(format, cl->type == CD_MLOOPUV ? "a" : base_name);
GPU_vertformat_alias_add(format, cl->type == CD_PROP_FLOAT2 ? "a" : base_name);
}
/* Active display layer name. */
@@ -252,7 +252,7 @@ static void mesh_cd_calc_active_uv_layer(const Object *object,
{
const Mesh *me_final = editmesh_final_or_this(object, me);
const CustomData *cd_ldata = mesh_cd_ldata_get_from_mesh(me_final);
int layer = CustomData_get_active_layer(cd_ldata, CD_MLOOPUV);
int layer = CustomData_get_active_layer(cd_ldata, CD_PROP_FLOAT2);
if (layer != -1) {
cd_used->uv |= (1 << layer);
}
@@ -264,7 +264,7 @@ static void mesh_cd_calc_active_mask_uv_layer(const Object *object,
{
const Mesh *me_final = editmesh_final_or_this(object, me);
const CustomData *cd_ldata = mesh_cd_ldata_get_from_mesh(me_final);
int layer = CustomData_get_stencil_layer(cd_ldata, CD_MLOOPUV);
int layer = CustomData_get_stencil_layer(cd_ldata, CD_PROP_FLOAT2);
if (layer != -1) {
cd_used->uv |= (1 << layer);
}
@@ -312,7 +312,7 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Object *object,
* We do it based on the specified name.
*/
if (name[0] != '\0') {
layer = CustomData_get_named_layer(cd_ldata, CD_MLOOPUV, name);
layer = CustomData_get_named_layer(cd_ldata, CD_PROP_FLOAT2, name);
type = CD_MTFACE;
#if 0 /* Tangents are always from UV's - this will never happen. */
@@ -354,8 +354,9 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Object *object,
switch (type) {
case CD_MTFACE: {
if (layer == -1) {
layer = (name[0] != '\0') ? CustomData_get_named_layer(cd_ldata, CD_MLOOPUV, name) :
CustomData_get_render_layer(cd_ldata, CD_MLOOPUV);
layer = (name[0] != '\0') ?
CustomData_get_named_layer(cd_ldata, CD_PROP_FLOAT2, name) :
CustomData_get_render_layer(cd_ldata, CD_PROP_FLOAT2);
}
if (layer != -1) {
cd_used.uv |= (1 << layer);
@@ -364,12 +365,13 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Object *object,
}
case CD_TANGENT: {
if (layer == -1) {
layer = (name[0] != '\0') ? CustomData_get_named_layer(cd_ldata, CD_MLOOPUV, name) :
CustomData_get_render_layer(cd_ldata, CD_MLOOPUV);
layer = (name[0] != '\0') ?
CustomData_get_named_layer(cd_ldata, CD_PROP_FLOAT2, name) :
CustomData_get_render_layer(cd_ldata, CD_PROP_FLOAT2);
/* Only fallback to orco (below) when we have no UV layers, see: T56545 */
if (layer == -1 && name[0] != '\0') {
layer = CustomData_get_render_layer(cd_ldata, CD_MLOOPUV);
layer = CustomData_get_render_layer(cd_ldata, CD_PROP_FLOAT2);
}
}
if (layer != -1) {
@@ -833,10 +833,10 @@ static void particle_batch_cache_ensure_procedural_strand_data(PTCacheEdit *edit
ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md;
if (psmd != NULL && psmd->mesh_final != NULL) {
if (CustomData_has_layer(&psmd->mesh_final->ldata, CD_MLOOPUV)) {
cache->num_uv_layers = CustomData_number_of_layers(&psmd->mesh_final->ldata, CD_MLOOPUV);
active_uv = CustomData_get_active_layer(&psmd->mesh_final->ldata, CD_MLOOPUV);
render_uv = CustomData_get_render_layer(&psmd->mesh_final->ldata, CD_MLOOPUV);
if (CustomData_has_layer(&psmd->mesh_final->ldata, CD_PROP_FLOAT2)) {
cache->num_uv_layers = CustomData_number_of_layers(&psmd->mesh_final->ldata, CD_PROP_FLOAT2);
active_uv = CustomData_get_active_layer(&psmd->mesh_final->ldata, CD_PROP_FLOAT2);
render_uv = CustomData_get_render_layer(&psmd->mesh_final->ldata, CD_PROP_FLOAT2);
}
if (CustomData_has_layer(&psmd->mesh_final->ldata, CD_PROP_BYTE_COLOR)) {
cache->num_col_layers = CustomData_number_of_layers(&psmd->mesh_final->ldata,
@@ -897,7 +897,7 @@ static void particle_batch_cache_ensure_procedural_strand_data(PTCacheEdit *edit
GPU_vertbuf_attr_get_raw_data(cache->proc_uv_buf[i], uv_id, &uv_step[i]);
char attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
const char *name = CustomData_get_layer_name(&psmd->mesh_final->ldata, CD_MLOOPUV, i);
const char *name = CustomData_get_layer_name(&psmd->mesh_final->ldata, CD_PROP_FLOAT2, i);
GPU_vertformat_safe_attr_name(name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME);
int n = 0;
@@ -1170,9 +1170,9 @@ static void particle_batch_cache_ensure_pos_and_seg(PTCacheEdit *edit,
MCol **parent_mcol = NULL;
if (psmd != NULL) {
if (CustomData_has_layer(&psmd->mesh_final->ldata, CD_MLOOPUV)) {
num_uv_layers = CustomData_number_of_layers(&psmd->mesh_final->ldata, CD_MLOOPUV);
active_uv = CustomData_get_active_layer(&psmd->mesh_final->ldata, CD_MLOOPUV);
if (CustomData_has_layer(&psmd->mesh_final->ldata, CD_PROP_FLOAT2)) {
num_uv_layers = CustomData_number_of_layers(&psmd->mesh_final->ldata, CD_PROP_FLOAT2);
active_uv = CustomData_get_active_layer(&psmd->mesh_final->ldata, CD_PROP_FLOAT2);
}
if (CustomData_has_layer(&psmd->mesh_final->ldata, CD_PROP_BYTE_COLOR)) {
num_col_layers = CustomData_number_of_layers(&psmd->mesh_final->ldata, CD_PROP_BYTE_COLOR);
@@ -1198,7 +1198,7 @@ static void particle_batch_cache_ensure_pos_and_seg(PTCacheEdit *edit,
for (int i = 0; i < num_uv_layers; i++) {
char uuid[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
const char *name = CustomData_get_layer_name(&psmd->mesh_final->ldata, CD_MLOOPUV, i);
const char *name = CustomData_get_layer_name(&psmd->mesh_final->ldata, CD_PROP_FLOAT2, i);
GPU_vertformat_safe_attr_name(name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME);
BLI_snprintf(uuid, sizeof(uuid), "a%s", attr_safe_name);
@@ -1422,11 +1422,11 @@ void DRW_shgroup_call_sculpt(DRWShadingGroup *shgroup,
}
if (use_uv) {
int layer_i = CustomData_get_active_layer_index(&me->ldata, CD_MLOOPUV);
int layer_i = CustomData_get_active_layer_index(&me->ldata, CD_PROP_FLOAT2);
if (layer_i != -1) {
CustomDataLayer *layer = me->ldata.layers + layer_i;
attrs[attrs_num].type = CD_MLOOPUV;
attrs[attrs_num].type = CD_PROP_FLOAT2;
attrs[attrs_num].domain = ATTR_DOMAIN_CORNER;
BLI_strncpy(attrs[attrs_num].name, layer->name, sizeof(attrs[attrs_num].name));
@@ -1483,11 +1483,11 @@ void DRW_shgroup_call_sculpt_with_materials(DRWShadingGroup **shgroups,
for (uint i = 0; i < 32; i++) {
if (cd_needed.uv & (1 << i)) {
int layer_i = CustomData_get_layer_index_n(&me->ldata, CD_MLOOPUV, i);
int layer_i = CustomData_get_layer_index_n(&me->ldata, CD_PROP_FLOAT2, i);
CustomDataLayer *layer = layer_i != -1 ? me->ldata.layers + layer_i : nullptr;
if (layer) {
attrs[attrs_i].type = CD_MLOOPUV;
attrs[attrs_i].type = CD_PROP_FLOAT2;
attrs[attrs_i].domain = ATTR_DOMAIN_CORNER;
BLI_strncpy(attrs[attrs_i].name, layer->name, sizeof(PBVHAttrReq::name));
attrs_i++;
+2 -15
View File
@@ -76,7 +76,7 @@ static bool valid_pbvh_attr(int type)
case CD_PBVH_MASK_TYPE:
case CD_PROP_COLOR:
case CD_PROP_BYTE_COLOR:
case CD_MLOOPUV:
case CD_PROP_FLOAT2:
return true;
}
@@ -651,15 +651,6 @@ struct PBVHBatches {
break;
}
case CD_MLOOPUV: {
MLoopUV *mloopuv = static_cast<MLoopUV *>(
CustomData_get_layer_named(args->ldata, CD_MLOOPUV, vbo.name.c_str()));
foreach_faces([&](int /*buffer_i*/, int tri_i, int /*vertex_i*/, const MLoopTri *tri) {
*static_cast<float2 *>(GPU_vertbuf_raw_step(&access)) = mloopuv[tri->tri[tri_i]].uv;
});
break;
}
case CD_PROP_COLOR:
if (vbo.domain == ATTR_DOMAIN_POINT) {
MPropCol *mpropcol = static_cast<MPropCol *>(
@@ -881,10 +872,6 @@ struct PBVHBatches {
GPU_vertformat_attr_add(&format, "a", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
need_aliases = true;
break;
case CD_MLOOPUV:
GPU_vertformat_attr_add(&format, "uvs", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
need_aliases = true;
break;
case CD_PBVH_FSET_TYPE:
GPU_vertformat_attr_add(&format, "fset", GPU_COMP_U8, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
break;
@@ -924,7 +911,7 @@ struct PBVHBatches {
}
else {
switch (type) {
case CD_MLOOPUV:
case CD_PROP_FLOAT2:
prefix = "u";
break;
default:
@@ -91,7 +91,7 @@ const MeshExtract *mesh_extract_override_get(const MeshExtract *extractor,
void mesh_render_data_face_flag(const MeshRenderData *mr,
const BMFace *efa,
const int cd_ofs,
const BMUVOffsets offsets,
EditLoopData *eattr)
{
if (efa == mr->efa_act) {
@@ -104,7 +104,7 @@ void mesh_render_data_face_flag(const MeshRenderData *mr,
if (efa == mr->efa_act_uv) {
eattr->v_flag |= VFLAG_FACE_UV_ACTIVE;
}
if ((cd_ofs != -1) && uvedit_face_select_test_ex(mr->toolsettings, (BMFace *)efa, cd_ofs)) {
if ((offsets.uv != -1) && uvedit_face_select_test_ex(mr->toolsettings, (BMFace *)efa, offsets)) {
eattr->v_flag |= VFLAG_FACE_UV_SELECT;
}
@@ -121,30 +121,29 @@ void mesh_render_data_face_flag(const MeshRenderData *mr,
void mesh_render_data_loop_flag(const MeshRenderData *mr,
BMLoop *l,
const int cd_ofs,
const BMUVOffsets offsets,
EditLoopData *eattr)
{
if (cd_ofs == -1) {
if (offsets.uv == -1) {
return;
}
MLoopUV *luv = (MLoopUV *)BM_ELEM_CD_GET_VOID_P(l, cd_ofs);
if (luv != nullptr && (luv->flag & MLOOPUV_PINNED)) {
if (BM_ELEM_CD_GET_BOOL(l, offsets.pin)) {
eattr->v_flag |= VFLAG_VERT_UV_PINNED;
}
if (uvedit_uv_select_test_ex(mr->toolsettings, l, cd_ofs)) {
if (uvedit_uv_select_test_ex(mr->toolsettings, l, offsets)) {
eattr->v_flag |= VFLAG_VERT_UV_SELECT;
}
}
void mesh_render_data_loop_edge_flag(const MeshRenderData *mr,
BMLoop *l,
const int cd_ofs,
const BMUVOffsets offsets,
EditLoopData *eattr)
{
if (cd_ofs == -1) {
if (offsets.uv == -1) {
return;
}
if (uvedit_edge_select_test_ex(mr->toolsettings, l, cd_ofs)) {
if (uvedit_edge_select_test_ex(mr->toolsettings, l, offsets)) {
eattr->v_flag |= VFLAG_EDGE_UV_SELECT;
eattr->v_flag |= VFLAG_VERT_UV_SELECT;
}
@@ -389,15 +389,15 @@ const MeshExtract *mesh_extract_override_get(const MeshExtract *extractor,
bool do_single_mat);
void mesh_render_data_face_flag(const MeshRenderData *mr,
const BMFace *efa,
int cd_ofs,
BMUVOffsets offsets,
EditLoopData *eattr);
void mesh_render_data_loop_flag(const MeshRenderData *mr,
BMLoop *l,
int cd_ofs,
BMUVOffsets offsets,
EditLoopData *eattr);
void mesh_render_data_loop_edge_flag(const MeshRenderData *mr,
BMLoop *l,
int cd_ofs,
BMUVOffsets offsets,
EditLoopData *eattr);
extern const MeshExtract extract_tris;
@@ -138,7 +138,7 @@ static void extract_edit_data_iter_poly_bm(const MeshRenderData *mr,
EditLoopData *data = vbo_data + l_index;
memset(data, 0x0, sizeof(*data));
mesh_render_data_face_flag(mr, f, -1, data);
mesh_render_data_face_flag(mr, f, {-1, -1, -1, -1}, data);
mesh_render_data_edge_flag(mr, l_iter->e, data);
mesh_render_data_vert_flag(mr, l_iter->v, data);
} while ((l_iter = l_iter->next) != l_first);
@@ -161,7 +161,7 @@ static void extract_edit_data_iter_poly_mesh(const MeshRenderData *mr,
BMEdge *eed = bm_original_edge_get(mr, ml->e);
BMVert *eve = bm_original_vert_get(mr, ml->v);
if (efa) {
mesh_render_data_face_flag(mr, efa, -1, data);
mesh_render_data_face_flag(mr, efa, {-1, -1, -1, -1}, data);
}
if (eed) {
mesh_render_data_edge_flag(mr, eed, data);
@@ -288,7 +288,7 @@ static void extract_edit_data_iter_subdiv_bm(const DRWSubdivCache *subdiv_cache,
/* coarse_quad can be null when called by the mesh iteration below. */
if (coarse_quad) {
/* The -1 parameter is for edit_uvs, which we don't do here. */
mesh_render_data_face_flag(mr, coarse_quad, -1, edit_loop_data);
mesh_render_data_face_flag(mr, coarse_quad, {-1, -1, -1, -1}, edit_loop_data);
}
}
}
@@ -19,7 +19,7 @@ namespace blender::draw {
struct MeshExtract_EditUVData_Data {
EditLoopData *vbo_data;
int cd_ofs;
BMUVOffsets offsets;
};
static void extract_edituv_data_init_common(const MeshRenderData *mr,
@@ -37,9 +37,8 @@ static void extract_edituv_data_init_common(const MeshRenderData *mr,
GPU_vertbuf_init_with_format(vbo, &format);
GPU_vertbuf_data_alloc(vbo, loop_len);
CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata;
data->vbo_data = (EditLoopData *)GPU_vertbuf_get_data(vbo);
data->cd_ofs = CustomData_get_offset(cd_ldata, CD_MLOOPUV);
data->offsets = BM_uv_map_get_offsets(mr->bm);
}
static void extract_edituv_data_init(const MeshRenderData *mr,
@@ -64,9 +63,9 @@ static void extract_edituv_data_iter_poly_bm(const MeshRenderData *mr,
MeshExtract_EditUVData_Data *data = static_cast<MeshExtract_EditUVData_Data *>(_data);
EditLoopData *eldata = &data->vbo_data[l_index];
memset(eldata, 0x0, sizeof(*eldata));
mesh_render_data_loop_flag(mr, l_iter, data->cd_ofs, eldata);
mesh_render_data_face_flag(mr, f, data->cd_ofs, eldata);
mesh_render_data_loop_edge_flag(mr, l_iter, data->cd_ofs, eldata);
mesh_render_data_loop_flag(mr, l_iter, data->offsets, eldata);
mesh_render_data_face_flag(mr, f, data->offsets, eldata);
mesh_render_data_loop_edge_flag(mr, l_iter, data->offsets, eldata);
} while ((l_iter = l_iter->next) != l_first);
}
@@ -90,8 +89,8 @@ static void extract_edituv_data_iter_poly_mesh(const MeshRenderData *mr,
if (eed && eve) {
/* Loop on an edge endpoint. */
BMLoop *l = BM_face_edge_share_loop(efa, eed);
mesh_render_data_loop_flag(mr, l, data->cd_ofs, eldata);
mesh_render_data_loop_edge_flag(mr, l, data->cd_ofs, eldata);
mesh_render_data_loop_flag(mr, l, data->offsets, eldata);
mesh_render_data_loop_edge_flag(mr, l, data->offsets, eldata);
}
else {
if (eed == nullptr) {
@@ -105,7 +104,7 @@ static void extract_edituv_data_iter_poly_mesh(const MeshRenderData *mr,
if (eed) {
/* Mapped points on an edge between two edit verts. */
BMLoop *l = BM_face_edge_share_loop(efa, eed);
mesh_render_data_loop_edge_flag(mr, l, data->cd_ofs, eldata);
mesh_render_data_loop_edge_flag(mr, l, data->offsets, eldata);
}
}
}
@@ -146,8 +145,8 @@ static void extract_edituv_data_iter_subdiv_bm(const DRWSubdivCache *subdiv_cach
BMEdge *eed = BM_edge_at_index(mr->bm, edge_origindex);
/* Loop on an edge endpoint. */
BMLoop *l = BM_face_edge_share_loop(const_cast<BMFace *>(coarse_quad), eed);
mesh_render_data_loop_flag(mr, l, data->cd_ofs, edit_loop_data);
mesh_render_data_loop_edge_flag(mr, l, data->cd_ofs, edit_loop_data);
mesh_render_data_loop_flag(mr, l, data->offsets, edit_loop_data);
mesh_render_data_loop_edge_flag(mr, l, data->offsets, edit_loop_data);
}
else {
if (edge_origindex == -1) {
@@ -160,11 +159,11 @@ static void extract_edituv_data_iter_subdiv_bm(const DRWSubdivCache *subdiv_cach
/* Mapped points on an edge between two edit verts. */
BMEdge *eed = BM_edge_at_index(mr->bm, edge_origindex);
BMLoop *l = BM_face_edge_share_loop(const_cast<BMFace *>(coarse_quad), eed);
mesh_render_data_loop_edge_flag(mr, l, data->cd_ofs, edit_loop_data);
mesh_render_data_loop_edge_flag(mr, l, data->offsets, edit_loop_data);
}
}
mesh_render_data_face_flag(mr, coarse_quad, data->cd_ofs, edit_loop_data);
mesh_render_data_face_flag(mr, coarse_quad, data->offsets, edit_loop_data);
}
}
@@ -9,6 +9,8 @@
#include "BKE_mesh.h"
#include "BLI_math_vector_types.hh"
#include "extract_mesh.hh"
#include "draw_subdivision.h"
@@ -26,7 +28,7 @@ struct UVStretchAngle {
struct MeshExtract_StretchAngle_Data {
UVStretchAngle *vbo_data;
const MLoopUV *luv;
const float2 *uv;
float auv[2][2], last_auv[2];
float av[2][3], last_av[3];
int cd_ofs;
@@ -94,11 +96,11 @@ static void extract_edituv_stretch_angle_init(const MeshRenderData *mr,
/* Special iterator needed to save about half of the computing cost. */
if (mr->extract_type == MR_EXTRACT_BMESH) {
data->cd_ofs = CustomData_get_offset(&mr->bm->ldata, CD_MLOOPUV);
data->cd_ofs = CustomData_get_offset(&mr->bm->ldata, CD_PROP_FLOAT2);
}
else {
BLI_assert(mr->extract_type == MR_EXTRACT_MESH);
data->luv = (const MLoopUV *)CustomData_get_layer(&mr->me->ldata, CD_MLOOPUV);
data->uv = (const float2 *)CustomData_get_layer(&mr->me->ldata, CD_PROP_FLOAT2);
}
}
@@ -115,18 +117,18 @@ static void extract_edituv_stretch_angle_iter_poly_bm(const MeshRenderData *mr,
do {
const int l_index = BM_elem_index_get(l_iter);
const MLoopUV *luv, *luv_next;
const float(*luv)[2], (*luv_next)[2];
BMLoop *l_next = l_iter->next;
if (l_iter == BM_FACE_FIRST_LOOP(f)) {
/* First loop in face. */
BMLoop *l_tmp = l_iter->prev;
BMLoop *l_next_tmp = l_iter;
luv = (const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_tmp, data->cd_ofs);
luv_next = (const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_next_tmp, data->cd_ofs);
luv = BM_ELEM_CD_GET_FLOAT2_P(l_tmp, data->cd_ofs);
luv_next = BM_ELEM_CD_GET_FLOAT2_P(l_next_tmp, data->cd_ofs);
compute_normalize_edge_vectors(auv,
av,
luv->uv,
luv_next->uv,
*luv,
*luv_next,
bm_vert_co_get(mr, l_tmp->v),
bm_vert_co_get(mr, l_next_tmp->v));
/* Save last edge. */
@@ -142,14 +144,10 @@ static void extract_edituv_stretch_angle_iter_poly_bm(const MeshRenderData *mr,
copy_v3_v3(av[1], last_av);
}
else {
luv = (const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter, data->cd_ofs);
luv_next = (const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_next, data->cd_ofs);
compute_normalize_edge_vectors(auv,
av,
luv->uv,
luv_next->uv,
bm_vert_co_get(mr, l_iter->v),
bm_vert_co_get(mr, l_next->v));
luv = BM_ELEM_CD_GET_FLOAT2_P(l_iter, data->cd_ofs);
luv_next = BM_ELEM_CD_GET_FLOAT2_P(l_next, data->cd_ofs);
compute_normalize_edge_vectors(
auv, av, *luv, *luv_next, bm_vert_co_get(mr, l_iter->v), bm_vert_co_get(mr, l_next->v));
}
edituv_get_edituv_stretch_angle(auv, av, &data->vbo_data[l_index]);
} while ((l_iter = l_iter->next) != l_first);
@@ -173,8 +171,8 @@ static void extract_edituv_stretch_angle_iter_poly_mesh(const MeshRenderData *mr
const int l_next_tmp = mp->loopstart;
compute_normalize_edge_vectors(auv,
av,
data->luv[ml_index_last].uv,
data->luv[l_next_tmp].uv,
data->uv[ml_index_last],
data->uv[l_next_tmp],
mr->vert_positions[mr->mloop[ml_index_last].v],
mr->vert_positions[mr->mloop[l_next_tmp].v]);
/* Save last edge. */
@@ -193,8 +191,8 @@ static void extract_edituv_stretch_angle_iter_poly_mesh(const MeshRenderData *mr
else {
compute_normalize_edge_vectors(auv,
av,
data->luv[ml_index].uv,
data->luv[l_next].uv,
data->uv[ml_index],
data->uv[l_next],
mr->vert_positions[mr->mloop[ml_index].v],
mr->vert_positions[mr->mloop[l_next].v]);
}
@@ -249,7 +247,7 @@ static void extract_edituv_stretch_angle_init_subdiv(const DRWSubdivCache *subdi
uint32_t uv_layers = cache->cd_used.uv;
/* HACK to fix T68857 */
if (mr->extract_type == MR_EXTRACT_BMESH && cache->cd_used.edit_uv == 1) {
int layer = CustomData_get_active_layer(cd_ldata, CD_MLOOPUV);
int layer = CustomData_get_active_layer(cd_ldata, CD_PROP_FLOAT2);
if (layer != -1) {
uv_layers |= (1 << layer);
}
@@ -258,7 +256,7 @@ static void extract_edituv_stretch_angle_init_subdiv(const DRWSubdivCache *subdi
int uvs_offset = 0;
for (int i = 0; i < MAX_MTFACE; i++) {
if (uv_layers & (1 << i)) {
if (i == CustomData_get_active_layer(cd_ldata, CD_MLOOPUV)) {
if (i == CustomData_get_active_layer(cd_ldata, CD_PROP_FLOAT2)) {
break;
}
@@ -5,6 +5,8 @@
* \ingroup draw
*/
#include "BLI_math_vector_types.hh"
#include "MEM_guardedalloc.h"
#include "BKE_mesh.h"
@@ -57,7 +59,7 @@ static void compute_area_ratio(const MeshRenderData *mr,
if (mr->extract_type == MR_EXTRACT_BMESH) {
CustomData *cd_ldata = &mr->bm->ldata;
int uv_ofs = CustomData_get_offset(cd_ldata, CD_MLOOPUV);
int uv_ofs = CustomData_get_offset(cd_ldata, CD_PROP_FLOAT2);
BMFace *efa;
BMIter f_iter;
@@ -72,12 +74,13 @@ static void compute_area_ratio(const MeshRenderData *mr,
}
else {
BLI_assert(mr->extract_type == MR_EXTRACT_MESH);
const MLoopUV *uv_data = (const MLoopUV *)CustomData_get_layer(&mr->me->ldata, CD_MLOOPUV);
const float2 *uv_data = (const float2 *)CustomData_get_layer(&mr->me->ldata, CD_PROP_FLOAT2);
const MPoly *mp = mr->mpoly;
for (int mp_index = 0; mp_index < mr->poly_len; mp_index++, mp++) {
float area = BKE_mesh_calc_poly_area(
mp, &mr->mloop[mp->loopstart], reinterpret_cast<const float(*)[3]>(mr->vert_positions));
float uvarea = BKE_mesh_calc_poly_uv_area(mp, uv_data);
float uvarea = area_poly_v2(reinterpret_cast<const float(*)[2]>(&uv_data[mp->loopstart]),
mp->totloop);
tot_area += area;
tot_uv_area += uvarea;
r_area_ratio[mp_index] = area_ratio_get(area, uvarea);
@@ -17,7 +17,7 @@ namespace blender::draw {
struct MeshExtract_EditUVFdotData_Data {
EditLoopData *vbo_data;
int cd_ofs;
BMUVOffsets offsets;
};
static void extract_fdots_edituv_data_init(const MeshRenderData *mr,
@@ -36,7 +36,7 @@ static void extract_fdots_edituv_data_init(const MeshRenderData *mr,
MeshExtract_EditUVFdotData_Data *data = static_cast<MeshExtract_EditUVFdotData_Data *>(tls_data);
data->vbo_data = (EditLoopData *)GPU_vertbuf_get_data(vbo);
data->cd_ofs = CustomData_get_offset(&mr->bm->ldata, CD_MLOOPUV);
data->offsets = BM_uv_map_get_offsets(mr->bm);
}
static void extract_fdots_edituv_data_iter_poly_bm(const MeshRenderData *mr,
@@ -47,7 +47,7 @@ static void extract_fdots_edituv_data_iter_poly_bm(const MeshRenderData *mr,
MeshExtract_EditUVFdotData_Data *data = static_cast<MeshExtract_EditUVFdotData_Data *>(_data);
EditLoopData *eldata = &data->vbo_data[BM_elem_index_get(f)];
memset(eldata, 0x0, sizeof(*eldata));
mesh_render_data_face_flag(mr, f, data->cd_ofs, eldata);
mesh_render_data_face_flag(mr, f, data->offsets, eldata);
}
static void extract_fdots_edituv_data_iter_poly_mesh(const MeshRenderData *mr,
@@ -60,7 +60,7 @@ static void extract_fdots_edituv_data_iter_poly_mesh(const MeshRenderData *mr,
memset(eldata, 0x0, sizeof(*eldata));
BMFace *efa = bm_original_face_get(mr, mp_index);
if (efa) {
mesh_render_data_face_flag(mr, efa, data->cd_ofs, eldata);
mesh_render_data_face_flag(mr, efa, data->offsets, eldata);
}
}
@@ -17,7 +17,7 @@ namespace blender::draw {
struct MeshExtract_FdotUV_Data {
float (*vbo_data)[2];
const MLoopUV *uv_data;
const float (*uv_data)[2];
int cd_ofs;
};
@@ -46,10 +46,10 @@ static void extract_fdots_uv_init(const MeshRenderData *mr,
data->vbo_data = (float(*)[2])GPU_vertbuf_get_data(vbo);
if (mr->extract_type == MR_EXTRACT_BMESH) {
data->cd_ofs = CustomData_get_offset(&mr->bm->ldata, CD_MLOOPUV);
data->cd_ofs = CustomData_get_offset(&mr->bm->ldata, CD_PROP_FLOAT2);
}
else {
data->uv_data = (const MLoopUV *)CustomData_get_layer(&mr->me->ldata, CD_MLOOPUV);
data->uv_data = (const float(*)[2])CustomData_get_layer(&mr->me->ldata, CD_PROP_FLOAT2);
}
}
@@ -63,8 +63,8 @@ static void extract_fdots_uv_iter_poly_bm(const MeshRenderData * /*mr*/,
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
float w = 1.0f / float(f->len);
const MLoopUV *luv = (const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter, data->cd_ofs);
madd_v2_v2fl(data->vbo_data[BM_elem_index_get(f)], luv->uv, w);
const float *luv = BM_ELEM_CD_GET_FLOAT_P(l_iter, data->cd_ofs);
madd_v2_v2fl(data->vbo_data[BM_elem_index_get(f)], luv, w);
} while ((l_iter = l_iter->next) != l_first);
}
@@ -82,12 +82,12 @@ static void extract_fdots_uv_iter_poly_mesh(const MeshRenderData *mr,
const MLoop *ml = &mloop[ml_index];
if (mr->use_subsurf_fdots) {
if (BLI_BITMAP_TEST(facedot_tags, ml->v)) {
copy_v2_v2(data->vbo_data[mp_index], data->uv_data[ml_index].uv);
copy_v2_v2(data->vbo_data[mp_index], data->uv_data[ml_index]);
}
}
else {
float w = 1.0f / float(mp->totloop);
madd_v2_v2fl(data->vbo_data[mp_index], data->uv_data[ml_index].uv, w);
madd_v2_v2fl(data->vbo_data[mp_index], data->uv_data[ml_index], w);
}
}
}
@@ -48,7 +48,8 @@ static void extract_tan_init_common(const MeshRenderData *mr,
/* FIXME(T91838): This is to avoid a crash when orco tangent was requested but there are valid
* uv layers. It would be better to fix the root cause. */
if (tan_layers == 0 && use_orco_tan && CustomData_get_layer_index(cd_ldata, CD_MLOOPUV) != -1) {
if (tan_layers == 0 && use_orco_tan &&
CustomData_get_layer_index(cd_ldata, CD_PROP_FLOAT2) != -1) {
tan_layers = 1;
use_orco_tan = false;
}
@@ -56,17 +57,17 @@ static void extract_tan_init_common(const MeshRenderData *mr,
for (int i = 0; i < MAX_MTFACE; i++) {
if (tan_layers & (1 << i)) {
char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
const char *layer_name = CustomData_get_layer_name(cd_ldata, CD_MLOOPUV, i);
const char *layer_name = CustomData_get_layer_name(cd_ldata, CD_PROP_FLOAT2, i);
GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME);
/* Tangent layer name. */
BLI_snprintf(attr_name, sizeof(attr_name), "t%s", attr_safe_name);
GPU_vertformat_attr_add(format, attr_name, comp_type, 4, fetch_mode);
/* Active render layer name. */
if (i == CustomData_get_render_layer(cd_ldata, CD_MLOOPUV)) {
if (i == CustomData_get_render_layer(cd_ldata, CD_PROP_FLOAT2)) {
GPU_vertformat_alias_add(format, "t");
}
/* Active display layer name. */
if (i == CustomData_get_active_layer(cd_ldata, CD_MLOOPUV)) {
if (i == CustomData_get_active_layer(cd_ldata, CD_PROP_FLOAT2)) {
GPU_vertformat_alias_add(format, "at");
}
@@ -5,6 +5,7 @@
* \ingroup draw
*/
#include "BLI_math_vector_types.hh"
#include "BLI_string.h"
#include "draw_subdivision.h"
@@ -29,7 +30,7 @@ static bool mesh_extract_uv_format_init(GPUVertFormat *format,
uint32_t uv_layers = cache->cd_used.uv;
/* HACK to fix T68857 */
if (extract_type == MR_EXTRACT_BMESH && cache->cd_used.edit_uv == 1) {
int layer = CustomData_get_active_layer(cd_ldata, CD_MLOOPUV);
int layer = CustomData_get_active_layer(cd_ldata, CD_PROP_FLOAT2);
if (layer != -1) {
uv_layers |= (1 << layer);
}
@@ -40,24 +41,24 @@ static bool mesh_extract_uv_format_init(GPUVertFormat *format,
for (int i = 0; i < MAX_MTFACE; i++) {
if (uv_layers & (1 << i)) {
char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
const char *layer_name = CustomData_get_layer_name(cd_ldata, CD_MLOOPUV, i);
const char *layer_name = CustomData_get_layer_name(cd_ldata, CD_PROP_FLOAT2, i);
GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME);
/* UV layer name. */
BLI_snprintf(attr_name, sizeof(attr_name), "a%s", attr_safe_name);
GPU_vertformat_attr_add(format, attr_name, GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
/* Active render layer name. */
if (i == CustomData_get_render_layer(cd_ldata, CD_MLOOPUV)) {
if (i == CustomData_get_render_layer(cd_ldata, CD_PROP_FLOAT2)) {
GPU_vertformat_alias_add(format, "a");
}
/* Active display layer name. */
if (i == CustomData_get_active_layer(cd_ldata, CD_MLOOPUV)) {
if (i == CustomData_get_active_layer(cd_ldata, CD_PROP_FLOAT2)) {
GPU_vertformat_alias_add(format, "au");
/* Alias to `pos` for edit uvs. */
GPU_vertformat_alias_add(format, "pos");
}
/* Stencil mask uv layer name. */
if (i == CustomData_get_stencil_layer(cd_ldata, CD_MLOOPUV)) {
if (i == CustomData_get_stencil_layer(cd_ldata, CD_PROP_FLOAT2)) {
GPU_vertformat_alias_add(format, "mu");
}
}
@@ -90,28 +91,28 @@ static void extract_uv_init(const MeshRenderData *mr,
GPU_vertbuf_init_with_format(vbo, &format);
GPU_vertbuf_data_alloc(vbo, v_len);
float(*uv_data)[2] = (float(*)[2])GPU_vertbuf_get_data(vbo);
float2 *uv_data = static_cast<float2 *>(GPU_vertbuf_get_data(vbo));
for (int i = 0; i < MAX_MTFACE; i++) {
if (uv_layers & (1 << i)) {
if (mr->extract_type == MR_EXTRACT_BMESH) {
int cd_ofs = CustomData_get_n_offset(cd_ldata, CD_MLOOPUV, i);
int cd_ofs = CustomData_get_n_offset(cd_ldata, CD_PROP_FLOAT2, i);
BMIter f_iter;
BMFace *efa;
BM_ITER_MESH (efa, &f_iter, mr->bm, BM_FACES_OF_MESH) {
BMLoop *l_iter, *l_first;
l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
do {
MLoopUV *luv = (MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter, cd_ofs);
memcpy(uv_data, luv->uv, sizeof(*uv_data));
float *luv = BM_ELEM_CD_GET_FLOAT_P(l_iter, cd_ofs);
memcpy(uv_data, luv, sizeof(*uv_data));
uv_data++;
} while ((l_iter = l_iter->next) != l_first);
}
}
else {
const MLoopUV *layer_data = (const MLoopUV *)CustomData_get_layer_n(
cd_ldata, CD_MLOOPUV, i);
const float2 *layer_data = static_cast<float2 *>(
CustomData_get_layer_n(cd_ldata, CD_PROP_FLOAT2, i));
for (int ml_index = 0; ml_index < mr->loop_len; ml_index++, uv_data++, layer_data++) {
memcpy(uv_data, layer_data->uv, sizeof(*uv_data));
memcpy(uv_data, layer_data, sizeof(*uv_data));
}
}
}
@@ -960,7 +960,7 @@ static int surface_set_exec(bContext *C, wmOperator *op)
Mesh &new_surface_mesh = *static_cast<Mesh *>(new_surface_ob.data);
const char *new_uv_map_name = CustomData_get_active_layer_name(&new_surface_mesh.ldata,
CD_MLOOPUV);
CD_PROP_FLOAT2);
CTX_DATA_BEGIN (C, Object *, selected_ob, selected_objects) {
if (selected_ob->type != OB_CURVES) {
@@ -248,7 +248,6 @@ static int geometry_color_attribute_add_exec(bContext *C, wmOperator *op)
enum class ConvertAttributeMode {
Generic,
UVMap,
VertexGroup,
};
@@ -301,23 +300,6 @@ static int geometry_attribute_convert_exec(bContext *C, wmOperator *op)
}
break;
}
case ConvertAttributeMode::UVMap: {
MLoopUV *dst_uvs = static_cast<MLoopUV *>(
MEM_calloc_arrayN(mesh->totloop, sizeof(MLoopUV), __func__));
VArray<float2> src_varray = attributes.lookup_or_default<float2>(
name, ATTR_DOMAIN_CORNER, {0.0f, 0.0f});
for (const int i : IndexRange(mesh->totloop)) {
copy_v2_v2(dst_uvs[i].uv, src_varray[i]);
}
attributes.remove(name);
CustomData_add_layer_named(
&mesh->ldata, CD_MLOOPUV, CD_ASSIGN, dst_uvs, mesh->totloop, name.c_str());
int *active_index = BKE_id_attributes_active_index_p(&mesh->id);
if (*active_index > 0) {
*active_index -= 1;
}
break;
}
case ConvertAttributeMode::VertexGroup: {
Array<float> src_weights(mesh->totvert);
VArray<float> src_varray = attributes.lookup_or_default<float>(
@@ -710,7 +692,6 @@ void GEOMETRY_OT_attribute_convert(wmOperatorType *ot)
static EnumPropertyItem mode_items[] = {
{int(ConvertAttributeMode::Generic), "GENERIC", 0, "Generic", ""},
{int(ConvertAttributeMode::UVMap), "UV_MAP", 0, "UV Map", ""},
{int(ConvertAttributeMode::VertexGroup), "VERTEX_GROUP", 0, "Vertex Group", ""},
{0, nullptr, 0, nullptr, nullptr},
};
+8
View File
@@ -552,6 +552,13 @@ void ED_mesh_geometry_clear(struct Mesh *mesh);
void ED_mesh_update(struct Mesh *mesh, struct bContext *C, bool calc_edges, bool calc_edges_loose);
bool *ED_mesh_uv_map_vert_select_layer_ensure(struct Mesh *mesh, int uv_map_index);
bool *ED_mesh_uv_map_edge_select_layer_ensure(struct Mesh *mesh, int uv_map_index);
bool *ED_mesh_uv_map_pin_layer_ensure(struct Mesh *mesh, int uv_map_index);
const bool *ED_mesh_uv_map_vert_select_layer_get(const struct Mesh *mesh, int uv_map_index);
const bool *ED_mesh_uv_map_edge_select_layer_get(const struct Mesh *mesh, int uv_map_index);
const bool *ED_mesh_uv_map_pin_layer_get(const struct Mesh *mesh, int uv_map_index);
bool ED_mesh_edge_is_loose(const struct Mesh *mesh, int index);
void ED_mesh_uv_ensure(struct Mesh *me, const char *name);
@@ -560,6 +567,7 @@ int ED_mesh_uv_add(
bool ED_mesh_uv_remove_index(struct Mesh *me, int n);
bool ED_mesh_uv_remove_active(struct Mesh *me);
bool ED_mesh_uv_remove_named(struct Mesh *me, const char *name);
void ED_mesh_uv_loop_reset(struct bContext *C, struct Mesh *me);
/**
* Without a #bContext, called when UV-editing.
+31 -24
View File
@@ -7,6 +7,8 @@
#pragma once
#include "BKE_customdata.h"
#ifdef __cplusplus
extern "C" {
#endif
@@ -87,17 +89,19 @@ bool ED_uvedit_test(struct Object *obedit);
bool uvedit_face_visible_test_ex(const struct ToolSettings *ts, struct BMFace *efa);
bool uvedit_face_select_test_ex(const struct ToolSettings *ts,
struct BMFace *efa,
int cd_loop_uv_offset);
BMUVOffsets offsets);
bool uvedit_edge_select_test_ex(const struct ToolSettings *ts,
struct BMLoop *l,
int cd_loop_uv_offset);
BMUVOffsets offsets);
bool uvedit_uv_select_test_ex(const struct ToolSettings *ts,
struct BMLoop *l,
int cd_loop_uv_offset);
BMUVOffsets offsets);
bool uvedit_face_visible_test(const struct Scene *scene, struct BMFace *efa);
bool uvedit_face_select_test(const struct Scene *scene, struct BMFace *efa, int cd_loop_uv_offset);
bool uvedit_edge_select_test(const struct Scene *scene, struct BMLoop *l, int cd_loop_uv_offset);
bool uvedit_uv_select_test(const struct Scene *scene, struct BMLoop *l, int cd_loop_uv_offset);
bool uvedit_face_select_test(const struct Scene *scene, struct BMFace *efa, BMUVOffsets offsets);
bool uvedit_edge_select_test(const struct Scene *scene, struct BMLoop *l, BMUVOffsets offsets);
bool uvedit_uv_select_test(const struct Scene *scene, struct BMLoop *l, BMUVOffsets offsets);
/* Individual UV element selection functions. */
@@ -111,7 +115,7 @@ void uvedit_face_select_set(const struct Scene *scene,
struct BMFace *efa,
bool select,
bool do_history,
int cd_loop_uv_offset);
BMUVOffsets offsets);
/**
* \brief Select UV Edge
*
@@ -122,7 +126,7 @@ void uvedit_edge_select_set(const struct Scene *scene,
struct BMLoop *l,
bool select,
bool do_history,
int cd_loop_uv_offset);
BMUVOffsets offsets);
/**
* \brief Select UV Vertex
*
@@ -133,7 +137,7 @@ void uvedit_uv_select_set(const struct Scene *scene,
struct BMLoop *l,
bool select,
bool do_history,
int cd_loop_uv_offset);
BMUVOffsets offsets);
/* Low level functions for (de)selecting individual UV elements. Ensure UV face visibility before
* use. */
@@ -142,29 +146,31 @@ void uvedit_face_select_enable(const struct Scene *scene,
struct BMesh *bm,
struct BMFace *efa,
bool do_history,
int cd_loop_uv_offset);
BMUVOffsets offsets);
void uvedit_face_select_disable(const struct Scene *scene,
struct BMesh *bm,
struct BMFace *efa,
int cd_loop_uv_offset);
BMUVOffsets offsets);
void uvedit_edge_select_enable(const struct Scene *scene,
struct BMesh *bm,
struct BMLoop *l,
bool do_history,
int cd_loop_uv_offset);
BMUVOffsets offsets);
void uvedit_edge_select_disable(const struct Scene *scene,
struct BMesh *bm,
struct BMLoop *l,
int cd_loop_uv_offset);
BMUVOffsets offsets);
void uvedit_uv_select_enable(const struct Scene *scene,
struct BMesh *bm,
struct BMLoop *l,
bool do_history,
int cd_loop_uv_offset);
BMUVOffsets offsets);
void uvedit_uv_select_disable(const struct Scene *scene,
struct BMesh *bm,
struct BMLoop *l,
int cd_loop_uv_offset);
BMUVOffsets offsets);
/* Sticky mode UV element selection functions. */
@@ -173,19 +179,20 @@ void uvedit_face_select_set_with_sticky(const struct Scene *scene,
struct BMFace *efa,
bool select,
bool do_history,
int cd_loop_uv_offset);
BMUVOffsets offsets);
void uvedit_edge_select_set_with_sticky(const struct Scene *scene,
struct BMEditMesh *em,
struct BMLoop *l,
bool select,
bool do_history,
int cd_loop_uv_offset);
BMUVOffsets offsets);
void uvedit_uv_select_set_with_sticky(const struct Scene *scene,
struct BMEditMesh *em,
struct BMLoop *l,
bool select,
bool do_history,
int cd_loop_uv_offset);
BMUVOffsets offsets);
/* Low level functions for sticky element selection (sticky mode independent). Type of sticky
* selection is specified explicitly (using sticky_flag, except for face selection). */
@@ -195,28 +202,28 @@ void uvedit_face_select_shared_vert(const struct Scene *scene,
struct BMFace *efa,
const bool select,
const bool do_history,
const int cd_loop_uv_offset);
BMUVOffsets offsets);
void uvedit_edge_select_shared_vert(const struct Scene *scene,
struct BMEditMesh *em,
struct BMLoop *l,
const bool select,
const int sticky_flag,
const bool do_history,
const int cd_loop_uv_offset);
BMUVOffsets offsets);
void uvedit_uv_select_shared_vert(const struct Scene *scene,
struct BMEditMesh *em,
struct BMLoop *l,
const bool select,
const int sticky_flag,
const bool do_history,
const int cd_loop_uv_offset);
BMUVOffsets offsets);
/* Sets required UV edge flags as specified by the sticky_flag. */
void uvedit_edge_select_set_noflush(const struct Scene *scene,
struct BMLoop *l,
const bool select,
const int sticky_flag,
const int cd_loop_uv_offset);
BMUVOffsets offsets);
/**
* \brief UV Select Mode set
@@ -315,7 +322,7 @@ struct FaceIsland {
* \note While this is duplicate information,
* it allows islands from multiple meshes to be stored in the same list.
*/
int cd_loop_uv_offset;
BMUVOffsets offsets;
float aspect_y;
};
@@ -326,7 +333,7 @@ int bm_mesh_calc_uv_islands(const Scene *scene,
const bool only_selected_uvs,
const bool use_seams,
const float aspect_y,
const int cd_loop_uv_offset);
BMUVOffsets offsets);
struct UVMapUDIM_Params {
const struct Image *image;
+1 -1
View File
@@ -379,7 +379,7 @@ bool paintface_minmax(Object *ob, float r_min[3], float r_max[3])
float vec[3], bmat[3][3];
const Mesh *me = BKE_mesh_from_object(ob);
if (!me || !CustomData_has_layer(&me->ldata, CD_MLOOPUV)) {
if (!me || !CustomData_has_layer(&me->ldata, CD_PROP_FLOAT2)) {
return ok;
}
@@ -3211,7 +3211,7 @@ static int select_linked_delimit_default_from_op(wmOperator *op, const int selec
static void select_linked_delimit_validate(BMesh *bm, int *delimit)
{
if ((*delimit) & BMO_DELIM_UV) {
if (!CustomData_has_layer(&bm->ldata, CD_MLOOPUV)) {
if (!CustomData_has_layer(&bm->ldata, CD_PROP_FLOAT2)) {
(*delimit) &= ~BMO_DELIM_UV;
}
}
@@ -3222,7 +3222,7 @@ static void select_linked_delimit_begin(BMesh *bm, int delimit)
DelimitData delimit_data = {0};
if (delimit & BMO_DELIM_UV) {
delimit_data.cd_loop_type = CD_MLOOPUV;
delimit_data.cd_loop_type = CD_PROP_FLOAT2;
delimit_data.cd_loop_offset = CustomData_get_offset(&bm->ldata, delimit_data.cd_loop_type);
if (delimit_data.cd_loop_offset == -1) {
delimit &= ~BMO_DELIM_UV;
+39 -40
View File
@@ -459,10 +459,10 @@ UvVertMap *BM_uv_vert_map_create(BMesh *bm, const bool use_select, const bool us
/* vars from original func */
UvVertMap *vmap;
UvMapVert *buf;
const MLoopUV *luv;
const float(*luv)[2];
uint a;
int totverts, i, totuv, totfaces;
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_PROP_FLOAT2);
bool *winding = NULL;
BLI_buffer_declare_static(vec2f, tf_uv_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE);
@@ -516,8 +516,8 @@ UvVertMap *BM_uv_vert_map_create(BMesh *bm, const bool use_select, const bool us
buf++;
if (use_winding) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
copy_v2_v2(tf_uv[i], luv->uv);
luv = BM_ELEM_CD_GET_FLOAT2_P(l, cd_loop_uv_offset);
copy_v2_v2(tf_uv[i], *luv);
}
}
@@ -542,8 +542,7 @@ UvVertMap *BM_uv_vert_map_create(BMesh *bm, const bool use_select, const bool us
efa = BM_face_at_index(bm, v->poly_index);
l = BM_iter_at_index(bm, BM_LOOPS_OF_FACE, efa, v->loop_of_poly_index);
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
uv = luv->uv;
uv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset);
lastv = NULL;
iterv = vlist;
@@ -552,8 +551,7 @@ UvVertMap *BM_uv_vert_map_create(BMesh *bm, const bool use_select, const bool us
next = iterv->next;
efa = BM_face_at_index(bm, iterv->poly_index);
l = BM_iter_at_index(bm, BM_LOOPS_OF_FACE, efa, iterv->loop_of_poly_index);
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
uv2 = luv->uv;
uv2 = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset);
if (compare_v2v2(uv2, uv, STD_UV_CONNECT_LIMIT) &&
(!use_winding || winding[iterv->poly_index] == winding[v->poly_index])) {
@@ -682,7 +680,7 @@ static int bm_uv_edge_select_build_islands(UvElementMap *element_map,
UvElement *islandbuf,
uint *map,
bool uv_selected,
const int cd_loop_uv_offset)
const BMUVOffsets offsets)
{
BM_uv_element_map_ensure_head_table(element_map);
@@ -723,7 +721,7 @@ static int bm_uv_edge_select_build_islands(UvElementMap *element_map,
while (element) {
/* Scan forwards around the BMFace that contains element->l. */
if (!uv_selected || uvedit_edge_select_test(scene, element->l, cd_loop_uv_offset)) {
if (!uv_selected || uvedit_edge_select_test(scene, element->l, offsets)) {
UvElement *next = BM_uv_element_get(element_map, element->l->next->f, element->l->next);
if (next->island == INVALID_ISLAND) {
UvElement *tail = element_map->head_table[next - element_map->storage];
@@ -739,7 +737,7 @@ static int bm_uv_edge_select_build_islands(UvElementMap *element_map,
}
/* Scan backwards around the BMFace that contains element->l. */
if (!uv_selected || uvedit_edge_select_test(scene, element->l->prev, cd_loop_uv_offset)) {
if (!uv_selected || uvedit_edge_select_test(scene, element->l->prev, offsets)) {
UvElement *prev = BM_uv_element_get(element_map, element->l->prev->f, element->l->prev);
if (prev->island == INVALID_ISLAND) {
UvElement *tail = element_map->head_table[prev - element_map->storage];
@@ -788,14 +786,14 @@ static void bm_uv_build_islands(UvElementMap *element_map,
int *island_number = MEM_callocN(sizeof(*island_number) * bm->totface, "uv_island_number_face");
copy_vn_i(island_number, bm->totface, INVALID_ISLAND);
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
const BMUVOffsets uv_offsets = BM_uv_map_get_offsets(bm);
const bool use_uv_edge_connectivity = scene->toolsettings->uv_flag & UV_SYNC_SELECTION ?
scene->toolsettings->selectmode & SCE_SELECT_EDGE :
scene->toolsettings->uv_selectmode & UV_SELECT_EDGE;
if (use_uv_edge_connectivity) {
nislands = bm_uv_edge_select_build_islands(
element_map, scene, islandbuf, map, uv_selected, cd_loop_uv_offset);
element_map, scene, islandbuf, map, uv_selected, uv_offsets);
islandbufsize = totuv;
}
@@ -813,7 +811,7 @@ static void bm_uv_build_islands(UvElementMap *element_map,
BMLoop *l;
BMIter liter;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (uv_selected && !uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
if (uv_selected && !uvedit_uv_select_test(scene, l, uv_offsets)) {
continue;
}
@@ -890,20 +888,23 @@ static void bm_uv_build_islands(UvElementMap *element_map,
}
/* return true if `loop` has UV co-ordinates which match `luv_a` and `luv_b` */
static bool loop_uv_match(BMLoop *loop, MLoopUV *luv_a, MLoopUV *luv_b, int cd_loop_uv_offset)
static bool loop_uv_match(BMLoop *loop,
const float luv_a[2],
const float luv_b[2],
int cd_loop_uv_offset)
{
MLoopUV *luv_c = BM_ELEM_CD_GET_VOID_P(loop, cd_loop_uv_offset);
MLoopUV *luv_d = BM_ELEM_CD_GET_VOID_P(loop->next, cd_loop_uv_offset);
return compare_v2v2(luv_a->uv, luv_c->uv, STD_UV_CONNECT_LIMIT) &&
compare_v2v2(luv_b->uv, luv_d->uv, STD_UV_CONNECT_LIMIT);
const float *luv_c = BM_ELEM_CD_GET_FLOAT_P(loop, cd_loop_uv_offset);
const float *luv_d = BM_ELEM_CD_GET_FLOAT_P(loop->next, cd_loop_uv_offset);
return compare_v2v2(luv_a, luv_c, STD_UV_CONNECT_LIMIT) &&
compare_v2v2(luv_b, luv_d, STD_UV_CONNECT_LIMIT);
}
/* Given `anchor` and `edge`, return true if there are edges that fan between them that are
* seam-free. */
static bool seam_connected_recursive(BMVert *anchor,
BMEdge *edge,
MLoopUV *luv_anchor,
MLoopUV *luv_fan,
float luv_anchor[2],
float luv_fan[2],
BMLoop *needle,
GSet *visited,
int cd_loop_uv_offset)
@@ -931,7 +932,7 @@ static bool seam_connected_recursive(BMVert *anchor,
return true; /* Success. */
}
MLoopUV *luv_far = BM_ELEM_CD_GET_VOID_P(loop->prev, cd_loop_uv_offset);
float *luv_far = BM_ELEM_CD_GET_FLOAT_P(loop->prev, cd_loop_uv_offset);
if (seam_connected_recursive(
anchor, loop->prev->e, luv_anchor, luv_far, needle, visited, cd_loop_uv_offset)) {
return true;
@@ -947,7 +948,7 @@ static bool seam_connected_recursive(BMVert *anchor,
return true; /* Success. */
}
MLoopUV *luv_far = BM_ELEM_CD_GET_VOID_P(loop->next->next, cd_loop_uv_offset);
float *luv_far = BM_ELEM_CD_GET_FLOAT_P(loop->next->next, cd_loop_uv_offset);
if (seam_connected_recursive(
anchor, loop->next->e, luv_anchor, luv_far, needle, visited, cd_loop_uv_offset)) {
return true;
@@ -970,8 +971,8 @@ static bool seam_connected(BMLoop *loop_a, BMLoop *loop_b, GSet *visited, int cd
BLI_gset_clear(visited, NULL);
MLoopUV *luv_anchor = BM_ELEM_CD_GET_VOID_P(loop_a, cd_loop_uv_offset);
MLoopUV *luv_fan = BM_ELEM_CD_GET_VOID_P(loop_a->next, cd_loop_uv_offset);
float *luv_anchor = BM_ELEM_CD_GET_FLOAT_P(loop_a, cd_loop_uv_offset);
float *luv_fan = BM_ELEM_CD_GET_FLOAT_P(loop_a->next, cd_loop_uv_offset);
const bool result = seam_connected_recursive(
loop_a->v, loop_a->e, luv_anchor, luv_fan, loop_b, visited, cd_loop_uv_offset);
return result;
@@ -991,9 +992,9 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm,
BMFace *efa;
BMIter iter, liter;
BLI_buffer_declare_static(vec2f, tf_uv_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE);
MLoopUV *luv;
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
if (cd_loop_uv_offset < 0) {
const BMUVOffsets offsets = BM_uv_map_get_offsets(bm);
if (offsets.uv < 0) {
return NULL;
}
@@ -1016,7 +1017,7 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm,
else {
BMLoop *l;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
if (uvedit_uv_select_test(scene, l, offsets)) {
totuv++;
}
}
@@ -1057,7 +1058,7 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm,
int i;
BMLoop *l;
BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
if (uv_selected && !uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
if (uv_selected && !uvedit_uv_select_test(scene, l, offsets)) {
continue;
}
@@ -1070,8 +1071,8 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm,
element_map->vertex[BM_elem_index_get(l->v)] = buf;
if (use_winding) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
copy_v2_v2(tf_uv[i], luv->uv);
const float *uv = BM_ELEM_CD_GET_FLOAT_P(l, offsets.uv);
copy_v2_v2(tf_uv[i], uv);
}
buf++;
@@ -1098,9 +1099,8 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm,
v->next = newvlist;
newvlist = v;
luv = BM_ELEM_CD_GET_VOID_P(v->l, cd_loop_uv_offset);
const float *uv = luv->uv;
bool uv_vert_sel = uvedit_uv_select_test(scene, v->l, cd_loop_uv_offset);
const float *uv = BM_ELEM_CD_GET_VOID_P(v->l, offsets.uv);
bool uv_vert_sel = uvedit_uv_select_test(scene, v->l, offsets);
UvElement *lastv = NULL;
UvElement *iterv = vlist;
@@ -1108,20 +1108,19 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm,
/* Scan through unsorted list, finding UvElements which are connected to `v`. */
while (iterv) {
UvElement *next = iterv->next;
luv = BM_ELEM_CD_GET_VOID_P(iterv->l, cd_loop_uv_offset);
bool connected = true; /* Assume connected unless we can prove otherwise. */
if (connected) {
/* Are the two UVs close together? */
const float *uv2 = luv->uv;
const float *uv2 = BM_ELEM_CD_GET_FLOAT_P(iterv->l, offsets.uv);
connected = compare_v2v2(uv2, uv, STD_UV_CONNECT_LIMIT);
}
if (connected) {
/* Check if the uv loops share the same selection state (if not, they are not connected
* as they have been ripped or other edit commands have separated them). */
const bool uv2_vert_sel = uvedit_uv_select_test(scene, iterv->l, cd_loop_uv_offset);
const bool uv2_vert_sel = uvedit_uv_select_test(scene, iterv->l, offsets);
connected = (uv_vert_sel == uv2_vert_sel);
}
@@ -1131,7 +1130,7 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm,
}
if (connected && use_seams) {
connected = seam_connected(iterv->l, v->l, seam_visited_gset, cd_loop_uv_offset);
connected = seam_connected(iterv->l, v->l, seam_visited_gset, offsets.uv);
}
if (connected) {
@@ -1257,7 +1256,7 @@ BMFace *EDBM_uv_active_face_get(BMEditMesh *em, const bool sloppy, const bool se
bool EDBM_uv_check(BMEditMesh *em)
{
/* some of these checks could be a touch overkill */
return em && em->bm->totface && CustomData_has_layer(&em->bm->ldata, CD_MLOOPUV);
return em && em->bm->totface && CustomData_has_layer(&em->bm->ldata, CD_PROP_FLOAT2);
}
bool EDBM_vert_color_check(BMEditMesh *em)
+109 -29
View File
@@ -36,6 +36,8 @@
#include "WM_api.h"
#include "WM_types.h"
#include "BLT_translation.h"
#include "ED_mesh.h"
#include "ED_object.h"
#include "ED_paint.h"
@@ -48,6 +50,7 @@
#include "mesh_intern.h" /* own include */
using blender::Array;
using blender::float2;
using blender::float3;
using blender::MutableSpan;
using blender::Span;
@@ -118,7 +121,7 @@ static void delete_customdata_layer(Mesh *me, CustomDataLayer *layer)
int layer_index, tot, n;
char htype = BM_FACE;
if (ELEM(type, CD_PROP_BYTE_COLOR, CD_MLOOPUV)) {
if (ELEM(type, CD_PROP_BYTE_COLOR, CD_PROP_FLOAT2)) {
htype = BM_LOOP;
}
else if (ELEM(type, CD_PROP_COLOR)) {
@@ -186,18 +189,18 @@ static void mesh_uv_reset_bmface(BMFace *f, const int cd_loop_uv_offset)
int i;
BM_ITER_ELEM_INDEX (l, &liter, f, BM_LOOPS_OF_FACE, i) {
fuv[i] = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset))->uv;
fuv[i] = ((float *)BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset));
}
mesh_uv_reset_array(fuv.data(), f->len);
}
static void mesh_uv_reset_mface(const MPoly *mp, MLoopUV *mloopuv)
static void mesh_uv_reset_mface(const MPoly *mp, float2 *mloopuv)
{
Array<float *, BM_DEFAULT_NGON_STACK_SIZE> fuv(mp->totloop);
for (int i = 0; i < mp->totloop; i++) {
fuv[i] = mloopuv[mp->loopstart + i].uv;
fuv[i] = mloopuv[mp->loopstart + i];
}
mesh_uv_reset_array(fuv.data(), mp->totloop);
@@ -209,7 +212,8 @@ void ED_mesh_uv_loop_reset_ex(Mesh *me, const int layernum)
if (em) {
/* Collect BMesh UVs */
const int cd_loop_uv_offset = CustomData_get_n_offset(&em->bm->ldata, CD_MLOOPUV, layernum);
const int cd_loop_uv_offset = CustomData_get_n_offset(
&em->bm->ldata, CD_PROP_FLOAT2, layernum);
BMFace *efa;
BMIter iter;
@@ -226,8 +230,9 @@ void ED_mesh_uv_loop_reset_ex(Mesh *me, const int layernum)
}
else {
/* Collect Mesh UVs */
BLI_assert(CustomData_has_layer(&me->ldata, CD_MLOOPUV));
MLoopUV *mloopuv = (MLoopUV *)CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, layernum);
BLI_assert(CustomData_has_layer(&me->ldata, CD_PROP_FLOAT2));
float2 *mloopuv = static_cast<float2 *>(
CustomData_get_layer_n(&me->ldata, CD_PROP_FLOAT2, layernum));
const MPoly *polys = BKE_mesh_polys(me);
for (int i = 0; i < me->totpoly; i++) {
@@ -242,7 +247,7 @@ void ED_mesh_uv_loop_reset(bContext *C, Mesh *me)
{
/* could be ldata or pdata */
CustomData *ldata = GET_CD_DATA(me, ldata);
const int layernum = CustomData_get_active_layer(ldata, CD_MLOOPUV);
const int layernum = CustomData_get_active_layer(ldata, CD_PROP_FLOAT2);
ED_mesh_uv_loop_reset_ex(me, layernum);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
@@ -256,53 +261,60 @@ int ED_mesh_uv_add(
BMEditMesh *em;
int layernum_dst;
if (!name) {
name = DATA_("UVMap");
}
char unique_name[MAX_CUSTOMDATA_LAYER_NAME];
BKE_id_attribute_calc_unique_name(&me->id, name, unique_name);
bool is_init = false;
if (me->edit_mesh) {
em = me->edit_mesh;
layernum_dst = CustomData_number_of_layers(&em->bm->ldata, CD_MLOOPUV);
layernum_dst = CustomData_number_of_layers(&em->bm->ldata, CD_PROP_FLOAT2);
if (layernum_dst >= MAX_MTFACE) {
BKE_reportf(reports, RPT_WARNING, "Cannot add more than %i UV maps", MAX_MTFACE);
return -1;
}
/* CD_MLOOPUV */
BM_data_layer_add_named(em->bm, &em->bm->ldata, CD_MLOOPUV, name);
BM_data_layer_add_named(em->bm, &em->bm->ldata, CD_PROP_FLOAT2, unique_name);
BM_uv_map_ensure_select_and_pin_attrs(em->bm);
/* copy data from active UV */
if (layernum_dst && do_init) {
const int layernum_src = CustomData_get_active_layer(&em->bm->ldata, CD_MLOOPUV);
BM_data_layer_copy(em->bm, &em->bm->ldata, CD_MLOOPUV, layernum_src, layernum_dst);
const int layernum_src = CustomData_get_active_layer(&em->bm->ldata, CD_PROP_FLOAT2);
BM_data_layer_copy(em->bm, &em->bm->ldata, CD_PROP_FLOAT2, layernum_src, layernum_dst);
is_init = true;
}
if (active_set || layernum_dst == 0) {
CustomData_set_layer_active(&em->bm->ldata, CD_MLOOPUV, layernum_dst);
CustomData_set_layer_active(&em->bm->ldata, CD_PROP_FLOAT2, layernum_dst);
}
}
else {
layernum_dst = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV);
layernum_dst = CustomData_number_of_layers(&me->ldata, CD_PROP_FLOAT2);
if (layernum_dst >= MAX_MTFACE) {
BKE_reportf(reports, RPT_WARNING, "Cannot add more than %i UV maps", MAX_MTFACE);
return -1;
}
if (CustomData_has_layer(&me->ldata, CD_MLOOPUV) && do_init) {
if (CustomData_has_layer(&me->ldata, CD_PROP_FLOAT2) && do_init) {
CustomData_add_layer_named(&me->ldata,
CD_MLOOPUV,
CD_PROP_FLOAT2,
CD_DUPLICATE,
CustomData_get_layer(&me->ldata, CD_MLOOPUV),
CustomData_get_layer(&me->ldata, CD_PROP_FLOAT2),
me->totloop,
name);
unique_name);
is_init = true;
}
else {
CustomData_add_layer_named(
&me->ldata, CD_MLOOPUV, CD_SET_DEFAULT, nullptr, me->totloop, name);
&me->ldata, CD_PROP_FLOAT2, CD_SET_DEFAULT, nullptr, me->totloop, unique_name);
}
if (active_set || layernum_dst == 0) {
CustomData_set_layer_active(&me->ldata, CD_MLOOPUV, layernum_dst);
CustomData_set_layer_active(&me->ldata, CD_PROP_FLOAT2, layernum_dst);
}
}
@@ -317,6 +329,72 @@ int ED_mesh_uv_add(
return layernum_dst;
}
static const bool *mesh_loop_boolean_custom_data_get_by_name(const Mesh &mesh, const char *name)
{
return static_cast<const bool *>(CustomData_get_layer_named(&mesh.ldata, CD_PROP_BOOL, name));
}
const bool *ED_mesh_uv_map_vert_select_layer_get(const Mesh *mesh, const int uv_index)
{
using namespace blender::bke;
char buffer[MAX_CUSTOMDATA_LAYER_NAME];
const char *uv_name = CustomData_get_layer_name(&mesh->ldata, CD_PROP_FLOAT2, uv_index);
return mesh_loop_boolean_custom_data_get_by_name(
*mesh, BKE_uv_map_vert_select_name_get(uv_name, buffer));
}
/* UV map edge selections are stored on face corners (loops) and not on edges
* because we need selections per face edge, even when the edge is split in UV space. */
const bool *ED_mesh_uv_map_edge_select_layer_get(const Mesh *mesh, const int uv_index)
{
using namespace blender::bke;
char buffer[MAX_CUSTOMDATA_LAYER_NAME];
const char *uv_name = CustomData_get_layer_name(&mesh->ldata, CD_PROP_FLOAT2, uv_index);
return mesh_loop_boolean_custom_data_get_by_name(
*mesh, BKE_uv_map_edge_select_name_get(uv_name, buffer));
}
const bool *ED_mesh_uv_map_pin_layer_get(const Mesh *mesh, const int uv_index)
{
using namespace blender::bke;
char buffer[MAX_CUSTOMDATA_LAYER_NAME];
const char *uv_name = CustomData_get_layer_name(&mesh->ldata, CD_PROP_FLOAT2, uv_index);
return mesh_loop_boolean_custom_data_get_by_name(*mesh,
BKE_uv_map_pin_name_get(uv_name, buffer));
}
static bool *ensure_corner_boolean_attribute(Mesh &mesh, const blender::StringRefNull name)
{
bool *data = static_cast<bool *>(CustomData_duplicate_referenced_layer_named(
&mesh.ldata, CD_PROP_BOOL, name.c_str(), mesh.totloop));
if (!data) {
data = static_cast<bool *>(CustomData_add_layer_named(
&mesh.ldata, CD_PROP_BOOL, CD_SET_DEFAULT, nullptr, mesh.totpoly, name.c_str()));
}
return data;
}
bool *ED_mesh_uv_map_vert_select_layer_ensure(Mesh *mesh, const int uv_index)
{
using namespace blender::bke;
char buffer[MAX_CUSTOMDATA_LAYER_NAME];
const char *uv_name = CustomData_get_layer_name(&mesh->ldata, CD_PROP_FLOAT2, uv_index);
return ensure_corner_boolean_attribute(*mesh, BKE_uv_map_vert_select_name_get(uv_name, buffer));
}
bool *ED_mesh_uv_map_edge_select_layer_ensure(Mesh *mesh, const int uv_index)
{
using namespace blender::bke;
char buffer[MAX_CUSTOMDATA_LAYER_NAME];
const char *uv_name = CustomData_get_layer_name(&mesh->ldata, CD_PROP_FLOAT2, uv_index);
return ensure_corner_boolean_attribute(*mesh, BKE_uv_map_edge_select_name_get(uv_name, buffer));
}
bool *ED_mesh_uv_map_pin_layer_ensure(Mesh *mesh, const int uv_index)
{
using namespace blender::bke;
char buffer[MAX_CUSTOMDATA_LAYER_NAME];
const char *uv_name = CustomData_get_layer_name(&mesh->ldata, CD_PROP_FLOAT2, uv_index);
return ensure_corner_boolean_attribute(*mesh, BKE_uv_map_pin_name_get(uv_name, buffer));
}
void ED_mesh_uv_ensure(Mesh *me, const char *name)
{
BMEditMesh *em;
@@ -325,13 +403,13 @@ void ED_mesh_uv_ensure(Mesh *me, const char *name)
if (me->edit_mesh) {
em = me->edit_mesh;
layernum_dst = CustomData_number_of_layers(&em->bm->ldata, CD_MLOOPUV);
layernum_dst = CustomData_number_of_layers(&em->bm->ldata, CD_PROP_FLOAT2);
if (layernum_dst == 0) {
ED_mesh_uv_add(me, name, true, true, nullptr);
}
}
else {
layernum_dst = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV);
layernum_dst = CustomData_number_of_layers(&me->ldata, CD_PROP_FLOAT2);
if (layernum_dst == 0) {
ED_mesh_uv_add(me, name, true, true, nullptr);
}
@@ -344,7 +422,7 @@ bool ED_mesh_uv_remove_index(Mesh *me, const int n)
CustomDataLayer *cdlu;
int index;
index = CustomData_get_layer_index_n(ldata, CD_MLOOPUV, n);
index = CustomData_get_layer_index_n(ldata, CD_PROP_FLOAT2, n);
cdlu = (index == -1) ? nullptr : &ldata->layers[index];
if (!cdlu) {
@@ -361,7 +439,7 @@ bool ED_mesh_uv_remove_index(Mesh *me, const int n)
bool ED_mesh_uv_remove_active(Mesh *me)
{
CustomData *ldata = GET_CD_DATA(me, ldata);
const int n = CustomData_get_active_layer(ldata, CD_MLOOPUV);
const int n = CustomData_get_active_layer(ldata, CD_PROP_FLOAT2);
if (n != -1) {
return ED_mesh_uv_remove_index(me, n);
@@ -371,7 +449,7 @@ bool ED_mesh_uv_remove_active(Mesh *me)
bool ED_mesh_uv_remove_named(Mesh *me, const char *name)
{
CustomData *ldata = GET_CD_DATA(me, ldata);
const int n = CustomData_get_named_layer(ldata, CD_MLOOPUV, name);
const int n = CustomData_get_named_layer(ldata, CD_PROP_FLOAT2, name);
if (n != -1) {
return ED_mesh_uv_remove_index(me, n);
}
@@ -508,7 +586,7 @@ static bool uv_texture_remove_poll(bContext *C)
Object *ob = ED_object_context(C);
Mesh *me = static_cast<Mesh *>(ob->data);
CustomData *ldata = GET_CD_DATA(me, ldata);
const int active = CustomData_get_active_layer(ldata, CD_MLOOPUV);
const int active = CustomData_get_active_layer(ldata, CD_PROP_FLOAT2);
if (active != -1) {
return true;
}
@@ -549,12 +627,14 @@ void MESH_OT_uv_texture_add(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
static int mesh_uv_texture_remove_exec(bContext *C, wmOperator * /*op*/)
static int mesh_uv_texture_remove_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_context(C);
Mesh *me = static_cast<Mesh *>(ob->data);
if (!ED_mesh_uv_remove_active(me)) {
CustomData *ldata = GET_CD_DATA(me, ldata);
const char *name = CustomData_get_active_layer_name(ldata, CD_PROP_FLOAT2);
if (!BKE_id_attribute_remove(&me->id, name, op->reports)) {
return OPERATOR_CANCELLED;
}
+3 -3
View File
@@ -1050,9 +1050,9 @@ static float *editmesh_get_mirror_uv(
BMLoop *l;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
MLoopUV *luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
if ((fabsf(luv->uv[0] - vec[0]) < 0.001f) && (fabsf(luv->uv[1] - vec[1]) < 0.001f)) {
return luv->uv;
float *luv2 = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_PROP_FLOAT2);
if ((fabsf(luv[0] - vec[0]) < 0.001f) && (fabsf(luv[1] - vec[1]) < 0.001f)) {
return luv;
}
}
}
+1 -1
View File
@@ -2097,7 +2097,7 @@ static int object_curves_empty_hair_add_exec(bContext *C, wmOperator *op)
/* Decide which UV map to use for attachment. */
Mesh *surface_mesh = static_cast<Mesh *>(surface_ob->data);
const char *uv_name = CustomData_get_active_layer_name(&surface_mesh->ldata, CD_MLOOPUV);
const char *uv_name = CustomData_get_active_layer_name(&surface_mesh->ldata, CD_PROP_FLOAT2);
if (uv_name != nullptr) {
curves_id->surface_uv_map = BLI_strdup(uv_name);
}
+1 -1
View File
@@ -155,7 +155,7 @@ static bool multiresbake_check(bContext *C, wmOperator *op)
break;
}
if (!CustomData_has_layer(&me->ldata, CD_MLOOPUV)) {
if (!CustomData_has_layer(&me->ldata, CD_PROP_FLOAT2)) {
BKE_report(op->reports, RPT_ERROR, "Mesh should be unwrapped before multires data baking");
ok = false;
@@ -461,7 +461,7 @@ static bool bake_object_check(const Scene *scene,
}
}
else if (target == R_BAKE_TARGET_IMAGE_TEXTURES) {
if (CustomData_get_active_layer_index(&me->ldata, CD_MLOOPUV) == -1) {
if (CustomData_get_active_layer_index(&me->ldata, CD_PROP_FLOAT2) == -1) {
BKE_reportf(
reports, RPT_ERROR, "No active UV layer found in the object \"%s\"", ob->id.name + 2);
return false;
@@ -1381,7 +1381,7 @@ static int bake(const BakeAPIRender *bkr,
if (bkr->uv_layer[0] != '\0') {
Mesh *me = (Mesh *)ob_low->data;
if (CustomData_get_named_layer(&me->ldata, CD_MLOOPUV, bkr->uv_layer) == -1) {
if (CustomData_get_named_layer(&me->ldata, CD_PROP_FLOAT2, bkr->uv_layer) == -1) {
BKE_reportf(reports,
RPT_ERROR,
"No UV layer named \"%s\" found in the object \"%s\"",
@@ -2246,7 +2246,7 @@ void OBJECT_OT_bake(wmOperatorType *ot)
RNA_def_string(ot->srna,
"uv_layer",
NULL,
MAX_CUSTOMDATA_LAYER_NAME,
MAX_CUSTOMDATA_LAYER_NAME_NO_PREFIX,
"UV Layer",
"UV layer to override active");
}
@@ -176,16 +176,16 @@ static const EnumPropertyItem *dt_layers_select_src_itemf(bContext *C,
Object *ob_src_eval = DEG_get_evaluated_object(depsgraph, ob_src);
CustomData_MeshMasks cddata_masks = CD_MASK_BAREMESH;
cddata_masks.lmask |= CD_MASK_MLOOPUV;
cddata_masks.lmask |= CD_MASK_PROP_FLOAT2;
Mesh *me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_src_eval, &cddata_masks);
int num_data = CustomData_number_of_layers(&me_eval->ldata, CD_MLOOPUV);
int num_data = CustomData_number_of_layers(&me_eval->ldata, CD_PROP_FLOAT2);
RNA_enum_item_add_separator(&item, &totitem);
for (int i = 0; i < num_data; i++) {
tmp_item.value = i;
tmp_item.identifier = tmp_item.name = CustomData_get_layer_name(
&me_eval->ldata, CD_MLOOPUV, i);
&me_eval->ldata, CD_PROP_FLOAT2, i);
RNA_enum_item_add(&item, &totitem, &tmp_item);
}
}
@@ -421,16 +421,16 @@ struct ProjPaintState {
const MLoop *mloop_eval;
const MLoopTri *mlooptri_eval;
const MLoopUV *mloopuv_stencil_eval;
const float (*mloopuv_stencil_eval)[2];
/**
* \note These UV layers are aligned to \a mpoly_eval
* but each pointer references the start of the layer,
* so a loop indirection is needed as well.
*/
const MLoopUV **poly_to_loop_uv;
const float (**poly_to_loop_uv)[2];
/** other UV map, use for cloning between layers. */
const MLoopUV **poly_to_loop_uv_clone;
const float (**poly_to_loop_uv_clone)[2];
/* Actual material for each index, either from object or Mesh datablock... */
Material **mat_array;
@@ -518,14 +518,13 @@ BLI_INLINE const MPoly *ps_tri_index_to_mpoly(const ProjPaintState *ps, int tri_
int(ps->mloop_eval[lt->tri[2]].v),
#define PS_LOOPTRI_AS_UV_3(uvlayer, lt) \
uvlayer[lt->poly][lt->tri[0]].uv, uvlayer[lt->poly][lt->tri[1]].uv, \
uvlayer[lt->poly][lt->tri[2]].uv,
uvlayer[lt->poly][lt->tri[0]], uvlayer[lt->poly][lt->tri[1]], uvlayer[lt->poly][lt->tri[2]],
#define PS_LOOPTRI_ASSIGN_UV_3(uv_tri, uvlayer, lt) \
{ \
(uv_tri)[0] = uvlayer[lt->poly][lt->tri[0]].uv; \
(uv_tri)[1] = uvlayer[lt->poly][lt->tri[1]].uv; \
(uv_tri)[2] = uvlayer[lt->poly][lt->tri[2]].uv; \
(uv_tri)[0] = uvlayer[lt->poly][lt->tri[0]]; \
(uv_tri)[1] = uvlayer[lt->poly][lt->tri[1]]; \
(uv_tri)[2] = uvlayer[lt->poly][lt->tri[2]]; \
} \
((void)0)
@@ -1672,9 +1671,9 @@ static float project_paint_uvpixel_mask(const ProjPaintState *ps,
if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, nullptr, nullptr))) {
const MLoopTri *lt_other = &ps->mlooptri_eval[tri_index];
const float *lt_other_tri_uv[3] = {ps->mloopuv_stencil_eval[lt_other->tri[0]].uv,
ps->mloopuv_stencil_eval[lt_other->tri[1]].uv,
ps->mloopuv_stencil_eval[lt_other->tri[2]].uv};
const float *lt_other_tri_uv[3] = {ps->mloopuv_stencil_eval[lt_other->tri[0]],
ps->mloopuv_stencil_eval[lt_other->tri[1]],
ps->mloopuv_stencil_eval[lt_other->tri[2]]};
/* #BKE_image_acquire_ibuf - TODO: this may be slow. */
uchar rgba_ub[4];
@@ -4048,7 +4047,7 @@ static bool proj_paint_state_mesh_eval_init(const bContext *C, ProjPaintState *p
CustomData_MeshMasks cddata_masks = scene_eval->customdata_mask;
cddata_masks.fmask |= CD_MASK_MTFACE;
cddata_masks.lmask |= CD_MASK_MLOOPUV;
cddata_masks.lmask |= CD_MASK_PROP_FLOAT2;
if (ps->do_face_sel) {
cddata_masks.vmask |= CD_MASK_ORIGINDEX;
cddata_masks.emask |= CD_MASK_ORIGINDEX;
@@ -4056,7 +4055,7 @@ static bool proj_paint_state_mesh_eval_init(const bContext *C, ProjPaintState *p
}
ps->me_eval = mesh_get_eval_final(depsgraph, scene_eval, ob_eval, &cddata_masks);
if (!CustomData_has_layer(&ps->me_eval->ldata, CD_MLOOPUV)) {
if (!CustomData_has_layer(&ps->me_eval->ldata, CD_PROP_FLOAT2)) {
ps->me_eval = nullptr;
return false;
}
@@ -4094,38 +4093,39 @@ static bool proj_paint_state_mesh_eval_init(const bContext *C, ProjPaintState *p
ps->mlooptri_eval = BKE_mesh_runtime_looptri_ensure(ps->me_eval);
ps->totlooptri_eval = BKE_mesh_runtime_looptri_len(ps->me_eval);
ps->poly_to_loop_uv = static_cast<const MLoopUV **>(
MEM_mallocN(ps->totpoly_eval * sizeof(MLoopUV *), "proj_paint_mtfaces"));
ps->poly_to_loop_uv = static_cast<const float(**)[2]>(
MEM_mallocN(ps->totpoly_eval * sizeof(float(*)[2]), "proj_paint_mtfaces"));
return true;
}
struct ProjPaintLayerClone {
const MLoopUV *mloopuv_clone_base;
const float (*mloopuv_clone_base)[2];
const TexPaintSlot *slot_last_clone;
const TexPaintSlot *slot_clone;
};
static void proj_paint_layer_clone_init(ProjPaintState *ps, ProjPaintLayerClone *layer_clone)
{
const MLoopUV *mloopuv_clone_base = nullptr;
const float(*mloopuv_clone_base)[2] = nullptr;
/* use clone mtface? */
if (ps->do_layer_clone) {
const int layer_num = CustomData_get_clone_layer(&((Mesh *)ps->ob->data)->ldata, CD_MLOOPUV);
const int layer_num = CustomData_get_clone_layer(&((Mesh *)ps->ob->data)->ldata,
CD_PROP_FLOAT2);
ps->poly_to_loop_uv_clone = static_cast<const MLoopUV **>(
MEM_mallocN(ps->totpoly_eval * sizeof(MLoopUV *), "proj_paint_mtfaces"));
ps->poly_to_loop_uv_clone = static_cast<const float(**)[2]>(
MEM_mallocN(ps->totpoly_eval * sizeof(float(*)[2]), "proj_paint_mtfaces"));
if (layer_num != -1) {
mloopuv_clone_base = static_cast<const MLoopUV *>(
CustomData_get_layer_n(&ps->me_eval->ldata, CD_MLOOPUV, layer_num));
mloopuv_clone_base = static_cast<const float(*)[2]>(
CustomData_get_layer_n(&ps->me_eval->ldata, CD_PROP_FLOAT2, layer_num));
}
if (mloopuv_clone_base == nullptr) {
/* get active instead */
mloopuv_clone_base = static_cast<const MLoopUV *>(
CustomData_get_layer(&ps->me_eval->ldata, CD_MLOOPUV));
mloopuv_clone_base = static_cast<const float(*)[2]>(
CustomData_get_layer(&ps->me_eval->ldata, CD_PROP_FLOAT2));
}
}
@@ -4154,10 +4154,10 @@ static bool project_paint_clone_face_skip(ProjPaintState *ps,
if (ps->do_material_slots) {
if (lc->slot_clone != lc->slot_last_clone) {
if (!lc->slot_clone->uvname ||
!(lc->mloopuv_clone_base = static_cast<const MLoopUV *>(CustomData_get_layer_named(
&ps->me_eval->ldata, CD_MLOOPUV, lc->slot_clone->uvname)))) {
lc->mloopuv_clone_base = static_cast<const MLoopUV *>(
CustomData_get_layer(&ps->me_eval->ldata, CD_MLOOPUV));
!(lc->mloopuv_clone_base = static_cast<const float(*)[2]>(CustomData_get_layer_named(
&ps->me_eval->ldata, CD_PROP_FLOAT2, lc->slot_clone->uvname)))) {
lc->mloopuv_clone_base = static_cast<const float(*)[2]>(
CustomData_get_layer(&ps->me_eval->ldata, CD_PROP_FLOAT2));
}
lc->slot_last_clone = lc->slot_clone;
}
@@ -4299,7 +4299,7 @@ static void project_paint_prepare_all_faces(ProjPaintState *ps,
MemArena *arena,
const ProjPaintFaceLookup *face_lookup,
ProjPaintLayerClone *layer_clone,
const MLoopUV *mloopuv_base,
const float (*mloopuv_base)[2],
const bool is_multi_view)
{
/* Image Vars - keep track of images we have used */
@@ -4325,17 +4325,17 @@ static void project_paint_prepare_all_faces(ProjPaintState *ps,
slot = project_paint_face_paint_slot(ps, tri_index);
/* all faces should have a valid slot, reassert here */
if (slot == nullptr) {
mloopuv_base = static_cast<const MLoopUV *>(
CustomData_get_layer(&ps->me_eval->ldata, CD_MLOOPUV));
mloopuv_base = static_cast<const float(*)[2]>(
CustomData_get_layer(&ps->me_eval->ldata, CD_PROP_FLOAT2));
tpage = ps->canvas_ima;
}
else {
if (slot != slot_last) {
if (!slot->uvname ||
!(mloopuv_base = static_cast<const MLoopUV *>(
CustomData_get_layer_named(&ps->me_eval->ldata, CD_MLOOPUV, slot->uvname)))) {
mloopuv_base = static_cast<const MLoopUV *>(
CustomData_get_layer(&ps->me_eval->ldata, CD_MLOOPUV));
!(mloopuv_base = static_cast<const float(*)[2]>(CustomData_get_layer_named(
&ps->me_eval->ldata, CD_PROP_FLOAT2, slot->uvname)))) {
mloopuv_base = static_cast<const float(*)[2]>(
CustomData_get_layer(&ps->me_eval->ldata, CD_PROP_FLOAT2));
}
slot_last = slot;
}
@@ -4360,7 +4360,7 @@ static void project_paint_prepare_all_faces(ProjPaintState *ps,
ps->poly_to_loop_uv[lt->poly] = mloopuv_base;
tile = project_paint_face_paint_tile(tpage, mloopuv_base[lt->tri[0]].uv);
tile = project_paint_face_paint_tile(tpage, mloopuv_base[lt->tri[0]]);
#ifndef PROJ_DEBUG_NOSEAMBLEED
project_paint_bleed_add_face_user(ps, arena, lt, tri_index);
@@ -4478,7 +4478,7 @@ static void project_paint_begin(const bContext *C,
{
ProjPaintLayerClone layer_clone;
ProjPaintFaceLookup face_lookup;
const MLoopUV *mloopuv_base = nullptr;
const float(*mloopuv_base)[2] = nullptr;
/* At the moment this is just ps->arena_mt[0], but use this to show were not multi-threading. */
MemArena *arena;
@@ -4508,17 +4508,17 @@ static void project_paint_begin(const bContext *C,
proj_paint_layer_clone_init(ps, &layer_clone);
if (ps->do_layer_stencil || ps->do_stencil_brush) {
// int layer_num = CustomData_get_stencil_layer(&ps->me_eval->ldata, CD_MLOOPUV);
int layer_num = CustomData_get_stencil_layer(&((Mesh *)ps->ob->data)->ldata, CD_MLOOPUV);
// int layer_num = CustomData_get_stencil_layer(&ps->me_eval->ldata, CD_PROP_FLOAT2);
int layer_num = CustomData_get_stencil_layer(&((Mesh *)ps->ob->data)->ldata, CD_PROP_FLOAT2);
if (layer_num != -1) {
ps->mloopuv_stencil_eval = static_cast<const MLoopUV *>(
CustomData_get_layer_n(&ps->me_eval->ldata, CD_MLOOPUV, layer_num));
ps->mloopuv_stencil_eval = static_cast<const float(*)[2]>(
CustomData_get_layer_n(&ps->me_eval->ldata, CD_PROP_FLOAT2, layer_num));
}
if (ps->mloopuv_stencil_eval == nullptr) {
/* get active instead */
ps->mloopuv_stencil_eval = static_cast<const MLoopUV *>(
CustomData_get_layer(&ps->me_eval->ldata, CD_MLOOPUV));
ps->mloopuv_stencil_eval = static_cast<const float(*)[2]>(
CustomData_get_layer(&ps->me_eval->ldata, CD_PROP_FLOAT2));
}
if (ps->do_stencil_brush) {
@@ -6424,7 +6424,7 @@ bool ED_paint_proj_mesh_data_check(
}
me = BKE_mesh_from_object(ob);
layernum = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV);
layernum = CustomData_number_of_layers(&me->ldata, CD_PROP_FLOAT2);
if (layernum == 0) {
hasuvs = false;
@@ -312,8 +312,8 @@ static void imapaint_pick_uv(
findex = index_mp_to_orig ? index_mp_to_orig[lt->poly] : lt->poly;
if (findex == faceindex) {
const MLoopUV *mloopuv;
const MLoopUV *tri_uv[3];
const float(*mloopuv)[2];
const float *tri_uv[3];
float tri_co[3][3];
for (int j = 3; j--;) {
@@ -329,17 +329,18 @@ static void imapaint_pick_uv(
slot = &ma->texpaintslot[ma->paint_active_slot];
if (!(slot && slot->uvname &&
(mloopuv = CustomData_get_layer_named(&me_eval->ldata, CD_MLOOPUV, slot->uvname)))) {
mloopuv = CustomData_get_layer(&me_eval->ldata, CD_MLOOPUV);
(mloopuv = CustomData_get_layer_named(
&me_eval->ldata, CD_PROP_FLOAT2, slot->uvname)))) {
mloopuv = CustomData_get_layer(&me_eval->ldata, CD_PROP_FLOAT2);
}
}
else {
mloopuv = CustomData_get_layer(&me_eval->ldata, CD_MLOOPUV);
mloopuv = CustomData_get_layer(&me_eval->ldata, CD_PROP_FLOAT2);
}
tri_uv[0] = &mloopuv[lt->tri[0]];
tri_uv[1] = &mloopuv[lt->tri[1]];
tri_uv[2] = &mloopuv[lt->tri[2]];
tri_uv[0] = mloopuv[lt->tri[0]];
tri_uv[1] = mloopuv[lt->tri[1]];
tri_uv[2] = mloopuv[lt->tri[2]];
p[0] = xy[0];
p[1] = xy[1];
@@ -347,8 +348,8 @@ static void imapaint_pick_uv(
imapaint_tri_weights(matrix, view, UNPACK3(tri_co), p, w);
absw = fabsf(w[0]) + fabsf(w[1]) + fabsf(w[2]);
if (absw < minabsw) {
uv[0] = tri_uv[0]->uv[0] * w[0] + tri_uv[1]->uv[0] * w[1] + tri_uv[2]->uv[0] * w[2];
uv[1] = tri_uv[0]->uv[1] * w[0] + tri_uv[1]->uv[1] * w[1] + tri_uv[2]->uv[1] * w[2];
uv[0] = tri_uv[0][0] * w[0] + tri_uv[1][0] * w[1] + tri_uv[2][0] * w[2];
uv[1] = tri_uv[0][1] * w[0] + tri_uv[1][1] * w[1] + tri_uv[2][1] * w[2];
minabsw = absw;
}
}
@@ -423,7 +424,7 @@ void paint_sample_color(
uint faceindex;
uint totpoly = me->totpoly;
if (CustomData_has_layer(&me_eval->ldata, CD_MLOOPUV)) {
if (CustomData_has_layer(&me_eval->ldata, CD_PROP_FLOAT2)) {
ED_view3d_viewcontext_init(C, &vc, depsgraph);
view3d_operator_needs_opengl(C);
+34 -33
View File
@@ -219,7 +219,7 @@ static void HC_relaxation_iteration_uv(BMEditMesh *em,
apply_sculpt_data_constraints(sculptdata, sculptdata->uv[i].uv);
for (element = sculptdata->uv[i].element; element; element = element->next) {
MLoopUV *luv;
float(*luv)[2];
BMLoop *l;
if (element->separate && element != sculptdata->uv[i].element) {
@@ -227,8 +227,8 @@ static void HC_relaxation_iteration_uv(BMEditMesh *em,
}
l = element->l;
luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
copy_v2_v2(luv->uv, sculptdata->uv[i].uv);
luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_PROP_FLOAT2);
copy_v2_v2(*luv, sculptdata->uv[i].uv);
}
}
}
@@ -302,7 +302,7 @@ static void laplacian_relaxation_iteration_uv(BMEditMesh *em,
apply_sculpt_data_constraints(sculptdata, sculptdata->uv[i].uv);
for (element = sculptdata->uv[i].element; element; element = element->next) {
MLoopUV *luv;
float(*luv)[2];
BMLoop *l;
if (element->separate && element != sculptdata->uv[i].element) {
@@ -310,8 +310,8 @@ static void laplacian_relaxation_iteration_uv(BMEditMesh *em,
}
l = element->l;
luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
copy_v2_v2(luv->uv, sculptdata->uv[i].uv);
luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_PROP_FLOAT2);
copy_v2_v2(*luv, sculptdata->uv[i].uv);
}
}
}
@@ -323,12 +323,12 @@ static void add_weighted_edge(float (*delta_buf)[3],
const UvElement *storage,
const UvElement *ele_next,
const UvElement *ele_prev,
const MLoopUV *luv_next,
const MLoopUV *luv_prev,
const float luv_next[2],
const float luv_prev[2],
const float weight)
{
float delta[2];
sub_v2_v2v2(delta, luv_next->uv, luv_prev->uv);
sub_v2_v2v2(delta, luv_next, luv_prev);
bool code1 = (ele_prev->flag & MARK_BOUNDARY);
bool code2 = (ele_next->flag & MARK_BOUNDARY);
@@ -380,7 +380,7 @@ static void relaxation_iteration_uv(BMEditMesh *em,
struct UvElement **head_table = BM_uv_element_map_ensure_head_table(sculptdata->elementMap);
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_PROP_FLOAT2);
BLI_assert(cd_loop_uv_offset >= 0);
const int total_uvs = sculptdata->elementMap->total_uvs;
@@ -397,9 +397,9 @@ static void relaxation_iteration_uv(BMEditMesh *em,
const float *v_prev_co = ele_prev->l->v->co;
const float *v_next_co = ele_next->l->v->co;
const MLoopUV *luv_curr = BM_ELEM_CD_GET_VOID_P(ele_curr->l, cd_loop_uv_offset);
const MLoopUV *luv_next = BM_ELEM_CD_GET_VOID_P(ele_next->l, cd_loop_uv_offset);
const MLoopUV *luv_prev = BM_ELEM_CD_GET_VOID_P(ele_prev->l, cd_loop_uv_offset);
const float(*luv_curr)[2] = BM_ELEM_CD_GET_FLOAT2_P(ele_curr->l, cd_loop_uv_offset);
const float(*luv_next)[2] = BM_ELEM_CD_GET_FLOAT2_P(ele_next->l, cd_loop_uv_offset);
const float(*luv_prev)[2] = BM_ELEM_CD_GET_FLOAT2_P(ele_prev->l, cd_loop_uv_offset);
const UvElement *head_curr = head_table[ele_curr - sculptdata->elementMap->storage];
const UvElement *head_next = head_table[ele_next - sculptdata->elementMap->storage];
@@ -407,11 +407,11 @@ static void relaxation_iteration_uv(BMEditMesh *em,
/* If the mesh is triangulated with no boundaries, only one edge is required. */
const float weight_curr = tri_weight_v3(method, v_curr_co, v_prev_co, v_next_co);
add_weighted_edge(delta_buf, storage, head_next, head_prev, luv_next, luv_prev, weight_curr);
add_weighted_edge(delta_buf, storage, head_next, head_prev, *luv_next, *luv_prev, weight_curr);
/* Triangulated with a boundary? We need the incoming edges to solve the boundary. */
const float weight_prev = tri_weight_v3(method, v_prev_co, v_curr_co, v_next_co);
add_weighted_edge(delta_buf, storage, head_next, head_curr, luv_next, luv_curr, weight_prev);
add_weighted_edge(delta_buf, storage, head_next, head_curr, *luv_next, *luv_curr, weight_prev);
if (method == UV_SCULPT_TOOL_RELAX_LAPLACIAN) {
/* Laplacian method has zero weights on virtual edges. */
@@ -420,7 +420,7 @@ static void relaxation_iteration_uv(BMEditMesh *em,
/* Meshes with quads (or other n-gons) need "virtual" edges too. */
const float weight_next = tri_weight_v3(method, v_next_co, v_curr_co, v_prev_co);
add_weighted_edge(delta_buf, storage, head_prev, head_curr, luv_prev, luv_curr, weight_next);
add_weighted_edge(delta_buf, storage, head_prev, head_curr, *luv_prev, *luv_curr, weight_next);
}
Brush *brush = BKE_paint_brush(sculptdata->uvsculpt);
@@ -444,18 +444,18 @@ static void relaxation_iteration_uv(BMEditMesh *em,
const float *delta_sum = delta_buf[adj_el->element - storage];
{
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(adj_el->element->l, cd_loop_uv_offset);
BLI_assert(adj_el->uv == luv->uv); /* Only true for head. */
adj_el->uv[0] = luv->uv[0] + strength * safe_divide(delta_sum[0], delta_sum[2]);
adj_el->uv[1] = luv->uv[1] + strength * safe_divide(delta_sum[1], delta_sum[2]);
const float(*luv)[2] = BM_ELEM_CD_GET_FLOAT2_P(adj_el->element->l, cd_loop_uv_offset);
BLI_assert(adj_el->uv == (float *)luv); /* Only true for head. */
adj_el->uv[0] = (*luv)[0] + strength * safe_divide(delta_sum[0], delta_sum[2]);
adj_el->uv[1] = (*luv)[1] + strength * safe_divide(delta_sum[1], delta_sum[2]);
apply_sculpt_data_constraints(sculptdata, adj_el->uv);
}
/* Copy UV co-ordinates to all UvElements. */
UvElement *tail = adj_el->element;
while (tail) {
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(tail->l, cd_loop_uv_offset);
copy_v2_v2(luv->uv, adj_el->uv);
float(*luv)[2] = BM_ELEM_CD_GET_FLOAT2_P(tail->l, cd_loop_uv_offset);
copy_v2_v2(*luv, adj_el->uv);
tail = tail->next;
if (tail && tail->separate) {
break;
@@ -527,7 +527,7 @@ static void uv_sculpt_stroke_apply(bContext *C,
apply_sculpt_data_constraints(sculptdata, sculptdata->uv[i].uv);
for (element = sculptdata->uv[i].element; element; element = element->next) {
MLoopUV *luv;
float(*luv)[2];
BMLoop *l;
if (element->separate && element != sculptdata->uv[i].element) {
@@ -535,8 +535,8 @@ static void uv_sculpt_stroke_apply(bContext *C,
}
l = element->l;
luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
copy_v2_v2(luv->uv, sculptdata->uv[i].uv);
luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_PROP_FLOAT2);
copy_v2_v2(*luv, sculptdata->uv[i].uv);
}
}
}
@@ -570,7 +570,7 @@ static void uv_sculpt_stroke_apply(bContext *C,
apply_sculpt_data_constraints(sculptdata, sculptdata->uv[uvindex].uv);
for (element = sculptdata->uv[uvindex].element; element; element = element->next) {
MLoopUV *luv;
float(*luv)[2];
BMLoop *l;
if (element->separate && element != sculptdata->uv[uvindex].element) {
@@ -578,8 +578,8 @@ static void uv_sculpt_stroke_apply(bContext *C,
}
l = element->l;
luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
copy_v2_v2(luv->uv, sculptdata->uv[uvindex].uv);
luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_PROP_FLOAT2);
copy_v2_v2(*luv, sculptdata->uv[uvindex].uv);
}
}
if (sima->flag & SI_LIVE_UNWRAP) {
@@ -666,7 +666,7 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm
ARegion *region = CTX_wm_region(C);
float co[2];
BMFace *efa;
MLoopUV *luv;
float(*luv)[2];
BMLoop *l;
BMIter iter, liter;
@@ -736,6 +736,8 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm
data->totalUniqueUvs = unique_uvs;
/* Index for the UvElements. */
int counter = -1;
const BMUVOffsets offsets = BM_uv_map_get_offsets(em->bm);
/* initialize the unique UVs */
for (int i = 0; i < bm->totvert; i++) {
UvElement *element = data->elementMap->vertex[i];
@@ -749,14 +751,13 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wm
continue;
}
l = element->l;
luv = CustomData_bmesh_get(&em->bm->ldata, l->head.data, CD_MLOOPUV);
luv = BM_ELEM_CD_GET_FLOAT2_P(element->l, offsets.uv);
counter++;
data->uv[counter].element = element;
data->uv[counter].uv = luv->uv;
data->uv[counter].uv = *luv;
if (data->tool != UV_SCULPT_TOOL_GRAB) {
if (luv->flag & MLOOPUV_PINNED) {
if (BM_ELEM_CD_GET_BOOL(element->l, offsets.pin)) {
data->uv[counter].is_locked = true;
}
}
@@ -2413,12 +2413,12 @@ void ED_view3d_datamask(const bContext *C,
CustomData_MeshMasks *r_cddata_masks)
{
if (ELEM(v3d->shading.type, OB_TEXTURE, OB_MATERIAL, OB_RENDER)) {
r_cddata_masks->lmask |= CD_MASK_MLOOPUV | CD_MASK_PROP_BYTE_COLOR;
r_cddata_masks->lmask |= CD_MASK_PROP_FLOAT2 | CD_MASK_PROP_BYTE_COLOR;
r_cddata_masks->vmask |= CD_MASK_ORCO | CD_MASK_PROP_COLOR;
}
else if (v3d->shading.type == OB_SOLID) {
if (v3d->shading.color_type == V3D_SHADING_TEXTURE_COLOR) {
r_cddata_masks->lmask |= CD_MASK_MLOOPUV;
r_cddata_masks->lmask |= CD_MASK_PROP_FLOAT2;
}
if (v3d->shading.color_type == V3D_SHADING_VERTEX_COLOR) {
r_cddata_masks->lmask |= CD_MASK_PROP_BYTE_COLOR;
@@ -90,7 +90,8 @@ static void uv_set_connectivity_distance(const ToolSettings *ts,
BLI_LINKSTACK_INIT(queue);
BLI_LINKSTACK_INIT(queue_next);
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
const BMUVOffsets offsets = BM_uv_map_get_offsets(bm);
BMIter fiter, liter;
BMVert *f;
BMLoop *l;
@@ -105,7 +106,7 @@ static void uv_set_connectivity_distance(const ToolSettings *ts,
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
float dist;
bool uv_vert_sel = uvedit_uv_select_test_ex(ts, l, cd_loop_uv_offset);
bool uv_vert_sel = uvedit_uv_select_test_ex(ts, l, offsets);
if (uv_vert_sel) {
BLI_LINKSTACK_PUSH(queue, l);
@@ -136,10 +137,10 @@ static void uv_set_connectivity_distance(const ToolSettings *ts,
BMLoop *l_other, *l_connected;
BMIter l_connected_iter;
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
float *luv = BM_ELEM_CD_GET_FLOAT_P(l, offsets.uv);
float l_uv[2];
copy_v2_v2(l_uv, luv->uv);
copy_v2_v2(l_uv, luv);
mul_v2_v2(l_uv, aspect);
BM_ITER_ELEM (l_other, &liter, l->f, BM_LOOPS_OF_FACE) {
@@ -147,9 +148,9 @@ static void uv_set_connectivity_distance(const ToolSettings *ts,
continue;
}
float other_uv[2], edge_vec[2];
MLoopUV *luv_other = BM_ELEM_CD_GET_VOID_P(l_other, cd_loop_uv_offset);
float *luv_other = BM_ELEM_CD_GET_FLOAT_P(l_other, offsets.uv);
copy_v2_v2(other_uv, luv_other->uv);
copy_v2_v2(other_uv, luv_other);
mul_v2_v2(other_uv, aspect);
sub_v2_v2v2(edge_vec, l_uv, other_uv);
@@ -179,14 +180,14 @@ static void uv_set_connectivity_distance(const ToolSettings *ts,
continue;
}
MLoopUV *luv_connected = BM_ELEM_CD_GET_VOID_P(l_connected, cd_loop_uv_offset);
float *luv_connected = BM_ELEM_CD_GET_FLOAT_P(l_connected, offsets.uv);
connected_vert_sel = BM_elem_flag_test_bool(l_connected, TMP_LOOP_SELECT_TAG);
/* Check if this loop is connected in UV space.
* If the uv loops share the same selection state (if not, they are not connected as
* they have been ripped or other edit commands have separated them). */
bool connected = other_vert_sel == connected_vert_sel &&
equals_v2v2(luv_other->uv, luv_connected->uv);
equals_v2v2(luv_other, luv_connected);
if (!connected) {
continue;
}
@@ -261,7 +262,7 @@ static void createTransUVs(bContext *C, TransInfo *t)
int co_num;
} *island_center = NULL;
int count = 0, countsel = 0;
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
const BMUVOffsets offsets = BM_uv_map_get_offsets(em->bm);
if (!ED_space_image_show_uvedit(sima, tc->obedit)) {
continue;
@@ -291,15 +292,15 @@ static void createTransUVs(bContext *C, TransInfo *t)
/* Make sure that the loop element flag is cleared for when we use it in
* uv_set_connectivity_distance later. */
BM_elem_flag_disable(l, BM_ELEM_TAG);
if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
if (uvedit_uv_select_test(scene, l, offsets)) {
countsel++;
if (island_center) {
UvElement *element = BM_uv_element_get(elementmap, efa, l);
if (element->flag == false) {
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
add_v2_v2(island_center[element->island].co, luv->uv);
float *luv = BM_ELEM_CD_GET_FLOAT_P(l, offsets.uv);
add_v2_v2(island_center[element->island].co, luv);
island_center[element->island].co_num++;
element->flag = true;
}
@@ -354,8 +355,8 @@ static void createTransUVs(bContext *C, TransInfo *t)
}
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
const bool selected = uvedit_uv_select_test(scene, l, cd_loop_uv_offset);
MLoopUV *luv;
const bool selected = uvedit_uv_select_test(scene, l, offsets);
float(*luv)[2];
const float *center = NULL;
float prop_distance = FLT_MAX;
@@ -375,8 +376,8 @@ static void createTransUVs(bContext *C, TransInfo *t)
}
}
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
UVsToTransData(t->aspect, td++, td2d++, luv->uv, center, prop_distance, selected);
luv = (float(*)[2])BM_ELEM_CD_GET_FLOAT_P(l, offsets.uv);
UVsToTransData(t->aspect, td++, td2d++, *luv, center, prop_distance, selected);
}
}
+10 -10
View File
@@ -47,7 +47,7 @@ static int uvedit_center(Scene *scene, Object **objects, uint objects_len, float
BMFace *f;
BMLoop *l;
BMIter iter, liter;
MLoopUV *luv;
float *luv;
int tot = 0;
zero_v2(center);
@@ -55,7 +55,7 @@ static int uvedit_center(Scene *scene, Object **objects, uint objects_len, float
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
BMEditMesh *em = BKE_editmesh_from_object(obedit);
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
const BMUVOffsets offsets = BM_uv_map_get_offsets(em->bm);
BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) {
if (!uvedit_face_visible_test(scene, f)) {
@@ -63,9 +63,9 @@ static int uvedit_center(Scene *scene, Object **objects, uint objects_len, float
}
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
add_v2_v2(center, luv->uv);
if (uvedit_uv_select_test(scene, l, offsets)) {
luv = BM_ELEM_CD_GET_FLOAT_P(l, offsets.uv);
add_v2_v2(center, luv);
tot++;
}
}
@@ -88,13 +88,13 @@ static void uvedit_translate(Scene *scene,
BMFace *f;
BMLoop *l;
BMIter iter, liter;
MLoopUV *luv;
float *luv;
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
BMEditMesh *em = BKE_editmesh_from_object(obedit);
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
const BMUVOffsets offsets = BM_uv_map_get_offsets(em->bm);
BM_ITER_MESH (f, &iter, em->bm, BM_FACES_OF_MESH) {
if (!uvedit_face_visible_test(scene, f)) {
@@ -102,9 +102,9 @@ static void uvedit_translate(Scene *scene,
}
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
add_v2_v2(luv->uv, delta);
if (uvedit_uv_select_test(scene, l, offsets)) {
luv = BM_ELEM_CD_GET_FLOAT_P(l, offsets.uv);
add_v2_v2(luv, delta);
}
}
}
@@ -157,8 +157,8 @@ void UV_ClipboardBuffer::append(UvElementMap *element_map, const int cd_loop_uv_
if (!element->separate) {
continue;
}
MLoopUV *luv = static_cast<MLoopUV *>(BM_ELEM_CD_GET_VOID_P(element->l, cd_loop_uv_offset));
uv.append(std::make_pair(luv->uv[0], luv->uv[1]));
float *luv = BM_ELEM_CD_GET_FLOAT_P(element->l, cd_loop_uv_offset);
uv.append(std::make_pair(luv[0], luv[1]));
}
}
}
@@ -183,9 +183,9 @@ void UV_ClipboardBuffer::write_uvs(UvElementMap *element_map,
BLI_assert(unique_uv < label.size());
const std::pair<float, float> &source_uv = uv_clipboard->uv[label[unique_uv]];
while (element) {
MLoopUV *luv = static_cast<MLoopUV *>(BM_ELEM_CD_GET_VOID_P(element->l, cd_loop_uv_offset));
luv->uv[0] = source_uv.first;
luv->uv[1] = source_uv.second;
float *luv = BM_ELEM_CD_GET_FLOAT_P(element->l, cd_loop_uv_offset);
luv[0] = source_uv.first;
luv[1] = source_uv.second;
element = element->next;
if (!element || element->separate) {
break;
@@ -282,7 +282,7 @@ static int uv_copy_exec(bContext *C, wmOperator * /*op*/)
UvElementMap *element_map = BM_uv_element_map_create(
em->bm, scene, true, false, use_seams, true);
if (element_map) {
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_PROP_FLOAT2);
uv_clipboard->append(element_map, cd_loop_uv_offset);
}
BM_uv_element_map_free(element_map);
@@ -313,7 +313,7 @@ static int uv_paste_exec(bContext *C, wmOperator * /*op*/)
BMEditMesh *em = BKE_editmesh_from_object(ob);
const bool use_seams = false;
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_PROP_FLOAT2);
UvElementMap *dest_element_map = BM_uv_element_map_create(
em->bm, scene, true, false, use_seams, true);
@@ -121,13 +121,13 @@ BMLoop *uv_find_nearest_loop_from_edge(struct Scene *scene,
bool uvedit_vert_is_edge_select_any_other(const struct Scene *scene,
struct BMLoop *l,
const int cd_loop_uv_offset);
BMUVOffsets offsets);
bool uvedit_vert_is_face_select_any_other(const struct Scene *scene,
struct BMLoop *l,
const int cd_loop_uv_offset);
BMUVOffsets offsets);
bool uvedit_vert_is_all_other_faces_selected(const struct Scene *scene,
struct BMLoop *l,
const int cd_loop_uv_offset);
BMUVOffsets offsets);
/* utility tool functions */
@@ -171,7 +171,7 @@ bool uvedit_select_is_any_selected_multi(const struct Scene *scene,
*/
const float *uvedit_first_selected_uv_from_vertex(struct Scene *scene,
struct BMVert *eve,
int cd_loop_uv_offset);
BMUVOffsets offsets);
void UV_OT_select_all(struct wmOperatorType *ot);
void UV_OT_select(struct wmOperatorType *ot);
+25 -27
View File
@@ -65,15 +65,15 @@ static void island_uv_transform(FaceIsland *island,
* To convert post-transform to pre-transform, use `A * x + b == A * (x + c), c = A^-1 * b`
*/
const int cd_loop_uv_offset = island->cd_loop_uv_offset;
const int cd_loop_uv_offset = island->offsets.uv;
const int faces_len = island->faces_len;
for (int i = 0; i < faces_len; i++) {
BMFace *f = island->faces[i];
BMLoop *l;
BMIter iter;
BM_ITER_ELEM (l, &iter, f, BM_LOOPS_OF_FACE) {
MLoopUV *luv = (MLoopUV *)BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
mul_v2_m2_add_v2v2(luv->uv, matrix, luv->uv, pre_translate);
float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset);
mul_v2_m2_add_v2v2(luv, matrix, luv, pre_translate);
}
}
}
@@ -134,9 +134,8 @@ static float (*bm_face_array_calc_unique_uv_coords(
}
BM_elem_flag_disable(l_iter, BM_ELEM_TAG);
const MLoopUV *luv = static_cast<const MLoopUV *>(
BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset));
copy_v2_v2(coords[coords_len++], luv->uv);
const float *luv = BM_ELEM_CD_GET_FLOAT_P(l_iter, cd_loop_uv_offset);
copy_v2_v2(coords[coords_len++], luv);
/* Un tag all connected so we don't add them twice.
* Note that we will tag other loops not part of `faces` but this is harmless,
@@ -150,9 +149,8 @@ static float (*bm_face_array_calc_unique_uv_coords(
do {
if (l_radial->v == l_iter->v) {
if (BM_elem_flag_test(l_radial, BM_ELEM_TAG)) {
const MLoopUV *luv_radial = static_cast<const MLoopUV *>(
BM_ELEM_CD_GET_VOID_P(l_radial, cd_loop_uv_offset));
if (equals_v2v2(luv->uv, luv_radial->uv)) {
const float *luv_radial = BM_ELEM_CD_GET_FLOAT_P(l_radial, cd_loop_uv_offset);
if (equals_v2v2(luv, luv_radial)) {
/* Don't add this UV when met in another face in `faces`. */
BM_elem_flag_disable(l_iter, BM_ELEM_TAG);
}
@@ -172,7 +170,7 @@ static void face_island_uv_rotate_fit_aabb(FaceIsland *island)
BMFace **faces = island->faces;
const int faces_len = island->faces_len;
const float aspect_y = island->aspect_y;
const int cd_loop_uv_offset = island->cd_loop_uv_offset;
const int cd_loop_uv_offset = island->offsets.uv;
/* Calculate unique coordinates since calculating a convex hull can be an expensive operation. */
int coords_len;
@@ -320,7 +318,7 @@ static float uv_nearest_grid_tile_distance(const int udim_grid[2],
* \{ */
struct SharedUVLoopData {
int cd_loop_uv_offset;
BMUVOffsets offsets;
bool use_seams;
};
@@ -334,7 +332,7 @@ static bool bm_loop_uv_shared_edge_check(const BMLoop *l_a, const BMLoop *l_b, v
}
}
return BM_loop_uv_share_edge_check((BMLoop *)l_a, (BMLoop *)l_b, data->cd_loop_uv_offset);
return BM_loop_uv_share_edge_check((BMLoop *)l_a, (BMLoop *)l_b, data->offsets.uv);
}
/**
@@ -347,9 +345,9 @@ int bm_mesh_calc_uv_islands(const Scene *scene,
const bool only_selected_uvs,
const bool use_seams,
const float aspect_y,
const int cd_loop_uv_offset)
const BMUVOffsets uv_offsets)
{
BLI_assert(cd_loop_uv_offset >= 0);
BLI_assert(uv_offsets.uv >= 0);
int island_added = 0;
BM_mesh_elem_table_ensure(bm, BM_FACE);
@@ -367,7 +365,7 @@ int bm_mesh_calc_uv_islands(const Scene *scene,
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
bool value = false;
if (BM_elem_flag_test(f, BM_ELEM_SELECT) &&
uvedit_face_select_test(scene, f, cd_loop_uv_offset)) {
uvedit_face_select_test(scene, f, uv_offsets)) {
value = true;
}
BM_elem_flag_set(f, BM_ELEM_TAG, value);
@@ -380,7 +378,7 @@ int bm_mesh_calc_uv_islands(const Scene *scene,
}
struct SharedUVLoopData user_data = {0};
user_data.cd_loop_uv_offset = cd_loop_uv_offset;
user_data.offsets = uv_offsets;
user_data.use_seams = use_seams;
const int group_len = BM_mesh_calc_face_groups(bm,
@@ -408,7 +406,7 @@ int bm_mesh_calc_uv_islands(const Scene *scene,
MEM_callocN(sizeof(*island), __func__));
island->faces = faces;
island->faces_len = faces_len;
island->cd_loop_uv_offset = cd_loop_uv_offset;
island->offsets = uv_offsets;
island->aspect_y = aspect_y;
BLI_addtail(island_list, island);
island_added += 1;
@@ -626,18 +624,17 @@ static bool island_has_pins(const Scene *scene,
const bool only_selected_faces = params->only_selected_faces;
BMLoop *l;
BMIter iter;
const int cd_loop_uv_offset = island->cd_loop_uv_offset;
const int pin_offset = island->offsets.pin;
for (int i = 0; i < island->faces_len; i++) {
BMFace *efa = island->faces[i];
if (pin_unselected && only_selected_faces && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
return true;
}
BM_ITER_ELEM (l, &iter, efa, BM_LOOPS_OF_FACE) {
MLoopUV *luv = static_cast<MLoopUV *>(BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset));
if (luv->flag & MLOOPUV_PINNED) {
BM_ITER_ELEM (l, &iter, island->faces[i], BM_LOOPS_OF_FACE) {
if (BM_ELEM_CD_GET_BOOL(l, pin_offset)) {
return true;
}
if (pin_unselected && !uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
if (pin_unselected && !uvedit_uv_select_test(scene, l, island->offsets)) {
return true;
}
}
@@ -672,8 +669,9 @@ void ED_uvedit_pack_islands_multi(const Scene *scene,
bm = em->bm;
}
BLI_assert(bm);
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
if (cd_loop_uv_offset == -1) {
const BMUVOffsets offsets = BM_uv_map_get_offsets(bm);
if (offsets.uv == -1) {
continue;
}
@@ -700,7 +698,7 @@ void ED_uvedit_pack_islands_multi(const Scene *scene,
only_selected_uvs,
params->use_seams,
aspect_y,
cd_loop_uv_offset);
offsets);
/* Remove from linked list and append to blender::Vector. */
LISTBASE_FOREACH_MUTABLE (struct FaceIsland *, island, &island_list) {
@@ -728,7 +726,7 @@ void ED_uvedit_pack_islands_multi(const Scene *scene,
/* Only calculate selection bounding box if using closest_udim. */
for (int i = 0; i < island->faces_len; i++) {
BMFace *f = island->faces[i];
BM_face_uv_minmax(f, selection_min_co, selection_max_co, island->cd_loop_uv_offset);
BM_face_uv_minmax(f, selection_min_co, selection_max_co, island->offsets.uv);
}
}
@@ -737,7 +735,7 @@ void ED_uvedit_pack_islands_multi(const Scene *scene,
}
bm_face_array_calc_bounds(
island->faces, island->faces_len, island->cd_loop_uv_offset, &island->bounds_rect);
island->faces, island->faces_len, island->offsets.uv, &island->bounds_rect);
}
/* Center of bounding box containing all selected UVs. */
+136 -143
View File
@@ -88,7 +88,7 @@ static int UNUSED_FUNCTION(ED_operator_uvmap_mesh)(bContext *C)
if (ob && ob->type == OB_MESH) {
Mesh *me = ob->data;
if (CustomData_get_layer(&me->ldata, CD_MLOOPUV) != NULL) {
if (CustomData_get_layer(&me->ldata, CD_PROP_FLOAT2) != NULL) {
return 1;
}
}
@@ -204,9 +204,9 @@ bool ED_uvedit_minmax_multi(
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
MLoopUV *luv;
float *luv;
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
const BMUVOffsets offsets = BM_uv_map_get_offsets(em->bm);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
if (!uvedit_face_visible_test(scene, efa)) {
@@ -214,9 +214,9 @@ bool ED_uvedit_minmax_multi(
}
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
minmax_v2v2_v2(r_min, r_max, luv->uv);
if (uvedit_uv_select_test(scene, l, offsets)) {
luv = BM_ELEM_CD_GET_FLOAT_P(l, offsets.uv);
minmax_v2v2_v2(r_min, r_max, luv);
changed = true;
}
}
@@ -235,14 +235,12 @@ void ED_uvedit_select_all(BMesh *bm)
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
MLoopUV *luv;
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
const BMUVOffsets offsets = BM_uv_map_get_offsets(bm);
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
luv->flag |= (MLOOPUV_VERTSEL | MLOOPUV_EDGESEL);
BM_ELEM_CD_SET_BOOL(l, offsets.select_vert, true);
BM_ELEM_CD_SET_BOOL(l, offsets.select_edge, true);
}
}
}
@@ -262,9 +260,9 @@ static bool ED_uvedit_median_multi(const Scene *scene,
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
MLoopUV *luv;
float *luv;
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
const BMUVOffsets offsets = BM_uv_map_get_offsets(em->bm);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
if (!uvedit_face_visible_test(scene, efa)) {
@@ -272,9 +270,9 @@ static bool ED_uvedit_median_multi(const Scene *scene,
}
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
add_v2_v2(co, luv->uv);
luv = BM_ELEM_CD_GET_FLOAT_P(l, offsets.uv);
if (uvedit_uv_select_test(scene, l, offsets)) {
add_v2_v2(co, luv);
sel++;
}
}
@@ -371,7 +369,7 @@ static bool uvedit_uv_align_weld(Scene *scene,
const float cent[2])
{
bool changed = false;
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
const BMUVOffsets offsets = BM_uv_map_get_offsets(bm);
BMIter iter;
BMFace *efa;
@@ -383,19 +381,19 @@ static bool uvedit_uv_align_weld(Scene *scene,
BMIter liter;
BMLoop *l;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (!uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
if (!uvedit_uv_select_test(scene, l, offsets)) {
continue;
}
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
float *luv = BM_ELEM_CD_GET_VOID_P(l, offsets.uv);
if (ELEM(tool, UV_ALIGN_X, UV_WELD)) {
if (luv->uv[0] != cent[0]) {
luv->uv[0] = cent[0];
if (luv[0] != cent[0]) {
luv[0] = cent[0];
changed = true;
}
}
if (ELEM(tool, UV_ALIGN_Y, UV_WELD)) {
if (luv->uv[1] != cent[1]) {
luv->uv[1] = cent[1];
if (luv[1] != cent[1]) {
luv[1] = cent[1];
changed = true;
}
}
@@ -404,17 +402,17 @@ static bool uvedit_uv_align_weld(Scene *scene,
return changed;
}
/** Bitwise-or together, then choose #MLoopUV with highest value. */
/** Bitwise-or together, then choose loop with highest value. */
typedef enum eUVEndPointPrecedence {
UVEP_INVALID = 0,
UVEP_SELECTED = (1 << 0),
UVEP_PINNED = (1 << 1), /* i.e. Pinned verts are preferred to selected. */
} eUVEndPointPrecedence;
static eUVEndPointPrecedence uvedit_line_update_get_precedence(const MLoopUV *luv)
static eUVEndPointPrecedence uvedit_line_update_get_precedence(const bool pinned)
{
eUVEndPointPrecedence precedence = UVEP_SELECTED;
if (luv->flag & MLOOPUV_PINNED) {
if (pinned) {
precedence |= UVEP_PINNED;
}
return precedence;
@@ -424,16 +422,17 @@ static eUVEndPointPrecedence uvedit_line_update_get_precedence(const MLoopUV *lu
* Helper to find two endpoints (`a` and `b`) which have higher precedence, and are far apart.
* Note that is only a heuristic and won't always find the best two endpoints.
*/
static bool uvedit_line_update_endpoint(const MLoopUV *luv,
static bool uvedit_line_update_endpoint(const float *luv,
const bool pinned,
float uv_a[2],
eUVEndPointPrecedence *prec_a,
float uv_b[2],
eUVEndPointPrecedence *prec_b)
{
eUVEndPointPrecedence flags = uvedit_line_update_get_precedence(luv);
eUVEndPointPrecedence flags = uvedit_line_update_get_precedence(pinned);
float len_sq_a = len_squared_v2v2(uv_a, luv->uv);
float len_sq_b = len_squared_v2v2(uv_b, luv->uv);
float len_sq_a = len_squared_v2v2(uv_a, luv);
float len_sq_b = len_squared_v2v2(uv_b, luv);
/* Caching the value of `len_sq_ab` is unlikely to be faster than recalculating.
* Profile before optimizing. */
@@ -441,13 +440,13 @@ static bool uvedit_line_update_endpoint(const MLoopUV *luv,
if ((*prec_a < flags && 0.0f < len_sq_b) || (*prec_a == flags && len_sq_ab < len_sq_b)) {
*prec_a = flags;
copy_v2_v2(uv_a, luv->uv);
copy_v2_v2(uv_a, luv);
return true;
}
if ((*prec_b < flags && 0.0f < len_sq_a) || (*prec_b == flags && len_sq_ab < len_sq_a)) {
*prec_b = flags;
copy_v2_v2(uv_b, luv->uv);
copy_v2_v2(uv_b, luv);
return true;
}
@@ -460,7 +459,7 @@ static bool uvedit_line_update_endpoint(const MLoopUV *luv,
*/
static bool uvedit_uv_straighten_elements(const UvElement *element,
const int len,
const int cd_loop_uv_offset,
const BMUVOffsets offsets,
const eUVWeldAlign tool)
{
float uv_start[2];
@@ -472,8 +471,9 @@ static bool uvedit_uv_straighten_elements(const UvElement *element,
for (int i = 0; i < 10; i++) { /* Heuristic to prevent infinite loop. */
bool update = false;
for (int j = 0; j < len; j++) {
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(element[j].l, cd_loop_uv_offset);
update |= uvedit_line_update_endpoint(luv, uv_start, &prec_start, uv_end, &prec_end);
float *luv = BM_ELEM_CD_GET_FLOAT_P(element[j].l, offsets.uv);
bool pinned = BM_ELEM_CD_GET_BOOL(element[j].l, offsets.pin);
update |= uvedit_line_update_endpoint(luv, pinned, uv_start, &prec_start, uv_end, &prec_end);
}
if (!update) {
break;
@@ -508,19 +508,19 @@ static bool uvedit_uv_straighten_elements(const UvElement *element,
bool changed = false;
for (int j = 0; j < len; j++) {
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(element[j].l, cd_loop_uv_offset);
float *luv = BM_ELEM_CD_GET_FLOAT_P(element[j].l, offsets.uv);
/* Projection of point (x, y) over line (x1, y1, x2, y2) along X axis:
* new_y = (y2 - y1) / (x2 - x1) * (x - x1) + y1
* Maybe this should be a BLI func? Or is it already existing?
* Could use interp_v2_v2v2, but not sure it's worth it here. */
if (tool_local == UV_STRAIGHTEN_X) {
luv->uv[0] = a * (luv->uv[1] - uv_start[1]) + uv_start[0];
luv[0] = a * (luv[1] - uv_start[1]) + uv_start[0];
}
else if (tool_local == UV_STRAIGHTEN_Y) {
luv->uv[1] = a * (luv->uv[0] - uv_start[0]) + uv_start[1];
luv[1] = a * (luv[0] - uv_start[0]) + uv_start[1];
}
else {
closest_to_line_segment_v2(luv->uv, luv->uv, uv_start, uv_end);
closest_to_line_segment_v2(luv, luv, uv_start, uv_end);
}
changed = true; /* TODO: Did the UV actually move? */
}
@@ -532,8 +532,8 @@ static bool uvedit_uv_straighten_elements(const UvElement *element,
*/
static bool uvedit_uv_straighten(Scene *scene, BMesh *bm, eUVWeldAlign tool)
{
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
if (cd_loop_uv_offset == -1) {
const BMUVOffsets offsets = BM_uv_map_get_offsets(bm);
if (offsets.uv == -1) {
return false;
}
@@ -546,7 +546,7 @@ static bool uvedit_uv_straighten(Scene *scene, BMesh *bm, eUVWeldAlign tool)
for (int i = 0; i < element_map->total_islands; i++) {
changed |= uvedit_uv_straighten_elements(element_map->storage + element_map->island_indices[i],
element_map->island_total_uvs[i],
cd_loop_uv_offset,
offsets,
tool);
}
@@ -578,7 +578,7 @@ static void uv_weld_align(bContext *C, eUVWeldAlign tool)
continue;
}
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
const BMUVOffsets offsets = BM_uv_map_get_offsets(em->bm);
BMIter iter, liter;
BMFace *efa;
@@ -590,9 +590,9 @@ static void uv_weld_align(bContext *C, eUVWeldAlign tool)
}
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
minmax_v2v2_v2(min, max, luv->uv);
if (uvedit_uv_select_test(scene, l, offsets)) {
float *luv = BM_ELEM_CD_GET_FLOAT_P(l, offsets.uv);
minmax_v2v2_v2(min, max, luv);
}
}
}
@@ -701,8 +701,8 @@ static int uv_remove_doubles_to_selected(bContext *C, wmOperator *op)
bool *changed = MEM_callocN(sizeof(bool) * objects_len, "uv_remove_doubles_selected.changed");
/* Maximum index of an objects[i]'s MLoopUVs in MLoopUV_arr.
* It helps find which MLoopUV in *MLoopUV_arr belongs to which object. */
/* Maximum index of an objects[i]'s UVs in UV_arr.
* It helps find which UV in *mloopuv_arr belongs to which object. */
uint *ob_mloopuv_max_idx = MEM_callocN(sizeof(uint) * objects_len,
"uv_remove_doubles_selected.ob_mloopuv_max_idx");
@@ -724,7 +724,7 @@ static int uv_remove_doubles_to_selected(bContext *C, wmOperator *op)
int *duplicates = NULL;
BLI_array_declare(duplicates);
MLoopUV **mloopuv_arr = NULL;
float **mloopuv_arr = NULL;
BLI_array_declare(mloopuv_arr);
int mloopuv_count = 0; /* Also used for *duplicates count. */
@@ -740,7 +740,7 @@ static int uv_remove_doubles_to_selected(bContext *C, wmOperator *op)
continue;
}
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
const BMUVOffsets offsets = BM_uv_map_get_offsets(em->bm);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
if (!uvedit_face_visible_test(scene, efa)) {
@@ -748,9 +748,9 @@ static int uv_remove_doubles_to_selected(bContext *C, wmOperator *op)
}
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
BLI_kdtree_2d_insert(tree, mloopuv_count, luv->uv);
if (uvedit_uv_select_test(scene, l, offsets)) {
float *luv = BM_ELEM_CD_GET_FLOAT_P(l, offsets.uv);
BLI_kdtree_2d_insert(tree, mloopuv_count, luv);
BLI_array_append(duplicates, -1);
BLI_array_append(mloopuv_arr, luv);
mloopuv_count++;
@@ -777,7 +777,7 @@ static int uv_remove_doubles_to_selected(bContext *C, wmOperator *op)
if (duplicates[i] != i) {
/* If not self then accumulate uv for averaging.
* Self uv is already present in accumulator */
add_v2_v2(mloopuv_arr[duplicates[i]]->uv, mloopuv_arr[i]->uv);
add_v2_v2(mloopuv_arr[duplicates[i]], mloopuv_arr[i]);
}
uv_duplicate_count[duplicates[i]]++;
}
@@ -787,14 +787,14 @@ static int uv_remove_doubles_to_selected(bContext *C, wmOperator *op)
continue;
}
mul_v2_fl(mloopuv_arr[i]->uv, 1.0f / (float)uv_duplicate_count[i]);
mul_v2_fl(mloopuv_arr[i], 1.0f / (float)uv_duplicate_count[i]);
}
MEM_freeN(uv_duplicate_count);
/* Update duplicated uvs. */
uint ob_index = 0;
for (int i = 0; i < mloopuv_count; i++) {
/* Make sure we know which object owns the MLoopUV at this index.
/* Make sure we know which object owns the mloopuv at this index.
* Remember that in some cases the object will have no loop uv,
* thus we need the while loop, and not simply an if check. */
while (ob_mloopuv_max_idx[ob_index] < i) {
@@ -805,7 +805,7 @@ static int uv_remove_doubles_to_selected(bContext *C, wmOperator *op)
continue;
}
copy_v2_v2(mloopuv_arr[i]->uv, mloopuv_arr[duplicates[i]]->uv);
copy_v2_v2(mloopuv_arr[i], mloopuv_arr[duplicates[i]]);
changed[ob_index] = true;
}
@@ -853,7 +853,7 @@ static int uv_remove_doubles_to_unselected(bContext *C, wmOperator *op)
KDTree_2d *tree = BLI_kdtree_2d_new(uv_maxlen);
MLoopUV **mloopuv_arr = NULL;
float **mloopuv_arr = NULL;
BLI_array_declare(mloopuv_arr);
int mloopuv_count = 0;
@@ -870,7 +870,7 @@ static int uv_remove_doubles_to_unselected(bContext *C, wmOperator *op)
continue;
}
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
const BMUVOffsets offsets = BM_uv_map_get_offsets(em->bm);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
if (!uvedit_face_visible_test(scene, efa)) {
@@ -878,9 +878,9 @@ static int uv_remove_doubles_to_unselected(bContext *C, wmOperator *op)
}
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (!uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
BLI_kdtree_2d_insert(tree, mloopuv_count, luv->uv);
if (!uvedit_uv_select_test(scene, l, offsets)) {
float *luv = BM_ELEM_CD_GET_FLOAT_P(l, offsets.uv);
BLI_kdtree_2d_insert(tree, mloopuv_count, luv);
BLI_array_append(mloopuv_arr, luv);
mloopuv_count++;
}
@@ -903,7 +903,7 @@ static int uv_remove_doubles_to_unselected(bContext *C, wmOperator *op)
continue;
}
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
const BMUVOffsets offsets = BM_uv_map_get_offsets(em->bm);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
if (!uvedit_face_visible_test(scene, efa)) {
@@ -911,13 +911,13 @@ static int uv_remove_doubles_to_unselected(bContext *C, wmOperator *op)
}
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (uvedit_uv_select_test(scene, l, offsets)) {
float *luv = BM_ELEM_CD_GET_FLOAT_P(l, offsets.uv);
KDTreeNearest_2d nearest;
const int i = BLI_kdtree_2d_find_nearest(tree, luv->uv, &nearest);
const int i = BLI_kdtree_2d_find_nearest(tree, luv, &nearest);
if (i != -1 && nearest.dist < threshold) {
copy_v2_v2(luv->uv, mloopuv_arr[i]->uv);
copy_v2_v2(luv, mloopuv_arr[i]);
changed = true;
}
}
@@ -1105,10 +1105,10 @@ static bool uv_snap_uvs_to_cursor(Scene *scene, Object *obedit, const float curs
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
MLoopUV *luv;
float *luv;
bool changed = false;
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
const BMUVOffsets offsets = BM_uv_map_get_offsets(em->bm);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
if (!uvedit_face_visible_test(scene, efa)) {
@@ -1116,9 +1116,9 @@ static bool uv_snap_uvs_to_cursor(Scene *scene, Object *obedit, const float curs
}
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
copy_v2_v2(luv->uv, cursor);
if (uvedit_uv_select_test(scene, l, offsets)) {
luv = BM_ELEM_CD_GET_FLOAT_P(l, offsets.uv);
copy_v2_v2(luv, cursor);
changed = true;
}
}
@@ -1133,10 +1133,10 @@ static bool uv_snap_uvs_offset(Scene *scene, Object *obedit, const float offset[
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
MLoopUV *luv;
float *luv;
bool changed = false;
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
const BMUVOffsets offsets = BM_uv_map_get_offsets(em->bm);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
if (!uvedit_face_visible_test(scene, efa)) {
@@ -1144,9 +1144,9 @@ static bool uv_snap_uvs_offset(Scene *scene, Object *obedit, const float offset[
}
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
add_v2_v2(luv->uv, offset);
if (uvedit_uv_select_test(scene, l, offsets)) {
luv = BM_ELEM_CD_GET_FLOAT_P(l, offsets.uv);
add_v2_v2(luv, offset);
changed = true;
}
}
@@ -1162,9 +1162,9 @@ static bool uv_snap_uvs_to_adjacent_unselected(Scene *scene, Object *obedit)
BMFace *f;
BMLoop *l, *lsub;
BMIter iter, liter, lsubiter;
MLoopUV *luv;
float *luv;
bool changed = false;
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
const BMUVOffsets offsets = BM_uv_map_get_offsets(em->bm);
/* index every vert that has a selected UV using it, but only once so as to
* get unique indices and to count how much to malloc */
@@ -1172,7 +1172,7 @@ static bool uv_snap_uvs_to_adjacent_unselected(Scene *scene, Object *obedit)
if (uvedit_face_visible_test(scene, f)) {
BM_elem_flag_enable(f, BM_ELEM_TAG);
BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
BM_elem_flag_set(l, BM_ELEM_TAG, uvedit_uv_select_test(scene, l, cd_loop_uv_offset));
BM_elem_flag_set(l, BM_ELEM_TAG, uvedit_uv_select_test(scene, l, offsets));
}
}
else {
@@ -1191,15 +1191,15 @@ static bool uv_snap_uvs_to_adjacent_unselected(Scene *scene, Object *obedit)
if (BM_elem_flag_test(lsub->f, BM_ELEM_TAG) && /* Face: visible. */
!BM_elem_flag_test(lsub, BM_ELEM_TAG)) /* Loop: unselected. */
{
luv = BM_ELEM_CD_GET_VOID_P(lsub, cd_loop_uv_offset);
add_v2_v2(uv, luv->uv);
luv = BM_ELEM_CD_GET_FLOAT_P(lsub, offsets.uv);
add_v2_v2(uv, luv);
uv_tot++;
}
}
if (uv_tot) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
mul_v2_v2fl(luv->uv, uv, 1.0f / (float)uv_tot);
luv = BM_ELEM_CD_GET_FLOAT_P(l, offsets.uv);
mul_v2_v2fl(luv, uv, 1.0f / (float)uv_tot);
changed = true;
}
}
@@ -1216,12 +1216,12 @@ static bool uv_snap_uvs_to_pixels(SpaceImage *sima, Scene *scene, Object *obedit
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
MLoopUV *luv;
float *luv;
int width = 0, height = 0;
float w, h;
bool changed = false;
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
const BMUVOffsets offsets = BM_uv_map_get_offsets(em->bm);
ED_space_image_get_size(sima, &width, &height);
w = (float)width;
@@ -1233,9 +1233,9 @@ static bool uv_snap_uvs_to_pixels(SpaceImage *sima, Scene *scene, Object *obedit
}
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
uv_snap_to_pixel(luv->uv, w, h);
if (uvedit_uv_select_test(scene, l, offsets)) {
luv = BM_ELEM_CD_GET_FLOAT_P(l, offsets.uv);
uv_snap_to_pixel(luv, w, h);
}
}
@@ -1343,7 +1343,6 @@ static int uv_pin_exec(bContext *C, wmOperator *op)
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
MLoopUV *luv;
const ToolSettings *ts = scene->toolsettings;
const bool clear = RNA_boolean_get(op->ptr, "clear");
const bool synced_selection = (ts->uv_flag & UV_SYNC_SELECTION) != 0;
@@ -1357,7 +1356,9 @@ static int uv_pin_exec(bContext *C, wmOperator *op)
BMEditMesh *em = BKE_editmesh_from_object(obedit);
bool changed = false;
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
const char *active_uv_name = CustomData_get_active_layer_name(&em->bm->ldata, CD_PROP_FLOAT2);
BM_uv_map_ensure_pin_attr(em->bm, active_uv_name);
const BMUVOffsets offsets = BM_uv_map_get_offsets(em->bm);
if (synced_selection && (em->bm->totvertsel == 0)) {
continue;
@@ -1369,16 +1370,10 @@ static int uv_pin_exec(bContext *C, wmOperator *op)
}
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
if (uvedit_uv_select_test(scene, l, offsets)) {
changed = true;
if (clear) {
luv->flag &= ~MLOOPUV_PINNED;
}
else {
luv->flag |= MLOOPUV_PINNED;
}
BM_ELEM_CD_SET_BOOL(l, offsets.pin, !clear);
}
}
}
@@ -1417,24 +1412,21 @@ static void UV_OT_pin(wmOperatorType *ot)
/** \name Hide Operator
* \{ */
/* Check if vertex/edge is selected or unselected based on #bool_test arg. Needed for select swap
* support */
#define UV_VERT_SEL_TEST(luv, bool_test) \
((((luv)->flag & MLOOPUV_VERTSEL) == MLOOPUV_VERTSEL) == bool_test)
/* check if we are selected or unselected based on 'bool_test' arg,
* needed for select swap support */
#define UV_VERT_SEL_TEST(l, bool_test) (BM_ELEM_CD_GET_BOOL(l, offsets.select_vert) == bool_test)
#define UV_EDGE_SEL_TEST(luv, bool_test) \
((((luv)->flag & MLOOPUV_EDGESEL) == MLOOPUV_EDGESEL) == bool_test)
#define UV_EDGE_SEL_TEST(l, bool_test) (BM_ELEM_CD_GET_BOOL(l, offsets.select_edge) == bool_test)
/* Is the specified UV face, selected or unselected depending on bool_test. */
static bool bm_face_is_all_uv_sel(BMFace *f, bool select_test, const int cd_loop_uv_offset)
/* is every UV vert selected or unselected depending on bool_test */
static bool bm_face_is_all_uv_sel(BMFace *f, bool select_test, const BMUVOffsets offsets)
{
BMLoop *l_iter;
BMLoop *l_first;
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset);
if (!UV_EDGE_SEL_TEST(luv, select_test)) {
if (!UV_EDGE_SEL_TEST(l_iter, select_test)) {
return false;
}
} while ((l_iter = l_iter->next) != l_first);
@@ -1460,9 +1452,11 @@ static int uv_hide_exec(bContext *C, wmOperator *op)
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
MLoopUV *luv;
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
const char *active_uv_name = CustomData_get_active_layer_name(&em->bm->ldata, CD_PROP_FLOAT2);
BM_uv_map_ensure_vert_select_attr(em->bm, active_uv_name);
BM_uv_map_ensure_edge_select_attr(em->bm, active_uv_name);
const BMUVOffsets offsets = BM_uv_map_get_offsets(em->bm);
if (ts->uv_flag & UV_SYNC_SELECTION) {
if (EDBM_mesh_hide(em, swap)) {
@@ -1484,9 +1478,8 @@ static int uv_hide_exec(bContext *C, wmOperator *op)
}
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (UV_VERT_SEL_TEST(luv, !swap) || UV_EDGE_SEL_TEST(luv, !swap)) {
if (UV_VERT_SEL_TEST(l, !swap) || UV_EDGE_SEL_TEST(l, !swap)) {
hide = 1;
break;
}
@@ -1496,27 +1489,26 @@ static int uv_hide_exec(bContext *C, wmOperator *op)
if (use_face_center) {
if (em->selectmode == SCE_SELECT_FACE) {
/* Deselect BMesh face if UV face is (de)selected depending on #swap. */
if (bm_face_is_all_uv_sel(efa, !swap, cd_loop_uv_offset)) {
if (bm_face_is_all_uv_sel(efa, !swap, offsets)) {
BM_face_select_set(em->bm, efa, false);
}
uvedit_face_select_disable(scene, em->bm, efa, cd_loop_uv_offset);
uvedit_face_select_disable(scene, em->bm, efa, offsets);
}
else {
if (bm_face_is_all_uv_sel(efa, true, cd_loop_uv_offset) == !swap) {
if (bm_face_is_all_uv_sel(efa, true, offsets) == !swap) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
/* For both cases rely on edge sel tests, since all vert sel tests are invalid in
* case of sticky selections. */
if (UV_EDGE_SEL_TEST(luv, !swap) && (em->selectmode == SCE_SELECT_EDGE)) {
if (UV_EDGE_SEL_TEST(l, !swap) && (em->selectmode == SCE_SELECT_EDGE)) {
BM_edge_select_set(em->bm, l->e, false);
}
else if (UV_EDGE_SEL_TEST(luv, !swap) && (em->selectmode == SCE_SELECT_VERTEX)) {
else if (UV_EDGE_SEL_TEST(l, !swap) && (em->selectmode == SCE_SELECT_VERTEX)) {
BM_vert_select_set(em->bm, l->v, false);
}
}
}
if (!swap) {
uvedit_face_select_disable(scene, em->bm, efa, cd_loop_uv_offset);
uvedit_face_select_disable(scene, em->bm, efa, offsets);
}
}
}
@@ -1524,12 +1516,11 @@ static int uv_hide_exec(bContext *C, wmOperator *op)
/* Deselect BMesh face depending on the type of UV selectmode and the type of UV element
* being considered. */
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (UV_EDGE_SEL_TEST(luv, !swap) && (ts->uv_selectmode == UV_SELECT_EDGE)) {
if (UV_EDGE_SEL_TEST(l, !swap) && (ts->uv_selectmode == UV_SELECT_EDGE)) {
BM_face_select_set(em->bm, efa, false);
break;
}
if (UV_VERT_SEL_TEST(luv, !swap) && (ts->uv_selectmode == UV_SELECT_VERTEX)) {
if (UV_VERT_SEL_TEST(l, !swap) && (ts->uv_selectmode == UV_SELECT_VERTEX)) {
BM_face_select_set(em->bm, efa, false);
break;
}
@@ -1538,12 +1529,11 @@ static int uv_hide_exec(bContext *C, wmOperator *op)
break;
}
}
uvedit_face_select_disable(scene, em->bm, efa, cd_loop_uv_offset);
uvedit_face_select_disable(scene, em->bm, efa, offsets);
}
else {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (UV_EDGE_SEL_TEST(luv, !swap) && (ts->uv_selectmode == UV_SELECT_EDGE)) {
if (UV_EDGE_SEL_TEST(l, !swap) && (ts->uv_selectmode == UV_SELECT_EDGE)) {
if (em->selectmode == SCE_SELECT_EDGE) {
BM_edge_select_set(em->bm, l->e, false);
}
@@ -1552,7 +1542,7 @@ static int uv_hide_exec(bContext *C, wmOperator *op)
BM_vert_select_set(em->bm, l->next->v, false);
}
}
else if (UV_VERT_SEL_TEST(luv, !swap) && (ts->uv_selectmode != UV_SELECT_EDGE)) {
else if (UV_VERT_SEL_TEST(l, !swap) && (ts->uv_selectmode != UV_SELECT_EDGE)) {
if (em->selectmode == SCE_SELECT_EDGE) {
BM_edge_select_set(em->bm, l->e, false);
}
@@ -1562,7 +1552,7 @@ static int uv_hide_exec(bContext *C, wmOperator *op)
}
}
if (!swap) {
uvedit_face_select_disable(scene, em->bm, efa, cd_loop_uv_offset);
uvedit_face_select_disable(scene, em->bm, efa, offsets);
}
}
}
@@ -1632,9 +1622,11 @@ static int uv_reveal_exec(bContext *C, wmOperator *op)
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
MLoopUV *luv;
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
const char *active_uv_name = CustomData_get_active_layer_name(&em->bm->ldata, CD_PROP_FLOAT2);
BM_uv_map_ensure_vert_select_attr(em->bm, active_uv_name);
BM_uv_map_ensure_edge_select_attr(em->bm, active_uv_name);
const BMUVOffsets offsets = BM_uv_map_get_offsets(em->bm);
/* NOTE: Selecting faces is delayed so that it doesn't select verts/edges and confuse certain
* UV selection checks.
@@ -1664,8 +1656,8 @@ static int uv_reveal_exec(bContext *C, wmOperator *op)
BM_elem_flag_disable(efa, BM_ELEM_TAG);
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
SET_FLAG_FROM_TEST(luv->flag, select, (MLOOPUV_VERTSEL | MLOOPUV_EDGESEL));
BM_ELEM_CD_SET_BOOL(l, offsets.select_vert, select);
BM_ELEM_CD_SET_BOOL(l, offsets.select_edge, select);
}
/* BM_face_select_set(em->bm, efa, true); */
BM_elem_flag_enable(efa, BM_ELEM_TAG);
@@ -1688,8 +1680,9 @@ static int uv_reveal_exec(bContext *C, wmOperator *op)
if (!totsel) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
SET_FLAG_FROM_TEST(luv->flag, select, (MLOOPUV_VERTSEL | MLOOPUV_EDGESEL));
BM_ELEM_CD_SET_BOOL(l, offsets.select_vert, select);
BM_ELEM_CD_SET_BOOL(l, offsets.select_edge, select);
}
}
/* BM_face_select_set(em->bm, efa, true); */
@@ -1703,8 +1696,8 @@ static int uv_reveal_exec(bContext *C, wmOperator *op)
BM_elem_flag_disable(efa, BM_ELEM_TAG);
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
SET_FLAG_FROM_TEST(luv->flag, select, (MLOOPUV_VERTSEL | MLOOPUV_EDGESEL));
BM_ELEM_CD_SET_BOOL(l, offsets.select_vert, select);
BM_ELEM_CD_SET_BOOL(l, offsets.select_edge, select);
}
/* BM_face_select_set(em->bm, efa, true); */
BM_elem_flag_enable(efa, BM_ELEM_TAG);
@@ -1716,8 +1709,8 @@ static int uv_reveal_exec(bContext *C, wmOperator *op)
BM_elem_flag_disable(efa, BM_ELEM_TAG);
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
SET_FLAG_FROM_TEST(luv->flag, select, (MLOOPUV_VERTSEL | MLOOPUV_EDGESEL));
BM_ELEM_CD_SET_BOOL(l, offsets.select_vert, select);
BM_ELEM_CD_SET_BOOL(l, offsets.select_edge, select);
}
/* BM_face_select_set(em->bm, efa, true); */
BM_elem_flag_enable(efa, BM_ELEM_TAG);
@@ -1853,7 +1846,7 @@ static int uv_seams_from_islands_exec(bContext *C, wmOperator *op)
continue;
}
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
const BMUVOffsets offsets = BM_uv_map_get_offsets(em->bm);
bool changed = false;
BMFace *f;
@@ -1870,14 +1863,14 @@ static int uv_seams_from_islands_exec(bContext *C, wmOperator *op)
if (l_iter == l_iter->radial_next) {
continue;
}
if (!uvedit_edge_select_test(scene, l_iter, cd_loop_uv_offset)) {
if (!uvedit_edge_select_test(scene, l_iter, offsets)) {
continue;
}
bool mark = false;
BMLoop *l_other = l_iter->radial_next;
do {
if (!BM_loop_uv_share_edge_check(l_iter, l_other, cd_loop_uv_offset)) {
if (!BM_loop_uv_share_edge_check(l_iter, l_other, offsets.uv)) {
mark = true;
break;
}
@@ -1959,12 +1952,12 @@ static int uv_mark_seam_exec(bContext *C, wmOperator *op)
continue;
}
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
const BMUVOffsets offsets = BM_uv_map_get_offsets(em->bm);
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
if (uvedit_face_visible_test(scene, efa)) {
BM_ITER_ELEM (loop, &liter, efa, BM_LOOPS_OF_FACE) {
if (uvedit_edge_select_test(scene, loop, cd_loop_uv_offset)) {
if (uvedit_edge_select_test(scene, loop, offsets)) {
BM_elem_flag_set(loop->e, BM_ELEM_SEAM, flag_set);
changed = true;
}
+43 -60
View File
@@ -71,7 +71,7 @@ struct PathSelectParams {
struct UserData_UV {
Scene *scene;
BMEditMesh *em;
int cd_loop_uv_offset;
BMUVOffsets offsets;
};
static void path_select_properties(wmOperatorType *ot)
@@ -121,15 +121,15 @@ static bool verttag_test_cb(BMLoop *l, void *user_data_v)
/* All connected loops are selected or we return false. */
struct UserData_UV *user_data = user_data_v;
const Scene *scene = user_data->scene;
const int cd_loop_uv_offset = user_data->cd_loop_uv_offset;
const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
const int cd_loop_uv_offset = user_data->offsets.uv;
const float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset);
BMIter iter;
BMLoop *l_iter;
BM_ITER_ELEM (l_iter, &iter, l->v, BM_LOOPS_OF_VERT) {
if (verttag_filter_cb(l_iter, user_data)) {
const MLoopUV *luv_iter = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset);
if (equals_v2v2(luv->uv, luv_iter->uv)) {
if (!uvedit_uv_select_test(scene, l_iter, cd_loop_uv_offset)) {
const float *luv_iter = BM_ELEM_CD_GET_FLOAT_P(l_iter, cd_loop_uv_offset);
if (equals_v2v2(luv, luv_iter)) {
if (!uvedit_uv_select_test(scene, l_iter, user_data->offsets)) {
return false;
}
}
@@ -142,15 +142,15 @@ static void verttag_set_cb(BMLoop *l, bool val, void *user_data_v)
struct UserData_UV *user_data = user_data_v;
const Scene *scene = user_data->scene;
BMEditMesh *em = user_data->em;
const int cd_loop_uv_offset = user_data->cd_loop_uv_offset;
const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
const uint cd_loop_uv_offset = user_data->offsets.uv;
const float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset);
BMIter iter;
BMLoop *l_iter;
BM_ITER_ELEM (l_iter, &iter, l->v, BM_LOOPS_OF_VERT) {
if (verttag_filter_cb(l_iter, user_data)) {
MLoopUV *luv_iter = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset);
if (equals_v2v2(luv->uv, luv_iter->uv)) {
uvedit_uv_select_set(scene, em->bm, l_iter, val, false, cd_loop_uv_offset);
const float *luv_iter = BM_ELEM_CD_GET_FLOAT_P(l_iter, cd_loop_uv_offset);
if (equals_v2v2(luv, luv_iter)) {
uvedit_uv_select_set(scene, em->bm, l_iter, val, false, user_data->offsets);
}
}
}
@@ -162,7 +162,7 @@ static int mouse_mesh_uv_shortest_path_vert(Scene *scene,
BMLoop *l_src,
BMLoop *l_dst,
const float aspect_y,
const int cd_loop_uv_offset)
const BMUVOffsets offsets)
{
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMesh *bm = em->bm;
@@ -171,14 +171,14 @@ static int mouse_mesh_uv_shortest_path_vert(Scene *scene,
struct UserData_UV user_data = {
.scene = scene,
.em = em,
.cd_loop_uv_offset = cd_loop_uv_offset,
.offsets = offsets,
};
const struct BMCalcPathUVParams params = {
.use_topology_distance = op_params->use_topology_distance,
.use_step_face = op_params->use_face_step,
.aspect_y = aspect_y,
.cd_loop_uv_offset = cd_loop_uv_offset,
.cd_loop_uv_offset = offsets.uv,
};
LinkNode *path = NULL;
@@ -253,13 +253,12 @@ static bool edgetag_test_cb(BMLoop *l, void *user_data_v)
/* All connected loops (UV) are selected or we return false. */
struct UserData_UV *user_data = user_data_v;
const Scene *scene = user_data->scene;
const int cd_loop_uv_offset = user_data->cd_loop_uv_offset;
BMIter iter;
BMLoop *l_iter;
BM_ITER_ELEM (l_iter, &iter, l->e, BM_LOOPS_OF_EDGE) {
if (edgetag_filter_cb(l_iter, user_data)) {
if (BM_loop_uv_share_edge_check(l, l_iter, cd_loop_uv_offset)) {
if (!uvedit_edge_select_test(scene, l_iter, cd_loop_uv_offset)) {
if (BM_loop_uv_share_edge_check(l, l_iter, user_data->offsets.uv)) {
if (!uvedit_edge_select_test(scene, l_iter, user_data->offsets)) {
return false;
}
}
@@ -272,8 +271,7 @@ static void edgetag_set_cb(BMLoop *l, bool val, void *user_data_v)
struct UserData_UV *user_data = user_data_v;
const Scene *scene = user_data->scene;
BMEditMesh *em = user_data->em;
const int cd_loop_uv_offset = user_data->cd_loop_uv_offset;
uvedit_edge_select_set_with_sticky(scene, em, l, val, false, cd_loop_uv_offset);
uvedit_edge_select_set_with_sticky(scene, em, l, val, false, user_data->offsets);
}
static int mouse_mesh_uv_shortest_path_edge(Scene *scene,
@@ -282,7 +280,7 @@ static int mouse_mesh_uv_shortest_path_edge(Scene *scene,
BMLoop *l_src,
BMLoop *l_dst,
const float aspect_y,
const int cd_loop_uv_offset)
const BMUVOffsets offsets)
{
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMesh *bm = em->bm;
@@ -291,14 +289,14 @@ static int mouse_mesh_uv_shortest_path_edge(Scene *scene,
struct UserData_UV user_data = {
.scene = scene,
.em = em,
.cd_loop_uv_offset = cd_loop_uv_offset,
.offsets = offsets,
};
const struct BMCalcPathUVParams params = {
.use_topology_distance = op_params->use_topology_distance,
.use_step_face = op_params->use_face_step,
.aspect_y = aspect_y,
.cd_loop_uv_offset = cd_loop_uv_offset,
.cd_loop_uv_offset = offsets.uv,
};
LinkNode *path = NULL;
@@ -375,11 +373,10 @@ static bool facetag_test_cb(BMFace *f, void *user_data_v)
/* All connected loops are selected or we return false. */
struct UserData_UV *user_data = user_data_v;
const Scene *scene = user_data->scene;
const int cd_loop_uv_offset = user_data->cd_loop_uv_offset;
BMIter iter;
BMLoop *l_iter;
BM_ITER_ELEM (l_iter, &iter, f, BM_LOOPS_OF_FACE) {
if (!uvedit_edge_select_test(scene, l_iter, cd_loop_uv_offset)) {
if (!uvedit_edge_select_test(scene, l_iter, user_data->offsets)) {
return false;
}
}
@@ -390,8 +387,7 @@ static void facetag_set_cb(BMFace *f, bool val, void *user_data_v)
struct UserData_UV *user_data = user_data_v;
const Scene *scene = user_data->scene;
BMEditMesh *em = user_data->em;
const int cd_loop_uv_offset = user_data->cd_loop_uv_offset;
uvedit_face_select_set_with_sticky(scene, em, f, val, false, cd_loop_uv_offset);
uvedit_face_select_set_with_sticky(scene, em, f, val, false, user_data->offsets);
}
static int mouse_mesh_uv_shortest_path_face(Scene *scene,
@@ -400,7 +396,7 @@ static int mouse_mesh_uv_shortest_path_face(Scene *scene,
BMFace *f_src,
BMFace *f_dst,
const float aspect_y,
const int cd_loop_uv_offset)
const BMUVOffsets offsets)
{
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMesh *bm = em->bm;
@@ -409,14 +405,14 @@ static int mouse_mesh_uv_shortest_path_face(Scene *scene,
struct UserData_UV user_data = {
.scene = scene,
.em = em,
.cd_loop_uv_offset = cd_loop_uv_offset,
.offsets = offsets,
};
const struct BMCalcPathUVParams params = {
.use_topology_distance = op_params->use_topology_distance,
.use_step_face = op_params->use_face_step,
.aspect_y = aspect_y,
.cd_loop_uv_offset = cd_loop_uv_offset,
.cd_loop_uv_offset = offsets.uv,
};
LinkNode *path = NULL;
@@ -492,7 +488,7 @@ static bool uv_shortest_path_pick_ex(Scene *scene,
BMElem *ele_src,
BMElem *ele_dst,
const float aspect_y,
const int cd_loop_uv_offset)
const BMUVOffsets offsets)
{
const ToolSettings *ts = scene->toolsettings;
const char uv_selectmode = ED_uvedit_select_mode_get(scene);
@@ -503,33 +499,18 @@ static bool uv_shortest_path_pick_ex(Scene *scene,
/* pass */
}
else if (ele_src->head.htype == BM_FACE) {
flush = mouse_mesh_uv_shortest_path_face(scene,
obedit,
op_params,
(BMFace *)ele_src,
(BMFace *)ele_dst,
aspect_y,
cd_loop_uv_offset);
flush = mouse_mesh_uv_shortest_path_face(
scene, obedit, op_params, (BMFace *)ele_src, (BMFace *)ele_dst, aspect_y, offsets);
ok = true;
}
else if (ele_src->head.htype == BM_LOOP) {
if (uv_selectmode & UV_SELECT_EDGE) {
flush = mouse_mesh_uv_shortest_path_edge(scene,
obedit,
op_params,
(BMLoop *)ele_src,
(BMLoop *)ele_dst,
aspect_y,
cd_loop_uv_offset);
flush = mouse_mesh_uv_shortest_path_edge(
scene, obedit, op_params, (BMLoop *)ele_src, (BMLoop *)ele_dst, aspect_y, offsets);
}
else {
flush = mouse_mesh_uv_shortest_path_vert(scene,
obedit,
op_params,
(BMLoop *)ele_src,
(BMLoop *)ele_dst,
aspect_y,
cd_loop_uv_offset);
flush = mouse_mesh_uv_shortest_path_vert(
scene, obedit, op_params, (BMLoop *)ele_src, (BMLoop *)ele_dst, aspect_y, offsets);
}
ok = true;
}
@@ -586,7 +567,7 @@ static int uv_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmEve
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMesh *bm = em->bm;
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
const BMUVOffsets offsets = BM_uv_map_get_offsets(bm);
float aspect_y;
{
@@ -628,8 +609,8 @@ static int uv_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmEve
else {
l_src = ED_uvedit_active_edge_loop_get(bm);
if (l_src != NULL) {
if (!uvedit_uv_select_test(scene, l_src, cd_loop_uv_offset) &&
!uvedit_uv_select_test(scene, l_src->next, cd_loop_uv_offset)) {
if (!uvedit_uv_select_test(scene, l_src, offsets) &&
!uvedit_uv_select_test(scene, l_src->next, offsets)) {
l_src = NULL;
}
ele_src = (BMElem *)l_src;
@@ -654,7 +635,7 @@ static int uv_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmEve
else {
l_src = ED_uvedit_active_vert_loop_get(bm);
if (l_src != NULL) {
if (!uvedit_uv_select_test(scene, l_src, cd_loop_uv_offset)) {
if (!uvedit_uv_select_test(scene, l_src, offsets)) {
l_src = NULL;
}
}
@@ -668,7 +649,7 @@ static int uv_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmEve
}
uv_shortest_path_pick_ex(
scene, depsgraph, obedit, &op_params, ele_src, ele_dst, aspect_y, cd_loop_uv_offset);
scene, depsgraph, obedit, &op_params, ele_src, ele_dst, aspect_y, offsets);
/* To support redo. */
int index;
@@ -697,7 +678,7 @@ static int uv_shortest_path_pick_exec(bContext *C, wmOperator *op)
Object *obedit = CTX_data_edit_object(C);
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMesh *bm = em->bm;
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
const BMUVOffsets offsets = BM_uv_map_get_offsets(bm);
float aspect_y;
{
@@ -743,7 +724,7 @@ static int uv_shortest_path_pick_exec(bContext *C, wmOperator *op)
op_params.track_active = true;
if (!uv_shortest_path_pick_ex(
scene, depsgraph, obedit, &op_params, ele_src, ele_dst, aspect_y, cd_loop_uv_offset)) {
scene, depsgraph, obedit, &op_params, ele_src, ele_dst, aspect_y, offsets)) {
return OPERATOR_CANCELLED;
}
@@ -804,7 +785,9 @@ static int uv_shortest_path_select_exec(bContext *C, wmOperator *op)
Object *obedit = objects[ob_index];
BMEditMesh *em = BKE_editmesh_from_object(obedit);
BMesh *bm = em->bm;
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
const BMUVOffsets offsets = BM_uv_map_get_offsets(bm);
BMElem *ele_src = NULL, *ele_dst = NULL;
/* Find 2x elements. */
@@ -833,7 +816,7 @@ static int uv_shortest_path_select_exec(bContext *C, wmOperator *op)
path_select_params_from_op(op, &op_params);
uv_shortest_path_pick_ex(
scene, depsgraph, obedit, &op_params, ele_src, ele_dst, aspect_y, cd_loop_uv_offset);
scene, depsgraph, obedit, &op_params, ele_src, ele_dst, aspect_y, offsets);
found_valid_elements = true;
}
+46 -47
View File
@@ -186,13 +186,13 @@ static BMLoop *bm_vert_step_fan_loop_uv(BMLoop *l, BMEdge **e_step, const int cd
static void bm_loop_uv_select_single_vert_validate(BMLoop *l_init, const int cd_loop_uv_offset)
{
const MLoopUV *luv_init = BM_ELEM_CD_GET_VOID_P(l_init, cd_loop_uv_offset);
const float *luv_init = BM_ELEM_CD_GET_FLOAT_P(l_init, cd_loop_uv_offset);
BMIter liter;
BMLoop *l;
bool is_single_vert = true;
BM_ITER_ELEM (l, &liter, l_init->v, BM_LOOPS_OF_VERT) {
const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (equals_v2v2(luv_init->uv, luv->uv)) {
const float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset);
if (equals_v2v2(luv_init, luv)) {
if (UL(l->prev)->is_select_edge || UL(l)->is_select_edge) {
is_single_vert = false;
break;
@@ -202,8 +202,8 @@ static void bm_loop_uv_select_single_vert_validate(BMLoop *l_init, const int cd_
if (is_single_vert == false) {
BM_ITER_ELEM (l, &liter, l_init->v, BM_LOOPS_OF_VERT) {
if (UL(l)->is_select_vert_single) {
const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (equals_v2v2(luv_init->uv, luv->uv)) {
const float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset);
if (equals_v2v2(luv_init, luv)) {
UL(l)->is_select_vert_single = false;
}
}
@@ -227,12 +227,12 @@ static void bm_loop_calc_uv_angle_from_dir(BMLoop *l,
{
/* Calculate 3 directions, return the shortest angle. */
float dir_test[3][2];
const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
const MLoopUV *luv_prev = BM_ELEM_CD_GET_VOID_P(l->prev, cd_loop_uv_offset);
const MLoopUV *luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset);
const float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset);
const float *luv_prev = BM_ELEM_CD_GET_FLOAT_P(l->prev, cd_loop_uv_offset);
const float *luv_next = BM_ELEM_CD_GET_FLOAT_P(l->next, cd_loop_uv_offset);
sub_v2_v2v2(dir_test[0], luv->uv, luv_prev->uv);
sub_v2_v2v2(dir_test[2], luv->uv, luv_next->uv);
sub_v2_v2v2(dir_test[0], luv, luv_prev);
sub_v2_v2v2(dir_test[2], luv, luv_next);
dir_test[0][1] /= aspect_y;
dir_test[2][1] /= aspect_y;
@@ -302,8 +302,7 @@ static UVRipSingle *uv_rip_single_from_loop(BMLoop *l_init_orig,
const int cd_loop_uv_offset)
{
UVRipSingle *rip = MEM_callocN(sizeof(*rip), __func__);
const float *co_center =
(((const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_init_orig, cd_loop_uv_offset))->uv);
const float *co_center = BM_ELEM_CD_GET_FLOAT_P(l_init_orig, cd_loop_uv_offset);
rip->loops = BLI_gset_ptr_new(__func__);
/* Track the closest loop, start walking from this so in the event we have multiple
@@ -328,8 +327,8 @@ static UVRipSingle *uv_rip_single_from_loop(BMLoop *l_init_orig,
BMLoop *l;
BM_ITER_ELEM (l, &liter, l_init_orig->v, BM_LOOPS_OF_VERT) {
if (BM_elem_flag_test(l->f, BM_ELEM_TAG)) {
const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (equals_v2v2(co_center, luv->uv)) {
const float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset);
if (equals_v2v2(co_center, luv)) {
uv_fan_count_all += 1;
/* Clear at the same time. */
UL(l)->is_select_vert_single = true;
@@ -462,19 +461,19 @@ static float uv_rip_pairs_calc_uv_angle(BMLoop *l_init,
const int cd_loop_uv_offset)
{
BMIter liter;
const MLoopUV *luv_init = BM_ELEM_CD_GET_VOID_P(l_init, cd_loop_uv_offset);
const float *luv_init = BM_ELEM_CD_GET_FLOAT_P(l_init, cd_loop_uv_offset);
float angle_of_side = 0.0f;
BMLoop *l;
BM_ITER_ELEM (l, &liter, l_init->v, BM_LOOPS_OF_VERT) {
if (UL(l)->in_rip_pairs) {
if (UL(l)->side == side) {
const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (equals_v2v2(luv_init->uv, luv->uv)) {
const MLoopUV *luv_prev = BM_ELEM_CD_GET_VOID_P(l->prev, cd_loop_uv_offset);
const MLoopUV *luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset);
const float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset);
if (equals_v2v2(luv_init, luv)) {
const float *luv_prev = BM_ELEM_CD_GET_FLOAT_P(l->prev, cd_loop_uv_offset);
const float *luv_next = BM_ELEM_CD_GET_FLOAT_P(l->next, cd_loop_uv_offset);
float dir_prev[2], dir_next[2];
sub_v2_v2v2(dir_prev, luv_prev->uv, luv->uv);
sub_v2_v2v2(dir_next, luv_next->uv, luv->uv);
sub_v2_v2v2(dir_prev, luv_prev, luv);
sub_v2_v2v2(dir_next, luv_next, luv);
dir_prev[1] /= aspect_y;
dir_next[1] /= aspect_y;
const float luv_angle = angle_v2v2(dir_prev, dir_next);
@@ -490,15 +489,15 @@ static float uv_rip_pairs_calc_uv_angle(BMLoop *l_init,
static int uv_rip_pairs_loop_count_on_side(BMLoop *l_init, uint side, const int cd_loop_uv_offset)
{
const MLoopUV *luv_init = BM_ELEM_CD_GET_VOID_P(l_init, cd_loop_uv_offset);
const float *luv_init = BM_ELEM_CD_GET_FLOAT_P(l_init, cd_loop_uv_offset);
int count = 0;
BMIter liter;
BMLoop *l;
BM_ITER_ELEM (l, &liter, l_init->v, BM_LOOPS_OF_VERT) {
if (UL(l)->in_rip_pairs) {
if (UL(l)->side == side) {
const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (equals_v2v2(luv_init->uv, luv->uv)) {
const float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset);
if (equals_v2v2(luv_init, luv)) {
count += 1;
}
}
@@ -694,18 +693,18 @@ static bool uv_rip_pairs_calc_center_and_direction(UVRipPairs *rip,
GSET_ITER (gs_iter, rip->loops) {
BMLoop *l = BLI_gsetIterator_getKey(&gs_iter);
int side = UL(l)->side;
const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
add_v2_v2(r_center, luv->uv);
const float *luv = BM_ELEM_CD_GET_FLOAT_P(l, cd_loop_uv_offset);
add_v2_v2(r_center, luv);
float dir[2];
if (!UL(l)->is_select_edge) {
const MLoopUV *luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset);
sub_v2_v2v2(dir, luv_next->uv, luv->uv);
const float *luv_next = BM_ELEM_CD_GET_FLOAT_P(l->next, cd_loop_uv_offset);
sub_v2_v2v2(dir, luv_next, luv);
add_v2_v2(r_dir_side[side], dir);
}
if (!UL(l->prev)->is_select_edge) {
const MLoopUV *luv_prev = BM_ELEM_CD_GET_VOID_P(l->prev, cd_loop_uv_offset);
sub_v2_v2v2(dir, luv_prev->uv, luv->uv);
const float *luv_prev = BM_ELEM_CD_GET_FLOAT_P(l->prev, cd_loop_uv_offset);
sub_v2_v2v2(dir, luv_prev, luv);
add_v2_v2(r_dir_side[side], dir);
}
side_total[side] += 1;
@@ -735,7 +734,10 @@ static bool uv_rip_object(Scene *scene, Object *obedit, const float co[2], const
Mesh *me = (Mesh *)obedit->data;
BMEditMesh *em = me->edit_mesh;
BMesh *bm = em->bm;
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
const char *active_uv_name = CustomData_get_active_layer_name(&bm->ldata, CD_PROP_FLOAT2);
BM_uv_map_ensure_vert_select_attr(bm, active_uv_name);
BM_uv_map_ensure_edge_select_attr(bm, active_uv_name);
const BMUVOffsets offsets = BM_uv_map_get_offsets(bm);
BMFace *efa;
BMIter iter, liter;
@@ -759,13 +761,11 @@ static bool uv_rip_object(Scene *scene, Object *obedit, const float co[2], const
if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
bool is_all = true;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (luv->flag & MLOOPUV_VERTSEL) {
const MLoopUV *luv_prev = BM_ELEM_CD_GET_VOID_P(l->prev, cd_loop_uv_offset);
if (luv->flag & MLOOPUV_EDGESEL) {
if (BM_ELEM_CD_GET_BOOL(l, offsets.select_vert)) {
if (BM_ELEM_CD_GET_BOOL(l, offsets.select_edge)) {
UL(l)->is_select_edge = true;
}
else if ((luv_prev->flag & MLOOPUV_EDGESEL) == 0) {
else if (!BM_ELEM_CD_GET_BOOL(l->prev, offsets.select_edge)) {
/* #bm_loop_uv_select_single_vert_validate validates below. */
UL(l)->is_select_vert_single = true;
is_all = false;
@@ -793,7 +793,7 @@ static bool uv_rip_object(Scene *scene, Object *obedit, const float co[2], const
if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (UL(l)->is_select_vert_single) {
bm_loop_uv_select_single_vert_validate(l, cd_loop_uv_offset);
bm_loop_uv_select_single_vert_validate(l, offsets.uv);
}
}
}
@@ -809,13 +809,12 @@ static bool uv_rip_object(Scene *scene, Object *obedit, const float co[2], const
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (!UL(l)->is_select_all) {
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
if (luv->flag & MLOOPUV_VERTSEL) {
luv->flag &= ~MLOOPUV_VERTSEL;
if (BM_ELEM_CD_GET_BOOL(l, offsets.select_vert)) {
BM_ELEM_CD_SET_BOOL(l, offsets.select_vert, false);
changed = true;
}
if (luv->flag & MLOOPUV_EDGESEL) {
luv->flag &= ~MLOOPUV_EDGESEL;
if (BM_ELEM_CD_GET_BOOL(l, offsets.select_edge)) {
BM_ELEM_CD_SET_BOOL(l, offsets.select_edge, false);
changed = true;
}
}
@@ -830,12 +829,12 @@ static bool uv_rip_object(Scene *scene, Object *obedit, const float co[2], const
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (UL(l)->is_select_edge) {
if (!UL(l)->in_rip_pairs) {
UVRipPairs *rip = uv_rip_pairs_from_loop(l, aspect_y, cd_loop_uv_offset);
UVRipPairs *rip = uv_rip_pairs_from_loop(l, aspect_y, offsets.uv);
float center[2];
float dir_cursor[2];
float dir_side[2][2];
int side_from_cursor = -1;
if (uv_rip_pairs_calc_center_and_direction(rip, cd_loop_uv_offset, center, dir_side)) {
if (uv_rip_pairs_calc_center_and_direction(rip, offsets.uv, center, dir_side)) {
for (int i = 0; i < 2; i++) {
sub_v2_v2v2(dir_cursor, center, co);
normalize_v2(dir_cursor);
@@ -848,7 +847,7 @@ static bool uv_rip_object(Scene *scene, Object *obedit, const float co[2], const
BMLoop *l_iter = BLI_gsetIterator_getKey(&gs_iter);
ULData *ul = UL(l_iter);
if (ul->side == side_from_cursor) {
uvedit_uv_select_disable(scene, em->bm, l_iter, cd_loop_uv_offset);
uvedit_uv_select_disable(scene, bm, l_iter, offsets);
changed = true;
}
/* Ensure we don't operate on these again. */
@@ -858,7 +857,7 @@ static bool uv_rip_object(Scene *scene, Object *obedit, const float co[2], const
}
}
else if (UL(l)->is_select_vert_single) {
UVRipSingle *rip = uv_rip_single_from_loop(l, co, aspect_y, cd_loop_uv_offset);
UVRipSingle *rip = uv_rip_single_from_loop(l, co, aspect_y, offsets.uv);
/* We only ever use one side. */
const int side_from_cursor = 0;
GSetIterator gs_iter;
@@ -866,7 +865,7 @@ static bool uv_rip_object(Scene *scene, Object *obedit, const float co[2], const
BMLoop *l_iter = BLI_gsetIterator_getKey(&gs_iter);
ULData *ul = UL(l_iter);
if (ul->side == side_from_cursor) {
uvedit_uv_select_disable(scene, em->bm, l_iter, cd_loop_uv_offset);
uvedit_uv_select_disable(scene, bm, l_iter, offsets);
changed = true;
}
/* Ensure we don't operate on these again. */
File diff suppressed because it is too large Load Diff
@@ -322,16 +322,14 @@ static bool stitch_check_uvs_stitchable(UvElement *element,
limit = ssc->limit_dist;
if (ssc->use_limit) {
MLoopUV *luv, *luv_iter;
BMLoop *l;
l = element->l;
luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
float *luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2);
l = element_iter->l;
luv_iter = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
float *luv_iter = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2);
if (fabsf(luv->uv[0] - luv_iter->uv[0]) < limit &&
fabsf(luv->uv[1] - luv_iter->uv[1]) < limit) {
if (fabsf(luv[0] - luv_iter[0]) < limit && fabsf(luv[1] - luv_iter[1]) < limit) {
return 1;
}
return 0;
@@ -355,23 +353,19 @@ static bool stitch_check_edges_stitchable(UvEdge *edge,
if (ssc->use_limit) {
BMLoop *l;
MLoopUV *luv_orig1, *luv_iter1;
MLoopUV *luv_orig2, *luv_iter2;
l = state->uvs[edge->uv1]->l;
luv_orig1 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
float *luv_orig1 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2);
l = state->uvs[edge_iter->uv1]->l;
luv_iter1 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
float *luv_iter1 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2);
l = state->uvs[edge->uv2]->l;
luv_orig2 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
float *luv_orig2 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2);
l = state->uvs[edge_iter->uv2]->l;
luv_iter2 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
float *luv_iter2 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2);
if (fabsf(luv_orig1->uv[0] - luv_iter1->uv[0]) < limit &&
fabsf(luv_orig1->uv[1] - luv_iter1->uv[1]) < limit &&
fabsf(luv_orig2->uv[0] - luv_iter2->uv[0]) < limit &&
fabsf(luv_orig2->uv[1] - luv_iter2->uv[1]) < limit) {
if (fabsf(luv_orig1[0] - luv_iter1[0]) < limit && fabsf(luv_orig1[1] - luv_iter1[1]) < limit &&
fabsf(luv_orig2[0] - luv_iter2[0]) < limit && fabsf(luv_orig2[1] - luv_iter2[1]) < limit) {
return 1;
}
return 0;
@@ -462,18 +456,16 @@ static void stitch_calculate_island_snapping(StitchState *state,
for (j = 0; j < numOfIslandUVs; j++, element++) {
/* stitchable uvs have already been processed, don't process */
if (!(element->flag & STITCH_PROCESSED)) {
MLoopUV *luv;
BMLoop *l;
l = element->l;
luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
float *luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2);
if (final) {
stitch_uv_rotate(
rotation_mat, island_stitch_data[i].medianPoint, luv->uv, state->aspect);
stitch_uv_rotate(rotation_mat, island_stitch_data[i].medianPoint, luv, state->aspect);
add_v2_v2(luv->uv, island_stitch_data[i].translation);
add_v2_v2(luv, island_stitch_data[i].translation);
}
else {
@@ -511,13 +503,12 @@ static void stitch_island_calculate_edge_rotation(UvEdge *edge,
float edgecos, edgesin;
int index1, index2;
float rotation;
MLoopUV *luv1, *luv2;
element1 = state->uvs[edge->uv1];
element2 = state->uvs[edge->uv2];
luv1 = CustomData_bmesh_get(&bm->ldata, element1->l->head.data, CD_MLOOPUV);
luv2 = CustomData_bmesh_get(&bm->ldata, element2->l->head.data, CD_MLOOPUV);
float *luv1 = CustomData_bmesh_get(&bm->ldata, element1->l->head.data, CD_PROP_FLOAT2);
float *luv2 = CustomData_bmesh_get(&bm->ldata, element2->l->head.data, CD_PROP_FLOAT2);
if (ssc->mode == STITCH_VERT) {
index1 = uvfinal_map[element1 - state->element_map->storage];
@@ -530,8 +521,8 @@ static void stitch_island_calculate_edge_rotation(UvEdge *edge,
/* the idea here is to take the directions of the edges and find the rotation between
* final and initial direction. This, using inner and outer vector products,
* gives the angle. Directions are differences so... */
uv1[0] = luv2->uv[0] - luv1->uv[0];
uv1[1] = luv2->uv[1] - luv1->uv[1];
uv1[0] = luv2[0] - luv1[0];
uv1[1] = luv2[1] - luv1[1];
uv1[1] /= state->aspect;
@@ -901,24 +892,23 @@ static void stitch_propagate_uv_final_position(Scene *scene,
BMesh *bm = state->em->bm;
StitchPreviewer *preview = state->stitch_preview;
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
const BMUVOffsets offsets = BM_uv_map_get_offsets(bm);
if (element->flag & STITCH_STITCHABLE) {
UvElement *element_iter = element;
/* propagate to coincident uvs */
do {
BMLoop *l;
MLoopUV *luv;
l = element_iter->l;
luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
float *luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2);
element_iter->flag |= STITCH_PROCESSED;
/* either flush to preview or to the MTFace, if final */
if (final) {
copy_v2_v2(luv->uv, final_position[index].uv);
copy_v2_v2(luv, final_position[index].uv);
uvedit_uv_select_enable(scene, state->em->bm, l, false, cd_loop_uv_offset);
uvedit_uv_select_enable(scene, state->em->bm, l, false, offsets);
}
else {
int face_preview_pos =
@@ -1053,7 +1043,7 @@ static int stitch_process_data(StitchStateContainer *ssc,
*********************************************************************/
if (!final) {
BMLoop *l;
MLoopUV *luv;
float *luv;
int stitchBufferIndex = 0, unstitchBufferIndex = 0;
int preview_size = (ssc->mode == STITCH_VERT) ? 2 : 4;
/* initialize the preview buffers */
@@ -1074,17 +1064,17 @@ static int stitch_process_data(StitchStateContainer *ssc,
UvElement *element = (UvElement *)state->uvs[i];
if (element->flag & STITCH_STITCHABLE) {
l = element->l;
luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2);
copy_v2_v2(&preview->preview_stitchable[stitchBufferIndex * 2], luv->uv);
copy_v2_v2(&preview->preview_stitchable[stitchBufferIndex * 2], luv);
stitchBufferIndex++;
}
else if (element->flag & STITCH_SELECTED) {
l = element->l;
luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2);
copy_v2_v2(&preview->preview_unstitchable[unstitchBufferIndex * 2], luv->uv);
copy_v2_v2(&preview->preview_unstitchable[unstitchBufferIndex * 2], luv);
unstitchBufferIndex++;
}
}
@@ -1097,24 +1087,24 @@ static int stitch_process_data(StitchStateContainer *ssc,
if (edge->flag & STITCH_STITCHABLE) {
l = element1->l;
luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
copy_v2_v2(&preview->preview_stitchable[stitchBufferIndex * 4], luv->uv);
luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2);
copy_v2_v2(&preview->preview_stitchable[stitchBufferIndex * 4], luv);
l = element2->l;
luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
copy_v2_v2(&preview->preview_stitchable[stitchBufferIndex * 4 + 2], luv->uv);
luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2);
copy_v2_v2(&preview->preview_stitchable[stitchBufferIndex * 4 + 2], luv);
stitchBufferIndex++;
BLI_assert(stitchBufferIndex <= preview->num_stitchable);
}
else if (edge->flag & STITCH_SELECTED) {
l = element1->l;
luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
copy_v2_v2(&preview->preview_unstitchable[unstitchBufferIndex * 4], luv->uv);
luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2);
copy_v2_v2(&preview->preview_unstitchable[unstitchBufferIndex * 4], luv);
l = element2->l;
luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
copy_v2_v2(&preview->preview_unstitchable[unstitchBufferIndex * 4 + 2], luv->uv);
luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2);
copy_v2_v2(&preview->preview_unstitchable[unstitchBufferIndex * 4 + 2], luv);
unstitchBufferIndex++;
BLI_assert(unstitchBufferIndex <= preview->num_unstitchable);
@@ -1152,7 +1142,7 @@ static int stitch_process_data(StitchStateContainer *ssc,
if (!final) {
BMIter liter;
BMLoop *l;
MLoopUV *luv;
float *luv;
uint buffer_index = 0;
/* initialize the preview buffers */
@@ -1171,7 +1161,7 @@ static int stitch_process_data(StitchStateContainer *ssc,
return 0;
}
/* copy data from MLoopUVs to the preview display buffers */
/* copy data from UVs to the preview display buffers */
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
/* just to test if face was added for processing.
* uvs of unselected vertices will return NULL */
@@ -1184,27 +1174,27 @@ static int stitch_process_data(StitchStateContainer *ssc,
if (face_preview_pos != STITCH_NO_PREVIEW) {
preview->uvs_per_polygon[preview_position[index].polycount_position] = efa->len;
BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
copy_v2_v2(preview->preview_polys + face_preview_pos + i * 2, luv->uv);
luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2);
copy_v2_v2(preview->preview_polys + face_preview_pos + i * 2, luv);
}
}
/* if this is the static_island on the active object */
if (element->island == ssc->static_island) {
BMLoop *fl = BM_FACE_FIRST_LOOP(efa);
MLoopUV *fuv = CustomData_bmesh_get(&bm->ldata, fl->head.data, CD_MLOOPUV);
float *fuv = CustomData_bmesh_get(&bm->ldata, fl->head.data, CD_PROP_FLOAT2);
BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
if (i < numoftris) {
/* using next since the first uv is already accounted for */
BMLoop *lnext = l->next;
MLoopUV *luvnext = CustomData_bmesh_get(
&bm->ldata, lnext->next->head.data, CD_MLOOPUV);
luv = CustomData_bmesh_get(&bm->ldata, lnext->head.data, CD_MLOOPUV);
float *luvnext = CustomData_bmesh_get(
&bm->ldata, lnext->next->head.data, CD_PROP_FLOAT2);
luv = CustomData_bmesh_get(&bm->ldata, lnext->head.data, CD_PROP_FLOAT2);
memcpy(preview->static_tris + buffer_index, fuv->uv, sizeof(float[2]));
memcpy(preview->static_tris + buffer_index + 2, luv->uv, sizeof(float[2]));
memcpy(preview->static_tris + buffer_index + 4, luvnext->uv, sizeof(float[2]));
memcpy(preview->static_tris + buffer_index, fuv, sizeof(float[2]));
memcpy(preview->static_tris + buffer_index + 2, luv, sizeof(float[2]));
memcpy(preview->static_tris + buffer_index + 4, luvnext, sizeof(float[2]));
buffer_index += 6;
}
else {
@@ -1238,14 +1228,14 @@ static int stitch_process_data(StitchStateContainer *ssc,
if (element->flag & STITCH_STITCHABLE) {
BMLoop *l;
MLoopUV *luv;
float *luv;
l = element->l;
luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2);
uvfinal_map[element - state->element_map->storage] = i;
copy_v2_v2(final_position[i].uv, luv->uv);
copy_v2_v2(final_position[i].uv, luv);
final_position[i].count = 1;
if (ssc->snap_islands && element->island == ssc->static_island && !stitch_midpoints) {
@@ -1257,16 +1247,16 @@ static int stitch_process_data(StitchStateContainer *ssc,
if (element_iter->separate) {
if (stitch_check_uvs_state_stitchable(element, element_iter, ssc, state)) {
l = element_iter->l;
luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2);
if (stitch_midpoints) {
add_v2_v2(final_position[i].uv, luv->uv);
add_v2_v2(final_position[i].uv, luv);
final_position[i].count++;
}
else if (element_iter->island == ssc->static_island) {
/* if multiple uvs on the static island exist,
* last checked remains. to disambiguate we need to limit or use
* edge stitch */
copy_v2_v2(final_position[i].uv, luv->uv);
copy_v2_v2(final_position[i].uv, luv);
}
}
}
@@ -1281,17 +1271,17 @@ static int stitch_process_data(StitchStateContainer *ssc,
UvEdge *edge = state->selection_stack[i];
if (edge->flag & STITCH_STITCHABLE) {
MLoopUV *luv2, *luv1;
float *luv2, *luv1;
BMLoop *l;
UvEdge *edge_iter;
l = state->uvs[edge->uv1]->l;
luv1 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
luv1 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2);
l = state->uvs[edge->uv2]->l;
luv2 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
luv2 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2);
copy_v2_v2(final_position[edge->uv1].uv, luv1->uv);
copy_v2_v2(final_position[edge->uv2].uv, luv2->uv);
copy_v2_v2(final_position[edge->uv1].uv, luv1);
copy_v2_v2(final_position[edge->uv2].uv, luv2);
final_position[edge->uv1].count = 1;
final_position[edge->uv2].count = 1;
@@ -1306,19 +1296,19 @@ static int stitch_process_data(StitchStateContainer *ssc,
for (edge_iter = edge->first; edge_iter; edge_iter = edge_iter->next) {
if (stitch_check_edges_state_stitchable(edge, edge_iter, ssc, state)) {
l = state->uvs[edge_iter->uv1]->l;
luv1 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
luv1 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2);
l = state->uvs[edge_iter->uv2]->l;
luv2 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
luv2 = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2);
if (stitch_midpoints) {
add_v2_v2(final_position[edge->uv1].uv, luv1->uv);
add_v2_v2(final_position[edge->uv1].uv, luv1);
final_position[edge->uv1].count++;
add_v2_v2(final_position[edge->uv2].uv, luv2->uv);
add_v2_v2(final_position[edge->uv2].uv, luv2);
final_position[edge->uv2].count++;
}
else if (edge_iter->element->island == ssc->static_island) {
copy_v2_v2(final_position[edge->uv1].uv, luv1->uv);
copy_v2_v2(final_position[edge->uv2].uv, luv2->uv);
copy_v2_v2(final_position[edge->uv1].uv, luv1);
copy_v2_v2(final_position[edge->uv2].uv, luv2);
}
}
}
@@ -1343,20 +1333,18 @@ static int stitch_process_data(StitchStateContainer *ssc,
if (element->flag & STITCH_STITCHABLE) {
BMLoop *l;
MLoopUV *luv;
float *luv;
l = element->l;
luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2);
/* accumulate each islands' translation from stitchable elements.
* It is important to do here because in final pass MTFaces
* get modified and result is zero. */
island_stitch_data[element->island].translation[0] += final_position[i].uv[0] -
luv->uv[0];
island_stitch_data[element->island].translation[1] += final_position[i].uv[1] -
luv->uv[1];
island_stitch_data[element->island].medianPoint[0] += luv->uv[0];
island_stitch_data[element->island].medianPoint[1] += luv->uv[1];
island_stitch_data[element->island].translation[0] += final_position[i].uv[0] - luv[0];
island_stitch_data[element->island].translation[1] += final_position[i].uv[1] - luv[1];
island_stitch_data[element->island].medianPoint[0] += luv[0];
island_stitch_data[element->island].medianPoint[1] += luv[1];
island_stitch_data[element->island].numOfElements++;
}
}
@@ -1398,20 +1386,18 @@ static int stitch_process_data(StitchStateContainer *ssc,
if (element->flag & STITCH_STITCHABLE) {
BMLoop *l;
MLoopUV *luv;
float *luv;
l = element->l;
luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_MLOOPUV);
luv = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PROP_FLOAT2);
/* accumulate each islands' translation from stitchable elements.
* it is important to do here because in final pass MTFaces
* get modified and result is zero. */
island_stitch_data[element->island].translation[0] += final_position[i].uv[0] -
luv->uv[0];
island_stitch_data[element->island].translation[1] += final_position[i].uv[1] -
luv->uv[1];
island_stitch_data[element->island].medianPoint[0] += luv->uv[0];
island_stitch_data[element->island].medianPoint[1] += luv->uv[1];
island_stitch_data[element->island].translation[0] += final_position[i].uv[0] - luv[0];
island_stitch_data[element->island].translation[1] += final_position[i].uv[1] - luv[1];
island_stitch_data[element->island].medianPoint[0] += luv[0];
island_stitch_data[element->island].medianPoint[1] += luv[1];
island_stitch_data[element->island].numOfElements++;
}
}
@@ -1645,13 +1631,12 @@ static void stitch_switch_selection_mode_all(StitchStateContainer *ssc)
static void stitch_calculate_edge_normal(BMEditMesh *em, UvEdge *edge, float *normal, float aspect)
{
BMLoop *l1 = edge->element->l;
MLoopUV *luv1, *luv2;
float tangent[2];
luv1 = CustomData_bmesh_get(&em->bm->ldata, l1->head.data, CD_MLOOPUV);
luv2 = CustomData_bmesh_get(&em->bm->ldata, l1->next->head.data, CD_MLOOPUV);
float *luv1 = CustomData_bmesh_get(&em->bm->ldata, l1->head.data, CD_PROP_FLOAT2);
float *luv2 = CustomData_bmesh_get(&em->bm->ldata, l1->next->head.data, CD_PROP_FLOAT2);
sub_v2_v2v2(tangent, luv2->uv, luv1->uv);
sub_v2_v2v2(tangent, luv2, luv1);
tangent[1] /= aspect;
@@ -1845,7 +1830,7 @@ static StitchState *stitch_init(bContext *C,
float aspx, aspy;
BMEditMesh *em = BKE_editmesh_from_object(obedit);
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
const BMUVOffsets offsets = BM_uv_map_get_offsets(em->bm);
state = MEM_callocN(sizeof(StitchState), "stitch state obj");
@@ -2076,7 +2061,7 @@ static StitchState *stitch_init(bContext *C,
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
if (uvedit_uv_select_test(scene, l, offsets)) {
UvElement *element = BM_uv_element_get(state->element_map, efa, l);
if (element) {
stitch_select_uv(element, state, 1);
@@ -2097,7 +2082,7 @@ static StitchState *stitch_init(bContext *C,
}
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (uvedit_edge_select_test(scene, l, cd_loop_uv_offset)) {
if (uvedit_edge_select_test(scene, l, offsets)) {
UvEdge *edge = uv_edge_get(l, state);
if (edge) {
stitch_select_edge(edge, state, true);

Some files were not shown because too many files have changed in this diff Show More