Implements #102359. Split the `MLoop` struct into two separate integer arrays called `corner_verts` and `corner_edges`, referring to the vertex each corner is attached to and the next edge around the face at each corner. These arrays can be sliced to give access to the edges or vertices in a face. Then they are often referred to as "poly_verts" or "poly_edges". The main benefits are halving the necessary memory bandwidth when only one array is used and simplifications from using regular integer indices instead of a special-purpose struct. The commit also starts a renaming from "loop" to "corner" in mesh code. Like the other mesh struct of array refactors, forward compatibility is kept by writing files with the older format. This will be done until 4.0 to ease the transition process. Looking at a small portion of the patch should give a good impression for the rest of the changes. I tried to make the changes as small as possible so it's easy to tell the correctness from the diff. Though I found Blender developers have been very inventive over the last decade when finding different ways to loop over the corners in a face. For performance, nearly every piece of code that deals with `Mesh` is slightly impacted. Any algorithm that is memory bottle-necked should see an improvement. For example, here is a comparison of interpolating a vertex float attribute to face corners (Ryzen 3700x): **Before** (Average: 3.7 ms, Min: 3.4 ms) ``` threading::parallel_for(loops.index_range(), 4096, [&](IndexRange range) { for (const int64_t i : range) { dst[i] = src[loops[i].v]; } }); ``` **After** (Average: 2.9 ms, Min: 2.6 ms) ``` array_utils::gather(src, corner_verts, dst); ``` That's an improvement of 28% to the average timings, and it's also a simplification, since an index-based routine can be used instead. For more examples using the new arrays, see the design task. Pull Request: blender/blender#104424
114 lines
4.3 KiB
C++
114 lines
4.3 KiB
C++
/* SPDX-License-Identifier: GPL-2.0-or-later
|
|
* Copyright 2001-2002 NaN Holding BV. All rights reserved. */
|
|
#pragma once
|
|
|
|
/** \file
|
|
* \ingroup bke
|
|
*
|
|
* This file contains access functions for the Mesh.runtime struct.
|
|
*/
|
|
|
|
#include "BKE_mesh_types.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
struct CustomData_MeshMasks;
|
|
struct Depsgraph;
|
|
struct KeyBlock;
|
|
struct MLoopTri;
|
|
struct MVertTri;
|
|
struct Mesh;
|
|
struct Object;
|
|
struct Scene;
|
|
|
|
/** Return the number of derived triangles (looptris). */
|
|
int BKE_mesh_runtime_looptri_len(const struct Mesh *mesh);
|
|
|
|
/**
|
|
* Return mesh triangulation data, calculated lazily when necessary.
|
|
* See #MLoopTri for further description of mesh triangulation.
|
|
*
|
|
* \note Prefer #Mesh::looptris() in C++ code.
|
|
*/
|
|
const struct MLoopTri *BKE_mesh_runtime_looptri_ensure(const struct Mesh *mesh);
|
|
|
|
bool BKE_mesh_runtime_ensure_edit_data(struct Mesh *mesh);
|
|
void BKE_mesh_runtime_reset_edit_data(struct Mesh *mesh);
|
|
|
|
/**
|
|
* Clear and free any derived caches associated with the mesh geometry data. Examples include BVH
|
|
* caches, normals, triangulation, etc. This should be called when replacing a mesh's geometry
|
|
* directly or making other large changes to topology. It does not need to be called on new meshes.
|
|
*
|
|
* For "smaller" changes to meshes like updating positions, consider calling a more specific update
|
|
* function like #BKE_mesh_tag_positions_changed.
|
|
*
|
|
* Also note that some derived caches like #CD_NORMAL and #CD_TANGENT are stored directly in
|
|
* #CustomData.
|
|
*/
|
|
void BKE_mesh_runtime_clear_geometry(struct Mesh *mesh);
|
|
|
|
/**
|
|
* Similar to #BKE_mesh_runtime_clear_geometry, but subtly different in that it also clears
|
|
* data-block level features like evaluated data-blocks and edit mode data. They will be
|
|
* functionally the same in most cases, but prefer this function if unsure, since it clears
|
|
* more data.
|
|
*/
|
|
void BKE_mesh_runtime_clear_cache(struct Mesh *mesh);
|
|
|
|
/**
|
|
* Convert triangles encoded as face corner indices to triangles encoded as vertex indices.
|
|
*/
|
|
void BKE_mesh_runtime_verttri_from_looptri(struct MVertTri *r_verttri,
|
|
const int *corner_verts,
|
|
const struct MLoopTri *looptri,
|
|
int looptri_num);
|
|
|
|
/** \note Only used for access in C. */
|
|
bool BKE_mesh_is_deformed_only(const struct Mesh *mesh);
|
|
/** \note Only used for access in C. */
|
|
eMeshWrapperType BKE_mesh_wrapper_type(const struct Mesh *mesh);
|
|
|
|
/* NOTE: the functions below are defined in DerivedMesh.cc, and are intended to be moved
|
|
* to a more suitable location when that file is removed.
|
|
* They should also be renamed to use conventions from BKE, not old DerivedMesh.cc.
|
|
* For now keep the names similar to avoid confusion. */
|
|
|
|
struct Mesh *mesh_get_eval_final(struct Depsgraph *depsgraph,
|
|
const struct Scene *scene,
|
|
struct Object *ob,
|
|
const struct CustomData_MeshMasks *dataMask);
|
|
|
|
struct Mesh *mesh_get_eval_deform(struct Depsgraph *depsgraph,
|
|
const struct Scene *scene,
|
|
struct Object *ob,
|
|
const struct CustomData_MeshMasks *dataMask);
|
|
|
|
struct Mesh *mesh_create_eval_final(struct Depsgraph *depsgraph,
|
|
const struct Scene *scene,
|
|
struct Object *ob,
|
|
const struct CustomData_MeshMasks *dataMask);
|
|
|
|
struct Mesh *mesh_create_eval_no_deform(struct Depsgraph *depsgraph,
|
|
const struct Scene *scene,
|
|
struct Object *ob,
|
|
const struct CustomData_MeshMasks *dataMask);
|
|
struct Mesh *mesh_create_eval_no_deform_render(struct Depsgraph *depsgraph,
|
|
const struct Scene *scene,
|
|
struct Object *ob,
|
|
const struct CustomData_MeshMasks *dataMask);
|
|
|
|
void BKE_mesh_runtime_eval_to_meshkey(struct Mesh *me_deformed,
|
|
struct Mesh *me,
|
|
struct KeyBlock *kb);
|
|
|
|
#ifndef NDEBUG
|
|
bool BKE_mesh_runtime_is_valid(struct Mesh *me_eval);
|
|
#endif /* NDEBUG */
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|