Cleanup: Reduce unnecessary mesh position copying

Continuation of #103789 to remove/reduce the copying of mesh position
data.

Pull Request: https://projects.blender.org/blender/blender/pulls/111313
This commit is contained in:
Jesse Yurkovich 2023-08-22 03:51:53 +02:00 committed by Jesse Yurkovich
parent d45f47a809
commit f30ac938de
3 changed files with 45 additions and 56 deletions

View File

@ -27,6 +27,7 @@
#include "BLI_math_geom.h" #include "BLI_math_geom.h"
#include "BLI_math_matrix.h" #include "BLI_math_matrix.h"
#include "BLI_math_vector_types.hh" #include "BLI_math_vector_types.hh"
#include "BLI_span.hh"
#include "BLI_task.h" #include "BLI_task.h"
#include "BLI_task.hh" #include "BLI_task.hh"
#include "BLI_utildefines.h" #include "BLI_utildefines.h"
@ -71,6 +72,7 @@
using blender::float3; using blender::float3;
using blender::IndexRange; using blender::IndexRange;
using blender::MutableSpan;
using blender::Span; using blender::Span;
using blender::VArray; using blender::VArray;
using blender::bke::GeometryOwnershipType; using blender::bke::GeometryOwnershipType;
@ -400,47 +402,51 @@ static Mesh *create_orco_mesh(Object *ob, Mesh *me, BMEditMesh *em, int layer)
return mesh; return mesh;
} }
static MutableSpan<float3> orco_coord_layer_ensure(Mesh *mesh, const eCustomDataType layer)
{
void *data = CustomData_get_layer_for_write(&mesh->vert_data, layer, mesh->totvert);
if (!data) {
data = CustomData_add_layer(&mesh->vert_data, layer, CD_CONSTRUCT, mesh->totvert);
}
return MutableSpan(reinterpret_cast<float3 *>(data), mesh->totvert);
}
static void add_orco_mesh( static void add_orco_mesh(
Object *ob, BMEditMesh *em, Mesh *mesh, Mesh *mesh_orco, const eCustomDataType layer) Object *ob, BMEditMesh *em, Mesh *mesh, Mesh *mesh_orco, const eCustomDataType layer)
{ {
float(*orco)[3], (*layerorco)[3]; const int totvert = mesh->totvert;
int totvert, free;
totvert = mesh->totvert;
MutableSpan<float3> layer_orco;
if (mesh_orco) { if (mesh_orco) {
free = 1; layer_orco = orco_coord_layer_ensure(mesh, layer);
if (mesh_orco->totvert == totvert) { if (mesh_orco->totvert == totvert) {
orco = BKE_mesh_vert_coords_alloc(mesh_orco, nullptr); layer_orco.copy_from(mesh_orco->vert_positions());
} }
else { else {
orco = BKE_mesh_vert_coords_alloc(mesh, nullptr); layer_orco.copy_from(mesh->vert_positions());
} }
} }
else { else {
/* TODO(sybren): totvert should potentially change here, as ob->data /* TODO(sybren): totvert should potentially change here, as ob->data
* or em may have a different number of vertices than dm. */ * or em may have a different number of vertices than dm. */
orco = get_orco_coords(ob, em, layer, &free); int free = 0;
} float(*orco)[3] = get_orco_coords(ob, em, layer, &free);
if (orco) {
if (orco) { layer_orco = orco_coord_layer_ensure(mesh, layer);
if (layer == CD_ORCO) { layer_orco.copy_from(Span<float3>(reinterpret_cast<float3 *>(orco), totvert));
BKE_mesh_orco_verts_transform((Mesh *)ob->data, orco, totvert, 0);
} }
layerorco = (float(*)[3])CustomData_get_layer_for_write(
&mesh->vert_data, layer, mesh->totvert);
if (!layerorco) {
layerorco = (float(*)[3])CustomData_add_layer(
&mesh->vert_data, eCustomDataType(layer), CD_SET_DEFAULT, mesh->totvert);
}
memcpy(layerorco, orco, sizeof(float[3]) * totvert);
if (free) { if (free) {
MEM_freeN(orco); MEM_freeN(orco);
} }
} }
if (!layer_orco.is_empty()) {
if (layer == CD_ORCO) {
BKE_mesh_orco_verts_transform(
(Mesh *)ob->data, reinterpret_cast<float(*)[3]>(layer_orco.data()), totvert, 0);
}
}
} }
static bool mesh_has_modifier_final_normals(const Mesh *mesh_input, static bool mesh_has_modifier_final_normals(const Mesh *mesh_input,
@ -1129,7 +1135,7 @@ static void editbmesh_calc_modifier_final_normals_or_defer(
editbmesh_calc_modifier_final_normals(mesh_final, final_datamask); editbmesh_calc_modifier_final_normals(mesh_final, final_datamask);
} }
static blender::MutableSpan<float3> mesh_wrapper_vert_coords_ensure_for_write(Mesh *mesh) static MutableSpan<float3> mesh_wrapper_vert_coords_ensure_for_write(Mesh *mesh)
{ {
switch (mesh->runtime->wrapper_type) { switch (mesh->runtime->wrapper_type) {
case ME_WRAPPER_TYPE_BMESH: case ME_WRAPPER_TYPE_BMESH:

View File

@ -779,8 +779,9 @@ static Mesh *create_applied_mesh_for_modifier(Depsgraph *depsgraph,
Mesh *mesh_temp = reinterpret_cast<Mesh *>( Mesh *mesh_temp = reinterpret_cast<Mesh *>(
BKE_id_copy_ex(nullptr, &me->id, nullptr, LIB_ID_COPY_LOCALIZE)); BKE_id_copy_ex(nullptr, &me->id, nullptr, LIB_ID_COPY_LOCALIZE));
int numVerts = 0; const int numVerts = mesh_temp->totvert;
float(*deformedVerts)[3] = nullptr; float(*deformedVerts)[3] = reinterpret_cast<float(*)[3]>(
mesh_temp->vert_positions_for_write().data());
if (use_virtual_modifiers) { if (use_virtual_modifiers) {
VirtualModifierData virtual_modifier_data; VirtualModifierData virtual_modifier_data;
@ -799,31 +800,21 @@ static Mesh *create_applied_mesh_for_modifier(Depsgraph *depsgraph,
continue; continue;
} }
if (deformedVerts == nullptr) {
deformedVerts = BKE_mesh_vert_coords_alloc(me, &numVerts);
}
mti_virt->deform_verts(md_eval_virt, &mectx, mesh_temp, deformedVerts, numVerts); mti_virt->deform_verts(md_eval_virt, &mectx, mesh_temp, deformedVerts, numVerts);
} }
} }
Mesh *result = nullptr; Mesh *result = nullptr;
if (mti->type == eModifierTypeType_OnlyDeform) { if (mti->type == eModifierTypeType_OnlyDeform) {
if (deformedVerts == nullptr) {
deformedVerts = BKE_mesh_vert_coords_alloc(me, &numVerts);
}
result = mesh_temp; result = mesh_temp;
mti->deform_verts(md_eval, &mectx, result, deformedVerts, numVerts); mti->deform_verts(md_eval, &mectx, result, deformedVerts, numVerts);
BKE_mesh_vert_coords_apply(result, deformedVerts); BKE_mesh_tag_positions_changed(result);
if (build_shapekey_layers) { if (build_shapekey_layers) {
add_shapekey_layers(*result, *me); add_shapekey_layers(*result, *me);
} }
} }
else { else {
if (deformedVerts != nullptr) {
BKE_mesh_vert_coords_apply(mesh_temp, deformedVerts);
}
if (build_shapekey_layers) { if (build_shapekey_layers) {
add_shapekey_layers(*mesh_temp, *me); add_shapekey_layers(*mesh_temp, *me);
} }
@ -846,10 +837,6 @@ static Mesh *create_applied_mesh_for_modifier(Depsgraph *depsgraph,
} }
} }
if (deformedVerts != nullptr) {
MEM_freeN(deformedVerts);
}
return result; return result;
} }

