2023-08-16 00:20:26 +10:00
|
|
|
/* SPDX-FileCopyrightText: 2005 Blender Authors
|
2023-05-31 16:19:06 +02:00
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
2005-03-27 20:34:18 +00:00
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
|
* \ingroup bke
|
2011-02-27 20:40:57 +00:00
|
|
|
*/
|
|
|
|
|
|
2020-12-14 13:00:28 +01:00
|
|
|
#include <cstring>
|
2005-07-23 19:15:08 +00:00
|
|
|
|
2005-03-27 20:34:18 +00:00
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
2010-03-30 11:49:07 +00:00
|
|
|
#include "DNA_cloth_types.h"
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
#include "DNA_customdata_types.h"
|
2006-08-28 01:12:36 +00:00
|
|
|
#include "DNA_key_types.h"
|
2012-02-19 22:17:30 +00:00
|
|
|
#include "DNA_mesh_types.h"
|
2005-03-27 20:34:18 +00:00
|
|
|
#include "DNA_meshdata_types.h"
|
|
|
|
|
#include "DNA_object_types.h"
|
2014-04-28 02:22:03 +10:00
|
|
|
#include "DNA_scene_types.h"
|
2005-03-27 20:34:18 +00:00
|
|
|
|
2014-09-04 17:53:10 +10:00
|
|
|
#include "BLI_bitmap.h"
|
2011-10-22 01:53:35 +00:00
|
|
|
#include "BLI_linklist.h"
|
Cleanup: reduce amount of math-related includes
Using ClangBuildAnalyzer on the whole Blender build, it was pointing
out that BLI_math.h is the heaviest "header hub" (i.e. non tiny file
that is included a lot).
However, there's very little (actually zero) source files in Blender
that need "all the math" (base, colors, vectors, matrices,
quaternions, intersection, interpolation, statistics, solvers and
time). A common use case is source files needing just vectors, or
just vectors & matrices, or just colors etc. Actually, 181 files
were including the whole math thing without needing it at all.
This change removes BLI_math.h completely, and instead in all the
places that need it, includes BLI_math_vector.h or BLI_math_color.h
and so on.
Change from that:
- BLI_math_color.h was included 1399 times -> now 408 (took 114.0sec
to parse -> now 36.3sec)
- BLI_simd.h 1403 -> 418 (109.7sec -> 34.9sec).
Full rebuild of Blender (Apple M1, Xcode, RelWithDebInfo) is not
affected much (342sec -> 334sec). Most of benefit would be when
someone's changing BLI_simd.h or BLI_math_color.h or similar files,
that now there's 3x fewer files result in a recompile.
Pull Request #110944
2023-08-09 11:39:20 +03:00
|
|
|
#include "BLI_math_geom.h"
|
|
|
|
|
#include "BLI_math_matrix.h"
|
2023-01-04 00:14:55 +01:00
|
|
|
#include "BLI_math_vector_types.hh"
|
2023-08-22 03:51:53 +02:00
|
|
|
#include "BLI_span.hh"
|
2025-01-28 15:27:34 +01:00
|
|
|
#include "BLI_string.h"
|
2021-06-21 18:44:40 +02:00
|
|
|
#include "BLI_task.hh"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BLI_utildefines.h"
|
2020-12-14 13:00:28 +01:00
|
|
|
#include "BLI_vector.hh"
|
2005-03-27 20:34:18 +00:00
|
|
|
|
2023-11-16 11:41:55 +01:00
|
|
|
#include "BKE_editmesh.hh"
|
2023-07-07 08:19:52 -04:00
|
|
|
#include "BKE_editmesh_cache.hh"
|
2020-12-15 12:42:10 +01:00
|
|
|
#include "BKE_geometry_set.hh"
|
2024-01-30 14:42:07 -05:00
|
|
|
#include "BKE_key.hh"
|
2024-01-23 15:18:09 -05:00
|
|
|
#include "BKE_layer.hh"
|
2024-01-15 12:44:04 -05:00
|
|
|
#include "BKE_lib_id.hh"
|
2025-01-09 17:26:40 +01:00
|
|
|
#include "BKE_material.hh"
|
2023-03-12 22:29:15 +01:00
|
|
|
#include "BKE_mesh.hh"
|
2023-08-02 22:14:18 +02:00
|
|
|
#include "BKE_mesh_iterators.hh"
|
|
|
|
|
#include "BKE_mesh_runtime.hh"
|
|
|
|
|
#include "BKE_mesh_wrapper.hh"
|
2023-11-14 09:30:40 +01:00
|
|
|
#include "BKE_modifier.hh"
|
2023-08-02 22:14:18 +02:00
|
|
|
#include "BKE_multires.hh"
|
2023-10-09 23:41:53 +02:00
|
|
|
#include "BKE_object.hh"
|
2023-11-15 18:46:07 +01:00
|
|
|
#include "BKE_object_types.hh"
|
2023-08-02 22:14:18 +02:00
|
|
|
#include "BKE_paint.hh"
|
2005-03-27 20:34:18 +00:00
|
|
|
|
2023-11-28 16:05:12 -05:00
|
|
|
#include "BKE_shrinkwrap.hh"
|
2023-09-22 03:18:17 +02:00
|
|
|
#include "DEG_depsgraph.hh"
|
|
|
|
|
#include "DEG_depsgraph_query.hh"
|
2018-04-16 20:45:43 +02:00
|
|
|
|
2024-05-20 12:26:07 -04:00
|
|
|
namespace blender::bke {
|
2022-07-08 14:45:48 +02:00
|
|
|
|
2025-01-24 13:41:38 +11:00
|
|
|
/**
|
|
|
|
|
* Validate all meshes being modified, input and output.
|
|
|
|
|
* This is slow (even for debug mode), enable manually when investigating bugs.
|
|
|
|
|
*
|
|
|
|
|
* \note Validating the input as well as the output can be useful
|
|
|
|
|
* to rule out corrupt input.
|
|
|
|
|
*/
|
2024-01-02 18:12:54 +01:00
|
|
|
// #define USE_MODIFIER_VALIDATE
|
2013-09-04 01:29:34 +00:00
|
|
|
|
|
|
|
|
#ifdef USE_MODIFIER_VALIDATE
|
2025-01-24 13:41:38 +11:00
|
|
|
# define ASSERT_IS_VALID_MESH_INPUT(mesh) (BLI_assert(BKE_mesh_is_valid(mesh) == true))
|
|
|
|
|
# define ASSERT_IS_VALID_MESH_OUTPUT(mesh) \
|
2020-12-14 13:00:28 +01:00
|
|
|
(BLI_assert((mesh == nullptr) || (BKE_mesh_is_valid(mesh) == true)))
|
2013-09-04 01:29:34 +00:00
|
|
|
#else
|
2025-01-24 13:41:38 +11:00
|
|
|
# define ASSERT_IS_VALID_MESH_INPUT(mesh) \
|
|
|
|
|
{ \
|
|
|
|
|
(void)mesh; \
|
|
|
|
|
};
|
|
|
|
|
# define ASSERT_IS_VALID_MESH_OUTPUT(mesh) \
|
|
|
|
|
{ \
|
|
|
|
|
(void)mesh; \
|
|
|
|
|
};
|
|
|
|
|
|
2013-09-04 01:29:34 +00:00
|
|
|
#endif
|
|
|
|
|
|
2024-05-20 13:11:12 -04:00
|
|
|
static void mesh_init_origspace(Mesh &mesh);
|
2018-05-11 03:53:52 -04:00
|
|
|
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
static void mesh_set_only_copy(Mesh *mesh, const CustomData_MeshMasks *mask)
|
2018-05-11 03:53:52 -04:00
|
|
|
{
|
2023-07-25 21:15:52 +02:00
|
|
|
CustomData_set_only_copy(&mesh->vert_data, mask->vmask);
|
|
|
|
|
CustomData_set_only_copy(&mesh->edge_data, mask->emask);
|
2023-07-24 22:06:55 +02:00
|
|
|
CustomData_set_only_copy(&mesh->fdata_legacy, mask->fmask);
|
2018-05-11 03:53:52 -04:00
|
|
|
/* this wasn't in 2.63 and is disabled for 2.64 because it gives problems with
|
|
|
|
|
* weight paint mode when there are modifiers applied, needs further investigation,
|
|
|
|
|
* see replies to r50969, Campbell */
|
|
|
|
|
#if 0
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
CustomData_set_only_copy(&mesh->ldata, mask->lmask);
|
|
|
|
|
CustomData_set_only_copy(&mesh->pdata, mask->pmask);
|
2018-05-11 03:53:52 -04:00
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2009-05-23 03:24:15 +00:00
|
|
|
/* orco custom data layer */
|
2024-05-20 13:11:12 -04:00
|
|
|
static Span<float3> get_orco_coords(const Object &ob,
|
2024-05-10 18:23:13 -04:00
|
|
|
const BMEditMesh *em,
|
|
|
|
|
eCustomDataType layer_type,
|
|
|
|
|
Array<float3> &storage)
|
2010-03-30 11:49:07 +00:00
|
|
|
{
|
2024-05-10 18:23:13 -04:00
|
|
|
if (layer_type == CD_ORCO) {
|
2010-03-30 11:49:07 +00:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (em) {
|
2024-05-10 18:23:13 -04:00
|
|
|
storage = BM_mesh_vert_coords_alloc(em->bm);
|
|
|
|
|
return storage;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2024-05-20 13:11:12 -04:00
|
|
|
storage = BKE_mesh_orco_verts_get(&ob);
|
2024-05-10 18:23:13 -04:00
|
|
|
return storage;
|
2010-03-30 11:49:07 +00:00
|
|
|
}
|
2024-05-10 18:23:13 -04:00
|
|
|
if (layer_type == CD_CLOTH_ORCO) {
|
2010-03-30 11:49:07 +00:00
|
|
|
/* apply shape key for cloth, this should really be solved
|
2012-03-09 18:28:30 +00:00
|
|
|
* by a more flexible customdata system, but not simple */
|
2012-03-24 06:18:31 +00:00
|
|
|
if (!em) {
|
2024-03-27 22:24:40 -04:00
|
|
|
const ClothModifierData *clmd = (const ClothModifierData *)BKE_modifiers_findby_type(
|
2024-05-20 13:11:12 -04:00
|
|
|
&ob, eModifierType_Cloth);
|
2023-07-14 20:57:28 +03:00
|
|
|
if (clmd && clmd->sim_parms->shapekey_rest) {
|
2024-03-27 22:24:40 -04:00
|
|
|
const KeyBlock *kb = BKE_keyblock_find_by_index(
|
2024-05-20 13:11:12 -04:00
|
|
|
BKE_key_from_object(const_cast<Object *>(&ob)), clmd->sim_parms->shapekey_rest);
|
2011-12-04 23:13:28 +00:00
|
|
|
|
2021-05-12 23:14:58 +02:00
|
|
|
if (kb && kb->data) {
|
2024-05-10 18:23:13 -04:00
|
|
|
return {static_cast<const float3 *>(kb->data), kb->totelem};
|
2021-05-12 23:14:58 +02:00
|
|
|
}
|
2015-04-13 15:54:37 +10:00
|
|
|
}
|
2010-03-30 11:49:07 +00:00
|
|
|
}
|
|
|
|
|
|
2024-05-10 18:23:13 -04:00
|
|
|
return {};
|
2010-03-30 11:49:07 +00:00
|
|
|
}
|
|
|
|
|
|
2024-05-10 18:23:13 -04:00
|
|
|
return {};
|
2010-03-30 11:49:07 +00:00
|
|
|
}
|
|
|
|
|
|
2024-05-20 13:11:12 -04:00
|
|
|
static Mesh *create_orco_mesh(const Object &ob,
|
|
|
|
|
const Mesh &mesh,
|
2024-05-10 18:23:13 -04:00
|
|
|
const BMEditMesh *em,
|
|
|
|
|
eCustomDataType layer)
|
2018-05-11 03:53:52 -04:00
|
|
|
{
|
2023-12-08 16:40:06 -05:00
|
|
|
Mesh *orco_mesh;
|
2018-05-11 03:53:52 -04:00
|
|
|
if (em) {
|
2024-05-20 13:11:12 -04:00
|
|
|
orco_mesh = BKE_mesh_from_bmesh_for_eval_nomain(em->bm, nullptr, &mesh);
|
2023-12-08 16:40:06 -05:00
|
|
|
BKE_mesh_ensure_default_orig_index_customdata(orco_mesh);
|
2018-05-11 03:53:52 -04:00
|
|
|
}
|
|
|
|
|
else {
|
2024-05-20 13:18:24 -04:00
|
|
|
orco_mesh = BKE_mesh_copy_for_eval(mesh);
|
2018-05-11 03:53:52 -04:00
|
|
|
}
|
|
|
|
|
|
2024-05-10 18:23:13 -04:00
|
|
|
Array<float3> storage;
|
|
|
|
|
const Span<float3> orco = get_orco_coords(ob, em, layer, storage);
|
2018-05-11 03:53:52 -04:00
|
|
|
|
2024-05-10 18:23:13 -04:00
|
|
|
if (!orco.is_empty()) {
|
|
|
|
|
orco_mesh->vert_positions_for_write().copy_from(orco);
|
2023-12-12 15:38:42 -05:00
|
|
|
orco_mesh->tag_positions_changed();
|
2018-05-11 03:53:52 -04:00
|
|
|
}
|
|
|
|
|
|
2023-12-08 16:40:06 -05:00
|
|
|
return orco_mesh;
|
2018-05-11 03:53:52 -04:00
|
|
|
}
|
|
|
|
|
|
2024-05-20 13:11:12 -04:00
|
|
|
static MutableSpan<float3> orco_coord_layer_ensure(Mesh &mesh, const eCustomDataType layer)
|
2023-08-22 03:51:53 +02:00
|
|
|
{
|
2024-05-20 13:11:12 -04:00
|
|
|
void *data = CustomData_get_layer_for_write(&mesh.vert_data, layer, mesh.verts_num);
|
2023-08-22 03:51:53 +02:00
|
|
|
if (!data) {
|
2024-05-20 13:11:12 -04:00
|
|
|
data = CustomData_add_layer(&mesh.vert_data, layer, CD_CONSTRUCT, mesh.verts_num);
|
2023-08-22 03:51:53 +02:00
|
|
|
}
|
2024-05-20 13:11:12 -04:00
|
|
|
return MutableSpan(reinterpret_cast<float3 *>(data), mesh.verts_num);
|
2023-08-22 03:51:53 +02:00
|
|
|
}
|
|
|
|
|
|
2024-05-20 13:11:12 -04:00
|
|
|
static void add_orco_mesh(Object &ob,
|
2024-03-27 22:24:40 -04:00
|
|
|
const BMEditMesh *em,
|
2024-05-20 13:11:12 -04:00
|
|
|
Mesh &mesh,
|
2024-03-27 22:24:40 -04:00
|
|
|
const Mesh *mesh_orco,
|
|
|
|
|
const eCustomDataType layer)
|
2018-05-11 03:53:52 -04:00
|
|
|
{
|
2024-05-20 13:11:12 -04:00
|
|
|
const int totvert = mesh.verts_num;
|
2018-05-11 03:53:52 -04:00
|
|
|
|
2023-08-22 03:51:53 +02:00
|
|
|
MutableSpan<float3> layer_orco;
|
2019-03-28 11:42:53 +01:00
|
|
|
if (mesh_orco) {
|
2023-08-22 03:51:53 +02:00
|
|
|
layer_orco = orco_coord_layer_ensure(mesh, layer);
|
2018-05-11 03:53:52 -04:00
|
|
|
|
2023-12-20 02:21:48 +01:00
|
|
|
if (mesh_orco->verts_num == totvert) {
|
2023-08-22 03:51:53 +02:00
|
|
|
layer_orco.copy_from(mesh_orco->vert_positions());
|
2018-05-11 03:53:52 -04:00
|
|
|
}
|
|
|
|
|
else {
|
2024-05-20 13:11:12 -04:00
|
|
|
layer_orco.copy_from(mesh.vert_positions());
|
2018-05-11 03:53:52 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
2024-09-25 19:24:18 +10:00
|
|
|
/* TODO(@sybren): `totvert` should potentially change here, as `ob->data`
|
|
|
|
|
* or `em` may have a different number of vertices than the evaluated `mesh`. */
|
2024-05-10 18:23:13 -04:00
|
|
|
Array<float3> storage;
|
|
|
|
|
const Span<float3> orco = get_orco_coords(ob, em, layer, storage);
|
|
|
|
|
if (!orco.is_empty()) {
|
2023-08-22 03:51:53 +02:00
|
|
|
layer_orco = orco_coord_layer_ensure(mesh, layer);
|
2024-05-10 18:23:13 -04:00
|
|
|
layer_orco.copy_from(orco);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2018-05-11 03:53:52 -04:00
|
|
|
}
|
2023-08-22 03:51:53 +02:00
|
|
|
|
|
|
|
|
if (!layer_orco.is_empty()) {
|
|
|
|
|
if (layer == CD_ORCO) {
|
2024-05-20 13:11:12 -04:00
|
|
|
BKE_mesh_orco_verts_transform((Mesh *)ob.data, layer_orco, false);
|
2023-08-22 03:51:53 +02:00
|
|
|
}
|
|
|
|
|
}
|
2018-05-11 03:53:52 -04:00
|
|
|
}
|
|
|
|
|
|
2024-09-25 19:24:20 +10:00
|
|
|
/**
|
|
|
|
|
* Does final touches to the final evaluated mesh, making sure it is perfectly usable.
|
2019-05-27 11:45:33 +02:00
|
|
|
*
|
|
|
|
|
* This is needed because certain information is not passed along intermediate meshes allocated
|
|
|
|
|
* during stack evaluation.
|
|
|
|
|
*/
|
2024-05-20 13:11:12 -04:00
|
|
|
static void mesh_calc_finalize(const Mesh &mesh_input, Mesh &mesh_eval)
|
2019-05-27 11:45:33 +02:00
|
|
|
{
|
|
|
|
|
/* Make sure the name is the same. This is because mesh allocation from template does not
|
|
|
|
|
* take care of naming. */
|
2024-05-20 13:11:12 -04:00
|
|
|
STRNCPY(mesh_eval.id.name, mesh_input.id.name);
|
2019-05-27 11:45:33 +02:00
|
|
|
}
|
|
|
|
|
|
2020-12-15 12:42:10 +01:00
|
|
|
/**
|
2021-02-02 09:20:54 -06:00
|
|
|
* Modifies the given mesh and geometry set. The mesh is not passed as part of the mesh component
|
|
|
|
|
* in the \a geometry_set input, it is only passed in \a input_mesh and returned in the return
|
|
|
|
|
* value.
|
2020-12-15 12:42:10 +01:00
|
|
|
*
|
2021-02-02 09:20:54 -06:00
|
|
|
* The purpose of the geometry set is to store all geometry components that are generated
|
|
|
|
|
* by modifiers to allow outputting non-mesh data from modifiers.
|
2020-12-15 12:42:10 +01:00
|
|
|
*/
|
|
|
|
|
static Mesh *modifier_modify_mesh_and_geometry_set(ModifierData *md,
|
|
|
|
|
const ModifierEvalContext &mectx,
|
|
|
|
|
Mesh *input_mesh,
|
|
|
|
|
GeometrySet &geometry_set)
|
|
|
|
|
{
|
|
|
|
|
Mesh *mesh_output = nullptr;
|
|
|
|
|
const ModifierTypeInfo *mti = BKE_modifier_get_info((ModifierType)md->type);
|
2023-07-27 12:04:18 +10:00
|
|
|
if (mti->modify_geometry_set == nullptr) {
|
2021-10-19 08:39:10 -05:00
|
|
|
mesh_output = BKE_modifier_modify_mesh(md, &mectx, input_mesh);
|
2020-12-15 12:42:10 +01:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* For performance reasons, this should be called by the modifier and/or nodes themselves at
|
|
|
|
|
* some point. */
|
|
|
|
|
BKE_mesh_wrapper_ensure_mdata(input_mesh);
|
|
|
|
|
|
2021-02-02 09:20:54 -06:00
|
|
|
/* Replace only the mesh rather than the whole component, because the entire #MeshComponent
|
|
|
|
|
* might have been replaced by data from a different object in the node tree, which means the
|
|
|
|
|
* component contains vertex group name data for that object that should not be removed. */
|
2023-07-07 09:59:55 -04:00
|
|
|
geometry_set.replace_mesh(input_mesh, GeometryOwnershipType::Editable);
|
2020-12-15 12:42:10 +01:00
|
|
|
|
|
|
|
|
/* Let the modifier change the geometry set. */
|
2023-07-27 12:04:18 +10:00
|
|
|
mti->modify_geometry_set(md, &mectx, &geometry_set);
|
2020-12-15 12:42:10 +01:00
|
|
|
|
|
|
|
|
/* Release the mesh from the geometry set again. */
|
|
|
|
|
if (geometry_set.has<MeshComponent>()) {
|
|
|
|
|
MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>();
|
2023-08-03 17:09:18 +02:00
|
|
|
if (mesh_component.get() != input_mesh) {
|
2021-11-03 10:42:48 +01:00
|
|
|
/* Make sure the mesh component actually owns the mesh before taking over ownership. */
|
|
|
|
|
mesh_component.ensure_owns_direct_data();
|
|
|
|
|
}
|
2020-12-15 12:42:10 +01:00
|
|
|
mesh_output = mesh_component.release();
|
|
|
|
|
}
|
2023-10-02 17:43:22 +02:00
|
|
|
/* Need to ensure that non-mesh data is also owned by the geometry set. Otherwise it might be
|
|
|
|
|
* freed while there is still a reference to it in the geometry. */
|
|
|
|
|
geometry_set.ensure_owns_direct_data();
|
2020-12-15 12:42:10 +01:00
|
|
|
|
2021-06-24 15:56:58 +10:00
|
|
|
/* Return an empty mesh instead of null. */
|
2020-12-15 12:42:10 +01:00
|
|
|
if (mesh_output == nullptr) {
|
2023-02-27 11:09:26 -05:00
|
|
|
mesh_output = BKE_mesh_new_nomain(0, 0, 0, 0);
|
2021-06-17 14:56:39 +10:00
|
|
|
BKE_mesh_copy_parameters_for_eval(mesh_output, input_mesh);
|
2020-12-15 12:42:10 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return mesh_output;
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-20 20:18:02 +02:00
|
|
|
static void set_rest_position(Mesh &mesh)
|
|
|
|
|
{
|
|
|
|
|
MutableAttributeAccessor attributes = mesh.attributes_for_write();
|
|
|
|
|
const AttributeReader positions = attributes.lookup<float3>("position");
|
|
|
|
|
attributes.remove("rest_position");
|
|
|
|
|
if (positions) {
|
|
|
|
|
if (positions.sharing_info && positions.varray.is_span()) {
|
|
|
|
|
attributes.add<float3>("rest_position",
|
2023-12-20 13:13:16 -05:00
|
|
|
AttrDomain::Point,
|
2023-04-20 20:18:02 +02:00
|
|
|
AttributeInitShared(positions.varray.get_internal_span().data(),
|
|
|
|
|
*positions.sharing_info));
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
attributes.add<float3>(
|
2023-12-20 13:13:16 -05:00
|
|
|
"rest_position", AttrDomain::Point, AttributeInitVArray(positions.varray));
|
2023-04-20 20:18:02 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-20 13:11:12 -04:00
|
|
|
static void mesh_calc_modifiers(Depsgraph &depsgraph,
|
|
|
|
|
const Scene &scene,
|
|
|
|
|
Object &ob,
|
2021-06-30 16:41:53 -05:00
|
|
|
const bool use_deform,
|
2019-03-27 19:07:16 +01:00
|
|
|
const bool need_mapping,
|
2024-05-20 13:11:12 -04:00
|
|
|
const CustomData_MeshMasks &dataMask,
|
2019-03-28 11:42:53 +01:00
|
|
|
const bool use_cache,
|
2019-05-31 10:05:56 +02:00
|
|
|
const bool allow_shared_mesh,
|
2015-07-02 16:20:22 +10:00
|
|
|
/* return args */
|
2019-03-27 19:07:16 +01:00
|
|
|
Mesh **r_deform,
|
2020-12-15 12:42:10 +01:00
|
|
|
Mesh **r_final,
|
|
|
|
|
GeometrySet **r_geometry_set)
|
2005-03-27 20:34:18 +00:00
|
|
|
{
|
2023-02-06 14:34:16 -05:00
|
|
|
/* Input mesh shouldn't be modified. */
|
2024-05-20 13:11:12 -04:00
|
|
|
Mesh &mesh_input = *static_cast<Mesh *>(ob.data);
|
2023-02-06 14:34:16 -05:00
|
|
|
/* The final mesh is the result of calculating all enabled modifiers. */
|
2024-05-20 13:36:58 -04:00
|
|
|
Mesh *mesh = nullptr;
|
2023-02-06 14:34:16 -05:00
|
|
|
/* The result of calculating all leading deform modifiers. */
|
2020-12-14 13:00:28 +01:00
|
|
|
Mesh *mesh_deform = nullptr;
|
2020-12-15 12:42:10 +01:00
|
|
|
/* This geometry set contains the non-mesh data that might be generated by modifiers. */
|
|
|
|
|
GeometrySet geometry_set_final;
|
2021-02-02 09:20:54 -06:00
|
|
|
|
2024-08-07 12:12:17 +02:00
|
|
|
BLI_assert((mesh_input.id.tag & ID_TAG_COPIED_ON_EVAL_FINAL_RESULT) == 0);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-28 11:42:53 +01:00
|
|
|
/* Mesh with constructive modifiers but no deformation applied. Tracked
|
|
|
|
|
* along with final mesh if undeformed / orco coordinates are requested
|
|
|
|
|
* for texturing. */
|
2020-12-14 13:00:28 +01:00
|
|
|
Mesh *mesh_orco = nullptr;
|
|
|
|
|
Mesh *mesh_orco_cloth = nullptr;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-28 11:42:53 +01:00
|
|
|
/* Modifier evaluation modes. */
|
2024-05-20 13:11:12 -04:00
|
|
|
const bool use_render = (DEG_get_mode(&depsgraph) == DAG_EVAL_RENDER);
|
2019-03-28 11:42:53 +01:00
|
|
|
const int required_mode = use_render ? eModifierMode_Render : eModifierMode_Realtime;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-28 11:42:53 +01:00
|
|
|
/* Sculpt can skip certain modifiers. */
|
2024-05-20 13:11:12 -04:00
|
|
|
const bool has_multires = BKE_sculpt_multires_active(&scene, &ob) != nullptr;
|
2014-01-28 03:52:21 +11:00
|
|
|
bool multires_applied = false;
|
2024-05-20 13:11:12 -04:00
|
|
|
const bool sculpt_mode = ob.mode & OB_MODE_SCULPT && ob.sculpt && !use_render;
|
|
|
|
|
const bool sculpt_dyntopo = (sculpt_mode && ob.sculpt->bm) && !use_render;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-28 11:42:53 +01:00
|
|
|
/* Modifier evaluation contexts for different types of modifiers. */
|
2023-05-26 16:11:54 -04:00
|
|
|
ModifierApplyFlag apply_render = use_render ? MOD_APPLY_RENDER : ModifierApplyFlag(0);
|
|
|
|
|
ModifierApplyFlag apply_cache = use_cache ? MOD_APPLY_USECACHE : ModifierApplyFlag(0);
|
2024-05-20 13:11:12 -04:00
|
|
|
const ModifierEvalContext mectx = {&depsgraph, &ob, apply_render | apply_cache};
|
|
|
|
|
const ModifierEvalContext mectx_orco = {&depsgraph, &ob, apply_render | MOD_APPLY_ORCO};
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-28 11:42:53 +01:00
|
|
|
/* Get effective list of modifiers to execute. Some effects like shape keys
|
|
|
|
|
* are added as virtual modifiers before the user created modifiers. */
|
2023-07-27 12:04:18 +10:00
|
|
|
VirtualModifierData virtual_modifier_data;
|
2024-05-20 13:11:12 -04:00
|
|
|
ModifierData *firstmd = BKE_modifiers_get_virtual_modifierlist(&ob, &virtual_modifier_data);
|
2019-03-28 11:42:53 +01:00
|
|
|
ModifierData *md = firstmd;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-28 11:42:53 +01:00
|
|
|
/* Compute accumulated datamasks needed by each modifier. It helps to do
|
|
|
|
|
* this fine grained so that for example vertex groups are preserved up to
|
|
|
|
|
* an armature modifier, but not through a following subsurf modifier where
|
|
|
|
|
* subdividing them is expensive. */
|
2024-05-20 13:11:12 -04:00
|
|
|
CustomData_MeshMasks final_datamask = dataMask;
|
|
|
|
|
CDMaskLink *datamasks = BKE_modifier_calc_data_masks(&scene, md, &final_datamask, required_mode);
|
2019-03-28 11:42:53 +01:00
|
|
|
CDMaskLink *md_datamask = datamasks;
|
|
|
|
|
/* XXX Always copying POLYINDEX, else tessellated data are no more valid! */
|
|
|
|
|
CustomData_MeshMasks append_mask = CD_MASK_BAREMESH_ORIGINDEX;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-28 11:42:53 +01:00
|
|
|
/* Clear errors before evaluation. */
|
2024-05-20 13:11:12 -04:00
|
|
|
BKE_modifiers_clear_errors(&ob);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2024-05-20 13:11:12 -04:00
|
|
|
if (ob.modifier_flag & OB_MODIFIER_FLAG_ADD_REST_POSITION) {
|
2024-05-20 13:36:58 -04:00
|
|
|
if (mesh == nullptr) {
|
2025-01-24 13:41:38 +11:00
|
|
|
ASSERT_IS_VALID_MESH_INPUT(&mesh_input);
|
2024-05-20 13:36:58 -04:00
|
|
|
mesh = BKE_mesh_copy_for_eval(mesh_input);
|
2025-01-24 13:41:38 +11:00
|
|
|
ASSERT_IS_VALID_MESH_OUTPUT(mesh);
|
2022-07-08 14:45:48 +02:00
|
|
|
}
|
2024-05-20 13:36:58 -04:00
|
|
|
set_rest_position(*mesh);
|
2022-07-08 14:45:48 +02:00
|
|
|
}
|
|
|
|
|
|
2019-03-28 11:42:53 +01:00
|
|
|
/* Apply all leading deform modifiers. */
|
2021-06-30 16:41:53 -05:00
|
|
|
if (use_deform) {
|
2019-03-28 11:42:53 +01:00
|
|
|
for (; md; md = md->next, md_datamask = md_datamask->next) {
|
2020-12-14 13:00:28 +01:00
|
|
|
const ModifierTypeInfo *mti = BKE_modifier_get_info((ModifierType)md->type);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2024-05-20 13:11:12 -04:00
|
|
|
if (!BKE_modifier_is_enabled(&scene, md, required_mode)) {
|
2015-07-02 16:20:22 +10:00
|
|
|
continue;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-11-14 10:03:56 +01:00
|
|
|
if (mti->type == ModifierTypeType::OnlyDeform && !sculpt_dyntopo) {
|
2023-12-28 11:23:40 -05:00
|
|
|
ScopedModifierTimer modifier_timer{*md};
|
2024-05-20 13:36:58 -04:00
|
|
|
if (!mesh) {
|
2025-01-24 13:41:38 +11:00
|
|
|
ASSERT_IS_VALID_MESH_INPUT(&mesh_input);
|
2024-05-20 13:36:58 -04:00
|
|
|
mesh = BKE_mesh_copy_for_eval(mesh_input);
|
2025-01-24 13:41:38 +11:00
|
|
|
ASSERT_IS_VALID_MESH_OUTPUT(mesh);
|
2019-03-18 15:37:46 +01:00
|
|
|
}
|
2023-10-13 20:35:16 +02:00
|
|
|
|
|
|
|
|
if (mti->required_data_mask) {
|
|
|
|
|
CustomData_MeshMasks mask{};
|
|
|
|
|
mti->required_data_mask(md, &mask);
|
|
|
|
|
if (mask.vmask & CD_MASK_ORCO) {
|
2024-05-20 13:36:58 -04:00
|
|
|
add_orco_mesh(ob, nullptr, *mesh, nullptr, CD_ORCO);
|
2023-10-13 20:35:16 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-20 13:36:58 -04:00
|
|
|
BKE_modifier_deform_verts(md, &mectx, mesh, mesh->vert_positions_for_write());
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2005-07-19 20:14:17 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2006-08-28 01:12:36 +00:00
|
|
|
/* Result of all leading deforming modifiers is cached for
|
|
|
|
|
* places that wish to use the original mesh but with deformed
|
2019-03-28 11:42:53 +01:00
|
|
|
* coordinates (like vertex paint). */
|
2018-10-10 15:00:37 +11:00
|
|
|
if (r_deform) {
|
2024-05-20 13:36:58 -04:00
|
|
|
mesh_deform = BKE_mesh_copy_for_eval(mesh ? *mesh : mesh_input);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2006-09-07 06:44:25 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-28 11:42:53 +01:00
|
|
|
/* Apply all remaining constructive and deforming modifiers. */
|
2023-07-17 11:40:08 +02:00
|
|
|
bool have_non_onlydeform_modifiers_applied = false;
|
2019-03-28 11:42:53 +01:00
|
|
|
for (; md; md = md->next, md_datamask = md_datamask->next) {
|
2020-12-14 13:00:28 +01:00
|
|
|
const ModifierTypeInfo *mti = BKE_modifier_get_info((ModifierType)md->type);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2024-05-20 13:11:12 -04:00
|
|
|
if (!BKE_modifier_is_enabled(&scene, md, required_mode)) {
|
2015-07-02 16:20:22 +10:00
|
|
|
continue;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-11-14 10:03:56 +01:00
|
|
|
if (mti->type == ModifierTypeType::OnlyDeform && !use_deform) {
|
2015-07-02 16:20:22 +10:00
|
|
|
continue;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-11-13 11:29:19 +01:00
|
|
|
if ((mti->flags & eModifierTypeFlag_RequiresOriginalData) &&
|
2024-01-02 18:12:54 +01:00
|
|
|
have_non_onlydeform_modifiers_applied)
|
|
|
|
|
{
|
2024-05-20 13:11:12 -04:00
|
|
|
BKE_modifier_set_error(&ob, md, "Modifier requires original data, bad stack position");
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
continue;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-05-09 18:29:21 +10:00
|
|
|
if (sculpt_mode && (!has_multires || multires_applied || sculpt_dyntopo)) {
|
2014-01-28 03:52:21 +11:00
|
|
|
bool unsupported = false;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-04-30 15:41:45 +02:00
|
|
|
if (md->type == eModifierType_Multires && ((MultiresModifierData *)md)->sculptlvl == 0) {
|
2013-06-03 08:26:12 +00:00
|
|
|
/* If multires is on level 0 skip it silently without warning message. */
|
2015-07-02 16:20:22 +10:00
|
|
|
if (!sculpt_dyntopo) {
|
2014-05-08 19:25:46 +03:00
|
|
|
continue;
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2015-07-02 16:20:22 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (sculpt_dyntopo) {
|
2014-01-28 03:52:21 +11:00
|
|
|
unsupported = true;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2024-05-20 13:11:12 -04:00
|
|
|
if (scene.toolsettings->sculpt->flags & SCULPT_ONLY_DEFORM) {
|
2023-11-14 10:03:56 +01:00
|
|
|
unsupported |= (mti->type != ModifierTypeType::OnlyDeform);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-05-12 19:18:02 +00:00
|
|
|
unsupported |= multires_applied;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-24 06:18:31 +00:00
|
|
|
if (unsupported) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (sculpt_dyntopo) {
|
2024-05-20 13:11:12 -04:00
|
|
|
BKE_modifier_set_error(&ob, md, "Not supported in dyntopo");
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
else {
|
2024-05-20 13:11:12 -04:00
|
|
|
BKE_modifier_set_error(&ob, md, "Not supported in sculpt mode");
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2011-01-31 20:02:51 +00:00
|
|
|
continue;
|
|
|
|
|
}
|
2014-05-08 19:15:36 +03:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-05-08 10:14:02 +02:00
|
|
|
if (need_mapping && !BKE_modifier_supports_mapping(md)) {
|
2015-07-02 16:20:22 +10:00
|
|
|
continue;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2024-05-20 12:26:07 -04:00
|
|
|
ScopedModifierTimer modifier_timer{*md};
|
Modifiers: measure execution time and provide Python access
The goal is to give technical artists the ability to optimize modifier usage
and/or geometry node groups for performance. In the long term, it
would be useful if Blender could provide its own UI to display profiling
information to users. However, right now, there are too many open
design questions making it infeasible to tackle this in the short term.
This commit uses a simpler approach: Instead of adding new ui for
profiling data, it exposes the execution-time of modifiers in the Python
API. This allows technical artists to access the information and to build
their own UI to display the relevant information. In the long term this
will hopefully also help us to integrate a native ui for this in Blender
by observing how users use this information.
Note: The execution time of a modifier highly depends on what other
things the CPU is doing at the same time. For example, in many more
complex files, many objects and therefore modifiers are evaluated at
the same time by multiple threads which makes the measurement
much less reliable. For best results, make sure that only one object
is evaluated at a time (e.g. by changing it in isolation) and that no
other process on the system keeps the CPU busy.
As shown below, the execution time has to be accessed on the
evaluated object, not the original object.
```lang=python
import bpy
depsgraph = bpy.context.view_layer.depsgraph
ob = bpy.context.active_object
ob_eval = ob.evaluated_get(depsgraph)
modifier_eval = ob_eval.modifiers[0]
print(modifier_eval.execution_time, "s")
```
Differential Revision: https://developer.blender.org/D17185
2023-02-06 15:39:59 +01:00
|
|
|
|
2019-06-10 15:42:15 +02:00
|
|
|
/* Add orco mesh as layer if needed by this modifier. */
|
2024-05-20 13:36:58 -04:00
|
|
|
if (mesh && mesh_orco && mti->required_data_mask) {
|
2019-03-28 11:42:53 +01:00
|
|
|
CustomData_MeshMasks mask = {0};
|
2023-07-27 12:04:18 +10:00
|
|
|
mti->required_data_mask(md, &mask);
|
2019-03-28 11:42:53 +01:00
|
|
|
if (mask.vmask & CD_MASK_ORCO) {
|
2024-05-20 13:36:58 -04:00
|
|
|
add_orco_mesh(ob, nullptr, *mesh, mesh_orco, CD_ORCO);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2019-03-28 11:42:53 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-11-14 10:03:56 +01:00
|
|
|
if (mti->type == ModifierTypeType::OnlyDeform) {
|
2024-05-20 13:36:58 -04:00
|
|
|
if (!mesh) {
|
2025-01-24 13:41:38 +11:00
|
|
|
ASSERT_IS_VALID_MESH_INPUT(&mesh_input);
|
2024-05-20 13:36:58 -04:00
|
|
|
mesh = BKE_mesh_copy_for_eval(mesh_input);
|
2025-01-24 13:41:38 +11:00
|
|
|
ASSERT_IS_VALID_MESH_OUTPUT(mesh);
|
2010-09-30 10:51:36 +00:00
|
|
|
}
|
2024-05-20 13:36:58 -04:00
|
|
|
BKE_modifier_deform_verts(md, &mectx, mesh, mesh->vert_positions_for_write());
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2020-09-23 15:09:53 +10:00
|
|
|
bool check_for_needs_mapping = false;
|
2024-05-20 13:36:58 -04:00
|
|
|
if (mesh != nullptr) {
|
2023-07-17 11:40:08 +02:00
|
|
|
if (have_non_onlydeform_modifiers_applied == false) {
|
2020-09-23 15:12:28 +10:00
|
|
|
/* If we only deformed, we won't have initialized #CD_ORIGINDEX.
|
|
|
|
|
* as this is the only part of the function that initializes mapping. */
|
|
|
|
|
check_for_needs_mapping = true;
|
|
|
|
|
}
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
else {
|
2025-01-24 13:41:38 +11:00
|
|
|
ASSERT_IS_VALID_MESH_INPUT(&mesh_input);
|
2024-05-20 13:36:58 -04:00
|
|
|
mesh = BKE_mesh_copy_for_eval(mesh_input);
|
2025-01-24 13:41:38 +11:00
|
|
|
ASSERT_IS_VALID_MESH_OUTPUT(mesh);
|
2020-09-23 15:09:53 +10:00
|
|
|
check_for_needs_mapping = true;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-07-17 11:40:08 +02:00
|
|
|
have_non_onlydeform_modifiers_applied = true;
|
2020-09-23 15:09:53 +10:00
|
|
|
|
|
|
|
|
/* determine which data layers are needed by following modifiers */
|
|
|
|
|
CustomData_MeshMasks nextmask = md_datamask->next ? md_datamask->next->mask : final_datamask;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-09-23 15:09:53 +10:00
|
|
|
if (check_for_needs_mapping) {
|
2019-03-28 11:42:53 +01:00
|
|
|
/* Initialize original indices the first time we evaluate a
|
|
|
|
|
* constructive modifier. Modifiers will then do mapping mostly
|
|
|
|
|
* automatic by copying them through CustomData_copy_data along
|
|
|
|
|
* with other data.
|
2010-10-21 01:08:12 +00:00
|
|
|
*
|
2019-03-28 11:42:53 +01:00
|
|
|
* These are created when either requested by evaluation, or if
|
|
|
|
|
* following modifiers requested them. */
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
if (need_mapping ||
|
2024-01-02 18:12:54 +01:00
|
|
|
((nextmask.vmask | nextmask.emask | nextmask.pmask) & CD_MASK_ORIGINDEX))
|
|
|
|
|
{
|
2010-10-21 01:08:12 +00:00
|
|
|
/* calc */
|
2024-05-20 13:36:58 -04:00
|
|
|
CustomData_add_layer(&mesh->vert_data, CD_ORIGINDEX, CD_CONSTRUCT, mesh->verts_num);
|
|
|
|
|
CustomData_add_layer(&mesh->edge_data, CD_ORIGINDEX, CD_CONSTRUCT, mesh->edges_num);
|
|
|
|
|
CustomData_add_layer(&mesh->face_data, CD_ORIGINDEX, CD_CONSTRUCT, mesh->faces_num);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-27 12:07:07 +10:00
|
|
|
/* Not worth parallelizing this,
|
|
|
|
|
* gives less than 0.1% overall speedup in best of best cases... */
|
2023-01-13 17:21:20 -06:00
|
|
|
range_vn_i((int *)CustomData_get_layer_for_write(
|
2024-05-20 13:36:58 -04:00
|
|
|
&mesh->vert_data, CD_ORIGINDEX, mesh->verts_num),
|
|
|
|
|
mesh->verts_num,
|
2020-12-14 13:00:28 +01:00
|
|
|
0);
|
2023-01-13 17:21:20 -06:00
|
|
|
range_vn_i((int *)CustomData_get_layer_for_write(
|
2024-05-20 13:36:58 -04:00
|
|
|
&mesh->edge_data, CD_ORIGINDEX, mesh->edges_num),
|
|
|
|
|
mesh->edges_num,
|
2020-12-14 13:00:28 +01:00
|
|
|
0);
|
2023-01-13 17:21:20 -06:00
|
|
|
range_vn_i((int *)CustomData_get_layer_for_write(
|
2024-05-20 13:36:58 -04:00
|
|
|
&mesh->face_data, CD_ORIGINDEX, mesh->faces_num),
|
|
|
|
|
mesh->faces_num,
|
2020-12-14 13:00:28 +01:00
|
|
|
0);
|
2006-08-28 01:12:36 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
|
2018-05-11 03:53:52 -04:00
|
|
|
/* set the Mesh to only copy needed data */
|
2019-03-28 11:42:53 +01:00
|
|
|
CustomData_MeshMasks mask = md_datamask->mask;
|
2023-02-12 14:37:16 +11:00
|
|
|
/* needMapping check here fixes bug #28112, otherwise it's
|
2016-01-28 00:30:50 -05:00
|
|
|
* possible that it won't be copied */
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
CustomData_MeshMasks_update(&mask, &append_mask);
|
|
|
|
|
if (need_mapping) {
|
|
|
|
|
mask.vmask |= CD_MASK_ORIGINDEX;
|
|
|
|
|
mask.emask |= CD_MASK_ORIGINDEX;
|
|
|
|
|
mask.pmask |= CD_MASK_ORIGINDEX;
|
|
|
|
|
}
|
2024-05-20 13:36:58 -04:00
|
|
|
mesh_set_only_copy(mesh, &mask);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-01-28 00:30:50 -05:00
|
|
|
/* add cloth rest shape key if needed */
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
if (mask.vmask & CD_MASK_CLOTH_ORCO) {
|
2024-05-20 13:36:58 -04:00
|
|
|
add_orco_mesh(ob, nullptr, *mesh, mesh_orco, CD_CLOTH_ORCO);
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2007-12-05 12:40:54 +00:00
|
|
|
/* add an origspace layer if needed */
|
2019-03-28 11:42:53 +01:00
|
|
|
if ((md_datamask->mask.lmask) & CD_MASK_ORIGSPACE_MLOOP) {
|
2024-05-20 13:36:58 -04:00
|
|
|
if (!CustomData_has_layer(&mesh->corner_data, CD_ORIGSPACE_MLOOP)) {
|
|
|
|
|
CustomData_add_layer(
|
|
|
|
|
&mesh->corner_data, CD_ORIGSPACE_MLOOP, CD_SET_DEFAULT, mesh->corners_num);
|
|
|
|
|
mesh_init_origspace(*mesh);
|
2012-02-05 11:30:26 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
|
2025-01-24 13:41:38 +11:00
|
|
|
ASSERT_IS_VALID_MESH_INPUT(mesh);
|
2024-05-20 13:36:58 -04:00
|
|
|
Mesh *mesh_next = modifier_modify_mesh_and_geometry_set(md, mectx, mesh, geometry_set_final);
|
2025-01-24 13:41:38 +11:00
|
|
|
ASSERT_IS_VALID_MESH_OUTPUT(mesh_next);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-28 11:42:53 +01:00
|
|
|
if (mesh_next) {
|
2018-05-11 03:53:52 -04:00
|
|
|
/* if the modifier returned a new mesh, release the old one */
|
2024-05-20 13:36:58 -04:00
|
|
|
if (mesh != mesh_next) {
|
|
|
|
|
BLI_assert(mesh != &mesh_input);
|
|
|
|
|
BKE_id_free(nullptr, mesh);
|
2018-05-11 03:53:52 -04:00
|
|
|
}
|
2024-05-20 13:36:58 -04:00
|
|
|
mesh = mesh_next;
|
2012-04-01 15:02:19 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-11 03:53:52 -04:00
|
|
|
/* create an orco mesh in parallel */
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
if (nextmask.vmask & CD_MASK_ORCO) {
|
2019-03-28 11:42:53 +01:00
|
|
|
if (!mesh_orco) {
|
2020-12-14 13:00:28 +01:00
|
|
|
mesh_orco = create_orco_mesh(ob, mesh_input, nullptr, CD_ORCO);
|
2018-05-11 03:53:52 -04:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
nextmask.vmask &= ~CD_MASK_ORCO;
|
2020-12-14 13:00:28 +01:00
|
|
|
CustomData_MeshMasks temp_cddata_masks = {0};
|
|
|
|
|
temp_cddata_masks.vmask = CD_MASK_ORIGINDEX;
|
|
|
|
|
temp_cddata_masks.emask = CD_MASK_ORIGINDEX;
|
|
|
|
|
temp_cddata_masks.fmask = CD_MASK_ORIGINDEX;
|
|
|
|
|
temp_cddata_masks.pmask = CD_MASK_ORIGINDEX;
|
|
|
|
|
|
2023-07-27 12:04:18 +10:00
|
|
|
if (mti->required_data_mask != nullptr) {
|
|
|
|
|
mti->required_data_mask(md, &temp_cddata_masks);
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
}
|
|
|
|
|
CustomData_MeshMasks_update(&temp_cddata_masks, &nextmask);
|
2019-03-28 11:42:53 +01:00
|
|
|
mesh_set_only_copy(mesh_orco, &temp_cddata_masks);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2025-01-24 13:41:38 +11:00
|
|
|
ASSERT_IS_VALID_MESH_INPUT(mesh_orco);
|
2020-05-08 10:14:02 +02:00
|
|
|
mesh_next = BKE_modifier_modify_mesh(md, &mectx_orco, mesh_orco);
|
2025-01-24 13:41:38 +11:00
|
|
|
ASSERT_IS_VALID_MESH_OUTPUT(mesh_next);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-28 11:42:53 +01:00
|
|
|
if (mesh_next) {
|
2018-05-11 03:53:52 -04:00
|
|
|
/* if the modifier returned a new mesh, release the old one */
|
2019-03-28 11:42:53 +01:00
|
|
|
if (mesh_orco != mesh_next) {
|
2024-05-20 13:11:12 -04:00
|
|
|
BLI_assert(mesh_orco != &mesh_input);
|
2020-12-14 13:00:28 +01:00
|
|
|
BKE_id_free(nullptr, mesh_orco);
|
2018-05-11 03:53:52 -04:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-28 11:42:53 +01:00
|
|
|
mesh_orco = mesh_next;
|
2010-03-30 11:49:07 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
|
2018-05-11 03:53:52 -04:00
|
|
|
/* create cloth orco mesh in parallel */
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
if (nextmask.vmask & CD_MASK_CLOTH_ORCO) {
|
2019-03-28 11:42:53 +01:00
|
|
|
if (!mesh_orco_cloth) {
|
2020-12-14 13:00:28 +01:00
|
|
|
mesh_orco_cloth = create_orco_mesh(ob, mesh_input, nullptr, CD_CLOTH_ORCO);
|
2018-05-16 17:35:54 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
nextmask.vmask &= ~CD_MASK_CLOTH_ORCO;
|
|
|
|
|
nextmask.vmask |= CD_MASK_ORIGINDEX;
|
|
|
|
|
nextmask.emask |= CD_MASK_ORIGINDEX;
|
|
|
|
|
nextmask.pmask |= CD_MASK_ORIGINDEX;
|
2019-03-28 11:42:53 +01:00
|
|
|
mesh_set_only_copy(mesh_orco_cloth, &nextmask);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2025-01-24 13:41:38 +11:00
|
|
|
ASSERT_IS_VALID_MESH_INPUT(mesh_orco_cloth);
|
2020-05-08 10:14:02 +02:00
|
|
|
mesh_next = BKE_modifier_modify_mesh(md, &mectx_orco, mesh_orco_cloth);
|
2025-01-24 13:41:38 +11:00
|
|
|
ASSERT_IS_VALID_MESH_OUTPUT(mesh_next);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-28 11:42:53 +01:00
|
|
|
if (mesh_next) {
|
2018-05-11 03:53:52 -04:00
|
|
|
/* if the modifier returned a new mesh, release the old one */
|
2019-03-28 11:42:53 +01:00
|
|
|
if (mesh_orco_cloth != mesh_next) {
|
2024-05-20 13:11:12 -04:00
|
|
|
BLI_assert(mesh_orco != &mesh_input);
|
2020-12-14 13:00:28 +01:00
|
|
|
BKE_id_free(nullptr, mesh_orco_cloth);
|
2015-07-02 16:20:22 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-28 11:42:53 +01:00
|
|
|
mesh_orco_cloth = mesh_next;
|
2010-03-30 11:49:07 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
|
2024-05-20 13:36:58 -04:00
|
|
|
mesh->runtime->deformed_only = false;
|
2005-07-19 20:14:17 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-01-28 03:52:21 +11:00
|
|
|
if (sculpt_mode && md->type == eModifierType_Multires) {
|
|
|
|
|
multires_applied = true;
|
|
|
|
|
}
|
2005-07-19 20:14:17 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-12-14 13:00:28 +01:00
|
|
|
BLI_linklist_free((LinkNode *)datamasks, nullptr);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
for (md = firstmd; md; md = md->next) {
|
2020-05-08 10:14:02 +02:00
|
|
|
BKE_modifier_free_temporary_data(md);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2024-05-20 13:36:58 -04:00
|
|
|
if (mesh == nullptr) {
|
2023-02-06 14:34:16 -05:00
|
|
|
if (allow_shared_mesh) {
|
2024-05-20 13:36:58 -04:00
|
|
|
mesh = &mesh_input;
|
2019-05-27 11:45:33 +02:00
|
|
|
}
|
|
|
|
|
else {
|
2024-05-20 13:36:58 -04:00
|
|
|
mesh = BKE_mesh_copy_for_eval(mesh_input);
|
2019-05-27 11:45:33 +02:00
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-05-27 11:45:33 +02:00
|
|
|
/* Denotes whether the object which the modifier stack came from owns the mesh or whether the
|
|
|
|
|
* mesh is shared across multiple objects since there are no effective modifiers. */
|
2024-05-20 13:36:58 -04:00
|
|
|
const bool is_own_mesh = (mesh != &mesh_input);
|
2019-05-27 11:45:33 +02:00
|
|
|
|
2019-03-28 11:42:53 +01:00
|
|
|
/* Add orco coordinates to final and deformed mesh if requested. */
|
2019-06-10 15:42:15 +02:00
|
|
|
if (final_datamask.vmask & CD_MASK_ORCO) {
|
2019-05-27 11:45:33 +02:00
|
|
|
/* No need in ORCO layer if the mesh was not deformed or modified: undeformed mesh in this case
|
|
|
|
|
* matches input mesh. */
|
|
|
|
|
if (is_own_mesh) {
|
2024-05-20 13:36:58 -04:00
|
|
|
add_orco_mesh(ob, nullptr, *mesh, mesh_orco, CD_ORCO);
|
2019-05-27 11:45:33 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:39:35 +10:00
|
|
|
if (mesh_deform) {
|
2024-05-20 13:11:12 -04:00
|
|
|
add_orco_mesh(ob, nullptr, *mesh_deform, nullptr, CD_ORCO);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2008-01-09 14:40:25 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-28 11:42:53 +01:00
|
|
|
if (mesh_orco) {
|
2020-12-14 13:00:28 +01:00
|
|
|
BKE_id_free(nullptr, mesh_orco);
|
2014-04-13 12:18:51 +02:00
|
|
|
}
|
2019-03-28 11:42:53 +01:00
|
|
|
if (mesh_orco_cloth) {
|
2020-12-14 13:00:28 +01:00
|
|
|
BKE_id_free(nullptr, mesh_orco_cloth);
|
2012-02-06 06:56:54 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2021-01-14 16:33:52 +01:00
|
|
|
/* Remove temporary data layer only needed for modifier evaluation.
|
|
|
|
|
* Save some memory, and ensure GPU subdivision does not need to deal with this. */
|
2025-02-17 19:44:54 +01:00
|
|
|
CustomData_free_layers(&mesh->vert_data, CD_CLOTH_ORCO);
|
2021-01-14 16:33:52 +01:00
|
|
|
|
2019-03-28 11:42:53 +01:00
|
|
|
/* Compute normals. */
|
2019-05-27 11:45:33 +02:00
|
|
|
if (is_own_mesh) {
|
2024-05-20 13:36:58 -04:00
|
|
|
mesh_calc_finalize(mesh_input, *mesh);
|
2019-05-27 11:45:33 +02:00
|
|
|
}
|
|
|
|
|
else {
|
2024-05-20 13:11:12 -04:00
|
|
|
MeshRuntime *runtime = mesh_input.runtime;
|
2020-12-14 13:00:28 +01:00
|
|
|
if (runtime->mesh_eval == nullptr) {
|
2024-05-20 13:11:12 -04:00
|
|
|
std::lock_guard lock{mesh_input.runtime->eval_mutex};
|
2020-12-14 13:00:28 +01:00
|
|
|
if (runtime->mesh_eval == nullptr) {
|
2022-04-06 20:29:28 +02:00
|
|
|
/* Not yet finalized by any instance, do it now
|
|
|
|
|
* Isolate since computing normals is multithreaded and we are holding a lock. */
|
2024-05-20 12:26:07 -04:00
|
|
|
threading::isolate_task([&] {
|
2024-05-20 13:36:58 -04:00
|
|
|
mesh = BKE_mesh_copy_for_eval(mesh_input);
|
|
|
|
|
mesh_calc_finalize(mesh_input, *mesh);
|
|
|
|
|
runtime->mesh_eval = mesh;
|
2021-06-21 18:44:40 +02:00
|
|
|
});
|
2019-05-27 11:45:33 +02:00
|
|
|
}
|
2022-04-06 20:29:28 +02:00
|
|
|
else {
|
|
|
|
|
/* Already finalized by another instance, reuse. */
|
2024-05-20 13:36:58 -04:00
|
|
|
mesh = runtime->mesh_eval;
|
2022-04-06 20:29:28 +02:00
|
|
|
}
|
2019-05-27 11:45:33 +02:00
|
|
|
}
|
2022-04-06 20:29:28 +02:00
|
|
|
else {
|
|
|
|
|
/* Already finalized by another instance, reuse. */
|
2024-05-20 13:36:58 -04:00
|
|
|
mesh = runtime->mesh_eval;
|
2022-04-06 20:29:28 +02:00
|
|
|
}
|
2019-05-27 11:45:33 +02:00
|
|
|
}
|
|
|
|
|
|
2019-03-28 11:42:53 +01:00
|
|
|
/* Return final mesh */
|
2024-05-20 13:36:58 -04:00
|
|
|
*r_final = mesh;
|
2019-03-28 11:42:53 +01:00
|
|
|
if (r_deform) {
|
|
|
|
|
*r_deform = mesh_deform;
|
2018-05-11 03:53:52 -04:00
|
|
|
}
|
2020-12-15 12:42:10 +01:00
|
|
|
if (r_geometry_set) {
|
|
|
|
|
*r_geometry_set = new GeometrySet(std::move(geometry_set_final));
|
|
|
|
|
}
|
2005-03-27 20:34:18 +00:00
|
|
|
}
|
|
|
|
|
|
2022-02-14 12:05:54 -06:00
|
|
|
bool editbmesh_modifier_is_enabled(const Scene *scene,
|
2020-10-26 17:07:58 +11:00
|
|
|
const Object *ob,
|
|
|
|
|
ModifierData *md,
|
|
|
|
|
bool has_prev_mesh)
|
2007-07-28 21:04:30 +00:00
|
|
|
{
|
2020-12-14 13:00:28 +01:00
|
|
|
const ModifierTypeInfo *mti = BKE_modifier_get_info((ModifierType)md->type);
|
2015-07-02 16:20:22 +10:00
|
|
|
const int required_mode = eModifierMode_Realtime | eModifierMode_Editmode;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-05-08 10:14:02 +02:00
|
|
|
if (!BKE_modifier_is_enabled(scene, md, required_mode)) {
|
2015-07-02 16:20:22 +10:00
|
|
|
return false;
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-10-09 15:04:51 +11:00
|
|
|
if ((mti->flags & eModifierTypeFlag_RequiresOriginalData) && has_prev_mesh) {
|
2020-10-26 17:07:58 +11:00
|
|
|
BKE_modifier_set_error(ob, md, "Modifier requires original data, bad stack position");
|
2014-12-01 17:11:18 +01:00
|
|
|
return false;
|
2007-07-28 21:04:30 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-12-01 17:11:18 +01:00
|
|
|
return true;
|
2007-07-28 21:04:30 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-08-22 03:51:53 +02:00
|
|
|
static MutableSpan<float3> mesh_wrapper_vert_coords_ensure_for_write(Mesh *mesh)
|
2023-07-07 13:07:15 +02:00
|
|
|
{
|
|
|
|
|
switch (mesh->runtime->wrapper_type) {
|
|
|
|
|
case ME_WRAPPER_TYPE_BMESH:
|
2024-03-28 18:25:24 -04:00
|
|
|
if (mesh->runtime->edit_data->vert_positions.is_empty()) {
|
2024-03-28 21:43:32 -04:00
|
|
|
mesh->runtime->edit_data->vert_positions = BM_mesh_vert_coords_alloc(
|
|
|
|
|
mesh->runtime->edit_mesh->bm);
|
2023-07-07 13:07:15 +02:00
|
|
|
}
|
2024-03-28 18:25:24 -04:00
|
|
|
return mesh->runtime->edit_data->vert_positions;
|
2023-07-07 13:07:15 +02:00
|
|
|
case ME_WRAPPER_TYPE_MDATA:
|
|
|
|
|
case ME_WRAPPER_TYPE_SUBD:
|
2023-07-10 19:49:54 +02:00
|
|
|
return mesh->vert_positions_for_write();
|
2023-07-07 13:07:15 +02:00
|
|
|
}
|
2023-07-10 19:49:54 +02:00
|
|
|
BLI_assert_unreachable();
|
|
|
|
|
return {};
|
2023-07-07 13:07:15 +02:00
|
|
|
}
|
|
|
|
|
|
2024-05-20 13:11:12 -04:00
|
|
|
static void editbmesh_calc_modifiers(Depsgraph &depsgraph,
|
|
|
|
|
const Scene &scene,
|
|
|
|
|
Object &ob,
|
|
|
|
|
const CustomData_MeshMasks &dataMask,
|
2015-07-02 16:20:22 +10:00
|
|
|
/* return args */
|
2019-03-27 19:07:16 +01:00
|
|
|
Mesh **r_cage,
|
2020-12-15 12:42:10 +01:00
|
|
|
Mesh **r_final,
|
|
|
|
|
GeometrySet **r_geometry_set)
|
2013-07-05 00:13:14 +00:00
|
|
|
{
|
2024-05-20 13:11:12 -04:00
|
|
|
Mesh &mesh_input = *static_cast<Mesh *>(ob.data);
|
|
|
|
|
BMEditMesh &em_input = *mesh_input.runtime->edit_mesh;
|
2024-04-18 13:52:20 +02:00
|
|
|
|
2020-12-14 13:00:28 +01:00
|
|
|
Mesh *mesh_cage = nullptr;
|
2020-12-15 12:42:10 +01:00
|
|
|
/* This geometry set contains the non-mesh data that might be generated by modifiers. */
|
|
|
|
|
GeometrySet geometry_set_final;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-28 11:42:53 +01:00
|
|
|
/* Mesh with constructive modifiers but no deformation applied. Tracked
|
|
|
|
|
* along with final mesh if undeformed / orco coordinates are requested
|
|
|
|
|
* for texturing. */
|
2020-12-14 13:00:28 +01:00
|
|
|
Mesh *mesh_orco = nullptr;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-28 11:42:53 +01:00
|
|
|
/* Modifier evaluation modes. */
|
|
|
|
|
const int required_mode = eModifierMode_Realtime | eModifierMode_Editmode;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2024-05-20 13:11:12 -04:00
|
|
|
const bool use_render = (DEG_get_mode(&depsgraph) == DAG_EVAL_RENDER);
|
2019-03-28 11:42:53 +01:00
|
|
|
/* Modifier evaluation contexts for different types of modifiers. */
|
2023-05-26 16:11:54 -04:00
|
|
|
ModifierApplyFlag apply_render = use_render ? MOD_APPLY_RENDER : ModifierApplyFlag(0);
|
2024-05-20 13:11:12 -04:00
|
|
|
const ModifierEvalContext mectx = {&depsgraph, &ob, MOD_APPLY_USECACHE | apply_render};
|
|
|
|
|
const ModifierEvalContext mectx_orco = {&depsgraph, &ob, MOD_APPLY_ORCO};
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-28 11:42:53 +01:00
|
|
|
/* Get effective list of modifiers to execute. Some effects like shape keys
|
|
|
|
|
* are added as virtual modifiers before the user created modifiers. */
|
2023-07-27 12:04:18 +10:00
|
|
|
VirtualModifierData virtual_modifier_data;
|
2024-05-20 13:11:12 -04:00
|
|
|
ModifierData *md = BKE_modifiers_get_virtual_modifierlist(&ob, &virtual_modifier_data);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-28 11:42:53 +01:00
|
|
|
/* Compute accumulated datamasks needed by each modifier. It helps to do
|
|
|
|
|
* this fine grained so that for example vertex groups are preserved up to
|
|
|
|
|
* an armature modifier, but not through a following subsurf modifier where
|
|
|
|
|
* subdividing them is expensive. */
|
2024-05-20 13:11:12 -04:00
|
|
|
CustomData_MeshMasks final_datamask = dataMask;
|
|
|
|
|
CDMaskLink *datamasks = BKE_modifier_calc_data_masks(&scene, md, &final_datamask, required_mode);
|
2019-03-28 11:42:53 +01:00
|
|
|
CDMaskLink *md_datamask = datamasks;
|
|
|
|
|
CustomData_MeshMasks append_mask = CD_MASK_BAREMESH;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2024-05-20 13:36:58 -04:00
|
|
|
Mesh *mesh = BKE_mesh_wrapper_from_editmesh(
|
2024-05-20 13:11:12 -04:00
|
|
|
mesh_input.runtime->edit_mesh, &final_datamask, &mesh_input);
|
2023-07-07 13:07:15 +02:00
|
|
|
|
2024-05-20 13:11:12 -04:00
|
|
|
int cageIndex = BKE_modifiers_get_cage_index(&scene, &ob, nullptr, true);
|
2019-06-10 15:42:15 +02:00
|
|
|
if (r_cage && cageIndex == -1) {
|
2024-05-20 13:36:58 -04:00
|
|
|
mesh_cage = mesh;
|
2019-06-10 15:42:15 +02:00
|
|
|
}
|
|
|
|
|
|
Mesh: Avoid creating incorrect original index layers
Currently, whenever any BMesh is converted to a Mesh (except for edit
mode switching), original index (`CD_ORIGINDEX`) layers are added.
This is incorrect, because many operations just convert some Mesh into
a BMesh and then back, but they shouldn't make any assumption about
where their input mesh came from. It might even come from a primitive
in geometry nodes, where there are no original indices at all.
Conceptually, mesh original indices should be filled by the modifier
stack when first creating the evaluated mesh. So that's where they're
moved in this patch. A separate function now fills the indices with their
default (0,1,2,3...) values. The way the mesh wrapper system defers
the BMesh to Mesh conversion makes this a bit less obvious though.
The old behavior is incorrect, but it's also slower, because three
arrays the size of the mesh's vertices, edges, and faces had to be
allocated and filled during the BMesh to Mesh conversion, which just
ends up putting more pressure on the cache. In the many cases where
original indices aren't used, I measured an **8% speedup** for the
conversion (from 76.5ms to 70.7ms).
Generally there is an assumption that BMesh is "original" and Mesh is
"evaluated". After this patch, that assumption isn't quite as strong,
but it still exists for two reasons. First, original indices are added
whenever converting a BMesh "wrapper" to a Mesh. Second, original
indices are not added to the BMesh at the beginning of evaluation,
which assumes that every BMesh in the viewport is original and doesn't
need the mapping.
Differential Revision: https://developer.blender.org/D14018
2022-02-18 10:51:00 -06:00
|
|
|
/* The mesh from edit mode should not have any original index layers already, since those
|
|
|
|
|
* are added during evaluation when necessary and are redundant on an original mesh. */
|
2024-05-20 13:11:12 -04:00
|
|
|
BLI_assert(CustomData_get_layer(&em_input.bm->pdata, CD_ORIGINDEX) == nullptr &&
|
|
|
|
|
CustomData_get_layer(&em_input.bm->edata, CD_ORIGINDEX) == nullptr &&
|
|
|
|
|
CustomData_get_layer(&em_input.bm->pdata, CD_ORIGINDEX) == nullptr);
|
Mesh: Avoid creating incorrect original index layers
Currently, whenever any BMesh is converted to a Mesh (except for edit
mode switching), original index (`CD_ORIGINDEX`) layers are added.
This is incorrect, because many operations just convert some Mesh into
a BMesh and then back, but they shouldn't make any assumption about
where their input mesh came from. It might even come from a primitive
in geometry nodes, where there are no original indices at all.
Conceptually, mesh original indices should be filled by the modifier
stack when first creating the evaluated mesh. So that's where they're
moved in this patch. A separate function now fills the indices with their
default (0,1,2,3...) values. The way the mesh wrapper system defers
the BMesh to Mesh conversion makes this a bit less obvious though.
The old behavior is incorrect, but it's also slower, because three
arrays the size of the mesh's vertices, edges, and faces had to be
allocated and filled during the BMesh to Mesh conversion, which just
ends up putting more pressure on the cache. In the many cases where
original indices aren't used, I measured an **8% speedup** for the
conversion (from 76.5ms to 70.7ms).
Generally there is an assumption that BMesh is "original" and Mesh is
"evaluated". After this patch, that assumption isn't quite as strong,
but it still exists for two reasons. First, original indices are added
whenever converting a BMesh "wrapper" to a Mesh. Second, original
indices are not added to the BMesh at the beginning of evaluation,
which assumes that every BMesh in the viewport is original and doesn't
need the mapping.
Differential Revision: https://developer.blender.org/D14018
2022-02-18 10:51:00 -06:00
|
|
|
|
2019-03-28 11:42:53 +01:00
|
|
|
/* Clear errors before evaluation. */
|
2024-05-20 13:11:12 -04:00
|
|
|
BKE_modifiers_clear_errors(&ob);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2024-05-20 13:11:12 -04:00
|
|
|
if (ob.modifier_flag & OB_MODIFIER_FLAG_ADD_REST_POSITION) {
|
2024-05-20 13:36:58 -04:00
|
|
|
BKE_mesh_wrapper_ensure_mdata(mesh);
|
|
|
|
|
set_rest_position(*mesh);
|
2023-04-20 20:18:02 +02:00
|
|
|
}
|
|
|
|
|
|
2023-07-07 13:07:15 +02:00
|
|
|
bool non_deform_modifier_applied = false;
|
2019-03-28 11:42:53 +01:00
|
|
|
for (int i = 0; md; i++, md = md->next, md_datamask = md_datamask->next) {
|
2020-12-14 13:00:28 +01:00
|
|
|
const ModifierTypeInfo *mti = BKE_modifier_get_info((ModifierType)md->type);
|
2024-05-20 13:11:12 -04:00
|
|
|
if (!editbmesh_modifier_is_enabled(&scene, &ob, md, non_deform_modifier_applied)) {
|
- added eModifierTypeFlag_RequiresOriginalData for modifiers that
can only follow deform (for example, they store mesh vertex
indices)
- added ModifierType.foreachObjectLink for iterating over Object
links inside modifier data (used for file load, relinking, etc)
- switched various modifiers_ functions to take object argument
instead of ListBase
- added user editable name field to modifiers
- bug fix, duplicate and make single user didn't relink object
pointers in modifier data
- added modifiers to outliner, needs icon
- added armature, hook, and softbody modifiers (softbody doesn't
do anything atm). added conversion of old hooks to modifiers.
NOTE-THE-FIRST: User name field is not initialized on loading 2.38 files
so if you have saved stuff with a cvs blender you will see blank names.
NOTE-THE-SECOND: Since modifiers aren't evaluated yet for non-Mesh
objects, hooks for lattices and curves are broken. Don't updated if
you actually, say, *use* Blender.
NOTE-THE-THIRD: Old hooks used a quirky weighting system during
deformation which can't be extended to modifiers. On the upside,
I doubt anyone relied on the old quirky system and the new system
makes much more sense. (Although the way falloff works is still
quite stupid I think).
2005-08-10 22:05:52 +00:00
|
|
|
continue;
|
2015-07-02 16:20:22 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2024-05-20 12:26:07 -04:00
|
|
|
ScopedModifierTimer modifier_timer{*md};
|
Modifiers: measure execution time and provide Python access
The goal is to give technical artists the ability to optimize modifier usage
and/or geometry node groups for performance. In the long term, it
would be useful if Blender could provide its own UI to display profiling
information to users. However, right now, there are too many open
design questions making it infeasible to tackle this in the short term.
This commit uses a simpler approach: Instead of adding new ui for
profiling data, it exposes the execution-time of modifiers in the Python
API. This allows technical artists to access the information and to build
their own UI to display the relevant information. In the long term this
will hopefully also help us to integrate a native ui for this in Blender
by observing how users use this information.
Note: The execution time of a modifier highly depends on what other
things the CPU is doing at the same time. For example, in many more
complex files, many objects and therefore modifiers are evaluated at
the same time by multiple threads which makes the measurement
much less reliable. For best results, make sure that only one object
is evaluated at a time (e.g. by changing it in isolation) and that no
other process on the system keeps the CPU busy.
As shown below, the execution time has to be accessed on the
evaluated object, not the original object.
```lang=python
import bpy
depsgraph = bpy.context.view_layer.depsgraph
ob = bpy.context.active_object
ob_eval = ob.evaluated_get(depsgraph)
modifier_eval = ob_eval.modifiers[0]
print(modifier_eval.execution_time, "s")
```
Differential Revision: https://developer.blender.org/D17185
2023-02-06 15:39:59 +01:00
|
|
|
|
2019-06-10 15:42:15 +02:00
|
|
|
/* Add an orco mesh as layer if needed by this modifier. */
|
2023-07-27 12:04:18 +10:00
|
|
|
if (mesh_orco && mti->required_data_mask) {
|
2019-03-28 11:42:53 +01:00
|
|
|
CustomData_MeshMasks mask = {0};
|
2023-07-27 12:04:18 +10:00
|
|
|
mti->required_data_mask(md, &mask);
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
if (mask.vmask & CD_MASK_ORCO) {
|
2024-05-20 13:36:58 -04:00
|
|
|
add_orco_mesh(ob, &em_input, *mesh, mesh_orco, CD_ORCO);
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2018-10-09 15:04:51 +11:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2024-05-20 13:36:58 -04:00
|
|
|
if (mesh == mesh_cage) {
|
2023-07-07 13:07:15 +02:00
|
|
|
/* If the cage mesh has already been assigned, we have passed the cage index in the modifier
|
|
|
|
|
* list. If the cage and final meshes are still the same, duplicate the final mesh so the
|
|
|
|
|
* cage mesh isn't modified anymore. */
|
2024-05-20 13:36:58 -04:00
|
|
|
mesh = BKE_mesh_copy_for_eval(*mesh);
|
2024-03-21 23:18:49 +01:00
|
|
|
if (mesh_cage->runtime->edit_mesh) {
|
2024-05-20 13:36:58 -04:00
|
|
|
mesh->runtime->is_original_bmesh = true;
|
2024-09-05 15:56:39 +10:00
|
|
|
mesh->runtime->deformed_only = mesh_cage->runtime->deformed_only;
|
2024-03-21 21:22:51 +01:00
|
|
|
if (mesh_cage->runtime->edit_data) {
|
2024-05-20 13:36:58 -04:00
|
|
|
mesh->runtime->edit_data = std::make_unique<EditMeshData>(
|
2024-03-21 21:22:51 +01:00
|
|
|
*mesh_cage->runtime->edit_data);
|
2024-03-20 23:16:02 +01:00
|
|
|
}
|
2019-03-18 15:37:46 +01:00
|
|
|
}
|
2023-07-07 13:07:15 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-11-14 10:03:56 +01:00
|
|
|
if (mti->type == ModifierTypeType::OnlyDeform) {
|
2023-07-27 12:04:18 +10:00
|
|
|
if (mti->deform_verts_EM) {
|
2024-05-20 13:36:58 -04:00
|
|
|
BKE_modifier_deform_vertsEM(
|
|
|
|
|
md, &mectx, &em_input, mesh, mesh_wrapper_vert_coords_ensure_for_write(mesh));
|
|
|
|
|
BKE_mesh_wrapper_tag_positions_changed(mesh);
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
else {
|
2024-05-20 13:36:58 -04:00
|
|
|
BKE_mesh_wrapper_ensure_mdata(mesh);
|
|
|
|
|
BKE_modifier_deform_verts(md, &mectx, mesh, mesh->vert_positions_for_write());
|
|
|
|
|
mesh->tag_positions_changed();
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2023-07-07 13:07:15 +02:00
|
|
|
non_deform_modifier_applied = true;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
/* create an orco derivedmesh in parallel */
|
2019-03-28 11:42:53 +01:00
|
|
|
CustomData_MeshMasks mask = md_datamask->mask;
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
if (mask.vmask & CD_MASK_ORCO) {
|
2019-03-28 11:42:53 +01:00
|
|
|
if (!mesh_orco) {
|
2024-05-20 13:11:12 -04:00
|
|
|
mesh_orco = create_orco_mesh(ob, mesh_input, &em_input, CD_ORCO);
|
2018-10-09 15:04:51 +11:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
mask.vmask &= ~CD_MASK_ORCO;
|
|
|
|
|
mask.vmask |= CD_MASK_ORIGINDEX;
|
|
|
|
|
mask.emask |= CD_MASK_ORIGINDEX;
|
|
|
|
|
mask.pmask |= CD_MASK_ORIGINDEX;
|
2019-03-28 11:42:53 +01:00
|
|
|
mesh_set_only_copy(mesh_orco, &mask);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2025-01-24 13:41:38 +11:00
|
|
|
ASSERT_IS_VALID_MESH_INPUT(mesh_orco);
|
2020-05-08 10:14:02 +02:00
|
|
|
Mesh *mesh_next = BKE_modifier_modify_mesh(md, &mectx_orco, mesh_orco);
|
2025-01-24 13:41:38 +11:00
|
|
|
ASSERT_IS_VALID_MESH_OUTPUT(mesh_next);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-28 11:42:53 +01:00
|
|
|
if (mesh_next) {
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
/* if the modifier returned a new dm, release the old one */
|
2019-03-28 11:42:53 +01:00
|
|
|
if (mesh_orco && mesh_orco != mesh_next) {
|
2020-12-14 13:00:28 +01:00
|
|
|
BKE_id_free(nullptr, mesh_orco);
|
2018-10-09 15:04:51 +11:00
|
|
|
}
|
2019-03-28 11:42:53 +01:00
|
|
|
mesh_orco = mesh_next;
|
Merge of first part of changes from the apricot branch, especially
the features that are needed to run the game. Compile tested with
scons, make, but not cmake, that seems to have an issue not related
to these changes. The changes include:
* GLSL support in the viewport and game engine, enable in the game
menu in textured draw mode.
* Synced and merged part of the duplicated blender and gameengine/
gameplayer drawing code.
* Further refactoring of game engine drawing code, especially mesh
storage changed a lot.
* Optimizations in game engine armatures to avoid recomputations.
* A python function to get the framerate estimate in game.
* An option take object color into account in materials.
* An option to restrict shadow casters to a lamp's layers.
* Increase from 10 to 18 texture slots for materials, lamps, word.
An extra texture slot shows up once the last slot is used.
* Memory limit for undo, not enabled by default yet because it
needs the .B.blend to be changed.
* Multiple undo for image painting.
* An offset for dupligroups, so not all objects in a group have to
be at the origin.
2008-09-04 20:51:28 +00:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2006-12-05 17:42:03 +00:00
|
|
|
/* set the DerivedMesh to only copy needed data */
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
CustomData_MeshMasks_update(&mask, &append_mask);
|
2022-03-07 17:25:50 +01:00
|
|
|
/* XXX WHAT? overwrites mask ??? */
|
2019-04-16 17:55:11 +02:00
|
|
|
/* CD_MASK_ORCO may have been cleared above */
|
|
|
|
|
mask = md_datamask->mask;
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
mask.vmask |= CD_MASK_ORIGINDEX;
|
|
|
|
|
mask.emask |= CD_MASK_ORIGINDEX;
|
|
|
|
|
mask.pmask |= CD_MASK_ORIGINDEX;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2024-05-20 13:36:58 -04:00
|
|
|
mesh_set_only_copy(mesh, &mask);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
if (mask.lmask & CD_MASK_ORIGSPACE_MLOOP) {
|
2024-05-20 13:36:58 -04:00
|
|
|
if (!CustomData_has_layer(&mesh->corner_data, CD_ORIGSPACE_MLOOP)) {
|
|
|
|
|
CustomData_add_layer(
|
|
|
|
|
&mesh->corner_data, CD_ORIGSPACE_MLOOP, CD_SET_DEFAULT, mesh->corners_num);
|
|
|
|
|
mesh_init_origspace(*mesh);
|
2012-02-05 11:30:26 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
|
2025-01-24 13:41:38 +11:00
|
|
|
ASSERT_IS_VALID_MESH_INPUT(mesh);
|
2024-05-20 13:36:58 -04:00
|
|
|
Mesh *mesh_next = modifier_modify_mesh_and_geometry_set(md, mectx, mesh, geometry_set_final);
|
2025-01-24 13:41:38 +11:00
|
|
|
ASSERT_IS_VALID_MESH_OUTPUT(mesh_next);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-28 11:42:53 +01:00
|
|
|
if (mesh_next) {
|
2024-05-20 13:36:58 -04:00
|
|
|
if (mesh != mesh_next) {
|
|
|
|
|
BKE_id_free(nullptr, mesh);
|
2018-10-09 15:04:51 +11:00
|
|
|
}
|
2024-05-20 13:36:58 -04:00
|
|
|
mesh = mesh_next;
|
2005-08-03 04:04:05 +00:00
|
|
|
}
|
2024-05-20 13:36:58 -04:00
|
|
|
mesh->runtime->deformed_only = false;
|
2005-08-03 04:04:05 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2015-07-02 16:20:22 +10:00
|
|
|
if (r_cage && i == cageIndex) {
|
2024-05-20 13:36:58 -04:00
|
|
|
mesh_cage = mesh;
|
- added data arguments to deformer modifiers, in case someone wants
to write one that is based on geometry (and not just vertex position)
- added editmode versions of modifier deform/apply calls and flag
to tag modifiers that support editmode
- added isFinalCalc param to applyModifier, basically a switch to let
subsurf know if it is calc'ng orco or not (so it can deal with cache
appropriately). This is kinda hacky and perhaps I can come up with
a better solution (its also a waste to do a complete subdivide just
to get vertex locations).
- changed ccgsubsurf to not preallocate hash's to be approximately correct
size... this was probably not a big performance savings but means that
the order of faces returned by the iterator can vary after the first
call, this messes up orco calculation so dropped for time being.
- minor bug fix, meshes with only key didn't get vertex normals correctly
calc'd
- updated editmesh derivedmesh to support auxiliary locations
- changed mesh_calc_modifiers to alloc deformVerts on demand
- added editmesh_calc_modifiers for calculating editmesh cage and final
derivedmesh's
- bug fix, update shadedisplist to always calc colors (even if totvert==0)
- changed load_editMesh and make_edge to build me->medge even if totedge==0
(incremental subsurf checks this)
todo: add drawFacesTex for ccgderivedmesh
So, modifiers in editmode are back (which means auto-mirror
in edit mode works now) although still not finished. Currently
no cage is computed, the cage is always the base mesh (in
other words, Optimal edge style editing is off), and the final
mesh currently includes all modifiers that work in edit mode
(including lattice and curve). At some point there will be toggles
for which modifiers affect the final/cage editmode derivedmesh's.
Also, very nice new feature is that incremental subsurf in object
mode returns a ccgderivedmesh object instead of copying to a new
displistmesh. This can make a *huge* speed difference, and is very
nice for working with deformed armatures (esp. with only small
per frame changes).
2005-07-22 07:37:15 +00:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2020-12-14 13:00:28 +01:00
|
|
|
BLI_linklist_free((LinkNode *)datamasks, nullptr);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-28 11:42:53 +01:00
|
|
|
/* Add orco coordinates to final and deformed mesh if requested. */
|
2019-06-10 15:42:15 +02:00
|
|
|
if (final_datamask.vmask & CD_MASK_ORCO) {
|
2023-02-09 11:30:25 +11:00
|
|
|
/* FIXME(@ideasman42): avoid the need to convert to mesh data just to add an orco layer. */
|
2024-05-20 13:36:58 -04:00
|
|
|
BKE_mesh_wrapper_ensure_mdata(mesh);
|
2020-05-25 20:16:42 +10:00
|
|
|
|
2024-05-20 13:36:58 -04:00
|
|
|
add_orco_mesh(ob, &em_input, *mesh, mesh_orco, CD_ORCO);
|
2012-02-28 10:22:21 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-28 11:42:53 +01:00
|
|
|
if (mesh_orco) {
|
2020-12-14 13:00:28 +01:00
|
|
|
BKE_id_free(nullptr, mesh_orco);
|
2014-04-13 12:18:51 +02:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-28 11:42:53 +01:00
|
|
|
/* Return final mesh. */
|
2024-05-20 13:36:58 -04:00
|
|
|
*r_final = mesh;
|
2019-03-28 11:42:53 +01:00
|
|
|
if (r_cage) {
|
|
|
|
|
*r_cage = mesh_cage;
|
2018-10-09 15:04:51 +11:00
|
|
|
}
|
2020-12-15 12:42:10 +01:00
|
|
|
if (r_geometry_set) {
|
|
|
|
|
*r_geometry_set = new GeometrySet(std::move(geometry_set_final));
|
|
|
|
|
}
|
- added data arguments to deformer modifiers, in case someone wants
to write one that is based on geometry (and not just vertex position)
- added editmode versions of modifier deform/apply calls and flag
to tag modifiers that support editmode
- added isFinalCalc param to applyModifier, basically a switch to let
subsurf know if it is calc'ng orco or not (so it can deal with cache
appropriately). This is kinda hacky and perhaps I can come up with
a better solution (its also a waste to do a complete subdivide just
to get vertex locations).
- changed ccgsubsurf to not preallocate hash's to be approximately correct
size... this was probably not a big performance savings but means that
the order of faces returned by the iterator can vary after the first
call, this messes up orco calculation so dropped for time being.
- minor bug fix, meshes with only key didn't get vertex normals correctly
calc'd
- updated editmesh derivedmesh to support auxiliary locations
- changed mesh_calc_modifiers to alloc deformVerts on demand
- added editmesh_calc_modifiers for calculating editmesh cage and final
derivedmesh's
- bug fix, update shadedisplist to always calc colors (even if totvert==0)
- changed load_editMesh and make_edge to build me->medge even if totedge==0
(incremental subsurf checks this)
todo: add drawFacesTex for ccgderivedmesh
So, modifiers in editmode are back (which means auto-mirror
in edit mode works now) although still not finished. Currently
no cage is computed, the cage is always the base mesh (in
other words, Optimal edge style editing is off), and the final
mesh currently includes all modifiers that work in edit mode
(including lattice and curve). At some point there will be toggles
for which modifiers affect the final/cage editmode derivedmesh's.
Also, very nice new feature is that incremental subsurf in object
mode returns a ccgderivedmesh object instead of copying to a new
displistmesh. This can make a *huge* speed difference, and is very
nice for working with deformed armatures (esp. with only small
per frame changes).
2005-07-22 07:37:15 +00:00
|
|
|
}
|
|
|
|
|
|
2024-05-20 13:11:12 -04:00
|
|
|
static void mesh_build_extra_data(const Depsgraph &depsgraph,
|
|
|
|
|
const Object &ob,
|
|
|
|
|
const Mesh &mesh_eval)
|
Shrinkwrap: new mode that projects along the target normal.
The Nearest Surface Point shrink method, while fast, is neither
smooth nor continuous: as the source point moves, the projected
point can both stop and jump. This causes distortions in the
deformation of the shrinkwrap modifier, and the motion of an
animated object with a shrinkwrap constraint.
This patch implements a new mode, which, instead of using the simple
nearest point search, iteratively solves an equation for each triangle
to find a point which has its interpolated normal point to or from the
original vertex. Non-manifold boundary edges are treated as infinitely
thin cylinders that cast normals in all perpendicular directions.
Since this is useful for the constraint, and having multiple
objects with constraints targeting the same guide mesh is a quite
reasonable use case, rather than calculating the mesh boundary edge
data over and over again, it is precomputed and cached in the mesh.
Reviewers: mont29
Differential Revision: https://developer.blender.org/D3836
2018-11-06 21:04:53 +03:00
|
|
|
{
|
2024-05-20 13:11:12 -04:00
|
|
|
uint32_t eval_flags = DEG_get_eval_flags_for_id(&depsgraph, &ob.id);
|
Shrinkwrap: new mode that projects along the target normal.
The Nearest Surface Point shrink method, while fast, is neither
smooth nor continuous: as the source point moves, the projected
point can both stop and jump. This causes distortions in the
deformation of the shrinkwrap modifier, and the motion of an
animated object with a shrinkwrap constraint.
This patch implements a new mode, which, instead of using the simple
nearest point search, iteratively solves an equation for each triangle
to find a point which has its interpolated normal point to or from the
original vertex. Non-manifold boundary edges are treated as infinitely
thin cylinders that cast normals in all perpendicular directions.
Since this is useful for the constraint, and having multiple
objects with constraints targeting the same guide mesh is a quite
reasonable use case, rather than calculating the mesh boundary edge
data over and over again, it is precomputed and cached in the mesh.
Reviewers: mont29
Differential Revision: https://developer.blender.org/D3836
2018-11-06 21:04:53 +03:00
|
|
|
|
|
|
|
|
if (eval_flags & DAG_EVAL_NEED_SHRINKWRAP_BOUNDARY) {
|
2024-05-20 13:11:12 -04:00
|
|
|
shrinkwrap::boundary_cache_ensure(mesh_eval);
|
Shrinkwrap: new mode that projects along the target normal.
The Nearest Surface Point shrink method, while fast, is neither
smooth nor continuous: as the source point moves, the projected
point can both stop and jump. This causes distortions in the
deformation of the shrinkwrap modifier, and the motion of an
animated object with a shrinkwrap constraint.
This patch implements a new mode, which, instead of using the simple
nearest point search, iteratively solves an equation for each triangle
to find a point which has its interpolated normal point to or from the
original vertex. Non-manifold boundary edges are treated as infinitely
thin cylinders that cast normals in all perpendicular directions.
Since this is useful for the constraint, and having multiple
objects with constraints targeting the same guide mesh is a quite
reasonable use case, rather than calculating the mesh boundary edge
data over and over again, it is precomputed and cached in the mesh.
Reviewers: mont29
Differential Revision: https://developer.blender.org/D3836
2018-11-06 21:04:53 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-20 13:11:12 -04:00
|
|
|
static void mesh_build_data(Depsgraph &depsgraph,
|
|
|
|
|
const Scene &scene,
|
|
|
|
|
Object &ob,
|
|
|
|
|
const CustomData_MeshMasks &dataMask,
|
2019-03-27 19:07:16 +01:00
|
|
|
const bool need_mapping)
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
{
|
2022-04-21 12:02:13 -05:00
|
|
|
#if 0 /* XXX This is already taken care of in #mesh_calc_modifiers... */
|
2018-12-01 12:12:18 +03:00
|
|
|
if (need_mapping) {
|
|
|
|
|
/* Also add the flag so that it is recorded in lastDataMask. */
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
dataMask->vmask |= CD_MASK_ORIGINDEX;
|
|
|
|
|
dataMask->emask |= CD_MASK_ORIGINDEX;
|
|
|
|
|
dataMask->pmask |= CD_MASK_ORIGINDEX;
|
2018-12-01 12:12:18 +03:00
|
|
|
}
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
#endif
|
2018-12-01 12:12:18 +03:00
|
|
|
|
2020-12-14 13:00:28 +01:00
|
|
|
Mesh *mesh_eval = nullptr, *mesh_deform_eval = nullptr;
|
2020-12-15 12:42:10 +01:00
|
|
|
GeometrySet *geometry_set_eval = nullptr;
|
2018-05-30 12:56:20 +02:00
|
|
|
mesh_calc_modifiers(depsgraph,
|
2019-03-27 19:07:16 +01:00
|
|
|
scene,
|
|
|
|
|
ob,
|
2021-07-01 10:08:24 +10:00
|
|
|
true,
|
2019-03-27 19:07:16 +01:00
|
|
|
need_mapping,
|
|
|
|
|
dataMask,
|
|
|
|
|
true,
|
2019-05-31 10:05:56 +02:00
|
|
|
true,
|
2020-02-27 11:23:15 +01:00
|
|
|
&mesh_deform_eval,
|
2020-12-15 12:42:10 +01:00
|
|
|
&mesh_eval,
|
|
|
|
|
&geometry_set_eval);
|
2018-11-25 18:39:57 +01:00
|
|
|
|
2020-02-27 11:23:15 +01:00
|
|
|
/* The modifier stack evaluation is storing result in mesh->runtime.mesh_eval, but this result
|
|
|
|
|
* is not guaranteed to be owned by object.
|
|
|
|
|
*
|
|
|
|
|
* Check ownership now, since later on we can not go to a mesh owned by someone else via
|
|
|
|
|
* object's runtime: this could cause access freed data on depsgraph destruction (mesh who owns
|
|
|
|
|
* the final result might be freed prior to object). */
|
2024-05-20 13:11:12 -04:00
|
|
|
Mesh *mesh = (Mesh *)ob.data;
|
2022-10-12 20:55:26 -05:00
|
|
|
const bool is_mesh_eval_owned = (mesh_eval != mesh->runtime->mesh_eval);
|
2024-05-20 13:11:12 -04:00
|
|
|
BKE_object_eval_assign_data(&ob, &mesh_eval->id, is_mesh_eval_owned);
|
2020-02-27 11:23:15 +01:00
|
|
|
|
2021-11-05 11:51:34 -05:00
|
|
|
/* Add the final mesh as a non-owning component to the geometry set. */
|
2020-12-15 12:42:10 +01:00
|
|
|
MeshComponent &mesh_component = geometry_set_eval->get_component_for_write<MeshComponent>();
|
2021-11-05 11:51:34 -05:00
|
|
|
mesh_component.replace(mesh_eval, GeometryOwnershipType::Editable);
|
2024-05-20 13:11:12 -04:00
|
|
|
ob.runtime->geometry_set_eval = geometry_set_eval;
|
2020-12-15 12:42:10 +01:00
|
|
|
|
2024-05-20 13:11:12 -04:00
|
|
|
ob.runtime->mesh_deform_eval = mesh_deform_eval;
|
|
|
|
|
ob.runtime->last_data_mask = dataMask;
|
|
|
|
|
ob.runtime->last_need_mapping = need_mapping;
|
2012-03-14 06:30:55 +00:00
|
|
|
|
2020-08-13 12:53:21 +02:00
|
|
|
/* Make sure that drivers can target shapekey properties.
|
|
|
|
|
* Note that this causes a potential inconsistency, as the shapekey may have a
|
|
|
|
|
* different topology than the evaluated mesh. */
|
2025-05-02 15:08:29 +02:00
|
|
|
BLI_assert(mesh->key == nullptr || DEG_is_evaluated(mesh->key));
|
2020-08-13 12:53:21 +02:00
|
|
|
mesh_eval->key = mesh->key;
|
|
|
|
|
|
2024-05-20 13:11:12 -04:00
|
|
|
if ((ob.mode & OB_MODE_ALL_SCULPT) && ob.sculpt) {
|
|
|
|
|
if (DEG_is_active(&depsgraph)) {
|
|
|
|
|
BKE_sculpt_update_object_after_eval(&depsgraph, &ob);
|
2019-05-31 12:50:15 +02:00
|
|
|
}
|
2012-03-14 06:30:55 +00:00
|
|
|
}
|
2013-05-30 17:36:43 +00:00
|
|
|
|
2024-05-20 13:11:12 -04:00
|
|
|
mesh_build_extra_data(depsgraph, ob, *mesh_eval);
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
}
|
|
|
|
|
|
2024-05-20 13:11:12 -04:00
|
|
|
static void editbmesh_build_data(Depsgraph &depsgraph,
|
|
|
|
|
const Scene &scene,
|
|
|
|
|
Object &obedit,
|
|
|
|
|
CustomData_MeshMasks &dataMask)
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
{
|
2024-05-20 13:11:12 -04:00
|
|
|
Mesh *mesh = static_cast<Mesh *>(obedit.data);
|
2018-10-09 15:04:51 +11:00
|
|
|
Mesh *me_cage;
|
|
|
|
|
Mesh *me_final;
|
2020-12-15 12:42:10 +01:00
|
|
|
GeometrySet *non_mesh_components;
|
2018-10-09 15:04:51 +11:00
|
|
|
|
2020-12-15 12:42:10 +01:00
|
|
|
editbmesh_calc_modifiers(
|
2024-04-18 13:52:20 +02:00
|
|
|
depsgraph, scene, obedit, dataMask, &me_cage, &me_final, &non_mesh_components);
|
2018-10-09 15:04:51 +11:00
|
|
|
|
2022-01-11 15:42:07 +01:00
|
|
|
/* Object has edit_mesh but is not in edit mode (object shares mesh datablock with another object
|
|
|
|
|
* with is in edit mode).
|
|
|
|
|
* Convert edit mesh to mesh until the draw manager can draw mesh wrapper which is not in the
|
|
|
|
|
* edit mode. */
|
2024-05-20 13:11:12 -04:00
|
|
|
if (!(obedit.mode & OB_MODE_EDIT)) {
|
2022-01-11 15:42:07 +01:00
|
|
|
BKE_mesh_wrapper_ensure_mdata(me_final);
|
|
|
|
|
if (me_final != me_cage) {
|
|
|
|
|
BKE_mesh_wrapper_ensure_mdata(me_cage);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-12 20:55:26 -05:00
|
|
|
const bool is_mesh_eval_owned = (me_final != mesh->runtime->mesh_eval);
|
2024-05-20 13:11:12 -04:00
|
|
|
BKE_object_eval_assign_data(&obedit, &me_final->id, is_mesh_eval_owned);
|
2022-01-11 15:42:07 +01:00
|
|
|
|
2022-11-03 15:48:54 +01:00
|
|
|
/* Make sure that drivers can target shapekey properties.
|
|
|
|
|
* Note that this causes a potential inconsistency, as the shapekey may have a
|
|
|
|
|
* different topology than the evaluated mesh. */
|
2025-05-02 15:08:29 +02:00
|
|
|
BLI_assert(mesh->key == nullptr || DEG_is_evaluated(mesh->key));
|
2022-11-03 15:48:54 +01:00
|
|
|
me_final->key = mesh->key;
|
|
|
|
|
|
2024-05-20 13:11:12 -04:00
|
|
|
obedit.runtime->editmesh_eval_cage = me_cage;
|
2022-01-11 15:42:07 +01:00
|
|
|
|
2024-05-20 13:11:12 -04:00
|
|
|
obedit.runtime->geometry_set_eval = non_mesh_components;
|
2015-07-02 16:20:22 +10:00
|
|
|
|
2024-05-20 13:11:12 -04:00
|
|
|
obedit.runtime->last_data_mask = dataMask;
|
2005-07-19 02:36:21 +00:00
|
|
|
}
|
|
|
|
|
|
2024-05-20 13:11:12 -04:00
|
|
|
static void object_get_datamask(const Depsgraph &depsgraph,
|
|
|
|
|
Object &ob,
|
|
|
|
|
CustomData_MeshMasks &r_mask,
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
bool *r_need_mapping)
|
2013-05-01 14:34:12 +00:00
|
|
|
{
|
2024-05-20 13:11:12 -04:00
|
|
|
Scene *scene = DEG_get_evaluated_scene(&depsgraph);
|
|
|
|
|
ViewLayer *view_layer = DEG_get_evaluated_view_layer(&depsgraph);
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
|
2024-05-20 13:11:12 -04:00
|
|
|
DEG_get_customdata_mask_for_object(&depsgraph, &ob, &r_mask);
|
2015-06-04 17:39:43 +02:00
|
|
|
|
2015-07-02 16:20:22 +10:00
|
|
|
if (r_need_mapping) {
|
|
|
|
|
*r_need_mapping = false;
|
|
|
|
|
}
|
2013-05-01 14:34:12 +00:00
|
|
|
|
2019-05-24 10:48:19 +02:00
|
|
|
/* Must never access original objects when dependency graph is not active: it might be already
|
|
|
|
|
* freed. */
|
2024-05-20 13:11:12 -04:00
|
|
|
if (!DEG_is_active(&depsgraph)) {
|
2019-05-24 10:48:19 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-14 21:33:51 +02:00
|
|
|
BKE_view_layer_synced_ensure(scene, view_layer);
|
|
|
|
|
Object *actob = BKE_view_layer_active_object_get(view_layer);
|
|
|
|
|
if (actob) {
|
2025-04-17 13:09:20 +02:00
|
|
|
actob = DEG_get_original(actob);
|
2022-09-14 21:33:51 +02:00
|
|
|
}
|
2025-04-17 13:09:20 +02:00
|
|
|
if (DEG_get_original(&ob) == actob) {
|
2018-12-01 12:12:18 +03:00
|
|
|
bool editing = BKE_paint_select_face_test(actob);
|
2015-06-04 17:39:43 +02:00
|
|
|
|
|
|
|
|
/* weight paint and face select need original indices because of selection buffer drawing */
|
2015-07-02 16:20:22 +10:00
|
|
|
if (r_need_mapping) {
|
2024-05-20 13:11:12 -04:00
|
|
|
*r_need_mapping = (editing || (ob.mode & (OB_MODE_WEIGHT_PAINT | OB_MODE_VERTEX_PAINT)));
|
2015-07-02 16:20:22 +10:00
|
|
|
}
|
2015-06-04 17:39:43 +02:00
|
|
|
|
2023-11-10 09:24:19 +11:00
|
|
|
/* Check if we need #MTFace & loop-color due to face select or texture paint. */
|
2024-05-20 13:11:12 -04:00
|
|
|
if ((ob.mode & OB_MODE_TEXTURE_PAINT) || editing) {
|
|
|
|
|
r_mask.lmask |= CD_MASK_PROP_FLOAT2 | CD_MASK_PROP_BYTE_COLOR;
|
|
|
|
|
r_mask.fmask |= CD_MASK_MTFACE;
|
2013-05-01 14:34:12 +00:00
|
|
|
}
|
|
|
|
|
|
2024-05-27 12:07:03 +10:00
|
|
|
/* Check if we need loop-color due to vertex paint or weight-paint. */
|
2024-05-20 13:11:12 -04:00
|
|
|
if (ob.mode & OB_MODE_VERTEX_PAINT) {
|
|
|
|
|
r_mask.lmask |= CD_MASK_PROP_BYTE_COLOR;
|
2013-05-01 14:34:12 +00:00
|
|
|
}
|
|
|
|
|
|
2024-05-20 13:11:12 -04:00
|
|
|
if (ob.mode & OB_MODE_WEIGHT_PAINT) {
|
|
|
|
|
r_mask.vmask |= CD_MASK_MDEFORMVERT;
|
2018-10-09 14:21:23 +03:00
|
|
|
}
|
2024-09-30 13:18:36 +10:00
|
|
|
}
|
2018-10-09 14:21:23 +03:00
|
|
|
|
2024-09-30 13:18:36 +10:00
|
|
|
/* Multiple objects can be in edit-mode at once. */
|
|
|
|
|
if (actob && (actob->mode & OB_MODE_EDIT)) {
|
2024-05-20 13:11:12 -04:00
|
|
|
if (ob.mode & OB_MODE_EDIT) {
|
|
|
|
|
r_mask.vmask |= CD_MASK_MVERT_SKIN;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2013-05-01 14:34:12 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-20 13:11:12 -04:00
|
|
|
void mesh_data_update(Depsgraph &depsgraph,
|
|
|
|
|
const Scene &scene,
|
|
|
|
|
Object &ob,
|
|
|
|
|
const CustomData_MeshMasks &dataMask)
|
2005-07-19 02:36:21 +00:00
|
|
|
{
|
2024-05-20 13:11:12 -04:00
|
|
|
BLI_assert(ob.type == OB_MESH);
|
2022-01-11 15:42:07 +01:00
|
|
|
|
|
|
|
|
/* Evaluated meshes aren't supposed to be created on original instances. If you do,
|
2023-02-12 14:37:16 +11:00
|
|
|
* they aren't cleaned up properly on mode switch, causing crashes, e.g #58150. */
|
2024-08-07 12:12:17 +02:00
|
|
|
BLI_assert(ob.id.tag & ID_TAG_COPIED_ON_EVAL);
|
2022-01-11 15:42:07 +01:00
|
|
|
|
2024-05-20 13:11:12 -04:00
|
|
|
BKE_object_free_derived_caches(&ob);
|
|
|
|
|
if (DEG_is_active(&depsgraph)) {
|
|
|
|
|
BKE_sculpt_update_object_before_eval(&ob);
|
2022-01-11 15:42:07 +01:00
|
|
|
}
|
|
|
|
|
|
2024-05-20 13:11:12 -04:00
|
|
|
/* NOTE: Access the `edit_mesh` after freeing the derived caches, so that `ob.data` is restored
|
2022-01-11 15:42:07 +01:00
|
|
|
* to the pre-evaluated state. This is because the evaluated state is not necessarily sharing the
|
|
|
|
|
* `edit_mesh` pointer with the input. For example, if the object is first evaluated in the
|
|
|
|
|
* object mode, and then user in another scene moves object to edit mode. */
|
2024-05-20 13:11:12 -04:00
|
|
|
Mesh *mesh = static_cast<Mesh *>(ob.data);
|
2022-01-11 15:42:07 +01:00
|
|
|
|
2015-07-02 16:20:22 +10:00
|
|
|
bool need_mapping;
|
2024-05-20 13:11:12 -04:00
|
|
|
CustomData_MeshMasks cddata_masks = dataMask;
|
|
|
|
|
object_get_datamask(depsgraph, ob, cddata_masks, &need_mapping);
|
2013-05-01 14:34:12 +00:00
|
|
|
|
2024-04-18 13:52:20 +02:00
|
|
|
if (mesh->runtime->edit_mesh) {
|
2024-05-20 13:11:12 -04:00
|
|
|
editbmesh_build_data(depsgraph, scene, ob, cddata_masks);
|
2012-03-24 06:18:31 +00:00
|
|
|
}
|
|
|
|
|
else {
|
2024-05-20 13:11:12 -04:00
|
|
|
mesh_build_data(depsgraph, scene, ob, cddata_masks, need_mapping);
|
- shuffled editmesh derived function name/function
- added ModifierTypeInfo.freeData function
- added modifier_{new,free] utility function
- added ccgSubSurf_getUseAgeCounts to query info
- removed subsurf modifier faking (ME_SUBSURF flag is no
longer valid). subsurf modifier gets converted on file load
although there is obscure linked mesh situation where this
can go wrong, will fix shortly. this also means that some
places in the code that test/copy subsurf settings are broken
for the time being.
- shuffled modifier calculation to be simpler. note that
all modifiers are currently disabled in editmode (including
subsurf). don't worry, will return shortly.
- bug fix, build modifier didn't randomize meshes with only verts
- cleaned up subsurf_ccg and adapted for future editmode modifier
work
- added editmesh.derived{Cage,Final}, not used yet
- added SubsurfModifierData.{mCache,emCache}, will be used to cache
subsurf instead of caching in derivedmesh itself
- removed old subsurf buttons
- added do_modifiers_buttons to handle modifier events
- removed count_object counting of modifier (subsurfed) objects...
this would be nice to add back at some point but requires care.
probably requires rewrite of counting system.
New feature: Incremental Subsurf in Object Mode
The previous release introduce incremental subsurf calculation during
editmode but it was not turned on during object mode. In general it
does not make sense to have it always enabled during object mode because
it requires caching a fair amount of information about the mesh which
is a waste of memory unless the mesh is often recalculated.
However, for mesh's that have subsurfed armatures for example, or that
have other modifiers so that the mesh is essentially changing on every
frame, it makes a lot of sense to keep the subsurf'd object around and
that is what the new incremental subsurf modifier toggle is for. The
intent is that the user will enable this option for (a) a mesh that is
currently under active editing or (b) a mesh that is heavily updated
in the scene, such as a character.
I will try to write more about this feature for release, because it
has advantages and disadvantages that are not immediately obvious (the
first user reaction will be to turn it on for ever object, which is
probably not correct).
2005-07-21 20:30:33 +00:00
|
|
|
}
|
2005-07-19 02:36:21 +00:00
|
|
|
}
|
|
|
|
|
|
2023-06-03 08:36:28 +10:00
|
|
|
Mesh *mesh_get_eval_deform(Depsgraph *depsgraph,
|
2022-02-14 12:05:54 -06:00
|
|
|
const Scene *scene,
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
Object *ob,
|
|
|
|
|
const CustomData_MeshMasks *dataMask)
|
2018-06-01 12:34:50 +02:00
|
|
|
{
|
2024-04-18 13:52:20 +02:00
|
|
|
BMEditMesh *em = ((Mesh *)ob->data)->runtime->edit_mesh.get();
|
2022-01-11 15:42:07 +01:00
|
|
|
if (em != nullptr) {
|
|
|
|
|
/* There is no such a concept as deformed mesh in edit mode.
|
|
|
|
|
* Explicitly disallow this request so that the evaluated result is not modified with evaluated
|
|
|
|
|
* result from the wrong mode. */
|
|
|
|
|
BLI_assert_msg(0, "Request of derformed mesh of object which is in edit mode");
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-03 15:22:19 +03:00
|
|
|
/* This function isn't thread-safe and can't be used during evaluation. */
|
2019-10-10 11:03:58 +02:00
|
|
|
BLI_assert(DEG_is_evaluating(depsgraph) == false);
|
2018-12-03 15:22:19 +03:00
|
|
|
|
|
|
|
|
/* Evaluated meshes aren't supposed to be created on original instances. If you do,
|
2023-02-12 14:37:16 +11:00
|
|
|
* they aren't cleaned up properly on mode switch, causing crashes, e.g #58150. */
|
2024-08-07 12:12:17 +02:00
|
|
|
BLI_assert(ob->id.tag & ID_TAG_COPIED_ON_EVAL);
|
2018-12-03 15:22:19 +03:00
|
|
|
|
2024-05-27 12:08:22 +10:00
|
|
|
/* If there's no evaluated mesh or the last data mask used doesn't include
|
|
|
|
|
* the data we need, rebuild the evaluated mesh. */
|
2018-06-01 12:34:50 +02:00
|
|
|
bool need_mapping;
|
|
|
|
|
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
CustomData_MeshMasks cddata_masks = *dataMask;
|
2024-05-20 13:11:12 -04:00
|
|
|
object_get_datamask(*depsgraph, *ob, cddata_masks, &need_mapping);
|
2018-06-01 12:34:50 +02:00
|
|
|
|
2023-11-15 18:46:07 +01:00
|
|
|
if (!ob->runtime->mesh_deform_eval ||
|
|
|
|
|
!CustomData_MeshMasks_are_matching(&(ob->runtime->last_data_mask), &cddata_masks) ||
|
|
|
|
|
(need_mapping && !ob->runtime->last_need_mapping))
|
2018-12-03 18:09:45 +03:00
|
|
|
{
|
2024-09-30 13:32:52 +10:00
|
|
|
/* FIXME: this block may leak memory (& assert) because it runs #BKE_object_eval_assign_data
|
|
|
|
|
* intended only to run during depsgraph-evaluation that overwrites the evaluated mesh
|
|
|
|
|
* without freeing beforehand, see: !128228. */
|
2023-11-15 18:46:07 +01:00
|
|
|
CustomData_MeshMasks_update(&cddata_masks, &ob->runtime->last_data_mask);
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
mesh_build_data(
|
2024-05-20 13:11:12 -04:00
|
|
|
*depsgraph, *scene, *ob, cddata_masks, need_mapping || ob->runtime->last_need_mapping);
|
2018-06-01 12:34:50 +02:00
|
|
|
}
|
|
|
|
|
|
2023-11-15 18:46:07 +01:00
|
|
|
return ob->runtime->mesh_deform_eval;
|
2018-06-01 12:34:50 +02:00
|
|
|
}
|
|
|
|
|
|
2020-08-18 12:58:48 +02:00
|
|
|
Mesh *mesh_create_eval_final(Depsgraph *depsgraph,
|
2022-02-14 12:05:54 -06:00
|
|
|
const Scene *scene,
|
2020-08-20 16:09:48 +10:00
|
|
|
Object *ob,
|
|
|
|
|
const CustomData_MeshMasks *dataMask)
|
2018-10-12 18:05:26 +11:00
|
|
|
{
|
2021-12-02 11:20:22 -05:00
|
|
|
Mesh *result;
|
2020-12-15 12:42:10 +01:00
|
|
|
mesh_calc_modifiers(
|
2024-05-20 13:11:12 -04:00
|
|
|
*depsgraph, *scene, *ob, true, false, *dataMask, false, false, nullptr, &result, nullptr);
|
2021-12-02 11:20:22 -05:00
|
|
|
return result;
|
2018-10-12 18:05:26 +11:00
|
|
|
}
|
2008-07-28 11:01:34 +00:00
|
|
|
|
2018-12-04 20:47:13 -02:00
|
|
|
Mesh *mesh_create_eval_no_deform(Depsgraph *depsgraph,
|
2022-02-14 12:05:54 -06:00
|
|
|
const Scene *scene,
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
Object *ob,
|
2019-03-27 19:07:16 +01:00
|
|
|
const CustomData_MeshMasks *dataMask)
|
2005-07-17 01:18:59 +00:00
|
|
|
{
|
2021-12-02 11:20:22 -05:00
|
|
|
Mesh *result;
|
2020-12-15 12:42:10 +01:00
|
|
|
mesh_calc_modifiers(
|
2024-05-20 13:11:12 -04:00
|
|
|
*depsgraph, *scene, *ob, false, false, *dataMask, false, false, nullptr, &result, nullptr);
|
2021-12-02 11:20:22 -05:00
|
|
|
return result;
|
2018-12-04 20:47:13 -02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Mesh *mesh_create_eval_no_deform_render(Depsgraph *depsgraph,
|
2022-02-14 12:05:54 -06:00
|
|
|
const Scene *scene,
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
Object *ob,
|
2019-03-27 19:07:16 +01:00
|
|
|
const CustomData_MeshMasks *dataMask)
|
2018-12-04 20:47:13 -02:00
|
|
|
{
|
2021-12-02 11:20:22 -05:00
|
|
|
Mesh *result;
|
2020-12-15 12:42:10 +01:00
|
|
|
mesh_calc_modifiers(
|
2024-05-20 13:11:12 -04:00
|
|
|
*depsgraph, *scene, *ob, false, false, *dataMask, false, false, nullptr, &result, nullptr);
|
2021-12-02 11:20:22 -05:00
|
|
|
return result;
|
2005-07-19 00:21:01 +00:00
|
|
|
}
|
2005-04-04 03:38:21 +00:00
|
|
|
|
2023-06-03 08:36:28 +10:00
|
|
|
Mesh *editbmesh_get_eval_cage(Depsgraph *depsgraph,
|
2022-02-14 12:05:54 -06:00
|
|
|
const Scene *scene,
|
2018-04-06 12:07:27 +02:00
|
|
|
Object *obedit,
|
2024-04-18 13:52:20 +02:00
|
|
|
BMEditMesh * /*em*/,
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
const CustomData_MeshMasks *dataMask)
|
2005-03-28 05:58:43 +00:00
|
|
|
{
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
CustomData_MeshMasks cddata_masks = *dataMask;
|
|
|
|
|
|
2024-05-27 12:08:22 +10:00
|
|
|
/* If there's no evaluated mesh or the last data mask used doesn't include
|
|
|
|
|
* the data we need, rebuild the evaluated mesh. */
|
2024-05-20 13:11:12 -04:00
|
|
|
object_get_datamask(*depsgraph, *obedit, cddata_masks, nullptr);
|
2013-05-01 14:34:12 +00:00
|
|
|
|
2023-11-15 18:46:07 +01:00
|
|
|
if (!obedit->runtime->editmesh_eval_cage ||
|
|
|
|
|
!CustomData_MeshMasks_are_matching(&(obedit->runtime->last_data_mask), &cddata_masks))
|
2022-01-11 15:42:07 +01:00
|
|
|
{
|
2024-09-30 13:32:52 +10:00
|
|
|
/* FIXME: this block may leak memory (& assert) because it runs #BKE_object_eval_assign_data
|
|
|
|
|
* intended only to run during depsgraph-evaluation that overwrites the evaluated mesh
|
|
|
|
|
* without freeing beforehand, see: !128228. */
|
2024-05-20 13:11:12 -04:00
|
|
|
editbmesh_build_data(*depsgraph, *scene, *obedit, cddata_masks);
|
2012-04-28 06:31:57 +00:00
|
|
|
}
|
2005-03-28 05:58:43 +00:00
|
|
|
|
2023-11-15 18:46:07 +01:00
|
|
|
return obedit->runtime->editmesh_eval_cage;
|
2005-03-28 05:58:43 +00:00
|
|
|
}
|
2005-08-06 20:44:59 +00:00
|
|
|
|
2023-06-03 08:36:28 +10:00
|
|
|
Mesh *editbmesh_get_eval_cage_from_orig(Depsgraph *depsgraph,
|
2022-02-14 12:05:54 -06:00
|
|
|
const Scene *scene,
|
2018-12-06 09:38:08 +11:00
|
|
|
Object *obedit,
|
Refactor CDData masks, to have one mask per mesh elem type.
We already have different storages for cddata of verts, edges etc.,
'simply' do the same for the mask flags we use all around Blender code
to request some data, or limit some operation to some layers, etc.
Reason we need this is that some cddata types (like Normals) are
actually shared between verts/polys/loops, and we don’t want to generate
clnors everytime we request vnors!
As a side note, this also does final fix to T59338, which was the
trigger for this patch (need to request computed loop normals for
another mesh than evaluated one).
Reviewers: brecht, campbellbarton, sergey
Differential Revision: https://developer.blender.org/D4407
2019-03-07 11:13:40 +01:00
|
|
|
const CustomData_MeshMasks *dataMask)
|
2018-12-06 09:38:08 +11:00
|
|
|
{
|
2024-08-07 12:12:17 +02:00
|
|
|
BLI_assert((obedit->id.tag & ID_TAG_COPIED_ON_EVAL) == 0);
|
2025-04-17 13:09:20 +02:00
|
|
|
const Scene *scene_eval = DEG_get_evaluated(depsgraph, scene);
|
|
|
|
|
Object *obedit_eval = DEG_get_evaluated(depsgraph, obedit);
|
2018-12-06 09:38:08 +11:00
|
|
|
BMEditMesh *em_eval = BKE_editmesh_from_object(obedit_eval);
|
|
|
|
|
return editbmesh_get_eval_cage(depsgraph, scene_eval, obedit_eval, em_eval, dataMask);
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-04 17:53:10 +10:00
|
|
|
/* same as above but for vert coords */
|
2020-12-14 13:00:28 +01:00
|
|
|
struct MappedUserData {
|
2014-09-04 17:53:10 +10:00
|
|
|
float (*vertexcos)[3];
|
|
|
|
|
BLI_bitmap *vertex_visit;
|
2020-12-14 13:00:28 +01:00
|
|
|
};
|
2014-09-04 17:53:10 +10:00
|
|
|
|
2023-07-27 12:04:18 +10:00
|
|
|
static void make_vertexcos__mapFunc(void *user_data,
|
2015-07-02 16:20:22 +10:00
|
|
|
int index,
|
|
|
|
|
const float co[3],
|
2022-10-12 10:27:27 +11:00
|
|
|
const float /*no*/[3])
|
2014-09-04 17:53:10 +10:00
|
|
|
{
|
2023-07-27 12:04:18 +10:00
|
|
|
MappedUserData *mappedData = (MappedUserData *)user_data;
|
2014-09-04 17:53:10 +10:00
|
|
|
|
|
|
|
|
if (BLI_BITMAP_TEST(mappedData->vertex_visit, index) == 0) {
|
|
|
|
|
/* we need coord from prototype vertex, not from copies,
|
|
|
|
|
* assume they stored in the beginning of vertex array stored in DM
|
|
|
|
|
* (mirror modifier for eg does this) */
|
|
|
|
|
copy_v3_v3(mappedData->vertexcos[index], co);
|
|
|
|
|
BLI_BITMAP_ENABLE(mappedData->vertex_visit, index);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-20 12:26:07 -04:00
|
|
|
void mesh_get_mapped_verts_coords(Mesh *mesh_eval, MutableSpan<float3> r_cos)
|
2014-09-04 17:53:10 +10:00
|
|
|
{
|
2024-03-11 11:21:12 -04:00
|
|
|
if (mesh_eval->runtime->deformed_only == false) {
|
2023-07-27 12:04:18 +10:00
|
|
|
MappedUserData user_data;
|
2023-11-16 18:29:52 +01:00
|
|
|
r_cos.fill(float3(0));
|
|
|
|
|
user_data.vertexcos = reinterpret_cast<float(*)[3]>(r_cos.data());
|
|
|
|
|
user_data.vertex_visit = BLI_BITMAP_NEW(r_cos.size(), "vertexcos flags");
|
2024-03-11 11:21:12 -04:00
|
|
|
BKE_mesh_foreach_mapped_vert(mesh_eval, make_vertexcos__mapFunc, &user_data, MESH_FOREACH_NOP);
|
2023-07-27 12:04:18 +10:00
|
|
|
MEM_freeN(user_data.vertex_visit);
|
2014-09-04 17:53:10 +10:00
|
|
|
}
|
|
|
|
|
else {
|
2024-10-16 16:54:15 +11:00
|
|
|
r_cos.copy_from(BKE_mesh_wrapper_vert_coords(mesh_eval));
|
2014-09-04 17:53:10 +10:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2024-05-20 13:11:12 -04:00
|
|
|
static void mesh_init_origspace(Mesh &mesh)
|
2018-05-11 03:53:52 -04:00
|
|
|
{
|
|
|
|
|
const float default_osf[4][2] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}};
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-01-13 17:21:20 -06:00
|
|
|
OrigSpaceLoop *lof_array = (OrigSpaceLoop *)CustomData_get_layer_for_write(
|
2024-05-20 13:11:12 -04:00
|
|
|
&mesh.corner_data, CD_ORIGSPACE_MLOOP, mesh.corners_num);
|
|
|
|
|
const Span<float3> positions = mesh.vert_positions();
|
|
|
|
|
const OffsetIndices faces = mesh.faces();
|
|
|
|
|
const Span<int> corner_verts = mesh.corner_verts();
|
Mesh: Remove redundant custom data pointers
For copy-on-write, we want to share attribute arrays between meshes
where possible. Mutable pointers like `Mesh.mvert` make that difficult
by making ownership vague. They also make code more complex by adding
redundancy.
The simplest solution is just removing them and retrieving layers from
`CustomData` as needed. Similar changes have already been applied to
curves and point clouds (e9f82d3dc7ee, 410a6efb747f). Removing use of
the pointers generally makes code more obvious and more reusable.
Mesh data is now accessed with a C++ API (`Mesh::edges()` or
`Mesh::edges_for_write()`), and a C API (`BKE_mesh_edges(mesh)`).
The CoW changes this commit makes possible are described in T95845
and T95842, and started in D14139 and D14140. The change also simplifies
the ongoing mesh struct-of-array refactors from T95965.
**RNA/Python Access Performance**
Theoretically, accessing mesh elements with the RNA API may become
slower, since the layer needs to be found on every random access.
However, overhead is already high enough that this doesn't make a
noticible differenc, and performance is actually improved in some
cases. Random access can be up to 10% faster, but other situations
might be a bit slower. Generally using `foreach_get/set` are the best
way to improve performance. See the differential revision for more
discussion about Python performance.
Cycles has been updated to use raw pointers and the internal Blender
mesh types, mostly because there is no sense in having this overhead
when it's already compiled with Blender. In my tests this roughly
halves the Cycles mesh creation time (0.19s to 0.10s for a 1 million
face grid).
Differential Revision: https://developer.blender.org/D15488
2022-09-05 11:56:34 -05:00
|
|
|
|
2023-03-03 10:50:54 -05:00
|
|
|
int j, k;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2024-05-20 12:26:07 -04:00
|
|
|
Vector<float2, 64> vcos_2d;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-07-24 22:06:55 +02:00
|
|
|
for (const int i : faces.index_range()) {
|
2024-05-20 12:26:07 -04:00
|
|
|
const IndexRange face = faces[i];
|
2023-07-24 22:06:55 +02:00
|
|
|
OrigSpaceLoop *lof = lof_array + face.start();
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-07-24 22:06:55 +02:00
|
|
|
if (ELEM(face.size(), 3, 4)) {
|
|
|
|
|
for (j = 0; j < face.size(); j++, lof++) {
|
2018-05-11 03:53:52 -04:00
|
|
|
copy_v2_v2(lof->uv, default_osf[j]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
2023-03-12 22:29:15 +01:00
|
|
|
float co[3];
|
2018-05-11 03:53:52 -04:00
|
|
|
float mat[3][3];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-11 03:53:52 -04:00
|
|
|
float min[2] = {FLT_MAX, FLT_MAX}, max[2] = {-FLT_MAX, -FLT_MAX};
|
|
|
|
|
float translate[2], scale[2];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2024-05-20 12:26:07 -04:00
|
|
|
const float3 p_nor = mesh::face_normal_calc(positions, corner_verts.slice(face));
|
2023-03-12 22:29:15 +01:00
|
|
|
|
2018-05-11 03:53:52 -04:00
|
|
|
axis_dominant_v3_to_m3(mat, p_nor);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2023-07-24 22:06:55 +02:00
|
|
|
vcos_2d.resize(face.size());
|
|
|
|
|
for (j = 0; j < face.size(); j++) {
|
|
|
|
|
mul_v3_m3v3(co, mat, positions[corner_verts[face[j]]]);
|
2018-05-11 03:53:52 -04:00
|
|
|
copy_v2_v2(vcos_2d[j], co);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-11 03:53:52 -04:00
|
|
|
for (k = 0; k < 2; k++) {
|
2019-04-22 09:39:35 +10:00
|
|
|
if (co[k] > max[k]) {
|
2018-05-11 03:53:52 -04:00
|
|
|
max[k] = co[k];
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
else if (co[k] < min[k]) {
|
2018-05-11 03:53:52 -04:00
|
|
|
min[k] = co[k];
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2018-05-11 03:53:52 -04:00
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-11 03:53:52 -04:00
|
|
|
/* Brings min to (0, 0). */
|
|
|
|
|
negate_v2_v2(translate, min);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-11 03:53:52 -04:00
|
|
|
/* Scale will bring max to (1, 1). */
|
|
|
|
|
sub_v2_v2v2(scale, max, min);
|
2019-04-22 09:39:35 +10:00
|
|
|
if (scale[0] == 0.0f) {
|
2018-05-11 03:53:52 -04:00
|
|
|
scale[0] = 1e-9f;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
|
|
|
|
if (scale[1] == 0.0f) {
|
2018-05-11 03:53:52 -04:00
|
|
|
scale[1] = 1e-9f;
|
2019-04-22 09:39:35 +10:00
|
|
|
}
|
2018-05-11 03:53:52 -04:00
|
|
|
invert_v2(scale);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-27 12:07:07 +10:00
|
|
|
/* Finally, transform all vcos_2d into ((0, 0), (1, 1))
|
|
|
|
|
* square and assign them as origspace. */
|
2023-07-24 22:06:55 +02:00
|
|
|
for (j = 0; j < face.size(); j++, lof++) {
|
2018-05-11 03:53:52 -04:00
|
|
|
add_v2_v2v2(lof->uv, vcos_2d[j], translate);
|
|
|
|
|
mul_v2_v2(lof->uv, scale);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2024-05-20 13:11:12 -04:00
|
|
|
BKE_mesh_tessface_clear(&mesh);
|
2018-05-11 03:53:52 -04:00
|
|
|
}
|
2024-05-20 12:26:07 -04:00
|
|
|
|
|
|
|
|
} // namespace blender::bke
|