View File

@ -98,8 +98,6 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd,
Mesh *mesh) Mesh *mesh)
{ {
using namespace blender; using namespace blender;
float(*coords)[3], (*co)[3];
int i, verts_num;
Projector projectors[MOD_UVPROJECT_MAXPROJECTORS]; Projector projectors[MOD_UVPROJECT_MAXPROJECTORS];
int projectors_num = 0; int projectors_num = 0;
char uvname[MAX_CUSTOMDATA_LAYER_NAME]; char uvname[MAX_CUSTOMDATA_LAYER_NAME];
@ -109,7 +107,7 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd,
float scay = umd->scaley ? umd->scaley : 1.0f; float scay = umd->scaley ? umd->scaley : 1.0f;
int free_uci = 0; int free_uci = 0;
for (i = 0; i < umd->projectors_num; i++) { for (int i = 0; i < umd->projectors_num; i++) {
if (umd->projectors[i] != nullptr) { if (umd->projectors[i] != nullptr) {
projectors[projectors_num++].ob = umd->projectors[i]; projectors[projectors_num++].ob = umd->projectors[i];
} }
@ -128,7 +126,7 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd,
CustomData_validate_layer_name(&mesh->loop_data, CD_PROP_FLOAT2, umd->uvlayer_name, uvname); CustomData_validate_layer_name(&mesh->loop_data, CD_PROP_FLOAT2, umd->uvlayer_name, uvname);
/* calculate a projection matrix and normal for each projector */ /* calculate a projection matrix and normal for each projector */
for (i = 0; i < projectors_num; i++) { for (int i = 0; i < projectors_num; i++) {
float tmpmat[4][4]; float tmpmat[4][4];
float offsetmat[4][4]; float offsetmat[4][4];
Camera *cam = nullptr; Camera *cam = nullptr;
@ -182,30 +180,30 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd,
mul_mat3_m4_v3(projectors[i].ob->object_to_world, projectors[i].normal); mul_mat3_m4_v3(projectors[i].ob->object_to_world, projectors[i].normal);
} }
const blender::Span<blender::float3> positions = mesh->vert_positions(); const Span<float3> positions = mesh->vert_positions();
const blender::OffsetIndices faces = mesh->faces(); const OffsetIndices faces = mesh->faces();
const Span<int> corner_verts = mesh->corner_verts(); const Span<int> corner_verts = mesh->corner_verts();
float(*mloop_uv)[2] = static_cast<float(*)[2]>(CustomData_get_layer_named_for_write( float(*mloop_uv)[2] = static_cast<float(*)[2]>(CustomData_get_layer_named_for_write(
&mesh->loop_data, CD_PROP_FLOAT2, uvname, corner_verts.size())); &mesh->loop_data, CD_PROP_FLOAT2, uvname, corner_verts.size()));
coords = BKE_mesh_vert_coords_alloc(mesh, &verts_num); Array<float3> coords(positions.size());
/* Convert coords to world-space. */ /* Convert coords to world-space. */
for (i = 0, co = coords; i < verts_num; i++, co++) { for (int64_t i = 0; i < positions.size(); i++) {
mul_m4_v3(ob->object_to_world, *co); mul_v3_m4v3(coords[i], ob->object_to_world, positions[i]);
} }
/* if only one projector, project coords to UVs */ /* if only one projector, project coords to UVs */
if (projectors_num == 1 && projectors[0].uci == nullptr) { if (projectors_num == 1 && projectors[0].uci == nullptr) {
for (i = 0, co = coords; i < verts_num; i++, co++) { for (int64_t i = 0; i < coords.size(); i++) {
mul_project_m4_v3(projectors[0].projmat, *co); mul_project_m4_v3(projectors[0].projmat, coords[i]);
} }
} }
/* apply coords as UVs */ /* apply coords as UVs */
for (const int i : faces.index_range()) { for (const int i : faces.index_range()) {
const blender::IndexRange face = faces[i]; const IndexRange face = faces[i];
if (projectors_num == 1) { if (projectors_num == 1) {
if (projectors[0].uci) { if (projectors[0].uci) {
for (const int corner : face) { for (const int corner : face) {
@ -229,8 +227,8 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd,
float best_dot; float best_dot;
/* get the untransformed face normal */ /* get the untransformed face normal */
const blender::float3 face_no = blender::bke::mesh::face_normal_calc( const float3 face_no = blender::bke::mesh::face_normal_calc(positions,
positions, corner_verts.slice(face)); corner_verts.slice(face));
/* find the projector which the face points at most directly /* find the projector which the face points at most directly
* (projector normal with largest dot product is best) * (projector normal with largest dot product is best)
@ -262,8 +260,6 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd,
} }
} }
MEM_freeN(coords);
if (free_uci) { if (free_uci) {
int j; int j;
for (j = 0; j < projectors_num; j++) { for (j = 0; j < projectors_num; j++) {